glade-editor-table.c 21.8 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) 2008 Tristan Van Berkom.
 *
 * 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>
#include <glib/gi18n-lib.h>
24
#include "glade.h"
25
#include "glade-private.h"
26
#include "gladeui-enum-types.h"
27 28 29

#include "glade-editor-table.h"

30

31 32 33 34 35
#define BLOCK_NAME_ENTRY_CB(table)                                                 \
  do { if (table->priv->name_entry)                                                \
         g_signal_handlers_block_by_func (G_OBJECT (table->priv->name_entry),      \
                                          G_CALLBACK (widget_name_edited), table); \
  } while (0);
36

37 38 39 40 41
#define UNBLOCK_NAME_ENTRY_CB(table)                                                 \
  do { if (table->priv->name_entry)                                                  \
         g_signal_handlers_unblock_by_func (G_OBJECT (table->priv->name_entry),      \
                                            G_CALLBACK (widget_name_edited), table); \
  } while (0);
42 43 44



45 46
static void glade_editor_table_init          (GladeEditorTable *self);
static void glade_editor_table_class_init    (GladeEditorTableClass *klass);
47

48 49 50 51 52
static void glade_editor_table_dispose       (GObject      *object);
static void glade_editor_table_set_property  (GObject      *object,
                                              guint         prop_id,
                                              const GValue *value,
                                              GParamSpec   *pspec);
53

54 55 56
static void glade_editor_table_editable_init (GladeEditableIface *iface);
static void glade_editor_table_realize       (GtkWidget *widget);
static void glade_editor_table_grab_focus    (GtkWidget *widget);
57

58 59
static void append_name_field (GladeEditorTable   *table);
static void append_items      (GladeEditorTable   *table,
60 61
                               GladeWidgetAdaptor *adaptor,
                               GladeEditorPageType type);
62 63


64 65 66
struct _GladeEditorTablePrivate
{
  GladeWidgetAdaptor *adaptor; /* The GladeWidgetAdaptor this
67 68
                                * table was created for.
                                */
69 70

  GladeWidget *loaded_widget; /* A pointer to the currently loaded GladeWidget
71 72
                               */

73 74
  GtkWidget *name_label; /* A pointer to the "Name:" label (for show/hide) */
  GtkWidget *name_entry; /* A pointer to the gtk_entry that holds
75 76 77 78 79 80
                          * the name of the widget. This is the
                          * first item _pack'ed to the table_widget.
                          * We have a pointer here because it is an
                          * entry which will not be created from a
                          * GladeProperty but rather from code.
                          */
81 82
  GtkWidget *composite_check; /* A pointer to the composite check button */
  GtkWidget *name_field; /* A box containing the name entry and composite check */
83 84

  GList *properties; /* A list of GladeEditorPropery items.
85 86 87
                      * For each row in the gtk_table, there is a
                      * corrsponding GladeEditorProperty struct.
                      */
88 89

  GladeEditorPageType type; /* Is this table to be used in the common tab, ?
90 91
                             * the general tab, a packing tab or the query popup ?
                             */
92 93

  gint rows;
94 95

  gboolean show_name;
96
};
97

98 99 100 101 102
enum {
  PROP_0,
  PROP_PAGE_TYPE,
};

103
G_DEFINE_TYPE_WITH_CODE (GladeEditorTable, glade_editor_table, GTK_TYPE_GRID,
104
                         G_ADD_PRIVATE (GladeEditorTable)
105 106 107 108
                         G_IMPLEMENT_INTERFACE (GLADE_TYPE_EDITABLE,
                                                glade_editor_table_editable_init));

