1 #define __SP_XMLVIEW_ATTR_LIST_C__
3 /*
4 * Specialization of GtkCList for the XML tree view
5 *
6 * Authors:
7 * MenTaLguY <mental@rydia.net>
8 *
9 * Copyright (C) 2002 MenTaLguY
10 *
11 * Released under the GNU GPL; see COPYING for details
12 */
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
17 #include "helper/sp-marshal.h"
18 #include <glibmm/i18n.h>
19 #include "../xml/node-event-vector.h"
20 #include "sp-xmlview-attr-list.h"
22 static void sp_xmlview_attr_list_class_init (SPXMLViewAttrListClass * klass);
23 static void sp_xmlview_attr_list_init (SPXMLViewAttrList * list);
24 static void sp_xmlview_attr_list_destroy (GtkObject * object);
26 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);
28 static GtkCListClass * parent_class = NULL;
30 static Inkscape::XML::NodeEventVector repr_events = {
31 NULL, /* child_added */
32 NULL, /* child_removed */
33 event_attr_changed,
34 NULL, /* content_changed */
35 NULL /* order_changed */
36 };
38 GtkWidget *
39 sp_xmlview_attr_list_new (Inkscape::XML::Node * repr)
40 {
41 SPXMLViewAttrList * list;
43 list = (SPXMLViewAttrList*)g_object_new (SP_TYPE_XMLVIEW_ATTR_LIST, "n_columns", 2, NULL);
45 gtk_clist_set_column_title (GTK_CLIST (list), 0, _("Attribute"));
46 gtk_clist_set_column_title (GTK_CLIST (list), 1, _("Value"));
47 gtk_clist_column_titles_show (GTK_CLIST (list));
49 gtk_clist_column_titles_passive (GTK_CLIST (list));
50 gtk_clist_set_column_auto_resize (GTK_CLIST (list), 0, TRUE);
51 gtk_clist_set_column_auto_resize (GTK_CLIST (list), 1, TRUE);
52 gtk_clist_set_sort_column (GTK_CLIST (list), 0);
53 gtk_clist_set_auto_sort (GTK_CLIST (list), TRUE);
55 sp_xmlview_attr_list_set_repr (list, repr);
57 return (GtkWidget *) list;
58 }
60 void
61 sp_xmlview_attr_list_set_repr (SPXMLViewAttrList * list, Inkscape::XML::Node * repr)
62 {
63 if ( repr == list->repr ) return;
64 gtk_clist_freeze (GTK_CLIST (list));
65 if (list->repr) {
66 gtk_clist_clear (GTK_CLIST (list));
67 sp_repr_remove_listener_by_data (list->repr, list);
68 Inkscape::GC::release(list->repr);
69 }
70 list->repr = repr;
71 if (repr) {
72 Inkscape::GC::anchor(repr);
73 sp_repr_add_listener (repr, &repr_events, list);
74 sp_repr_synthesize_events (repr, &repr_events, list);
75 }
76 gtk_clist_thaw (GTK_CLIST (list));
77 }
79 GtkType
80 sp_xmlview_attr_list_get_type (void)
81 {
82 static GtkType type = 0;
84 if (!type) {
85 static const GtkTypeInfo info = {
86 "SPXMLViewAttrList",
87 sizeof (SPXMLViewAttrList),
88 sizeof (SPXMLViewAttrListClass),
89 (GtkClassInitFunc) sp_xmlview_attr_list_class_init,
90 (GtkObjectInitFunc) sp_xmlview_attr_list_init,
91 NULL, NULL, NULL
92 };
93 type = gtk_type_unique (GTK_TYPE_CLIST, &info);
94 }
96 return type;
97 }
99 void
100 sp_xmlview_attr_list_class_init (SPXMLViewAttrListClass * klass)
101 {
102 GtkObjectClass * object_class;
104 object_class = (GtkObjectClass *) klass;
105 object_class->destroy = sp_xmlview_attr_list_destroy;
107 parent_class = (GtkCListClass*)gtk_type_class (GTK_TYPE_CLIST);
109 g_signal_new ( "row-value-changed",
110 G_TYPE_FROM_CLASS(klass),
111 G_SIGNAL_RUN_FIRST,
112 G_STRUCT_OFFSET (SPXMLViewAttrListClass, row_changed),
113 NULL, NULL,
114 sp_marshal_NONE__UINT,
115 G_TYPE_NONE, 1,
116 G_TYPE_UINT);
117 }
119 void
120 sp_xmlview_attr_list_init (SPXMLViewAttrList * list)
121 {
122 list->repr = NULL;
123 }
125 void
126 sp_xmlview_attr_list_destroy (GtkObject * object)
127 {
128 SPXMLViewAttrList * list;
130 list = SP_XMLVIEW_ATTR_LIST (object);
132 sp_xmlview_attr_list_set_repr (list, NULL);
134 GTK_OBJECT_CLASS (parent_class)->destroy (object);
135 }
137 void
138 event_attr_changed (Inkscape::XML::Node * repr, const gchar * name, const gchar * old_value, const gchar * new_value, bool is_interactive, gpointer data)
139 {
140 gint row;
141 SPXMLViewAttrList * list;
142 gchar new_text[128 + 4];
143 gchar *gtktext;
145 list = SP_XMLVIEW_ATTR_LIST (data);
147 gtk_clist_freeze (GTK_CLIST (list));
149 if (new_value) {
150 strncpy (new_text, new_value, 128);
151 if (strlen (new_value) >= 128) {
152 strcpy (new_text + 128, "...");
153 }
154 gtktext = new_text;
155 } else {
156 gtktext = NULL;
157 }
159 row = gtk_clist_find_row_from_data (GTK_CLIST (list), GINT_TO_POINTER (g_quark_from_string (name)));
160 if (row != -1) {
161 if (new_value) {
162 gtk_clist_set_text (GTK_CLIST (list), row, 1, gtktext);
163 } else {
164 gtk_clist_remove (GTK_CLIST (list), row);
165 }
166 } else if (new_value != NULL) {
167 const gchar * text[2];
169 text[0] = name;
170 text[1] = gtktext;
172 row = gtk_clist_append (GTK_CLIST (list), (gchar **)text);
173 gtk_clist_set_row_data (GTK_CLIST (list), row, GINT_TO_POINTER (g_quark_from_string (name)));
174 }
176 gtk_clist_thaw (GTK_CLIST (list));
178 // send a "changed" signal so widget owners will know I've updated
179 g_signal_emit_by_name(G_OBJECT (list), "row-value-changed", row );
180 }