| 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 uic_context_add_destructor(obj->ctx, menuitem_list_remove_binding, ls); |
| |
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) { |
| 502 // TODO |
543 // TODO |
| 503 } |
544 } |
| 504 |
545 |
| 505 void ui_gmenu_add_radioitem(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) { |
546 void ui_gmenu_add_radioitem(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) { |
| 506 |
547 |
| |
548 } |
| |
549 |
| |
550 static void menuitem_list_remove_binding(void *obj) { |
| |
551 UiActiveGMenuItemList *ls = obj; |
| |
552 UiList *list = ls->var->value; |
| |
553 CxList *bindings = list->obj; |
| |
554 if(bindings) { |
| |
555 (void)cxListFindRemove(bindings, obj); |
| |
556 if(cxListSize(bindings) == 0) { |
| |
557 cxListFree(bindings); |
| |
558 list->obj = NULL; |
| |
559 list->update = NULL; |
| |
560 } |
| |
561 } |
| 507 } |
562 } |
| 508 |
563 |
| 509 void ui_gmenu_add_menuitem_list(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) { |
564 void ui_gmenu_add_menuitem_list(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) { |
| 510 UiMenuItemList *il = (UiMenuItemList*)item; |
565 UiMenuItemList *il = (UiMenuItemList*)item; |
| 511 |
566 |
| 519 ls->menu = p; |
574 ls->menu = p; |
| 520 ls->index = index; |
575 ls->index = index; |
| 521 ls->oldcount = 0; |
576 ls->oldcount = 0; |
| 522 ls->getvalue = il->getvalue; |
577 ls->getvalue = il->getvalue; |
| 523 |
578 |
| 524 UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); |
579 //UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); |
| |
580 UiVar* var = uic_create_var(obj->ctx, il->varname, UI_VAR_LIST); |
| 525 ls->var = var; |
581 ls->var = var; |
| 526 UiList *list = var->value; |
582 if(var) { |
| |
583 UiList *list = var->value; |
| |
584 list->update = ui_menulist_update; |
| |
585 list->getselection = NULL; |
| |
586 list->setselection = NULL; |
| |
587 |
| |
588 // It is possible, that the UiVar is from a global shared context, |
| |
589 // used by multiple windows. To support this usecase, the list->obj |
| |
590 // binding object is a list of all connected UiActiveMenuItemList. |
| |
591 CxList *bindings = list->obj; |
| |
592 if(!bindings) { |
| |
593 bindings = cxLinkedListCreate(var->from_ctx->mp->allocator, NULL, CX_STORE_POINTERS); |
| |
594 list->obj = bindings; |
| |
595 } |
| |
596 cxListAdd(bindings, ls); |
| |
597 |
| |
598 // The destruction of the toplevel obj must remove the menulist binding |
| |
599 uic_context_add_destructor(obj->ctx, menuitem_list_remove_binding, ls); |
| |
600 |
| |
601 ui_update_gmenu_item_list(ls); |
| |
602 } |
| 527 |
603 |
| 528 ls->callback = il->callback; |
604 ls->callback = il->callback; |
| 529 ls->userdata = il->userdata; |
605 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 |
606 |
| 535 GSimpleAction *action = g_simple_action_new(item->id, g_variant_type_new("i")); |
607 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)); |
608 g_action_map_add_action(obj->ctx->action_map, G_ACTION(action)); |
| 537 snprintf(ls->action, 32, "win.%s", item->id); |
609 snprintf(ls->action, 32, "win.%s", item->id); |
| 538 |
610 |
| 552 g_signal_connect( |
625 g_signal_connect( |
| 553 obj->widget, |
626 obj->widget, |
| 554 "destroy", |
627 "destroy", |
| 555 G_CALLBACK(ui_destroy_userdata), |
628 G_CALLBACK(ui_destroy_userdata), |
| 556 event); |
629 event); |
| 557 |
|
| 558 ui_update_gmenu_item_list(NULL, ls); |
|
| 559 } |
630 } |
| 560 |
631 |
| 561 void ui_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEventData *event) { |
632 void ui_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEventData *event) { |
| 562 int intval = event->value; |
633 int intval = event->value; |
| 563 if(parameter && g_variant_is_of_type(parameter, G_VARIANT_TYPE_INT32)) { |
634 if(parameter && g_variant_is_of_type(parameter, G_VARIANT_TYPE_INT32)) { |
| 567 UiEvent evt; |
638 UiEvent evt; |
| 568 evt.obj = event->obj; |
639 evt.obj = event->obj; |
| 569 evt.window = event->obj->window; |
640 evt.window = event->obj->window; |
| 570 evt.document = event->obj->ctx->document; |
641 evt.document = event->obj->ctx->document; |
| 571 evt.eventdata = event->customdata; |
642 evt.eventdata = event->customdata; |
| |
643 evt.eventdatatype = event->customint; |
| 572 evt.intval = intval; |
644 evt.intval = intval; |
| 573 event->callback(&evt, event->userdata); |
645 event->callback(&evt, event->userdata); |
| 574 } |
646 } |
| 575 |
647 |
| 576 void ui_menu_list_item_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEventData *event) { |
648 void ui_menu_list_item_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEventData *event) { |
| 581 UiEvent evt; |
653 UiEvent evt; |
| 582 evt.obj = event->obj; |
654 evt.obj = event->obj; |
| 583 evt.window = event->obj->window; |
655 evt.window = event->obj->window; |
| 584 evt.document = event->obj->ctx->document; |
656 evt.document = event->obj->ctx->document; |
| 585 evt.eventdata = ui_list_get(list, index); |
657 evt.eventdata = ui_list_get(list, index); |
| |
658 evt.eventdatatype = UI_EVENT_DATA_LIST_ELM; |
| 586 evt.intval = index; |
659 evt.intval = index; |
| 587 event->callback(&evt, event->userdata); |
660 event->callback(&evt, event->userdata); |
| 588 |
661 |
| 589 } |
662 } |
| 590 |
663 |
| 591 void ui_update_gmenu_item_list(UiEvent *event, UiActiveGMenuItemList *list) { |
664 void ui_menulist_update(UiList *list, int ignored) { |
| |
665 CxList *bindings = list->obj; |
| |
666 CxIterator i = cxListIterator(bindings); |
| |
667 cx_foreach(UiActiveGMenuItemList *, ls, i) { |
| |
668 ui_update_gmenu_item_list(ls); |
| |
669 } |
| |
670 } |
| |
671 |
| |
672 void ui_update_gmenu_item_list(UiActiveGMenuItemList *list) { |
| 592 // remove old items |
673 // remove old items |
| 593 for(int i=0;i<list->oldcount;i++) { |
674 for(int i=0;i<list->oldcount;i++) { |
| 594 g_menu_remove(list->menu, list->index); |
675 g_menu_remove(list->menu, list->index); |
| 595 } |
676 } |
| 596 UiList *ls = list->var->value; |
677 UiList *ls = list->var->value; |