glade-editor.c 44.5 KB
Newer Older
Jose Maria Celorio's avatar
Jose Maria Celorio committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * 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
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Jose Maria Celorio's avatar
Jose Maria Celorio committed
17 18 19
 *
 * Authors:
 *   Chema Celorio <chema@celorio.com>
20
 *   Tristan Van Berkom <tvb@gnome.org>
Jose Maria Celorio's avatar
Jose Maria Celorio committed
21 22 23
 */


24 25 26 27
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

28 29 30 31 32 33 34
/**
 * SECTION:glade-editor
 * @Short_Description: A Widget to edit a #GladeWidget.
 *
 * This is the Glade Notebook containing all the controls needed to configure a #GladeWidget.
 */

35
#include <stdio.h>
36
#include <string.h>
37
#include <glib/gi18n-lib.h>
Jose Maria Celorio's avatar
Jose Maria Celorio committed
38

39 40
#include <gtk/gtk.h>

Jose Maria Celorio's avatar
Jose Maria Celorio committed
41 42
#include "glade.h"
#include "glade-widget.h"
43
#include "glade-widget-adaptor.h"
Jose Maria Celorio's avatar
Jose Maria Celorio committed
44
#include "glade-editor.h"
45
#include "glade-signal-editor.h"
Jose Maria Celorio's avatar
Jose Maria Celorio committed
46 47
#include "glade-property.h"
#include "glade-property-class.h"
48
#include "glade-command.h"
49
#include "glade-debug.h"
50
#include "glade-marshallers.h"
51
#include "glade-project.h"
52
#include "glade-utils.h"
53
#include "glade-editor-property.h"
Jose Maria Celorio's avatar
Jose Maria Celorio committed
54

55
static void glade_editor_switch_page (GtkNotebook     *notebook,
56 57 58
                                      GtkWidget       *page,
                                      guint            page_num,
                                      GladeEditor     *editor);
59

60 61
enum
{
62 63
  PROP_0,
  PROP_SHOW_INFO,
64
  PROP_WIDGET,
65
  PROP_SHOW_CLASS_FIELD,
66
  PROP_CLASS_FIELD,
67
  PROP_SHOW_BORDER,
68
  PROP_SIGNAL_EDITOR,
69
  N_PROPERTIES
70 71
};

72 73
#define GLADE_EDITOR_PRIVATE(object) (((GladeEditor*)object)->priv)

74
struct _GladeEditorPrivate
75 76
{

77 78 79
  GtkWidget *notebook; /* The notebook widget */

  GladeWidget *loaded_widget; /* A handy pointer to the GladeWidget
80 81 82
                               * that is loaded in the editor. NULL
                               * if no widgets are selected
                               */
83 84

  GladeWidgetAdaptor *loaded_adaptor; /* A pointer to the loaded
85 86 87 88 89 90 91 92 93 94 95 96 97
                                       * GladeWidgetAdaptor. Note that we can
                                       * have a class loaded without a
                                       * loaded_widget. For this reason we
                                       * can't use loaded_widget->adaptor.
                                       * When a widget is selected we load
                                       * this class in the editor first and
                                       * then fill the values of the inputs
                                       * with the GladeProperty items.
                                       * This is usefull for not having
                                       * to redraw/container_add the widgets
                                       * when we switch from widgets of the
                                       * same class
                                       */
98 99 100 101 102 103 104

  GtkWidget *page_widget;
  GtkWidget *page_packing;
  GtkWidget *page_common;
  GtkWidget *page_atk;

  GladeSignalEditor *signal_editor; /* The signal editor packed into vbox_signals
105
                                     */
106 107

  GList *editables;     /* A list of GladeEditables. We have a widget
108 109 110 111
                         * for each GladeWidgetAdaptor and we only load
                         * them on demand
                         */
        
112
  GtkWidget *packing_page; /* Packing pages are dynamicly created each
113 114 115
                            * selection, this pointer is only to free
                            * the last packing page.
                            */
116 117
  
  gboolean loading; /* Use when loading a GladeWidget into the editor
118 119 120 121 122
                     * we set this flag so that we can ignore the
                     * "changed" signal of the name entry text since
                     * the name has not really changed, just a new name
                     * was loaded.
                     */
123 124 125 126 127 128 129 130 131

  gulong project_closed_signal_id; /* Unload widget when widget's project closes  */
  gulong project_removed_signal_id; /* Unload widget when its removed from the project. */
  gulong widget_warning_id; /* Update when widget changes warning messages. */
  gulong widget_name_id;    /* Update class field when widget name changes  */

  GtkWidget *class_field; /* The class header */

  GtkWidget *warning;   /* A pointer to an icon we can show in the class
132 133 134
                         * field to publish tooltips for class related
                         * versioning errors.
                         */
135 136 137 138

  GtkWidget *class_icon; /* An image with the current widget's class icon.  */
  GtkWidget *class_label; /* A label with the current class label. */

139
  gboolean show_class_field; /* Whether or not to show the class field at the top */
140
};
141

142
G_DEFINE_TYPE_WITH_PRIVATE (GladeEditor, glade_editor, GTK_TYPE_BOX);
143

144
static GParamSpec *properties[N_PROPERTIES];
145

146
static void
147 148
glade_editor_set_property (GObject      *object,
                           guint         prop_id,
149
                           const GValue *value,
150
                           GParamSpec   *pspec)
