33 |
33 |
34 #include <cx/linked_list.h> |
34 #include <cx/linked_list.h> |
35 #include <cx/array_list.h> |
35 #include <cx/array_list.h> |
36 |
36 |
37 |
37 |
38 static UiMenu *menus_begin; |
38 static UiMenuBuilder *current_builder; |
39 static UiMenu *menus_end; |
39 static UiMenuBuilder global_builder; |
40 static CxList *current; |
|
41 |
40 |
42 static int menu_item_counter = 0; |
41 static int menu_item_counter = 0; |
|
42 |
|
43 void uic_menu_init(void) { |
|
44 global_builder.current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); |
|
45 current_builder = &global_builder; |
|
46 } |
43 |
47 |
44 static void add_menu(UiMenu *menu) { |
48 static void add_menu(UiMenu *menu) { |
45 cx_linked_list_add( |
49 cx_linked_list_add( |
46 (void**)&menus_begin, |
50 (void**)¤t_builder->menus_begin, |
47 (void**)&menus_end, |
51 (void**)¤t_builder->menus_end, |
48 offsetof(UiMenu, item.prev), |
52 offsetof(UiMenu, item.prev), |
49 offsetof(UiMenu, item.next), |
53 offsetof(UiMenu, item.next), |
50 menu); |
54 menu); |
51 } |
55 } |
52 |
56 |
53 static void add_item(UiMenuItemI *item) { |
57 static void add_item(UiMenuItemI *item) { |
54 UiMenu *menu = cxListAt(current, 0); |
58 UiMenu *menu = cxListAt(current_builder->current, 0); |
55 cx_linked_list_add( |
59 cx_linked_list_add( |
56 (void**)&menu->items_begin, |
60 (void**)&menu->items_begin, |
57 (void**)&menu->items_end, |
61 (void**)&menu->items_end, |
58 offsetof(UiMenu, item.prev), |
62 offsetof(UiMenu, item.prev), |
59 offsetof(UiMenu, item.next), |
63 offsetof(UiMenu, item.next), |
84 return newarray; |
88 return newarray; |
85 } |
89 } |
86 return NULL; |
90 return NULL; |
87 } |
91 } |
88 |
92 |
89 void ui_menu_create(const char *label) { |
93 void ui_menu_create(const char *label) { |
90 if(!current) { |
|
91 current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); |
|
92 } |
|
93 |
|
94 // create menu |
94 // create menu |
95 UiMenu *menu = malloc(sizeof(UiMenu)); |
95 UiMenu *menu = malloc(sizeof(UiMenu)); |
96 mitem_set_id(&menu->item); |
96 mitem_set_id(&menu->item); |
97 menu->item.prev = NULL; |
97 menu->item.prev = NULL; |
98 menu->item.next = NULL; |
98 menu->item.next = NULL; |
103 menu->items_end = NULL; |
103 menu->items_end = NULL; |
104 menu->parent = NULL; |
104 menu->parent = NULL; |
105 |
105 |
106 menu->end = 0; |
106 menu->end = 0; |
107 |
107 |
108 if (cxListSize(current) == 0) { |
108 if (cxListSize(current_builder->current) == 0) { |
109 add_menu(menu); |
109 add_menu(menu); |
110 } |
110 } |
111 else { |
111 else { |
112 add_item((UiMenuItemI*)menu); |
112 add_item((UiMenuItemI*)menu); |
113 } |
113 } |
114 uic_add_menu_to_stack(menu); |
114 uic_add_menu_to_stack(menu); |
115 } |
115 } |
116 |
116 |
117 UIEXPORT void ui_menu_end(void) { |
117 UIEXPORT void ui_menu_end(void) { |
118 cxListRemove(current, 0); |
118 cxListRemove(current_builder->current, 0); |
|
119 if(cxListSize(current_builder->current) == 0) { |
|
120 current_builder = &global_builder; |
|
121 } |
119 } |
122 } |
120 |
123 |
121 |
124 |
122 |
125 |
123 void ui_menuitem_create(UiMenuItemArgs args) { |
126 void ui_menuitem_create(UiMenuItemArgs args) { |
124 if (!current) { |
|
125 return; // error? |
|
126 } |
|
127 |
|
128 UiMenuItem* item = malloc(sizeof(UiMenuItem)); |
127 UiMenuItem* item = malloc(sizeof(UiMenuItem)); |
129 mitem_set_id(&item->item); |
128 mitem_set_id(&item->item); |
130 item->item.prev = NULL; |
129 item->item.prev = NULL; |
131 item->item.next = NULL; |
130 item->item.next = NULL; |
132 item->item.type = UI_MENU_ITEM; |
131 item->item.type = UI_MENU_ITEM; |
140 |
139 |
141 add_item((UiMenuItemI*)item); |
140 add_item((UiMenuItemI*)item); |
142 } |
141 } |
143 |
142 |
144 void ui_menuseparator() { |
143 void ui_menuseparator() { |
145 if(!current) { |
|
146 return; |
|
147 } |
|
148 |
|
149 UiMenuItemI *item = malloc(sizeof(UiMenuItemI)); |
144 UiMenuItemI *item = malloc(sizeof(UiMenuItemI)); |
150 item->id[0] = 0; |
145 item->id[0] = 0; |
151 item->prev = NULL; |
146 item->prev = NULL; |
152 item->next = NULL; |
147 item->next = NULL; |
153 item->type = UI_MENU_SEPARATOR; |
148 item->type = UI_MENU_SEPARATOR; |
154 |
149 |
155 add_item((UiMenuItemI*)item); |
150 add_item((UiMenuItemI*)item); |
156 } |
151 } |
157 |
152 |
158 void ui_menu_toggleitem_create(UiMenuToggleItemArgs args) { |
153 void ui_menu_toggleitem_create(UiMenuToggleItemArgs args) { |
159 if(!current) { |
|
160 return; |
|
161 } |
|
162 |
|
163 UiMenuCheckItem *item = malloc(sizeof(UiMenuCheckItem)); |
154 UiMenuCheckItem *item = malloc(sizeof(UiMenuCheckItem)); |
164 mitem_set_id(&item->item); |
155 mitem_set_id(&item->item); |
165 item->item.prev = NULL; |
156 item->item.prev = NULL; |
166 item->item.next = NULL; |
157 item->item.next = NULL; |
167 item->item.type = UI_MENU_CHECK_ITEM; |
158 item->item.type = UI_MENU_CHECK_ITEM; |
176 |
167 |
177 add_item((UiMenuItemI*)item); |
168 add_item((UiMenuItemI*)item); |
178 } |
169 } |
179 |
170 |
180 void ui_menu_radioitem_create(UiMenuToggleItemArgs args) { |
171 void ui_menu_radioitem_create(UiMenuToggleItemArgs args) { |
181 if (!current) { |
|
182 return; |
|
183 } |
|
184 |
|
185 UiMenuCheckItem* item = malloc(sizeof(UiMenuCheckItem)); |
172 UiMenuCheckItem* item = malloc(sizeof(UiMenuCheckItem)); |
186 mitem_set_id(&item->item); |
173 mitem_set_id(&item->item); |
187 item->item.prev = NULL; |
174 item->item.prev = NULL; |
188 item->item.next = NULL; |
175 item->item.next = NULL; |
189 item->item.type = UI_MENU_CHECK_ITEM; |
176 item->item.type = UI_MENU_CHECK_ITEM; |
198 |
185 |
199 add_item((UiMenuItemI*)item); |
186 add_item((UiMenuItemI*)item); |
200 } |
187 } |
201 |
188 |
202 void ui_menu_itemlist_create(UiMenuItemListArgs args) { |
189 void ui_menu_itemlist_create(UiMenuItemListArgs args) { |
203 if(!current) { |
|
204 return; |
|
205 } |
|
206 |
|
207 UiMenuItemList*item = malloc(sizeof(UiMenuItemList)); |
190 UiMenuItemList*item = malloc(sizeof(UiMenuItemList)); |
208 mitem_set_id(&item->item); |
191 mitem_set_id(&item->item); |
209 item->item.prev = NULL; |
192 item->item.prev = NULL; |
210 item->item.next = NULL; |
193 item->item.next = NULL; |
211 item->item.type = UI_MENU_ITEM_LIST; |
194 item->item.type = UI_MENU_ITEM_LIST; |
216 |
199 |
217 add_item((UiMenuItemI*)item); |
200 add_item((UiMenuItemI*)item); |
218 } |
201 } |
219 |
202 |
220 void ui_menu_checkitemlist_create(UiMenuItemListArgs args) { |
203 void ui_menu_checkitemlist_create(UiMenuItemListArgs args) { |
221 if (!current) { |
|
222 return; |
|
223 } |
|
224 |
|
225 UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); |
204 UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); |
226 mitem_set_id(&item->item); |
205 mitem_set_id(&item->item); |
227 item->item.prev = NULL; |
206 item->item.prev = NULL; |
228 item->item.next = NULL; |
207 item->item.next = NULL; |
229 item->item.type = UI_MENU_CHECKITEM_LIST; |
208 item->item.type = UI_MENU_CHECKITEM_LIST; |
233 |
212 |
234 add_item((UiMenuItemI*)item); |
213 add_item((UiMenuItemI*)item); |
235 } |
214 } |
236 |
215 |
237 void ui_menu_radioitemlist_create(UiMenuItemListArgs args) { |
216 void ui_menu_radioitemlist_create(UiMenuItemListArgs args) { |
238 if (!current) { |
|
239 return; |
|
240 } |
|
241 |
|
242 UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); |
217 UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); |
243 mitem_set_id(&item->item); |
218 mitem_set_id(&item->item); |
244 item->item.prev = NULL; |
219 item->item.prev = NULL; |
245 item->item.next = NULL; |
220 item->item.next = NULL; |
246 item->item.type = UI_MENU_RADIOITEM_LIST; |
221 item->item.type = UI_MENU_RADIOITEM_LIST; |
251 add_item((UiMenuItemI*)item); |
226 add_item((UiMenuItemI*)item); |
252 } |
227 } |
253 |
228 |
254 |
229 |
255 void uic_add_menu_to_stack(UiMenu* menu) { |
230 void uic_add_menu_to_stack(UiMenu* menu) { |
256 if (!current) { |
231 cxListInsert(current_builder->current, 0, menu); |
257 current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); |
|
258 } |
|
259 |
|
260 cxListInsert(current, 0, menu); |
|
261 } |
232 } |
262 |
233 |
263 UiMenu* uic_get_menu_list(void) { |
234 UiMenu* uic_get_menu_list(void) { |
264 return menus_begin; |
235 return current_builder->menus_begin; |
265 } |
236 } |
266 |
237 |
267 UIEXPORT void ui_menu_close(void) { |
238 UIEXPORT void ui_menu_close(void) { |
268 UiMenu* menu = cxListAt(current, 0); |
239 UiMenu* menu = cxListAt(current_builder->current, 0); |
269 menu->end = 1; |
240 menu->end = 1; |
270 } |
241 } |
271 |
242 |
272 UIEXPORT int ui_menu_is_open(void) { |
243 UIEXPORT int ui_menu_is_open(void) { |
273 UiMenu* menu = cxListAt(current, 0); |
244 UiMenu* menu = cxListAt(current_builder->current, 0); |
274 if (menu->end) { |
245 if (menu->end) { |
275 ui_menu_end(); |
246 ui_menu_end(); |
276 return 0; |
247 return 0; |
277 } |
248 } |
278 return 1; |
249 return 1; |
279 } |
250 } |
|
251 |
|
252 |
|
253 void ui_contextmenu_builder(UiMenuBuilder **out_builder) { |
|
254 UiMenuBuilder *builder = malloc(sizeof(UiMenuBuilder)); |
|
255 builder->menus_begin = NULL; |
|
256 builder->menus_end = NULL; |
|
257 builder->current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); |
|
258 current_builder = builder; |
|
259 *out_builder = builder; |
|
260 |
|
261 ui_menu_create(NULL); |
|
262 } |
|
263 |
|
264 |
|
265 |
|
266 static void free_menuitem(UiMenuItemI *item) { |
|
267 switch(item->type) { |
|
268 default: break; |
|
269 case UI_MENU: { |
|
270 UiMenu *menu = (UiMenu*)item; |
|
271 UiMenuItemI *m = menu->items_begin; |
|
272 while(m) { |
|
273 UiMenuItemI *next = m->next; |
|
274 free_menuitem(m); |
|
275 m = next; |
|
276 } |
|
277 break; |
|
278 } |
|
279 case UI_MENU_ITEM: { |
|
280 UiMenuItem *i = (UiMenuItem*)item; |
|
281 free(i->groups); |
|
282 free(i->label); |
|
283 free(i->stockid); |
|
284 free(i->icon); |
|
285 break; |
|
286 } |
|
287 case UI_MENU_CHECK_ITEM: { |
|
288 UiMenuCheckItem *i = (UiMenuCheckItem*)item; |
|
289 free(i->groups); |
|
290 free(i->label); |
|
291 free(i->stockid); |
|
292 free(i->icon); |
|
293 free(i->varname); |
|
294 break; |
|
295 } |
|
296 case UI_MENU_RADIO_ITEM: { |
|
297 UiMenuRadioItem *i = (UiMenuRadioItem*)item; |
|
298 free(i->groups); |
|
299 free(i->label); |
|
300 free(i->stockid); |
|
301 free(i->icon); |
|
302 //free(i->varname); |
|
303 break; |
|
304 } |
|
305 case UI_MENU_ITEM_LIST: { |
|
306 break; |
|
307 } |
|
308 case UI_MENU_CHECKITEM_LIST: { |
|
309 break; |
|
310 } |
|
311 case UI_MENU_RADIOITEM_LIST: { |
|
312 break; |
|
313 } |
|
314 } |
|
315 |
|
316 free(item); |
|
317 } |
|
318 |
|
319 void ui_menubuilder_free(UiMenuBuilder *builder) { |
|
320 UiMenuItemI *m = &builder->menus_begin->item; |
|
321 while(m) { |
|
322 UiMenuItemI *next = m->next; |
|
323 free_menuitem(m); |
|
324 m = next; |
|
325 } |
|
326 cxListDestroy(builder->current); |
|
327 free(builder); |
|
328 } |