serial_debugger/hardware/_controller/src/guislice/XTemplate.c

308 lines
11 KiB
C
Raw Normal View History

// =======================================================================
// GUIslice library (extensions template)
// - Calvin Hass
// - https://www.impulseadventure.com/elec/guislice-gui.html
// - https://github.com/ImpulseAdventure/GUIslice
// =======================================================================
//
// The MIT License
//
// Copyright 2016-2020 Calvin Hass
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// =======================================================================
/// \file XTemplate.c
// GUIslice library
#include "GUIslice.h"
#include "GUIslice_drv.h"
#include "XTemplate.h"
#include <stdio.h>
#if (GSLC_USE_PROGMEM)
#include <avr/pgmspace.h>
#endif
// ----------------------------------------------------------------------------
// Error Messages
// ----------------------------------------------------------------------------
extern const char GSLC_PMEM ERRSTR_NULL[];
extern const char GSLC_PMEM ERRSTR_PXD_NULL[];
// ----------------------------------------------------------------------------
// Extended element definitions
// ----------------------------------------------------------------------------
//
// - This file extends the core GUIslice functionality with
// additional widget types
//
// ----------------------------------------------------------------------------
// ============================================================================
// Extended Element: Template example
// - Demonstrates minimum code to implement an extended element
// ============================================================================
// Create a text element and add it to the GUI element list
// - Defines default styling for the element
// - Defines callback for redraw and touch
gslc_tsElemRef* gslc_ElemXTemplateCreate(gslc_tsGui* pGui, int16_t nElemId, int16_t nPage,
gslc_tsXTemplate* pXData, gslc_tsRect rElem, char* pStrBuf, uint8_t nStrBufMax, int16_t nFontId)
{
if ((pGui == NULL) || (pXData == NULL)) {
static const char GSLC_PMEM FUNCSTR[] = "ElemXTemplateCreate";
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
return NULL;
}
gslc_tsElem sElem;
gslc_tsElemRef* pElemRef = NULL;
sElem = gslc_ElemCreate(pGui,nElemId,nPage,GSLC_TYPEX_TEMPLATE,rElem,pStrBuf,nStrBufMax,nFontId);
sElem.colElemFill = GSLC_COL_BLACK;
sElem.colElemFillGlow = GSLC_COL_BLACK;
sElem.colElemFrame = GSLC_COL_GRAY;
sElem.colElemFrameGlow = GSLC_COL_GRAY;
sElem.colElemText = GSLC_COL_WHITE;
sElem.colElemTextGlow = GSLC_COL_WHITE;
sElem.nFeatures |= GSLC_ELEM_FEA_FILL_EN;
sElem.nFeatures &= ~GSLC_ELEM_FEA_FRAME_EN;
sElem.nFeatures |= GSLC_ELEM_FEA_CLICK_EN;
sElem.nFeatures |= GSLC_ELEM_FEA_GLOW_EN;
sElem.eTxtAlign = GSLC_ALIGN_MID_LEFT;
sElem.nGroup = GSLC_GROUP_ID_NONE;
// TODO:
// - Initialize any pxData members with the constructor parameters
// eg. pXData->nPos = nPos;
sElem.pXData = (void*)(pXData);
// Specify the custom drawing callback
sElem.pfuncXDraw = &gslc_ElemXTemplateDraw;
// Specify the custom touch tracking callback
sElem.pfuncXTouch = &gslc_ElemXTemplateTouch;
if (nPage != GSLC_PAGE_NONE) {
pElemRef = gslc_ElemAdd(pGui,nPage,&sElem,GSLC_ELEMREF_DEFAULT);
return pElemRef;
#if (GSLC_FEATURE_COMPOUND)
} else {
// Save as temporary element
pGui->sElemTmp = sElem;
pGui->sElemRefTmp.pElem = &(pGui->sElemTmp);
pGui->sElemRefTmp.eElemFlags = GSLC_ELEMREF_DEFAULT | GSLC_ELEMREF_REDRAW_FULL;
return &(pGui->sElemRefTmp);
#endif
}
return NULL;
}
// Redraw the element
// - Note that this redraw is for the entire element rect region
// - The Draw function parameters use void pointers to allow for
// simpler callback function definition & scalability.
bool gslc_ElemXTemplateDraw(void* pvGui,void* pvElemRef,gslc_teRedrawType eRedraw)
{
if ((pvGui == NULL) || (pvElemRef == NULL)) {
static const char GSLC_PMEM FUNCSTR[] = "ElemXTemplateDraw";
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
return false;
}
// Typecast the parameters to match the GUI and element types
gslc_tsGui* pGui = (gslc_tsGui*)(pvGui);
gslc_tsElemRef* pElemRef = (gslc_tsElemRef*)(pvElemRef);
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
// Fetch the element's extended data structure
gslc_tsXTemplate* pTemplate = (gslc_tsXTemplate*)(pElem->pXData);
if (pTemplate == NULL) {
GSLC_DEBUG2_PRINT("ERROR: ElemXTemplateDraw(%s) pXData is NULL\n","");
return false;
}
// Template example drawing routine implements formatted text field
// --------------------------------------------------------------------------
// Init for default drawing
// --------------------------------------------------------------------------
bool bGlowEn,bGlowing,bGlowNow;
//int16_t nElemX,nElemY;
//uint16_t nElemW,nElemH;
//nElemX = pElem->rElem.x;
//nElemY = pElem->rElem.y;
//nElemW = pElem->rElem.w;
//nElemH = pElem->rElem.h;
bGlowEn = pElem->nFeatures & GSLC_ELEM_FEA_GLOW_EN; // Does the element support glow state?
bGlowing = gslc_ElemGetGlow(pGui,pElemRef); // Element should be glowing (if enabled)
bGlowNow = bGlowEn & bGlowing; // Element is currently glowing
gslc_tsColor colBg = GSLC_COL_BLACK;
// --------------------------------------------------------------------------
// Background
// --------------------------------------------------------------------------
// Fill in the background
gslc_tsRect rElemInner = pElem->rElem;
// - If both fill and frame are enabled then contract
// the fill region slightly so that we don't overdraw
// the frame (prevent unnecessary flicker).
if ((pElem->nFeatures & GSLC_ELEM_FEA_FILL_EN) && (pElem->nFeatures & GSLC_ELEM_FEA_FRAME_EN)) {
// NOTE: If the region is already too small to shrink (eg. w=1 or h=1)
// then a zero dimension box will be returned by ExpandRect() and not drawn
rElemInner = gslc_ExpandRect(rElemInner,-1,-1);
}
// - This also changes the fill color if selected and glow state is enabled
if (pElem->nFeatures & GSLC_ELEM_FEA_FILL_EN) {
if (bGlowEn && bGlowing) {
colBg = pElem->colElemFillGlow;
} else {
colBg = pElem->colElemFill;
}
if (pElem->nFeatures & GSLC_ELEM_FEA_ROUND_EN) {
gslc_DrawFillRoundRect(pGui, rElemInner, pGui->nRoundRadius, colBg);
} else {
gslc_DrawFillRect(pGui, rElemInner, colBg);
}
} else {
// TODO: If unfilled, then we might need
// to redraw the background layer(s)
}
// --------------------------------------------------------------------------
// Frame
// --------------------------------------------------------------------------
// Frame the region
if (pElem->nFeatures & GSLC_ELEM_FEA_FRAME_EN) {
if (pElem->nFeatures & GSLC_ELEM_FEA_ROUND_EN) {
gslc_DrawFrameRoundRect(pGui, pElem->rElem, pGui->nRoundRadius, pElem->colElemFrame);
} else {
gslc_DrawFrameRect(pGui, pElem->rElem, pElem->colElemFrame);
}
}
// --------------------------------------------------------------------------
// Text overlays
// --------------------------------------------------------------------------
// Draw text string if defined
if (pElem->pStrBuf) {
gslc_tsColor colTxt = (bGlowNow)? pElem->colElemTextGlow : pElem->colElemText;
int8_t nMarginX = pElem->nTxtMarginX;
int8_t nMarginY = pElem->nTxtMarginY;
gslc_DrawTxtBase(pGui, pElem->pStrBuf, pElem->rElem, pElem->pTxtFont, pElem->eTxtFlags,
pElem->eTxtAlign, colTxt, colBg, nMarginX, nMarginY);
}
// --------------------------------------------------------------------------
// Mark the element as no longer requiring redraw
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_NONE);
return true;
}
// This callback function is called by gslc_ElemSendEventTouch()
// after any touch event
bool gslc_ElemXTemplateTouch(void* pvGui,void* pvElemRef,gslc_teTouch eTouch,int16_t nRelX,int16_t nRelY)
{
#if defined(DRV_TOUCH_NONE)
return false;
#else
// Define any specific touch handling here
if ((pvGui == NULL) || (pvElemRef == NULL)) {
static const char GSLC_PMEM FUNCSTR[] = "ElemXTemplateTouch";
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
return false;
}
gslc_tsGui* pGui = NULL;
gslc_tsElemRef* pElemRef = NULL;
//gslc_tsElem* pElem = NULL;
//gslc_tsXTemplate* pTemplate = NULL;
// Typecast the parameters to match the GUI
pGui = (gslc_tsGui*)(pvGui);
pElemRef = (gslc_tsElemRef*)(pvElemRef);
//pElem = gslc_GetElemFromRef(pGui,pElemRef);
//pTemplate = (gslc_tsXTemplate*)(pElem->pXData);
bool bGlowingOld = gslc_ElemGetGlow(pGui,pElemRef);
// Example touch handler simply tracks "glowing" status
switch(eTouch) {
case GSLC_TOUCH_DOWN_IN:
// Start glowing as must be over it
gslc_ElemSetGlow(pGui,pElemRef,true);
break;
case GSLC_TOUCH_MOVE_IN:
gslc_ElemSetGlow(pGui,pElemRef,true);
break;
case GSLC_TOUCH_MOVE_OUT:
gslc_ElemSetGlow(pGui,pElemRef,false);
break;
case GSLC_TOUCH_UP_IN:
// End glow
gslc_ElemSetGlow(pGui,pElemRef,false);
break;
case GSLC_TOUCH_UP_OUT:
// End glow
gslc_ElemSetGlow(pGui,pElemRef,false);
break;
case GSLC_TOUCH_SET_REL:
case GSLC_TOUCH_SET_ABS:
gslc_ElemSetGlow(pGui,pElemRef,true);
break;
default:
return false;
break;
}
// If the slider changed state, redraw
if (gslc_ElemGetGlow(pGui,pElemRef) != bGlowingOld) {
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_FULL);
}
return true;
#endif // !DRV_TOUCH_NONE
}
// ============================================================================