Skip to content

Commit

Permalink
Add element visibility API #24 w/o selective redraw
Browse files Browse the repository at this point in the history
- New API: ElemSetShow()
- NOTE: This implementation triggers full-page redraw when an element is hidden. Future implementations will perform selective redraw of revealed regions.
- ElemRefFlags updated to add GSLC_ELEMREF_SHOW
- Create default ElemRefFlags GSLC_ELEMREF_DEFAULT
  • Loading branch information
ImpulseAdventure committed Jan 16, 2019
1 parent b60f841 commit ebca38d
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 22 deletions.
5 changes: 4 additions & 1 deletion examples/arduino/ex04_ard_ctrls/ex04_ard_ctrls.ino
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ bool CbCheckbox(void* pvGui, void* pvElemRef, int16_t nSelId, bool bChecked)
switch (pElem->nId) {
case E_ELEM_CHECK1:
GSLC_DEBUG_PRINT("Callback: Check[ID=%d] state=%u\n", pElem->nId,bChecked);
// Demonstrate changing visibility of another element
gslc_ElemSetShow(pGui, m_pElemProgress1, bChecked);
break;
case E_ELEM_RADIO1:
case E_ELEM_RADIO2:
Expand All @@ -126,6 +128,7 @@ bool CbCheckbox(void* pvGui, void* pvElemRef, int16_t nSelId, bool bChecked)
default:
break;
} // switch
return true;
}


Expand Down Expand Up @@ -176,7 +179,7 @@ bool InitOverlays()
pElemRef = gslc_ElemCreateTxt(&m_gui,GSLC_ID_AUTO,E_PG_MAIN,(gslc_tsRect){20,100,20,20},
(char*)"Check1:",0,E_FONT_TXT);
pElemRef = gslc_ElemXCheckboxCreate(&m_gui,E_ELEM_CHECK1,E_PG_MAIN,&m_asXCheck[0],
(gslc_tsRect){80,100,20,20},false,GSLCX_CHECKBOX_STYLE_X,GSLC_COL_BLUE_LT2,false);
(gslc_tsRect){80,100,20,20},false,GSLCX_CHECKBOX_STYLE_X,GSLC_COL_BLUE_LT2,true);
gslc_ElemXCheckboxSetStateFunc(&m_gui, pElemRef, &CbCheckbox);

// Create radio 1
Expand Down
62 changes: 59 additions & 3 deletions examples/linux/ex04_lnx_ctrls.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
// - https://www.impulseadventure.com/elec/guislice-gui.html
// - https://github.com/ImpulseAdventure/GUIslice
// - Example 04 (LINUX): Dynamic content
// Demonstrates push buttons, checkboxes and slider controls
// - Demonstrates push buttons, checkboxes and slider controls
// - Shows callback notifications for checkboxes and radio buttons
//

#include "GUIslice.h"
Expand Down Expand Up @@ -49,6 +50,13 @@ gslc_tsXSlider m_sXSlider;
// Enable frame/update rate reporting? (1 to enable, 0 to disable)
#define TEST_UPDATE_RATE 0

// Save some element references for quick access
gslc_tsElemRef* m_pElemCnt = NULL;
gslc_tsElemRef* m_pElemProgress = NULL;
gslc_tsElemRef* m_pElemProgress1 = NULL;
gslc_tsElemRef* m_pElemSlider = NULL;


// Configure environment variables suitable for display
// - These may need modification to match your system
// environment and display type
Expand Down Expand Up @@ -78,14 +86,55 @@ void UserInitEnv()
static int16_t DebugOut(char ch) { fputc(ch,stderr); return 0; }

// Button callbacks
bool CbBtnQuit(void* pvGui,void *pvElemRef,gslc_teTouch eTouch,int16_t nX,int16_t nY)
// - Detect a button press
// - In this particular example, we are looking for the Quit button press
// which is used to terminate the program.
bool CbBtnQuit(void* pvGui,void *pvElem,gslc_teTouch eTouch,int16_t nX,int16_t nY)
{
if (eTouch == GSLC_TOUCH_UP_IN) {
m_bQuit = true;
}
return true;
}

