diff options
author | inmarket <andrewh@inmarket.com.au> | 2013-06-08 02:27:59 +1000 |
---|---|---|
committer | inmarket <andrewh@inmarket.com.au> | 2013-06-08 02:27:59 +1000 |
commit | 777ec6af7c1b594f7b7a9cbaaf7ead90d8fb7e8f (patch) | |
tree | 2827629985d75e63f53b3de689d52a5080404780 /src | |
parent | 663caba66214acdb6170903f6a203740ea1de8b9 (diff) | |
download | uGFX-777ec6af7c1b594f7b7a9cbaaf7ead90d8fb7e8f.tar.gz uGFX-777ec6af7c1b594f7b7a9cbaaf7ead90d8fb7e8f.tar.bz2 uGFX-777ec6af7c1b594f7b7a9cbaaf7ead90d8fb7e8f.zip |
Add a simple GWIN window manager, Change the way GWIN visibility works
Diffstat (limited to 'src')
-rw-r--r-- | src/gfx.c | 2 | ||||
-rw-r--r-- | src/gqueue/gqueue.c | 29 | ||||
-rw-r--r-- | src/gwin/button.c | 9 | ||||
-rw-r--r-- | src/gwin/checkbox.c | 5 | ||||
-rw-r--r-- | src/gwin/console.c | 3 | ||||
-rw-r--r-- | src/gwin/graph.c | 3 | ||||
-rw-r--r-- | src/gwin/gwidget.c | 46 | ||||
-rw-r--r-- | src/gwin/gwin.c | 290 | ||||
-rw-r--r-- | src/gwin/gwin.mk | 1 | ||||
-rw-r--r-- | src/gwin/gwm.c | 144 | ||||
-rw-r--r-- | src/gwin/slider.c | 7 |
11 files changed, 461 insertions, 78 deletions
@@ -32,7 +32,7 @@ void DEPRECATED("Use gfxInit() instead") gdispInit() { gfxInit(); } /* These init functions are defined by each module but not published */ extern void _gosInit(void); -#if GFX_USE_GDISP && (GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC) +#if GFX_USE_GDISP extern void _gdispInit(void); #endif #if GFX_USE_TDISP diff --git a/src/gqueue/gqueue.c b/src/gqueue/gqueue.c index d515a425..11d10c0a 100644 --- a/src/gqueue/gqueue.c +++ b/src/gqueue/gqueue.c @@ -21,6 +21,9 @@ * @file src/gqueue/gqueue.c * @brief GQUEUE source file. */ + +#include "gfx.h" + #if GFX_USE_GQUEUE #if GQUEUE_NEED_ASYNC @@ -34,7 +37,7 @@ gfxSystemLock(); if ((pi = pqueue->head)) pqueue->head = pi->next; - gfxSytemUnlock(); + gfxSystemUnlock(); return pi; } void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { @@ -58,13 +61,15 @@ gfxSystemUnlock(); } void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { + gfxQueueASyncItem *pi; + if (!pitem) return; gfxSystemLock(); if (pqueue->head) { if (pqueue->head == pitem) { pqueue->head = pitem->next; } else { - for(gfxQueueASyncItem *pi = pqueue->head; pi->next; pi = pi->next) { + for(pi = pqueue->head; pi->next; pi = pi->next) { if (pi->next == pitem) { pi->next = pitem->next; if (pqueue->tail == pitem) @@ -80,8 +85,10 @@ return pqueue->head == NULL; } bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { + gfxQueueASyncItem *pi; + gfxSystemLock(); - for(gfxQueueASyncItem *pi = pqueue->head; pi; pi = pi->next) { + for(pi = pqueue->head; pi; pi = pi->next) { if (pi == pitem) { gfxSystemUnlock(); return TRUE; @@ -132,13 +139,15 @@ gfxSemSignal(&pqueue->sem); } void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { + gfxQueueGSyncItem *pi; + if (!pitem) return; gfxSystemLock(); if (pqueue->head) { if (pqueue->head == pitem) { pqueue->head = pitem->next; } else { - for(gfxQueueGSyncItem *pi = pqueue->head; pi->next; pi = pi->next) { + for(pi = pqueue->head; pi->next; pi = pi->next) { if (pi->next == pitem) { pi->next = pitem->next; if (pqueue->tail == pitem) @@ -154,8 +163,10 @@ return pqueue->head == NULL; } bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { + gfxQueueGSyncItem *pi; + gfxSystemLock(); - for(gfxQueueGSyncItem *pi = pqueue->head; pi; pi = pi->next) { + for(pi = pqueue->head; pi; pi = pi->next) { if (pi == pitem) { gfxSystemUnlock(); return TRUE; @@ -214,6 +225,8 @@ return gfxSemWait(&pitem->sem, ms); } void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) { + gfxQueueFSyncItem *pi; + if (!pitem) return; gfxSystemLock(); if (pqueue->head) { @@ -225,7 +238,7 @@ gfxSemDestroy(&pitem->sem); return; } - for(gfxQueueFSyncItem *pi = pqueue->head; pi->next; pi = pi->next) { + for(pi = pqueue->head; pi->next; pi = pi->next) { if (pi->next == pitem) { pi->next = pitem->next; if (pqueue->tail == pitem) @@ -240,8 +253,10 @@ return pqueue->head == NULL; } bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) { + gfxQueueASyncItem *pi; + gfxSystemLock(); - for(gfxQueueFSyncItem *pi = pqueue->head; pi; pi = pi->next) { + for(pi = pqueue->head; pi; pi = pi->next) { if (pi == pitem) { gfxSystemUnlock(); return TRUE; diff --git a/src/gwin/button.c b/src/gwin/button.c index 1ebc8ee5..83b81b03 100644 --- a/src/gwin/button.c +++ b/src/gwin/button.c @@ -40,6 +40,7 @@ static const gwidgetVMT buttonVMT = { { "Button", // The classname _gwidgetDestroy, // The destroy routine + _gwidgetRedraw, // The redraw routine 0, // The after-clear routine }, gwinButtonDraw_3D, // The default drawing routine @@ -94,14 +95,14 @@ static void SendButtonEvent(GWidgetObject *gw) { static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) { (void) x; (void) y; gw->g.flags |= GBUTTON_FLG_PRESSED; - gwinDraw((GHandle)gw); + _gwidgetRedraw((GHandle)gw); } // A mouse up has occurred (it may or may not be over the button) static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) { (void) x; (void) y; gw->g.flags &= ~GBUTTON_FLG_PRESSED; - gwinDraw((GHandle)gw); + _gwidgetRedraw((GHandle)gw); #if !GWIN_BUTTON_LAZY_RELEASE // If the mouse up was not over the button then cancel the event @@ -116,14 +117,14 @@ static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) { static void ToggleOff(GWidgetObject *gw, uint16_t instance) { (void) instance; gw->g.flags &= ~GBUTTON_FLG_PRESSED; - gwinDraw((GHandle)gw); + _gwidgetRedraw((GHandle)gw); } // A toggle on has occurred static void ToggleOn(GWidgetObject *gw, uint16_t instance) { (void) instance; gw->g.flags |= GBUTTON_FLG_PRESSED; - gwinDraw((GHandle)gw); + _gwidgetRedraw((GHandle)gw); // Trigger the event on button down (different than for mouse/touch) SendButtonEvent(gw); } diff --git a/src/gwin/checkbox.c b/src/gwin/checkbox.c index d35f271c..893dab9c 100644 --- a/src/gwin/checkbox.c +++ b/src/gwin/checkbox.c @@ -33,6 +33,7 @@ static const gwidgetVMT checkboxVMT = { { "Checkbox", // The classname _gwidgetDestroy, // The destroy routine + _gwidgetRedraw, // The redraw routine 0, // The after-clear routine }, gwinCheckboxDraw_CheckOnLeft, // The default drawing routine @@ -78,7 +79,7 @@ static void SendCheckboxEvent(GWidgetObject *gw) { static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) { (void) x; (void) y; gw->g.flags ^= GCHECKBOX_FLG_CHECKED; - gwinDraw((GHandle)gw); + _gwidgetRedraw((GHandle)gw); SendCheckboxEvent(gw); } @@ -86,7 +87,7 @@ static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) { static void ToggleOn(GWidgetObject *gw, uint16_t instance) { (void) instance; gw->g.flags ^= GCHECKBOX_FLG_CHECKED; - gwinDraw((GHandle)gw); + _gwidgetRedraw((GHandle)gw); SendCheckboxEvent(gw); } diff --git a/src/gwin/console.c b/src/gwin/console.c index d9bda362..c4b2798d 100644 --- a/src/gwin/console.c +++ b/src/gwin/console.c @@ -61,11 +61,12 @@ static void AfterClear(GWindowObject *gh) { static const gwinVMT consoleVMT = { "Console", // The classname 0, // The destroy routine + 0, // The redraw routine AfterClear, // The after-clear routine }; GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height) { - if (!(gc = (GConsoleObject *)_gwinInit((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject), &consoleVMT))) + if (!(gc = (GConsoleObject *)_gwindowInit((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject), &consoleVMT, GWIN_FLG_VISIBLE))) return 0; #if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM gc->stream.vmt = &GWindowConsoleVMT; diff --git a/src/gwin/graph.c b/src/gwin/graph.c index 0ae9822b..393297e7 100644 --- a/src/gwin/graph.c +++ b/src/gwin/graph.c @@ -32,6 +32,7 @@ static const GGraphStyle GGraphDefaultStyle = { static const gwinVMT graphVMT = { "Graph", // The classname 0, // The destroy routine + 0, // The redraw routine 0, // The after-clear routine }; @@ -164,7 +165,7 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t } GHandle gwinCreateGraph(GGraphObject *gg, coord_t x, coord_t y, coord_t width, coord_t height) { - if (!(gg = (GGraphObject *)_gwinInit((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject), &graphVMT))) + if (!(gg = (GGraphObject *)_gwindowInit((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject), &graphVMT, GWIN_FLG_VISIBLE))) return 0; gg->xorigin = gg->yorigin = 0; gg->lastx = gg->lasty = 0; diff --git a/src/gwin/gwidget.c b/src/gwin/gwidget.c index 3f23140c..773a715d 100644 --- a/src/gwin/gwidget.c +++ b/src/gwin/gwidget.c @@ -7,7 +7,7 @@ #include "gfx.h" -#if GFX_USE_GWIN +#if GFX_USE_GWIN && GWIN_NEED_WIDGET #include <string.h> @@ -24,7 +24,7 @@ static void gwidgetCallback(void *param, GEvent *pe) { #define pde ((GEventDial *)pe) // check if widget is disabled - if (!(gw->g.flags & GWIN_FLG_ENABLED)) + if ((gw->g.flags & (GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) return; // Process via AllEvents() if it is defined @@ -87,10 +87,9 @@ static void gwidgetCallback(void *param, GEvent *pe) { } GHandle _gwidgetInit(GWidgetObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwidgetVMT *vmt) { - if (!(pgw = (GWidgetObject *)_gwinInit((GWindowObject *)pgw, x, y, width, height, size, (const gwinVMT *)vmt))) + if (!(pgw = (GWidgetObject *)_gwindowInit((GWindowObject *)pgw, x, y, width, height, size, (const gwinVMT *)vmt, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED))) return 0; - pgw->g.flags |= (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED); pgw->txt = ""; pgw->fnDraw = vmt->DefaultDraw; pgw->fnParam = 0; @@ -101,9 +100,6 @@ GHandle _gwidgetInit(GWidgetObject *pgw, coord_t x, coord_t y, coord_t width, co } void _gwidgetDestroy(GHandle gh) { - if (!(gh->flags & GWIN_FLG_WIDGET)) - return; - // Deallocate the text (if necessary) if ((gh->flags & GWIN_FLG_ALLOCTXT)) { gh->flags &= ~GWIN_FLG_ALLOCTXT; @@ -112,21 +108,10 @@ void _gwidgetDestroy(GHandle gh) { // Untangle the listeners (both on us and to us). geventDetachSource(&gw->listener, 0); geventDetachSourceListeners((GSourceHandle)gh); - gh->flags &= ~GWIN_FLG_WIDGET; -} - -void gwinSetEnabled(GHandle gh, bool_t enabled) { - if (!(gh->flags & GWIN_FLG_WIDGET)) - return; - - if (enabled) - gh->flags |= GWIN_FLG_ENABLED; - else - gh->flags &= ~GWIN_FLG_ENABLED; } -void gwinDraw(GHandle gh) { - if (!(gh->flags & GWIN_FLG_WIDGET)) +void _gwidgetRedraw(GHandle gh) { + if (!(gh->flags & GWIN_FLG_VISIBLE)) return; #if GDISP_NEED_CLIP @@ -136,6 +121,23 @@ void gwinDraw(GHandle gh) { gw->fnDraw(gw, gw->fnParam); } +void gwinSetEnabled(GHandle gh, bool_t enabled) { + if (!(gh->flags & GWIN_FLG_WIDGET)) + return; + + if (enabled) { + if (!(gh->flags & GWIN_FLG_ENABLED)) { + gh->flags |= GWIN_FLG_ENABLED; + _gwidgetRedraw(gh); + } + } else { + if ((gh->flags & GWIN_FLG_ENABLED)) { + gh->flags &= ~GWIN_FLG_ENABLED; + _gwidgetRedraw(gh); + } + } +} + void gwinSetText(GHandle gh, const char *txt, bool_t useAlloc) { if (!(gh->flags & GWIN_FLG_WIDGET)) return; @@ -162,6 +164,7 @@ void gwinSetText(GHandle gh, const char *txt, bool_t useAlloc) { } gw->txt = txt ? txt : ""; + _gwidgetRedraw(gh); } const char *gwinGetText(GHandle gh) { @@ -177,6 +180,7 @@ void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param) { gw->fnDraw = fn ? fn : wvmt->DefaultDraw; gw->fnParam = param; + _gwidgetRedraw(gh); } bool_t gwinAttachListener(GHandle gh, GListener *pl, unsigned flags) { @@ -249,6 +253,6 @@ bool_t gwinAttachListener(GHandle gh, GListener *pl, unsigned flags) { } #endif -#endif /* GFX_USE_GWIN */ +#endif /* GFX_USE_GWIN && GWIN_NEED_WIDGET */ /** @} */ diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c index 163e821d..3e790d38 100644 --- a/src/gwin/gwin.c +++ b/src/gwin/gwin.c @@ -11,90 +11,247 @@ #include "gwin/class_gwin.h" +// Needed if there is no window manager +#define MIN_WIN_WIDTH 1 +#define MIN_WIN_HEIGHT 1 + +/*----------------------------------------------- + * Data + *-----------------------------------------------*/ + static const gwinVMT basegwinVMT = { "GWIN", // The classname 0, // The destroy routine + 0, // The redraw routine 0, // The after-clear routine }; -static font_t defaultFont; static color_t defaultFgColor = White; static color_t defaultBgColor = Black; +#if GDISP_NEED_TEXT + static font_t defaultFont; +#endif +#if GWIN_NEED_WINDOWMANAGER + gfxQueueASync _GWINList; + extern GWindowManager GNullWindowManager; + static GWindowManager * cwm; +#endif + +/*----------------------------------------------- + * Helper Routines + *-----------------------------------------------*/ + +#if !GWIN_NEED_WINDOWMANAGER + static void _gwm_vis(GHandle gh) { + if (gh->vmt->Redraw) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gh->vmt->Redraw(gh); + } else + gwinClear(gh); + } + static void _gwm_redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) { + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } + if (x > gdispGetWidth()-MIN_WIN_WIDTH) x = gdispGetWidth()-MIN_WIN_WIDTH; + if (y > gdispGetHeight()-MIN_WIN_HEIGHT) y = gdispGetHeight()-MIN_WIN_HEIGHT; + if (w < MIN_WIN_WIDTH) { w = MIN_WIN_WIDTH; } + if (h < MIN_WIN_HEIGHT) { h = MIN_WIN_HEIGHT; } + if (x+w > gdispGetWidth()) w = gdispGetWidth() - x; + if (y+h > gdispGetHeight()) h = gdispGetHeight() - y; + gh->x = x; gh->y = y; + gh->width = w; gh->height = h; + } +#endif + +/*----------------------------------------------- + * Class Routines + *-----------------------------------------------*/ + +void _gwinInit(void) { + #if GWIN_NEED_WINDOWMANAGER + gfxQueueASyncInit(&_GWINList); + cwm = &GNullWindowManager; + cwm->vmt->Init(); + #endif +} // Internal routine for use by GWIN components only -// Initialise a window creating it dynamicly if required. -GHandle _gwinInit(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwinVMT *vmt) { - coord_t w, h; - - // Check the window size against the screen size - w = gdispGetWidth(); - h = gdispGetHeight(); - if (x < 0) { width += x; x = 0; } - if (y < 0) { height += y; y = 0; } - if (x >= w || y >= h) return 0; - if (x+width > w) width = w - x; - if (y+height > h) height = h - y; - +// Initialise a window creating it dynamically if required. +GHandle _gwindowInit(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwinVMT *vmt, uint16_t flags) { // Allocate the structure if necessary if (!pgw) { if (!(pgw = (GWindowObject *)gfxAlloc(size))) return 0; - pgw->flags = GWIN_FLG_DYNAMIC; + pgw->flags = flags|GWIN_FLG_DYNAMIC; } else - pgw->flags = 0; + pgw->flags = flags; // Initialise all basic fields pgw->vmt = vmt; - pgw->x = x; - pgw->y = y; - pgw->width = width; - pgw->height = height; pgw->color = defaultFgColor; pgw->bgcolor = defaultBgColor; #if GDISP_NEED_TEXT pgw->font = defaultFont; #endif + + #if GWIN_NEED_WINDOWMANAGER + if (!cwm->vmt->Add(pgw, x, y, width, height)) { + if ((pgw->flags & GWIN_FLG_DYNAMIC)) + gfxFree(pgw); + return 0; + } + #else + _gwm_redim(pgw, x, y, width, height); + if ((pgw->flags & GWIN_FLG_VISIBLE)) + _gwm_vis(pgw); + #endif + return (GHandle)pgw; } +/*----------------------------------------------- + * Routines that affect all windows + *-----------------------------------------------*/ + +#if GWIN_NEED_WINDOWMANAGER + void gwinSetWindowManager(struct GWindowManager *gwm) { + if (!gwm) + gwm = &GNullWindowManager; + if (cwm != gwm) { + cwm->vmt->DeInit(); + cwm = gwm; + cwm->vmt->Init(); + } + } +#endif + +void gwinSetDefaultColor(color_t clr) { + defaultFgColor = clr; +} + +void gwinSetDefaultBgColor(color_t bgclr) { + defaultBgColor = bgclr; +} + +#if GDISP_NEED_TEXT + void gwinSetDefaultFont(font_t font) { + defaultFont = font; + } +#endif + +/*----------------------------------------------- + * The GWindow Routines + *-----------------------------------------------*/ + GHandle gwinCreateWindow(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height) { - return _gwinInit(pgw, x, y, width, height, sizeof(GWindowObject), &basegwinVMT); + return _gwindowInit(pgw, x, y, width, height, sizeof(GWindowObject), &basegwinVMT, GWIN_FLG_VISIBLE); } void gwinDestroy(GHandle gh) { + // Remove from the window manager + #if GWIN_NEED_WINDOWMANAGER + cwm->vmt->Delete(gh); + #endif + + // Class destroy routine if (gh->vmt->Destroy) gh->vmt->Destroy(gh); // Clean up the structure - if (gh->flags & GWIN_FLG_DYNAMIC) { - gh->flags = 0; // To be sure, to be sure + if (gh->flags & GWIN_FLG_DYNAMIC) gfxFree((void *)gh); - } + + gh->flags = 0; // To be sure, to be sure } const char *gwinGetClassName(GHandle gh) { return gh->vmt->classname; } -void gwinSetDefaultColor(color_t clr) { - defaultFgColor = clr; +void gwinSetVisible(GHandle gh, bool_t visible) { + if (visible) { + if (!(gh->flags & GWIN_FLG_VISIBLE)) { + gh->flags |= GWIN_FLG_VISIBLE; + #if GWIN_NEED_WINDOWMANAGER + cwm->vmt->Visible(gh); + #else + _gwm_vis(gh); + #endif + } + } else { + if ((gh->flags & GWIN_FLG_VISIBLE)) { + gh->flags &= ~GWIN_FLG_VISIBLE; + #if GWIN_NEED_WINDOWMANAGER + cwm->vmt->Visible(gh); + #endif + } + } } -void gwinSetDefaultBgColor(color_t bgclr) { - defaultBgColor = bgclr; +bool_t gwinGetVisible(GHandle gh) { + return (gh->flags & GWIN_FLG_VISIBLE) ? TRUE : FALSE; } -#if GDISP_NEED_TEXT - void gwinSetDefaultFont(font_t font) { - defaultFont = font; - } +void gwinMove(GHandle gh, coord_t x, coord_t y) { + #if GWIN_NEED_WINDOWMANAGER + cwm->vmt->Redim(gh, x, y, gh->width, gh->height); + #else + _gwm_redim(gh, x, y, gh->width, gh->height); + #endif +} + +void gwinResize(GHandle gh, coord_t width, coord_t height) { + #if GWIN_NEED_WINDOWMANAGER + cwm->vmt->Redim(gh, gh->x, gh->y, width, height); + #else + _gwm_redim(gh, gh->x, gh->y, width, height); + #endif +} +void gwinSetMinMax(GHandle gh, GWindowMinMax minmax) { + #if GWIN_NEED_WINDOWMANAGER + cwm->vmt->MinMax(gh, minmax); + #else + (void) gh; + (void) minmax; + #endif +} + +void gwinRaise(GHandle gh) { + #if GWIN_NEED_WINDOWMANAGER + cwm->vmt->Raise(gh); + #else + if ((gh->flags & GWIN_FLG_VISIBLE)) { + if (gh->vmt->Redraw) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gh->vmt->Redraw(gh); + } + } + #endif +} + +GWindowMinMax gwinGetMinMax(GHandle gh) { + if (gh->flags & GWIN_FLG_MINIMIZED) + return GWIN_MINIMIZE; + if (gh->flags & GWIN_FLG_MAXIMIZED) + return GWIN_MAXIMIZE; + return GWIN_NORMAL; +} + +#if GDISP_NEED_TEXT void gwinSetFont(GHandle gh, font_t font) { gh->font = font; } #endif void gwinClear(GHandle gh) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -104,6 +261,9 @@ void gwinClear(GHandle gh) { } void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -111,6 +271,9 @@ void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) { } void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -118,6 +281,9 @@ void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) { } void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -125,6 +291,9 @@ void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) { } void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -132,6 +301,9 @@ void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) { } void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -140,6 +312,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor #if GDISP_NEED_CIRCLE void gwinDrawCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -147,6 +322,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor } void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -156,6 +334,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor #if GDISP_NEED_ELLIPSE void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -163,6 +344,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor } void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -172,6 +356,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor #if GDISP_NEED_ARC void gwinDrawArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -179,6 +366,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor } void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -188,6 +378,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor #if GDISP_NEED_PIXELREAD color_t gwinGetPixelColor(GHandle gh, coord_t x, coord_t y) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -197,7 +390,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor #if GDISP_NEED_TEXT void gwinDrawChar(GHandle gh, coord_t x, coord_t y, char c) { - if (!gh->font) return; + if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -205,7 +400,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor } void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c) { - if (!gh->font) return; + if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -213,7 +410,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor } void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str) { - if (!gh->font) return; + if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -221,7 +420,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor } void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str) { - if (!gh->font) return; + if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -229,7 +430,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor } void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) { - if (!gh->font) return; + if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -237,7 +440,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor } void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) { - if (!gh->font) return; + if (!((gh->flags & GWIN_FLG_VISIBLE)) || !gh->font) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -247,6 +452,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor #if GDISP_NEED_CONVEX_POLYGON void gwinDrawPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -254,6 +462,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor } void gwinFillConvexPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif @@ -263,6 +474,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor #if GDISP_NEED_IMAGE gdispImageError gwinImageDraw(GHandle gh, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { + if (!((gh->flags & GWIN_FLG_VISIBLE))) + return GDISP_IMAGE_ERR_OK; + #if GDISP_NEED_CLIP gdispSetClip(gh->x, gh->y, gh->width, gh->height); #endif diff --git a/src/gwin/gwin.mk b/src/gwin/gwin.mk index 90a8e9b4..fb8fdfd1 100644 --- a/src/gwin/gwin.mk +++ b/src/gwin/gwin.mk @@ -1,5 +1,6 @@ GFXSRC += $(GFXLIB)/src/gwin/gwin.c \ $(GFXLIB)/src/gwin/gwidget.c \ + $(GFXLIB)/src/gwin/gwm.c \ $(GFXLIB)/src/gwin/console.c \ $(GFXLIB)/src/gwin/graph.c \ $(GFXLIB)/src/gwin/button.c \ diff --git a/src/gwin/gwm.c b/src/gwin/gwm.c new file mode 100644 index 00000000..bc561345 --- /dev/null +++ b/src/gwin/gwm.c @@ -0,0 +1,144 @@ +/* + * This file is subject to the terms of the GFX License, v1.0. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://chibios-gfx.com/license.html + */ + +#include "gfx.h" + +// Used by the NULL window manager +#define MIN_WIN_WIDTH 3 +#define MIN_WIN_HEIGHT 3 + +/*----------------------------------------------- + * The default window manager (GNullWindowManager) + *-----------------------------------------------*/ + +#if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER + +#include "gwin/class_gwin.h" + +/*----------------------------------------------- + * Data + *-----------------------------------------------*/ + +static void WM_Init(void); +static void WM_DeInit(void); +static bool_t WM_Add(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h); +static void WM_Delete(GHandle gh); +static void WM_Visible(GHandle gh); +static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h); +static void WM_Raise(GHandle gh); +static void WM_MinMax(GHandle gh, GWindowMinMax minmax); + +static const gwmVMT GNullWindowManagerVMT = { + WM_Init, + WM_DeInit, + WM_Add, + WM_Delete, + WM_Visible, + WM_Redim, + WM_Raise, + WM_MinMax, +}; + +const GWindowManager GNullWindowManager = { + &GNullWindowManagerVMT, +}; + +/*----------------------------------------------- + * Window Manager Routines + *-----------------------------------------------*/ + +static void WM_Init(void) { + // We don't need to do anything here. + // A full window manager would move the windows around, add borders etc + + // clear the screen + // cycle through the windows already defined displaying them + // or cut all the window areas out of the screen and clear the remainder +} + +static void WM_DeInit(void) { + // We don't need to do anything here. + // A full window manager would remove any borders etc +} + +static bool_t WM_Add(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) { + // Put it on the queue + gfxQueueASyncPut(&_GWINList, &gh->wmq); + + // Make sure the size is valid + WM_Redim(gh, x, y, w, h); + + // Display it if it is visible + WM_Visible(gh); + return TRUE; +} + +static void WM_Delete(GHandle gh) { + // A real window manager would make the window invisible + // (and then clear the area underneath) + + // Just remove it from the queue + gfxQueueASyncRemove(&_GWINList, &gh->wmq); +} + +static void WM_Visible(GHandle gh) { + if ((gh->flags & GWIN_FLG_VISIBLE)) { + if (gh->vmt->Redraw) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gh->vmt->Redraw(gh); + } else + gwinClear(gh); + // A real window manager would also redraw the borders + } + + // else + // A real window manager would make the window invisible + // (and then clear the area underneath) + +} + +static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) { + // This is the simplest way of doing it - just clip the the screen + // If it won't fit on the screen move it around until it does. + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } + if (x > gdispGetWidth()-MIN_WIN_WIDTH) x = gdispGetWidth()-MIN_WIN_WIDTH; + if (y > gdispGetHeight()-MIN_WIN_HEIGHT) y = gdispGetHeight()-MIN_WIN_HEIGHT; + if (w < MIN_WIN_WIDTH) { w = MIN_WIN_WIDTH; } + if (h < MIN_WIN_HEIGHT) { h = MIN_WIN_HEIGHT; } + if (x+w > gdispGetWidth()) w = gdispGetWidth() - x; + if (y+h > gdispGetHeight()) h = gdispGetHeight() - y; + gh->x = x; gh->y = y; + gh->width = w; gh->height = h; +} + +static void WM_MinMax(GHandle gh, GWindowMinMax minmax) { + (void)gh; (void) minmax; + // We don't support minimising, maximising or restoring +} + +static void WM_Raise(GHandle gh) { + // Take it off the list and then put it back on top + // The order of the list then reflects the z-order. + gfxQueueASyncRemove(&_GWINList, &gh->wmq); + gfxQueueASyncPut(&_GWINList, &gh->wmq); + + // Redraw the window + if ((gh->flags & GWIN_FLG_VISIBLE)) { + if (gh->vmt->Redraw) { + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + gh->vmt->Redraw(gh); + } + } +} + +#endif /* GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER */ +/** @} */ diff --git a/src/gwin/slider.c b/src/gwin/slider.c index a0289d3d..1a1855a9 100644 --- a/src/gwin/slider.c +++ b/src/gwin/slider.c @@ -35,6 +35,7 @@ static const gwidgetVMT sliderVMT = { { "Slider", // The classname _gwidgetDestroy, // The destroy routine + _gwidgetRedraw, // The redraw routine 0, // The after-clear routine }, gwinSliderDraw_Std, // The default drawing routine @@ -101,7 +102,7 @@ static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) { if (x < 0 || x >= gh->width || y < 0 || y >= gh->height) { // No - restore the slider ResetDisplayPos(gsw); - gwinDraw(gh); + _gwidgetRedraw(gh); return; } #endif @@ -124,7 +125,7 @@ static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) { } ResetDisplayPos(gsw); - gwinDraw(gh); + _gwidgetRedraw(gh); // Generate the event SendSliderEvent(gw); @@ -154,7 +155,7 @@ static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y) { } // Update the display - gwinDraw(&gw->g); + _gwidgetRedraw(&gw->g); #undef gsw } |