36 #include "../common/context.h" |
36 #include "../common/context.h" |
37 #include "../ui/properties.h" |
37 #include "../ui/properties.h" |
38 #include "../ui/window.h" |
38 #include "../ui/window.h" |
39 #include "container.h" |
39 #include "container.h" |
40 |
40 |
41 static UcxList *menus; |
41 #include <cx/linked_list.h> |
42 static UcxList *current; |
42 #include <cx/array_list.h> |
|
43 |
|
44 static UiMenu *menus_begin; |
|
45 static UiMenu *menus_end; |
|
46 static CxList *current; |
|
47 |
|
48 static void add_menu(UiMenu *menu) { |
|
49 cx_linked_list_add( |
|
50 (void**)&menus_begin, |
|
51 (void**)&menus_end, |
|
52 offsetof(UiMenu, item.prev), |
|
53 offsetof(UiMenu, item.next), |
|
54 menu); |
|
55 } |
|
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 } |
43 |
66 |
44 void ui_menu(char *label) { |
67 void ui_menu(char *label) { |
45 // free current menu hierarchy |
68 if(!current) { |
46 ucx_list_free(current); |
69 current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); |
|
70 } else { |
|
71 // free current menu hierarchy |
|
72 cxListClear(current); |
|
73 } |
47 |
74 |
48 // create menu |
75 // create menu |
49 UiMenu *menu = malloc(sizeof(UiMenu)); |
76 UiMenu *menu = malloc(sizeof(UiMenu)); |
|
77 menu->item.prev = NULL; |
|
78 menu->item.next = NULL; |
50 menu->item.add_to = (ui_menu_add_f)add_menu_widget; |
79 menu->item.add_to = (ui_menu_add_f)add_menu_widget; |
51 |
80 |
52 menu->label = label; |
81 menu->label = label; |
53 menu->items = NULL; |
82 menu->items_begin = NULL; |
54 menu->parent = NULL; |
83 menu->items_end = NULL; |
55 |
84 menu->parent = NULL; |
56 current = ucx_list_prepend(NULL, menu); |
85 |
57 menus = ucx_list_append(menus, menu); |
86 add_menu(menu); |
58 |
87 cxListAdd(current, menu); |
59 } |
88 } |
60 |
89 |
61 void ui_submenu(char *label) { |
90 void ui_submenu(char *label) { |
62 UiMenu *menu = malloc(sizeof(UiMenu)); |
91 UiMenu *menu = malloc(sizeof(UiMenu)); |
|
92 menu->item.prev = NULL; |
|
93 menu->item.next = NULL; |
63 menu->item.add_to = (ui_menu_add_f)add_menu_widget; |
94 menu->item.add_to = (ui_menu_add_f)add_menu_widget; |
64 |
95 |
65 menu->label = label; |
96 menu->label = label; |
66 menu->items = NULL; |
97 menu->items_begin = NULL; |
67 menu->parent = NULL; |
98 menu->items_end = NULL; |
|
99 menu->parent = NULL; |
68 |
100 |
69 // add submenu to current menu |
101 // add submenu to current menu |
70 UiMenu *cm = current->data; |
102 add_item((UiMenuItemI*)menu); |
71 cm->items = ucx_list_append(cm->items, menu); |
|
72 |
103 |
73 // set the submenu to current menu |
104 // set the submenu to current menu |
74 current = ucx_list_prepend(current, menu); |
105 cxListInsert(current, 0, menu); |
75 } |
106 } |
76 |
107 |
77 void ui_submenu_end() { |
108 void ui_submenu_end() { |
78 if(ucx_list_size(current) < 2) { |
109 if(current->size < 2) { |
79 return; |
110 return; |
80 } |
111 } |
81 current = ucx_list_remove(current, current); |
112 cxListRemove(current, 0); |
82 //UcxList *c = current; |
|
83 } |
113 } |
84 |
114 |
85 void ui_menuitem(char *label, ui_callback f, void *userdata) { |
115 void ui_menuitem(char *label, ui_callback f, void *userdata) { |
86 ui_menuitem_gr(label, f, userdata, -1); |
116 ui_menuitem_gr(label, f, userdata, -1); |
87 } |
117 } |
106 // add groups |
138 // add groups |
107 va_list ap; |
139 va_list ap; |
108 va_start(ap, userdata); |
140 va_start(ap, userdata); |
109 int group; |
141 int group; |
110 while((group = va_arg(ap, int)) != -1) { |
142 while((group = va_arg(ap, int)) != -1) { |
111 item->groups = ucx_list_append(item->groups, (void*)(intptr_t)group); |
143 if(!item->groups) { |
|
144 item->groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 8); |
|
145 } |
|
146 cxListAdd(item->groups, &group); |
112 } |
147 } |
113 va_end(ap); |
148 va_end(ap); |
114 |
149 |
115 UiMenu *cm = current->data; |
150 add_item((UiMenuItemI*)item); |
116 cm->items = ucx_list_append(cm->items, item); |
|
117 } |
151 } |
118 |
152 |
119 void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) { |
153 void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) { |
120 if(!current) { |
154 if(!current) { |
121 return; |
155 return; |
122 } |
156 } |
123 |
157 |
124 UiStMenuItem *item = malloc(sizeof(UiStMenuItem)); |
158 UiStMenuItem *item = malloc(sizeof(UiStMenuItem)); |
|
159 item->item.prev = NULL; |
|
160 item->item.next = NULL; |
125 item->item.add_to = (ui_menu_add_f)add_menuitem_st_widget; |
161 item->item.add_to = (ui_menu_add_f)add_menuitem_st_widget; |
126 |
162 |
127 item->stockid = stockid; |
163 item->stockid = stockid; |
128 item->userdata = userdata; |
164 item->userdata = userdata; |
129 item->callback = f; |
165 item->callback = f; |
132 // add groups |
168 // add groups |
133 va_list ap; |
169 va_list ap; |
134 va_start(ap, userdata); |
170 va_start(ap, userdata); |
135 int group; |
171 int group; |
136 while((group = va_arg(ap, int)) != -1) { |
172 while((group = va_arg(ap, int)) != -1) { |
137 item->groups = ucx_list_append(item->groups, (void*)(intptr_t)group); |
173 if(!item->groups) { |
|
174 item->groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 8); |
|
175 } |
|
176 cxListAdd(item->groups, &group); |
138 } |
177 } |
139 va_end(ap); |
178 va_end(ap); |
140 |
179 |
141 UiMenu *cm = current->data; |
180 add_item((UiMenuItemI*)item); |
142 cm->items = ucx_list_append(cm->items, item); |
|
143 } |
181 } |
144 |
182 |
145 void ui_menuseparator() { |
183 void ui_menuseparator() { |
146 if(!current) { |
184 if(!current) { |
147 return; |
185 return; |
148 } |
186 } |
149 |
187 |
150 UiMenuItemI *item = malloc(sizeof(UiMenuItemI)); |
188 UiMenuItemI *item = malloc(sizeof(UiMenuItemI)); |
|
189 item->prev = NULL; |
|
190 item->next = NULL; |
151 item->add_to = (ui_menu_add_f)add_menuseparator_widget; |
191 item->add_to = (ui_menu_add_f)add_menuseparator_widget; |
152 |
192 |
153 UiMenu *cm = current->data; |
193 add_item((UiMenuItemI*)item); |
154 cm->items = ucx_list_append(cm->items, item); |
|
155 } |
194 } |
156 |
195 |
157 void ui_checkitem(char *label, ui_callback f, void *userdata) { |
196 void ui_checkitem(char *label, ui_callback f, void *userdata) { |
158 if(!current) { |
197 if(!current) { |
159 return; |
198 return; |
160 } |
199 } |
161 |
200 |
162 UiCheckItem *item = malloc(sizeof(UiCheckItem)); |
201 UiCheckItem *item = malloc(sizeof(UiCheckItem)); |
|
202 item->item.prev = NULL; |
|
203 item->item.next = NULL; |
163 item->item.add_to = (ui_menu_add_f)add_checkitem_widget; |
204 item->item.add_to = (ui_menu_add_f)add_checkitem_widget; |
164 item->label = label; |
205 item->label = label; |
165 item->callback = f; |
206 item->callback = f; |
166 item->userdata = userdata; |
207 item->userdata = userdata; |
167 |
208 |
168 UiMenu *cm = current->data; |
209 add_item((UiMenuItemI*)item); |
169 cm->items = ucx_list_append(cm->items, item); |
|
170 } |
210 } |
171 |
211 |
172 void ui_checkitem_nv(char *label, char *vname) { |
212 void ui_checkitem_nv(char *label, char *vname) { |
173 if(!current) { |
213 if(!current) { |
174 return; |
214 return; |
175 } |
215 } |
176 |
216 |
177 UiCheckItemNV *item = malloc(sizeof(UiCheckItemNV)); |
217 UiCheckItemNV *item = malloc(sizeof(UiCheckItemNV)); |
|
218 item->item.prev = NULL; |
|
219 item->item.next = NULL; |
178 item->item.add_to = (ui_menu_add_f)add_checkitemnv_widget; |
220 item->item.add_to = (ui_menu_add_f)add_checkitemnv_widget; |
179 item->varname = vname; |
221 item->varname = vname; |
180 item->label = label; |
222 item->label = label; |
181 |
223 |
182 UiMenu *cm = current->data; |
224 add_item((UiMenuItemI*)item); |
183 cm->items = ucx_list_append(cm->items, item); |
|
184 } |
225 } |
185 |
226 |
186 void ui_menuitem_list(UiList *items, ui_callback f, void *userdata) { |
227 void ui_menuitem_list(UiList *items, ui_callback f, void *userdata) { |
187 if(!current) { |
228 if(!current) { |
188 return; |
229 return; |
189 } |
230 } |
190 |
231 |
191 UiMenuItemList *item = malloc(sizeof(UiMenuItemList)); |
232 UiMenuItemList *item = malloc(sizeof(UiMenuItemList)); |
|
233 item->item.prev = NULL; |
|
234 item->item.next = NULL; |
192 item->item.add_to = (ui_menu_add_f)add_menuitem_list_widget; |
235 item->item.add_to = (ui_menu_add_f)add_menuitem_list_widget; |
193 item->callback = f; |
236 item->callback = f; |
194 item->userdata = userdata; |
237 item->userdata = userdata; |
195 item->list = items; |
238 item->list = items; |
196 |
239 |
197 UiMenu *cm = current->data; |
240 add_item((UiMenuItemI*)item); |
198 cm->items = ucx_list_append(cm->items, item); |
|
199 } |
241 } |
200 |
242 |
201 // private menu functions |
243 // private menu functions |
202 GtkWidget *ui_create_menubar(UiObject *obj) { |
244 GtkWidget *ui_create_menubar(UiObject *obj) { |
203 if(menus == NULL) { |
245 if(menus_begin == NULL) { |
204 return NULL; |
246 return NULL; |
205 } |
247 } |
206 |
248 |
207 GtkWidget *mb = gtk_menu_bar_new(); |
249 GtkWidget *mb = gtk_menu_bar_new(); |
208 |
250 |
209 UcxList *ls = menus; |
251 UiMenu *ls = menus_begin; |
210 while(ls) { |
252 while(ls) { |
211 UiMenu *menu = ls->data; |
253 UiMenu *menu = ls; |
212 menu->item.add_to(mb, 0, &menu->item, obj); |
254 menu->item.add_to(mb, 0, &menu->item, obj); |
213 |
255 |
214 ls = ls->next; |
256 ls = (UiMenu*)ls->item.next; |
215 } |
257 } |
216 |
258 |
217 return mb; |
259 return mb; |
218 } |
260 } |
219 |
261 |
222 |
264 |
223 GtkWidget *menu_widget = gtk_menu_new(); |
265 GtkWidget *menu_widget = gtk_menu_new(); |
224 GtkWidget *menu_item = gtk_menu_item_new_with_mnemonic(menu->label); |
266 GtkWidget *menu_item = gtk_menu_item_new_with_mnemonic(menu->label); |
225 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu_widget); |
267 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu_widget); |
226 |
268 |
227 UcxList *ls = menu->items; |
269 UiMenuItemI *it = menu->items_begin; |
228 int index = 0; |
270 int index = 0; |
229 while(ls) { |
271 while(it) { |
230 UiMenuItemI *i = ls->data; |
272 it->add_to(menu_widget, index, it, obj); |
231 i->add_to(menu_widget, index, i, obj); |
|
232 |
273 |
233 ls = ls->next; |
274 it = it->next; |
234 index++; |
275 index++; |
235 } |
276 } |
236 |
277 |
237 gtk_menu_shell_append(GTK_MENU_SHELL(parent), menu_item); |
278 gtk_menu_shell_append(GTK_MENU_SHELL(parent), menu_item); |
238 } |
279 } |
553 |
597 |
554 gtk_menu_shell_append(GTK_MENU_SHELL(ct->menu), widget); |
598 gtk_menu_shell_append(GTK_MENU_SHELL(ct->menu), widget); |
555 |
599 |
556 if(groups) { |
600 if(groups) { |
557 uic_add_group_widget(obj->ctx, widget, (ui_enablefunc)ui_set_enabled, groups); |
601 uic_add_group_widget(obj->ctx, widget, (ui_enablefunc)ui_set_enabled, groups); |
|
602 cxListDestroy(groups); |
558 } |
603 } |
559 } |
604 } |
560 |
605 |
561 void ui_widget_menuitem_st(UiObject *obj, char *stockid, ui_callback f, void *userdata) { |
606 void ui_widget_menuitem_st(UiObject *obj, char *stockid, ui_callback f, void *userdata) { |
562 ui_widget_menuitem_stgr(obj, stockid, f, userdata, -1); |
607 ui_widget_menuitem_stgr(obj, stockid, f, userdata, -1); |