151
{
152 153 154 155 156 157 158 159
  GladeEditor *editor = GLADE_EDITOR (object);

  switch (prop_id)
    {
      case PROP_SHOW_INFO:
        break;
      case PROP_WIDGET:
        glade_editor_load_widget (editor,
160
                                  GLADE_WIDGET (g_value_get_object (value)));
161
        break;
162 163 164 165 166 167
      case PROP_SHOW_CLASS_FIELD:
        if (g_value_get_boolean (value))
          glade_editor_show_class_field (editor);
        else
          glade_editor_hide_class_field (editor);
        break;
168 169 170 171
      case PROP_SHOW_BORDER:
        gtk_notebook_set_show_border (GTK_NOTEBOOK (editor->priv->notebook),
                                      g_value_get_boolean (value));
        break;
172 173 174 175
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
176 177 178
}

static void
179 180 181
glade_editor_get_property (GObject    *object,
                           guint       prop_id,
                           GValue     *value,
182
                           GParamSpec *pspec)
183
{
184 185 186 187 188
  GladeEditor *editor = GLADE_EDITOR (object);

  switch (prop_id)
    {
      case PROP_SHOW_INFO:
189
        g_value_set_boolean (value, FALSE);
190 191
        break;
      case PROP_WIDGET:
192
        g_value_set_object (value, editor->priv->loaded_widget);
193
        break;
194 195 196
      case PROP_SHOW_CLASS_FIELD:
        g_value_set_boolean (value, editor->priv->show_class_field);
        break;
197 198 199
      case PROP_CLASS_FIELD:
        g_value_set_static_string (value, gtk_label_get_label (GTK_LABEL (editor->priv->class_label)));
        break;
200 201 202
      case PROP_SHOW_BORDER:
        g_value_set_boolean (value, gtk_notebook_get_show_border (GTK_NOTEBOOK (editor->priv->notebook)));
        break;
203 204 205
      case PROP_SIGNAL_EDITOR:
        g_value_set_object (value, editor->priv->signal_editor);
        break;
206 207 208 209
      default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
210 211
}

212 213 214
static void
glade_editor_dispose (GObject *object)
{
215
  GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (object);
216 217 218 219 220
  GladeEditor *editor = GLADE_EDITOR (object);

  glade_editor_load_widget (editor, NULL);

  /* Unref all the cached pages */
221 222
  g_list_foreach (priv->editables, (GFunc) g_object_unref, NULL);
  priv->editables = (g_list_free (priv->editables), NULL);
223

224
  G_OBJECT_CLASS (glade_editor_parent_class)->dispose (object);
225
}
226

Jose Maria Celorio's avatar
Jose Maria Celorio committed
227
static void
228
glade_editor_class_init (GladeEditorClass *klass)
Jose Maria Celorio's avatar
Jose Maria Celorio committed
229
{
230 231
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
232

233
  object_class->dispose      = glade_editor_dispose;
234 235 236 237
  object_class->set_property = glade_editor_set_property;
  object_class->get_property = glade_editor_get_property;

  /* Properties */
238 239 240 241 242 243
  properties[PROP_SHOW_INFO] =
    g_param_spec_boolean ("show-info",
                          _("Show info"),
                          _("Whether to show an informational "
                            "button for the loaded widget"),
                          FALSE,
244
                          G_PARAM_READABLE | G_PARAM_DEPRECATED);
245 246 247 248 249 250 251

  properties[PROP_WIDGET] =
    g_param_spec_object ("widget",
                         _("Widget"),
                         _("The currently loaded widget in this editor"),
                         GLADE_TYPE_WIDGET,
                         G_PARAM_READWRITE);
252 253 254 255

  properties[PROP_SHOW_CLASS_FIELD] =
    g_param_spec_boolean ("show-class-field",
                          _("Show Class Field"),
256
                          _("Whether to show the class field at the top"),
257 258
                          TRUE,
                          G_PARAM_READWRITE);
259 260 261 262 263 264 265

  properties[PROP_CLASS_FIELD] =
    g_param_spec_string ("class-field",
                         _("Class Field"),
                         _("The class field string"),
                         NULL,
                         G_PARAM_READABLE);
266

267 268 269 270 271 272
  properties[PROP_SHOW_BORDER] =
    g_param_spec_boolean ("show-boder",
                          _("Show Border"),
                          _("Whether the border should be shown"),
                          TRUE,
                          G_PARAM_READWRITE);
273 274 275 276 277 278 279

  properties[PROP_SIGNAL_EDITOR] =
    g_param_spec_object ("signal-editor",
                         _("Signal Editor"),
                         _("The signal editor used to edit signals"),
                         GLADE_TYPE_SIGNAL_EDITOR,
                         G_PARAM_READABLE);
280 281 282
  
  /* Install all properties */
  g_object_class_install_properties (object_class, N_PROPERTIES, properties);
283

284 285
  /* Bind to template */
  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/gladeui/glade-editor.ui");
286

287 288 289 290 291 292 293 294 295 296 297 298
  gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, notebook);
  gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, page_widget);
  gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, page_packing);
  gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, page_common);
  gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, page_atk);
  gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, class_field);
  gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, class_icon);
  gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, class_label);
  gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, warning);
  gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, signal_editor);

  gtk_widget_class_bind_template_callback (widget_class, glade_editor_switch_page);
Jose Maria Celorio's avatar
Jose Maria Celorio committed
299
}
300

301
static void
302
glade_editor_update_class_warning_cb (GladeWidget *widget,
303
                                      GParamSpec  *pspec,
304
                                      GladeEditor *editor)
305
{
306 307
  GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (editor);

308
  if (glade_widget_support_warning (widget))
309
    gtk_widget_show (priv->warning);
310
  else
311
    gtk_widget_hide (priv->warning);
312

313
  gtk_widget_set_tooltip_text (priv->warning, glade_widget_support_warning (widget));
314 315
}

316

