Task Manager now it's own library.

This commit is contained in:
Scott Duensing 2026-03-26 16:11:01 -05:00
parent 8886cee933
commit 227b1179cc
44 changed files with 657 additions and 537 deletions

View file

@ -3,9 +3,9 @@
# Builds the full DVX stack: core library, task switcher,
# bootstrap loader, text help library, widgets, shell, and apps.
.PHONY: all clean core tasks loader texthelp listhelp widgets shell apps
.PHONY: all clean core tasks loader texthelp listhelp widgets shell taskmgr apps
all: core tasks loader texthelp listhelp widgets shell apps
all: core tasks loader texthelp listhelp widgets shell taskmgr apps
core:
$(MAKE) -C core
@ -28,6 +28,9 @@ widgets: core tasks texthelp listhelp
shell: core tasks
$(MAKE) -C shell
taskmgr: shell
$(MAKE) -C taskmgr
apps: core tasks shell
$(MAKE) -C apps
@ -39,6 +42,7 @@ clean:
$(MAKE) -C listhelp clean
$(MAKE) -C widgets clean
$(MAKE) -C shell clean
$(MAKE) -C taskmgr clean
$(MAKE) -C apps clean
-rmdir obj 2>/dev/null
-rm -rf bin/config bin/widgets bin/libs

View file

