diff options
author | inmarket <andrewh@inmarket.com.au> | 2013-07-04 00:20:32 +1000 |
---|---|---|
committer | inmarket <andrewh@inmarket.com.au> | 2013-07-04 00:20:32 +1000 |
commit | 09a359813f0abe8f99c32dadfa1ac2c68356ddfd (patch) | |
tree | ce6bfc9861baac4ed2de9e84995f307b8fd7cffa /src/gwin | |
parent | 3f80e1f89dbeec06dd97a914d6851ad4596b1743 (diff) | |
download | uGFX-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.c | 173 | ||||
-rw-r--r-- | src/gwin/gwin.c | 18 | ||||
-rw-r--r-- | src/gwin/gwin.mk | 2 | ||||
-rw-r--r-- | src/gwin/gwm.c | 44 | ||||
-rw-r--r-- | src/gwin/image.c | 95 | ||||
-rw-r--r-- | src/gwin/label.c | 44 |
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; } |