diff options
Diffstat (limited to 'src/gwin/gwin.c')
| -rw-r--r-- | src/gwin/gwin.c | 369 | 
1 files changed, 281 insertions, 88 deletions
| diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c index 2f9d2dfd..b918d297 100644 --- a/src/gwin/gwin.c +++ b/src/gwin/gwin.c @@ -9,127 +9,266 @@  #if GFX_USE_GWIN -#include "gwin/internal.h" +#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 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_WIDGET +		extern void _gwidgetInit(void); + +		_gwidgetInit(); +	#endif +	#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 *gw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size) { -	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 _gwindowCreate(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 (!gw) { -		if (!(gw = (GWindowObject *)gfxAlloc(size))) +	if (!pgw) { +		if (!(pgw = (GWindowObject *)gfxAlloc(size)))  			return 0; -		gw->flags = GWIN_FLG_DYNAMIC; +		pgw->flags = flags|GWIN_FLG_DYNAMIC;  	} else -		gw->flags = 0; +		pgw->flags = flags; -	// Initialise all basic fields (except the type) -	gw->x = x; -	gw->y = y; -	gw->width = width; -	gw->height = height; -	gw->color = White; -	gw->bgcolor = Black; +	// Initialise all basic fields +	pgw->vmt = vmt; +	pgw->color = defaultFgColor; +	pgw->bgcolor = defaultBgColor;  	#if GDISP_NEED_TEXT -		gw->font = 0; +		pgw->font = defaultFont;  	#endif -	return (GHandle)gw; -} -GHandle gwinCreateWindow(GWindowObject *gw, coord_t x, coord_t y, coord_t width, coord_t height) { -	if (!(gw = (GWindowObject *)_gwinInit((GWindowObject *)gw, x, y, width, height, sizeof(GWindowObject)))) -		return 0; -	gw->type = GW_WINDOW; -	return (GHandle)gw; -} +	#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 -void gwinSetEnabled(GHandle gh, bool_t enabled) { -	(void)gh; -	(void)enabled; +	return (GHandle)pgw;  } -void gwinDestroyWindow(GHandle gh) { -	// Clean up any type specific dynamic memory allocations -	switch(gh->type) { -#if GWIN_NEED_BUTTON -	case GW_BUTTON: -		if ((gh->flags & GBTN_FLG_ALLOCTXT)) { -			gh->flags &= ~GBTN_FLG_ALLOCTXT;		// To be sure, to be sure -			gfxFree((void *)((GButtonObject *)gh)->txt); +/*----------------------------------------------- + * 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();  		} -		geventDetachSource(&((GButtonObject *)gh)->listener, 0); -		geventDetachSourceListeners((GSourceHandle)gh); -		break; -#endif -#if GWIN_NEED_SLIDER -	case GW_SLIDER: -		geventDetachSource(&((GSliderObject *)gh)->listener, 0); -		geventDetachSourceListeners((GSourceHandle)gh); -		break; +	}  #endif -	default: -		break; + +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 _gwindowCreate(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 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 gwinDraw(GHandle gh) { -	switch(gh->type) { -	#if GWIN_NEED_BUTTON -		case GW_BUTTON: -			gwinButtonDraw(gh); -			break; +bool_t gwinGetVisible(GHandle gh) { +	return (gh->flags & GWIN_FLG_VISIBLE) ? TRUE : FALSE; +} + +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 -	#if GWIN_NEED_SLIDER -		case GW_SLIDER: -			gwinSliderDraw(gh); -			break; +} + +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; -	#if GWIN_NEED_CONSOLE -		if (font && gh->type == GW_CONSOLE) { -			((GConsoleObject *)gh)->fy = gdispGetFontMetric(font, fontHeight); -			((GConsoleObject *)gh)->fp = gdispGetFontMetric(font, fontCharPadding); -		} -	#endif  	}  #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  	gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor); - -	#if GWIN_NEED_CONSOLE -		if (gh->type == GW_CONSOLE) { -			((GConsoleObject *)gh)->cx = 0; -			((GConsoleObject *)gh)->cy = 0; -		} -	#endif +	if (gh->vmt->AfterClear) +		gh->vmt->AfterClear(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 @@ -137,6 +276,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 @@ -144,6 +286,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 @@ -151,6 +296,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 @@ -158,6 +306,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 @@ -166,6 +317,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 @@ -173,6 +327,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 @@ -182,6 +339,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 @@ -189,6 +349,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 @@ -198,6 +361,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 @@ -205,6 +371,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 @@ -214,6 +383,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 @@ -223,7 +395,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 @@ -231,7 +405,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 @@ -239,7 +415,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 @@ -247,7 +425,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 @@ -255,7 +435,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 @@ -263,7 +445,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 @@ -273,6 +457,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 @@ -280,6 +467,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 @@ -289,6 +479,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 | 
