Freaking margins and clipping regions finally fixed. Not that we clip yet.
This commit is contained in:
parent
70f944d416
commit
6edae8ed47
29 changed files with 507 additions and 279 deletions
|
@ -51,8 +51,10 @@ HEADERS = \
|
||||||
src/gui/label.h \
|
src/gui/label.h \
|
||||||
src/gui/picture.h \
|
src/gui/picture.h \
|
||||||
src/gui/radio.h \
|
src/gui/radio.h \
|
||||||
|
src/gui/rect.h \
|
||||||
src/gui/task.h \
|
src/gui/task.h \
|
||||||
src/gui/textbox.h \
|
src/gui/textbox.h \
|
||||||
|
src/gui/timer.h \
|
||||||
src/thirdparty/stb_ds.h \
|
src/thirdparty/stb_ds.h \
|
||||||
src/thirdparty/stb_leakcheck.h \
|
src/thirdparty/stb_leakcheck.h \
|
||||||
src/thirdparty/stb_image.h \
|
src/thirdparty/stb_image.h \
|
||||||
|
@ -72,22 +74,23 @@ HEADERS = \
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
$$LINUX_SOURCES \
|
$$LINUX_SOURCES \
|
||||||
src/gui/array.c \
|
src/gui/array.c \
|
||||||
src/gui/button.c \
|
|
||||||
src/gui/checkbox.c \
|
|
||||||
src/gui/font.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/image.c \
|
||||||
src/gui/log.c \
|
src/gui/log.c \
|
||||||
src/gui/memory.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
|
src/main.c
|
||||||
|
|
||||||
LIBS = \
|
LIBS = \
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
static void buttonMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
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) {
|
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;
|
ButtonT *b = (ButtonT *)button;
|
||||||
|
|
||||||
b->base.magic = MAGIC_BUTTON;
|
|
||||||
b->base.x = x;
|
|
||||||
b->base.y = y;
|
|
||||||
b->base.delMethod = buttonDel;
|
b->base.delMethod = buttonDel;
|
||||||
b->base.paintMethod = buttonPaint;
|
b->base.paintMethod = buttonPaint;
|
||||||
b->base.mouseEventMethod = buttonMouseEvent;
|
b->base.mouseEventMethod = buttonMouseEvent;
|
||||||
b->title = NULL;
|
b->title = NULL;
|
||||||
|
|
||||||
buttonSetClickHandler(b, callback);
|
buttonSetClickHandler(b, callback);
|
||||||
buttonSetTitle(b, title);
|
|
||||||
|
|
||||||
// Width is set in buttonSetTitle
|
// 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;
|
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 *buttonNew(uint16_t x, uint16_t y, char *title, widgetCallback callback) {
|
||||||
ButtonT *button = (ButtonT *)malloc(sizeof(ButtonT));
|
ButtonT *button = (ButtonT *)malloc(sizeof(ButtonT));
|
||||||
WidgetT *widget = NULL;
|
WidgetT *widget = NULL;
|
||||||
|
uint16_t h = fontHeightGet(_guiFont) + (_guiMetric[METRIC_BUTTON_VERTICAL_PADDING] * 2) + (_guiMetric[METRIC_BUTTON_BEZEL_SIZE] * 2);
|
||||||
|
|
||||||
|
|
||||||
if (!button) return NULL;
|
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) {
|
if (!widget) {
|
||||||
free(button);
|
free(button);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
button = (ButtonT *)buttonInit((WidgetT *)button, x, y, title, callback);
|
button = (ButtonT *)buttonInit((WidgetT *)button, title, callback);
|
||||||
|
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void buttonPaint(WidgetT *widget) {
|
static void buttonPaint(WidgetT *widget, RectT pos) {
|
||||||
ButtonT *b = (ButtonT *)widget;
|
ButtonT *b;
|
||||||
int16_t i;
|
int16_t i;
|
||||||
int8_t active = GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE);
|
int8_t active;
|
||||||
ColorT highlight = active ? _guiColor[COLOR_BUTTON_SHADOW] : _guiColor[COLOR_BUTTON_HIGHLIGHT];
|
ColorT highlight;
|
||||||
ColorT shadow = active ? _guiColor[COLOR_BUTTON_HIGHLIGHT] : _guiColor[COLOR_BUTTON_SHADOW] ;
|
ColorT shadow;
|
||||||
|
|
||||||
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
|
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.
|
// Draw bezel.
|
||||||
for (i=0; i<_guiMetric[METRIC_BUTTON_BEZEL_SIZE]; i++) {
|
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).
|
// 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).
|
// 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);
|
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
@ -134,6 +136,6 @@ void buttonSetClickHandler(ButtonT *button, widgetCallback callback) {
|
||||||
void buttonSetTitle(ButtonT *button, char *title) {
|
void buttonSetTitle(ButtonT *button, char *title) {
|
||||||
if (button->title) free(button->title);
|
if (button->title) free(button->title);
|
||||||
button->title = strdup(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);
|
GUI_SET_FLAG((WidgetT *)button, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ typedef struct ButtonS {
|
||||||
|
|
||||||
|
|
||||||
void buttonDel(WidgetT **widget);
|
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);
|
ButtonT *buttonNew(uint16_t x, uint16_t y, char *title, widgetCallback callback);
|
||||||
void buttonSetClickHandler(ButtonT *button, widgetCallback callback);
|
void buttonSetClickHandler(ButtonT *button, widgetCallback callback);
|
||||||
void buttonSetTitle(ButtonT *button, char *title);
|
void buttonSetTitle(ButtonT *button, char *title);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
static void checkboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
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) {
|
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;
|
CheckboxT *c = (CheckboxT *)widget;
|
||||||
|
|
||||||
c->base.magic = MAGIC_CHECKBOX;
|
|
||||||
c->base.x = x;
|
|
||||||
c->base.y = y;
|
|
||||||
c->base.delMethod = checkboxDel;
|
c->base.delMethod = checkboxDel;
|
||||||
c->base.paintMethod = checkboxPaint;
|
c->base.paintMethod = checkboxPaint;
|
||||||
c->base.mouseEventMethod = checkboxMouseEvent;
|
c->base.mouseEventMethod = checkboxMouseEvent;
|
||||||
|
@ -53,9 +50,6 @@ WidgetT *checkboxInit(WidgetT *widget, uint16_t x, uint16_t y, char *title) {
|
||||||
|
|
||||||
checkboxSetTitle(c, title);
|
checkboxSetTitle(c, title);
|
||||||
|
|
||||||
// Width is set in checkboxSetTitle
|
|
||||||
c->base.h = fontHeightGet(_guiFont);
|
|
||||||
|
|
||||||
return widget;
|
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 *checkboxNew(uint16_t x, uint16_t y, char *title) {
|
||||||
CheckboxT *checkbox = (CheckboxT *)malloc(sizeof(CheckboxT));
|
CheckboxT *checkbox = (CheckboxT *)malloc(sizeof(CheckboxT));
|
||||||
WidgetT *widget = NULL;
|
WidgetT *widget = NULL;
|
||||||
|
uint16_t h = fontHeightGet(_guiFont);
|
||||||
|
|
||||||
if (!checkbox) return NULL;
|
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) {
|
if (!widget) {
|
||||||
free(checkbox);
|
free(checkbox);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkbox = (CheckboxT *)checkboxInit((WidgetT *)checkbox, x, y, title);
|
checkbox = (CheckboxT *)checkboxInit((WidgetT *)checkbox, title);
|
||||||
|
|
||||||
return checkbox;
|
return checkbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void checkboxPaint(WidgetT *widget) {
|
static void checkboxPaint(WidgetT *widget, RectT pos) {
|
||||||
CheckboxT *c = (CheckboxT *)widget;
|
CheckboxT *c = (CheckboxT *)widget;
|
||||||
int16_t o;
|
int16_t o;
|
||||||
int8_t active = checkboxGetValue(c);
|
int8_t active;
|
||||||
ColorT highlight = active ? _guiColor[COLOR_CHECKBOX_SHADOW] : _guiColor[COLOR_CHECKBOX_HIGHLIGHT];
|
ColorT highlight;
|
||||||
ColorT shadow = active ? _guiColor[COLOR_CHECKBOX_HIGHLIGHT] : _guiColor[COLOR_CHECKBOX_SHADOW];
|
ColorT shadow;
|
||||||
ColorT fill = active ? _guiColor[COLOR_CHECKBOX_ACTIVE] : _guiColor[COLOR_CHECKBOX_INACTIVE];
|
ColorT fill;
|
||||||
|
|
||||||
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
|
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.
|
// Checkbox is 10x10 pixels. Find offset based on font height.
|
||||||
o = (_guiFont->height - 10) * 0.5;
|
o = (_guiFont->height - 10) * 0.5;
|
||||||
|
|
||||||
// Draw outline of checkbox.
|
// 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.
|
// 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.
|
// 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);
|
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
@ -130,7 +129,7 @@ void checkboxSetClickHandler(CheckboxT *checkbox, widgetCallback callback) {
|
||||||
void checkboxSetTitle(CheckboxT *checkbox, char *title) {
|
void checkboxSetTitle(CheckboxT *checkbox, char *title) {
|
||||||
if (checkbox->title) free(checkbox->title);
|
if (checkbox->title) free(checkbox->title);
|
||||||
checkbox->title = strdup(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);
|
GUI_SET_FLAG((WidgetT *)checkbox, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ typedef struct CheckboxS {
|
||||||
|
|
||||||
void checkboxDel(WidgetT **widget);
|
void checkboxDel(WidgetT **widget);
|
||||||
uint8_t checkboxGetValue(CheckboxT *checkbox);
|
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);
|
CheckboxT *checkboxNew(uint16_t x, uint16_t y, char *title);
|
||||||
void checkboxSetClickHandler(CheckboxT *checkbox, widgetCallback callback);
|
void checkboxSetClickHandler(CheckboxT *checkbox, widgetCallback callback);
|
||||||
void checkboxSetTitle(CheckboxT *checkbox, char *title);
|
void checkboxSetTitle(CheckboxT *checkbox, char *title);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
|
|
||||||
static void desktopPaint(WidgetT *desktop);
|
static void desktopPaint(WidgetT *desktop, RectT pos);
|
||||||
|
|
||||||
|
|
||||||
void desktopDel(WidgetT **widget) {
|
void desktopDel(WidgetT **widget) {
|
||||||
|
@ -38,13 +38,11 @@ WidgetT *desktopInit(WidgetT *desktop) {
|
||||||
DesktopT *d = (DesktopT *)desktop;
|
DesktopT *d = (DesktopT *)desktop;
|
||||||
|
|
||||||
d->base.magic = MAGIC_DESKTOP;
|
d->base.magic = MAGIC_DESKTOP;
|
||||||
d->base.w = vbeDisplayWidthGet();
|
|
||||||
d->base.h = vbeDisplayHeightGet();
|
|
||||||
d->base.delMethod = desktopDel;
|
d->base.delMethod = desktopDel;
|
||||||
d->base.paintMethod = desktopPaint;
|
d->base.paintMethod = desktopPaint;
|
||||||
|
|
||||||
GUI_SET_FLAG(desktop, WIDGET_FLAG_OWNS_SURFACE);
|
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) {
|
if (!d->base.surface) {
|
||||||
free(d);
|
free(d);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -60,7 +58,7 @@ DesktopT *desktopNew(void) {
|
||||||
|
|
||||||
if (!desktop) return NULL;
|
if (!desktop) return NULL;
|
||||||
|
|
||||||
widget = widgetInit((WidgetT *)desktop);
|
widget = widgetInit(W(desktop), MAGIC_DESKTOP, 0, 0, vbeDisplayWidthGet(), vbeDisplayHeightGet(), 0, 0, 0, 0);
|
||||||
if (!widget) {
|
if (!widget) {
|
||||||
free(desktop);
|
free(desktop);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -72,11 +70,10 @@ DesktopT *desktopNew(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void desktopPaint(WidgetT *desktop) {
|
static void desktopPaint(WidgetT *desktop, RectT pos) {
|
||||||
DesktopT *d = (DesktopT *)desktop;
|
(void)pos;
|
||||||
|
|
||||||
if (GUI_GET_FLAG(desktop, WIDGET_FLAG_DIRTY)) {
|
if (GUI_GET_FLAG(desktop, WIDGET_FLAG_DIRTY)) {
|
||||||
vbeSurfaceSet(d->base.surface);
|
|
||||||
vbeSurfaceClear(_guiColor[COLOR_DESKTOP]);
|
vbeSurfaceClear(_guiColor[COLOR_DESKTOP]);
|
||||||
GUI_CLEAR_FLAG(desktop, WIDGET_FLAG_DIRTY);
|
GUI_CLEAR_FLAG(desktop, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
|
|
||||||
|
|
||||||
static void framePaint(WidgetT *widget);
|
static void framePaint(WidgetT *widget, RectT pos);
|
||||||
|
|
||||||
|
|
||||||
void frameDel(WidgetT **widget) {
|
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;
|
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.delMethod = frameDel;
|
||||||
f->base.paintMethod = framePaint;
|
f->base.paintMethod = framePaint;
|
||||||
f->title = NULL;
|
f->title = NULL;
|
||||||
|
|
||||||
f->base.marginX += 3;
|
|
||||||
f->base.marginY += 9;
|
|
||||||
|
|
||||||
frameSetTitle(f, title);
|
frameSetTitle(f, title);
|
||||||
|
|
||||||
return widget;
|
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;
|
if (!frame) return NULL;
|
||||||
|
|
||||||
widget = widgetInit((WidgetT *)frame);
|
widget = widgetInit(W(frame), MAGIC_FRAME, x, y, w, h, 4, 20, 4, 4);
|
||||||
if (!widget) {
|
if (!widget) {
|
||||||
free(frame);
|
free(frame);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame = (FrameT *)frameInit((WidgetT *)frame, x, y, w, h, title);
|
frame = (FrameT *)frameInit((WidgetT *)frame, title);
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void framePaint(WidgetT *widget) {
|
static void framePaint(WidgetT *widget, RectT pos) {
|
||||||
FrameT *f = (FrameT *)widget;
|
FrameT *f = (FrameT *)widget;
|
||||||
uint16_t o = _guiFont->height * 0.5;
|
|
||||||
|
|
||||||
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
|
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
|
||||||
vbeSurfaceSet(f->base.surface);
|
|
||||||
|
|
||||||
// Draw frame.
|
// 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.
|
// 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);
|
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ typedef struct FrameS {
|
||||||
|
|
||||||
|
|
||||||
void frameDel(WidgetT **widget);
|
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);
|
FrameT *frameNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title);
|
||||||
void frameSetTitle(FrameT *frame, char *title);
|
void frameSetTitle(FrameT *frame, char *title);
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,22 @@ static uint8_t _guiLastWidgetLeftEvent = MOUSE_EVENT_NONE;
|
||||||
static WidgetT *_guiFocused = NULL;
|
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 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);
|
static uint8_t guiProcessMouseChildren(WidgetT *widget, MouseT *mouse);
|
||||||
|
|
||||||
|
@ -62,27 +78,35 @@ void guiAttach(WidgetT *parent, WidgetT *child) {
|
||||||
child->window = (WindowT *)p;
|
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 this widget does not own a surface, find one for it to draw on.
|
||||||
if (!GUI_GET_FLAG(child, WIDGET_FLAG_OWNS_SURFACE)) {
|
if (!GUI_GET_FLAG(child, WIDGET_FLAG_OWNS_SURFACE)) {
|
||||||
p = child;
|
p = child;
|
||||||
while (p != NULL && !GUI_GET_FLAG(p, WIDGET_FLAG_OWNS_SURFACE)) {
|
while (p != NULL && !GUI_GET_FLAG(p, WIDGET_FLAG_OWNS_SURFACE)) {
|
||||||
// Check parent.
|
// Check parent.
|
||||||
p = p->parent;
|
p = p->parent;
|
||||||
if (p) {
|
|
||||||
// Calculate margins as we go.
|
|
||||||
child->marginX += p->marginX;
|
|
||||||
child->marginY += p->marginY;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
child->surface = p->surface;
|
child->surface = p->surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the specified location by the margin so the widget doesn't have to deal with margins.
|
// New windows should be active.
|
||||||
child->x += child->marginX;
|
|
||||||
child->y += child->marginY;
|
|
||||||
|
|
||||||
if (child->magic == MAGIC_WINDOW) {
|
if (child->magic == MAGIC_WINDOW) {
|
||||||
// New windows should be active.
|
|
||||||
windowSetActive((WindowT *)child);
|
windowSetActive((WindowT *)child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +124,7 @@ void guiComposite() {
|
||||||
|
|
||||||
// Render us?
|
// Render us?
|
||||||
if (GUI_GET_FLAG(widget, WIDGET_FLAG_OWNS_SURFACE)) {
|
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.
|
//***TODO*** This is wrong. Should be recursive.
|
||||||
|
@ -109,7 +133,7 @@ void guiComposite() {
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
for (x=0; x<len; x++) {
|
for (x=0; x<len; x++) {
|
||||||
if (GUI_GET_FLAG(widget->children[x], WIDGET_FLAG_OWNS_SURFACE)) {
|
if (GUI_GET_FLAG(widget->children[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) {
|
void guiMousePositionOnWidgetGet(WidgetT *widget, MouseT *mouse, uint16_t *x, uint16_t *y) {
|
||||||
guiWidgetPositionOnScreenGet(widget, x, y);
|
RectT r;
|
||||||
*x = mouse->x - *x;
|
guiWidgetPositionOnScreenGet(widget, &r);
|
||||||
*y = mouse->y - *y;
|
*x = mouse->x - r.x;
|
||||||
|
*y = mouse->y - r.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void guiPaint(WidgetT *widget) {
|
void guiPaint(WidgetT *widget) {
|
||||||
size_t len = arrlenu(widget->children);
|
size_t len = arrlenu(widget->children);
|
||||||
size_t x;
|
size_t x;
|
||||||
|
RectT pos;
|
||||||
|
|
||||||
// Paint us. Widget handles dirty flag so they can animate if needed.
|
// Paint us. Widget handles dirty flag so they can animate if needed.
|
||||||
if (widget->paintMethod) {
|
if (widget->paintMethod) {
|
||||||
widget->paintMethod(widget);
|
vbeSurfaceSet(widget->surface);
|
||||||
|
guiPaintBoundsGet(widget, &pos);
|
||||||
|
widget->paintMethod(widget, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paint all children.
|
// 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) {
|
void guiProcessMouse(MouseT *mouse) {
|
||||||
guiProcessMouseChildren(W(_guiDesktop), mouse);
|
guiProcessMouseChildren(W(_guiDesktop), mouse);
|
||||||
}
|
}
|
||||||
|
@ -280,6 +322,7 @@ void guiProcessMouse(MouseT *mouse) {
|
||||||
static uint8_t guiProcessMouseChildren(WidgetT *widget, MouseT *mouse) {
|
static uint8_t guiProcessMouseChildren(WidgetT *widget, MouseT *mouse) {
|
||||||
size_t len;
|
size_t len;
|
||||||
int16_t x;
|
int16_t x;
|
||||||
|
RectT r;
|
||||||
uint16_t mx;
|
uint16_t mx;
|
||||||
uint16_t my;
|
uint16_t my;
|
||||||
uint16_t sx;
|
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);
|
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.
|
// 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
|
// 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.
|
// 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?
|
// 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?
|
// Is this the same widget we were over before?
|
||||||
if (_guiLastWidgetLeft != widget) {
|
if (_guiLastWidgetLeft != widget) {
|
||||||
|
@ -492,15 +539,58 @@ void guiUserDataSet(WidgetT *widget, void *userData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void guiWidgetPositionOnScreenGet(WidgetT *widget, uint16_t *x, uint16_t *y) {
|
void guiWidgetBoundsDrawableOnScreenGet(WidgetT *widget, RectT *bounds) {
|
||||||
WidgetT *p = widget;
|
guiPaintBoundsGet(widget, bounds);
|
||||||
|
if (GUI_GET_FLAG(widget, WIDGET_FLAG_OWNS_SURFACE)) {
|
||||||
*x = 0;
|
bounds->x += widget->pos.x;
|
||||||
*y = 0;
|
bounds->y += widget->pos.y;
|
||||||
|
} else {
|
||||||
do {
|
bounds->x += widget->window->base.pos.x;
|
||||||
*x += p->x;
|
bounds->y += widget->window->base.pos.y;
|
||||||
*y += p->y;
|
}
|
||||||
p = p->parent;
|
bounds->x += widget->margin.x;
|
||||||
} while (p != NULL);
|
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; x<depth*2; x++) line[x] = '-';
|
||||||
|
line[x] = 0;
|
||||||
|
|
||||||
|
logWrite("%s %s P:%dx%d-%dx%d M:%dx%d-%dx%d C:%dx%d-%dx%d F:%d\n",
|
||||||
|
line,
|
||||||
|
_magicDebugNames[widget->magic],
|
||||||
|
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; x<len; x++) {
|
||||||
|
guiWidgetTreeDump(widget->children[x], depth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
#include "mouse.h"
|
#include "mouse.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
#include "rect.h"
|
||||||
|
|
||||||
|
|
||||||
#define GUI_GET_FLAG(w,f) (((w)->flags & (1 << (f))) != 0)
|
#define GUI_GET_FLAG(w,f) (((w)->flags & (1 << (f))) != 0)
|
||||||
|
@ -50,6 +51,7 @@ enum MagicE {
|
||||||
MAGIC_TEXTBOX,
|
MAGIC_TEXTBOX,
|
||||||
//MAGIC_UPDOWN,
|
//MAGIC_UPDOWN,
|
||||||
//MAGIC_LISTBOX,
|
//MAGIC_LISTBOX,
|
||||||
|
//MAGIC_TERMINAL,
|
||||||
MAGIC_COUNT
|
MAGIC_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -149,7 +151,9 @@ DesktopT *guiStartup(void);
|
||||||
void guiShutdown(void);
|
void guiShutdown(void);
|
||||||
void *guiUserDataGet(WidgetT *widget);
|
void *guiUserDataGet(WidgetT *widget);
|
||||||
void guiUserDataSet(WidgetT *widget, void *userData);
|
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
|
#endif // GUI_H
|
||||||
|
|
|
@ -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) {
|
ImageT *imageLoad(char *filename) {
|
||||||
uint16_t x;
|
uint16_t x;
|
||||||
uint16_t y;
|
uint16_t y;
|
||||||
|
|
|
@ -38,6 +38,7 @@ typedef struct ImageS {
|
||||||
ImageT *imageAllocate(uint16_t w, uint16_t h);
|
ImageT *imageAllocate(uint16_t w, uint16_t h);
|
||||||
ImageT *imageCreate(uint16_t w, uint16_t h, ColorT color);
|
ImageT *imageCreate(uint16_t w, uint16_t h, ColorT color);
|
||||||
uint16_t imageHeightGet(ImageT *image);
|
uint16_t imageHeightGet(ImageT *image);
|
||||||
|
uint8_t imageInfoGet(char *filename, uint16_t *width, uint16_t *height);
|
||||||
ImageT *imageLoad(char *filename);
|
ImageT *imageLoad(char *filename);
|
||||||
ColorT imagePixelGet(ImageT *image, uint16_t x, uint16_t y);
|
ColorT imagePixelGet(ImageT *image, uint16_t x, uint16_t y);
|
||||||
void imageRender(ImageT *image, uint16_t x, uint16_t y);
|
void imageRender(ImageT *image, uint16_t x, uint16_t y);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
static void labelMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
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) {
|
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;
|
LabelT *l = (LabelT *)widget;
|
||||||
|
|
||||||
l->base.magic = MAGIC_LABEL;
|
|
||||||
l->base.x = x;
|
|
||||||
l->base.y = y;
|
|
||||||
l->base.delMethod = labelDel;
|
l->base.delMethod = labelDel;
|
||||||
l->base.paintMethod = labelPaint;
|
l->base.paintMethod = labelPaint;
|
||||||
l->base.mouseEventMethod = labelMouseEvent;
|
l->base.mouseEventMethod = labelMouseEvent;
|
||||||
|
@ -50,9 +47,6 @@ WidgetT *labelInit(WidgetT *widget, uint16_t x, uint16_t y, char *title) {
|
||||||
|
|
||||||
labelSetTitle(l, title);
|
labelSetTitle(l, title);
|
||||||
|
|
||||||
// Width is set in labelSetTitle
|
|
||||||
l->base.h = fontHeightGet(_guiFont);
|
|
||||||
|
|
||||||
return widget;
|
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 *labelNew(uint16_t x, uint16_t y, char *title) {
|
||||||
LabelT *label = (LabelT *)malloc(sizeof(LabelT));
|
LabelT *label = (LabelT *)malloc(sizeof(LabelT));
|
||||||
WidgetT *widget = NULL;
|
WidgetT *widget = NULL;
|
||||||
|
uint16_t h = fontHeightGet(_guiFont);
|
||||||
|
|
||||||
if (!label) return NULL;
|
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) {
|
if (!widget) {
|
||||||
free(label);
|
free(label);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
label = (LabelT *)labelInit((WidgetT *)label, x, y, title);
|
label = (LabelT *)labelInit((WidgetT *)label, title);
|
||||||
|
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void labelPaint(WidgetT *widget) {
|
static void labelPaint(WidgetT *widget, RectT pos) {
|
||||||
LabelT *l = (LabelT *)widget;
|
LabelT *l = (LabelT *)widget;
|
||||||
ColorT text = GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE) ? l->active : l->foreground;
|
ColorT text = GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE) ? l->active : l->foreground;
|
||||||
|
|
||||||
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
|
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
|
||||||
vbeSurfaceSet(l->base.surface);
|
|
||||||
|
|
||||||
// Draw title.
|
// 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);
|
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
@ -143,6 +137,6 @@ void labelSetForegroundColor(LabelT *label, ColorT color) {
|
||||||
void labelSetTitle(LabelT *label, char *title) {
|
void labelSetTitle(LabelT *label, char *title) {
|
||||||
if (label->title) free(label->title);
|
if (label->title) free(label->title);
|
||||||
label->title = strdup(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);
|
GUI_SET_FLAG((WidgetT *)label, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ typedef struct LabelS {
|
||||||
|
|
||||||
|
|
||||||
void labelDel(WidgetT **widget);
|
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);
|
LabelT *labelNew(uint16_t x, uint16_t y, char *title);
|
||||||
void labelSetActiveColor(LabelT *label, ColorT color);
|
void labelSetActiveColor(LabelT *label, ColorT color);
|
||||||
void labelSetBackgroundColor(LabelT *label, ColorT color);
|
void labelSetBackgroundColor(LabelT *label, ColorT color);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
|
|
||||||
static void pictureMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
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) {
|
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;
|
PictureT *l = (PictureT *)widget;
|
||||||
|
|
||||||
l->base.magic = MAGIC_PICTURE;
|
|
||||||
l->base.x = x;
|
|
||||||
l->base.y = y;
|
|
||||||
l->base.delMethod = pictureDel;
|
l->base.delMethod = pictureDel;
|
||||||
l->base.paintMethod = picturePaint;
|
l->base.paintMethod = picturePaint;
|
||||||
l->base.mouseEventMethod = pictureMouseEvent;
|
l->base.mouseEventMethod = pictureMouseEvent;
|
||||||
|
@ -53,9 +50,6 @@ WidgetT *pictureInit(WidgetT *widget, uint16_t x, uint16_t y, char *filename) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
l->base.w = imageWidthGet(l->image);
|
|
||||||
l->base.h = imageHeightGet(l->image);
|
|
||||||
|
|
||||||
return widget;
|
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 *pictureNew(uint16_t x, uint16_t y, char *filename) {
|
||||||
PictureT *picture = (PictureT *)malloc(sizeof(PictureT));
|
PictureT *picture = (PictureT *)malloc(sizeof(PictureT));
|
||||||
WidgetT *widget = NULL;
|
WidgetT *widget = NULL;
|
||||||
|
uint16_t w;
|
||||||
|
uint16_t h;
|
||||||
|
|
||||||
if (!picture) return NULL;
|
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) {
|
if (!widget) {
|
||||||
free(picture);
|
free(picture);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
picture = (PictureT *)pictureInit((WidgetT *)picture, x, y, filename);
|
picture = (PictureT *)pictureInit((WidgetT *)picture, filename);
|
||||||
if (!picture) {
|
if (!picture) {
|
||||||
free(picture);
|
free(picture);
|
||||||
return NULL;
|
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;
|
PictureT *p = (PictureT *)widget;
|
||||||
|
|
||||||
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
|
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
|
||||||
vbeSurfaceSet(p->base.surface);
|
imageRender(p->image, pos.x, pos.y);
|
||||||
|
|
||||||
imageRender(p->image, p->base.x, p->base.y);
|
|
||||||
|
|
||||||
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ typedef struct PictureS {
|
||||||
|
|
||||||
|
|
||||||
void pictureDel(WidgetT **widget);
|
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);
|
PictureT *pictureNew(uint16_t x, uint16_t y, char *filename);
|
||||||
void pictureSetClickHandler(PictureT *picture, widgetCallback callback);
|
void pictureSetClickHandler(PictureT *picture, widgetCallback callback);
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
static void radioClearSelectedInGroup(WidgetT *widget, uint32_t group);
|
static void radioClearSelectedInGroup(WidgetT *widget, uint32_t group);
|
||||||
static RadioT *radioFindSelectedInGroup(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 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) {
|
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;
|
RadioT *r = (RadioT *)widget;
|
||||||
|
|
||||||
r->base.magic = MAGIC_RADIOBUTTON;
|
|
||||||
r->base.x = x;
|
|
||||||
r->base.y = y;
|
|
||||||
r->base.delMethod = radioDel;
|
r->base.delMethod = radioDel;
|
||||||
r->base.paintMethod = radioPaint;
|
r->base.paintMethod = radioPaint;
|
||||||
r->base.mouseEventMethod = radioMouseEvent;
|
r->base.mouseEventMethod = radioMouseEvent;
|
||||||
|
@ -107,7 +104,7 @@ WidgetT *radioInit(WidgetT *widget, uint16_t x, uint16_t y, char *title, uint16_
|
||||||
radioSetTitle(r, title);
|
radioSetTitle(r, title);
|
||||||
|
|
||||||
// Width is set in radioSetTitle
|
// Width is set in radioSetTitle
|
||||||
r->base.h = fontHeightGet(_guiFont);
|
r->base.pos.h = fontHeightGet(_guiFont);
|
||||||
|
|
||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
|
@ -135,47 +132,51 @@ RadioT *radioNew(uint16_t x, uint16_t y, char *title, uint16_t group) {
|
||||||
|
|
||||||
if (!radio) return NULL;
|
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) {
|
if (!widget) {
|
||||||
free(radio);
|
free(radio);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
radio = (RadioT *)radioInit((WidgetT *)radio, x, y, title, group);
|
radio = (RadioT *)radioInit((WidgetT *)radio, title, group);
|
||||||
|
|
||||||
return radio;
|
return radio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void radioPaint(WidgetT *widget) {
|
static void radioPaint(WidgetT *widget, RectT pos) {
|
||||||
RadioT *r = (RadioT *)widget;
|
RadioT *r = (RadioT *)widget;
|
||||||
int16_t i;
|
int16_t i;
|
||||||
int16_t o;
|
int16_t o;
|
||||||
uint8_t active = (radioGetSelected(r) == r);
|
uint8_t active;
|
||||||
ColorT highlight = active ? _guiColor[COLOR_RADIOBUTTON_SHADOW] : _guiColor[COLOR_RADIOBUTTON_HIGHLIGHT];
|
ColorT highlight;
|
||||||
ColorT shadow = active ? _guiColor[COLOR_RADIOBUTTON_HIGHLIGHT] : _guiColor[COLOR_RADIOBUTTON_SHADOW];
|
ColorT shadow;
|
||||||
ColorT fill = active ? _guiColor[COLOR_RADIOBUTTON_ACTIVE] : _guiColor[COLOR_RADIOBUTTON_INACTIVE];
|
ColorT fill;
|
||||||
|
|
||||||
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
|
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.
|
// Radio button is 10x10 pixels. Find offset based on font height.
|
||||||
o = (_guiFont->height - 10) * 0.5;
|
o = (_guiFont->height - 10) * 0.5;
|
||||||
|
|
||||||
// Draw outline of radio button.
|
// Draw outline of radio button.
|
||||||
guiDrawLine(r->base.x, r->base.y + o + 5, r->base.x + 5, r->base.y + o, highlight);
|
guiDrawLine(pos.x, pos.y + o + 5, pos.x + 5, pos.y + o, highlight);
|
||||||
guiDrawLine(r->base.x + 5, r->base.y + o, r->base.x + 10, r->base.y + o + 5, highlight);
|
guiDrawLine(pos.x + 5, pos.y + o, pos.x + 10, pos.y + o + 5, highlight);
|
||||||
guiDrawLine(r->base.x, r->base.y + o + 5, r->base.x + 5, r->base.y + o + 10, shadow);
|
guiDrawLine(pos.x, pos.y + o + 5, pos.x + 5, pos.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 + 5, pos.y + o + 10, pos.x + 10, pos.y + o + 5, shadow);
|
||||||
|
|
||||||
// Fill radio button.
|
// Fill radio button.
|
||||||
for (i=0; i<4; i++) {
|
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(pos.x + 5 - i, pos.y + o + i + 1, pos.x + 5 + i, pos.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 + 8, pos.x + 5 + i, pos.y + o - i + 8, fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw title.
|
// 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);
|
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
@ -202,6 +203,6 @@ void radioSetSelected(RadioT *radio) {
|
||||||
void radioSetTitle(RadioT *radio, char *title) {
|
void radioSetTitle(RadioT *radio, char *title) {
|
||||||
if (radio->title) free(radio->title);
|
if (radio->title) free(radio->title);
|
||||||
radio->title = strdup(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);
|
GUI_SET_FLAG((WidgetT *)radio, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ typedef struct RadioS {
|
||||||
|
|
||||||
void radioDel(WidgetT **widget);
|
void radioDel(WidgetT **widget);
|
||||||
RadioT *radioGetSelected(RadioT *radio);
|
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);
|
RadioT *radioNew(uint16_t x, uint16_t y, char *title, uint16_t group);
|
||||||
void radioSetClickHandler(RadioT *radio, widgetCallback callback);
|
void radioSetClickHandler(RadioT *radio, widgetCallback callback);
|
||||||
void radioSetSelected(RadioT *radio);
|
void radioSetSelected(RadioT *radio);
|
||||||
|
|
36
client/src/gui/rect.h
Normal file
36
client/src/gui/rect.h
Normal file
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
|
@ -24,7 +24,7 @@
|
||||||
static void textboxFocusEvent(WidgetT *widget, uint8_t focused);
|
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 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 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) {
|
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;
|
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.delMethod = textboxDel;
|
||||||
t->base.focusMethod = textboxFocusEvent;
|
t->base.focusMethod = textboxFocusEvent;
|
||||||
t->base.keyboardEventMethod = textboxKeyboardEvent;
|
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 *textboxNew(uint16_t x, uint16_t y, uint16_t w, char *title) {
|
||||||
TextboxT *textbox = (TextboxT *)malloc(sizeof(TextboxT));
|
TextboxT *textbox = (TextboxT *)malloc(sizeof(TextboxT));
|
||||||
WidgetT *widget = NULL;
|
WidgetT *widget = NULL;
|
||||||
|
uint16_t h = fontHeightGet(_guiFont) + 4 + (_guiMetric[METRIC_TEXTBOX_VERTICAL_PADDING] * 2);
|
||||||
|
|
||||||
if (!textbox) return NULL;
|
if (!textbox) return NULL;
|
||||||
|
|
||||||
widget = widgetInit((WidgetT *)textbox);
|
widget = widgetInit(W(textbox), MAGIC_TEXTBOX, x, y, w, h, 0, 0, 0, 0);
|
||||||
if (!widget) {
|
if (!widget) {
|
||||||
free(textbox);
|
free(textbox);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textbox = (TextboxT *)textboxInit((WidgetT *)textbox, title);
|
||||||
if (!textbox) return NULL;
|
|
||||||
|
|
||||||
widget = widgetInit((WidgetT *)textbox);
|
|
||||||
if (!widget) {
|
|
||||||
free(textbox);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
textbox = (TextboxT *)textboxInit((WidgetT *)textbox, x, y, w, title);
|
|
||||||
|
|
||||||
return textbox;
|
return textbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void textboxPaint(WidgetT *widget) {
|
static void textboxPaint(WidgetT *widget, RectT pos) {
|
||||||
TextboxT *t = (TextboxT *)widget;
|
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;
|
char *draw = NULL;
|
||||||
|
uint16_t labelWidth;
|
||||||
|
uint16_t valueWidth;
|
||||||
|
|
||||||
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
|
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.
|
// 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.
|
// 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]);
|
guiDrawHighlightFrame( pos.x + labelWidth, pos.y, pos.x + labelWidth + valueWidth + 2, pos.y + pos.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]);
|
guiDrawRectangle( pos.x + labelWidth + 1, pos.y + 1, pos.x + labelWidth + valueWidth + 1, pos.y + pos.h - 1, _guiColor[COLOR_WINDOW_BACKGROUND]);
|
||||||
|
|
||||||
// Draw 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 value. ***TODO*** This needs much more!
|
||||||
draw = strdup(t->value);
|
draw = strdup(t->value);
|
||||||
if (strlen(t->value) > t->visible) draw[t->visible] = 0;
|
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);
|
free(draw);
|
||||||
|
|
||||||
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
|
@ -172,7 +160,7 @@ void textboxSetTitle(TextboxT *textbox, char *title) {
|
||||||
textbox->title = strdup(title);
|
textbox->title = strdup(title);
|
||||||
|
|
||||||
// Figure out how many characters we have room to display.
|
// 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);
|
GUI_SET_FLAG((WidgetT *)textbox, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ typedef struct TextboxS {
|
||||||
|
|
||||||
void textboxDel(WidgetT **widget);
|
void textboxDel(WidgetT **widget);
|
||||||
char *textboxGetValue(TextboxT *textbox);
|
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);
|
TextboxT *textboxNew(uint16_t x, uint16_t y, uint16_t w, char *title);
|
||||||
void textboxSetValue(TextboxT *textbox, char *value);
|
void textboxSetValue(TextboxT *textbox, char *value);
|
||||||
void textboxSetMaxLength(TextboxT *textbox, uint16_t length);
|
void textboxSetMaxLength(TextboxT *textbox, uint16_t length);
|
||||||
|
|
36
client/src/gui/timer.c
Normal file
36
client/src/gui/timer.c
Normal file
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
|
||||||
|
void timerShutdown(void) {
|
||||||
|
// Nothing yet.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void timerStartup(void) {
|
||||||
|
// Nothing yet.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void timerUpdate(void) {
|
||||||
|
|
||||||
|
}
|
30
client/src/gui/timer.h
Normal file
30
client/src/gui/timer.h
Normal file
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TIMER_H
|
||||||
|
#define TIMER_H
|
||||||
|
|
||||||
|
|
||||||
|
void timerShutdown(void);
|
||||||
|
void timerStartup(void);
|
||||||
|
void timerUpdate(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TIMER_H
|
|
@ -19,30 +19,33 @@
|
||||||
|
|
||||||
|
|
||||||
#include "widget.h"
|
#include "widget.h"
|
||||||
|
#include "window.h"
|
||||||
|
|
||||||
|
|
||||||
uint16_t widgetGetHeight(WidgetT *widget) {
|
uint16_t widgetHeightGet(WidgetT *widget) {
|
||||||
return widget->h;
|
return widget->pos.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t widgetGetWidth(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) {
|
||||||
return widget->w;
|
widget->magic = magic;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
WidgetT *widgetInit(WidgetT *widget) {
|
|
||||||
widget->magic = MAGIC_UNKNOWN;
|
|
||||||
widget->flags = 0;
|
widget->flags = 0;
|
||||||
widget->x = 0;
|
widget->pos.x = x;
|
||||||
widget->y = 0;
|
widget->pos.y = y;
|
||||||
widget->w = 0;
|
widget->pos.w = w;
|
||||||
widget->h = 0;
|
widget->pos.h = h;
|
||||||
widget->marginX = 0;
|
widget->margin.x = marginX;
|
||||||
widget->marginY = 0;
|
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->surface = NULL;
|
||||||
widget->children = NULL;
|
widget->children = NULL;
|
||||||
widget->parent = NULL;
|
widget->parent = NULL;
|
||||||
|
widget->window = NULL;
|
||||||
widget->delMethod = NULL;
|
widget->delMethod = NULL;
|
||||||
widget->focusMethod = NULL;
|
widget->focusMethod = NULL;
|
||||||
widget->keyboardEventMethod = 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));
|
WidgetT *widget = (WidgetT *)malloc(sizeof(WidgetT));
|
||||||
|
|
||||||
if (!widget) return NULL;
|
if (!widget) return NULL;
|
||||||
|
|
||||||
widget = widgetInit(widget);
|
widget = widgetInit(widget, magic, x, y, w, h, marginX, marginY, marginX2, marginY2);
|
||||||
|
|
||||||
return widget;
|
return widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t widgetWidthGet(WidgetT *widget) {
|
||||||
|
return widget->pos.w;
|
||||||
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ typedef void (*widgetCallback)(struct WidgetS *widget);
|
||||||
typedef void (*widgetDelMethod)(struct WidgetS **widget);
|
typedef void (*widgetDelMethod)(struct WidgetS **widget);
|
||||||
typedef void (*widgetFocusMethod)(struct WidgetS *widget, uint8_t focused);
|
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 (*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);
|
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
|
uint8_t flags; // See above enum
|
||||||
SurfaceT *surface; // Pointer to compositable surface or NULL
|
SurfaceT *surface; // Pointer to compositable surface or NULL
|
||||||
WindowT *window; // The window holding this widget or NULL
|
WindowT *window; // The window holding this widget or NULL
|
||||||
int16_t x; // Position of widget on parent
|
RectT pos; // Position of widget on parent
|
||||||
int16_t y; // Position of widget on parent
|
RectT margin; // Pixels to skip over on each edge when rendering children
|
||||||
uint16_t w; // Width of widget
|
RectT clip; // Calculated clipping region on surface
|
||||||
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
|
|
||||||
WidgetT **children; // List of children
|
WidgetT **children; // List of children
|
||||||
WidgetT *parent; // Parent of this widget
|
WidgetT *parent; // Parent of this widget
|
||||||
widgetDelMethod delMethod; // Delete method
|
widgetDelMethod delMethod; // Delete method
|
||||||
|
@ -67,10 +64,10 @@ typedef struct WidgetS {
|
||||||
} WidgetT;
|
} WidgetT;
|
||||||
|
|
||||||
|
|
||||||
uint16_t widgetGetHeight(WidgetT *widget);
|
uint16_t widgetHeightGet(WidgetT *widget);
|
||||||
uint16_t widgetGetWidth(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 *widgetInit(WidgetT *widget);
|
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 *widgetNew(void);
|
uint16_t widgetWidthGet(WidgetT *widget);
|
||||||
|
|
||||||
|
|
||||||
#endif // WIDGET_H
|
#endif // WIDGET_H
|
||||||
|
|
|
@ -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;
|
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.delMethod = windowDel;
|
||||||
win->base.paintMethod = windowPaint;
|
win->base.paintMethod = windowPaint;
|
||||||
win->base.mouseEventMethod = windowMouseEvent;
|
win->base.mouseEventMethod = windowMouseEvent;
|
||||||
win->flags = 0;
|
win->flags = 0;
|
||||||
win->title = NULL;
|
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);
|
windowSetTitle(win, title);
|
||||||
|
|
||||||
GUI_SET_FLAG(window, WIDGET_FLAG_OWNS_SURFACE);
|
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) {
|
if (!win->base.surface) {
|
||||||
free(win->title);
|
free(win->title);
|
||||||
free(win);
|
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]) {
|
if (y < _guiMetric[METRIC_WINDOW_TITLE_GRAB_HEIGHT]) {
|
||||||
// Start dragging.
|
// Start dragging.
|
||||||
_guiDragWidget = widget;
|
_guiDragWidget = widget;
|
||||||
_guiDragOffsetX = mouse->x - window->base.x;
|
_guiDragOffsetX = mouse->x - window->base.pos.x;
|
||||||
_guiDragOffsetY = mouse->y - window->base.y;
|
_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.
|
// 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)) {
|
if (_guiDragWidget == widget && mouse->buttonLeft && GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE)) {
|
||||||
// Move window.
|
// Move window.
|
||||||
window->base.x = mouse->x - _guiDragOffsetX;
|
window->base.pos.x = mouse->x - _guiDragOffsetX;
|
||||||
window->base.y = mouse->y - _guiDragOffsetY;
|
window->base.pos.y = mouse->y - _guiDragOffsetY;
|
||||||
// Keep it on the screen.
|
// Keep it on the screen.
|
||||||
if (window->base.x < 0) window->base.x = 0;
|
if (window->base.pos.x < 0) window->base.pos.x = 0;
|
||||||
if (window->base.x + window->base.w > vbeDisplayWidthGet()) window->base.x = vbeDisplayWidthGet() - window->base.w;
|
if (window->base.pos.x + window->base.pos.w > vbeDisplayWidthGet()) window->base.pos.x = vbeDisplayWidthGet() - window->base.pos.w;
|
||||||
if (window->base.y < 0) window->base.y = 0;
|
if (window->base.pos.y < 0) window->base.pos.y = 0;
|
||||||
if (window->base.y + window->base.h > vbeDisplayHeightGet()) window->base.y = vbeDisplayHeightGet() - window->base.h;
|
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.
|
// 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;
|
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) {
|
if (!widget) {
|
||||||
free(window);
|
free(window);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
window = (WindowT *)windowInit((WidgetT *)window, x, y, w, h, title);
|
window = (WindowT *)windowInit((WidgetT *)window, title);
|
||||||
|
|
||||||
return window;
|
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) {
|
static void windowPaint(WidgetT *widget) {
|
||||||
WindowT *w = (WindowT *)widget;
|
WindowT *w = (WindowT *)widget;
|
||||||
uint16_t x2 = w->base.w - 1;
|
uint16_t x2 = w->base.pos.w - 1;
|
||||||
uint16_t y2 = w->base.h - 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 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];
|
ColorT text = GUI_GET_FLAG(widget, WIDGET_FLAG_ACTIVE) ? _guiColor[COLOR_WINDOW_TITLE_TEXT_ACTIVE] : _guiColor[COLOR_WINDOW_TITLE_TEXT_INACTIVE];
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ typedef struct WindowS {
|
||||||
|
|
||||||
|
|
||||||
void windowDel(WidgetT **widget);
|
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);
|
WindowT *windowNew(uint16_t x, uint16_t y, uint16_t w, uint16_t h, char *title);
|
||||||
void windowSetActive(WindowT *window);
|
void windowSetActive(WindowT *window);
|
||||||
void windowSetTitle(WindowT *window, char *title);
|
void windowSetTitle(WindowT *window, char *title);
|
||||||
|
|
|
@ -259,7 +259,7 @@ uint8_t vbeStartup(uint16_t xRes, uint16_t yRes, uint8_t bpp) {
|
||||||
|
|
||||||
(void)bpp;
|
(void)bpp;
|
||||||
|
|
||||||
_windowScale = 2;
|
_windowScale = 3;
|
||||||
vbePutPixel = vbePutPixel32;
|
vbePutPixel = vbePutPixel32;
|
||||||
|
|
||||||
SDL_Init(SDL_INIT_EVERYTHING);
|
SDL_Init(SDL_INIT_EVERYTHING);
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
* - More widget states: Ghosted, hidden
|
* - More widget states: Ghosted, hidden
|
||||||
* - Move setup math for paint events inside the dirty check
|
* - 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
|
* - 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 "task.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
#include "widget.h"
|
#include "widget.h"
|
||||||
|
@ -56,10 +58,67 @@ void buttonClick(WidgetT *widget) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test(void *data) {
|
|
||||||
MouseT *mouse = NULL;
|
void drawWidgetDebug(WidgetT *widget, uint8_t debugToggle) {
|
||||||
ImageT *pointer = NULL;
|
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; i<len; i++) {
|
||||||
|
drawWidgetDebug(widget->children[i], debugToggle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mainLoop(void *data) {
|
||||||
|
MouseT *mouse = NULL;
|
||||||
|
ImageT *pointer = NULL;
|
||||||
ColorT alpha;
|
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();
|
DesktopT *desktop = (DesktopT *)guiRootGet();
|
||||||
WindowT *w1 = NULL;
|
WindowT *w1 = NULL;
|
||||||
WindowT *w2 = NULL;
|
WindowT *w2 = NULL;
|
||||||
|
@ -76,13 +135,9 @@ void test(void *data) {
|
||||||
PictureT *p1 = NULL;
|
PictureT *p1 = NULL;
|
||||||
FrameT *f1 = NULL;
|
FrameT *f1 = NULL;
|
||||||
TextboxT *t1 = NULL;
|
TextboxT *t1 = NULL;
|
||||||
int8_t key = 0;
|
|
||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
|
|
||||||
pointer = imageLoad("mouse.png");
|
|
||||||
alpha = imagePixelGet(pointer, 5, 0);
|
|
||||||
|
|
||||||
// Windows
|
// Windows
|
||||||
w1 = windowNew(25, 25, 300, 200, "Window 1");
|
w1 = windowNew(25, 25, 300, 200, "Window 1");
|
||||||
guiAttach(W(desktop), W(w1));
|
guiAttach(W(desktop), W(w1));
|
||||||
|
@ -98,15 +153,15 @@ void test(void *data) {
|
||||||
// Window 2
|
// Window 2
|
||||||
r1a = radioNew(10, 10, "Radio 1a", 1);
|
r1a = radioNew(10, 10, "Radio 1a", 1);
|
||||||
guiAttach(W(w2), W(r1a));
|
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));
|
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));
|
guiAttach(W(w2), W(r3a));
|
||||||
r1b = radioNew(10, 35, "Radio 1b", 2);
|
r1b = radioNew(10, 35, "Radio 1b", 2);
|
||||||
guiAttach(W(w2), W(r1b));
|
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));
|
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));
|
guiAttach(W(w2), W(r3b));
|
||||||
radioSetSelected(r1a);
|
radioSetSelected(r1a);
|
||||||
radioSetSelected(r2b);
|
radioSetSelected(r2b);
|
||||||
|
@ -117,29 +172,12 @@ void test(void *data) {
|
||||||
// Window 3
|
// Window 3
|
||||||
f1 = frameNew(10, 5, 175, 125, "Test Frame");
|
f1 = frameNew(10, 5, 175, 125, "Test Frame");
|
||||||
guiAttach(W(w3), W(f1));
|
guiAttach(W(w3), W(f1));
|
||||||
b1 = buttonNew(10, 10, "Test Button", buttonClick);
|
b1 = buttonNew(0, 0, "Test Button", buttonClick);
|
||||||
guiAttach(W(f1), W(b1));
|
guiAttach(W(f1), W(b1));
|
||||||
l1 = labelNew(10, 40, "Test Label");
|
l1 = labelNew(10, 40, "Test Label");
|
||||||
guiAttach(W(f1), W(l1));
|
guiAttach(W(f1), W(l1));
|
||||||
c1 = checkboxNew(10, 65, "Test Checkbox");
|
c1 = checkboxNew(10, 65, "Test Checkbox");
|
||||||
guiAttach(W(f1), W(c1));
|
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();
|
mouseStartup();
|
||||||
|
timerStartup();
|
||||||
guiStartup();
|
guiStartup();
|
||||||
taskStartup(64);
|
taskStartup(64);
|
||||||
|
|
||||||
taskCreate(test, NULL);
|
taskCreate(test, NULL);
|
||||||
|
taskCreate(mainLoop, NULL);
|
||||||
taskRun();
|
taskRun();
|
||||||
|
|
||||||
taskShutdown();
|
taskShutdown();
|
||||||
guiShutdown();
|
guiShutdown();
|
||||||
|
timerShutdown();
|
||||||
mouseShutdown();
|
mouseShutdown();
|
||||||
vbeShutdown();
|
vbeShutdown();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue