1 /*
2 * Specialization of GtkCList for the XML tree view
3 *
4 * Authors:
5 * MenTaLguY <mental@rydia.net>
6 *
7 * Copyright (C) 2002 MenTaLguY
8 *
9 * Released under the GNU GPL; see COPYING for details
10 */
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
16 #include <cstring>
17 #include <glibmm/i18n.h>
19 #include "helper/sp-marshal.h"
20 #include "../xml/node-event-vector.h"
21 #include "sp-xmlview-attr-list.h"
23 static void sp_xmlview_attr_list_class_init (SPXMLViewAttrListClass * klass);
24 static void sp_xmlview_attr_list_init (SPXMLViewAttrList * list);
25 static void sp_xmlview_attr_list_destroy (GtkObject * object);
27 static void event_attr_changed (Inkscape::XML::Node * repr, const gchar * name, const gchar * old_value, const gchar * new_value, bool is_interactive, gpointer data);
29 static GtkCListClass * parent_class = NULL;
31 static Inkscape::XML::NodeEventVector repr_events = {
32 NULL, /* child_added */
33 NULL, /* child_removed */
34 event_attr_changed,
35 NULL, /* content_changed */
36 NULL /* order_changed */
37 };
39 GtkWidget *
40 sp_xmlview_attr_list_new (Inkscape::XML::Node * repr)
41 {
42 SPXMLViewAttrList * list;
44 list = (SPXMLViewAttrList*)g_object_new (SP_TYPE_XMLVIEW_ATTR_LIST, "n_columns", 2, NULL);
46 gtk_clist_set_column_title (GTK_CLIST (list), 0, _("Attribute"));
47 gtk_clist_set_column_title (GTK_CLIST (list), 1, _("Value"));
48 gtk_clist_column_titles_show (GTK_CLIST (list));
50 gtk_clist_column_titles_passive (GTK_CLIST (list));
51 gtk_clist_set_column_auto_resize (GTK_CLIST (list), 0, TRUE);
52 gtk_clist_set_column_auto_resize (GTK_CLIST (list), 1, TRUE);
53 gtk_clist_set_sort_column (GTK_CLIST (list), 0);
54 gtk_clist_set_auto_sort (GTK_CLIST (list), TRUE);
56 sp_xmlview_attr_list_set_repr (list, repr);
58 return (GtkWidget *) list;
59 }
61 void
62 sp_xmlview_attr_list_set_repr (SPXMLViewAttrList * list, Inkscape::XML::Node * repr)
63 {
64 if ( repr == list->repr ) return;
65 gtk_clist_freeze (GTK_CLIST (list));
66 if (list->repr) {
67 gtk_clist_clear (GTK_CLIST (list));
68 sp_repr_remove_listener_by_data (list->repr, list);
69 Inkscape::GC::release(list->repr);
70 }
71 list->repr = repr;
72 if (repr) {
73 Inkscape::GC::anchor(repr);
74 sp_repr_add_listener (repr, &repr_events, list);
75 sp_repr_synthesize_events (repr, &repr_events, list);
76 }
77 gtk_clist_thaw (GTK_CLIST (list));
78 }
80 GtkType
81 sp_xmlview_attr_list_get_type (void)
82 {
83 static GtkType type = 0;
85 if (!type) {
86 static const GtkTypeInfo info = {
87 "SPXMLViewAttrList",
88 sizeof (SPXMLViewAttrList),
89 sizeof (SPXMLViewAttrListClass),
90 (GtkClassInitFunc) sp_xmlview_attr_list_class_init,
91 (GtkObjectInitFunc) sp_xmlview_attr_list_init,
92 NULL, NULL, NULL
93 };
94 type = gtk_type_unique (GTK_TYPE_CLIST, &info);
95 }
97 return type;
98 }
100 void
101 sp_xmlview_attr_list_class_init (SPXMLViewAttrListClass * klass)
102 {
103 GtkObjectClass * object_class;
105 object_class = (GtkObjectClass *) klass;
106 object_class->destroy = sp_xmlview_attr_list_destroy;
108 parent_class = (GtkCListClass*)gtk_type_class (GTK_TYPE_CLIST);
110 g_signal_new ( "row-value-changed",
111 G_TYPE_FROM_CLASS(klass),
112 G_SIGNAL_RUN_FIRST,
113 G_STRUCT_OFFSET (SPXMLViewAttrListClass, row_changed),
114 NULL, NULL,
115 sp_marshal_NONE__UINT,
116 G_TYPE_NONE, 1,
117 G_TYPE_UINT);
118 }
120 void
121 sp_xmlview_attr_list_init (SPXMLViewAttrList * list)
122 {
123 list->repr = NULL;
124 }
126 void
127 sp_xmlview_attr_list_destroy (GtkObject * object)
128 {
129 SPXMLViewAttrList * list;
131 list = SP_XMLVIEW_ATTR_LIST (object);
133 sp_xmlview_attr_list_set_repr (list, NULL);
135 GTK_OBJECT_CLASS (parent_class)->destroy (object);
136 }
138 void
139 event_attr_changed (Inkscape::XML::Node * /*repr*/,
140 const gchar * name,
141 const gchar * /*old_value*/,
142 const gchar * new_value,
143 bool /*is_interactive*/,
144 gpointer data)
145 {
146 gint row;
147 SPXMLViewAttrList * list;
148 gchar new_text[128 + 4];
149 gchar *gtktext;
151 list = SP_XMLVIEW_ATTR_LIST (data);
153 gtk_clist_freeze (GTK_CLIST (list));
155 if (new_value) {
156 strncpy (new_text, new_value, 128);
157 if (strlen (new_value) >= 128) {
158 strcpy (new_text + 128, "...");
159 }
160 gtktext = new_text;
161 } else {
162 gtktext = NULL;
163 }
165 row = gtk_clist_find_row_from_data (GTK_CLIST (list), GINT_TO_POINTER (g_quark_from_string (name)));
166 if (row != -1) {
167 if (new_value) {
168 gtk_clist_set_text (GTK_CLIST (list), row, 1, gtktext);
169 } else {
170 gtk_clist_remove (GTK_CLIST (list), row);
171 }
172 } else if (new_value != NULL) {
173 const gchar * text[2];
175 text[0] = name;
176 text[1] = gtktext;
178 row = gtk_clist_append (GTK_CLIST (list), (gchar **)text);
179 gtk_clist_set_row_data (GTK_CLIST (list), row, GINT_TO_POINTER (g_quark_from_string (name)));
180 }
182 gtk_clist_thaw (GTK_CLIST (list));
184 // send a "changed" signal so widget owners will know I've updated
185 g_signal_emit_by_name(G_OBJECT (list), "row-value-changed", row );
186 }