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