static void
109
glade_editor_table_class_init (GladeEditorTableClass *klass)
110
{
111 112
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
113

114
  object_class->dispose = glade_editor_table_dispose;
115 116
  object_class->set_property = glade_editor_table_set_property;

117 118
  widget_class->realize = glade_editor_table_realize;
  widget_class->grab_focus = glade_editor_table_grab_focus;
119

120 121 122
  g_object_class_install_property
      (object_class, PROP_PAGE_TYPE,
       g_param_spec_enum ("page-type", _("Page Type"),
123 124 125
                          _("The editor page type to create this GladeEditorTable for"),
                          GLADE_TYPE_EDITOR_PAGE_TYPE, GLADE_PAGE_GENERAL,
                          G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
126 127 128
}

static void
129
glade_editor_table_init (GladeEditorTable *self)
130
{
131
  self->priv = glade_editor_table_get_instance_private (self);
132

133 134
  gtk_orientable_set_orientation (GTK_ORIENTABLE (self),
                                  GTK_ORIENTATION_VERTICAL);
135
  gtk_grid_set_row_spacing (GTK_GRID (self), 2);
136
  gtk_grid_set_column_spacing (GTK_GRID (self), 6);
137 138 139

  /* Show name by default */
  self->priv->show_name = TRUE;
140 141 142
}

static void
143
glade_editor_table_dispose (GObject *object)
144
{
145
  GladeEditorTable *table = GLADE_EDITOR_TABLE (object);
146

147
  table->priv->properties = (g_list_free (table->priv->properties), NULL);
148

149 150 151
  /* the entry is finalized anyway, just avoid setting
   * text in it from _load();
   */
152
  table->priv->name_entry = NULL;
153

154
  glade_editable_load (GLADE_EDITABLE (table), NULL);
155

156
  G_OBJECT_CLASS (glade_editor_table_parent_class)->dispose (object);
157 158
}

159
static void
160 161 162 163
glade_editor_table_set_property (GObject      *object,
                                 guint         prop_id,
                                 const GValue *value,
                                 GParamSpec   *pspec)
164 165 166 167 168 169 170 171 172 173 174 175 176
{
  GladeEditorTable *table = GLADE_EDITOR_TABLE (object);

  switch (prop_id)
    {
    case PROP_PAGE_TYPE:
      table->priv->type = g_value_get_enum (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}
177

178
static void
179
glade_editor_table_realize (GtkWidget *widget)
180
{
181 182 183 184 185 186 187
  GladeEditorTable *table = GLADE_EDITOR_TABLE (widget);
  GList *list;
  GladeEditorProperty *property;

  GTK_WIDGET_CLASS (glade_editor_table_parent_class)->realize (widget);

  /* Sync up properties, even if widget is NULL */
188
  for (list = table->priv->properties; list; list = list->next)
189 190
    {
      property = list->data;
191
      glade_editor_property_load_by_widget (property, table->priv->loaded_widget);
192
    }
193 194
}

195
static void
196
glade_editor_table_grab_focus (GtkWidget *widget)
197
{
198 199
  GladeEditorTable *editor_table = GLADE_EDITOR_TABLE (widget);

200 201 202 203 204
  if (editor_table->priv->name_entry &&
      gtk_widget_get_mapped (editor_table->priv->name_entry))
    gtk_widget_grab_focus (editor_table->priv->name_entry);
  else if (editor_table->priv->properties)
    gtk_widget_grab_focus (GTK_WIDGET (editor_table->priv->properties->data));
205 206
  else
    GTK_WIDGET_CLASS (glade_editor_table_parent_class)->grab_focus (widget);
207 208
}

209
static void
210
widget_name_edited (GtkWidget *editable, GladeEditorTable *table)
211
{
212 213 214 215 216 217
  GladeWidget *widget;
  gchar *new_name;

  g_return_if_fail (GTK_IS_EDITABLE (editable));
  g_return_if_fail (GLADE_IS_EDITOR_TABLE (table));

218
  if (table->priv->loaded_widget == NULL)
219 220 221 222 223 224
    {
      g_warning ("Name entry edited with no loaded widget in editor %p!\n",
                 table);
      return;
    }

225
  widget = table->priv->loaded_widget;
226 227
  new_name = gtk_editable_get_chars (GTK_EDITABLE (editable), 0, -1);

228 229 230 231 232 233 234 235 236
  if (new_name == NULL || new_name[0] == '\0')
    {
      /* If we are explicitly trying to set the widget name to be empty,
       * then we must not allow it there are any active references to
       * the widget which would otherwise break.
       *
       * Otherwise, we need to allocate a new unnamed prefix name for the widget
       */
      if (!glade_widget_has_prop_refs (widget))
237 238 239 240 241
        {
          gchar *unnamed_name = glade_project_new_widget_name (glade_widget_get_project (widget), NULL, GLADE_UNNAMED_PREFIX);
          glade_command_set_name (widget, unnamed_name);
          g_free (unnamed_name);
        }
242 243
    }
  else if (glade_project_available_widget_name (glade_widget_get_project (widget), 
244
                                                widget, new_name))
245
    glade_command_set_name (widget, new_name);
246

247
  g_free (new_name);
248
}
249

250 251
static void
widget_composite_toggled (GtkToggleButton  *composite_check,
252
                          GladeEditorTable *table)
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
{
  GladeProject *project;

  if (table->priv->loaded_widget == NULL)
    {
      g_warning ("Name entry edited with no loaded widget in editor %p!\n",
                 table);
      return;
    }

  project = glade_widget_get_project (table->priv->loaded_widget);

  if (project)
    {
      if (gtk_toggle_button_get_active (composite_check))
268
        glade_command_set_project_template (project, table->priv->loaded_widget);
269
      else
270
        glade_command_set_project_template (project, NULL);
271 272 273
    }
}

274
static void
275 276
widget_name_changed (GladeWidget      *widget,
                     GParamSpec       *pspec,
277
                     GladeEditorTable *table)
278
{
279 280
  if (!gtk_widget_get_mapped (GTK_WIDGET (table)))
    return;
281

282
  if (table->priv->name_entry)
283 284
    {
      BLOCK_NAME_ENTRY_CB (table);
285

286
      if (glade_widget_has_name (table->priv->loaded_widget))
287
        gtk_entry_set_text (GTK_ENTRY (table->priv->name_entry), glade_widget_get_name (table->priv->loaded_widget));
288
      else
289
        gtk_entry_set_text (GTK_ENTRY (table->priv->name_entry), "");
290

291 292
      UNBLOCK_NAME_ENTRY_CB (table);
    }
293 294 295 296
}

static void
widget_composite_changed (GladeWidget      *widget,
297 298
                          GParamSpec       *pspec,
                          GladeEditorTable *table)
299 300 301
{
  if (!gtk_widget_get_mapped (GTK_WIDGET (table)))
    return;
302

303 304
  if (table->priv->name_label)
    gtk_label_set_text (GTK_LABEL (table->priv->name_label),
305 306
                        glade_widget_get_is_composite (table->priv->loaded_widget) ?
                        _("Class Name:") : _("ID:"));
307 308 309 310

  if (table->priv->composite_check)
    {
      g_signal_handlers_block_by_func (G_OBJECT (table->priv->composite_check),
311
                                       G_CALLBACK (widget_composite_toggled), table);
312
      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (table->priv->composite_check),
313
                                    glade_widget_get_is_composite (table->priv->loaded_widget));
314
      g_signal_handlers_unblock_by_func (G_OBJECT (table->priv->composite_check),
315
                                         G_CALLBACK (widget_composite_toggled), table);
316
    }
317
}
318 319

static void
320
widget_finalized (GladeEditorTable *table, GladeWidget *where_widget_was)
321
{
322
  table->priv->loaded_widget = NULL;
323

324
  glade_editable_load (GLADE_EDITABLE (table), NULL);
325 326 327 328
}


static void
329
glade_editor_table_load (GladeEditable *editable, GladeWidget *widget)
330
{
331 332 333 334
  GladeEditorTable *table = GLADE_EDITOR_TABLE (editable);
  GladeEditorProperty *property;
  GList *list;

335 336 337 338 339 340
  /* Setup the table the first time the widget is loaded */
  if (widget && table->priv->adaptor == NULL)
    {
      table->priv->adaptor = glade_widget_get_adaptor (widget);

      if (table->priv->type == GLADE_PAGE_GENERAL)
341
        append_name_field (table);
342 343 344 345

      append_items (table, table->priv->adaptor, table->priv->type);
    }

346
  /* abort mission */
347
  if (table->priv->loaded_widget == widget)
348 349
    return;

350
  if (table->priv->loaded_widget)
351
    {
352
      g_signal_handlers_disconnect_by_func (G_OBJECT (table->priv->loaded_widget),
353 354
                                            G_CALLBACK (widget_name_changed),
                                            table);
355 356 357
      g_signal_handlers_disconnect_by_func (G_OBJECT (table->priv->loaded_widget),
                                            G_CALLBACK (widget_composite_changed),
                                            table);
358 359

      /* The widget could die unexpectedly... */
360
      g_object_weak_unref (G_OBJECT (table->priv->loaded_widget),
361 362 363
                           (GWeakNotify) widget_finalized, table);
    }

364
  table->priv->loaded_widget = widget;
365 366 367

  BLOCK_NAME_ENTRY_CB (table);

368
  if (table->priv->loaded_widget)
369
    {
370
      g_signal_connect (G_OBJECT (table->priv->loaded_widget), "notify::name",
371 372
                        G_CALLBACK (widget_name_changed), table);

373 374 375
      g_signal_connect (G_OBJECT (table->priv->loaded_widget), "notify::composite",
                        G_CALLBACK (widget_composite_changed), table);

376
      /* The widget could die unexpectedly... */
377
      g_object_weak_ref (G_OBJECT (table->priv->loaded_widget),
378 379
                         (GWeakNotify) widget_finalized, table);

380
      if (table->priv->composite_check)
381 382 383
        {
          GObject *object = glade_widget_get_object (table->priv->loaded_widget);
          GladeWidgetAdaptor *adaptor = glade_widget_get_adaptor (table->priv->loaded_widget);
384

385 386 387 388 389 390 391 392
          if (GTK_IS_WIDGET (object) &&
              glade_widget_get_parent (table->priv->loaded_widget) == NULL)
            gtk_widget_show (table->priv->composite_check);
          else
            gtk_widget_hide (table->priv->composite_check);

          gtk_widget_set_sensitive (table->priv->composite_check,
                                    !g_str_has_prefix (glade_widget_adaptor_get_name (adaptor),
393
                                                       GWA_INSTANTIABLE_PREFIX));
394
        }
395

396
      if (table->priv->name_entry)
397 398 399 400 401 402
        {
          if (glade_widget_has_name (widget))
            gtk_entry_set_text (GTK_ENTRY (table->priv->name_entry), glade_widget_get_name (widget));
          else
            gtk_entry_set_text (GTK_ENTRY (table->priv->name_entry), "");
        }
403

404
      if (table->priv->name_label)
405
        widget_composite_changed (widget, NULL, table);
406
    }
407 408
  else if (table->priv->name_entry)
    gtk_entry_set_text (GTK_ENTRY (table->priv->name_entry), "");
409 410 411 412

  UNBLOCK_NAME_ENTRY_CB (table);

  /* Sync up properties, even if widget is NULL */
413
  for (list = table->priv->properties; list; list = list->next)
414 415 416 417
    {
      property = list->data;
      glade_editor_property_load_by_widget (property, widget);
    }
418 419
}

420
static void
421
glade_editor_table_set_show_name (GladeEditable *editable, gboolean show_name)
422
{
423 424
  GladeEditorTable *table = GLADE_EDITOR_TABLE (editable);

425
  if (table->priv->show_name != show_name)
426
    {
427 428 429
      table->priv->show_name = show_name;

      if (table->priv->name_label)
430 431 432 433
        {
          gtk_widget_set_visible (table->priv->name_label, show_name);
          gtk_widget_set_visible (table->priv->name_field, show_name);
        }
434
    }
435 436
}

437
static void
438
glade_editor_table_editable_init (GladeEditableIface *iface)
439
{
440 441
  iface->load = glade_editor_table_load;
  iface->set_show_name = glade_editor_table_set_show_name;
442 443 444
}

static void
445 446
glade_editor_table_attach (GladeEditorTable * table,
                           GtkWidget * child, gint pos, gint row)
447
{
448
  gtk_grid_attach (GTK_GRID (table), child, pos, row, 1, 1);
Tristan Van Berkom's avatar
Tristan Van Berkom committed
449

450 451
  if (pos)
    gtk_widget_set_hexpand (child, TRUE);
452 453 454 455 456
}

static gint
property_class_comp (gconstpointer a, gconstpointer b)
{
457 458
  GladePropertyClass *ca = (GladePropertyClass *)a, *cb = (GladePropertyClass *)b;
  GParamSpec *pa, *pb;
459
  const gchar *name_a, *name_b;
460

461 462 463
  pa = glade_property_class_get_pspec (ca);
  pb = glade_property_class_get_pspec (cb);

464 465 466 467 468 469 470 471 472 473
  name_a = glade_property_class_id (ca);
  name_b = glade_property_class_id (cb);

  /* Special case for the 'name' property, it *always* comes first. */
  if (strcmp (name_a, "name") == 0)
    return -1;
  else if (strcmp (name_b, "name") == 0)
    return 1;
  /* Properties of the same class are sorted in the same level */
  else if (pa->owner_type == pb->owner_type)
474
    {
475
      gdouble result = glade_property_class_weight (ca) - glade_property_class_weight (cb);
476 477 478 479 480 481 482 483
      /* Avoid cast to int */
      if (result < 0.0)
        return -1;
      else if (result > 0.0)
        return 1;
      else
        return 0;
    }
484
  /* Group properties by thier class hierarchy */
485 486
  else
    {
487 488
      if (g_type_is_a (pa->owner_type, pb->owner_type))
        return (glade_property_class_common (ca) || glade_property_class_get_is_packing (ca)) ? 1 : -1;
489
      else
490
        return (glade_property_class_common (ca) || glade_property_class_get_is_packing (ca)) ? -1 : 1;
491
    }
492 493 494
}

static GList *
495
get_sorted_properties (GladeWidgetAdaptor *adaptor, GladeEditorPageType type)
496
{
497 498
  const GList *l, *properties;
  GList *list = NULL;
499 500

  properties =
501 502 503
    (type == GLADE_PAGE_PACKING) ? 
    glade_widget_adaptor_get_packing_props (adaptor) : 
    glade_widget_adaptor_get_properties (adaptor);
504 505 506 507 508 509

  for (l = properties; l; l = g_list_next (l))
    {
      GladePropertyClass *klass = l->data;

      /* Collect properties in our domain, query dialogs are allowed editor 
510 511
       * invisible (or custom-layout) properties, allow adaptors to filter
       * out properties from the GladeEditorTable using the "custom-layout" attribute.
512
       */
513
      if (GLADE_PROPERTY_CLASS_IS_TYPE (klass, type) &&
514 515 516
          (type == GLADE_PAGE_QUERY || 
           (!glade_property_class_custom_layout (klass) &&
            glade_property_class_is_visible (klass))))
517 518 519 520 521 522
        {
          list = g_list_prepend (list, klass);
        }

    }
  return g_list_sort (list, property_class_comp);
523 524 525
}

static GladeEditorProperty *
526 527 528
append_item (GladeEditorTable   *table,
             GladePropertyClass *klass,
             gboolean            from_query_dialog)
529
{
530
  GladeEditorProperty *property;
531
  GtkWidget *label;
532

533
  if (!(property = glade_widget_adaptor_create_eprop
534
        (glade_property_class_get_adaptor (klass), klass, from_query_dialog == FALSE)))
535 536
    {
      g_critical ("Unable to create editor for property '%s' of class '%s'",
537
                  glade_property_class_id (klass), 
538
                  glade_widget_adaptor_get_name (glade_property_class_get_adaptor (klass)));
539 540
      return NULL;
    }
541

542
  gtk_widget_show (GTK_WIDGET (property));
543
  gtk_widget_show_all (glade_editor_property_get_item_label (property));
544

545 546 547 548
  label = glade_editor_property_get_item_label (property);
  gtk_widget_set_hexpand (label, FALSE);

  glade_editor_table_attach (table, label, 0, table->priv->rows);
549
  glade_editor_table_attach (table, GTK_WIDGET (property), 1, table->priv->rows);
550

551
  table->priv->rows++;
552

553
  return property;
554 555 556
}

static void
557 558 559
append_items (GladeEditorTable   *table,
              GladeWidgetAdaptor *adaptor,
              GladeEditorPageType type)
560
{
561 562 563
  GladeEditorProperty *property;
  GladePropertyClass *property_class;
  GList *list, *sorted_list;
564

565 566 567 568
  sorted_list = get_sorted_properties (adaptor, type);
  for (list = sorted_list; list != NULL; list = list->next)
    {
      property_class = (GladePropertyClass *) list->data;
569

570
      property = append_item (table, property_class, type == GLADE_PAGE_QUERY);
571
      table->priv->properties = g_list_prepend (table->priv->properties, property);
572 573
    }
  g_list_free (sorted_list);
574

575
  table->priv->properties = g_list_reverse (table->priv->properties);
576 577 578
}

static void
579
append_name_field (GladeEditorTable *table)
580
{
581
  gchar *text = _("The object's unique identifier");
582

583 584
  /* translators: The unique identifier of an object in the project */
  table->priv->name_label = gtk_label_new (_("ID:"));
585
  gtk_widget_set_halign (table->priv->name_label, GTK_ALIGN_START);
586 587
  gtk_widget_show (table->priv->name_label);
  gtk_widget_set_no_show_all (table->priv->name_label, TRUE);
588

589 590 591 592 593 594 595 596 597
  table->priv->name_field = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
  gtk_widget_set_no_show_all (table->priv->name_field, TRUE);
  gtk_widget_show (table->priv->name_field);

  table->priv->composite_check = gtk_check_button_new_with_label (_("Composite"));
  gtk_widget_set_hexpand (table->priv->composite_check, FALSE);
  gtk_widget_set_tooltip_text (table->priv->composite_check, _("Whether this widget is a composite template"));
  gtk_widget_set_no_show_all (table->priv->composite_check, TRUE);

598 599
  table->priv->name_entry = gtk_entry_new ();
  gtk_widget_show (table->priv->name_entry);
600

601 602
  gtk_widget_set_tooltip_text (table->priv->name_label, text);
  gtk_widget_set_tooltip_text (table->priv->name_entry, text);
603

604
  g_signal_connect (G_OBJECT (table->priv->name_entry), "activate",
605
                    G_CALLBACK (widget_name_edited), table);
606
  g_signal_connect (G_OBJECT (table->priv->name_entry), "changed",
607
                    G_CALLBACK (widget_name_edited), table);
608 609 610 611 612
  g_signal_connect (G_OBJECT (table->priv->composite_check), "toggled",
                    G_CALLBACK (widget_composite_toggled), table);

  gtk_box_pack_start (GTK_BOX (table->priv->name_field), table->priv->name_entry, TRUE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX (table->priv->name_field), table->priv->composite_check, FALSE, FALSE, 0);
613

614
  glade_editor_table_attach (table, table->priv->name_label, 0, table->priv->rows);
615
  glade_editor_table_attach (table, table->priv->name_field, 1, table->priv->rows);
616

617 618 619 620
  /* Set initial visiblity */
  gtk_widget_set_visible (table->priv->name_label, table->priv->show_name);
  gtk_widget_set_visible (table->priv->name_field, table->priv->show_name);

621
  table->priv->rows++;
622 623 624 625 626 627 628 629 630 631 632 633 634
}

/**
 * glade_editor_table_new:
 * @adaptor: A #GladeWidgetAdaptor
 * @type: The #GladeEditorPageType
 *
 * Creates a new #GladeEditorTable. 
 *
 * Returns: a new #GladeEditorTable
 *
 */
GtkWidget *
635
glade_editor_table_new (GladeWidgetAdaptor *adaptor, GladeEditorPageType type)
636
{
637 638 639
  GladeEditorTable *table;

  g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), NULL);
640

641
  table = g_object_new (GLADE_TYPE_EDITOR_TABLE, "page-type", type, NULL);
642
  table->priv->adaptor = adaptor;
643

644
  if (table->priv->type == GLADE_PAGE_GENERAL)
645
    append_name_field (table);
646

647
  append_items (table, table->priv->adaptor, table->priv->type);
648

649
  return (GtkWidget *)table;
650
}