1 #define __SP_WIDGET_C__
3 /*
4 * Abstract base class for dynamic control widgets
5 *
6 * Authors:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 * bulia byak <buliabyak@users.sf.net>
9 *
10 * Copyright (C) 1999-2002 Lauris Kaplinski
11 * Copyright (C) 2000-2001 Ximian, Inc.
12 *
13 * Released under GNU GPL, read the file 'COPYING' for more information
14 */
16 #include "macros.h"
17 #include "../document.h"
18 #include "sp-widget.h"
20 enum {
21 CONSTRUCT,
22 MODIFY_SELECTION,
23 CHANGE_SELECTION,
24 SET_SELECTION,
25 LAST_SIGNAL
26 };
28 static void sp_widget_class_init (SPWidgetClass *klass);
29 static void sp_widget_init (SPWidget *widget);
31 static void sp_widget_destroy (GtkObject *object);
33 static void sp_widget_show (GtkWidget *widget);
34 static void sp_widget_hide (GtkWidget *widget);
35 static gint sp_widget_expose (GtkWidget *widget, GdkEventExpose *event);
36 static void sp_widget_size_request (GtkWidget *widget, GtkRequisition *requisition);
37 static void sp_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
39 static void sp_widget_modify_selection (Inkscape::Application *inkscape, Inkscape::Selection *selection, guint flags, SPWidget *spw);
40 static void sp_widget_change_selection (Inkscape::Application *inkscape, Inkscape::Selection *selection, SPWidget *spw);
41 static void sp_widget_set_selection (Inkscape::Application *inkscape, Inkscape::Selection *selection, SPWidget *spw);
43 static GtkBinClass *parent_class;
44 static guint signals[LAST_SIGNAL] = {0};
46 GtkType
47 sp_widget_get_type (void)
48 {
49 static GtkType type = 0;
50 if (!type) {
51 static const GtkTypeInfo info = {
52 "SPWidget",
53 sizeof (SPWidget),
54 sizeof (SPWidgetClass),
55 (GtkClassInitFunc) sp_widget_class_init,
56 (GtkObjectInitFunc) sp_widget_init,
57 NULL, NULL, NULL
58 };
59 type = gtk_type_unique (GTK_TYPE_BIN, &info);
60 }
61 return type;
62 }
64 static void
65 sp_widget_class_init (SPWidgetClass *klass)
66 {
67 GtkObjectClass *object_class;
68 GtkWidgetClass *widget_class;
70 object_class = (GtkObjectClass *) klass;
71 widget_class = (GtkWidgetClass *) klass;
73 parent_class = (GtkBinClass*)gtk_type_class (GTK_TYPE_BIN);
75 object_class->destroy = sp_widget_destroy;
77 signals[CONSTRUCT] = gtk_signal_new ("construct",
78 GTK_RUN_FIRST,
79 GTK_CLASS_TYPE(object_class),
80 GTK_SIGNAL_OFFSET (SPWidgetClass, construct),
81 gtk_marshal_NONE__NONE,
82 GTK_TYPE_NONE, 0);
83 signals[CHANGE_SELECTION] = gtk_signal_new ("change_selection",
84 GTK_RUN_FIRST,
85 GTK_CLASS_TYPE(object_class),
86 GTK_SIGNAL_OFFSET (SPWidgetClass, change_selection),
87 gtk_marshal_NONE__POINTER,
88 GTK_TYPE_NONE, 1,
89 GTK_TYPE_POINTER);
90 signals[MODIFY_SELECTION] = gtk_signal_new ("modify_selection",
91 GTK_RUN_FIRST,
92 GTK_CLASS_TYPE(object_class),
93 GTK_SIGNAL_OFFSET (SPWidgetClass, modify_selection),
94 gtk_marshal_NONE__POINTER_UINT,
95 GTK_TYPE_NONE, 2,
96 GTK_TYPE_POINTER, GTK_TYPE_UINT);
97 signals[SET_SELECTION] = gtk_signal_new ("set_selection",
98 GTK_RUN_FIRST,
99 GTK_CLASS_TYPE(object_class),
100 GTK_SIGNAL_OFFSET (SPWidgetClass, set_selection),
101 gtk_marshal_NONE__POINTER,
102 GTK_TYPE_NONE, 1,
103 GTK_TYPE_POINTER);
105 widget_class->show = sp_widget_show;
106 widget_class->hide = sp_widget_hide;
107 widget_class->expose_event = sp_widget_expose;
108 widget_class->size_request = sp_widget_size_request;
109 widget_class->size_allocate = sp_widget_size_allocate;
110 }
112 static void
113 sp_widget_init (SPWidget *spw)
114 {
115 spw->inkscape = NULL;
116 }
118 static void
119 sp_widget_destroy (GtkObject *object)
120 {
121 SPWidget *spw;
123 spw = (SPWidget *) object;
125 if (spw->inkscape) {
126 /* Disconnect signals */
127 // the checks are necessary because when destroy is caused by the the program shutting down,
128 // the inkscape object may already be (partly?) invalid --bb
129 if (G_IS_OBJECT(spw->inkscape) && G_OBJECT_GET_CLASS(G_OBJECT(spw->inkscape)))
130 sp_signal_disconnect_by_data (spw->inkscape, spw);
131 spw->inkscape = NULL;
132 }
134 if (((GtkObjectClass *) parent_class)->destroy)
135 (* ((GtkObjectClass *) parent_class)->destroy) (object);
136 }
138 static void
139 sp_widget_show (GtkWidget *widget)
140 {
141 SPWidget *spw;
143 spw = SP_WIDGET (widget);
145 if (spw->inkscape) {
146 /* Connect signals */
147 g_signal_connect (G_OBJECT (spw->inkscape), "modify_selection", G_CALLBACK (sp_widget_modify_selection), spw);
148 g_signal_connect (G_OBJECT (spw->inkscape), "change_selection", G_CALLBACK (sp_widget_change_selection), spw);
149 g_signal_connect (G_OBJECT (spw->inkscape), "set_selection", G_CALLBACK (sp_widget_set_selection), spw);
150 }
152 if (((GtkWidgetClass *) parent_class)->show)
153 (* ((GtkWidgetClass *) parent_class)->show) (widget);
154 }
156 static void
157 sp_widget_hide (GtkWidget *widget)
158 {
159 SPWidget *spw;
161 spw = SP_WIDGET (widget);
163 if (spw->inkscape) {
164 /* Disconnect signals */
165 sp_signal_disconnect_by_data (spw->inkscape, spw);
166 }
168 if (((GtkWidgetClass *) parent_class)->hide)
169 (* ((GtkWidgetClass *) parent_class)->hide) (widget);
170 }
172 static gint
173 sp_widget_expose (GtkWidget *widget, GdkEventExpose *event)
174 {
175 GtkBin *bin;
177 bin = GTK_BIN (widget);
179 if ( bin->child ) {
180 gtk_container_propagate_expose (GTK_CONTAINER(widget), bin->child, event);
181 }
182 /*
183 if ((bin->child) && (GTK_WIDGET_NO_WINDOW (bin->child))) {
184 GdkEventExpose ce;
185 ce = *event;
186 gtk_widget_event (bin->child, (GdkEvent *) &ce);
187 }
188 */
190 return FALSE;
191 }
193 static void
194 sp_widget_size_request (GtkWidget *widget, GtkRequisition *requisition)
195 {
196 if (((GtkBin *) widget)->child)
197 gtk_widget_size_request (((GtkBin *) widget)->child, requisition);
198 }
200 static void
201 sp_widget_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
202 {
203 widget->allocation = *allocation;
205 if (((GtkBin *) widget)->child)
206 gtk_widget_size_allocate (((GtkBin *) widget)->child, allocation);
207 }
209 /* Methods */
211 GtkWidget *
212 sp_widget_new_global (Inkscape::Application *inkscape)
213 {
214 SPWidget *spw;
216 spw = (SPWidget*)gtk_type_new (SP_TYPE_WIDGET);
218 if (!sp_widget_construct_global (spw, inkscape)) {
219 gtk_object_unref (GTK_OBJECT (spw));
220 return NULL;
221 }
223 return (GtkWidget *) spw;
224 }
226 GtkWidget *
227 sp_widget_construct_global (SPWidget *spw, Inkscape::Application *inkscape)
228 {
229 g_return_val_if_fail (!spw->inkscape, NULL);
231 spw->inkscape = inkscape;
232 if (GTK_WIDGET_VISIBLE (spw)) {
233 g_signal_connect (G_OBJECT (inkscape), "modify_selection", G_CALLBACK (sp_widget_modify_selection), spw);
234 g_signal_connect (G_OBJECT (inkscape), "change_selection", G_CALLBACK (sp_widget_change_selection), spw);
235 g_signal_connect (G_OBJECT (inkscape), "set_selection", G_CALLBACK (sp_widget_set_selection), spw);
236 }
238 g_signal_emit (G_OBJECT (spw), signals[CONSTRUCT], 0);
240 return (GtkWidget *) spw;
241 }
243 static void
244 sp_widget_modify_selection (Inkscape::Application *inkscape, Inkscape::Selection *selection, guint flags, SPWidget *spw)
245 {
246 g_signal_emit (G_OBJECT (spw), signals[MODIFY_SELECTION], 0, selection, flags);
247 }
249 static void
250 sp_widget_change_selection (Inkscape::Application *inkscape, Inkscape::Selection *selection, SPWidget *spw)
251 {
252 g_signal_emit (G_OBJECT (spw), signals[CHANGE_SELECTION], 0, selection);
253 }
255 static void
256 sp_widget_set_selection (Inkscape::Application *inkscape, Inkscape::Selection *selection, SPWidget *spw)
257 {
258 /* Emit "set_selection" signal */
259 g_signal_emit (G_OBJECT (spw), signals[SET_SELECTION], 0, selection);
260 /* Inkscape will force "change_selection" anyways */
261 }