From 34dd7d7fbe51bf3cc0f5c5a6c7d4c1638ff2444d Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Sun, 26 Jun 2022 18:37:00 -0500 Subject: [PATCH] Basic click handling for widgets implemented. --- client/src/gui/font.c | 33 +++++++++++++++++++++++++++ client/src/gui/font.h | 1 + client/src/gui/gui.h | 13 ++++++----- client/src/gui/widgets/label.c | 34 ++++++++++++++++++++++------ client/src/gui/widgets/label.h | 11 +++++++-- client/src/gui/wmwindow.c | 41 ++++++++++++++++++++++++++++++++-- client/src/main.c | 9 +++++++- 7 files changed, 124 insertions(+), 18 deletions(-) diff --git a/client/src/gui/font.c b/client/src/gui/font.c index 703f03c..946fedd 100644 --- a/client/src/gui/font.c +++ b/client/src/gui/font.c @@ -101,6 +101,7 @@ void fontRender(char *string, uint16_t x, uint16_t y) { for (c=0; cwidth; } diff --git a/client/src/gui/font.h b/client/src/gui/font.h index 4c6044c..a8a68e3 100644 --- a/client/src/gui/font.h +++ b/client/src/gui/font.h @@ -25,6 +25,7 @@ void fontModsEnabledSet(uint8_t enabled); void fontRender(char *string, uint16_t x, uint16_t y); void fontSet(FontT *font); void fontUnload(FontT **font); +uint16_t fontWidthCharactersGet(char *string); uint16_t fontWidthGet(FontT *font); diff --git a/client/src/gui/gui.h b/client/src/gui/gui.h index 7acefcd..a58f4da 100644 --- a/client/src/gui/gui.h +++ b/client/src/gui/gui.h @@ -11,6 +11,7 @@ struct WidgetS; typedef void (*GuiCallbackT)(void *data, ...); typedef void (*WidgetEventT)(struct WidgetS *widget, ...); +typedef void (*ClickHandlerT)(struct WidgetS *widget, uint16_t x, uint16_t y, void *data); typedef struct PointS { int16_t x; @@ -31,16 +32,16 @@ typedef struct RectS { } RectT; typedef struct RegisterS { - char *widgetName; // Text name of widget. - WidgetEventT click; // Click handler. - WidgetEventT destroy; // Destroy routine. - WidgetEventT paint; // Paint routine. - GuiCallbackT unregister; // Unregister routine. + char *widgetName; // Text name of widget. + ClickHandlerT click; // Click handler. + WidgetEventT destroy; // Destroy routine. + WidgetEventT paint; // Paint routine. + GuiCallbackT unregister; // Unregister routine. } RegisterT; typedef struct WidgetS { uint8_t magic; // Magic ID of widget. - RectT r; // Outer bounds, except for windows. + 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 dirty; // Is the widget dirty? diff --git a/client/src/gui/widgets/label.c b/client/src/gui/widgets/label.c index 33fe514..4a26517 100644 --- a/client/src/gui/widgets/label.c +++ b/client/src/gui/widgets/label.c @@ -8,7 +8,7 @@ static void labelDestroy(struct WidgetS *widget, ...); static void labelPaint(struct WidgetS *widget, ...); -void labelClickSet(LabelT *label, WidgetEventT handler, void *data) { +void labelClickSet(LabelT *label, ClickHandlerT handler, void *data) { label->base.reg->click = handler; label->base.data = data; } @@ -21,19 +21,39 @@ void labelColorSet(LabelT *label, ColorT foreground, ColorT background) { } -LabelT *labelCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, FontT *font, char *contents, ...) { - LabelT *l = NULL; - - // ***TODO*** Auto-calculate width/height. +LabelT *labelCreate(uint16_t x, uint16_t y, uint8_t alignment, FontT *font, char *contents, ...) { + LabelT *l = NULL; + uint16_t width; + uint16_t height; NEW(LabelT, l); memset(l, 0, sizeof(LabelT)); - guiWidgetBaseSet((WidgetT *)l, __MAGIC_LABEL, x, y, w, h); l->font = font; l->text = strdup(contents); l->foreground = GUI_BLACK; l->background = GUI_LIGHTGRAY; l->modsEnabled = 0; + l->alignment = alignment; + l->pos.x = x; + l->pos.y = y; + + width = fontWidthCharactersGet(contents) * fontWidthGet(font); + height = fontHeightGet(font); + switch (alignment) { + case LABEL_ALIGN_LEFT: + // Passed in values are fine. + break; + + case LABEL_ALIGN_CENTER: + x -= width * 0.5; + break; + + case LABEL_ALIGN_RIGHT: + x -= width; + break; + } + + guiWidgetBaseSet((WidgetT *)l, __MAGIC_LABEL, x, y, width, height); return l; } @@ -55,7 +75,7 @@ static void labelPaint(struct WidgetS *widget, ...) { fontSet(l->font); fontColorSet(l->foreground, l->background); fontModsEnabledSet(l->modsEnabled); - // ***TODO*** Alignment, clipping, etc. + // ***TODO*** Clipping. fontRender(l->text, l->base.r.x, l->base.r.y); } } diff --git a/client/src/gui/widgets/label.h b/client/src/gui/widgets/label.h index 5ee6f8f..b0301f7 100644 --- a/client/src/gui/widgets/label.h +++ b/client/src/gui/widgets/label.h @@ -5,9 +5,16 @@ #include "../gui.h" +#define LABEL_ALIGN_LEFT 0 +#define LABEL_ALIGN_RIGHT 1 +#define LABEL_ALIGN_CENTER 2 + + typedef struct LabelS { WidgetT base; // Required by all widgets. char *text; // Contents of label. + PointT pos; // Anchor position (before alignment). + uint8_t alignment; // Alignment from specified location. FontT *font; // Font to use. uint8_t modsEnabled; // Escape codes enabled? ColorT foreground; // Foreground color. @@ -18,9 +25,9 @@ typedef struct LabelS { extern uint8_t __MAGIC_LABEL; // Magic ID assigned to us from the GUI. -void labelClickSet(LabelT *label, WidgetEventT handler, void *data); +void labelClickSet(LabelT *label, ClickHandlerT handler, void *data); void labelColorSet(LabelT *label, ColorT foreground, ColorT background); -LabelT *labelCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, FontT *font, char *contents, ...); +LabelT *labelCreate(uint16_t x, uint16_t y, uint8_t alignment, FontT *font, char *contents, ...); RegisterT *labelRegister(uint8_t magic); diff --git a/client/src/gui/wmwindow.c b/client/src/gui/wmwindow.c index 634bd76..965a524 100644 --- a/client/src/gui/wmwindow.c +++ b/client/src/gui/wmwindow.c @@ -870,6 +870,8 @@ void wmStartup(void) { void wmUpdate(EventT *event) { int16_t i; + int16_t x; + int16_t y; int16_t x2; int16_t y2; uint8_t onResize = 0; @@ -879,6 +881,7 @@ void wmUpdate(EventT *event) { static PointT resizeOffset = { 0 }; static uint8_t dragging = 0; static PointT dragOffset = { 0 }; + static WidgetT *widgetDown = NULL; // Do we have windows? if (arrlen(_windowList) > 0) { @@ -968,9 +971,19 @@ void wmUpdate(EventT *event) { break; } - // Are we inside the window content? Most likely, check first. + // Are we inside the window content? Most likely, check this first. if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) { - //***TODO*** Send to window for processing. + // Are we over a widget? + x = event->x - win->bounds.x + win->offset.x; + y = event->y - win->bounds.y + win->offset.y; + for (i=0; ichildren); i++) { + widget = win->children[i]; + if (x >= widget->r.x && x < widget->r.x + widget->r.x2 && y >= widget->r.y && y < widget->r.y + widget->r.y2) { + // Remember this widget for when left-up occurs. + widgetDown = widget; + break; + } + } } // Are we inside the close button? Does not include button frame on purpose. @@ -1093,6 +1106,30 @@ void wmUpdate(EventT *event) { // Can no longer be resizing. resizing = 0; + + // Did the left button just come up? + if (event->flags & EVENT_FLAG_LEFT_UP) { + + // Did this click begin over a widget? + if (widgetDown) { + // Are we still inside the window content? + if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) { + // Are we stll over the same widget? + x = event->x - win->bounds.x + win->offset.x; + y = event->y - win->bounds.y + win->offset.y; + for (i=0; ichildren); i++) { + widget = win->children[i]; + if (widget == widgetDown && x >= widget->r.x && x < widget->r.x + widget->r.x2 && y >= widget->r.y && y < widget->r.y + widget->r.y2) { + // Send to widget for processing. + if (widget->reg->click) widget->reg->click(widget, x - widget->r.x, y - widget->r.y, widget->data); + break; + } + } + } + widgetDown = NULL; + } // widgetDown + + } } break; diff --git a/client/src/main.c b/client/src/main.c index 4290ba1..51ea703 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -3,6 +3,12 @@ #include "gui/widgets/label.h" +void clickHandler(WidgetT *widget, uint16_t x, uint16_t y, void *data) { + (void)widget; + logWrite("%dx%d %s\n", x, y, data); +} + + int main(int argc, char *argv[]) { char title[256]; uint16_t i; @@ -19,8 +25,9 @@ int main(int argc, char *argv[]) { sprintf(title, "Testing %d", i); w = windowCreate(i * 50, i * 50, 300, 200, title, WIN_STANDARD, 640, 480); - l = labelCreate(10, 10, 0, 0, __guiFontVGA8x16, "Label Test"); + l = labelCreate(150, 10, LABEL_ALIGN_LEFT, __guiFontVGA8x16, "Label Test"); labelColorSet(l, __guiBaseColors[i], GUI_BLACK); + labelClickSet(l, clickHandler, title); windowWidgetAdd(w, W(l)); } guiRun();