Mercurial > pidgin
annotate finch/libgnt/gntbox.c @ 19171:9f7587b86b0d
propagate from branch 'tmpbranch' (head e6743aa2d424749cd40350df703d079ef61fd5ce)
to branch 'im.pidgin.soc.2007.finchfeat' (head a87f346863ddc48e5705c2c555c7ed842325a9a3)
author | Eric Polino <aluink@pidgin.im> |
---|---|
date | Sun, 22 Jul 2007 01:28:19 +0000 |
parents | ac904659104f 2e11d73c4ff1 |
children | c79177766e13 |
rev | line source |
---|---|
18049
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
1 /** |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
2 * GNT - The GLib Ncurses Toolkit |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
3 * |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
4 * GNT is the legal property of its developers, whose names are too numerous |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
5 * to list here. Please refer to the COPYRIGHT file distributed with this |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
6 * source distribution. |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
7 * |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
8 * This library is free software; you can redistribute it and/or modify |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
9 * it under the terms of the GNU General Public License as published by |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
10 * the Free Software Foundation; either version 2 of the License, or |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
11 * (at your option) any later version. |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
12 * |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
13 * This program is distributed in the hope that it will be useful, |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
16 * GNU General Public License for more details. |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
17 * |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
18 * You should have received a copy of the GNU General Public License |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
19 * along with this program; if not, write to the Free Software |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
21 */ |
1cedd520cd18
Doxygen skeleton and license info for gnt files.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18000
diff
changeset
|
22 |
15817 | 23 #include "gntbox.h" |
24 #include "gntutils.h" | |
25 | |
26 #include <string.h> | |
27 | |
28 enum | |
29 { | |
30 SIGS = 1, | |
31 }; | |
32 | |
33 static GntWidgetClass *parent_class = NULL; | |
34 | |
35 static GntWidget * find_focusable_widget(GntBox *box); | |
36 | |
37 static void | |
38 add_to_focus(gpointer value, gpointer data) | |
39 { | |
40 GntBox *box = GNT_BOX(data); | |
41 GntWidget *w = GNT_WIDGET(value); | |
42 | |
43 if (GNT_IS_BOX(w)) | |
44 g_list_foreach(GNT_BOX(w)->list, add_to_focus, box); | |
45 else if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_CAN_TAKE_FOCUS)) | |
46 box->focus = g_list_append(box->focus, w); | |
47 } | |
48 | |
49 static void | |
50 get_title_thingies(GntBox *box, char *title, int *p, int *r) | |
51 { | |
52 GntWidget *widget = GNT_WIDGET(box); | |
53 int len; | |
54 char *end = (char*)gnt_util_onscreen_width_to_pointer(title, widget->priv.width - 4, &len); | |
55 | |
56 if (p) | |
57 *p = (widget->priv.width - len) / 2; | |
58 if (r) | |
59 *r = (widget->priv.width + len) / 2; | |
60 *end = '\0'; | |
61 } | |
62 | |
63 static void | |
64 gnt_box_draw(GntWidget *widget) | |
65 { | |
66 GntBox *box = GNT_BOX(widget); | |
67 | |
68 if (box->focus == NULL && widget->parent == NULL) | |
69 g_list_foreach(box->list, add_to_focus, box); | |
70 | |
71 g_list_foreach(box->list, (GFunc)gnt_widget_draw, NULL); | |
72 | |
73 gnt_box_sync_children(box); | |
74 | |
75 if (box->title && !GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) | |
76 { | |
77 int pos, right; | |
78 char *title = g_strdup(box->title); | |
79 | |
80 get_title_thingies(box, title, &pos, &right); | |
81 | |
82 if (gnt_widget_has_focus(widget)) | |
83 wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TITLE)); | |
84 else | |
85 wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_TITLE_D)); | |
86 mvwaddch(widget->window, 0, pos-1, ACS_RTEE | COLOR_PAIR(GNT_COLOR_NORMAL)); | |
87 mvwaddstr(widget->window, 0, pos, title); | |
88 mvwaddch(widget->window, 0, right, ACS_LTEE | COLOR_PAIR(GNT_COLOR_NORMAL)); | |
89 g_free(title); | |
90 } | |
91 | |
92 GNTDEBUG; | |
93 } | |
94 | |
95 static void | |
96 reposition_children(GntWidget *widget) | |
97 { | |
98 GList *iter; | |
99 GntBox *box = GNT_BOX(widget); | |
100 int w, h, curx, cury, max; | |
101 gboolean has_border = FALSE; | |
102 | |
103 w = h = 0; | |
104 max = 0; | |
105 curx = widget->priv.x; | |
106 cury = widget->priv.y; | |
107 if (!(GNT_WIDGET_FLAGS(widget) & GNT_WIDGET_NO_BORDER)) | |
108 { | |
109 has_border = TRUE; | |
110 curx += 1; | |
111 cury += 1; | |
112 } | |
113 | |
114 for (iter = box->list; iter; iter = iter->next) | |
115 { | |
116 if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(iter->data), GNT_WIDGET_INVISIBLE)) | |
117 continue; | |
118 gnt_widget_set_position(GNT_WIDGET(iter->data), curx, cury); | |
119 gnt_widget_get_size(GNT_WIDGET(iter->data), &w, &h); | |
120 if (box->vertical) | |
121 { | |
122 if (h) | |
123 { | |
124 cury += h + box->pad; | |
125 if (max < w) | |
126 max = w; | |
127 } | |
128 } | |
129 else | |
130 { | |
131 if (w) | |
132 { | |
133 curx += w + box->pad; | |
134 if (max < h) | |
135 max = h; | |
136 } | |
137 } | |
138 } | |
139 | |
140 if (has_border) | |
141 { | |
142 curx += 1; | |
143 cury += 1; | |
144 max += 2; | |
145 } | |
146 | |
147 if (box->list) | |
148 { | |
149 if (box->vertical) | |
150 cury -= box->pad; | |
151 else | |
152 curx -= box->pad; | |
153 } | |
154 | |
155 if (box->vertical) | |
156 { | |
157 widget->priv.width = max; | |
158 widget->priv.height = cury - widget->priv.y; | |
159 } | |
160 else | |
161 { | |
162 widget->priv.width = curx - widget->priv.x; | |
163 widget->priv.height = max; | |
164 } | |
165 } | |
166 | |
167 static void | |
168 gnt_box_set_position(GntWidget *widget, int x, int y) | |
169 { | |
170 GList *iter; | |
171 int changex, changey; | |
172 | |
173 changex = widget->priv.x - x; | |
174 changey = widget->priv.y - y; | |
175 | |
176 for (iter = GNT_BOX(widget)->list; iter; iter = iter->next) | |
177 { | |
178 GntWidget *w = GNT_WIDGET(iter->data); | |
179 gnt_widget_set_position(w, w->priv.x - changex, | |
180 w->priv.y - changey); | |
181 } | |
182 } | |
183 | |
184 static void | |
185 gnt_box_size_request(GntWidget *widget) | |
186 { | |
187 GntBox *box = GNT_BOX(widget); | |
188 GList *iter; | |
189 int maxw = 0, maxh = 0; | |
190 | |
191 g_list_foreach(box->list, (GFunc)gnt_widget_size_request, NULL); | |
192 | |
193 for (iter = box->list; iter; iter = iter->next) | |
194 { | |
195 int w, h; | |
196 gnt_widget_get_size(GNT_WIDGET(iter->data), &w, &h); | |
197 if (maxh < h) | |
198 maxh = h; | |
199 if (maxw < w) | |
200 maxw = w; | |
201 } | |
202 | |
203 for (iter = box->list; iter; iter = iter->next) | |
204 { | |
205 int w, h; | |
206 GntWidget *wid = GNT_WIDGET(iter->data); | |
207 | |
208 gnt_widget_get_size(wid, &w, &h); | |
209 | |
210 if (box->homogeneous) | |
211 { | |
212 if (box->vertical) | |
213 h = maxh; | |
214 else | |
215 w = maxw; | |
216 } | |
217 if (box->fill) | |
218 { | |
219 if (box->vertical) | |
220 w = maxw; | |
221 else | |
222 h = maxh; | |
223 } | |
224 | |
18538
2e11d73c4ff1
Properly set the initial size of widgets.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
18049
diff
changeset
|
225 gnt_widget_confirm_size(wid, w, h); |
15817 | 226 gnt_widget_set_size(wid, w, h); |
227 } | |
228 | |
229 reposition_children(widget); | |
230 } | |
231 | |
232 static void | |
233 gnt_box_map(GntWidget *widget) | |
234 { | |
235 if (widget->priv.width == 0 || widget->priv.height == 0) | |
236 { | |
237 gnt_widget_size_request(widget); | |
238 find_focusable_widget(GNT_BOX(widget)); | |
239 } | |
240 GNTDEBUG; | |
241 } | |
242 | |
243 /* Ensures that the current widget can take focus */ | |
244 static GntWidget * | |
245 find_focusable_widget(GntBox *box) | |
246 { | |
247 /* XXX: Make sure the widget is visible? */ | |
248 if (box->focus == NULL && GNT_WIDGET(box)->parent == NULL) | |
249 g_list_foreach(box->list, add_to_focus, box); | |
250 | |
251 if (box->active == NULL && box->focus) | |
252 box->active = box->focus->data; | |
253 | |
254 return box->active; | |
255 } | |
256 | |
257 static void | |
258 find_next_focus(GntBox *box) | |
259 { | |
260 gpointer last = box->active; | |
261 do | |
262 { | |
263 GList *iter = g_list_find(box->focus, box->active); | |
264 if (iter && iter->next) | |
265 box->active = iter->next->data; | |
266 else if (box->focus) | |
267 box->active = box->focus->data; | |
268 if (!GNT_WIDGET_IS_FLAG_SET(box->active, GNT_WIDGET_INVISIBLE)) | |
269 break; | |
270 } while (box->active != last); | |
271 } | |
272 | |
273 static void | |
274 find_prev_focus(GntBox *box) | |
275 { | |
276 gpointer last = box->active; | |
277 | |
278 if (!box->focus) | |
279 return; | |
280 | |
281 do | |
282 { | |
283 GList *iter = g_list_find(box->focus, box->active); | |
284 if (!iter) | |
285 box->active = box->focus->data; | |
286 else if (!iter->prev) | |
287 box->active = g_list_last(box->focus)->data; | |
288 else | |
289 box->active = iter->prev->data; | |
290 if (!GNT_WIDGET_IS_FLAG_SET(box->active, GNT_WIDGET_INVISIBLE)) | |
291 break; | |
292 } while (box->active != last); | |
293 } | |
294 | |
295 static gboolean | |
296 gnt_box_key_pressed(GntWidget *widget, const char *text) | |
297 { | |
298 GntBox *box = GNT_BOX(widget); | |
299 GntWidget *now; | |
300 | |
301 if (box->active == NULL && !find_focusable_widget(box)) | |
302 return FALSE; | |
303 | |
304 if (gnt_widget_key_pressed(box->active, text)) | |
305 return TRUE; | |
306 | |
307 now = box->active; | |
308 | |
309 if (text[0] == 27) | |
310 { | |
311 if (strcmp(text, GNT_KEY_LEFT) == 0) | |
312 { | |
313 find_prev_focus(box); | |
314 } | |
315 else if (strcmp(text, GNT_KEY_RIGHT) == 0) | |
316 { | |
317 find_next_focus(box); | |
318 } | |
319 } | |
320 else if (text[0] == '\t') | |
321 { | |
322 find_next_focus(box); | |
323 } | |
324 | |
325 if (now && now != box->active) | |
326 { | |
327 gnt_widget_set_focus(now, FALSE); | |
328 gnt_widget_set_focus(box->active, TRUE); | |
329 return TRUE; | |
330 } | |
331 | |
332 return FALSE; | |
333 } | |
334 | |
335 static void | |
336 gnt_box_lost_focus(GntWidget *widget) | |
337 { | |
338 GntWidget *w = GNT_BOX(widget)->active; | |
339 if (w) | |
340 gnt_widget_set_focus(w, FALSE); | |
341 gnt_widget_draw(widget); | |
342 } | |
343 | |
344 static void | |
345 gnt_box_gained_focus(GntWidget *widget) | |
346 { | |
347 GntWidget *w = GNT_BOX(widget)->active; | |
348 if (w) | |
349 gnt_widget_set_focus(w, TRUE); | |
350 gnt_widget_draw(widget); | |
351 } | |
352 | |
353 static void | |
354 gnt_box_destroy(GntWidget *w) | |
355 { | |
356 GntBox *box = GNT_BOX(w); | |
357 | |
358 gnt_box_remove_all(box); | |
359 gnt_screen_release(w); | |
360 } | |
361 | |
362 static void | |
363 gnt_box_expose(GntWidget *widget, int x, int y, int width, int height) | |
364 { | |
365 WINDOW *win = newwin(height, width, widget->priv.y + y, widget->priv.x + x); | |
366 copywin(widget->window, win, y, x, 0, 0, height - 1, width - 1, FALSE); | |
367 wrefresh(win); | |
368 delwin(win); | |
369 } | |
370 | |
371 static gboolean | |
372 gnt_box_confirm_size(GntWidget *widget, int width, int height) | |
373 { | |
374 GList *iter; | |
375 GntBox *box = GNT_BOX(widget); | |
376 int wchange, hchange; | |
377 | |
378 if (!box->list) | |
379 return TRUE; | |
380 | |
381 wchange = widget->priv.width - width; | |
382 hchange = widget->priv.height - height; | |
383 | |
384 if (wchange == 0 && hchange == 0) | |
385 return TRUE; /* Quit playing games */ | |
386 | |
387 /* XXX: Right now, I am trying to just apply all the changes to | |
388 * just one widget. It should be possible to distribute the | |
389 * changes to all the widgets in the box. */ | |
390 for (iter = box->list; iter; iter = iter->next) | |
391 { | |
392 GntWidget *wid = iter->data; | |
393 int w, h; | |
394 | |
395 gnt_widget_get_size(wid, &w, &h); | |
396 | |
397 if (gnt_widget_confirm_size(wid, w - wchange, h - hchange)) | |
398 { | |
399 GList *i; | |
400 | |
401 for (i = box->list; i; i = i->next) | |
402 { | |
403 int tw, th; | |
404 if (i == iter) continue; | |
405 gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th); | |
406 if (box->vertical) | |
407 { | |
15945
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15817
diff
changeset
|
408 if (!gnt_widget_confirm_size(i->data, tw - wchange, th)) { |
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15817
diff
changeset
|
409 /* If we are decreasing the size and the widget is going |
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15817
diff
changeset
|
410 * to be too large to fit into the box, then do not allow |
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15817
diff
changeset
|
411 * resizing. */ |
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15817
diff
changeset
|
412 if (wchange > 0 && tw >= widget->priv.width) |
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15817
diff
changeset
|
413 return FALSE; |
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15817
diff
changeset
|
414 } |
15817 | 415 } |
416 else | |
417 { | |
15945
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15817
diff
changeset
|
418 if (!gnt_widget_confirm_size(i->data, tw, th - hchange)) { |
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15817
diff
changeset
|
419 if (hchange > 0 && th >= widget->priv.height) |
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15817
diff
changeset
|
420 return FALSE; |
15817 | 421 return FALSE; |
15945
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15817
diff
changeset
|
422 } |
15817 | 423 } |
424 } | |
425 #if 0 | |
426 gnt_widget_set_size(wid, w - wchange, h - hchange); | |
427 if (box->vertical) | |
428 hchange = 0; | |
429 else | |
430 wchange = 0; | |
431 | |
432 for (i = box->list; i; i = i->next) | |
433 { | |
434 int tw, th; | |
435 if (i == iter) continue; | |
436 gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th); | |
437 gnt_widget_set_size(i->data, tw - wchange, th - hchange); | |
438 } | |
439 #endif | |
440 g_object_set_data(G_OBJECT(box), "size-queued", wid); | |
441 return TRUE; | |
442 } | |
443 } | |
444 | |
445 return FALSE; | |
446 } | |
447 | |
448 static void | |
449 gnt_box_size_changed(GntWidget *widget, int oldw, int oldh) | |
450 { | |
451 int wchange, hchange; | |
452 GList *i; | |
453 GntBox *box = GNT_BOX(widget); | |
454 GntWidget *wid; | |
455 int tw, th; | |
456 | |
457 wchange = widget->priv.width - oldw; | |
458 hchange = widget->priv.height - oldh; | |
459 | |
460 wid = g_object_get_data(G_OBJECT(box), "size-queued"); | |
461 if (wid) | |
462 { | |
463 gnt_widget_get_size(wid, &tw, &th); | |
464 gnt_widget_set_size(wid, tw + wchange, th + hchange); | |
465 g_object_set_data(G_OBJECT(box), "size-queued", NULL); | |
466 } | |
467 | |
468 if (box->vertical) | |
469 hchange = 0; | |
470 else | |
471 wchange = 0; | |
472 | |
473 for (i = box->list; i; i = i->next) | |
474 { | |
475 if (wid != i->data) | |
476 { | |
477 gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th); | |
478 gnt_widget_set_size(i->data, tw + wchange, th + hchange); | |
479 } | |
480 } | |
481 | |
482 reposition_children(widget); | |
483 } | |
484 | |
485 static gboolean | |
486 gnt_box_clicked(GntWidget *widget, GntMouseEvent event, int cx, int cy) | |
487 { | |
488 GList *iter; | |
489 for (iter = GNT_BOX(widget)->list; iter; iter = iter->next) { | |
490 int x, y, w, h; | |
491 GntWidget *wid = iter->data; | |
492 | |
493 gnt_widget_get_position(wid, &x, &y); | |
494 gnt_widget_get_size(wid, &w, &h); | |
495 | |
496 if (cx >= x && cx < x + w && cy >= y && cy < y + h) { | |
497 if (event <= GNT_MIDDLE_MOUSE_DOWN && | |
498 GNT_WIDGET_IS_FLAG_SET(wid, GNT_WIDGET_CAN_TAKE_FOCUS)) { | |
499 while (widget->parent) | |
500 widget = widget->parent; | |
501 gnt_box_give_focus_to_child(GNT_BOX(widget), wid); | |
502 } | |
503 return gnt_widget_clicked(wid, event, cx, cy); | |
504 } | |
505 } | |
506 return FALSE; | |
507 } | |
508 | |
509 static void | |
510 gnt_box_class_init(GntBoxClass *klass) | |
511 { | |
512 parent_class = GNT_WIDGET_CLASS(klass); | |
513 parent_class->destroy = gnt_box_destroy; | |
514 parent_class->draw = gnt_box_draw; | |
515 parent_class->expose = gnt_box_expose; | |
516 parent_class->map = gnt_box_map; | |
517 parent_class->size_request = gnt_box_size_request; | |
518 parent_class->set_position = gnt_box_set_position; | |
519 parent_class->key_pressed = gnt_box_key_pressed; | |
520 parent_class->clicked = gnt_box_clicked; | |
521 parent_class->lost_focus = gnt_box_lost_focus; | |
522 parent_class->gained_focus = gnt_box_gained_focus; | |
523 parent_class->confirm_size = gnt_box_confirm_size; | |
524 parent_class->size_changed = gnt_box_size_changed; | |
525 | |
526 GNTDEBUG; | |
527 } | |
528 | |
529 static void | |
530 gnt_box_init(GTypeInstance *instance, gpointer class) | |
531 { | |
532 GntWidget *widget = GNT_WIDGET(instance); | |
533 GntBox *box = GNT_BOX(widget); | |
534 /* Initially make both the height and width resizable. | |
535 * Update the flags as necessary when widgets are added to it. */ | |
536 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X | GNT_WIDGET_GROW_Y); | |
537 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS); | |
538 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); | |
539 box->pad = 1; | |
540 box->fill = TRUE; | |
541 GNTDEBUG; | |
542 } | |
543 | |
544 /****************************************************************************** | |
545 * GntBox API | |
546 *****************************************************************************/ | |
547 GType | |
548 gnt_box_get_gtype(void) | |
549 { | |
550 static GType type = 0; | |
551 | |
552 if(type == 0) | |
553 { | |
554 static const GTypeInfo info = { | |
555 sizeof(GntBoxClass), | |
556 NULL, /* base_init */ | |
557 NULL, /* base_finalize */ | |
558 (GClassInitFunc)gnt_box_class_init, | |
559 NULL, /* class_finalize */ | |
560 NULL, /* class_data */ | |
561 sizeof(GntBox), | |
562 0, /* n_preallocs */ | |
563 gnt_box_init, /* instance_init */ | |
564 NULL /* value_table */ | |
565 }; | |
566 | |
567 type = g_type_register_static(GNT_TYPE_WIDGET, | |
568 "GntBox", | |
569 &info, 0); | |
570 } | |
571 | |
572 return type; | |
573 } | |
574 | |
575 GntWidget *gnt_box_new(gboolean homo, gboolean vert) | |
576 { | |
577 GntWidget *widget = g_object_new(GNT_TYPE_BOX, NULL); | |
578 GntBox *box = GNT_BOX(widget); | |
579 | |
580 box->homogeneous = homo; | |
581 box->vertical = vert; | |
582 box->alignment = vert ? GNT_ALIGN_LEFT : GNT_ALIGN_MID; | |
583 | |
584 return widget; | |
585 } | |
586 | |
587 void gnt_box_add_widget(GntBox *b, GntWidget *widget) | |
588 { | |
589 b->list = g_list_append(b->list, widget); | |
590 widget->parent = GNT_WIDGET(b); | |
591 } | |
592 | |
593 void gnt_box_set_title(GntBox *b, const char *title) | |
594 { | |
595 char *prev = b->title; | |
596 GntWidget *w = GNT_WIDGET(b); | |
597 b->title = g_strdup(title); | |
598 if (w->window && !GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_NO_BORDER)) { | |
599 /* Erase the old title */ | |
600 int pos, right; | |
601 get_title_thingies(b, prev, &pos, &right); | |
602 mvwhline(w->window, 0, pos - 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), | |
603 right - pos + 2); | |
604 g_free(prev); | |
605 } | |
606 } | |
607 | |
608 void gnt_box_set_pad(GntBox *box, int pad) | |
609 { | |
610 box->pad = pad; | |
611 /* XXX: Perhaps redraw if already showing? */ | |
612 } | |
613 | |
614 void gnt_box_set_toplevel(GntBox *box, gboolean set) | |
615 { | |
616 GntWidget *widget = GNT_WIDGET(box); | |
617 if (set) | |
618 { | |
619 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); | |
620 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS); | |
621 } | |
622 else | |
623 { | |
624 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); | |
625 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS); | |
626 } | |
627 } | |
628 | |
629 void gnt_box_sync_children(GntBox *box) | |
630 { | |
631 GList *iter; | |
632 GntWidget *widget = GNT_WIDGET(box); | |
633 int pos = 1; | |
634 | |
635 if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) | |
636 pos = 0; | |
637 | |
638 for (iter = box->list; iter; iter = iter->next) | |
639 { | |
640 GntWidget *w = GNT_WIDGET(iter->data); | |
641 int height, width; | |
642 int x, y; | |
643 | |
644 if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_INVISIBLE)) | |
645 continue; | |
646 | |
647 if (GNT_IS_BOX(w)) | |
648 gnt_box_sync_children(GNT_BOX(w)); | |
649 | |
650 gnt_widget_get_size(w, &width, &height); | |
651 | |
652 x = w->priv.x - widget->priv.x; | |
653 y = w->priv.y - widget->priv.y; | |
654 | |
655 if (box->vertical) | |
656 { | |
657 x = pos; | |
658 if (box->alignment == GNT_ALIGN_RIGHT) | |
659 x += widget->priv.width - width; | |
660 else if (box->alignment == GNT_ALIGN_MID) | |
661 x += (widget->priv.width - width)/2; | |
662 if (x + width > widget->priv.width - pos) | |
663 x -= x + width - (widget->priv.width - pos); | |
664 } | |
665 else | |
666 { | |
667 y = pos; | |
668 if (box->alignment == GNT_ALIGN_BOTTOM) | |
669 y += widget->priv.height - height; | |
670 else if (box->alignment == GNT_ALIGN_MID) | |
671 y += (widget->priv.height - height)/2; | |
672 if (y + height >= widget->priv.height - pos) | |
673 y = widget->priv.height - height - pos; | |
674 } | |
675 | |
676 copywin(w->window, widget->window, 0, 0, | |
677 y, x, y + height - 1, x + width - 1, FALSE); | |
678 gnt_widget_set_position(w, x + widget->priv.x, y + widget->priv.y); | |
679 } | |
680 } | |
681 | |
682 void gnt_box_set_alignment(GntBox *box, GntAlignment alignment) | |
683 { | |
684 box->alignment = alignment; | |
685 } | |
686 | |
687 void gnt_box_remove(GntBox *box, GntWidget *widget) | |
688 { | |
689 box->list = g_list_remove(box->list, widget); | |
690 if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS) | |
691 && GNT_WIDGET(box)->parent == NULL && box->focus) | |
692 { | |
693 if (widget == box->active) | |
694 { | |
695 find_next_focus(box); | |
696 if (box->active == widget) /* There's only one widget */ | |
697 box->active = NULL; | |
698 } | |
699 box->focus = g_list_remove(box->focus, widget); | |
700 } | |
701 | |
702 if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(box), GNT_WIDGET_MAPPED)) | |
703 gnt_widget_draw(GNT_WIDGET(box)); | |
704 } | |
705 | |
706 void gnt_box_remove_all(GntBox *box) | |
707 { | |
708 g_list_foreach(box->list, (GFunc)gnt_widget_destroy, NULL); | |
709 g_list_free(box->list); | |
710 g_list_free(box->focus); | |
711 box->list = NULL; | |
712 box->focus = NULL; | |
713 GNT_WIDGET(box)->priv.width = 0; | |
714 GNT_WIDGET(box)->priv.height = 0; | |
715 } | |
716 | |
717 void gnt_box_readjust(GntBox *box) | |
718 { | |
719 GList *iter; | |
720 GntWidget *wid; | |
721 int width, height; | |
722 | |
723 if (GNT_WIDGET(box)->parent != NULL) | |
724 return; | |
725 | |
726 for (iter = box->list; iter; iter = iter->next) | |
727 { | |
728 GntWidget *w = iter->data; | |
729 if (GNT_IS_BOX(w)) | |
730 gnt_box_readjust(GNT_BOX(w)); | |
731 else | |
732 { | |
733 GNT_WIDGET_UNSET_FLAGS(w, GNT_WIDGET_MAPPED); | |
734 w->priv.width = 0; | |
735 w->priv.height = 0; | |
736 } | |
737 } | |
738 | |
739 wid = GNT_WIDGET(box); | |
740 GNT_WIDGET_UNSET_FLAGS(wid, GNT_WIDGET_MAPPED); | |
741 wid->priv.width = 0; | |
742 wid->priv.height = 0; | |
743 | |
744 if (wid->parent == NULL) | |
745 { | |
746 g_list_free(box->focus); | |
747 box->focus = NULL; | |
748 box->active = NULL; | |
749 gnt_widget_size_request(wid); | |
750 gnt_widget_get_size(wid, &width, &height); | |
751 gnt_screen_resize_widget(wid, width, height); | |
752 find_focusable_widget(box); | |
753 } | |
754 } | |
755 | |
756 void gnt_box_set_fill(GntBox *box, gboolean fill) | |
757 { | |
758 box->fill = fill; | |
759 } | |
760 | |
761 void gnt_box_move_focus(GntBox *box, int dir) | |
762 { | |
763 GntWidget *now; | |
764 | |
765 if (box->active == NULL) | |
766 { | |
767 find_focusable_widget(box); | |
768 return; | |
769 } | |
770 | |
771 now = box->active; | |
772 | |
773 if (dir == 1) | |
774 find_next_focus(box); | |
775 else if (dir == -1) | |
776 find_prev_focus(box); | |
777 | |
778 if (now && now != box->active) | |
779 { | |
780 gnt_widget_set_focus(now, FALSE); | |
781 gnt_widget_set_focus(box->active, TRUE); | |
782 } | |
783 | |
784 if (GNT_WIDGET(box)->window) | |
785 gnt_widget_draw(GNT_WIDGET(box)); | |
786 } | |
787 | |
788 void gnt_box_give_focus_to_child(GntBox *box, GntWidget *widget) | |
789 { | |
790 GList *find = g_list_find(box->focus, widget); | |
791 gpointer now = box->active; | |
792 if (find) | |
793 box->active = widget; | |
794 if (now && now != box->active) | |
795 { | |
796 gnt_widget_set_focus(now, FALSE); | |
797 gnt_widget_set_focus(box->active, TRUE); | |
798 } | |
799 | |
800 if (GNT_WIDGET(box)->window) | |
801 gnt_widget_draw(GNT_WIDGET(box)); | |
802 } | |
803 |