317
static void
318
glade_editor_update_class_field (GladeEditor *editor)
319
{
320 321 322
  GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (editor);

  if (priv->loaded_widget)
323
    {
324
      GladeWidget *widget = priv->loaded_widget;
325
      gchar *text;
326

327 328
      gtk_image_set_from_icon_name (GTK_IMAGE (priv->class_icon),
                                    glade_widget_adaptor_get_icon_name (priv->loaded_adaptor),
329
                                    GTK_ICON_SIZE_BUTTON);
330
      gtk_widget_show (priv->class_icon);
331

332
      if (glade_widget_has_name (widget))
333 334 335 336 337 338
        {
          /* translators: %s(Class Title) Properties - %s (ClassName) [%s(WidgetName)]
           * example: Window Properties - GtkWindow [window1]
           */
          text = g_strdup_printf (_("%s Properties - %s [%s]"),
                                  glade_widget_adaptor_get_title (priv->loaded_adaptor),
339
                                  glade_widget_adaptor_get_display_name (priv->loaded_adaptor),
340
                                  glade_widget_get_display_name (widget));
341
        }
342 343 344 345 346 347 348
      else
        {
          /* translators: %s(Class Title) Properties - %s (ClassName)
           * example: Window Properties - GtkWindow
           */
          text = g_strdup_printf (_("%s Properties - %s"),
                                  glade_widget_adaptor_get_title (priv->loaded_adaptor),
349
                                  glade_widget_adaptor_get_display_name (priv->loaded_adaptor));
350 351
        }

352
      gtk_label_set_text (GTK_LABEL (priv->class_label), text);
353 354
      g_free (text);

355
      glade_editor_update_class_warning_cb (priv->loaded_widget, NULL, editor);
356 357 358
    }
  else
    {
359 360 361
      gtk_widget_hide (priv->class_icon);
      gtk_widget_hide (priv->warning);
      gtk_label_set_text (GTK_LABEL (priv->class_label), _("Properties"));
362
    }
363 364

  g_object_notify_by_pspec (G_OBJECT (editor), properties[PROP_CLASS_FIELD]);
365 366
}

367
static void
368
glade_editor_update_widget_name_cb (GladeWidget *widget,
369
                                    GParamSpec  *pspec,
370
                                    GladeEditor *editor)
371
{
372
  glade_editor_update_class_field (editor);
373 374
}

375
static void
376 377 378 379
glade_editor_switch_page (GtkNotebook *notebook,
                          GtkWidget   *page,
                          guint        page_num,
                          GladeEditor *editor)
380
{
381 382 383 384 385 386
  GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (editor);

  gtk_widget_hide (priv->page_widget);
  gtk_widget_hide (priv->page_packing);
  gtk_widget_hide (priv->page_common);
  gtk_widget_hide (priv->page_atk);
387 388 389 390

  switch (page_num)
    {
    case 0:
391
      gtk_widget_show (priv->page_widget);
392 393
      break;
    case 1:
394
      gtk_widget_show (priv->page_packing);
395 396
      break;
    case 2:
397
      gtk_widget_show (priv->page_common);
398 399
      break;
    case 4:
400
      gtk_widget_show (priv->page_atk);
401 402 403 404
      break;
    }
}

Jose Maria Celorio's avatar
Jose Maria Celorio committed
405
static void
406
glade_editor_init (GladeEditor *editor)
Jose Maria Celorio's avatar
Jose Maria Celorio committed
407
{
408
  GladeEditorPrivate *priv;
409
  gint                icon_height;
410

411
  editor->priv = priv = glade_editor_get_instance_private (editor);
412

413 414
  priv->show_class_field = TRUE;

415
  gtk_widget_init_template (GTK_WIDGET (editor));
Tristan Van Berkom's avatar
Tristan Van Berkom committed
416

417 418
  gtk_icon_size_lookup (GTK_ICON_SIZE_BUTTON, NULL, &icon_height);
  gtk_widget_set_size_request (priv->class_label, -1, icon_height + 2);
419

420
  glade_editor_update_class_field (editor);
Jose Maria Celorio's avatar
Jose Maria Celorio committed
421 422
}

423
static GtkWidget *
424
glade_editor_get_editable_by_adaptor (GladeEditor        *editor,
425
                                      GladeWidgetAdaptor *adaptor,
426
                                      GladeEditorPageType type)
Jose Maria Celorio's avatar
Jose Maria Celorio committed
427
{
428
  GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (editor);
429 430 431 432 433
  GtkWidget *editable;
  GList *list;

  g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), NULL);

434
  for (list = priv->editables; list; list = list->next)
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
    {
      editable = list->data;
      if (type !=
          GPOINTER_TO_INT (g_object_get_data
                           (G_OBJECT (editable), "glade-editor-page-type")))
        continue;
      if (g_object_get_data (G_OBJECT (editable), "glade-widget-adaptor") ==
          adaptor)
        return editable;
    }

  editable = (GtkWidget *) glade_widget_adaptor_create_editable (adaptor, type);
  g_return_val_if_fail (editable != NULL, NULL);

  g_object_set_data (G_OBJECT (editable), "glade-editor-page-type",
                     GINT_TO_POINTER (type));
  g_object_set_data (G_OBJECT (editable), "glade-widget-adaptor", adaptor);

  if (type != GLADE_PAGE_PACKING)
    {
455
      priv->editables = g_list_prepend (priv->editables, editable);
456 457 458 459
      g_object_ref_sink (editable);
    }

  return editable;
Jose Maria Celorio's avatar
Jose Maria Celorio committed
460 461
}

462
static void
463
hide_or_remove_visible_child (GtkContainer *container, gboolean remove)
464 465 466 467 468 469 470 471 472
{
  GList *l, *children = gtk_container_get_children (container);
  GtkWidget *widget;

  for (l = children; l; l = l->next)
    {
      widget = l->data;

      if (gtk_widget_get_visible (widget))
473 474
        {
          gtk_widget_hide (widget);
475

476 477
          if (remove)
            gtk_container_remove (container, widget);
478

479 480
          break;
        }
481 482 483 484
    }
  g_list_free (children);
}

Tristan Van Berkom's avatar
Tristan Van Berkom committed
485
static GtkWidget *
486
glade_editor_load_editable_in_page (GladeEditor        *editor,
487
                                    GladeWidgetAdaptor *adaptor,
488
                                    GladeEditorPageType type)
