diff --git a/.gitignore b/.gitignore index 9cab4d11..b16e2726 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,4 @@ build *.lst *.o *.map -*.sublime-* src/gdisp/fonts/*.dat diff --git a/demos/modules/gadc/main.c b/demos/modules/gadc/main.c index 7db14c82..ae508278 100644 --- a/demos/modules/gadc/main.c +++ b/demos/modules/gadc/main.c @@ -152,6 +152,8 @@ int main(void) { gwinSetDefaultFont(font); { GWindowInit wi; + + gwinClearInit(&wi); wi.show = TRUE; wi.x = wi.y = 0; wi.width = swidth-SCOPE_CX; @@ -184,6 +186,8 @@ int main(void) { /* Set up the scope window in the top right on the screen */ { GWindowInit wi; + + gwinClearInit(&wi); wi.show = TRUE; wi.x = swidth-SCOPE_CX; wi.y = 0; diff --git a/demos/modules/gaudio/oscilloscope/main.c b/demos/modules/gaudio/oscilloscope/main.c index 3636e8f9..b544016e 100644 --- a/demos/modules/gaudio/oscilloscope/main.c +++ b/demos/modules/gaudio/oscilloscope/main.c @@ -73,6 +73,7 @@ int main(void) { { GWindowInit wi; + gwinClearInit(&wi); wi.show = TRUE; wi.x = wi.y = 0; wi.width = swidth; wi.height = sheight; diff --git a/demos/modules/gwin/basic/main.c b/demos/modules/gwin/basic/main.c index 4d8fa33c..fca150c9 100644 --- a/demos/modules/gwin/basic/main.c +++ b/demos/modules/gwin/basic/main.c @@ -43,6 +43,7 @@ int main(void) { { GWindowInit wi; + gwinClearInit(&wi); wi.show = TRUE; wi.x = 20; wi.y = 10; wi.width = 200; wi.height = 150; GW1 = gwinWindowCreate(0, &wi); wi.show = TRUE; wi.x = 50; wi.y = 190; wi.width = 150; wi.height = 100; diff --git a/demos/modules/gwin/button/main.c b/demos/modules/gwin/button/main.c index 6349ca09..156e929e 100644 --- a/demos/modules/gwin/button/main.c +++ b/demos/modules/gwin/button/main.c @@ -36,9 +36,7 @@ static void createWidgets(void) { GWidgetInit wi; // Apply some default values for GWIN - wi.customDraw = 0; - wi.customParam = 0; - wi.customStyle = 0; + gwinWidgetClearInit(&wi); wi.g.show = TRUE; // Apply the button parameters diff --git a/demos/modules/gwin/checkbox/main.c b/demos/modules/gwin/checkbox/main.c index b6cef40b..2a2df2fb 100644 --- a/demos/modules/gwin/checkbox/main.c +++ b/demos/modules/gwin/checkbox/main.c @@ -36,9 +36,7 @@ static void createWidgets(void) { GWidgetInit wi; // Apply some default values for GWIN - wi.customDraw = 0; - wi.customParam = 0; - wi.customStyle = 0; + gwinWidgetClearInit(&wi); wi.g.show = TRUE; // Apply the checkbox parameters diff --git a/demos/modules/gwin/console/main.c b/demos/modules/gwin/console/main.c index 14f68cd4..0e9000b5 100644 --- a/demos/modules/gwin/console/main.c +++ b/demos/modules/gwin/console/main.c @@ -48,6 +48,7 @@ int main(void) { { GWindowInit wi; + gwinClearInit(&wi); wi.show = TRUE; wi.x = 0; wi.y = 0; wi.width = gdispGetWidth(); wi.height = gdispGetHeight()/2; GW1 = gwinConsoleCreate(0, &wi); diff --git a/demos/modules/gwin/graph/main.c b/demos/modules/gwin/graph/main.c index 4dd67ae8..7a496fae 100644 --- a/demos/modules/gwin/graph/main.c +++ b/demos/modules/gwin/graph/main.c @@ -69,6 +69,7 @@ int main(void) { { GWindowInit wi; + gwinClearInit(&wi); wi.show = TRUE; wi.x = wi.y = 0; wi.width = gdispGetWidth(); diff --git a/demos/modules/gwin/imagebox/gfxconf.h b/demos/modules/gwin/imagebox/gfxconf.h index 7ff4dece..4db8be39 100644 --- a/demos/modules/gwin/imagebox/gfxconf.h +++ b/demos/modules/gwin/imagebox/gfxconf.h @@ -42,7 +42,7 @@ #define GDISP_NEED_PIXELREAD FALSE #define GDISP_NEED_CONTROL FALSE #define GDISP_NEED_QUERY FALSE -#define GDISP_NEED_MULTITHREAD FALSE +#define GDISP_NEED_MULTITHREAD TRUE #define GDISP_NEED_STREAMING FALSE #define GDISP_NEED_TEXT TRUE #define GDISP_NEED_ANTIALIAS FALSE diff --git a/demos/modules/gwin/list/main.c b/demos/modules/gwin/list/main.c index 3811c36f..6d469626 100644 --- a/demos/modules/gwin/list/main.c +++ b/demos/modules/gwin/list/main.c @@ -37,9 +37,7 @@ static void createWidgets(void) { GWidgetInit wi; // Apply some default values for GWIN - wi.customDraw = 0; - wi.customParam = 0; - wi.customStyle = 0; + gwinWidgetClearInit(&wi); wi.g.show = TRUE; // Create the label for the first list diff --git a/demos/modules/gwin/progressbar/gfxconf.h b/demos/modules/gwin/progressbar/gfxconf.h index 4ea487b9..6af70faf 100644 --- a/demos/modules/gwin/progressbar/gfxconf.h +++ b/demos/modules/gwin/progressbar/gfxconf.h @@ -82,6 +82,7 @@ #define GWIN_NEED_IMAGE_ANIMATION FALSE #define GWIN_NEED_LIST_IMAGES FALSE #define GWIN_NEED_PROGRESSBAR TRUE +#define GWIN_PROGRESSBAR_AUTO TRUE /* Features for the GINPUT sub-system. */ #define GINPUT_NEED_MOUSE TRUE diff --git a/demos/modules/gwin/progressbar/main.c b/demos/modules/gwin/progressbar/main.c index 960a3293..6fb53c2e 100644 --- a/demos/modules/gwin/progressbar/main.c +++ b/demos/modules/gwin/progressbar/main.c @@ -5,9 +5,7 @@ GHandle ghProgressbar; static void _createWidget(void) { GWidgetInit wi; - wi.customDraw = 0; - wi.customParam = 0; - wi.customStyle = 0; + gwinWidgetClearInit(&wi); wi.g.show = TRUE; wi.g.y = 10; wi.g.x = 10; wi.g.width = 200; wi.g.height = 20; wi.text = "Progress 1"; diff --git a/demos/modules/gwin/radio/main.c b/demos/modules/gwin/radio/main.c index a3c493c3..60bf206f 100644 --- a/demos/modules/gwin/radio/main.c +++ b/demos/modules/gwin/radio/main.c @@ -40,9 +40,7 @@ static void createWidgets(void) { GWidgetInit wi; // Apply some default values for GWIN - wi.customDraw = 0; - wi.customParam = 0; - wi.customStyle = 0; + gwinWidgetClearInit(&wi); wi.g.show = TRUE; // create Radio11 diff --git a/demos/modules/gwin/slider/main.c b/demos/modules/gwin/slider/main.c index 0897f1f3..475f68cf 100644 --- a/demos/modules/gwin/slider/main.c +++ b/demos/modules/gwin/slider/main.c @@ -36,9 +36,7 @@ static void createWidgets(void) { GWidgetInit wi; // Apply some default values for GWIN - wi.customDraw = 0; - wi.customParam = 0; - wi.customStyle = 0; + gwinWidgetClearInit(&wi); wi.g.show = TRUE; // create Slider1 diff --git a/demos/modules/gwin/widgets/gfxconf.h b/demos/modules/gwin/widgets/gfxconf.h index c5673367..25065b27 100644 --- a/demos/modules/gwin/widgets/gfxconf.h +++ b/demos/modules/gwin/widgets/gfxconf.h @@ -65,6 +65,7 @@ #define GWIN_NEED_LIST TRUE #define GWIN_NEED_LIST_IMAGES TRUE #define GWIN_NEED_PROGRESSBAR TRUE + #define GWIN_PROGRESSBAR_AUTO TRUE /////////////////////////////////////////////////////////////////////////// // GEVENT // diff --git a/demos/modules/gwin/widgets/main.c b/demos/modules/gwin/widgets/main.c index 17f87d46..9742a027 100644 --- a/demos/modules/gwin/widgets/main.c +++ b/demos/modules/gwin/widgets/main.c @@ -113,7 +113,7 @@ static gdispImage imgYesNo; static void createWidgets(void) { GWidgetInit wi; - wi.customDraw = 0; wi.customParam = 0; wi.customStyle = 0; + gwinWidgetClearInit(&wi); // Create the Tabs wi.g.show = TRUE; wi.customDraw = gwinRadioDraw_Tab; diff --git a/docs/releases.txt b/docs/releases.txt index 859c7edd..e5be2311 100644 --- a/docs/releases.txt +++ b/docs/releases.txt @@ -33,6 +33,8 @@ FEATURE: Added vs1053 audio play driver FEATURE: Added GAUDIO wave-play demo FEATURE: Added many GWIN simple demo's and updated the combined widget demo FEATURE: Added gwinEnable() and gwinDisable() +FIX: Progressbar widget bug fix that could gwinProgressbarStop() to crash +FIX: Imagebox widget bug fix that could cause gwinImageOpenFile() to crash *** changes after 1.9 *** diff --git a/gfxconf.example.h b/gfxconf.example.h index dfeab406..d4bf7e96 100644 --- a/gfxconf.example.h +++ b/gfxconf.example.h @@ -134,7 +134,6 @@ #define GWIN_CONSOLE_USE_FLOAT FALSE #define GWIN_NEED_GRAPH FALSE #define GWIN_NEED_WIDGET FALSE - #define GWIN_NEED_HIERARCHY FALSE #define GWIN_NEED_LABEL FALSE #define GWIN_LABEL_ATTRIBUTE FALSE #define GWIN_NEED_BUTTON FALSE @@ -147,7 +146,7 @@ #define GWIN_NEED_LIST FALSE #define GWIN_NEED_LIST_IMAGES FALSE #define GWIN_NEED_PROGRESSBAR FALSE - #define GWIN_NEED_FRAME FALSE + #define GWIN_PROGRESSBAR_AUTO FALSE #define GWIN_FLAT_STYLING FALSE diff --git a/src/gaudio/sys_options.h b/src/gaudio/sys_options.h index 1363d703..eb903424 100644 --- a/src/gaudio/sys_options.h +++ b/src/gaudio/sys_options.h @@ -14,7 +14,7 @@ */ #ifndef _GAUDIO_OPTIONS_H -#define _GAUDOUT_OPTIONS_H +#define _GAUDIO_OPTIONS_H /** * @name GAUDIO Functionality to be included diff --git a/src/gdisp/image.c b/src/gdisp/image.c index 5a743905..e2b7d758 100644 --- a/src/gdisp/image.c +++ b/src/gdisp/image.c @@ -130,6 +130,10 @@ gdispImageError } #endif +void gdispImageInit(gdispImage *img) { + img->type = GDISP_IMAGE_TYPE_UNKNOWN; +} + gdispImageError gdispImageOpenGFile(gdispImage *img, GFILE *f) { gdispImageError err; diff --git a/src/gdisp/image.h b/src/gdisp/image.h index 1bf378f1..76e8bdea 100644 --- a/src/gdisp/image.h +++ b/src/gdisp/image.h @@ -130,6 +130,14 @@ extern "C" { #define gdispImageSetSimulFileReader(img, fname) gdispImageSetFileReader(img, fname) #endif + /** + * @brief Initialise a gdispImage object + * + * @param[in] img The image structure to initialise + * + */ + void gdispImageInit(gdispImage *img); + /** * @brief Open an image using an open GFILE and get it ready for drawing * @details Determine the image format and get ready to decode the first image frame diff --git a/src/gqueue/gqueue.c b/src/gqueue/gqueue.c index 8540bcea..45ca6fce 100644 --- a/src/gqueue/gqueue.c +++ b/src/gqueue/gqueue.c @@ -87,6 +87,30 @@ void _gqueueDeinit(void) pqueue->tail = pitem; } + void gfxQueueASyncInsert(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem, gfxQueueASyncItem *pafter) { + gfxSystemLock(); + gfxQueueASyncInsertI(pqueue, pitem, pafter); + gfxSystemUnlock(); + } + void gfxQueueASyncInsertI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem, gfxQueueASyncItem *pafter) { + if (!pitem) return; // Safety + + if (pafter && gfxQueueASyncIsInI(pqueue, pafter)) { + pitem->next = pafter->next; + pafter->next = pitem; + if (pqueue->tail == pafter) + pqueue->tail = pitem; + } else { + pitem->next = 0; + if (!pqueue->head) { + pqueue->head = pqueue->tail = pitem; + } else { + pqueue->tail->next = pitem; + pqueue->tail = pitem; + } + } + } + void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { gfxSystemLock(); gfxQueueASyncRemoveI(pqueue, pitem); @@ -201,6 +225,30 @@ void _gqueueDeinit(void) gfxSemSignalI(&pqueue->sem); } + void gfxQueueGSyncInsert(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem, gfxQueueASyncItem *pafter) { + gfxSystemLock(); + gfxQueueGSyncInsertI(pqueue, pitem, pafter); + gfxSystemUnlock(); + } + void gfxQueueGSyncInsertI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem, gfxQueueASyncItem *pafter) { + if (!pitem) return; // Safety + + if (pafter && gfxQueueGSyncIsInI(pqueue, pafter)) { + pitem->next = pafter->next; + pafter->next = pitem; + if (pqueue->tail == pafter) + pqueue->tail = pitem; + } else { + pitem->next = 0; + if (!pqueue->head) { + pqueue->head = pqueue->tail = pitem; + } else { + pqueue->tail->next = pitem; + pqueue->tail = pitem; + } + } + } + void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { gfxSystemLock(); gfxQueueGSyncRemoveI(pqueue, pitem); @@ -312,6 +360,33 @@ void _gqueueDeinit(void) return gfxSemWait(&pitem->sem, ms); } + bool_t gfxQueueFSyncInsert(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, gfxQueueASyncItem *pafter, delaytime_t ms) { + if (!pitem) return; // Safety + gfxSemInit(&pitem->sem, 0, 1); + + gfxSystemLock(); + if (pafter && gfxQueueGSyncIsInI(pqueue, pafter)) { + pitem->next = pafter->next; + pafter->next = pitem; + if (pqueue->tail == pafter) + pqueue->tail = pitem; + } else { + pitem->next = 0; + if (!pqueue->head) { + pqueue->head = pqueue->tail = pitem; + } else { + pqueue->tail->next = pitem; + pqueue->tail = pitem; + } + } + gfxSystemUnlock(); + + gfxSemSignal(&pqueue->sem); + + return gfxSemWait(&pitem->sem, ms); + + } + void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) { gfxQueueFSyncItem *pi; diff --git a/src/gqueue/sys_defs.h b/src/gqueue/sys_defs.h index b97f2f4d..d0e46be1 100644 --- a/src/gqueue/sys_defs.h +++ b/src/gqueue/sys_defs.h @@ -198,6 +198,31 @@ void gfxQueueGSyncPushI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem); bool_t gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms); /* @} */ +/** + * @brief Insert an item on the queue after the specified item. + * @return none for ASync and GSync queues; For FSync queues - FALSE on timeout, otherwise TRUE + * + * @param[in] pqueue A pointer to the queue + * @param[in] pitem A pointer to the queue item + * @param[in] pafter A pointer to the queue item this new item must be inserted after. If NULL or + * pafter can't be found in the queue, it puts the new item at the end of the queue. + * @param[in] ms The maxmimum time to wait for an item to be removed from the queue (only for FSync queues) + * + * @note FSync: Use a delay time of TIME_IMMEDIATE if you don't want to wait until the + * item is removed from the queue. Note that even if the timeout occurs - the item + * remains in the queue. + * @note The routines ending in "I" are interrupt/system/iclass level routines. + * + * @api + * @{ + */ +void gfxQueueASyncInsert(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem, gfxQueueASyncItem *pafter); +void gfxQueueASyncInsertI(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem, gfxQueueASyncItem *pafter); +void gfxQueueGSyncInsert(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem, gfxQueueASyncItem *pafter); +void gfxQueueGSyncInsertI(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem, gfxQueueASyncItem *pafter); +bool_t gfxQueueFSyncInsert(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, gfxQueueASyncItem *pafter, delaytime_t ms); +/* @} */ + /** * @brief Remove an item from the queue. * @note Removes the specified item from the queue where-ever it is in the queue diff --git a/src/gwin/class_gwin.h b/src/gwin/class_gwin.h index 49fc6084..50dd480e 100644 --- a/src/gwin/class_gwin.h +++ b/src/gwin/class_gwin.h @@ -170,7 +170,7 @@ extern "C" { * * @notapi */ -GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit, const gwinVMT *vmt, uint16_t flags); +GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit, const gwinVMT *vmt, uint32_t flags); #if GWIN_NEED_WIDGET || defined(__DOXYGEN__) /** diff --git a/src/gwin/gimage.c b/src/gwin/gimage.c index fdc6df84..9d6363ba 100644 --- a/src/gwin/gimage.c +++ b/src/gwin/gimage.c @@ -26,10 +26,20 @@ static void _destroy(GWindowObject *gh) { #if GWIN_NEED_IMAGE_ANIMATION static void _redraw(GHandle gh); - static void _timer(void *gh) { + static void _timer(void *param) { + #define gh ((GHandle)param) + // 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); + if ((gh->flags & GWIN_FLG_VISIBLE)) { + // Setting the clip here shouldn't be necessary if the redraw doesn't overdraw + // but we put it in for safety anyway + #if GDISP_NEED_CLIP + gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height); + #endif + _redraw(gh); + } + + #undef gh } #endif @@ -127,7 +137,7 @@ GHandle gwinGImageCreate(GDisplay *g, GImageObject *gobj, GWindowInit *pInit) { return 0; // Ensure the gdispImageIsOpen() gives valid results - gobj->image.type = 0; + gdispImageInit(&gobj->image); // Initialise the timer #if GWIN_NEED_IMAGE_ANIMATION diff --git a/src/gwin/image.h b/src/gwin/gimage.h similarity index 100% rename from src/gwin/image.h rename to src/gwin/gimage.h diff --git a/src/gwin/gwidget.c b/src/gwin/gwidget.c index 181b7425..c46520ea 100644 --- a/src/gwin/gwidget.c +++ b/src/gwin/gwidget.c @@ -297,6 +297,14 @@ void _gwidgetRedraw(GHandle gh) { gw->fnDraw(gw, gw->fnParam); } +void gwinWidgetClearInit(GWidgetInit *pwi) { + char *p; + unsigned len; + + for(p = (char *)pwi, len = sizeof(GWidgetInit); len; len--) + *p++ = 0; +} + void gwinSetDefaultStyle(const GWidgetStyle *pstyle, bool_t updateAll) { if (!pstyle) pstyle = &BlackWidgetStyle; diff --git a/src/gwin/gwidget.h b/src/gwin/gwidget.h index 6568859d..8795a95b 100644 --- a/src/gwin/gwidget.h +++ b/src/gwin/gwidget.h @@ -78,6 +78,10 @@ typedef void (*CustomWidgetDrawFunction)(struct GWidgetObject *gw, void *param); * @brief The structure to initialise a widget. * * @note Some widgets may have extra parameters. + * @note If you create this structure on the stack, you should always memset + * it to all zero's first in case a future version of the software + * add's extra fields. Alternatively you can use @p gwinWidgetClearInit() + * to clear it. * @note The text element must be static string (not stack allocated). If you want to use * a dynamic string (eg a stack allocated string) use NULL for this member and then call * @p gwinSetText() with useAlloc set to TRUE. @@ -126,6 +130,18 @@ typedef struct GWidgetObject { extern "C" { #endif +/** + * @brief Clear a GWidgetInit structure to all zero's + * @note This function is provided just to prevent problems + * on operating systems where using memset() causes issues + * in the users application. + * + * @param[in] pwi The GWidgetInit structure to clear + * + * @api + */ +void gwinWidgetClearInit(GWidgetInit *pwi); + /** * @brief Set the default style for widgets created hereafter. * diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c index b9a488d3..b48d8335 100644 --- a/src/gwin/gwin.c +++ b/src/gwin/gwin.c @@ -114,7 +114,7 @@ void _gwinDeinit(void) // Internal routine for use by GWIN components only // Initialise a window creating it dynamically if required. -GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit, const gwinVMT *vmt, uint16_t flags) { +GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit, const gwinVMT *vmt, uint32_t flags) { // Allocate the structure if necessary if (!pgw) { if (!(pgw = gfxAlloc(vmt->size))) @@ -155,6 +155,14 @@ GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit * Routines that affect all windows *-----------------------------------------------*/ +void gwinClearInit(GWindowInit *pwi) { + char *p; + unsigned len; + + for(p = (char *)pwi, len = sizeof(GWindowInit); len; len--) + *p++ = 0; +} + void gwinSetDefaultColor(color_t clr) { defaultFgColor = clr; } @@ -195,10 +203,8 @@ GHandle gwinGWindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pI } void gwinDestroy(GHandle gh) { - if (!gh) { - // should log a runtime error here + if (!gh) return; - } #if GWIN_NEED_HIERARCHY GHandle tmp; @@ -394,7 +400,7 @@ void gwinRedraw(GHandle gh) { void gwinClear(GHandle gh) { /* * Don't render anything when the window is not visible but - * still call tthe AfterClear() routine as some widgets will + * still call the AfterClear() routine as some widgets will * need this to clear internal buffers or similar */ if (!((gh->flags & GWIN_FLG_VISIBLE))) { diff --git a/src/gwin/gwm.c b/src/gwin/gwm.c index 9c158f68..3140b03f 100644 --- a/src/gwin/gwm.c +++ b/src/gwin/gwm.c @@ -127,7 +127,7 @@ void gwinRedrawDisplay(GDisplay *g, bool_t preserve) { } /*----------------------------------------------- - * Window Manager Routines + * "Null" Window Manager Routines *-----------------------------------------------*/ static void WM_Init(void) { @@ -145,9 +145,9 @@ static void WM_DeInit(void) { } static bool_t WM_Add(GHandle gh, const GWindowInit *pInit) { - // Note the window will not be marked as visible yet + // Note the window will not currently be marked as visible - // Put it on the queue + // Put it on the end of the queue gfxQueueASyncPut(&_GWINList, &gh->wmq); // Make sure the size is valid @@ -156,7 +156,7 @@ static bool_t WM_Add(GHandle gh, const GWindowInit *pInit) { } static void WM_Delete(GHandle gh) { - // Remove it from the queue + // Remove it from the window list gfxQueueASyncRemove(&_GWINList, &gh->wmq); } diff --git a/src/gwin/label.c b/src/gwin/label.c index 8960300b..2aa0c860 100644 --- a/src/gwin/label.c +++ b/src/gwin/label.c @@ -138,6 +138,7 @@ void gwinLabelSetBorder(GHandle gh, bool_t border) { static void gwinLabelDefaultDraw(GWidgetObject *gw, void *param) { coord_t w, h; + color_t c; (void) param; // is it a valid handle? @@ -146,6 +147,7 @@ static void gwinLabelDefaultDraw(GWidgetObject *gw, void *param) { w = (gw->g.flags & GLABEL_FLG_WAUTO) ? getwidth(gw->text, gw->g.font, gdispGGetWidth(gw->g.display) - gw->g.x) : gw->g.width; h = (gw->g.flags & GLABEL_FLG_HAUTO) ? getheight(gw->text, gw->g.font, gdispGGetWidth(gw->g.display) - gw->g.x) : gw->g.height; + c = (gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.text : gw->pstyle->disabled.text; if (gw->g.width != w || gw->g.height != h) { gwinResize(&gw->g, w, h); @@ -154,29 +156,18 @@ static void gwinLabelDefaultDraw(GWidgetObject *gw, void *param) { } #if GWIN_LABEL_ATTRIBUTE - if (gw2obj->attr != 0) { - gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw2obj->attr, gw->g.font, - (gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.text : gw->pstyle->disabled.text, gw->pstyle->background, - justifyLeft); - - gdispGFillStringBox(gw->g.display, gw->g.x + gw2obj->tab, gw->g.y, gw->g.width, gw->g.height, gw->text, gw->g.font, - (gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.text : gw->pstyle->disabled.text, gw->pstyle->background, - justifyLeft); - } else { - gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->text, gw->g.font, - (gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.text : gw->pstyle->disabled.text, gw->pstyle->background, - justifyLeft); - - } + if (gw2obj->attr) { + gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw2obj->tab, h, gw2obj->attr, gw->g.font, c, gw->pstyle->background, justifyLeft); + gdispGFillStringBox(gw->g.display, gw->g.x + gw2obj->tab, gw->g.y, w-gw2obj->tab, h, gw->text, gw->g.font, c, gw->pstyle->background, justifyLeft); + } else + gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, w, h, gw->text, gw->g.font, c, gw->pstyle->background, justifyLeft); #else - gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->text, gw->g.font, - (gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.text : gw->pstyle->disabled.text, gw->pstyle->background, - justifyLeft); + gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, w, h, gw->text, gw->g.font, c, gw->pstyle->background, justifyLeft); #endif // render the border (if any) if (gw->g.flags & GLABEL_FLG_BORDER) - gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, (gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge); + gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, w, h, (gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge); } #endif // GFX_USE_GWIN && GFX_NEED_LABEL diff --git a/src/gwin/progressbar.c b/src/gwin/progressbar.c index c64e2119..524a5346 100644 --- a/src/gwin/progressbar.c +++ b/src/gwin/progressbar.c @@ -84,6 +84,10 @@ GHandle gwinGProgressbarCreate(GDisplay *g, GProgressbarObject *gs, const GWidge gs->pos = 0; gs->delay = 0; + #if GWIN_PROGRESSBAR_AUTO + gtimerInit(&gs->gt); + #endif + ResetDisplayPos(gs); gwinSetVisible((GHandle)gs, pInit->g.show); @@ -179,54 +183,47 @@ void gwinProgressbarDecrement(GHandle gh) { #undef gsw } -// used by gwinProgressbarStart(); -static void _progressbarCallback(void *param) { - #define gsw ((GProgressbarObject *)gh) - GHandle gh = (GHandle)param; - - if (gh->vmt != (gwinVMT *)&progressbarVMT) - return; - - gwinProgressbarIncrement(gh); - - if (gsw->pos < gsw->max) +#if GWIN_PROGRESSBAR_AUTO + // used by gwinProgressbarStart(); + static void _progressbarCallback(void *param) { + #define gsw ((GProgressbarObject *)gh) + GHandle gh = (GHandle)param; + + if (gh->vmt != (gwinVMT *)&progressbarVMT) + return; + + gwinProgressbarIncrement(gh); + + if (gsw->pos < gsw->max) + gtimerStart(&(gsw->gt), _progressbarCallback, gh, FALSE, gsw->delay); + + #undef gsw + } + + void gwinProgressbarStart(GHandle gh, delaytime_t delay) { + #define gsw ((GProgressbarObject *)gh) + + if (gh->vmt != (gwinVMT *)&progressbarVMT) + return; + + gsw->delay = delay; + gtimerStart(&(gsw->gt), _progressbarCallback, gh, FALSE, gsw->delay); - - #undef gsw -} - -void gwinProgressbarStart(GHandle gh, delaytime_t delay) { - #define gsw ((GProgressbarObject *)gh) - - if (gh->vmt != (gwinVMT *)&progressbarVMT) - return; - - gsw->delay = delay; - - gtimerInit(&(gsw->gt)); - gtimerStart(&(gsw->gt), _progressbarCallback, gh, FALSE, gsw->delay); - - #if 0 - // if this is not made, the progressbar will not start when it's already visible - if (gsw->w.g.flags & GWIN_FLG_VISIBLE) { - gwinSetVisible(gh, FALSE); - gwinSetVisible(gh, TRUE); - } - #endif - - #undef gsw -} - -void gwinProgressbarStop(GHandle gh) { - #define gsw ((GProgressbarObject *)gh) - - if (gh->vmt != (gwinVMT *)&progressbarVMT) - return; - - gtimerStop(&(gsw->gt)); - - #undef gsw -} + + #undef gsw + } + + void gwinProgressbarStop(GHandle gh) { + #define gsw ((GProgressbarObject *)gh) + + if (gh->vmt != (gwinVMT *)&progressbarVMT) + return; + + gtimerStop(&(gsw->gt)); + + #undef gsw + } +#endif /* GWIN_PROGRESSBAR_AUTO */ /*---------------------------------------------------------- * Custom Draw Routines diff --git a/src/gwin/progressbar.h b/src/gwin/progressbar.h index fcf76b12..5253ba0c 100644 --- a/src/gwin/progressbar.h +++ b/src/gwin/progressbar.h @@ -30,7 +30,7 @@ typedef struct GProgressbarObject { int max; int res; int pos; - #if GFX_USE_GTIMER + #if GWIN_PROGRESSBAR_AUTO GTimer gt; delaytime_t delay; #endif @@ -147,31 +147,33 @@ void gwinProgressbarDecrement(GHandle gh); */ #define gwinProgressbarReset(gh) gwinProgressbarSetPosition(gh, ((GProgressbarObject *)(gh))->min) -/** - * @brief Automatically increments the progress bar - * - * @note The delay is generated using the GTIMER module which is based on software/virtual timer. - * Therefore, the delay is totally unprecise. - * - * @note The progressbar incrementation starts at the current level. It is not reset to the minimum value. - * - * @note An event is generated once the maximum value has been reached (ToDo) - * - * @param[in] gh The window handle (must be a progressbar window) - * @param[in] delay The incrementation delay (in milliseconds) - * - * @api - */ -void gwinProgressbarStart(GHandle gh, delaytime_t delay); - -/** - * @brief Stop the timer which is started by @p gwinProgressbarStart() - * - * @param[in] gh The window handle (must be a progressbar window) - * - * @api - */ -void gwinProgressbarStop(GHandle gh); +#if GWIN_PROGRESSBAR_AUTO + /** + * @brief Automatically increments the progress bar + * + * @note The delay is generated using the GTIMER module which is based on software/virtual timer. + * Therefore, the delay is totally unprecise. + * + * @note The progressbar incrementation starts at the current level. It is not reset to the minimum value. + * + * @note An event is generated once the maximum value has been reached (ToDo) + * + * @param[in] gh The window handle (must be a progressbar window) + * @param[in] delay The incrementation delay (in milliseconds) + * + * @api + */ + void gwinProgressbarStart(GHandle gh, delaytime_t delay); + + /** + * @brief Stop the timer which is started by @p gwinProgressbarStart() + * + * @param[in] gh The window handle (must be a progressbar window) + * + * @api + */ + void gwinProgressbarStop(GHandle gh); +#endif /* GWIN_PROGRESSBAR_AUTO */ /** * @brief Some custom progressbar drawing routines diff --git a/src/gwin/sys_defs.h b/src/gwin/sys_defs.h index be99be1e..431de67c 100644 --- a/src/gwin/sys_defs.h +++ b/src/gwin/sys_defs.h @@ -37,7 +37,7 @@ typedef struct GWindowObject *GHandle; */ typedef struct GWindowObject { #if GWIN_NEED_WINDOWMANAGER - // This MUST be the first member of the struct + // This MUST be the first member of the structure gfxQueueASyncItem wmq; // @< The next window (for the window manager) #endif const struct gwinVMT *vmt; // @< The VMT for this GWIN @@ -62,6 +62,10 @@ typedef struct GWindowObject { * * @note Some gwin's will need extra parameters. * @note The dimensions and position may be changed to fit on the real screen. + * @note If you create this structure on the stack, you should always memset + * it to all zero's first in case a future version of the software + * add's extra fields. Alternatively you can use @p gwinClearInit() + * to clear it. * * @{ */ @@ -110,6 +114,18 @@ extern "C" { * Functions that affect all windows *-------------------------------------------------*/ + /** + * @brief Clear a GWindowInit structure to all zero's + * @note This function is provided just to prevent problems + * on operating systems where using memset() causes issues + * in the users application. + * + * @param[in] pwi The GWindowInit structure to clear + * + * @api + */ + void gwinClearInit(GWindowInit *pwi); + /** * @brief Set the default foreground color for all new GWIN windows * @@ -941,7 +957,7 @@ extern "C" { #endif #if GWIN_NEED_IMAGE || defined(__DOXYGEN__) - #include "src/gwin/image.h" + #include "src/gwin/gimage.h" #endif #endif /* GFX_USE_GWIN */ diff --git a/src/gwin/sys_options.h b/src/gwin/sys_options.h index bd720711..69507b94 100644 --- a/src/gwin/sys_options.h +++ b/src/gwin/sys_options.h @@ -71,6 +71,13 @@ #ifndef GWIN_NEED_BUTTON #define GWIN_NEED_BUTTON FALSE #endif + /** + * @brief Should progressbar functions be included. + * @details Defaults to FALSE + */ + #ifndef GWIN_NEED_PROGRESSBAR + #define GWIN_NEED_PROGRESSBAR FALSE + #endif /** * @brief Should slider functions be included. * @details Defaults to FALSE @@ -221,6 +228,13 @@ #ifndef GWIN_NEED_IMAGE_ANIMATION #define GWIN_NEED_IMAGE_ANIMATION FALSE #endif + /** + * @brief Enable the API to automatically increment the progressbar over time + * @details Defaults to FALSE + */ + #ifndef GWIN_PROGRESSBAR_AUTO + #define GWIN_PROGRESSBAR_AUTO FALSE + #endif /** @} */ #endif /* _GWIN_OPTIONS_H */ diff --git a/src/gwin/sys_rules.h b/src/gwin/sys_rules.h index 3178def8..fda55fe7 100644 --- a/src/gwin/sys_rules.h +++ b/src/gwin/sys_rules.h @@ -17,6 +17,7 @@ #define _GWIN_RULES_H #if GFX_USE_GWIN + // Sub-system rules #if !GFX_USE_GDISP #error "GWIN: GFX_USE_GDISP must be TRUE when using GWIN" #endif @@ -25,18 +26,8 @@ #warning "GWIN: Drawing can occur outside the defined windows as GDISP_NEED_CLIP is FALSE" #endif #endif - #if GWIN_NEED_IMAGE - #if !GDISP_NEED_IMAGE - #error "GWIN: GDISP_NEED_IMAGE is required when GWIN_NEED_IMAGE is TRUE." - #endif - #endif - #if GWIN_NEED_RADIO - #if !GDISP_NEED_CIRCLE - #if GFX_DISPLAY_RULE_WARNINGS - #warning "GWIN: GDISP_NEED_CIRCLE should be set to TRUE for much nicer radio button widgets." - #endif - #endif - #endif + + // Objects require their super-class #if GWIN_NEED_HIERARCHY #if !GQUEUE_NEED_ASYNC #if GFX_DISPLAY_RULE_WARNINGS @@ -59,17 +50,14 @@ GWIN_NEED_IMAGE || GWIN_NEED_CHECKBOX || GWIN_NEED_PROGRESSBAR #if !GWIN_NEED_WIDGET #if GFX_DISPLAY_RULE_WARNINGS - #warning "GWIN: GWIN_NEED_WIDGET is required when a Widget is used. It has been turned on for you." + #warning "GWIN: GWIN_NEED_WIDGET is required when a widget is used. It has been turned on for you." #endif #undef GWIN_NEED_WIDGET #define GWIN_NEED_WIDGET TRUE #endif #endif - #if GWIN_NEED_LIST - #if !GDISP_NEED_TEXT - #error "GWIN: GDISP_NEED_TEXT is required when GWIN_NEED_LIST is TRUE." - #endif - #endif + + // Rules for the super-classes #if GWIN_NEED_WIDGET #if !GDISP_NEED_TEXT #error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_WIDGET is TRUE." @@ -104,12 +92,36 @@ #define GQUEUE_NEED_ASYNC TRUE #endif #endif + + // Rules for individual objects + #if GWIN_NEED_LIST + #if !GDISP_NEED_TEXT + #error "GWIN: GDISP_NEED_TEXT is required when GWIN_NEED_LIST is TRUE." + #endif + #endif + #if GWIN_NEED_RADIO + #if !GDISP_NEED_CIRCLE + #if GFX_DISPLAY_RULE_WARNINGS + #warning "GWIN: GDISP_NEED_CIRCLE should be set to TRUE for much nicer radio button widgets." + #endif + #endif + #endif + #if GWIN_NEED_IMAGE + #if !GDISP_NEED_IMAGE + #error "GWIN: GDISP_NEED_IMAGE is required when GWIN_NEED_IMAGE is TRUE." + #endif + #endif #if GWIN_NEED_CONSOLE #if !GDISP_NEED_TEXT #error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE." #endif #endif - #if GWIN_NEED_GRAPH + #if GWIN_NEED_PROGRESSBAR + #if GWIN_PROGRESSBAR_AUTO + #if !GFX_USE_GTIMER + #error "GWIN: GFX_USE_GTIMER is required if GWIN_PROGRESSBAR_AUTO is TRUE." + #endif + #endif #endif #endif diff --git a/tools/touch_driver_test/main.c b/tools/touch_driver_test/main.c index adfafa0f..a8318edd 100644 --- a/tools/touch_driver_test/main.c +++ b/tools/touch_driver_test/main.c @@ -66,6 +66,7 @@ int main(void) { { GWindowInit wi; + gwinClearInit(&wi); wi.show = TRUE; wi.x = 0; wi.y = bHeight; wi.width = swidth; wi.height = sheight-bHeight; ghc = gwinConsoleCreate(&gc, &wi); }