diff --git a/.gitignore b/.gitignore index 19d31b1b3..25406a508 100644 --- a/.gitignore +++ b/.gitignore @@ -46,4 +46,7 @@ nbdist/ /Makefile # Builder files -builder/.gradle \ No newline at end of file +builder/.gradle + +# Dep Files +*.dep \ No newline at end of file diff --git a/src/GUIslice.c b/src/GUIslice.c index 45e40fa06..9901744d9 100755 --- a/src/GUIslice.c +++ b/src/GUIslice.c @@ -172,6 +172,7 @@ bool gslc_Init(gslc_tsGui* pGui,void* pvDriver,gslc_tsPage* asPage,uint8_t nMaxP } pGui->bScreenNeedRedraw = true; pGui->bScreenNeedFlip = false; + pGui->bScreenDisableRedraw = false; gslc_InvalidateRgnReset(pGui); @@ -211,6 +212,7 @@ bool gslc_Init(gslc_tsGui* pGui,void* pvDriver,gslc_tsPage* asPage,uint8_t nMaxP //pGui->pfuncXEvent = NULL; // UNUSED pGui->pfuncPinPoll = NULL; + pGui->pfuncXTouchDisabled = false; pGui->asInputMap = NULL; pGui->nInputMapMax = 0; @@ -280,6 +282,10 @@ void gslc_SetPinPollFunc(gslc_tsGui* pGui,GSLC_CB_PIN_POLL pfunc) pGui->pfuncPinPoll = pfunc; } +void gslc_SetTouchDisabled(gslc_tsGui* pGui,bool pbool) +{ + pGui->pfuncXTouchDisabled = pbool; +} void gslc_InitInputMap(gslc_tsGui* pGui,gslc_tsInputMap* asInputMap,uint8_t nInputMapMax) { @@ -703,7 +709,9 @@ void gslc_Update(gslc_tsGui* pGui) } // Perform any redraw required for current page - gslc_PageRedrawGo(pGui); + if (!pGui->bScreenDisableRedraw) { + gslc_PageRedrawGo(pGui); + } // Simple "frame" rate reporting // - Note that the rate is based on the number of calls to gslc_Update() @@ -2443,6 +2451,11 @@ int16_t gslc_PageFocusStep(gslc_tsGui* pGui, gslc_tsPage* pPage, bool bNext) } +void gslc_SetScreenDisableRedraw(gslc_tsGui* pGui,bool pbool) +{ + pGui->bScreenDisableRedraw = pbool; +} + // ------------------------------------------------------------------------ // Element General Functions // ------------------------------------------------------------------------ @@ -2853,7 +2866,7 @@ bool gslc_ElemEvent(void* pvGui,gslc_tsEvent sEvent) pfuncXTouch = pElemTracked->pfuncXTouch; // Invoke the callback function - if (pfuncXTouch != NULL) { + if (!pGui->pfuncXTouchDisabled && pfuncXTouch != NULL) { // Pass in the relative position from corner of element region (*pfuncXTouch)(pvGui,(void*)(pElemRefTracked),eTouch,nRelX,nRelY); } diff --git a/src/GUIslice.h b/src/GUIslice.h index cb39018b7..42d890278 100755 --- a/src/GUIslice.h +++ b/src/GUIslice.h @@ -786,6 +786,7 @@ typedef struct { // Redraw of screen (ie. across page stack) bool bScreenNeedRedraw; ///< Screen requires a redraw bool bScreenNeedFlip; ///< Screen requires a page flip + bool bScreenDisableRedraw; ///< Screen redrawing disabled // Current clip region bool bInvalidateEn; ///< A region of the display has been invalidated @@ -794,6 +795,7 @@ typedef struct { // Callback functions //GSLC_CB_EVENT pfuncXEvent; ///< UNUSED: Callback func ptr for events GSLC_CB_PIN_POLL pfuncPinPoll; ///< Callback func ptr for pin polling + bool pfuncXTouchDisabled; ///< Disable touch events // Key/pin input control mapping @@ -2460,6 +2462,9 @@ void gslc_SetTouchRemapYX(gslc_tsGui* pGui, bool bSwap); /// \todo Doc. This API is experimental and subject to change void gslc_SetPinPollFunc(gslc_tsGui* pGui, GSLC_CB_PIN_POLL pfunc); +/// \todo Doc. This API is experimental and subject to change +void gslc_SetTouchDisabled(gslc_tsGui* pGui,bool pbool); + /// \todo Doc. This API is experimental and subject to change void gslc_InitInputMap(gslc_tsGui* pGui,gslc_tsInputMap* asInputMap,uint8_t nInputMapMax); @@ -3430,6 +3435,8 @@ void gslc_PageRedrawCalc(gslc_tsGui* pGui); /// \todo Doc. This API is experimental and subject to change int16_t gslc_PageFocusStep(gslc_tsGui* pGui,gslc_tsPage* pPage,bool bNext); +/// \todo Doc. This API is experimental and subject to change +void gslc_SetScreenDisableRedraw(gslc_tsGui* pGui,bool pbool); /// /// Create an event structure diff --git a/src/elem/XSlider.c b/src/elem/XSlider.c index 47f0ca801..6da2d46a3 100644 --- a/src/elem/XSlider.c +++ b/src/elem/XSlider.c @@ -105,7 +105,10 @@ gslc_tsElemRef* gslc_ElemXSliderCreate(gslc_tsGui* pGui,int16_t nElemId,int16_t pXData->bTrim = false; pXData->colTrim = GSLC_COL_BLACK; pXData->nTickDiv = 0; + pXData->anTickPos = NULL; pXData->pfuncXPos = NULL; + pXData->eTouch = GSLC_TOUCH_NONE; + pXData->eTickFmt = teXSliderFmt_TickBelow; sElem.pXData = (void*)(pXData); // Specify the custom drawing callback sElem.pfuncXDraw = &gslc_ElemXSliderDraw; @@ -154,6 +157,19 @@ void gslc_ElemXSliderSetStyle(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef, gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_FULL); } +void gslc_ElemXSliderSetStyleCustom(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef, uint16_t* anTickPos, bool bTickAbove, bool bTickBelow) +{ + gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef); + gslc_tsXSlider* pSlider = (gslc_tsXSlider*)(pElem->pXData); + pSlider->eTickFmt = 0; + if (anTickPos != NULL) { + pSlider->anTickPos = anTickPos; + pSlider->eTickFmt |= teXSliderFmt_PosCustom; + } + pSlider->eTickFmt |= (bTickAbove)? teXSliderFmt_TickAbove : 0; + pSlider->eTickFmt |= (bTickBelow)? teXSliderFmt_TickBelow : 0; +} + int gslc_ElemXSliderGetPos(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef) { if (pElemRef == NULL) { @@ -191,6 +207,7 @@ void gslc_ElemXSliderSetPos(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,int16_t nP if (pSlider->pfuncXPos != NULL) { (*pSlider->pfuncXPos)((void*)(pGui),(void*)(pElemRef),nPos); } + pSlider->eTouch = GSLC_TOUCH_NONE; // Mark for redraw // - Only need incremental redraw @@ -213,7 +230,6 @@ void gslc_ElemXSliderSetPosFunc(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,GSLC_C pSlider->pfuncXPos = funcCb; } - // Redraw the slider // - Note that this redraw is for the entire element rect region // - The Draw function parameters use void pointers to allow for @@ -248,7 +264,9 @@ bool gslc_ElemXSliderDraw(void* pvGui,void* pvElemRef,gslc_teRedrawType eRedraw) gslc_tsColor colTrim = pSlider->colTrim; uint16_t nTickDiv = pSlider->nTickDiv; int16_t nTickLen = pSlider->nTickLen; + uint8_t eTickFmt = pSlider->eTickFmt; gslc_tsColor colTick = pSlider->colTick; + uint16_t* anTickPos = pSlider->anTickPos; // Range check on nPos if (nPos < nPosMin) { nPos = nPosMin; } @@ -292,19 +310,34 @@ bool gslc_ElemXSliderDraw(void* pvGui,void* pvElemRef,gslc_teRedrawType eRedraw) if (nTickDiv>=1) { uint16_t nTickInd; int16_t nTickOffset; + int16_t nTickLenAbove,nTickLenBelow; + bool bTickPosCustom; + nTickLenAbove = (eTickFmt & teXSliderFmt_TickAbove) ? nTickLen : 0; + nTickLenBelow = (eTickFmt & teXSliderFmt_TickBelow) ? nTickLen : 0; + bTickPosCustom = (eTickFmt & teXSliderFmt_PosCustom); for (nTickInd=0;nTickInd<=nTickDiv;++nTickInd) { - nTickOffset = (int16_t)((int32_t)nTickInd * (int32_t)nCtrlRng / (int32_t)nTickDiv); + if (!bTickPosCustom) { + // Tick marks are evenly spaced along length + // - In this mode, nTickDiv defines the number of "divisions", so we + // draw nTickDiv+1 lines in total + nTickOffset = (int16_t)((int32_t)nTickInd * (int32_t)nCtrlRng / (int32_t)nTickDiv); + } else { + // Tick marks are positioned according to custom tick array + // - In this mode, nTickDiv defines the length of the tick array + // so we need to skip the last loop iteration + if (nTickInd == nTickDiv) { continue; } + nTickOffset = (int16_t)(anTickPos[nTickInd]); + } if (!bVert) { - gslc_DrawLine(pGui,nX0+nMargin+ nTickOffset,nYMid, - nX0+nMargin + nTickOffset,nYMid+nTickLen,colTick); + gslc_DrawLine(pGui,nX0+nMargin+nTickOffset,nYMid-nTickLenAbove, + nX0+nMargin+nTickOffset,nYMid+nTickLenBelow,colTick); } else { - gslc_DrawLine(pGui,nXMid,nY0+nMargin+ nTickOffset, - nXMid+nTickLen,nY0+nMargin + nTickOffset,colTick); + gslc_DrawLine(pGui,nXMid-nTickLenAbove,nY0+nMargin+nTickOffset, + nXMid+nTickLenBelow,nY0+nMargin+nTickOffset,colTick); } } } - // Draw the track if (!bVert) { // Make the track highlight during glow @@ -335,7 +368,7 @@ bool gslc_ElemXSliderDraw(void* pvGui,void* pvElemRef,gslc_teRedrawType eRedraw) nCtrlX0 = nXMid-nThumbSz; nCtrlY0 = nY0+nCtrlPos-nThumbSz; } - rThumb.x = nCtrlX0; + rThumb.x = nCtrlX0 - (rThumb.w / 2); rThumb.y = nCtrlY0; rThumb.w = 2*nThumbSz; rThumb.h = 2*nThumbSz; @@ -383,6 +416,7 @@ bool gslc_ElemXSliderTouch(void* pvGui,void* pvElemRef,gslc_teTouch eTouch,int16 pElemRef = (gslc_tsElemRef*)(pvElemRef); pElem = gslc_GetElemFromRef(pGui,pElemRef); pSlider = (gslc_tsXSlider*)(pElem->pXData); + pSlider->eTouch = eTouch; bool bGlowingOld = gslc_ElemGetGlow(pGui,pElemRef); int16_t nPosRng; diff --git a/src/elem/XSlider.h b/src/elem/XSlider.h index 0a0f60fcd..4199523f5 100644 --- a/src/elem/XSlider.h +++ b/src/elem/XSlider.h @@ -56,6 +56,13 @@ typedef bool (*GSLC_CB_XSLIDER_POS)(void* pvGui,void* pvElem,int16_t nPos); // - These data structures are maintained in the gslc_tsElem // structure via the pXData pointer +/// Enumerations for custom tick styling +enum { + teXSliderFmt_TickAbove = 1, ///< Draw a tick mark above/left of the line + teXSliderFmt_TickBelow = 2, ///< Draw a tick mark below/right of the line + teXSliderFmt_PosCustom = 32, ///< Position of tick marks defined by user array +}; + /// Extended data for Slider element typedef struct { // Config @@ -69,10 +76,14 @@ typedef struct { gslc_tsColor colTick; ///< Style: color of ticks bool bTrim; ///< Style: show a trim color gslc_tsColor colTrim; ///< Style: color of trim + uint8_t eTickFmt; ///< Style: tick format options + uint16_t* anTickPos; ///< Style: custom tick position array (pixel offset), nTickDiv entries // State int16_t nPos; ///< Current position value of the slider // Callbacks GSLC_CB_XSLIDER_POS pfuncXPos; ///< Callback func ptr for position update + // EventType + gslc_teTouch eTouch; ///< Touch event type } gslc_tsXSlider; @@ -98,7 +109,7 @@ gslc_tsElemRef* gslc_ElemXSliderCreate(gslc_tsGui* pGui,int16_t nElemId,int16_t /// -/// Set a Slider element's current position +/// Set a Slider element's appearance /// /// \param[in] pGui: Pointer to GUI /// \param[in] pElemRef: Pointer to Element reference @@ -114,6 +125,22 @@ void gslc_ElemXSliderSetStyle(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef, bool bTrim,gslc_tsColor colTrim,uint16_t nTickDiv, int16_t nTickLen,gslc_tsColor colTick); +/// +/// Set a Slider element's appearance (custom options) +/// +/// \param[in] pGui: Pointer to GUI +/// \param[in] pElemRef: Pointer to Element reference +/// \param[in] anTickPos: Pointer to custom tick position array (in pixels) +/// If NULL, the default evenly-spaced ticks are used +/// If non-NULL, the tick positions are defined by the array +/// with a length defined by nTickDiv +/// \param[in] bTickAbove: If enabled, draw tick marks above/left of the line +/// \param[in] bTickBelow: If enabled, draw tick marks below/right of the line +/// +/// \return none +/// +void gslc_ElemXSliderSetStyleCustom(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef, + uint16_t* anTickPos, bool bTickAbove, bool bTickBelow); /// /// Get a Slider element's current position @@ -149,6 +176,19 @@ void gslc_ElemXSliderSetPos(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,int16_t nP /// void gslc_ElemXSliderSetPosFunc(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,GSLC_CB_XSLIDER_POS funcCb); + +/// +/// Assign user defined ticks for a slider +/// +/// \param[in] pGui: Pointer to GUI +/// \param[in] pElemRef: Pointer to Element reference +/// \param[in] nTickArr: Pointer of dbl types, offset percentages from left side +/// +/// \return none +/// +void gslc_ElemXSliderSetTicks(gslc_tsGui* pGui, gslc_tsElemRef* pElemRef, uint16_t* nTickArr, uint8_t nTickArrLen); + + /// /// Draw a Slider element on the screen /// - Called from gslc_ElemDraw() @@ -229,6 +269,9 @@ bool gslc_ElemXSliderTouch(void* pvGui,void* pvElemRef,gslc_teTouch eTouch,int16 sSlider##nElemId.colTrim = GSLC_COL_BLACK; \ sSlider##nElemId.nPos = nPos_; \ sSlider##nElemId.pfuncXPos = NULL; \ + sSlider##nElemId.eTouch = GSLC_TOUCH_NONE; \ + sSlider##nElemId.nTickArr = GSLC_TOUCH_NONE; \ + sSlider##nElemId.nTickArrLen = 0; \ static const gslc_tsElem sElem##nElemId PROGMEM = { \ nElemId, \ nFeatures##nElemId, \ @@ -276,6 +319,9 @@ bool gslc_ElemXSliderTouch(void* pvGui,void* pvElemRef,gslc_teTouch eTouch,int16 sSlider##nElemId.colTrim = GSLC_COL_BLACK; \ sSlider##nElemId.nPos = nPos_; \ sSlider##nElemId.pfuncXPos = NULL; \ + sSlider##nElemId.eTouch = GSLC_TOUCH_NONE; \ + sSlider##nElemId.nTickArr = GSLC_TOUCH_NONE; \ + sSlider##nElemId.nTickArrLen = 0; \ static const gslc_tsElem sElem##nElemId = { \ nElemId, \ nFeatures##nElemId, \ diff --git a/src/elem/XSpinner.c b/src/elem/XSpinner.c index 02683567e..9e2677edf 100644 --- a/src/elem/XSpinner.c +++ b/src/elem/XSpinner.c @@ -106,7 +106,7 @@ gslc_tsElemRef* gslc_ElemXSpinnerCreate(gslc_tsGui* pGui, int16_t nElemId, int16 nBtnPosY = rElem.y + (rElem.h - nButtonSz) / 2; // set our intial value for our text field - snprintf(acTxtNum, XSPINNER_STR_LEN - 1, "%d", nVal); + snprintf(acTxtNum, XSPINNER_STR_LEN - 1, "%hd", nVal); gslc_tsElem sElem;