| 231 // TODO: error |
231 // TODO: error |
| 232 } |
232 } |
| 233 } |
233 } |
| 234 */ |
234 */ |
| 235 |
235 |
| |
236 static void menuitem_list_remove_binding(void *obj) { |
| |
237 UiActiveMenuItemList *ls = obj; |
| |
238 UiList *list = ls->var->value; |
| |
239 CxList *bindings = list->obj; |
| |
240 if(bindings) { |
| |
241 (void)cxListFindRemove(bindings, obj); |
| |
242 if(cxListSize(bindings) == 0) { |
| |
243 cxListFree(bindings); |
| |
244 list->obj = NULL; |
| |
245 list->update = NULL; |
| |
246 } |
| |
247 } |
| |
248 } |
| |
249 |
| 236 void add_menuitem_list_widget(GtkWidget *p, int index, UiMenuItemI *item, UiObject *obj) { |
250 void add_menuitem_list_widget(GtkWidget *p, int index, UiMenuItemI *item, UiObject *obj) { |
| 237 UiMenuItemList *il = (UiMenuItemList*)item; |
251 UiMenuItemList *il = (UiMenuItemList*)item; |
| 238 const CxAllocator *a = obj->ctx->allocator; |
252 const CxAllocator *a = obj->ctx->allocator; |
| 239 |
253 |
| 240 UiActiveMenuItemList *ls = cxMalloc( |
254 UiActiveMenuItemList *ls = cxMalloc( |
| 245 ls->menu = GTK_MENU_SHELL(p); |
259 ls->menu = GTK_MENU_SHELL(p); |
| 246 ls->index = index; |
260 ls->index = index; |
| 247 ls->oldcount = 0; |
261 ls->oldcount = 0; |
| 248 ls->getvalue = il->getvalue; |
262 ls->getvalue = il->getvalue; |
| 249 |
263 |
| 250 UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); |
264 //UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); |
| 251 ls->list = var->value; |
265 UiVar* var = uic_create_var(obj->ctx, il->varname, UI_VAR_LIST); |
| |
266 ls->var = var; |
| |
267 if(var) { |
| |
268 UiList *list = var->value; |
| |
269 list->update = ui_menulist_update; |
| |
270 list->getselection = NULL; |
| |
271 list->setselection = NULL; |
| |
272 |
| |
273 // It is possible, that the UiVar is from a global shared context, |
| |
274 // used by multiple windows. To support this usecase, the list->obj |
| |
275 // binding object is a list of all connected UiActiveMenuItemList. |
| |
276 CxList *bindings = list->obj; |
| |
277 if(!bindings) { |
| |
278 bindings = cxLinkedListCreate(var->from_ctx->mp->allocator, NULL, CX_STORE_POINTERS); |
| |
279 list->obj = bindings; |
| |
280 } |
| |
281 cxListAdd(bindings, ls); |
| |
282 |
| |
283 // The destruction of the toplevel obj must remove the menulist binding |
| |
284 cxMempoolRegister(obj->ctx->mp, ls, menuitem_list_remove_binding); |
| |
285 |
| |
286 ui_update_menuitem_list(ls); |
| |
287 } |
| 252 |
288 |
| 253 ls->callback = il->callback; |
289 ls->callback = il->callback; |
| 254 ls->userdata = il->userdata; |
290 ls->userdata = il->userdata; |
| 255 |
291 } |
| 256 UiObserver *observer = ui_observer_new((ui_callback)ui_update_menuitem_list, ls); |
292 |
| 257 ls->list->observers = ui_obsvlist_add(ls->list->observers, observer); |
293 void ui_menulist_update(UiList *list, int ignored) { |
| 258 uic_list_register_observer_destructor(obj->ctx, ls->list, observer); |
294 CxList *bindings = list->obj; |
| 259 |
295 CxIterator i = cxListIterator(bindings); |
| 260 ui_update_menuitem_list(NULL, ls); |
296 cx_foreach(UiActiveMenuItemList *, ls, i) { |
| 261 } |
297 ui_update_menuitem_list(ls); |
| 262 |
298 } |
| 263 |
299 } |
| 264 void ui_update_menuitem_list(UiEvent *event, UiActiveMenuItemList *list) { |
300 |
| |
301 |
| |
302 void ui_update_menuitem_list(UiActiveMenuItemList *list) { |
| 265 // remove old items |
303 // remove old items |
| 266 if(list->oldcount > 0) { |
304 if(list->oldcount > 0) { |
| 267 int i = 0; |
305 int i = 0; |
| 268 GList *mi = gtk_container_get_children(GTK_CONTAINER(list->menu)); |
306 GList *mi = gtk_container_get_children(GTK_CONTAINER(list->menu)); |
| 269 while(mi) { |
307 while(mi) { |
| 504 |
544 |
| 505 void ui_gmenu_add_radioitem(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) { |
545 void ui_gmenu_add_radioitem(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) { |
| 506 |
546 |
| 507 } |
547 } |
| 508 |
548 |
| |
549 static void menuitem_list_remove_binding(void *obj) { |
| |
550 UiActiveGMenuItemList *ls = obj; |
| |
551 UiList *list = ls->var->value; |
| |
552 CxList *bindings = list->obj; |
| |
553 if(bindings) { |
| |
554 (void)cxListFindRemove(bindings, obj); |
| |
555 if(cxListSize(bindings) == 0) { |
| |
556 cxListFree(bindings); |
| |
557 list->obj = NULL; |
| |
558 list->update = NULL; |
| |
559 } |
| |
560 } |
| |
561 } |
| |
562 |
| 509 void ui_gmenu_add_menuitem_list(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) { |
563 void ui_gmenu_add_menuitem_list(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) { |
| 510 UiMenuItemList *il = (UiMenuItemList*)item; |
564 UiMenuItemList *il = (UiMenuItemList*)item; |
| 511 |
565 |
| 512 const CxAllocator *a = obj->ctx->allocator; |
566 const CxAllocator *a = obj->ctx->allocator; |
| 513 |
567 |
| 519 ls->menu = p; |
573 ls->menu = p; |
| 520 ls->index = index; |
574 ls->index = index; |
| 521 ls->oldcount = 0; |
575 ls->oldcount = 0; |
| 522 ls->getvalue = il->getvalue; |
576 ls->getvalue = il->getvalue; |
| 523 |
577 |
| 524 UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); |
578 //UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); |
| |
579 UiVar* var = uic_create_var(obj->ctx, il->varname, UI_VAR_LIST); |
| 525 ls->var = var; |
580 ls->var = var; |
| 526 UiList *list = var->value; |
581 if(var) { |
| |
582 UiList *list = var->value; |
| |
583 list->update = ui_menulist_update; |
| |
584 list->getselection = NULL; |
| |
585 list->setselection = NULL; |
| |
586 |
| |
587 // It is possible, that the UiVar is from a global shared context, |
| |
588 // used by multiple windows. To support this usecase, the list->obj |
| |
589 // binding object is a list of all connected UiActiveMenuItemList. |
| |
590 CxList *bindings = list->obj; |
| |
591 if(!bindings) { |
| |
592 bindings = cxLinkedListCreate(var->from_ctx->mp->allocator, NULL, CX_STORE_POINTERS); |
| |
593 list->obj = bindings; |
| |
594 } |
| |
595 cxListAdd(bindings, ls); |
| |
596 |
| |
597 // The destruction of the toplevel obj must remove the menulist binding |
| |
598 cxMempoolRegister(obj->ctx->mp, ls, menuitem_list_remove_binding); |
| |
599 |
| |
600 ui_update_gmenu_item_list(ls); |
| |
601 } |
| 527 |
602 |
| 528 ls->callback = il->callback; |
603 ls->callback = il->callback; |
| 529 ls->userdata = il->userdata; |
604 ls->userdata = il->userdata; |
| 530 |
|
| 531 UiObserver *observer = ui_observer_new((ui_callback)ui_update_gmenu_item_list, ls); |
|
| 532 list->observers = ui_obsvlist_add(list->observers, observer); |
|
| 533 uic_list_register_observer_destructor(obj->ctx, list, observer); |
|
| 534 |
605 |
| 535 GSimpleAction *action = g_simple_action_new(item->id, g_variant_type_new("i")); |
606 GSimpleAction *action = g_simple_action_new(item->id, g_variant_type_new("i")); |
| 536 g_action_map_add_action(obj->ctx->action_map, G_ACTION(action)); |
607 g_action_map_add_action(obj->ctx->action_map, G_ACTION(action)); |
| 537 snprintf(ls->action, 32, "win.%s", item->id); |
608 snprintf(ls->action, 32, "win.%s", item->id); |
| 538 |
609 |
| 552 g_signal_connect( |
623 g_signal_connect( |
| 553 obj->widget, |
624 obj->widget, |
| 554 "destroy", |
625 "destroy", |
| 555 G_CALLBACK(ui_destroy_userdata), |
626 G_CALLBACK(ui_destroy_userdata), |
| 556 event); |
627 event); |
| 557 |
|
| 558 ui_update_gmenu_item_list(NULL, ls); |
|
| 559 } |
628 } |
| 560 |
629 |
| 561 void ui_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEventData *event) { |
630 void ui_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEventData *event) { |
| 562 int intval = event->value; |
631 int intval = event->value; |
| 563 if(parameter && g_variant_is_of_type(parameter, G_VARIANT_TYPE_INT32)) { |
632 if(parameter && g_variant_is_of_type(parameter, G_VARIANT_TYPE_INT32)) { |
| 586 evt.intval = index; |
655 evt.intval = index; |
| 587 event->callback(&evt, event->userdata); |
656 event->callback(&evt, event->userdata); |
| 588 |
657 |
| 589 } |
658 } |
| 590 |
659 |
| 591 void ui_update_gmenu_item_list(UiEvent *event, UiActiveGMenuItemList *list) { |
660 void ui_menulist_update(UiList *list, int ignored) { |
| |
661 CxList *bindings = list->obj; |
| |
662 CxIterator i = cxListIterator(bindings); |
| |
663 cx_foreach(UiActiveGMenuItemList *, ls, i) { |
| |
664 ui_update_gmenu_item_list(ls); |
| |
665 } |
| |
666 } |
| |
667 |
| |
668 void ui_update_gmenu_item_list(UiActiveGMenuItemList *list) { |
| 592 // remove old items |
669 // remove old items |
| 593 for(int i=0;i<list->oldcount;i++) { |
670 for(int i=0;i<list->oldcount;i++) { |
| 594 g_menu_remove(list->menu, list->index); |
671 g_menu_remove(list->menu, list->index); |
| 595 } |
672 } |
| 596 UiList *ls = list->var->value; |
673 UiList *ls = list->var->value; |