comparison console/libgnt/gntwidget.c @ 13850:0e1e59770cb0

[gaim-migrate @ 16308] This is my first commit here. So don't yell at me if things get borked. Also, I haven't looked at the auto-thingies yet. So don't puke at the Makefiles. Files in console/libgnt/ are for the 'Gaim/GObjectified Ncurses Toolkit' library. Files in console/ uses libgaim and libgnt. Currently, only the buddylist-ui is 'functional', ie. the buddy-list updates when someone logs on or logs off. It still needs a lot of work. committer: Tailor Script <tailor@pidgin.im>
author Sadrul Habib Chowdhury <imadil@gmail.com>
date Thu, 22 Jun 2006 08:33:54 +0000
parents
children 5b288502a382
comparison
equal deleted inserted replaced
13849:8d1c55309e3c 13850:0e1e59770cb0
1 /* Stuff brutally ripped from Gflib */
2
3 #include "gntwidget.h"
4 #include "gntutils.h"
5 #include "gnt.h"
6
7 enum
8 {
9 SIG_DESTROY,
10 SIG_DRAW,
11 SIG_GIVE_FOCUS,
12 SIG_LOST_FOCUS,
13 SIG_KEY_PRESSED,
14 SIG_MAP,
15 SIG_ACTIVATE,
16 SIG_EXPOSE,
17 SIG_SIZE_REQUEST,
18 SIG_POSITION,
19 SIGS
20 };
21
22 static GObjectClass *parent_class = NULL;
23 static guint signals[SIGS] = { 0 };
24
25 static void
26 gnt_widget_init(GTypeInstance *instance, gpointer class)
27 {
28 GntWidget *widget = GNT_WIDGET(instance);
29 widget->priv.name = NULL;
30 DEBUG;
31 }
32
33 static void
34 gnt_widget_map(GntWidget *widget)
35 {
36 /* Get some default size for the widget */
37 DEBUG;
38 g_signal_emit(widget, signals[SIG_MAP], 0);
39 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_MAPPED);
40 }
41
42 static void
43 gnt_widget_dispose(GObject *obj)
44 {
45 GntWidget *self = GNT_WIDGET(obj);
46
47 if(!(GNT_WIDGET_FLAGS(self) & GNT_WIDGET_DESTROYING)) {
48 GNT_WIDGET_SET_FLAGS(self, GNT_WIDGET_DESTROYING);
49
50 g_signal_emit(self, signals[SIG_DESTROY], 0);
51
52 GNT_WIDGET_UNSET_FLAGS(self, GNT_WIDGET_DESTROYING);
53 }
54
55 parent_class->dispose(obj);
56 DEBUG;
57 }
58
59 static void
60 gnt_widget_focus_change(GntWidget *widget)
61 {
62 if (GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_MAPPED)
63 gnt_widget_draw(widget);
64 }
65
66 static void
67 gnt_widget_class_init(GntWidgetClass *klass)
68 {
69 GObjectClass *obj_class = G_OBJECT_CLASS(klass);
70
71 parent_class = g_type_class_peek_parent(klass);
72
73 obj_class->dispose = gnt_widget_dispose;
74
75 klass->destroy = gnt_widget_destroy;
76 klass->show = gnt_widget_show;
77 klass->draw = gnt_widget_draw;
78 klass->expose = gnt_widget_expose;
79 klass->map = gnt_widget_map;
80 klass->lost_focus = gnt_widget_focus_change;
81 klass->gained_focus = gnt_widget_focus_change;
82
83 klass->key_pressed = NULL;
84 klass->activate = NULL;
85
86 signals[SIG_DESTROY] =
87 g_signal_new("destroy",
88 G_TYPE_FROM_CLASS(klass),
89 G_SIGNAL_RUN_LAST,
90 G_STRUCT_OFFSET(GntWidgetClass, destroy),
91 NULL, NULL,
92 g_cclosure_marshal_VOID__VOID,
93 G_TYPE_NONE, 0);
94 signals[SIG_GIVE_FOCUS] =
95 g_signal_new("gained-focus",
96 G_TYPE_FROM_CLASS(klass),
97 G_SIGNAL_RUN_LAST,
98 G_STRUCT_OFFSET(GntWidgetClass, gained_focus),
99 NULL, NULL,
100 g_cclosure_marshal_VOID__VOID,
101 G_TYPE_NONE, 0);
102 signals[SIG_LOST_FOCUS] =
103 g_signal_new("lost-focus",
104 G_TYPE_FROM_CLASS(klass),
105 G_SIGNAL_RUN_LAST,
106 G_STRUCT_OFFSET(GntWidgetClass, lost_focus),
107 NULL, NULL,
108 g_cclosure_marshal_VOID__VOID,
109 G_TYPE_NONE, 0);
110 signals[SIG_ACTIVATE] =
111 g_signal_new("activate",
112 G_TYPE_FROM_CLASS(klass),
113 G_SIGNAL_RUN_LAST,
114 G_STRUCT_OFFSET(GntWidgetClass, activate),
115 NULL, NULL,
116 g_cclosure_marshal_VOID__VOID,
117 G_TYPE_NONE, 0);
118 signals[SIG_MAP] =
119 g_signal_new("map",
120 G_TYPE_FROM_CLASS(klass),
121 G_SIGNAL_RUN_LAST,
122 G_STRUCT_OFFSET(GntWidgetClass, map),
123 NULL, NULL,
124 g_cclosure_marshal_VOID__VOID,
125 G_TYPE_NONE, 0);
126 signals[SIG_DRAW] =
127 g_signal_new("draw",
128 G_TYPE_FROM_CLASS(klass),
129 G_SIGNAL_RUN_LAST,
130 G_STRUCT_OFFSET(GntWidgetClass, draw),
131 NULL, NULL,
132 g_cclosure_marshal_VOID__VOID,
133 G_TYPE_NONE, 0);
134 signals[SIG_EXPOSE] =
135 g_signal_new("expose",
136 G_TYPE_FROM_CLASS(klass),
137 G_SIGNAL_RUN_LAST,
138 G_STRUCT_OFFSET(GntWidgetClass, expose),
139 NULL, NULL,
140 gnt_closure_marshal_VOID__INT_INT_INT_INT,
141 G_TYPE_NONE, 4, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
142 signals[SIG_POSITION] =
143 g_signal_new("position-set",
144 G_TYPE_FROM_CLASS(klass),
145 G_SIGNAL_RUN_LAST,
146 G_STRUCT_OFFSET(GntWidgetClass, set_position),
147 NULL, NULL,
148 gnt_closure_marshal_VOID__INT_INT,
149 G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_INT);
150 signals[SIG_SIZE_REQUEST] =
151 g_signal_new("size_request",
152 G_TYPE_FROM_CLASS(klass),
153 G_SIGNAL_RUN_LAST,
154 G_STRUCT_OFFSET(GntWidgetClass, size_request),
155 NULL, NULL,
156 g_cclosure_marshal_VOID__VOID,
157 G_TYPE_NONE, 0);
158 signals[SIG_KEY_PRESSED] =
159 g_signal_new("key_pressed",
160 G_TYPE_FROM_CLASS(klass),
161 G_SIGNAL_RUN_LAST,
162 G_STRUCT_OFFSET(GntWidgetClass, key_pressed),
163 NULL, NULL,
164 gnt_closure_marshal_BOOLEAN__STRING,
165 G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
166 DEBUG;
167 }
168
169 /******************************************************************************
170 * GntWidget API
171 *****************************************************************************/
172 GType
173 gnt_widget_get_gtype(void)
174 {
175 static GType type = 0;
176
177 if(type == 0) {
178 static const GTypeInfo info = {
179 sizeof(GntWidgetClass),
180 NULL, /* base_init */
181 NULL, /* base_finalize */
182 (GClassInitFunc)gnt_widget_class_init,
183 NULL, /* class_finalize */
184 NULL, /* class_data */
185 sizeof(GntWidget),
186 0, /* n_preallocs */
187 gnt_widget_init, /* instance_init */
188 };
189
190 type = g_type_register_static(G_TYPE_OBJECT,
191 "GntWidget",
192 &info, G_TYPE_FLAG_ABSTRACT);
193 }
194
195 return type;
196 }
197
198 static void
199 gnt_widget_take_focus(GntWidget *widget)
200 {
201 gnt_screen_take_focus(widget);
202 }
203
204 void gnt_widget_set_take_focus(GntWidget *widget, gboolean can)
205 {
206 if (can)
207 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
208 else
209 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS);
210 }
211
212 /**
213 * gnt_widget_destroy:
214 * @obj: The #GntWidget instance.
215 *
216 * Emits the "destroy" signal notifying all reference holders that they
217 * should release @obj.
218 */
219 void
220 gnt_widget_destroy(GntWidget *obj)
221 {
222 g_return_if_fail(GNT_IS_WIDGET(obj));
223
224 delwin(obj->window);
225 if(!(GNT_WIDGET_FLAGS(obj) & GNT_WIDGET_DESTROYING))
226 g_object_run_dispose(G_OBJECT(obj));
227 gnt_screen_remove_widget(obj);
228 DEBUG;
229 }
230
231 void
232 gnt_widget_show(GntWidget *widget)
233 {
234 /* Draw the widget and take focus */
235 gnt_widget_draw(widget);
236 if (GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_CAN_TAKE_FOCUS)
237 {
238 gnt_widget_take_focus(widget);
239 }
240 }
241
242 void
243 gnt_widget_draw(GntWidget *widget)
244 {
245 /* Draw the widget */
246 DEBUG;
247 if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_MAPPED))
248 gnt_widget_map(widget);
249
250 if (widget->window)
251 {
252 delwin(widget->window);
253 }
254
255 widget->window = newwin(widget->priv.height, widget->priv.width,
256 widget->priv.y, widget->priv.x);
257 wbkgd(widget->window, COLOR_PAIR(GNT_COLOR_NORMAL));
258 if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER))
259 {
260 box(widget->window, 0, 0);
261 }
262 else
263 werase(widget->window);
264
265 if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_SHADOW))
266 {
267 /* XXX: Find out the actual windows beneath this window, and
268 * draw the shadow on them */
269 /* XXX: Or perhaps do all these from a psedo-WM! */
270 widget->back = newwin(widget->priv.height, widget->priv.width,
271 widget->priv.y + 1, widget->priv.x + 1);
272 wbkgd(widget->back, COLOR_PAIR(GNT_COLOR_SHADOW));
273 werase(widget->back);
274
275 mvwchgat(widget->back, 0, 0, widget->priv.height,
276 A_REVERSE | A_BLINK, 0, 0);
277 touchline(widget->back, 0, widget->priv.height);
278 wrefresh(widget->back);
279 }
280
281 wrefresh(widget->window);
282 g_signal_emit(widget, signals[SIG_DRAW], 0);
283 }
284
285 gboolean
286 gnt_widget_key_pressed(GntWidget *widget, const char *keys)
287 {
288 gboolean ret;
289 g_signal_emit(widget, signals[SIG_KEY_PRESSED], 0, keys, &ret);
290 return ret;
291 }
292
293 void
294 gnt_widget_expose(GntWidget *widget, int x, int y, int width, int height)
295 {
296 g_signal_emit(widget, signals[SIG_EXPOSE], 0, x, y, width, height);
297 }
298
299 void
300 gnt_widget_hide(GntWidget *widget)
301 {
302 int i;
303
304 /* XXX: Currently it simply empties the window. Ideally, it will
305 * detect what windows are immediately beneath this one, and cause
306 * those windows to redraw themselves by emitting the approrpiate
307 * expose signal. */
308
309 werase(widget->window);
310 wrefresh(widget->window);
311 }
312
313 void
314 gnt_widget_set_position(GntWidget *wid, int x, int y)
315 {
316 /* XXX: Need to install properties for these and g_object_notify */
317 wid->priv.x = x;
318 wid->priv.y = y;
319 g_signal_emit(wid, signals[SIG_POSITION], 0, x, y);
320 }
321
322 void
323 gnt_widget_get_position(GntWidget *wid, int *x, int *y)
324 {
325 if (x)
326 *x = wid->priv.x;
327 if (y)
328 *y = wid->priv.y;
329 }
330
331 void
332 gnt_widget_size_request(GntWidget *widget)
333 {
334 g_signal_emit(widget, signals[SIG_SIZE_REQUEST], 0);
335 }
336
337 void
338 gnt_widget_get_size(GntWidget *wid, int *width, int *height)
339 {
340 if (width)
341 *width = wid->priv.width;
342 if (height)
343 *height = wid->priv.height;
344 }
345
346 void
347 gnt_widget_set_size(GntWidget *widget, int width, int height)
348 {
349 widget->priv.width = width;
350 widget->priv.height = height;
351 }
352
353 gboolean
354 gnt_widget_set_focus(GntWidget *widget, gboolean set)
355 {
356 if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_CAN_TAKE_FOCUS))
357 return FALSE;
358
359 if (set && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_HAS_FOCUS))
360 {
361 g_signal_emit(widget->parent, signals[SIG_LOST_FOCUS], 0);
362 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_HAS_FOCUS);
363 g_signal_emit(widget, signals[SIG_GIVE_FOCUS], 0);
364 }
365 else if (!set)
366 {
367 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_HAS_FOCUS);
368 g_signal_emit(widget, signals[SIG_LOST_FOCUS], 0);
369 }
370 else
371 return FALSE;
372
373 return TRUE;
374 }
375
376 void gnt_widget_set_name(GntWidget *widget, const char *name)
377 {
378 g_free(widget->priv.name);
379 widget->priv.name = g_strdup(name);
380 }
381
382 void gnt_widget_activate(GntWidget *widget)
383 {
384 g_signal_emit(widget, signals[SIG_ACTIVATE], 0);
385 }
386