glade-widget-adaptor.c 141 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Copyright (C) 2001 Ximian, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * Authors:
 *   Tristan Van Berkom <tvb@gnome.org>
 */

#include <config.h>

24 25 26 27
/**
 * SECTION:glade-widget-adaptor
 * @Short_Description: Adaptor base class to add runtime support for each widget class.
 * 
28 29 30 31 32
 * The #GladeWidgetAdaptor object is a proxy for widget class support in Glade.
 * it is automatically generated from the xml and allows you to override its
 * methods in the plugin library for fine grained support on how you load/save
 * widgets and handle thier properties in the runtime and more.
 * 
33 34
 */

35 36 37 38 39
#include "glade.h"
#include "glade-widget-adaptor.h"
#include "glade-xml-utils.h"
#include "glade-property-class.h"
#include "glade-signal.h"
40 41
#include "glade-marshallers.h"
#include "glade-accumulators.h"
42
#include "glade-displayable-values.h"
43
#include "glade-editor-table.h"
44
#include "glade-cursor.h"
45

46 47 48 49
/* For g_file_exists */
#include <sys/types.h>
#include <string.h>

50
#include <glib.h>
51 52 53 54
#include <glib/gi18n-lib.h>
#include <gmodule.h>
#include <ctype.h>

Vincent Geddes's avatar
Vincent Geddes committed
55
#define DEFAULT_ICON_NAME "widget-gtk-frame"
56

Vincent Geddes's avatar
Vincent Geddes committed
57 58 59
#define GLADE_WIDGET_ADAPTOR_GET_PRIVATE(o)  \
        (G_TYPE_INSTANCE_GET_PRIVATE ((o), GLADE_TYPE_WIDGET_ADAPTOR, GladeWidgetAdaptorPrivate))

60 61
struct _GladeWidgetAdaptorPrivate
{
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
  GType        type;                /* GType of the widget */
  GType        real_type;

  gchar       *name;                /* Name of the widget, for example GtkButton */
  gchar       *generic_name;        /* Used to generate names of new widgets, for
				     * example "button" so that we generate button1,
				     * button2, buttonX ..
				     */
  gchar       *icon_name;           /* icon name to use for widget class */
  gchar       *missing_icon;        /* the name of the missing icon if it was not found */

  gchar       *title;               /* Translated class name used in the UI */
  GList       *properties;          /* List of GladePropertyClass objects.
				     * [see glade-property.h] this list contains
				     * properties about the widget that we are going
				     * to modify. Like "title", "label", "rows" .
				     * Each property creates an input in the propety
				     * editor.
				     */
  GList       *packing_props;       /* List of GladePropertyClass objects that describe
				     * properties for child objects packing definition -
				     * note there may be more than one type of child supported
				     * by a widget and thus they may have different sets
				     * of properties for each type - this association is
				     * managed on the GladePropertyClass proper.
				     */
  GList       *signals;              /* List of GladeSignalClass objects */
  GList       *child_packings;       /* Default packing property values */
  GList       *actions;              /* A list of GWActionClass */
  GList       *packing_actions;      /* A list of GWActionClass for child objects */
92
  GList       *internal_children;    /* A list of GladeInternalChild */
93 94 95 96 97 98 99 100 101 102 103 104
  gchar       *catalog;              /* The name of the widget catalog this class
				      * was declared by.
				      */
  gchar       *book;                 /* DevHelp search namespace for this widget class
				      */

  GdkCursor   *cursor;                /* a cursor for inserting widgets */

  gchar       *special_child_type;    /* Special case code for children that
				       * are special children (like notebook tab 
				       * widgets for example).
				       */
105 106
};

107 108 109 110
struct _GladeChildPacking
{
  gchar *parent_name;
  GList *packing_defaults;
111 112
};

113

114 115 116 117
struct _GladePackingDefault
{
  gchar *id;
  gchar *value;
118 119
};

120 121 122 123 124 125
struct _GladeInternalChild
{
  gchar *name;
  gboolean anarchist;
  GList *children;
};
126

127 128 129 130 131 132 133 134 135 136 137
enum
{
  PROP_0,
  PROP_NAME,
  PROP_TYPE,
  PROP_TITLE,
  PROP_GENERIC_NAME,
  PROP_ICON_NAME,
  PROP_CATALOG,
  PROP_BOOK,
  PROP_SPECIAL_TYPE,
138
  PROP_CURSOR
139 140
};

141 142
typedef struct _GladeChildPacking GladeChildPacking;
typedef struct _GladePackingDefault GladePackingDefault;
143
typedef struct _GladeInternalChild GladeInternalChild;
144

145
static GHashTable *adaptor_hash = NULL;
146

147 148 149 150 151 152
/* This object used to be registered as GladeGObjectAdaptor but there is
 * no reason for it since the autogenerated class for GtWidget is GladeGtkWidgetAdaptor
 * TODO: rename GladeWidgetAdaptor to GladeGObjectAdator or GladeObjectAdator
 */
G_DEFINE_TYPE (GladeWidgetAdaptor, glade_widget_adaptor, G_TYPE_OBJECT);

153 154 155 156 157
/*******************************************************************************
                              Helper functions
 *******************************************************************************/

static void
158
gwa_create_cursor (GladeWidgetAdaptor *adaptor)
159
{
160 161 162 163 164 165
  GdkPixbuf *tmp_pixbuf, *widget_pixbuf;
  const GdkPixbuf *add_pixbuf;
  GdkDisplay *display;
  GError *error = NULL;

  /* only certain widget classes need to have cursors */
166 167 168
  if (G_TYPE_IS_INSTANTIATABLE (adaptor->priv->type) == FALSE ||
      G_TYPE_IS_ABSTRACT (adaptor->priv->type) != FALSE ||
      adaptor->priv->generic_name == NULL)
169
    return;
170

171 172 173
  /* cannot continue if 'add widget' cursor pixbuf has not been loaded for any reason */
  if ((add_pixbuf = glade_cursor_get_add_widget_pixbuf ()) == NULL)
    return;
174

175
  display = gdk_display_get_default ();
176

177 178 179
  /* create a temporary pixbuf clear to transparent black */
  tmp_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 32, 32);
  gdk_pixbuf_fill (tmp_pixbuf, 0x00000000);
180

181
  if (gtk_icon_theme_has_icon
182
      (gtk_icon_theme_get_default (), adaptor->priv->icon_name))
