From 2cb35d6815a0a12035f4792c266b688c77085620 Mon Sep 17 00:00:00 2001 From: inmarket Date: Mon, 10 Jun 2013 17:18:01 +1000 Subject: Clean up GWIN Event assignment. Optimise event efficiency. --- src/gwin/button.c | 58 ++++++++---- src/gwin/checkbox.c | 50 ++++++++--- src/gwin/console.c | 2 +- src/gwin/graph.c | 2 +- src/gwin/gwidget.c | 254 ++++++++++++++++++++++++++++++++++++++-------------- src/gwin/gwin.c | 9 +- src/gwin/slider.c | 91 +++++++++++++++---- 7 files changed, 345 insertions(+), 121 deletions(-) (limited to 'src/gwin') diff --git a/src/gwin/button.c b/src/gwin/button.c index 83b81b03..285a406c 100644 --- a/src/gwin/button.c +++ b/src/gwin/button.c @@ -32,8 +32,10 @@ // Prototypes for button VMT functions static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y); static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y); -static void ToggleOff(GWidgetObject *gw, uint16_t instance); -static void ToggleOn(GWidgetObject *gw, uint16_t instance); +static void ToggleOff(GWidgetObject *gw, uint16_t role); +static void ToggleOn(GWidgetObject *gw, uint16_t role); +static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance); +static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role); // The button VMT table static const gwidgetVMT buttonVMT = { @@ -43,16 +45,25 @@ static const gwidgetVMT buttonVMT = { _gwidgetRedraw, // The redraw routine 0, // The after-clear routine }, - gwinButtonDraw_3D, // The default drawing routine - MouseDown, // Process mouse down events - MouseUp, // Process mouse up events - 0, // Process mouse move events (NOT USED) - ToggleOff, // Process toggle off events - ToggleOn, // Process toggle on events - 0, // Process dial move events (NOT USED) - 0, // Process all events (NOT USED) - 0, // AssignToggle (NOT USED) - 0, // AssignDial (NOT USED) + gwinButtonDraw_3D, // The default drawing routine + { + MouseDown, // Process mouse down events + MouseUp, // Process mouse up events + 0, // Process mouse move events (NOT USED) + }, + { + 1, // 1 toggle role + ToggleAssign, // Assign Toggles + ToggleGet, // Get Toggles + ToggleOff, // Process toggle off events + ToggleOn, // Process toggle on events + }, + { + 0, // No dial roles + 0, // Assign Dials (NOT USED) + 0, // Get Dials (NOT USED) + 0, // Process dial move events (NOT USED) + } }; // Default color scheme @@ -80,7 +91,7 @@ static void SendButtonEvent(GWidgetObject *gw) { // Trigger a GWIN Button Event psl = 0; - while ((psl = geventGetSourceListener((GSourceHandle)gw, psl))) { + while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) { if (!(pe = geventGetEventBuffer(psl))) continue; pbe->type = GEVENT_GWIN_BUTTON; @@ -114,25 +125,36 @@ static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) { } // A toggle off has occurred -static void ToggleOff(GWidgetObject *gw, uint16_t instance) { - (void) instance; +static void ToggleOff(GWidgetObject *gw, uint16_t role) { + (void) role; gw->g.flags &= ~GBUTTON_FLG_PRESSED; _gwidgetRedraw((GHandle)gw); } // A toggle on has occurred -static void ToggleOn(GWidgetObject *gw, uint16_t instance) { - (void) instance; +static void ToggleOn(GWidgetObject *gw, uint16_t role) { + (void) role; gw->g.flags |= GBUTTON_FLG_PRESSED; _gwidgetRedraw((GHandle)gw); // Trigger the event on button down (different than for mouse/touch) SendButtonEvent(gw); } +static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) { + (void) role; + ((GButtonObject *)gw)->toggle = instance; +} + +static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) { + (void) role; + return ((GButtonObject *)gw)->toggle; +} + GHandle gwinCreateButton(GButtonObject *gw, coord_t x, coord_t y, coord_t width, coord_t height) { - if (!(gw = (GButtonObject *)_gwidgetInit((GWidgetObject *)gw, x, y, width, height, sizeof(GButtonObject), &buttonVMT))) + if (!(gw = (GButtonObject *)_gwidgetCreate((GWidgetObject *)gw, x, y, width, height, sizeof(GButtonObject), &buttonVMT))) return 0; + gw->toggle = GWIDGET_NO_INSTANCE; gw->c_up = GButtonDefaultColorsUp; gw->c_dn = GButtonDefaultColorsDown; gw->c_dis = GButtonDefaultColorsDisabled; diff --git a/src/gwin/checkbox.c b/src/gwin/checkbox.c index 893dab9c..53e99e42 100644 --- a/src/gwin/checkbox.c +++ b/src/gwin/checkbox.c @@ -26,7 +26,9 @@ // Prototypes for button VMT functions static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y); -static void ToggleOn(GWidgetObject *gw, uint16_t instance); +static void ToggleOn(GWidgetObject *gw, uint16_t role); +static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance); +static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role); // The button VMT table static const gwidgetVMT checkboxVMT = { @@ -37,15 +39,24 @@ static const gwidgetVMT checkboxVMT = { 0, // The after-clear routine }, gwinCheckboxDraw_CheckOnLeft, // The default drawing routine - MouseDown, // Process mouse down events - 0, // Process mouse up events (NOT USED) - 0, // Process mouse move events (NOT USED) - 0, // Process toggle off events (NOT USED) - ToggleOn, // Process toggle on events - 0, // Process dial move events (NOT USED) - 0, // Process all events (NOT USED) - 0, // AssignToggle (NOT USED) - 0, // AssignDial (NOT USED) + { + MouseDown, // Process mouse down events + 0, // Process mouse up events (NOT USED) + 0, // Process mouse move events (NOT USED) + }, + { + 1, // 1 toggle role + ToggleAssign, // Assign Toggles + ToggleGet, // Get Toggles + 0, // Process toggle off events (NOT USED) + ToggleOn, // Process toggle on events + }, + { + 0, // No dial roles + 0, // Assign Dials (NOT USED) + 0, // Get Dials (NOT USED) + 0, // Process dial move events (NOT USED) + } }; static const GCheckboxColors defaultColors = { @@ -63,7 +74,7 @@ static void SendCheckboxEvent(GWidgetObject *gw) { // Trigger a GWIN Checkbox Event psl = 0; - while ((psl = geventGetSourceListener((GSourceHandle)gw, psl))) { + while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) { if (!(pe = geventGetEventBuffer(psl))) continue; pce->type = GEVENT_GWIN_CHECKBOX; @@ -84,17 +95,28 @@ static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) { } // A toggle on has occurred -static void ToggleOn(GWidgetObject *gw, uint16_t instance) { - (void) instance; +static void ToggleOn(GWidgetObject *gw, uint16_t role) { + (void) role; gw->g.flags ^= GCHECKBOX_FLG_CHECKED; _gwidgetRedraw((GHandle)gw); SendCheckboxEvent(gw); } +static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) { + (void) role; + ((GCheckboxObject *)gw)->toggle = instance; +} + +static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) { + (void) role; + return ((GCheckboxObject *)gw)->toggle; +} + GHandle gwinCreateCheckbox(GCheckboxObject *gb, coord_t x, coord_t y, coord_t width, coord_t height) { - if (!(gb = (GCheckboxObject *)_gwidgetInit((GWidgetObject *)gb, x, y, width, height, sizeof(GCheckboxObject), &checkboxVMT))) + if (!(gb = (GCheckboxObject *)_gwidgetCreate((GWidgetObject *)gb, x, y, width, height, sizeof(GCheckboxObject), &checkboxVMT))) return 0; + gb->toggle = (uint16_t) -1; gb->c = defaultColors; // assign the default colors return (GHandle)gb; } diff --git a/src/gwin/console.c b/src/gwin/console.c index c4b2798d..6941295a 100644 --- a/src/gwin/console.c +++ b/src/gwin/console.c @@ -66,7 +66,7 @@ static const gwinVMT consoleVMT = { }; GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height) { - if (!(gc = (GConsoleObject *)_gwindowInit((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject), &consoleVMT, GWIN_FLG_VISIBLE))) + if (!(gc = (GConsoleObject *)_gwindowCreate((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject), &consoleVMT, GWIN_FLG_VISIBLE))) return 0; #if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM gc->stream.vmt = &GWindowConsoleVMT; diff --git a/src/gwin/graph.c b/src/gwin/graph.c index 393297e7..264c0c2c 100644 --- a/src/gwin/graph.c +++ b/src/gwin/graph.c @@ -165,7 +165,7 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t } GHandle gwinCreateGraph(GGraphObject *gg, coord_t x, coord_t y, coord_t width, coord_t height) { - if (!(gg = (GGraphObject *)_gwindowInit((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject), &graphVMT, GWIN_FLG_VISIBLE))) + if (!(gg = (GGraphObject *)_gwindowCreate((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject), &graphVMT, GWIN_FLG_VISIBLE))) return 0; gg->xorigin = gg->yorigin = 0; gg->lastx = gg->lasty = 0; 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 */ /** @} */ - diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c index 3e790d38..98e61c52 100644 --- a/src/gwin/gwin.c +++ b/src/gwin/gwin.c @@ -70,6 +70,11 @@ static color_t defaultBgColor = Black; *-----------------------------------------------*/ void _gwinInit(void) { + #if GWIN_NEED_WIDGET + extern void _gwidgetInit(void); + + _gwidgetInit(); + #endif #if GWIN_NEED_WINDOWMANAGER gfxQueueASyncInit(&_GWINList); cwm = &GNullWindowManager; @@ -79,7 +84,7 @@ void _gwinInit(void) { // Internal routine for use by GWIN components only // Initialise a window creating it dynamically if required. -GHandle _gwindowInit(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwinVMT *vmt, uint16_t flags) { +GHandle _gwindowCreate(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwinVMT *vmt, uint16_t flags) { // Allocate the structure if necessary if (!pgw) { if (!(pgw = (GWindowObject *)gfxAlloc(size))) @@ -146,7 +151,7 @@ void gwinSetDefaultBgColor(color_t bgclr) { *-----------------------------------------------*/ GHandle gwinCreateWindow(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height) { - return _gwindowInit(pgw, x, y, width, height, sizeof(GWindowObject), &basegwinVMT, GWIN_FLG_VISIBLE); + return _gwindowCreate(pgw, x, y, width, height, sizeof(GWindowObject), &basegwinVMT, GWIN_FLG_VISIBLE); } void gwinDestroy(GHandle gh) { diff --git a/src/gwin/slider.c b/src/gwin/slider.c index 1a1855a9..343973a2 100644 --- a/src/gwin/slider.c +++ b/src/gwin/slider.c @@ -25,10 +25,19 @@ #define GWIN_SLIDER_DEAD_BAND 5 #endif +#ifndef GWIN_SLIDER_TOGGLE_INC + #define GWIN_SLIDER_TOGGLE_INC 20 // How many toggles to go from minimum to maximum +#endif + // Prototypes for slider VMT functions static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y); static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y); -static void DialMove(GWidgetObject *gw, uint16_t instance, uint16_t value); +static void ToggleOn(GWidgetObject *gw, uint16_t role); +static void DialMove(GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max); +static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance); +static void DialAssign(GWidgetObject *gw, uint16_t role, uint16_t instance); +static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role); +static uint16_t DialGet(GWidgetObject *gw, uint16_t role); // The button VMT table static const gwidgetVMT sliderVMT = { @@ -38,16 +47,25 @@ static const gwidgetVMT sliderVMT = { _gwidgetRedraw, // The redraw routine 0, // The after-clear routine }, - gwinSliderDraw_Std, // The default drawing routine - MouseMove, // Process mouse down events (AS MOUSEMOVE) - MouseUp, // Process mouse up events - MouseMove, // Process mouse move events - 0, // Process toggle off events (NOT USED) - 0, // Process toggle on events (NOT USED) - DialMove, // Process dial move events - 0, // Process all events (NOT USED) - 0, // AssignToggle (NOT USED) - 0, // AssignDial (NOT USED) + gwinSliderDraw_Std, // The default drawing routine + { + 0, // Process mouse down events (NOT USED) + MouseUp, // Process mouse up events + MouseMove, // Process mouse move events + }, + { + 2, // 1 toggle role + ToggleAssign, // Assign Toggles + ToggleGet, // Get Toggles + 0, // Process toggle off events (NOT USED) + ToggleOn, // Process toggle on events + }, + { + 1, // 1 dial roles + DialAssign, // Assign Dials + DialGet, // Get Dials + DialMove, // Process dial move events + } }; static const GSliderColors GSliderDefaultColors = { @@ -66,7 +84,7 @@ static void SendSliderEvent(GWidgetObject *gw) { // Trigger a GWIN Button Event psl = 0; - while ((psl = geventGetSourceListener((GSourceHandle)gw, psl))) { + while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) { if (!(pe = geventGetEventBuffer(psl))) continue; pse->type = GEVENT_GWIN_SLIDER; @@ -75,7 +93,7 @@ static void SendSliderEvent(GWidgetObject *gw) { geventSendEvent(psl); } - #undef pbe + #undef pse } // Reset the display position back to the value predicted by the saved slider position @@ -159,13 +177,28 @@ static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y) { #undef gsw } +// A toggle on has occurred +static void ToggleOn(GWidgetObject *gw, uint16_t role) { + #define gsw ((GSliderObject *)gw) + + if (role) { + gwinSetSliderPosition((GHandle)gw, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC); + SendSliderEvent(gw); + } else { + gwinSetSliderPosition((GHandle)gw, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC); + SendSliderEvent(gw); + } + #undef gsw +} + // A dial move event -static void DialMove(GWidgetObject *gw, uint16_t instance, uint16_t value) { +static void DialMove(GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max) { #if GFX_USE_GINPUT && GINPUT_NEED_DIAL #define gsw ((GSliderObject *)gw) + (void) role; // Set the new position - gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/ginputGetDialRange(instance) + gsw->min); + gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/max + gsw->min); ResetDisplayPos(gsw); gwinDraw(&gw->g); @@ -174,13 +207,37 @@ static void DialMove(GWidgetObject *gw, uint16_t instance, uint16_t value) { SendSliderEvent(gw); #undef gsw #else - (void)gw; (void)instance; (void)value; + (void)gw; (void)role; (void)value; (void)max; #endif } +static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) { + if (role) + ((GSliderObject *)gw)->t_up = instance; + else + ((GSliderObject *)gw)->t_dn = instance; +} + +static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) { + return role ? ((GSliderObject *)gw)->t_up : ((GSliderObject *)gw)->t_dn; +} + +static void DialAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) { + (void) role; + ((GSliderObject *)gw)->dial = instance; +} + +static uint16_t DialGet(GWidgetObject *gw, uint16_t role) { + (void) role; + return ((GSliderObject *)gw)->dial; +} + GHandle gwinCreateSlider(GSliderObject *gs, coord_t x, coord_t y, coord_t width, coord_t height) { - if (!(gs = (GSliderObject *)_gwidgetInit((GWidgetObject *)gs, x, y, width, height, sizeof(GSliderObject), &sliderVMT))) + if (!(gs = (GSliderObject *)_gwidgetCreate((GWidgetObject *)gs, x, y, width, height, sizeof(GSliderObject), &sliderVMT))) return 0; + gs->t_dn = (uint16_t) -1; + gs->t_up = (uint16_t) -1; + gs->dial = (uint16_t) -1; gs->c = GSliderDefaultColors; gs->min = 0; gs->max = 100; -- cgit v1.2.3