diff options
Diffstat (limited to 'src/gwin/gwidget.c')
-rw-r--r-- | src/gwin/gwidget.c | 254 |
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 */ /** @} */ - |