183 184
    {
      widget_pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
185
                                                adaptor->priv->icon_name,
186 187 188 189 190
                                                22, 0, &error);

      if (error)
        {
          g_warning ("Could not load image data for named icon '%s': %s",
191
                     adaptor->priv->icon_name, error->message);
192 193 194
          g_error_free (error);
          return;
        }
195

196 197 198 199 200
    }
  else
    {
      return;
    }
201

202 203 204
  /* composite pixbufs */
  gdk_pixbuf_composite (widget_pixbuf, tmp_pixbuf,
                        8, 8, 22, 22, 8, 8, 1, 1, GDK_INTERP_NEAREST, 255);
205

206 207
  gdk_pixbuf_composite (add_pixbuf, tmp_pixbuf,
                        0, 0, 12, 12, 0, 0, 1, 1, GDK_INTERP_NEAREST, 255);
208 209


210 211
  adaptor->priv->cursor =
      gdk_cursor_new_from_pixbuf (display, tmp_pixbuf, 6, 6);
212

213 214
  g_object_unref (tmp_pixbuf);
  g_object_unref (widget_pixbuf);
215 216 217 218 219
}



static gboolean
220
gwa_gtype_equal (gconstpointer v1, gconstpointer v2)
221
{
222
  return *((const GType *) v1) == *((const GType *) v2);
223 224 225 226 227
}

static guint
gwa_gtype_hash (gconstpointer v)
{
228
  return *(const GType *) v;
229 230
}

231
static gboolean
232 233
glade_widget_adaptor_hash_find (gpointer key, gpointer value,
                                gpointer user_data)
234
{
235 236 237
  GladeWidgetAdaptor *adaptor = value;
  GType *type = user_data;

238
  if (g_type_is_a (adaptor->priv->type, *type))
239
    {
240
      *type = adaptor->priv->type;
241 242 243 244
      return TRUE;
    }

  return FALSE;
245 246 247 248 249
}

static void
glade_abort_if_derived_adaptors_exist (GType type)
{
250 251 252 253 254 255 256 257 258
  if (adaptor_hash)
    {
      GType retval = type;

      g_hash_table_find (adaptor_hash, glade_widget_adaptor_hash_find, &retval);
      if (retval != type)
        g_error (_("A derived adaptor (%s) of %s already exist!"),
                 g_type_name (retval), g_type_name (type));
    }
259
}
260 261 262 263

/*******************************************************************************
                     Base Object Implementation detail
 *******************************************************************************/
264 265
#define gwa_get_parent_adaptor(a) glade_widget_adaptor_get_parent_adaptor (a)

266 267
static GladeWidgetAdaptor *
glade_widget_adaptor_get_parent_adaptor_by_type (GType adaptor_type)
268
{
269 270
  GladeWidgetAdaptor *parent_adaptor = NULL;
  GType iter_type;
271

272 273 274 275 276 277 278
  for (iter_type = g_type_parent (adaptor_type);
       iter_type > 0; iter_type = g_type_parent (iter_type))
    {
      if ((parent_adaptor =
           glade_widget_adaptor_get_by_type (iter_type)) != NULL)
        return parent_adaptor;
    }
279

280
  return NULL;
281 282
}

283 284 285
/* XXX DOCME
 */
GladeWidgetAdaptor *
286
glade_widget_adaptor_get_parent_adaptor (GladeWidgetAdaptor *adaptor)
287
{
288
  g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), NULL);
289

290
  return glade_widget_adaptor_get_parent_adaptor_by_type (adaptor->priv->type);
291
}
292

293 294 295 296 297 298 299
gboolean
glade_widget_adaptor_has_internal_children (GladeWidgetAdaptor *adaptor)
{
  g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), FALSE);
  return adaptor->priv->internal_children != NULL;
}

300
static gint
301
gwa_signal_comp (gpointer a, gpointer b)
302
{
303 304 305 306
  GladeSignalClass *signal_a = a, *signal_b = b;

  return strcmp (glade_signal_class_get_name (signal_b), 
		 glade_signal_class_get_name (signal_a));
307 308
}

309
static gint
310
gwa_signal_find_comp (gpointer a, gpointer b)
311
{
312 313 314
  GladeSignalClass *signal = a;
  gchar *name = b;
  return strcmp (name, glade_signal_class_get_name (signal));
315 316
}

317
static void
318
gwa_add_signals (GladeWidgetAdaptor *adaptor, GList **signals, GType type)
319
{
320
  guint               count, *sig_ids, num_signals;
321
  GladeWidgetAdaptor *type_adaptor;
322 323
  GladeSignalClass   *signal;
  GList              *list = NULL;
324 325 326

  type_adaptor = glade_widget_adaptor_get_by_type (type);

327
  sig_ids = g_signal_list_ids (type, &num_signals);
328

329 330 331 332 333
  for (count = 0; count < num_signals; count++)
    {
      signal = glade_signal_class_new (type_adaptor ? 
				       type_adaptor : adaptor,
				       type, sig_ids[count]);
334

335
      list = g_list_prepend (list, signal);
336
    }
337 338 339 340
  g_free (sig_ids);

  list = g_list_sort (list, (GCompareFunc)gwa_signal_comp);
  *signals = g_list_concat (list, *signals);
341 342 343
}

static GList *
344
gwa_list_signals (GladeWidgetAdaptor *adaptor, GType real_type)
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
{
  GList *signals = NULL;
  GType type, parent, *i, *p;

  g_return_val_if_fail (real_type != 0, NULL);

  for (type = real_type; g_type_is_a (type, G_TYPE_OBJECT); type = parent)
    {
      parent = g_type_parent (type);

      /* Add class signals */
      gwa_add_signals (adaptor, &signals, type);

      /* Add class interfaces signals */
      for (i = p = g_type_interfaces (type, NULL); *i; i++)
360
        if (!g_type_is_a (parent, *i))
361 362 363 364 365 366 367 368 369
          gwa_add_signals (adaptor, &signals, *i);

      g_free (p);
    }

  return g_list_reverse (signals);
}