Jose Maria Celorio's avatar
Jose Maria Celorio committed
489
{
490
  GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (editor);
491
  GtkContainer *container = NULL;
492
  GtkWidget *scrolled_window, *editable;
493 494 495 496 497 498
  GtkAdjustment *adj;

  /* Remove the old table that was in this container */
  switch (type)
    {
      case GLADE_PAGE_GENERAL:
499
        container = GTK_CONTAINER (priv->page_widget);
500 501
        break;
      case GLADE_PAGE_COMMON:
502
        container = GTK_CONTAINER (priv->page_common);
503 504
        break;
      case GLADE_PAGE_PACKING:
505
        container = GTK_CONTAINER (priv->page_packing);
506 507
        break;
      case GLADE_PAGE_ATK:
508
        container = GTK_CONTAINER (priv->page_atk);
509 510 511 512 513 514 515
        break;
      case GLADE_PAGE_QUERY:
      default:
        g_critical ("Unreachable code reached !");
        break;
    }

516 517
  /* Hide the editable (this will destroy on packing pages) */
  hide_or_remove_visible_child (container, type == GLADE_PAGE_PACKING);
518 519 520 521 522 523 524 525 526

  if (!adaptor)
    return NULL;

  if ((editable =
       glade_editor_get_editable_by_adaptor (editor, adaptor, type)) == NULL)
    return NULL;

  /* Attach the new page */
527 528
  if (!gtk_widget_get_parent (editable))
    gtk_container_add (GTK_CONTAINER (container), editable);
529 530
  gtk_widget_show (editable);

531 532
  if ((scrolled_window = 
       gtk_widget_get_ancestor (GTK_WIDGET (container), 
533
                                GTK_TYPE_SCROLLED_WINDOW)) != NULL)
534 535 536
    {
      adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window));
      gtk_container_set_focus_vadjustment (GTK_CONTAINER (editable), adj);
537

538 539 540
      adj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled_window));
      gtk_container_set_focus_hadjustment (GTK_CONTAINER (editable), adj);
    }
541 542

  return editable;
543 544
}

Jose Maria Celorio's avatar
Jose Maria Celorio committed
545
static void
546 547
glade_editor_load_widget_class (GladeEditor *editor,
                                GladeWidgetAdaptor *adaptor)
Jose Maria Celorio's avatar
Jose Maria Celorio committed
548
{
549

550 551 552
  glade_editor_load_editable_in_page (editor, adaptor, GLADE_PAGE_GENERAL);
  glade_editor_load_editable_in_page (editor, adaptor, GLADE_PAGE_COMMON);
  glade_editor_load_editable_in_page (editor, adaptor, GLADE_PAGE_ATK);
553
  glade_editor_load_editable_in_page (editor, NULL, GLADE_PAGE_PACKING);
Tristan Van Berkom's avatar
Tristan Van Berkom committed
554

555
  editor->priv->loaded_adaptor = adaptor;
Jose Maria Celorio's avatar
Jose Maria Celorio committed
556 557
}

558
static void
559
glade_editor_close_cb (GladeProject *project, GladeEditor *editor)
560
{
561 562 563 564
  /* project we are viewing was closed,
   * detatch from editor.
   */
  glade_editor_load_widget (editor, NULL);
565 566
}

567
static void
568 569 570
glade_editor_removed_cb (GladeProject *project,
                         GladeWidget *widget,
                         GladeEditor *editor)
571
{
572 573 574
  /* Widget we were viewing was removed from project,
   * detatch from editor.
   */
575
  if (widget == editor->priv->loaded_widget)
576
    glade_editor_load_widget (editor, NULL);
577 578 579 580

}


Tristan Van Berkom's avatar
Tristan Van Berkom committed
581
static void
582 583
glade_editor_load_editable (GladeEditor        *editor,
                            GladeWidget        *widget,
584
                            GladeEditorPageType type)
585
{
586 587
  GtkWidget   *editable;
  GladeWidget *parent = glade_widget_get_parent (widget);
588 589 590 591

  /* Use the parenting adaptor for packing pages... so deffer creating the widgets
   * until load time.
   */
592
  if (type == GLADE_PAGE_PACKING)
593
    {
594 595 596
      GladeWidgetAdaptor *adaptor;

      if (!parent)
597
        return;
598 599

      adaptor = glade_widget_get_adaptor (parent);
600
      editable =
601 602
        glade_editor_load_editable_in_page (editor, adaptor,
                                            GLADE_PAGE_PACKING);
603 604
    }
  else
605 606
    editable = 
      glade_editor_get_editable_by_adaptor (editor, 
607 608
                                            glade_widget_get_adaptor (widget), 
                                            type);
609 610 611 612 613 614 615 616 617 618

  g_assert (editable);

  if (!widget)
    gtk_widget_hide (editable);

  glade_editable_load (GLADE_EDITABLE (editable), widget);

  if (widget)
    gtk_widget_show (editable);
619
}
620

621
static void
622
clear_editables (GladeEditor *editor)
623
{
624 625 626
  GladeEditable *editable;
  GList *l;

627
  for (l = editor->priv->editables; l; l = l->next)
628 629 630 631
    {
      editable = l->data;
      glade_editable_load (editable, NULL);
    }
632 633
}

