From 6edae8ed47eab4786961bdbc9928b429b47787eb Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Mon, 25 Oct 2021 19:06:43 -0500 Subject: [PATCH] Freaking margins and clipping regions finally fixed. Not that we clip yet. --- client/client.pro | 27 +++---- client/src/gui/button.c | 44 ++++++------ client/src/gui/button.h | 2 +- client/src/gui/checkbox.c | 41 ++++++----- client/src/gui/checkbox.h | 2 +- client/src/gui/desktop.c | 13 ++-- client/src/gui/frame.c | 25 ++----- client/src/gui/frame.h | 2 +- client/src/gui/gui.c | 148 ++++++++++++++++++++++++++++++-------- client/src/gui/gui.h | 6 +- client/src/gui/image.c | 17 +++++ client/src/gui/image.h | 1 + client/src/gui/label.c | 28 +++----- client/src/gui/label.h | 2 +- client/src/gui/picture.c | 27 ++++--- client/src/gui/picture.h | 2 +- client/src/gui/radio.c | 45 ++++++------ client/src/gui/radio.h | 2 +- client/src/gui/rect.h | 36 ++++++++++ client/src/gui/textbox.c | 44 +++++------- client/src/gui/textbox.h | 2 +- client/src/gui/timer.c | 36 ++++++++++ client/src/gui/timer.h | 30 ++++++++ client/src/gui/widget.c | 42 ++++++----- client/src/gui/widget.h | 19 +++-- client/src/gui/window.c | 40 +++++------ client/src/gui/window.h | 2 +- client/src/linux/linux.c | 2 +- client/src/main.c | 99 +++++++++++++++++-------- 29 files changed, 507 insertions(+), 279 deletions(-) create mode 100644 client/src/gui/rect.h create mode 100644 client/src/gui/timer.c create mode 100644 client/src/gui/timer.h diff --git a/client/client.pro b/client/client.pro index d0debfc..e202457 100644 --- a/client/client.pro +++ b/client/client.pro @@ -51,8 +51,10 @@ HEADERS = \ src/gui/label.h \ src/gui/picture.h \ src/gui/radio.h \ + src/gui/rect.h \ src/gui/task.h \ src/gui/textbox.h \ + src/gui/timer.h \ src/thirdparty/stb_ds.h \ src/thirdparty/stb_leakcheck.h \ src/thirdparty/stb_image.h \ @@ -72,22 +74,23 @@ HEADERS = \ SOURCES = \ $$LINUX_SOURCES \ src/gui/array.c \ - src/gui/button.c \ - src/gui/checkbox.c \ src/gui/font.c \ - src/gui/desktop.c \ - src/gui/frame.c \ - src/gui/gui.c \ - src/gui/label.c \ - src/gui/picture.c \ - src/gui/radio.c \ - src/gui/task.c \ - src/gui/textbox.c \ - src/gui/widget.c \ - src/gui/window.c \ src/gui/image.c \ src/gui/log.c \ src/gui/memory.c \ + src/gui/timer.c \ + src/gui/task.c \ + src/gui/gui.c \ + src/gui/desktop.c \ + src/gui/widget.c \ + src/gui/window.c \ + src/gui/picture.c \ + src/gui/radio.c \ + src/gui/textbox.c \ + src/gui/frame.c \ + src/gui/button.c \ + src/gui/checkbox.c \ + src/gui/label.c \ src/main.c LIBS = \ diff --git a/client/src/gui/button.c b/client/src/gui/button.c index 9201616..c877a46 100644 --- a/client/src/gui/button.c +++ b/client/src/gui/button.c @@ -22,7 +22,7 @@ static void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event); -static void buttonPaint(WidgetT *widget); +static void buttonPaint(WidgetT *widget, RectT pos); void buttonDel(WidgetT **widget) { @@ -34,22 +34,18 @@ void buttonDel(WidgetT **widget) { } -WidgetT *buttonInit(WidgetT *button, uint16_t x, uint16_t y, char *title, widgetCallback callback) { +WidgetT *buttonInit(WidgetT *button, char *title, widgetCallback callback) { ButtonT *b = (ButtonT *)button; - b->base.magic = MAGIC_BUTTON; - b->base.x = x; - b->base.y = y; b->base.delMethod = buttonDel; b->base.paintMethod = buttonPaint; b->base.mouseEventMethod = buttonMouseEvent; b->title = NULL; buttonSetClickHandler(b, callback); - buttonSetTitle(b, title); // Width is set in buttonSetTitle - b->base.h = fontHeightGet(_guiFont) + (_guiMetric[METRIC_BUTTON_VERTICAL_PADDING] * 2) + (_guiMetric[METRIC_BUTTON_BEZEL_SIZE] * 2); + buttonSetTitle(b, title); return button; } @@ -83,43 +79,49 @@ static void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_ ButtonT *buttonNew(uint16_t x, uint16_t y, char *title, widgetCallback callback) { - ButtonT *button = (ButtonT *)malloc(sizeof(ButtonT)); - WidgetT *widget = NULL; + ButtonT *button = (ButtonT *)malloc(sizeof(ButtonT)); + WidgetT *widget = NULL; + uint16_t h = fontHeightGet(_guiFont) + (_guiMetric[METRIC_BUTTON_VERTICAL_PADDING] * 2) + (_guiMetric[METRIC_BUTTON_BEZEL_SIZE] * 2); + if (!button) return NULL; - widget = widgetInit((WidgetT *)button); + // Width is set in Init. + widget = widgetInit(W(button), MAGIC_BUTTON, x, y, 0, h, 0, 0, 0, 0); if (!widget) { free(button); return NULL; } - button = (ButtonT *)buttonInit((WidgetT *)button, x, y, title, callback); + button = (ButtonT *)buttonInit((WidgetT *)button, title, callback); return button; } -static void buttonPaint(WidgetT *widget) { - ButtonT *b = (ButtonT *)widget; +static void buttonPaint(WidgetT *widget, RectT pos) { + ButtonT *b; int16_t i; - int8_t active = GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE); - ColorT highlight = active ? _guiColor[COLOR_BUTTON_SHADOW] : _guiColor[COLOR_BUTTON_HIGHLIGHT]; - ColorT shadow = active ? _guiColor[COLOR_BUTTON_HIGHLIGHT] : _guiColor[COLOR_BUTTON_SHADOW] ; + int8_t active; + ColorT highlight; + ColorT shadow; if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) { - vbeSurfaceSet(b->base.surface); + b = (ButtonT *)widget; + active = GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE); + highlight = active ? _guiColor[COLOR_BUTTON_SHADOW] : _guiColor[COLOR_BUTTON_HIGHLIGHT]; + shadow = active ? _guiColor[COLOR_BUTTON_HIGHLIGHT] : _guiColor[COLOR_BUTTON_SHADOW]; // Draw bezel. for (i=0; i<_guiMetric[METRIC_BUTTON_BEZEL_SIZE]; i++) { - guiDrawHighlightFrame(b->base.x + i, b->base.y + i, b->base.x + b->base.w - i, b->base.y + b->base.h - i, highlight, shadow); + guiDrawHighlightFrame(pos.x + i, pos.y + i, pos.x + pos.w - i, pos.y + pos.h - i, highlight, shadow); } // Draw background (depends on x from above). - guiDrawRectangleFilled(b->base.x + i, b->base.y + i, b->base.x + b->base.w - i, b->base.y + b->base.h - i, _guiColor[COLOR_BUTTON_BACKGROUND]); + guiDrawRectangleFilled(pos.x + i, pos.y + i, pos.x + pos.w - i, pos.y + pos.h - i, _guiColor[COLOR_BUTTON_BACKGROUND]); // Draw title (depends on x from above). - fontRender(_guiFont, b->title, _guiColor[COLOR_BUTTON_TEXT], _guiColor[COLOR_BUTTON_BACKGROUND], b->base.x + i + _guiMetric[METRIC_BUTTON_HORIZONTAL_PADDING] + active, b->base.y + i + _guiMetric[METRIC_BUTTON_VERTICAL_PADDING] + active); + fontRender(_guiFont, b->title, _guiColor[COLOR_BUTTON_TEXT], _guiColor[COLOR_BUTTON_BACKGROUND], pos.x + i + _guiMetric[METRIC_BUTTON_HORIZONTAL_PADDING] + active, pos.y + i + _guiMetric[METRIC_BUTTON_VERTICAL_PADDING] + active); GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY); } @@ -134,6 +136,6 @@ void buttonSetClickHandler(ButtonT *button, widgetCallback callback) { void buttonSetTitle(ButtonT *button, char *title) { if (button->title) free(button->title); button->title = strdup(title); - button->base.w = (strlen(title) * fontWidthGet(_guiFont)) + (_guiMetric[METRIC_BUTTON_HORIZONTAL_PADDING] * 2) + (_guiMetric[METRIC_BUTTON_BEZEL_SIZE] * 2); + button->base.pos.w = (strlen(title) * fontWidthGet(_guiFont)) + (_guiMetric[METRIC_BUTTON_HORIZONTAL_PADDING] * 2) + (_guiMetric[METRIC_BUTTON_BEZEL_SIZE] * 2); GUI_SET_FLAG((WidgetT *)button, WIDGET_FLAG_DIRTY); } diff --git a/client/src/gui/button.h b/client/src/gui/button.h index 37d7a1a..784427f 100644 --- a/client/src/gui/button.h +++ b/client/src/gui/button.h @@ -34,7 +34,7 @@ typedef struct ButtonS { void buttonDel(WidgetT **widget); -WidgetT *buttonInit(WidgetT *button, uint16_t x, uint16_t y, char *title, widgetCallback callback); +WidgetT *buttonInit(WidgetT *button, char *title, widgetCallback callback); ButtonT *buttonNew(uint16_t x, uint16_t y, char *title, widgetCallback callback); void buttonSetClickHandler(ButtonT *button, widgetCallback callback); void buttonSetTitle(ButtonT *button, char *title); diff --git a/client/src/gui/checkbox.c b/client/src/gui/checkbox.c index a259d71..02a9610 100644 --- a/client/src/gui/checkbox.c +++ b/client/src/gui/checkbox.c @@ -22,7 +22,7 @@ static void checkboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event); -static void checkboxPaint(WidgetT *widget); +static void checkboxPaint(WidgetT *widget, RectT pos); void checkboxDel(WidgetT **widget) { @@ -39,12 +39,9 @@ uint8_t checkboxGetValue(CheckboxT *checkbox) { } -WidgetT *checkboxInit(WidgetT *widget, uint16_t x, uint16_t y, char *title) { +WidgetT *checkboxInit(WidgetT *widget, char *title) { CheckboxT *c = (CheckboxT *)widget; - c->base.magic = MAGIC_CHECKBOX; - c->base.x = x; - c->base.y = y; c->base.delMethod = checkboxDel; c->base.paintMethod = checkboxPaint; c->base.mouseEventMethod = checkboxMouseEvent; @@ -53,9 +50,6 @@ WidgetT *checkboxInit(WidgetT *widget, uint16_t x, uint16_t y, char *title) { checkboxSetTitle(c, title); - // Width is set in checkboxSetTitle - c->base.h = fontHeightGet(_guiFont); - return widget; } @@ -78,44 +72,49 @@ static void checkboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint1 CheckboxT *checkboxNew(uint16_t x, uint16_t y, char *title) { CheckboxT *checkbox = (CheckboxT *)malloc(sizeof(CheckboxT)); - WidgetT *widget = NULL; + WidgetT *widget = NULL; + uint16_t h = fontHeightGet(_guiFont); if (!checkbox) return NULL; - widget = widgetInit((WidgetT *)checkbox); + // Width is set in Init + widget = widgetInit(W(checkbox), MAGIC_CHECKBOX, x, y, 0, h, 0, 0, 0, 0); if (!widget) { free(checkbox); return NULL; } - checkbox = (CheckboxT *)checkboxInit((WidgetT *)checkbox, x, y, title); + checkbox = (CheckboxT *)checkboxInit((WidgetT *)checkbox, title); return checkbox; } -static void checkboxPaint(WidgetT *widget) { +static void checkboxPaint(WidgetT *widget, RectT pos) { CheckboxT *c = (CheckboxT *)widget; int16_t o; - int8_t active = checkboxGetValue(c); - ColorT highlight = active ? _guiColor[COLOR_CHECKBOX_SHADOW] : _guiColor[COLOR_CHECKBOX_HIGHLIGHT]; - ColorT shadow = active ? _guiColor[COLOR_CHECKBOX_HIGHLIGHT] : _guiColor[COLOR_CHECKBOX_SHADOW]; - ColorT fill = active ? _guiColor[COLOR_CHECKBOX_ACTIVE] : _guiColor[COLOR_CHECKBOX_INACTIVE]; + int8_t active; + ColorT highlight; + ColorT shadow; + ColorT fill; if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) { - vbeSurfaceSet(c->base.surface); + active = checkboxGetValue(c); + highlight = active ? _guiColor[COLOR_CHECKBOX_SHADOW] : _guiColor[COLOR_CHECKBOX_HIGHLIGHT]; + shadow = active ? _guiColor[COLOR_CHECKBOX_HIGHLIGHT] : _guiColor[COLOR_CHECKBOX_SHADOW]; + fill = active ? _guiColor[COLOR_CHECKBOX_ACTIVE] : _guiColor[COLOR_CHECKBOX_INACTIVE]; // Checkbox is 10x10 pixels. Find offset based on font height. o = (_guiFont->height - 10) * 0.5; // Draw outline of checkbox. - guiDrawHighlightFrame(c->base.x, c->base.y + o, c->base.x + 10, c->base.y + 10 + o, highlight, shadow); + guiDrawHighlightFrame(pos.x, pos.y + o, pos.x + 10, pos.y + 10 + o, highlight, shadow); // Draw background. - guiDrawRectangleFilled(c->base.x + 1, c->base.y + o + 1, c->base.x + 9, c->base.y + + o + 9, fill); + guiDrawRectangleFilled(pos.x + 1, pos.y + o + 1, pos.x + 9, pos.y + + o + 9, fill); // Draw title. - fontRender(_guiFont, c->title, _guiColor[COLOR_CHECKBOX_TEXT], _guiColor[COLOR_WINDOW_BACKGROUND], c->base.x + 10 + _guiMetric[METRIC_CHECKBOX_PADDING], c->base.y); + fontRender(_guiFont, c->title, _guiColor[COLOR_CHECKBOX_TEXT], _guiColor[COLOR_WINDOW_BACKGROUND], pos.x + 10 + _guiMetric[METRIC_CHECKBOX_PADDING], pos.y); GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY); } @@ -130,7 +129,7 @@ void checkboxSetClickHandler(CheckboxT *checkbox, widgetCallback callback) { void checkboxSetTitle(CheckboxT *checkbox, char *title) { if (checkbox->title) free(checkbox->title); checkbox->title = strdup(title); - checkbox->base.w = (strlen(title) * fontWidthGet(_guiFont)) + 10 + _guiMetric[METRIC_CHECKBOX_PADDING]; + checkbox->base.pos.w = (strlen(title) * fontWidthGet(_guiFont)) + 10 + _guiMetric[METRIC_CHECKBOX_PADDING]; GUI_SET_FLAG((WidgetT *)checkbox, WIDGET_FLAG_DIRTY); } diff --git a/client/src/gui/checkbox.h b/client/src/gui/checkbox.h index 8838820..c03267d 100644 --- a/client/src/gui/checkbox.h +++ b/client/src/gui/checkbox.h @@ -35,7 +35,7 @@ typedef struct CheckboxS { void checkboxDel(WidgetT **widget); uint8_t checkboxGetValue(CheckboxT *checkbox); -WidgetT *checkboxInit(WidgetT *widget, uint16_t x, uint16_t y, char *title); +WidgetT *checkboxInit(WidgetT *widget, char *title); CheckboxT *checkboxNew(uint16_t x, uint16_t y, char *title); void checkboxSetClickHandler(CheckboxT *checkbox, widgetCallback callback); void checkboxSetTitle(CheckboxT *checkbox, char *title); diff --git a/client/src/gui/desktop.c b/client/src/gui/desktop.c index 9d48440..0d303e6 100644 --- a/client/src/gui/desktop.c +++ b/client/src/gui/desktop.c @@ -22,7 +22,7 @@ #include "window.h" -static void desktopPaint(WidgetT *desktop); +static void desktopPaint(WidgetT *desktop, RectT pos); void desktopDel(WidgetT **widget) { @@ -38,13 +38,11 @@ WidgetT *desktopInit(WidgetT *desktop) { DesktopT *d = (DesktopT *)desktop; d->base.magic = MAGIC_DESKTOP; - d->base.w = vbeDisplayWidthGet(); - d->base.h = vbeDisplayHeightGet(); d->base.delMethod = desktopDel; d->base.paintMethod = desktopPaint; GUI_SET_FLAG(desktop, WIDGET_FLAG_OWNS_SURFACE); - d->base.surface = vbeSurfaceCreate(d->base.w, d->base.h); + d->base.surface = vbeSurfaceCreate(d->base.pos.w, d->base.pos.h); if (!d->base.surface) { free(d); return NULL; @@ -60,7 +58,7 @@ DesktopT *desktopNew(void) { if (!desktop) return NULL; - widget = widgetInit((WidgetT *)desktop); + widget = widgetInit(W(desktop), MAGIC_DESKTOP, 0, 0, vbeDisplayWidthGet(), vbeDisplayHeightGet(), 0, 0, 0, 0); if (!widget) { free(desktop); return NULL; @@ -72,11 +70,10 @@ DesktopT *desktopNew(void) { } -static void desktopPaint(WidgetT *desktop) { - DesktopT *d = (DesktopT *)desktop; +static void desktopPaint(WidgetT *desktop, RectT pos) { + (void)pos; if (GUI_GET_FLAG(desktop, WIDGET_FLAG_DIRTY)) { - vbeSurfaceSet(d->base.surface); vbeSurfaceClear(_guiColor[COLOR_DESKTOP]); GUI_CLEAR_FLAG(desktop, WIDGET_FLAG_DIRTY); } diff --git a/client/src/gui/frame.c b/client/src/gui/frame.c index 07a38d8..4257f6f 100644 --- a/client/src/gui/frame.c +++ b/client/src/gui/frame.c @@ -21,7 +21,7 @@ #include "frame.h" -static void framePaint(WidgetT *widget); +static void framePaint(WidgetT *widget, RectT pos); void frameDel(WidgetT **widget) { @@ -33,21 +33,13 @@ void frameDel(WidgetT **widget) { } -WidgetT *frameInit(WidgetT *widget, uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title) { +WidgetT *frameInit(WidgetT *widget, char *title) { FrameT *f = (FrameT *)widget; - f->base.magic = MAGIC_FRAME; - f->base.x = x; - f->base.y = y; - f->base.w = w; - f->base.h = h; f->base.delMethod = frameDel; f->base.paintMethod = framePaint; f->title = NULL; - f->base.marginX += 3; - f->base.marginY += 9; - frameSetTitle(f, title); return widget; @@ -60,30 +52,27 @@ FrameT *frameNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title) { if (!frame) return NULL; - widget = widgetInit((WidgetT *)frame); + widget = widgetInit(W(frame), MAGIC_FRAME, x, y, w, h, 4, 20, 4, 4); if (!widget) { free(frame); return NULL; } - frame = (FrameT *)frameInit((WidgetT *)frame, x, y, w, h, title); + frame = (FrameT *)frameInit((WidgetT *)frame, title); return frame; } -static void framePaint(WidgetT *widget) { +static void framePaint(WidgetT *widget, RectT pos) { FrameT *f = (FrameT *)widget; - uint16_t o = _guiFont->height * 0.5; if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) { - vbeSurfaceSet(f->base.surface); - // Draw frame. - guiDrawHighlightFrame(f->base.x, f->base.y + o, f->base.x + f->base.w, f->base.y + f->base.h - o, _guiColor[COLOR_FRAME_SHADOW], _guiColor[COLOR_FRAME_HIGHLIGHT]); + guiDrawHighlightFrame(pos.x, pos.y + (fontHeightGet(_guiFont) * 0.5), pos.x + pos.w, pos.y + pos.h, _guiColor[COLOR_FRAME_SHADOW], _guiColor[COLOR_FRAME_HIGHLIGHT]); // Draw title. - fontRender(_guiFont, f->title, _guiColor[COLOR_FRAME_TEXT], _guiColor[COLOR_WINDOW_BACKGROUND], f->base.x + 10, f->base.y); + fontRender(_guiFont, f->title, _guiColor[COLOR_FRAME_TEXT], _guiColor[COLOR_WINDOW_BACKGROUND], pos.x + 10, pos.y); GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY); } diff --git a/client/src/gui/frame.h b/client/src/gui/frame.h index 687caa1..794214a 100644 --- a/client/src/gui/frame.h +++ b/client/src/gui/frame.h @@ -33,7 +33,7 @@ typedef struct FrameS { void frameDel(WidgetT **widget); -WidgetT *frameInit(WidgetT *widget, uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title); +WidgetT *frameInit(WidgetT *widget, char *title); FrameT *frameNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title); void frameSetTitle(FrameT *frame, char *title); diff --git a/client/src/gui/gui.c b/client/src/gui/gui.c index 42934ee..81cd7af 100644 --- a/client/src/gui/gui.c +++ b/client/src/gui/gui.c @@ -42,6 +42,22 @@ static uint8_t _guiLastWidgetLeftEvent = MOUSE_EVENT_NONE; static WidgetT *_guiFocused = NULL; +// Widget Magic Debug Info +static char *_magicDebugNames[MAGIC_COUNT] = { + "Unknown", + "Desktop", + "Window", + "Button", + "Label", + "Checkbox", + "RadioButton", + "Picture", + "Frame", + "Textbox" +}; + + +static void guiPaintBoundsGet(WidgetT *widget, RectT *pos); static void guiProcessKeyboardChildren(WidgetT *widget, uint8_t ascii, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt); static uint8_t guiProcessMouseChildren(WidgetT *widget, MouseT *mouse); @@ -62,27 +78,35 @@ void guiAttach(WidgetT *parent, WidgetT *child) { child->window = (WindowT *)p; } + // Caluclate clipping region - this is for the surface on which the widget is drawn, not in screen space. + if (GUI_GET_FLAG(child, WIDGET_FLAG_OWNS_SURFACE)) { + child->clip.x = child->margin.x; + child->clip.y = child->margin.y; + } else { + child->clip.x = child->pos.x; + child->clip.y = child->pos.y; + p = child; + while (p != NULL) { + child->clip.x += p->margin.x; + child->clip.y += p->margin.y; + p = p->parent; + } + } + child->clip.w = child->pos.w - child->margin.x - child->margin.w; + child->clip.h = child->pos.h - child->margin.y - child->margin.h; + // If this widget does not own a surface, find one for it to draw on. if (!GUI_GET_FLAG(child, WIDGET_FLAG_OWNS_SURFACE)) { p = child; while (p != NULL && !GUI_GET_FLAG(p, WIDGET_FLAG_OWNS_SURFACE)) { // Check parent. p = p->parent; - if (p) { - // Calculate margins as we go. - child->marginX += p->marginX; - child->marginY += p->marginY; - } } child->surface = p->surface; } - // Move the specified location by the margin so the widget doesn't have to deal with margins. - child->x += child->marginX; - child->y += child->marginY; - + // New windows should be active. if (child->magic == MAGIC_WINDOW) { - // New windows should be active. windowSetActive((WindowT *)child); } } @@ -100,7 +124,7 @@ void guiComposite() { // Render us? if (GUI_GET_FLAG(widget, WIDGET_FLAG_OWNS_SURFACE)) { - vbeSurfaceBlit(widget->surface, widget->x, widget->y); + vbeSurfaceBlit(widget->surface, widget->pos.x, widget->pos.y); } //***TODO*** This is wrong. Should be recursive. @@ -109,7 +133,7 @@ void guiComposite() { if (len > 0) { for (x=0; xchildren[x], WIDGET_FLAG_OWNS_SURFACE)) { - vbeSurfaceBlit(widget->children[x]->surface, widget->children[x]->x, widget->children[x]->y); + vbeSurfaceBlit(widget->children[x]->surface, widget->children[x]->pos.x, widget->children[x]->pos.y); } } } @@ -248,19 +272,23 @@ void guiFocusSet(WidgetT *widget) { void guiMousePositionOnWidgetGet(WidgetT *widget, MouseT *mouse, uint16_t *x, uint16_t *y) { - guiWidgetPositionOnScreenGet(widget, x, y); - *x = mouse->x - *x; - *y = mouse->y - *y; + RectT r; + guiWidgetPositionOnScreenGet(widget, &r); + *x = mouse->x - r.x; + *y = mouse->y - r.y; } void guiPaint(WidgetT *widget) { size_t len = arrlenu(widget->children); size_t x; + RectT pos; // Paint us. Widget handles dirty flag so they can animate if needed. if (widget->paintMethod) { - widget->paintMethod(widget); + vbeSurfaceSet(widget->surface); + guiPaintBoundsGet(widget, &pos); + widget->paintMethod(widget, pos); } // Paint all children. @@ -272,6 +300,20 @@ void guiPaint(WidgetT *widget) { } +static void guiPaintBoundsGet(WidgetT *widget, RectT *pos) { + if (widget->magic == MAGIC_DESKTOP || widget->magic == MAGIC_WINDOW) { + pos->x = 0; + pos->y = 0; + } else { + *pos = widget->parent->clip; + pos->x += widget->pos.x; + pos->y += widget->pos.y; + } + pos->w = widget->pos.w; + pos->h = widget->pos.h; +} + + void guiProcessMouse(MouseT *mouse) { guiProcessMouseChildren(W(_guiDesktop), mouse); } @@ -280,6 +322,7 @@ void guiProcessMouse(MouseT *mouse) { static uint8_t guiProcessMouseChildren(WidgetT *widget, MouseT *mouse) { size_t len; int16_t x; + RectT r; uint16_t mx; uint16_t my; uint16_t sx; @@ -295,9 +338,13 @@ static uint8_t guiProcessMouseChildren(WidgetT *widget, MouseT *mouse) { } } - guiWidgetPositionOnScreenGet(widget, &sx, &sy); + guiWidgetPositionOnScreenGet(widget, &r); + sx = r.x; + sy = r.y; guiMousePositionOnWidgetGet(widget, mouse, &mx, &my); + //logWrite("Mouse %dx%d Widget %s %dx%d\n", mouse->x, mouse->y, MagicDebugNames[widget->magic], sx, sy); + // Serious hack to make window dragging work better. // This is because it's possible to move the mouse faster than METRIC_WINDOW_TITLE_GRAB_HEIGHT pixels // which causes it to switch widgets. So this prevents that. @@ -307,7 +354,7 @@ static uint8_t guiProcessMouseChildren(WidgetT *widget, MouseT *mouse) { } // Is the mouse inside this widget? - if (mouse->x >= sx && mouse->y >= sy && mouse->x < sx + widget->w && mouse->y < sy + widget->h) { + if (mouse->x >= sx && mouse->y >= sy && mouse->x < sx + widget->pos.w && mouse->y < sy + widget->pos.h) { // Is this the same widget we were over before? if (_guiLastWidgetLeft != widget) { @@ -492,15 +539,58 @@ void guiUserDataSet(WidgetT *widget, void *userData) { } -void guiWidgetPositionOnScreenGet(WidgetT *widget, uint16_t *x, uint16_t *y) { - WidgetT *p = widget; - - *x = 0; - *y = 0; - - do { - *x += p->x; - *y += p->y; - p = p->parent; - } while (p != NULL); +void guiWidgetBoundsDrawableOnScreenGet(WidgetT *widget, RectT *bounds) { + guiPaintBoundsGet(widget, bounds); + if (GUI_GET_FLAG(widget, WIDGET_FLAG_OWNS_SURFACE)) { + bounds->x += widget->pos.x; + bounds->y += widget->pos.y; + } else { + bounds->x += widget->window->base.pos.x; + bounds->y += widget->window->base.pos.y; + } + bounds->x += widget->margin.x; + bounds->y += widget->margin.y; + bounds->w -= (widget->margin.x + widget->margin.w); + bounds->h -= (widget->margin.y + widget->margin.h); +} + + +void guiWidgetPositionOnScreenGet(WidgetT *widget, RectT *pos) { + WidgetT *p = widget->parent; + + if (GUI_GET_FLAG(widget, WIDGET_FLAG_OWNS_SURFACE)) { + *pos = widget->pos; + } else { + *pos = p->clip; + pos->x += widget->pos.x + widget->window->base.pos.x; + pos->y += widget->pos.y + widget->window->base.pos.y; + pos->w = widget->pos.w; + pos->h = widget->pos.h; + } + +} + + +void guiWidgetTreeDump(WidgetT *widget, uint16_t depth) { + size_t len = arrlenu(widget->children); + size_t x; + char line[256]; + + for (x=0; xmagic], + widget->pos.x, widget->pos.y, widget->pos.w, widget->pos.h, + widget->margin.x, widget->margin.y, widget->margin.w, widget->margin.h, + widget->clip.x, widget->clip.y, widget->clip.w, widget->clip.h, + widget->flags); + + // Mark all children. + if (len > 0) { + for (x=0; xchildren[x], depth + 1); + } + } } diff --git a/client/src/gui/gui.h b/client/src/gui/gui.h index daa8076..85f9fa5 100644 --- a/client/src/gui/gui.h +++ b/client/src/gui/gui.h @@ -27,6 +27,7 @@ #include "array.h" #include "mouse.h" #include "font.h" +#include "rect.h" #define GUI_GET_FLAG(w,f) (((w)->flags & (1 << (f))) != 0) @@ -50,6 +51,7 @@ enum MagicE { MAGIC_TEXTBOX, //MAGIC_UPDOWN, //MAGIC_LISTBOX, + //MAGIC_TERMINAL, MAGIC_COUNT }; @@ -149,7 +151,9 @@ DesktopT *guiStartup(void); void guiShutdown(void); void *guiUserDataGet(WidgetT *widget); void guiUserDataSet(WidgetT *widget, void *userData); -void guiWidgetPositionOnScreenGet(WidgetT *widget, uint16_t *x, uint16_t *y); +void guiWidgetBoundsDrawableOnScreenGet(WidgetT *widget, RectT *bounds); +void guiWidgetPositionOnScreenGet(WidgetT *widget, RectT *pos); +void guiWidgetTreeDump(WidgetT *widget, uint16_t depth); #endif // GUI_H diff --git a/client/src/gui/image.c b/client/src/gui/image.c index c318b73..58b233c 100644 --- a/client/src/gui/image.c +++ b/client/src/gui/image.c @@ -79,6 +79,23 @@ uint16_t imageHeightGet(ImageT *image) { } +uint8_t imageInfoGet(char *filename, uint16_t *width, uint16_t *height) { + int w; // Using boring old compiler 'int' on purpose. + int h; + int n; + int r; + + r = stbi_info(filename, &w, &h, &n); + if (r) { + *width = w; + *height = h; + return 1; + } + + return 0; +} + + ImageT *imageLoad(char *filename) { uint16_t x; uint16_t y; diff --git a/client/src/gui/image.h b/client/src/gui/image.h index f052d69..4a824f7 100644 --- a/client/src/gui/image.h +++ b/client/src/gui/image.h @@ -38,6 +38,7 @@ typedef struct ImageS { ImageT *imageAllocate(uint16_t w, uint16_t h); ImageT *imageCreate(uint16_t w, uint16_t h, ColorT color); uint16_t imageHeightGet(ImageT *image); +uint8_t imageInfoGet(char *filename, uint16_t *width, uint16_t *height); ImageT *imageLoad(char *filename); ColorT imagePixelGet(ImageT *image, uint16_t x, uint16_t y); void imageRender(ImageT *image, uint16_t x, uint16_t y); diff --git a/client/src/gui/label.c b/client/src/gui/label.c index 4c89435..deae15d 100644 --- a/client/src/gui/label.c +++ b/client/src/gui/label.c @@ -22,7 +22,7 @@ static void labelMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event); -static void labelPaint(WidgetT *widget); +static void labelPaint(WidgetT *widget, RectT pos); void labelDel(WidgetT **widget) { @@ -34,12 +34,9 @@ void labelDel(WidgetT **widget) { } -WidgetT *labelInit(WidgetT *widget, uint16_t x, uint16_t y, char *title) { +WidgetT *labelInit(WidgetT *widget, char *title) { LabelT *l = (LabelT *)widget; - l->base.magic = MAGIC_LABEL; - l->base.x = x; - l->base.y = y; l->base.delMethod = labelDel; l->base.paintMethod = labelPaint; l->base.mouseEventMethod = labelMouseEvent; @@ -50,9 +47,6 @@ WidgetT *labelInit(WidgetT *widget, uint16_t x, uint16_t y, char *title) { labelSetTitle(l, title); - // Width is set in labelSetTitle - l->base.h = fontHeightGet(_guiFont); - return widget; } @@ -85,32 +79,32 @@ static void labelMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t LabelT *labelNew(uint16_t x, uint16_t y, char *title) { - LabelT *label = (LabelT *)malloc(sizeof(LabelT)); - WidgetT *widget = NULL; + LabelT *label = (LabelT *)malloc(sizeof(LabelT)); + WidgetT *widget = NULL; + uint16_t h = fontHeightGet(_guiFont); if (!label) return NULL; - widget = widgetInit((WidgetT *)label); + // Width is set in Init + widget = widgetInit(W(label), MAGIC_LABEL, x, y, 0, h, 0, 0, 0, 0); if (!widget) { free(label); return NULL; } - label = (LabelT *)labelInit((WidgetT *)label, x, y, title); + label = (LabelT *)labelInit((WidgetT *)label, title); return label; } -static void labelPaint(WidgetT *widget) { +static void labelPaint(WidgetT *widget, RectT pos) { LabelT *l = (LabelT *)widget; ColorT text = GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE) ? l->active : l->foreground; if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) { - vbeSurfaceSet(l->base.surface); - // Draw title. - fontRender(_guiFont, l->title, text, l->background, l->base.x, l->base.y); + fontRender(_guiFont, l->title, text, l->background, pos.x, pos.y); GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY); } @@ -143,6 +137,6 @@ void labelSetForegroundColor(LabelT *label, ColorT color) { void labelSetTitle(LabelT *label, char *title) { if (label->title) free(label->title); label->title = strdup(title); - label->base.w = (strlen(title) * fontWidthGet(_guiFont)); + label->base.pos.w = (strlen(title) * fontWidthGet(_guiFont)); GUI_SET_FLAG((WidgetT *)label, WIDGET_FLAG_DIRTY); } diff --git a/client/src/gui/label.h b/client/src/gui/label.h index 47cedb2..a2a81c5 100644 --- a/client/src/gui/label.h +++ b/client/src/gui/label.h @@ -37,7 +37,7 @@ typedef struct LabelS { void labelDel(WidgetT **widget); -WidgetT *labelInit(WidgetT *widget, uint16_t x, uint16_t y, char *title); +WidgetT *labelInit(WidgetT *widget, char *title); LabelT *labelNew(uint16_t x, uint16_t y, char *title); void labelSetActiveColor(LabelT *label, ColorT color); void labelSetBackgroundColor(LabelT *label, ColorT color); diff --git a/client/src/gui/picture.c b/client/src/gui/picture.c index 6092972..11cdc50 100644 --- a/client/src/gui/picture.c +++ b/client/src/gui/picture.c @@ -22,7 +22,7 @@ static void pictureMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event); -static void picturePaint(WidgetT *widget); +static void picturePaint(WidgetT *widget, RectT pos); void pictureDel(WidgetT **widget) { @@ -35,12 +35,9 @@ void pictureDel(WidgetT **widget) { } -WidgetT *pictureInit(WidgetT *widget, uint16_t x, uint16_t y, char *filename) { +WidgetT *pictureInit(WidgetT *widget, char *filename) { PictureT *l = (PictureT *)widget; - l->base.magic = MAGIC_PICTURE; - l->base.x = x; - l->base.y = y; l->base.delMethod = pictureDel; l->base.paintMethod = picturePaint; l->base.mouseEventMethod = pictureMouseEvent; @@ -53,9 +50,6 @@ WidgetT *pictureInit(WidgetT *widget, uint16_t x, uint16_t y, char *filename) { return NULL; } - l->base.w = imageWidthGet(l->image); - l->base.h = imageHeightGet(l->image); - return widget; } @@ -77,16 +71,23 @@ static void pictureMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16 PictureT *pictureNew(uint16_t x, uint16_t y, char *filename) { PictureT *picture = (PictureT *)malloc(sizeof(PictureT)); WidgetT *widget = NULL; + uint16_t w; + uint16_t h; if (!picture) return NULL; - widget = widgetInit((WidgetT *)picture); + if (!imageInfoGet(filename, &w, &h)) { + free(picture); + return NULL; + } + + widget = widgetInit(W(picture), MAGIC_PICTURE, x, y, w, h, 0, 0, 0, 0); if (!widget) { free(picture); return NULL; } - picture = (PictureT *)pictureInit((WidgetT *)picture, x, y, filename); + picture = (PictureT *)pictureInit((WidgetT *)picture, filename); if (!picture) { free(picture); return NULL; @@ -96,13 +97,11 @@ PictureT *pictureNew(uint16_t x, uint16_t y, char *filename) { } -static void picturePaint(WidgetT *widget) { +static void picturePaint(WidgetT *widget, RectT pos) { PictureT *p = (PictureT *)widget; if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) { - vbeSurfaceSet(p->base.surface); - - imageRender(p->image, p->base.x, p->base.y); + imageRender(p->image, pos.x, pos.y); GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY); } diff --git a/client/src/gui/picture.h b/client/src/gui/picture.h index 735d42c..941a2f2 100644 --- a/client/src/gui/picture.h +++ b/client/src/gui/picture.h @@ -36,7 +36,7 @@ typedef struct PictureS { void pictureDel(WidgetT **widget); -WidgetT *pictureInit(WidgetT *widget, uint16_t x, uint16_t y, char *filename); +WidgetT *pictureInit(WidgetT *widget, char *filename); PictureT *pictureNew(uint16_t x, uint16_t y, char *filename); void pictureSetClickHandler(PictureT *picture, widgetCallback callback); diff --git a/client/src/gui/radio.c b/client/src/gui/radio.c index d8ebd60..4f056f8 100644 --- a/client/src/gui/radio.c +++ b/client/src/gui/radio.c @@ -24,7 +24,7 @@ static void radioClearSelectedInGroup(WidgetT *widget, uint32_t group); static RadioT *radioFindSelectedInGroup(WidgetT *widget, uint32_t group); static void radioMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event); -static void radioPaint(WidgetT *widget); +static void radioPaint(WidgetT *widget, RectT pos); static void radioClearSelectedInGroup(WidgetT *widget, uint32_t group) { @@ -91,12 +91,9 @@ RadioT *radioGetSelected(RadioT *radio) { } -WidgetT *radioInit(WidgetT *widget, uint16_t x, uint16_t y, char *title, uint16_t group) { +WidgetT *radioInit(WidgetT *widget, char *title, uint16_t group) { RadioT *r = (RadioT *)widget; - r->base.magic = MAGIC_RADIOBUTTON; - r->base.x = x; - r->base.y = y; r->base.delMethod = radioDel; r->base.paintMethod = radioPaint; r->base.mouseEventMethod = radioMouseEvent; @@ -107,7 +104,7 @@ WidgetT *radioInit(WidgetT *widget, uint16_t x, uint16_t y, char *title, uint16_ radioSetTitle(r, title); // Width is set in radioSetTitle - r->base.h = fontHeightGet(_guiFont); + r->base.pos.h = fontHeightGet(_guiFont); return widget; } @@ -135,47 +132,51 @@ RadioT *radioNew(uint16_t x, uint16_t y, char *title, uint16_t group) { if (!radio) return NULL; - widget = widgetInit((WidgetT *)radio); + // We set the widget width and height in Init. + widget = widgetInit(W(radio), MAGIC_RADIOBUTTON, x, y, 0, 0, 0, 0, 0, 0); if (!widget) { free(radio); return NULL; } - radio = (RadioT *)radioInit((WidgetT *)radio, x, y, title, group); + radio = (RadioT *)radioInit((WidgetT *)radio, title, group); return radio; } -static void radioPaint(WidgetT *widget) { +static void radioPaint(WidgetT *widget, RectT pos) { RadioT *r = (RadioT *)widget; int16_t i; int16_t o; - uint8_t active = (radioGetSelected(r) == r); - ColorT highlight = active ? _guiColor[COLOR_RADIOBUTTON_SHADOW] : _guiColor[COLOR_RADIOBUTTON_HIGHLIGHT]; - ColorT shadow = active ? _guiColor[COLOR_RADIOBUTTON_HIGHLIGHT] : _guiColor[COLOR_RADIOBUTTON_SHADOW]; - ColorT fill = active ? _guiColor[COLOR_RADIOBUTTON_ACTIVE] : _guiColor[COLOR_RADIOBUTTON_INACTIVE]; + uint8_t active; + ColorT highlight; + ColorT shadow; + ColorT fill; if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) { - vbeSurfaceSet(r->base.surface); + active = (radioGetSelected(r) == r); + highlight = active ? _guiColor[COLOR_RADIOBUTTON_SHADOW] : _guiColor[COLOR_RADIOBUTTON_HIGHLIGHT]; + shadow = active ? _guiColor[COLOR_RADIOBUTTON_HIGHLIGHT] : _guiColor[COLOR_RADIOBUTTON_SHADOW]; + fill = active ? _guiColor[COLOR_RADIOBUTTON_ACTIVE] : _guiColor[COLOR_RADIOBUTTON_INACTIVE]; // Radio button is 10x10 pixels. Find offset based on font height. o = (_guiFont->height - 10) * 0.5; // Draw outline of radio button. - guiDrawLine(r->base.x, r->base.y + o + 5, r->base.x + 5, r->base.y + o, highlight); - guiDrawLine(r->base.x + 5, r->base.y + o, r->base.x + 10, r->base.y + o + 5, highlight); - guiDrawLine(r->base.x, r->base.y + o + 5, r->base.x + 5, r->base.y + o + 10, shadow); - guiDrawLine(r->base.x + 5, r->base.y + o + 10, r->base.x + 10, r->base.y + o + 5, shadow); + guiDrawLine(pos.x, pos.y + o + 5, pos.x + 5, pos.y + o, highlight); + guiDrawLine(pos.x + 5, pos.y + o, pos.x + 10, pos.y + o + 5, highlight); + guiDrawLine(pos.x, pos.y + o + 5, pos.x + 5, pos.y + o + 10, shadow); + guiDrawLine(pos.x + 5, pos.y + o + 10, pos.x + 10, pos.y + o + 5, shadow); // Fill radio button. for (i=0; i<4; i++) { - guiDrawLine(r->base.x + 5 - i, r->base.y + o + i + 1, r->base.x + 5 + i, r->base.y + o + i + 1, fill); - guiDrawLine(r->base.x + 5 - i, r->base.y + o - i + 8, r->base.x + 5 + i, r->base.y + o - i + 8, fill); + guiDrawLine(pos.x + 5 - i, pos.y + o + i + 1, pos.x + 5 + i, pos.y + o + i + 1, fill); + guiDrawLine(pos.x + 5 - i, pos.y + o - i + 8, pos.x + 5 + i, pos.y + o - i + 8, fill); } // Draw title. - fontRender(_guiFont, r->title, _guiColor[COLOR_RADIOBUTTON_TEXT], _guiColor[COLOR_WINDOW_BACKGROUND], r->base.x + 10 + _guiMetric[METRIC_RADIOBUTTON_PADDING], r->base.y); + fontRender(_guiFont, r->title, _guiColor[COLOR_RADIOBUTTON_TEXT], _guiColor[COLOR_WINDOW_BACKGROUND], pos.x + 10 + _guiMetric[METRIC_RADIOBUTTON_PADDING], pos.y); GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY); } @@ -202,6 +203,6 @@ void radioSetSelected(RadioT *radio) { void radioSetTitle(RadioT *radio, char *title) { if (radio->title) free(radio->title); radio->title = strdup(title); - radio->base.w = (strlen(title) * fontWidthGet(_guiFont)) + 10 + _guiMetric[METRIC_RADIOBUTTON_PADDING]; + radio->base.pos.w = (strlen(title) * fontWidthGet(_guiFont)) + 10 + _guiMetric[METRIC_RADIOBUTTON_PADDING]; GUI_SET_FLAG((WidgetT *)radio, WIDGET_FLAG_DIRTY); } diff --git a/client/src/gui/radio.h b/client/src/gui/radio.h index c56f58c..001cfc1 100644 --- a/client/src/gui/radio.h +++ b/client/src/gui/radio.h @@ -36,7 +36,7 @@ typedef struct RadioS { void radioDel(WidgetT **widget); RadioT *radioGetSelected(RadioT *radio); -WidgetT *radioInit(WidgetT *widget, uint16_t x, uint16_t y, char *title, uint16_t group); +WidgetT *radioInit(WidgetT *widget, char *title, uint16_t group); RadioT *radioNew(uint16_t x, uint16_t y, char *title, uint16_t group); void radioSetClickHandler(RadioT *radio, widgetCallback callback); void radioSetSelected(RadioT *radio); diff --git a/client/src/gui/rect.h b/client/src/gui/rect.h new file mode 100644 index 0000000..6e553f2 --- /dev/null +++ b/client/src/gui/rect.h @@ -0,0 +1,36 @@ +/* + * Kangaroo Punch MultiPlayer Game Server Mark II + * Copyright (C) 2020-2021 Scott Duensing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#ifndef RECT_H +#define RECT_H + + +#include "os.h" + + +typedef struct RectS { + int16_t x; + int16_t y; + int16_t w; + int16_t h; +} RectT; + + +#endif // RECT_H diff --git a/client/src/gui/textbox.c b/client/src/gui/textbox.c index 1d642ac..c031f6d 100644 --- a/client/src/gui/textbox.c +++ b/client/src/gui/textbox.c @@ -24,7 +24,7 @@ static void textboxFocusEvent(WidgetT *widget, uint8_t focused); static void textboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event); static void textboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt); -static void textboxPaint(WidgetT *widget); +static void textboxPaint(WidgetT *widget, RectT pos); void textboxDel(WidgetT **widget) { @@ -47,14 +47,9 @@ char *textboxGetValue(TextboxT *textbox) { } -WidgetT *textboxInit(WidgetT *widget, uint16_t x, uint16_t y, uint16_t w, char *title) { +WidgetT *textboxInit(WidgetT *widget, char *title) { TextboxT *t = (TextboxT *)widget; - t->base.magic = MAGIC_TEXTBOX; - t->base.x = x; - t->base.y = y; - t->base.w = w; - t->base.h = fontHeightGet(_guiFont) + 4 + (_guiMetric[METRIC_TEXTBOX_VERTICAL_PADDING] * 2); t->base.delMethod = textboxDel; t->base.focusMethod = textboxFocusEvent; t->base.keyboardEventMethod = textboxKeyboardEvent; @@ -94,53 +89,46 @@ static void textboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16 TextboxT *textboxNew(uint16_t x, uint16_t y, uint16_t w, char *title) { TextboxT *textbox = (TextboxT *)malloc(sizeof(TextboxT)); WidgetT *widget = NULL; + uint16_t h = fontHeightGet(_guiFont) + 4 + (_guiMetric[METRIC_TEXTBOX_VERTICAL_PADDING] * 2); if (!textbox) return NULL; - widget = widgetInit((WidgetT *)textbox); + widget = widgetInit(W(textbox), MAGIC_TEXTBOX, x, y, w, h, 0, 0, 0, 0); if (!widget) { free(textbox); return NULL; } - - if (!textbox) return NULL; - - widget = widgetInit((WidgetT *)textbox); - if (!widget) { - free(textbox); - return NULL; - } - - textbox = (TextboxT *)textboxInit((WidgetT *)textbox, x, y, w, title); + textbox = (TextboxT *)textboxInit((WidgetT *)textbox, title); return textbox; } -static void textboxPaint(WidgetT *widget) { +static void textboxPaint(WidgetT *widget, RectT pos) { TextboxT *t = (TextboxT *)widget; - uint16_t labelWidth = (strlen(t->title) * fontWidthGet(_guiFont)) + _guiMetric[METRIC_TEXTBOX_PADDING]; - uint16_t valueWidth = (t->visible * fontWidthGet(_guiFont)) + (_guiMetric[METRIC_TEXTBOX_HORIZONTAL_PADDING] * 2); char *draw = NULL; + uint16_t labelWidth; + uint16_t valueWidth; if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) { - vbeSurfaceSet(t->base.surface); + labelWidth = (strlen(t->title) * fontWidthGet(_guiFont)) + _guiMetric[METRIC_TEXTBOX_PADDING]; + valueWidth = (t->visible * fontWidthGet(_guiFont)) + (_guiMetric[METRIC_TEXTBOX_HORIZONTAL_PADDING] * 2); // Draw title. - fontRender(_guiFont, t->title, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_WINDOW_BACKGROUND], t->base.x, t->base.y + 1 + _guiMetric[METRIC_TEXTBOX_VERTICAL_PADDING]); + fontRender(_guiFont, t->title, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_WINDOW_BACKGROUND], pos.x, pos.y + 2 + _guiMetric[METRIC_TEXTBOX_VERTICAL_PADDING]); // Draw outline of textbox. - guiDrawHighlightFrame( t->base.x + labelWidth, t->base.y, t->base.x + labelWidth + valueWidth + 2, t->base.y + t->base.h, _guiColor[COLOR_TEXTBOX_SHADOW], _guiColor[COLOR_TEXTBOX_HIGHLIGHT]); - guiDrawRectangle( t->base.x + labelWidth + 1, t->base.y + 1, t->base.x + labelWidth + valueWidth + 1, t->base.y + t->base.h - 1, _guiColor[COLOR_WINDOW_BACKGROUND]); + guiDrawHighlightFrame( pos.x + labelWidth, pos.y, pos.x + labelWidth + valueWidth + 2, pos.y + pos.h, _guiColor[COLOR_TEXTBOX_SHADOW], _guiColor[COLOR_TEXTBOX_HIGHLIGHT]); + guiDrawRectangle( pos.x + labelWidth + 1, pos.y + 1, pos.x + labelWidth + valueWidth + 1, pos.y + pos.h - 1, _guiColor[COLOR_WINDOW_BACKGROUND]); // Draw background. - guiDrawRectangleFilled(t->base.x + labelWidth + 2, t->base.y + 2, t->base.x + labelWidth + valueWidth, t->base.y + t->base.h - 2, _guiColor[COLOR_TEXTBOX_BACKGROUND]); + guiDrawRectangleFilled(pos.x + labelWidth + 2, pos.y + 2, pos.x + labelWidth + valueWidth, pos.y + pos.h - 2, _guiColor[COLOR_TEXTBOX_BACKGROUND]); // Draw value. ***TODO*** This needs much more! draw = strdup(t->value); if (strlen(t->value) > t->visible) draw[t->visible] = 0; - fontRender(_guiFont, draw, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], t->base.x + labelWidth + 2 + _guiMetric[METRIC_TEXTBOX_HORIZONTAL_PADDING], t->base.y + 2 + _guiMetric[METRIC_TEXTBOX_VERTICAL_PADDING]); + fontRender(_guiFont, draw, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], pos.x + labelWidth + 2 + _guiMetric[METRIC_TEXTBOX_HORIZONTAL_PADDING], pos.y + 2 + _guiMetric[METRIC_TEXTBOX_VERTICAL_PADDING]); free(draw); GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY); @@ -172,7 +160,7 @@ void textboxSetTitle(TextboxT *textbox, char *title) { textbox->title = strdup(title); // Figure out how many characters we have room to display. - textbox->visible = (textbox->base.w - ((strlen(title) * fontWidthGet(_guiFont)) + _guiMetric[METRIC_TEXTBOX_PADDING] + 4 + (_guiMetric[METRIC_TEXTBOX_HORIZONTAL_PADDING] * 2))) / fontWidthGet(_guiFont); + textbox->visible = (textbox->base.pos.w - ((strlen(title) * fontWidthGet(_guiFont)) + _guiMetric[METRIC_TEXTBOX_PADDING] + 4 + (_guiMetric[METRIC_TEXTBOX_HORIZONTAL_PADDING] * 2))) / fontWidthGet(_guiFont); GUI_SET_FLAG((WidgetT *)textbox, WIDGET_FLAG_DIRTY); } diff --git a/client/src/gui/textbox.h b/client/src/gui/textbox.h index 85e9475..6b45f68 100644 --- a/client/src/gui/textbox.h +++ b/client/src/gui/textbox.h @@ -40,7 +40,7 @@ typedef struct TextboxS { void textboxDel(WidgetT **widget); char *textboxGetValue(TextboxT *textbox); -WidgetT *textboxInit(WidgetT *widget, uint16_t x, uint16_t y, uint16_t w, char *title); +WidgetT *textboxInit(WidgetT *widget, char *title); TextboxT *textboxNew(uint16_t x, uint16_t y, uint16_t w, char *title); void textboxSetValue(TextboxT *textbox, char *value); void textboxSetMaxLength(TextboxT *textbox, uint16_t length); diff --git a/client/src/gui/timer.c b/client/src/gui/timer.c new file mode 100644 index 0000000..3ff9246 --- /dev/null +++ b/client/src/gui/timer.c @@ -0,0 +1,36 @@ +/* + * Kangaroo Punch MultiPlayer Game Server Mark II + * Copyright (C) 2020-2021 Scott Duensing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#include "timer.h" + + +void timerShutdown(void) { + // Nothing yet. +} + + +void timerStartup(void) { + // Nothing yet. +} + + +void timerUpdate(void) { + +} diff --git a/client/src/gui/timer.h b/client/src/gui/timer.h new file mode 100644 index 0000000..efcdf12 --- /dev/null +++ b/client/src/gui/timer.h @@ -0,0 +1,30 @@ +/* + * Kangaroo Punch MultiPlayer Game Server Mark II + * Copyright (C) 2020-2021 Scott Duensing + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#ifndef TIMER_H +#define TIMER_H + + +void timerShutdown(void); +void timerStartup(void); +void timerUpdate(void); + + +#endif // TIMER_H diff --git a/client/src/gui/widget.c b/client/src/gui/widget.c index fc98c28..b403321 100644 --- a/client/src/gui/widget.c +++ b/client/src/gui/widget.c @@ -19,30 +19,33 @@ #include "widget.h" +#include "window.h" -uint16_t widgetGetHeight(WidgetT *widget) { - return widget->h; +uint16_t widgetHeightGet(WidgetT *widget) { + return widget->pos.h; } -uint16_t widgetGetWidth(WidgetT *widget) { - return widget->w; -} - - -WidgetT *widgetInit(WidgetT *widget) { - widget->magic = MAGIC_UNKNOWN; +WidgetT *widgetInit(WidgetT *widget, uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t marginX, uint16_t marginY, uint16_t marginX2, uint16_t marginY2) { + widget->magic = magic; widget->flags = 0; - widget->x = 0; - widget->y = 0; - widget->w = 0; - widget->h = 0; - widget->marginX = 0; - widget->marginY = 0; + widget->pos.x = x; + widget->pos.y = y; + widget->pos.w = w; + widget->pos.h = h; + widget->margin.x = marginX; + widget->margin.y = marginY; + widget->margin.w = marginX2; + widget->margin.h = marginY2; + widget->clip.x = 0; + widget->clip.y = 0; + widget->clip.w = 0; + widget->clip.h = 0; widget->surface = NULL; widget->children = NULL; widget->parent = NULL; + widget->window = NULL; widget->delMethod = NULL; widget->focusMethod = NULL; widget->keyboardEventMethod = NULL; @@ -56,12 +59,17 @@ WidgetT *widgetInit(WidgetT *widget) { } -WidgetT *widgetNew(void) { +WidgetT *widgetNew(uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t marginX, uint16_t marginY, uint16_t marginX2, uint16_t marginY2) { WidgetT *widget = (WidgetT *)malloc(sizeof(WidgetT)); if (!widget) return NULL; - widget = widgetInit(widget); + widget = widgetInit(widget, magic, x, y, w, h, marginX, marginY, marginX2, marginY2); return widget; } + + +uint16_t widgetWidthGet(WidgetT *widget) { + return widget->pos.w; +} diff --git a/client/src/gui/widget.h b/client/src/gui/widget.h index 2138dbd..73903f8 100644 --- a/client/src/gui/widget.h +++ b/client/src/gui/widget.h @@ -41,7 +41,7 @@ typedef void (*widgetCallback)(struct WidgetS *widget); typedef void (*widgetDelMethod)(struct WidgetS **widget); typedef void (*widgetFocusMethod)(struct WidgetS *widget, uint8_t focused); typedef void (*widgetKeyboardEventMethod)(struct WidgetS *widget, uint8_t ascii, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt); -typedef void (*widgetPaintMethod)(struct WidgetS *widget); +typedef void (*widgetPaintMethod)(struct WidgetS *widget, RectT pos); typedef void (*widgetMouseEventMethod)(struct WidgetS *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event); @@ -50,12 +50,9 @@ typedef struct WidgetS { uint8_t flags; // See above enum SurfaceT *surface; // Pointer to compositable surface or NULL WindowT *window; // The window holding this widget or NULL - int16_t x; // Position of widget on parent - int16_t y; // Position of widget on parent - uint16_t w; // Width of widget - uint16_t h; // Height of widget - uint16_t marginX; // Pixels to skip when placing child widgets - uint16_t marginY; // Pixels to skip when placing child widgets + RectT pos; // Position of widget on parent + RectT margin; // Pixels to skip over on each edge when rendering children + RectT clip; // Calculated clipping region on surface WidgetT **children; // List of children WidgetT *parent; // Parent of this widget widgetDelMethod delMethod; // Delete method @@ -67,10 +64,10 @@ typedef struct WidgetS { } WidgetT; -uint16_t widgetGetHeight(WidgetT *widget); -uint16_t widgetGetWidth(WidgetT *widget); -WidgetT *widgetInit(WidgetT *widget); -WidgetT *widgetNew(void); +uint16_t widgetHeightGet(WidgetT *widget); +WidgetT *widgetInit(WidgetT *widget, uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t marginX, uint16_t marginY, uint16_t marginX2, uint16_t marginY2); +WidgetT *widgetNew(uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t marginX, uint16_t marginY, uint16_t marginX2, uint16_t marginY2); +uint16_t widgetWidthGet(WidgetT *widget); #endif // WIDGET_H diff --git a/client/src/gui/window.c b/client/src/gui/window.c index 5fb93ef..4c895af 100644 --- a/client/src/gui/window.c +++ b/client/src/gui/window.c @@ -56,27 +56,19 @@ void windowDel(WidgetT **widget) { } -WidgetT *windowInit(WidgetT *window, uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title) { +WidgetT *windowInit(WidgetT *window, char *title) { WindowT *win = (WindowT *)window; - win->base.magic = MAGIC_WINDOW; - win->base.x = x; - win->base.y = y; - win->base.w = w; - win->base.h = h; win->base.delMethod = windowDel; win->base.paintMethod = windowPaint; win->base.mouseEventMethod = windowMouseEvent; win->flags = 0; win->title = NULL; - win->base.marginX += _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 6; - win->base.marginY += _guiMetric[METRIC_WINDOW_TITLE_GRAB_HEIGHT] + 1; - windowSetTitle(win, title); GUI_SET_FLAG(window, WIDGET_FLAG_OWNS_SURFACE); - win->base.surface = vbeSurfaceCreate(win->base.w, win->base.h); + win->base.surface = vbeSurfaceCreate(win->base.pos.w, win->base.pos.h); if (!win->base.surface) { free(win->title); free(win); @@ -102,21 +94,21 @@ static void windowMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_ if (y < _guiMetric[METRIC_WINDOW_TITLE_GRAB_HEIGHT]) { // Start dragging. _guiDragWidget = widget; - _guiDragOffsetX = mouse->x - window->base.x; - _guiDragOffsetY = mouse->y - window->base.y; + _guiDragOffsetX = mouse->x - window->base.pos.x; + _guiDragOffsetY = mouse->y - window->base.pos.y; } } // Still dragging? We use raw mouse data here because it's possible to drag too quickly and trigger "OUT" events. if (_guiDragWidget == widget && mouse->buttonLeft && GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE)) { // Move window. - window->base.x = mouse->x - _guiDragOffsetX; - window->base.y = mouse->y - _guiDragOffsetY; + window->base.pos.x = mouse->x - _guiDragOffsetX; + window->base.pos.y = mouse->y - _guiDragOffsetY; // Keep it on the screen. - if (window->base.x < 0) window->base.x = 0; - if (window->base.x + window->base.w > vbeDisplayWidthGet()) window->base.x = vbeDisplayWidthGet() - window->base.w; - if (window->base.y < 0) window->base.y = 0; - if (window->base.y + window->base.h > vbeDisplayHeightGet()) window->base.y = vbeDisplayHeightGet() - window->base.h; + if (window->base.pos.x < 0) window->base.pos.x = 0; + if (window->base.pos.x + window->base.pos.w > vbeDisplayWidthGet()) window->base.pos.x = vbeDisplayWidthGet() - window->base.pos.w; + if (window->base.pos.y < 0) window->base.pos.y = 0; + if (window->base.pos.y + window->base.pos.h > vbeDisplayHeightGet()) window->base.pos.y = vbeDisplayHeightGet() - window->base.pos.h; } // Be sure we stop dragging on mouse up or move out. @@ -132,13 +124,17 @@ WindowT *windowNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title) if (!window) return NULL; - widget = widgetInit((WidgetT *)window); + widget = widgetInit(W(window), MAGIC_WINDOW, x, y, w, h, + _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 3, + _guiMetric[METRIC_WINDOW_TITLE_GRAB_HEIGHT], + _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 4, + _guiMetric[METRIC_WINDOW_BORDER_WIDTH] + 4); if (!widget) { free(window); return NULL; } - window = (WindowT *)windowInit((WidgetT *)window, x, y, w, h, title); + window = (WindowT *)windowInit((WidgetT *)window, title); return window; } @@ -146,8 +142,8 @@ WindowT *windowNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title) static void windowPaint(WidgetT *widget) { WindowT *w = (WindowT *)widget; - uint16_t x2 = w->base.w - 1; - uint16_t y2 = w->base.h - 1; + uint16_t x2 = w->base.pos.w - 1; + uint16_t y2 = w->base.pos.h - 1; ColorT background = GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE) ? _guiColor[COLOR_WINDOW_TITLE_ACTIVE] : _guiColor[COLOR_WINDOW_TITLE_INACTIVE]; ColorT text = GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE) ? _guiColor[COLOR_WINDOW_TITLE_TEXT_ACTIVE] : _guiColor[COLOR_WINDOW_TITLE_TEXT_INACTIVE]; diff --git a/client/src/gui/window.h b/client/src/gui/window.h index 3fe3eb1..2f1065d 100644 --- a/client/src/gui/window.h +++ b/client/src/gui/window.h @@ -40,7 +40,7 @@ typedef struct WindowS { void windowDel(WidgetT **widget); -WidgetT *windowInit(WidgetT *window, uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title); +WidgetT *windowInit(WidgetT *window, char *title); WindowT *windowNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title); void windowSetActive(WindowT *window); void windowSetTitle(WindowT *window, char *title); diff --git a/client/src/linux/linux.c b/client/src/linux/linux.c index e2459f5..4e8c1fa 100644 --- a/client/src/linux/linux.c +++ b/client/src/linux/linux.c @@ -259,7 +259,7 @@ uint8_t vbeStartup(uint16_t xRes, uint16_t yRes, uint8_t bpp) { (void)bpp; - _windowScale = 2; + _windowScale = 3; vbePutPixel = vbePutPixel32; SDL_Init(SDL_INIT_EVERYTHING); diff --git a/client/src/main.c b/client/src/main.c index 8112168..c095164 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -26,6 +26,7 @@ * - More widget states: Ghosted, hidden * - Move setup math for paint events inside the dirty check * - Methods that can change the width of a widget (such as setTitle) need to repaint the parent window as well + * - 'pos' should be passed in to the paint method and the surface should already be set * */ @@ -37,6 +38,7 @@ #include "task.h" #include "image.h" #include "font.h" +#include "timer.h" #include "gui.h" #include "widget.h" @@ -56,10 +58,67 @@ void buttonClick(WidgetT *widget) { } -void test(void *data) { - MouseT *mouse = NULL; - ImageT *pointer = NULL; + +void drawWidgetDebug(WidgetT *widget, uint8_t debugToggle) { + size_t len = arrlenu(widget->children); + size_t i; + RectT r; + + if (debugToggle) { + // Clipping region (blue) + guiWidgetBoundsDrawableOnScreenGet(widget, &r); + guiDrawRectangle(r.x, r.y, r.x + r.w, r.y + r.h, vbeMakeColor(0, 0, 255)); + } else { + // Widget border (red) + guiWidgetPositionOnScreenGet(widget, &r); + guiDrawRectangle(r.x, r.y, r.x + widget->pos.w, r.y + widget->pos.h, vbeMakeColor(255, 0, 0)); + } + + if (len > 0) { + for (i=0; ichildren[i], debugToggle); + } + } +} + + +void mainLoop(void *data) { + MouseT *mouse = NULL; + ImageT *pointer = NULL; ColorT alpha; + int8_t key = 0; + int8_t debugToggle = 0; + + (void)data; + + pointer = imageLoad("mouse.png"); + alpha = imagePixelGet(pointer, 5, 0); + + do { + mouse = mouseRead(); + if (keyHit()) { + key = keyASCII(); + guiProcessKeyboard(keyASCII(), keyScanCode(), keyShift(), keyControl(), keyAlt()); + debugToggle = !debugToggle; + } else { + key = 0; + } + guiProcessMouse(mouse); + guiComposite(); + imageRenderWithAlpha(pointer, mouse->x, mouse->y, alpha); + + if (key == 'd') guiWidgetTreeDump(guiRootGet(), 0); + drawWidgetDebug(guiRootGet(), debugToggle); + + vbeWaitVBlank(); + vbePresent(); + } while (key != 27 && !(!mouse->buttonRight && mouse->buttonRightWasDown)); // Exit on release of right-click. + + imageUnload(&pointer); +} + + +void test(void *data) { DesktopT *desktop = (DesktopT *)guiRootGet(); WindowT *w1 = NULL; WindowT *w2 = NULL; @@ -76,13 +135,9 @@ void test(void *data) { PictureT *p1 = NULL; FrameT *f1 = NULL; TextboxT *t1 = NULL; - int8_t key = 0; (void)data; - pointer = imageLoad("mouse.png"); - alpha = imagePixelGet(pointer, 5, 0); - // Windows w1 = windowNew(25, 25, 300, 200, "Window 1"); guiAttach(W(desktop), W(w1)); @@ -98,15 +153,15 @@ void test(void *data) { // Window 2 r1a = radioNew(10, 10, "Radio 1a", 1); guiAttach(W(w2), W(r1a)); - r2a = radioNew(20 + widgetGetWidth(W(r1a)), 10, "Radio 2a", 1); + r2a = radioNew(20 + widgetWidthGet(W(r1a)), 10, "Radio 2a", 1); guiAttach(W(w2), W(r2a)); - r3a = radioNew(30 + widgetGetWidth(W(r1a)) + widgetGetWidth(W(r2a)), 10, "Radio 3a", 1); + r3a = radioNew(30 + widgetWidthGet(W(r1a)) + widgetWidthGet(W(r2a)), 10, "Radio 3a", 1); guiAttach(W(w2), W(r3a)); r1b = radioNew(10, 35, "Radio 1b", 2); guiAttach(W(w2), W(r1b)); - r2b = radioNew(20 + widgetGetWidth(W(r1b)), 35, "Radio 2b", 2); + r2b = radioNew(20 + widgetWidthGet(W(r1b)), 35, "Radio 2b", 2); guiAttach(W(w2), W(r2b)); - r3b = radioNew(30 + widgetGetWidth(W(r1b)) + widgetGetWidth(W(r2b)), 35, "Radio 3b", 2); + r3b = radioNew(30 + widgetWidthGet(W(r1b)) + widgetWidthGet(W(r2b)), 35, "Radio 3b", 2); guiAttach(W(w2), W(r3b)); radioSetSelected(r1a); radioSetSelected(r2b); @@ -117,29 +172,12 @@ void test(void *data) { // Window 3 f1 = frameNew(10, 5, 175, 125, "Test Frame"); guiAttach(W(w3), W(f1)); - b1 = buttonNew(10, 10, "Test Button", buttonClick); + b1 = buttonNew(0, 0, "Test Button", buttonClick); guiAttach(W(f1), W(b1)); l1 = labelNew(10, 40, "Test Label"); guiAttach(W(f1), W(l1)); c1 = checkboxNew(10, 65, "Test Checkbox"); guiAttach(W(f1), W(c1)); - - do { - mouse = mouseRead(); - if (keyHit()) { - key = keyASCII(); - guiProcessKeyboard(keyASCII(), keyScanCode(), keyShift(), keyControl(), keyAlt()); - } else { - key = 0; - } - guiProcessMouse(mouse); - guiComposite(); - imageRenderWithAlpha(pointer, mouse->x, mouse->y, alpha); - vbeWaitVBlank(); - vbePresent(); - } while (key != 27 && !(!mouse->buttonRight && mouse->buttonRightWasDown)); // Exit on release of right-click. - - imageUnload(&pointer); } @@ -187,14 +225,17 @@ int main(int argc, char *argv[]) { } mouseStartup(); + timerStartup(); guiStartup(); taskStartup(64); taskCreate(test, NULL); + taskCreate(mainLoop, NULL); taskRun(); taskShutdown(); guiShutdown(); + timerShutdown(); mouseShutdown(); vbeShutdown();