From 9e165b71d4e6d358cb968fe159c3630c0af0af44 Mon Sep 17 00:00:00 2001 From: Nishi Date: Sat, 23 May 2026 03:16:33 +0900 Subject: [PATCH] add MwNiconPixmap to frame and MwTabFocus --- examples/basic/tab.c | 4 ++ include/Mw/Widget/Tab.h | 10 +++ milsko.xml | 6 ++ src/core.c | 8 +++ src/widget/tab.c | 139 ++++++++++++++++++++++++++++++++++------ 5 files changed, 147 insertions(+), 20 deletions(-) diff --git a/examples/basic/tab.c b/examples/basic/tab.c index 8b0ad4a..8ae16c0 100644 --- a/examples/basic/tab.c +++ b/examples/basic/tab.c @@ -31,6 +31,10 @@ int main() { MwTabAdd(tab, buf); } + MwVaApply(MwTabGetFrame(tab, "Tab 1"), + MwNiconPixmap, MwLoadIcon(tab, MwIconWarning), + NULL); + MwAddUserHandler(w, MwNresizeHandler, resize, NULL); resize(w, NULL, NULL); diff --git a/include/Mw/Widget/Tab.h b/include/Mw/Widget/Tab.h index ea30023..9f80a0d 100644 --- a/include/Mw/Widget/Tab.h +++ b/include/Mw/Widget/Tab.h @@ -42,6 +42,16 @@ MwInline MwWidget MwTabGetFrame(MwWidget handle, const char* name) { return out; } +/*! + * @brief Focus on a tab frame + * @param handle Widget + * @param name Tab name + * @return Frame + */ +MwInline void MwTabFocus(MwWidget handle, const char* name) { + MwVaWidgetExecute(handle, "mwTabFocus", NULL, name); +} + #ifdef __cplusplus } #endif diff --git a/milsko.xml b/milsko.xml index 837934e..a94c847 100644 --- a/milsko.xml +++ b/milsko.xml @@ -668,6 +668,7 @@ + @@ -961,6 +962,11 @@ + + + + + diff --git a/src/core.c b/src/core.c index 0db801f..c081950 100644 --- a/src/core.c +++ b/src/core.c @@ -569,10 +569,13 @@ void MwSetInteger(MwWidget handle, const char* key, int n) { arrput(keys, NULL); MwDispatch3(handle, props_change, keys); arrfree(keys); + } + if(handle->parent != NULL && handle->parent->prop_event) { MwDispatch3(handle, prop_change, key); if(handle->parent != NULL) MwDispatch4(handle->parent, children_prop_change, handle, key); } + if(strcmp(key, MwNforceInverted) == 0) { MwForceRender(handle); } @@ -614,10 +617,13 @@ void MwSetText(MwWidget handle, const char* key, const char* value) { arrput(keys, NULL); MwDispatch3(handle, props_change, keys); arrfree(keys); + } + if(handle->parent != NULL && handle->parent->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); } @@ -642,7 +648,9 @@ void MwSetVoid(MwWidget handle, const char* key, void* value) { arrput(keys, NULL); MwDispatch3(handle, props_change, keys); arrfree(keys); + } + if(handle->parent != NULL && handle->parent->prop_event) { MwDispatch3(handle, prop_change, key); if(handle->parent != NULL) MwDispatch4(handle->parent, children_prop_change, handle, key); } diff --git a/src/widget/tab.c b/src/widget/tab.c index e779bd5..f8eda14 100644 --- a/src/widget/tab.c +++ b/src/widget/tab.c @@ -39,6 +39,23 @@ static int tab_height(MwWidget handle) { return MwTextHeight(handle, NULL, "M") + 10; } +static int icon_width(MwWidget handle, const char* text) { + MwTab t = handle->internal; + int i; + + for(i = 0; i < arrlen(t->names); i++) { + if(strcmp(t->names[i], text) == 0) { + MwLLPixmap px = MwGetVoid(t->frames[i], MwNiconPixmap); + + if(px == NULL) return 0; + + return px->common.width * tab_height(handle) / px->common.height; + } + } + + return 0; +} + static void draw(MwWidget handle) { MwTab t = handle->internal; MwLLColor c = MwParseColor(handle, MwGetText(handle, MwNbackground)); @@ -60,6 +77,7 @@ static void draw(MwWidget handle) { x = 0; for(i = 0; i < arrlen(t->names); i++) { int render = 0; + int iw = icon_width(handle, t->names[i]); if(i == MwGetInteger(handle, MwNvalue) && n == 1) { r.y += h; @@ -73,11 +91,26 @@ static void draw(MwWidget handle) { r2.x = x; r2.y = 0; - r2.width = tab_width(handle, t->names[i]); + r2.width = tab_width(handle, t->names[i]) + iw; r2.height = tab_height(handle) + MwDefaultBorderWidth(handle); x += r2.width; + if(iw > 0) { + MwLLPixmap px = MwGetVoid(t->frames[i], MwNiconPixmap); + MwRect rp; + + rp = r2; + + rp.x += 5; + rp.y += 5; + + rp.width = iw - 10; + rp.height = rp.height * (iw - 10) / iw; + + MwLLDrawPixmap(handle->lowlevel, &rp, px); + } + if(render) { MwPoint p; @@ -151,7 +184,7 @@ static void draw(MwWidget handle) { MwDrawRect(handle, &r3, c); } - p.x = r2.x + r2.width / 2; + p.x = r2.x + (r2.width + iw / 2) / 2; p.y = r2.y + r2.height / 2; MwDrawText(handle, NULL, &p, t->names[i], MwALIGNMENT_CENTER, ct); } @@ -177,7 +210,10 @@ static void click(MwWidget handle) { int h = tab_height(handle); for(i = 0; i < arrlen(t->names); i++) { - int w = tab_width(handle, t->names[i]); + int w = tab_width(handle, t->names[i]); + int iw = icon_width(handle, t->names[i]); + + w += iw; if(MwGetInteger(handle, MwNvalue) != i && x <= handle->mouse_point.x && handle->mouse_point.x <= (x + w) && 0 <= handle->mouse_point.y && handle->mouse_point.y <= h) { MwSetInteger(handle, MwNvalue, i); @@ -188,6 +224,12 @@ static void click(MwWidget handle) { } } +static void prop_change(MwWidget handle, const char* key) { + if(strcmp(key, MwNvalue) == 0) { + show_frame(handle); + } +} + static MwWidget mwTabAddImpl(MwWidget handle, const char* name) { MwTab t = handle->internal; MwWidget f = MwCreateWidget(MwFrameClass, "tabframe", handle, MwDefaultBorderWidth(handle), tab_height(handle) + MwDefaultBorderWidth(handle), MwGetInteger(handle, MwNwidth) - MwDefaultBorderWidth(handle) * 2, MwGetInteger(handle, MwNheight) - tab_height(handle) - MwDefaultBorderWidth(handle) * 2); @@ -219,6 +261,19 @@ static MwWidget mwTabGetFrameImpl(MwWidget handle, const char* name) { return NULL; } +static void mwTabFocusImpl(MwWidget handle, const char* name) { + MwTab t = handle->internal; + int i; + + for(i = 0; i < arrlen(t->names); i++) { + if(strcmp(t->names[i], name) == 0) { + MwSetInteger(handle, MwNvalue, i); + show_frame(handle); + break; + } + } +} + static void func_handler(MwWidget handle, const char* name, void* out, va_list va) { if(strcmp(name, "mwTabAdd") == 0) { const char* name = va_arg(va, const char*); @@ -228,6 +283,10 @@ static void func_handler(MwWidget handle, const char* name, void* out, va_list v const char* name = va_arg(va, const char*); *(MwWidget*)out = mwTabGetFrameImpl(handle, name); + } else if(strcmp(name, "mwTabFocus") == 0) { + const char* name = va_arg(va, const char*); + + mwTabFocusImpl(handle, name); } } @@ -251,24 +310,64 @@ static void resize(MwWidget handle) { } } +static void children_update(MwWidget handle, MwWidget child, int new_child) { + MwTab t = handle->internal; + int v = MwGetInteger(handle, MwNvalue); + int c = v; + int n; + int i; + + if(new_child) return; + + for(i = 0; i < arrlen(t->frames); i++) { + if(t->frames[i] == child) { + n = i; + break; + } + } + + free(t->names[n]); + + arrdel(t->frames, n); + arrdel(t->names, n); + + if(n <= v) { + if(v > 0) v--; + + MwSetInteger(handle, MwNvalue, v); + show_frame(handle); + } else { + MwSetInteger(handle, MwNvalue, v); + show_frame(handle); + } + + MwForceRender(handle); +} + +static void children_prop_change(MwWidget handle, MwWidget child, const char* key) { + if(strcmp(key, MwNiconPixmap) == 0) { + MwForceRender(handle); + } +} + MwClassRec MwTabClassRec = { - wcreate, /* create */ - destroy, /* destroy */ - draw, /* draw */ - click, /* click */ - NULL, /* parent_resize */ - NULL, /* prop_change */ - NULL, /* mouse_move */ - NULL, /* mouse_up */ - NULL, /* mouse_down */ - NULL, /* key */ - func_handler, /* execute */ - NULL, /* tick */ - resize, /* resize */ - NULL, /* children_update */ - NULL, /* children_prop_change */ - NULL, /* clipboard */ - NULL, /* props_change */ + wcreate, /* create */ + destroy, /* destroy */ + draw, /* draw */ + click, /* click */ + NULL, /* parent_resize */ + prop_change, /* prop_change */ + NULL, /* mouse_move */ + NULL, /* mouse_up */ + NULL, /* mouse_down */ + NULL, /* key */ + func_handler, /* execute */ + NULL, /* tick */ + resize, /* resize */ + children_update, /* children_update */ + children_prop_change, /* children_prop_change */ + NULL, /* clipboard */ + NULL, /* props_change */ NULL, NULL, NULL};