Widgets can now contain other widgets.

This commit is contained in:
Scott Duensing 2022-07-17 17:31:53 -05:00
parent fe79a0b139
commit 3bc40f02a5
10 changed files with 60 additions and 59 deletions

View file

@ -211,6 +211,14 @@ void guiStop(void) {
}
void widgetAdd(WidgetT *target, int16_t x, int16_t y, WidgetT *widget) {
widget->parent = target;
widget->r.x = x;
widget->r.y = y;
arrput(target->children, widget);
}
void widgetBaseSet(WidgetT *widget, uint8_t magic, uint16_t w, uint16_t h) {
widget->magic = magic;
@ -252,8 +260,8 @@ void widgetInputSetRaw(WidgetT *widget, uint8_t raw) {
}
uint8_t widgetIsInWindow(WidgetT *widget, struct WindowS *window) {
return widget->parent == window;;
uint8_t widgetIsInWidget(WidgetT *widget, WidgetT *parent) {
return widget->parent == parent;
}
@ -266,3 +274,16 @@ void widgetPaintManually(WidgetT *widget, int16_t x, int16_t y) {
widget->reg->paint(widget);
widget->r = r;
}
void widgetRemove(WidgetT *target, WidgetT *widget) {
uint16_t i;
for (i=0; i<arrlen(target->children); i++) {
if (target->children[i] == widget) {
arrdel(target->children, i);
break;
}
}
}

View file

@ -77,12 +77,13 @@ typedef struct RegisterS {
} RegisterT;
typedef struct WidgetS {
uint8_t magic; // Magic ID of widget.
RectT r; // Outer bounds of widget. NOTE: USES WIDTH/HEIGHT, NOT X2/Y2!
RegisterT *reg; // Registration information.
void *data; // Pointer to arbitrary data for user.
uint8_t flags; // Widget flags (see defines above).
struct WindowS *parent; // Who owns this widget?
uint8_t magic; // Magic ID of widget. Must be first!
RectT r; // Outer bounds of widget. NOTE: USES WIDTH/HEIGHT, NOT X2/Y2!
RegisterT *reg; // Registration information.
void *data; // Pointer to arbitrary data for user.
uint8_t flags; // Widget flags (see defines above).
struct WidgetS *parent; // Who owns this widget?
struct WidgetS **children; // Widgets contained in this widget.
} WidgetT;
typedef struct ClickRawInputS {
@ -137,13 +138,15 @@ void guiShutdown(void);
uint8_t guiStartup(int16_t width, int16_t height, int16_t depth);
void guiStop(void);
void widgetAdd(WidgetT *target, int16_t x, int16_t y, WidgetT *widget);
void widgetBaseSet(WidgetT *widget, uint8_t magic, uint16_t w, uint16_t h);
void widgetDestroy(WidgetT *widget);
uint8_t widgetDirtyGet(WidgetT *widget);
void widgetDirtySet(WidgetT *widget, uint8_t dirty);
void widgetInputSetRaw(WidgetT *widget, uint8_t raw);
uint8_t widgetIsInWindow(WidgetT *widget, struct WindowS *window);
uint8_t widgetIsInWidget(WidgetT *widget, WidgetT *parent);
void widgetPaintManually(WidgetT *widget, int16_t x, int16_t y);
void widgetRemove(WidgetT *target, WidgetT *widget);
#endif // GUI_H

View file

@ -108,7 +108,7 @@ static void checkboxPaint(struct WidgetS *widget, ...) {
// Finish initializing.
if (!c->attached) {
c->attached = 1;
windowWidgetAdd(c->base.parent, c->base.r.x + w, c->base.r.y, W(c->label));
widgetAdd(c->base.parent, c->base.r.x + w, c->base.r.y, W(c->label));
}
}
}

View file

@ -143,7 +143,7 @@ static void hscrollPaint(struct WidgetS *widget, ...) {
if (widgetDirtyGet(widget)) {
widgetDirtySet(widget, 0);
// Find some colors.
if (widgetIsInWindow(widget, wmWindowOnTopGet())) {
if (widgetIsInWidget(widget, W(wmWindowOnTopGet()))) {
scrollBackgroundColor = GUI_DARKGRAY;
widgetColor = GUI_LIGHTGRAY;
} else {

View file

@ -145,7 +145,7 @@ static void radioPaint(struct WidgetS *widget, ...) {
// Finish initializing.
if (!r->attached) {
r->attached = 1;
windowWidgetAdd(r->base.parent, r->base.r.x + w, r->base.r.y, W(r->label));
widgetAdd(r->base.parent, r->base.r.x + w, r->base.r.y, W(r->label));
}
}
}
@ -174,7 +174,7 @@ uint8_t radioValueGet(RadioT *radio) {
void radioValueSet(RadioT *radio, uint8_t value) {
int16_t i;
WindowT *p;
WidgetT *p;
RadioT *r;
radio->value = (value != 0);

View file

@ -107,14 +107,14 @@ static void scrollablePaint(struct WidgetS *widget, ...) {
if (s->scrollh) {
s->sizes.y = s->base.r.h - s->scrollh->base.r.h;
s->base.r.h -= s->scrollh->base.r.h;
windowWidgetAdd(s->base.parent, s->base.r.x, s->base.r.y + s->sizes.y, W(s->scrollh));
widgetAdd(s->base.parent, s->base.r.x, s->base.r.y + s->sizes.y, W(s->scrollh));
} else {
s->sizes.y = s->base.r.h;
}
if (s->scrollv) {
s->sizes.x = s->base.r.w - s->scrollv->base.r.w;
s->base.r.w -= s->scrollv->base.r.w;
windowWidgetAdd(s->base.parent, s->base.r.x + s->sizes.x, s->base.r.y, W(s->scrollv));
widgetAdd(s->base.parent, s->base.r.x + s->sizes.x, s->base.r.y, W(s->scrollv));
} else {
s->sizes.x = s->base.r.w;
}

View file

@ -143,7 +143,7 @@ static void vscrollPaint(struct WidgetS *widget, ...) {
if (widgetDirtyGet(widget)) {
widgetDirtySet(widget, 0);
// Find some colors.
if (widgetIsInWindow(widget, wmWindowOnTopGet())) {
if (widgetIsInWidget(widget, W(wmWindowOnTopGet()))) {
scrollBackgroundColor = GUI_DARKGRAY;
widgetColor = GUI_LIGHTGRAY;
} else {

View file

@ -414,8 +414,8 @@ static void windowDestroy(struct WidgetS *widget, ...) {
// Free the title.
if (window->title) DEL(window->title);
// Free children.
for (c=0; c<arrlen(window->children); c++) widgetDestroy(window->children[c]);
arrfree(window->children);
for (c=0; c<arrlen(window->base.children); c++) widgetDestroy(window->base.children[c]);
arrfree(window->base.children);
// Free cached surface.
if (window->cached) surfaceDestroy(&window->cached);
// Free content surface.
@ -649,12 +649,12 @@ static void windowPaint(struct WidgetS *widget, ...) {
// Are any child widgets dirty?
y = 0;
for (x=0; x<arrlen(w->children); x++) {
if (widgetDirtyGet(w->children[x])) {
for (x=0; x<arrlen(w->base.children); x++) {
if (widgetDirtyGet(w->base.children[x])) {
y = 1;
if (w->children[x]->reg->paint) {
if (w->base.children[x]->reg->paint) {
surfaceSet(w->content);
w->children[x]->reg->paint(w->children[x]);
w->base.children[x]->reg->paint(w->base.children[x]);
}
}
}
@ -849,26 +849,6 @@ static void windowScrollVerticalHandler(EventT *e, WindowT *w) {
}
void windowWidgetAdd(WindowT *window, int16_t x, int16_t y, WidgetT *widget) {
widget->parent = window;
widget->r.x = x;
widget->r.y = y;
arrput(window->children, widget);
}
void windowWidgetRemove(WindowT *window, WidgetT *widget) {
uint16_t i;
for (i=0; i<arrlen(window->children); i++) {
if (window->children[i] == widget) {
arrdel(window->children, i);
break;
}
}
}
void wmShutdown(void) {
uint16_t i;
@ -1164,8 +1144,8 @@ static WidgetT *wuWidgetUnderMouseGet(WindowT *win, EventT *event, int16_t *loca
*localX = event->x - win->bounds.x + win->offset.x;
*localY = event->y - win->bounds.y + win->offset.y;
// Find widget under mouse.
for (i=0; i<arrlen(win->children); i++) {
widget = win->children[i];
for (i=0; i<arrlen(win->base.children); i++) {
widget = win->base.children[i];
if (*localX >= widget->r.x && *localX < widget->r.x + widget->r.x2 && *localY >= widget->r.y && *localY < widget->r.y + widget->r.y2) {
// Return this widget.
return widget;

View file

@ -69,7 +69,6 @@ typedef struct WindowS {
PointT offset; // Content scroll offset in window.
SurfaceT *content; // Actual window contents - widgets and such.
SurfaceT *cached; // Once rendered, keep a cached copy for faster redrawing.
WidgetT **children; // Widgets contained in the window.
} WindowT;
@ -83,8 +82,6 @@ void windowMinimize(WindowT *win);
void windowMove(WindowT *win, uint16_t x, uint16_t y);
RegisterT *windowRegister(uint8_t magic);
void windowResize(WindowT *win, uint16_t width, uint16_t height);
void windowWidgetAdd(WindowT *window, int16_t x, int16_t y, WidgetT *widget);
void windowWidgetRemove(WindowT *window, WidgetT *widget);
void wmShutdown(void);

View file

@ -73,38 +73,38 @@ int main(int argc, char *argv[]) {
l = labelCreate(LABEL_ALIGN_LEFT, __guiFontVGA8x16, "Label");
labelColorSet(l, __guiBaseColors[i], GUI_BLACK);
labelClickSet(l, clickHandler, title);
windowWidgetAdd(w, 20, 10, W(l));
widgetAdd(W(w), 20, 10, W(l));
b = buttonCreate("Button", clickHandler, NULL);
windowWidgetAdd(w, 20, 40, W(b));
widgetAdd(W(w), 20, 40, W(b));
c = checkboxCreate("Checkbox", 0);
windowWidgetAdd(w, 20, 80, W(c));
widgetAdd(W(w), 20, 80, W(c));
r = radioCreate("Radio 1", 0, 1);
windowWidgetAdd(w, 20, 110, W(r));
widgetAdd(W(w), 20, 110, W(r));
r = radioCreate("Radio 2", 0, 0);
windowWidgetAdd(w, 120, 110, W(r));
widgetAdd(W(w), 120, 110, W(r));
r = radioCreate("Radio 3", 0, 0);
windowWidgetAdd(w, 220, 110, W(r));
widgetAdd(W(w), 220, 110, W(r));
r = radioCreate("Radio A", 1, 0);
windowWidgetAdd(w, 20, 140, W(r));
widgetAdd(W(w), 20, 140, W(r));
r = radioCreate("Radio B", 1, 1);
windowWidgetAdd(w, 120, 140, W(r));
widgetAdd(W(w), 120, 140, W(r));
r = radioCreate("Radio C", 1, 0);
windowWidgetAdd(w, 220, 140, W(r));
widgetAdd(W(w), 220, 140, W(r));
_v = vscrollCreate(100, clickHandler, NULL);
vscrollRangeSet(_v, 0, 640);
windowWidgetAdd(w, 200, 5, W(_v));
widgetAdd(W(w), 200, 5, W(_v));
_h = hscrollCreate(100, clickHandler, NULL);
hscrollRangeSet(_h, 0, 640);
windowWidgetAdd(w, 100, 5, W(_h));
widgetAdd(W(w), 100, 5, W(_h));
s = scrollableCreate(300, 200, 648, 480, SCROLLABLE_STANDARD);
windowWidgetAdd(w, 20, 170, W(s));
widgetAdd(W(w), 20, 170, W(s));
}
guiRun();
guiShutdown();