Update the frame window to use much less RAM and also to support transparent and tiled image backgrounds
This commit is contained in:
parent
0fc1d5f033
commit
87c2793248
2 changed files with 284 additions and 215 deletions
411
src/gwin/frame.c
411
src/gwin/frame.c
|
@ -16,93 +16,146 @@
|
||||||
|
|
||||||
#include "src/gwin/class_gwin.h"
|
#include "src/gwin/class_gwin.h"
|
||||||
|
|
||||||
#if GWIN_FRAME_BORDER != GWIN_FIRST_CONTROL_FLAG
|
/* Some position values */
|
||||||
|
#define BUTTON_X 18 // Button Width
|
||||||
|
#define BUTTON_Y 18 // Button Height
|
||||||
|
#define BUTTON_I 3 // Button inner margin
|
||||||
|
#define BUTTON_T 2 // Gap from top of window to button
|
||||||
|
#define BUTTON_B 2 // Gap from button to the bottom of the frame title area
|
||||||
|
#define BORDER_L 2 // Left Border
|
||||||
|
#define BORDER_R 2 // Right Border
|
||||||
|
#define BORDER_T (BUTTON_Y+BUTTON_T+BUTTON_B) // Top Border (Title area)
|
||||||
|
#define BORDER_B 2 // Bottom Border
|
||||||
|
|
||||||
|
/* Internal state flags */
|
||||||
|
#define GWIN_FRAME_USER_FLAGS (GWIN_FRAME_CLOSE_BTN|GWIN_FRAME_MINMAX_BTN)
|
||||||
|
#define GWIN_FRAME_CLOSE_PRESSED (GWIN_FRAME_MINMAX_BTN << 1)
|
||||||
|
#define GWIN_FRAME_MIN_PRESSED (GWIN_FRAME_MINMAX_BTN << 2)
|
||||||
|
#define GWIN_FRAME_MAX_PRESSED (GWIN_FRAME_MINMAX_BTN << 3)
|
||||||
|
#define GWIN_FRAME_REDRAW_FRAME (GWIN_FRAME_MINMAX_BTN << 4) // Only redraw the frame
|
||||||
|
#if GWIN_FRAME_CLOSE_BTN < GWIN_FIRST_CONTROL_FLAG
|
||||||
|
#error "GWIN Frame: - Flag definitions don't match"
|
||||||
|
#endif
|
||||||
|
#if GWIN_FRAME_REDRAW_FRAME > GWIN_LAST_CONTROL_FLAG
|
||||||
#error "GWIN Frame: - Flag definitions don't match"
|
#error "GWIN Frame: - Flag definitions don't match"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Some values for the default render */
|
static coord_t BorderSizeL(GHandle gh) { (void)gh; return BORDER_L; }
|
||||||
#define BORDER_X 5
|
static coord_t BorderSizeR(GHandle gh) { (void)gh; return BORDER_R; }
|
||||||
#define BORDER_Y 30
|
static coord_t BorderSizeT(GHandle gh) { (void)gh; return BORDER_T; }
|
||||||
#define BUTTON_X 20
|
static coord_t BorderSizeB(GHandle gh) { (void)gh; return BORDER_B; }
|
||||||
#define BUTTON_Y 20
|
|
||||||
|
|
||||||
/* Some useful macros for data type conversions */
|
static void forceFrameRedraw(GWidgetObject *gw) {
|
||||||
#define gh2obj ((GFrameObject *)gh)
|
// Force a redraw of just the frame.
|
||||||
|
// This is a big naughty but who really cares.
|
||||||
/* Forware declarations */
|
gw->g.flags |= GWIN_FRAME_REDRAW_FRAME;
|
||||||
static void gwinFrameDraw_Std(GWidgetObject *gw, void *param);
|
gw->fnDraw(gw, gw->fnParam);
|
||||||
static void _callbackBtn(void *param, GEvent *pe);
|
gw->g.flags &= ~GWIN_FRAME_REDRAW_FRAME;
|
||||||
|
|
||||||
static coord_t BorderSizeLRB(GHandle gh) { return (gh->flags & GWIN_FRAME_BORDER) ? BORDER_X : 0; }
|
|
||||||
static coord_t BorderSizeT(GHandle gh) { return (gh->flags & GWIN_FRAME_BORDER) ? BORDER_Y : 0; }
|
|
||||||
|
|
||||||
static void _frameDestroy(GHandle gh) {
|
|
||||||
/* Deregister the button callback */
|
|
||||||
if ((gh->flags & (GWIN_FRAME_CLOSE_BTN|GWIN_FRAME_MINMAX_BTN))) {
|
|
||||||
geventRegisterCallback(&gh2obj->gl, NULL, NULL);
|
|
||||||
geventDetachSource(&gh2obj->gl, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* call the gcontainer standard destroy routine */
|
#if GINPUT_NEED_MOUSE
|
||||||
_gcontainerDestroy(gh);
|
static void mouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
|
||||||
|
coord_t pos;
|
||||||
|
|
||||||
|
// We must be clicking on the frame button area to be of interest
|
||||||
|
if (y < BUTTON_T && y >= BUTTON_T+BUTTON_Y)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pos = gw->g.width - (BORDER_R+BUTTON_X);
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_CLOSE_BTN)) {
|
||||||
|
if (x >= pos && x < pos+BUTTON_X) {
|
||||||
|
// Close is pressed - force redraw the frame only
|
||||||
|
gw->g.flags |= GWIN_FRAME_CLOSE_PRESSED;
|
||||||
|
forceFrameRedraw(gw);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pos -= BUTTON_X;
|
||||||
|
}
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_MINMAX_BTN)) {
|
||||||
|
if (x >= pos && x < pos+BUTTON_X) {
|
||||||
|
// Close is pressed - force redraw the frame only
|
||||||
|
gw->g.flags |= GWIN_FRAME_MAX_PRESSED;
|
||||||
|
forceFrameRedraw(gw);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pos -= BUTTON_X;
|
||||||
|
if (x >= pos && x < pos+BUTTON_X) {
|
||||||
|
// Close is pressed - force redraw the frame only
|
||||||
|
gw->g.flags |= GWIN_FRAME_MIN_PRESSED;
|
||||||
|
forceFrameRedraw(gw);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pos -= BUTTON_X;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _closeBtnDraw(struct GWidgetObject *gw, void *param) {
|
static void mouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
|
||||||
(void) param;
|
#if GWIN_BUTTON_LAZY_RELEASE
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_CLOSE_PRESSED)) {
|
||||||
|
// Close is released - destroy the window
|
||||||
|
gw->g.flags &= ~(GWIN_FRAME_CLOSE_PRESSED|GWIN_FRAME_MAX_PRESSED|GWIN_FRAME_MIN_PRESSED);
|
||||||
|
forceFrameRedraw(gw);
|
||||||
|
gwinDestroy(&gw->g);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_MAX_PRESSED)) {
|
||||||
|
// Max is released - maximize the window
|
||||||
|
gw->g.flags &= ~(GWIN_FRAME_CLOSE_PRESSED|GWIN_FRAME_MAX_PRESSED|GWIN_FRAME_MIN_PRESSED);
|
||||||
|
forceFrameRedraw(gw);
|
||||||
|
gwinSetMinMax(&gw->g, GWIN_MAXIMIZE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_MIN_PRESSED)) {
|
||||||
|
// Min is released - minimize the window
|
||||||
|
gw->g.flags &= ~(GWIN_FRAME_CLOSE_PRESSED|GWIN_FRAME_MAX_PRESSED|GWIN_FRAME_MIN_PRESSED);
|
||||||
|
forceFrameRedraw(gw);
|
||||||
|
gwinSetMinMax(&gw->g, GWIN_MINIMIZE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// If nothing is pressed we have nothing to do.
|
||||||
|
if (!(gw->g.flags & (GWIN_FRAME_CLOSE_PRESSED|GWIN_FRAME_MAX_PRESSED|GWIN_FRAME_MIN_PRESSED)))
|
||||||
|
return;
|
||||||
|
|
||||||
// the background
|
// We must be releasing over the button
|
||||||
if (gwinButtonIsPressed( (GHandle)gw)) {
|
if (y >= BUTTON_T && y < BUTTON_T+BUTTON_Y) {
|
||||||
gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gdispBlendColor(Black, HTML2COLOR(0xC55152), 50));
|
coord_t pos;
|
||||||
} else {
|
|
||||||
gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gw->g.height, HTML2COLOR(0xC55152));
|
pos = gw->g.width - (BORDER_R+BUTTON_X);
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_CLOSE_BTN)) {
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_CLOSE_PRESSED) && x >= pos && x <= pos+BUTTON_X) {
|
||||||
|
// Close is released - destroy the window
|
||||||
|
gw->g.flags &= ~(GWIN_FRAME_CLOSE_PRESSED|GWIN_FRAME_MAX_PRESSED|GWIN_FRAME_MIN_PRESSED);
|
||||||
|
forceFrameRedraw(gw);
|
||||||
|
gwinDestroy(&gw->g);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pos -= BUTTON_X;
|
||||||
|
}
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_MINMAX_BTN)) {
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_MAX_PRESSED) && x >= pos && x <= pos+BUTTON_X) {
|
||||||
|
// Max is released - maximize the window
|
||||||
|
gw->g.flags &= ~(GWIN_FRAME_CLOSE_PRESSED|GWIN_FRAME_MAX_PRESSED|GWIN_FRAME_MIN_PRESSED);
|
||||||
|
forceFrameRedraw(gw);
|
||||||
|
gwinSetMinMax(&gw->g, GWIN_MAXIMIZE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pos -= BUTTON_X;
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_MIN_PRESSED) && x >= pos && x <= pos+BUTTON_X) {
|
||||||
|
// Min is released - minimize the window
|
||||||
|
gw->g.flags &= ~(GWIN_FRAME_CLOSE_PRESSED|GWIN_FRAME_MAX_PRESSED|GWIN_FRAME_MIN_PRESSED);
|
||||||
|
forceFrameRedraw(gw);
|
||||||
|
gwinSetMinMax(&gw->g, GWIN_MINIMIZE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pos -= BUTTON_X;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the cross
|
// Clear any flags and redraw the frame
|
||||||
gdispDrawLine(gw->g.x+4, gw->g.y+4, gw->g.x+gw->g.width-5, gw->g.y+gw->g.height-5, White);
|
gw->g.flags &= ~(GWIN_FRAME_CLOSE_PRESSED|GWIN_FRAME_MAX_PRESSED|GWIN_FRAME_MIN_PRESSED);
|
||||||
gdispDrawLine(gw->g.x+gw->g.width-5, gw->g.y+4, gw->g.x+4, gw->g.y+gw->g.height-5, White);
|
forceFrameRedraw(gw);
|
||||||
}
|
#endif
|
||||||
|
|
||||||
static void _closeBtnMin(struct GWidgetObject *gw, void *param) {
|
|
||||||
(void) param;
|
|
||||||
|
|
||||||
// the background
|
|
||||||
if (gwinButtonIsPressed( (GHandle)gw)) {
|
|
||||||
gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gdispBlendColor(Black, Grey, 50));
|
|
||||||
} else {
|
|
||||||
gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gdispBlendColor(White, Grey, 50));
|
|
||||||
}
|
|
||||||
|
|
||||||
// the symbol
|
|
||||||
gdispDrawLine(gw->g.x+5, gw->g.y+gw->g.height-5, gw->g.x+gw->g.width-5, gw->g.y+gw->g.height-5, White);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _closeBtnMax(struct GWidgetObject *gw, void *param) {
|
|
||||||
(void) param;
|
|
||||||
|
|
||||||
// the background
|
|
||||||
if (gwinButtonIsPressed( (GHandle)gw)) {
|
|
||||||
gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gdispBlendColor(Black, Grey, 50));
|
|
||||||
} else {
|
|
||||||
gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gdispBlendColor(White, Grey, 50));
|
|
||||||
}
|
|
||||||
|
|
||||||
// the symbol
|
|
||||||
gdispDrawBox(gw->g.x+4, gw->g.y+4, gw->g.width-8, gw->g.height-8, White);
|
|
||||||
gdispDrawLine(gw->g.x+4, gw->g.y+5, gw->g.x+gw->g.width-5, gw->g.y+5, White);
|
|
||||||
gdispDrawLine(gw->g.x+4, gw->g.y+6, gw->g.x+gw->g.width-5, gw->g.y+6, White);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0 && GINPUT_NEED_MOUSE
|
|
||||||
static void _mouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _mouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _mouseMove(GWidgetObject *gw, coord_t x, coord_t y) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -111,16 +164,16 @@ static const gcontainerVMT frameVMT = {
|
||||||
{
|
{
|
||||||
"Frame", // The classname
|
"Frame", // The classname
|
||||||
sizeof(GFrameObject), // The object size
|
sizeof(GFrameObject), // The object size
|
||||||
_frameDestroy, // The destroy routie
|
_gcontainerDestroy, // The destroy routine
|
||||||
_gcontainerRedraw, // The redraw routine
|
_gcontainerRedraw, // The redraw routine
|
||||||
0, // The after-clear routine
|
0, // The after-clear routine
|
||||||
},
|
},
|
||||||
gwinFrameDraw_Std, // The default drawing routine
|
gwinFrameDraw_Std, // The default drawing routine
|
||||||
#if GINPUT_NEED_MOUSE
|
#if GINPUT_NEED_MOUSE
|
||||||
{
|
{
|
||||||
0,//_mouseDown, // Process mouse down event
|
mouseDown, // Process mouse down event
|
||||||
0,//_mouseUp, // Process mouse up events
|
mouseUp, // Process mouse up events
|
||||||
0,//_mouseMove, // Process mouse move events
|
0, // Process mouse move events
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
#if GINPUT_NEED_TOGGLE
|
#if GINPUT_NEED_TOGGLE
|
||||||
|
@ -141,136 +194,126 @@ static const gcontainerVMT frameVMT = {
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
BorderSizeLRB, // The size of the left border (mandatory)
|
BorderSizeL, // The size of the left border (mandatory)
|
||||||
BorderSizeT, // The size of the top border (mandatory)
|
BorderSizeT, // The size of the top border (mandatory)
|
||||||
BorderSizeLRB, // The size of the right border (mandatory)
|
BorderSizeR, // The size of the right border (mandatory)
|
||||||
BorderSizeLRB, // The size of the bottom border (mandatory)
|
BorderSizeB, // The size of the bottom border (mandatory)
|
||||||
0, // A child has been added (optional)
|
0, // A child has been added (optional)
|
||||||
0, // A child has been deleted (optional)
|
0, // A child has been deleted (optional)
|
||||||
};
|
};
|
||||||
|
|
||||||
GHandle gwinGFrameCreate(GDisplay *g, GFrameObject *fo, GWidgetInit *pInit, uint32_t flags) {
|
GHandle gwinGFrameCreate(GDisplay *g, GFrameObject *fo, GWidgetInit *pInit, uint32_t flags) {
|
||||||
if (!(fo = (GFrameObject *)_gcontainerCreate(g, &fo->gc, pInit, &frameVMT)))
|
if (!(fo = (GFrameObject *)_gcontainerCreate(g, (GContainerObject *)fo, pInit, &frameVMT)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fo->btnClose = 0;
|
// Make sure we only have "safe" flags.
|
||||||
fo->btnMin = 0;
|
flags &= GWIN_FRAME_USER_FLAGS;
|
||||||
fo->btnMax = 0;
|
|
||||||
|
|
||||||
/* Buttons require a border */
|
|
||||||
if ((flags & (GWIN_FRAME_CLOSE_BTN|GWIN_FRAME_MINMAX_BTN)))
|
|
||||||
flags |= GWIN_FRAME_BORDER;
|
|
||||||
|
|
||||||
/* create and initialize the listener if any button is present. */
|
|
||||||
if ((flags & (GWIN_FRAME_CLOSE_BTN|GWIN_FRAME_MINMAX_BTN))) {
|
|
||||||
geventListenerInit(&fo->gl);
|
|
||||||
gwinAttachListener(&fo->gl);
|
|
||||||
geventRegisterCallback(&fo->gl, _callbackBtn, (GHandle)fo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create close button if necessary */
|
|
||||||
if ((flags & GWIN_FRAME_CLOSE_BTN)) {
|
|
||||||
GWidgetInit wi;
|
|
||||||
|
|
||||||
gwinWidgetClearInit(&wi);
|
|
||||||
wi.g.show = TRUE;
|
|
||||||
wi.g.parent = &fo->gc.g;
|
|
||||||
|
|
||||||
wi.g.x = fo->gc.g.width - BORDER_X - BUTTON_X;
|
|
||||||
wi.g.y = (BORDER_Y - BUTTON_Y) / 2;
|
|
||||||
wi.g.width = BUTTON_X;
|
|
||||||
wi.g.height = BUTTON_Y;
|
|
||||||
wi.text = "Frame Close Button";
|
|
||||||
wi.customDraw = _closeBtnDraw;
|
|
||||||
fo->btnClose = gwinGButtonCreate(g, 0, &wi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create minimize and maximize buttons if necessary */
|
|
||||||
if ((flags & GWIN_FRAME_MINMAX_BTN)) {
|
|
||||||
GWidgetInit wi;
|
|
||||||
|
|
||||||
gwinWidgetClearInit(&wi);
|
|
||||||
wi.g.show = TRUE;
|
|
||||||
wi.g.parent = &fo->gc.g;
|
|
||||||
|
|
||||||
wi.g.x = (flags & GWIN_FRAME_CLOSE_BTN) ? fo->gc.g.width - 2*BORDER_X - 2*BUTTON_X : fo->gc.g.width - BORDER_X - BUTTON_X;
|
|
||||||
wi.g.y = (BORDER_Y - BUTTON_Y) / 2;
|
|
||||||
wi.g.width = BUTTON_X;
|
|
||||||
wi.g.height = BUTTON_Y;
|
|
||||||
wi.text = "Frame Max Button";
|
|
||||||
wi.customDraw = _closeBtnMax;
|
|
||||||
fo->btnMax = gwinGButtonCreate(g, 0, &wi);
|
|
||||||
|
|
||||||
wi.g.x = (flags & GWIN_FRAME_CLOSE_BTN) ? fo->gc.g.width - 3*BORDER_X - 3*BUTTON_X : fo->gc.g.width - BORDER_X - BUTTON_X;
|
|
||||||
wi.g.y = (BORDER_Y - BUTTON_Y) / 2;
|
|
||||||
wi.g.width = BUTTON_X;
|
|
||||||
wi.g.height = BUTTON_Y;
|
|
||||||
wi.text = "Frame Min Button";
|
|
||||||
wi.customDraw = _closeBtnMin;
|
|
||||||
fo->btnMin = gwinGButtonCreate(g, 0, &wi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Apply flags. We apply these here so the controls above are outside the child area */
|
/* Apply flags. We apply these here so the controls above are outside the child area */
|
||||||
fo->gc.g.flags |= flags;
|
fo->g.flags |= flags;
|
||||||
|
|
||||||
gwinSetVisible(&fo->gc.g, pInit->g.show);
|
gwinSetVisible(&fo->g, pInit->g.show);
|
||||||
|
|
||||||
return &fo->gc.g;
|
return &fo->g;
|
||||||
}
|
|
||||||
|
|
||||||
/* Process a button event */
|
|
||||||
static void _callbackBtn(void *param, GEvent *pe) {
|
|
||||||
switch (pe->type) {
|
|
||||||
case GEVENT_GWIN_BUTTON:
|
|
||||||
if (((GEventGWinButton *)pe)->button == ((GFrameObject*)(GHandle)param)->btnClose)
|
|
||||||
gwinDestroy((GHandle)param);
|
|
||||||
|
|
||||||
else if (((GEventGWinButton *)pe)->button == ((GFrameObject*)(GHandle)param)->btnMin) {
|
|
||||||
;/* ToDo */
|
|
||||||
|
|
||||||
} else if (((GEventGWinButton *)pe)->button == ((GFrameObject*)(GHandle)param)->btnMax) {
|
|
||||||
;/* ToDo */
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Default render routines //
|
// Default render routines //
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static const GColorSet* _getDrawColors(GWidgetObject *gw) {
|
void gwinFrameDraw_Transparent(GWidgetObject *gw, void *param) {
|
||||||
if (!(gw->g.flags & GWIN_FLG_SYSENABLED))
|
|
||||||
return &gw->pstyle->disabled;
|
|
||||||
//if ((gw->g.flags & GBUTTON_FLG_PRESSED))
|
|
||||||
// return &gw->pstyle->pressed;
|
|
||||||
|
|
||||||
return &gw->pstyle->enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void gwinFrameDraw_Std(GWidgetObject *gw, void *param) {
|
|
||||||
const GColorSet *pcol;
|
const GColorSet *pcol;
|
||||||
|
coord_t pos;
|
||||||
|
color_t contrast;
|
||||||
(void)param;
|
(void)param;
|
||||||
|
|
||||||
if (gw->g.vmt != (gwinVMT *)&frameVMT)
|
if (gw->g.vmt != (gwinVMT *)&frameVMT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pcol = _getDrawColors(gw);
|
pcol = (gw->g.flags & GWIN_FLG_SYSENABLED) ? &gw->pstyle->enabled : &gw->pstyle->disabled;
|
||||||
|
contrast = gdispContrastColor(pcol->edge);
|
||||||
|
|
||||||
// Render the actual frame (with border, if any)
|
// Render the frame
|
||||||
if (gw->g.flags & GWIN_FRAME_BORDER) {
|
gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, BORDER_T, gw->text, gw->g.font, contrast, pcol->edge, justifyCenter);
|
||||||
gdispGFillArea(gw->g.display, gw->g.x + BORDER_X, gw->g.y + BORDER_Y, gw->g.width - 2*BORDER_X, gw->g.height - BORDER_Y - BORDER_X, gw->pstyle->background);
|
gdispGFillArea(gw->g.display, gw->g.x, gw->g.y+BORDER_T, BORDER_L, gw->g.height-(BORDER_T+BORDER_B), pcol->edge);
|
||||||
gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, BORDER_Y, gw->text, gw->g.font, gdispContrastColor(pcol->edge), pcol->edge, justifyCenter);
|
gdispGFillArea(gw->g.display, gw->g.x+gw->g.width-BORDER_R, gw->g.y+BORDER_T, BORDER_R, gw->g.height-(BORDER_T+BORDER_B), pcol->edge);
|
||||||
gdispGFillArea(gw->g.display, gw->g.x, gw->g.y+BORDER_Y, BORDER_X, gw->g.height-(BORDER_Y+BORDER_X), pcol->edge);
|
gdispGFillArea(gw->g.display, gw->g.x, gw->g.y+gw->g.height-BORDER_B, gw->g.width, BORDER_B, pcol->edge);
|
||||||
gdispGFillArea(gw->g.display, gw->g.x+gw->g.width-BORDER_X, gw->g.y+BORDER_Y, BORDER_X, gw->g.height-(BORDER_Y+BORDER_X), pcol->edge);
|
|
||||||
gdispGFillArea(gw->g.display, gw->g.x, gw->g.y+gw->g.height-BORDER_X, gw->g.width, BORDER_X, pcol->edge);
|
// Add the buttons
|
||||||
} else {
|
pos = gw->g.x+gw->g.width - (BORDER_R+BUTTON_X);
|
||||||
gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background);
|
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_CLOSE_BTN)) {
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_CLOSE_PRESSED))
|
||||||
|
gdispFillArea(pos, gw->g.y+BUTTON_T, BUTTON_X, BUTTON_Y, gdispBlendColor(pcol->edge, contrast, 192));
|
||||||
|
gdispDrawLine(pos+BUTTON_I, gw->g.y+(BUTTON_T+BUTTON_I), pos+(BUTTON_X-BUTTON_I-1), gw->g.y+(BUTTON_T+BUTTON_Y-BUTTON_I-1), contrast);
|
||||||
|
gdispDrawLine(pos+(BUTTON_X-BUTTON_I-1), gw->g.y+(BUTTON_T+BUTTON_I), pos+BUTTON_I, gw->g.y+(BUTTON_T+BUTTON_Y-BUTTON_I-1), contrast);
|
||||||
|
pos -= BUTTON_X;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_MINMAX_BTN)) {
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_MAX_PRESSED))
|
||||||
|
gdispFillArea(pos, gw->g.y+BUTTON_T, BUTTON_X, BUTTON_Y, gdispBlendColor(pcol->edge, contrast, 192));
|
||||||
|
// the symbol
|
||||||
|
gdispDrawBox(pos+BUTTON_I, gw->g.y+(BUTTON_T+BUTTON_I), BUTTON_X-2*BUTTON_I, BUTTON_Y-2*BUTTON_I, contrast);
|
||||||
|
gdispDrawLine(pos+(BUTTON_I+1), gw->g.y+(BUTTON_T+BUTTON_I+1), pos+(BUTTON_X-BUTTON_I-2), gw->g.y+(BUTTON_T+BUTTON_I+1), contrast);
|
||||||
|
gdispDrawLine(pos+(BUTTON_I+1), gw->g.y+(BUTTON_T+BUTTON_I+2), pos+(BUTTON_X-BUTTON_I-2), gw->g.y+(BUTTON_T+BUTTON_I+2), contrast);
|
||||||
|
pos -= BUTTON_X;
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_MIN_PRESSED))
|
||||||
|
gdispFillArea(pos, gw->g.y+BUTTON_T, BUTTON_X, BUTTON_Y, gdispBlendColor(pcol->edge, contrast, 192));
|
||||||
|
gdispDrawLine(pos+BUTTON_I, gw->g.y+(BUTTON_T+BUTTON_Y-BUTTON_I-1), pos+(BUTTON_X-BUTTON_I-1), gw->g.y+(BUTTON_T+BUTTON_Y-BUTTON_I-1), contrast);
|
||||||
|
pos -= BUTTON_X;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't touch the client area
|
||||||
|
}
|
||||||
|
|
||||||
|
void gwinFrameDraw_Std(GWidgetObject *gw, void *param) {
|
||||||
|
(void)param;
|
||||||
|
|
||||||
|
if (gw->g.vmt != (gwinVMT *)&frameVMT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Draw the frame
|
||||||
|
gwinFrameDraw_Transparent(gw, param);
|
||||||
|
|
||||||
|
// Drop out if that is all we want to draw
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_REDRAW_FRAME))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Draw the client area
|
||||||
|
gdispGFillArea(gw->g.display, gw->g.x + BORDER_L, gw->g.y + BORDER_T, gw->g.width - (BORDER_L+BORDER_R), gw->g.height - (BORDER_T+BORDER_B), gw->pstyle->background);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GDISP_NEED_IMAGE
|
||||||
|
void gwinFrameDraw_Image(GWidgetObject *gw, void *param) {
|
||||||
|
#define gi ((gdispImage *)param)
|
||||||
|
coord_t x, y, iw, ih, mx, my;
|
||||||
|
|
||||||
|
if (gw->g.vmt != (gwinVMT *)&frameVMT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Draw the frame
|
||||||
|
gwinFrameDraw_Transparent(gw, param);
|
||||||
|
|
||||||
|
// Drop out if that is all we want to draw
|
||||||
|
if ((gw->g.flags & GWIN_FRAME_REDRAW_FRAME))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Draw the client area by tiling the image
|
||||||
|
mx = gw->x+gw->g.width - BORDER_R;
|
||||||
|
my = gw->y+gw->g.height - BORDER_B;
|
||||||
|
for(y = gw->g.y+BORDER_T, ih=gi->height; y < my; y += ih) {
|
||||||
|
if (ih > my - y)
|
||||||
|
ih = my - y;
|
||||||
|
for(x = gw->g.x+BORDER_L; 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 /* (GFX_USE_GWIN && GWIN_NEED_FRAME) || defined(__DOXYGEN__) */
|
#endif /* (GFX_USE_GWIN && GWIN_NEED_FRAME) || defined(__DOXYGEN__) */
|
||||||
|
|
|
@ -27,20 +27,16 @@
|
||||||
* @brief Flags for gwinFrameCreate()
|
* @brief Flags for gwinFrameCreate()
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#define GWIN_FRAME_BORDER 0x00000001
|
#define GWIN_FRAME_BORDER 0x00000000 // Deprecated. A border is always shown with a frame window now.
|
||||||
#define GWIN_FRAME_CLOSE_BTN 0x00000002
|
#define GWIN_FRAME_CLOSE_BTN 0x00000001
|
||||||
#define GWIN_FRAME_MINMAX_BTN 0x00000004
|
#define GWIN_FRAME_MINMAX_BTN 0x00000002
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
typedef struct GFrameObject {
|
typedef GContainerObject GFrameObject;
|
||||||
GContainerObject gc;
|
|
||||||
|
|
||||||
GListener gl; // internal listener for the buttons
|
#ifdef __cplusplus
|
||||||
// These could probably be removed... I have to think harder later
|
extern "C" {
|
||||||
GHandle btnClose;
|
#endif
|
||||||
GHandle btnMin;
|
|
||||||
GHandle btnMax;
|
|
||||||
} GFrameObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create a frame widget
|
* @brief Create a frame widget
|
||||||
|
@ -52,8 +48,7 @@ typedef struct GFrameObject {
|
||||||
* @param[in] pInit The initialization parameters
|
* @param[in] pInit The initialization parameters
|
||||||
* @param[in] flags Some flags, see notes.
|
* @param[in] flags Some flags, see notes.
|
||||||
*
|
*
|
||||||
* @note Possible flags are: GWIN_FRAME_BORDER, GWIN_FRAME_CLOSE_BTN, GWIN_FRAME_MINMAX_BTN.
|
* @note Possible flags are: GWIN_FRAME_CLOSE_BTN, GWIN_FRAME_MINMAX_BTN.
|
||||||
* When the close or the minimize/maximize buttons are used, the boarder is automatically invoked.
|
|
||||||
* @note These frame buttons are processed internally. The close button will invoke a gwinDestroy() which will
|
* @note These frame buttons are processed internally. The close button will invoke a gwinDestroy() which will
|
||||||
* destroy the window itself and EVERY child it contains (also children of children).
|
* destroy the window itself and EVERY child it contains (also children of children).
|
||||||
*
|
*
|
||||||
|
@ -64,6 +59,37 @@ typedef struct GFrameObject {
|
||||||
GHandle gwinGFrameCreate(GDisplay *g, GFrameObject *fo, GWidgetInit *pInit, uint32_t flags);
|
GHandle gwinGFrameCreate(GDisplay *g, GFrameObject *fo, GWidgetInit *pInit, uint32_t flags);
|
||||||
#define gwinFrameCreate(fo, pInit, flags) gwinGFrameCreate(GDISP, fo, pInit, flags);
|
#define gwinFrameCreate(fo, pInit, flags) gwinGFrameCreate(GDISP, fo, pInit, flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The custom draw routines for a frame window
|
||||||
|
* @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 gwinFrameDraw_Std() will fill the client area with the background color.<br/>
|
||||||
|
* gwinFrameDraw_Transparent() will not fill the client area at all.<br/>
|
||||||
|
* gwinFrameDraw_Image() will tile the image throughout the client area.<br/>
|
||||||
|
* All these drawing functions draw the frame itself the same way.
|
||||||
|
*
|
||||||
|
* @note The standard functions below ignore the param parameter except for @p gwinFrameDraw_Image().
|
||||||
|
* @note The image custom draw function @p gwinFrameDraw_Image() uses param to pass in the gdispImage pointer.
|
||||||
|
* The image must be already opened before calling @p gwinSetCustomDraw().
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
void gwinFrameDraw_Std(GWidgetObject *gw, void *param);
|
||||||
|
void gwinFrameDraw_Transparent(GWidgetObject *gw, void *param);
|
||||||
|
void gwinFrameDraw_Image(GWidgetObject *gw, void *param);
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _GWIN_FRAME_H */
|
#endif /* _GWIN_FRAME_H */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue