/* LIBPIKA - The PIKA Library
 * Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
 *
 * pikaparamspecs-body.c
 *
 * This library is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.  If not, see
 * <https://www.gnu.org/licenses/>.
 */

/*  this file is included by both
 *
 *  libpika/pikaparamspecs.c
 *  app/core/pikaparamspecs.c
 */

/*
 * PIKA_TYPE_PARAM_IMAGE
 */

static void       pika_param_image_class_init (GParamSpecClass *klass);
static void       pika_param_image_init       (GParamSpec      *pspec);
static gboolean   pika_param_image_validate   (GParamSpec      *pspec,
                                               GValue          *value);

GType
pika_param_image_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_image_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecImage),
        0,
        (GInstanceInitFunc) pika_param_image_init
      };

      type = g_type_register_static (G_TYPE_PARAM_OBJECT,
                                     "PikaParamImage", &info, 0);
    }

  return type;
}

static void
pika_param_image_class_init (GParamSpecClass *klass)
{
  klass->value_type     = PIKA_TYPE_IMAGE;
  klass->value_validate = pika_param_image_validate;
}

static void
pika_param_image_init (GParamSpec *pspec)
{
  PikaParamSpecImage *ispec = PIKA_PARAM_SPEC_IMAGE (pspec);

  ispec->none_ok = FALSE;
}

static gboolean
pika_param_image_validate (GParamSpec *pspec,
                           GValue     *value)
{
  PikaParamSpecImage *ispec = PIKA_PARAM_SPEC_IMAGE (pspec);
  PikaImage          *image = value->data[0].v_pointer;

  if (! ispec->none_ok && image == NULL)
    return TRUE;

  if (image && (! PIKA_IS_IMAGE (image) ||
                ! pika_image_is_valid (image)))
    {
      g_object_unref (image);
      value->data[0].v_pointer = NULL;
      return TRUE;
    }

  return FALSE;
}

/**
 * pika_param_spec_image:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecImage specifying a
 * [type@Image] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecImage.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_image (const gchar *name,
                       const gchar *nick,
                       const gchar *blurb,
                       gboolean     none_ok,
                       GParamFlags  flags)
{
  PikaParamSpecImage *ispec;

  ispec = g_param_spec_internal (PIKA_TYPE_PARAM_IMAGE,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (ispec, NULL);

  ispec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (ispec);
}


/*
 * PIKA_TYPE_PARAM_ITEM
 */

static void       pika_param_item_class_init (GParamSpecClass *klass);
static void       pika_param_item_init       (GParamSpec      *pspec);
static gboolean   pika_param_item_validate   (GParamSpec      *pspec,
                                              GValue          *value);

GType
pika_param_item_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_item_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecItem),
        0,
        (GInstanceInitFunc) pika_param_item_init
      };

      type = g_type_register_static (G_TYPE_PARAM_OBJECT,
                                     "PikaParamItem", &info, 0);
    }

  return type;
}

static void
pika_param_item_class_init (GParamSpecClass *klass)
{
  klass->value_type     = PIKA_TYPE_ITEM;
  klass->value_validate = pika_param_item_validate;
}

static void
pika_param_item_init (GParamSpec *pspec)
{
  PikaParamSpecItem *ispec = PIKA_PARAM_SPEC_ITEM (pspec);

  ispec->none_ok = FALSE;
}

static gboolean
pika_param_item_validate (GParamSpec *pspec,
                          GValue     *value)
{
  PikaParamSpecItem *ispec = PIKA_PARAM_SPEC_ITEM (pspec);
  PikaItem          *item  = value->data[0].v_pointer;

  if (! ispec->none_ok && item == NULL)
    return TRUE;

  if (item && (! g_type_is_a (G_OBJECT_TYPE (item), pspec->value_type) ||
               ! pika_item_is_valid (item)))
    {
      g_object_unref (item);
      value->data[0].v_pointer = NULL;
      return TRUE;
    }

  return FALSE;
}

