Mercurial > pidgin
annotate finch/libgnt/gntcombobox.c @ 28233:e8eaf57f42da
Add a purple_account_get_name_for_display function (I'm not a huge fan of that
name but didn't want to use get_display_name as that means something else for
connections).
This wants to be used in places where we need to display an identifier for the
account to the user and honor the appropriate aliases/etc.
Refs #8391
author | Etan Reisner <pidgin@unreliablesource.net> |
---|---|
date | Sat, 15 Aug 2009 05:10:07 +0000 |
parents | c67d43408daa |
children | a18f421696dc |
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; | |
26439
c67d43408daa
Update hardware cursor correctly.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
22289
diff
changeset
|
76 |
15817 | 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)); |
26439
c67d43408daa
Update hardware cursor correctly.
Sadrul Habib Chowdhury <imadil@gmail.com>
parents:
22289
diff
changeset
|
97 wmove(widget->window, 1, 1); |
15817 | 98 |
99 g_free(text); | |
100 GNTDEBUG; | |
101 } | |
102 | |
103 static void | |
104 gnt_combo_box_size_request(GntWidget *widget) | |
105 { | |
106 if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED)) | |
107 { | |
108 GntWidget *dd = GNT_COMBO_BOX(widget)->dropdown; | |
109 gnt_widget_size_request(dd); | |
110 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
|
111 widget->priv.width = MAX(10, dd->priv.width + 2); |
15817 | 112 } |
113 } | |
114 | |
115 static void | |
116 gnt_combo_box_map(GntWidget *widget) | |
117 { | |
118 if (widget->priv.width == 0 || widget->priv.height == 0) | |
119 gnt_widget_size_request(widget); | |
120 GNTDEBUG; | |
121 } | |
122 | |
123 static void | |
124 popup_dropdown(GntComboBox *box) | |
125 { | |
126 GntWidget *widget = GNT_WIDGET(box); | |
127 GntWidget *parent = box->dropdown->parent; | |
128 int height = g_list_length(GNT_TREE(box->dropdown)->list); | |
129 int y = widget->priv.y + widget->priv.height - 1; | |
130 gnt_widget_set_size(box->dropdown, widget->priv.width, height + 2); | |
131 | |
132 if (y + height + 2 >= getmaxy(stdscr)) | |
133 y = widget->priv.y - height - 1; | |
134 gnt_widget_set_position(parent, widget->priv.x, y); | |
135 if (parent->window) | |
136 { | |
137 mvwin(parent->window, y, widget->priv.x); | |
138 wresize(parent->window, height+2, widget->priv.width); | |
139 } | |
140 parent->priv.width = widget->priv.width; | |
141 parent->priv.height = height + 2; | |
142 | |
143 GNT_WIDGET_UNSET_FLAGS(parent, GNT_WIDGET_INVISIBLE); | |
144 gnt_widget_draw(parent); | |
145 } | |
146 | |
147 static gboolean | |
148 gnt_combo_box_key_pressed(GntWidget *widget, const char *text) | |
149 { | |
150 GntComboBox *box = GNT_COMBO_BOX(widget); | |
151 if (GNT_WIDGET_IS_FLAG_SET(box->dropdown->parent, GNT_WIDGET_MAPPED)) | |
152 { | |
153 if (text[1] == 0) | |
154 { | |
155 switch (text[0]) | |
156 { | |
157 case '\r': | |
158 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
|
159 case '\n': |
15817 | 160 hide_popup(box, TRUE); |
161 return TRUE; | |
162 case 27: | |
163 hide_popup(box, FALSE); | |
164 return TRUE; | |
165 } | |
166 } | |
167 if (gnt_widget_key_pressed(box->dropdown, text)) | |
168 return TRUE; | |
169 } | |
170 else | |
171 { | |
172 if (text[0] == 27) | |
173 { | |
174 if (strcmp(text, GNT_KEY_UP) == 0 || | |
175 strcmp(text, GNT_KEY_DOWN) == 0) | |
176 { | |
177 popup_dropdown(box); | |
178 return TRUE; | |
179 } | |
180 } | |
181 } | |
182 | |
183 return FALSE; | |
184 } | |
185 | |
186 static void | |
187 gnt_combo_box_destroy(GntWidget *widget) | |
188 { | |
189 gnt_widget_destroy(GNT_COMBO_BOX(widget)->dropdown->parent); | |
190 } | |
191 | |
192 static void | |
193 gnt_combo_box_lost_focus(GntWidget *widget) | |
194 { | |
195 GntComboBox *combo = GNT_COMBO_BOX(widget); | |
196 if (GNT_WIDGET_IS_FLAG_SET(combo->dropdown->parent, GNT_WIDGET_MAPPED)) | |
197 hide_popup(combo, FALSE); | |
198 widget_lost_focus(widget); | |
199 } | |
200 | |
201 static gboolean | |
202 gnt_combo_box_clicked(GntWidget *widget, GntMouseEvent event, int x, int y) | |
203 { | |
204 GntComboBox *box = GNT_COMBO_BOX(widget); | |
205 gboolean dshowing = GNT_WIDGET_IS_FLAG_SET(box->dropdown->parent, GNT_WIDGET_MAPPED); | |
206 | |
207 if (event == GNT_MOUSE_SCROLL_UP) { | |
208 if (dshowing) | |
209 gnt_widget_key_pressed(box->dropdown, GNT_KEY_UP); | |
210 } else if (event == GNT_MOUSE_SCROLL_DOWN) { | |
211 if (dshowing) | |
212 gnt_widget_key_pressed(box->dropdown, GNT_KEY_DOWN); | |
213 } else if (event == GNT_LEFT_MOUSE_DOWN) { | |
214 if (dshowing) { | |
215 hide_popup(box, TRUE); | |
216 } else { | |
217 popup_dropdown(GNT_COMBO_BOX(widget)); | |
218 } | |
219 } else | |
220 return FALSE; | |
221 return TRUE; | |
222 } | |
223 | |
224 static void | |
225 gnt_combo_box_size_changed(GntWidget *widget, int oldw, int oldh) | |
226 { | |
227 GntComboBox *box = GNT_COMBO_BOX(widget); | |
228 gnt_widget_set_size(box->dropdown, widget->priv.width - 1, box->dropdown->priv.height); | |
229 } | |
230 | |
231 static void | |
232 gnt_combo_box_class_init(GntComboBoxClass *klass) | |
233 { | |
234 parent_class = GNT_WIDGET_CLASS(klass); | |
235 | |
236 parent_class->destroy = gnt_combo_box_destroy; | |
237 parent_class->draw = gnt_combo_box_draw; | |
238 parent_class->map = gnt_combo_box_map; | |
239 parent_class->size_request = gnt_combo_box_size_request; | |
240 parent_class->key_pressed = gnt_combo_box_key_pressed; | |
241 parent_class->clicked = gnt_combo_box_clicked; | |
242 parent_class->size_changed = gnt_combo_box_size_changed; | |
243 | |
244 widget_lost_focus = parent_class->lost_focus; | |
245 parent_class->lost_focus = gnt_combo_box_lost_focus; | |
246 | |
247 signals[SIG_SELECTION_CHANGED] = | |
248 g_signal_new("selection-changed", | |
249 G_TYPE_FROM_CLASS(klass), | |
250 G_SIGNAL_RUN_LAST, | |
251 0, | |
252 NULL, NULL, | |
253 gnt_closure_marshal_VOID__POINTER_POINTER, | |
254 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); | |
255 | |
256 GNTDEBUG; | |
257 } | |
258 | |
259 static void | |
260 gnt_combo_box_init(GTypeInstance *instance, gpointer class) | |
261 { | |
262 GntWidget *box; | |
263 GntWidget *widget = GNT_WIDGET(instance); | |
264 GntComboBox *combo = GNT_COMBO_BOX(instance); | |
265 | |
266 GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance), | |
267 GNT_WIDGET_GROW_X | GNT_WIDGET_CAN_TAKE_FOCUS | GNT_WIDGET_NO_SHADOW); | |
268 combo->dropdown = gnt_tree_new(); | |
269 | |
270 box = gnt_box_new(FALSE, FALSE); | |
271 GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER | GNT_WIDGET_TRANSIENT); | |
272 gnt_box_set_pad(GNT_BOX(box), 0); | |
273 gnt_box_add_widget(GNT_BOX(box), combo->dropdown); | |
274 | |
275 widget->priv.minw = 4; | |
276 widget->priv.minh = 3; | |
277 GNTDEBUG; | |
278 } | |
279 | |
280 /****************************************************************************** | |
281 * GntComboBox API | |
282 *****************************************************************************/ | |
283 GType | |
284 gnt_combo_box_get_gtype(void) | |
285 { | |
286 static GType type = 0; | |
287 | |
288 if(type == 0) | |
289 { | |
290 static const GTypeInfo info = { | |
291 sizeof(GntComboBoxClass), | |
292 NULL, /* base_init */ | |
293 NULL, /* base_finalize */ | |
294 (GClassInitFunc)gnt_combo_box_class_init, | |
295 NULL, /* class_finalize */ | |
296 NULL, /* class_data */ | |
297 sizeof(GntComboBox), | |
298 0, /* n_preallocs */ | |
299 gnt_combo_box_init, /* instance_init */ | |
300 NULL /* value_table */ | |
301 }; | |
302 | |
303 type = g_type_register_static(GNT_TYPE_WIDGET, | |
304 "GntComboBox", | |
305 &info, 0); | |
306 } | |
307 | |
308 return type; | |
309 } | |
310 | |
311 GntWidget *gnt_combo_box_new() | |
312 { | |
313 GntWidget *widget = g_object_new(GNT_TYPE_COMBO_BOX, NULL); | |
314 | |
315 return widget; | |
316 } | |
317 | |
318 void gnt_combo_box_add_data(GntComboBox *box, gpointer key, const char *text) | |
319 { | |
320 gnt_tree_add_row_last(GNT_TREE(box->dropdown), key, | |
321 gnt_tree_create_row(GNT_TREE(box->dropdown), text), NULL); | |
322 if (box->selected == NULL) | |
323 set_selection(box, key); | |
324 } | |
325 | |
326 gpointer gnt_combo_box_get_selected_data(GntComboBox *box) | |
327 { | |
328 return box->selected; | |
329 } | |
330 | |
331 void gnt_combo_box_set_selected(GntComboBox *box, gpointer key) | |
332 { | |
333 set_selection(box, key); | |
334 } | |
335 | |
336 void gnt_combo_box_remove(GntComboBox *box, gpointer key) | |
337 { | |
338 gnt_tree_remove(GNT_TREE(box->dropdown), key); | |
339 if (box->selected == key) | |
340 set_selection(box, NULL); | |
341 } | |
342 | |
343 void gnt_combo_box_remove_all(GntComboBox *box) | |
344 { | |
345 gnt_tree_remove_all(GNT_TREE(box->dropdown)); | |
346 set_selection(box, NULL); | |
347 } | |
348 |