diff options
Diffstat (limited to 'src')
| -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;  }  | 