/**
 * pika_param_spec_item:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecItem specifying a
 * [type@Item] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecItem.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_item (const gchar *name,
                      const gchar *nick,
                      const gchar *blurb,
                      gboolean     none_ok,
                      GParamFlags  flags)
{
  PikaParamSpecItem *ispec;

  ispec = g_param_spec_internal (PIKA_TYPE_PARAM_ITEM,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (ispec, NULL);

  ispec->none_ok = none_ok;

  return G_PARAM_SPEC (ispec);
}


/*
 * PIKA_TYPE_PARAM_DRAWABLE
 */

static void   pika_param_drawable_class_init (GParamSpecClass *klass);
static void   pika_param_drawable_init       (GParamSpec      *pspec);

GType
pika_param_drawable_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_drawable_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecDrawable),
        0,
        (GInstanceInitFunc) pika_param_drawable_init
      };

      type = g_type_register_static (PIKA_TYPE_PARAM_ITEM,
                                     "PikaParamDrawable", &info, 0);
    }

  return type;
}

static void
pika_param_drawable_class_init (GParamSpecClass *klass)
{
  klass->value_type = PIKA_TYPE_DRAWABLE;
}

static void
pika_param_drawable_init (GParamSpec *pspec)
{
}

/**
 * pika_param_spec_drawable:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecDrawable specifying a
 * [type@Drawable] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecDrawable.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_drawable (const gchar *name,
                          const gchar *nick,
                          const gchar *blurb,
                          gboolean     none_ok,
                          GParamFlags  flags)
{
  PikaParamSpecItem *ispec;

  ispec = g_param_spec_internal (PIKA_TYPE_PARAM_DRAWABLE,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (ispec, NULL);

  ispec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (ispec);
}


/*
 * PIKA_TYPE_PARAM_LAYER
 */

static void   pika_param_layer_class_init (GParamSpecClass *klass);
static void   pika_param_layer_init       (GParamSpec      *pspec);

GType
pika_param_layer_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_layer_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecLayer),
        0,
        (GInstanceInitFunc) pika_param_layer_init
      };

      type = g_type_register_static (PIKA_TYPE_PARAM_DRAWABLE,
                                     "PikaParamLayer", &info, 0);
    }

  return type;
}

static void
pika_param_layer_class_init (GParamSpecClass *klass)
{
  klass->value_type = PIKA_TYPE_LAYER;
}

static void
pika_param_layer_init (GParamSpec *pspec)
{
}

/**
 * pika_param_spec_layer:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecLayer specifying a
 * [type@Layer] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecLayer.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_layer (const gchar *name,
                       const gchar *nick,
                       const gchar *blurb,
                       gboolean     none_ok,
                       GParamFlags  flags)
{
  PikaParamSpecItem *ispec;

  ispec = g_param_spec_internal (PIKA_TYPE_PARAM_LAYER,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (ispec, NULL);

  ispec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (ispec);
}


/*
 * PIKA_TYPE_PARAM_TEXT_LAYER
 */

static void   pika_param_text_layer_class_init (GParamSpecClass *klass);
static void   pika_param_text_layer_init       (GParamSpec      *pspec);

GType
pika_param_text_layer_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_text_layer_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecTextLayer),
        0,
        (GInstanceInitFunc) pika_param_text_layer_init
      };

      type = g_type_register_static (PIKA_TYPE_PARAM_LAYER,
                                     "PikaParamTextLayer", &info, 0);
    }

  return type;
}

static void
pika_param_text_layer_class_init (GParamSpecClass *klass)
{
  klass->value_type = PIKA_TYPE_TEXT_LAYER;
}

static void
pika_param_text_layer_init (GParamSpec *pspec)
{
}

/**
 * pika_param_spec_text_layer:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecTextLayer specifying a
 * [type@TextLayer] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecTextLayer.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_text_layer (const gchar *name,
                            const gchar *nick,
                            const gchar *blurb,
                            gboolean     none_ok,
                            GParamFlags  flags)
{
  PikaParamSpecItem *ispec;

  ispec = g_param_spec_internal (PIKA_TYPE_PARAM_TEXT_LAYER,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (ispec, NULL);

  ispec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (ispec);
}


/*
 * PIKA_TYPE_PARAM_CHANNEL
 */

