ugfx/src/gwin/frame.c

233 lines
5.9 KiB
C

/*
* 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/frame.c
* @brief GWIN sub-system frame code.
*
* @defgroup Frame Frame
* @ingroup GWIN
*
* @{
*/
#include "gfx.h"
#if (GFX_USE_GWIN && GWIN_NEED_FRAME) || defined(__DOXYGEN__)
/* Some values for the default render */
#define BORDER_X 5
#define BORDER_Y 30
#define BUTTON_X 20
#define BUTTON_Y 20
/* Some useful macros for data type conversions */
#define gh2obj ((GFrameObject *)gh)
/* Forware declarations */
void gwinFrameDraw_Std(GWidgetObject *gw, void *param);
#if 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
static const gwidgetVMT frameVMT = {
{
"Frame", // The classname
sizeof(GFrameObject), // The object size
_gwidgetDestroy, // The destroy routine
_gwidgetRedraw, // The redraw routine
0, // The after-clear routine
},
gwinFrameDraw_Std, // The default drawing routine
#if GINPUT_NEED_MOUSE
{
_mouseDown, // Process mouse down event
_mouseUp, // Process mouse up events
_mouseMove, // Process mouse move events
},
#endif
#if GINPUT_NEED_TOGGLE
{
0, // 1 toggle role
0, // Assign Toggles
0, // Get Toggles
0, // Process toggle off events
0, // Process toggle on events
},
#endif
#if GINPUT_NEED_DIAL
{
0, // 1 dial roles
0, // Assign Dials
0, // Get Dials
0, // Process dial move events
},
#endif
};
GHandle gwinGFrameCreate(GDisplay *g, GFrameObject *fo, GWidgetInit *pInit, uint16_t flags) {
uint16_t tmp;
if (!(fo = (GFrameObject *)_gwidgetCreate(g, &fo->w, pInit, &frameVMT)))
return 0;
fo->btnClose = NULL;
fo->btnMin = NULL;
fo->btnMax = NULL;
/* Buttons require a border */
tmp = flags;
if ((tmp & GWIN_FRAME_CLOSE_BTN || tmp & GWIN_FRAME_MINMAX_BTN) && !(tmp & GWIN_FRAME_BORDER)) {
tmp |= GWIN_FRAME_BORDER;
}
/* apply flags */
fo->w.g.flags |= tmp;
/* create close button if necessary */
if (fo->w.g.flags & GWIN_FRAME_CLOSE_BTN) {
GWidgetInit wi;
wi.customDraw = 0;
wi.customParam = 0;
wi.customStyle = 0;
wi.g.show = TRUE;
wi.g.x = fo->w.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 = "X";
fo->btnClose = gwinButtonCreate(NULL, &wi);
gwinAddChild((GHandle)fo, fo->btnClose, FALSE);
}
/* create minimize and maximize buttons if necessary */
if (fo->w.g.flags & GWIN_FRAME_MINMAX_BTN) {
GWidgetInit wi;
wi.customDraw = 0;
wi.customParam = 0;
wi.customStyle = 0;
wi.g.show = TRUE;
wi.g.x = (fo->w.g.flags & GWIN_FRAME_CLOSE_BTN) ? fo->w.g.width - 2*BORDER_X - 2*BUTTON_X : fo->w.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 = "O";
fo->btnMin = gwinButtonCreate(NULL, &wi);
gwinAddChild((GHandle)fo, fo->btnMin, FALSE);
wi.g.x = (fo->w.g.flags & GWIN_FRAME_CLOSE_BTN) ? fo->w.g.width - 3*BORDER_X - 3*BUTTON_X : fo->w.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 = "_";
fo->btnMax = gwinButtonCreate(NULL, &wi);
gwinAddChild((GHandle)fo, fo->btnMax, FALSE);
}
gwinSetVisible(&fo->w.g, pInit->g.show);
return (GHandle)fo;
}
GHandle gwinFrameGetClose(GHandle gh) {
if (gh->vmt != (gwinVMT *)&frameVMT)
return;
return gh2obj->btnClose;
}
GHandle gwinFrameGetMin(GHandle gh) {
if (gh->vmt != (gwinVMT *)&frameVMT)
return;
return gh2obj->btnMin;
}
GHandle gwinFrameGetMax(GHandle gh) {
if (gh->vmt != (gwinVMT *)&frameVMT)
return;
return gh2obj->btnMax;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Default render routines //
///////////////////////////////////////////////////////////////////////////////////////////////////
static const GColorSet* _getDrawColors(GWidgetObject *gw) {
if (!(gw->g.flags & GWIN_FLG_ENABLED))
return &gw->pstyle->disabled;
//if ((gw->g.flags & GBUTTON_FLG_PRESSED))
// return &gw->pstyle->pressed;
return &gw->pstyle->enabled;
}
void gwinFrameDraw_Std(GWidgetObject *gw, void *param) {
GColorSet *pcol;
color_t border;
color_t background;
(void)param;
if (gw->g.vmt != (gwinVMT *)&frameVMT)
return;
pcol = _getDrawColors(gw);
// do some magic to make the background lighter than the widgets. Fix this somewhen.
border = HTML2COLOR(0x2698DE);
background = HTML2COLOR(0xEEEEEE);
#if GDISP_NEED_CLIP
gdispGSetClip(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height);
#endif
if (gw->g.flags & GWIN_FRAME_BORDER) {
gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, border);
gdispGFillArea(gw->g.display, gw->g.x + BORDER_X, gw->g.y + BORDER_Y, gw->g.width - 2*BORDER_X, gw->g.width - BORDER_Y - BORDER_X, background);
} else {
// This ensure that the actual frame content (it's children) render at the same spot, no mather whether the frame has a border or not
gdispGFillArea(gw->g.display, gw->g.x + BORDER_X, gw->g.y + BORDER_Y, gw->g.width, gw->g.height, background);
}
#if GDISP_NEED_CLIP
gdispGUnsetClip(gw->g.display);
#endif
// redraw buttons if necessary - this should be done due the parent-child relationship but that is buggy...
if (gw->g.flags & GWIN_FRAME_CLOSE_BTN) {
gwinRedraw(((GFrameObject*)gw)->btnClose);
}
if (gw->g.flags & GWIN_FRAME_MINMAX_BTN) {
gwinRedraw(((GFrameObject*)gw)->btnMin);
gwinRedraw(((GFrameObject*)gw)->btnMax);
}
// FixMe...
//gwinRedraw(gw);
}
#endif /* (GFX_USE_GWIN && GWIN_NEED_FRAME) || defined(__DOXYGEN__) */
/** @} */