From 362c25f9673f96ade74b9316b3db356c28e66aa6 Mon Sep 17 00:00:00 2001 From: inmarket Date: Sat, 16 Aug 2014 23:35:50 +1000 Subject: Update the simple container to support custom draws such as transparent client area or tiled image client area. --- src/gwin/gcontainer.c | 75 ++++++++++++++++++++++++++++++++++++++++++--------- src/gwin/gcontainer.h | 28 ++++++++++++++++++- 2 files changed, 90 insertions(+), 13 deletions(-) (limited to 'src/gwin') diff --git a/src/gwin/gcontainer.c b/src/gwin/gcontainer.c index 2d711ffd..97b5fabb 100644 --- a/src/gwin/gcontainer.c +++ b/src/gwin/gcontainer.c @@ -90,17 +90,9 @@ coord_t gwinGetInnerHeight(GHandle gh) { #error "GWIN Container: - Flag definitions don't match" #endif -static coord_t BorderSize(GHandle gh) { return (gh->flags & GWIN_CONTAINER_BORDER) ? 2 : 0; } +#define BORDER_WIDTH 2 -static void DrawSimpleContainer(GWidgetObject *gw, void *param) { - (void)param; - - if (!(gw->g.flags & GWIN_CONTAINER_TRANSPARENT)) - gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); - - if ((gw->g.flags & GWIN_CONTAINER_BORDER)) - gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge); -} +static coord_t BorderSize(GHandle gh) { return (gh->flags & GWIN_CONTAINER_BORDER) ? BORDER_WIDTH : 0; } // The container VMT table static const gcontainerVMT containerVMT = { @@ -112,7 +104,7 @@ static const gcontainerVMT containerVMT = { _gcontainerRedraw, // The redraw routine 0, // The after-clear routine }, - DrawSimpleContainer, // The default drawing routine + gwinContainerDraw_Std, // The default drawing routine #if GINPUT_NEED_MOUSE { 0, 0, 0, // No mouse @@ -141,10 +133,69 @@ GHandle gwinGContainerCreate(GDisplay *g, GContainerObject *gc, const GWidgetIni if (!(gc = (GContainerObject *)_gcontainerCreate(g, gc, pInit, &containerVMT))) return 0; - gc->g.flags |= flags; + gc->g.flags |= (flags & GWIN_CONTAINER_BORDER); gwinSetVisible((GHandle)gc, pInit->g.show); return (GHandle)gc; } +void gwinContainerDraw_Transparent(GWidgetObject *gw, void *param) { + (void)param; + + if (gw->g.vmt != (gwinVMT *)&containerVMT) + return; + + if ((gw->g.flags & GWIN_CONTAINER_BORDER)) + gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, (gw->g.flags & GWIN_FLG_SYSENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge); + + // Don't touch the client area +} + +void gwinContainerDraw_Std(GWidgetObject *gw, void *param) { + (void)param; + + if (gw->g.vmt != (gwinVMT *)&containerVMT) + return; + + gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); + gwinContainerDraw_Transparent(gw, param); +} + +#if GDISP_NEED_IMAGE + void gwinContainerDraw_Image(GWidgetObject *gw, void *param) { + #define gi ((gdispImage *)param) + coord_t x, y, iw, ih, mx, my; + + if (gw->g.vmt != (gwinVMT *)&containerVMT) + return; + + // Draw the frame + gwinContainerDraw_Transparent(gw, param); + + // Draw the client area by tiling the image + mx = gw->g.x+gw->g.width; + my = gw->g.y+gw->g.height; + y = gw->g.y; + if ((gw->g.flags & GWIN_CONTAINER_BORDER)) { + mx--; + my--; + y++; + } + for(ih=gi->height; y < my; y += ih) { + if (ih > my - y) + ih = my - y; + x = gw->g.x; + if ((gw->g.flags & GWIN_CONTAINER_BORDER)) + x++; + for(iw=gi->width; x < mx; x += iw) { + if (iw > mx - x) + iw = mx - x; + gdispGImageDraw(gw->g.display, gi, x, y, ih, iw, 0, 0); + } + } + + #undef gi + } +#endif + #endif diff --git a/src/gwin/gcontainer.h b/src/gwin/gcontainer.h index 942cf8c0..98707ede 100644 --- a/src/gwin/gcontainer.h +++ b/src/gwin/gcontainer.h @@ -105,7 +105,6 @@ extern "C" { * @{ */ #define GWIN_CONTAINER_BORDER 0x00000001 - #define GWIN_CONTAINER_TRANSPARENT 0x00000002 /** @} */ /** @@ -122,6 +121,33 @@ extern "C" { GHandle gwinGContainerCreate(GDisplay *g, GContainerObject *gw, const GWidgetInit *pInit, uint32_t flags); #define gwinContainerCreate(gc, pInit, flags) gwinGContainerCreate(GDISP, gc, pInit, flags) + /** + * @brief The custom draw routines for a simple container + * @details These function may be passed to @p gwinSetCustomDraw() to get different frame drawing styles + * + * @param[in] gw The widget object (in this case a frame) + * @param[in] param A parameter passed in from the user + * + * @note In your own custom drawing function you may optionally call these + * standard functions and then draw your extra details on top. + * + * @note gwinContainerDraw_Std() will fill the client area with the background color.
+ * gwinContainerDraw_Transparent() will not fill the client area at all.
+ * gwinContainerDraw_Image() will tile the image throughout the client area.
+ * All these drawing functions draw the frame itself the same way. + * + * @note The standard functions below ignore the param parameter except for @p gwinContainerDraw_Image(). + * @note The image custom draw function @p gwinContainerDraw_Image() uses param to pass in the gdispImage pointer. + * The image must be already opened before calling @p gwinSetCustomDraw(). + * + * @api + * @{ + */ + void gwinContainerDraw_Std(GWidgetObject *gw, void *param); + void gwinContainerDraw_Transparent(GWidgetObject *gw, void *param); + void gwinContainerDraw_Image(GWidgetObject *gw, void *param); + /** @} */ + #ifdef __cplusplus } #endif -- cgit v1.2.3