634
static void
635
glade_editor_load_widget_real (GladeEditor *editor, GladeWidget *widget)
Jose Maria Celorio's avatar
Jose Maria Celorio committed
636
{
637
  GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (editor);
638 639 640 641
  GladeWidgetAdaptor *adaptor;
  GladeProject *project;

  /* Disconnect from last widget */
642
  if (priv->loaded_widget != NULL)
643 644 645 646 647 648
    {
      /* better pay a small price now and avoid unseen editables
       * waking up on project metadata changes.
       */
      clear_editables (editor);

649
      project = glade_widget_get_project (priv->loaded_widget);
650
      g_signal_handler_disconnect (G_OBJECT (project),
651
                                   priv->project_closed_signal_id);
652
      g_signal_handler_disconnect (G_OBJECT (project),
653 654 655 656 657
                                   priv->project_removed_signal_id);
      g_signal_handler_disconnect (G_OBJECT (priv->loaded_widget),
                                   priv->widget_warning_id);
      g_signal_handler_disconnect (G_OBJECT (priv->loaded_widget),
                                   priv->widget_name_id);
658 659 660
    }

  /* Load the GladeWidgetClass */
661
  adaptor = widget ? glade_widget_get_adaptor (widget) : NULL;
662
  if (priv->loaded_adaptor != adaptor || adaptor == NULL)
663 664
    glade_editor_load_widget_class (editor, adaptor);

665
  glade_signal_editor_load_widget (priv->signal_editor, widget);
666 667 668 669

  /* we are just clearing, we are done */
  if (widget == NULL)
    {
670
      priv->loaded_widget = NULL;
671 672 673 674

      /* Clear class header */
      glade_editor_update_class_field (editor);

675
      g_object_notify_by_pspec (G_OBJECT (editor), properties[PROP_WIDGET]);
676

677 678 679
      return;
    }

680
  priv->loading = TRUE;
681 682 683 684 685 686 687

  /* Load each GladeEditorProperty from 'widget' */
  glade_editor_load_editable (editor, widget, GLADE_PAGE_GENERAL);
  glade_editor_load_editable (editor, widget, GLADE_PAGE_COMMON);
  glade_editor_load_editable (editor, widget, GLADE_PAGE_ATK);
  glade_editor_load_editable (editor, widget, GLADE_PAGE_PACKING);

688 689
  priv->loaded_widget = widget;
  priv->loading = FALSE;
690 691 692 693 694

  /* Update class header */
  glade_editor_update_class_field (editor);

  /* Connect to new widget */
695 696
  project = glade_widget_get_project (priv->loaded_widget);
  priv->project_closed_signal_id =
697 698
      g_signal_connect (G_OBJECT (project), "close",
                        G_CALLBACK (glade_editor_close_cb), editor);
699
  priv->project_removed_signal_id =
700 701
      g_signal_connect (G_OBJECT (project), "remove-widget",
                        G_CALLBACK (glade_editor_removed_cb), editor);
702
  priv->widget_warning_id =
703 704 705
      g_signal_connect (G_OBJECT (widget), "notify::support-warning",
                        G_CALLBACK (glade_editor_update_class_warning_cb),
                        editor);
706
  priv->widget_name_id =
707 708 709 710
      g_signal_connect (G_OBJECT (widget), "notify::name",
                        G_CALLBACK (glade_editor_update_widget_name_cb),
                        editor);

711
  g_object_notify_by_pspec (G_OBJECT (editor), properties[PROP_WIDGET]);
Jose Maria Celorio's avatar
Jose Maria Celorio committed
712 713
}

714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729

/**
 * glade_editor_new:
 *
 * Returns: a new #GladeEditor
 */
GladeEditor *
glade_editor_new (void)
{
  GladeEditor *editor;

  editor = g_object_new (GLADE_TYPE_EDITOR, "spacing", 6, NULL);

  return editor;
}

730
/**
731
 * glade_editor_load_widget:
732
 * @editor: a #GladeEditor
733
 * @widget: a #GladeWidget
734
 *
735
 * Load @widget into @editor. If @widget is %NULL, clear the editor.
736
 */
737
void
738
glade_editor_load_widget (GladeEditor *editor, GladeWidget *widget)
739
{
740 741
  g_return_if_fail (GLADE_IS_EDITOR (editor));
  g_return_if_fail (widget == NULL || GLADE_IS_WIDGET (widget));
742

743
  if (editor->priv->loaded_widget == widget)
744
    return;
745

746
  glade_editor_load_widget_real (editor, widget);
747 748
}

Vincent Geddes's avatar
Vincent Geddes committed
749
static void
750 751 752
query_dialog_style_set_cb (GtkWidget *dialog,
                           GtkStyle *previous_style,
                           gpointer user_data)
Vincent Geddes's avatar
Vincent Geddes committed
753
{
754 755 756 757 758 759 760 761
  GtkWidget *content_area, *action_area;

  content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
  gtk_container_set_border_width (GTK_CONTAINER (content_area), 12);
  gtk_box_set_spacing (GTK_BOX (content_area), 12);
  action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
  gtk_container_set_border_width (GTK_CONTAINER (action_area), 0);
  gtk_box_set_spacing (GTK_BOX (action_area), 6);
Vincent Geddes's avatar
Vincent Geddes committed
762 763
}

764 765
static gboolean
query_dialog_delete_event_cb (GtkDialog *dialog,
766 767
                              GdkEvent  *event,
                              gpointer   user_data)
768 769 770 771 772
{
  gtk_dialog_response (dialog, GTK_RESPONSE_CANCEL);
  return TRUE;
}

773
gboolean
774
glade_editor_query_dialog (GladeWidget *widget)
775
{
776
  GladeWidgetAdaptor *adaptor;
777
  GtkWidget *dialog, *editable, *content_area;
778
  GtkWidget *create;
779 780 781
  gchar *title;
  gint answer;
  gboolean retval = TRUE;
782

783 784 785
  g_return_val_if_fail (GLADE_IS_WIDGET (widget), FALSE);
  
  adaptor = glade_widget_get_adaptor (widget);
786

787
  title = g_strdup_printf (_("Create a %s"), glade_widget_adaptor_get_display_name (adaptor));
788 789 790
  dialog = gtk_dialog_new_with_buttons (title, NULL,
                                        GTK_DIALOG_MODAL |
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
791
                                        _("_Cancel"), GTK_RESPONSE_CANCEL,
792
                                        NULL);
793
  g_free (title);
794

795 796 797 798 799
  create = gtk_button_new_with_mnemonic (_("Crea_te"));
  gtk_widget_show (create);
  gtk_widget_set_can_default (create, TRUE);
  gtk_dialog_add_action_widget (GTK_DIALOG (dialog), create, GTK_RESPONSE_OK);

800 801 802 803
  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
                                           GTK_RESPONSE_OK,
                                           GTK_RESPONSE_CANCEL, -1);
  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
Vincent Geddes's avatar
Vincent Geddes committed
804

