From 81c47a97338ff14b451961b681ddfc0eddb50a30 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Thu, 2 Oct 2025 02:17:27 +0000 Subject: [PATCH] stuff git-svn-id: http://svn2.nishi.boats/svn/milsko/trunk@131 b9cfdab3-6d41-4d17-bbe4-086880011989 --- GNUmakefile | 2 +- doc/index.html | 24 ++++++++- examples/example.c | 12 +++-- include/Mw/Menu.h | 2 +- include/Mw/Milsko.h | 1 + include/Mw/SubMenu.h | 27 ++++++++++ include/Mw/TypeDefs.h | 8 +++ src/core.c | 16 +++--- src/widget/menu.c | 45 +++++++++------- src/widget/submenu.c | 123 ++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 225 insertions(+), 35 deletions(-) create mode 100644 include/Mw/SubMenu.h create mode 100644 src/widget/submenu.c diff --git a/GNUmakefile b/GNUmakefile index cb86487..125849c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -32,7 +32,7 @@ E_LIBS = $(LIBS) -lMw L_OBJS = src/core.o src/default.o src/draw.o src/lowlevel.o src/font.o src/boldfont.o src/error.o L_OBJS += src/external/ds.o src/external/image.o -L_OBJS += src/widget/window.o src/widget/button.o src/widget/frame.o src/widget/menu.o +L_OBJS += src/widget/window.o src/widget/button.o src/widget/frame.o src/widget/menu.o src/widget/submenu.o ifeq ($(TARGET),NetBSD) CFLAGS += -I/usr/X11R7/include -I/usr/pkg/include diff --git a/doc/index.html b/doc/index.html index 753ae64..e38b728 100644 --- a/doc/index.html +++ b/doc/index.html @@ -188,6 +188,12 @@
Mw/StringDefs.h
+
+ Mw/SubMenu.h +
+
+ MwSubMenuClass +
Mw/TypeDefs.h
@@ -1373,9 +1379,9 @@
-
MWDECL void* MwMenuAdd (
+
MWDECL MwMenu MwMenuAdd (
 	MwWidget handle,
-	void* menu,
+	MwMenu menu,
 	const char* name
 );
@@ -1494,6 +1500,20 @@

+

Mw/SubMenu.h

+
+
+ SubMenu widget. +
+
+
+
MWDECL MwClass MwSubMenuClass;
+
+
+ SubMenu widget class. +
+
+

Mw/TypeDefs.h

diff --git a/examples/example.c b/examples/example.c index 90bc5dc..e0a2ebe 100644 --- a/examples/example.c +++ b/examples/example.c @@ -46,6 +46,8 @@ void resize(MwWidget handle, void* user_data, void* call_data) { } int main() { + MwMenu m; + window = MwVaCreateWidget(MwWindowClass, "main", NULL, 0, 0, 400, 400, MwNtitle, "hello world", NULL); @@ -72,12 +74,12 @@ int main() { MwAddUserHandler(button3, MwNactivateHandler, handler, NULL); MwAddUserHandler(button4, MwNactivateHandler, handler, NULL); - MwMenuAdd(menu, NULL, "test 1"); - MwMenuAdd(menu, NULL, "test 2"); - MwMenuAdd(menu, NULL, "test 3"); - MwMenuAdd(menu, NULL, "test 4"); + m = MwMenuAdd(menu, NULL, "test 1"); + MwMenuAdd(menu, m, "test 2"); + m = MwMenuAdd(menu, m, "test 3"); + MwMenuAdd(menu, m, "test 4"); + MwMenuAdd(menu, m, "test 6"); MwMenuAdd(menu, NULL, "?test 5"); - MwMenuAdd(menu, NULL, "test 6"); MwLoop(window); } diff --git a/include/Mw/Menu.h b/include/Mw/Menu.h index b94507b..847d4e6 100644 --- a/include/Mw/Menu.h +++ b/include/Mw/Menu.h @@ -25,7 +25,7 @@ MWDECL MwClass MwMenuClass; * %param name Menu name * %return Menu */ -MWDECL void* MwMenuAdd(MwWidget handle, void* menu, const char* name); +MWDECL MwMenu MwMenuAdd(MwWidget handle, MwMenu menu, const char* name); #ifdef __cplusplus } diff --git a/include/Mw/Milsko.h b/include/Mw/Milsko.h index 83ba060..1a4b529 100644 --- a/include/Mw/Milsko.h +++ b/include/Mw/Milsko.h @@ -18,6 +18,7 @@ #include #include +#include #include #include diff --git a/include/Mw/SubMenu.h b/include/Mw/SubMenu.h new file mode 100644 index 0000000..d7150b8 --- /dev/null +++ b/include/Mw/SubMenu.h @@ -0,0 +1,27 @@ +/* $Id$ */ +/*! + * %file Mw/SubMenu.h + * %brief SubMenu widget + */ +#ifndef __MW_SUBMENU_H__ +#define __MW_SUBMENU_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * %brief SubMenu widget class + */ +MWDECL MwClass MwSubMenuClass; + +MWDECL void MwSubMenuAppear(MwWidget handle, MwMenu menu, MwPoint* point); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 5be2552..bb6362b 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -18,8 +18,10 @@ typedef struct _MwVoidKeyValue MwVoidKeyValue; typedef struct _MwFont MwFont; #ifdef _MILSKO typedef struct _MwWidget *MwWidget, MwWidgetRec; +typedef struct _MwMenu * MwMenu, MwMenuRec; #else typedef void* MwWidget; +typedef void* MwMenu; #endif typedef void (*MwHandler)(MwWidget handle); typedef void (*MwUserHandler)(MwWidget handle, void* user_data, void* call_data); @@ -83,6 +85,12 @@ struct _MwWidget { MwUserHandlerKeyValue* handler; MwVoidKeyValue* data; }; + +struct _MwMenu { + char* name; + MwWidget wsub; + MwMenu* sub; +}; #endif struct _MwClass { diff --git a/src/core.c b/src/core.c index ab3b131..e962ed9 100644 --- a/src/core.c +++ b/src/core.c @@ -55,9 +55,13 @@ MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, h->name = malloc(strlen(name) + 1); strcpy(h->name, name); - h->parent = parent; - h->children = NULL; - h->lowlevel = MwLLCreate(parent == NULL ? NULL : parent->lowlevel, x, y, width, height); + h->parent = parent; + h->children = NULL; + if((h->lowlevel = MwLLCreate(parent == NULL ? NULL : parent->lowlevel, x, y, width, height)) == NULL) { + free(h->name); + free(h); + return NULL; + } h->widget_class = widget_class; h->pressed = 0; h->close = 0; @@ -115,10 +119,8 @@ void MwDestroyWidget(MwWidget handle) { if(handle->children != NULL) { for(i = 0; i < arrlen(handle->children); i++) { - if(handle->children[i] == handle) { - MwDestroyWidget(handle->children[i]); - break; - } + MwDestroyWidget(handle->children[i]); + break; } arrfree(handle->children); } diff --git a/src/widget/menu.c b/src/widget/menu.c index b56c69a..d2e748c 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -3,17 +3,10 @@ #include "../external/stb_ds.h" -typedef struct menu menu_t; - -struct menu { - char* name; - menu_t** sub; -}; - static void set_xywh(MwWidget handle) { - int height = 0; - int i; - menu_t* m = handle->internal; + int height = 0; + int i; + MwMenu m = handle->internal; for(i = 0; i < arrlen(m->sub); i++) { int h = MwTextHeight(handle, m->sub[i]->name); @@ -33,9 +26,10 @@ static void set_xywh(MwWidget handle) { } static void create(MwWidget handle) { - menu_t* m = malloc(sizeof(*m)); + MwMenu m = malloc(sizeof(*m)); m->name = NULL; + m->wsub = NULL; m->sub = NULL; handle->internal = m; @@ -44,7 +38,7 @@ static void create(MwWidget handle) { set_xywh(handle); } -static void recursive_free(menu_t* m) { +static void recursive_free(MwMenu m) { int i; for(i = 0; i < arrlen(m->sub); i++) { @@ -57,7 +51,7 @@ static void recursive_free(menu_t* m) { } static void destroy(MwWidget handle) { - menu_t* m = handle->internal; + MwMenu m = handle->internal; recursive_free(m); } @@ -67,7 +61,7 @@ static void draw(MwWidget handle) { MwPoint p; MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); - menu_t* m = handle->internal; + MwMenu m = handle->internal; int i; p.x = 10; @@ -98,6 +92,18 @@ static void draw(MwWidget handle) { if(handle->pressed && r.x <= handle->pressed_point.x && r.y <= handle->pressed_point.y && handle->pressed_point.x <= (int)(r.x + r.width) && handle->pressed_point.y <= (int)(r.y + r.height)) { MwDrawFrame(handle, &r, base, 0); + if(m->sub[i]->wsub == NULL && arrlen(m->sub[i]->sub) > 0) { + MwPoint p2; + + p2.x = p.x - tw / 2 - 5; + p2.y = p.y + th / 2 + 5; + + m->sub[i]->wsub = MwCreateWidget(MwSubMenuClass, "submenu", handle, 0, 0, 0, 0); + MwSubMenuAppear(m->sub[i]->wsub, m->sub[i], &p2); + } + } else if(!handle->pressed && m->sub[i]->wsub != NULL) { + MwDestroyWidget(m->sub[i]->wsub); + m->sub[i]->wsub = NULL; } MwDrawText(handle, &p, m->sub[i]->name + incr, 1, text); @@ -123,11 +129,12 @@ MwClassRec MwMenuClassRec = { }; MwClass MwMenuClass = &MwMenuClassRec; -void* MwMenuAdd(MwWidget handle, void* menu, const char* name) { - menu_t* m = menu == NULL ? handle->internal : menu; - menu_t* new = malloc(sizeof(*new)); - new->name = malloc(strlen(name) + 1); - new->sub = NULL; +MwMenu MwMenuAdd(MwWidget handle, MwMenu menu, const char* name) { + MwMenu m = menu == NULL ? handle->internal : menu; + MwMenu new = malloc(sizeof(*new)); + new->name = malloc(strlen(name) + 1); + new->sub = NULL; + new->wsub = NULL; strcpy(new->name, name); diff --git a/src/widget/submenu.c b/src/widget/submenu.c new file mode 100644 index 0000000..53638c7 --- /dev/null +++ b/src/widget/submenu.c @@ -0,0 +1,123 @@ +/* $Id$ */ +#include + +#include "../external/stb_ds.h" + +static void create(MwWidget handle) { +#ifdef _WIN32 +#else + XUnmapWindow(handle->lowlevel->display, handle->lowlevel->window); +#endif + + MwSetDefault(handle); +} + +static void null_all(MwMenu menu) { + int i; + for(i = 0; i < arrlen(menu->sub); i++) { + null_all(menu->sub[i]); + } + menu->wsub = NULL; +} + +static void destroy(MwWidget handle) { + MwMenu menu = handle->internal; + + null_all(menu); +} + +static void draw(MwWidget handle) { + MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); + MwRect r; + MwMenu menu = handle->internal; + + r.x = 0; + r.y = 0; + r.width = MwGetInteger(handle, MwNwidth); + r.height = MwGetInteger(handle, MwNheight); + + MwDrawFrame(handle, &r, base, 0); + MwDrawRect(handle, &r, base); + + if(menu != NULL) { + MwPoint p; + int i; + + p.x = 0; + p.y = 5; + + for(i = 0; i < arrlen(menu->sub); i++) { + int tw = MwTextWidth(handle, menu->sub[i]->name); + int th = MwTextHeight(handle, menu->sub[i]->name); + + p.x = 5 + tw / 2; + + if(menu->sub[i]->wsub == NULL && arrlen(menu->sub[i]->sub) > 0) { + MwPoint p2 = p; + p2.x += tw / 2 + 5; + p2.y -= 5; + + menu->sub[i]->wsub = MwCreateWidget(MwSubMenuClass, "submenu", handle, 0, 0, 0, 0); + MwSubMenuAppear(menu->sub[i]->wsub, menu->sub[i], &p2); + } + + p.y += th / 2; + MwDrawText(handle, &p, menu->sub[i]->name, 1, text); + p.y += th / 2; + } + } + + MwLLFreeColor(text); + MwLLFreeColor(base); +} + +MwClassRec MwSubMenuClassRec = { + create, /* create */ + destroy, /* destroy */ + draw, /* draw */ + NULL, /* click */ + NULL /* parent_resize */ +}; +MwClass MwSubMenuClass = &MwSubMenuClassRec; + +void MwSubMenuAppear(MwWidget handle, MwMenu menu, MwPoint* point) { + int i, w = 0, h = 0; +#ifdef _WIN32 +#else + Atom wndtype = XInternAtom(handle->lowlevel->display, "_NET_WM_WINDOW_TYPE", False); + Atom wndmenu = XInternAtom(handle->lowlevel->display, "_NET_WM_WINDOW_TYPE_MENU", False); + int x = 0, y = 0; + Window child; + XSetWindowAttributes xswa; + + xswa.override_redirect = True; + + XTranslateCoordinates(handle->parent->lowlevel->display, handle->parent->lowlevel->window, RootWindow(handle->parent->lowlevel->display, DefaultScreen(handle->parent->lowlevel->display)), 0, 0, &x, &y, &child); + + XReparentWindow(handle->lowlevel->display, handle->lowlevel->window, RootWindow(handle->lowlevel->display, DefaultScreen(handle->lowlevel->display)), x + point->x, y + point->y); + + XChangeWindowAttributes(handle->lowlevel->display, handle->lowlevel->window, CWOverrideRedirect, &xswa); + XChangeProperty(handle->lowlevel->display, handle->lowlevel->window, wndtype, 4, 32, PropModeReplace, (unsigned char*)&wndmenu, 1); + + XMapWindow(handle->lowlevel->display, handle->lowlevel->window); +#endif + + handle->internal = menu; + + for(i = 0; i < arrlen(menu->sub); i++) { + int tw = MwTextWidth(handle, menu->sub[i]->name); + h += MwTextHeight(handle, menu->sub[i]->name); + if(tw > w) { + w = tw; + } + } + + w += 10; + h += 10; + + MwVaApply(handle, + MwNwidth, w, + MwNheight, h, + NULL); +}