Widget clicking now working properly with containers.
This commit is contained in:
parent
7bd4d41582
commit
9b0eb302a8
11 changed files with 132 additions and 86 deletions
|
@ -287,12 +287,23 @@ uint8_t widgetDirtyGet(WidgetT *widget) {
|
|||
void widgetDirtySet(WidgetT *widget, uint8_t dirty) {
|
||||
if (dirty) {
|
||||
widget->flags |= WIDGET_DIRTY;
|
||||
// Also set parent, if any.
|
||||
if (widget->parent) widgetDirtySet(widget->parent, 1);
|
||||
} else {
|
||||
widget->flags &= ~WIDGET_DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WidgetT *widgetFinder(WidgetT *widget, uint16_t x, uint16_t y, int16_t *localX, int16_t *localY) {
|
||||
// Find mouse position in widget-local space.
|
||||
*localX = x - widget->r.x;
|
||||
*localY = y - widget->r.y;
|
||||
// By default, widgets just return themselves. Widgets such as scrollarea, window, frame, etc. that contain other widgets will need to override this.
|
||||
return widget;
|
||||
}
|
||||
|
||||
|
||||
void widgetInputSetRaw(WidgetT *widget, uint8_t raw) {
|
||||
if (raw) {
|
||||
widget->flags |= WIDGET_RAW_INPUT;
|
||||
|
|
|
@ -50,6 +50,8 @@ struct WindowS;
|
|||
typedef void (*GuiCallbackT)(void *data, ...);
|
||||
typedef void (*WidgetEventT)(struct WidgetS *widget, ...);
|
||||
typedef void (*ClickHandlerT)(struct WidgetS *widget, uint16_t x, uint16_t y, uint8_t event, void *data);
|
||||
typedef struct WidgetS *(*WidgetFindT)(struct WidgetS *widget, uint16_t x, uint16_t y, int16_t *localX, int16_t *localY);
|
||||
|
||||
|
||||
typedef struct PointS {
|
||||
int16_t x;
|
||||
|
@ -76,6 +78,7 @@ typedef struct RegisterS {
|
|||
WidgetEventT destroy; // Destroy routine.
|
||||
WidgetEventT paint; // Paint routine.
|
||||
GuiCallbackT unregister; // Unregister routine.
|
||||
WidgetFindT findWidget; // Returns widget located under cursor.
|
||||
} RegisterT;
|
||||
|
||||
typedef struct WidgetS {
|
||||
|
@ -144,18 +147,19 @@ void guiShutdown(void);
|
|||
uint8_t guiStartup(int16_t width, int16_t height, int16_t depth);
|
||||
void guiStop(void);
|
||||
|
||||
void widgetAdd(WidgetT *target, int16_t x, int16_t y, WidgetT *widget);
|
||||
void widgetBaseSet(WidgetT *widget, uint8_t magic, uint16_t w, uint16_t h);
|
||||
uint8_t widgetChildrenDirty(WidgetT *widget);
|
||||
uint8_t widgetChildrenPaint(WidgetT *widget);
|
||||
void widgetDestroy(WidgetT *widget);
|
||||
uint8_t widgetDirtyGet(WidgetT *widget);
|
||||
void widgetDirtySet(WidgetT *widget, uint8_t dirty);
|
||||
void widgetInputSetRaw(WidgetT *widget, uint8_t raw);
|
||||
uint8_t widgetIsInWidget(WidgetT *widget, WidgetT *parent);
|
||||
void widgetMove(WidgetT *widget, int16_t x, int16_t y);
|
||||
void widgetPaintManually(WidgetT *widget, int16_t x, int16_t y);
|
||||
void widgetRemove(WidgetT *target, WidgetT *widget);
|
||||
void widgetAdd(WidgetT *target, int16_t x, int16_t y, WidgetT *widget);
|
||||
void widgetBaseSet(WidgetT *widget, uint8_t magic, uint16_t w, uint16_t h);
|
||||
uint8_t widgetChildrenDirty(WidgetT *widget);
|
||||
uint8_t widgetChildrenPaint(WidgetT *widget);
|
||||
void widgetDestroy(WidgetT *widget);
|
||||
uint8_t widgetDirtyGet(WidgetT *widget);
|
||||
void widgetDirtySet(WidgetT *widget, uint8_t dirty);
|
||||
WidgetT *widgetFinder(WidgetT *widget, uint16_t x, uint16_t y, int16_t *localX, int16_t *localY);
|
||||
void widgetInputSetRaw(WidgetT *widget, uint8_t raw);
|
||||
uint8_t widgetIsInWidget(WidgetT *widget, WidgetT *parent);
|
||||
void widgetMove(WidgetT *widget, int16_t x, int16_t y);
|
||||
void widgetPaintManually(WidgetT *widget, int16_t x, int16_t y);
|
||||
void widgetRemove(WidgetT *target, WidgetT *widget);
|
||||
|
||||
|
||||
#endif // GUI_H
|
||||
|
|
|
@ -124,7 +124,8 @@ RegisterT *buttonRegister(uint8_t magic) {
|
|||
buttonClick,
|
||||
buttonDestroy,
|
||||
buttonPaint,
|
||||
NULL // No unregister handler.
|
||||
NULL, // No unregister handler.
|
||||
widgetFinder
|
||||
};
|
||||
|
||||
// One-time widget startup code.
|
||||
|
|
|
@ -120,7 +120,8 @@ RegisterT *checkboxRegister(uint8_t magic) {
|
|||
checkboxClick,
|
||||
checkboxDestroy,
|
||||
checkboxPaint,
|
||||
NULL // No unregister handler.
|
||||
NULL, // No unregister handler.
|
||||
widgetFinder
|
||||
};
|
||||
|
||||
// One-time widget startup code.
|
||||
|
|
|
@ -233,7 +233,8 @@ RegisterT *hscrollRegister(uint8_t magic) {
|
|||
hscrollClick,
|
||||
hscrollDestroy,
|
||||
hscrollPaint,
|
||||
NULL // No unregister handler.
|
||||
NULL, // No unregister handler.
|
||||
widgetFinder
|
||||
};
|
||||
|
||||
// One-time widget startup code.
|
||||
|
|
|
@ -141,10 +141,11 @@ static void labelPaint(struct WidgetS *widget, ...) {
|
|||
RegisterT *labelRegister(uint8_t magic) {
|
||||
static RegisterT reg = {
|
||||
"Label",
|
||||
NULL, // No default on-click handler.
|
||||
NULL, // No default on-click handler.
|
||||
labelDestroy,
|
||||
labelPaint,
|
||||
NULL // No unregister handler.
|
||||
NULL, // No unregister handler.
|
||||
widgetFinder
|
||||
};
|
||||
|
||||
// One-time widget startup code.
|
||||
|
|
|
@ -79,10 +79,11 @@ static void picturePaint(struct WidgetS *widget, ...) {
|
|||
RegisterT *pictureRegister(uint8_t magic) {
|
||||
static RegisterT reg = {
|
||||
"Picture",
|
||||
NULL, // No default on-click handler.
|
||||
NULL, // No default on-click handler.
|
||||
pictureDestroy,
|
||||
picturePaint,
|
||||
NULL // No unregister handler.
|
||||
NULL, // No unregister handler.
|
||||
widgetFinder
|
||||
};
|
||||
|
||||
// One-time widget startup code.
|
||||
|
|
|
@ -157,7 +157,8 @@ RegisterT *radioRegister(uint8_t magic) {
|
|||
radioClick,
|
||||
radioDestroy,
|
||||
radioPaint,
|
||||
NULL // No unregister handler.
|
||||
NULL, // No unregister handler.
|
||||
widgetFinder
|
||||
};
|
||||
|
||||
// One-time widget startup code.
|
||||
|
|
|
@ -32,10 +32,11 @@
|
|||
uint8_t __MAGIC_SCROLLABLE = 0;
|
||||
|
||||
|
||||
static void scrollableClickHandler(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data);
|
||||
static void scrollableDestroy(struct WidgetS *widget, ...);
|
||||
static void scrollableFixupSizes(ScrollableT *s);
|
||||
static void scrollablePaint(struct WidgetS *widget, ...);
|
||||
static void scrollableClickHandler(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data);
|
||||
static void scrollableDestroy(struct WidgetS *widget, ...);
|
||||
static void scrollableFixupSizes(ScrollableT *s);
|
||||
static void scrollablePaint(struct WidgetS *widget, ...);
|
||||
static WidgetT *scrollableWidgetFinder(WidgetT *widget, uint16_t x, uint16_t y, int16_t *localX, int16_t *localY);
|
||||
|
||||
|
||||
static void scrollableClickHandler(WidgetT *widget, uint16_t x, uint16_t y, uint8_t event, void *data) {
|
||||
|
@ -203,7 +204,8 @@ RegisterT *scrollableRegister(uint8_t magic) {
|
|||
NULL, // No default on-click handler.
|
||||
scrollableDestroy,
|
||||
scrollablePaint,
|
||||
NULL // No unregister handler.
|
||||
NULL, // No unregister handler.
|
||||
scrollableWidgetFinder
|
||||
};
|
||||
|
||||
// One-time widget startup code.
|
||||
|
@ -214,7 +216,10 @@ RegisterT *scrollableRegister(uint8_t magic) {
|
|||
|
||||
|
||||
int32_t scrollableValueHGet(ScrollableT *scroll) {
|
||||
return hscrollValueGet(scroll->scrollh);
|
||||
if (scroll->scrollh) {
|
||||
return hscrollValueGet(scroll->scrollh);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -226,7 +231,10 @@ void scrollableValueHSet(ScrollableT *scroll, int32_t value) {
|
|||
|
||||
|
||||
int32_t scrollableValueVGet(ScrollableT *scroll) {
|
||||
return vscrollValueGet(scroll->scrollv);
|
||||
if (scroll->scrollh) {
|
||||
return vscrollValueGet(scroll->scrollv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -237,6 +245,32 @@ void scrollableValueVSet(ScrollableT *scroll, int32_t value) {
|
|||
}
|
||||
|
||||
|
||||
static WidgetT *scrollableWidgetFinder(WidgetT *widget, uint16_t x, uint16_t y, int16_t *localX, int16_t *localY) {
|
||||
int16_t i;
|
||||
ScrollableT *scroll = (ScrollableT *)widget;
|
||||
WidgetT *w;
|
||||
PointT p;
|
||||
|
||||
// Widget local mouse position.
|
||||
*localX = x - widget->r.x + scroll->offset.x;
|
||||
*localY = y - widget->r.y + scroll->offset.y;
|
||||
|
||||
// Find widget under mouse.
|
||||
for (i=0; i<arrlen(widget->children); i++) {
|
||||
w = widget->children[i];
|
||||
if (*localX >= w->r.x && *localX < w->r.x + w->r.w && *localY >= w->r.y && *localY < w->r.y + w->r.h) {
|
||||
// Ask this widget who we're pointing at.
|
||||
p.x = *localX;
|
||||
p.y = *localY;
|
||||
return w->reg->findWidget(w, p.x, p.y, localX, localY);
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find a widget.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void scrollableWidthSet(ScrollableT *scroll, int16_t w) {
|
||||
int32_t in = 0;
|
||||
if (scroll->scrollh) in = hscrollValueGet(scroll->scrollh);
|
||||
|
|
|
@ -243,7 +243,8 @@ RegisterT *vscrollRegister(uint8_t magic) {
|
|||
vscrollClick,
|
||||
vscrollDestroy,
|
||||
vscrollPaint,
|
||||
NULL // No unregister handler.
|
||||
NULL, // No unregister handler.
|
||||
widgetFinder
|
||||
};
|
||||
|
||||
// One-time widget startup code.
|
||||
|
|
|
@ -36,11 +36,10 @@ static WindowT *_windowTop = NULL;
|
|||
static int16_t _iconCount = 0;
|
||||
|
||||
|
||||
static void windowCache(WindowT *w, uint8_t redrawWindow);
|
||||
static void windowDestroy(struct WidgetS *widget, ...);
|
||||
static void windowPaint(struct WidgetS *widget, ...);
|
||||
|
||||
static WidgetT *wuWidgetUnderMouseGet(WindowT *win, EventT *event, int16_t *localX, int16_t *localY);
|
||||
static void windowCache(WindowT *w, uint8_t redrawWindow);
|
||||
static void windowDestroy(struct WidgetS *widget, ...);
|
||||
static void windowPaint(struct WidgetS *widget, ...);
|
||||
static WidgetT *windowWidgetFinder(WidgetT *widget, uint16_t x, uint16_t y, int16_t *localX, int16_t *localY);
|
||||
|
||||
|
||||
static void windowCache(WindowT *w, uint8_t redrawWindow) {
|
||||
|
@ -562,7 +561,8 @@ RegisterT *windowRegister(uint8_t magic) {
|
|||
NULL, // Click event is special for windows.
|
||||
windowDestroy, // Destroy.
|
||||
windowPaint, // Paint.
|
||||
NULL // Unregister.
|
||||
NULL, // Unregister.
|
||||
windowWidgetFinder
|
||||
};
|
||||
|
||||
// One-time widget startup code.
|
||||
|
@ -588,8 +588,6 @@ void windowResize(WindowT *win, uint16_t width, uint16_t height) {
|
|||
if (height < (GADGET_SIZE * 4) + chrome.y) height = (GADGET_SIZE * 4) + chrome.y;
|
||||
|
||||
// Too big? Horizontal.
|
||||
// Get the current view offset.
|
||||
x = scrollableValueHGet(win->scroll);
|
||||
// Width of content area of window.
|
||||
content = win->bounds.x2 - win->bounds.x + 1;
|
||||
// Do we need to take the height of the vertical scroll bar into account?
|
||||
|
@ -599,8 +597,6 @@ void windowResize(WindowT *win, uint16_t width, uint16_t height) {
|
|||
if (width > x) width = x;
|
||||
|
||||
// Too big? Vertical.
|
||||
// Get the current view offset.
|
||||
y = scrollableValueVGet(win->scroll);
|
||||
// Height of content area of window.
|
||||
content = win->bounds.y2 - win->bounds.y + 1;
|
||||
// Clamp.
|
||||
|
@ -620,6 +616,38 @@ void windowResize(WindowT *win, uint16_t width, uint16_t height) {
|
|||
}
|
||||
|
||||
|
||||
static WidgetT *windowWidgetFinder(WidgetT *widget, uint16_t x, uint16_t y, int16_t *localX, int16_t *localY) {
|
||||
int16_t i;
|
||||
PointT br;
|
||||
WidgetT *w;
|
||||
|
||||
// Find window bottom/right bounds.
|
||||
br.x = widget->r.x + widget->r.w - 1;
|
||||
br.y = widget->r.y + widget->r.h - 1;
|
||||
|
||||
// Are we over the provided window?
|
||||
if (x <= br.x && x >= widget->r.x && y <= br.y && y >= widget->r.y) {
|
||||
// Widget local mouse position.
|
||||
*localX = x - widget->r.x;
|
||||
*localY = y - widget->r.y;
|
||||
// Find widget under mouse.
|
||||
for (i=0; i<arrlen(widget->children); i++) {
|
||||
w = widget->children[i];
|
||||
if (*localX >= w->r.x && *localX < w->r.x + w->r.w && *localY >= w->r.y && *localY < w->r.y + w->r.h) {
|
||||
// Ask this widget who we're pointing at. Reuse 'br'.
|
||||
br.x = *localX;
|
||||
br.y = *localY;
|
||||
w = w->reg->findWidget(w, br.x, br.y, localX, localY);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find a widget.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void wmShutdown(void) {
|
||||
uint16_t i;
|
||||
|
||||
|
@ -636,8 +664,7 @@ void wmStartup(void) {
|
|||
|
||||
void wmUpdate(EventT *event) {
|
||||
int16_t i;
|
||||
int16_t windowLocalX;
|
||||
int16_t windowLocalY;
|
||||
PointT widgetLocal;
|
||||
int16_t x2;
|
||||
int16_t y2;
|
||||
uint8_t onResize = 0;
|
||||
|
@ -682,7 +709,7 @@ void wmUpdate(EventT *event) {
|
|||
x2 = win->base.r.x + win->base.r.w - 1;
|
||||
y2 = win->base.r.y + win->base.r.h - 1;
|
||||
// Are we over a widget?
|
||||
widgetOver = wuWidgetUnderMouseGet(win, event, &windowLocalX, &windowLocalY);
|
||||
widgetOver = windowWidgetFinder(W(win), event->x, event->y, &widgetLocal.x, &widgetLocal.y);
|
||||
} else {
|
||||
x2 = 0;
|
||||
y2 = 0;
|
||||
|
@ -693,9 +720,8 @@ void wmUpdate(EventT *event) {
|
|||
if (widgetOver && !widgetDown && !dragging && !resizing && (widgetOver->flags & WIDGET_RAW_INPUT) && (event->buttons != 0)) {
|
||||
if (widgetOver->reg->click) {
|
||||
rawEvent.event = event;
|
||||
rawEvent.data = widget->data;
|
||||
//logWrite("Firing raw click for %s\n", widgetOver->reg->widgetName);
|
||||
widgetOver->reg->click(widgetOver, windowLocalX - widgetOver->r.x, windowLocalY - widgetOver->r.y, CLICK_RAW_INPUT, &rawEvent);
|
||||
rawEvent.data = widgetOver->data;
|
||||
widgetOver->reg->click(widgetOver, widgetLocal.x, widgetLocal.y, CLICK_RAW_INPUT, &rawEvent);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -765,10 +791,9 @@ void wmUpdate(EventT *event) {
|
|||
}
|
||||
|
||||
// Are we over a widget?
|
||||
widget = wuWidgetUnderMouseGet(win, event, &windowLocalX, &windowLocalY);
|
||||
if (widget) {
|
||||
if (widget->reg->click) widget->reg->click(widget, windowLocalX - widget->r.x, windowLocalY - widget->r.y, CLICK_LEFT_DOWN, widget->data);
|
||||
widgetDown = widget;
|
||||
if (widgetOver) {
|
||||
if (widgetOver->reg->click) widgetOver->reg->click(widgetOver, widgetLocal.x, widgetLocal.y, CLICK_LEFT_DOWN, widgetOver->data);
|
||||
widgetDown = widgetOver;
|
||||
}
|
||||
|
||||
// Are we inside the close button? Does not include button frame on purpose.
|
||||
|
@ -878,9 +903,9 @@ void wmUpdate(EventT *event) {
|
|||
// 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?
|
||||
widget = wuWidgetUnderMouseGet(win, event, &windowLocalX, &windowLocalY);
|
||||
// Send to widget for processing or send cancel. Convert mouse to widget-local coordinates.
|
||||
if (widgetDown->reg->click) widgetDown->reg->click(widgetDown, windowLocalX - widgetDown->r.x, windowLocalY - widgetDown->r.y, (widget == widgetDown) ? CLICK_LEFT_UP : CLICK_LEFT_CANCEL, widgetDown->data);
|
||||
widget = windowWidgetFinder(W(win), event->x, event->y, &widgetLocal.x, &widgetLocal.y);
|
||||
// Send to widget for processing or send cancel.
|
||||
if (widgetDown->reg->click) widgetDown->reg->click(widgetDown, widgetLocal.x, widgetLocal.y, (widget == widgetDown) ? CLICK_LEFT_UP : CLICK_LEFT_CANCEL, widgetDown->data);
|
||||
}
|
||||
widgetDown = NULL;
|
||||
} // widgetDown
|
||||
|
@ -895,41 +920,6 @@ void wmUpdate(EventT *event) {
|
|||
}
|
||||
|
||||
|
||||
static WidgetT *wuWidgetUnderMouseGet(WindowT *win, EventT *event, int16_t *localX, int16_t *localY) {
|
||||
int16_t i;
|
||||
int16_t x2;
|
||||
int16_t y2;
|
||||
PointT offset;
|
||||
WidgetT *widget;
|
||||
|
||||
// If we have scrollbars, get the offset for the view.
|
||||
if (win->scroll->scrollh) offset.x = hscrollValueGet(win->scroll->scrollh);
|
||||
if (win->scroll->scrollv) offset.y = vscrollValueGet(win->scroll->scrollv);
|
||||
|
||||
// Find window bounds.
|
||||
x2 = win->base.r.x + win->base.r.w - 1;
|
||||
y2 = win->base.r.y + win->base.r.h - 1;
|
||||
|
||||
// Are we over the provided window?
|
||||
if (event->x <= x2 && event->x >= win->base.r.x && event->y <= y2 && event->y >= win->base.r.y) {
|
||||
// Find window-local mouse coordinates.
|
||||
*localX = event->x - win->base.r.x;// + offset.x;
|
||||
*localY = event->y - win->base.r.y;// + offset.y;
|
||||
// Find widget under mouse.
|
||||
for (i=0; i<arrlen(win->base.children); i++) {
|
||||
widget = win->base.children[i];
|
||||
if (*localX >= widget->r.x && *localX < widget->r.x + widget->r.w && *localY >= widget->r.y && *localY < widget->r.y + widget->r.h) {
|
||||
//logWrite("Over %s\n", widget->reg->widgetName);
|
||||
// Return this widget.
|
||||
return widget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
WindowT *wmWindowOnTopGet(void) {
|
||||
return _windowTop;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue