ui/gtk/menu.c

branch
newapi
changeset 175
2cb06c231057
parent 174
0358f1d9c506
child 253
087cc9216f28
equal deleted inserted replaced
174:0358f1d9c506 175:2cb06c231057
32 #include <stdarg.h> 32 #include <stdarg.h>
33 33
34 #include "menu.h" 34 #include "menu.h"
35 #include "toolkit.h" 35 #include "toolkit.h"
36 #include "../common/context.h" 36 #include "../common/context.h"
37 #include "../common/menu.h"
37 #include "../ui/properties.h" 38 #include "../ui/properties.h"
38 #include "../ui/window.h" 39 #include "../ui/window.h"
39 #include "container.h" 40 #include "container.h"
40 41
41 #include <cx/linked_list.h> 42 #include <cx/linked_list.h>
42 #include <cx/array_list.h> 43 #include <cx/array_list.h>
43 44
44 static UiMenu *menus_begin; 45
45 static UiMenu *menus_end; 46 static ui_menu_add_f createMenuItem[] = {
46 static CxList *current; 47 /* UI_MENU */ add_menu_widget,
47 48 /* UI_MENU_SUBMENU */ add_menu_widget,
48 static void add_menu(UiMenu *menu) { 49 /* UI_MENU_ITEM */ add_menuitem_widget,
49 cx_linked_list_add( 50 /* UI_MENU_STOCK_ITEM */ add_menuitem_st_widget,
50 (void**)&menus_begin, 51 /* UI_MENU_CHECK_ITEM */ add_checkitem_widget,
51 (void**)&menus_end, 52 /* UI_MENU_CHECK_ITEM_NV */ add_checkitemnv_widget,
52 offsetof(UiMenu, item.prev), 53 /* UI_MENU_ITEM_LIST */ add_menuitem_list_widget,
53 offsetof(UiMenu, item.next), 54 /* UI_MENU_ITEM_LIST_NV */ NULL, // TODO
54 menu); 55 /* UI_MENU_SEPARATOR */ add_menuseparator_widget
55 } 56 };
56
57 static void add_item(UiMenuItemI *item) {
58 UiMenu *menu = cxListAt(current, 0);
59 cx_linked_list_add(
60 (void**)&menu->items_begin,
61 (void**)&menu->items_end,
62 offsetof(UiMenu, item.prev),
63 offsetof(UiMenu, item.next),
64 item);
65 }
66
67 void ui_menu(char *label) {
68 if(!current) {
69 current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS);
70 } else {
71 // free current menu hierarchy
72 cxListClear(current);
73 }
74
75 // create menu
76 UiMenu *menu = malloc(sizeof(UiMenu));
77 menu->item.prev = NULL;
78 menu->item.next = NULL;
79 menu->item.add_to = (ui_menu_add_f)add_menu_widget;
80
81 menu->label = label;
82 menu->items_begin = NULL;
83 menu->items_end = NULL;
84 menu->parent = NULL;
85
86 add_menu(menu);
87 cxListAdd(current, menu);
88 }
89
90 void ui_submenu(char *label) {
91 UiMenu *menu = malloc(sizeof(UiMenu));
92 menu->item.prev = NULL;
93 menu->item.next = NULL;
94 menu->item.add_to = (ui_menu_add_f)add_menu_widget;
95
96 menu->label = label;
97 menu->items_begin = NULL;
98 menu->items_end = NULL;
99 menu->parent = NULL;
100
101 // add submenu to current menu
102 add_item((UiMenuItemI*)menu);
103
104 // set the submenu to current menu
105 cxListInsert(current, 0, menu);
106 }
107
108 void ui_submenu_end() {
109 if(current->size < 2) {
110 return;
111 }
112 cxListRemove(current, 0);
113 }
114
115 void ui_menuitem(char *label, ui_callback f, void *userdata) {
116 ui_menuitem_gr(label, f, userdata, -1);
117 }
118
119 void ui_menuitem_st(char *stockid, ui_callback f, void *userdata) {
120 ui_menuitem_stgr(stockid, f, userdata, -1);
121 }
122
123 void ui_menuitem_gr(char *label, ui_callback f, void *userdata, ...) {
124 if(!current) {
125 return;
126 }
127
128 UiMenuItem *item = malloc(sizeof(UiMenuItem));
129 item->item.prev = NULL;
130 item->item.next = NULL;
131 item->item.add_to = (ui_menu_add_f)add_menuitem_widget;
132
133 item->label = label;
134 item->userdata = userdata;
135 item->callback = f;
136 item->groups = NULL;
137
138 // add groups
139 va_list ap;
140 va_start(ap, userdata);
141 int group;
142 while((group = va_arg(ap, int)) != -1) {
143 if(!item->groups) {
144 item->groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 8);
145 }
146 cxListAdd(item->groups, &group);
147 }
148 va_end(ap);
149
150 add_item((UiMenuItemI*)item);
151 }
152
153 void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) {
154 if(!current) {
155 return;
156 }
157
158 UiStMenuItem *item = malloc(sizeof(UiStMenuItem));
159 item->item.prev = NULL;
160 item->item.next = NULL;
161 item->item.add_to = (ui_menu_add_f)add_menuitem_st_widget;
162
163 item->stockid = stockid;
164 item->userdata = userdata;
165 item->callback = f;
166 item->groups = NULL;
167
168 // add groups
169 va_list ap;
170 va_start(ap, userdata);
171 int group;
172 while((group = va_arg(ap, int)) != -1) {
173 if(!item->groups) {
174 item->groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 8);
175 }
176 cxListAdd(item->groups, &group);
177 }
178 va_end(ap);
179
180 add_item((UiMenuItemI*)item);
181 }
182
183 void ui_menuseparator() {
184 if(!current) {
185 return;
186 }
187
188 UiMenuItemI *item = malloc(sizeof(UiMenuItemI));
189 item->prev = NULL;
190 item->next = NULL;
191 item->add_to = (ui_menu_add_f)add_menuseparator_widget;
192
193 add_item((UiMenuItemI*)item);
194 }
195
196 void ui_checkitem(char *label, ui_callback f, void *userdata) {
197 if(!current) {
198 return;
199 }
200
201 UiCheckItem *item = malloc(sizeof(UiCheckItem));
202 item->item.prev = NULL;
203 item->item.next = NULL;
204 item->item.add_to = (ui_menu_add_f)add_checkitem_widget;
205 item->label = label;
206 item->callback = f;
207 item->userdata = userdata;
208
209 add_item((UiMenuItemI*)item);
210 }
211
212 void ui_checkitem_nv(char *label, char *vname) {
213 if(!current) {
214 return;
215 }
216
217 UiCheckItemNV *item = malloc(sizeof(UiCheckItemNV));
218 item->item.prev = NULL;
219 item->item.next = NULL;
220 item->item.add_to = (ui_menu_add_f)add_checkitemnv_widget;
221 item->varname = vname;
222 item->label = label;
223
224 add_item((UiMenuItemI*)item);
225 }
226
227 void ui_menuitem_list(UiList *items, ui_callback f, void *userdata) {
228 if(!current) {
229 return;
230 }
231
232 UiMenuItemList *item = malloc(sizeof(UiMenuItemList));
233 item->item.prev = NULL;
234 item->item.next = NULL;
235 item->item.add_to = (ui_menu_add_f)add_menuitem_list_widget;
236 item->callback = f;
237 item->userdata = userdata;
238 item->list = items;
239
240 add_item((UiMenuItemI*)item);
241 }
242 57
243 // private menu functions 58 // private menu functions
244 GtkWidget *ui_create_menubar(UiObject *obj) { 59 GtkWidget *ui_create_menubar(UiObject *obj) {
60 UiMenu *menus_begin = uic_get_menu_list();
245 if(menus_begin == NULL) { 61 if(menus_begin == NULL) {
246 return NULL; 62 return NULL;
247 } 63 }
248 64
249 GtkWidget *mb = gtk_menu_bar_new(); 65 GtkWidget *mb = gtk_menu_bar_new();
250 66
251 UiMenu *ls = menus_begin; 67 UiMenu *ls = menus_begin;
252 while(ls) { 68 while(ls) {
253 UiMenu *menu = ls; 69 UiMenu *menu = ls;
254 menu->item.add_to(mb, 0, &menu->item, obj); 70 add_menu_widget(mb, 0, &menu->item, obj);
255 71
256 ls = (UiMenu*)ls->item.next; 72 ls = (UiMenu*)ls->item.next;
257 } 73 }
258 74
259 return mb; 75 return mb;
267 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu_widget); 83 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu_widget);
268 84
269 UiMenuItemI *it = menu->items_begin; 85 UiMenuItemI *it = menu->items_begin;
270 int index = 0; 86 int index = 0;
271 while(it) { 87 while(it) {
272 it->add_to(menu_widget, index, it, obj); 88 createMenuItem[it->type](menu_widget, index, it, obj);
273 89
274 it = it->next; 90 it = it->next;
275 index++; 91 index++;
276 } 92 }
277 93

mercurial