Mercurial > pidgin
annotate finch/libgnt/gntcombobox.c @ 25265:2307f8124407
Only initialize dbus threading if glib threading is initialized. The idea is
that anything that will encounter the side effect of other libraries using dbus
from gthreads will have had to already initialize glib threading earlier.
Fixes #7538
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Wed, 07 Jan 2009 04:04:05 +0000 |
parents | 0ba0f2804299 |
children | c67d43408daa |
rev | line source |
---|---|
17928
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
diff
changeset
|
1 /** |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
diff
changeset
|
2 * GNT - The GLib Ncurses Toolkit |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
diff
changeset
|
3 * |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
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:
15817
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:
15817
diff
changeset
|
6 * source distribution. |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
diff
changeset
|
7 * |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
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:
15817
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:
15817
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:
15817
diff
changeset
|
11 * (at your option) any later version. |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
diff
changeset
|
12 * |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
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:
15817
diff
changeset
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
diff
changeset
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
diff
changeset
|
16 * GNU General Public License for more details. |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
diff
changeset
|
17 * |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
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:
15817
diff
changeset
|
19 * along with this program; if not, write to the Free Software |
19681
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 |
17928
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
diff
changeset
|
21 */ |
8410511f4dbb
applied changes from 016401bd409e6229fae0ab1e80d9fef9365511b3
Eric Polino <aluink@pidgin.im>
parents:
15817
diff
changeset
|
22 |
15817 | 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:
19681
diff
changeset
|
88 wbkgdset(widget->window, '\0' | gnt_color_pair(type)); |
15817 | 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:
19681
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:
19681
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:
19681
diff
changeset
|
96 mvwaddch(widget->window, 1, widget->priv.width - 2, ACS_DARROW | gnt_color_pair(GNT_COLOR_NORMAL)); |
15817 | 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:
17928
diff
changeset
|
110 widget->priv.width = MAX(10, dd->priv.width + 2); |
15817 | 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': | |
22289
0ba0f2804299
'\n' (ctrl-j) should behave similar to '\r' (ctrl-m). Fixes #4833.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
21250
diff
changeset
|
158 case '\n': |
15817 | 159 hide_popup(box, TRUE); |
160 return TRUE; | |
161 case 27: | |
162 hide_popup(box, FALSE); | |
163 return TRUE; | |
164 } | |
165 } | |
166 if (gnt_widget_key_pressed(box->dropdown, text)) | |
167 return TRUE; | |
168 } | |
169 else | |
170 { | |
171 if (text[0] == 27) | |
172 { | |
173 if (strcmp(text, GNT_KEY_UP) == 0 || | |
174 strcmp(text, GNT_KEY_DOWN) == 0) | |
175 { | |
176 popup_dropdown(box); | |
177 return TRUE; | |
178 } | |
179 } | |
180 } | |
181 | |
182 return FALSE; | |
183 } | |
184 | |
185 static void | |
186 gnt_combo_box_destroy(GntWidget *widget) | |
187 { | |
188 gnt_widget_destroy(GNT_COMBO_BOX(widget)->dropdown->parent); | |
189 } | |
190 | |
191 static void | |
192 gnt_combo_box_lost_focus(GntWidget *widget) | |
193 { | |
194 GntComboBox *combo = GNT_COMBO_BOX(widget); | |
195 if (GNT_WIDGET_IS_FLAG_SET(combo->dropdown->parent, GNT_WIDGET_MAPPED)) | |
196 hide_popup(combo, FALSE); | |
197 widget_lost_focus(widget); | |
198 } | |
199 | |
200 static gboolean | |
201 gnt_combo_box_clicked(GntWidget *widget, GntMouseEvent event, int x, int y) | |
202 { | |
203 GntComboBox *box = GNT_COMBO_BOX(widget); | |
204 gboolean dshowing = GNT_WIDGET_IS_FLAG_SET(box->dropdown->parent, GNT_WIDGET_MAPPED); | |
205 | |
206 if (event == GNT_MOUSE_SCROLL_UP) { | |
207 if (dshowing) | |
208 gnt_widget_key_pressed(box->dropdown, GNT_KEY_UP); | |
209 } else if (event == GNT_MOUSE_SCROLL_DOWN) { | |
210 if (dshowing) | |
211 gnt_widget_key_pressed(box->dropdown, GNT_KEY_DOWN); | |
212 } else if (event == GNT_LEFT_MOUSE_DOWN) { | |
213 if (dshowing) { | |
214 hide_popup(box, TRUE); | |
215 } else { | |
216 popup_dropdown(GNT_COMBO_BOX(widget)); | |
217 } | |
218 } else | |
219 return FALSE; | |
220 return TRUE; | |
221 } | |
222 | |
223 static void | |
224 gnt_combo_box_size_changed(GntWidget *widget, int oldw, int oldh) | |
225 { | |
226 GntComboBox *box = GNT_COMBO_BOX(widget); | |
227 gnt_widget_set_size(box->dropdown, widget->priv.width - 1, box->dropdown->priv.height); | |
228 } | |
229 | |
230 static void | |
231 gnt_combo_box_class_init(GntComboBoxClass *klass) | |
232 { | |
233 parent_class = GNT_WIDGET_CLASS(klass); | |
234 | |
235 parent_class->destroy = gnt_combo_box_destroy; | |
236 parent_class->draw = gnt_combo_box_draw; | |
237 parent_class->map = gnt_combo_box_map; | |
238 parent_class->size_request = gnt_combo_box_size_request; | |
239 parent_class->key_pressed = gnt_combo_box_key_pressed; | |
240 parent_class->clicked = gnt_combo_box_clicked; | |
241 parent_class->size_changed = gnt_combo_box_size_changed; | |
242 | |
243 widget_lost_focus = parent_class->lost_focus; | |
244 parent_class->lost_focus = gnt_combo_box_lost_focus; | |
245 | |
246 signals[SIG_SELECTION_CHANGED] = | |
247 g_signal_new("selection-changed", | |
248 G_TYPE_FROM_CLASS(klass), | |
249 G_SIGNAL_RUN_LAST, | |
250 0, | |
251 NULL, NULL, | |
252 gnt_closure_marshal_VOID__POINTER_POINTER, | |
253 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); | |
254 | |
255 GNTDEBUG; | |
256 } | |
257 | |
258 static void | |
259 gnt_combo_box_init(GTypeInstance *instance, gpointer class) | |
260 { | |
261 GntWidget *box; | |
262 GntWidget *widget = GNT_WIDGET(instance); | |
263 GntComboBox *combo = GNT_COMBO_BOX(instance); | |
264 | |
265 GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance), | |
266 GNT_WIDGET_GROW_X | GNT_WIDGET_CAN_TAKE_FOCUS | GNT_WIDGET_NO_SHADOW); | |
267 combo->dropdown = gnt_tree_new(); | |
268 | |
269 box = gnt_box_new(FALSE, FALSE); | |
270 GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER | GNT_WIDGET_TRANSIENT); | |
271 gnt_box_set_pad(GNT_BOX(box), 0); | |
272 gnt_box_add_widget(GNT_BOX(box), combo->dropdown); | |
273 | |
274 widget->priv.minw = 4; | |
275 widget->priv.minh = 3; | |
276 GNTDEBUG; | |
277 } | |
278 | |
279 /****************************************************************************** | |
280 * GntComboBox API | |
281 *****************************************************************************/ | |
282 GType | |
283 gnt_combo_box_get_gtype(void) | |
284 { | |
285 static GType type = 0; | |
286 | |
287 if(type == 0) | |
288 { | |
289 static const GTypeInfo info = { | |
290 sizeof(GntComboBoxClass), | |
291 NULL, /* base_init */ | |
292 NULL, /* base_finalize */ | |
293 (GClassInitFunc)gnt_combo_box_class_init, | |
294 NULL, /* class_finalize */ | |
295 NULL, /* class_data */ | |
296 sizeof(GntComboBox), | |
297 0, /* n_preallocs */ | |
298 gnt_combo_box_init, /* instance_init */ | |
299 NULL /* value_table */ | |
300 }; | |
301 | |
302 type = g_type_register_static(GNT_TYPE_WIDGET, | |
303 "GntComboBox", | |
304 &info, 0); | |
305 } | |
306 | |
307 return type; | |
308 } | |
309 | |
310 GntWidget *gnt_combo_box_new() | |
311 { | |
312 GntWidget *widget = g_object_new(GNT_TYPE_COMBO_BOX, NULL); | |
313 | |
314 return widget; | |
315 } | |
316 | |
317 void gnt_combo_box_add_data(GntComboBox *box, gpointer key, const char *text) | |
318 { | |
319 gnt_tree_add_row_last(GNT_TREE(box->dropdown), key, | |
320 gnt_tree_create_row(GNT_TREE(box->dropdown), text), NULL); | |
321 if (box->selected == NULL) | |
322 set_selection(box, key); | |
323 } | |
324 | |
325 gpointer gnt_combo_box_get_selected_data(GntComboBox *box) | |
326 { | |
327 return box->selected; | |
328 } | |
329 | |
330 void gnt_combo_box_set_selected(GntComboBox *box, gpointer key) | |
331 { | |
332 set_selection(box, key); | |
333 } | |
334 | |
335 void gnt_combo_box_remove(GntComboBox *box, gpointer key) | |
336 { | |
337 gnt_tree_remove(GNT_TREE(box->dropdown), key); | |
338 if (box->selected == key) | |
339 set_selection(box, NULL); | |
340 } | |
341 | |
342 void gnt_combo_box_remove_all(GntComboBox *box) | |
343 { | |
344 gnt_tree_remove_all(GNT_TREE(box->dropdown)); | |
345 set_selection(box, NULL); | |
346 } | |
347 |