From 75c73e98e12258be26f6b7385abd6064ca1d8774 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Thu, 20 Nov 2025 12:45:07 +0000 Subject: [PATCH] treeview works git-svn-id: http://svn2.nishi.boats/svn/milsko/trunk@762 b9cfdab3-6d41-4d17-bbe4-086880011989 --- include/Mw/LowLevel/X11.h | 1 + include/Mw/TypeDefs.h | 21 +++--- milsko.xml | 17 +++++ src/backend/x11.c | 16 +++-- src/widget/treeview.c | 144 +++++++++++++++++++++++--------------- 5 files changed, 126 insertions(+), 73 deletions(-) diff --git a/include/Mw/LowLevel/X11.h b/include/Mw/LowLevel/X11.h index c0cc2f4..eef85ae 100644 --- a/include/Mw/LowLevel/X11.h +++ b/include/Mw/LowLevel/X11.h @@ -35,6 +35,7 @@ struct _MwLLX11 { int top; int grabbed; + int force_render; unsigned long red_mask; unsigned long red_max; diff --git a/include/Mw/TypeDefs.h b/include/Mw/TypeDefs.h index 907cc81..63ab075 100644 --- a/include/Mw/TypeDefs.h +++ b/include/Mw/TypeDefs.h @@ -140,19 +140,20 @@ struct _MwComboBox { }; struct _MwTreeViewEntry { - char* label; - MwLLPixmap pixmap; - MwTreeViewEntry* tree; - int opened; - int selected; - unsigned long click_time; + char* label; + MwLLPixmap pixmap; + MwTreeViewEntry** tree; + int opened; + int selected; + unsigned long click_time; + MwTreeViewEntry* parent; }; struct _MwTreeView { - MwWidget frame; - MwWidget vscroll; - int changed; - MwTreeViewEntry* tree; + MwWidget frame; + MwWidget vscroll; + int changed; + MwTreeViewEntry** tree; MwPoint pressed; }; diff --git a/milsko.xml b/milsko.xml index 9ef872c..7e81351 100644 --- a/milsko.xml +++ b/milsko.xml @@ -618,5 +618,22 @@ + + + + + + + + + + + + + + + + + diff --git a/src/backend/x11.c b/src/backend/x11.c index fba2d1e..49afe5e 100644 --- a/src/backend/x11.c +++ b/src/backend/x11.c @@ -201,7 +201,8 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->x11.width = width; r->x11.height = height; - r->x11.grabbed = 0; + r->x11.grabbed = 0; + r->x11.force_render = 0; r->x11.colormap = DefaultColormap(r->x11.display, XDefaultScreen(r->x11.display)); r->x11.wm_delete = XInternAtom(r->x11.display, "WM_DELETE_WINDOW", False); @@ -400,7 +401,8 @@ static void MwLLNextEventImpl(MwLL handle) { while(XCheckTypedWindowEvent(handle->x11.display, handle->x11.window, ClientMessage, &ev) || XCheckWindowEvent(handle->x11.display, handle->x11.window, mask, &ev)) { int render = 0; if(ev.type == Expose) { - render = 1; + handle->x11.force_render = 0; + render = 1; } else if(ev.type == ButtonPress) { MwLLMouse p; p.point.x = ev.xbutton.x; @@ -759,9 +761,13 @@ static void MwLLForceRenderImpl(MwLL handle) { XEvent ev; memset(&ev, 0, sizeof(ev)); - ev.type = Expose; - ev.xexpose.window = handle->x11.window; - XSendEvent(handle->x11.display, handle->x11.window, False, ExposureMask, &ev); + if(!handle->x11.force_render) { + ev.type = Expose; + ev.xexpose.window = handle->x11.window; + XSendEvent(handle->x11.display, handle->x11.window, False, ExposureMask, &ev); + + handle->x11.force_render = 1; + } } static void MwLLSetCursorImpl(MwLL handle, MwCursor* image, MwCursor* mask) { diff --git a/src/widget/treeview.c b/src/widget/treeview.c index 656180c..96aa2b9 100644 --- a/src/widget/treeview.c +++ b/src/widget/treeview.c @@ -15,15 +15,15 @@ static void vscroll_changed(MwWidget handle, void* user, void* call) { tv->changed = 1; } -static void set_all(MwTreeViewEntry* root, int v){ +static void set_all(MwTreeViewEntry** root, int v) { int i; - for(i = 0; i < arrlen(root); i++){ - root[i].selected = v; - set_all(root[i].tree, v); + for(i = 0; i < arrlen(root); i++) { + root[i]->selected = v; + set_all(root[i]->tree, v); } } -static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry* root, MwLLColor base, MwLLColor text, MwPoint* p, int next, int shift, int* skip, int* shared, int draw, MwPoint* mouse) { +static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry** root, MwLLColor base, MwLLColor text, MwPoint* p, int next, int shift, int* skip, int* shared, int draw, MwPoint* mouse) { int i; MwPoint l[2]; int skipped = 0; @@ -58,12 +58,12 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry* r r.y = p->y - MwTextHeight(handle, "M") / 2 + (MwTextHeight(handle, "M") - r.height) / 2; if(draw) { MwLLColor col = tree->opened ? MwLightenColor(handle, base, -8, -8, -8) : base; - MwRect r2 = r; + MwRect r2 = r; const int len = 4; MwDrawRect(handle, &r, col); MwDrawFrame(handle, &r, base, tree->opened); - if(tree->opened){ + if(tree->opened) { l[0].x = r.x + (r.width - len) / 2; l[0].y = r.y + r.height / 2; @@ -71,7 +71,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry* r l[1].y = l[0].y; MwLLLine(handle->lowlevel, &l[0], text); - }else{ + } else { l[0].x = r.x + (r.width - len) / 2; l[0].y = r.y + r.height / 2; @@ -102,30 +102,30 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry* r r.height = MwTextHeight(handle, "M"); r.width = r.height * tree->pixmap->common.width / tree->pixmap->common.height; - r.x = p->x; - r.y = p->y - MwTextHeight(handle, "M") / 2; + r.x = p->x; + r.y = p->y - MwTextHeight(handle, "M") / 2; if(draw) MwLLDrawPixmap(handle->lowlevel, &r, tree->pixmap); } p->x += MwGetInteger(handle->parent, MwNleftPadding); - if(draw){ - if(tree->selected){ - r.x = p->x; - r.y = p->y - MwTextHeight(handle, "M") / 2; - r.width = MwTextWidth(handle, tree->label); + if(draw) { + if(tree->selected) { + r.x = p->x; + r.y = p->y - MwTextHeight(handle, "M") / 2; + r.width = MwTextWidth(handle, tree->label); r.height = MwTextHeight(handle, "M"); MwDrawRect(handle, &r, text); } handle->bgcolor = tree->selected ? text : base; MwDrawText(handle, p, tree->label, 0, MwALIGNMENT_BEGINNING, tree->selected ? base : text); handle->bgcolor = NULL; - }else{ - if(p->x <= mouse->x && mouse->x <= (p->x + MwTextWidth(handle, tree->label)) && (p->y - MwTextHeight(handle, "M") / 2) <= mouse->y && mouse->y <= (p->y + MwTextHeight(handle, "M") / 2)){ + } else { + if(p->x <= mouse->x && mouse->x <= (p->x + MwTextWidth(handle, tree->label)) && (p->y - MwTextHeight(handle, "M") / 2) <= mouse->y && mouse->y <= (p->y + MwTextHeight(handle, "M") / 2)) { unsigned long t; set_all(root, 0); tree->selected = 1; - if(((t = MwTimeGetTick()) - tree->click_time) < MwDoubleClickTimeout || MwGetInteger(handle->parent, MwNsingleClickSelectable)){ + if(((t = MwTimeGetTick()) - tree->click_time) < MwDoubleClickTimeout || MwGetInteger(handle->parent, MwNsingleClickSelectable)) { /* TODO: dispatch event */ } @@ -145,7 +145,7 @@ static void recursion(MwWidget handle, MwTreeViewEntry* tree, MwTreeViewEntry* r l[0].x += shift + LineSpace / 2; l[0].y += MwTextHeight(handle, "M") - (MwTextHeight(handle, "M") - OpenerSize) / 2; - recursion(handle, &tree->tree[i], root, base, text, p, i != (arrlen(tree->tree) - 1) ? 1 : 0, shift + LineSpace, skip, shared, draw, mouse); + recursion(handle, tree->tree[i], root, base, text, p, i != (arrlen(tree->tree) - 1) ? 1 : 0, shift + LineSpace, skip, shared, draw, mouse); l[1] = *p; l[1].x += shift + LineSpace / 2; @@ -177,7 +177,7 @@ static void frame_draw(MwWidget handle) { for(i = 0; i < arrlen(tv->tree); i++) { if(shared > (r.height / MwTextHeight(handle, "M"))) break; - recursion(handle, &tv->tree[i], tv->tree, base, text, &p, 0, 0, &skip, &shared, 1, NULL); + recursion(handle, tv->tree[i], tv->tree, base, text, &p, 0, 0, &skip, &shared, 1, NULL); } MwDrawFrame(handle, &r, base, 1); @@ -186,11 +186,11 @@ static void frame_draw(MwWidget handle) { MwLLFreeColor(base); } -static int recursive_length(MwTreeViewEntry* e) { +static int recursive_length(MwTreeViewEntry** e) { int l = 0; int i; for(i = 0; i < arrlen(e); i++) { - if(e[i].opened && e[i].tree != NULL) l += recursive_length(e[i].tree); + if(e[i]->opened && e[i]->tree != NULL) l += recursive_length(e[i]->tree); l++; } return l; @@ -222,7 +222,7 @@ static void frame_mouse_up(MwWidget handle, void* user, void* call) { p.y = MwDefaultBorderWidth(tv->frame); for(i = 0; i < arrlen(tv->tree); i++) { if(shared > (MwGetInteger(tv->frame, MwNheight) / MwTextHeight(tv->frame, "M"))) break; - recursion(tv->frame, &tv->tree[i], tv->tree, NULL, NULL, &p, 0, 0, &skip, &shared, 0, &tv->pressed); + recursion(tv->frame, tv->tree[i], tv->tree, NULL, NULL, &p, 0, 0, &skip, &shared, 0, &tv->pressed); } resize(handle->parent); } @@ -281,7 +281,7 @@ static void resize(MwWidget handle) { } static int create(MwWidget handle) { - MwTreeView tv = malloc(sizeof(*tv)); + MwTreeView tv = malloc(sizeof(*tv)); memset(tv, 0, sizeof(*tv)); handle->internal = tv; @@ -318,40 +318,68 @@ static void prop_change(MwWidget handle, const char* prop) { if(strcmp(prop, MwNwidth) == 0 || strcmp(prop, MwNheight) == 0) resize(handle); } -static void* mwTreeViewAddImpl(MwWidget handle, void* parent, MwLLPixmap pixmap, const char* item){ - MwTreeView tv = handle->internal; - MwTreeViewEntry t; +static void* mwTreeViewAddImpl(MwWidget handle, void* parent, MwLLPixmap pixmap, const char* item) { + MwTreeView tv = handle->internal; + MwTreeViewEntry* t = malloc(sizeof(*t)); - t.label = MwStringDuplicate(item); - t.pixmap = pixmap; - t.selected = 0; - t.opened = 1; - t.click_time = 0; + t->label = MwStringDuplicate(item); + t->pixmap = pixmap; + t->selected = 0; + t->opened = 1; + t->click_time = 0; + t->tree = NULL; + t->parent = parent; - if(parent == NULL){ + if(parent == NULL) { arrput(tv->tree, t); + } else { + MwTreeViewEntry* e = parent; + + arrput(e->tree, t); } resize(handle); + + return t; +} + +static void free_all(MwTreeViewEntry** tree) { + int i; + for(i = 0; i < arrlen(tree); i++) { + free(tree[i]->label); + free_all(tree[i]->tree); + free(tree[i]); + } + arrfree(tree); +} + +static void mwTreeViewDeleteImpl(MwWidget handle, void* item) { + MwTreeViewEntry* e = item; + MwTreeViewEntry* p = e->parent; + + free_all(p->tree); + p->tree = NULL; +} + +static void mwTreeViewResetImpl(MwWidget handle) { + MwTreeView tv = handle->internal; + + free_all(tv->tree); + tv->tree = NULL; + resize(handle); } -static void mwTreeViewDeleteImpl(MwWidget handle, void* item){ -} - -static void mwTreeViewResetImpl(MwWidget handle){ -} - static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { - if(strcmp(name, "mwTreeViewAdd") == 0){ - void* parent = va_arg(va, void*); - MwLLPixmap pixmap = va_arg(va, MwLLPixmap); - const char* item = va_arg(va, const char*); - *(void**)out = mwTreeViewAddImpl(handle, parent, pixmap, item); + if(strcmp(name, "mwTreeViewAdd") == 0) { + void* parent = va_arg(va, void*); + MwLLPixmap pixmap = va_arg(va, MwLLPixmap); + const char* item = va_arg(va, const char*); + *(void**)out = mwTreeViewAddImpl(handle, parent, pixmap, item); } - if(strcmp(name, "mwTreeViewDelete") == 0){ + if(strcmp(name, "mwTreeViewDelete") == 0) { void* item = va_arg(va, void*); mwTreeViewDeleteImpl(handle, item); } - if(strcmp(name, "mwTreeViewReset") == 0){ + if(strcmp(name, "mwTreeViewReset") == 0) { mwTreeViewResetImpl(handle); } } @@ -366,18 +394,18 @@ static void tick(MwWidget handle) { } MwClassRec MwTreeViewClassRec = { - create, /* create */ - destroy, /* destroy */ - draw, /* draw */ - NULL, /* click */ - NULL, /* parent_resize */ - prop_change, /* prop_change */ - NULL, /* mouse_move */ - NULL, /* mouse_up */ - NULL, /* mouse_down */ - NULL, /* key */ - func_handler, /* execute */ - tick, /* tick */ + create, /* create */ + destroy, /* destroy */ + draw, /* draw */ + NULL, /* click */ + NULL, /* parent_resize */ + prop_change, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler, /* execute */ + tick, /* tick */ NULL, NULL, NULL};