Mercurial > pidgin.yaz
annotate finch/libgnt/gntcombobox.c @ 21304:add12afc3140
Fix size calculation when shadow is enabled.
Also, when the terminal is resized, the SIGWINCH callback needs to refresh
after endwin to get the correct new size of the terminal.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Sat, 10 Nov 2007 23:48:57 +0000 |
parents | 9187d331aebe |
children | 0ba0f2804299 |
rev | line source |
---|---|
17718
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
1 /** |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
2 * GNT - The GLib Ncurses Toolkit |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
3 * |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
4 * GNT is the legal property of its developers, whose names are too numerous |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
5 * to list here. Please refer to the COPYRIGHT file distributed with this |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
6 * source distribution. |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
7 * |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
8 * This library is free software; you can redistribute it and/or modify |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
9 * it under the terms of the GNU General Public License as published by |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
10 * the Free Software Foundation; either version 2 of the License, or |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
11 * (at your option) any later version. |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
12 * |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
13 * This program is distributed in the hope that it will be useful, |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
16 * GNU General Public License for more details. |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
17 * |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
18 * You should have received a copy of the GNU General Public License |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
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:
18443
diff
changeset
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
17718
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
21 */ |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15818
diff
changeset
|
22 |
15818 | 23 #include "gntbox.h" |
24 #include "gntcombobox.h" | |
25 #include "gnttree.h" | |
26 #include "gntmarshal.h" | |
27 #include "gntutils.h" | |
28 | |
29 #include <string.h> | |
30 | |
31 enum | |
32 { | |
33 SIG_SELECTION_CHANGED, | |
34 SIGS, | |
35 }; | |
36 | |
37 static GntWidgetClass *parent_class = NULL; | |
38 static guint signals[SIGS] = { 0 }; | |
39 static void (*widget_lost_focus)(GntWidget *widget); | |
40 | |
41 static void | |
42 set_selection(GntComboBox *box, gpointer key) | |
43 { | |
44 if (box->selected != key) | |
45 { | |
46 /* XXX: make sure the key actually does exist */ | |
47 gpointer old = box->selected; | |
48 box->selected = key; | |
49 if (GNT_WIDGET(box)->window) | |
50 gnt_widget_draw(GNT_WIDGET(box)); | |
51 if (box->dropdown) | |
52 gnt_tree_set_selected(GNT_TREE(box->dropdown), key); | |
53 g_signal_emit(box, signals[SIG_SELECTION_CHANGED], 0, old, key); | |
54 } | |
55 } | |
56 | |
57 static void | |
58 hide_popup(GntComboBox *box, gboolean set) | |
59 { | |
60 gnt_widget_set_size(box->dropdown, | |
61 box->dropdown->priv.width - 1, box->dropdown->priv.height); | |
62 if (set) | |
63 set_selection(box, gnt_tree_get_selection_data(GNT_TREE(box->dropdown))); | |
64 else | |
65 gnt_tree_set_selected(GNT_TREE(box->dropdown), box->selected); | |
66 gnt_widget_hide(box->dropdown->parent); | |
67 } | |
68 | |
69 static void | |
70 gnt_combo_box_draw(GntWidget *widget) | |
71 { | |
72 GntComboBox *box = GNT_COMBO_BOX(widget); | |
73 char *text = NULL, *s; | |
74 GntColorType type; | |
75 int len; | |
76 | |
77 if (box->dropdown && box->selected) | |
78 text = gnt_tree_get_selection_text(GNT_TREE(box->dropdown)); | |
79 | |
80 if (text == NULL) | |
81 text = g_strdup(""); | |
82 | |
83 if (gnt_widget_has_focus(widget)) | |
84 type = GNT_COLOR_HIGHLIGHT; | |
85 else | |
86 type = GNT_COLOR_NORMAL; | |
87 | |
21250
9187d331aebe
Add gnt_color_pair, which will replace color codes with 'appropriate' text
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
19680
diff
changeset
|
88 wbkgdset(widget->window, '\0' | gnt_color_pair(type)); |
15818 | 89 |
90 s = (char*)gnt_util_onscreen_width_to_pointer(text, widget->priv.width - 4, &len); | |
91 *s = '\0'; | |
92 | |
93 mvwaddstr(widget->window, 1, 1, text); | |
21250
9187d331aebe
Add gnt_color_pair, which will replace color codes with 'appropriate' text
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
19680
diff
changeset
|
94 whline(widget->window, ' ' | gnt_color_pair(type), widget->priv.width - 4 - len); |
9187d331aebe
Add gnt_color_pair, which will replace color codes with 'appropriate' text
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
19680
diff
changeset
|
95 mvwaddch(widget->window, 1, widget->priv.width - 3, ACS_VLINE | gnt_color_pair(GNT_COLOR_NORMAL)); |
9187d331aebe
Add gnt_color_pair, which will replace color codes with 'appropriate' text
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
19680
diff
changeset
|
96 mvwaddch(widget->window, 1, widget->priv.width - 2, ACS_DARROW | gnt_color_pair(GNT_COLOR_NORMAL)); |
15818 | 97 |
98 g_free(text); | |
99 GNTDEBUG; | |
100 } | |
101 | |
102 static void | |
103 gnt_combo_box_size_request(GntWidget *widget) | |
104 { | |
105 if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED)) | |
106 { | |
107 GntWidget *dd = GNT_COMBO_BOX(widget)->dropdown; | |
108 gnt_widget_size_request(dd); | |
109 widget->priv.height = 3; /* For now, a combobox will have border */ | |
18443
92f845cd977c
Fix the initial size of a combobox.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
17718
diff
changeset
|
110 widget->priv.width = MAX(10, dd->priv.width + 2); |
15818 | 111 } |
112 } | |
113 | |
114 static void | |
115 gnt_combo_box_map(GntWidget *widget) | |
116 { | |
117 if (widget->priv.width == 0 || widget->priv.height == 0) | |
118 gnt_widget_size_request(widget); | |
119 GNTDEBUG; | |
120 } | |
121 | |
122 static void | |
123 popup_dropdown(GntComboBox *box) | |
124 { | |
125 GntWidget *widget = GNT_WIDGET(box); | |
126 GntWidget *parent = box->dropdown->parent; | |
127 int height = g_list_length(GNT_TREE(box->dropdown)->list); | |
128 int y = widget->priv.y + widget->priv.height - 1; | |
129 gnt_widget_set_size(box->dropdown, widget->priv.width, height + 2); | |
130 | |
131 if (y + height + 2 >= getmaxy(stdscr)) | |
132 y = widget->priv.y - height - 1; | |
133 gnt_widget_set_position(parent, widget->priv.x, y); | |
134 if (parent->window) | |
135 { | |
136 mvwin(parent->window, y, widget->priv.x); | |
137 wresize(parent->window, height+2, widget->priv.width); | |
138 } | |
139 parent->priv.width = widget->priv.width; | |
140 parent->priv.height = height + 2; | |
141 | |
142 GNT_WIDGET_UNSET_FLAGS(parent, GNT_WIDGET_INVISIBLE); | |
143 gnt_widget_draw(parent); | |
144 } | |
145 | |
146 static gboolean | |
147 gnt_combo_box_key_pressed(GntWidget *widget, const char *text) | |
148 { | |
149 GntComboBox *box = GNT_COMBO_BOX(widget); | |
150 if (GNT_WIDGET_IS_FLAG_SET(box->dropdown->parent, GNT_WIDGET_MAPPED)) | |
151 { | |
152 if (text[1] == 0) | |
153 { | |
154 switch (text[0]) | |
155 { | |
156 case '\r': | |
157 case '\t': | |
158 hide_popup(box, TRUE); | |
159 return TRUE; | |
160 case 27: | |
161 hide_popup(box, FALSE); | |
162 return TRUE; | |
163 } | |
164 } | |
165 if (gnt_widget_key_pressed(box->dropdown, text)) | |
166 return TRUE; | |
167 } | |
168 else | |
169 { | |
170 if (text[0] == 27) | |
171 { | |
172 if (strcmp(text, GNT_KEY_UP) == 0 || | |
173 strcmp(text, GNT_KEY_DOWN) == 0) | |
174 { | |
175 popup_dropdown(box); | |
176 return TRUE; | |
177 } | |
178 } | |
179 } | |
180 | |
181 return FALSE; | |
182 } | |
183 | |
184 static void | |
185 gnt_combo_box_destroy(GntWidget *widget) | |
186 { | |
187 gnt_widget_destroy(GNT_COMBO_BOX(widget)->dropdown->parent); | |
188 } | |
189 | |
190 static void | |
191 gnt_combo_box_lost_focus(GntWidget *widget) | |
192 { | |
193 GntComboBox *combo = GNT_COMBO_BOX(widget); | |
194 if (GNT_WIDGET_IS_FLAG_SET(combo->dropdown->parent, GNT_WIDGET_MAPPED)) | |
195 hide_popup(combo, FALSE); | |
196 widget_lost_focus(widget); | |
197 } | |
198 | |
199 static gboolean | |
200 gnt_combo_box_clicked(GntWidget *widget, GntMouseEvent event, int x, int y) | |
201 { | |
202 GntComboBox *box = GNT_COMBO_BOX(widget); | |
203 gboolean dshowing = GNT_WIDGET_IS_FLAG_SET(box->dropdown->parent, GNT_WIDGET_MAPPED); | |
204 | |
205 if (event == GNT_MOUSE_SCROLL_UP) { | |
206 if (dshowing) | |
207 gnt_widget_key_pressed(box->dropdown, GNT_KEY_UP); | |
208 } else if (event == GNT_MOUSE_SCROLL_DOWN) { | |
209 if (dshowing) | |
210 gnt_widget_key_pressed(box->dropdown, GNT_KEY_DOWN); | |
211 } else if (event == GNT_LEFT_MOUSE_DOWN) { | |
212 if (dshowing) { | |
213 hide_popup(box, TRUE); | |
214 } else { | |
215 popup_dropdown(GNT_COMBO_BOX(widget)); | |
216 } | |
217 } else | |
218 return FALSE; | |
219 return TRUE; | |
220 } | |
221 | |
222 static void | |
223 gnt_combo_box_size_changed(GntWidget *widget, int oldw, int oldh) | |
224 { | |
225 GntComboBox *box = GNT_COMBO_BOX(widget); | |
226 gnt_widget_set_size(box->dropdown, widget->priv.width - 1, box->dropdown->priv.height); | |
227 } | |
228 | |
229 static void | |
230 gnt_combo_box_class_init(GntComboBoxClass *klass) | |
231 { | |
232 parent_class = GNT_WIDGET_CLASS(klass); | |
233 | |
234 parent_class->destroy = gnt_combo_box_destroy; | |
235 parent_class->draw = gnt_combo_box_draw; | |
236 parent_class->map = gnt_combo_box_map; | |
237 parent_class->size_request = gnt_combo_box_size_request; | |
238 parent_class->key_pressed = gnt_combo_box_key_pressed; | |
239 parent_class->clicked = gnt_combo_box_clicked; | |
240 parent_class->size_changed = gnt_combo_box_size_changed; | |
241 | |
242 widget_lost_focus = parent_class->lost_focus; | |
243 parent_class->lost_focus = gnt_combo_box_lost_focus; | |
244 | |
245 signals[SIG_SELECTION_CHANGED] = | |
246 g_signal_new("selection-changed", | |
247 G_TYPE_FROM_CLASS(klass), | |
248 G_SIGNAL_RUN_LAST, | |
249 0, | |
250 NULL, NULL, | |
251 gnt_closure_marshal_VOID__POINTER_POINTER, | |
252 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); | |
253 | |
254 GNTDEBUG; | |
255 } | |
256 | |
257 static void | |
258 gnt_combo_box_init(GTypeInstance *instance, gpointer class) | |
259 { | |
260 GntWidget *box; | |
261 GntWidget *widget = GNT_WIDGET(instance); | |
262 GntComboBox *combo = GNT_COMBO_BOX(instance); | |
263 | |
264 GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance), | |
265 GNT_WIDGET_GROW_X | GNT_WIDGET_CAN_TAKE_FOCUS | GNT_WIDGET_NO_SHADOW); | |
266 combo->dropdown = gnt_tree_new(); | |
267 | |
268 box = gnt_box_new(FALSE, FALSE); | |
269 GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER | GNT_WIDGET_TRANSIENT); | |
270 gnt_box_set_pad(GNT_BOX(box), 0); | |
271 gnt_box_add_widget(GNT_BOX(box), combo->dropdown); | |
272 | |
273 widget->priv.minw = 4; | |
274 widget->priv.minh = 3; | |
275 GNTDEBUG; | |
276 } | |
277 | |
278 /****************************************************************************** | |
279 * GntComboBox API | |
280 *****************************************************************************/ | |
281 GType | |
282 gnt_combo_box_get_gtype(void) | |
283 { | |
284 static GType type = 0; | |
285 | |
286 if(type == 0) | |
287 { | |
288 static const GTypeInfo info = { | |
289 sizeof(GntComboBoxClass), | |
290 NULL, /* base_init */ | |
291 NULL, /* base_finalize */ | |
292 (GClassInitFunc)gnt_combo_box_class_init, | |
293 NULL, /* class_finalize */ | |
294 NULL, /* class_data */ | |
295 sizeof(GntComboBox), | |
296 0, /* n_preallocs */ | |
297 gnt_combo_box_init, /* instance_init */ | |
298 NULL /* value_table */ | |
299 }; | |
300 | |
301 type = g_type_register_static(GNT_TYPE_WIDGET, | |
302 "GntComboBox", | |
303 &info, 0); | |
304 } | |
305 | |
306 return type; | |
307 } | |
308 | |
309 GntWidget *gnt_combo_box_new() | |
310 { | |
311 GntWidget *widget = g_object_new(GNT_TYPE_COMBO_BOX, NULL); | |
312 | |
313 return widget; | |
314 } | |
315 | |
316 void gnt_combo_box_add_data(GntComboBox *box, gpointer key, const char *text) | |
317 { | |
318 gnt_tree_add_row_last(GNT_TREE(box->dropdown), key, | |
319 gnt_tree_create_row(GNT_TREE(box->dropdown), text), NULL); | |
320 if (box->selected == NULL) | |
321 set_selection(box, key); | |
322 } | |
323 | |
324 gpointer gnt_combo_box_get_selected_data(GntComboBox *box) | |
325 { | |
326 return box->selected; | |
327 } | |
328 | |
329 void gnt_combo_box_set_selected(GntComboBox *box, gpointer key) | |
330 { | |
331 set_selection(box, key); | |
332 } | |
333 | |
334 void gnt_combo_box_remove(GntComboBox *box, gpointer key) | |
335 { | |
336 gnt_tree_remove(GNT_TREE(box->dropdown), key); | |
337 if (box->selected == key) | |
338 set_selection(box, NULL); | |
339 } | |
340 | |
341 void gnt_combo_box_remove_all(GntComboBox *box) | |
342 { | |
343 gnt_tree_remove_all(GNT_TREE(box->dropdown)); | |
344 set_selection(box, NULL); | |
345 } | |
346 |