805
  editable = (GtkWidget *) glade_widget_adaptor_create_editable (adaptor, GLADE_PAGE_QUERY);
806
  gtk_widget_show (editable);
807

808 809
  content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
  gtk_box_pack_start (GTK_BOX (content_area), editable, FALSE, FALSE, 6);
810

811
  glade_editable_load (GLADE_EDITABLE (editable), widget);
812

813 814
  g_signal_connect (dialog, "style-set",
                    G_CALLBACK (query_dialog_style_set_cb), NULL);
Vincent Geddes's avatar
Vincent Geddes committed
815

816 817 818
  g_signal_connect (dialog, "delete-event",
                    G_CALLBACK (query_dialog_delete_event_cb), NULL);

819
  answer = gtk_dialog_run (GTK_DIALOG (dialog));
820

821 822 823 824 825 826 827
  /*
   * If user cancel's we cancel the whole "create operation" by
   * return FALSE. glade_widget_new() will see the FALSE, and
   * take care of canceling the "create" operation.
   */
  if (answer == GTK_RESPONSE_CANCEL)
    retval = FALSE;
828

829 830
  gtk_widget_destroy (dialog);
  return retval;
831
}
832

833 834 835 836 837 838 839 840 841 842 843
enum
{
  COLUMN_ENABLED = 0,
  COLUMN_PROP_NAME,
  COLUMN_PROPERTY,
  COLUMN_WEIGHT,
  COLUMN_CHILD,
  COLUMN_DEFAULT,
  COLUMN_NDEFAULT,
  COLUMN_DEFSTRING,
  NUM_COLUMNS
844 845 846 847
};


static void
848
glade_editor_reset_toggled (GtkCellRendererToggle *cell,
849 850
                            gchar                 *path_str,
                            GtkTreeModel          *model)
851
{
852 853 854 855 856 857 858 859 860 861
  GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
  GtkTreeIter iter;
  gboolean enabled;

  /* get toggled iter */
  gtk_tree_model_get_iter (model, &iter, path);
  gtk_tree_model_get (model, &iter, COLUMN_ENABLED, &enabled, -1);
  gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
                      COLUMN_ENABLED, !enabled, -1);
  gtk_tree_path_free (path);
862 863 864
}

static GtkWidget *
865
glade_editor_reset_view (void)
866
{
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883
  GtkWidget *view_widget;
  GtkTreeModel *model;
  GtkCellRenderer *renderer;
  GtkTreeViewColumn *column;

  model = (GtkTreeModel *) gtk_tree_store_new (NUM_COLUMNS, G_TYPE_BOOLEAN,     /* Enabled  value      */
                                               G_TYPE_STRING,   /* Property name       */
                                               GLADE_TYPE_PROPERTY,     /* The property        */
                                               G_TYPE_INT,      /* Parent node ?       */
                                               G_TYPE_BOOLEAN,  /* Child node ?        */
                                               G_TYPE_BOOLEAN,  /* Has default value   */
                                               G_TYPE_BOOLEAN,  /* Doesn't have defaut */
                                               G_TYPE_STRING);  /* Default string      */

  view_widget = gtk_tree_view_new_with_model (model);
  g_object_set (G_OBJECT (view_widget), "enable-search", FALSE, NULL);

884
  /********************* fake invisible column *********************/
885 886 887 888 889 890 891 892 893
  renderer = gtk_cell_renderer_text_new ();
  g_object_set (G_OBJECT (renderer), "editable", FALSE, "visible", FALSE, NULL);

  column = gtk_tree_view_column_new_with_attributes (NULL, renderer, NULL);
  gtk_tree_view_append_column (GTK_TREE_VIEW (view_widget), column);

  gtk_tree_view_column_set_visible (column, FALSE);
  gtk_tree_view_set_expander_column (GTK_TREE_VIEW (view_widget), column);

894
  /************************ enabled column ************************/
895 896 897 898 899 900 901 902 903 904 905 906 907
  renderer = gtk_cell_renderer_toggle_new ();
  g_object_set (G_OBJECT (renderer),
                "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
                "activatable", TRUE, NULL);
  g_signal_connect (renderer, "toggled",
                    G_CALLBACK (glade_editor_reset_toggled), model);
  gtk_tree_view_insert_column_with_attributes
      (GTK_TREE_VIEW (view_widget), COLUMN_ENABLED,
       _("Reset"), renderer,
       "sensitive", COLUMN_NDEFAULT,
       "activatable", COLUMN_NDEFAULT,
       "active", COLUMN_ENABLED, "visible", COLUMN_CHILD, NULL);

908
  /********************* property name column *********************/
909 910 911 912 913 914 915 916
  renderer = gtk_cell_renderer_text_new ();
  g_object_set (G_OBJECT (renderer), "editable", FALSE, NULL);

  gtk_tree_view_insert_column_with_attributes
      (GTK_TREE_VIEW (view_widget), COLUMN_PROP_NAME,
       _("Property"), renderer,
       "text", COLUMN_PROP_NAME, "weight", COLUMN_WEIGHT, NULL);

917
  /******************* default indicator column *******************/
918 919 920 921 922 923 924 925 926 927 928
  renderer = gtk_cell_renderer_text_new ();
  g_object_set (G_OBJECT (renderer),
                "editable", FALSE,
                "style", PANGO_STYLE_ITALIC, "foreground", "Gray", NULL);

  gtk_tree_view_insert_column_with_attributes
      (GTK_TREE_VIEW (view_widget), COLUMN_DEFSTRING,
       NULL, renderer,
       "text", COLUMN_DEFSTRING, "visible", COLUMN_DEFAULT, NULL);

  return view_widget;
929 930 931
}

