Wed, 31 Dec 2025 10:06:15 +0100
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