The offical µGFX repository.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

418 lines
12 KiB

/*
* 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://ugfx.org/license.html
*/
/**
* @file src/gwin/gwin.c
* @brief GWIN sub-system code
*/
#include "../../gfx.h"
#if GFX_USE_GWIN
#include "gwin_class.h"
#include <string.h>
/*-----------------------------------------------
* Data
*-----------------------------------------------*/
static const gwinVMT basegwinVMT = {
"GWIN", // The classname
sizeof(GWindowObject), // The object size
0, // The destroy routine
0, // The redraw routine
0, // The after-clear routine
};
static gColor defaultFgColor = GFX_WHITE;
static gColor defaultBgColor = GFX_BLACK;
#if GDISP_NEED_TEXT
static font_t defaultFont;
#endif
/* These init functions are defined by each module but not published */
extern void _gwmInit(void);
extern void _gwmDeinit(void);
#if GWIN_NEED_WIDGET
extern void _gwidgetInit(void);
extern void _gwidgetDeinit(void);
#endif
#if GWIN_NEED_CONTAINERS
extern void _gcontainerInit(void);
extern void _gcontainerDeinit(void);
#endif
/*-----------------------------------------------
* Helper Routines
*-----------------------------------------------*/
/*-----------------------------------------------
* Class Routines
*-----------------------------------------------*/
void _gwinInit(void)
{
_gwmInit();
#if GWIN_NEED_WIDGET
_gwidgetInit();
#endif
#if GWIN_NEED_CONTAINERS
_gcontainerInit();
#endif
}
void _gwinDeinit(void)
{
#if GWIN_NEED_CONTAINERS
_gcontainerDeinit();
#endif
#if GWIN_NEED_WIDGET
_gwidgetDeinit();
#endif
_gwmDeinit();
}
// Internal routine for use by GWIN components only
// Initialise a window creating it dynamically if required.
GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit, const gwinVMT *vmt, uint32_t flags) {
// Allocate the structure if necessary
if (!pgw) {
if (!(pgw = gfxAlloc(vmt->size)))
return 0;
pgw->flags = flags|GWIN_FLG_DYNAMIC;
} else
pgw->flags = flags;
// Initialise all basic fields
pgw->display = g;
pgw->vmt = vmt;
pgw->color = defaultFgColor;
pgw->bgcolor = defaultBgColor;
#if GDISP_NEED_TEXT
pgw->font = defaultFont;
#endif
// Make sure we don't create nasty problems for ourselves
if (vmt->size > sizeof(GWindowObject))
memset(pgw+1, 0, vmt->size - sizeof(GWindowObject));
if (!_gwinWMAdd(pgw, pInit)) {
if ((pgw->flags & GWIN_FLG_DYNAMIC))
gfxFree(pgw);
return 0;
}
return (GHandle)pgw;
}
// Internal routine for use by GWIN components only
void _gwinDestroy(GHandle gh, GRedrawMethod how) {
if (!gh)
return;
// Make the window invisible
gwinSetVisible(gh, gFalse);
// Make sure it is flushed first - must be REDRAW_WAIT or REDRAW_INSESSION
_gwinFlushRedraws(how);
#if GWIN_NEED_CONTAINERS
// Notify the parent it is about to be deleted
if (gh->parent && ((gcontainerVMT *)gh->parent->vmt)->NotifyDelete)
((gcontainerVMT *)gh->parent->vmt)->NotifyDelete(gh->parent, gh);
#endif
// Remove from the window manager
#if GWIN_NEED_WINDOWMANAGER
_GWINwm->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
gfxFree((void *)gh);
} else
gh->flags = 0; // To be sure, to be sure
}
/*-----------------------------------------------
* Routines that affect all windows
*-----------------------------------------------*/
void gwinClearInit(GWindowInit *pwi) {
char *p;
unsigned len;
for(p = (char *)pwi, len = sizeof(GWindowInit); len; len--)
*p++ = 0;
}
void gwinSetDefaultColor(gColor clr) {
defaultFgColor = clr;
}
gColor gwinGetDefaultColor(void) {
return defaultFgColor;
}
void gwinSetDefaultBgColor(gColor bgclr) {
defaultBgColor = bgclr;
}
gColor gwinGetDefaultBgColor(void) {
return defaultBgColor;
}
#if GDISP_NEED_TEXT
void gwinSetDefaultFont(font_t font) {
defaultFont = font;
}
font_t gwinGetDefaultFont(void) {
return defaultFont;
}
#endif
/*-----------------------------------------------
* The GWindow Routines
*-----------------------------------------------*/
GHandle gwinGWindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit) {
if (!(pgw = _gwindowCreate(g, pgw, pInit, &basegwinVMT, 0)))
return 0;
gwinSetVisible(pgw, pInit->show);
_gwinFlushRedraws(REDRAW_WAIT);
return pgw;
}
void gwinDestroy(GHandle gh) {
_gwinDestroy(gh, REDRAW_WAIT);
}
const char *gwinGetClassName(GHandle gh) {
return gh->vmt->classname;
}
gBool gwinGetVisible(GHandle gh) {
return (gh->flags & GWIN_FLG_SYSVISIBLE) ? gTrue : gFalse;
}
gBool gwinGetEnabled(GHandle gh) {
return (gh->flags & GWIN_FLG_SYSENABLED) ? gTrue : gFalse;
}
#if GDISP_NEED_TEXT
void gwinSetFont(GHandle gh, font_t font) {
gh->font = font;
}
#endif
void gwinClear(GHandle gh) {
/*
* Don't render anything when the window is not visible but
* still call the AfterClear() routine as some widgets will
* need this to clear internal buffers or similar
*/
if (_gwinDrawStart(gh)) {
gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);
_gwinDrawEnd(gh);
}
if (gh->vmt->AfterClear)
gh->vmt->AfterClear(gh);
}
void gwinDrawPixel(GHandle gh, gCoord x, gCoord y) {
if (!_gwinDrawStart(gh)) return;
gdispGDrawPixel(gh->display, gh->x+x, gh->y+y, gh->color);
_gwinDrawEnd(gh);
}
void gwinDrawLine(GHandle gh, gCoord x0, gCoord y0, gCoord x1, gCoord y1) {
if (!_gwinDrawStart(gh)) return;
gdispGDrawLine(gh->display, gh->x+x0, gh->y+y0, gh->x+x1, gh->y+y1, gh->color);
_gwinDrawEnd(gh);
}
void gwinDrawBox(GHandle gh, gCoord x, gCoord y, gCoord cx, gCoord cy) {
if (!_gwinDrawStart(gh)) return;
gdispGDrawBox(gh->display, gh->x+x, gh->y+y, cx, cy, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillArea(GHandle gh, gCoord x, gCoord y, gCoord cx, gCoord cy) {
if (!_gwinDrawStart(gh)) return;
gdispGFillArea(gh->display, gh->x+x, gh->y+y, cx, cy, gh->color);
_gwinDrawEnd(gh);
}
void gwinBlitArea(GHandle gh, gCoord x, gCoord y, gCoord cx, gCoord cy, gCoord srcx, gCoord srcy, gCoord srccx, const gPixel *buffer) {
if (!_gwinDrawStart(gh)) return;
gdispGBlitArea(gh->display, gh->x+x, gh->y+y, cx, cy, srcx, srcy, srccx, buffer);
_gwinDrawEnd(gh);
}
#if GDISP_NEED_CIRCLE
void gwinDrawCircle(GHandle gh, gCoord x, gCoord y, gCoord radius) {
if (!_gwinDrawStart(gh)) return;
gdispGDrawCircle(gh->display, gh->x+x, gh->y+y, radius, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillCircle(GHandle gh, gCoord x, gCoord y, gCoord radius) {
if (!_gwinDrawStart(gh)) return;
gdispGFillCircle(gh->display, gh->x+x, gh->y+y, radius, gh->color);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_DUALCIRCLE
void gwinFillDualCircle(GHandle gh, gCoord x, gCoord y, gCoord radius1, gCoord radius2) {
if (!_gwinDrawStart(gh)) return;
gdispGFillDualCircle(gh->display, gh->x+x, gh->y+y, radius1, gh->bgcolor, radius2, gh->color);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_ELLIPSE
void gwinDrawEllipse(GHandle gh, gCoord x, gCoord y, gCoord a, gCoord b) {
if (!_gwinDrawStart(gh)) return;
gdispGDrawEllipse(gh->display, gh->x+x, gh->y+y, a, b, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillEllipse(GHandle gh, gCoord x, gCoord y, gCoord a, gCoord b) {
if (!_gwinDrawStart(gh)) return;
gdispGFillEllipse(gh->display, gh->x+x, gh->y+y, a, b, gh->color);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_ARC
void gwinDrawArc(GHandle gh, gCoord x, gCoord y, gCoord radius, gCoord startangle, gCoord endangle) {
if (!_gwinDrawStart(gh)) return;
gdispGDrawArc(gh->display, gh->x+x, gh->y+y, radius, startangle, endangle, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillArc(GHandle gh, gCoord x, gCoord y, gCoord radius, gCoord startangle, gCoord endangle) {
if (!_gwinDrawStart(gh)) return;
gdispGFillArc(gh->display, gh->x+x, gh->y+y, radius, startangle, endangle, gh->color);
_gwinDrawEnd(gh);
}
void gwinDrawThickArc(GHandle gh, gCoord x, gCoord y, gCoord startradius, gCoord endradius, gCoord startangle, gCoord endangle) {
if (!_gwinDrawStart(gh)) return;
gdispGDrawThickArc(gh->display, gh->x+x, gh->y+y, startradius, endradius, startangle, endangle, gh->color);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_ARCSECTORS
void gwinDrawArcSectors(GHandle gh, gCoord x, gCoord y, gCoord radius, uint8_t sectors) {
if (!_gwinDrawStart(gh)) return;
gdispGDrawArcSectors(gh->display, gh->x+x, gh->y+y, radius, sectors, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillArcSectors(GHandle gh, gCoord x, gCoord y, gCoord radius, uint8_t sectors) {
if (!_gwinDrawStart(gh)) return;
gdispGFillArcSectors(gh->display, gh->x+x, gh->y+y, radius, sectors, gh->color);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_PIXELREAD
gColor gwinGetPixelColor(GHandle gh, gCoord x, gCoord y) {
if (!_gwinDrawStart(gh)) return (gColor)0;
return gdispGGetPixelColor(gh->display, gh->x+x, gh->y+y);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_TEXT
void gwinDrawChar(GHandle gh, gCoord x, gCoord y, char c) {
if (!gh->font || !_gwinDrawStart(gh)) return;
gdispGDrawChar(gh->display, gh->x+x, gh->y+y, c, gh->font, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillChar(GHandle gh, gCoord x, gCoord y, char c) {
if (!gh->font || !_gwinDrawStart(gh)) return;
gdispGFillChar(gh->display, gh->x+x, gh->y+y, c, gh->font, gh->color, gh->bgcolor);
_gwinDrawEnd(gh);
}
void gwinDrawString(GHandle gh, gCoord x, gCoord y, const char *str) {
if (!gh->font || !_gwinDrawStart(gh)) return;
gdispGDrawString(gh->display, gh->x+x, gh->y+y, str, gh->font, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillString(GHandle gh, gCoord x, gCoord y, const char *str) {
if (!gh->font || !_gwinDrawStart(gh)) return;
gdispGFillString(gh->display, gh->x+x, gh->y+y, str, gh->font, gh->color, gh->bgcolor);
_gwinDrawEnd(gh);
}
void gwinDrawStringBox(GHandle gh, gCoord x, gCoord y, gCoord cx, gCoord cy, const char* str, gJustify justify) {
if (!gh->font || !_gwinDrawStart(gh)) return;
gdispGDrawStringBox(gh->display, gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, justify);
_gwinDrawEnd(gh);
}
void gwinFillStringBox(GHandle gh, gCoord x, gCoord y, gCoord cx, gCoord cy, const char* str, gJustify justify) {
if (!gh->font || !_gwinDrawStart(gh)) return;
gdispGFillStringBox(gh->display, gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, gh->bgcolor, justify);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_CONVEX_POLYGON
void gwinDrawPoly(GHandle gh, gCoord tx, gCoord ty, const gPoint *pntarray, unsigned cnt) {
if (!_gwinDrawStart(gh)) return;
gdispGDrawPoly(gh->display, tx+gh->x, ty+gh->y, pntarray, cnt, gh->color);
_gwinDrawEnd(gh);
}
void gwinFillConvexPoly(GHandle gh, gCoord tx, gCoord ty, const gPoint *pntarray, unsigned cnt) {
if (!_gwinDrawStart(gh)) return;
gdispGFillConvexPoly(gh->display, tx+gh->x, ty+gh->y, pntarray, cnt, gh->color);
_gwinDrawEnd(gh);
}
void gwinDrawThickLine(GHandle gh, gCoord x0, gCoord y0, gCoord x1, gCoord y1, gCoord width, gBool round) {
if (!_gwinDrawStart(gh)) return;
gdispGDrawThickLine(gh->display, gh->x+x0, gh->y+y0, gh->x+x1, gh->y+y1, gh->color, width, round);
_gwinDrawEnd(gh);
}
#endif
#if GDISP_NEED_IMAGE
gdispImageError gwinDrawImage(GHandle gh, gdispImage *img, gCoord x, gCoord y, gCoord cx, gCoord cy, gCoord sx, gCoord sy) {
gdispImageError ret;
if (!_gwinDrawStart(gh)) return GDISP_IMAGE_ERR_OK;
ret = gdispGImageDraw(gh->display, img, gh->x+x, gh->y+y, cx, cy, sx, sy);
_gwinDrawEnd(gh);
return ret;
}
#endif
#endif /* GFX_USE_GWIN */
/** @} */