aboutsummaryrefslogtreecommitdiffstats
path: root/src/gwin/gwidget.c
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2013-06-10 17:18:01 +1000
committerinmarket <andrewh@inmarket.com.au>2013-06-10 17:18:01 +1000
commit2cb35d6815a0a12035f4792c266b688c77085620 (patch)
tree292ebc4760767d67b41f7f0e0022185afcf05067 /src/gwin/gwidget.c
parent777ec6af7c1b594f7b7a9cbaaf7ead90d8fb7e8f (diff)
downloaduGFX-2cb35d6815a0a12035f4792c266b688c77085620.tar.gz
uGFX-2cb35d6815a0a12035f4792c266b688c77085620.tar.bz2
uGFX-2cb35d6815a0a12035f4792c266b688c77085620.zip
Clean up GWIN Event assignment. Optimise event efficiency.
Diffstat (limited to 'src/gwin/gwidget.c')
-rw-r--r--src/gwin/gwidget.c254
1 files changed, 186 insertions, 68 deletions
diff --git a/src/gwin/gwidget.c b/src/gwin/gwidget.c
index 773a715d..ee7986d1 100644
--- a/src/gwin/gwidget.c
+++ b/src/gwin/gwidget.c
@@ -13,23 +13,25 @@
#include "gwin/class_gwin.h"
+/* Our listener for events for widgets */
+static GListener gl;
+
/* We use these everywhere in this file */
#define gw ((GWidgetObject *)gh)
#define wvmt ((gwidgetVMT *)gh->vmt)
-static void gwidgetCallback(void *param, GEvent *pe) {
- #define gh ((GWindowObject *)param)
+/* Process an event */
+static void gwidgetEvent(void *param, GEvent *pe) {
+ #define gh QItem2GWindow(qi)
#define pme ((GEventMouse *)pe)
#define pte ((GEventToggle *)pe)
#define pde ((GEventDial *)pe)
- // check if widget is disabled
- if ((gw->g.flags & (GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
- return;
-
- // Process via AllEvents() if it is defined
- if (wvmt->AllEvents)
- wvmt->AllEvents(gw, pe);
+ const gfxQueueASyncItem * qi;
+ #if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
+ uint16_t role;
+ #endif
+ (void) param;
// Process various events
switch (pe->type) {
@@ -37,76 +39,179 @@ static void gwidgetCallback(void *param, GEvent *pe) {
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
case GEVENT_MOUSE:
case GEVENT_TOUCH:
- // Are we captured?
- if ((gw->g.flags & GWIN_FLG_MOUSECAPTURE)) {
- if ((pme->last_buttons & ~pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) {
- gw->g.flags &= ~GWIN_FLG_MOUSECAPTURE;
- if (wvmt->MouseUp)
- wvmt->MouseUp(gw, pme->x - gw->g.x, pme->y - gw->g.y);
- return;
- } else if (wvmt->MouseMove)
- wvmt->MouseMove(gw, pme->x - gw->g.x, pme->y - gw->g.y);
-
- // We are not captured - look for mouse downs over the widget
- } else if ((~pme->last_buttons & pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
- && pme->x >= gw->g.x && pme->x < gw->g.x + gw->g.width
- && pme->y >= gw->g.y && pme->y < gw->g.y + gw->g.height) {
- gw->g.flags |= GWIN_FLG_MOUSECAPTURE;
- if (wvmt->MouseDown)
- wvmt->MouseDown(gw, pme->x - gw->g.x, pme->y - gw->g.y);
+ // Cycle through all windows
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+
+ // check if it a widget that is enabled and visible
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
+ continue;
+
+ // Are we captured?
+ if ((gw->g.flags & GWIN_FLG_MOUSECAPTURE)) {
+ if ((pme->last_buttons & ~pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) {
+ gw->g.flags &= ~GWIN_FLG_MOUSECAPTURE;
+ if (wvmt->MouseUp)
+ wvmt->MouseUp(gw, pme->x - gw->g.x, pme->y - gw->g.y);
+ } else if (wvmt->MouseMove)
+ wvmt->MouseMove(gw, pme->x - gw->g.x, pme->y - gw->g.y);
+
+ // We are not captured - look for mouse downs over the widget
+ } else if ((~pme->last_buttons & pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
+ && pme->x >= gw->g.x && pme->x < gw->g.x + gw->g.width
+ && pme->y >= gw->g.y && pme->y < gw->g.y + gw->g.height) {
+ gw->g.flags |= GWIN_FLG_MOUSECAPTURE;
+ if (wvmt->MouseDown)
+ wvmt->MouseDown(gw, pme->x - gw->g.x, pme->y - gw->g.y);
+ }
}
break;
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
case GEVENT_TOGGLE:
- if (pte->on) {
- if (wvmt->ToggleOn)
- wvmt->ToggleOn(gw, pte->instance);
- } else {
- if (wvmt->ToggleOff)
- wvmt->ToggleOff(gw, pte->instance);
+ // Cycle through all windows
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+
+ // check if it a widget that is enabled and visible
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
+ continue;
+
+ for(role = 0; role < wvmt->toggleroles; role++) {
+ if (wvmt->ToggleGet(gw, role) == pte->instance) {
+ if (pte->on) {
+ if (wvmt->ToggleOn)
+ wvmt->ToggleOn(gw, role);
+ } else {
+ if (wvmt->ToggleOff)
+ wvmt->ToggleOff(gw, role);
+ }
+ }
+ }
}
break;
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
case GEVENT_DIAL:
- if (wvmt->DialMove)
- wvmt->DialMove(gw, pde->instance, pde->value);
+ // Cycle through all windows
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+
+ // check if it a widget that is enabled and visible
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
+ continue;
+
+ for(role = 0; role < wvmt->dialroles; role++) {
+ if (wvmt->DialGet(gw, role) == pte->instance) {
+ if (wvmt->DialMove)
+ wvmt->DialMove(gw, role, pde->value, pde->maxvalue);
+ }
+ }
+ }
break;
#endif
default:
break;
}
+
#undef gh
#undef pme
#undef pte
#undef pde
}
-GHandle _gwidgetInit(GWidgetObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwidgetVMT *vmt) {
- if (!(pgw = (GWidgetObject *)_gwindowInit((GWindowObject *)pgw, x, y, width, height, size, (const gwinVMT *)vmt, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED)))
+#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+ static GHandle FindToggleUser(uint16_t instance) {
+ #define gh QItem2GWindow(qi)
+ const gfxQueueASyncItem * qi;
+ uint16_t role;
+
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+ if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
+ continue;
+
+ for(role = 0; role < wvmt->toggleroles; role++) {
+ if (wvmt->ToggleGet(gw, role) == instance)
+ return gh;
+ }
+ }
+ return 0;
+ #undef gh
+ }
+#endif
+
+#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ static GHandle FindDialUser(uint16_t instance) {
+ #define gh QItem2GWindow(qi)
+ const gfxQueueASyncItem * qi;
+ uint16_t role;
+
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+ if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
+ continue;
+
+ for(role = 0; role < wvmt->dialroles; role++) {
+ if (wvmt->DialGet(gw, role) == instance)
+ return gh;
+ }
+ }
+ return 0;
+ #undef gh
+ }
+#endif
+
+void _gwidgetInit(void) {
+ geventListenerInit(&gl);
+ geventRegisterCallback(&gl, gwidgetEvent, 0);
+}
+
+GHandle _gwidgetCreate(GWidgetObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwidgetVMT *vmt) {
+ if (!(pgw = (GWidgetObject *)_gwindowCreate((GWindowObject *)pgw, x, y, width, height, size, (const gwinVMT *)vmt, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED)))
return 0;
pgw->txt = "";
pgw->fnDraw = vmt->DefaultDraw;
pgw->fnParam = 0;
- geventListenerInit(&pgw->listener);
- geventRegisterCallback(&pgw->listener, gwidgetCallback, pgw);
return (GHandle)pgw;
}
void _gwidgetDestroy(GHandle gh) {
+ #if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
+ uint16_t role, instance;
+ #endif
+
// Deallocate the text (if necessary)
if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
gh->flags &= ~GWIN_FLG_ALLOCTXT;
gfxFree((void *)gw->txt);
}
- // Untangle the listeners (both on us and to us).
- geventDetachSource(&gw->listener, 0);
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+ // Detach any toggles from this object
+ for(role = 0; role < wvmt->toggleroles; role++) {
+ instance = wvmt->ToggleGet(gw, role);
+ if (instance != GWIDGET_NO_INSTANCE) {
+ wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindToggleUser(instance))
+ geventDetachSource(&gl, ginputGetToggle(instance));
+ }
+ }
+ #endif
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ // Detach any dials from this object
+ for(role = 0; role < wvmt->dialroles; role++) {
+ instance = wvmt->DialGet(gw, role);
+ if (instance != GWIDGET_NO_INSTANCE) {
+ wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindDialUser(instance))
+ geventDetachSource(&gl, ginputGetDial(instance));
+ }
+ }
+ #endif
+
+ // Remove any listeners on this object.
geventDetachSourceListeners((GSourceHandle)gh);
}
@@ -183,76 +288,89 @@ void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param) {
_gwidgetRedraw(gh);
}
-bool_t gwinAttachListener(GHandle gh, GListener *pl, unsigned flags) {
- if (!(gh->flags & GWIN_FLG_WIDGET))
- return FALSE;
-
- return geventAttachSource(pl, (GSourceHandle)gh, flags);
+bool_t gwinAttachListener(GListener *pl) {
+ return geventAttachSource(pl, GWIDGET_SOURCE, 0);
}
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- bool_t gwinAttachMouse(GHandle gh, uint16_t instance) {
+ bool_t gwinAttachMouse(uint16_t instance) {
GSourceHandle gsh;
- unsigned flags;
-
- if (!(gh->flags & GWIN_FLG_WIDGET))
- return FALSE;
-
- if (!wvmt->MouseDown && !wvmt->MouseMove && !wvmt->MouseUp)
- return FALSE;
if (!(gsh = ginputGetMouse(instance)))
return FALSE;
- flags = wvmt->MouseMove ? (GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES) : GLISTEN_MOUSEMETA;
- return geventAttachSource(&gw->listener, gsh, flags);
+ return geventAttachSource(&gl, gsh, GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance) {
GSourceHandle gsh;
- unsigned flags;
+ uint16_t oi;
+ // Is this a widget
if (!(gh->flags & GWIN_FLG_WIDGET))
return FALSE;
- flags = 0;
- if (wvmt->ToggleOff) flags |= GLISTEN_TOGGLE_OFF;
- if (wvmt->ToggleOn) flags |= GLISTEN_TOGGLE_ON;
- if (!flags)
+ // Is the role valid
+ if (role >= wvmt->toggleroles)
return FALSE;
+ // Is this a valid device
if (!(gsh = ginputGetToggle(instance)))
return FALSE;
- if (wvmt->AssignToggle && !wvmt->AssignToggle(gw, role, instance))
- return FALSE;
+ // Is this already done?
+ oi = wvmt->ToggleGet(gw, role);
+ if (instance == oi)
+ return TRUE;
- return geventAttachSource(&gw->listener, gsh, flags);
+ // Remove the old instance
+ if (oi != GWIDGET_NO_INSTANCE) {
+ wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindToggleUser(oi))
+ geventDetachSource(&gl, ginputGetToggle(oi));
+ }
+
+ // Assign the new
+ wvmt->ToggleAssign(gw, role, instance);
+ return geventAttachSource(&gl, gsh, GLISTEN_TOGGLE_ON|GLISTEN_TOGGLE_OFF);
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance) {
GSourceHandle gsh;
+ uint16_t oi;
if (!(gh->flags & GWIN_FLG_WIDGET))
return FALSE;
- if (!wvmt->DialMove)
+ // Is the role valid
+ if (role >= wvmt->dialroles)
return FALSE;
+ // Is this a valid device
if (!(gsh = ginputGetDial(instance)))
return FALSE;
- if (wvmt->AssignDial && !wvmt->AssignDial(gw, role, instance))
- return FALSE;
+ // Is this already done?
+ oi = wvmt->DialGet(gw, role);
+ if (instance == oi)
+ return TRUE;
- return geventAttachSource(&gw->listener, gsh, 0);
+ // Remove the old instance
+ if (oi != GWIDGET_NO_INSTANCE) {
+ wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindDialUser(oi))
+ geventDetachSource(&gl, ginputGetDial(oi));
+ }
+
+ // Assign the new
+ wvmt->DialAssign(gw, role, instance);
+ return geventAttachSource(&gl, gsh, 0);
}
#endif
#endif /* GFX_USE_GWIN && GWIN_NEED_WIDGET */
/** @} */
-