Mercurial > pidgin
comparison finch/libgnt/gntcombobox.c @ 15817:0e3a8505ebbe
renamed gaim-text to finch
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sun, 18 Mar 2007 19:38:15 +0000 |
parents | |
children | 8410511f4dbb |
comparison
equal
deleted
inserted
replaced
15816:317e7613e581 | 15817:0e3a8505ebbe |
---|---|
1 #include "gntbox.h" | |
2 #include "gntcombobox.h" | |
3 #include "gnttree.h" | |
4 #include "gntmarshal.h" | |
5 #include "gntutils.h" | |
6 | |
7 #include <string.h> | |
8 | |
9 enum | |
10 { | |
11 SIG_SELECTION_CHANGED, | |
12 SIGS, | |
13 }; | |
14 | |
15 static GntWidgetClass *parent_class = NULL; | |
16 static guint signals[SIGS] = { 0 }; | |
17 static void (*widget_lost_focus)(GntWidget *widget); | |
18 | |
19 static void | |
20 set_selection(GntComboBox *box, gpointer key) | |
21 { | |
22 if (box->selected != key) | |
23 { | |
24 /* XXX: make sure the key actually does exist */ | |
25 gpointer old = box->selected; | |
26 box->selected = key; | |
27 if (GNT_WIDGET(box)->window) | |
28 gnt_widget_draw(GNT_WIDGET(box)); | |
29 if (box->dropdown) | |
30 gnt_tree_set_selected(GNT_TREE(box->dropdown), key); | |
31 g_signal_emit(box, signals[SIG_SELECTION_CHANGED], 0, old, key); | |
32 } | |
33 } | |
34 | |
35 static void | |
36 hide_popup(GntComboBox *box, gboolean set) | |
37 { | |
38 gnt_widget_set_size(box->dropdown, | |
39 box->dropdown->priv.width - 1, box->dropdown->priv.height); | |
40 if (set) | |
41 set_selection(box, gnt_tree_get_selection_data(GNT_TREE(box->dropdown))); | |
42 else | |
43 gnt_tree_set_selected(GNT_TREE(box->dropdown), box->selected); | |
44 gnt_widget_hide(box->dropdown->parent); | |
45 } | |
46 | |
47 static void | |
48 gnt_combo_box_draw(GntWidget *widget) | |
49 { | |
50 GntComboBox *box = GNT_COMBO_BOX(widget); | |
51 char *text = NULL, *s; | |
52 GntColorType type; | |
53 int len; | |
54 | |
55 if (box->dropdown && box->selected) | |
56 text = gnt_tree_get_selection_text(GNT_TREE(box->dropdown)); | |
57 | |
58 if (text == NULL) | |
59 text = g_strdup(""); | |
60 | |
61 if (gnt_widget_has_focus(widget)) | |
62 type = GNT_COLOR_HIGHLIGHT; | |
63 else | |
64 type = GNT_COLOR_NORMAL; | |
65 | |
66 wbkgdset(widget->window, '\0' | COLOR_PAIR(type)); | |
67 | |
68 s = (char*)gnt_util_onscreen_width_to_pointer(text, widget->priv.width - 4, &len); | |
69 *s = '\0'; | |
70 | |
71 mvwaddstr(widget->window, 1, 1, text); | |
72 whline(widget->window, ' ' | COLOR_PAIR(type), widget->priv.width - 4 - len); | |
73 mvwaddch(widget->window, 1, widget->priv.width - 3, ACS_VLINE | COLOR_PAIR(GNT_COLOR_NORMAL)); | |
74 mvwaddch(widget->window, 1, widget->priv.width - 2, ACS_DARROW | COLOR_PAIR(GNT_COLOR_NORMAL)); | |
75 | |
76 g_free(text); | |
77 GNTDEBUG; | |
78 } | |
79 | |
80 static void | |
81 gnt_combo_box_size_request(GntWidget *widget) | |
82 { | |
83 if (!GNT_WIDGET_IS_FLAG_SET(widget, GNT_WIDGET_MAPPED)) | |
84 { | |
85 GntWidget *dd = GNT_COMBO_BOX(widget)->dropdown; | |
86 gnt_widget_size_request(dd); | |
87 widget->priv.height = 3; /* For now, a combobox will have border */ | |
88 widget->priv.width = MAX(10, dd->priv.width + 4); | |
89 } | |
90 } | |
91 | |
92 static void | |
93 gnt_combo_box_map(GntWidget *widget) | |
94 { | |
95 if (widget->priv.width == 0 || widget->priv.height == 0) | |
96 gnt_widget_size_request(widget); | |
97 GNTDEBUG; | |
98 } | |
99 | |
100 static void | |
101 popup_dropdown(GntComboBox *box) | |
102 { | |
103 GntWidget *widget = GNT_WIDGET(box); | |
104 GntWidget *parent = box->dropdown->parent; | |
105 int height = g_list_length(GNT_TREE(box->dropdown)->list); | |
106 int y = widget->priv.y + widget->priv.height - 1; | |
107 gnt_widget_set_size(box->dropdown, widget->priv.width, height + 2); | |
108 | |
109 if (y + height + 2 >= getmaxy(stdscr)) | |
110 y = widget->priv.y - height - 1; | |
111 gnt_widget_set_position(parent, widget->priv.x, y); | |
112 if (parent->window) | |
113 { | |
114 mvwin(parent->window, y, widget->priv.x); | |
115 wresize(parent->window, height+2, widget->priv.width); | |
116 } | |
117 parent->priv.width = widget->priv.width; | |
118 parent->priv.height = height + 2; | |
119 | |
120 GNT_WIDGET_UNSET_FLAGS(parent, GNT_WIDGET_INVISIBLE); | |
121 gnt_widget_draw(parent); | |
122 } | |
123 | |
124 static gboolean | |
125 gnt_combo_box_key_pressed(GntWidget *widget, const char *text) | |
126 { | |
127 GntComboBox *box = GNT_COMBO_BOX(widget); | |
128 if (GNT_WIDGET_IS_FLAG_SET(box->dropdown->parent, GNT_WIDGET_MAPPED)) | |
129 { | |
130 if (text[1] == 0) | |
131 { | |
132 switch (text[0]) | |
133 { | |
134 case '\r': | |
135 case '\t': | |
136 hide_popup(box, TRUE); | |
137 return TRUE; | |
138 case 27: | |
139 hide_popup(box, FALSE); | |
140 return TRUE; | |
141 } | |
142 } | |
143 if (gnt_widget_key_pressed(box->dropdown, text)) | |
144 return TRUE; | |
145 } | |
146 else | |
147 { | |
148 if (text[0] == 27) | |
149 { | |
150 if (strcmp(text, GNT_KEY_UP) == 0 || | |
151 strcmp(text, GNT_KEY_DOWN) == 0) | |
152 { | |
153 popup_dropdown(box); | |
154 return TRUE; | |
155 } | |
156 } | |
157 } | |
158 | |
159 return FALSE; | |
160 } | |
161 | |
162 static void | |
163 gnt_combo_box_destroy(GntWidget *widget) | |
164 { | |
165 gnt_widget_destroy(GNT_COMBO_BOX(widget)->dropdown->parent); | |
166 } | |
167 | |
168 static void | |
169 gnt_combo_box_lost_focus(GntWidget *widget) | |
170 { | |
171 GntComboBox *combo = GNT_COMBO_BOX(widget); | |
172 if (GNT_WIDGET_IS_FLAG_SET(combo->dropdown->parent, GNT_WIDGET_MAPPED)) | |
173 hide_popup(combo, FALSE); | |
174 widget_lost_focus(widget); | |
175 } | |
176 | |
177 static gboolean | |
178 gnt_combo_box_clicked(GntWidget *widget, GntMouseEvent event, int x, int y) | |
179 { | |
180 GntComboBox *box = GNT_COMBO_BOX(widget); | |
181 gboolean dshowing = GNT_WIDGET_IS_FLAG_SET(box->dropdown->parent, GNT_WIDGET_MAPPED); | |
182 | |
183 if (event == GNT_MOUSE_SCROLL_UP) { | |
184 if (dshowing) | |
185 gnt_widget_key_pressed(box->dropdown, GNT_KEY_UP); | |
186 } else if (event == GNT_MOUSE_SCROLL_DOWN) { | |
187 if (dshowing) | |
188 gnt_widget_key_pressed(box->dropdown, GNT_KEY_DOWN); | |
189 } else if (event == GNT_LEFT_MOUSE_DOWN) { | |
190 if (dshowing) { | |
191 hide_popup(box, TRUE); | |
192 } else { | |
193 popup_dropdown(GNT_COMBO_BOX(widget)); | |
194 } | |
195 } else | |
196 return FALSE; | |
197 return TRUE; | |
198 } | |
199 | |
200 static void | |
201 gnt_combo_box_size_changed(GntWidget *widget, int oldw, int oldh) | |
202 { | |
203 GntComboBox *box = GNT_COMBO_BOX(widget); | |
204 gnt_widget_set_size(box->dropdown, widget->priv.width - 1, box->dropdown->priv.height); | |
205 } | |
206 | |
207 static void | |
208 gnt_combo_box_class_init(GntComboBoxClass *klass) | |
209 { | |
210 parent_class = GNT_WIDGET_CLASS(klass); | |
211 | |
212 parent_class->destroy = gnt_combo_box_destroy; | |
213 parent_class->draw = gnt_combo_box_draw; | |
214 parent_class->map = gnt_combo_box_map; | |
215 parent_class->size_request = gnt_combo_box_size_request; | |
216 parent_class->key_pressed = gnt_combo_box_key_pressed; | |
217 parent_class->clicked = gnt_combo_box_clicked; | |
218 parent_class->size_changed = gnt_combo_box_size_changed; | |
219 | |
220 widget_lost_focus = parent_class->lost_focus; | |
221 parent_class->lost_focus = gnt_combo_box_lost_focus; | |
222 | |
223 signals[SIG_SELECTION_CHANGED] = | |
224 g_signal_new("selection-changed", | |
225 G_TYPE_FROM_CLASS(klass), | |
226 G_SIGNAL_RUN_LAST, | |
227 0, | |
228 NULL, NULL, | |
229 gnt_closure_marshal_VOID__POINTER_POINTER, | |
230 G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER); | |
231 | |
232 GNTDEBUG; | |
233 } | |
234 | |
235 static void | |
236 gnt_combo_box_init(GTypeInstance *instance, gpointer class) | |
237 { | |
238 GntWidget *box; | |
239 GntWidget *widget = GNT_WIDGET(instance); | |
240 GntComboBox *combo = GNT_COMBO_BOX(instance); | |
241 | |
242 GNT_WIDGET_SET_FLAGS(GNT_WIDGET(instance), | |
243 GNT_WIDGET_GROW_X | GNT_WIDGET_CAN_TAKE_FOCUS | GNT_WIDGET_NO_SHADOW); | |
244 combo->dropdown = gnt_tree_new(); | |
245 | |
246 box = gnt_box_new(FALSE, FALSE); | |
247 GNT_WIDGET_SET_FLAGS(box, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER | GNT_WIDGET_TRANSIENT); | |
248 gnt_box_set_pad(GNT_BOX(box), 0); | |
249 gnt_box_add_widget(GNT_BOX(box), combo->dropdown); | |
250 | |
251 widget->priv.minw = 4; | |
252 widget->priv.minh = 3; | |
253 GNTDEBUG; | |
254 } | |
255 | |
256 /****************************************************************************** | |
257 * GntComboBox API | |
258 *****************************************************************************/ | |
259 GType | |
260 gnt_combo_box_get_gtype(void) | |
261 { | |
262 static GType type = 0; | |
263 | |
264 if(type == 0) | |
265 { | |
266 static const GTypeInfo info = { | |
267 sizeof(GntComboBoxClass), | |
268 NULL, /* base_init */ | |
269 NULL, /* base_finalize */ | |
270 (GClassInitFunc)gnt_combo_box_class_init, | |
271 NULL, /* class_finalize */ | |
272 NULL, /* class_data */ | |
273 sizeof(GntComboBox), | |
274 0, /* n_preallocs */ | |
275 gnt_combo_box_init, /* instance_init */ | |
276 NULL /* value_table */ | |
277 }; | |
278 | |
279 type = g_type_register_static(GNT_TYPE_WIDGET, | |
280 "GntComboBox", | |
281 &info, 0); | |
282 } | |
283 | |
284 return type; | |
285 } | |
286 | |
287 GntWidget *gnt_combo_box_new() | |
288 { | |
289 GntWidget *widget = g_object_new(GNT_TYPE_COMBO_BOX, NULL); | |
290 | |
291 return widget; | |
292 } | |
293 | |
294 void gnt_combo_box_add_data(GntComboBox *box, gpointer key, const char *text) | |
295 { | |
296 gnt_tree_add_row_last(GNT_TREE(box->dropdown), key, | |
297 gnt_tree_create_row(GNT_TREE(box->dropdown), text), NULL); | |
298 if (box->selected == NULL) | |
299 set_selection(box, key); | |
300 } | |
301 | |
302 gpointer gnt_combo_box_get_selected_data(GntComboBox *box) | |
303 { | |
304 return box->selected; | |
305 } | |
306 | |
307 void gnt_combo_box_set_selected(GntComboBox *box, gpointer key) | |
308 { | |
309 set_selection(box, key); | |
310 } | |
311 | |
312 void gnt_combo_box_remove(GntComboBox *box, gpointer key) | |
313 { | |
314 gnt_tree_remove(GNT_TREE(box->dropdown), key); | |
315 if (box->selected == key) | |
316 set_selection(box, NULL); | |
317 } | |
318 | |
319 void gnt_combo_box_remove_all(GntComboBox *box) | |
320 { | |
321 gnt_tree_remove_all(GNT_TREE(box->dropdown)); | |
322 set_selection(box, NULL); | |
323 } | |
324 |