ui/common/menu.c

branch
newapi
changeset 178
7c3ff86ee9d4
parent 176
bc63cb601f6d
child 205
b1ac0dd1d38b
equal deleted inserted replaced
177:e79a60b3a7cb 178:7c3ff86ee9d4
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2023 Olaf Wintermann. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "menu.h"
30
31 #include <stdarg.h>
32
33 #include <cx/linked_list.h>
34 #include <cx/array_list.h>
35
36 static UiMenu *menus_begin;
37 static UiMenu *menus_end;
38 static CxList *current;
39
40 static void add_menu(UiMenu *menu) {
41 cx_linked_list_add(
42 (void**)&menus_begin,
43 (void**)&menus_end,
44 offsetof(UiMenu, item.prev),
45 offsetof(UiMenu, item.next),
46 menu);
47 }
48
49 static void add_item(UiMenuItemI *item) {
50 UiMenu *menu = cxListAt(current, 0);
51 cx_linked_list_add(
52 (void**)&menu->items_begin,
53 (void**)&menu->items_end,
54 offsetof(UiMenu, item.prev),
55 offsetof(UiMenu, item.next),
56 item);
57 }
58
59 void ui_menu(char *label) {
60 if(!current) {
61 current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS);
62 } else {
63 // free current menu hierarchy
64 cxListClear(current);
65 }
66
67 // create menu
68 UiMenu *menu = malloc(sizeof(UiMenu));
69 menu->item.prev = NULL;
70 menu->item.next = NULL;
71 menu->item.type = UI_MENU;
72
73 menu->label = label;
74 menu->items_begin = NULL;
75 menu->items_end = NULL;
76 menu->parent = NULL;
77
78 add_menu(menu);
79 cxListAdd(current, menu);
80 }
81
82 void ui_submenu(char *label) {
83 UiMenu *menu = malloc(sizeof(UiMenu));
84 menu->item.prev = NULL;
85 menu->item.next = NULL;
86 menu->item.type = UI_MENU_SUBMENU;
87
88 menu->label = label;
89 menu->items_begin = NULL;
90 menu->items_end = NULL;
91 menu->parent = NULL;
92
93 // add submenu to current menu
94 add_item((UiMenuItemI*)menu);
95
96 // set the submenu to current menu
97 cxListInsert(current, 0, menu);
98 }
99
100 void ui_submenu_end() {
101 if(current->size < 2) {
102 return;
103 }
104 cxListRemove(current, 0);
105 }
106
107 void ui_menuitem(char *label, ui_callback f, void *userdata) {
108 ui_menuitem_gr(label, f, userdata, -1);
109 }
110
111 void ui_menuitem_st(char *stockid, ui_callback f, void *userdata) {
112 ui_menuitem_stgr(stockid, f, userdata, -1);
113 }
114
115 void ui_menuitem_gr(char *label, ui_callback f, void *userdata, ...) {
116 if(!current) {
117 return;
118 }
119
120 UiMenuItem *item = malloc(sizeof(UiMenuItem));
121 item->item.prev = NULL;
122 item->item.next = NULL;
123 item->item.type = UI_MENU_ITEM;
124
125 item->label = label;
126 item->userdata = userdata;
127 item->callback = f;
128 item->groups = NULL;
129
130 // add groups
131 va_list ap;
132 va_start(ap, userdata);
133 int group;
134 while((group = va_arg(ap, int)) != -1) {
135 if(!item->groups) {
136 item->groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 8);
137 }
138 cxListAdd(item->groups, &group);
139 }
140 va_end(ap);
141
142 add_item((UiMenuItemI*)item);
143 }
144
145 void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) {
146 if(!current) {
147 return;
148 }
149
150 UiStMenuItem *item = malloc(sizeof(UiStMenuItem));
151 item->item.prev = NULL;
152 item->item.next = NULL;
153 item->item.type = UI_MENU_STOCK_ITEM;
154
155 item->stockid = stockid;
156 item->userdata = userdata;
157 item->callback = f;
158 item->groups = NULL;
159
160 // add groups
161 va_list ap;
162 va_start(ap, userdata);
163 int group;
164 while((group = va_arg(ap, int)) != -1) {
165 if(!item->groups) {
166 item->groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 8);
167 }
168 cxListAdd(item->groups, &group);
169 }
170 va_end(ap);
171
172 add_item((UiMenuItemI*)item);
173 }
174
175 void ui_menuseparator() {
176 if(!current) {
177 return;
178 }
179
180 UiMenuItemI *item = malloc(sizeof(UiMenuItemI));
181 item->prev = NULL;
182 item->next = NULL;
183 item->type = UI_MENU_SEPARATOR;
184
185 add_item((UiMenuItemI*)item);
186 }
187
188 void ui_checkitem(char *label, ui_callback f, void *userdata) {
189 if(!current) {
190 return;
191 }
192
193 UiCheckItem *item = malloc(sizeof(UiCheckItem));
194 item->item.prev = NULL;
195 item->item.next = NULL;
196 item->item.type = UI_MENU_CHECK_ITEM;
197 item->label = label;
198 item->callback = f;
199 item->userdata = userdata;
200
201 add_item((UiMenuItemI*)item);
202 }
203
204 void ui_checkitem_nv(char *label, char *vname) {
205 if(!current) {
206 return;
207 }
208
209 UiCheckItemNV *item = malloc(sizeof(UiCheckItemNV));
210 item->item.prev = NULL;
211 item->item.next = NULL;
212 item->item.type = UI_MENU_CHECK_ITEM_NV;
213 item->varname = vname;
214 item->label = label;
215
216 add_item((UiMenuItemI*)item);
217 }
218
219 void ui_menuitem_list(UiList *items, ui_callback f, void *userdata) {
220 if(!current) {
221 return;
222 }
223
224 UiMenuItemList *item = malloc(sizeof(UiMenuItemList));
225 item->item.prev = NULL;
226 item->item.next = NULL;
227 item->item.type = UI_MENU_ITEM_LIST;
228 item->callback = f;
229 item->userdata = userdata;
230 item->list = items;
231
232 add_item((UiMenuItemI*)item);
233 }
234
235 void ui_menuitem_list_nv(const char *varname, ui_callback f, void *userdata) {
236 if(!current) {
237 return;
238 }
239
240 UiMenuItemListNV *item = malloc(sizeof(UiMenuItemListNV));
241 item->item.prev = NULL;
242 item->item.next = NULL;
243 item->item.type = UI_MENU_ITEM_LIST;
244 item->callback = f;
245 item->userdata = userdata;
246 item->varname = varname;
247
248 add_item((UiMenuItemI*)item);
249 }
250
251
252
253 UiMenu* uic_get_menu_list(void) {
254 return menus_begin;
255 }

mercurial