From 9b6ed7b6c3fafb537f10d95ae8c5fabf3f35816b Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Sat, 4 Oct 2025 21:21:31 +0000 Subject: [PATCH] it works git-svn-id: http://svn2.nishi.boats/svn/milsko/trunk@169 b9cfdab3-6d41-4d17-bbe4-086880011989 --- include/Mw/Default.h | 5 ++ include/Mw/StringDefs.h | 4 + include/Mw/Widget/ScrollBar.h | 7 ++ src/default.c | 5 +- src/draw.c | 5 +- src/widget/scrollbar.c | 134 ++++++++++++++++++++++++++++++---- src/widget/submenu.c | 4 +- 7 files changed, 142 insertions(+), 22 deletions(-) diff --git a/include/Mw/Default.h b/include/Mw/Default.h index f090b7c..6e97028 100644 --- a/include/Mw/Default.h +++ b/include/Mw/Default.h @@ -23,6 +23,11 @@ MWDECL const char* MwDefaultBackground; */ MWDECL const char* MwDefaultForeground; +/*! + * %brief Default border width + */ +MWDECL const int MwDefaultBorderWidth; + #ifdef __cplusplus } #endif diff --git a/include/Mw/StringDefs.h b/include/Mw/StringDefs.h index a39e3da..7ebffb7 100644 --- a/include/Mw/StringDefs.h +++ b/include/Mw/StringDefs.h @@ -11,6 +11,10 @@ #define MwNwidth "Iwidth" #define MwNheight "Iheight" #define MwNorientation "Iorientation" +#define MwNminValue "IminValue" +#define MwNmaxValue "ImaxValue" +#define MwNvalue "Ivalue" +#define MwNareaShown "IareaShown" #define MwNtitle "Stitle" #define MwNtext "Stext" diff --git a/include/Mw/Widget/ScrollBar.h b/include/Mw/Widget/ScrollBar.h index 5125a47..62bde8e 100644 --- a/include/Mw/Widget/ScrollBar.h +++ b/include/Mw/Widget/ScrollBar.h @@ -18,6 +18,13 @@ extern "C" { */ MWDECL MwClass MwScrollBarClass; +/*! + * %brief Calculates a visible length of scrollbar + * %param handle Widget + * %return Visible length + */ +MWDECL int MwScrollBarGetVisibleLength(MwWidget handle); + #ifdef __cplusplus } #endif diff --git a/src/default.c b/src/default.c index f5bfb0f..e13f7ce 100644 --- a/src/default.c +++ b/src/default.c @@ -1,5 +1,6 @@ /* $Id$ */ #include -const char* MwDefaultBackground = "#ddd"; -const char* MwDefaultForeground = "#000"; +const int MwDefaultBorderWidth = 2; +const char* MwDefaultBackground = "#ddd"; +const char* MwDefaultForeground = "#000"; diff --git a/src/draw.c b/src/draw.c index 676a157..ff859e9 100644 --- a/src/draw.c +++ b/src/draw.c @@ -7,7 +7,6 @@ #define FontHeight 14 #define FontScale 1 #define ColorDiff 128 -#define BorderWidth 2 static int hex(const char* txt, int len) { int i; @@ -84,7 +83,7 @@ void MwDrawRect(MwWidget handle, MwRect* rect, MwLLColor color) { } void MwDrawFrame(MwWidget handle, MwRect* rect, MwLLColor color, int invert) { - MwDrawFrameEx(handle, rect, color, invert, BorderWidth); + MwDrawFrameEx(handle, rect, color, invert, MwDefaultBorderWidth); } void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int border) { @@ -143,7 +142,7 @@ void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int invert, i void MwDrawTriangle(MwWidget handle, MwRect* rect, MwLLColor color, int invert, int direction) { MwPoint p1[4], p2[4], p3[4], p4[3]; - const int border = BorderWidth; + const int border = MwDefaultBorderWidth; MwLLColor darker = MwLightenColor(handle, color, -ColorDiff, -ColorDiff, -ColorDiff); MwLLColor lighter = MwLightenColor(handle, color, ColorDiff, ColorDiff, ColorDiff); diff --git a/src/widget/scrollbar.c b/src/widget/scrollbar.c index f69bab0..fd3e4d3 100644 --- a/src/widget/scrollbar.c +++ b/src/widget/scrollbar.c @@ -3,17 +3,23 @@ typedef struct scrollbar { MwPoint point; - int point_set; + int drag; + int pos; } scrollbar_t; static int create(MwWidget handle) { scrollbar_t* scr = malloc(sizeof(*scr)); - scr->point_set = 0; - handle->internal = scr; MwSetDefault(handle); + MwVaApply(handle, + MwNminValue, 0, + MwNmaxValue, 100, + MwNvalue, 0, + MwNareaShown, 25, + MwNorientation, MwVERTICAL, + NULL); return 0; } @@ -22,8 +28,24 @@ static void destroy(MwWidget handle) { free(handle->internal); } +static int calc_length(MwWidget handle) { + int max = MwScrollBarGetVisibleLength(handle); + int len = MwGetInteger(handle, MwNmaxValue) - MwGetInteger(handle, MwNminValue); + int area = MwGetInteger(handle, MwNareaShown); + + return max * (double)area / len; +} + +static int calc_positition(MwWidget handle) { + int max = MwScrollBarGetVisibleLength(handle); + int len = MwGetInteger(handle, MwNmaxValue) - MwGetInteger(handle, MwNminValue); + int val = MwGetInteger(handle, MwNvalue); + + return (max - calc_length(handle)) * (double)val / len; +} + static void draw(MwWidget handle) { - MwRect r, rt; + MwRect r, rt, rbar; MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwLLColor dark = MwLightenColor(handle, base, -64, -64, -64); scrollbar_t* scr = handle->internal; @@ -44,45 +66,127 @@ static void draw(MwWidget handle) { MwDrawFrame(handle, &r, dark, 1); MwDrawRect(handle, &r, dark); - if(handle->pressed && !scr->point_set) { - scr->point = handle->mouse_point; - scr->point_set = 1; - } else if(!handle->pressed && scr->point_set) { - scr->point_set = 0; - } - rt = r; - if((or = MwGetInteger(handle, MwNorientation)) == -1 || or == MwVERTICAL) { + or = MwGetInteger(handle, MwNorientation); + if(or == MwVERTICAL) { rt.height = rt.width; rt.y = r.y; MwDrawTriangle(handle, &rt, base, (handle->pressed && scr->point.y <= uy) ? 1 : 0, MwNORTH); + rbar.width = r.width; + rbar.height = calc_length(handle); + rbar.x = r.x; + rbar.y = r.y + rt.height + calc_positition(handle); + rt.y = r.y + r.height - rt.height; MwDrawTriangle(handle, &rt, base, (handle->pressed && scr->point.y >= dy) ? 1 : 0, MwSOUTH); - } else if((or = MwGetInteger(handle, MwNorientation)) == -1 || or == MwHORIZONTAL) { + } else if(or == MwHORIZONTAL) { rt.width = rt.height; rt.x = r.x; MwDrawTriangle(handle, &rt, base, (handle->pressed && scr->point.x <= ux) ? 1 : 0, MwWEST); + rbar.width = calc_length(handle); + rbar.height = r.height; + rbar.x = r.x + rt.width + calc_positition(handle); + rbar.y = r.y; + rt.x = r.x + r.width - rt.width; MwDrawTriangle(handle, &rt, base, (handle->pressed && scr->point.x >= dx) ? 1 : 0, MwEAST); } + MwDrawFrame(handle, &rbar, base, 0); + MwDrawRect(handle, &rbar, base); + MwLLFreeColor(dark); MwLLFreeColor(base); } +static void mouse_move(MwWidget handle) { + int ww = MwGetInteger(handle, MwNwidth); + int wh = MwGetInteger(handle, MwNheight); + int or = MwGetInteger(handle, MwNorientation); + scrollbar_t* scr = handle->internal; + + if(!handle->pressed) return; + + if(scr->drag) { + int l = 0; + double len = MwScrollBarGetVisibleLength(handle) - calc_length(handle); + int min = MwGetInteger(handle, MwNminValue); + int max = MwGetInteger(handle, MwNmaxValue); + + if(or == MwVERTICAL) { + int tri = (ww - MwDefaultBorderWidth * 2) + MwDefaultBorderWidth; + l = handle->mouse_point.y - tri + scr->pos; + len -= tri * 2; + } else if(or == MwHORIZONTAL) { + int tri = (wh - MwDefaultBorderWidth * 2) + MwDefaultBorderWidth; + l = handle->mouse_point.x - tri + scr->pos; + len -= tri * 2; + } + + len = l / len; + if(len < 0) len = 0; + if(len > 1) len = 1; + MwSetInteger(handle, MwNvalue, (max - min) * len - min); + + MwForceRender(handle); + } +} + +static void mouse_down(MwWidget handle) { + int ww = MwGetInteger(handle, MwNwidth); + int wh = MwGetInteger(handle, MwNheight); + int or = MwGetInteger(handle, MwNorientation); + scrollbar_t* scr = handle->internal; + + scr->point = handle->mouse_point; + scr->drag = 0; + if(or == MwVERTICAL) { + int tri = (ww - MwDefaultBorderWidth * 2) + MwDefaultBorderWidth; + if(tri <= scr->point.y && scr->point.y <= (wh - tri)) { + scr->drag = 1; + scr->pos = calc_positition(handle) - scr->point.y; + } + } else if(or == MwHORIZONTAL) { + int tri = (wh - MwDefaultBorderWidth * 2) + MwDefaultBorderWidth; + if(tri <= scr->point.x && scr->point.x <= (ww - tri)) { + scr->drag = 1; + scr->pos = calc_positition(handle) - scr->point.x; + } + } + + MwForceRender(handle); +} + MwClassRec MwScrollBarClassRec = { create, /* create */ destroy, /* destroy */ draw, /* draw */ NULL, /* click */ NULL, /* parent_resize */ - NULL, /* mouse_move */ + mouse_move, /* mouse_move */ MwForceRender, /* mouse_up */ - MwForceRender /* mouse_down */ + mouse_down /* mouse_down */ }; MwClass MwScrollBarClass = &MwScrollBarClassRec; + +int MwScrollBarGetVisibleLength(MwWidget handle) { + int ww = MwGetInteger(handle, MwNwidth); + int wh = MwGetInteger(handle, MwNheight); + int or = MwGetInteger(handle, MwNorientation); + int tri = 0; + int s = 0; + + if(or == MwVERTICAL) { + tri = (ww - MwDefaultBorderWidth * 2) * 2; + s = wh; + } else if(or == MwHORIZONTAL) { + tri = (wh - MwDefaultBorderWidth * 2) * 2; + s = ww; + } + return s - tri - MwDefaultBorderWidth * 2; +} diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 1883860..6ad61fa 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -125,7 +125,7 @@ static void click(MwWidget handle) { MwDestroyWidget(menu->sub[i]->wsub); menu->sub[i]->wsub = NULL; - MwLLForceRender(handle->lowlevel); + MwForceRender(handle); } else if(arrlen(menu->sub[i]->sub) == 0) { MwWidget p; @@ -136,7 +136,7 @@ static void click(MwWidget handle) { MwDestroyWidget(w); - MwLLForceRender(p->lowlevel); + MwForceRender(p); MwDispatchUserHandler(p, MwNmenuHandler, menu->sub[i]);