// Checkbox / radio callbacks
// - Creating a callback function is optional, but doing so enables you to
// detect changes in the state of the elements.
bool CbCheckbox(void* pvGui, void* pvElemRef, int16_t nSelId, bool bChecked)
{
gslc_tsGui* pGui = (gslc_tsGui*)(pvGui);
gslc_tsElemRef* pElemRef = (gslc_tsElemRef*)(pvElemRef);
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
if (pElemRef == NULL) {
return false;
}

// Determine which element issued the callback
switch (pElem->nId) {
case E_ELEM_CHECK1:
GSLC_DEBUG_PRINT("Callback: Check[ID=%d] state=%u\n", pElem->nId,bChecked);
// Demonstrate changing visibility of another element
gslc_ElemSetShow(pGui, m_pElemProgress1, bChecked);
break;
case E_ELEM_RADIO1:
case E_ELEM_RADIO2:
// For the radio buttons, determine which ID is currently selected (nSelId)
// - Note that this may not always be the same as the element that
// issued the callback (pElem->nId)
// - A return value of GSLC_ID_NONE indicates that no radio buttons
// in the group are currently selected
if (nSelId == GSLC_ID_NONE) {
GSLC_DEBUG_PRINT("Callback: Radio[ID=NONE] selected\n", "");
} else {
GSLC_DEBUG_PRINT("Callback: Radio[ID=%d] selected\n", nSelId);
}
break;
default:
break;
} // switch
return true;
}


// Create page elements
bool InitOverlays()
Expand Down Expand Up @@ -113,44 +162,51 @@ bool InitOverlays()
pElemRef = gslc_ElemCreateTxt(&m_gui,E_ELEM_TXT_COUNT,E_PG_MAIN,(gslc_tsRect){80,60,50,10},
"",0,E_FONT_TXT);
gslc_ElemSetTxtCol(&m_gui,pElemRef,GSLC_COL_YELLOW);
m_pElemCnt = pElemRef; // Save for quick access

// Create progress bar (horizontal)
pElemRef = gslc_ElemCreateTxt(&m_gui,GSLC_ID_AUTO,E_PG_MAIN,(gslc_tsRect){20,80,50,10},
"Progress:",0,E_FONT_TXT);
pElemRef = gslc_ElemXGaugeCreate(&m_gui,E_ELEM_PROGRESS,E_PG_MAIN,&m_sXGauge,
(gslc_tsRect){80,80,50,10},0,100,0,GSLC_COL_GREEN,false);
m_pElemProgress = pElemRef; // Save for quick access

// Second progress bar (vertical)
// - Demonstration of vertical bar with offset zero-pt showing both positive and negative range
pElemRef = gslc_ElemXGaugeCreate(&m_gui,E_ELEM_PROGRESS1,E_PG_MAIN,&m_sXGauge1,
(gslc_tsRect){280,80,10,100},-25,75,-15,GSLC_COL_RED,true);
gslc_ElemSetCol(&m_gui,pElemRef,GSLC_COL_BLUE_DK3,GSLC_COL_BLACK,GSLC_COL_BLACK);
m_pElemProgress1 = pElemRef; // Save for quick access

// Create checkbox 1
pElemRef = gslc_ElemCreateTxt(&m_gui,GSLC_ID_AUTO,E_PG_MAIN,(gslc_tsRect){20,100,20,20},
"Check1:",0,E_FONT_TXT);
pElemRef = gslc_ElemXCheckboxCreate(&m_gui,E_ELEM_CHECK1,E_PG_MAIN,&m_asXCheck[0],
(gslc_tsRect){80,100,20,20},false,GSLCX_CHECKBOX_STYLE_X,GSLC_COL_BLUE_LT2,false);
(gslc_tsRect){80,100,20,20},false,GSLCX_CHECKBOX_STYLE_X,GSLC_COL_BLUE_LT2,true);
gslc_ElemXCheckboxSetStateFunc(&m_gui, pElemRef, &CbCheckbox);

