ui/gtk/menu.c

changeset 88
e27526429d85
parent 46
31bc86844659
child 95
e92c72705da4
equal deleted inserted replaced
87:5360027fb282 88:e27526429d85
353 353
354 /* 354 /*
355 * widget menu functions 355 * widget menu functions
356 */ 356 */
357 357
358 UIMENU ui_contextmenu_create(UiMenuBuilder *builder, UiObject *obj, UIWIDGET widget) {
359 GtkWidget *menu_widget = gtk_menu_new();
360 ui_add_menu_items(menu_widget, 0, builder->menus_begin, obj);
361 return GTK_MENU(menu_widget);
362 }
363
358 static gboolean ui_button_press_event(GtkWidget *widget, GdkEvent *event, GtkMenu *menu) { 364 static gboolean ui_button_press_event(GtkWidget *widget, GdkEvent *event, GtkMenu *menu) {
359 if(event->type == GDK_BUTTON_PRESS) { 365 if(event->type == GDK_BUTTON_PRESS) {
360 GdkEventButton *e = (GdkEventButton*)event; 366 GdkEventButton *e = (GdkEventButton*)event;
361 if(e->button == 3) { 367 if(e->button == 3) {
362 gtk_widget_show_all(GTK_WIDGET(menu)); 368 gtk_widget_show_all(GTK_WIDGET(menu));
363 ui_contextmenu_popup(menu); 369 ui_contextmenu_popup(menu, widget, 0, 0);
364 return TRUE;
365 } 370 }
366 } 371 }
367 return FALSE; 372 return FALSE;
368 } 373 }
369 374
370 UIMENU ui_contextmenu(UiObject *obj) { 375 void ui_widget_set_contextmenu(GtkWidget *widget, GtkMenu *menu) {
371 UiContainer *ct = uic_get_current_container(obj);
372 return ui_contextmenu_w(obj, ct->current);
373 }
374
375 UIMENU ui_contextmenu_w(UiObject *obj, UIWIDGET widget) {
376 UiContainer *ct = uic_get_current_container(obj);
377
378 GtkMenu *menu = GTK_MENU(gtk_menu_new());
379 g_signal_connect(widget, "button-press-event", (GCallback) ui_button_press_event, menu); 376 g_signal_connect(widget, "button-press-event", (GCallback) ui_button_press_event, menu);
380 377 }
381 ct->menu = menu; 378
382 return menu; 379 void ui_contextmenu_popup(UIMENU menu, GtkWidget *widget, int x, int y) {
383 }
384
385 void ui_contextmenu_popup(UIMENU menu) {
386 #if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 16 380 #if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 16
387 gtk_menu_popup_at_pointer(menu, NULL); 381 gtk_menu_popup_at_pointer(menu, NULL);
388 #else 382 #else
389 gtk_menu_popup(menu, NULL, NULL, 0, 0, 0, gtk_get_current_event_time()); 383 gtk_menu_popup(menu, NULL, NULL, 0, 0, 0, gtk_get_current_event_time());
390 #endif 384 #endif
391 }
392
393 void ui_widget_menuitem(UiObject *obj, char *label, ui_callback f, void *userdata) {
394 ui_widget_menuitem_gr(obj, label, f, userdata, -1);
395 }
396
397 void ui_widget_menuitem_gr(UiObject *obj, char *label, ui_callback f, void *userdata, ...) {
398 UiContainer *ct = uic_get_current_container(obj);
399 if(!ct->menu) {
400 return;
401 }
402
403 // add groups
404 CxList *groups = NULL;
405 va_list ap;
406 va_start(ap, userdata);
407 int group;
408 while((group = va_arg(ap, int)) != -1) {
409 if(!groups) {
410 groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 16);
411 }
412 cxListAdd(groups, &group);
413 }
414 va_end(ap);
415
416 // create menuitem
417 GtkWidget *widget = gtk_menu_item_new_with_mnemonic(label);
418 gtk_widget_show(widget);
419
420 if(f) {
421 UiEventData *event = malloc(sizeof(UiEventData));
422 event->obj = obj;
423 event->userdata = userdata;
424 event->callback = f;
425 event->value = 0;
426 event->customdata = NULL;
427
428 g_signal_connect(
429 widget,
430 "activate",
431 G_CALLBACK(ui_menu_event_wrapper),
432 event);
433 g_signal_connect(
434 widget,
435 "destroy",
436 G_CALLBACK(ui_destroy_userdata),
437 event);
438 }
439
440 gtk_menu_shell_append(GTK_MENU_SHELL(ct->menu), widget);
441
442 if(groups) {
443 uic_add_group_widget(obj->ctx, widget, (ui_enablefunc)ui_set_enabled, groups);
444 cxListDestroy(groups);
445 }
446 }
447
448 void ui_widget_menuitem_st(UiObject *obj, char *stockid, ui_callback f, void *userdata) {
449 ui_widget_menuitem_stgr(obj, stockid, f, userdata, -1);
450 }
451
452 void ui_widget_menuitem_stgr(UiObject *obj, char *stockid, ui_callback f, void *userdata, ...) {
453 UiContainer *ct = uic_get_current_container(obj);
454 if(!ct->menu) {
455 return;
456 }
457
458 // add groups
459 CxList *groups = NULL;
460 va_list ap;
461 va_start(ap, userdata);
462 int group;
463 while((group = va_arg(ap, int)) != -1) {
464 if(!groups) {
465 groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 16);
466 }
467 cxListAdd(groups, &group);
468 }
469 va_end(ap);
470
471 // create menuitem
472 GtkWidget *widget = gtk_image_menu_item_new_from_stock(stockid, obj->ctx->accel_group);
473 gtk_widget_show(widget);
474
475 if(f) {
476 UiEventData *event = malloc(sizeof(UiEventData));
477 event->obj = obj;
478 event->userdata = userdata;
479 event->callback = f;
480 event->value = 0;
481 event->customdata = NULL;
482
483 g_signal_connect(
484 widget,
485 "activate",
486 G_CALLBACK(ui_menu_event_wrapper),
487 event);
488 g_signal_connect(
489 widget,
490 "destroy",
491 G_CALLBACK(ui_destroy_userdata),
492 event);
493 }
494
495 gtk_menu_shell_append(GTK_MENU_SHELL(ct->menu), widget);
496
497 if(groups) {
498 uic_add_group_widget(obj->ctx, widget, (ui_enablefunc)ui_set_enabled, groups);
499 cxListDestroy(groups);
500 }
501 } 385 }
502 386
503 #endif /* GTK_MAJOR_VERSION <= 3 */ 387 #endif /* GTK_MAJOR_VERSION <= 3 */
504 388
505 389
546 GMenu *menu = g_menu_new(); 430 GMenu *menu = g_menu_new();
547 ui_gmenu_add_menu_items(menu, 0, mi, obj); 431 ui_gmenu_add_menu_items(menu, 0, mi, obj);
548 g_menu_append_submenu(parent, mi->label, G_MENU_MODEL(menu)); 432 g_menu_append_submenu(parent, mi->label, G_MENU_MODEL(menu));
549 } 433 }
550 434
435 static void action_enable(GSimpleAction *action, int enabled) {
436 g_simple_action_set_enabled(action, enabled);
437 }
438
551 void ui_gmenu_add_menuitem(GMenu *parent, int index, UiMenuItemI *item, UiObject *obj) { 439 void ui_gmenu_add_menuitem(GMenu *parent, int index, UiMenuItemI *item, UiObject *obj) {
552 UiMenuItem *i = (UiMenuItem*)item; 440 UiMenuItem *i = (UiMenuItem*)item;
553 441
554 GSimpleAction *action = g_simple_action_new(item->id, NULL); 442 GSimpleAction *action = g_simple_action_new(item->id, NULL);
555 g_action_map_add_action(obj->ctx->action_map, G_ACTION(action)); 443 g_action_map_add_action(obj->ctx->action_map, G_ACTION(action));
444
445 if(i->groups) {
446 CxList *groups = cxArrayListCreateSimple(sizeof(int), i->ngroups);
447 cxListAddArray(groups, i->groups, i->ngroups);
448 uic_add_group_widget(obj->ctx, action, (ui_enablefunc)action_enable, groups);
449 cxListDestroy(groups);
450 }
556 451
557 if(i->callback != NULL) { 452 if(i->callback != NULL) {
558 UiEventData *event = malloc(sizeof(UiEventData)); 453 UiEventData *event = malloc(sizeof(UiEventData));
559 event->obj = obj; 454 event->obj = obj;
560 event->userdata = i->userdata; 455 event->userdata = i->userdata;
700 } 595 }
701 596
702 list->oldcount = i; 597 list->oldcount = i;
703 } 598 }
704 599
600
601 /* --------------------- context menu / menubuilder --------------------- */
602
603 static void remove_popover(GtkWidget *object, GtkPopoverMenu *menu) {
604 gtk_widget_unparent(GTK_WIDGET(menu));
605 }
606
607 UIMENU ui_contextmenu_create(UiMenuBuilder *builder, UiObject *obj, GtkWidget *widget) {
608 GMenu *menu = g_menu_new();
609 ui_gmenu_add_menu_items(menu, 0, builder->menus_begin, obj);
610 GtkWidget *contextmenu = gtk_popover_menu_new_from_model(G_MENU_MODEL(menu));
611 gtk_popover_set_has_arrow(GTK_POPOVER(contextmenu), FALSE);
612 gtk_widget_set_halign(contextmenu, GTK_ALIGN_START);
613 gtk_widget_set_parent(GTK_WIDGET(contextmenu), widget);
614 g_signal_connect(
615 widget,
616 "destroy",
617 G_CALLBACK(remove_popover),
618 contextmenu);
619 return GTK_POPOVER_MENU(contextmenu);
620 }
621
622 static void gesture_button_press(GtkGestureClick *gesture, gint n_press, gdouble x, gdouble y, gpointer user_data) {
623 gtk_popover_set_pointing_to(GTK_POPOVER(user_data), &(GdkRectangle){ x, y, 0, 0 });
624 gtk_popover_popup(GTK_POPOVER(user_data));
625 }
626
627 void ui_widget_set_contextmenu(GtkWidget *widget, GtkPopoverMenu *menu) {
628 GtkGesture *gesture = gtk_gesture_click_new();
629 gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(gesture), 3);
630 gtk_widget_add_controller(widget, GTK_EVENT_CONTROLLER(gesture));
631 g_signal_connect(gesture, "pressed", G_CALLBACK(gesture_button_press), menu);
632 }
633
634 void ui_contextmenu_popup(UIMENU menu, UIWIDGET widget, int x, int y) {
635 gtk_popover_set_pointing_to(GTK_POPOVER(menu), &(GdkRectangle){ x, y, 0, 0 });
636 gtk_popover_popup(GTK_POPOVER(menu));
637 }
638
705 #endif 639 #endif

mercurial