Label, Image and Window Manager changes

ugfx_release_2.6
inmarket 2013-07-04 00:20:32 +10:00
parent 3f80e1f89d
commit 09a359813f
9 changed files with 275 additions and 147 deletions

View File

@ -46,7 +46,12 @@
#warning "GWIN: Drawing can occur outside the defined windows as GDISP_NEED_CLIP is FALSE"
#endif
#endif
#if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX
#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_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX || GWIN_NEED_LABEL
#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."

View File

@ -111,6 +111,13 @@ extern "C" {
*/
void gwinSetDefaultColor(color_t clr);
/**
* @brief Get the default foreground color for all new GWIN windows
*
* @api
*/
color_t gwinGetDefaultColor(void);
/**
* @brief Set the default background color for all new GWIN windows
*
@ -120,6 +127,13 @@ extern "C" {
*/
void gwinSetDefaultBgColor(color_t bgclr);
/**
* @brief Get the default background color for all new GWIN windows
*
* @api
*/
color_t gwinGetDefaultBgColor(void);
#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
/**
* @brief Set the default font for all new GWIN windows

View File

@ -32,9 +32,7 @@
// An image window
typedef struct GImageWidget_t {
GWindowObject g;
gdispImage *image;
color_t bgColor;
gdispImage image;
} GImageWidget;
#ifdef __cplusplus
@ -50,11 +48,10 @@ extern "C" {
* @param[in] pInit The initialization parameters to use.
*
* @note The default background color gets set to the current default one.
* @note An image widget does not save the current drawing state. It is not automatically redrawn if the window
* is moved or its visibility state is changed.
* @note An image window knows how to redraw.
*
* @api
*/
*/
GHandle gwinImageCreate(GImageWidget *widget, GWindowInit *pInit);
/**
@ -98,7 +95,7 @@ bool_t gwinImageOpenMemory(GHandle gh, const void* memory);
#endif
/**
* @brief Cache an image.
* @brief Cache the image.
* @details Decodes and caches the current frame into RAM.
*
* param[in] gh The widget (must be an image widget)
@ -109,20 +106,6 @@ bool_t gwinImageOpenMemory(GHandle gh, const void* memory);
*/
gdispImageError gwinImageCache(GHandle gh);
/**
* @brief Set the background color of an image widget.
* @details Transparent images need a background color. If no background color has been set, the current default
* on is used.
*
* @param[in] gh The widget (must be an image widget)
* @param[in] bgColor The background color to be set
*
* @api
*/
void gwinImageSetBgColor(GHandle gh, color_t bgColor);
void gwinImageDraw(GHandle gh);
#ifdef __cplusplus
}
#endif

173
src/gwin/gimage.c 100644
View File

@ -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
/** @} */

View File

@ -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;

View File

@ -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 \

View File

@ -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) {

View File

@ -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
/** @} */

View File

@ -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
}
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
);
// Simple: single line with no wrapping
static coord_t getheight(const char *txt, font_t font, coord_t maxwidth) {
(void) txt;
(void) maxwidth;
gdispFillArea( widget(gh)->w.g.x, widget(gh)->w.g.y, widget(gh)->w.g.width, widget(gh)->w.g.height, Green);
return gdispGetFontMetric(font, fontHeight);
}
printf("Text: %s\r\n", widget(gh)->w.txt);
static void gwinLabelDefaultDraw(GWidgetObject *gw, void *param) {
(void) param;
coord_t w, h;
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;
if (gw->g.width != w || gw->g.height != h) {
gwinResize(&gw->g, w, h);
return;
}
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;
}