2 * Copyright (C) 2000 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library 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 GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
23 #undef GTK_DISABLE_DEPRECATED
26 #include "prop-editor.h"
32 GObject *alive_object;
37 disconnect_func (gpointer data)
39 DisconnectData *dd = data;
41 g_signal_handler_disconnect (dd->instance, dd->id);
45 signal_removed (gpointer data,
48 DisconnectData *dd = data;
50 g_object_steal_data (dd->alive_object, "alive-object-data");
55 is_child_property (GParamSpec *pspec)
57 return g_param_spec_get_qdata (pspec, g_quark_from_string ("is-child-prop")) != NULL;
61 mark_child_property (GParamSpec *pspec)
63 g_param_spec_set_qdata (pspec, g_quark_from_string ("is-child-prop"),
64 GINT_TO_POINTER (TRUE));
68 g_object_connect_property (GObject *object,
72 GObject *alive_object)
78 if (is_child_property (spec))
79 with_detail = g_strconcat ("child-notify::", spec->name, NULL);
81 with_detail = g_strconcat ("notify::", spec->name, NULL);
83 dd = g_new (DisconnectData, 1);
85 closure = g_cclosure_new (func, data, NULL);
87 g_closure_add_invalidate_notifier (closure, dd, signal_removed);
89 dd->id = g_signal_connect_closure (object, with_detail,
92 dd->instance = object;
93 dd->alive_object = alive_object;
95 g_object_set_data_full (G_OBJECT (alive_object),
100 g_free (with_detail);
111 free_object_property (ObjectProperty *p)
117 connect_controller (GObject *controller,
125 p = g_new (ObjectProperty, 1);
129 p->modified_id = g_signal_connect_data (controller, signal, func, p,
130 (GClosureNotify)free_object_property,
132 g_object_set_data (controller, "object-property", p);
136 block_controller (GObject *controller)
138 ObjectProperty *p = g_object_get_data (controller, "object-property");
141 g_signal_handler_block (controller, p->modified_id);
145 unblock_controller (GObject *controller)
147 ObjectProperty *p = g_object_get_data (controller, "object-property");
150 g_signal_handler_unblock (controller, p->modified_id);
154 int_modified (GtkAdjustment *adj, gpointer data)
156 ObjectProperty *p = data;
158 if (is_child_property (p->spec))
160 GtkWidget *widget = GTK_WIDGET (p->obj);
161 GtkWidget *parent = gtk_widget_get_parent (widget);
163 gtk_container_child_set (GTK_CONTAINER (parent),
164 widget, p->spec->name, (int) adj->value, NULL);
167 g_object_set (p->obj, p->spec->name, (int) adj->value, NULL);
171 get_property_value (GObject *object, GParamSpec *pspec, GValue *value)
173 if (is_child_property (pspec))
175 GtkWidget *widget = GTK_WIDGET (object);
176 GtkWidget *parent = gtk_widget_get_parent (widget);
178 gtk_container_child_get_property (GTK_CONTAINER (parent),
179 widget, pspec->name, value);
182 g_object_get_property (object, pspec->name, value);
186 int_changed (GObject *object, GParamSpec *pspec, gpointer data)
188 GtkAdjustment *adj = GTK_ADJUSTMENT (data);
191 g_value_init (&val, G_TYPE_INT);
193 get_property_value (object, pspec, &val);
195 if (g_value_get_int (&val) != (int)adj->value)
197 block_controller (G_OBJECT (adj));
198 gtk_adjustment_set_value (adj, g_value_get_int (&val));
199 unblock_controller (G_OBJECT (adj));
202 g_value_unset (&val);
206 uint_modified (GtkAdjustment *adj, gpointer data)
208 ObjectProperty *p = data;
210 if (is_child_property (p->spec))
212 GtkWidget *widget = GTK_WIDGET (p->obj);
213 GtkWidget *parent = gtk_widget_get_parent (widget);
215 gtk_container_child_set (GTK_CONTAINER (parent),
216 widget, p->spec->name, (guint) adj->value, NULL);
219 g_object_set (p->obj, p->spec->name, (guint) adj->value, NULL);
223 uint_changed (GObject *object, GParamSpec *pspec, gpointer data)
225 GtkAdjustment *adj = GTK_ADJUSTMENT (data);
228 g_value_init (&val, G_TYPE_UINT);
229 get_property_value (object, pspec, &val);
231 if (g_value_get_uint (&val) != (guint)adj->value)
233 block_controller (G_OBJECT (adj));
234 gtk_adjustment_set_value (adj, g_value_get_uint (&val));
235 unblock_controller (G_OBJECT (adj));
238 g_value_unset (&val);
242 float_modified (GtkAdjustment *adj, gpointer data)
244 ObjectProperty *p = data;
246 if (is_child_property (p->spec))
248 GtkWidget *widget = GTK_WIDGET (p->obj);
249 GtkWidget *parent = gtk_widget_get_parent (widget);
251 gtk_container_child_set (GTK_CONTAINER (parent),
252 widget, p->spec->name, (float) adj->value, NULL);
255 g_object_set (p->obj, p->spec->name, (float) adj->value, NULL);
259 float_changed (GObject *object, GParamSpec *pspec, gpointer data)
261 GtkAdjustment *adj = GTK_ADJUSTMENT (data);
264 g_value_init (&val, G_TYPE_FLOAT);
265 get_property_value (object, pspec, &val);
267 if (g_value_get_float (&val) != (float) adj->value)
269 block_controller (G_OBJECT (adj));
270 gtk_adjustment_set_value (adj, g_value_get_float (&val));
271 unblock_controller (G_OBJECT (adj));
274 g_value_unset (&val);
278 double_modified (GtkAdjustment *adj, gpointer data)
280 ObjectProperty *p = data;
282 if (is_child_property (p->spec))
284 GtkWidget *widget = GTK_WIDGET (p->obj);
285 GtkWidget *parent = gtk_widget_get_parent (widget);
287 gtk_container_child_set (GTK_CONTAINER (parent),
288 widget, p->spec->name, (double) adj->value, NULL);
291 g_object_set (p->obj, p->spec->name, (double) adj->value, NULL);
295 double_changed (GObject *object, GParamSpec *pspec, gpointer data)
297 GtkAdjustment *adj = GTK_ADJUSTMENT (data);
300 g_value_init (&val, G_TYPE_DOUBLE);
301 get_property_value (object, pspec, &val);
303 if (g_value_get_double (&val) != adj->value)
305 block_controller (G_OBJECT (adj));
306 gtk_adjustment_set_value (adj, g_value_get_double (&val));
307 unblock_controller (G_OBJECT (adj));
310 g_value_unset (&val);
314 string_modified (GtkEntry *entry, gpointer data)
316 ObjectProperty *p = data;
319 text = gtk_entry_get_text (entry);
321 if (is_child_property (p->spec))
323 GtkWidget *widget = GTK_WIDGET (p->obj);
324 GtkWidget *parent = gtk_widget_get_parent (widget);
326 gtk_container_child_set (GTK_CONTAINER (parent),
327 widget, p->spec->name, text, NULL);
330 g_object_set (p->obj, p->spec->name, text, NULL);
334 string_changed (GObject *object, GParamSpec *pspec, gpointer data)
336 GtkEntry *entry = GTK_ENTRY (data);
341 g_value_init (&val, G_TYPE_STRING);
342 get_property_value (object, pspec, &val);
344 str = g_value_get_string (&val);
347 text = gtk_entry_get_text (entry);
349 if (strcmp (str, text) != 0)
351 block_controller (G_OBJECT (entry));
352 gtk_entry_set_text (entry, str);
353 unblock_controller (G_OBJECT (entry));
356 g_value_unset (&val);
360 bool_modified (GtkToggleButton *tb, gpointer data)
362 ObjectProperty *p = data;
364 if (is_child_property (p->spec))
366 GtkWidget *widget = GTK_WIDGET (p->obj);
367 GtkWidget *parent = gtk_widget_get_parent (widget);
369 gtk_container_child_set (GTK_CONTAINER (parent),
370 widget, p->spec->name, (int) tb->active, NULL);
373 g_object_set (p->obj, p->spec->name, (int) tb->active, NULL);
377 bool_changed (GObject *object, GParamSpec *pspec, gpointer data)
379 GtkToggleButton *tb = GTK_TOGGLE_BUTTON (data);
382 g_value_init (&val, G_TYPE_BOOLEAN);
383 get_property_value (object, pspec, &val);
385 if (g_value_get_boolean (&val) != tb->active)
387 block_controller (G_OBJECT (tb));
388 gtk_toggle_button_set_active (tb, g_value_get_boolean (&val));
389 unblock_controller (G_OBJECT (tb));
392 gtk_label_set_text (GTK_LABEL (GTK_BIN (tb)->child), g_value_get_boolean (&val) ?
395 g_value_unset (&val);
400 enum_modified (GtkOptionMenu *om, gpointer data)
402 ObjectProperty *p = data;
406 eclass = G_ENUM_CLASS (g_type_class_peek (p->spec->value_type));
408 i = gtk_option_menu_get_history (om);
410 if (is_child_property (p->spec))
412 GtkWidget *widget = GTK_WIDGET (p->obj);
413 GtkWidget *parent = gtk_widget_get_parent (widget);
415 gtk_container_child_set (GTK_CONTAINER (parent),
416 widget, p->spec->name, eclass->values[i].value, NULL);
419 g_object_set (p->obj, p->spec->name, eclass->values[i].value, NULL);
423 enum_changed (GObject *object, GParamSpec *pspec, gpointer data)
425 GtkOptionMenu *om = GTK_OPTION_MENU (data);
430 eclass = G_ENUM_CLASS (g_type_class_peek (pspec->value_type));
432 g_value_init (&val, pspec->value_type);
433 get_property_value (object, pspec, &val);
436 while (i < eclass->n_values)
438 if (eclass->values[i].value == g_value_get_enum (&val))
443 if (gtk_option_menu_get_history (om) != i)
445 block_controller (G_OBJECT (om));
446 gtk_option_menu_set_history (om, i);
447 unblock_controller (G_OBJECT (om));
450 g_value_unset (&val);
455 unichar_get_value (GtkEntry *entry)
457 const gchar *text = gtk_entry_get_text (entry);
460 return g_utf8_get_char (text);
466 unichar_modified (GtkEntry *entry, gpointer data)
468 ObjectProperty *p = data;
469 gunichar val = unichar_get_value (entry);
471 if (is_child_property (p->spec))
473 GtkWidget *widget = GTK_WIDGET (p->obj);
474 GtkWidget *parent = gtk_widget_get_parent (widget);
476 gtk_container_child_set (GTK_CONTAINER (parent),
477 widget, p->spec->name, val, NULL);
480 g_object_set (p->obj, p->spec->name, val, NULL);
484 unichar_changed (GObject *object, GParamSpec *pspec, gpointer data)
486 GtkEntry *entry = GTK_ENTRY (data);
488 gunichar old_val = unichar_get_value (entry);
493 g_value_init (&val, pspec->value_type);
494 get_property_value (object, pspec, &val);
495 new_val = (gunichar)g_value_get_uint (&val);
497 if (new_val != old_val)
502 len = g_unichar_to_utf8 (new_val, buf);
506 block_controller (G_OBJECT (entry));
507 gtk_entry_set_text (entry, buf);
508 unblock_controller (G_OBJECT (entry));
513 pointer_changed (GObject *object, GParamSpec *pspec, gpointer data)
515 GtkLabel *label = GTK_LABEL (data);
519 g_object_get (object, pspec->name, &ptr, NULL);
521 str = g_strdup_printf ("Pointer: %p", ptr);
522 gtk_label_set_text (label, str);
527 object_changed (GObject *object, GParamSpec *pspec, gpointer data)
529 GtkWidget *label, *button;
534 GList *children = gtk_container_get_children (GTK_CONTAINER (data));
535 label = GTK_WIDGET (children->data);
536 button = GTK_WIDGET (children->next->data);
537 g_object_get (object, pspec->name, &obj, NULL);
538 g_list_free (children);
541 name = g_type_name (G_TYPE_FROM_INSTANCE (obj));
544 str = g_strdup_printf ("Object: %p (%s)", obj, name);
546 gtk_label_set_text (GTK_LABEL (label), str);
547 gtk_widget_set_sensitive (button, G_IS_OBJECT (obj));
550 g_object_unref (obj);
556 model_destroy (gpointer data)
558 g_object_steal_data (data, "model-object");
559 gtk_widget_destroy (data);
563 window_destroy (gpointer data)
565 g_object_steal_data (data, "prop-editor-win");
569 object_properties (GtkWidget *button,
575 name = (gchar *) g_object_get_data (G_OBJECT (button), "property-name");
576 g_object_get (object, name, &obj, NULL);
577 if (G_IS_OBJECT (obj))
578 create_prop_editor (obj, 0);
582 property_widget (GObject *object,
586 GtkWidget *prop_edit;
589 GType type = G_PARAM_SPEC_TYPE (spec);
591 if (type == G_TYPE_PARAM_INT)
593 adj = GTK_ADJUSTMENT (gtk_adjustment_new (G_PARAM_SPEC_INT (spec)->default_value,
594 G_PARAM_SPEC_INT (spec)->minimum,
595 G_PARAM_SPEC_INT (spec)->maximum,
597 MAX ((G_PARAM_SPEC_INT (spec)->maximum -
598 G_PARAM_SPEC_INT (spec)->minimum) / 10, 1),
601 prop_edit = gtk_spin_button_new (adj, 1.0, 0);
603 g_object_connect_property (object, spec,
604 G_CALLBACK (int_changed),
605 adj, G_OBJECT (adj));
608 connect_controller (G_OBJECT (adj), "value_changed",
609 object, spec, (GtkSignalFunc) int_modified);
611 else if (type == G_TYPE_PARAM_UINT)
613 adj = GTK_ADJUSTMENT (
614 gtk_adjustment_new (G_PARAM_SPEC_UINT (spec)->default_value,
615 G_PARAM_SPEC_UINT (spec)->minimum,
616 G_PARAM_SPEC_UINT (spec)->maximum,
618 MAX ((G_PARAM_SPEC_UINT (spec)->maximum -
619 G_PARAM_SPEC_UINT (spec)->minimum) / 10, 1),
622 prop_edit = gtk_spin_button_new (adj, 1.0, 0);
624 g_object_connect_property (object, spec,
625 G_CALLBACK (uint_changed),
626 adj, G_OBJECT (adj));
629 connect_controller (G_OBJECT (adj), "value_changed",
630 object, spec, (GtkSignalFunc) uint_modified);
632 else if (type == G_TYPE_PARAM_FLOAT)
635 adj = GTK_ADJUSTMENT (gtk_adjustment_new (G_PARAM_SPEC_FLOAT (spec)->default_value,
636 G_PARAM_SPEC_FLOAT (spec)->minimum,
637 G_PARAM_SPEC_FLOAT (spec)->maximum,
639 MAX ((G_PARAM_SPEC_FLOAT (spec)->maximum -
640 G_PARAM_SPEC_FLOAT (spec)->minimum) / 10, 0.1),
643 prop_edit = gtk_spin_button_new (adj, 0.1, 2);
645 g_object_connect_property (object, spec,
646 G_CALLBACK (float_changed),
647 adj, G_OBJECT (adj));
650 connect_controller (G_OBJECT (adj), "value_changed",
651 object, spec, (GtkSignalFunc) float_modified);
653 else if (type == G_TYPE_PARAM_DOUBLE)
655 adj = GTK_ADJUSTMENT (gtk_adjustment_new (G_PARAM_SPEC_DOUBLE (spec)->default_value,
656 G_PARAM_SPEC_DOUBLE (spec)->minimum,
657 G_PARAM_SPEC_DOUBLE (spec)->maximum,
659 MAX ((G_PARAM_SPEC_DOUBLE (spec)->maximum -
660 G_PARAM_SPEC_DOUBLE (spec)->minimum) / 10, 0.1),
663 prop_edit = gtk_spin_button_new (adj, 0.1, 2);
665 g_object_connect_property (object, spec,
666 G_CALLBACK (double_changed),
667 adj, G_OBJECT (adj));
670 connect_controller (G_OBJECT (adj), "value_changed",
671 object, spec, (GtkSignalFunc) double_modified);
673 else if (type == G_TYPE_PARAM_STRING)
675 prop_edit = gtk_entry_new ();
677 g_object_connect_property (object, spec,
678 G_CALLBACK (string_changed),
679 prop_edit, G_OBJECT (prop_edit));
682 connect_controller (G_OBJECT (prop_edit), "changed",
683 object, spec, (GtkSignalFunc) string_modified);
685 else if (type == G_TYPE_PARAM_BOOLEAN)
687 prop_edit = gtk_toggle_button_new_with_label ("");
689 g_object_connect_property (object, spec,
690 G_CALLBACK (bool_changed),
691 prop_edit, G_OBJECT (prop_edit));
694 connect_controller (G_OBJECT (prop_edit), "toggled",
695 object, spec, (GtkSignalFunc) bool_modified);
697 else if (type == G_TYPE_PARAM_ENUM)
704 prop_edit = gtk_option_menu_new ();
706 menu = gtk_menu_new ();
708 eclass = G_ENUM_CLASS (g_type_class_ref (spec->value_type));
711 while (j < eclass->n_values)
715 mi = gtk_menu_item_new_with_label (eclass->values[j].value_name);
717 gtk_widget_show (mi);
719 gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
724 g_type_class_unref (eclass);
726 gtk_option_menu_set_menu (GTK_OPTION_MENU (prop_edit), menu);
728 g_object_connect_property (object, spec,
729 G_CALLBACK (enum_changed),
730 prop_edit, G_OBJECT (prop_edit));
733 connect_controller (G_OBJECT (prop_edit), "changed",
734 object, spec, (GtkSignalFunc) enum_modified);
737 else if (type == G_TYPE_PARAM_UNICHAR)
739 prop_edit = gtk_entry_new ();
740 gtk_entry_set_max_length (GTK_ENTRY (prop_edit), 1);
742 g_object_connect_property (object, spec,
743 G_CALLBACK (unichar_changed),
744 prop_edit, G_OBJECT (prop_edit));
747 connect_controller (G_OBJECT (prop_edit), "changed",
748 object, spec, (GtkSignalFunc) unichar_modified);
750 else if (type == G_TYPE_PARAM_POINTER)
752 prop_edit = gtk_label_new ("");
754 g_object_connect_property (object, spec,
755 G_CALLBACK (pointer_changed),
756 prop_edit, G_OBJECT (prop_edit));
758 else if (type == G_TYPE_PARAM_OBJECT)
760 GtkWidget *label, *button;
762 prop_edit = gtk_hbox_new (FALSE, 5);
764 label = gtk_label_new ("");
765 button = gtk_button_new_with_label ("Properties");
766 g_object_set_data (G_OBJECT (button), "property-name", spec->name);
767 g_signal_connect (button, "clicked",
768 G_CALLBACK (object_properties),
771 gtk_container_add (GTK_CONTAINER (prop_edit), label);
772 gtk_container_add (GTK_CONTAINER (prop_edit), button);
774 g_object_connect_property (object, spec,
775 G_CALLBACK (object_changed),
776 prop_edit, G_OBJECT (label));
780 msg = g_strdup_printf ("uneditable property type: %s",
781 g_type_name (G_PARAM_SPEC_TYPE (spec)));
782 prop_edit = gtk_label_new (msg);
784 gtk_misc_set_alignment (GTK_MISC (prop_edit), 0.0, 0.5);
791 properties_from_type (GObject *object,
795 GtkWidget *prop_edit;
804 if (G_TYPE_IS_INTERFACE (type))
806 gpointer vtable = g_type_default_interface_peek (type);
807 specs = g_object_interface_list_properties (vtable, &n_specs);
811 GObjectClass *class = G_OBJECT_CLASS (g_type_class_peek (type));
812 specs = g_object_class_list_properties (class, &n_specs);
818 table = gtk_table_new (n_specs, 2, FALSE);
819 gtk_table_set_col_spacing (GTK_TABLE (table), 0, 10);
820 gtk_table_set_row_spacings (GTK_TABLE (table), 3);
825 GParamSpec *spec = specs[i];
830 can_modify = ((spec->flags & G_PARAM_WRITABLE) != 0 &&
831 (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
833 if ((spec->flags & G_PARAM_READABLE) == 0)
835 /* can't display unreadable properties */
840 if (spec->owner_type != type)
842 /* we're only interested in params of type */
847 label = gtk_label_new (g_param_spec_get_nick (spec));
848 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
849 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, i, i + 1);
851 prop_edit = property_widget (object, spec, can_modify);
852 gtk_table_attach_defaults (GTK_TABLE (table), prop_edit, 1, 2, i, i + 1);
857 gtk_widget_set_sensitive (prop_edit, FALSE);
859 if (g_param_spec_get_blurb (spec))
860 gtk_tooltips_set_tip (tips, prop_edit, g_param_spec_get_blurb (spec), NULL);
862 /* set initial value */
863 g_object_notify (object, spec->name);
870 vbox = gtk_vbox_new (FALSE, 0);
871 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
873 sw = gtk_scrolled_window_new (NULL, NULL);
874 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
875 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
877 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), vbox);
885 child_properties_from_object (GObject *object,
888 GtkWidget *prop_edit;
898 if (!GTK_IS_WIDGET (object))
901 parent = gtk_widget_get_parent (GTK_WIDGET (object));
906 specs = gtk_container_class_list_child_properties (G_OBJECT_GET_CLASS (parent), &n_specs);
908 table = gtk_table_new (n_specs, 2, FALSE);
909 gtk_table_set_col_spacing (GTK_TABLE (table), 0, 10);
910 gtk_table_set_row_spacings (GTK_TABLE (table), 3);
915 GParamSpec *spec = specs[i];
920 can_modify = ((spec->flags & G_PARAM_WRITABLE) != 0 &&
921 (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
923 if ((spec->flags & G_PARAM_READABLE) == 0)
925 /* can't display unreadable properties */
930 label = gtk_label_new (g_param_spec_get_nick (spec));
931 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
932 gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 1, i, i + 1);
934 mark_child_property (spec);
935 prop_edit = property_widget (object, spec, can_modify);
936 gtk_table_attach_defaults (GTK_TABLE (table), prop_edit, 1, 2, i, i + 1);
941 gtk_widget_set_sensitive (prop_edit, FALSE);
943 if (g_param_spec_get_blurb (spec))
944 gtk_tooltips_set_tip (tips, prop_edit, g_param_spec_get_blurb (spec), NULL);
946 /* set initial value */
947 gtk_widget_child_notify (GTK_WIDGET (object), spec->name);
953 vbox = gtk_vbox_new (FALSE, 0);
954 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
956 sw = gtk_scrolled_window_new (NULL, NULL);
957 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
958 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
960 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), vbox);
968 kill_tips (GtkWindow *win, GtkObject *tips)
970 gtk_object_destroy (tips);
971 g_object_unref (tips);
974 /* Pass zero for type if you want all properties */
976 create_prop_editor (GObject *object,
982 GtkWidget *properties;
988 if ((win = g_object_get_data (G_OBJECT (object), "prop-editor-win")))
990 gtk_window_present (GTK_WINDOW (win));
994 win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
995 if (GTK_IS_WIDGET (object))
996 gtk_window_set_screen (GTK_WINDOW (win),
997 gtk_widget_get_screen (GTK_WIDGET (object)));
999 tips = gtk_tooltips_new ();
1000 g_object_ref (tips);
1001 gtk_object_sink (GTK_OBJECT (tips));
1003 /* Kill the tips when the widget goes away. */
1004 g_signal_connect (win, "destroy", G_CALLBACK (kill_tips), tips);
1006 /* hold a weak ref to the object we're editing */
1007 g_object_set_data_full (G_OBJECT (object), "prop-editor-win", win, model_destroy);
1008 g_object_set_data_full (G_OBJECT (win), "model-object", object, window_destroy);
1012 notebook = gtk_notebook_new ();
1013 gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_LEFT);
1015 gtk_container_add (GTK_CONTAINER (win), notebook);
1017 type = G_TYPE_FROM_INSTANCE (object);
1019 title = g_strdup_printf ("Properties of %s widget", g_type_name (type));
1020 gtk_window_set_title (GTK_WINDOW (win), title);
1025 properties = properties_from_type (object, type, tips);
1028 label = gtk_label_new (g_type_name (type));
1029 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1033 type = g_type_parent (type);
1036 ifaces = g_type_interfaces (G_TYPE_FROM_INSTANCE (object), &n_ifaces);
1039 properties = properties_from_type (object, ifaces[n_ifaces], tips);
1042 label = gtk_label_new (g_type_name (ifaces[n_ifaces]));
1043 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1050 properties = child_properties_from_object (object, tips);
1053 label = gtk_label_new ("Child properties");
1054 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
1060 properties = properties_from_type (object, type, tips);
1061 gtk_container_add (GTK_CONTAINER (win), properties);
1062 title = g_strdup_printf ("Properties of %s", g_type_name (type));
1063 gtk_window_set_title (GTK_WINDOW (win), title);
1067 gtk_window_set_default_size (GTK_WINDOW (win), -1, 400);
1069 gtk_widget_show_all (win);