diff --git a/demos/modules/gwin/widgets/gfxconf.h b/demos/modules/gwin/widgets/gfxconf.h index 1665047c..fffe685d 100644 --- a/demos/modules/gwin/widgets/gfxconf.h +++ b/demos/modules/gwin/widgets/gfxconf.h @@ -81,6 +81,8 @@ #define GWIN_NEED_LABEL TRUE #define GWIN_NEED_IMAGE TRUE #define GWIN_NEED_RADIO TRUE +#define GWIN_NEED_IMAGE_ANIMATION TRUE + /* Features for the GINPUT sub-system. */ #define GINPUT_NEED_MOUSE TRUE diff --git a/gfxconf.example.h b/gfxconf.example.h index 1797cadc..dfeb707a 100644 --- a/gfxconf.example.h +++ b/gfxconf.example.h @@ -87,6 +87,8 @@ #define GWIN_NEED_BUTTON FALSE #define GWIN_NEED_SLIDER FALSE #define GWIN_NEED_CHECKBOX FALSE +#define GWIN_NEED_IMAGE FALSE +#define GWIN_NEED_RADIO FALSE /* Features for the GEVENT subsystem. */ #define GEVENT_ASSERT_NO_RESOURCE FALSE @@ -129,6 +131,7 @@ #define GWIN_BUTTON_LAZY_RELEASE FALSE #define GWIN_CONSOLE_USE_BASESTREAM FALSE #define GWIN_CONSOLE_USE_FLOAT FALSE + #define GWIN_NEED_IMAGE_ANIMATION FALSE */ /* Optional Low Level Driver Definitions */ diff --git a/include/gwin/image.h b/include/gwin/image.h index 6f4cc289..55d086bc 100644 --- a/include/gwin/image.h +++ b/include/gwin/image.h @@ -32,8 +32,10 @@ // An image window typedef struct GImageObject { GWindowObject g; - gdispImage image; // The image itself - GTimer timer; // Timer used for animated images + gdispImage image; // The image itself + #if GWIN_NEED_IMAGE_ANIMATION + GTimer timer; // Timer used for animated images + #endif } GImageObject; #ifdef __cplusplus diff --git a/include/gwin/options.h b/include/gwin/options.h index 5de2e43b..5a90dacd 100644 --- a/include/gwin/options.h +++ b/include/gwin/options.h @@ -123,6 +123,13 @@ #ifndef GWIN_CONSOLE_USE_BASESTREAM #define GWIN_CONSOLE_USE_BASESTREAM FALSE #endif + /** + * @brief Image windows can optionally support animated images + * @details Defaults to FALSE + */ + #ifndef GWIN_NEED_IMAGE_ANIMATION + #define GWIN_NEED_IMAGE_ANIMATION FALSE + #endif /** @} */ #endif /* _GWIN_OPTIONS_H */ diff --git a/src/gwin/gimage.c b/src/gwin/gimage.c index c30662f3..3f0d7231 100644 --- a/src/gwin/gimage.c +++ b/src/gwin/gimage.c @@ -23,9 +23,22 @@ static void _destroy(GWindowObject *gh) { gdispImageClose(&widget(gh)->image); } +#if GWIN_NEED_IMAGE_ANIMATION + static void _redraw(GHandle gh); + + static void _timer(void *gh) { + // We need to re-test the visibility in case it has been made invisible since the last frame. + if ((((GHandle)gh)->flags & GWIN_FLG_VISIBLE)) + _redraw((GHandle)gh); + } +#endif + static void _redraw(GHandle gh) { coord_t x, y, w, h, dx, dy; color_t bg; + #if GWIN_NEED_IMAGE_ANIMATION + delaytime_t delay; + #endif // The default display area x = gh->x; @@ -77,8 +90,27 @@ static void _redraw(GHandle gh) { // Display the image gdispImageDraw(&widget(gh)->image, x, y, w, h, dx, dy); -} + #if GWIN_NEED_IMAGE_ANIMATION + // read the delay for the next frame + delay = gdispImageNext(&widget((GHandle)gh)->image); + + // Wait for that delay if required + switch(delay) { + case TIME_INFINITE: + // Everything is done + break; + case TIME_IMMEDIATE: + // We can't allow a continuous loop here as it would lock the system up so we delay for the minimum period + delay = 1; + // Fall through + default: + // Start the timer to draw the next frame of the animation + gtimerStart(&widget((GHandle)gh)->timer, _timer, (void*)gh, FALSE, delay); + break; + } + #endif +} static const gwinVMT imageVMT = { "Image", // The class name @@ -88,33 +120,17 @@ static const gwinVMT imageVMT = { 0, // The after-clear routine }; -// This is the callback for the automated redraw for animated images -static void _animatedRedraw(void* gh) { - // draw pending frame - _redraw((GHandle)gh); - - // read the delay for the next frame and set the timer - gtimerStart(&(widget((GHandle)gh)->timer), _animatedRedraw, (void*)gh, FALSE, gdispImageNext(&(widget((GHandle)gh)->image))); -} - -// check for an animated image -static bool_t _checkAnimated(GHandle gh) { - if (widget(gh)->image.flags & GDISP_IMAGE_FLG_ANIMATED) { - gtimerInit(&(widget(gh)->timer)); - gtimerStart(&(widget(gh)->timer), _animatedRedraw, (void*)gh, FALSE, gdispImageNext(&(widget(gh)->image))); - - return true; - } - - return false; -} - GHandle gwinImageCreate(GImageObject *gobj, GWindowInit *pInit) { if (!(gobj = (GImageObject *)_gwindowCreate(&gobj->g, pInit, &imageVMT, 0))) return 0; // Ensure the gdispImageIsOpen() gives valid results gobj->image.type = 0; + + // Initialise the timer + #if GWIN_NEED_IMAGE_ANIMATION + gtimerInit(&gobj->timer); + #endif gwinSetVisible((GHandle)gobj, pInit->show); @@ -137,10 +153,8 @@ bool_t gwinImageOpenMemory(GHandle gh, const void* memory) { #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif - } - - if(!_checkAnimated(gh)) _redraw(gh); + } return TRUE; } @@ -162,10 +176,8 @@ bool_t gwinImageOpenFile(GHandle gh, const char* filename) { #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif - } - - if(!_checkAnimated(gh)) _redraw(gh); + } return TRUE; } @@ -188,10 +200,8 @@ bool_t gwinImageOpenStream(GHandle gh, void *streamPtr) { #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif - } - - if(!_checkAnimated(gh)) _redraw(gh); + } return TRUE; }