// Create radio 1
pElemRef = gslc_ElemCreateTxt(&m_gui,GSLC_ID_AUTO,E_PG_MAIN,(gslc_tsRect){20,135,20,20},
"Radio1:",0,E_FONT_TXT);
pElemRef = gslc_ElemXCheckboxCreate(&m_gui,E_ELEM_RADIO1,E_PG_MAIN,&m_asXCheck[1],
(gslc_tsRect){80,135,20,20},true,GSLCX_CHECKBOX_STYLE_ROUND,GSLC_COL_ORANGE,false);
gslc_ElemSetGroup(&m_gui,pElemRef,E_GROUP1);
gslc_ElemXCheckboxSetStateFunc(&m_gui, pElemRef, &CbCheckbox);

// Create radio 2
pElemRef = gslc_ElemCreateTxt(&m_gui,GSLC_ID_AUTO,E_PG_MAIN,(gslc_tsRect){20,160,20,20},
"Radio2:",0,E_FONT_TXT);
pElemRef = gslc_ElemXCheckboxCreate(&m_gui,E_ELEM_RADIO2,E_PG_MAIN,&m_asXCheck[2],
(gslc_tsRect){80,160,20,20},true,GSLCX_CHECKBOX_STYLE_ROUND,GSLC_COL_ORANGE,false);
gslc_ElemSetGroup(&m_gui,pElemRef,E_GROUP1);
gslc_ElemXCheckboxSetStateFunc(&m_gui, pElemRef, &CbCheckbox);

// Create slider
pElemRef = gslc_ElemXSliderCreate(&m_gui,E_ELEM_SLIDER,E_PG_MAIN,&m_sXSlider,
(gslc_tsRect){160,140,100,20},0,100,60,5,false);
gslc_ElemXSliderSetStyle(&m_gui,pElemRef,true,(gslc_tsColor){0,0,128},10,
5,(gslc_tsColor){64,64,64});
m_pElemSlider = pElemRef; // Save for quick access
pElemRef = gslc_ElemCreateTxt(&m_gui,E_ELEM_TXT_SLIDER,E_PG_MAIN,(gslc_tsRect){160,160,80,20},
"Slider: ???",0,E_FONT_TXT);

