diff options
author | inmarket <andrewh@inmarket.com.au> | 2014-12-06 15:48:47 +1000 |
---|---|---|
committer | inmarket <andrewh@inmarket.com.au> | 2014-12-06 15:48:47 +1000 |
commit | 5bf2b8678a5a58059baffe780d00cd570781cea7 (patch) | |
tree | 001a4d387ecfb39b79c1863a643e36966fd39638 /src/gwin | |
parent | 4931f39a0d26f53a03834cfdc65d5e365a928652 (diff) | |
download | uGFX-5bf2b8678a5a58059baffe780d00cd570781cea7.tar.gz uGFX-5bf2b8678a5a58059baffe780d00cd570781cea7.tar.bz2 uGFX-5bf2b8678a5a58059baffe780d00cd570781cea7.zip |
Extended slider events. Updated the demo to match.
Actually reduced code size :)
Diffstat (limited to 'src/gwin')
-rw-r--r-- | src/gwin/gwin_slider.c | 161 | ||||
-rw-r--r-- | src/gwin/gwin_slider.h | 21 |
2 files changed, 122 insertions, 60 deletions
diff --git a/src/gwin/gwin_slider.c b/src/gwin/gwin_slider.c index f1230d5a..9652e6df 100644 --- a/src/gwin/gwin_slider.c +++ b/src/gwin/gwin_slider.c @@ -16,6 +16,8 @@ #include "gwin_class.h" +#define GSLIDER_FLG_EXTENDED_EVENTS (GWIN_FIRST_CONTROL_FLAG<<0) + #ifndef GWIN_SLIDER_DEAD_BAND #define GWIN_SLIDER_DEAD_BAND 5 #endif @@ -24,23 +26,58 @@ #define GWIN_SLIDER_TOGGLE_INC 20 // How many toggles to go from minimum to maximum #endif +// Calculate the slider position from the display position +static int CalculatePosFromDPos(GSliderObject *gsw) { + // Set the new position + if (gsw->w.g.width < gsw->w.g.height) { + if (gsw->dpos > gsw->w.g.height-GWIN_SLIDER_DEAD_BAND) + return gsw->min; + if (gsw->dpos < GWIN_SLIDER_DEAD_BAND) + return gsw->max; + return ((int)(gsw->w.g.height-1-gsw->dpos-GWIN_SLIDER_DEAD_BAND))*(gsw->max-gsw->min)/(gsw->w.g.height-2*GWIN_SLIDER_DEAD_BAND) + gsw->min; + } + if (gsw->dpos > gsw->w.g.width-GWIN_SLIDER_DEAD_BAND) + return gsw->max; + if (gsw->dpos < GWIN_SLIDER_DEAD_BAND) + return gsw->min; + return ((int)(gsw->dpos-GWIN_SLIDER_DEAD_BAND))*(gsw->max-gsw->min)/(gsw->w.g.width-2*GWIN_SLIDER_DEAD_BAND) + gsw->min; +} + // Send the slider event -static void SendSliderEvent(GWidgetObject *gw) { +static void SendSliderEvent(GSliderObject *gsw, uint8_t action) { GSourceListener * psl; GEvent * pe; #define pse ((GEventGWinSlider *)pe) - // Trigger a GWIN Button Event + // Does this slider want more than just SET events? + if (action != GSLIDER_EVENT_SET && !(gsw->w.g.flags & GSLIDER_FLG_EXTENDED_EVENTS)) + return; + psl = 0; while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) { + // Work out which action to send. + // This precedence order helps provide some protection against missed events. + // Saving it into srcflags works regardless of if a buffer is available. + if (psl->srcflags < action) + psl->srcflags = action; + + // Skip sending if no buffer is available if (!(pe = geventGetEventBuffer(psl))) continue; + + // Fill in the event pse->type = GEVENT_GWIN_SLIDER; - pse->gwin = (GHandle)gw; - pse->position = ((GSliderObject *)gw)->pos; + pse->gwin = (GHandle)gsw; + pse->action = psl->srcflags; #if GWIN_WIDGET_TAGS - pse->tag = gw->tag; + pse->tag = gsw->w.tag; #endif + + // If it is a cancel or set use the defined position else use the calculated position. + pse->position = pse->action >= GSLIDER_EVENT_CANCEL ? gsw->pos : CalculatePosFromDPos(gsw); + + // Cleanup and send. + psl->srcflags = 0; geventSendEvent(psl); } @@ -56,76 +93,72 @@ static void ResetDisplayPos(GSliderObject *gsw) { } #if GINPUT_NEED_MOUSE + // Set the display position from the mouse position + static void SetDisplayPosFromMouse(GSliderObject *gsw, coord_t x, coord_t y) { + if (gsw->w.g.width < gsw->w.g.height) + gsw->dpos = y < 0 ? 0 : (y >= gsw->w.g.height ? gsw->w.g.height-1 : y); + else + gsw->dpos = x < 0 ? 0 : (x >= gsw->w.g.width ? gsw->w.g.width-1 : x); + } + // A mouse up event static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) { #define gsw ((GSliderObject *)gw) - #define gh ((GHandle)gw) - - #if GWIN_BUTTON_LAZY_RELEASE - // Clip to the slider - if (x < 0) x = 0; - else if (x >= gh->width) x = gh->width-1; - if (y < 0) y = 0; - else if (y >= gh->height) x = gh->height-1; - #else + + #if !GWIN_BUTTON_LAZY_RELEASE // Are we over the slider? - if (x < 0 || x >= gh->width || y < 0 || y >= gh->height) { + if (x < 0 || x >= gsw->w.g.width || y < 0 || y >= gsw->w.g.height) { // No - restore the slider ResetDisplayPos(gsw); - _gwinUpdate(gh); + _gwinUpdate(&gsw->w.g); + SendSliderEvent(gsw, GSLIDER_EVENT_CANCEL); return; } #endif // Set the new position - if (gh->width < gh->height) { - if (y > gh->height-GWIN_SLIDER_DEAD_BAND) - gsw->pos = gsw->min; - else if (y < GWIN_SLIDER_DEAD_BAND) - gsw->pos = gsw->max; - else - gsw->pos = (uint16_t)((int32_t)(gh->height-1-y-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->height-2*GWIN_SLIDER_DEAD_BAND) + gsw->min); - } else { - if (x > gh->width-GWIN_SLIDER_DEAD_BAND) - gsw->pos = gsw->max; - else if (x < GWIN_SLIDER_DEAD_BAND) - gsw->pos = gsw->min; - else - gsw->pos = (uint16_t)((int32_t)(x-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->width-2*GWIN_SLIDER_DEAD_BAND) + gsw->min); - } + SetDisplayPosFromMouse(gsw, x, y); + gsw->pos = CalculatePosFromDPos(gsw); + // Update the display ResetDisplayPos(gsw); - _gwinUpdate(gh); + _gwinUpdate(&gsw->w.g); // Generate the event - SendSliderEvent(gw); - #undef gh + SendSliderEvent(gsw, GSLIDER_EVENT_SET); + #undef gsw } - // A mouse move (or mouse down) event + // A mouse down event + static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) { + #define gsw ((GSliderObject *)gw) + + // Determine the display position + SetDisplayPosFromMouse(gsw, x, y); + + // Update the display + _gwinUpdate(&gsw->w.g); + + // Send the event + SendSliderEvent(gsw, GSLIDER_EVENT_START); + + #undef gsw + } + + // A mouse move event static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y) { #define gsw ((GSliderObject *)gw) - // Determine the temporary display position (with range checking) - if (gw->g.width < gw->g.height) { - if (y < 0) - gsw->dpos = 0; - else if (y >= gw->g.height) - gsw->dpos = gw->g.height-1; - else - gsw->dpos = y; - } else { - if (x < 0) - gsw->dpos = 0; - else if (x >= gw->g.width) - gsw->dpos = gw->g.width-1; - else - gsw->dpos = x; - } + // Determine the display position + SetDisplayPosFromMouse(gsw, x, y); // Update the display - _gwinUpdate(&gw->g); + _gwinUpdate(&gsw->w.g); + + // Send the event + SendSliderEvent(gsw, GSLIDER_EVENT_MOVE); + #undef gsw } #endif @@ -136,11 +169,11 @@ static void ResetDisplayPos(GSliderObject *gsw) { #define gsw ((GSliderObject *)gw) if (role) { - gwinSliderSetPosition((GHandle)gw, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC); - SendSliderEvent(gw); + gwinSliderSetPosition(&gsw->w.g, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC); + SendSliderEvent(gsw, GSLIDER_EVENT_SET); } else { - gwinSliderSetPosition((GHandle)gw, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC); - SendSliderEvent(gw); + gwinSliderSetPosition(&gsw->w.g, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC); + SendSliderEvent(gsw, GSLIDER_EVENT_SET); } #undef gsw } @@ -167,10 +200,10 @@ static void ResetDisplayPos(GSliderObject *gsw) { gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/max + gsw->min); ResetDisplayPos(gsw); - _gwinUpdate((GHandle)gw); + _gwinUpdate(&gsw->w.g); // Generate the event - SendSliderEvent(gw); + SendSliderEvent(gsw, GSLIDER_EVENT_SET); #undef gsw } @@ -197,7 +230,7 @@ static const gwidgetVMT sliderVMT = { gwinSliderDraw_Std, // The default drawing routine #if GINPUT_NEED_MOUSE { - 0, // Process mouse down events (NOT USED) + MouseDown, // Process mouse down events MouseUp, // Process mouse up events MouseMove, // Process mouse move events }, @@ -275,6 +308,16 @@ void gwinSliderSetPosition(GHandle gh, int pos) { #undef gsw } +void gwinSliderSendExtendedEvents(GHandle gh, bool_t enabled) { + if (gh->vmt != (gwinVMT *)&sliderVMT) + return; + + if (enabled) + gh->flags |= GSLIDER_FLG_EXTENDED_EVENTS; + else + gh->flags &= ~GSLIDER_FLG_EXTENDED_EVENTS; +} + /*---------------------------------------------------------- * Custom Draw Routines *----------------------------------------------------------*/ diff --git a/src/gwin/gwin_slider.h b/src/gwin/gwin_slider.h index b88d6dfd..91a381a5 100644 --- a/src/gwin/gwin_slider.h +++ b/src/gwin/gwin_slider.h @@ -27,12 +27,18 @@ #define GEVENT_GWIN_SLIDER (GEVENT_GWIN_CTRL_FIRST+1) typedef struct GEventGWinSlider { - GEventType type; // The type of this event (GEVENT_GWIN_BUTTON) + GEventType type; // The type of this event (GEVENT_GWIN_SLIDER) GHandle gwin; // The slider that is returning results #if GWIN_WIDGET_TAGS WidgetTag tag; // The slider tag #endif int position; + + uint8_t action; + #define GSLIDER_EVENT_SET 4 /* Slider position is set. This is the only event returned by default */ + #define GSLIDER_EVENT_CANCEL 3 /* Slider position changing has been cancelled */ + #define GSLIDER_EVENT_START 2 /* Slider position has started changing */ + #define GSLIDER_EVENT_MOVE 1 /* Slider position has been moved */ } GEventGWinSlider; // There are currently no GEventGWinSlider listening flags - use 0 @@ -124,6 +130,19 @@ void gwinSliderSetPosition(GHandle gh, int pos); #define gwinSliderGetPosition(gh) (((GSliderObject *)(gh))->pos) /** + * @brief Should the slider send extended events. + * + * @param[in] gh The window handle (must be a slider window) + * @param[in] enabled TRUE to enable extended events, FALSE to disable them + * + * @note The slider by default will only send slider events with an action of GSLIDER_EVENT_SET. + * This call can be used to enable other slider action's to be sent as events + * + * @api + */ +void gwinSliderSendExtendedEvents(GHandle gh, bool_t enabled); + +/** * @brief Some custom slider drawing routines * @details These function may be passed to @p gwinSetCustomDraw() to get different slider drawing styles * |