ui/gtk/menu.c

branch
newapi
changeset 311
450a813dc2a5
parent 294
7232a8e68eeb
child 312
3f2b3d15668b
--- a/ui/gtk/menu.c	Thu Sep 26 22:43:13 2024 +0200
+++ b/ui/gtk/menu.c	Sun Sep 29 11:29:37 2024 +0200
@@ -42,8 +42,7 @@
 #include <cx/linked_list.h>
 #include <cx/array_list.h>
 
-#if UI_GTK2 || UI_GTK3
-
+#if GTK_MAJOR_VERSION <= 3
 
 static ui_menu_add_f createMenuItem[] = {
     /* UI_MENU                 */ add_menu_widget,
@@ -501,4 +500,177 @@
     }
 }
 
-#endif /* UI_GTK2 || UI_GTK3 */
+#endif /* GTK_MAJOR_VERSION <= 3 */
+
+
+
+#if GTK_MAJOR_VERSION >= 4
+
+
+
+static ui_gmenu_add_f createMenuItem[] = {
+    /* UI_MENU                 */ ui_gmenu_add_menu,
+    /* UI_MENU_ITEM            */ ui_gmenu_add_menuitem,
+    /* UI_MENU_CHECK_ITEM      */ ui_gmenu_add_checkitem,
+    /* UI_MENU_RADIO_ITEM      */ ui_gmenu_add_radioitem,
+    /* UI_MENU_ITEM_LIST       */ ui_gmenu_add_menuitem_list,
+    /* UI_MENU_CHECKITEM_LIST  */ ui_gmenu_add_menuitem_list,
+    /* UI_MENU_RADIOITEM_LIST  */ ui_gmenu_add_menuitem_list,
+    /* UI_MENU_SEPARATOR       */ ui_gmenu_add_menuseparator
+};
+
+void ui_gmenu_add_menu_items(GMenu *parent, int i, UiMenu *menu, UiObject *obj) {
+    UiMenuItemI *it = menu->items_begin;
+    int index = 0;
+    while(it) {
+        createMenuItem[it->type](parent, index, it, obj);
+        it = it->next;
+        index++;
+    }
+}
+
+void ui_gmenu_add_menu(GMenu *parent, int index, UiMenuItemI *item, UiObject *obj) {
+    UiMenu *mi = (UiMenu*)item;
+    GMenu *menu = g_menu_new();
+    ui_gmenu_add_menu_items(menu, 0, mi, obj);
+    g_menu_append_submenu(parent, mi->label, G_MENU_MODEL(menu));
+}
+
+void ui_gmenu_add_menuitem(GMenu *parent, int index, UiMenuItemI *item, UiObject *obj) {
+    UiMenuItem *i = (UiMenuItem*)item;
+
+    GSimpleAction *action = g_simple_action_new(item->id, NULL);
+    g_action_map_add_action(obj->ctx->action_map, G_ACTION(action));
+    
+    if(i->callback != NULL) {
+        UiEventData *event = malloc(sizeof(UiEventData));
+        event->obj = obj;
+        event->userdata = i->userdata;
+        event->callback = i->callback;
+        event->value = 0;
+        event->customdata = NULL;
+
+        g_signal_connect(
+                action,
+                "activate",
+                G_CALLBACK(ui_activate_event_wrapper),
+                event);
+        g_signal_connect(
+                obj->widget,
+                "destroy",
+                G_CALLBACK(ui_destroy_userdata),
+                event);
+    }
+    
+    char action_name[32];
+    snprintf(action_name, 32, "win.%s", item->id);
+    g_menu_append(parent, i->label, action_name);
+}
+
+void ui_gmenu_add_menuseparator(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) {
+    
+}
+
+void ui_gmenu_add_checkitem(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) {
+    UiMenuCheckItem *checkitem = (UiMenuCheckItem*)item;
+    
+    // TODO
+}
+
+void ui_gmenu_add_radioitem(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) {
+    
+}
+
+void ui_gmenu_add_menuitem_list(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) {
+    UiMenuItemList *il = (UiMenuItemList*)item; 
+    
+    const CxAllocator *a = obj->ctx->allocator;
+    
+    UiActiveGMenuItemList *ls = cxMalloc(
+            a,
+            sizeof(UiActiveGMenuItemList));
+    
+    ls->object = obj;
+    ls->menu = p;
+    ls->index = index;
+    ls->oldcount = 0;
+    ls->getvalue = il->getvalue;
+    
+    UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST);
+    ls->list = var->value;
+    
+    ls->callback = il->callback;
+    ls->userdata = il->userdata;
+    
+    ls->list->observers = ui_add_observer(
+            ls->list->observers,
+            (ui_callback)ui_update_gmenu_item_list,
+            ls);
+    
+    GSimpleAction *action = g_simple_action_new(item->id, g_variant_type_new("i"));
+    g_action_map_add_action(obj->ctx->action_map, G_ACTION(action));
+    snprintf(ls->action, 32, "win.%s", item->id);
+    
+    
+    UiEventData *event = malloc(sizeof(UiEventData));
+    event->obj = obj;
+    event->userdata = il->userdata;
+    event->callback = il->callback;
+    event->customdata = NULL;
+    event->value = 0;
+    
+    g_signal_connect(
+            action,
+            "activate",
+            G_CALLBACK(ui_activate_event_wrapper),
+            event);
+    g_signal_connect(
+            obj->widget,
+            "destroy",
+            G_CALLBACK(ui_destroy_userdata),
+            event);
+    
+    ui_update_gmenu_item_list(NULL, ls);
+}
+
+void ui_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEventData *event) {
+    int intval = event->value;
+    if(parameter && g_variant_is_of_type(parameter, G_VARIANT_TYPE_INT32)) {
+        intval = g_variant_get_int32(parameter);
+    }
+    
+    UiEvent evt;
+    evt.obj = event->obj;
+    evt.window = event->obj->window;
+    evt.document = event->obj->ctx->document;
+    evt.eventdata = event->customdata;
+    evt.intval = intval;
+    event->callback(&evt, event->userdata);    
+}
+
+void ui_update_gmenu_item_list(UiEvent *event, UiActiveGMenuItemList *list) {
+    // remove old items
+    for(int i=0;i<list->oldcount;i++) {
+        g_menu_remove(list->menu, list->index);
+    }
+    
+    // add list items
+    ui_getvaluefunc getvalue = list->getvalue;
+    int i = 0;
+    void* elm = ui_list_first(list->list);
+    while(elm) {
+        char *label = (char*) (getvalue ? getvalue(elm, 0) : elm);
+        
+        GMenuItem *item = g_menu_item_new(label, NULL);
+        GVariant *v = g_variant_new("i", i);
+        g_menu_item_set_action_and_target_value(item, list->action, v);
+        g_menu_insert_item(list->menu, list->index+i, item);
+        
+        elm = ui_list_next(list->list);
+        i++;
+    }
+    
+    list->oldcount = i;
+}
+
+#endif

mercurial