From d7896289d12652039443e1bf512d7ae521542d6f Mon Sep 17 00:00:00 2001 From: inmarket Date: Sat, 13 Dec 2014 18:33:53 +1000 Subject: [PATCH] Updates to the slider to fix positioning issues. Also fixes negative ranges, ranges > 65536 and very small ranges. --- gfxconf.example.h | 3 +++ src/gwin/gwin_slider.c | 46 ++++++++++++++++++++++++++++-------------- src/gwin/sys_options.h | 28 +++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/gfxconf.example.h b/gfxconf.example.h index b679669b..ab56ff90 100644 --- a/gfxconf.example.h +++ b/gfxconf.example.h @@ -162,6 +162,9 @@ // #define GWIN_NEED_BUTTON FALSE // #define GWIN_BUTTON_LAZY_RELEASE FALSE // #define GWIN_NEED_SLIDER FALSE +// #define GWIN_SLIDER_NOSNAP FALSE +// #define GWIN_SLIDER_DEAD_BAND 5 +// #define GWIN_SLIDER_TOGGLE_INC 20 // #define GWIN_NEED_CHECKBOX FALSE // #define GWIN_NEED_IMAGE FALSE // #define GWIN_NEED_IMAGE_ANIMATION FALSE diff --git a/src/gwin/gwin_slider.c b/src/gwin/gwin_slider.c index 9652e6df..33039a92 100644 --- a/src/gwin/gwin_slider.c +++ b/src/gwin/gwin_slider.c @@ -18,29 +18,29 @@ #define GSLIDER_FLG_EXTENDED_EVENTS (GWIN_FIRST_CONTROL_FLAG<<0) -#ifndef GWIN_SLIDER_DEAD_BAND - #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 - // Calculate the slider position from the display position static int CalculatePosFromDPos(GSliderObject *gsw) { + int halfbit; + // Set the new position if (gsw->w.g.width < gsw->w.g.height) { - if (gsw->dpos > gsw->w.g.height-GWIN_SLIDER_DEAD_BAND) + 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; + halfbit = gsw->w.g.height/2-GWIN_SLIDER_DEAD_BAND; + if (gsw->min > gsw->max) + halfbit = -halfbit; + return (((int)(gsw->w.g.height-(GWIN_SLIDER_DEAD_BAND+1)-gsw->dpos))*(gsw->max-gsw->min) + halfbit)/(gsw->w.g.height-(2*GWIN_SLIDER_DEAD_BAND+1)) + gsw->min; } - if (gsw->dpos > gsw->w.g.width-GWIN_SLIDER_DEAD_BAND) + 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; + halfbit = gsw->w.g.width/2-GWIN_SLIDER_DEAD_BAND; + if (gsw->min > gsw->max) + halfbit = -halfbit; + return (((int)gsw->dpos-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min) + halfbit)/(gsw->w.g.width-(2*GWIN_SLIDER_DEAD_BAND+1)) + gsw->min; } // Send the slider event @@ -87,9 +87,9 @@ static void SendSliderEvent(GSliderObject *gsw, uint8_t action) { // Reset the display position back to the value predicted by the saved slider position static void ResetDisplayPos(GSliderObject *gsw) { if (gsw->w.g.width < gsw->w.g.height) - gsw->dpos = gsw->w.g.height-1-((gsw->w.g.height-1)*(gsw->pos-gsw->min))/(gsw->max-gsw->min); + gsw->dpos = gsw->w.g.height-1-(gsw->w.g.height-1)*(gsw->pos-gsw->min)/(gsw->max-gsw->min); else - gsw->dpos = ((gsw->w.g.width-1)*(gsw->pos-gsw->min))/(gsw->max-gsw->min); + gsw->dpos = (gsw->w.g.width-1)*(gsw->pos-gsw->min)/(gsw->max-gsw->min); } #if GINPUT_NEED_MOUSE @@ -121,7 +121,22 @@ static void ResetDisplayPos(GSliderObject *gsw) { gsw->pos = CalculatePosFromDPos(gsw); // Update the display - ResetDisplayPos(gsw); + #if GWIN_SLIDER_NOSNAP + //only adjust dpos if it equals one of the end values. + if (gsw->w.g.width < gsw->w.g.height) { + if (gsw->pos == gsw->min) + gsw->dpos = gsw->w.g.height-1; + else if (gsw->pos == gsw->max) + gsw->dpos = 0; + } else { + if (gsw->pos == gsw->max) + gsw->dpos = gsw->w.g.width-1; + else if (gsw->pos == gsw->min) + gsw->dpos = 0; + } + #else + ResetDisplayPos(gsw); + #endif _gwinUpdate(&gsw->w.g); // Generate the event @@ -413,6 +428,7 @@ void gwinSliderDraw_Image(GWidgetObject *gw, void *param) { gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter); #undef gsw + #undef gi } #endif /* GDISP_NEED_IMAGE */ diff --git a/src/gwin/sys_options.h b/src/gwin/sys_options.h index 199cad5b..bb7e3598 100644 --- a/src/gwin/sys_options.h +++ b/src/gwin/sys_options.h @@ -286,6 +286,34 @@ #ifndef GWIN_PROGRESSBAR_AUTO #define GWIN_PROGRESSBAR_AUTO FALSE #endif + /** + * @brief Should the slider avoid snapping to a fixed position when the mouse is released + * @details Defaults to FALSE + * @note If FALSE the slider will snap to the closest set-able position when the + * mouse is released. If TRUE it will maintain the position the + * mouse was released at, except when at the minimum and maximum slider values. + */ + #ifndef GWIN_SLIDER_NOSNAP + #define GWIN_SLIDER_NOSNAP FALSE + #endif + /** + * @brief The number of pixels of dead-band at each end of the slider + * @details Defaults to 5 + * @note A dead-band is required because fingers can often cannot + * accurately control the slider peg at the edges of the slider + */ + #ifndef GWIN_SLIDER_DEAD_BAND + #define GWIN_SLIDER_DEAD_BAND 5 + #endif + /** + * @brief How many toggles it takes to go from minimum to maximum value on a slider + * @details Defaults to 20 + * @note When the slider is being operated by a toggle device this setting describes + * how many toggles are required to go from end to end. + */ + #ifndef GWIN_SLIDER_TOGGLE_INC + #define GWIN_SLIDER_TOGGLE_INC 20 + #endif /** @} */ #endif /* _GWIN_OPTIONS_H */