ui/gtk/menu.c

changeset 553
90e38db0c755
parent 440
7c4b9cba09ca
child 558
62aefa91ffc5
equal deleted inserted replaced
552:131059d41671 553:90e38db0c755
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) {
274 mi = mi->next; 312 mi = mi->next;
275 i++; 313 i++;
276 } 314 }
277 } 315 }
278 316
279 void* elm = ui_list_first(list->list); 317 UiList *ls = list->var->value;
318
319 void* elm = ui_list_first(ls);
280 if(elm) { 320 if(elm) {
281 GtkWidget *widget = gtk_separator_menu_item_new(); 321 GtkWidget *widget = gtk_separator_menu_item_new();
282 gtk_menu_shell_insert(list->menu, widget, list->index); 322 gtk_menu_shell_insert(list->menu, widget, list->index);
283 gtk_widget_show(widget); 323 gtk_widget_show(widget);
284 } 324 }
310 "destroy", 350 "destroy",
311 G_CALLBACK(ui_destroy_userdata), 351 G_CALLBACK(ui_destroy_userdata),
312 event); 352 event);
313 } 353 }
314 354
315 elm = ui_list_next(list->list); 355 elm = ui_list_next(ls);
316 i++; 356 i++;
317 } 357 }
318 358
319 list->oldcount = i; 359 list->oldcount = i;
320 } 360 }
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;

mercurial