static void   pika_param_channel_class_init (GParamSpecClass *klass);
static void   pika_param_channel_init       (GParamSpec      *pspec);

GType
pika_param_channel_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_channel_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecChannel),
        0,
        (GInstanceInitFunc) pika_param_channel_init
      };

      type = g_type_register_static (PIKA_TYPE_PARAM_DRAWABLE,
                                     "PikaParamChannel", &info, 0);
    }

  return type;
}

static void
pika_param_channel_class_init (GParamSpecClass *klass)
{
  klass->value_type = PIKA_TYPE_CHANNEL;
}

static void
pika_param_channel_init (GParamSpec *pspec)
{
}

/**
 * pika_param_spec_channel:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecChannel specifying a
 * [type@Channel] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecChannel.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_channel (const gchar *name,
                         const gchar *nick,
                         const gchar *blurb,
                         gboolean     none_ok,
                         GParamFlags  flags)
{
  PikaParamSpecItem *ispec;

  ispec = g_param_spec_internal (PIKA_TYPE_PARAM_CHANNEL,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (ispec, NULL);

  ispec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (ispec);
}


/*
 * PIKA_TYPE_PARAM_LAYER_MASK
 */

static void   pika_param_layer_mask_class_init (GParamSpecClass *klass);
static void   pika_param_layer_mask_init       (GParamSpec      *pspec);

GType
pika_param_layer_mask_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_layer_mask_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecLayerMask),
        0,
        (GInstanceInitFunc) pika_param_layer_mask_init
      };

      type = g_type_register_static (PIKA_TYPE_PARAM_CHANNEL,
                                     "PikaParamLayerMask", &info, 0);
    }

  return type;
}

static void
pika_param_layer_mask_class_init (GParamSpecClass *klass)
{
  klass->value_type = PIKA_TYPE_LAYER_MASK;
}

static void
pika_param_layer_mask_init (GParamSpec *pspec)
{
}

/**
 * pika_param_spec_layer_mask:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecLayerMask specifying a
 * [type@LayerMask] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecLayerMask.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_layer_mask (const gchar *name,
                            const gchar *nick,
                            const gchar *blurb,
                            gboolean     none_ok,
                            GParamFlags  flags)
{
  PikaParamSpecItem *ispec;

  ispec = g_param_spec_internal (PIKA_TYPE_PARAM_LAYER_MASK,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (ispec, NULL);

  ispec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (ispec);
}


/*
 * PIKA_TYPE_PARAM_SELECTION
 */

static void   pika_param_selection_class_init (GParamSpecClass *klass);
static void   pika_param_selection_init       (GParamSpec      *pspec);

GType
pika_param_selection_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_selection_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecSelection),
        0,
        (GInstanceInitFunc) pika_param_selection_init
      };

      type = g_type_register_static (PIKA_TYPE_PARAM_CHANNEL,
                                     "PikaParamSelection", &info, 0);
    }

  return type;
}

static void
pika_param_selection_class_init (GParamSpecClass *klass)
{
  klass->value_type = PIKA_TYPE_SELECTION;
}

static void
pika_param_selection_init (GParamSpec *pspec)
{
}

/**
 * pika_param_spec_selection:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecSelection specifying a
 * [type@Selection] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecSelection.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_selection (const gchar *name,
                           const gchar *nick,
                           const gchar *blurb,
                           gboolean     none_ok,
                           GParamFlags  flags)
{
  PikaParamSpecItem *ispec;

  ispec = g_param_spec_internal (PIKA_TYPE_PARAM_SELECTION,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (ispec, NULL);

  ispec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (ispec);
}


/*
 * PIKA_TYPE_PARAM_VECTORS
 */

static void   pika_param_vectors_class_init (GParamSpecClass *klass);
static void   pika_param_vectors_init       (GParamSpec      *pspec);

GType
pika_param_vectors_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_vectors_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecVectors),
        0,
        (GInstanceInitFunc) pika_param_vectors_init
      };

      type = g_type_register_static (PIKA_TYPE_PARAM_ITEM,
                                     "PikaParamVectors", &info, 0);
    }

  return type;
}

