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; |