static GList *
370
gwa_clone_parent_properties (GladeWidgetAdaptor *adaptor, gboolean is_packing)
371 372 373 374 375 376
{
  GladeWidgetAdaptor *parent_adaptor;
  GList *properties = NULL, *list, *proplist;

  if ((parent_adaptor = gwa_get_parent_adaptor (adaptor)) != NULL)
    {
377 378
      gboolean reset_version;

379
      proplist = is_packing ?
380
          parent_adaptor->priv->packing_props : parent_adaptor->priv->properties;
381

382
      /* Reset versioning in derived catalogs just once */
383
      reset_version = strcmp (adaptor->priv->catalog, parent_adaptor->priv->catalog) != 0;
384

385 386
      for (list = proplist; list; list = list->next)
        {
387 388 389
          GladePropertyClass *pclass = glade_property_class_clone (list->data, reset_version);

	  glade_property_class_set_adaptor (pclass, adaptor);
390 391 392 393 394 395

          properties = g_list_prepend (properties, pclass);
        }
    }

  return g_list_reverse (properties);
396 397 398
}

static void
399 400
gwa_setup_introspected_props_from_pspecs (GladeWidgetAdaptor *adaptor,
                                          GParamSpec **specs,
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
                                          gint n_specs, gboolean is_packing)
{
  GladeWidgetAdaptor *parent_adaptor = gwa_get_parent_adaptor (adaptor);
  GladePropertyClass *property_class;
  gint i;
  GList *list = NULL;

  for (i = 0; i < n_specs; i++)
    {
      if (parent_adaptor == NULL ||
          /* Dont create it if it already exists */
          (!is_packing &&
           !glade_widget_adaptor_get_property_class (parent_adaptor,
                                                     specs[i]->name)) ||
          (is_packing &&
           !glade_widget_adaptor_get_pack_property_class (parent_adaptor,
                                                          specs[i]->name)))
        {
          if ((property_class =
               glade_property_class_new_from_spec (adaptor, specs[i])) != NULL)
            list = g_list_prepend (list, property_class);
        }
    }

  if (is_packing)
426 427
    adaptor->priv->packing_props =
        g_list_concat (adaptor->priv->packing_props, g_list_reverse (list));
428
  else
429 430
    adaptor->priv->properties =
        g_list_concat (adaptor->priv->properties, g_list_reverse (list));
431 432 433
}

static void
434 435
gwa_setup_properties (GladeWidgetAdaptor *adaptor,
                      GObjectClass *object_class, gboolean is_packing)
436 437 438 439 440 441
{
  GParamSpec **specs = NULL;
  guint n_specs = 0;
  GList *l;

  /* only GtkContainer child propeties can be introspected */
442
  if (is_packing && !g_type_is_a (adaptor->priv->type, GTK_TYPE_CONTAINER))
443 444 445 446
    return;

  /* First clone the parents properties */
  if (is_packing)
447
    adaptor->priv->packing_props = gwa_clone_parent_properties (adaptor, is_packing);
448
  else
449
    adaptor->priv->properties = gwa_clone_parent_properties (adaptor, is_packing);
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471

  /* Now automaticly introspect new properties added in this class,
   * allow the class writer to decide what to override in the resulting
   * list of properties.
   */
  if (is_packing)
    specs = gtk_container_class_list_child_properties (object_class, &n_specs);
  else
    specs = g_object_class_list_properties (object_class, &n_specs);
  gwa_setup_introspected_props_from_pspecs (adaptor, specs, n_specs,
                                            is_packing);
  g_free (specs);

  if (is_packing)
    {
      /* We have to mark packing properties from GladeWidgetAdaptor
       * because GladePropertyClass doesnt have a valid parent GType
       * to introspect it.
       *
       * (which could be used to call gtk_container_class_find_child_property()
       * and properly introspect whether or not its a packing property).
       */
472
      for (l = adaptor->priv->packing_props; l; l = l->next)
473 474
        {
          GladePropertyClass *property_class = l->data;
475 476

	  glade_property_class_set_is_packing (property_class, TRUE);
477 478
        }
    }
479 480 481
}

static GList *
482
gwa_inherit_child_packing (GladeWidgetAdaptor *adaptor)
483
{
484 485
  GladeWidgetAdaptor *parent_adaptor;
  GList *child_packings = NULL, *packing_list, *default_list;
486

487 488
  if ((parent_adaptor = gwa_get_parent_adaptor (adaptor)) != NULL)
    {
489
      for (packing_list = parent_adaptor->priv->child_packings;
490 491 492 493
           packing_list; packing_list = packing_list->next)
        {
          GladeChildPacking *packing = packing_list->data;
          GladeChildPacking *packing_dup = g_new0 (GladeChildPacking, 1);
494

495
          packing_dup->parent_name = g_strdup (packing->parent_name);
496

497 498 499 500 501
          for (default_list = packing->packing_defaults;
               default_list; default_list = default_list->next)
            {
              GladePackingDefault *def = default_list->data;
              GladePackingDefault *def_dup = g_new0 (GladePackingDefault, 1);
502

503 504
              def_dup->id = g_strdup (def->id);
              def_dup->value = g_strdup (def->value);
505

506 507 508
              packing_dup->packing_defaults =
                  g_list_prepend (packing_dup->packing_defaults, def_dup);
            }
509

510 511 512 513
          child_packings = g_list_prepend (child_packings, packing_dup);
        }
    }
  return child_packings;
514 515
}

516
static void
517
gwa_inherit_signals (GladeWidgetAdaptor *adaptor)
518 519 520 521 522 523 524
{
  GladeWidgetAdaptor *parent_adaptor;
  GList *list, *node;
  GladeSignalClass *signal, *parent_signal;

  if ((parent_adaptor = gwa_get_parent_adaptor (adaptor)) != NULL)
    {
525
      for (list = adaptor->priv->signals; list; list = list->next)
526 527 528
        {
          signal = list->data;

529 530 531
          if ((node = g_list_find_custom (parent_adaptor->priv->signals, 
					  glade_signal_class_get_name (signal),
					  (GCompareFunc) gwa_signal_find_comp)) != NULL)
532 533 534
            {
              parent_signal = node->data;

535 536 537 538 539
              /* XXX FIXME: This is questionable, why should derived catalogs
	       * reset the derived signal versions ???
	       *
	       * Reset versioning in derived catalogs just once
	       */
540 541
              if (strcmp (adaptor->priv->catalog,
                          parent_adaptor->priv->catalog))
542
		glade_signal_class_set_since (signal, 0, 0);
543
              else
544 545 546
		glade_signal_class_set_since (signal, 
					      glade_signal_class_since_major (parent_signal),
					      glade_signal_class_since_minor (parent_signal));
547 548

	      glade_signal_class_set_deprecated (signal, glade_signal_class_deprecated (parent_signal));
549 550 551
            }
        }
    }
552 553
}

