518 lines
18 KiB
C
518 lines
18 KiB
C
|
// =======================================================================
|
||
|
// GUIslice library (extensions)
|
||
|
// - 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 XCheckbox.c
|
||
|
|
||
|
|
||
|
|
||
|
// GUIslice library
|
||
|
#include "GUIslice.h"
|
||
|
#include "GUIslice_drv.h"
|
||
|
|
||
|
#include "XCheckbox.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: Checkbox
|
||
|
// - Checkbox with custom handler for touch tracking which
|
||
|
// enables glow to be defined whenever touch is tracked over
|
||
|
// the element.
|
||
|
// ============================================================================
|
||
|
|
||
|
// Create a checkbox element and add it to the GUI element list
|
||
|
// - Defines default styling for the element
|
||
|
// - Defines callback for redraw but does not track touch/click
|
||
|
gslc_tsElemRef* gslc_ElemXCheckboxCreate(gslc_tsGui* pGui,int16_t nElemId,int16_t nPage,
|
||
|
gslc_tsXCheckbox* pXData,gslc_tsRect rElem,bool bRadio,gslc_teXCheckboxStyle nStyle,
|
||
|
gslc_tsColor colCheck,bool bChecked)
|
||
|
{
|
||
|
if ((pGui == NULL) || (pXData == NULL)) {
|
||
|
static const char GSLC_PMEM FUNCSTR[] = "ElemXCheckboxCreate";
|
||
|
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||
|
return NULL;
|
||
|
}
|
||
|
gslc_tsElem sElem;
|
||
|
gslc_tsElemRef* pElemRef = NULL;
|
||
|
sElem = gslc_ElemCreate(pGui,nElemId,nPage,GSLC_TYPEX_CHECKBOX,rElem,NULL,0,GSLC_FONT_NONE);
|
||
|
sElem.nFeatures &= ~GSLC_ELEM_FEA_FRAME_EN;
|
||
|
sElem.nFeatures |= GSLC_ELEM_FEA_FILL_EN;
|
||
|
sElem.nFeatures |= GSLC_ELEM_FEA_CLICK_EN;
|
||
|
sElem.nFeatures |= GSLC_ELEM_FEA_GLOW_EN;
|
||
|
|
||
|
// Default group assignment. Can override later with ElemSetGroup()
|
||
|
sElem.nGroup = GSLC_GROUP_ID_NONE;
|
||
|
|
||
|
// Define other extended data
|
||
|
pXData->bRadio = bRadio;
|
||
|
pXData->bChecked = bChecked;
|
||
|
pXData->colCheck = colCheck;
|
||
|
pXData->nStyle = nStyle;
|
||
|
pXData->pfuncXToggle = NULL;
|
||
|
sElem.pXData = (void*)(pXData);
|
||
|
// Specify the custom drawing callback
|
||
|
sElem.pfuncXDraw = &gslc_ElemXCheckboxDraw;
|
||
|
// Specify the custom touch tracking callback
|
||
|
// - NOTE: This is optional (and can be set to NULL).
|
||
|
// See the discussion under gslc_ElemXCheckboxTouch()
|
||
|
sElem.pfuncXTouch = &gslc_ElemXCheckboxTouch;
|
||
|
sElem.colElemFill = GSLC_COL_BLACK;
|
||
|
sElem.colElemFillGlow = GSLC_COL_BLACK;
|
||
|
sElem.colElemFrame = GSLC_COL_GRAY;
|
||
|
sElem.colElemFrameGlow = GSLC_COL_WHITE;
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
bool gslc_ElemXCheckboxGetState(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef)
|
||
|
{
|
||
|
gslc_tsXCheckbox* pCheckbox = (gslc_tsXCheckbox*)gslc_GetXDataFromRef(pGui, pElemRef, GSLC_TYPEX_CHECKBOX, __LINE__);
|
||
|
if (!pCheckbox) return false;
|
||
|
|
||
|
return pCheckbox->bChecked;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Determine which checkbox in the group has been "checked"
|
||
|
gslc_tsElemRef* gslc_ElemXCheckboxFindChecked(gslc_tsGui* pGui,int16_t nGroupId)
|
||
|
{
|
||
|
int16_t nCurInd;
|
||
|
gslc_tsElemRef* pCurElemRef = NULL;
|
||
|
gslc_tsElem* pCurElem = NULL;
|
||
|
int16_t nCurType;
|
||
|
int16_t nCurGroup;
|
||
|
bool bCurChecked;
|
||
|
gslc_tsElemRef* pFoundElemRef = NULL;
|
||
|
|
||
|
// Operate on current page
|
||
|
// TODO: Support other page layers
|
||
|
gslc_tsPage* pPage = pGui->apPageStack[GSLC_STACK_CUR];
|
||
|
if (pPage == NULL) {
|
||
|
return NULL; // No page added yet
|
||
|
}
|
||
|
|
||
|
if (pGui == NULL) {
|
||
|
static const char GSLC_PMEM FUNCSTR[] = "ElemXCheckboxFindChecked";
|
||
|
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
gslc_tsCollect* pCollect = &pPage->sCollect;
|
||
|
for (nCurInd=0;nCurInd<pCollect->nElemCnt;nCurInd++) {
|
||
|
// Fetch extended data
|
||
|
pCurElemRef = &(pCollect->asElemRef[nCurInd]);
|
||
|
pCurElem = gslc_GetElemFromRef(pGui,pCurElemRef);
|
||
|
nCurType = pCurElem->nType;
|
||
|
// Only want to proceed if it is a checkbox
|
||
|
if (nCurType != GSLC_TYPEX_CHECKBOX) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
nCurGroup = pCurElem->nGroup;
|
||
|
bCurChecked = gslc_ElemXCheckboxGetState(pGui,pCurElemRef);
|
||
|
|
||
|
// If this is in a different group, ignore it
|
||
|
if (nCurGroup != nGroupId) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Did we find an element in the group that was checked?
|
||
|
if (bCurChecked) {
|
||
|
pFoundElemRef = pCurElemRef;
|
||
|
break;
|
||
|
}
|
||
|
} // nCurInd
|
||
|
return pFoundElemRef;
|
||
|
}
|
||
|
|
||
|
// Assign the callback function for checkbox/radio state change events
|
||
|
void gslc_ElemXCheckboxSetStateFunc(gslc_tsGui* pGui, gslc_tsElemRef* pElemRef, GSLC_CB_XCHECKBOX pfuncCb)
|
||
|
{
|
||
|
gslc_tsXCheckbox* pCheckbox = (gslc_tsXCheckbox*)gslc_GetXDataFromRef(pGui, pElemRef, GSLC_TYPEX_CHECKBOX, __LINE__);
|
||
|
if (!pCheckbox) return;
|
||
|
|
||
|
pCheckbox->pfuncXToggle = pfuncCb;
|
||
|
}
|
||
|
|
||
|
// Helper routine for gslc_ElemXCheckboxSetState()
|
||
|
// - Updates the checkbox/radio control's state but does
|
||
|
// not touch any other controls in the group
|
||
|
void gslc_ElemXCheckboxSetStateHelp(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,bool bChecked,bool bDoCb)
|
||
|
{
|
||
|
gslc_tsXCheckbox* pCheckbox = (gslc_tsXCheckbox*)gslc_GetXDataFromRef(pGui, pElemRef, GSLC_TYPEX_CHECKBOX, __LINE__);
|
||
|
if (!pCheckbox) return;
|
||
|
|
||
|
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||
|
|
||
|
// Update our data element
|
||
|
bool const bCheckedOld = pCheckbox->bChecked;
|
||
|
pCheckbox->bChecked = bChecked;
|
||
|
|
||
|
// Element needs redraw
|
||
|
if (bChecked != bCheckedOld) {
|
||
|
// Only need an incremental redraw
|
||
|
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_INC);
|
||
|
} else {
|
||
|
// Same state as before
|
||
|
// - No need to do anything further since we don't need to
|
||
|
// trigger any callbacks or redraw
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// If no callbacks requested, exit now
|
||
|
if (!bDoCb) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// If any state callback is defined, call it now
|
||
|
// - In all cases, return the ElementRef of the element that issued the callback
|
||
|
//
|
||
|
// For checkbox:
|
||
|
// - If not selected: return current ID and state=false
|
||
|
// - If selected: return current ID and state=true
|
||
|
// For radio button:
|
||
|
// - If none selected: return ID_NONE and state=false
|
||
|
// - If one selected: return selected ID and state=true
|
||
|
if (pCheckbox->pfuncXToggle != NULL) {
|
||
|
gslc_tsElemRef* pRetRef = NULL;
|
||
|
int16_t nGroup = GSLC_GROUP_ID_NONE;
|
||
|
int16_t nSelId = GSLC_ID_NONE;
|
||
|
if (!pCheckbox->bRadio) {
|
||
|
// Checkbox
|
||
|
nSelId = pElem->nId;
|
||
|
} else {
|
||
|
// Radio button
|
||
|
// - Determine the group that the radio button belongs to
|
||
|
nGroup = pElem->nGroup;
|
||
|
// Determine if any radio button in the group has been selected
|
||
|
pRetRef = gslc_ElemXCheckboxFindChecked(pGui, nGroup);
|
||
|
if (pRetRef != NULL) {
|
||
|
// One has been selected, return its ID
|
||
|
bChecked = true;
|
||
|
nSelId = pRetRef->pElem->nId;
|
||
|
} else {
|
||
|
// No radio button selected, return ID NONE
|
||
|
bChecked = false;
|
||
|
nSelId = GSLC_ID_NONE;
|
||
|
}
|
||
|
}
|
||
|
// Now send the callback notification
|
||
|
(*pCheckbox->pfuncXToggle)((void*)(pGui), (void*)(pElemRef), nSelId, bChecked);
|
||
|
} // pfuncXToggle
|
||
|
|
||
|
}
|
||
|
|
||
|
// Update the checkbox/radio control's state. If it is a radio button
|
||
|
// then also update the state of all other buttons in the group.
|
||
|
void gslc_ElemXCheckboxSetState(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,bool bChecked)
|
||
|
{
|
||
|
gslc_tsXCheckbox* pCheckbox = (gslc_tsXCheckbox*)gslc_GetXDataFromRef(pGui, pElemRef, GSLC_TYPEX_CHECKBOX, __LINE__);
|
||
|
if (!pCheckbox) return;
|
||
|
|
||
|
|
||
|
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||
|
gslc_tsPage* pPage = NULL;
|
||
|
|
||
|
bool bRadio = pCheckbox->bRadio;
|
||
|
int16_t nGroup = pElem->nGroup;
|
||
|
int16_t nElemId = pElem->nId;
|
||
|
|
||
|
// Special handling when we select a radio button
|
||
|
if (bRadio && bChecked) {
|
||
|
|
||
|
// If we are selecting a radio button that is already
|
||
|
// selected, then skip further update events.
|
||
|
// NOTE: This check is not very efficient, but it avoids
|
||
|
// the creation of extra events.
|
||
|
gslc_tsElemRef* pTmpRef = gslc_ElemXCheckboxFindChecked(pGui, nGroup);
|
||
|
if (pTmpRef == pElemRef) {
|
||
|
// Same element, so skip
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Proceed to deselect any other selected items in the group.
|
||
|
// Note that SetState calls itself to deselect other items so it
|
||
|
// is important to qualify this logic with bChecked=true
|
||
|
int16_t nCurInd;
|
||
|
int16_t nCurId;
|
||
|
gslc_tsElem* pCurElem = NULL;
|
||
|
gslc_tsElemRef* pCurElemRef = NULL;
|
||
|
int16_t nCurType;
|
||
|
int16_t nCurGroup;
|
||
|
|
||
|
// We use the GUI pointer for access to other elements
|
||
|
|
||
|
// Check all pages in case we are affecting radio buttons on other pages
|
||
|
for (int8_t nPageInd=0;nPageInd<pGui->nPageCnt;nPageInd++) {
|
||
|
pPage = &pGui->asPage[nPageInd];
|
||
|
if (!pPage) {
|
||
|
// If this stack page is not enabled, skip to next stack page
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
gslc_tsCollect* pCollect = &pPage->sCollect;
|
||
|
for (nCurInd=0;nCurInd<pCollect->nElemRefCnt;nCurInd++) {
|
||
|
// Fetch extended data
|
||
|
pCurElemRef = &pCollect->asElemRef[nCurInd];
|
||
|
pCurElem = gslc_GetElemFromRef(pGui,pCurElemRef);
|
||
|
|
||
|
// FIXME: Handle pCurElemRef->eElemFlags
|
||
|
nCurId = pCurElem->nId;
|
||
|
nCurType = pCurElem->nType;
|
||
|
|
||
|
// Only want to proceed if it is a checkbox
|
||
|
if (nCurType != GSLC_TYPEX_CHECKBOX) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
nCurGroup = pCurElem->nGroup;
|
||
|
|
||
|
// If this is in a different group, ignore it
|
||
|
if (nCurGroup != nGroup) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Is this our element? If so, ignore the deselect operation
|
||
|
if (nCurId == nElemId) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Deselect all other elements
|
||
|
// - But don't trigger any callbacks
|
||
|
gslc_ElemXCheckboxSetStateHelp(pGui,pCurElemRef,false,false);
|
||
|
|
||
|
} // nInd
|
||
|
} // nStackPage
|
||
|
|
||
|
} // bRadio
|
||
|
|
||
|
// Set the state of the current element
|
||
|
// - Trigger callback if enabled
|
||
|
gslc_ElemXCheckboxSetStateHelp(pGui,pElemRef,bChecked,true);
|
||
|
}
|
||
|
|
||
|
// Toggle the checkbox control's state
|
||
|
void gslc_ElemXCheckboxToggleState(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef)
|
||
|
{
|
||
|
if (pElemRef == NULL) {
|
||
|
static const char GSLC_PMEM FUNCSTR[] = "ElemXCheckboxToggleState";
|
||
|
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||
|
return;
|
||
|
}
|
||
|
// Update the data element
|
||
|
bool bCheckNew = (gslc_ElemXCheckboxGetState(pGui,pElemRef))? false : true;
|
||
|
gslc_ElemXCheckboxSetState(pGui,pElemRef,bCheckNew);
|
||
|
|
||
|
// Element needs redraw
|
||
|
// - Only incremental is needed
|
||
|
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_INC);
|
||
|
}
|
||
|
|
||
|
// Redraw the checkbox
|
||
|
// - 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_ElemXCheckboxDraw(void* pvGui,void* pvElemRef,gslc_teRedrawType eRedraw)
|
||
|
{
|
||
|
// Typecast the parameters to match the GUI and element types
|
||
|
gslc_tsGui* pGui = (gslc_tsGui*)(pvGui);
|
||
|
gslc_tsElemRef* pElemRef = (gslc_tsElemRef*)(pvElemRef);
|
||
|
|
||
|
gslc_tsXCheckbox* pCheckbox = (gslc_tsXCheckbox*)gslc_GetXDataFromRef(pGui, pElemRef, GSLC_TYPEX_CHECKBOX, __LINE__);
|
||
|
if (!pCheckbox) return false;
|
||
|
|
||
|
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||
|
gslc_tsRect rInner;
|
||
|
|
||
|
bool bChecked = pCheckbox->bChecked;
|
||
|
gslc_teXCheckboxStyle nStyle = pCheckbox->nStyle;
|
||
|
bool bGlow = (pElem->nFeatures & GSLC_ELEM_FEA_GLOW_EN) && gslc_ElemGetGlow(pGui,pElemRef);
|
||
|
|
||
|
// Draw the background
|
||
|
gslc_DrawFillRect(pGui,pElem->rElem,pElem->colElemFill);
|
||
|
|
||
|
// Generic coordinate calcs
|
||
|
int16_t nX0,nY0,nX1,nY1,nMidX,nMidY;
|
||
|
nX0 = pElem->rElem.x;
|
||
|
nY0 = pElem->rElem.y;
|
||
|
nX1 = pElem->rElem.x + pElem->rElem.w - 1;
|
||
|
nY1 = pElem->rElem.y + pElem->rElem.h - 1;
|
||
|
nMidX = (nX0+nX1)/2;
|
||
|
nMidY = (nY0+nY1)/2;
|
||
|
if (nStyle == GSLCX_CHECKBOX_STYLE_BOX) {
|
||
|
// Draw the center indicator if checked
|
||
|
rInner = gslc_ExpandRect(pElem->rElem,-5,-5);
|
||
|
if (bChecked) {
|
||
|
// If checked, fill in the inner region
|
||
|
gslc_DrawFillRect(pGui,rInner,pCheckbox->colCheck);
|
||
|
} else {
|
||
|
// Assume the background fill has already been done so
|
||
|
// we don't need to do anything more in the unchecked case
|
||
|
}
|
||
|
// Draw a frame around the checkbox
|
||
|
gslc_DrawFrameRect(pGui,pElem->rElem,(bGlow)?pElem->colElemFrameGlow:pElem->colElemFrame);
|
||
|
|
||
|
} else if (nStyle == GSLCX_CHECKBOX_STYLE_X) {
|
||
|
// Draw an X through center if checked
|
||
|
if (bChecked) {
|
||
|
gslc_DrawLine(pGui,nX0,nY0,nX1,nY1,pCheckbox->colCheck);
|
||
|
gslc_DrawLine(pGui,nX0,nY1,nX1,nY0,pCheckbox->colCheck);
|
||
|
}
|
||
|
// Draw a frame around the checkbox
|
||
|
gslc_DrawFrameRect(pGui,pElem->rElem,(bGlow)?pElem->colElemFrameGlow:pElem->colElemFrame);
|
||
|
|
||
|
} else if (nStyle == GSLCX_CHECKBOX_STYLE_ROUND) {
|
||
|
// Draw inner circle if checked
|
||
|
if (bChecked) {
|
||
|
gslc_DrawFillCircle(pGui,nMidX,nMidY,5,pCheckbox->colCheck);
|
||
|
}
|
||
|
// Draw a frame around the checkbox
|
||
|
gslc_DrawFrameCircle(pGui,nMidX,nMidY,(pElem->rElem.w/2),(bGlow)?pElem->colElemFrameGlow:pElem->colElemFrame);
|
||
|
|
||
|
}
|
||
|
|
||
|
// Clear the redraw flag
|
||
|
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_NONE);
|
||
|
|
||
|
// Mark page as needing flip
|
||
|
gslc_PageFlipSet(pGui,true);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// This callback function is called by gslc_ElemSendEventTouch()
|
||
|
// after any touch event
|
||
|
// - NOTE: Adding this touch callback is optional. Without it, we
|
||
|
// can still have a functional checkbox, but doing the touch
|
||
|
// tracking allows us to change the glow state of the element
|
||
|
// dynamically, as well as updating the checkbox state if the
|
||
|
// user releases over it (ie. a click event).
|
||
|
//
|
||
|
bool gslc_ElemXCheckboxTouch(void* pvGui,void* pvElemRef,gslc_teTouch eTouch,int16_t nRelX,int16_t nRelY)
|
||
|
{
|
||
|
#if defined(DRV_TOUCH_NONE)
|
||
|
return false;
|
||
|
#else
|
||
|
|
||
|
// Typecast the parameters to match the GUI and element types
|
||
|
gslc_tsGui* pGui = (gslc_tsGui*)(pvGui);
|
||
|
gslc_tsElemRef* pElemRef = (gslc_tsElemRef*)(pvElemRef);
|
||
|
|
||
|
gslc_tsXCheckbox* pCheckbox = (gslc_tsXCheckbox*)gslc_GetXDataFromRef(pGui, pElemRef, GSLC_TYPEX_CHECKBOX, __LINE__);
|
||
|
if (!pCheckbox) return false;
|
||
|
|
||
|
//gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||
|
|
||
|
bool bRadio = pCheckbox->bRadio;
|
||
|
bool bCheckedOld = pCheckbox->bChecked;
|
||
|
bool bGlowingOld = gslc_ElemGetGlow(pGui,pElemRef);
|
||
|
|
||
|
switch(eTouch) {
|
||
|
|
||
|
case GSLC_TOUCH_DOWN_IN:
|
||
|
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:
|
||
|
gslc_ElemSetGlow(pGui,pElemRef,false);
|
||
|
// Now that we released on element, update the state
|
||
|
bool bCheckNew;
|
||
|
if (bRadio) {
|
||
|
// Radio button action: set
|
||
|
bCheckNew = true;
|
||
|
} else {
|
||
|
// Checkbox button action: toggle
|
||
|
bCheckNew = (pCheckbox->bChecked)?false:true;
|
||
|
}
|
||
|
gslc_ElemXCheckboxSetState(pGui,pElemRef,bCheckNew);
|
||
|
break;
|
||
|
case GSLC_TOUCH_UP_OUT:
|
||
|
gslc_ElemSetGlow(pGui,pElemRef,false);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return false;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// If the checkbox changed state, redraw
|
||
|
bool bChanged = false;
|
||
|
if (gslc_ElemGetGlow(pGui,pElemRef) != bGlowingOld) { bChanged = true; }
|
||
|
if (pCheckbox->bChecked != bCheckedOld) { bChanged = true; }
|
||
|
if (bChanged) {
|
||
|
// Incremental redraw
|
||
|
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_INC);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
#endif // !DRV_TOUCH_NONE
|
||
|
}
|
||
|
|
||
|
// ============================================================================
|