Expand Down
71 changes: 59 additions & 12 deletions src/GUIslice.c
Original file line number Diff line number Diff line change
Expand Up @@ -2000,14 +2000,14 @@ gslc_tsElemRef* gslc_ElemCreateTxt(gslc_tsGui* pGui,int16_t nElemId,int16_t nPag
sElem.nFeatures |= GSLC_ELEM_FEA_FILL_EN;
sElem.eTxtAlign = GSLC_ALIGN_MID_LEFT;
if (nPage != GSLC_PAGE_NONE) {
pElemRef = gslc_ElemAdd(pGui,nPage,&sElem,GSLC_ELEMREF_SRC_RAM);
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_SRC_RAM | GSLC_ELEMREF_REDRAW_FULL;
pGui->sElemRefTmp.eElemFlags = GSLC_ELEMREF_DEFAULT | GSLC_ELEMREF_REDRAW_FULL;
return &(pGui->sElemRefTmp);
#endif
}
Expand Down Expand Up @@ -2039,14 +2039,14 @@ gslc_tsElemRef* gslc_ElemCreateBtnTxt(gslc_tsGui* pGui,int16_t nElemId,int16_t n
sElem.nFeatures |= GSLC_ELEM_FEA_GLOW_EN;
sElem.pfuncXTouch = cbTouch;
if (nPage != GSLC_PAGE_NONE) {
pElemRef = gslc_ElemAdd(pGui,nPage,&sElem,GSLC_ELEMREF_SRC_RAM);
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_SRC_RAM | GSLC_ELEMREF_REDRAW_FULL;
pGui->sElemRefTmp.eElemFlags = GSLC_ELEMREF_DEFAULT | GSLC_ELEMREF_REDRAW_FULL;
return &(pGui->sElemRefTmp);
#endif
}
Expand All @@ -2072,14 +2072,14 @@ gslc_tsElemRef* gslc_ElemCreateBtnImg(gslc_tsGui* pGui,int16_t nElemId,int16_t n
gslc_DrvSetElemImageNorm(pGui,&sElem,sImgRef);
gslc_DrvSetElemImageGlow(pGui,&sElem,sImgRefSel);
if (nPage != GSLC_PAGE_NONE) {
pElemRef = gslc_ElemAdd(pGui,nPage,&sElem,GSLC_ELEMREF_SRC_RAM);
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_SRC_RAM | GSLC_ELEMREF_REDRAW_FULL;
pGui->sElemRefTmp.eElemFlags = GSLC_ELEMREF_DEFAULT | GSLC_ELEMREF_REDRAW_FULL;
return &(pGui->sElemRefTmp);
#endif
}
Expand All @@ -2099,14 +2099,14 @@ gslc_tsElemRef* gslc_ElemCreateBox(gslc_tsGui* pGui,int16_t nElemId,int16_t nPag
sElem.nFeatures |= GSLC_ELEM_FEA_FILL_EN;
sElem.nFeatures |= GSLC_ELEM_FEA_FRAME_EN;
if (nPage != GSLC_PAGE_NONE) {
pElemRef = gslc_ElemAdd(pGui,nPage,&sElem,GSLC_ELEMREF_SRC_RAM);
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_SRC_RAM | GSLC_ELEMREF_REDRAW_FULL;
pGui->sElemRefTmp.eElemFlags = GSLC_ELEMREF_DEFAULT | GSLC_ELEMREF_REDRAW_FULL;
return &(pGui->sElemRefTmp);
#endif
}
Expand All @@ -2129,14 +2129,14 @@ gslc_tsElemRef* gslc_ElemCreateLine(gslc_tsGui* pGui,int16_t nElemId,int16_t nPa
sElem.nFeatures &= ~GSLC_ELEM_FEA_FILL_EN; // Disable boundary box fill
sElem.nFeatures &= ~GSLC_ELEM_FEA_FRAME_EN; // Disable boundary box frame
if (nPage != GSLC_PAGE_NONE) {
pElemRef = gslc_ElemAdd(pGui,nPage,&sElem,GSLC_ELEMREF_SRC_RAM);
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_SRC_RAM | GSLC_ELEMREF_REDRAW_FULL;
pGui->sElemRefTmp.eElemFlags = GSLC_ELEMREF_DEFAULT | GSLC_ELEMREF_REDRAW_FULL;
return &(pGui->sElemRefTmp);
#endif
}
Expand All @@ -2157,14 +2157,14 @@ gslc_tsElemRef* gslc_ElemCreateImg(gslc_tsGui* pGui,int16_t nElemId,int16_t nPag
gslc_DrvSetElemImageGlow(pGui,&sElem,sImgRef);

if (nPage != GSLC_PAGE_NONE) {
pElemRef = gslc_ElemAdd(pGui,nPage,&sElem,GSLC_ELEMREF_SRC_RAM);
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_SRC_RAM | GSLC_ELEMREF_REDRAW_FULL;
pGui->sElemRefTmp.eElemFlags = GSLC_ELEMREF_DEFAULT | GSLC_ELEMREF_REDRAW_FULL;
return &(pGui->sElemRefTmp);
#endif
}
Expand Down Expand Up @@ -2313,6 +2313,15 @@ bool gslc_ElemDrawByRef(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_teRedrawT

gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);

// --------------------------------------------------------------------------
// Handle visibility
// --------------------------------------------------------------------------
bool bShow = gslc_ElemGetShow(pGui, pElemRef);
if (!bShow) {
// The element is hidden, so no drawing required
return true;
}

// --------------------------------------------------------------------------
// Custom drawing
// --------------------------------------------------------------------------
Expand Down Expand Up @@ -2809,6 +2818,39 @@ bool gslc_ElemGetGlow(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef)
return gslc_GetElemRefFlag(pGui,pElemRef,GSLC_ELEMREF_GLOWING);
}

void gslc_ElemSetShow(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,bool bShow)
{
if ((pElemRef == NULL) || (pElemRef->pElem == NULL)) {
static const char GSLC_PMEM FUNCSTR[] = "ElemSetShow";
GSLC_DEBUG_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
return;
}
bool bShowOld = gslc_ElemGetShow(pGui,pElemRef);
gslc_SetElemRefFlag(pGui,pElemRef,GSLC_ELEMREF_SHOW,(bShow)?GSLC_ELEMREF_SHOW:0);

// Mark the element as needing redraw if its show status changed
if (bShow != bShowOld) {
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_FULL);
}

// Request page redraw if element is being hidden
// TODO: Determine minimum page redraw required to display
// background that may be revealed behind hidden element
if ((!bShow) && (bShowOld)) {
gslc_PageRedrawSet(pGui, true);
}
}

bool gslc_ElemGetShow(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef)
{
if (pElemRef == NULL) {
static const char GSLC_PMEM FUNCSTR[] = "ElemGetShow";
GSLC_DEBUG_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
return false;
}
return gslc_GetElemRefFlag(pGui,pElemRef,GSLC_ELEMREF_SHOW);
}


void gslc_ElemSetGlowEn(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,bool bGlowEn)
{
Expand Down Expand Up @@ -4169,6 +4211,11 @@ gslc_tsElemRef* gslc_CollectFindElemFromCoord(gslc_tsGui* pGui,gslc_tsCollect* p
for (nInd=0;nInd<pCollect->nElemRefCnt;nInd++) {
pElemRef = &(pCollect->asElemRef[nInd]);

if (!gslc_ElemGetShow(pGui, pElemRef)) {
// Element is marked as hidden, so don't accept touch
continue;
}

bFound = gslc_ElemOwnsCoord(pGui,pElemRef,nX,nY,true);
if (bFound) {
pFoundElemRef = pElemRef;
Expand Down
25 changes: 25 additions & 0 deletions src/GUIslice.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,13 +402,17 @@ typedef enum {
GSLC_ELEMREF_REDRAW_INC = (2<<4), ///< Incremental redraw of element requested

GSLC_ELEMREF_GLOWING = (1<<6), ///< Element state is glowing
GSLC_ELEMREF_SHOW = (1<<7), ///< Element is currently shown (ie. visible)

// Mask values for bitfield comparisons
GSLC_ELEMREF_SRC = (3<<0), ///< Mask for Source flags
GSLC_ELEMREF_REDRAW_MASK = (3<<4), ///< Mask for Redraw flags

} gslc_teElemRefFlags;

/// Define the default element reference flags for new elements
#define GSLC_ELEMREF_DEFAULT (GSLC_ELEMREF_SRC_RAM | GSLC_ELEMREF_SHOW)


/// Image reference flags: Describes characteristics of an image reference
typedef enum {
Expand Down Expand Up @@ -1814,6 +1818,27 @@ void gslc_ElemSetGlow(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,bool bGlowing);
///
bool gslc_ElemGetGlow(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef);

///
/// Update the show (visibility) status for an element
///
/// \param[in] pGui: Pointer to GUI
/// \param[in] pElemRef: Pointer to Element reference
/// \param[in] bShow: True if element is shown, false if hidden
///
/// \return none
///
void gslc_ElemSetShow(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,bool bShow);

///
/// Get the show (visibility) status for an element
///
/// \param[in] pGui: Pointer to GUI
/// \param[in] pElemRef: Pointer to Element reference
///
/// \return True if element is shown, false if hidden
///
bool gslc_ElemGetShow(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef);

///
/// Assign the event callback function for a element
///
Expand Down
Loading

0 comments on commit ebca38d

Please sign in to comment.