1 /*
2  * Copyright (C) 2001 Ximian, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Authors:
19  *   Chema Celorio <chema@celorio.com>
20  *   Tristan Van Berkom <tvb@gnome.org>
21  */
22 
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 /**
29  * SECTION:glade-editor
30  * @Short_Description: A Widget to edit a #GladeWidget.
31  *
32  * This is the Glade Notebook containing all the controls needed to configure a #GladeWidget.
33  */
34 
35 #include <stdio.h>
36 #include <string.h>
37 #include <glib/gi18n-lib.h>
38 
39 #include <gtk/gtk.h>
40 
41 #include "glade.h"
42 #include "glade-widget.h"
43 #include "glade-widget-adaptor.h"
44 #include "glade-editor.h"
45 #include "glade-signal-editor.h"
46 #include "glade-property.h"
47 #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"
54 
55 static void glade_editor_switch_page (GtkNotebook     *notebook,
56 				      GtkWidget       *page,
57 				      guint            page_num,
58 				      GladeEditor     *editor);
59 
60 enum
61 {
62   PROP_0,
63   PROP_SHOW_INFO,
64   PROP_WIDGET,
65   PROP_SHOW_CLASS_FIELD,
66   PROP_CLASS_FIELD,
67   PROP_SHOW_BORDER,
68   N_PROPERTIES
69 };
70 
71 #define GLADE_EDITOR_PRIVATE(object) (((GladeEditor*)object)->priv)
72 
73 struct _GladeEditorPrivate
74 {
75 
76   GtkWidget *notebook; /* The notebook widget */
77 
78   GladeWidget *loaded_widget; /* A handy pointer to the GladeWidget
79 			       * that is loaded in the editor. NULL
80 			       * if no widgets are selected
81 			       */
82 
83   GladeWidgetAdaptor *loaded_adaptor; /* A pointer to the loaded
84 				       * GladeWidgetAdaptor. Note that we can
85 				       * have a class loaded without a
86 				       * loaded_widget. For this reason we
87 				       * can't use loaded_widget->adaptor.
88 				       * When a widget is selected we load
89 				       * this class in the editor first and
90 				       * then fill the values of the inputs
91 				       * with the GladeProperty items.
92 				       * This is usefull for not having
93 				       * to redraw/container_add the widgets
94 				       * when we switch from widgets of the
95 				       * same class
96 				       */
97 
98   GtkWidget *page_widget;
99   GtkWidget *page_packing;
100   GtkWidget *page_common;
101   GtkWidget *page_atk;
102 
103   GladeSignalEditor *signal_editor; /* The signal editor packed into vbox_signals
104 				     */
105 
106   GList *editables;     /* A list of GladeEditables. We have a widget
107 			 * for each GladeWidgetAdaptor and we only load
108 			 * them on demand
109 			 */
110 
111   GtkWidget *packing_page; /* Packing pages are dynamicly created each
112 			    * selection, this pointer is only to free
113 			    * the last packing page.
114 			    */
115 
116   gboolean loading; /* Use when loading a GladeWidget into the editor
117 		     * we set this flag so that we can ignore the
118 		     * "changed" signal of the name entry text since
119 		     * the name has not really changed, just a new name
120 		     * was loaded.
121 		     */
122 
123   gulong project_closed_signal_id; /* Unload widget when widget's project closes  */
124   gulong project_removed_signal_id; /* Unload widget when its removed from the project. */
125   gulong widget_warning_id; /* Update when widget changes warning messages. */
126   gulong widget_name_id;    /* Update class field when widget name changes  */
127 
128   GtkWidget *class_field; /* The class header */
129 
130   GtkWidget *warning;   /* A pointer to an icon we can show in the class
131 			 * field to publish tooltips for class related
132 			 * versioning errors.
133 			 */
134 
135   GtkWidget *class_icon; /* An image with the current widget's class icon.  */
136   GtkWidget *class_label; /* A label with the current class label. */
137 
138   gboolean show_class_field; /* Whether or not to show the class field at the top */
139 };
140 
141 G_DEFINE_TYPE_WITH_PRIVATE (GladeEditor, glade_editor, GTK_TYPE_BOX);
142 
143 static GParamSpec *properties[N_PROPERTIES];
144 
145 static void
glade_editor_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)146 glade_editor_set_property (GObject      *object,
147                            guint         prop_id,
148                            const GValue *value,
149                            GParamSpec   *pspec)
150 {
151   GladeEditor *editor = GLADE_EDITOR (object);
152 
153   switch (prop_id)
154     {
155       case PROP_SHOW_INFO:
156         break;
157       case PROP_WIDGET:
158         glade_editor_load_widget (editor,
159                                   GLADE_WIDGET (g_value_get_object (value)));
160         break;
161       case PROP_SHOW_CLASS_FIELD:
162         if (g_value_get_boolean (value))
163           glade_editor_show_class_field (editor);
164         else
165           glade_editor_hide_class_field (editor);
166         break;
167       case PROP_SHOW_BORDER:
168         gtk_notebook_set_show_border (GTK_NOTEBOOK (editor->priv->notebook),
169                                       g_value_get_boolean (value));
170         break;
171       default:
172         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
173         break;
174     }
175 }
176 
177 static void
glade_editor_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)178 glade_editor_get_property (GObject    *object,
179                            guint       prop_id,
180                            GValue     *value,
181                            GParamSpec *pspec)
182 {
183   GladeEditor *editor = GLADE_EDITOR (object);
184 
185   switch (prop_id)
186     {
187       case PROP_SHOW_INFO:
188         g_value_set_boolean (value, FALSE);
189         break;
190       case PROP_WIDGET:
191         g_value_set_object (value, editor->priv->loaded_widget);
192         break;
193       case PROP_SHOW_CLASS_FIELD:
194         g_value_set_boolean (value, editor->priv->show_class_field);
195         break;
196       case PROP_CLASS_FIELD:
197         g_value_set_static_string (value, gtk_label_get_label (GTK_LABEL (editor->priv->class_label)));
198         break;
199       case PROP_SHOW_BORDER:
200         g_value_set_boolean (value, gtk_notebook_get_show_border (GTK_NOTEBOOK (editor->priv->notebook)));
201         break;
202       default:
203         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
204         break;
205     }
206 }
207 
208 static void
glade_editor_dispose(GObject * object)209 glade_editor_dispose (GObject *object)
210 {
211   GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (object);
212   GladeEditor *editor = GLADE_EDITOR (object);
213 
214   glade_editor_load_widget (editor, NULL);
215 
216   /* Unref all the cached pages */
217   g_list_foreach (priv->editables, (GFunc) g_object_unref, NULL);
218   priv->editables = (g_list_free (priv->editables), NULL);
219 
220   G_OBJECT_CLASS (glade_editor_parent_class)->dispose (object);
221 }
222 
223 static void
glade_editor_class_init(GladeEditorClass * klass)224 glade_editor_class_init (GladeEditorClass *klass)
225 {
226   GObjectClass *object_class = G_OBJECT_CLASS (klass);
227   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
228 
229   object_class->dispose      = glade_editor_dispose;
230   object_class->set_property = glade_editor_set_property;
231   object_class->get_property = glade_editor_get_property;
232 
233   /* Properties */
234   properties[PROP_SHOW_INFO] =
235     g_param_spec_boolean ("show-info",
236                           _("Show info"),
237                           _("Whether to show an informational "
238                             "button for the loaded widget"),
239                           FALSE,
240                           G_PARAM_READABLE | G_PARAM_DEPRECATED);
241 
242   properties[PROP_WIDGET] =
243     g_param_spec_object ("widget",
244                          _("Widget"),
245                          _("The currently loaded widget in this editor"),
246                          GLADE_TYPE_WIDGET,
247                          G_PARAM_READWRITE);
248 
249   properties[PROP_SHOW_CLASS_FIELD] =
250     g_param_spec_boolean ("show-class-field",
251                           _("Show Class Field"),
252                           _("Whether to show the class field at the top"),
253                           TRUE,
254                           G_PARAM_READWRITE);
255 
256   properties[PROP_CLASS_FIELD] =
257     g_param_spec_string ("class-field",
258                          _("Class Field"),
259                          _("The class field string"),
260                          NULL,
261                          G_PARAM_READABLE);
262   properties[PROP_SHOW_BORDER] =
263     g_param_spec_boolean ("show-boder",
264                           _("Show Border"),
265                           _("Whether the border should be shown"),
266                           TRUE,
267                           G_PARAM_READWRITE);
268 
269   /* Install all properties */
270   g_object_class_install_properties (object_class, N_PROPERTIES, properties);
271 
272   /* Bind to template */
273   gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/gladeui/glade-editor.ui");
274 
275   gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, notebook);
276   gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, page_widget);
277   gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, page_packing);
278   gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, page_common);
279   gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, page_atk);
280   gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, class_field);
281   gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, class_icon);
282   gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, class_label);
283   gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, warning);
284   gtk_widget_class_bind_template_child_private (widget_class, GladeEditor, signal_editor);
285 
286   gtk_widget_class_bind_template_callback (widget_class, glade_editor_switch_page);
287 }
288 
289 static void
glade_editor_update_class_warning_cb(GladeWidget * widget,GParamSpec * pspec,GladeEditor * editor)290 glade_editor_update_class_warning_cb (GladeWidget *widget,
291                                       GParamSpec  *pspec,
292                                       GladeEditor *editor)
293 {
294   GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (editor);
295 
296   if (glade_widget_support_warning (widget))
297     gtk_widget_show (priv->warning);
298   else
299     gtk_widget_hide (priv->warning);
300 
301   gtk_widget_set_tooltip_text (priv->warning, glade_widget_support_warning (widget));
302 }
303 
304 
305 static void
glade_editor_update_class_field(GladeEditor * editor)306 glade_editor_update_class_field (GladeEditor *editor)
307 {
308   GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (editor);
309 
310   if (priv->loaded_widget)
311     {
312       GladeWidget *widget = priv->loaded_widget;
313       gchar *text;
314 
315       gtk_image_set_from_icon_name (GTK_IMAGE (priv->class_icon),
316                                     glade_widget_adaptor_get_icon_name (priv->loaded_adaptor),
317                                     GTK_ICON_SIZE_BUTTON);
318       gtk_widget_show (priv->class_icon);
319 
320       if (glade_widget_has_name (widget))
321         {
322           /* translators: %s(Class Title) Properties - %s (ClassName) [%s(WidgetName)]
323            * example: Window Properties - GtkWindow [window1]
324            */
325           text = g_strdup_printf (_("%s Properties - %s [%s]"),
326                                   glade_widget_adaptor_get_title (priv->loaded_adaptor),
327                                   glade_widget_adaptor_get_name (priv->loaded_adaptor),
328 		                  glade_widget_get_display_name (widget));
329         }
330       else
331         {
332           /* translators: %s(Class Title) Properties - %s (ClassName)
333            * example: Window Properties - GtkWindow
334            */
335           text = g_strdup_printf (_("%s Properties - %s"),
336                                   glade_widget_adaptor_get_title (priv->loaded_adaptor),
337                                   glade_widget_adaptor_get_name (priv->loaded_adaptor));
338 	}
339 
340       gtk_label_set_text (GTK_LABEL (priv->class_label), text);
341       g_free (text);
342 
343       glade_editor_update_class_warning_cb (priv->loaded_widget, NULL, editor);
344     }
345   else
346     {
347       gtk_widget_hide (priv->class_icon);
348       gtk_widget_hide (priv->warning);
349       gtk_label_set_text (GTK_LABEL (priv->class_label), _("Properties"));
350     }
351 
352   g_object_notify_by_pspec (G_OBJECT (editor), properties[PROP_CLASS_FIELD]);
353 }
354 
355 static void
glade_editor_update_widget_name_cb(GladeWidget * widget,GParamSpec * pspec,GladeEditor * editor)356 glade_editor_update_widget_name_cb (GladeWidget *widget,
357                                     GParamSpec  *pspec,
358                                     GladeEditor *editor)
359 {
360   glade_editor_update_class_field (editor);
361 }
362 
363 static void
glade_editor_switch_page(GtkNotebook * notebook,GtkWidget * page,guint page_num,GladeEditor * editor)364 glade_editor_switch_page (GtkNotebook     *notebook,
365 			  GtkWidget       *page,
366 			  guint            page_num,
367 			  GladeEditor     *editor)
368 {
369   GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (editor);
370 
371   gtk_widget_hide (priv->page_widget);
372   gtk_widget_hide (priv->page_packing);
373   gtk_widget_hide (priv->page_common);
374   gtk_widget_hide (priv->page_atk);
375 
376   switch (page_num)
377     {
378     case 0:
379       gtk_widget_show (priv->page_widget);
380       break;
381     case 1:
382       gtk_widget_show (priv->page_packing);
383       break;
384     case 2:
385       gtk_widget_show (priv->page_common);
386       break;
387     case 4:
388       gtk_widget_show (priv->page_atk);
389       break;
390     }
391 }
392 
393 static void
glade_editor_init(GladeEditor * editor)394 glade_editor_init (GladeEditor *editor)
395 {
396   GladeEditorPrivate *priv;
397   gint                icon_height;
398 
399   editor->priv = priv = glade_editor_get_instance_private (editor);
400 
401   priv->show_class_field = TRUE;
402 
403   gtk_widget_init_template (GTK_WIDGET (editor));
404 
405   gtk_icon_size_lookup (GTK_ICON_SIZE_BUTTON, NULL, &icon_height);
406   gtk_widget_set_size_request (priv->class_label, -1, icon_height + 2);
407 
408   glade_editor_update_class_field (editor);
409 }
410 
411 static GtkWidget *
glade_editor_get_editable_by_adaptor(GladeEditor * editor,GladeWidgetAdaptor * adaptor,GladeEditorPageType type)412 glade_editor_get_editable_by_adaptor (GladeEditor        *editor,
413                                       GladeWidgetAdaptor *adaptor,
414                                       GladeEditorPageType type)
415 {
416   GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (editor);
417   GtkWidget *editable;
418   GList *list;
419 
420   g_return_val_if_fail (GLADE_IS_WIDGET_ADAPTOR (adaptor), NULL);
421 
422   for (list = priv->editables; list; list = list->next)
423     {
424       editable = list->data;
425       if (type !=
426           GPOINTER_TO_INT (g_object_get_data
427                            (G_OBJECT (editable), "glade-editor-page-type")))
428         continue;
429       if (g_object_get_data (G_OBJECT (editable), "glade-widget-adaptor") ==
430           adaptor)
431         return editable;
432     }
433 
434   editable = (GtkWidget *) glade_widget_adaptor_create_editable (adaptor, type);
435   g_return_val_if_fail (editable != NULL, NULL);
436 
437   g_object_set_data (G_OBJECT (editable), "glade-editor-page-type",
438                      GINT_TO_POINTER (type));
439   g_object_set_data (G_OBJECT (editable), "glade-widget-adaptor", adaptor);
440 
441   if (type != GLADE_PAGE_PACKING)
442     {
443       priv->editables = g_list_prepend (priv->editables, editable);
444       g_object_ref_sink (editable);
445     }
446 
447   return editable;
448 }
449 
450 static void
hide_or_remove_visible_child(GtkContainer * container,gboolean remove)451 hide_or_remove_visible_child (GtkContainer *container, gboolean remove)
452 {
453   GList *l, *children = gtk_container_get_children (container);
454   GtkWidget *widget;
455 
456   for (l = children; l; l = l->next)
457     {
458       widget = l->data;
459 
460       if (gtk_widget_get_visible (widget))
461 	{
462 	  gtk_widget_hide (widget);
463 
464 	  if (remove)
465 	    gtk_container_remove (container, widget);
466 
467 	  break;
468 	}
469     }
470   g_list_free (children);
471 }
472 
473 static GtkWidget *
glade_editor_load_editable_in_page(GladeEditor * editor,GladeWidgetAdaptor * adaptor,GladeEditorPageType type)474 glade_editor_load_editable_in_page (GladeEditor        *editor,
475                                     GladeWidgetAdaptor *adaptor,
476                                     GladeEditorPageType type)
477 {
478   GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (editor);
479   GtkContainer *container = NULL;
480   GtkWidget *scrolled_window, *editable;
481   GtkAdjustment *adj;
482 
483   /* Remove the old table that was in this container */
484   switch (type)
485     {
486       case GLADE_PAGE_GENERAL:
487         container = GTK_CONTAINER (priv->page_widget);
488         break;
489       case GLADE_PAGE_COMMON:
490         container = GTK_CONTAINER (priv->page_common);
491         break;
492       case GLADE_PAGE_PACKING:
493         container = GTK_CONTAINER (priv->page_packing);
494         break;
495       case GLADE_PAGE_ATK:
496         container = GTK_CONTAINER (priv->page_atk);
497         break;
498       case GLADE_PAGE_QUERY:
499       default:
500         g_critical ("Unreachable code reached !");
501         break;
502     }
503 
504   /* Hide the editable (this will destroy on packing pages) */
505   hide_or_remove_visible_child (container, type == GLADE_PAGE_PACKING);
506 
507   if (!adaptor)
508     return NULL;
509 
510   if ((editable =
511        glade_editor_get_editable_by_adaptor (editor, adaptor, type)) == NULL)
512     return NULL;
513 
514   /* Attach the new page */
515   if (!gtk_widget_get_parent (editable))
516     gtk_container_add (GTK_CONTAINER (container), editable);
517   gtk_widget_show (editable);
518 
519   if ((scrolled_window =
520        gtk_widget_get_ancestor (GTK_WIDGET (container),
521 				GTK_TYPE_SCROLLED_WINDOW)) != NULL)
522     {
523       adj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window));
524       gtk_container_set_focus_vadjustment (GTK_CONTAINER (editable), adj);
525 
526       adj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled_window));
527       gtk_container_set_focus_hadjustment (GTK_CONTAINER (editable), adj);
528     }
529 
530   return editable;
531 }
532 
533 static void
glade_editor_load_widget_class(GladeEditor * editor,GladeWidgetAdaptor * adaptor)534 glade_editor_load_widget_class (GladeEditor *editor,
535                                 GladeWidgetAdaptor *adaptor)
536 {
537 
538   glade_editor_load_editable_in_page (editor, adaptor, GLADE_PAGE_GENERAL);
539   glade_editor_load_editable_in_page (editor, adaptor, GLADE_PAGE_COMMON);
540   glade_editor_load_editable_in_page (editor, adaptor, GLADE_PAGE_ATK);
541   glade_editor_load_editable_in_page (editor, NULL, GLADE_PAGE_PACKING);
542 
543   editor->priv->loaded_adaptor = adaptor;
544 }
545 
546 static void
glade_editor_close_cb(GladeProject * project,GladeEditor * editor)547 glade_editor_close_cb (GladeProject *project, GladeEditor *editor)
548 {
549   /* project we are viewing was closed,
550    * detatch from editor.
551    */
552   glade_editor_load_widget (editor, NULL);
553 }
554 
555 static void
glade_editor_removed_cb(GladeProject * project,GladeWidget * widget,GladeEditor * editor)556 glade_editor_removed_cb (GladeProject *project,
557                          GladeWidget *widget,
558                          GladeEditor *editor)
559 {
560   /* Widget we were viewing was removed from project,
561    * detatch from editor.
562    */
563   if (widget == editor->priv->loaded_widget)
564     glade_editor_load_widget (editor, NULL);
565 
566 }
567 
568 
569 static void
glade_editor_load_editable(GladeEditor * editor,GladeWidget * widget,GladeEditorPageType type)570 glade_editor_load_editable (GladeEditor        *editor,
571                             GladeWidget        *widget,
572                             GladeEditorPageType type)
573 {
574   GtkWidget   *editable;
575   GladeWidget *parent = glade_widget_get_parent (widget);
576 
577   /* Use the parenting adaptor for packing pages... so deffer creating the widgets
578    * until load time.
579    */
580   if (type == GLADE_PAGE_PACKING)
581     {
582       GladeWidgetAdaptor *adaptor;
583 
584       if (!parent)
585 	return;
586 
587       adaptor = glade_widget_get_adaptor (parent);
588       editable =
589 	glade_editor_load_editable_in_page (editor, adaptor,
590 					    GLADE_PAGE_PACKING);
591     }
592   else
593     editable =
594       glade_editor_get_editable_by_adaptor (editor,
595 					    glade_widget_get_adaptor (widget),
596 					    type);
597 
598   g_assert (editable);
599 
600   if (!widget)
601     gtk_widget_hide (editable);
602 
603   glade_editable_load (GLADE_EDITABLE (editable), widget);
604 
605   if (widget)
606     gtk_widget_show (editable);
607 }
608 
609 static void
clear_editables(GladeEditor * editor)610 clear_editables (GladeEditor *editor)
611 {
612   GladeEditable *editable;
613   GList *l;
614 
615   for (l = editor->priv->editables; l; l = l->next)
616     {
617       editable = l->data;
618       glade_editable_load (editable, NULL);
619     }
620 }
621 
622 static void
glade_editor_load_widget_real(GladeEditor * editor,GladeWidget * widget)623 glade_editor_load_widget_real (GladeEditor *editor, GladeWidget *widget)
624 {
625   GladeEditorPrivate *priv = GLADE_EDITOR_PRIVATE (editor);
626   GladeWidgetAdaptor *adaptor;
627   GladeProject *project;
628 
629   /* Disconnect from last widget */
630   if (priv->loaded_widget != NULL)
631     {
632       /* better pay a small price now and avoid unseen editables
633        * waking up on project metadata changes.
634        */
635       clear_editables (editor);
636 
637       project = glade_widget_get_project (priv->loaded_widget);
638       g_signal_handler_disconnect (G_OBJECT (project),
639                                    priv->project_closed_signal_id);
640       g_signal_handler_disconnect (G_OBJECT (project),
641                                    priv->project_removed_signal_id);
642       g_signal_handler_disconnect (G_OBJECT (priv->loaded_widget),
643                                    priv->widget_warning_id);
644       g_signal_handler_disconnect (G_OBJECT (priv->loaded_widget),
645                                    priv->widget_name_id);
646     }
647 
648   /* Load the GladeWidgetClass */
649   adaptor = widget ? glade_widget_get_adaptor (widget) : NULL;
650   if (priv->loaded_adaptor != adaptor || adaptor == NULL)
651     glade_editor_load_widget_class (editor, adaptor);
652 
653   glade_signal_editor_load_widget (priv->signal_editor, widget);
654 
655   /* we are just clearing, we are done */
656   if (widget == NULL)
657     {
658       priv->loaded_widget = NULL;
659 
660       /* Clear class header */
661       glade_editor_update_class_field (editor);
662 
663       g_object_notify_by_pspec (G_OBJECT (editor), properties[PROP_WIDGET]);
664 
665       return;
666     }
667 
668   priv->loading = TRUE;
669 
670   /* Load each GladeEditorProperty from 'widget' */
671   glade_editor_load_editable (editor, widget, GLADE_PAGE_GENERAL);
672   glade_editor_load_editable (editor, widget, GLADE_PAGE_COMMON);
673   glade_editor_load_editable (editor, widget, GLADE_PAGE_ATK);
674   glade_editor_load_editable (editor, widget, GLADE_PAGE_PACKING);
675 
676   priv->loaded_widget = widget;
677   priv->loading = FALSE;
678 
679   /* Update class header */
680   glade_editor_update_class_field (editor);
681 
682   /* Connect to new widget */
683   project = glade_widget_get_project (priv->loaded_widget);
684   priv->project_closed_signal_id =
685       g_signal_connect (G_OBJECT (project), "close",
686                         G_CALLBACK (glade_editor_close_cb), editor);
687   priv->project_removed_signal_id =
688       g_signal_connect (G_OBJECT (project), "remove-widget",
689                         G_CALLBACK (glade_editor_removed_cb), editor);
690   priv->widget_warning_id =
691       g_signal_connect (G_OBJECT (widget), "notify::support-warning",
692                         G_CALLBACK (glade_editor_update_class_warning_cb),
693                         editor);
694   priv->widget_name_id =
695       g_signal_connect (G_OBJECT (widget), "notify::name",
696                         G_CALLBACK (glade_editor_update_widget_name_cb),
697                         editor);
698 
699   g_object_notify_by_pspec (G_OBJECT (editor), properties[PROP_WIDGET]);
700 }
701 
702 
703 /**
704  * glade_editor_new:
705  *
706  * Returns: a new #GladeEditor
707  */
708 GladeEditor *
glade_editor_new(void)709 glade_editor_new (void)
710 {
711   GladeEditor *editor;
712 
713   editor = g_object_new (GLADE_TYPE_EDITOR, "spacing", 6, NULL);
714 
715   return editor;
716 }
717 
718 /**
719  * glade_editor_load_widget:
720  * @editor: a #GladeEditor
721  * @widget: a #GladeWidget
722  *
723  * Load @widget into @editor. If @widget is %NULL, clear the editor.
724  */
725 void
glade_editor_load_widget(GladeEditor * editor,GladeWidget * widget)726 glade_editor_load_widget (GladeEditor *editor, GladeWidget *widget)
727 {
728   g_return_if_fail (GLADE_IS_EDITOR (editor));
729   g_return_if_fail (widget == NULL || GLADE_IS_WIDGET (widget));
730 
731   if (editor->priv->loaded_widget == widget)
732     return;
733 
734   glade_editor_load_widget_real (editor, widget);
735 }
736 
737 static void
query_dialog_style_set_cb(GtkWidget * dialog,GtkStyle * previous_style,gpointer user_data)738 query_dialog_style_set_cb (GtkWidget *dialog,
739                            GtkStyle *previous_style,
740                            gpointer user_data)
741 {
742   GtkWidget *content_area, *action_area;
743 
744   content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
745   gtk_container_set_border_width (GTK_CONTAINER (content_area), 12);
746   gtk_box_set_spacing (GTK_BOX (content_area), 12);
747   action_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
748   gtk_container_set_border_width (GTK_CONTAINER (action_area), 0);
749   gtk_box_set_spacing (GTK_BOX (action_area), 6);
750 }
751 
752 static gboolean
query_dialog_delete_event_cb(GtkDialog * dialog,GdkEvent * event,gpointer user_data)753 query_dialog_delete_event_cb (GtkDialog *dialog,
754 			      GdkEvent  *event,
755 			      gpointer   user_data)
756 {
757   gtk_dialog_response (dialog, GTK_RESPONSE_CANCEL);
758   return TRUE;
759 }
760 
761 gboolean
glade_editor_query_dialog(GladeWidget * widget)762 glade_editor_query_dialog (GladeWidget *widget)
763 {
764   GladeWidgetAdaptor *adaptor;
765   GtkWidget *dialog, *editable, *content_area;
766   GtkWidget *create;
767   gchar *title;
768   gint answer;
769   gboolean retval = TRUE;
770 
771   g_return_val_if_fail (GLADE_IS_WIDGET (widget), FALSE);
772 
773   adaptor = glade_widget_get_adaptor (widget);
774 
775   title = g_strdup_printf (_("Create a %s"), glade_widget_adaptor_get_name (adaptor));
776   dialog = gtk_dialog_new_with_buttons (title, NULL,
777                                         GTK_DIALOG_MODAL |
778                                         GTK_DIALOG_DESTROY_WITH_PARENT,
779                                         _("_Cancel"), GTK_RESPONSE_CANCEL,
780                                         NULL);
781   g_free (title);
782 
783   create = gtk_button_new_with_mnemonic (_("Crea_te"));
784   gtk_widget_show (create);
785   gtk_widget_set_can_default (create, TRUE);
786   gtk_dialog_add_action_widget (GTK_DIALOG (dialog), create, GTK_RESPONSE_OK);
787 
788   gtk_dialog_set_alternative_button_order (GTK_DIALOG (dialog),
789                                            GTK_RESPONSE_OK,
790                                            GTK_RESPONSE_CANCEL, -1);
791   gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
792 
793   editable = (GtkWidget *) glade_widget_adaptor_create_editable (adaptor, GLADE_PAGE_QUERY);
794   gtk_widget_show (editable);
795 
796   content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
797   gtk_box_pack_start (GTK_BOX (content_area), editable, FALSE, FALSE, 6);
798 
799   glade_editable_load (GLADE_EDITABLE (editable), widget);
800 
801   g_signal_connect (dialog, "style-set",
802                     G_CALLBACK (query_dialog_style_set_cb), NULL);
803 
804   g_signal_connect (dialog, "delete-event",
805                     G_CALLBACK (query_dialog_delete_event_cb), NULL);
806 
807   answer = gtk_dialog_run (GTK_DIALOG (dialog));
808 
809   /*
810    * If user cancel's we cancel the whole "create operation" by
811    * return FALSE. glade_widget_new() will see the FALSE, and
812    * take care of canceling the "create" operation.
813    */
814   if (answer == GTK_RESPONSE_CANCEL)
815     retval = FALSE;
816 
817   gtk_widget_destroy (dialog);
818   return retval;
819 }
820 
821 enum
822 {
823   COLUMN_ENABLED = 0,
824   COLUMN_PROP_NAME,
825   COLUMN_PROPERTY,
826   COLUMN_WEIGHT,
827   COLUMN_CHILD,
828   COLUMN_DEFAULT,
829   COLUMN_NDEFAULT,
830   COLUMN_DEFSTRING,
831   NUM_COLUMNS
832 };
833 
834 
835 static void
glade_editor_reset_toggled(GtkCellRendererToggle * cell,gchar * path_str,GtkTreeModel * model)836 glade_editor_reset_toggled (GtkCellRendererToggle *cell,
837                             gchar                 *path_str,
838                             GtkTreeModel          *model)
839 {
840   GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
841   GtkTreeIter iter;
842   gboolean enabled;
843 
844   /* get toggled iter */
845   gtk_tree_model_get_iter (model, &iter, path);
846   gtk_tree_model_get (model, &iter, COLUMN_ENABLED, &enabled, -1);
847   gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
848                       COLUMN_ENABLED, !enabled, -1);
849   gtk_tree_path_free (path);
850 }
851 
852 static GtkWidget *
glade_editor_reset_view(void)853 glade_editor_reset_view (void)
854 {
855   GtkWidget *view_widget;
856   GtkTreeModel *model;
857   GtkCellRenderer *renderer;
858   GtkTreeViewColumn *column;
859 
860   model = (GtkTreeModel *) gtk_tree_store_new (NUM_COLUMNS, G_TYPE_BOOLEAN,     /* Enabled  value      */
861                                                G_TYPE_STRING,   /* Property name       */
862                                                GLADE_TYPE_PROPERTY,     /* The property        */
863                                                G_TYPE_INT,      /* Parent node ?       */
864                                                G_TYPE_BOOLEAN,  /* Child node ?        */
865                                                G_TYPE_BOOLEAN,  /* Has default value   */
866                                                G_TYPE_BOOLEAN,  /* Doesn't have defaut */
867                                                G_TYPE_STRING);  /* Default string      */
868 
869   view_widget = gtk_tree_view_new_with_model (model);
870   g_object_set (G_OBJECT (view_widget), "enable-search", FALSE, NULL);
871 
872   /********************* fake invisible column *********************/
873   renderer = gtk_cell_renderer_text_new ();
874   g_object_set (G_OBJECT (renderer), "editable", FALSE, "visible", FALSE, NULL);
875 
876   column = gtk_tree_view_column_new_with_attributes (NULL, renderer, NULL);
877   gtk_tree_view_append_column (GTK_TREE_VIEW (view_widget), column);
878 
879   gtk_tree_view_column_set_visible (column, FALSE);
880   gtk_tree_view_set_expander_column (GTK_TREE_VIEW (view_widget), column);
881 
882   /************************ enabled column ************************/
883   renderer = gtk_cell_renderer_toggle_new ();
884   g_object_set (G_OBJECT (renderer),
885                 "mode", GTK_CELL_RENDERER_MODE_ACTIVATABLE,
886                 "activatable", TRUE, NULL);
887   g_signal_connect (renderer, "toggled",
888                     G_CALLBACK (glade_editor_reset_toggled), model);
889   gtk_tree_view_insert_column_with_attributes
890       (GTK_TREE_VIEW (view_widget), COLUMN_ENABLED,
891        _("Reset"), renderer,
892        "sensitive", COLUMN_NDEFAULT,
893        "activatable", COLUMN_NDEFAULT,
894        "active", COLUMN_ENABLED, "visible", COLUMN_CHILD, NULL);
895 
896   /********************* property name column *********************/
897   renderer = gtk_cell_renderer_text_new ();
898   g_object_set (G_OBJECT (renderer), "editable", FALSE, NULL);
899 
900   gtk_tree_view_insert_column_with_attributes
901       (GTK_TREE_VIEW (view_widget), COLUMN_PROP_NAME,
902        _("Property"), renderer,
903        "text", COLUMN_PROP_NAME, "weight", COLUMN_WEIGHT, NULL);
904 
905   /******************* default indicator column *******************/
906   renderer = gtk_cell_renderer_text_new ();
907   g_object_set (G_OBJECT (renderer),
908                 "editable", FALSE,
909                 "style", PANGO_STYLE_ITALIC, "foreground", "Gray", NULL);
910 
911   gtk_tree_view_insert_column_with_attributes
912       (GTK_TREE_VIEW (view_widget), COLUMN_DEFSTRING,
913        NULL, renderer,
914        "text", COLUMN_DEFSTRING, "visible", COLUMN_DEFAULT, NULL);
915 
916   return view_widget;
917 }
918 
919 static void
glade_editor_populate_reset_view(GladeWidget * widget,GtkTreeView * tree_view)920 glade_editor_populate_reset_view (GladeWidget *widget, GtkTreeView *tree_view)
921 {
922   GtkTreeStore *model = GTK_TREE_STORE (gtk_tree_view_get_model (tree_view));
923   GtkTreeIter property_iter, general_iter, common_iter, atk_iter, *iter;
924   GList *list;
925   GladeProperty *property;
926   GladePropertyClass *pclass;
927   gboolean def;
928 
929   g_return_if_fail (widget != NULL);
930 
931   gtk_tree_store_append (model, &general_iter, NULL);
932   gtk_tree_store_set (model, &general_iter,
933                       COLUMN_PROP_NAME, _("General"),
934                       COLUMN_PROPERTY, NULL,
935                       COLUMN_WEIGHT, PANGO_WEIGHT_BOLD,
936                       COLUMN_CHILD, FALSE,
937                       COLUMN_DEFAULT, FALSE, COLUMN_NDEFAULT, FALSE, -1);
938 
939   gtk_tree_store_append (model, &common_iter, NULL);
940   gtk_tree_store_set (model, &common_iter,
941                       COLUMN_PROP_NAME, _("Common"),
942                       COLUMN_PROPERTY, NULL,
943                       COLUMN_WEIGHT, PANGO_WEIGHT_BOLD,
944                       COLUMN_CHILD, FALSE,
945                       COLUMN_DEFAULT, FALSE, COLUMN_NDEFAULT, FALSE, -1);
946 
947   gtk_tree_store_append (model, &atk_iter, NULL);
948   gtk_tree_store_set (model, &atk_iter,
949                       COLUMN_PROP_NAME, _("Accessibility"),
950                       COLUMN_PROPERTY, NULL,
951                       COLUMN_WEIGHT, PANGO_WEIGHT_BOLD,
952                       COLUMN_CHILD, FALSE,
953                       COLUMN_DEFAULT, FALSE, COLUMN_NDEFAULT, FALSE, -1);
954 
955   /* General & Common */
956   for (list = glade_widget_get_properties (widget); list; list = list->next)
957     {
958       property = list->data;
959       pclass   = glade_property_get_class (property);
960 
961       if (glade_property_class_is_visible (pclass) == FALSE)
962         continue;
963 
964       if (glade_property_class_atk (pclass))
965         iter = &atk_iter;
966       else if (glade_property_class_common (pclass))
967         iter = &common_iter;
968       else
969         iter = &general_iter;
970 
971       def = glade_property_default (property);
972 
973       gtk_tree_store_append (model, &property_iter, iter);
974       gtk_tree_store_set (model, &property_iter,
975                           COLUMN_ENABLED, !def,
976                           COLUMN_PROP_NAME, glade_property_class_get_name (pclass),
977                           COLUMN_PROPERTY, property,
978                           COLUMN_WEIGHT, PANGO_WEIGHT_NORMAL,
979                           COLUMN_CHILD, TRUE,
980                           COLUMN_DEFAULT, def,
981                           COLUMN_NDEFAULT, !def,
982                           COLUMN_DEFSTRING, _("(default)"), -1);
983     }
984 }
985 
986 static gboolean
glade_editor_reset_selection_changed_cb(GtkTreeSelection * selection,GtkTextView * desc_view)987 glade_editor_reset_selection_changed_cb (GtkTreeSelection *selection,
988                                          GtkTextView      *desc_view)
989 {
990   GtkTreeIter iter;
991   GladeProperty *property = NULL;
992   GtkTreeModel *model = NULL;
993   GtkTextBuffer *text_buffer;
994   GladePropertyClass *pclass = NULL;
995 
996   const gchar *message =
997       _("Select the properties that you want to reset to their default values");
998 
999   /* Find selected data and show property blurb here */
1000   if (gtk_tree_selection_get_selected (selection, &model, &iter))
1001     {
1002       text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (desc_view));
1003       gtk_tree_model_get (model, &iter, COLUMN_PROPERTY, &property, -1);
1004 
1005       if (property)
1006 	pclass = glade_property_get_class (property);
1007 
1008       gtk_text_buffer_set_text (text_buffer,
1009                                 pclass ? glade_property_class_get_tooltip (pclass) : message,
1010                                 -1);
1011       if (property)
1012         g_object_unref (G_OBJECT (property));
1013     }
1014   return TRUE;
1015 }
1016 
1017 static gboolean
glade_editor_reset_foreach_selection(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,gboolean select)1018 glade_editor_reset_foreach_selection (GtkTreeModel *model,
1019                                       GtkTreePath  *path,
1020                                       GtkTreeIter  *iter,
1021                                       gboolean      select)
1022 {
1023   gboolean def;
1024 
1025   gtk_tree_model_get (model, iter, COLUMN_DEFAULT, &def, -1);
1026   /* Dont modify rows that are already default */
1027   if (def == FALSE)
1028     gtk_tree_store_set (GTK_TREE_STORE (model), iter,
1029                         COLUMN_ENABLED, select, -1);
1030   return FALSE;
1031 }
1032 
1033 
1034 static void
glade_editor_reset_select_all_clicked(GtkButton * button,GtkTreeView * tree_view)1035 glade_editor_reset_select_all_clicked (GtkButton   *button,
1036                                        GtkTreeView *tree_view)
1037 {
1038   GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
1039   gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc)
1040                           glade_editor_reset_foreach_selection,
1041                           GINT_TO_POINTER (TRUE));
1042 }
1043 
1044 static void
glade_editor_reset_unselect_all_clicked(GtkButton * button,GtkTreeView * tree_view)1045 glade_editor_reset_unselect_all_clicked (GtkButton   *button,
1046                                          GtkTreeView *tree_view)
1047 {
1048   GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
1049   gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc)
1050                           glade_editor_reset_foreach_selection,
1051                           GINT_TO_POINTER (FALSE));
1052 }
1053 
1054 static gboolean
glade_editor_reset_accumulate_selected_props(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,GList ** accum)1055 glade_editor_reset_accumulate_selected_props (GtkTreeModel *model,
1056                                               GtkTreePath  *path,
1057                                               GtkTreeIter  *iter,
1058                                               GList       **accum)
1059 {
1060   GladeProperty *property;
1061   gboolean enabled, def;
1062 
1063   gtk_tree_model_get (model, iter,
1064                       COLUMN_PROPERTY, &property,
1065                       COLUMN_ENABLED, &enabled, COLUMN_DEFAULT, &def, -1);
1066 
1067   if (property && enabled && !def)
1068     *accum = g_list_prepend (*accum, property);
1069 
1070 
1071   if (property)
1072     g_object_unref (G_OBJECT (property));
1073 
1074   return FALSE;
1075 }
1076 
1077 static GList *
glade_editor_reset_get_selected_props(GtkTreeModel * model)1078 glade_editor_reset_get_selected_props (GtkTreeModel *model)
1079 {
1080   GList *ret = NULL;
1081 
1082   gtk_tree_model_foreach (model, (GtkTreeModelForeachFunc)
1083                           glade_editor_reset_accumulate_selected_props, &ret);
1084 
1085   return ret;
1086 }
1087 
1088 static void
glade_editor_reset_properties(GList * props)1089 glade_editor_reset_properties (GList *props)
1090 {
1091   GList *list, *sdata_list = NULL;
1092   GCSetPropData *sdata;
1093   GladeProperty *prop;
1094   GladeWidget   *widget;
1095   GladeProject *project = NULL;
1096 
1097   for (list = props; list; list = list->next)
1098     {
1099       prop    = list->data;
1100       widget  = glade_property_get_widget (prop);
1101       project = glade_widget_get_project (widget);
1102 
1103       sdata = g_new (GCSetPropData, 1);
1104       sdata->property = prop;
1105 
1106       sdata->old_value = g_new0 (GValue, 1);
1107       sdata->new_value = g_new0 (GValue, 1);
1108 
1109       glade_property_get_value (prop, sdata->old_value);
1110       glade_property_get_default (prop, sdata->new_value);
1111 
1112       sdata_list = g_list_prepend (sdata_list, sdata);
1113     }
1114 
1115   if (project)
1116     /* GladeCommand takes ownership of allocated list, ugly but practicle */
1117     glade_command_set_properties_list (project, sdata_list);
1118 
1119 }
1120 
1121 void
glade_editor_reset_dialog_run(GtkWidget * parent,GladeWidget * gwidget)1122 glade_editor_reset_dialog_run (GtkWidget *parent, GladeWidget *gwidget)
1123 {
1124   GtkTreeSelection *selection;
1125   GtkWidget *dialog;
1126   GtkWidget *vbox, *hbox, *label, *sw, *button;
1127   GtkWidget *tree_view, *description_view;
1128   gint res;
1129   GList *list;
1130 
1131   dialog = gtk_dialog_new_with_buttons (_("Reset Widget Properties"),
1132                                         parent ? GTK_WINDOW (parent) : NULL,
1133                                         GTK_DIALOG_MODAL |
1134                                         GTK_DIALOG_DESTROY_WITH_PARENT,
1135                                         _("_Cancel"), GTK_RESPONSE_CANCEL,
1136                                         _("_OK"), GTK_RESPONSE_OK, NULL);
1137 
1138   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
1139   gtk_widget_show (vbox);
1140 
1141   gtk_container_set_border_width (GTK_CONTAINER (vbox), 6);
1142 
1143   gtk_box_pack_start (GTK_BOX
1144                       (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), vbox,
1145                       TRUE, TRUE, 0);
1146 
1147   /* Checklist */
1148   label = gtk_label_new_with_mnemonic (_("_Properties:"));
1149   gtk_widget_show (label);
1150   gtk_widget_set_halign (label, GTK_ALIGN_START);
1151   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
1152 
1153   sw = gtk_scrolled_window_new (NULL, NULL);
1154   gtk_widget_show (sw);
1155   gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
1156   gtk_widget_set_size_request (sw, 400, 200);
1157   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
1158                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1159   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
1160 
1161 
1162   tree_view = glade_editor_reset_view ();
1163   if (gwidget)
1164     glade_editor_populate_reset_view (gwidget, GTK_TREE_VIEW (tree_view));
1165   gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
1166 
1167   gtk_widget_show (tree_view);
1168   gtk_label_set_mnemonic_widget (GTK_LABEL (label), tree_view);
1169   gtk_container_add (GTK_CONTAINER (sw), tree_view);
1170 
1171   /* Select all / Unselect all */
1172   hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
1173   gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_END);
1174   gtk_widget_show (hbox);
1175   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
1176 
1177   button = gtk_button_new_with_mnemonic (_("_Select All"));
1178   gtk_widget_show (button);
1179   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
1180   gtk_container_set_border_width (GTK_CONTAINER (button), 6);
1181   g_signal_connect (G_OBJECT (button), "clicked",
1182                     G_CALLBACK (glade_editor_reset_select_all_clicked),
1183                     tree_view);
1184 
1185   button = gtk_button_new_with_mnemonic (_("_Unselect All"));
1186   gtk_widget_show (button);
1187   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
1188   gtk_container_set_border_width (GTK_CONTAINER (button), 6);
1189   g_signal_connect (G_OBJECT (button), "clicked",
1190                     G_CALLBACK (glade_editor_reset_unselect_all_clicked),
1191                     tree_view);
1192 
1193 
1194   /* Description */
1195   label = gtk_label_new_with_mnemonic (_("Property _Description:"));
1196   gtk_widget_show (label);
1197   gtk_widget_set_halign (label, GTK_ALIGN_START);
1198   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
1199 
1200   sw = gtk_scrolled_window_new (NULL, NULL);
1201   gtk_widget_show (sw);
1202   gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
1203   gtk_widget_set_size_request (sw, 400, 80);
1204   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
1205                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1206   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
1207 
1208   description_view = gtk_text_view_new ();
1209   gtk_text_view_set_editable (GTK_TEXT_VIEW (description_view), FALSE);
1210   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (description_view), GTK_WRAP_WORD);
1211 
1212   gtk_widget_show (description_view);
1213   gtk_label_set_mnemonic_widget (GTK_LABEL (label), description_view);
1214   gtk_container_add (GTK_CONTAINER (sw), description_view);
1215 
1216   /* Update description */
1217   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view));
1218   g_signal_connect (G_OBJECT (selection), "changed",
1219                     G_CALLBACK (glade_editor_reset_selection_changed_cb),
1220                     description_view);
1221 
1222 
1223 
1224   /* Run the dialog */
1225   res = gtk_dialog_run (GTK_DIALOG (dialog));
1226   if (res == GTK_RESPONSE_OK)
1227     {
1228 
1229       /* get all selected properties and reset properties through glade_command */
1230       if ((list = glade_editor_reset_get_selected_props
1231            (gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view)))) != NULL)
1232         {
1233           glade_editor_reset_properties (list);
1234           g_list_free (list);
1235         }
1236     }
1237   gtk_widget_destroy (dialog);
1238 }
1239 
1240 void
glade_editor_show_info(GladeEditor * editor)1241 glade_editor_show_info (GladeEditor *editor)
1242 {
1243   g_warning ("%s function is deprecated and does nothing", __func__);
1244 }
1245 
1246 void
glade_editor_hide_info(GladeEditor * editor)1247 glade_editor_hide_info (GladeEditor *editor)
1248 {
1249   g_warning ("%s function is deprecated and does nothing", __func__);
1250 }
1251 
1252 void
glade_editor_show_class_field(GladeEditor * editor)1253 glade_editor_show_class_field (GladeEditor *editor)
1254 {
1255   GladeEditorPrivate *priv;
1256 
1257   g_return_if_fail (GLADE_IS_EDITOR (editor));
1258 
1259   priv = GLADE_EDITOR_PRIVATE (editor);
1260 
1261   if (priv->show_class_field != TRUE)
1262     {
1263       priv->show_class_field = TRUE;
1264       gtk_widget_show (priv->class_field);
1265 
1266       g_object_notify_by_pspec (G_OBJECT (editor), properties[PROP_SHOW_CLASS_FIELD]);
1267     }
1268 }
1269 
1270 void
glade_editor_hide_class_field(GladeEditor * editor)1271 glade_editor_hide_class_field (GladeEditor *editor)
1272 {
1273   GladeEditorPrivate *priv;
1274 
1275   g_return_if_fail (GLADE_IS_EDITOR (editor));
1276 
1277   priv = GLADE_EDITOR_PRIVATE (editor);
1278 
1279   if (priv->show_class_field != FALSE)
1280     {
1281       priv->show_class_field = FALSE;
1282       gtk_widget_hide (priv->class_field);
1283 
1284       g_object_notify_by_pspec (G_OBJECT (editor), properties[PROP_SHOW_CLASS_FIELD]);
1285     }
1286 }
1287 
1288 static void
editor_widget_name_changed(GladeWidget * widget,GParamSpec * pspec,GtkWindow * window)1289 editor_widget_name_changed (GladeWidget *widget,
1290 			    GParamSpec  *pspec,
1291 			    GtkWindow   *window)
1292 {
1293   gchar *title, *prj_name;
1294 
1295   prj_name = glade_project_get_name (glade_widget_get_project (widget));
1296   /* Translators: first %s is the project name, second is a widget name */
1297   title = g_strdup_printf (_("%s - %s Properties"), prj_name,
1298                            glade_widget_get_display_name (widget));
1299   gtk_window_set_title (window, title);
1300   g_free (title);
1301   g_free (prj_name);
1302 }
1303 
1304 /**
1305  * glade_editor_dialog_for_widget:
1306  * @widget: a #GladeWidget
1307  *
1308  * This convenience function creates a new dialog window to edit @widget
1309  * specifically.
1310  *
1311  * Returns: the newly created dialog window
1312  */
1313 GtkWidget *
glade_editor_dialog_for_widget(GladeWidget * widget)1314 glade_editor_dialog_for_widget (GladeWidget *widget)
1315 {
1316   GtkWidget *window, *editor;
1317 
1318   g_return_val_if_fail (GLADE_IS_WIDGET (widget), NULL);
1319 
1320   /* Window */
1321   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1322   gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_UTILITY);
1323 
1324   /* Keep the title up to date */
1325   editor_widget_name_changed (widget, NULL, GTK_WINDOW (window));
1326   g_signal_connect_object (G_OBJECT (widget), "notify::name",
1327 			   G_CALLBACK (editor_widget_name_changed), window, 0);
1328 
1329   if (glade_app_get_accel_group ())
1330     {
1331       gtk_window_add_accel_group (GTK_WINDOW (window),
1332                                   glade_app_get_accel_group ());
1333       g_signal_connect (G_OBJECT (window), "key-press-event",
1334                         G_CALLBACK (glade_utils_hijack_key_press), NULL);
1335     }
1336 
1337   editor = (GtkWidget *)glade_editor_new ();
1338   glade_editor_load_widget (GLADE_EDITOR (editor), widget);
1339 
1340   g_signal_connect_swapped (G_OBJECT (editor), "notify::widget",
1341                             G_CALLBACK (gtk_widget_destroy), window);
1342 
1343   gtk_container_set_border_width (GTK_CONTAINER (editor), 6);
1344   gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (editor));
1345 
1346   gtk_window_set_default_size (GTK_WINDOW (window), 400, 480);
1347 
1348   gtk_widget_show (editor);
1349 
1350   return window;
1351 }
1352