static void
932
glade_editor_populate_reset_view (GladeWidget *widget, GtkTreeView *tree_view)
933
{
934
  GtkTreeStore *model = GTK_TREE_STORE (gtk_tree_view_get_model (tree_view));
935 936 937
  GtkTreeIter property_iter, general_iter, common_iter, atk_iter, *iter;
  GList *list;
  GladeProperty *property;
938
  GladePropertyClass *pclass;
939 940
  gboolean def;

941
  g_return_if_fail (widget != NULL);
942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967

  gtk_tree_store_append (model, &general_iter, NULL);
  gtk_tree_store_set (model, &general_iter,
                      COLUMN_PROP_NAME, _("General"),
                      COLUMN_PROPERTY, NULL,
                      COLUMN_WEIGHT, PANGO_WEIGHT_BOLD,
                      COLUMN_CHILD, FALSE,
                      COLUMN_DEFAULT, FALSE, COLUMN_NDEFAULT, FALSE, -1);

  gtk_tree_store_append (model, &common_iter, NULL);
  gtk_tree_store_set (model, &common_iter,
                      COLUMN_PROP_NAME, _("Common"),
                      COLUMN_PROPERTY, NULL,
                      COLUMN_WEIGHT, PANGO_WEIGHT_BOLD,
                      COLUMN_CHILD, FALSE,
                      COLUMN_DEFAULT, FALSE, COLUMN_NDEFAULT, FALSE, -1);

  gtk_tree_store_append (model, &atk_iter, NULL);
  gtk_tree_store_set (model, &atk_iter,
                      COLUMN_PROP_NAME, _("Accessibility"),
                      COLUMN_PROPERTY, NULL,
                      COLUMN_WEIGHT, PANGO_WEIGHT_BOLD,
                      COLUMN_CHILD, FALSE,
                      COLUMN_DEFAULT, FALSE, COLUMN_NDEFAULT, FALSE, -1);

  /* General & Common */
968
  for (list = glade_widget_get_properties (widget); list; list = list->next)
969 970
    {
      property = list->data;
971
      pclass   = glade_property_get_class (property);
972

973
      if (glade_property_class_is_visible (pclass) == FALSE)
974 975
        continue;

976
      if (glade_property_class_atk (pclass))
977
        iter = &atk_iter;
978
      else if (glade_property_class_common (pclass))
979 980 981 982 983 984 985 986 987
        iter = &common_iter;
      else
        iter = &general_iter;

      def = glade_property_default (property);

      gtk_tree_store_append (model, &property_iter, iter);
      gtk_tree_store_set (model, &property_iter,
                          COLUMN_ENABLED, !def,
988
                          COLUMN_PROP_NAME, glade_property_class_get_name (pclass),
989 990 991 992 993 994 995
                          COLUMN_PROPERTY, property,
                          COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL,
                          COLUMN_CHILD, TRUE,
                          COLUMN_DEFAULT, def,
                          COLUMN_NDEFAULT, !def,
                          COLUMN_DEFSTRING, _("(default)"), -1);
    }
996 997 998
}

static gboolean
999
glade_editor_reset_selection_changed_cb (GtkTreeSelection *selection,
1000
                                         GtkTextView      *desc_view)
1001
{
1002 1003 1004 1005
  GtkTreeIter iter;
  GladeProperty *property = NULL;
  GtkTreeModel *model = NULL;
  GtkTextBuffer *text_buffer;
1006
  GladePropertyClass *pclass = NULL;
1007 1008 1009 1010 1011 1012 1013 1014 1015

  const gchar *message =
      _("Select the properties that you want to reset to their default values");

  /* Find selected data and show property blurb here */
  if (gtk_tree_selection_get_selected (selection, &model, &iter))
    {
      text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (desc_view));
      gtk_tree_model_get (model, &iter, COLUMN_PROPERTY, &property, -1);
1016 1017

      if (property)
1018
        pclass = glade_property_get_class (property);
1019

1020
      gtk_text_buffer_set_text (text_buffer,
1021
                                pclass ? glade_property_class_get_tooltip (pclass) : message,
1022 1023 1024 1025 1026
                                -1);
      if (property)
        g_object_unref (G_OBJECT (property));
    }
  return TRUE;
1027 1028 1029
}

static gboolean
1030
glade_editor_reset_foreach_selection (GtkTreeModel *model,
1031 1032 1033
                                      GtkTreePath  *path,
                                      GtkTreeIter  *iter,
                                      gboolean      select)
1034
{
1035 1036 1037 1038 1039 1040 1041 1042
  gboolean def;

  gtk_tree_model_get (model, iter, COLUMN_DEFAULT, &def, -1);
  /* Dont modify rows that are already default */
  if (def == FALSE)
    gtk_tree_store_set (GTK_TREE_STORE (model), iter,
                        COLUMN_ENABLED, select, -1);
  return FALSE;
1043 1044 1045 1046
}


static void
1047
glade_editor_reset_select_all_clicked (GtkButton   *button,
1048
                                       GtkTreeView *tree_view)
1049
{
1050 1051 1052 1053
  GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
  gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc)
                          glade_editor_reset_foreach_selection,
                          GINT_TO_POINTER (TRUE));
1054 1055 1056
}

static void
1057
glade_editor_reset_unselect_all_clicked (GtkButton   *button,
1058
                                         GtkTreeView *tree_view)
1059
{
1060 1061 1062 1063
  GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
  gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc)
                          glade_editor_reset_foreach_selection,
                          GINT_TO_POINTER (FALSE));
1064 1065 1066
}

static gboolean
1067
glade_editor_reset_accumulate_selected_props (GtkTreeModel *model,
1068 1069 1070
                                              GtkTreePath  *path,
                                              GtkTreeIter  *iter,
                                              GList       **accum)
1071
{
1072 1073
  GladeProperty *property;
  gboolean enabled, def;
1074

1075 1076 1077
  gtk_tree_model_get (model, iter,
                      COLUMN_PROPERTY, &property,
                      COLUMN_ENABLED, &enabled, COLUMN_DEFAULT, &def, -1);
1078

1079 1080
  if (property && enabled && !def)
    *accum = g_list_prepend (*accum, property);
1081 1082


1083 1084
  if (property)
    g_object_unref (G_OBJECT (property));
1085

1086
  return FALSE;
1087 1088 1089
}

