From b9f53aa7936686134f19c480346816a3d234f7f7 Mon Sep 17 00:00:00 2001 From: inmarket Date: Sun, 25 Jan 2015 17:40:34 +1000 Subject: Add the ability to flash a gwin window/widget. Only the button draws for checkbox's and radio's currently do anything about it. Widget demo updated to show this on Checkbox 3 (the toggle button). --- src/gwin/gwin.h | 34 ++++++++++++++++++++++ src/gwin/gwin_checkbox.c | 10 +++++++ src/gwin/gwin_class.h | 19 +++++++++++- src/gwin/gwin_options.h | 15 ++++++++++ src/gwin/gwin_radio.c | 12 +++++++- src/gwin/gwin_wm.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 163 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gwin/gwin.h b/src/gwin/gwin.h index 81bf38e5..9b2d18b7 100644 --- a/src/gwin/gwin.h +++ b/src/gwin/gwin.h @@ -547,6 +547,40 @@ extern "C" { */ GHandle gwinGetNextWindow(GHandle gh); + /** + * @brief Set a window or widget to flash + * + * @param[in] gh The window handle + * @param[in] flash Enable or disable the flashing of the window + * + * @note The window is automatically redrawn if it supports self-redrawing. + * @note When a window is set to flash, its appearance changes in some + * way every flash period (GWIN_FLASHING_PERIOD). How its appearance + * changes depends on the draw for each window/widget. + * + * @pre Requires GWIN_NEED_FLASHING to be TRUE + * + * @api + */ + void gwinSetFlashing(GHandle gh, bool_t flash); + + /** + * @brief Enables flashing of a window or widget + * + * @param[in] gh The window handle + * + * @api + */ + #define gwinFlash(gh) gwinSetFlashing(gh, TRUE) + + /** + * @brief Disables a widget + * + * @param[in] gh The window handle + * + * @api + */ + #define gwinNoFlash(gh) gwinSetFlashing(gh, FALSE) #endif #if GDISP_NEED_TEXT || defined(__DOXYGEN__) diff --git a/src/gwin/gwin_checkbox.c b/src/gwin/gwin_checkbox.c index ff0507d9..3f1d46bf 100644 --- a/src/gwin/gwin_checkbox.c +++ b/src/gwin/gwin_checkbox.c @@ -216,6 +216,11 @@ void gwinCheckboxDraw_CheckOnRight(GWidgetObject *gw, void *param) { if (gw->g.vmt != (gwinVMT *)&checkboxVMT) return; pcol = getDrawColors(gw); + #if GWIN_NEED_FLASHING + // Flash the on and off state. + pcol = _gwinGetFlashedColor(gw, pcol, TRUE); + #endif + gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter); gdispGDrawLine(gw->g.display, gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge); gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge); @@ -232,6 +237,11 @@ void gwinCheckboxDraw_CheckOnRight(GWidgetObject *gw, void *param) { if (gw->g.vmt != (gwinVMT *)&checkboxVMT) return; pcol = getDrawColors(gw); + #if GWIN_NEED_FLASHING + // Flash the on and off state. + pcol = _gwinGetFlashedColor(gw, pcol, TRUE); + #endif + /* Fill the box blended from variants of the fill color */ tcol = gdispBlendColor(White, pcol->fill, TOP_FADE); bcol = gdispBlendColor(Black, pcol->fill, BOTTOM_FADE); diff --git a/src/gwin/gwin_class.h b/src/gwin/gwin_class.h index 8cb17ac8..01b6e596 100644 --- a/src/gwin/gwin_class.h +++ b/src/gwin/gwin_class.h @@ -47,6 +47,7 @@ #define GWIN_FLG_MINIMIZED 0x00100000 // @< The window is minimized #define GWIN_FLG_MAXIMIZED 0x00200000 // @< The window is maximized #define GWIN_FLG_MOUSECAPTURE 0x00400000 // @< The window has captured the mouse +#define GWIN_FLG_FLASHING 0x00800000 // @< The window is flashing - see the _gwinFlashState boolean #define GWIN_FIRST_WM_FLAG 0x01000000 // @< 8 bits free for the window manager to use #define GWIN_LAST_WM_FLAG 0x80000000 // @< 8 bits free for the window manager to use /** @} */ @@ -165,7 +166,9 @@ typedef struct gwinVMT { /** * @brief The current window manager */ - extern GWindowManager * _GWINwm; + extern GWindowManager * _GWINwm; + extern bool_t _gwinFlashState; + #endif #ifdef __cplusplus @@ -313,6 +316,20 @@ bool_t _gwinWMAdd(GHandle gh, const GWindowInit *pInit); * @notapi */ void _gwinSendEvent(GHandle gh, GEventType type); + + + #if GWIN_NEED_FLASHING || defined(__DOXYGEN__) + /** + * @brief Convert a chosen style color set pressed/enabled etc if flashing + * @return The colorset - after flashing is taken into account + * + * @param[in] gw The widget + * @param[in] pcol The style color set that has been chosen to reflect the state of the widget + * @param[in] flashOffState Whether the off-state should be flashed as well. If false, only the + * pressed color set is flashed. + */ + const GColorSet *_gwinGetFlashedColor(GWidgetObject *gw, const GColorSet *pcol, bool_t flashOffState); + #endif #endif #if GWIN_NEED_CONTAINERS || defined(__DOXYGEN__) diff --git a/src/gwin/gwin_options.h b/src/gwin/gwin_options.h index 9252e67a..106c5e06 100644 --- a/src/gwin/gwin_options.h +++ b/src/gwin/gwin_options.h @@ -328,6 +328,21 @@ #ifndef GWIN_TABSET_TABHEIGHT #define GWIN_TABSET_TABHEIGHT 18 #endif + /** + * @brief Should flashing of widgets be supported + * @details Defaults to FALSE + * @pre Requires GWIN_NEED_WINDOWMANAGER to be TRUE + */ + #ifndef GWIN_NEED_FLASHING + #define GWIN_NEED_FLASHING FALSE + #endif + /** + * @brief What is the period for the flashing timer + * @details Defaults to 250 milliseconds + */ + #ifndef GWIN_FLASHING_PERIOD + #define GWIN_FLASHING_PERIOD 250 + #endif /** @} */ #endif /* _GWIN_OPTIONS_H */ diff --git a/src/gwin/gwin_radio.c b/src/gwin/gwin_radio.c index 0bafa7cc..b9076109 100644 --- a/src/gwin/gwin_radio.c +++ b/src/gwin/gwin_radio.c @@ -203,7 +203,12 @@ void gwinRadioDraw_Radio(GWidgetObject *gw, void *param) { if (gw->g.vmt != (gwinVMT *)&radioVMT) return; pcol = getDrawColors(gw); - + + #if GWIN_NEED_FLASHING + // Flash only the on state. + pcol = _gwinGetFlashedColor(gw, pcol, FALSE); + #endif + gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter); gdispGDrawLine(gw->g.display, gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge); gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge); @@ -215,6 +220,11 @@ void gwinRadioDraw_Radio(GWidgetObject *gw, void *param) { if (gw->g.vmt != (gwinVMT *)&radioVMT) return; pcol = getDrawColors(gw); + #if GWIN_NEED_FLASHING + // Flash only the on state. + pcol = _gwinGetFlashedColor(gw, pcol, FALSE); + #endif + if ((gw->g.flags & GRADIO_FLG_PRESSED)) { gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); gdispGFillStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter); diff --git a/src/gwin/gwin_wm.c b/src/gwin/gwin_wm.c index 6d860f23..00365c36 100644 --- a/src/gwin/gwin_wm.c +++ b/src/gwin/gwin_wm.c @@ -161,9 +161,13 @@ // The default window manager extern const GWindowManager GNullWindowManager; GWindowManager * _GWINwm; +bool_t _gwinFlashState; static gfxSem gwinsem; static gfxQueueASync _GWINList; +#if GWIN_NEED_FLASHING + static GTimer FlashTimer; +#endif #if !GWIN_REDRAW_IMMEDIATE static GTimer RedrawTimer; static void RedrawTimerFn(void *param); @@ -171,6 +175,7 @@ static gfxQueueASync _GWINList; static volatile uint8_t RedrawPending; #define DOREDRAW_INVISIBLES 0x01 #define DOREDRAW_VISIBLES 0x02 + #define DOREDRAW_FLASHRUNNING 0x04 /*----------------------------------------------- @@ -181,6 +186,9 @@ void _gwmInit(void) { gfxSemInit(&gwinsem, 1, 1); gfxQueueASyncInit(&_GWINList); + #if GWIN_NEED_FLASHING + gtimerInit(&FlashTimer); + #endif #if !GWIN_REDRAW_IMMEDIATE gtimerInit(&RedrawTimer); gtimerStart(&RedrawTimer, RedrawTimerFn, 0, TRUE, TIME_INFINITE); @@ -563,6 +571,73 @@ GHandle gwinGetNextWindow(GHandle gh) { return gh ? (GHandle)gfxQueueASyncNext(&gh->wmq) : (GHandle)gfxQueueASyncPeek(&_GWINList); } +#if GWIN_NEED_FLASHING + static void FlashTimerFn(void *param) { + GHandle gh; + (void) param; + + // Assume we will be stopping + RedrawPending &= ~DOREDRAW_FLASHRUNNING; + + // Swap the flash state + _gwinFlashState = !_gwinFlashState; + + // Redraw all flashing windows + for(gh = (GHandle)gfxQueueASyncPeek(&_GWINList); gh; gh = (GHandle)gfxQueueASyncNext(&gh->wmq)) { + if ((gh->flags & GWIN_FLG_FLASHING)) { + RedrawPending |= DOREDRAW_FLASHRUNNING; + _gwinUpdate(gh); + } + } + + // Do we have no flashers left? + if (!(RedrawPending & DOREDRAW_FLASHRUNNING)) + gtimerStop(&FlashTimer); + } + + void gwinSetFlashing(GHandle gh, bool_t flash) { + + // Start flashing? + if (flash) { + gh->flags |= GWIN_FLG_FLASHING; // A redraw will occur on the next flash period. + + // Start the flash timer if needed + if (!(RedrawPending & DOREDRAW_FLASHRUNNING)) { + RedrawPending |= DOREDRAW_FLASHRUNNING; + + // Ensure we start the timer with flash bit on + _gwinFlashState = FALSE; + FlashTimerFn(0); // First flash + gtimerStart(&FlashTimer, FlashTimerFn, 0, TRUE, GWIN_FLASHING_PERIOD); // Subsequent flashes + } + + // Stop flashing? + } else if ((gh->flags & GWIN_FLG_FLASHING)) { + gh->flags &= ~GWIN_FLG_FLASHING; + // We need to manually redraw as the timer is now turned off for this window + _gwinUpdate(gh); + } + } + + #if GWIN_NEED_WIDGET + const GColorSet *_gwinGetFlashedColor(GWidgetObject *gw, const GColorSet *pcol, bool_t flashOffState) { + // Does the flashing state affect the current colors? + if ((gw->g.flags & GWIN_FLG_FLASHING) && _gwinFlashState) { + + // For a pressed state show an unpressed state + if (pcol == &gw->pstyle->pressed) + pcol = &gw->pstyle->enabled; + + // For a non-pressed state (if allowed) show a pressed state + else if (flashOffState && pcol == &gw->pstyle->enabled) + pcol = &gw->pstyle->pressed; + } + return pcol; + } + #endif +#endif + + /*----------------------------------------------- * "Null" Window Manager Routines *-----------------------------------------------*/ -- cgit v1.2.3