aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gfx.c2
-rw-r--r--src/gqueue/gqueue.c29
-rw-r--r--src/gwin/button.c9
-rw-r--r--src/gwin/checkbox.c5
-rw-r--r--src/gwin/console.c3
-rw-r--r--src/gwin/graph.c3
-rw-r--r--src/gwin/gwidget.c46
-rw-r--r--src/gwin/gwin.c290
-rw-r--r--src/gwin/gwin.mk1
-rw-r--r--src/gwin/gwm.c144
-rw-r--r--src/gwin/slider.c7
11 files changed, 461 insertions, 78 deletions
diff --git a/src/gfx.c b/src/gfx.c
index 2b307426..3856eea3 100644
--- a/src/gfx.c
+++ b/src/gfx.c
@@ -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
}