static void
pika_param_vectors_class_init (GParamSpecClass *klass)
{
  klass->value_type = PIKA_TYPE_VECTORS;
}

static void
pika_param_vectors_init (GParamSpec *pspec)
{
}

/**
 * pika_param_spec_vectors:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecVectors specifying a
 * [type@Vectors] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecVectors.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_vectors (const gchar *name,
                         const gchar *nick,
                         const gchar *blurb,
                         gboolean     none_ok,
                         GParamFlags  flags)
{
  PikaParamSpecItem *ispec;

  ispec = g_param_spec_internal (PIKA_TYPE_PARAM_VECTORS,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (ispec, NULL);

  ispec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (ispec);
}


/*
 * PIKA_TYPE_PARAM_DISPLAY
 */

static void       pika_param_display_class_init (GParamSpecClass *klass);
static void       pika_param_display_init       (GParamSpec      *pspec);
static gboolean   pika_param_display_validate   (GParamSpec      *pspec,
                                                 GValue          *value);

GType
pika_param_display_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_display_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecDisplay),
        0,
        (GInstanceInitFunc) pika_param_display_init
      };

      type = g_type_register_static (G_TYPE_PARAM_OBJECT,
                                     "PikaParamDisplay", &info, 0);
    }

  return type;
}

static void
pika_param_display_class_init (GParamSpecClass *klass)
{
  klass->value_type     = PIKA_TYPE_DISPLAY;
  klass->value_validate = pika_param_display_validate;
}

static void
pika_param_display_init (GParamSpec *pspec)
{
  PikaParamSpecDisplay *dspec = PIKA_PARAM_SPEC_DISPLAY (pspec);

  dspec->none_ok = FALSE;
}

static gboolean
pika_param_display_validate (GParamSpec *pspec,
                             GValue     *value)
{
  PikaParamSpecDisplay *dspec   = PIKA_PARAM_SPEC_DISPLAY (pspec);
  PikaDisplay          *display = value->data[0].v_pointer;

  if (! dspec->none_ok && display == NULL)
   return TRUE;

  if (display && (! PIKA_IS_DISPLAY (display) ||
                  ! pika_display_is_valid (display)))
    {
      g_object_unref (display);
      value->data[0].v_pointer = NULL;
      return TRUE;
    }

  return FALSE;
}

/**
 * pika_param_spec_display:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecDisplay specifying a
 * [type@Display] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecDisplay.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_display (const gchar *name,
                         const gchar *nick,
                         const gchar *blurb,
                         gboolean     none_ok,
                         GParamFlags  flags)
{
  PikaParamSpecDisplay *dspec;

  dspec = g_param_spec_internal (PIKA_TYPE_PARAM_DISPLAY,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (dspec, NULL);

  dspec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (dspec);
}


 /*
  * PIKA_TYPE_PARAM_RESOURCE
  */

 static void       pika_param_resource_class_init (GParamSpecClass *klass);
 static void       pika_param_resource_init       (GParamSpec      *pspec);
 static gboolean   pika_param_resource_validate   (GParamSpec      *pspec,
                                                   GValue          *value);

 GType
 pika_param_resource_get_type (void)
 {
   static GType type = 0;

   if (! type)
     {
       const GTypeInfo info =
       {
         sizeof (GParamSpecClass),
         NULL, NULL,
         (GClassInitFunc) pika_param_resource_class_init,
         NULL, NULL,
         sizeof (PikaParamSpecResource),
         0,
         (GInstanceInitFunc) pika_param_resource_init
       };

       type = g_type_register_static (G_TYPE_PARAM_OBJECT,
                                      "PikaParamResource", &info, 0);
     }

   return type;
 }

 static void
 pika_param_resource_class_init (GParamSpecClass *klass)
 {
   klass->value_type     = PIKA_TYPE_RESOURCE;
   klass->value_validate = pika_param_resource_validate;
 }

