ui/common/menu.c

branch
newapi
changeset 208
f632bc0589ab
parent 207
93b9f502cb88
child 229
a952760955b4
equal deleted inserted replaced
207:93b9f502cb88 208:f632bc0589ab
27 */ 27 */
28 28
29 #include "menu.h" 29 #include "menu.h"
30 30
31 #include <stdarg.h> 31 #include <stdarg.h>
32 #include <string.h>
32 33
33 #include <cx/linked_list.h> 34 #include <cx/linked_list.h>
34 #include <cx/array_list.h> 35 #include <cx/array_list.h>
35 36
36 static UiMenu *menus_begin; 37 static UiMenu *menus_begin;
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 }

mercurial