static GList *
1090
glade_editor_reset_get_selected_props (GtkTreeModel *model)
1091
{
1092
  GList *ret = NULL;
1093

1094 1095
  gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc)
                          glade_editor_reset_accumulate_selected_props, &ret);
1096

1097
  return ret;
1098 1099 1100
}

static void
1101
glade_editor_reset_properties (GList *props)
1102
{
1103 1104 1105
  GList *list, *sdata_list = NULL;
  GCSetPropData *sdata;
  GladeProperty *prop;
1106
  GladeWidget   *widget;
1107
  GladeProject *project = NULL;
1108

1109 1110
  for (list = props; list; list = list->next)
    {
1111 1112 1113
      prop    = list->data;
      widget  = glade_property_get_widget (prop);
      project = glade_widget_get_project (widget);
1114

1115 1116
      sdata = g_new (GCSetPropData, 1);
      sdata->property = prop;
1117

1118 1119
      sdata->old_value = g_new0 (GValue, 1);
      sdata->new_value = g_new0 (GValue, 1);
1120

1121 1122
      glade_property_get_value (prop, sdata->old_value);
      glade_property_get_default (prop, sdata->new_value);
1123

1124 1125
      sdata_list = g_list_prepend (sdata_list, sdata);
    }
1126

1127 1128 1129
  if (project)
    /* GladeCommand takes ownership of allocated list, ugly but practicle */
    glade_command_set_properties_list (project, sdata_list);
1130 1131 1132

}

1133 1134
void
glade_editor_reset_dialog_run (GtkWidget *parent, GladeWidget *gwidget)
1135
{
1136
  GtkTreeSelection *selection;
1137
  GtkWidget *dialog;
1138 1139 1140 1141 1142 1143
  GtkWidget *vbox, *hbox, *label, *sw, *button;
  GtkWidget *tree_view, *description_view;
  gint res;
  GList *list;

  dialog = gtk_dialog_new_with_buttons (_("Reset Widget Properties"),
1144
                                        parent ? GTK_WINDOW (parent) : NULL,
1145 1146
                                        GTK_DIALOG_MODAL |
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
1147 1148
                                        _("_Cancel"), GTK_RESPONSE_CANCEL,
                                        _("_OK"), GTK_RESPONSE_OK, NULL);
1149

1150
  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161
  gtk_widget_show (vbox);

  gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);

  gtk_box_pack_start (GTK_BOX
                      (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), vbox,
                      TRUE, TRUE, 0);

  /* Checklist */
  label = gtk_label_new_with_mnemonic (_("_Properties:"));
  gtk_widget_show (label);
1162
  gtk_widget_set_halign (label, GTK_ALIGN_START);
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

  sw = gtk_scrolled_window_new (NULL, NULL);
  gtk_widget_show (sw);
  gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
  gtk_widget_set_size_request (sw, 400, 200);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);


1174 1175 1176
  tree_view = glade_editor_reset_view ();
  if (gwidget)
    glade_editor_populate_reset_view (gwidget, GTK_TREE_VIEW (tree_view));
1177 1178 1179 1180 1181 1182 1183
  gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));

  gtk_widget_show (tree_view);
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), tree_view);
  gtk_container_add (GTK_CONTAINER (sw), tree_view);

  /* Select all / Unselect all */
1184
  hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
  gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END);
  gtk_widget_show (hbox);
  gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);

  button = gtk_button_new_with_mnemonic (_("_Select All"));
  gtk_widget_show (button);
  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  gtk_container_set_border_width (GTK_CONTAINER (button), 6);
  g_signal_connect (G_OBJECT (button), "clicked",
                    G_CALLBACK (glade_editor_reset_select_all_clicked),
                    tree_view);

  button = gtk_button_new_with_mnemonic (_("_Unselect All"));
  gtk_widget_show (button);
  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
  gtk_container_set_border_width (GTK_CONTAINER (button), 6);
  g_signal_connect (G_OBJECT (button), "clicked",
                    G_CALLBACK (glade_editor_reset_unselect_all_clicked),
                    tree_view);


  /* Description */
  label = gtk_label_new_with_mnemonic (_("Property _Description:"));
  gtk_widget_show (label);
1209
  gtk_widget_set_halign (label, GTK_ALIGN_START);
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249
  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);

  sw = gtk_scrolled_window_new (NULL, NULL);
  gtk_widget_show (sw);
  gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
  gtk_widget_set_size_request (sw, 400, 80);
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);

  description_view = gtk_text_view_new ();
  gtk_text_view_set_editable (GTK_TEXT_VIEW (description_view), FALSE);
  gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (description_view), GTK_WRAP_WORD);

  gtk_widget_show (description_view);
  gtk_label_set_mnemonic_widget (GTK_LABEL (label), description_view);
  gtk_container_add (GTK_CONTAINER (sw), description_view);

  /* Update description */
  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
  g_signal_connect (G_OBJECT (selection), "changed",
                    G_CALLBACK (glade_editor_reset_selection_changed_cb),
                    description_view);



  /* Run the dialog */
  res = gtk_dialog_run (GTK_DIALOG (dialog));
  if (res == GTK_RESPONSE_OK)
    {

      /* get all selected properties and reset properties through glade_command */
      if ((list = glade_editor_reset_get_selected_props
           (gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)))) != NULL)
        {
          glade_editor_reset_properties (list);
          g_list_free (list);
        }
    }
  gtk_widget_destroy (dialog);
1250
}
1251 1252

void
1253
glade_editor_show_info (GladeEditor *editor)
1254
{
1255
  g_warning ("%s function is deprecated and does nothing", __func__);
1256 1257 1258
}

void
1259
glade_editor_hide_info (GladeEditor *editor)
1260
{
1261
  g_warning ("%s function is deprecated and does nothing", __func__);
1262
}
1263

1264 1265 1266
void
glade_editor_show_class_field (GladeEditor *editor)<