ui/gtk/menu.c

branch
newapi
changeset 174
0358f1d9c506
parent 168
1b99acacc5bb
child 175
2cb06c231057
equal deleted inserted replaced
173:809581724cc7 174:0358f1d9c506
36 #include "../common/context.h" 36 #include "../common/context.h"
37 #include "../ui/properties.h" 37 #include "../ui/properties.h"
38 #include "../ui/window.h" 38 #include "../ui/window.h"
39 #include "container.h" 39 #include "container.h"
40 40
41 static UcxList *menus; 41 #include <cx/linked_list.h>
42 static UcxList *current; 42 #include <cx/array_list.h>
43
44 static UiMenu *menus_begin;
45 static UiMenu *menus_end;
46 static CxList *current;
47
48 static void add_menu(UiMenu *menu) {
49 cx_linked_list_add(
50 (void**)&menus_begin,
51 (void**)&menus_end,
52 offsetof(UiMenu, item.prev),
53 offsetof(UiMenu, item.next),
54 menu);
55 }
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 }
43 66
44 void ui_menu(char *label) { 67 void ui_menu(char *label) {
45 // free current menu hierarchy 68 if(!current) {
46 ucx_list_free(current); 69 current = cxLinkedListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS);
70 } else {
71 // free current menu hierarchy
72 cxListClear(current);
73 }
47 74
48 // create menu 75 // create menu
49 UiMenu *menu = malloc(sizeof(UiMenu)); 76 UiMenu *menu = malloc(sizeof(UiMenu));
77 menu->item.prev = NULL;
78 menu->item.next = NULL;
50 menu->item.add_to = (ui_menu_add_f)add_menu_widget; 79 menu->item.add_to = (ui_menu_add_f)add_menu_widget;
51 80
52 menu->label = label; 81 menu->label = label;
53 menu->items = NULL; 82 menu->items_begin = NULL;
54 menu->parent = NULL; 83 menu->items_end = NULL;
55 84 menu->parent = NULL;
56 current = ucx_list_prepend(NULL, menu); 85
57 menus = ucx_list_append(menus, menu); 86 add_menu(menu);
58 87 cxListAdd(current, menu);
59 } 88 }
60 89
61 void ui_submenu(char *label) { 90 void ui_submenu(char *label) {
62 UiMenu *menu = malloc(sizeof(UiMenu)); 91 UiMenu *menu = malloc(sizeof(UiMenu));
92 menu->item.prev = NULL;
93 menu->item.next = NULL;
63 menu->item.add_to = (ui_menu_add_f)add_menu_widget; 94 menu->item.add_to = (ui_menu_add_f)add_menu_widget;
64 95
65 menu->label = label; 96 menu->label = label;
66 menu->items = NULL; 97 menu->items_begin = NULL;
67 menu->parent = NULL; 98 menu->items_end = NULL;
99 menu->parent = NULL;
68 100
69 // add submenu to current menu 101 // add submenu to current menu
70 UiMenu *cm = current->data; 102 add_item((UiMenuItemI*)menu);
71 cm->items = ucx_list_append(cm->items, menu);
72 103
73 // set the submenu to current menu 104 // set the submenu to current menu
74 current = ucx_list_prepend(current, menu); 105 cxListInsert(current, 0, menu);
75 } 106 }
76 107
77 void ui_submenu_end() { 108 void ui_submenu_end() {
78 if(ucx_list_size(current) < 2) { 109 if(current->size < 2) {
79 return; 110 return;
80 } 111 }
81 current = ucx_list_remove(current, current); 112 cxListRemove(current, 0);
82 //UcxList *c = current;
83 } 113 }
84 114
85 void ui_menuitem(char *label, ui_callback f, void *userdata) { 115 void ui_menuitem(char *label, ui_callback f, void *userdata) {
86 ui_menuitem_gr(label, f, userdata, -1); 116 ui_menuitem_gr(label, f, userdata, -1);
87 } 117 }
94 if(!current) { 124 if(!current) {
95 return; 125 return;
96 } 126 }
97 127
98 UiMenuItem *item = malloc(sizeof(UiMenuItem)); 128 UiMenuItem *item = malloc(sizeof(UiMenuItem));
129 item->item.prev = NULL;
130 item->item.next = NULL;
99 item->item.add_to = (ui_menu_add_f)add_menuitem_widget; 131 item->item.add_to = (ui_menu_add_f)add_menuitem_widget;
100 132
101 item->label = label; 133 item->label = label;
102 item->userdata = userdata; 134 item->userdata = userdata;
103 item->callback = f; 135 item->callback = f;
106 // add groups 138 // add groups
107 va_list ap; 139 va_list ap;
108 va_start(ap, userdata); 140 va_start(ap, userdata);
109 int group; 141 int group;
110 while((group = va_arg(ap, int)) != -1) { 142 while((group = va_arg(ap, int)) != -1) {
111 item->groups = ucx_list_append(item->groups, (void*)(intptr_t)group); 143 if(!item->groups) {
144 item->groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 8);
145 }
146 cxListAdd(item->groups, &group);
112 } 147 }
113 va_end(ap); 148 va_end(ap);
114 149
115 UiMenu *cm = current->data; 150 add_item((UiMenuItemI*)item);
116 cm->items = ucx_list_append(cm->items, item);
117 } 151 }
118 152
119 void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) { 153 void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) {
120 if(!current) { 154 if(!current) {
121 return; 155 return;
122 } 156 }
123 157
124 UiStMenuItem *item = malloc(sizeof(UiStMenuItem)); 158 UiStMenuItem *item = malloc(sizeof(UiStMenuItem));
159 item->item.prev = NULL;
160 item->item.next = NULL;
125 item->item.add_to = (ui_menu_add_f)add_menuitem_st_widget; 161 item->item.add_to = (ui_menu_add_f)add_menuitem_st_widget;
126 162
127 item->stockid = stockid; 163 item->stockid = stockid;
128 item->userdata = userdata; 164 item->userdata = userdata;
129 item->callback = f; 165 item->callback = f;
132 // add groups 168 // add groups
133 va_list ap; 169 va_list ap;
134 va_start(ap, userdata); 170 va_start(ap, userdata);
135 int group; 171 int group;
136 while((group = va_arg(ap, int)) != -1) { 172 while((group = va_arg(ap, int)) != -1) {
137 item->groups = ucx_list_append(item->groups, (void*)(intptr_t)group); 173 if(!item->groups) {
174 item->groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 8);
175 }
176 cxListAdd(item->groups, &group);
138 } 177 }
139 va_end(ap); 178 va_end(ap);
140 179
141 UiMenu *cm = current->data; 180 add_item((UiMenuItemI*)item);
142 cm->items = ucx_list_append(cm->items, item);
143 } 181 }
144 182
145 void ui_menuseparator() { 183 void ui_menuseparator() {
146 if(!current) { 184 if(!current) {
147 return; 185 return;
148 } 186 }
149 187
150 UiMenuItemI *item = malloc(sizeof(UiMenuItemI)); 188 UiMenuItemI *item = malloc(sizeof(UiMenuItemI));
189 item->prev = NULL;
190 item->next = NULL;
151 item->add_to = (ui_menu_add_f)add_menuseparator_widget; 191 item->add_to = (ui_menu_add_f)add_menuseparator_widget;
152 192
153 UiMenu *cm = current->data; 193 add_item((UiMenuItemI*)item);
154 cm->items = ucx_list_append(cm->items, item);
155 } 194 }
156 195
157 void ui_checkitem(char *label, ui_callback f, void *userdata) { 196 void ui_checkitem(char *label, ui_callback f, void *userdata) {
158 if(!current) { 197 if(!current) {
159 return; 198 return;
160 } 199 }
161 200
162 UiCheckItem *item = malloc(sizeof(UiCheckItem)); 201 UiCheckItem *item = malloc(sizeof(UiCheckItem));
202 item->item.prev = NULL;
203 item->item.next = NULL;
163 item->item.add_to = (ui_menu_add_f)add_checkitem_widget; 204 item->item.add_to = (ui_menu_add_f)add_checkitem_widget;
164 item->label = label; 205 item->label = label;
165 item->callback = f; 206 item->callback = f;
166 item->userdata = userdata; 207 item->userdata = userdata;
167 208
168 UiMenu *cm = current->data; 209 add_item((UiMenuItemI*)item);
169 cm->items = ucx_list_append(cm->items, item);
170 } 210 }
171 211
172 void ui_checkitem_nv(char *label, char *vname) { 212 void ui_checkitem_nv(char *label, char *vname) {
173 if(!current) { 213 if(!current) {
174 return; 214 return;
175 } 215 }
176 216
177 UiCheckItemNV *item = malloc(sizeof(UiCheckItemNV)); 217 UiCheckItemNV *item = malloc(sizeof(UiCheckItemNV));
218 item->item.prev = NULL;
219 item->item.next = NULL;
178 item->item.add_to = (ui_menu_add_f)add_checkitemnv_widget; 220 item->item.add_to = (ui_menu_add_f)add_checkitemnv_widget;
179 item->varname = vname; 221 item->varname = vname;
180 item->label = label; 222 item->label = label;
181 223
182 UiMenu *cm = current->data; 224 add_item((UiMenuItemI*)item);
183 cm->items = ucx_list_append(cm->items, item);
184 } 225 }
185 226
186 void ui_menuitem_list(UiList *items, ui_callback f, void *userdata) { 227 void ui_menuitem_list(UiList *items, ui_callback f, void *userdata) {
187 if(!current) { 228 if(!current) {
188 return; 229 return;
189 } 230 }
190 231
191 UiMenuItemList *item = malloc(sizeof(UiMenuItemList)); 232 UiMenuItemList *item = malloc(sizeof(UiMenuItemList));
233 item->item.prev = NULL;
234 item->item.next = NULL;
192 item->item.add_to = (ui_menu_add_f)add_menuitem_list_widget; 235 item->item.add_to = (ui_menu_add_f)add_menuitem_list_widget;
193 item->callback = f; 236 item->callback = f;
194 item->userdata = userdata; 237 item->userdata = userdata;
195 item->list = items; 238 item->list = items;
196 239
197 UiMenu *cm = current->data; 240 add_item((UiMenuItemI*)item);
198 cm->items = ucx_list_append(cm->items, item);
199 } 241 }
200 242
201 // private menu functions 243 // private menu functions
202 GtkWidget *ui_create_menubar(UiObject *obj) { 244 GtkWidget *ui_create_menubar(UiObject *obj) {
203 if(menus == NULL) { 245 if(menus_begin == NULL) {
204 return NULL; 246 return NULL;
205 } 247 }
206 248
207 GtkWidget *mb = gtk_menu_bar_new(); 249 GtkWidget *mb = gtk_menu_bar_new();
208 250
209 UcxList *ls = menus; 251 UiMenu *ls = menus_begin;
210 while(ls) { 252 while(ls) {
211 UiMenu *menu = ls->data; 253 UiMenu *menu = ls;
212 menu->item.add_to(mb, 0, &menu->item, obj); 254 menu->item.add_to(mb, 0, &menu->item, obj);
213 255
214 ls = ls->next; 256 ls = (UiMenu*)ls->item.next;
215 } 257 }
216 258
217 return mb; 259 return mb;
218 } 260 }
219 261
222 264
223 GtkWidget *menu_widget = gtk_menu_new(); 265 GtkWidget *menu_widget = gtk_menu_new();
224 GtkWidget *menu_item = gtk_menu_item_new_with_mnemonic(menu->label); 266 GtkWidget *menu_item = gtk_menu_item_new_with_mnemonic(menu->label);
225 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu_widget); 267 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), menu_widget);
226 268
227 UcxList *ls = menu->items; 269 UiMenuItemI *it = menu->items_begin;
228 int index = 0; 270 int index = 0;
229 while(ls) { 271 while(it) {
230 UiMenuItemI *i = ls->data; 272 it->add_to(menu_widget, index, it, obj);
231 i->add_to(menu_widget, index, i, obj);
232 273
233 ls = ls->next; 274 it = it->next;
234 index++; 275 index++;
235 } 276 }
236 277
237 gtk_menu_shell_append(GTK_MENU_SHELL(parent), menu_item); 278 gtk_menu_shell_append(GTK_MENU_SHELL(parent), menu_item);
238 } 279 }
358 } 399 }
359 } 400 }
360 401
361 void add_menuitem_list_widget(GtkWidget *p, int index, UiMenuItemI *item, UiObject *obj) { 402 void add_menuitem_list_widget(GtkWidget *p, int index, UiMenuItemI *item, UiObject *obj) {
362 UiMenuItemList *il = (UiMenuItemList*)item; 403 UiMenuItemList *il = (UiMenuItemList*)item;
363 UcxMempool *mp = obj->ctx->mempool; 404 const CxAllocator *a = obj->ctx->allocator;
364 405
365 UiActiveMenuItemList *ls = ucx_mempool_malloc( 406 UiActiveMenuItemList *ls = cxMalloc(
366 mp, 407 a,
367 sizeof(UiActiveMenuItemList)); 408 sizeof(UiActiveMenuItemList));
368 409
369 ls->object = obj; 410 ls->object = obj;
370 ls->menu = GTK_MENU_SHELL(p); 411 ls->menu = GTK_MENU_SHELL(p);
371 ls->index = index; 412 ls->index = index;
517 if(!ct->menu) { 558 if(!ct->menu) {
518 return; 559 return;
519 } 560 }
520 561
521 // add groups 562 // add groups
522 UcxList *groups = NULL; 563 CxList *groups = NULL;
523 va_list ap; 564 va_list ap;
524 va_start(ap, userdata); 565 va_start(ap, userdata);
525 int group; 566 int group;
526 while((group = va_arg(ap, int)) != -1) { 567 while((group = va_arg(ap, int)) != -1) {
527 ucx_list_append(groups, (void*)(intptr_t)group); 568 if(!groups) {
569 groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 16);
570 }
571 cxListAdd(groups, &group);
528 } 572 }
529 va_end(ap); 573 va_end(ap);
530 574
531 // create menuitem 575 // create menuitem
532 GtkWidget *widget = gtk_menu_item_new_with_mnemonic(label); 576 GtkWidget *widget = gtk_menu_item_new_with_mnemonic(label);
553 597
554 gtk_menu_shell_append(GTK_MENU_SHELL(ct->menu), widget); 598 gtk_menu_shell_append(GTK_MENU_SHELL(ct->menu), widget);
555 599
556 if(groups) { 600 if(groups) {
557 uic_add_group_widget(obj->ctx, widget, (ui_enablefunc)ui_set_enabled, groups); 601 uic_add_group_widget(obj->ctx, widget, (ui_enablefunc)ui_set_enabled, groups);
602 cxListDestroy(groups);
558 } 603 }
559 } 604 }
560 605
561 void ui_widget_menuitem_st(UiObject *obj, char *stockid, ui_callback f, void *userdata) { 606 void ui_widget_menuitem_st(UiObject *obj, char *stockid, ui_callback f, void *userdata) {
562 ui_widget_menuitem_stgr(obj, stockid, f, userdata, -1); 607 ui_widget_menuitem_stgr(obj, stockid, f, userdata, -1);
567 if(!ct->menu) { 612 if(!ct->menu) {
568 return; 613 return;
569 } 614 }
570 615
571 // add groups 616 // add groups
572 UcxList *groups = NULL; 617 CxList *groups = NULL;
573 va_list ap; 618 va_list ap;
574 va_start(ap, userdata); 619 va_start(ap, userdata);
575 int group; 620 int group;
576 while((group = va_arg(ap, int)) != -1) { 621 while((group = va_arg(ap, int)) != -1) {
577 ucx_list_append(groups, (void*)(intptr_t)group); 622 if(!groups) {
623 groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 16);
624 }
625 cxListAdd(groups, &group);
578 } 626 }
579 va_end(ap); 627 va_end(ap);
580 628
581 // create menuitem 629 // create menuitem
582 GtkWidget *widget = gtk_image_menu_item_new_from_stock(stockid, obj->ctx->accel_group); 630 GtkWidget *widget = gtk_image_menu_item_new_from_stock(stockid, obj->ctx->accel_group);
603 651
604 gtk_menu_shell_append(GTK_MENU_SHELL(ct->menu), widget); 652 gtk_menu_shell_append(GTK_MENU_SHELL(ct->menu), widget);
605 653
606 if(groups) { 654 if(groups) {
607 uic_add_group_widget(obj->ctx, widget, (ui_enablefunc)ui_set_enabled, groups); 655 uic_add_group_widget(obj->ctx, widget, (ui_enablefunc)ui_set_enabled, groups);
608 } 656 cxListDestroy(groups);
609 } 657 }
658 }

mercurial