static void
pika_param_resource_init (GParamSpec *pspec)
{
  PikaParamSpecResource *rspec = PIKA_PARAM_SPEC_RESOURCE (pspec);

  rspec->none_ok = FALSE;
}

static gboolean
pika_param_resource_validate (GParamSpec *pspec,
                              GValue     *value)
{
  PikaParamSpecResource *rspec    = PIKA_PARAM_SPEC_RESOURCE (pspec);
  GObject               *resource = value->data[0].v_pointer;

  if (! rspec->none_ok && resource == NULL)
    return TRUE;

  if (resource && (! g_type_is_a (G_OBJECT_TYPE (resource), pspec->value_type) ||
                   ! pika_resource_is_valid ((gpointer) resource)))
    {
      g_object_unref (resource);
      value->data[0].v_pointer = NULL;
      return TRUE;
    }

  return FALSE;
}

/**
 * pika_param_spec_resource:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecResource specifying a
 * [type@Resource] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecResource.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_resource (const gchar *name,
                          const gchar *nick,
                          const gchar *blurb,
                          gboolean     none_ok,
                          GParamFlags  flags)
{
  PikaParamSpecResource *rspec;

  rspec = g_param_spec_internal (PIKA_TYPE_PARAM_RESOURCE,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (rspec, NULL);

  rspec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (rspec);
}


/*
 * PIKA_TYPE_PARAM_BRUSH
 */

static void   pika_param_brush_class_init (GParamSpecClass *klass);
static void   pika_param_brush_init       (GParamSpec      *pspec);

GType
pika_param_brush_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_brush_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecBrush),
        0,
        (GInstanceInitFunc) pika_param_brush_init
      };

      type = g_type_register_static (PIKA_TYPE_PARAM_RESOURCE,
                                     "PikaParamBrush", &info, 0);
    }

  return type;
}

static void
pika_param_brush_class_init (GParamSpecClass *klass)
{
  klass->value_type = PIKA_TYPE_BRUSH;
}

static void
pika_param_brush_init (GParamSpec *pspec)
{
}

/**
 * pika_param_spec_brush:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecBrush specifying a
 * [type@Brush] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecBrush.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_brush (const gchar *name,
                       const gchar *nick,
                       const gchar *blurb,
                       gboolean     none_ok,
                       GParamFlags  flags)
{
  PikaParamSpecResource *rspec;

  rspec = g_param_spec_internal (PIKA_TYPE_PARAM_BRUSH,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (rspec, NULL);

  rspec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (rspec);
}


/*
 * PIKA_TYPE_PARAM_PATTERN
 */

static void   pika_param_pattern_class_init (GParamSpecClass *klass);
static void   pika_param_pattern_init       (GParamSpec      *pspec);

GType
pika_param_pattern_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_pattern_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecPattern),
        0,
        (GInstanceInitFunc) pika_param_pattern_init
      };

      type = g_type_register_static (PIKA_TYPE_PARAM_RESOURCE,
                                     "PikaParamPattern", &info, 0);
    }

  return type;
}

static void
pika_param_pattern_class_init (GParamSpecClass *klass)
{
  klass->value_type = PIKA_TYPE_PATTERN;
}

static void
pika_param_pattern_init (GParamSpec *pspec)
{
}

/**
 * pika_param_spec_pattern:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecPattern specifying a
 * [type@Pattern] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecPattern.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_pattern (const gchar *name,
                         const gchar *nick,
                         const gchar *blurb,
                         gboolean     none_ok,
                         GParamFlags  flags)
{
  PikaParamSpecResource *rspec;

  rspec = g_param_spec_internal (PIKA_TYPE_PARAM_PATTERN,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (rspec, NULL);

  rspec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (rspec);
}


/*
 * PIKA_TYPE_PARAM_GRADIENT
 */

static void   pika_param_gradient_class_init (GParamSpecClass *klass);
static void   pika_param_gradient_init       (GParamSpec      *pspec);

GType
pika_param_gradient_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_gradient_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecGradient),
        0,
        (GInstanceInitFunc) pika_param_gradient_init
      };

      type = g_type_register_static (PIKA_TYPE_PARAM_RESOURCE,
                                     "PikaParamGradient", &info, 0);
    }

  return type;
}

