From 6aa34e4fdcf3ffa45e2c9b3a8c7c15a43c043d38 Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Mon, 6 Jan 2014 21:20:35 +0100 Subject: [PATCH] initial version of frames - still work in progress, DO NOT USE!!! --- gfxconf.example.h | 1 + include/gfx_rules.h | 11 +- include/gwin/frame.h | 52 +++++++++ include/gwin/gwidget.h | 4 + include/gwin/gwin.h | 4 - src/gwin/frame.c | 232 +++++++++++++++++++++++++++++++++++++++++ src/gwin/gwin.mk | 1 + 7 files changed, 300 insertions(+), 5 deletions(-) create mode 100644 include/gwin/frame.h create mode 100644 src/gwin/frame.c diff --git a/gfxconf.example.h b/gfxconf.example.h index 38e36100..349f0c3c 100644 --- a/gfxconf.example.h +++ b/gfxconf.example.h @@ -140,6 +140,7 @@ #define GWIN_NEED_RADIO FALSE #define GWIN_NEED_LIST FALSE #define GWIN_NEED_PROGRESSBAR FALSE + #define GWIN_NEED_FRAME FALSE /////////////////////////////////////////////////////////////////////////// diff --git a/include/gfx_rules.h b/include/gfx_rules.h index 301cf263..d547f923 100644 --- a/include/gfx_rules.h +++ b/include/gfx_rules.h @@ -61,12 +61,21 @@ #if GWIN_NEED_HIERARCHY #if !GQUEUE_NEED_ASYNC #if GFX_DISPLAY_RULE_WARNINGS - #warning "GWIN: GQUEUE_NEED_ASYNC is required when a GWIN_NEED_HIERARCHY is enabled. It has been turned on for you." + #warning "GWIN: GQUEUE_NEED_ASYNC is required when GWIN_NEED_HIERARCHY is enabled. It has been turned on for you." #endif #undef GQUEUE_NEED_ASYNC #define GQUEUE_NEED_ASYNC TRUE #endif #endif + #if GWIN_NEED_FRAME + #if !GWIN_NEED_HIERARCHY + #if GFX_DISPLAY_RULE_WARNINGS + #warning "GWIN: GWIN_NEED_HIERARCHY is required when GIWN_NEED_FRAME is enabled. It has been turned on for you." + #endif + #undef GWIN_NEED_HIERARCHY + #define GWIN_NEED_HIERARCHY TRUE + #endif + #endif #if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX || GWIN_NEED_LABEL || GWIN_NEED_RADIO || GWIN_NEED_LIST || \ GWIN_NEED_IMAGE || GWIN_NEED_CHECKBOX || GWIN_NEED_PROGRESSBAR #if !GWIN_NEED_WIDGET diff --git a/include/gwin/frame.h b/include/gwin/frame.h new file mode 100644 index 00000000..156bdcd0 --- /dev/null +++ b/include/gwin/frame.h @@ -0,0 +1,52 @@ +/* + * 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 include/gwin/frame.h + * @brief GWIN Graphic window subsystem header file. + * + * @defgroup Frame Frame + * @ingroup GWIN + * + * @details A frame is a rectangular window that can have optional border as well as buttons to + * close, maximize and minimize it. The main purpose of this widget is to contain children. + * + * @pre GFX_USE_GWIN must be set to TRUE in your gfxconf.h + * @pre GWIN_NEED_FRAME must be set to TRUE in your gfxconf.h + * @{ + */ + +#ifndef _GWIN_FRAME_H +#define _GWIN_FRAME_H + +#include "gwin/class_gwin.h" + +// Flags for gwinFrameCreate() +#define GWIN_FRAME_BORDER (GWIN_FIRST_CONTROL_FLAG << 0) +#define GWIN_FRAME_CLOSE_BTN (GWIN_FIRST_CONTROL_FLAG << 1) +#define GWIN_FRAME_MINMAX_BTN (GWIN_FIRST_CONTROL_FLAG << 2) + +typedef struct GFrameObject { + GWidgetObject w; + + GHandle btnClose; + GHandle btnMin; + GHandle btnMax; +} GFrameObject; + +GHandle gwinGFrameCreate(GDisplay *g, GFrameObject *fo, GWidgetInit *pInit, uint16_t flags); +#define gwinFrameCreate(fo, pInit, flags) gwinGFrameCreate(GDISP, fo, pInit, flags); + +GHandle gwinFrameGetClose(GHandle gh); + +GHandle gwinFrameGetMin(GHandle gh); + +GHandle gwinFrameGetMax(GHandle gh); + +#endif /* _GWIN_FRAME_H */ +/** @} */ + diff --git a/include/gwin/gwidget.h b/include/gwin/gwidget.h index fa40c51c..8697ca92 100644 --- a/include/gwin/gwidget.h +++ b/include/gwin/gwidget.h @@ -304,5 +304,9 @@ bool_t gwinAttachListener(GListener *pl); #include "gwin/progressbar.h" #endif +#if GWIN_NEED_FRAME || defined(__DOXYGEN__) + #include "gwin/frame.h" +#endif + #endif /* _GWIDGET_H */ /** @} */ diff --git a/include/gwin/gwin.h b/include/gwin/gwin.h index 73f7ff82..c59a1bcf 100644 --- a/include/gwin/gwin.h +++ b/include/gwin/gwin.h @@ -894,10 +894,6 @@ extern "C" { #include "gwin/image.h" #endif - #if GWIN_NEED_LAYOUT || defined(__DOXYGEN__) - #include "gwin/layout.h" - #endif - #endif /* GFX_USE_GWIN */ #endif /* _GWIN_H */ diff --git a/src/gwin/frame.c b/src/gwin/frame.c new file mode 100644 index 00000000..0a8f0a6e --- /dev/null +++ b/src/gwin/frame.c @@ -0,0 +1,232 @@ +/* + * 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__) */ +/** @} */ + diff --git a/src/gwin/gwin.mk b/src/gwin/gwin.mk index 4c670ea2..dbca7fd8 100644 --- a/src/gwin/gwin.mk +++ b/src/gwin/gwin.mk @@ -11,4 +11,5 @@ GFXSRC += $(GFXLIB)/src/gwin/gwin.c \ $(GFXLIB)/src/gwin/radio.c \ $(GFXLIB)/src/gwin/list.c \ $(GFXLIB)/src/gwin/progressbar.c \ + $(GFXLIB)/src/gwin/frame.c \