ui/gtk/menu.c

changeset 108
77254bd6dccb
parent 101
7b3a3130be44
child 110
c00e968d018b
equal deleted inserted replaced
107:b34bd1557c6c 108:77254bd6dccb
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) {
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 }
472 event->obj = obj; 512 event->obj = obj;
473 event->userdata = i->userdata; 513 event->userdata = i->userdata;
474 event->callback = i->callback; 514 event->callback = i->callback;
475 event->value = 0; 515 event->value = 0;
476 event->customdata = NULL; 516 event->customdata = NULL;
517 event->customint = 0;
477 518
478 g_signal_connect( 519 g_signal_connect(
479 action, 520 action,
480 "activate", 521 "activate",
481 G_CALLBACK(ui_activate_event_wrapper), 522 G_CALLBACK(ui_activate_event_wrapper),
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
540 UiEventData *event = malloc(sizeof(UiEventData)); 612 UiEventData *event = malloc(sizeof(UiEventData));
541 event->obj = obj; 613 event->obj = obj;
542 event->userdata = il->userdata; 614 event->userdata = il->userdata;
543 event->callback = il->callback; 615 event->callback = il->callback;
544 event->customdata = var; 616 event->customdata = var;
617 event->customint = 0;
545 event->value = 0; 618 event->value = 0;
546 619
547 g_signal_connect( 620 g_signal_connect(
548 action, 621 action,
549 "activate", 622 "activate",
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;

mercurial