static void
pika_param_gradient_class_init (GParamSpecClass *klass)
{
  klass->value_type = PIKA_TYPE_GRADIENT;
}

static void
pika_param_gradient_init (GParamSpec *pspec)
{
}

/**
 * pika_param_spec_gradient:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecGradient specifying a
 * [type@Gradient] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecGradient.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_gradient (const gchar *name,
                          const gchar *nick,
                          const gchar *blurb,
                          gboolean     none_ok,
                          GParamFlags  flags)
{
  PikaParamSpecResource *rspec;

  rspec = g_param_spec_internal (PIKA_TYPE_PARAM_GRADIENT,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (rspec, NULL);

  rspec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (rspec);
}


/*
 * PIKA_TYPE_PARAM_PALETTE
 */

static void   pika_param_palette_class_init (GParamSpecClass *klass);
static void   pika_param_palette_init       (GParamSpec      *pspec);

GType
pika_param_palette_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_palette_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecPalette),
        0,
        (GInstanceInitFunc) pika_param_palette_init
      };

      type = g_type_register_static (PIKA_TYPE_PARAM_RESOURCE,
                                     "PikaParamPalette", &info, 0);
    }

  return type;
}

static void
pika_param_palette_class_init (GParamSpecClass *klass)
{
  klass->value_type = PIKA_TYPE_PALETTE;
}

static void
pika_param_palette_init (GParamSpec *pspec)
{
}

/**
 * pika_param_spec_palette:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecPalette specifying a
 * [type@Palette] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecPalette.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_palette (const gchar *name,
                         const gchar *nick,
                         const gchar *blurb,
                         gboolean     none_ok,
                         GParamFlags  flags)
{
  PikaParamSpecResource *rspec;

  rspec = g_param_spec_internal (PIKA_TYPE_PARAM_PALETTE,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (rspec, NULL);

  rspec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (rspec);
}


/*
 * PIKA_TYPE_PARAM_FONT
 */

static void   pika_param_font_class_init (GParamSpecClass *klass);
static void   pika_param_font_init       (GParamSpec      *pspec);

GType
pika_param_font_get_type (void)
{
  static GType type = 0;

  if (! type)
    {
      const GTypeInfo info =
      {
        sizeof (GParamSpecClass),
        NULL, NULL,
        (GClassInitFunc) pika_param_font_class_init,
        NULL, NULL,
        sizeof (PikaParamSpecFont),
        0,
        (GInstanceInitFunc) pika_param_font_init
      };

      type = g_type_register_static (PIKA_TYPE_PARAM_RESOURCE,
                                     "PikaParamFont", &info, 0);
    }

  return type;
}

static void
pika_param_font_class_init (GParamSpecClass *klass)
{
  klass->value_type = PIKA_TYPE_FONT;
}

static void
pika_param_font_init (GParamSpec *pspec)
{
}

/**
 * pika_param_spec_font:
 * @name:    Canonical name of the property specified.
 * @nick:    Nick name of the property specified.
 * @blurb:   Description of the property specified.
 * @none_ok: Whether no  is a valid value.
 * @flags:   Flags for the property specified.
 *
 * Creates a new #PikaParamSpecFont specifying a
 * [type@Font] property.
 *
 * See g_param_spec_internal() for details on property names.
 *
 * Returns: (transfer full): The newly created #PikaParamSpecFont.
 *
 * Since: 3.0
 **/
GParamSpec *
pika_param_spec_font (const gchar *name,
                      const gchar *nick,
                      const gchar *blurb,
                      gboolean     none_ok,
                      GParamFlags  flags)
{
  PikaParamSpecResource *rspec;

  rspec = g_param_spec_internal (PIKA_TYPE_PARAM_FONT,
                                 name, nick, blurb, flags);

  g_return_val_if_fail (rspec, NULL);

  rspec->none_ok = none_ok ? TRUE : FALSE;

  return G_PARAM_SPEC (rspec);
}
