implement menu item events (Win32)

Wed, 31 Dec 2025 10:06:15 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 31 Dec 2025 10:06:15 +0100
changeset 1035
86d3a45dc928
parent 1034
330b415910bd
child 1036
24677835f298

implement menu item events (Win32)

ucx/json.c file | annotate | diff | comparison | revisions
ui/common/context.c file | annotate | diff | comparison | revisions
ui/common/context.h file | annotate | diff | comparison | revisions
ui/common/object.c file | annotate | diff | comparison | revisions
ui/win32/menu.c file | annotate | diff | comparison | revisions
ui/win32/toolkit.c file | annotate | diff | comparison | revisions
ui/win32/toolkit.h file | annotate | diff | comparison | revisions
ui/win32/window.c file | annotate | diff | comparison | revisions
ui/win32/window.h file | annotate | diff | comparison | revisions
--- a/ucx/json.c	Wed Dec 31 09:16:02 2025 +0100
+++ b/ucx/json.c	Wed Dec 31 10:06:15 2025 +0100
@@ -485,7 +485,7 @@
         CxJsonValue *parent = json->vbuf.data[json->vbuf.size - 1];
         assert(parent != NULL);
         if (parent->type == CX_JSON_ARRAY) {
-            if (cx_array_add_a(json->allocator, parent->array, &v)) {
+            if (cx_array_add_a(json->allocator, parent->array, v)) {
                 goto create_json_value_exit_error; // LCOV_EXCL_LINE
             }
         } else if (parent->type == CX_JSON_OBJECT) {
--- a/ui/common/context.c	Wed Dec 31 09:16:02 2025 +0100
+++ b/ui/common/context.c	Wed Dec 31 10:06:15 2025 +0100
@@ -777,6 +777,8 @@
             v->observers = ui_add_observer(v->observers, f, data);
             break;
         }
+        case UI_VAR_GENERIC: break;
+        case UI_VAR_SPECIAL: break;
     }
 }
 
--- a/ui/common/context.h	Wed Dec 31 09:16:02 2025 +0100
+++ b/ui/common/context.h	Wed Dec 31 10:06:15 2025 +0100
@@ -84,6 +84,10 @@
     GtkAccelGroup *accel_group;
 #endif 
 #endif
+#ifdef UI_WIN32
+    CxMap *command_map; // key: int, value: UiCommand
+    uint64_t command_id_counter;
+#endif
     
     // allow only one document to be attached
     // attaching a document will automatically detach the current document
--- a/ui/common/object.c	Wed Dec 31 09:16:02 2025 +0100
+++ b/ui/common/object.c	Wed Dec 31 10:06:15 2025 +0100
@@ -107,15 +107,11 @@
 }
 
 UiObject* uic_object_new_toplevel(void) {
-    fflush(stdout);
     CxMempool *mp = cxMempoolCreateSimple(256);
     UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObjectPrivate));
-    fflush(stdout);
     obj->ctx = uic_context(obj, mp);
     obj->ctx->parent = ui_global_context();
-    fflush(stdout);
     uic_object_created(obj);
-    fflush(stdout);
     return obj;
 }
 
--- a/ui/win32/menu.c	Wed Dec 31 09:16:02 2025 +0100
+++ b/ui/win32/menu.c	Wed Dec 31 10:06:15 2025 +0100
@@ -58,7 +58,6 @@
     UiMenu *menu = (UiMenu*)item;
     HMENU hMenu = CreatePopupMenu();
     AppendMenu(parent, MF_POPUP, (UINT_PTR)hMenu, menu->label);
-
     int i = 0;
     UiMenuItemI *child = menu->items_begin;
     while (child) {
@@ -67,9 +66,30 @@
     }
 }
 
+static void menu_item_clicked(UiObject *obj, UiMenuItem *item) {
+    UiEvent event;
+    event.obj = obj;
+    event.window = obj->window;
+    event.document = obj->ctx->document;
+    event.eventdata = NULL;
+    event.eventdatatype = 0;
+    event.intval = 0;
+    event.set = 0;
+    if (item->callback) {
+        item->callback(&event, item->userdata);
+    }
+}
+
 void ui_add_menu_item(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) {
+    uint64_t id = ++obj->ctx->command_id_counter;
+
     UiMenuItem *i = (UiMenuItem*)item;
-    AppendMenu(parent, MF_STRING, 0, i->label);
+    AppendMenu(parent, MF_STRING, id, i->label);
+
+    UiCommand cmd;
+    cmd.callback = (ui_command_func)menu_item_clicked;
+    cmd.userdata = i;
+    cxMapPut(obj->ctx->command_map, id, &cmd);
 }
 
 void ui_add_menu_checkitem(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) {
--- a/ui/win32/toolkit.c	Wed Dec 31 09:16:02 2025 +0100
+++ b/ui/win32/toolkit.c	Wed Dec 31 10:06:15 2025 +0100
@@ -117,6 +117,16 @@
             break;
         }
         case WM_COMMAND: {
+            UiWindow *win = ui_widget2window(widget);
+            if (win) {
+                uint64_t id = LOWORD(wParam);
+                UiCommand *cmd = cxMapGet(win->obj->ctx->command_map, id);
+                if (cmd) {
+                    cmd->callback(win->obj, cmd->userdata);
+                    break;
+                }
+            }
+
             HWND hwndCtrl = (HWND)lParam;
             W32Widget *cmdWidget = (W32Widget*)GetWindowLongPtr(hwndCtrl, GWLP_USERDATA);
             if (cmdWidget && cmdWidget->wclass->eventproc) {
--- a/ui/win32/toolkit.h	Wed Dec 31 09:16:02 2025 +0100
+++ b/ui/win32/toolkit.h	Wed Dec 31 10:06:15 2025 +0100
@@ -55,6 +55,12 @@
 
 LRESULT CALLBACK ui_default_eventproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
+typedef void(*ui_command_func)(UiObject *, void *userdata);
+typedef struct UiCommand {
+    ui_command_func callback;
+    void *userdata;
+} UiCommand;
+
 HFONT ui_win32_get_font(void);
 void ui_win32_set_ui_font(HWND control);
 
--- a/ui/win32/window.c	Wed Dec 31 09:16:02 2025 +0100
+++ b/ui/win32/window.c	Wed Dec 31 10:06:15 2025 +0100
@@ -29,6 +29,7 @@
 #include "window.h"
 #include <Windows.h>
 
+#include "toolkit.h"
 #include "container.h"
 
 #include "../common/object.h"
@@ -70,8 +71,16 @@
     }
 }
 
+UiWindow* ui_widget2window(W32Widget *widget) {
+    if (widget->wclass != &w32_toplevel_widget_class) {
+        return NULL;
+    }
+    return (UiWindow*)widget;
+}
+
 static UiObject* create_window(const char *title, bool simple) {
     UiObject *obj = uic_object_new_toplevel();
+    obj->ctx->command_map = cxHashMapCreate(obj->ctx->allocator, sizeof(UiCommand), 64);
 
     HWND hwnd = CreateWindowExA(
             0,
--- a/ui/win32/window.h	Wed Dec 31 09:16:02 2025 +0100
+++ b/ui/win32/window.h	Wed Dec 31 10:06:15 2025 +0100
@@ -51,6 +51,8 @@
 int ui_window_widget_event(W32Widget *widget, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 void ui_window_widget_show(W32Widget *w, BOOLEAN show);
 
+UiWindow* ui_widget2window(W32Widget *widget);
+
 #ifdef	__cplusplus
 }
 #endif

mercurial