15818
|
1 #include "gntmenu.h"
|
|
2 #include "gntmenuitemcheck.h"
|
|
3
|
|
4 #include <string.h>
|
|
5
|
|
6 enum
|
|
7 {
|
|
8 SIGS = 1,
|
|
9 };
|
|
10
|
|
11 static GntTreeClass *parent_class = NULL;
|
|
12
|
|
13 static void (*org_draw)(GntWidget *wid);
|
|
14 static void (*org_destroy)(GntWidget *wid);
|
|
15 static void (*org_map)(GntWidget *wid);
|
|
16 static gboolean (*org_key_pressed)(GntWidget *w, const char *t);
|
|
17
|
|
18 static void
|
|
19 gnt_menu_draw(GntWidget *widget)
|
|
20 {
|
|
21 GntMenu *menu = GNT_MENU(widget);
|
|
22 GList *iter;
|
|
23 chtype type;
|
|
24 int i;
|
|
25
|
|
26 if (menu->type == GNT_MENU_TOPLEVEL) {
|
|
27 wbkgdset(widget->window, '\0' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT));
|
|
28 werase(widget->window);
|
|
29
|
|
30 for (i = 0, iter = menu->list; iter; iter = iter->next, i++) {
|
|
31 GntMenuItem *item = GNT_MENUITEM(iter->data);
|
|
32 type = ' ' | COLOR_PAIR(GNT_COLOR_HIGHLIGHT);
|
|
33 if (i == menu->selected)
|
|
34 type |= A_REVERSE;
|
|
35 item->priv.x = getcurx(widget->window) + widget->priv.x;
|
|
36 item->priv.y = getcury(widget->window) + widget->priv.y + 1;
|
|
37 wbkgdset(widget->window, type);
|
|
38 wprintw(widget->window, " %s ", item->text);
|
|
39 }
|
|
40 } else {
|
|
41 org_draw(widget);
|
|
42 }
|
|
43
|
|
44 GNTDEBUG;
|
|
45 }
|
|
46
|
|
47 static void
|
|
48 gnt_menu_size_request(GntWidget *widget)
|
|
49 {
|
|
50 GntMenu *menu = GNT_MENU(widget);
|
|
51
|
|
52 if (menu->type == GNT_MENU_TOPLEVEL) {
|
|
53 widget->priv.height = 1;
|
|
54 widget->priv.width = getmaxx(stdscr);
|
|
55 } else {
|
|
56 widget->priv.height = g_list_length(menu->list) + 2;
|
|
57 widget->priv.width = 25; /* XXX: */
|
|
58 }
|
|
59 }
|
|
60
|
|
61 static void
|
|
62 menu_tree_add(GntMenu *menu, GntMenuItem *item, GntMenuItem *parent)
|
|
63 {
|
|
64 if (GNT_IS_MENUITEM_CHECK(item)) {
|
|
65 gnt_tree_add_choice(GNT_TREE(menu), item,
|
|
66 gnt_tree_create_row(GNT_TREE(menu), item->text, " "), parent, NULL);
|
|
67 gnt_tree_set_choice(GNT_TREE(menu), item, gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item)));
|
|
68 } else
|
|
69 gnt_tree_add_row_last(GNT_TREE(menu), item,
|
|
70 gnt_tree_create_row(GNT_TREE(menu), item->text, item->submenu ? ">" : " "), parent);
|
|
71
|
|
72 if (0 && item->submenu) {
|
|
73 GntMenu *sub = GNT_MENU(item->submenu);
|
|
74 GList *iter;
|
|
75 for (iter = sub->list; iter; iter = iter->next) {
|
|
76 GntMenuItem *it = GNT_MENUITEM(iter->data);
|
|
77 menu_tree_add(menu, it, item);
|
|
78 }
|
|
79 }
|
|
80 }
|
|
81
|
|
82 static void
|
|
83 gnt_menu_map(GntWidget *widget)
|
|
84 {
|
|
85 GntMenu *menu = GNT_MENU(widget);
|
|
86
|
|
87 if (menu->type == GNT_MENU_TOPLEVEL) {
|
|
88 gnt_widget_size_request(widget);
|
|
89 } else {
|
|
90 /* Populate the tree */
|
|
91 GList *iter;
|
|
92 gnt_tree_remove_all(GNT_TREE(widget));
|
|
93 for (iter = menu->list; iter; iter = iter->next) {
|
|
94 GntMenuItem *item = GNT_MENUITEM(iter->data);
|
|
95 menu_tree_add(menu, item, NULL);
|
|
96 }
|
|
97 org_map(widget);
|
|
98 gnt_tree_adjust_columns(GNT_TREE(widget));
|
|
99 }
|
|
100 GNTDEBUG;
|
|
101 }
|
|
102
|
|
103 static void
|
|
104 menuitem_activate(GntMenu *menu, GntMenuItem *item)
|
|
105 {
|
|
106 if (item) {
|
|
107 if (item->submenu) {
|
|
108 GntMenu *sub = GNT_MENU(item->submenu);
|
|
109 menu->submenu = sub;
|
|
110 sub->type = GNT_MENU_POPUP; /* Submenus are *never* toplevel */
|
|
111 sub->parentmenu = menu;
|
|
112 if (menu->type != GNT_MENU_TOPLEVEL) {
|
|
113 GntWidget *widget = GNT_WIDGET(menu);
|
|
114 item->priv.x = widget->priv.x + widget->priv.width - 1;
|
|
115 item->priv.y = widget->priv.y + gnt_tree_get_selection_visible_line(GNT_TREE(menu));
|
|
116 }
|
|
117 gnt_widget_set_position(GNT_WIDGET(sub), item->priv.x, item->priv.y);
|
|
118 GNT_WIDGET_UNSET_FLAGS(GNT_WIDGET(sub), GNT_WIDGET_INVISIBLE);
|
|
119 gnt_widget_draw(GNT_WIDGET(sub));
|
|
120 } else if (item->callback) {
|
|
121 item->callback(item, item->callbackdata);
|
|
122 while (menu) {
|
|
123 gnt_widget_hide(GNT_WIDGET(menu));
|
|
124 menu = menu->parentmenu;
|
|
125 }
|
|
126 }
|
|
127 }
|
|
128 }
|
|
129
|
|
130 static gboolean
|
|
131 gnt_menu_key_pressed(GntWidget *widget, const char *text)
|
|
132 {
|
|
133 GntMenu *menu = GNT_MENU(widget);
|
|
134 int current = menu->selected;
|
|
135
|
|
136 if (menu->submenu) {
|
|
137 do menu = menu->submenu; while (menu->submenu);
|
|
138 return (gnt_widget_key_pressed(GNT_WIDGET(menu), text));
|
|
139 }
|
|
140
|
|
141 if (text[0] == 27 && text[1] == 0) {
|
|
142 /* Escape closes menu */
|
|
143 GntMenu *par = menu->parentmenu;
|
|
144 if (par != NULL) {
|
|
145 par->submenu = NULL;
|
|
146 gnt_widget_hide(widget);
|
|
147 } else
|
|
148 gnt_widget_hide(widget);
|
|
149 return TRUE;
|
|
150 }
|
|
151
|
|
152 if (menu->type == GNT_MENU_TOPLEVEL) {
|
|
153 if (strcmp(text, GNT_KEY_LEFT) == 0) {
|
|
154 menu->selected--;
|
|
155 if (menu->selected < 0)
|
|
156 menu->selected = g_list_length(menu->list) - 1;
|
|
157 } else if (strcmp(text, GNT_KEY_RIGHT) == 0) {
|
|
158 menu->selected++;
|
|
159 if (menu->selected >= g_list_length(menu->list))
|
|
160 menu->selected = 0;
|
|
161 } else if (strcmp(text, GNT_KEY_ENTER) == 0) {
|
|
162 gnt_widget_activate(widget);
|
|
163 }
|
|
164
|
|
165 if (current != menu->selected) {
|
|
166 gnt_widget_draw(widget);
|
|
167 return TRUE;
|
|
168 }
|
|
169 } else {
|
|
170 return org_key_pressed(widget, text);
|
|
171 }
|
|
172
|
|
173 return FALSE;
|
|
174 }
|
|
175
|
|
176 static void
|
|
177 gnt_menu_destroy(GntWidget *widget)
|
|
178 {
|
|
179 GntMenu *menu = GNT_MENU(widget);
|
|
180 g_list_foreach(menu->list, (GFunc)g_object_unref, NULL);
|
|
181 g_list_free(menu->list);
|
|
182 org_destroy(widget);
|
|
183 }
|
|
184
|
|
185 static void
|
|
186 gnt_menu_toggled(GntTree *tree, gpointer key)
|
|
187 {
|
|
188 GntMenuItem *item = GNT_MENUITEM(key);
|
|
189 GntMenu *menu = GNT_MENU(tree);
|
|
190 gboolean check = gnt_menuitem_check_get_checked(GNT_MENUITEM_CHECK(item));
|
|
191 gnt_menuitem_check_set_checked(GNT_MENUITEM_CHECK(item), !check);
|
|
192 if (item->callback)
|
|
193 item->callback(item, item->callbackdata);
|
|
194 while (menu) {
|
|
195 gnt_widget_hide(GNT_WIDGET(menu));
|
|
196 menu = menu->parentmenu;
|
|
197 }
|
|
198 }
|
|
199
|
|
200 static void
|
|
201 gnt_menu_activate(GntWidget *widget)
|
|
202 {
|
|
203 GntMenu *menu = GNT_MENU(widget);
|
|
204 GntMenuItem *item;
|
|
205
|
|
206 if (menu->type == GNT_MENU_TOPLEVEL) {
|
|
207 item = g_list_nth_data(menu->list, menu->selected);
|
|
208 } else {
|
|
209 item = gnt_tree_get_selection_data(GNT_TREE(menu));
|
|
210 }
|
|
211
|
|
212 if (item) {
|
|
213 if (GNT_IS_MENUITEM_CHECK(item))
|
|
214 gnt_menu_toggled(GNT_TREE(widget), item);
|
|
215 else
|
|
216 menuitem_activate(menu, item);
|
|
217 }
|
|
218 }
|
|
219
|
|
220 static void
|
|
221 gnt_menu_hide(GntWidget *widget)
|
|
222 {
|
|
223 GntMenu *menu = GNT_MENU(widget);
|
|
224 if (menu->parentmenu)
|
|
225 menu->parentmenu->submenu = NULL;
|
|
226 }
|
|
227
|
|
228 static void
|
|
229 gnt_menu_class_init(GntMenuClass *klass)
|
|
230 {
|
|
231 GntWidgetClass *wid_class = GNT_WIDGET_CLASS(klass);
|
|
232 parent_class = GNT_TREE_CLASS(klass);
|
|
233
|
|
234 org_destroy = wid_class->destroy;
|
|
235 org_map = wid_class->map;
|
|
236 org_draw = wid_class->draw;
|
|
237 org_key_pressed = wid_class->key_pressed;
|
|
238
|
|
239 wid_class->destroy = gnt_menu_destroy;
|
|
240 wid_class->draw = gnt_menu_draw;
|
|
241 wid_class->map = gnt_menu_map;
|
|
242 wid_class->size_request = gnt_menu_size_request;
|
|
243 wid_class->key_pressed = gnt_menu_key_pressed;
|
|
244 wid_class->activate = gnt_menu_activate;
|
|
245 wid_class->hide = gnt_menu_hide;
|
|
246
|
|
247 parent_class->toggled = gnt_menu_toggled;
|
|
248
|
|
249 GNTDEBUG;
|
|
250 }
|
|
251
|
|
252 static void
|
|
253 gnt_menu_init(GTypeInstance *instance, gpointer class)
|
|
254 {
|
|
255 GntWidget *widget = GNT_WIDGET(instance);
|
|
256 GNT_WIDGET_SET_FLAGS(widget, GNT_WIDGET_NO_SHADOW | GNT_WIDGET_NO_BORDER |
|
|
257 GNT_WIDGET_CAN_TAKE_FOCUS | GNT_WIDGET_TRANSIENT);
|
|
258 GNTDEBUG;
|
|
259 }
|
|
260
|
|
261 /******************************************************************************
|
|
262 * GntMenu API
|
|
263 *****************************************************************************/
|
|
264 GType
|
|
265 gnt_menu_get_gtype(void)
|
|
266 {
|
|
267 static GType type = 0;
|
|
268
|
|
269 if(type == 0)
|
|
270 {
|
|
271 static const GTypeInfo info = {
|
|
272 sizeof(GntMenuClass),
|
|
273 NULL, /* base_init */
|
|
274 NULL, /* base_finalize */
|
|
275 (GClassInitFunc)gnt_menu_class_init,
|
|
276 NULL, /* class_finalize */
|
|
277 NULL, /* class_data */
|
|
278 sizeof(GntMenu),
|
|
279 0, /* n_preallocs */
|
|
280 gnt_menu_init, /* instance_init */
|
|
281 NULL /* value_table */
|
|
282 };
|
|
283
|
|
284 type = g_type_register_static(GNT_TYPE_TREE,
|
|
285 "GntMenu",
|
|
286 &info, 0);
|
|
287 }
|
|
288
|
|
289 return type;
|
|
290 }
|
|
291
|
|
292 GntWidget *gnt_menu_new(GntMenuType type)
|
|
293 {
|
|
294 GntWidget *widget = g_object_new(GNT_TYPE_MENU, NULL);
|
|
295 GntMenu *menu = GNT_MENU(widget);
|
|
296 menu->list = NULL;
|
|
297 menu->selected = 0;
|
|
298 menu->type = type;
|
|
299
|
|
300 if (type == GNT_MENU_TOPLEVEL) {
|
|
301 widget->priv.x = 0;
|
|
302 widget->priv.y = 0;
|
|
303 } else {
|
|
304 GNT_TREE(widget)->show_separator = FALSE;
|
|
305 _gnt_tree_init_internals(GNT_TREE(widget), 2);
|
|
306 gnt_tree_set_col_width(GNT_TREE(widget), 1, 1); /* The second column is to indicate that it has a submenu */
|
|
307 GNT_WIDGET_UNSET_FLAGS(widget, GNT_WIDGET_NO_BORDER);
|
|
308 }
|
|
309
|
|
310 return widget;
|
|
311 }
|
|
312
|
|
313 void gnt_menu_add_item(GntMenu *menu, GntMenuItem *item)
|
|
314 {
|
|
315 menu->list = g_list_append(menu->list, item);
|
|
316 }
|
|
317
|