54 offsetof(UiMenu, item.prev), |
55 offsetof(UiMenu, item.prev), |
55 offsetof(UiMenu, item.next), |
56 offsetof(UiMenu, item.next), |
56 item); |
57 item); |
57 } |
58 } |
58 |
59 |
59 void ui_menu(char *label) { |
60 static char* nl_strdup(const char* s) { |
|
61 return s ? strdup(s) : NULL; |
|
62 } |
|
63 |
|
64 static int* copy_groups(int* groups, size_t *ngroups) { |
|
65 *ngroups = 0; |
|
66 if (!groups) { |
|
67 return NULL; |
|
68 } |
|
69 |
|
70 size_t n; |
|
71 for (n = 0; groups[n] > -1; n++) { } |
|
72 |
|
73 if (ngroups > 0) { |
|
74 int* newarray = calloc(n, sizeof(int)); |
|
75 memcpy(newarray, groups, n); |
|
76 *ngroups = n; |
|
77 return newarray; |
|
78 } |
|
79 return NULL; |
|
80 } |
|
81 |
|
82 void ui_menu_create(const char *label) { |
60 if(!current) { |
83 if(!current) { |
61 current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); |
84 current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS); |
62 } else { |
|
63 // free current menu hierarchy |
|
64 cxListClear(current); |
|
65 } |
85 } |
66 |
86 |
67 // create menu |
87 // create menu |
68 UiMenu *menu = malloc(sizeof(UiMenu)); |
88 UiMenu *menu = malloc(sizeof(UiMenu)); |
69 menu->item.prev = NULL; |
89 menu->item.prev = NULL; |
74 menu->items_begin = NULL; |
94 menu->items_begin = NULL; |
75 menu->items_end = NULL; |
95 menu->items_end = NULL; |
76 menu->parent = NULL; |
96 menu->parent = NULL; |
77 |
97 |
78 menu->end = 0; |
98 menu->end = 0; |
79 |
99 |
80 add_menu(menu); |
100 if (current->size == 0) { |
81 cxListAdd(current, menu); |
101 add_menu(menu); |
82 } |
102 } |
83 |
103 else { |
84 void ui_submenu(char *label) { |
104 add_item((UiMenuItemI*)menu); |
85 UiMenu *menu = malloc(sizeof(UiMenu)); |
105 } |
86 menu->item.prev = NULL; |
|
87 menu->item.next = NULL; |
|
88 menu->item.type = UI_MENU_SUBMENU; |
|
89 |
|
90 menu->label = label; |
|
91 menu->items_begin = NULL; |
|
92 menu->items_end = NULL; |
|
93 menu->parent = NULL; |
|
94 |
|
95 menu->end = 0; |
|
96 |
|
97 // add submenu to current menu |
|
98 add_item((UiMenuItemI*)menu); |
|
99 |
|
100 // set the submenu to current menu |
|
101 uic_add_menu_to_stack(menu); |
106 uic_add_menu_to_stack(menu); |
102 } |
|
103 |
|
104 void ui_submenu_end() { |
|
105 if(current->size < 2) { |
|
106 return; |
|
107 } |
|
108 cxListRemove(current, 0); |
|
109 } |
107 } |
110 |
108 |
111 UIEXPORT void ui_menu_end(void) { |
109 UIEXPORT void ui_menu_end(void) { |
112 cxListRemove(current, 0); |
110 cxListRemove(current, 0); |
113 } |
111 } |
114 |
112 |
115 void ui_menuitem(char *label, ui_callback f, void *userdata) { |
113 |
116 ui_menuitem_gr(label, f, userdata, -1); |
114 |
117 } |
115 void ui_menuitem_create(UiMenuItemArgs args) { |
118 |
116 if (!current) { |
119 void ui_menuitem_st(char *stockid, ui_callback f, void *userdata) { |
117 return; // error? |
120 ui_menuitem_stgr(stockid, f, userdata, -1); |
118 } |
121 } |
119 |
122 |
120 UiMenuItem* item = malloc(sizeof(UiMenuItem)); |
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; |
121 item->item.prev = NULL; |
130 item->item.next = NULL; |
122 item->item.next = NULL; |
131 item->item.type = UI_MENU_ITEM; |
123 item->item.type = UI_MENU_ITEM; |
132 |
124 |
133 item->label = label; |
125 item->label = nl_strdup(args.label); |
134 item->userdata = userdata; |
126 item->stockid = nl_strdup(args.stockid); |
135 item->callback = f; |
127 item->icon = nl_strdup(args.icon); |
136 item->groups = NULL; |
128 item->userdata = args.onclickdata; |
137 |
129 item->callback = args.onclick; |
138 // add groups |
130 item->groups = copy_groups(args.groups, &item->ngroups); |
139 va_list ap; |
131 |
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.type = UI_MENU_STOCK_ITEM; |
|
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); |
132 add_item((UiMenuItemI*)item); |
181 } |
133 } |
182 |
134 |
183 void ui_menuseparator() { |
135 void ui_menuseparator() { |
184 if(!current) { |
136 if(!current) { |
191 item->type = UI_MENU_SEPARATOR; |
143 item->type = UI_MENU_SEPARATOR; |
192 |
144 |
193 add_item((UiMenuItemI*)item); |
145 add_item((UiMenuItemI*)item); |
194 } |
146 } |
195 |
147 |
196 void ui_checkitem(char *label, ui_callback f, void *userdata) { |
148 void ui_menu_toggleitem_create(UiMenuToggleItemArgs args) { |
197 if(!current) { |
149 if(!current) { |
198 return; |
150 return; |
199 } |
151 } |
200 |
152 |
201 UiCheckItem *item = malloc(sizeof(UiCheckItem)); |
153 UiMenuCheckItem *item = malloc(sizeof(UiMenuCheckItem)); |
202 item->item.prev = NULL; |
154 item->item.prev = NULL; |
203 item->item.next = NULL; |
155 item->item.next = NULL; |
204 item->item.type = UI_MENU_CHECK_ITEM; |
156 item->item.type = UI_MENU_CHECK_ITEM; |
205 item->label = label; |
157 |
206 item->callback = f; |
158 item->label = nl_strdup(args.label); |
207 item->userdata = userdata; |
159 item->stockid = nl_strdup(args.stockid); |
208 |
160 item->icon = nl_strdup(args.icon); |
209 add_item((UiMenuItemI*)item); |
161 item->varname = nl_strdup(args.varname); |
210 } |
162 item->userdata = args.onchangedata; |
211 |
163 item->callback = args.onchange; |
212 void ui_checkitem_nv(char *label, char *vname) { |
164 item->groups = copy_groups(args.groups, &item->ngroups); |
213 if(!current) { |
165 |
214 return; |
166 add_item((UiMenuItemI*)item); |
215 } |
167 } |
216 |
168 |
217 UiCheckItemNV *item = malloc(sizeof(UiCheckItemNV)); |
169 void ui_menu_radioitem_create(UiMenuToggleItemArgs args) { |
218 item->item.prev = NULL; |
170 if (!current) { |
219 item->item.next = NULL; |
171 return; |
220 item->item.type = UI_MENU_CHECK_ITEM_NV; |
172 } |
221 item->varname = vname; |
173 |
222 item->label = label; |
174 UiMenuCheckItem* item = malloc(sizeof(UiMenuCheckItem)); |
223 |
175 item->item.prev = NULL; |
224 add_item((UiMenuItemI*)item); |
176 item->item.next = NULL; |
225 } |
177 item->item.type = UI_MENU_CHECK_ITEM; |
226 |
178 |
227 void ui_menuitem_list(UiList *items, ui_callback f, void *userdata) { |
179 item->label = nl_strdup(args.label); |
228 if(!current) { |
180 item->stockid = nl_strdup(args.stockid); |
229 return; |
181 item->icon = nl_strdup(args.icon); |
230 } |
182 item->varname = nl_strdup(args.varname); |
231 |
183 item->userdata = args.onchangedata; |
232 UiMenuItemList *item = malloc(sizeof(UiMenuItemList)); |
184 item->callback = args.onchange; |
|
185 item->groups = copy_groups(args.groups, &item->ngroups); |
|
186 |
|
187 add_item((UiMenuItemI*)item); |
|
188 } |
|
189 |
|
190 void ui_menu_itemlist_create(UiMenuItemListArgs args) { |
|
191 if(!current) { |
|
192 return; |
|
193 } |
|
194 |
|
195 UiMenuItemList*item = malloc(sizeof(UiMenuItemList)); |
233 item->item.prev = NULL; |
196 item->item.prev = NULL; |
234 item->item.next = NULL; |
197 item->item.next = NULL; |
235 item->item.type = UI_MENU_ITEM_LIST; |
198 item->item.type = UI_MENU_ITEM_LIST; |
236 item->callback = f; |
199 item->callback = args.onselect; |
237 item->userdata = userdata; |
200 item->userdata = args.onselectdata; |
238 item->list = items; |
201 item->varname = nl_strdup(args.varname); |
239 |
202 |
240 add_item((UiMenuItemI*)item); |
203 add_item((UiMenuItemI*)item); |
241 } |
204 } |
242 |
205 |
243 void ui_menuitem_list_nv(const char *varname, ui_callback f, void *userdata) { |
206 void ui_menu_checkitemlist_create(UiMenuItemListArgs args) { |
244 if(!current) { |
207 if (!current) { |
245 return; |
208 return; |
246 } |
209 } |
247 |
210 |
248 UiMenuItemListNV *item = malloc(sizeof(UiMenuItemListNV)); |
211 UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); |
249 item->item.prev = NULL; |
212 item->item.prev = NULL; |
250 item->item.next = NULL; |
213 item->item.next = NULL; |
251 item->item.type = UI_MENU_ITEM_LIST; |
214 item->item.type = UI_MENU_ITEM_LIST; |
252 item->callback = f; |
215 item->callback = args.onselect; |
253 item->userdata = userdata; |
216 item->userdata = args.onselectdata; |
254 item->varname = varname; |
217 item->varname = nl_strdup(args.varname); |
255 |
218 |
256 add_item((UiMenuItemI*)item); |
219 add_item((UiMenuItemI*)item); |
257 } |
220 } |
|
221 |
|
222 void ui_menu_radioitemlist_create(UiMenuItemListArgs args) { |
|
223 if (!current) { |
|
224 return; |
|
225 } |
|
226 |
|
227 UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); |
|
228 item->item.prev = NULL; |
|
229 item->item.next = NULL; |
|
230 item->item.type = UI_MENU_ITEM_LIST; |
|
231 item->callback = args.onselect; |
|
232 item->userdata = args.onselectdata; |
|
233 item->varname = nl_strdup(args.varname); |
|
234 |
|
235 add_item((UiMenuItemI*)item); |
|
236 } |
|
237 |
258 |
238 |
259 void uic_add_menu_to_stack(UiMenu* menu) { |
239 void uic_add_menu_to_stack(UiMenu* menu) { |
260 cxListInsert(current, 0, menu); |
240 cxListInsert(current, 0, menu); |
261 } |
241 } |
262 |
242 |
263 UiMenu* uic_get_menu_list(void) { |
243 UiMenu* uic_get_menu_list(void) { |
264 return menus_begin; |
244 return menus_begin; |
265 } |
245 } |
266 |
|
267 |
|
268 |
|
269 |
246 |
270 UIEXPORT void ui_menu_close(void) { |
247 UIEXPORT void ui_menu_close(void) { |
271 UiMenu* menu = cxListAt(current, 0); |
248 UiMenu* menu = cxListAt(current, 0); |
272 menu->end = 1; |
249 menu->end = 1; |
273 } |
250 } |