554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
static GladeInternalChild *
gwa_internal_children_new (gchar *name, gboolean anarchist)
{
  GladeInternalChild *data = g_slice_new0 (GladeInternalChild);

  data->name = g_strdup (name);
  data->anarchist = anarchist;

  return data;
}

static GList *
gwa_internal_children_clone (GList *children)
{
  GList *l, *retval = NULL;
  
  for (l = children; l; l = g_list_next (l))
    {
      GladeInternalChild *data, *child = l->data;

      data = gwa_internal_children_new (child->name, child->anarchist);
      retval = g_list_prepend (retval, data);

      if (child->children)
        data->children = gwa_internal_children_clone (child->children);
    }

  return g_list_reverse (retval);
}

584
static GObject *
585 586 587 588 589 590 591 592 593 594
glade_widget_adaptor_constructor (GType type,
                                  guint n_construct_properties,
                                  GObjectConstructParam * construct_properties)
{
  GladeWidgetAdaptor *adaptor, *parent_adaptor;
  GObject *ret_obj;
  GObjectClass *object_class;

  glade_abort_if_derived_adaptors_exist (type);

595
  ret_obj = G_OBJECT_CLASS (glade_widget_adaptor_parent_class)->constructor
596 597 598 599 600
      (type, n_construct_properties, construct_properties);

  adaptor = GLADE_WIDGET_ADAPTOR (ret_obj);
  parent_adaptor = gwa_get_parent_adaptor (adaptor);

601
  if (adaptor->priv->type == G_TYPE_NONE)
602
    g_warning ("Adaptor created without a type");
603
  if (adaptor->priv->name == NULL)
604 605 606
    g_warning ("Adaptor created without a name");

  /* Build decorations */
607
  if (!adaptor->priv->icon_name)
608
    adaptor->priv->icon_name = g_strdup ("gtk-missing-image");
609 610

  /* Let it leek */
611
  if ((object_class = g_type_class_ref (adaptor->priv->type)))
612 613
    {
      /* Build signals & properties */
614
      adaptor->priv->signals = gwa_list_signals (adaptor, adaptor->priv->type);
615 616 617 618 619 620 621

      gwa_inherit_signals (adaptor);
      gwa_setup_properties (adaptor, object_class, FALSE);
      gwa_setup_properties (adaptor, object_class, TRUE);
    }

  /* Inherit packing defaults here */
622
  adaptor->priv->child_packings = gwa_inherit_child_packing (adaptor);
623 624 625 626 627 628 629 630 631 632

  /* Inherit special-child-type */
  if (parent_adaptor)
    adaptor->priv->special_child_type =
        parent_adaptor->priv->special_child_type ?
        g_strdup (parent_adaptor->priv->special_child_type) : NULL;


  /* Reset version numbering if we're in a new catalog just once */
  if (parent_adaptor &&
633
      strcmp (adaptor->priv->catalog, parent_adaptor->priv->catalog))
634 635 636 637 638 639 640 641 642 643
    {
      GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->version_since_major =
          GLADE_WIDGET_ADAPTOR_GET_CLASS (adaptor)->version_since_minor = 0;
    }

  /* Copy parent actions */
  if (parent_adaptor)
    {
      GList *l;

644
      if (parent_adaptor->priv->actions)
645
        {
646
          for (l = parent_adaptor->priv->actions; l; l = g_list_next (l))
647 648
            {
              GWActionClass *child = glade_widget_action_class_clone (l->data);
649
              adaptor->priv->actions = g_list_prepend (adaptor->priv->actions, child);
650
            }
651
          adaptor->priv->actions = g_list_reverse (adaptor->priv->actions);
652 653
        }

654
      if (parent_adaptor->priv->packing_actions)
655
        {
656
          for (l = parent_adaptor->priv->packing_actions; l; l = g_list_next (l))
657 658
            {
              GWActionClass *child = glade_widget_action_class_clone (l->data);
659 660
              adaptor->priv->packing_actions =
                  g_list_prepend (adaptor->priv->packing_actions, child);
661
            }
662
          adaptor->priv->packing_actions = g_list_reverse (adaptor->priv->packing_actions);
663 664 665
        }
    }

666 667 668 669
  /* Copy parent internal children */
  if (parent_adaptor && parent_adaptor->priv->internal_children)
    adaptor->priv->internal_children = gwa_internal_children_clone (parent_adaptor->priv->internal_children);

670
  return ret_obj;
671 672 673
}

static void
674
gwa_packing_default_free (GladePackingDefault * def)
675
{
676 677
  g_free (def->id);
  g_free (def->value);
678 679 680
}

static void
681
gwa_child_packing_free (GladeChildPacking * packing)
682
{
683
  g_free (packing->parent_name);
684

685 686 687
  g_list_foreach (packing->packing_defaults,
                  (GFunc) gwa_packing_default_free, NULL);
  g_list_free (packing->packing_defaults);
688 689
}

690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
static void
gwa_glade_internal_child_free (GladeInternalChild *child)
{
  g_free (child->name);

  if (child->children)
    {
      g_list_foreach (child->children, (GFunc) gwa_glade_internal_child_free, NULL);
      g_list_free (child->children);
    }
  
  g_slice_free (GladeInternalChild, child);
}

static void
gwa_internal_children_free (GladeWidgetAdaptor *adaptor)
{
  if (adaptor->priv->internal_children)
    {
      g_list_foreach (adaptor->priv->internal_children,
                      (GFunc) gwa_glade_internal_child_free, NULL);
      g_list_free (adaptor->priv->internal_children);
      adaptor->priv->internal_children = NULL;
    }
}

