aboutsummaryrefslogtreecommitdiffstats
path: root/src/gwin
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2013-07-04 00:20:32 +1000
committerinmarket <andrewh@inmarket.com.au>2013-07-04 00:20:32 +1000
commit09a359813f0abe8f99c32dadfa1ac2c68356ddfd (patch)
treece6bfc9861baac4ed2de9e84995f307b8fd7cffa /src/gwin
parent3f80e1f89dbeec06dd97a914d6851ad4596b1743 (diff)
downloaduGFX-09a359813f0abe8f99c32dadfa1ac2c68356ddfd.tar.gz
uGFX-09a359813f0abe8f99c32dadfa1ac2c68356ddfd.tar.bz2
uGFX-09a359813f0abe8f99c32dadfa1ac2c68356ddfd.zip
Label, Image and Window Manager changes
Diffstat (limited to 'src/gwin')
-rw-r--r--src/gwin/gimage.c173
-rw-r--r--src/gwin/gwin.c18
-rw-r--r--src/gwin/gwin.mk2
-rw-r--r--src/gwin/gwm.c44
-rw-r--r--src/gwin/image.c95
-rw-r--r--src/gwin/label.c44
6 files changed, 251 insertions, 125 deletions
diff --git a/src/gwin/gimage.c b/src/gwin/gimage.c
new file mode 100644
index 00000000..464bc595
--- /dev/null
+++ b/src/gwin/gimage.c
@@ -0,0 +1,173 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://chibios-gfx.com/license.html
+ */
+
+/**
+ * @file src/gwin/image.c
+ * @brief GWIN sub-system image code.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GWIN && GWIN_NEED_IMAGE
+
+#include "gwin/class_gwin.h"
+
+#define widget(gh) ((GImageWidget*)gh)
+
+static void _destroy(GWindowObject *gh) {
+ if (gdispImageIsOpen(&widget(gh)->image))
+ gdispImageClose(&widget(gh)->image);
+}
+
+static void _redraw(GHandle gh) {
+ coord_t x, y, w, h, dx, dy;
+
+ // The default display area
+ x = gh->x;
+ y = gh->y;
+ w = gh->width;
+ h = gh->height;
+
+ // If the image isn't open just clear the area
+ if (!gdispImageIsOpen(&widget(gh)->image)) {
+ gdispFillArea(x, y, w, h, gh->bgcolor);
+ return;
+ }
+
+ // Center horizontally if the area is larger than the image
+ if (widget(gh)->image.width < w) {
+ w = widget(gh)->image.width;
+ dx = (gh->width-w)/2;
+ x += dx;
+ if (dx)
+ gdispFillArea(gh->x, y, dx, h, gh->bgcolor);
+ gdispFillArea(x+w, y, gh->width-dx-w, h, gh->bgcolor);
+ dx = 0;
+ }
+
+ // Center image horizontally if the area is smaller than the image
+ else if (widget(gh)->image.width > w) {
+ dx = (widget(gh)->image.width - w)/2;
+ }
+
+ // Center vertically if the area is larger than the image
+ if (widget(gh)->image.height < h) {
+ h = widget(gh)->image.height;
+ dy = (gh->height-h)/2;
+ y += dy;
+ if (dy)
+ gdispFillArea(x, gh->y, w, dy, gh->bgcolor);
+ gdispFillArea(x, y+h, w, gh->height-dy-h, gh->bgcolor);
+ dy = 0;
+ }
+
+ // Center image vertically if the area is smaller than the image
+ else if (widget(gh)->image.height > h) {
+ dy = (widget(gh)->image.height - h)/2;
+ }
+
+ // Reset the background color in case it has changed
+ gdispImageSetBgColor(&widget(gh)->image, gh->bgcolor);
+
+ // Display the image
+ gdispImageDraw(&widget(gh)->image, x, y, w, h, dx, dy);
+}
+
+
+static const gwinVMT imageVMT = {
+ "Image", // The class name
+ sizeof(GImageWidget), // The object size
+ _destroy, // The destroy routine
+ _redraw, // The redraw routine
+ 0, // The after-clear routine
+};
+
+GHandle gwinImageCreate(GImageWidget *gobj, GWindowInit *pInit) {
+ if (!(gobj = (GImageWidget *)_gwindowCreate(&gobj->g, pInit, &imageVMT, 0)))
+ return 0;
+
+ // Ensure the gdispImageIsOpen() gives valid results
+ gobj->image.type = 0;
+
+ gwinSetVisible((GHandle)gobj, pInit->show);
+
+ return (GHandle)gobj;
+}
+
+bool_t gwinImageOpenMemory(GHandle gh, const void* memory) {
+ if (gdispImageIsOpen(&widget(gh)->image))
+ gdispImageClose(&widget(gh)->image);
+
+ if (!gdispImageSetMemoryReader(&widget(gh)->image, memory))
+ return FALSE;
+
+ if (gdispImageOpen(&widget(gh)->image) != GDISP_IMAGE_ERR_OK)
+ return FALSE;
+
+ 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
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ _redraw(gh);
+ }
+ return TRUE;
+}
+
+#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_POSIX || defined(__DOXYGEN__)
+bool_t gwinImageOpenFile(GHandle gh, const char* filename) {
+ if (gdispImageIsOpen(&widget(gh)->image))
+ gdispImageClose(&widget(gh)->image);
+
+ if (!gdispImageSetFileReader(&widget(gh)->image, filename))
+ return FALSE;
+
+ if (gdispImageOpen(&widget(gh)->image) != GDISP_IMAGE_ERR_OK)
+ return FALSE;
+
+ 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
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ _redraw(gh);
+ }
+ return TRUE;
+}
+#endif
+
+#if GFX_USE_OS_CHIBIOS || defined(__DOXYGEN__)
+bool_t gwinImageOpenStream(GHandle gh, void *streamPtr) {
+ if (gdispImageIsOpen(&widget(gh)->image))
+ gdispImageClose(&widget(gh)->image);
+
+ if (!gdispImageSetBaseFileStreamReader(&widget(gh)->image, streamPtr))
+ return FALSE;
+
+ if (gdispImageOpen(&widget(gh)->image) != GDISP_IMAGE_ERR_OK)
+ return FALSE;
+
+ 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
+ gdispSetClip(gh->x, gh->y, gh->width, gh->height);
+ #endif
+ _redraw(gh);
+ }
+ return TRUE;
+}
+#endif
+
+gdispImageError gwinImageCache(GHandle gh) {
+ return gdispImageCache(&widget(gh)->image);
+}
+
+#endif // GFX_USE_GWIN && GWIN_NEED_IMAGE
+/** @} */
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
index f080ac64..de1673cb 100644
--- a/src/gwin/gwin.c
+++ b/src/gwin/gwin.c
@@ -63,6 +63,16 @@ static color_t defaultBgColor = Black;
if (gh->height < MIN_WIN_HEIGHT) { gh->height = MIN_WIN_HEIGHT; }
if (gh->x+gh->width > gdispGetWidth()) gh->width = gdispGetWidth() - gh->x;
if (gh->y+gh->height > gdispGetHeight()) gh->height = gdispGetHeight() - gh->y;
+
+ // 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
@@ -135,10 +145,18 @@ void gwinSetDefaultColor(color_t clr) {
defaultFgColor = clr;
}
+color_t gwinGetDefaultColor(void) {
+ return defaultFgColor;
+}
+
void gwinSetDefaultBgColor(color_t bgclr) {
defaultBgColor = bgclr;
}
+color_t gwinGetDefaultBgColor(void) {
+ return defaultBgColor;
+}
+
#if GDISP_NEED_TEXT
void gwinSetDefaultFont(font_t font) {
defaultFont = font;
diff --git a/src/gwin/gwin.mk b/src/gwin/gwin.mk
index 9a81728e..b9e6a9ee 100644
--- a/src/gwin/gwin.mk
+++ b/src/gwin/gwin.mk
@@ -6,6 +6,6 @@ GFXSRC += $(GFXLIB)/src/gwin/gwin.c \
$(GFXLIB)/src/gwin/button.c \
$(GFXLIB)/src/gwin/slider.c \
$(GFXLIB)/src/gwin/checkbox.c \
- $(GFXLIB)/src/gwin/image.c \
+ $(GFXLIB)/src/gwin/gimage.c \
$(GFXLIB)/src/gwin/label.c \
diff --git a/src/gwin/gwm.c b/src/gwin/gwm.c
index c3405d83..75b08be6 100644
--- a/src/gwin/gwm.c
+++ b/src/gwin/gwm.c
@@ -25,7 +25,7 @@
static void WM_Init(void);
static void WM_DeInit(void);
-static bool_t WM_Add(GHandle gh, GWindowInit *pInit);
+static bool_t WM_Add(GHandle gh, const GWindowInit *pInit);
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);
@@ -65,23 +65,25 @@ static void WM_DeInit(void) {
// A full window manager would remove any borders etc
}
-static bool_t WM_Add(GHandle gh, GWindowInit *pInit) {
+static bool_t WM_Add(GHandle gh, const GWindowInit *pInit) {
+ // Note the window will not be marked as visible yet
+
// Put it on the queue
gfxQueueASyncPut(&_GWINList, &gh->wmq);
// Make sure the size is valid
WM_Redim(gh, pInit->x, pInit->y, pInit->width, pInit->height);
-
- // 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)
+ // Make the window invisible and clear the area underneath
+ if ((gh->flags & GWIN_FLG_VISIBLE)) {
+ gh->flags &= ~GWIN_FLG_VISIBLE;
+ gdispFillArea(gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
+ }
- // Just remove it from the queue
+ // Remove it from the queue
gfxQueueASyncRemove(&_GWINList, &gh->wmq);
}
@@ -97,10 +99,8 @@ static void WM_Visible(GHandle 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)
-
+ else
+ gdispFillArea(gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
}
static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) {
@@ -114,8 +114,28 @@ static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) {
if (h < MIN_WIN_HEIGHT) { h = MIN_WIN_HEIGHT; }
if (x+w > gdispGetWidth()) w = gdispGetWidth() - x;
if (y+h > gdispGetHeight()) h = gdispGetHeight() - y;
+
+ // If there has been no resize just exit
+ if (gh->x == x && gh->y == y && gh->width == w && gh->height == h)
+ return;
+
+ // Clear the old area
+ if ((gh->flags & GWIN_FLG_VISIBLE))
+ gdispFillArea(gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());
+
+ // Set the new size
gh->x = x; gh->y = y;
gh->width = w; gh->height = h;
+
+ // Redraw the window (if possible)
+ 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);
+ }
+ }
}
static void WM_MinMax(GHandle gh, GWindowMinMax minmax) {
diff --git a/src/gwin/image.c b/src/gwin/image.c
deleted file mode 100644
index bba92238..00000000
--- a/src/gwin/image.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * This file is subject to the terms of the GFX License. If a copy of
- * the license was not distributed with this file, you can obtain one at:
- *
- * http://chibios-gfx.com/license.html
- */
-
-/**
- * @file src/gwin/image.c
- * @brief GWIN sub-system image code.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GWIN && GWIN_NEED_IMAGE
-
-#include "gwin/class_gwin.h"
-
-#define widget(gh) ((GImageWidget*)gh)
-
-static void _destroy(GWindowObject *gh) {
- if (gdispImageIsOpen(&widget(gh)->image))
- gdispImageClose(&widget(gh)->image);
-
- return;
-}
-
-static void _afterClear(GWindowObject *gh) {
- (void)gh;
-
- return;
-}
-
-static const gwinVMT imageVMT = {
- "Image", // The class name
- sizeof(GImageWidget), // The object size
- _destroy, // The destroy routine
- 0,
- _afterClear, // The after-clear routine
-};
-
-GHandle gwinImageCreate(GImageWidget *widget, GWindowInit *pInit) {
- if (!(widget = (GImageWidget *)_gwindowCreate(&widget->g, pInit, &imageVMT, 0)))
- return 0;
-
- widget->image = gfxAlloc(sizeof(gdispImage));
- if (widget->image == NULL)
- return 0;
-
- widget->g.x = pInit->x;
- widget->g.y = pInit->y;
- widget->g.width = pInit->width;
- widget->g.height = pInit->height;
- widget->bgColor = Black;
- gwinSetVisible((GHandle)widget, pInit->show);
-
- return (GHandle)widget;
-}
-
-bool_t gwinImageOpenMemory(GHandle gh, const void* memory) {
- bool_t err;
-
- err = gdispImageSetMemoryReader(widget(gh)->image, memory);
- gdispImageOpen(widget(gh)->image);
-
- return err;
-}
-
-#if defined(WIN32) || GFX_USE_OS_WIN32 || GFX_USE_OS_POSIX || defined(__DOXYGEN__)
-bool_t gwinImageOpenFile(GHandle gh, const char* filename) {
- return gdispImageSetFileReader(widget(gh)->image, filename);
-}
-#endif
-
-#if GFX_USE_OS_CHIBIOS || defined(__DOXYGEN__)
-bool_t gwinImageOpenStream(GHandle gh, void *streamPtr) {
- return gdispImageSetBaseFileStreamReader(widget(gh)->image, streamPtr);
-}
-#endif
-
-gdispImageError gwinImageCache(GHandle gh) {
- return gdispImageCache(widget(gh)->image);
-}
-
-void gwinImageSetBgColor(GHandle gh, color_t bgColor) {
- widget(gh)->bgColor = bgColor;
-}
-
-void gwinImageDraw(GHandle gh) {
- gdispImageDraw(widget(gh)->image, widget(gh)->g.x, widget(gh)->g.y, widget(gh)->image->width, widget(gh)->image->height, 0, 0);
-}
-
-#endif // GFX_USE_GWIN && GWIN_NEED_IMAGE
-/** @} */
-
diff --git a/src/gwin/label.c b/src/gwin/label.c
index 7f8ab814..e757892d 100644
--- a/src/gwin/label.c
+++ b/src/gwin/label.c
@@ -21,26 +21,36 @@
#include "gwin/class_gwin.h"
-#define widget(gh) ((GLabelWidget*)gh)
#define GLABEL_FLG_WAUTO (GWIN_FIRST_CONTROL_FLAG<<0)
#define GLABEL_FLG_HAUTO (GWIN_FIRST_CONTROL_FLAG<<1)
-static void gwinLabelDefaultDraw(GHandle gh) {
- // if( check if auto flag is set )
- // if( call current size != font size )
- // gwinResize();
+// Simple: single line with no wrapping
+static coord_t getwidth(const char *txt, font_t font, coord_t maxwidth) {
+ (void) maxwidth;
+ return gdispGetStringWidth(txt, font)+2; // Allow one pixel of padding on each side
+}
+
+// Simple: single line with no wrapping
+static coord_t getheight(const char *txt, font_t font, coord_t maxwidth) {
+ (void) txt;
+ (void) maxwidth;
+
+ return gdispGetFontMetric(font, fontHeight);
+}
+
+static void gwinLabelDefaultDraw(GWidgetObject *gw, void *param) {
+ (void) param;
+ coord_t w, h;
- gdispFillString( widget(gh)->w.g.x,
- widget(gh)->w.g.y,
- widget(gh)->w.txt,
- widget(gh)->w.g.font,
- widget(gh)->w.g.color,
- widget(gh)->w.g.bgcolor
- );
+ w = (gw->g.flags & GLABEL_FLG_WAUTO) ? getwidth(gw->txt, gw->g.font, gdispGetWidth() - gw->g.x) : gw->g.width;
+ h = (gw->g.flags & GLABEL_FLG_HAUTO) ? getheight(gw->txt, gw->g.font, gdispGetWidth() - gw->g.x) : gw->g.height;
- gdispFillArea( widget(gh)->w.g.x, widget(gh)->w.g.y, widget(gh)->w.g.width, widget(gh)->w.g.height, Green);
+ if (gw->g.width != w || gw->g.height != h) {
+ gwinResize(&gw->g, w, h);
+ return;
+ }
- printf("Text: %s\r\n", widget(gh)->w.txt);
+ gdispFillStringBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->txt, gw->g.font, gw->g.color, gw->g.bgcolor, justifyLeft);
}
static const gwidgetVMT labelVMT = {
@@ -78,21 +88,21 @@ GHandle gwinLabelCreate(GLabelWidget *widget, GWidgetInit *pInit) {
// auto assign width
if (pInit->g.width <= 0) {
flags |= GLABEL_FLG_WAUTO;
- pInit->g.width = gdispGetStringWidth(pInit->text, gwinGetDefaultFont());
+ pInit->g.width = getwidth(pInit->text, gwinGetDefaultFont(), gdispGetWidth() - pInit->g.x);
}
// auto assign height
if (pInit->g.height <= 0) {
flags |= GLABEL_FLG_HAUTO;
- pInit->g.height = gdispGetFontMetric(gwinGetDefaultFont(), fontHeight);
+ pInit->g.height = getheight(pInit->text, gwinGetDefaultFont(), gdispGetWidth() - pInit->g.x);
}
if (!(widget = (GLabelWidget *)_gwidgetCreate(&widget->w, pInit, &labelVMT)))
return 0;
- gwinLabelDefaultDraw((GHandle)widget);
widget->w.g.flags |= flags;
+ gwinSetVisible(&widget->w.g, pInit->g.show);
return (GHandle)widget;
}