Basic click handling for widgets implemented.
This commit is contained in:
parent
018ccedd46
commit
34dd7d7fbe
7 changed files with 124 additions and 18 deletions
|
@ -101,6 +101,7 @@ void fontRender(char *string, uint16_t x, uint16_t y) {
|
||||||
for (c=0; c<strlen(string); c++) {
|
for (c=0; c<strlen(string); c++) {
|
||||||
character = string[c];
|
character = string[c];
|
||||||
|
|
||||||
|
// Don't forget to update fontWidthCharactersGet.
|
||||||
if (_allowMods) {
|
if (_allowMods) {
|
||||||
// Change _foreground to GUI Color Index.
|
// Change _foreground to GUI Color Index.
|
||||||
if (character == 1) {
|
if (character == 1) {
|
||||||
|
@ -197,6 +198,38 @@ void fontUnload(FontT **font) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t fontWidthCharactersGet(char *string) {
|
||||||
|
uint8_t character;
|
||||||
|
uint8_t c;
|
||||||
|
uint16_t count = 0;
|
||||||
|
|
||||||
|
// This duplicates a lot of code from fontRender but it keeps the render loop from being ugly.
|
||||||
|
|
||||||
|
for (c=0; c<strlen(string); c++) {
|
||||||
|
character = string[c];
|
||||||
|
|
||||||
|
if (_allowMods) {
|
||||||
|
// Change _foreground to GUI Color Index.
|
||||||
|
if (character == 1) {
|
||||||
|
character = string[++c];
|
||||||
|
if (character == 16) character = 0; // Because we can't pass NULL in a string, 16 is used for black.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Change _background to GUI Color Index.
|
||||||
|
if (character == 2) {
|
||||||
|
character = string[++c];
|
||||||
|
if (character == 16) character = 0; // Because we can't pass NULL in a string, 16 is used for black.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t fontWidthGet(FontT *font) {
|
uint16_t fontWidthGet(FontT *font) {
|
||||||
return font->width;
|
return font->width;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ void fontModsEnabledSet(uint8_t enabled);
|
||||||
void fontRender(char *string, uint16_t x, uint16_t y);
|
void fontRender(char *string, uint16_t x, uint16_t y);
|
||||||
void fontSet(FontT *font);
|
void fontSet(FontT *font);
|
||||||
void fontUnload(FontT **font);
|
void fontUnload(FontT **font);
|
||||||
|
uint16_t fontWidthCharactersGet(char *string);
|
||||||
uint16_t fontWidthGet(FontT *font);
|
uint16_t fontWidthGet(FontT *font);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ struct WidgetS;
|
||||||
|
|
||||||
typedef void (*GuiCallbackT)(void *data, ...);
|
typedef void (*GuiCallbackT)(void *data, ...);
|
||||||
typedef void (*WidgetEventT)(struct WidgetS *widget, ...);
|
typedef void (*WidgetEventT)(struct WidgetS *widget, ...);
|
||||||
|
typedef void (*ClickHandlerT)(struct WidgetS *widget, uint16_t x, uint16_t y, void *data);
|
||||||
|
|
||||||
typedef struct PointS {
|
typedef struct PointS {
|
||||||
int16_t x;
|
int16_t x;
|
||||||
|
@ -31,16 +32,16 @@ typedef struct RectS {
|
||||||
} RectT;
|
} RectT;
|
||||||
|
|
||||||
typedef struct RegisterS {
|
typedef struct RegisterS {
|
||||||
char *widgetName; // Text name of widget.
|
char *widgetName; // Text name of widget.
|
||||||
WidgetEventT click; // Click handler.
|
ClickHandlerT click; // Click handler.
|
||||||
WidgetEventT destroy; // Destroy routine.
|
WidgetEventT destroy; // Destroy routine.
|
||||||
WidgetEventT paint; // Paint routine.
|
WidgetEventT paint; // Paint routine.
|
||||||
GuiCallbackT unregister; // Unregister routine.
|
GuiCallbackT unregister; // Unregister routine.
|
||||||
} RegisterT;
|
} RegisterT;
|
||||||
|
|
||||||
typedef struct WidgetS {
|
typedef struct WidgetS {
|
||||||
uint8_t magic; // Magic ID of widget.
|
uint8_t magic; // Magic ID of widget.
|
||||||
RectT r; // Outer bounds, except for windows.
|
RectT r; // Outer bounds of widget. NOTE: USES WIDTH/HEIGHT, NOT X2/Y2!
|
||||||
RegisterT *reg; // Registration information.
|
RegisterT *reg; // Registration information.
|
||||||
void *data; // Pointer to arbitrary data for user.
|
void *data; // Pointer to arbitrary data for user.
|
||||||
uint8_t dirty; // Is the widget dirty?
|
uint8_t dirty; // Is the widget dirty?
|
||||||
|
|
|
@ -8,7 +8,7 @@ static void labelDestroy(struct WidgetS *widget, ...);
|
||||||
static void labelPaint(struct WidgetS *widget, ...);
|
static void labelPaint(struct WidgetS *widget, ...);
|
||||||
|
|
||||||
|
|
||||||
void labelClickSet(LabelT *label, WidgetEventT handler, void *data) {
|
void labelClickSet(LabelT *label, ClickHandlerT handler, void *data) {
|
||||||
label->base.reg->click = handler;
|
label->base.reg->click = handler;
|
||||||
label->base.data = data;
|
label->base.data = data;
|
||||||
}
|
}
|
||||||
|
@ -21,19 +21,39 @@ void labelColorSet(LabelT *label, ColorT foreground, ColorT background) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LabelT *labelCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, FontT *font, char *contents, ...) {
|
LabelT *labelCreate(uint16_t x, uint16_t y, uint8_t alignment, FontT *font, char *contents, ...) {
|
||||||
LabelT *l = NULL;
|
LabelT *l = NULL;
|
||||||
|
uint16_t width;
|
||||||
// ***TODO*** Auto-calculate width/height.
|
uint16_t height;
|
||||||
|
|
||||||
NEW(LabelT, l);
|
NEW(LabelT, l);
|
||||||
memset(l, 0, sizeof(LabelT));
|
memset(l, 0, sizeof(LabelT));
|
||||||
guiWidgetBaseSet((WidgetT *)l, __MAGIC_LABEL, x, y, w, h);
|
|
||||||
l->font = font;
|
l->font = font;
|
||||||
l->text = strdup(contents);
|
l->text = strdup(contents);
|
||||||
l->foreground = GUI_BLACK;
|
l->foreground = GUI_BLACK;
|
||||||
l->background = GUI_LIGHTGRAY;
|
l->background = GUI_LIGHTGRAY;
|
||||||
l->modsEnabled = 0;
|
l->modsEnabled = 0;
|
||||||
|
l->alignment = alignment;
|
||||||
|
l->pos.x = x;
|
||||||
|
l->pos.y = y;
|
||||||
|
|
||||||
|
width = fontWidthCharactersGet(contents) * fontWidthGet(font);
|
||||||
|
height = fontHeightGet(font);
|
||||||
|
switch (alignment) {
|
||||||
|
case LABEL_ALIGN_LEFT:
|
||||||
|
// Passed in values are fine.
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LABEL_ALIGN_CENTER:
|
||||||
|
x -= width * 0.5;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LABEL_ALIGN_RIGHT:
|
||||||
|
x -= width;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
guiWidgetBaseSet((WidgetT *)l, __MAGIC_LABEL, x, y, width, height);
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +75,7 @@ static void labelPaint(struct WidgetS *widget, ...) {
|
||||||
fontSet(l->font);
|
fontSet(l->font);
|
||||||
fontColorSet(l->foreground, l->background);
|
fontColorSet(l->foreground, l->background);
|
||||||
fontModsEnabledSet(l->modsEnabled);
|
fontModsEnabledSet(l->modsEnabled);
|
||||||
// ***TODO*** Alignment, clipping, etc.
|
// ***TODO*** Clipping.
|
||||||
fontRender(l->text, l->base.r.x, l->base.r.y);
|
fontRender(l->text, l->base.r.x, l->base.r.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,16 @@
|
||||||
#include "../gui.h"
|
#include "../gui.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define LABEL_ALIGN_LEFT 0
|
||||||
|
#define LABEL_ALIGN_RIGHT 1
|
||||||
|
#define LABEL_ALIGN_CENTER 2
|
||||||
|
|
||||||
|
|
||||||
typedef struct LabelS {
|
typedef struct LabelS {
|
||||||
WidgetT base; // Required by all widgets.
|
WidgetT base; // Required by all widgets.
|
||||||
char *text; // Contents of label.
|
char *text; // Contents of label.
|
||||||
|
PointT pos; // Anchor position (before alignment).
|
||||||
|
uint8_t alignment; // Alignment from specified location.
|
||||||
FontT *font; // Font to use.
|
FontT *font; // Font to use.
|
||||||
uint8_t modsEnabled; // Escape codes enabled?
|
uint8_t modsEnabled; // Escape codes enabled?
|
||||||
ColorT foreground; // Foreground color.
|
ColorT foreground; // Foreground color.
|
||||||
|
@ -18,9 +25,9 @@ typedef struct LabelS {
|
||||||
extern uint8_t __MAGIC_LABEL; // Magic ID assigned to us from the GUI.
|
extern uint8_t __MAGIC_LABEL; // Magic ID assigned to us from the GUI.
|
||||||
|
|
||||||
|
|
||||||
void labelClickSet(LabelT *label, WidgetEventT handler, void *data);
|
void labelClickSet(LabelT *label, ClickHandlerT handler, void *data);
|
||||||
void labelColorSet(LabelT *label, ColorT foreground, ColorT background);
|
void labelColorSet(LabelT *label, ColorT foreground, ColorT background);
|
||||||
LabelT *labelCreate(uint16_t x, uint16_t y, uint16_t w, uint16_t h, FontT *font, char *contents, ...);
|
LabelT *labelCreate(uint16_t x, uint16_t y, uint8_t alignment, FontT *font, char *contents, ...);
|
||||||
RegisterT *labelRegister(uint8_t magic);
|
RegisterT *labelRegister(uint8_t magic);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -870,6 +870,8 @@ void wmStartup(void) {
|
||||||
|
|
||||||
void wmUpdate(EventT *event) {
|
void wmUpdate(EventT *event) {
|
||||||
int16_t i;
|
int16_t i;
|
||||||
|
int16_t x;
|
||||||
|
int16_t y;
|
||||||
int16_t x2;
|
int16_t x2;
|
||||||
int16_t y2;
|
int16_t y2;
|
||||||
uint8_t onResize = 0;
|
uint8_t onResize = 0;
|
||||||
|
@ -879,6 +881,7 @@ void wmUpdate(EventT *event) {
|
||||||
static PointT resizeOffset = { 0 };
|
static PointT resizeOffset = { 0 };
|
||||||
static uint8_t dragging = 0;
|
static uint8_t dragging = 0;
|
||||||
static PointT dragOffset = { 0 };
|
static PointT dragOffset = { 0 };
|
||||||
|
static WidgetT *widgetDown = NULL;
|
||||||
|
|
||||||
// Do we have windows?
|
// Do we have windows?
|
||||||
if (arrlen(_windowList) > 0) {
|
if (arrlen(_windowList) > 0) {
|
||||||
|
@ -968,9 +971,19 @@ void wmUpdate(EventT *event) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we inside the window content? Most likely, check first.
|
// Are we inside the window content? Most likely, check this first.
|
||||||
if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) {
|
if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) {
|
||||||
//***TODO*** Send to window for processing.
|
// Are we over a widget?
|
||||||
|
x = event->x - win->bounds.x + win->offset.x;
|
||||||
|
y = event->y - win->bounds.y + win->offset.y;
|
||||||
|
for (i=0; i<arrlen(win->children); i++) {
|
||||||
|
widget = win->children[i];
|
||||||
|
if (x >= widget->r.x && x < widget->r.x + widget->r.x2 && y >= widget->r.y && y < widget->r.y + widget->r.y2) {
|
||||||
|
// Remember this widget for when left-up occurs.
|
||||||
|
widgetDown = widget;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we inside the close button? Does not include button frame on purpose.
|
// Are we inside the close button? Does not include button frame on purpose.
|
||||||
|
@ -1093,6 +1106,30 @@ void wmUpdate(EventT *event) {
|
||||||
|
|
||||||
// Can no longer be resizing.
|
// Can no longer be resizing.
|
||||||
resizing = 0;
|
resizing = 0;
|
||||||
|
|
||||||
|
// Did the left button just come up?
|
||||||
|
if (event->flags & EVENT_FLAG_LEFT_UP) {
|
||||||
|
|
||||||
|
// Did this click begin over a widget?
|
||||||
|
if (widgetDown) {
|
||||||
|
// Are we still inside the window content?
|
||||||
|
if (event->x <= win->bounds.x2 && event->x >= win->bounds.x && event->y <= win->bounds.y2 && event->y >= win->bounds.y) {
|
||||||
|
// Are we stll over the same widget?
|
||||||
|
x = event->x - win->bounds.x + win->offset.x;
|
||||||
|
y = event->y - win->bounds.y + win->offset.y;
|
||||||
|
for (i=0; i<arrlen(win->children); i++) {
|
||||||
|
widget = win->children[i];
|
||||||
|
if (widget == widgetDown && x >= widget->r.x && x < widget->r.x + widget->r.x2 && y >= widget->r.y && y < widget->r.y + widget->r.y2) {
|
||||||
|
// Send to widget for processing.
|
||||||
|
if (widget->reg->click) widget->reg->click(widget, x - widget->r.x, y - widget->r.y, widget->data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
widgetDown = NULL;
|
||||||
|
} // widgetDown
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -3,6 +3,12 @@
|
||||||
#include "gui/widgets/label.h"
|
#include "gui/widgets/label.h"
|
||||||
|
|
||||||
|
|
||||||
|
void clickHandler(WidgetT *widget, uint16_t x, uint16_t y, void *data) {
|
||||||
|
(void)widget;
|
||||||
|
logWrite("%dx%d %s\n", x, y, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
char title[256];
|
char title[256];
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
|
@ -19,8 +25,9 @@ int main(int argc, char *argv[]) {
|
||||||
sprintf(title, "Testing %d", i);
|
sprintf(title, "Testing %d", i);
|
||||||
w = windowCreate(i * 50, i * 50, 300, 200, title, WIN_STANDARD, 640, 480);
|
w = windowCreate(i * 50, i * 50, 300, 200, title, WIN_STANDARD, 640, 480);
|
||||||
|
|
||||||
l = labelCreate(10, 10, 0, 0, __guiFontVGA8x16, "Label Test");
|
l = labelCreate(150, 10, LABEL_ALIGN_LEFT, __guiFontVGA8x16, "Label Test");
|
||||||
labelColorSet(l, __guiBaseColors[i], GUI_BLACK);
|
labelColorSet(l, __guiBaseColors[i], GUI_BLACK);
|
||||||
|
labelClickSet(l, clickHandler, title);
|
||||||
windowWidgetAdd(w, W(l));
|
windowWidgetAdd(w, W(l));
|
||||||
}
|
}
|
||||||
guiRun();
|
guiRun();
|
||||||
|
|
Loading…
Add table
Reference in a new issue