716
static void
717
glade_widget_adaptor_finalize (GObject *object)
718 719
{
  GladeWidgetAdaptor *adaptor = GLADE_WIDGET_ADAPTOR (object);
720

721
  /* Free properties and signals */
722 723
  g_list_foreach (adaptor->priv->properties, (GFunc) glade_property_class_free, NULL);
  g_list_free (adaptor->priv->properties);
724

725
  g_list_foreach (adaptor->priv->packing_props, (GFunc) glade_property_class_free,
726
                  NULL);
727
  g_list_free (adaptor->priv->packing_props);
728 729 730

  /* Be careful, this list holds GladeSignalClass* not GladeSignal,
   * thus g_free is enough as all members are const */
731 732 733
  g_list_foreach (adaptor->priv->signals, (GFunc) g_free, NULL);
  g_list_free (adaptor->priv->signals);

734 735

  /* Free child packings */
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
  g_list_foreach (adaptor->priv->child_packings,
                  (GFunc) gwa_child_packing_free, NULL);
  g_list_free (adaptor->priv->child_packings);

  if (adaptor->priv->book)
    g_free (adaptor->priv->book);
  if (adaptor->priv->catalog)
    g_free (adaptor->priv->catalog);
  if (adaptor->priv->special_child_type)
    g_free (adaptor->priv->special_child_type);

  if (adaptor->priv->cursor != NULL)
    g_object_unref (adaptor->priv->cursor);

  if (adaptor->priv->name)
    g_free (adaptor->priv->name);
  if (adaptor->priv->generic_name)
    g_free (adaptor->priv->generic_name);
  if (adaptor->priv->title)
    g_free (adaptor->priv->title);
  if (adaptor->priv->icon_name)
    g_free (adaptor->priv->icon_name);
  if (adaptor->priv->missing_icon)
    g_free (adaptor->priv->missing_icon);

  if (adaptor->priv->actions)
    {
      g_list_foreach (adaptor->priv->actions,
764
                      (GFunc) glade_widget_action_class_free, NULL);
765
      g_list_free (adaptor->priv->actions);
766 767
    }

768
  if (adaptor->priv->packing_actions)
769
    {
770
      g_list_foreach (adaptor->priv->packing_actions,
771
                      (GFunc) glade_widget_action_class_free, NULL);
772
      g_list_free (adaptor->priv->packing_actions);
773 774
    }

775 776
  gwa_internal_children_free (adaptor);

777
  G_OBJECT_CLASS (glade_widget_adaptor_parent_class)->finalize (object);
778 779 780
}

static void
781
glade_widget_adaptor_real_set_property (GObject *object,
782
                                        guint prop_id,
783 784
                                        const GValue *value,
                                        GParamSpec *pspec)
785 786 787 788 789 790 791 792 793
{
  GladeWidgetAdaptor *adaptor;

  adaptor = GLADE_WIDGET_ADAPTOR (object);

  switch (prop_id)
    {
      case PROP_NAME:
        /* assume once (construct-only) */
794 795
        adaptor->priv->name = g_value_dup_string (value);
        adaptor->priv->real_type = g_type_from_name (adaptor->priv->name);
796 797 798
        break;
      case PROP_ICON_NAME:
        /* assume once (construct-only) */
799
        adaptor->priv->icon_name = g_value_dup_string (value);
800 801
        break;
      case PROP_TYPE:
802
        adaptor->priv->type = g_value_get_gtype (value);
803 804
        break;
      case PROP_TITLE:
805 806 807
        if (adaptor->priv->title)
          g_free (adaptor->priv->title);
        adaptor->priv->title = g_value_dup_string (value);
808 809
        break;
      case PROP_GENERIC_NAME:
810 811 812
        if (adaptor->priv->generic_name)
          g_free (adaptor->priv->generic_name);
        adaptor->priv->generic_name = g_value_dup_string (value);
813 814 815
        break;
      case PROP_CATALOG:
        /* assume once (construct-only) */
816
	g_free (adaptor->priv->catalog);
817 818 819 820
        adaptor->priv->catalog = g_value_dup_string (value);
        break;
      case PROP_BOOK:
        /* assume once (construct-only) */
821
	g_free (adaptor->priv->book);
822 823 824
        adaptor->priv->book = g_value_dup_string (value);
        break;
      case PROP_SPECIAL_TYPE:
825 826 827
        /* assume once (construct-only) */ 
	g_free (adaptor->priv->special_child_type);
	adaptor->priv->special_child_type = g_value_dup_string (value);
828 829 830 831 832
        break;
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
833 834 835
}

static void
836
glade_widget_adaptor_real_get_property (GObject *object,
837
                                        guint prop_id,
838 839
                                        GValue *value,
                                        GParamSpec *pspec)
840 841 842 843 844 845 846 847 848
{

  GladeWidgetAdaptor *adaptor;

  adaptor = GLADE_WIDGET_ADAPTOR (object);

  switch (prop_id)
    {
      case PROP_NAME:
849
        g_value_set_string (value, adaptor->priv->name);
850 851
        break;
      case PROP_TYPE:
852
        g_value_set_gtype (value, adaptor->priv->type);
853 854
        break;
      case PROP_TITLE:
855
        g_value_set_string (value, adaptor->priv->title);
856 857
        break;
      case PROP_GENERIC_NAME:
858
        g_value_set_string (value, adaptor->priv->generic_name);
859 860
        break;
      case PROP_ICON_NAME:
861
        g_value_set_string (value, adaptor->priv->icon_name);
862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878
        break;
      case PROP_CATALOG:
        g_value_set_string (value, adaptor->priv->catalog);
        break;
      case PROP_BOOK:
        g_value_set_string (value, adaptor->priv->book);
        break;
      case PROP_SPECIAL_TYPE:
        g_value_set_string (value, adaptor->priv->special_child_type);
        break;
      case PROP_CURSOR:
        g_value_set_pointer (value, adaptor->priv->cursor);
        break;
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
879 880
}

881 882 883
/*******************************************************************************
                  GladeWidgetAdaptor base class implementations
 *******************************************************************************/
884
static GladeWidget *
885 886
glade_widget_adaptor_object_create_widget (GladeWidgetAdaptor *adaptor,
                                           const gchar *first_property_name,
887
                                           va_list var_args)
888
{
889 890
  return GLADE_WIDGET (g_object_new_valist (GLADE_TYPE_WIDGET,
                                            first_property_name, var_args));
891 892
}

893
static GObject *
894
glade_widget_adaptor_object_construct_object (GladeWidgetAdaptor *adaptor,
895
                                              guint n_parameters,
896
                                              GParameter *parameters)
897
{
898
  return g_object_newv (adaptor->priv->type, n_parameters, parameters);
899 900
}

901 902 903 904 905 906 907
static void
glade_widget_adaptor_object_destroy_object (GladeWidgetAdaptor *adaptor,
					    GObject            *object)
{
  /* Do nothing, just have a method here incase classes chain up */
}

908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923

static GObject *
glade_widget_adaptor_object_get_internal_child (GladeWidgetAdaptor *adaptor,
                                                GObject *object,
                                                const gchar *name)
{
  static GtkBuilder *builder = NULL;
  
  g_return_val_if_fail (GTK_IS_BUILDABLE (object), NULL);

  /* Dummy object just in case the interface use it for something */
  if (builder == NULL) builder = gtk_builder_new ();
  
  return gtk_buildable_get_internal_child (GTK_BUILDABLE (object), builder, name);
}

924 925 926 927 928 929 930 931 932 933 934 935 936 937
static gboolean
glade_widget_adaptor_object_add_verify (GladeWidgetAdaptor *adaptor,
					GObject            *parent,
					GObject            *child,
					gboolean            user_feedback)
{
  if (user_feedback)
    glade_util_ui_message (glade_app_get_window (),
			   GLADE_UI_INFO, NULL,
			   _("%s does not support adding any children."), 
			   adaptor->priv->title);

  return FALSE;
}
938

939
static void
940 941 942 943
glade_widget_adaptor_object_set_property (GladeWidgetAdaptor *adaptor,
                                          GObject *object,
                                          const gchar *property_name,
                                          const GValue *value)
944
{
945
  g_object_set_property (object, property_name, value);
946 947 948
}

static void
949 950 951 952
glade_widget_adaptor_object_get_property (GladeWidgetAdaptor *adaptor,
                                          GObject *object,
                                          const gchar *property_name,
                                          GValue *value)
953
{
954
  g_object_get_property (object, property_name, value);
955 956
}

957
static void
958 959 960
glade_widget_adaptor_object_action_activate (GladeWidgetAdaptor *adaptor,
                                             GObject *object,
                                             const gchar *action_id)
961
{
962
  g_message ("No action_activate() support in adaptor %s for action '%s'",
963
             adaptor->priv->name, action_id);
964
}
965

966
static void
967 968 969 970
glade_widget_adaptor_object_child_action_activate (GladeWidgetAdaptor *adaptor,
                                                   GObject *container,
                                                   GObject *object,
                                                   const gchar *action_id)
971
{
972
  g_message ("No child_action_activate() support in adaptor %s for action '%s'",
973
             adaptor->priv->name, action_id);
974 975
}

976
static gboolean
977 978 979
glade_widget_adaptor_object_depends (GladeWidgetAdaptor *adaptor,
                                     GladeWidget *widget,
                                     GladeWidget *another)
980
{
981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
  GList   *prop_refs, *l;
  gboolean depends = FALSE;

  prop_refs = glade_widget_list_prop_refs (another);

  for (l = prop_refs; !depends && l; l = l->next)
    {
      GladeProperty *property = l->data;
      GladeWidget   *prop_widget = glade_property_get_widget (property);

      /* If one of the properties that reference @another is
       * owned by @widget then @widget depends on @another
       */
      if (prop_widget == widget)
	depends = TRUE;

      /* Or if the widget that owns a property which references
       * @another is somewhere inside @widget... then @widget
       * also depends on @another.
       */
      else if (glade_widget_is_ancestor (prop_widget, widget))
	depends = TRUE;
    }

  g_list_free (prop_refs);

  return depends;
1008 1009
}

1010
static void
1011 1012 1013
glade_widget_adaptor_object_read_widget (GladeWidgetAdaptor *adaptor,
                                         GladeWidget *widget,
                                         GladeXmlNode *node)
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037
{
  GladeXmlNode *iter_node;
  GladeSignal *signal;
  GladeProperty *property;
  gchar *name, *prop_name;
  GList *read_properties = NULL, *l;

  /* Read in the properties */
  for (iter_node = glade_xml_node_get_children (node);
       iter_node; iter_node = glade_xml_node_next (iter_node))
    {
      if (!glade_xml_node_verify_silent (iter_node, GLADE_XML_TAG_PROPERTY))
        continue;

      /* Get prop name from node and lookup property ... */
      if (!(name = glade_xml_get_property_string_required
            (iter_node, GLADE_XML_TAG_NAME, NULL)))
        continue;

      prop_name = glade_util_read_prop_name (name);

      /* Some properties may be special child type of custom, just leave them for the adaptor */
      if ((property = glade_widget_get_property (widget, prop_name)) != NULL)
        {
1038
          glade_property_read (property, glade_widget_get_project (widget), iter_node);
1039 1040 1041 1042 1043 1044 1045 1046
          read_properties = g_list_prepend (read_properties, property);
        }

      g_free (prop_name);
      g_free (name);
    }

  /* Sync the remaining values not read in from the Glade file.. */
1047
  for (l = glade_widget_get_properties (widget); l; l = l->next)
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
    {
      property = l->data;

      if (!g_list_find (read_properties, property))
        glade_property_sync (property);
    }
  g_list_free (read_properties);

  /* Read in the signals */
  for (iter_node = glade_xml_node_get_children (node);
       iter_node; iter_node = glade_xml_node_next (iter_node))
    {
      if (!glade_xml_node_verify_silent (iter_node, GLADE_XML_TAG_SIGNAL))
        continue;

1063
      if (!(signal = glade_signal_read (iter_node, adaptor)))
1064 1065
        continue;

1066 1067
      /* The widget doesnt use the signal handler directly but rather
       * creates it's own copy */
1068
      glade_widget_add_signal_handler (widget, signal);
1069
      g_object_unref (signal);
1070 1071 1072 1073 1074 1075 1076 1077 1078
    }

  /* Read in children */
  for (iter_node = glade_xml_node_get_children (node);
       iter_node; iter_node = glade_xml_node_next (iter_node))
    {
      if (glade_xml_node_verify_silent (iter_node, GLADE_XML_TAG_CHILD))
        glade_widget_read_child (widget, iter_node);

1079
      if (glade_project_load_cancelled (glade_widget_get_project (widget)))
1080 1081
        return;
    }
1082 1083 1084
}

static void
1085 1086 1087 1088
glade_widget_adaptor_object_write_widget (GladeWidgetAdaptor *adaptor,
                                          GladeWidget *widget,
                                          GladeXmlContext *context,
                                          GladeXmlNode *node)
1089
{
1090
  GList *props;
1091

1092
  /* Write the properties */
1093
  for (props = glade_widget_get_properties (widget); props; props = props->next)
1094
    {
1095 1096 1097
      GladeProperty      *property = props->data;
      GladePropertyClass *klass = glade_property_get_class (property);

1098 1099
      if (glade_property_class_save (klass) && 
	  glade_property_get_enabled (property))
1100 1101
        glade_property_write (GLADE_PROPERTY (props->data), context, node);
    }
1102 1103
}

1104 1105 1106 1107 1108 1109 1110 1111 1112
static void
glade_widget_adaptor_object_write_widget_after (GladeWidgetAdaptor *adaptor,
						GladeWidget *widget,
						GladeXmlContext *context,
						GladeXmlNode *node)
{

}

1113
static void
1114 1115 1116
glade_widget_adaptor_object_read_child (GladeWidgetAdaptor *adaptor,
                                        GladeWidget *widget,
                                        GladeXmlNode *node)
1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
{
  GladeXmlNode *widget_node, *packing_node, *iter_node;
  GladeWidget *child_widget;
  gchar *internal_name;
  gchar *name, *prop_name;
  GladeProperty *property;

  if (!glade_xml_node_verify (node, GLADE_XML_TAG_CHILD))
    return;

  internal_name =
      glade_xml_get_property_string (node, GLADE_XML_TAG_INTERNAL_CHILD);

  if ((widget_node =
       glade_xml_search_child (node, GLADE_XML_TAG_WIDGET)) != NULL)
    {
      child_widget =
1134 1135
	glade_widget_read (glade_widget_get_project (widget),
			   widget, widget_node, internal_name);
1136 1137 1138 1139 1140 1141

      if (child_widget)
        {
          if (!internal_name)
            {
              glade_widget_set_child_type_from_node
1142
		(widget, glade_widget_get_object (child_widget), node);
1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
              glade_widget_add_child (widget, child_widget, FALSE);
            }

          if ((packing_node =
               glade_xml_search_child (node, GLADE_XML_TAG_PACKING)) != NULL)
            {

              /* Read in the properties */
              for (iter_node = glade_xml_node_get_children (packing_node);
                   iter_node; iter_node = glade_xml_node_next (iter_node))
                {
                  if (!glade_xml_node_verify_silent
                      (iter_node, GLADE_XML_TAG_PROPERTY))
                    continue;

                  /* Get prop name from node and lookup property ... */
                  if (!(name = glade_xml_get_property_string_required
                        (iter_node, GLADE_XML_TAG_NAME, NULL)))
                    continue;

                  prop_name = glade_util_read_prop_name (name);

                  /* Some properties may be special child type of custom, 
                   * just leave them for the adaptor */
                  if ((property =
                       glade_widget_get_pack_property (child_widget,
                                                       prop_name)) != NULL)
1170 1171
                    glade_property_read (property, 
					 glade_widget_get_project (child_widget),
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
                                         iter_node);

                  g_free (prop_name);
                  g_free (name);
                }
            }
        }

    }
  else
    {
      GObject *palaceholder = G_OBJECT (glade_placeholder_new ());
      glade_widget_set_child_type_from_node (widget, palaceholder, node);
1185
      glade_widget_adaptor_add (adaptor, glade_widget_get_object (widget), palaceholder);
1186 1187
    }
  g_free (internal_name);
1188 1189 1190
}

static void
1191 1192 1193 1194
glade_widget_adaptor_object_write_child (GladeWidgetAdaptor *adaptor,
                                         GladeWidget *widget,
                                         GladeXmlContext *context,
                                         GladeXmlNode *node)
1195 1196 1197 1198 1199 1200 1201 1202
{
  GladeXmlNode *child_node, *packing_node;
  GList *props;

  child_node = glade_xml_node_new (context, GLADE_XML_TAG_CHILD);
  glade_xml_node_append_child (node, child_node);

  /* Set internal child */
1203
  if (glade_widget_get_internal (widget))
1204 1205
    glade_xml_node_set_property_string (child_node,
                                        GLADE_XML_TAG_INTERNAL_CHILD,
1206
                                        glade_widget_get_internal (widget));
1207 1208 1209 1210 1211 1212 1213 1214

  /* Write out the widget */
  glade_widget_write (widget, context, child_node);

  /* Write out packing properties and special-child-type */
  packing_node = glade_xml_node_new (context, GLADE_XML_TAG_PACKING);
  glade_xml_node_append_child (child_node, packing_node);

1215
  for (props = glade_widget_get_packing_properties (widget); props; props = props->next)
1216
    {
1217 1218 1219
      GladeProperty      *property = props->data;
      GladePropertyClass *klass = glade_property_get_class (property);

1220 1221
      if (glade_property_class_save (klass) && 
	  glade_property_get_enabled (property))
1222 1223 1224 1225
        glade_property_write (GLADE_PROPERTY (props->data),
                              context, packing_node);
    }

1226 1227 1228
  glade_widget_write_special_child_prop (glade_widget_get_parent (widget),
                                         glade_widget_get_object (widget), 
					 context, child_node);
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241

  /* Default packing properties and such are not saved,
   * so lets check afterwords if there was anything saved
   * and then just remove the node.
   */
  if (!glade_xml_node_get_children (packing_node))
    {
      glade_xml_node_remove (packing_node);
      glade_xml_node_delete (packing_node);
    }
}

static GType
1242
glade_widget_adaptor_get_eprop_type (GParamSpec *pspec)
1243 1244 1245 1246 1247 1248 1249 1250 1251
{
  GType type = 0;

  if (G_IS_PARAM_SPEC_ENUM (pspec))
    type = GLADE_TYPE_EPROP_ENUM;
  else if (G_IS_PARAM_SPEC_FLAGS (pspec))
    type = GLADE_TYPE_EPROP_FLAGS;
  else if (G_IS_PARAM_SPEC_VALUE_ARRAY (pspec))
    {
1252 1253
      /* Require deprecated code */
      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1254 1255
      if (pspec->value_type == G_TYPE_VALUE_ARRAY)
        type = GLADE_TYPE_EPROP_TEXT;
1256
      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
1257 1258 1259
    }
  else if (G_IS_PARAM_SPEC_BOXED (pspec))
    {
1260 1261
      if (pspec->value_type == GDK_TYPE_COLOR ||
	  pspec->value_type == GDK_TYPE_RGBA)
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290
        type = GLADE_TYPE_EPROP_COLOR;
      else if (pspec->value_type == G_TYPE_STRV)
        type = GLADE_TYPE_EPROP_TEXT;
    }
  else if (G_IS_PARAM_SPEC_STRING (pspec))
    type = GLADE_TYPE_EPROP_TEXT;
  else if (G_IS_PARAM_SPEC_BOOLEAN (pspec))
    type = GLADE_TYPE_EPROP_BOOL;
  else if (G_IS_PARAM_SPEC_FLOAT (pspec) ||
           G_IS_PARAM_SPEC_DOUBLE (pspec) ||
           G_IS_PARAM_SPEC_INT (pspec) ||
           G_IS_PARAM_SPEC_UINT (pspec) ||
           G_IS_PARAM_SPEC_LONG (pspec) ||
           G_IS_PARAM_SPEC_ULONG (pspec) ||
           G_IS_PARAM_SPEC_INT64 (pspec) || G_IS_PARAM_SPEC_UINT64 (pspec))
    type = GLADE_TYPE_EPROP_NUMERIC;
  else if (G_IS_PARAM_SPEC_UNICHAR (pspec))
    type = GLADE_TYPE_EPROP_UNICHAR;
  else if (G_IS_PARAM_SPEC_OBJECT (pspec))
    {
      if (pspec->value_type == GDK_TYPE_PIXBUF)
        type = GLADE_TYPE_EPROP_TEXT;
      else
        type = GLADE_TYPE_EPROP_OBJECT;
    }
  else if (GLADE_IS_PARAM_SPEC_OBJECTS (pspec))
    type = GLADE_TYPE_EPROP_OBJECTS;

  return type;
1291 1292 1293
}

static GladeEditorProperty *
1294 1295
glade_widget_adaptor_object_create_eprop (GladeWidgetAdaptor *adaptor,
                                          GladePropertyClass *klass,
1296
                                          gboolean use_command)
1297
{
1298
  GladeEditorProperty *eprop;
1299 1300 1301 1302
  GParamSpec          *pspec;
  GType                type = 0;

  pspec = glade_property_class_get_pspec (klass);
1303 1304 1305 1306

  /* Find the right type of GladeEditorProperty for this
   * GladePropertyClass.
   */
1307
  if ((type = glade_widget_adaptor_get_eprop_type (pspec)) == 0)
1308
    return NULL;
1309

1310
  /* special case for string specs that denote themed application icons. */
1311
  if (glade_property_class_themed_icon (klass))
1312
    type = GLADE_TYPE_EPROP_NAMED_ICON;
1313

1314 1315 1316 1317
  /* Create and return the correct type of GladeEditorProperty */
  eprop = g_object_new (type,
                        "property-class", klass,
                        "use-command", use_command, NULL);
1318

1319
  return eprop;
1320 1321 1322
}

static gchar *
1323 1324 1325
glade_widget_adaptor_object_string_from_value (GladeWidgetAdaptor *adaptor,
                                               GladePropertyClass *klass,
                                               const GValue *value)
1326
{
1327
  return glade_property_class_make_string_from_gvalue (klass, value);
1328 1329
}

1330
static GladeEditable *
1331
glade_widget_adaptor_object_create_editable (GladeWidgetAdaptor *adaptor,
1332
                                             GladeEditorPageType type)
1333
{
1334
  return (GladeEditable *) glade_editor_table_new (adaptor, type);
1335 1336
}

1337 1338 1339
static GList *
glade_widget_adaptor_object_get_children (GladeWidgetAdaptor *adaptor,
                                          GObject *object)
1340
{
1341 1342
  GList *list = adaptor->priv->internal_children;
  GList *l, *children = NULL;
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352
  
  for (l = list; l; l = g_list_next (l))
    {
      GladeInternalChild *internal = l->data;
      GObject *child;
        
      child = glade_widget_adaptor_get_internal_child (adaptor,
                                                       object,
                                                       internal->name);
      if (child)
1353
        children = g_list_prepend (children, child);
1354 1355 1356 1357 1358
    }

  return children;
}

1359

1360 1361 1362
/*******************************************************************************
            GladeWidgetAdaptor type registration and class initializer
 *******************************************************************************/
1363
static void
1364
glade_widget_adaptor_init (GladeWidgetAdaptor *adaptor)
1365
{
1366
  adaptor->priv = GLADE_WIDGET_ADAPTOR_GET_PRIVATE (adaptor);
1367

1368 1369 1370
}

static void
1371
glade_widget_adaptor_class_init (GladeWidgetAdaptorClass *adaptor_class)
1372 1373 1374 1375
{
  GObjectClass *object_class;
  g_return_if_fail (adaptor_class != NULL);

1376
  glade_widget_adaptor_parent_class = g_type_class_peek_parent (adaptor_class);
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386
  object_class = G_OBJECT_CLASS (adaptor_class);

  /* GObjectClass */
  object_class->constructor = glade_widget_adaptor_constructor;
  object_class->finalize = glade_widget_adaptor_finalize;
  object_class->set_property = glade_widget_adaptor_real_set_property;
  object_class->get_property = glade_widget_adaptor_real_get_property;

  /* Class methods */
  adaptor_class->create_widget = glade_widget_adaptor_object_create_widget;
1387
  adaptor_class->construct_object = glade_widget_adaptor_object_construct_object;
1388
  adaptor_class->destroy_object = glade_widget_adaptor_object_destroy_object;
1389 1390
  adaptor_class->deep_post_create = NULL;
  adaptor_class->post_create = NULL;
1391
  adaptor_class->get_internal_child = glade_widget_adaptor_object_get_internal_child;
1392 1393 1394
  adaptor_class->verify_property = NULL;
  adaptor_class->set_property = glade_widget_adaptor_object_set_property;
  adaptor_class->get_property = glade_widget_adaptor_object_get_property;
1395
  adaptor_class->add_verify = glade_widget_adaptor_object_add_verify;
1396 1397 1398
  adaptor_class->add = NULL;
  adaptor_class->remove = NULL;
  adaptor_class->replace_child = NULL;
1399
  adaptor_class->get_children = glade_widget_adaptor_object_get_children;
1400 1401 1402
  adaptor_class->child_set_property = NULL;
  adaptor_class->child_get_property = NULL;
  adaptor_class->action_activate = glade_widget_adaptor_object_action_activate;
1403
  adaptor_class->child_action_activate = glade_widget_adaptor_object_child_action_activate;
1404 1405 1406 1407
  adaptor_class->action_submenu = NULL;
  adaptor_class->depends = glade_widget_adaptor_object_depends;
  adaptor_class->read_widget = glade_widget_adaptor_object_read_widget;
  adaptor_class->write_widget = glade_widget_adaptor_object_write_widget;