diff --git a/examples/basic/box.c b/examples/basic/box.c new file mode 100644 index 0000000..517a540 --- /dev/null +++ b/examples/basic/box.c @@ -0,0 +1,63 @@ +#include + +MwWidget window, box; + +void resize(MwWidget handle, void* user, void* client) { + int ww = MwGetInteger(handle, MwNwidth); + int wh = MwGetInteger(handle, MwNheight); + + (void)user; + (void)client; + + MwVaApply(box, + MwNwidth, ww, + MwNheight, wh, + NULL); +} + +int main() { + MwWidget box2, box3; + + MwLibraryInit(); + + window = MwVaCreateWidget(MwWindowClass, "main", NULL, MwDEFAULT, MwDEFAULT, 200, 200, + MwNtitle, "box", + NULL); + + box = MwVaCreateWidget(MwBoxClass, "box", window, 0, 0, 0, 0, + MwNpadding, 10, + NULL); + + box2 = MwVaCreateWidget(MwBoxClass, "box2", box, 0, 0, 0, 0, + MwNpadding, 10, + MwNorientation, MwVERTICAL, + NULL); + + box3 = MwVaCreateWidget(MwBoxClass, "box3", box, 0, 0, 0, 0, + MwNpadding, 10, + MwNorientation, MwVERTICAL, + NULL); + + MwVaCreateWidget(MwButtonClass, "btn1", box2, 0, 0, 0, 0, + MwNbackground, "#a00", + NULL); + + MwVaCreateWidget(MwButtonClass, "btn2", box2, 0, 0, 0, 0, + MwNbackground, "#0a0", + MwNboxRatio, 2, + NULL); + + MwVaCreateWidget(MwButtonClass, "btn3", box2, 0, 0, 0, 0, + MwNbackground, "#00a", + NULL); + + MwVaCreateWidget(MwButtonClass, "btn4", box3, 0, 0, 0, 0, + MwNbackground, "#00a", + NULL); + + MwAddUserHandler(window, MwNresizeHandler, resize, NULL); + + resize(window, NULL, NULL); + + MwLoop(window); +} diff --git a/include/Mw/Core.h b/include/Mw/Core.h index e873b41..e714a32 100644 --- a/include/Mw/Core.h +++ b/include/Mw/Core.h @@ -37,6 +37,17 @@ #define MwDispatch3(x, y, z) \ if(!x->destroyed && x->widget_class != NULL && x->widget_class->y != NULL) x->widget_class->y(x, z) +/*! + * @warning Used internally + * @brief Dispatches the handler of widget class + * @param x Widget + * @param y Handler name + * @param z Argument + * @param w Argument + */ +#define MwDispatch4(x, y, z, w) \ + if(!x->destroyed && x->widget_class != NULL && x->widget_class->y != NULL) x->widget_class->y(x, z, w) + #define MwWaitMS 30 #define MwDoubleClickTimeout 250 diff --git a/include/Mw/Milsko.h b/include/Mw/Milsko.h index 5e14588..4bd157a 100644 --- a/include/Mw/Milsko.h +++ b/include/Mw/Milsko.h @@ -50,5 +50,6 @@ #include #include #include +#include #endif diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index de8b8bb..238c0ba 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -32,6 +32,7 @@ #define MwNpadding "Ipadding" #define MwNborderWidth "IborderWidth" #define MwNfillArea "IfillArea" +#define MwNboxRatio "IboxRatio" #define MwNtitle "Stitle" #define MwNtext "Stext" diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 3c58e95..0d2eeca 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -32,11 +32,13 @@ typedef void* MwWidget; typedef void (*MwHandler)(MwWidget handle); typedef int (*MwHandlerWithStatus)(MwWidget handle); typedef void (*MwHandlerProp)(MwWidget handle, const char* key); +typedef void (*MwHandlerChildrenProp)(MwWidget handle, MwWidget child, const char* key); typedef void (*MwHandlerKey)(MwWidget handle, int key); typedef void (*MwHandlerMouse)(MwWidget handle, void* ptr); +typedef void (*MwHandlerExecute)(MwWidget handle, const char* name, void* out, va_list args); + typedef void (*MwUserHandler)(MwWidget handle, void* user_data, void* call_data); typedef void (*MwErrorHandler)(int code, const char* message, void* user_data); -typedef void (*MwHandlerExecute)(MwWidget handle, const char* name, void* out, va_list args); struct _MwTextKeyValue { char* key; @@ -175,21 +177,26 @@ struct _MwListBoxPacket { }; struct _MwClass { - MwHandlerWithStatus create; - MwHandler destroy; - MwHandler draw; - MwHandler click; - MwHandler parent_resize; - MwHandlerProp prop_change; - MwHandler mouse_move; - MwHandlerMouse mouse_up; - MwHandlerMouse mouse_down; - MwHandlerKey key; - MwHandlerExecute execute; - MwHandler tick; - void* reserved3; - void* reserved4; - void* reserved5; + MwHandlerWithStatus create; + MwHandler destroy; + MwHandler draw; + MwHandler click; + MwHandler parent_resize; + MwHandlerProp prop_change; + MwHandler mouse_move; + MwHandlerMouse mouse_up; + MwHandlerMouse mouse_down; + MwHandlerKey key; + MwHandlerExecute execute; + MwHandler tick; + MwHandler resize; + MwHandler children_update; + MwHandlerChildrenProp children_prop_change; + void* reserved1; + void* reserved2; + void* reserved3; + void* reserved4; + void* reserved5; }; #endif diff --git a/include/Mw/Widget/Box.h b/include/Mw/Widget/Box.h new file mode 100644 index 0000000..172e5f6 --- /dev/null +++ b/include/Mw/Widget/Box.h @@ -0,0 +1,24 @@ +/*! + * @file Mw/Widget/Box.h + * @brief Box widget + */ +#ifndef __MW_WIDGET_BOX_H__ +#define __MW_WIDGET_BOX_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * @brief Box widget class + */ +MWDECL MwClass MwBoxClass; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/milsko.xml b/milsko.xml index 5e74580..faf0405 100644 --- a/milsko.xml +++ b/milsko.xml @@ -49,6 +49,7 @@ - MwNheight - MwNborderWidth - MwNbackgroundPixmap + - MwNboxRatio Integer properties must be prefixed with I. String properties must be prefixed with S. @@ -82,6 +83,7 @@ + @@ -483,6 +485,12 @@ + + + + + + diff --git a/pl/rules.pl b/pl/rules.pl index ab5521b..f8aec46 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -71,6 +71,7 @@ new_object("src/icon/*.c"); new_object("src/font/*.c"); new_object("src/cursor/*.c"); +new_object("src/widget/box.c"); new_object("src/widget/button.c"); new_object("src/widget/checkbox.c"); new_object("src/widget/combobox.c"); @@ -116,6 +117,7 @@ new_example("examples/basic/progressbar"); new_example("examples/basic/colorpicker"); new_example("examples/basic/combobox"); new_example("examples/basic/treeview"); +new_example("examples/basic/box"); if (param_get("opengl")) { new_example("examples/gldemos/boing", $gl_libs); diff --git a/src/core.c b/src/core.c index ec7cb7d..4afafb7 100644 --- a/src/core.c +++ b/src/core.c @@ -50,6 +50,7 @@ static void llresizehandler(MwLL handle, void* data) { for(i = 0; i < arrlen(h->children); i++) { MwDispatch(h->children[i], parent_resize); } + MwDispatch(h, resize); } static void llclosehandler(MwLL handle, void* data) { @@ -176,6 +177,8 @@ MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent, MwAddTickList(h); } + if(h->parent != NULL) MwDispatch(h->parent, children_update); + return h; } @@ -378,7 +381,10 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { } else { shput(handle->integer, key, n); } - if(handle->prop_event) MwDispatch3(handle, prop_change, key); + if(handle->prop_event) { + MwDispatch3(handle, prop_change, key); + if(handle->parent != NULL) MwDispatch4(handle->parent, children_prop_change, handle, key); + } } void MwSetText(MwWidget handle, const char* key, const char* value) { @@ -395,7 +401,10 @@ void MwSetText(MwWidget handle, const char* key, const char* value) { shdel(handle->text, key); } } - if(handle->prop_event) MwDispatch3(handle, prop_change, key); + if(handle->prop_event) { + MwDispatch3(handle, prop_change, key); + if(handle->parent != NULL) MwDispatch4(handle->parent, children_prop_change, handle, key); + } if(strcmp(key, MwNbackground) == 0 || strcmp(key, MwNforeground) == 0 || strcmp(key, MwNsubBackground) == 0 || strcmp(key, MwNsubForeground) == 0) { MwForceRender(handle); } @@ -413,7 +422,10 @@ void MwSetVoid(MwWidget handle, const char* key, void* value) { } else { shput(handle->data, key, value); } - if(handle->prop_event) MwDispatch3(handle, prop_change, key); + if(handle->prop_event) { + MwDispatch3(handle, prop_change, key); + if(handle->parent != NULL) MwDispatch4(handle->parent, children_prop_change, handle, key); + } } int MwGetInteger(MwWidget handle, const char* key) { @@ -732,10 +744,14 @@ void MwReparent(MwWidget handle, MwWidget new_parent) { break; } } + + MwDispatch(handle->parent, children_update); } handle->parent = new_parent; arrput(new_parent->children, handle); + + MwDispatch(handle->parent, children_update); } MwClass MwGetClass(MwWidget handle) { diff --git a/src/widget/box.c b/src/widget/box.c new file mode 100644 index 0000000..31b0a07 --- /dev/null +++ b/src/widget/box.c @@ -0,0 +1,100 @@ +#include + +#include "../../external/stb_ds.h" + +static int create(MwWidget handle) { + MwSetDefault(handle); + + MwSetInteger(handle, MwNorientation, MwHORIZONTAL); + MwSetInteger(handle, MwNpadding, 0); + + return 0; +} + +static void draw(MwWidget handle) { + MwRect r; + MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); + + r.x = 0; + r.y = 0; + r.width = MwGetInteger(handle, MwNwidth); + r.height = MwGetInteger(handle, MwNheight); + MwDrawRect(handle, &r, base); + + MwLLFreeColor(base); +} + +static void layout(MwWidget handle) { + int i; + int sum = 0; + int horiz = MwGetInteger(handle, MwNorientation) == MwHORIZONTAL ? 1 : 0; + int sz = MwGetInteger(handle, horiz ? MwNwidth : MwNheight) - MwGetInteger(handle, MwNpadding); + int fsz = MwGetInteger(handle, horiz ? MwNheight : MwNwidth) - MwGetInteger(handle, MwNpadding) * 2; + int sk = 0; + if(arrlen(handle->children) == 0) return; + + for(i = 0; i < arrlen(handle->children); i++) { + int n = MwGetInteger(handle->children[i], MwNboxRatio); + if(n == MwDEFAULT) n = 1; + + sum += n; + } + + for(i = 0; i < arrlen(handle->children); i++) { + int n = MwGetInteger(handle->children[i], MwNboxRatio); + int wsz; + if(n == MwDEFAULT) n = 1; + + wsz = sz * n / sum - MwGetInteger(handle, MwNpadding); + + sk += MwGetInteger(handle, MwNpadding); + MwVaApply(handle->children[i], + horiz ? MwNx : MwNy, sk, /* this is what gets changed */ + horiz ? MwNy : MwNx, MwGetInteger(handle, MwNpadding), /* fixed between widgets */ + horiz ? MwNwidth : MwNheight, wsz, /* this is what gets changed */ + horiz ? MwNheight : MwNwidth, fsz, /* fixed between widgets */ + NULL); + sk += wsz; + } +} + +static void prop_change(MwWidget handle, const char* key) { + if(strcmp(key, MwNorientation) == 0) layout(handle); +} + +static void children_prop_change(MwWidget handle, MwWidget child, const char* key) { + (void)child; + + if(strcmp(key, MwNboxRatio) == 0) layout(handle); +} + +static void resize(MwWidget handle) { + layout(handle); +} + +static void children_update(MwWidget handle) { + layout(handle); +} + +MwClassRec MwBoxClassRec = { + create, /* create */ + NULL, /* destroy */ + draw, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + prop_change, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + NULL, /* execute */ + NULL, /* tick */ + resize, /* resize */ + children_update, /* children_update */ + children_prop_change, /* children_prop_change */ + NULL, + NULL, + NULL, + NULL, + NULL}; +MwClass MwBoxClass = &MwBoxClassRec; diff --git a/src/widget/button.c b/src/widget/button.c index a484eea..dfff6d5 100644 --- a/src/widget/button.c +++ b/src/widget/button.c @@ -101,6 +101,11 @@ MwClassRec MwButtonClassRec = { NULL, /* key */ NULL, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/checkbox.c b/src/widget/checkbox.c index 0a117a4..8a42b89 100644 --- a/src/widget/checkbox.c +++ b/src/widget/checkbox.c @@ -50,6 +50,11 @@ MwClassRec MwCheckBoxClassRec = { NULL, /* key */ NULL, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/combobox.c b/src/widget/combobox.c index 9de2ac0..156242e 100644 --- a/src/widget/combobox.c +++ b/src/widget/combobox.c @@ -201,6 +201,11 @@ MwClassRec MwComboBoxClassRec = { NULL, /* key */ func_handler, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/entry.c b/src/widget/entry.c index b5ac1e0..85f9a86 100644 --- a/src/widget/entry.c +++ b/src/widget/entry.c @@ -170,6 +170,11 @@ MwClassRec MwEntryClassRec = { key, /* key */ NULL, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/frame.c b/src/widget/frame.c index 38ff990..36085a6 100644 --- a/src/widget/frame.c +++ b/src/widget/frame.c @@ -59,6 +59,11 @@ MwClassRec MwFrameClassRec = { NULL, /* key */ NULL, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/image.c b/src/widget/image.c index 8d2e1c7..487521d 100644 --- a/src/widget/image.c +++ b/src/widget/image.c @@ -46,6 +46,11 @@ MwClassRec MwImageClassRec = { NULL, /* key */ NULL, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/label.c b/src/widget/label.c index f26edd0..2cf6a8d 100644 --- a/src/widget/label.c +++ b/src/widget/label.c @@ -59,6 +59,11 @@ MwClassRec MwLabelClassRec = { NULL, /* key */ NULL, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/listbox.c b/src/widget/listbox.c index 784594b..4141f48 100644 --- a/src/widget/listbox.c +++ b/src/widget/listbox.c @@ -606,6 +606,11 @@ MwClassRec MwListBoxClassRec = { NULL, /* key */ func_handler, /* execute */ tick, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/menu.c b/src/widget/menu.c index 0538812..ffb8bb6 100644 --- a/src/widget/menu.c +++ b/src/widget/menu.c @@ -201,6 +201,11 @@ MwClassRec MwMenuClassRec = { NULL, /* key */ func_handler, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/numberentry.c b/src/widget/numberentry.c index edfbe9e..ccbdf14 100644 --- a/src/widget/numberentry.c +++ b/src/widget/numberentry.c @@ -140,6 +140,11 @@ MwClassRec MwNumberEntryClassRec = { key, /* key */ NULL, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/opengl.c b/src/widget/opengl.c index f6cc369..9481c49 100644 --- a/src/widget/opengl.c +++ b/src/widget/opengl.c @@ -249,6 +249,11 @@ MwClassRec MwOpenGLClassRec = { NULL, /* key */ func_handler, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/progressbar.c b/src/widget/progressbar.c index f3f99eb..bd036dd 100644 --- a/src/widget/progressbar.c +++ b/src/widget/progressbar.c @@ -58,6 +58,11 @@ MwClassRec MwProgressBarClassRec = { NULL, /* key */ NULL, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/radiobox.c b/src/widget/radiobox.c index 85c7871..a6f78f9 100644 --- a/src/widget/radiobox.c +++ b/src/widget/radiobox.c @@ -59,6 +59,11 @@ MwClassRec MwRadioBoxClassRec = { NULL, /* key */ NULL, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index e00d0b5..254e05b 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -275,6 +275,11 @@ MwClassRec MwScrollBarClassRec = { NULL, /* key */ func_handler, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/separator.c b/src/widget/separator.c index 009c42b..5800ba3 100644 --- a/src/widget/separator.c +++ b/src/widget/separator.c @@ -47,6 +47,11 @@ MwClassRec MwSeparatorClassRec = { NULL, /* key */ NULL, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 3e7eaaa..09a0274 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -212,6 +212,11 @@ MwClassRec MwSubMenuClassRec = { NULL, /* key */ func_handler, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/treeview.c b/src/widget/treeview.c index 2379937..27607ce 100644 --- a/src/widget/treeview.c +++ b/src/widget/treeview.c @@ -493,6 +493,11 @@ MwClassRec MwTreeViewClassRec = { NULL, /* key */ func_handler, /* execute */ tick, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/viewport.c b/src/widget/viewport.c index 1cd3ee9..9bdf860 100644 --- a/src/widget/viewport.c +++ b/src/widget/viewport.c @@ -188,6 +188,11 @@ MwClassRec MwViewportClassRec = { NULL, /* key */ func_handler, /* execute */ tick, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/vulkan.c b/src/widget/vulkan.c index 29a2fab..bda24bf 100644 --- a/src/widget/vulkan.c +++ b/src/widget/vulkan.c @@ -521,6 +521,11 @@ MwClassRec MwVulkanClassRec = { NULL, /* key */ func_handler, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/src/widget/window.c b/src/widget/window.c index f8e8394..98a128f 100644 --- a/src/widget/window.c +++ b/src/widget/window.c @@ -56,6 +56,11 @@ MwClassRec MwWindowClassRec = { NULL, /* key */ func_handler, /* execute */ NULL, /* tick */ + NULL, /* resize */ + NULL, /* children_update */ + NULL, /* children_prop_change */ + NULL, + NULL, NULL, NULL, NULL}; diff --git a/tools/watcom-pack.sh b/tools/watcom-pack.sh index 1c465e3..81626db 100755 --- a/tools/watcom-pack.sh +++ b/tools/watcom-pack.sh @@ -18,5 +18,6 @@ for i in *.c; do done cd ../.. rm -f milsko-examples.zip +cp resource/logo/logo.png examples/picture.jpg examples/picture.png milsko-examples/ zip -rv milsko-examples.zip milsko-examples rm -rf milsko-examples