Mercurial > pidgin.yaz
annotate finch/libgnt/gntbox.c @ 21174:6e0c99e134c2
Fix the win32 build for the file synchronization changes. Hopefully this will fix some of the occasional issues that people have had on Windows with their files getting corrupted on power failure or something.
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Fri, 09 Nov 2007 01:39:51 +0000 |
parents | 44b4e8bd759b |
children | 9187d331aebe |
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 |
19680
44b4e8bd759b
The FSF changed its address a while ago; our files were out of date.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
18538
diff
changeset
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
18049
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 |
15818 | 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); |
15818 | 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 } | |
18000
05d7fe2320a9
(16:39:44) rekkanoryo: i have a feature request
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15945
diff
changeset
|
319 else if (strcmp(text, GNT_KEY_BACK_TAB) == 0) |
05d7fe2320a9
(16:39:44) rekkanoryo: i have a feature request
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15945
diff
changeset
|
320 { |
05d7fe2320a9
(16:39:44) rekkanoryo: i have a feature request
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15945
diff
changeset
|
321 find_prev_focus(box); |
05d7fe2320a9
(16:39:44) rekkanoryo: i have a feature request
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15945
diff
changeset
|
322 } |
15818 | 323 } |
324 else if (text[0] == '\t') | |
325 { | |
326 find_next_focus(box); | |
327 } | |
328 | |
329 if (now && now != box->active) | |
330 { | |
331 gnt_widget_set_focus(now, FALSE); | |
332 gnt_widget_set_focus(box->active, TRUE); | |
333 return TRUE; | |
334 } | |
335 | |
336 return FALSE; | |
337 } | |
338 | |
339 static void | |
340 gnt_box_lost_focus(GntWidget *widget) | |
341 { | |
342 GntWidget *w = GNT_BOX(widget)->active; | |
343 if (w) | |
344 gnt_widget_set_focus(w, FALSE); | |
345 gnt_widget_draw(widget); | |
346 } | |
347 | |
348 static void | |
349 gnt_box_gained_focus(GntWidget *widget) | |
350 { | |
351 GntWidget *w = GNT_BOX(widget)->active; | |
352 if (w) | |
353 gnt_widget_set_focus(w, TRUE); | |
354 gnt_widget_draw(widget); | |
355 } | |
356 | |
357 static void | |
358 gnt_box_destroy(GntWidget *w) | |
359 { | |
360 GntBox *box = GNT_BOX(w); | |
361 | |
362 gnt_box_remove_all(box); | |
363 gnt_screen_release(w); | |
364 } | |
365 | |
366 static void | |
367 gnt_box_expose(GntWidget *widget, int x, int y, int width, int height) | |
368 { | |
369 WINDOW *win = newwin(height, width, widget->priv.y + y, widget->priv.x + x); | |
370 copywin(widget->window, win, y, x, 0, 0, height - 1, width - 1, FALSE); | |
371 wrefresh(win); | |
372 delwin(win); | |
373 } | |
374 | |
375 static gboolean | |
376 gnt_box_confirm_size(GntWidget *widget, int width, int height) | |
377 { | |
378 GList *iter; | |
379 GntBox *box = GNT_BOX(widget); | |
380 int wchange, hchange; | |
381 | |
382 if (!box->list) | |
383 return TRUE; | |
384 | |
385 wchange = widget->priv.width - width; | |
386 hchange = widget->priv.height - height; | |
387 | |
388 if (wchange == 0 && hchange == 0) | |
389 return TRUE; /* Quit playing games */ | |
390 | |
391 /* XXX: Right now, I am trying to just apply all the changes to | |
392 * just one widget. It should be possible to distribute the | |
393 * changes to all the widgets in the box. */ | |
394 for (iter = box->list; iter; iter = iter->next) | |
395 { | |
396 GntWidget *wid = iter->data; | |
397 int w, h; | |
398 | |
399 gnt_widget_get_size(wid, &w, &h); | |
400 | |
401 if (gnt_widget_confirm_size(wid, w - wchange, h - hchange)) | |
402 { | |
403 GList *i; | |
404 | |
405 for (i = box->list; i; i = i->next) | |
406 { | |
407 int tw, th; | |
408 if (i == iter) continue; | |
409 gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th); | |
410 if (box->vertical) | |
411 { | |
15945
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
412 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
|
413 /* 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
|
414 * 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
|
415 * resizing. */ |
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
416 if (wchange > 0 && tw >= widget->priv.width) |
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
417 return FALSE; |
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
418 } |
15818 | 419 } |
420 else | |
421 { | |
15945
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
422 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
|
423 if (hchange > 0 && th >= widget->priv.height) |
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
424 return FALSE; |
15818 | 425 return FALSE; |
15945
92fa7d6e75b0
A few more fixes for resizing.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
15818
diff
changeset
|
426 } |
15818 | 427 } |
428 } | |
429 #if 0 | |
430 gnt_widget_set_size(wid, w - wchange, h - hchange); | |
431 if (box->vertical) | |
432 hchange = 0; | |
433 else | |
434 wchange = 0; | |
435 | |
436 for (i = box->list; i; i = i->next) | |
437 { | |
438 int tw, th; | |
439 if (i == iter) continue; | |
440 gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th); | |
441 gnt_widget_set_size(i->data, tw - wchange, th - hchange); | |
442 } | |
443 #endif | |
444 g_object_set_data(G_OBJECT(box), "size-queued", wid); | |
445 return TRUE; | |
446 } | |
447 } | |
448 | |
449 return FALSE; | |
450 } | |
451 | |
452 static void | |
453 gnt_box_size_changed(GntWidget *widget, int oldw, int oldh) | |
454 { | |
455 int wchange, hchange; | |
456 GList *i; | |
457 GntBox *box = GNT_BOX(widget); | |
458 GntWidget *wid; | |
459 int tw, th; | |
460 | |
461 wchange = widget->priv.width - oldw; | |
462 hchange = widget->priv.height - oldh; | |
463 | |
464 wid = g_object_get_data(G_OBJECT(box), "size-queued"); | |
465 if (wid) | |
466 { | |
467 gnt_widget_get_size(wid, &tw, &th); | |
468 gnt_widget_set_size(wid, tw + wchange, th + hchange); | |
469 g_object_set_data(G_OBJECT(box), "size-queued", NULL); | |
470 } | |
471 | |
472 if (box->vertical) | |
473 hchange = 0; | |
474 else | |
475 wchange = 0; | |
476 | |
477 for (i = box->list; i; i = i->next) | |
478 { | |
479 if (wid != i->data) | |
480 { | |
481 gnt_widget_get_size(GNT_WIDGET(i->data), &tw, &th); | |
482 gnt_widget_set_size(i->data, tw + wchange, th + hchange); | |
483 } | |
484 } | |
485 | |
486 reposition_children(widget); | |
487 } | |
488 | |
489 static gboolean | |
490 gnt_box_clicked(GntWidget *widget, GntMouseEvent event, int cx, int cy) | |
491 { | |
492 GList *iter; | |
493 for (iter = GNT_BOX(widget)->list; iter; iter = iter->next) { | |
494 int x, y, w, h; | |
495 GntWidget *wid = iter->data; | |
496 | |
497 gnt_widget_get_position(wid, &x, &y); | |
498 gnt_widget_get_size(wid, &w, &h); | |
499 | |
500 if (cx >= x && cx < x + w && cy >= y && cy < y + h) { | |
501 if (event <= GNT_MIDDLE_MOUSE_DOWN && | |
502 GNT_WIDGET_IS_FLAG_SET(wid, GNT_WIDGET_CAN_TAKE_FOCUS)) { | |
503 while (widget->parent) | |
504 widget = widget->parent; | |
505 gnt_box_give_focus_to_child(GNT_BOX(widget), wid); | |
506 } | |
507 return gnt_widget_clicked(wid, event, cx, cy); | |
508 } | |
509 } | |
510 return FALSE; | |
511 } | |
512 | |
513 static void | |
514 gnt_box_class_init(GntBoxClass *klass) | |
515 { | |
516 parent_class = GNT_WIDGET_CLASS(klass); | |
517 parent_class->destroy = gnt_box_destroy; | |
518 parent_class->draw = gnt_box_draw; | |
519 parent_class->expose = gnt_box_expose; | |
520 parent_class->map = gnt_box_map; | |
521 parent_class->size_request = gnt_box_size_request; | |
522 parent_class->set_position = gnt_box_set_position; | |
523 parent_class->key_pressed = gnt_box_key_pressed; | |
524 parent_class->clicked = gnt_box_clicked; | |
525 parent_class->lost_focus = gnt_box_lost_focus; | |
526 parent_class->gained_focus = gnt_box_gained_focus; | |
527 parent_class->confirm_size = gnt_box_confirm_size; | |
528 parent_class->size_changed = gnt_box_size_changed; | |
529 | |
530 GNTDEBUG; | |
531 } | |
532 | |
533 static void | |
534 gnt_box_init(GTypeInstance *instance, gpointer class) | |
535 { | |
536 GntWidget *widget = GNT_WIDGET(instance); | |
537 GntBox *box = GNT_BOX(widget); | |
538 /* Initially make both the height and width resizable. | |
539 * Update the flags as necessary when widgets are added to it. */ | |
540 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_GROW_X | GNT_WIDGET_GROW_Y); | |
541 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS); | |
542 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); | |
543 box->pad = 1; | |
544 box->fill = TRUE; | |
545 GNTDEBUG; | |
546 } | |
547 | |
548 /****************************************************************************** | |
549 * GntBox API | |
550 *****************************************************************************/ | |
551 GType | |
552 gnt_box_get_gtype(void) | |
553 { | |
554 static GType type = 0; | |
555 | |
556 if(type == 0) | |
557 { | |
558 static const GTypeInfo info = { | |
559 sizeof(GntBoxClass), | |
560 NULL, /* base_init */ | |
561 NULL, /* base_finalize */ | |
562 (GClassInitFunc)gnt_box_class_init, | |
563 NULL, /* class_finalize */ | |
564 NULL, /* class_data */ | |
565 sizeof(GntBox), | |
566 0, /* n_preallocs */ | |
567 gnt_box_init, /* instance_init */ | |
568 NULL /* value_table */ | |
569 }; | |
570 | |
571 type = g_type_register_static(GNT_TYPE_WIDGET, | |
572 "GntBox", | |
573 &info, 0); | |
574 } | |
575 | |
576 return type; | |
577 } | |
578 | |
579 GntWidget *gnt_box_new(gboolean homo, gboolean vert) | |
580 { | |
581 GntWidget *widget = g_object_new(GNT_TYPE_BOX, NULL); | |
582 GntBox *box = GNT_BOX(widget); | |
583 | |
584 box->homogeneous = homo; | |
585 box->vertical = vert; | |
586 box->alignment = vert ? GNT_ALIGN_LEFT : GNT_ALIGN_MID; | |
587 | |
588 return widget; | |
589 } | |
590 | |
591 void gnt_box_add_widget(GntBox *b, GntWidget *widget) | |
592 { | |
593 b->list = g_list_append(b->list, widget); | |
594 widget->parent = GNT_WIDGET(b); | |
595 } | |
596 | |
597 void gnt_box_set_title(GntBox *b, const char *title) | |
598 { | |
599 char *prev = b->title; | |
600 GntWidget *w = GNT_WIDGET(b); | |
601 b->title = g_strdup(title); | |
602 if (w->window && !GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_NO_BORDER)) { | |
603 /* Erase the old title */ | |
604 int pos, right; | |
605 get_title_thingies(b, prev, &pos, &right); | |
606 mvwhline(w->window, 0, pos - 1, ACS_HLINE | COLOR_PAIR(GNT_COLOR_NORMAL), | |
607 right - pos + 2); | |
608 g_free(prev); | |
609 } | |
610 } | |
611 | |
612 void gnt_box_set_pad(GntBox *box, int pad) | |
613 { | |
614 box->pad = pad; | |
615 /* XXX: Perhaps redraw if already showing? */ | |
616 } | |
617 | |
618 void gnt_box_set_toplevel(GntBox *box, gboolean set) | |
619 { | |
620 GntWidget *widget = GNT_WIDGET(box); | |
621 if (set) | |
622 { | |
623 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); | |
624 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS); | |
625 } | |
626 else | |
627 { | |
628 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_BORDER | GNT_WIDGET_NO_SHADOW); | |
629 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_CAN_TAKE_FOCUS); | |
630 } | |
631 } | |
632 | |
633 void gnt_box_sync_children(GntBox *box) | |
634 { | |
635 GList *iter; | |
636 GntWidget *widget = GNT_WIDGET(box); | |
637 int pos = 1; | |
638 | |
639 if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_NO_BORDER)) | |
640 pos = 0; | |
641 | |
642 for (iter = box->list; iter; iter = iter->next) | |
643 { | |
644 GntWidget *w = GNT_WIDGET(iter->data); | |
645 int height, width; | |
646 int x, y; | |
647 | |
648 if (GNT_WIDGET_IS_FLAG_SET(w, GNT_WIDGET_INVISIBLE)) | |
649 continue; | |
650 | |
651 if (GNT_IS_BOX(w)) | |
652 gnt_box_sync_children(GNT_BOX(w)); | |
653 | |
654 gnt_widget_get_size(w, &width, &height); | |
655 | |
656 x = w->priv.x - widget->priv.x; | |
657 y = w->priv.y - widget->priv.y; | |
658 | |
659 if (box->vertical) | |
660 { | |
661 x = pos; | |
662 if (box->alignment == GNT_ALIGN_RIGHT) | |
663 x += widget->priv.width - width; | |
664 else if (box->alignment == GNT_ALIGN_MID) | |
665 x += (widget->priv.width - width)/2; | |
666 if (x + width > widget->priv.width - pos) | |
667 x -= x + width - (widget->priv.width - pos); | |
668 } | |
669 else | |
670 { | |
671 y = pos; | |
672 if (box->alignment == GNT_ALIGN_BOTTOM) | |
673 y += widget->priv.height - height; | |
674 else if (box->alignment == GNT_ALIGN_MID) | |
675 y += (widget->priv.height - height)/2; | |
676 if (y + height >= widget->priv.height - pos) | |
677 y = widget->priv.height - height - pos; | |
678 } | |
679 | |
680 copywin(w->window, widget->window, 0, 0, | |
681 y, x, y + height - 1, x + width - 1, FALSE); | |
682 gnt_widget_set_position(w, x + widget->priv.x, y + widget->priv.y); | |
683 } | |
684 } | |
685 | |
686 void gnt_box_set_alignment(GntBox *box, GntAlignment alignment) | |
687 { | |
688 box->alignment = alignment; | |
689 } | |
690 | |
691 void gnt_box_remove(GntBox *box, GntWidget *widget) | |
692 { | |
693 box->list = g_list_remove(box->list, widget); | |
694 if (GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_CAN_TAKE_FOCUS) | |
695 && GNT_WIDGET(box)->parent == NULL && box->focus) | |
696 { | |
697 if (widget == box->active) | |
698 { | |
699 find_next_focus(box); | |
700 if (box->active == widget) /* There's only one widget */ | |
701 box->active = NULL; | |
702 } | |
703 box->focus = g_list_remove(box->focus, widget); | |
704 } | |
705 | |
706 if (GNT_WIDGET_IS_FLAG_SET(GNT_WIDGET(box), GNT_WIDGET_MAPPED)) | |
707 gnt_widget_draw(GNT_WIDGET(box)); | |
708 } | |
709 | |
710 void gnt_box_remove_all(GntBox *box) | |
711 { | |
712 g_list_foreach(box->list, (GFunc)gnt_widget_destroy, NULL); | |
713 g_list_free(box->list); | |
714 g_list_free(box->focus); | |
715 box->list = NULL; | |
716 box->focus = NULL; | |
717 GNT_WIDGET(box)->priv.width = 0; | |
718 GNT_WIDGET(box)->priv.height = 0; | |
719 } | |
720 | |
721 void gnt_box_readjust(GntBox *box) | |
722 { | |
723 GList *iter; | |
724 GntWidget *wid; | |
725 int width, height; | |
726 | |
727 if (GNT_WIDGET(box)->parent != NULL) | |
728 return; | |
729 | |
730 for (iter = box->list; iter; iter = iter->next) | |
731 { | |
732 GntWidget *w = iter->data; | |
733 if (GNT_IS_BOX(w)) | |
734 gnt_box_readjust(GNT_BOX(w)); | |
735 else | |
736 { | |
737 GNT_WIDGET_UNSET_FLAGS(w, GNT_WIDGET_MAPPED); | |
738 w->priv.width = 0; | |
739 w->priv.height = 0; | |
740 } | |
741 } | |
742 | |
743 wid = GNT_WIDGET(box); | |
744 GNT_WIDGET_UNSET_FLAGS(wid, GNT_WIDGET_MAPPED); | |
745 wid->priv.width = 0; | |
746 wid->priv.height = 0; | |
747 | |
748 if (wid->parent == NULL) | |
749 { | |
750 g_list_free(box->focus); | |
751 box->focus = NULL; | |
752 box->active = NULL; | |
753 gnt_widget_size_request(wid); | |
754 gnt_widget_get_size(wid, &width, &height); | |
755 gnt_screen_resize_widget(wid, width, height); | |
756 find_focusable_widget(box); | |
757 } | |
758 } | |
759 | |
760 void gnt_box_set_fill(GntBox *box, gboolean fill) | |
761 { | |
762 box->fill = fill; | |
763 } | |
764 | |
765 void gnt_box_move_focus(GntBox *box, int dir) | |
766 { | |
767 GntWidget *now; | |
768 | |
769 if (box->active == NULL) | |
770 { | |
771 find_focusable_widget(box); | |
772 return; | |
773 } | |
774 | |
775 now = box->active; | |
776 | |
777 if (dir == 1) | |
778 find_next_focus(box); | |
779 else if (dir == -1) | |
780 find_prev_focus(box); | |
781 | |
782 if (now && now != box->active) | |
783 { | |
784 gnt_widget_set_focus(now, FALSE); | |
785 gnt_widget_set_focus(box->active, TRUE); | |
786 } | |
787 | |
788 if (GNT_WIDGET(box)->window) | |
789 gnt_widget_draw(GNT_WIDGET(box)); | |
790 } | |
791 | |
792 void gnt_box_give_focus_to_child(GntBox *box, GntWidget *widget) | |
793 { | |
794 GList *find = g_list_find(box->focus, widget); | |
795 gpointer now = box->active; | |
796 if (find) | |
797 box->active = widget; | |
798 if (now && now != box->active) | |
799 { | |
800 gnt_widget_set_focus(now, FALSE); | |
801 gnt_widget_set_focus(box->active, TRUE); | |
802 } | |
803 | |
804 if (GNT_WIDGET(box)->window) | |
805 gnt_widget_draw(GNT_WIDGET(box)); | |
806 } | |
807 |