@ -313,26 +313,26 @@ static void onMenu(WindowT *win, int32_t menuId) {
break;
case CMD_CUT:
if (sTextArea && sTextArea->wclass && sTextArea->wclass->onKey) {
sTextArea->wclass->onKey(sTextArea, 24, 0); // Ctrl+X
if (sTextArea) {
wclsOnKey(sTextArea, 24, 0); // Ctrl+X
}
break;
case CMD_COPY:
if (sTextArea && sTextArea->wclass && sTextArea->wclass->onKey) {
sTextArea->wclass->onKey(sTextArea, 3, 0); // Ctrl+C
if (sTextArea) {
wclsOnKey(sTextArea, 3, 0); // Ctrl+C
}
break;
case CMD_PASTE:
if (sTextArea && sTextArea->wclass && sTextArea->wclass->onKey) {
sTextArea->wclass->onKey(sTextArea, 22, 0); // Ctrl+V
if (sTextArea) {
wclsOnKey(sTextArea, 22, 0); // Ctrl+V
}
break;
case CMD_SELALL:
if (sTextArea && sTextArea->wclass && sTextArea->wclass->onKey) {
sTextArea->wclass->onKey(sTextArea, 1, 0); // Ctrl+A
if (sTextArea) {
wclsOnKey(sTextArea, 1, 0); // Ctrl+A
}
break;
}

View file

@ -30,7 +30,6 @@
#include "dvxWm.h"
#include "dvxPlatform.h"
#include "shellApp.h"
#include "shellTaskMgr.h"
#include "shellInfo.h"
#include <stdint.h>
@ -314,7 +313,9 @@ static void onPmMenu(WindowT *win, int32_t menuId) {
break;
case CMD_TASK_MGR:
shellTaskMgrOpen(sAc);
if (shellCtrlEscFn) {
shellCtrlEscFn(sAc);
}
break;
}
}

5
config/taskmgr.dep Normal file
View file

@ -0,0 +1,5 @@
dvxshell
libtasks
libdvx
texthelp
listhelp

View file

@ -726,17 +726,15 @@ static bool dispatchAccelKey(AppContextT *ctx, char key) {
sFocusedWidget = next;
next->focused = true;
if (next->wclass && next->wclass->onAccelActivate) {
next->wclass->onAccelActivate(next, win->widgetRoot);
}
wclsOnAccelActivate(next, win->widgetRoot);
wgtInvalidate(win->widgetRoot);
}
} else if (target->wclass->onAccelActivate) {
} else if (wclsHas(target, WGT_METHOD_ON_ACCEL_ACTIVATE)) {
if (sFocusedWidget) { sFocusedWidget->focused = false; }
sFocusedWidget = target;
target->focused = true;
target->wclass->onAccelActivate(target, win->widgetRoot);
wclsOnAccelActivate(target, win->widgetRoot);
wgtInvalidate(win->widgetRoot);
}
@ -1136,7 +1134,7 @@ static void dispatchEvents(AppContextT *ctx) {
if (win->widgetRoot) {
WidgetT *focus = wgtGetFocused();
if (focus && focus->wclass && focus->wclass->onKey) {
if (focus && wclsHas(focus, WGT_METHOD_ON_KEY)) {
// Find the scrollable target: either the focused widget
// itself or a ScrollPane ancestor that contains it.
WidgetT *target = NULL;
@ -1153,13 +1151,13 @@ static void dispatchEvents(AppContextT *ctx) {
}
}
if (target && target->wclass && target->wclass->onKey) {
if (target && wclsHas(target, WGT_METHOD_ON_KEY)) {
int32_t delta = ctx->mouseWheel * ctx->wheelDirection;
int32_t arrowKey = (delta > 0) ? (0x50 | 0x100) : (0x48 | 0x100);
int32_t steps = abs(delta) * MOUSE_WHEEL_STEP;
for (int32_t s = 0; s < steps; s++) {
target->wclass->onKey(target, arrowKey, 0);
wclsOnKey(target, arrowKey, 0);
}
// Ensure the window repaints even if the widget's
@ -2657,12 +2655,12 @@ bool dvxUpdate(AppContextT *ctx) {
// onClick. The one-frame delay ensures the pressed visual state
// renders before the callback runs (which may open a dialog, etc.).
if (sKeyPressedBtn) {
if (sKeyPressedBtn->wclass && sKeyPressedBtn->wclass->onDragEnd) {
if (wclsHas(sKeyPressedBtn, WGT_METHOD_ON_DRAG_END)) {
// Pass button center as coordinates so bounds check succeeds and onClick fires
WidgetT *root = sKeyPressedBtn->window ? sKeyPressedBtn->window->widgetRoot : sKeyPressedBtn;
sKeyPressedBtn->wclass->onDragEnd(sKeyPressedBtn, root,
sKeyPressedBtn->x + sKeyPressedBtn->w / 2,
sKeyPressedBtn->y + sKeyPressedBtn->h / 2);
wclsOnDragEnd(sKeyPressedBtn, root,
sKeyPressedBtn->x + sKeyPressedBtn->w / 2,
sKeyPressedBtn->y + sKeyPressedBtn->h / 2);
}
wgtInvalidate(sKeyPressedBtn);
@ -3634,17 +3632,17 @@ static void pollWidgets(AppContextT *ctx) {
// ============================================================
static void pollWidgetsWalk(AppContextT *ctx, WidgetT *w, WindowT *win) {
if (w->wclass && (w->wclass->flags & WCLASS_NEEDS_POLL) && w->wclass->poll) {
w->wclass->poll(w, win);
if (w->wclass && (w->wclass->flags & WCLASS_NEEDS_POLL) && wclsHas(w, WGT_METHOD_POLL)) {
wclsPoll(w, win);
// If the poll dirtied internal state and the widget supports
// quickRepaint, render the dirty rows directly into the window's
// content buffer and add the affected area to the global dirty list.
if (w->wclass->quickRepaint) {
if (wclsHas(w, WGT_METHOD_QUICK_REPAINT)) {
int32_t dirtyY = 0;
int32_t dirtyH = 0;
if (w->wclass->quickRepaint(w, &dirtyY, &dirtyH) > 0) {
if (wclsQuickRepaint(w, &dirtyY, &dirtyH) > 0) {
int32_t scrollY = win->vScroll ? win->vScroll->value : 0;
int32_t rectX = win->x + win->contentX;
int32_t rectY = win->y + win->contentY + dirtyY - scrollY;
@ -4220,17 +4218,13 @@ static void pollKeyboard(AppContextT *ctx) {
int32_t popY;
int32_t popW;
int32_t popH;
if (sOpenPopup->wclass && sOpenPopup->wclass->getPopupRect) {
sOpenPopup->wclass->getPopupRect(sOpenPopup, &ctx->font, popWin->contentH, &popX, &popY, &popW, &popH);
}
wclsGetPopupRect(sOpenPopup, &ctx->font, popWin->contentH, &popX, &popY, &popW, &popH);
dirtyListAdd(&ctx->dirty, popWin->x + popWin->contentX + popX, popWin->y + popWin->contentY + popY, popW, popH);
WidgetT *closing = sOpenPopup;
sOpenPopup = NULL;
if (closing->wclass && closing->wclass->closePopup) {
closing->wclass->closePopup(closing);
}
wclsClosePopup(closing);
wgtInvalidate(closing);
continue;
@ -4364,8 +4358,8 @@ static void pollKeyboard(AppContextT *ctx) {
// Scroll into view inside any scroll container ancestor
for (WidgetT *p = next->parent; p; p = p->parent) {
if (p->wclass && (p->wclass->flags & WCLASS_SCROLL_CONTAINER) &&
p->wclass->scrollChildIntoView) {
p->wclass->scrollChildIntoView(p, next);
wclsHas(p, WGT_METHOD_SCROLL_CHILD_INTO_VIEW)) {
wclsScrollChildIntoView(p, next);
break;
}
}
@ -4552,8 +4546,8 @@ static void updateCursorShape(AppContextT *ctx) {
}
}
// Active widget drag -- query cursor shape from the dragged widget
else if (sDragWidget && sDragWidget->wclass && sDragWidget->wclass->getCursorShape) {
int32_t shape = sDragWidget->wclass->getCursorShape(sDragWidget, 0, 0);
else if (sDragWidget) {
int32_t shape = wclsGetCursorShape(sDragWidget, 0, 0);
if (shape > 0) {
newCursor = shape;
@ -4597,8 +4591,8 @@ static void updateCursorShape(AppContextT *ctx) {
WidgetT *hit = widgetHitTest(win->widgetRoot, vx, vy);
if (hit && hit->wclass && hit->wclass->getCursorShape) {
int32_t shape = hit->wclass->getCursorShape(hit, vx, vy);
if (hit) {
int32_t shape = wclsGetCursorShape(hit, vx, vy);
if (shape > 0) {
newCursor = shape;

View file

@ -111,7 +111,7 @@ typedef enum {
// in their respective widget .c files.
// ============================================================
// Widget class vtable
// Widget class dispatch table
// ============================================================
//
// Each widget type has a WidgetClassT that defines its behavior.
@ -119,6 +119,13 @@ typedef enum {
// (from DXE plugins) are stored in the mutable region of
// widgetClassTable[].
//
// The handlers[] array provides ABI-stable dispatch: method IDs are
// fixed constants that never change. Adding new methods appends new
// IDs without shifting existing ones, so widget DXEs compiled against
// an older DVX version continue to work unmodified. The version field
// is checked at wgtRegisterClass() time to catch DXEs compiled against
// an incompatible layout.
//
// Flags encode static properties checked by the framework:
// FOCUSABLE -- can receive keyboard focus (Tab navigation)
// BOX_CONTAINER -- uses the generic VBox/HBox layout algorithm
@ -143,55 +150,38 @@ typedef enum {
#define WCLASS_PRESS_RELEASE 0x00001000 // click = press+release (Button, ImageButton)
#define WCLASS_ACCEL_WHEN_HIDDEN 0x00002000 // accel matching works even when invisible
// Method IDs -- stable ABI, never reorder, never reuse.
// New methods are appended at the end with the next sequential ID.
#define WGT_METHOD_PAINT 0 // void (w, d, ops, font, colors)
#define WGT_METHOD_PAINT_OVERLAY 1 // void (w, d, ops, font, colors)
#define WGT_METHOD_CALC_MIN_SIZE 2 // void (w, font)
#define WGT_METHOD_LAYOUT 3 // void (w, font)
#define WGT_METHOD_GET_LAYOUT_METRICS 4 // void (w, font, pad, gap, extraTop, borderW)
#define WGT_METHOD_ON_MOUSE 5 // void (w, root, vx, vy)
#define WGT_METHOD_ON_KEY 6 // void (w, key, mod)
#define WGT_METHOD_ON_ACCEL_ACTIVATE 7 // void (w, root)
#define WGT_METHOD_DESTROY 8 // void (w)
#define WGT_METHOD_ON_CHILD_CHANGED 9 // void (parent, child)
#define WGT_METHOD_GET_TEXT 10 // const char *(w)
#define WGT_METHOD_SET_TEXT 11 // void (w, text)
#define WGT_METHOD_CLEAR_SELECTION 12 // bool (w)
#define WGT_METHOD_CLOSE_POPUP 13 // void (w)
#define WGT_METHOD_GET_POPUP_RECT 14 // void (w, font, contentH, popX, popY, popW, popH)
#define WGT_METHOD_ON_DRAG_UPDATE 15 // void (w, root, x, y)
#define WGT_METHOD_ON_DRAG_END 16 // void (w, root, x, y)
#define WGT_METHOD_GET_CURSOR_SHAPE 17 // int32_t (w, vx, vy)
#define WGT_METHOD_POLL 18 // void (w, win)
#define WGT_METHOD_QUICK_REPAINT 19 // int32_t (w, outY, outH)
#define WGT_METHOD_SCROLL_CHILD_INTO_VIEW 20 // void (parent, child)
#define WGT_METHOD_COUNT 21
#define WGT_METHOD_MAX 32 // room for future methods
#define WGT_CLASS_VERSION 1 // bump on breaking ABI change
typedef struct WidgetClassT {
uint32_t flags;
// Rendering
void (*paint)(struct WidgetT *w, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors);
void (*paintOverlay)(struct WidgetT *w, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors);
// Layout
void (*calcMinSize)(struct WidgetT *w, const BitmapFontT *font);
void (*layout)(struct WidgetT *w, const BitmapFontT *font);
void (*getLayoutMetrics)(const struct WidgetT *w, const BitmapFontT *font, int32_t *pad, int32_t *gap, int32_t *extraTop, int32_t *borderW);
// Input
void (*onMouse)(struct WidgetT *w, struct WidgetT *root, int32_t vx, int32_t vy);
void (*onKey)(struct WidgetT *w, int32_t key, int32_t mod);
void (*onAccelActivate)(struct WidgetT *w, struct WidgetT *root);
// Lifecycle
void (*destroy)(struct WidgetT *w);
void (*onChildChanged)(struct WidgetT *parent, struct WidgetT *child);
// Text
const char *(*getText)(const struct WidgetT *w);
void (*setText)(struct WidgetT *w, const char *text);
// Selection
bool (*clearSelection)(struct WidgetT *w);
// Popup (dropdown/combobox)
void (*closePopup)(struct WidgetT *w);
void (*getPopupRect)(const struct WidgetT *w, const BitmapFontT *font, int32_t contentH, int32_t *popX, int32_t *popY, int32_t *popW, int32_t *popH);
// Generic drag (button press, slider, scrollbar, text select, reorder, etc.)
// Core sets sDragWidget on mouse-down; calls onDragUpdate on mouse-move
// and onDragEnd on mouse-up. Each widget stores its own drag state.
void (*onDragUpdate)(struct WidgetT *w, struct WidgetT *root, int32_t x, int32_t y);
void (*onDragEnd)(struct WidgetT *w, struct WidgetT *root, int32_t x, int32_t y);
// Cursor shape (returns cursor ID, 0 = default)
int32_t (*getCursorShape)(const struct WidgetT *w, int32_t vx, int32_t vy);
// Polling (AnsiTerm comms)
void (*poll)(struct WidgetT *w, WindowT *win);
// Fast incremental repaint (returns dirty row count, 0 = none)
int32_t (*quickRepaint)(struct WidgetT *w, int32_t *outY, int32_t *outH);
// Scroll a child widget into the visible area (ScrollPane, etc.)
void (*scrollChildIntoView)(struct WidgetT *parent, const struct WidgetT *child);
uint32_t version;
uint32_t flags;
void *handlers[WGT_METHOD_MAX];
} WidgetClassT;
// ============================================================
@ -277,6 +267,145 @@ typedef struct WidgetT {
} WidgetT;
// ============================================================
// Typed dispatch helpers
// ============================================================
//
// Each wclsFoo() inline function extracts a handler by stable method ID,
// casts it to the correct function pointer type, and calls it with a
// NULL check. This gives callers type-safe dispatch with the same
// codegen as a direct struct field call.
static inline bool wclsHas(const WidgetT *w, int32_t methodId) {
return w->wclass && w->wclass->handlers[methodId] != NULL;
}
static inline void wclsPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors) {
typedef void (*FnT)(WidgetT *, DisplayT *, const BlitOpsT *, const BitmapFontT *, const ColorSchemeT *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_PAINT] : NULL;
if (fn) { fn(w, d, ops, font, colors); }
}
static inline void wclsPaintOverlay(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors) {
typedef void (*FnT)(WidgetT *, DisplayT *, const BlitOpsT *, const BitmapFontT *, const ColorSchemeT *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_PAINT_OVERLAY] : NULL;
if (fn) { fn(w, d, ops, font, colors); }
}
static inline void wclsCalcMinSize(WidgetT *w, const BitmapFontT *font) {
typedef void (*FnT)(WidgetT *, const BitmapFontT *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_CALC_MIN_SIZE] : NULL;
if (fn) { fn(w, font); }
}
static inline void wclsLayout(WidgetT *w, const BitmapFontT *font) {
typedef void (*FnT)(WidgetT *, const BitmapFontT *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_LAYOUT] : NULL;
if (fn) { fn(w, font); }
}
static inline void wclsGetLayoutMetrics(const WidgetT *w, const BitmapFontT *font, int32_t *pad, int32_t *gap, int32_t *extraTop, int32_t *borderW) {
typedef void (*FnT)(const WidgetT *, const BitmapFontT *, int32_t *, int32_t *, int32_t *, int32_t *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_GET_LAYOUT_METRICS] : NULL;
if (fn) { fn(w, font, pad, gap, extraTop, borderW); }
}
static inline void wclsOnMouse(WidgetT *w, WidgetT *root, int32_t vx, int32_t vy) {
typedef void (*FnT)(WidgetT *, WidgetT *, int32_t, int32_t);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_ON_MOUSE] : NULL;
if (fn) { fn(w, root, vx, vy); }
}
static inline void wclsOnKey(WidgetT *w, int32_t key, int32_t mod) {
typedef void (*FnT)(WidgetT *, int32_t, int32_t);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_ON_KEY] : NULL;
if (fn) { fn(w, key, mod); }
}
static inline void wclsOnAccelActivate(WidgetT *w, WidgetT *root) {
typedef void (*FnT)(WidgetT *, WidgetT *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_ON_ACCEL_ACTIVATE] : NULL;
if (fn) { fn(w, root); }
}
static inline void wclsDestroy(WidgetT *w) {
typedef void (*FnT)(WidgetT *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_DESTROY] : NULL;
if (fn) { fn(w); }
}
static inline void wclsOnChildChanged(WidgetT *parent, WidgetT *child) {
typedef void (*FnT)(WidgetT *, WidgetT *);
FnT fn = parent->wclass ? (FnT)parent->wclass->handlers[WGT_METHOD_ON_CHILD_CHANGED] : NULL;
if (fn) { fn(parent, child); }
}
static inline const char *wclsGetText(const WidgetT *w) {
typedef const char *(*FnT)(const WidgetT *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_GET_TEXT] : NULL;
return fn ? fn(w) : "";
}
static inline void wclsSetText(WidgetT *w, const char *text) {
typedef void (*FnT)(WidgetT *, const char *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_SET_TEXT] : NULL;
if (fn) { fn(w, text); }
}
static inline bool wclsClearSelection(WidgetT *w) {
typedef bool (*FnT)(WidgetT *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_CLEAR_SELECTION] : NULL;
return fn ? fn(w) : false;
}
static inline void wclsClosePopup(WidgetT *w) {
typedef void (*FnT)(WidgetT *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_CLOSE_POPUP] : NULL;
if (fn) { fn(w); }
}
static inline void wclsGetPopupRect(const WidgetT *w, const BitmapFontT *font, int32_t contentH, int32_t *popX, int32_t *popY, int32_t *popW, int32_t *popH) {
typedef void (*FnT)(const WidgetT *, const BitmapFontT *, int32_t, int32_t *, int32_t *, int32_t *, int32_t *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_GET_POPUP_RECT] : NULL;
if (fn) { fn(w, font, contentH, popX, popY, popW, popH); }
}
static inline void wclsOnDragUpdate(WidgetT *w, WidgetT *root, int32_t x, int32_t y) {
typedef void (*FnT)(WidgetT *, WidgetT *, int32_t, int32_t);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_ON_DRAG_UPDATE] : NULL;
if (fn) { fn(w, root, x, y); }
}
static inline void wclsOnDragEnd(WidgetT *w, WidgetT *root, int32_t x, int32_t y) {
typedef void (*FnT)(WidgetT *, WidgetT *, int32_t, int32_t);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_ON_DRAG_END] : NULL;
if (fn) { fn(w, root, x, y); }
}
static inline int32_t wclsGetCursorShape(const WidgetT *w, int32_t vx, int32_t vy) {
typedef int32_t (*FnT)(const WidgetT *, int32_t, int32_t);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_GET_CURSOR_SHAPE] : NULL;
return fn ? fn(w, vx, vy) : 0;
}
static inline void wclsPoll(WidgetT *w, WindowT *win) {
typedef void (*FnT)(WidgetT *, WindowT *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_POLL] : NULL;
if (fn) { fn(w, win); }
}
static inline int32_t wclsQuickRepaint(WidgetT *w, int32_t *outY, int32_t *outH) {
typedef int32_t (*FnT)(WidgetT *, int32_t *, int32_t *);
FnT fn = w->wclass ? (FnT)w->wclass->handlers[WGT_METHOD_QUICK_REPAINT] : NULL;
return fn ? fn(w, outY, outH) : 0;
}
static inline void wclsScrollChildIntoView(WidgetT *parent, const WidgetT *child) {
typedef void (*FnT)(WidgetT *, const WidgetT *);
FnT fn = parent->wclass ? (FnT)parent->wclass->handlers[WGT_METHOD_SCROLL_CHILD_INTO_VIEW] : NULL;
if (fn) { fn(parent, child); }
}
// ============================================================
// Window integration
// ============================================================

View file

@ -251,9 +251,7 @@ void widgetDestroyChildren(WidgetT *w) {
WidgetT *next = child->nextSibling;
widgetDestroyChildren(child);
if (child->wclass && child->wclass->destroy) {
child->wclass->destroy(child);
}
wclsDestroy(child);
// Clear static references if they point to destroyed widgets
if (sFocusedWidget == child) {
@ -455,7 +453,7 @@ WidgetT *widgetFindPrevFocusable(WidgetT *root, WidgetT *before) {
// ============================================================
int32_t widgetFrameBorderWidth(const WidgetT *w) {
if (!w->wclass || !w->wclass->getLayoutMetrics) {
if (!wclsHas(w, WGT_METHOD_GET_LAYOUT_METRICS)) {
return 0;
}
@ -464,7 +462,7 @@ int32_t widgetFrameBorderWidth(const WidgetT *w) {
int32_t extraTop = 0;
int32_t borderW = 0;
w->wclass->getLayoutMetrics(w, NULL, &pad, &gap, &extraTop, &borderW);
wclsGetLayoutMetrics(w, NULL, &pad, &gap, &extraTop, &borderW);
return borderW;
}

View file

@ -173,9 +173,7 @@ void widgetOnKey(WindowT *win, int32_t key, int32_t mod) {
}
// Dispatch to per-widget onKey handler via vtable
if (focus->wclass && focus->wclass->onKey) {
focus->wclass->onKey(focus, key, mod);
}
wclsOnKey(focus, key, mod);
}
@ -207,18 +205,13 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
// Close popups from other windows
if (sOpenPopup && sOpenPopup->window != win) {
if (sOpenPopup->wclass && sOpenPopup->wclass->closePopup) {
sOpenPopup->wclass->closePopup(sOpenPopup);
}
wclsClosePopup(sOpenPopup);
sOpenPopup = NULL;
}
// Handle drag release
if (sDragWidget && !(buttons & MOUSE_LEFT)) {
if (sDragWidget->wclass && sDragWidget->wclass->onDragEnd) {
sDragWidget->wclass->onDragEnd(sDragWidget, root, x, y);
}
wclsOnDragEnd(sDragWidget, root, x, y);
wgtInvalidatePaint(root);
sDragWidget = NULL;
@ -227,16 +220,14 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
// Handle drag move
if (sDragWidget && (buttons & MOUSE_LEFT)) {
if (sDragWidget->wclass && sDragWidget->wclass->onDragUpdate) {
sDragWidget->wclass->onDragUpdate(sDragWidget, root, x, y);
}
wclsOnDragUpdate(sDragWidget, root, x, y);
// quickRepaint fast path for text drag (dirty rect instead of full repaint)
if (sDragWidget->wclass && sDragWidget->wclass->quickRepaint) {
if (wclsHas(sDragWidget, WGT_METHOD_QUICK_REPAINT)) {
int32_t dirtyY = 0;
int32_t dirtyH = 0;
if (sDragWidget->wclass->quickRepaint(sDragWidget, &dirtyY, &dirtyH) > 0) {
if (wclsQuickRepaint(sDragWidget, &dirtyY, &dirtyH) > 0) {
AppContextT *ctx = (AppContextT *)root->userData;
int32_t scrollY2 = win->vScroll ? win->vScroll->value : 0;
int32_t rectX = win->x + win->contentX;
@ -268,18 +259,16 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
int32_t popW;
int32_t popH;
if (!sOpenPopup->wclass || !sOpenPopup->wclass->getPopupRect) {
if (!wclsHas(sOpenPopup, WGT_METHOD_GET_POPUP_RECT)) {
sOpenPopup = NULL;
return;
}
sOpenPopup->wclass->getPopupRect(sOpenPopup, font, win->contentH, &popX, &popY, &popW, &popH);
wclsGetPopupRect(sOpenPopup, font, win->contentH, &popX, &popY, &popW, &popH);
if (x >= popX && x < popX + popW && y >= popY && y < popY + popH) {
// Click on popup item -- dispatch to widget's onMouse
if (sOpenPopup->wclass && sOpenPopup->wclass->onMouse) {
sOpenPopup->wclass->onMouse(sOpenPopup, root, x, y);
}
wclsOnMouse(sOpenPopup, root, x, y);
sOpenPopup = NULL;
wgtInvalidate(root);
@ -289,10 +278,7 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
// Click outside popup -- close it and remember which widget it was
sClosedPopup = sOpenPopup;
if (sOpenPopup->wclass && sOpenPopup->wclass->closePopup) {
sOpenPopup->wclass->closePopup(sOpenPopup);
}
wclsClosePopup(sOpenPopup);
sOpenPopup = NULL;
wgtInvalidatePaint(root);
// Fall through to normal click handling
@ -325,8 +311,8 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
// Dispatch to the hit widget's mouse handler via vtable. The handler
// is responsible for setting hit->focused=true if it wants focus.
if (hit->enabled && hit->wclass && hit->wclass->onMouse) {
hit->wclass->onMouse(hit, root, vx, vy);
if (hit->enabled) {
wclsOnMouse(hit, root, vx, vy);
}
// Universal click/double-click callbacks -- fire for ALL widget types

View file

@ -62,9 +62,9 @@ void widgetCalcMinSizeBox(WidgetT *w, const BitmapFontT *font) {
// Widgets with getLayoutMetrics override default padding/gap/extraTop
int32_t frameExtraTop = 0;
if (w->wclass && w->wclass->getLayoutMetrics) {
if (wclsHas(w, WGT_METHOD_GET_LAYOUT_METRICS)) {
int32_t metricBorderW = 0;
w->wclass->getLayoutMetrics(w, font, &pad, &gap, &frameExtraTop, &metricBorderW);
wclsGetLayoutMetrics(w, font, &pad, &gap, &frameExtraTop, &metricBorderW);
}
for (WidgetT *c = w->firstChild; c; c = c->nextSibling) {
@ -103,7 +103,7 @@ void widgetCalcMinSizeBox(WidgetT *w, const BitmapFontT *font) {
}
// Border (Frame and similar containers with getLayoutMetrics)
if (w->wclass && w->wclass->getLayoutMetrics) {
if (wclsHas(w, WGT_METHOD_GET_LAYOUT_METRICS)) {
int32_t fb = widgetFrameBorderWidth(w);
w->calcMinW += fb * 2;
w->calcMinH += fb * 2;
@ -130,8 +130,8 @@ void widgetCalcMinSizeBox(WidgetT *w, const BitmapFontT *font) {
void widgetCalcMinSizeTree(WidgetT *w, const BitmapFontT *font) {
if (widgetIsBoxContainer(w->type)) {
widgetCalcMinSizeBox(w, font);
} else if (w->wclass && w->wclass->calcMinSize) {
w->wclass->calcMinSize(w, font);
} else if (wclsHas(w, WGT_METHOD_CALC_MIN_SIZE)) {
wclsCalcMinSize(w, font);
} else {
w->calcMinW = 0;
w->calcMinH = 0;
@ -201,8 +201,8 @@ void widgetLayoutBox(WidgetT *w, const BitmapFontT *font) {
int32_t frameExtraTop = 0;
int32_t fb = 0;
if (w->wclass && w->wclass->getLayoutMetrics) {
w->wclass->getLayoutMetrics(w, font, &pad, &gap, &frameExtraTop, &fb);
if (wclsHas(w, WGT_METHOD_GET_LAYOUT_METRICS)) {
wclsGetLayoutMetrics(w, font, &pad, &gap, &frameExtraTop, &fb);
}
int32_t innerX = w->x + pad + fb;
@ -338,8 +338,8 @@ void widgetLayoutBox(WidgetT *w, const BitmapFontT *font) {
void widgetLayoutChildren(WidgetT *w, const BitmapFontT *font) {
if (widgetIsBoxContainer(w->type)) {
widgetLayoutBox(w, font);
} else if (w->wclass && w->wclass->layout) {
w->wclass->layout(w, font);
} else if (wclsHas(w, WGT_METHOD_LAYOUT)) {
wclsLayout(w, font);
}
}

View file

@ -75,9 +75,7 @@ void widgetPaintOne(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const BitmapFo
}
// Paint this widget via vtable
if (w->wclass && w->wclass->paint) {
w->wclass->paint(w, d, ops, font, colors);
}
wclsPaint(w, d, ops, font, colors);
// Widgets that paint their own children return early
if (w->wclass && (w->wclass->flags & WCLASS_PAINTS_CHILDREN)) {
@ -128,9 +126,7 @@ void widgetPaintOverlays(WidgetT *root, DisplayT *d, const BlitOpsT *ops, const
return;
}
if (sOpenPopup->wclass && sOpenPopup->wclass->paintOverlay) {
sOpenPopup->wclass->paintOverlay(sOpenPopup, d, ops, font, colors);
}
wclsPaintOverlay(sOpenPopup, d, ops, font, colors);
}
@ -158,8 +154,8 @@ void wgtDestroy(WidgetT *w) {
// Notify parent chain of child destruction via onChildChanged vtable
if (w->parent) {
for (WidgetT *p = w->parent; p; p = p->parent) {
if (p->wclass && p->wclass->onChildChanged) {
p->wclass->onChildChanged(p, w);
if (wclsHas(p, WGT_METHOD_ON_CHILD_CHANGED)) {
wclsOnChildChanged(p, w);
break;
}
}
@ -171,9 +167,7 @@ void wgtDestroy(WidgetT *w) {
widgetDestroyChildren(w);
if (w->wclass && w->wclass->destroy) {
w->wclass->destroy(w);
}
wclsDestroy(w);
// Clear static references
if (sFocusedWidget == w) {
@ -280,11 +274,7 @@ const char *wgtGetText(const WidgetT *w) {
return "";
}
if (w->wclass && w->wclass->getText) {
return w->wclass->getText(w);
}
return "";
return wclsGetText(w);
}
@ -502,9 +492,7 @@ void wgtSetText(WidgetT *w, const char *text) {
return;
}
if (w->wclass && w->wclass->setText) {
w->wclass->setText(w, text);
}
wclsSetText(w, text);
wgtInvalidate(w);
}
@ -532,8 +520,8 @@ void wgtSetVisible(WidgetT *w, bool visible) {
// Notify parent chain of child visibility change via onChildChanged vtable
if (w->parent) {
for (WidgetT *p = w->parent; p; p = p->parent) {
if (p->wclass && p->wclass->onChildChanged) {
p->wclass->onChildChanged(p, w);
if (wclsHas(p, WGT_METHOD_ON_CHILD_CHANGED)) {
wclsOnChildChanged(p, w);
break;
}
}

View file

@ -13,7 +13,7 @@ CONFIGDIR = ../bin/config
THEMEDIR = ../bin/config/themes
WPAPERDIR = ../bin/config/wpaper
SRCS = shellMain.c shellApp.c shellInfo.c shellTaskMgr.c
SRCS = shellMain.c shellApp.c shellInfo.c
OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
TARGET = $(LIBSDIR)/dvxshell.lib
@ -63,7 +63,6 @@ SHELL_DEPS = shellApp.h ../core/dvxWidget.h ../core/dvxApp.h ../core/dvxTypes.h
$(OBJDIR)/shellMain.o: shellMain.c $(SHELL_DEPS)
$(OBJDIR)/shellApp.o: shellApp.c $(SHELL_DEPS)
$(OBJDIR)/shellInfo.o: shellInfo.c shellInfo.h $(SHELL_DEPS)
$(OBJDIR)/shellTaskMgr.o: shellTaskMgr.c shellTaskMgr.h $(SHELL_DEPS)
clean:
rm -f $(OBJS) $(TARGET) $(LIBSDIR)/dvxshell.dep

View file

@ -25,6 +25,9 @@
static ShellAppT *sApps = NULL;
static int32_t sAppsCap = 0; // number of slots allocated (including slot 0)
// Ctrl+Esc handler -- set by taskmgr DXE constructor, NULL if not loaded
void (*shellCtrlEscFn)(AppContextT *ctx) = NULL;
// ============================================================
// Prototypes
// ============================================================

View file

@ -170,4 +170,12 @@ void shellUnregisterDesktopUpdate(void (*updateFn)(void));
// Notify the desktop app that app state has changed (load, reap, crash).
void shellDesktopUpdate(void);
// ============================================================
// Ctrl+Esc handler (set by taskmgr library)
// ============================================================
// Function pointer set by the taskmgr DXE's constructor. The shell
// calls this on Ctrl+Esc. NULL if taskmgr is not loaded.
extern void (*shellCtrlEscFn)(AppContextT *ctx);
#endif // SHELL_APP_H

View file

@ -28,7 +28,6 @@
#include "shellApp.h"
#include "shellInfo.h"
#include "shellTaskMgr.h"
#include "dvxDialog.h"
#include "dvxPrefs.h"
#include "dvxPlatform.h"
@ -77,7 +76,9 @@ void shellDesktopUpdate(void) {
// ============================================================
static void ctrlEscHandler(void *ctx) {
shellTaskMgrOpen((AppContextT *)ctx);
if (shellCtrlEscFn) {
shellCtrlEscFn((AppContextT *)ctx);
}
}

41
taskmgr/Makefile Normal file
View file

@ -0,0 +1,41 @@
# DVX Task Manager Makefile for DJGPP cross-compilation
#
# Builds taskmgr.lib -- the Task Manager, loaded as a separate DXE.
DJGPP_PREFIX = $(HOME)/djgpp/djgpp
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
DXE3GEN = PATH=$(DJGPP_PREFIX)/bin:$(PATH) DJDIR=$(DJGPP_PREFIX)/i586-pc-msdosdjgpp $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/dxe3gen
CFLAGS = -O2 -Wall -Wextra -march=i486 -mtune=i586 -I../core -I../core/platform -I../widgets -I../shell -I../tasks -I../core/thirdparty
OBJDIR = ../obj/taskmgr
LIBSDIR = ../bin/libs
SRCS = shellTaskMgr.c
OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
TARGET = $(LIBSDIR)/taskmgr.lib
.PHONY: all clean
all: $(TARGET) $(LIBSDIR)/taskmgr.dep
$(LIBSDIR)/taskmgr.dep: ../config/taskmgr.dep | $(LIBSDIR)
sed 's/$$/\r/' $< > $@
$(TARGET): $(OBJS) | $(LIBSDIR)
$(DXE3GEN) -o $(LIBSDIR)/taskmgr.dxe -U $(OBJS)
mv $(LIBSDIR)/taskmgr.dxe $@
$(OBJDIR)/%.o: %.c | $(OBJDIR)
$(CC) $(CFLAGS) -c -o $@ $<
$(OBJDIR):
mkdir -p $(OBJDIR)
$(LIBSDIR):
mkdir -p $(LIBSDIR)
# Dependencies
$(OBJDIR)/shellTaskMgr.o: shellTaskMgr.c shellTaskMgr.h ../shell/shellApp.h ../core/dvxWidget.h ../core/dvxApp.h
clean:
rm -f $(OBJS) $(TARGET) $(LIBSDIR)/taskmgr.dep

View file

@ -5,7 +5,7 @@
// all running apps with Switch To, End Task, and Run buttons.
#include "shellTaskMgr.h"
#include "shellApp.h"
#include "../shell/shellApp.h"
#include "dvxDialog.h"
#include "dvxWidget.h"
#include "widgetBox.h"
@ -329,8 +329,9 @@ void shellTaskMgrOpen(AppContextT *ctx) {
tmCols[4].align = ListViewAlignLeftE;
sTmListView = wgtListView(root);
sTmListView->weight = 100;
sTmListView->prefH = wgtPixels(TM_LIST_PREF_H);
sTmListView->weight = 100;
sTmListView->prefH = wgtPixels(TM_LIST_PREF_H);
sTmListView->onDblClick = onTmSwitchTo;
wgtListViewSetColumns(sTmListView, tmCols, TM_COL_COUNT);
WidgetT *btnRow = wgtHBox(root);
@ -339,15 +340,15 @@ void shellTaskMgrOpen(AppContextT *ctx) {
sTmStatusLbl = wgtLabel(btnRow, "");
sTmStatusLbl->weight = 100;
WidgetT *switchBtn = wgtButton(btnRow, "Switch To");
WidgetT *switchBtn = wgtButton(btnRow, "&Switch To");
switchBtn->onClick = onTmSwitchTo;
switchBtn->prefW = wgtPixels(TM_BTN_W);
WidgetT *endBtn = wgtButton(btnRow, "End Task");
WidgetT *endBtn = wgtButton(btnRow, "&End Task");
endBtn->onClick = onTmEndTask;
endBtn->prefW = wgtPixels(TM_BTN_W);
WidgetT *runBtn = wgtButton(btnRow, "Run...");
WidgetT *runBtn = wgtButton(btnRow, "&Run...");
runBtn->onClick = onTmRun;
runBtn->prefW = wgtPixels(TM_BTN_W);
@ -368,3 +369,13 @@ void shellTaskMgrRefresh(void) {
updateStatusText();
}
}
// ============================================================
// DXE constructor -- register Ctrl+Esc handler with the shell
// ============================================================
static void taskmgrInit(void) __attribute__((constructor));
static void taskmgrInit(void) {
shellCtrlEscFn = shellTaskMgrOpen;
}

View file

@ -114,11 +114,7 @@ void clearOtherSelections(WidgetT *except) {
static bool clearSelectionOnWidget(WidgetT *w) {
if (w->wclass && w->wclass->clearSelection) {
return w->wclass->clearSelection(w);
}
return false;
return wclsClearSelection(w);
}

View file

@ -960,20 +960,19 @@ static void widgetAnsiTermOnDragUpdate(WidgetT *w, WidgetT *root, int32_t vx, in
static const WidgetClassT sClassAnsiTerm = {
.flags = WCLASS_FOCUSABLE | WCLASS_SCROLLABLE | WCLASS_NEEDS_POLL | WCLASS_SWALLOWS_TAB,
.paint = widgetAnsiTermPaint,
.paintOverlay = NULL,
.calcMinSize = widgetAnsiTermCalcMinSize,
.layout = NULL,
.onMouse = widgetAnsiTermOnMouse,
.onKey = widgetAnsiTermOnKey,
.destroy = widgetAnsiTermDestroy,
.getText = NULL,
.setText = NULL,
.clearSelection = widgetAnsiTermClearSelection,
.onDragUpdate = widgetAnsiTermOnDragUpdate,
.poll = widgetAnsiTermPollVtable,
.quickRepaint = wgtAnsiTermRepaint
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE | WCLASS_SCROLLABLE | WCLASS_NEEDS_POLL | WCLASS_SWALLOWS_TAB,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetAnsiTermPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetAnsiTermCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetAnsiTermOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetAnsiTermOnKey,
[WGT_METHOD_DESTROY] = (void *)widgetAnsiTermDestroy,
[WGT_METHOD_CLEAR_SELECTION] = (void *)widgetAnsiTermClearSelection,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetAnsiTermOnDragUpdate,
[WGT_METHOD_POLL] = (void *)widgetAnsiTermPollVtable,
[WGT_METHOD_QUICK_REPAINT] = (void *)wgtAnsiTermRepaint,
}
};

View file

@ -140,43 +140,23 @@ void widgetFrameDestroy(WidgetT *w) {
static const WidgetClassT sClassVBox = {
.flags = WCLASS_BOX_CONTAINER,
.paint = NULL,
.paintOverlay = NULL,
.calcMinSize = NULL,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.destroy = NULL,
.getText = NULL,
.setText = NULL
.version = WGT_CLASS_VERSION,
.flags = WCLASS_BOX_CONTAINER,
};
static const WidgetClassT sClassHBox = {
.flags = WCLASS_BOX_CONTAINER | WCLASS_HORIZ_CONTAINER,
.paint = NULL,
.paintOverlay = NULL,
.calcMinSize = NULL,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.destroy = NULL,
.getText = NULL,
.setText = NULL
.version = WGT_CLASS_VERSION,
.flags = WCLASS_BOX_CONTAINER | WCLASS_HORIZ_CONTAINER,
};
static const WidgetClassT sClassFrame = {
.flags = WCLASS_BOX_CONTAINER | WCLASS_FOCUS_FORWARD,
.paint = widgetFramePaint,
.paintOverlay = NULL,
.calcMinSize = NULL,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.destroy = widgetFrameDestroy,
.getText = NULL,
.setText = NULL,
.getLayoutMetrics = widgetFrameGetLayoutMetrics
.version = WGT_CLASS_VERSION,
.flags = WCLASS_BOX_CONTAINER | WCLASS_FOCUS_FORWARD,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetFramePaint,
[WGT_METHOD_DESTROY] = (void *)widgetFrameDestroy,
[WGT_METHOD_GET_LAYOUT_METRICS] = (void *)widgetFrameGetLayoutMetrics,
}
};
// ============================================================

View file

@ -215,19 +215,20 @@ void widgetButtonSetText(WidgetT *w, const char *text) {
static const WidgetClassT sClassButton = {
.flags = WCLASS_FOCUSABLE | WCLASS_PRESS_RELEASE,
.paint = widgetButtonPaint,
.paintOverlay = NULL,
.calcMinSize = widgetButtonCalcMinSize,
.layout = NULL,
.onMouse = widgetButtonOnMouse,
.onKey = widgetButtonOnKey,
.onAccelActivate = widgetButtonAccelActivate,
.destroy = widgetButtonDestroy,
.getText = widgetButtonGetText,
.setText = widgetButtonSetText,
.onDragUpdate = widgetButtonOnDragUpdate,
.onDragEnd = widgetButtonOnDragEnd
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE | WCLASS_PRESS_RELEASE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetButtonPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetButtonCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetButtonOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetButtonOnKey,
[WGT_METHOD_ON_ACCEL_ACTIVATE] = (void *)widgetButtonAccelActivate,
[WGT_METHOD_DESTROY] = (void *)widgetButtonDestroy,
[WGT_METHOD_GET_TEXT] = (void *)widgetButtonGetText,
[WGT_METHOD_SET_TEXT] = (void *)widgetButtonSetText,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetButtonOnDragUpdate,
[WGT_METHOD_ON_DRAG_END] = (void *)widgetButtonOnDragEnd,
}
};
// ============================================================

View file

@ -657,17 +657,15 @@ void widgetCanvasPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const Bitma
// ============================================================
static const WidgetClassT sClassCanvas = {
.flags = 0,
.paint = widgetCanvasPaint,
.paintOverlay = NULL,
.calcMinSize = widgetCanvasCalcMinSize,
.layout = NULL,
.onMouse = widgetCanvasOnMouse,
.onDragUpdate = widgetCanvasOnDragUpdate,
.onKey = NULL,
.destroy = widgetCanvasDestroy,
.getText = NULL,
.setText = NULL
.version = WGT_CLASS_VERSION,
.flags = 0,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetCanvasPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetCanvasCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetCanvasOnMouse,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetCanvasOnDragUpdate,
[WGT_METHOD_DESTROY] = (void *)widgetCanvasDestroy,
}
};

View file

@ -186,17 +186,18 @@ void widgetCheckboxSetText(WidgetT *w, const char *text) {
static const WidgetClassT sClassCheckbox = {
.flags = WCLASS_FOCUSABLE,
.paint = widgetCheckboxPaint,
.paintOverlay = NULL,
.calcMinSize = widgetCheckboxCalcMinSize,
.layout = NULL,
.onMouse = widgetCheckboxOnMouse,
.onKey = widgetCheckboxOnKey,
.onAccelActivate = widgetCheckboxAccelActivate,
.destroy = widgetCheckboxDestroy,
.getText = widgetCheckboxGetText,
.setText = widgetCheckboxSetText
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetCheckboxPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetCheckboxCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetCheckboxOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetCheckboxOnKey,
[WGT_METHOD_ON_ACCEL_ACTIVATE] = (void *)widgetCheckboxAccelActivate,
[WGT_METHOD_DESTROY] = (void *)widgetCheckboxDestroy,
[WGT_METHOD_GET_TEXT] = (void *)widgetCheckboxGetText,
[WGT_METHOD_SET_TEXT] = (void *)widgetCheckboxSetText,
}
};
// ============================================================

View file

@ -415,21 +415,23 @@ static void widgetComboBoxOnDragUpdate(WidgetT *w, WidgetT *root, int32_t vx, in
static const WidgetClassT sClassComboBox = {
.flags = WCLASS_FOCUSABLE | WCLASS_HAS_POPUP | WCLASS_SCROLLABLE,
.paint = widgetComboBoxPaint,
.paintOverlay = widgetComboBoxPaintPopup,
.calcMinSize = widgetComboBoxCalcMinSize,
.layout = NULL,
.onMouse = widgetComboBoxOnMouse,
.onKey = widgetComboBoxOnKey,
.onAccelActivate = widgetComboBoxAccelActivate,
.destroy = widgetComboBoxDestroy,
.getText = widgetComboBoxGetText,
.setText = widgetComboBoxSetText,
.closePopup = widgetComboBoxClosePopup,
.clearSelection = widgetComboBoxClearSelection,
.onDragUpdate = widgetComboBoxOnDragUpdate,
.getPopupRect = widgetComboBoxGetPopupRect
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE | WCLASS_HAS_POPUP | WCLASS_SCROLLABLE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetComboBoxPaint,
[WGT_METHOD_PAINT_OVERLAY] = (void *)widgetComboBoxPaintPopup,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetComboBoxCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetComboBoxOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetComboBoxOnKey,
[WGT_METHOD_ON_ACCEL_ACTIVATE] = (void *)widgetComboBoxAccelActivate,
[WGT_METHOD_DESTROY] = (void *)widgetComboBoxDestroy,
[WGT_METHOD_GET_TEXT] = (void *)widgetComboBoxGetText,
[WGT_METHOD_SET_TEXT] = (void *)widgetComboBoxSetText,
[WGT_METHOD_CLOSE_POPUP] = (void *)widgetComboBoxClosePopup,
[WGT_METHOD_CLEAR_SELECTION] = (void *)widgetComboBoxClearSelection,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetComboBoxOnDragUpdate,
[WGT_METHOD_GET_POPUP_RECT] = (void *)widgetComboBoxGetPopupRect,
}
};

View file

@ -309,19 +309,20 @@ static void widgetDropdownGetPopupRect(const WidgetT *w, const BitmapFontT *font
static const WidgetClassT sClassDropdown = {
.flags = WCLASS_FOCUSABLE | WCLASS_HAS_POPUP | WCLASS_SCROLLABLE,
.paint = widgetDropdownPaint,
.paintOverlay = widgetDropdownPaintPopup,
.calcMinSize = widgetDropdownCalcMinSize,
.layout = NULL,
.onMouse = widgetDropdownOnMouse,
.onKey = widgetDropdownOnKey,
.onAccelActivate = widgetDropdownAccelActivate,
.destroy = widgetDropdownDestroy,
.getText = widgetDropdownGetText,
.setText = NULL,
.closePopup = widgetDropdownClosePopup,
.getPopupRect = widgetDropdownGetPopupRect
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE | WCLASS_HAS_POPUP | WCLASS_SCROLLABLE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetDropdownPaint,
[WGT_METHOD_PAINT_OVERLAY] = (void *)widgetDropdownPaintPopup,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetDropdownCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetDropdownOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetDropdownOnKey,
[WGT_METHOD_ON_ACCEL_ACTIVATE] = (void *)widgetDropdownAccelActivate,
[WGT_METHOD_DESTROY] = (void *)widgetDropdownDestroy,
[WGT_METHOD_GET_TEXT] = (void *)widgetDropdownGetText,
[WGT_METHOD_CLOSE_POPUP] = (void *)widgetDropdownClosePopup,
[WGT_METHOD_GET_POPUP_RECT] = (void *)widgetDropdownGetPopupRect,
}
};
// ============================================================

View file

@ -117,16 +117,14 @@ void widgetImagePaint(WidgetT *w, DisplayT *disp, const BlitOpsT *ops, const Bit
// ============================================================
static const WidgetClassT sClassImage = {
.flags = 0,
.paint = widgetImagePaint,
.paintOverlay = NULL,
.calcMinSize = widgetImageCalcMinSize,
.layout = NULL,
.onMouse = widgetImageOnMouse,
.onKey = NULL,
.destroy = widgetImageDestroy,
.getText = NULL,
.setText = NULL
.version = WGT_CLASS_VERSION,
.flags = 0,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetImagePaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetImageCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetImageOnMouse,
[WGT_METHOD_DESTROY] = (void *)widgetImageDestroy,
}
};

View file

@ -181,19 +181,18 @@ static void widgetImageButtonOnDragUpdate(WidgetT *w, WidgetT *root, int32_t x,
// ============================================================
static const WidgetClassT sClassImageButton = {
.flags = WCLASS_FOCUSABLE | WCLASS_PRESS_RELEASE,
.paint = widgetImageButtonPaint,
.paintOverlay = NULL,
.calcMinSize = widgetImageButtonCalcMinSize,
.layout = NULL,
.onMouse = widgetImageButtonOnMouse,
.onKey = widgetImageButtonOnKey,
.onAccelActivate = widgetImageButtonAccelActivate,
.destroy = widgetImageButtonDestroy,
.getText = NULL,
.setText = NULL,
.onDragUpdate = widgetImageButtonOnDragUpdate,
.onDragEnd = widgetImageButtonOnDragEnd
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE | WCLASS_PRESS_RELEASE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetImageButtonPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetImageButtonCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetImageButtonOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetImageButtonOnKey,
[WGT_METHOD_ON_ACCEL_ACTIVATE] = (void *)widgetImageButtonAccelActivate,
[WGT_METHOD_DESTROY] = (void *)widgetImageButtonDestroy,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetImageButtonOnDragUpdate,
[WGT_METHOD_ON_DRAG_END] = (void *)widgetImageButtonOnDragEnd,
}
};

View file

@ -109,16 +109,15 @@ void widgetLabelSetText(WidgetT *w, const char *text) {
static const WidgetClassT sClassLabel = {
.flags = WCLASS_FOCUS_FORWARD,
.paint = widgetLabelPaint,
.paintOverlay = NULL,
.calcMinSize = widgetLabelCalcMinSize,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.destroy = widgetLabelDestroy,
.getText = widgetLabelGetText,
.setText = widgetLabelSetText
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUS_FORWARD,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetLabelPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetLabelCalcMinSize,
[WGT_METHOD_DESTROY] = (void *)widgetLabelDestroy,
[WGT_METHOD_GET_TEXT] = (void *)widgetLabelGetText,
[WGT_METHOD_SET_TEXT] = (void *)widgetLabelSetText,
}
};
// ============================================================

View file

@ -623,18 +623,17 @@ static void widgetListBoxOnDragUpdate(WidgetT *w, WidgetT *root, int32_t x, int3
static const WidgetClassT sClassListBox = {
.flags = WCLASS_FOCUSABLE | WCLASS_SCROLLABLE,
.paint = widgetListBoxPaint,
.paintOverlay = NULL,
.calcMinSize = widgetListBoxCalcMinSize,
.layout = NULL,
.onMouse = widgetListBoxOnMouse,
.onKey = widgetListBoxOnKey,
.destroy = widgetListBoxDestroy,
.getText = NULL,
.setText = NULL,
.onDragUpdate = widgetListBoxOnDragUpdate,
.onDragEnd = widgetListBoxOnDragEnd
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE | WCLASS_SCROLLABLE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetListBoxPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetListBoxCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetListBoxOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetListBoxOnKey,
[WGT_METHOD_DESTROY] = (void *)widgetListBoxDestroy,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetListBoxOnDragUpdate,
[WGT_METHOD_ON_DRAG_END] = (void *)widgetListBoxOnDragEnd,
}
};
// ============================================================

View file

@ -1460,18 +1460,29 @@ static void widgetListViewReorderDrop(WidgetT *w) {
moving[c] = lv->cellData[from * cols + c];
}
// Save the moving row's selection bit
uint8_t movingSel = (lv->selBits && from < lv->rowCount) ? lv->selBits[from] : 0;
if (to > from) {
// Moving down: shift rows up
for (int32_t r = from; r < to - 1; r++) {
for (int32_t c = 0; c < cols; c++) {
((const char **)lv->cellData)[r * cols + c] = lv->cellData[(r + 1) * cols + c];
}
if (lv->selBits) {
lv->selBits[r] = lv->selBits[r + 1];
}
}
for (int32_t c = 0; c < cols; c++) {
((const char **)lv->cellData)[(to - 1) * cols + c] = moving[c];
}
if (lv->selBits) {
lv->selBits[to - 1] = movingSel;
}
lv->selectedIdx = to - 1;
} else {
// Moving up: shift rows down
@ -1479,12 +1490,20 @@ static void widgetListViewReorderDrop(WidgetT *w) {
for (int32_t c = 0; c < cols; c++) {
((const char **)lv->cellData)[r * cols + c] = lv->cellData[(r - 1) * cols + c];
}
if (lv->selBits) {
lv->selBits[r] = lv->selBits[r - 1];
}
}
for (int32_t c = 0; c < cols; c++) {
((const char **)lv->cellData)[to * cols + c] = moving[c];
}
if (lv->selBits) {
lv->selBits[to] = movingSel;
}
lv->selectedIdx = to;
}
@ -1534,19 +1553,18 @@ static void widgetListViewOnDragUpdate(WidgetT *w, WidgetT *root, int32_t x, int
static const WidgetClassT sClassListView = {
.flags = WCLASS_FOCUSABLE | WCLASS_NO_HIT_RECURSE | WCLASS_SCROLLABLE,
.paint = widgetListViewPaint,
.paintOverlay = NULL,
.calcMinSize = widgetListViewCalcMinSize,
.layout = NULL,
.onMouse = widgetListViewOnMouse,
.onKey = widgetListViewOnKey,
.destroy = widgetListViewDestroy,
.getText = NULL,
.setText = NULL,
.getCursorShape = widgetListViewGetCursorShape,
.onDragUpdate = widgetListViewOnDragUpdate,
.onDragEnd = widgetListViewOnDragEnd
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE | WCLASS_NO_HIT_RECURSE | WCLASS_SCROLLABLE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetListViewPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetListViewCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetListViewOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetListViewOnKey,
[WGT_METHOD_DESTROY] = (void *)widgetListViewDestroy,
[WGT_METHOD_GET_CURSOR_SHAPE] = (void *)widgetListViewGetCursorShape,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetListViewOnDragUpdate,
[WGT_METHOD_ON_DRAG_END] = (void *)widgetListViewOnDragEnd,
}
};

View file

@ -122,16 +122,13 @@ void widgetProgressBarDestroy(WidgetT *w) {
// ============================================================
static const WidgetClassT sClassProgressBar = {
.flags = 0,
.paint = widgetProgressBarPaint,
.paintOverlay = NULL,
.calcMinSize = widgetProgressBarCalcMinSize,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.destroy = widgetProgressBarDestroy,
.getText = NULL,
.setText = NULL
.version = WGT_CLASS_VERSION,
.flags = 0,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetProgressBarPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetProgressBarCalcMinSize,
[WGT_METHOD_DESTROY] = (void *)widgetProgressBarDestroy,
}
};

View file

@ -313,30 +313,26 @@ void widgetRadioSetText(WidgetT *w, const char *text) {
static const WidgetClassT sClassRadioGroup = {
.flags = WCLASS_BOX_CONTAINER,
.paint = NULL,
.paintOverlay = NULL,
.calcMinSize = NULL,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.destroy = widgetRadioGroupDestroy,
.getText = NULL,
.setText = NULL
.version = WGT_CLASS_VERSION,
.flags = WCLASS_BOX_CONTAINER,
.handlers = {
[WGT_METHOD_DESTROY] = (void *)widgetRadioGroupDestroy,
}
};
static const WidgetClassT sClassRadio = {
.flags = WCLASS_FOCUSABLE,
.paint = widgetRadioPaint,
.paintOverlay = NULL,
.calcMinSize = widgetRadioCalcMinSize,
.layout = NULL,
.onMouse = widgetRadioOnMouse,
.onKey = widgetRadioOnKey,
.onAccelActivate = widgetRadioAccelActivate,
.destroy = widgetRadioDestroy,
.getText = widgetRadioGetText,
.setText = widgetRadioSetText
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetRadioPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetRadioCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetRadioOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetRadioOnKey,
[WGT_METHOD_ON_ACCEL_ACTIVATE] = (void *)widgetRadioAccelActivate,
[WGT_METHOD_DESTROY] = (void *)widgetRadioDestroy,
[WGT_METHOD_GET_TEXT] = (void *)widgetRadioGetText,
[WGT_METHOD_SET_TEXT] = (void *)widgetRadioSetText,
}
};
// ============================================================

View file

@ -608,13 +608,13 @@ void widgetScrollPaneOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy
}
}
if (child && child->enabled && child->wclass && child->wclass->onMouse) {
if (child && child->enabled && wclsHas(child, WGT_METHOD_ON_MOUSE)) {
// Clear old focus
if (sFocusedWidget && sFocusedWidget != child) {
sFocusedWidget->focused = false;
}
child->wclass->onMouse(child, root, vx, vy);
wclsOnMouse(child, root, vx, vy);
if (child->focused) {
sFocusedWidget = child;
@ -776,18 +776,18 @@ void widgetScrollPanePaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const B
// ============================================================
static const WidgetClassT sClassScrollPane = {
.flags = WCLASS_PAINTS_CHILDREN | WCLASS_NO_HIT_RECURSE | WCLASS_SCROLL_CONTAINER | WCLASS_RELAYOUT_ON_SCROLL,
.paint = widgetScrollPanePaint,
.paintOverlay = NULL,
.calcMinSize = widgetScrollPaneCalcMinSize,
.layout = widgetScrollPaneLayout,
.onMouse = widgetScrollPaneOnMouse,
.onKey = widgetScrollPaneOnKey,
.destroy = widgetScrollPaneDestroy,
.getText = NULL,
.setText = NULL,
.scrollChildIntoView = wgtScrollPaneScrollToChild,
.onDragUpdate = widgetScrollPaneOnDragUpdate
.version = WGT_CLASS_VERSION,
.flags = WCLASS_PAINTS_CHILDREN | WCLASS_NO_HIT_RECURSE | WCLASS_SCROLL_CONTAINER | WCLASS_RELAYOUT_ON_SCROLL,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetScrollPanePaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetScrollPaneCalcMinSize,
[WGT_METHOD_LAYOUT] = (void *)widgetScrollPaneLayout,
[WGT_METHOD_ON_MOUSE] = (void *)widgetScrollPaneOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetScrollPaneOnKey,
[WGT_METHOD_DESTROY] = (void *)widgetScrollPaneDestroy,
[WGT_METHOD_SCROLL_CHILD_INTO_VIEW] = (void *)wgtScrollPaneScrollToChild,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetScrollPaneOnDragUpdate,
}
};

View file

@ -90,16 +90,13 @@ void widgetSeparatorPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const Bi
static const WidgetClassT sClassSeparator = {
.flags = 0,
.paint = widgetSeparatorPaint,
.paintOverlay = NULL,
.calcMinSize = widgetSeparatorCalcMinSize,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.destroy = widgetSeparatorDestroy,
.getText = NULL,
.setText = NULL
.version = WGT_CLASS_VERSION,
.flags = 0,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetSeparatorPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetSeparatorCalcMinSize,
[WGT_METHOD_DESTROY] = (void *)widgetSeparatorDestroy,
}
};
// ============================================================

View file

@ -320,17 +320,16 @@ static void widgetSliderDestroy(WidgetT *w) {
static const WidgetClassT sClassSlider = {
.flags = WCLASS_FOCUSABLE | WCLASS_SCROLLABLE,
.paint = widgetSliderPaint,
.paintOverlay = NULL,
.calcMinSize = widgetSliderCalcMinSize,
.layout = NULL,
.onMouse = widgetSliderOnMouse,
.onKey = widgetSliderOnKey,
.destroy = widgetSliderDestroy,
.getText = NULL,
.setText = NULL,
.onDragUpdate = widgetSliderOnDragUpdate
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE | WCLASS_SCROLLABLE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetSliderPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetSliderCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetSliderOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetSliderOnKey,
[WGT_METHOD_DESTROY] = (void *)widgetSliderDestroy,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetSliderOnDragUpdate,
}
};
// ============================================================

View file

@ -35,16 +35,11 @@ void widgetSpacerCalcMinSize(WidgetT *w, const BitmapFontT *font) {
static const WidgetClassT sClassSpacer = {
.flags = 0,
.paint = NULL,
.paintOverlay = NULL,
.calcMinSize = widgetSpacerCalcMinSize,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.destroy = NULL,
.getText = NULL,
.setText = NULL
.version = WGT_CLASS_VERSION,
.flags = 0,
.handlers = {
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetSpacerCalcMinSize,
}
};
// ============================================================

View file

@ -489,16 +489,17 @@ void widgetSpinnerDestroy(WidgetT *w) {
// ============================================================
static const WidgetClassT sClassSpinner = {
.flags = WCLASS_FOCUSABLE | WCLASS_SCROLLABLE,
.paint = widgetSpinnerPaint,
.paintOverlay = NULL,
.calcMinSize = widgetSpinnerCalcMinSize,
.layout = NULL,
.onMouse = widgetSpinnerOnMouse,
.onKey = widgetSpinnerOnKey,
.destroy = widgetSpinnerDestroy,
.getText = widgetSpinnerGetText,
.setText = widgetSpinnerSetText
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE | WCLASS_SCROLLABLE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetSpinnerPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetSpinnerCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetSpinnerOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetSpinnerOnKey,
[WGT_METHOD_DESTROY] = (void *)widgetSpinnerDestroy,
[WGT_METHOD_GET_TEXT] = (void *)widgetSpinnerGetText,
[WGT_METHOD_SET_TEXT] = (void *)widgetSpinnerSetText,
}
};

View file

@ -271,12 +271,12 @@ void widgetSplitterOnMouse(WidgetT *hit, WidgetT *root, int32_t vx, int32_t vy)
}
}
if (child && child->enabled && child->wclass && child->wclass->onMouse) {
if (child && child->enabled && wclsHas(child, WGT_METHOD_ON_MOUSE)) {
if (sFocusedWidget && sFocusedWidget != child) {
sFocusedWidget->focused = false;
}
child->wclass->onMouse(child, root, vx, vy);
wclsOnMouse(child, root, vx, vy);
if (child->focused) {
sFocusedWidget = child;
@ -406,8 +406,8 @@ int32_t widgetSplitterGetCursorShape(const WidgetT *w, int32_t vx, int32_t vy) {
for (WidgetT *c = w->firstChild; c; c = c->nextSibling) {
WidgetT *child = widgetHitTest(c, vx, vy);
if (child && child->wclass && child->wclass->getCursorShape) {
int32_t shape = child->wclass->getCursorShape(child, vx, vy);
if (child) {
int32_t shape = wclsGetCursorShape(child, vx, vy);
if (shape > 0) {
return shape;
@ -462,18 +462,17 @@ static void widgetSplitterOnDragUpdate(WidgetT *w, WidgetT *root, int32_t mouseX
// ============================================================
static const WidgetClassT sClassSplitter = {
.flags = WCLASS_PAINTS_CHILDREN | WCLASS_NO_HIT_RECURSE,
.paint = widgetSplitterPaint,
.paintOverlay = NULL,
.calcMinSize = widgetSplitterCalcMinSize,
.layout = widgetSplitterLayout,
.onMouse = widgetSplitterOnMouse,
.onKey = NULL,
.destroy = widgetSplitterDestroy,
.getText = NULL,
.setText = NULL,
.getCursorShape = widgetSplitterGetCursorShape,
.onDragUpdate = widgetSplitterOnDragUpdate
.version = WGT_CLASS_VERSION,
.flags = WCLASS_PAINTS_CHILDREN | WCLASS_NO_HIT_RECURSE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetSplitterPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetSplitterCalcMinSize,
[WGT_METHOD_LAYOUT] = (void *)widgetSplitterLayout,
[WGT_METHOD_ON_MOUSE] = (void *)widgetSplitterOnMouse,
[WGT_METHOD_DESTROY] = (void *)widgetSplitterDestroy,
[WGT_METHOD_GET_CURSOR_SHAPE] = (void *)widgetSplitterGetCursorShape,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetSplitterOnDragUpdate,
}
};

View file

@ -71,17 +71,12 @@ void widgetStatusBarGetLayoutMetrics(const WidgetT *w, const BitmapFontT *font,
static const WidgetClassT sClassStatusBar = {
.flags = WCLASS_BOX_CONTAINER | WCLASS_HORIZ_CONTAINER,
.paint = widgetStatusBarPaint,
.paintOverlay = NULL,
.calcMinSize = NULL,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.destroy = NULL,
.getText = NULL,
.setText = NULL,
.getLayoutMetrics = widgetStatusBarGetLayoutMetrics
.version = WGT_CLASS_VERSION,
.flags = WCLASS_BOX_CONTAINER | WCLASS_HORIZ_CONTAINER,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetStatusBarPaint,
[WGT_METHOD_GET_LAYOUT_METRICS] = (void *)widgetStatusBarGetLayoutMetrics,
}
};
// ============================================================

View file

@ -68,10 +68,7 @@ static bool tabNeedScroll(const WidgetT *w, const BitmapFontT *font);
static void tabClosePopup(void) {
if (sOpenPopup) {
if (sOpenPopup->wclass && sOpenPopup->wclass->closePopup) {
sOpenPopup->wclass->closePopup(sOpenPopup);
}
wclsClosePopup(sOpenPopup);
sOpenPopup = NULL;
}
}
@ -585,30 +582,25 @@ void widgetTabPageDestroy(WidgetT *w) {
static const WidgetClassT sClassTabControl = {
.flags = WCLASS_FOCUSABLE | WCLASS_PAINTS_CHILDREN,
.paint = widgetTabControlPaint,
.paintOverlay = NULL,
.calcMinSize = widgetTabControlCalcMinSize,
.layout = widgetTabControlLayout,
.onMouse = widgetTabControlOnMouse,
.onKey = widgetTabControlOnKey,
.destroy = widgetTabControlDestroy,
.getText = NULL,
.setText = NULL
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE | WCLASS_PAINTS_CHILDREN,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetTabControlPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetTabControlCalcMinSize,
[WGT_METHOD_LAYOUT] = (void *)widgetTabControlLayout,
[WGT_METHOD_ON_MOUSE] = (void *)widgetTabControlOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetTabControlOnKey,
[WGT_METHOD_DESTROY] = (void *)widgetTabControlDestroy,
}
};
static const WidgetClassT sClassTabPage = {
.flags = WCLASS_BOX_CONTAINER | WCLASS_ACCEL_WHEN_HIDDEN,
.paint = NULL,
.paintOverlay = NULL,
.calcMinSize = NULL,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.onAccelActivate = widgetTabPageAccelActivate,
.destroy = widgetTabPageDestroy,
.getText = NULL,
.setText = NULL
.version = WGT_CLASS_VERSION,
.flags = WCLASS_BOX_CONTAINER | WCLASS_ACCEL_WHEN_HIDDEN,
.handlers = {
[WGT_METHOD_ON_ACCEL_ACTIVATE] = (void *)widgetTabPageAccelActivate,
[WGT_METHOD_DESTROY] = (void *)widgetTabPageDestroy,
}
};

View file

@ -2045,18 +2045,19 @@ static void widgetTextInputOnDragUpdate(WidgetT *w, WidgetT *root, int32_t vx, i
static const WidgetClassT sClassTextInput = {
.flags = WCLASS_FOCUSABLE,
.paint = widgetTextInputPaint,
.paintOverlay = NULL,
.calcMinSize = widgetTextInputCalcMinSize,
.layout = NULL,
.onMouse = widgetTextInputOnMouse,
.onKey = widgetTextInputOnKey,
.destroy = widgetTextInputDestroy,
.getText = widgetTextInputGetText,
.setText = widgetTextInputSetText,
.clearSelection = widgetTextInputClearSelection,
.onDragUpdate = widgetTextInputOnDragUpdate
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetTextInputPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetTextInputCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetTextInputOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetTextInputOnKey,
[WGT_METHOD_DESTROY] = (void *)widgetTextInputDestroy,
[WGT_METHOD_GET_TEXT] = (void *)widgetTextInputGetText,
[WGT_METHOD_SET_TEXT] = (void *)widgetTextInputSetText,
[WGT_METHOD_CLEAR_SELECTION] = (void *)widgetTextInputClearSelection,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetTextInputOnDragUpdate,
}
};
// ============================================================
@ -2201,18 +2202,19 @@ static void widgetTextAreaDragSelect(WidgetT *w, WidgetT *root, int32_t vx, int3
static const WidgetClassT sClassTextArea = {
.flags = WCLASS_FOCUSABLE | WCLASS_SCROLLABLE,
.paint = widgetTextAreaPaint,
.paintOverlay = NULL,
.calcMinSize = widgetTextAreaCalcMinSize,
.layout = NULL,
.onMouse = widgetTextAreaOnMouse,
.onKey = widgetTextAreaOnKey,
.destroy = widgetTextAreaDestroy,
.getText = widgetTextAreaGetText,
.setText = widgetTextAreaSetText,
.clearSelection = widgetTextAreaClearSelection,
.onDragUpdate = widgetTextAreaOnDragUpdate
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE | WCLASS_SCROLLABLE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetTextAreaPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetTextAreaCalcMinSize,
[WGT_METHOD_ON_MOUSE] = (void *)widgetTextAreaOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetTextAreaOnKey,
[WGT_METHOD_DESTROY] = (void *)widgetTextAreaDestroy,
[WGT_METHOD_GET_TEXT] = (void *)widgetTextAreaGetText,
[WGT_METHOD_SET_TEXT] = (void *)widgetTextAreaSetText,
[WGT_METHOD_CLEAR_SELECTION] = (void *)widgetTextAreaClearSelection,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetTextAreaOnDragUpdate,
}
};
// ============================================================

View file

@ -94,16 +94,12 @@ static void widgetTimerDestroy(WidgetT *w) {
// ============================================================
static const WidgetClassT sClassTimer = {
.flags = 0,
.paint = NULL,
.paintOverlay = NULL,
.calcMinSize = widgetTimerCalcMinSize,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.destroy = widgetTimerDestroy,
.getText = NULL,
.setText = NULL
.version = WGT_CLASS_VERSION,
.flags = 0,
.handlers = {
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetTimerCalcMinSize,
[WGT_METHOD_DESTROY] = (void *)widgetTimerDestroy,
}
};

View file

@ -63,17 +63,12 @@ void widgetToolbarGetLayoutMetrics(const WidgetT *w, const BitmapFontT *font, in
// ============================================================
static const WidgetClassT sClassToolbar = {
.flags = WCLASS_BOX_CONTAINER | WCLASS_HORIZ_CONTAINER,
.paint = widgetToolbarPaint,
.paintOverlay = NULL,
.calcMinSize = NULL,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.destroy = NULL,
.getText = NULL,
.setText = NULL,
.getLayoutMetrics = widgetToolbarGetLayoutMetrics
.version = WGT_CLASS_VERSION,
.flags = WCLASS_BOX_CONTAINER | WCLASS_HORIZ_CONTAINER,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetToolbarPaint,
[WGT_METHOD_GET_LAYOUT_METRICS] = (void *)widgetToolbarGetLayoutMetrics,
}
};

View file

@ -1520,32 +1520,29 @@ static void widgetTreeViewOnDragUpdate(WidgetT *w, WidgetT *root, int32_t x, int
static const WidgetClassT sClassTreeView = {
.flags = WCLASS_FOCUSABLE | WCLASS_PAINTS_CHILDREN | WCLASS_NO_HIT_RECURSE | WCLASS_SCROLLABLE,
.paint = widgetTreeViewPaint,
.paintOverlay = NULL,
.calcMinSize = widgetTreeViewCalcMinSize,
.layout = widgetTreeViewLayout,
.onMouse = widgetTreeViewOnMouse,
.onKey = widgetTreeViewOnKey,
.destroy = widgetTreeViewDestroy,
.getText = NULL,
.setText = NULL,
.onChildChanged = widgetTreeViewOnChildChanged,
.onDragUpdate = widgetTreeViewOnDragUpdate,
.onDragEnd = widgetTreeViewOnDragEnd
.version = WGT_CLASS_VERSION,
.flags = WCLASS_FOCUSABLE | WCLASS_PAINTS_CHILDREN | WCLASS_NO_HIT_RECURSE | WCLASS_SCROLLABLE,
.handlers = {
[WGT_METHOD_PAINT] = (void *)widgetTreeViewPaint,
[WGT_METHOD_CALC_MIN_SIZE] = (void *)widgetTreeViewCalcMinSize,
[WGT_METHOD_LAYOUT] = (void *)widgetTreeViewLayout,
[WGT_METHOD_ON_MOUSE] = (void *)widgetTreeViewOnMouse,
[WGT_METHOD_ON_KEY] = (void *)widgetTreeViewOnKey,
[WGT_METHOD_DESTROY] = (void *)widgetTreeViewDestroy,
[WGT_METHOD_ON_CHILD_CHANGED] = (void *)widgetTreeViewOnChildChanged,
[WGT_METHOD_ON_DRAG_UPDATE] = (void *)widgetTreeViewOnDragUpdate,
[WGT_METHOD_ON_DRAG_END] = (void *)widgetTreeViewOnDragEnd,
}
};
static const WidgetClassT sClassTreeItem = {
.flags = 0,
.paint = NULL,
.paintOverlay = NULL,
.calcMinSize = NULL,
.layout = NULL,
.onMouse = NULL,
.onKey = NULL,
.destroy = widgetTreeItemDestroy,
.getText = widgetTreeItemGetText,
.setText = widgetTreeItemSetText
.version = WGT_CLASS_VERSION,
.flags = 0,
.handlers = {
[WGT_METHOD_DESTROY] = (void *)widgetTreeItemDestroy,
[WGT_METHOD_GET_TEXT] = (void *)widgetTreeItemGetText,
[WGT_METHOD_SET_TEXT] = (void *)widgetTreeItemSetText,
}
};