73 } |
73 } |
74 |
74 |
75 return mb; |
75 return mb; |
76 } |
76 } |
77 |
77 |
|
78 GtkMenu* ui_create_menu(UiMenuBuilder *builder, UiObject *obj) { |
|
79 GtkWidget *menu_widget = gtk_menu_new(); |
|
80 ui_add_menu_items(menu_widget, 0, builder->menus_begin, obj); |
|
81 return GTK_MENU(menu_widget); |
|
82 } |
|
83 |
78 void ui_add_menu_items(GtkWidget *parent, int i, UiMenu *menu, UiObject *obj) { |
84 void ui_add_menu_items(GtkWidget *parent, int i, UiMenu *menu, UiObject *obj) { |
79 UiMenuItemI *it = menu->items_begin; |
85 UiMenuItemI *it = menu->items_begin; |
80 int index = 0; |
86 int index = 0; |
81 while(it) { |
87 while(it) { |
82 createMenuItem[it->type](parent, index, it, obj); |
88 createMenuItem[it->type](parent, index, it, obj); |
366 } |
371 } |
367 } |
372 } |
368 return FALSE; |
373 return FALSE; |
369 } |
374 } |
370 |
375 |
371 UIMENU ui_contextmenu(UiObject *obj) { |
376 void ui_widget_set_contextmenu(GtkWidget *widget, GtkMenu *menu) { |
372 UiContainer *ct = uic_get_current_container(obj); |
|
373 return ui_contextmenu_w(obj, ct->current); |
|
374 } |
|
375 |
|
376 UIMENU ui_contextmenu_w(UiObject *obj, UIWIDGET widget) { |
|
377 UiContainer *ct = uic_get_current_container(obj); |
|
378 |
|
379 GtkMenu *menu = GTK_MENU(gtk_menu_new()); |
|
380 g_signal_connect(widget, "button-press-event", (GCallback) ui_button_press_event, menu); |
377 g_signal_connect(widget, "button-press-event", (GCallback) ui_button_press_event, menu); |
381 |
|
382 ct->menu = menu; |
|
383 return menu; |
|
384 } |
378 } |
385 |
379 |
386 void ui_contextmenu_popup(UIMENU menu) { |
380 void ui_contextmenu_popup(UIMENU menu) { |
387 #if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 16 |
381 #if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 16 |
388 gtk_menu_popup_at_pointer(menu, NULL); |
382 gtk_menu_popup_at_pointer(menu, NULL); |
389 #else |
383 #else |
390 gtk_menu_popup(menu, NULL, NULL, 0, 0, 0, gtk_get_current_event_time()); |
384 gtk_menu_popup(menu, NULL, NULL, 0, 0, 0, gtk_get_current_event_time()); |
391 #endif |
385 #endif |
392 } |
|
393 */ |
|
394 |
|
395 void ui_widget_menuitem(UiObject *obj, char *label, ui_callback f, void *userdata) { |
|
396 ui_widget_menuitem_gr(obj, label, f, userdata, -1); |
|
397 } |
|
398 |
|
399 void ui_widget_menuitem_gr(UiObject *obj, char *label, ui_callback f, void *userdata, ...) { |
|
400 UiContainer *ct = uic_get_current_container(obj); |
|
401 if(!ct->menu) { |
|
402 return; |
|
403 } |
|
404 |
|
405 // add groups |
|
406 CxList *groups = NULL; |
|
407 va_list ap; |
|
408 va_start(ap, userdata); |
|
409 int group; |
|
410 while((group = va_arg(ap, int)) != -1) { |
|
411 if(!groups) { |
|
412 groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 16); |
|
413 } |
|
414 cxListAdd(groups, &group); |
|
415 } |
|
416 va_end(ap); |
|
417 |
|
418 // create menuitem |
|
419 GtkWidget *widget = gtk_menu_item_new_with_mnemonic(label); |
|
420 gtk_widget_show(widget); |
|
421 |
|
422 if(f) { |
|
423 UiEventData *event = malloc(sizeof(UiEventData)); |
|
424 event->obj = obj; |
|
425 event->userdata = userdata; |
|
426 event->callback = f; |
|
427 event->value = 0; |
|
428 event->customdata = NULL; |
|
429 |
|
430 g_signal_connect( |
|
431 widget, |
|
432 "activate", |
|
433 G_CALLBACK(ui_menu_event_wrapper), |
|
434 event); |
|
435 g_signal_connect( |
|
436 widget, |
|
437 "destroy", |
|
438 G_CALLBACK(ui_destroy_userdata), |
|
439 event); |
|
440 } |
|
441 |
|
442 gtk_menu_shell_append(GTK_MENU_SHELL(ct->menu), widget); |
|
443 |
|
444 if(groups) { |
|
445 uic_add_group_widget(obj->ctx, widget, (ui_enablefunc)ui_set_enabled, groups); |
|
446 cxListDestroy(groups); |
|
447 } |
|
448 } |
|
449 |
|
450 void ui_widget_menuitem_st(UiObject *obj, char *stockid, ui_callback f, void *userdata) { |
|
451 ui_widget_menuitem_stgr(obj, stockid, f, userdata, -1); |
|
452 } |
|
453 |
|
454 void ui_widget_menuitem_stgr(UiObject *obj, char *stockid, ui_callback f, void *userdata, ...) { |
|
455 UiContainer *ct = uic_get_current_container(obj); |
|
456 if(!ct->menu) { |
|
457 return; |
|
458 } |
|
459 |
|
460 // add groups |
|
461 CxList *groups = NULL; |
|
462 va_list ap; |
|
463 va_start(ap, userdata); |
|
464 int group; |
|
465 while((group = va_arg(ap, int)) != -1) { |
|
466 if(!groups) { |
|
467 groups = cxArrayListCreate(cxDefaultAllocator, NULL, sizeof(int), 16); |
|
468 } |
|
469 cxListAdd(groups, &group); |
|
470 } |
|
471 va_end(ap); |
|
472 |
|
473 // create menuitem |
|
474 GtkWidget *widget = gtk_image_menu_item_new_from_stock(stockid, obj->ctx->accel_group); |
|
475 gtk_widget_show(widget); |
|
476 |
|
477 if(f) { |
|
478 UiEventData *event = malloc(sizeof(UiEventData)); |
|
479 event->obj = obj; |
|
480 event->userdata = userdata; |
|
481 event->callback = f; |
|
482 event->value = 0; |
|
483 event->customdata = NULL; |
|
484 |
|
485 g_signal_connect( |
|
486 widget, |
|
487 "activate", |
|
488 G_CALLBACK(ui_menu_event_wrapper), |
|
489 event); |
|
490 g_signal_connect( |
|
491 widget, |
|
492 "destroy", |
|
493 G_CALLBACK(ui_destroy_userdata), |
|
494 event); |
|
495 } |
|
496 |
|
497 gtk_menu_shell_append(GTK_MENU_SHELL(ct->menu), widget); |
|
498 |
|
499 if(groups) { |
|
500 uic_add_group_widget(obj->ctx, widget, (ui_enablefunc)ui_set_enabled, groups); |
|
501 cxListDestroy(groups); |
|
502 } |
|
503 } |
386 } |
504 |
387 |
505 #endif /* GTK_MAJOR_VERSION <= 3 */ |
388 #endif /* GTK_MAJOR_VERSION <= 3 */ |
506 |
389 |
507 |
390 |
702 } |
585 } |
703 |
586 |
704 list->oldcount = i; |
587 list->oldcount = i; |
705 } |
588 } |
706 |
589 |
|
590 |
|
591 /* --------------------- context menu / menubuilder --------------------- */ |
|
592 |
|
593 GtkPopoverMenu* ui_create_menu(UiMenuBuilder *builder, UiObject *obj) { |
|
594 GMenu *menu = g_menu_new(); |
|
595 ui_gmenu_add_menu_items(menu, 0, builder->menus_begin, obj); |
|
596 GtkWidget *contextmenu = gtk_popover_menu_new_from_model(G_MENU_MODEL(menu)); |
|
597 gtk_popover_set_has_arrow(GTK_POPOVER(contextmenu), FALSE); |
|
598 gtk_widget_set_halign(contextmenu, GTK_ALIGN_START); |
|
599 return GTK_POPOVER_MENU(contextmenu); |
|
600 } |
|
601 |
|
602 static void gesture_button_press(GtkGestureClick *gesture, gint n_press, gdouble x, gdouble y, gpointer user_data) { |
|
603 gtk_popover_set_pointing_to (GTK_POPOVER (user_data), &(GdkRectangle){ x, y, 0, 0 }); |
|
604 gtk_popover_popup(GTK_POPOVER(user_data)); |
|
605 } |
|
606 |
|
607 static void remove_popover(GtkWidget *object, GtkPopoverMenu *menu) { |
|
608 gtk_widget_unparent(GTK_WIDGET(menu)); |
|
609 } |
|
610 |
|
611 void ui_widget_set_contextmenu(GtkWidget *widget, GtkPopoverMenu *menu) { |
|
612 GtkGesture *gesture = gtk_gesture_click_new(); |
|
613 gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(gesture), 3); |
|
614 gtk_widget_add_controller(widget, GTK_EVENT_CONTROLLER(gesture)); |
|
615 g_signal_connect(gesture, "pressed", G_CALLBACK(gesture_button_press), menu); |
|
616 gtk_widget_set_parent(GTK_WIDGET(menu), widget); |
|
617 g_signal_connect( |
|
618 widget, |
|
619 "destroy", |
|
620 G_CALLBACK(remove_popover), |
|
621 menu); |
|
622 } |
|
623 |
707 #endif |
624 #endif |