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