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 |