aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Bodenmann <joel@embedded.pro>2017-10-03 14:13:08 +0200
committerJoel Bodenmann <joel@embedded.pro>2017-10-03 14:13:57 +0200
commitc3b484a865a98bff5a89115c56364fdb7a2d854d (patch)
treed2880aa63bcbc290cf39ae821016d7d21e89bf53
parentd0fb5411910f7985feb653fff81a6bcd5d3b2139 (diff)
downloaduGFX-c3b484a865a98bff5a89115c56364fdb7a2d854d.tar.gz
uGFX-c3b484a865a98bff5a89115c56364fdb7a2d854d.tar.bz2
uGFX-c3b484a865a98bff5a89115c56364fdb7a2d854d.zip
Compiler warnings
-rw-r--r--src/gwin/gwin_widget.c1469
1 files changed, 738 insertions, 731 deletions
diff --git a/src/gwin/gwin_widget.c b/src/gwin/gwin_widget.c
index 476ee6ba..34b047eb 100644
--- a/src/gwin/gwin_widget.c
+++ b/src/gwin/gwin_widget.c
@@ -1,731 +1,738 @@
-/*
- * 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_widget.c
- * @brief GWIN sub-system widget code
- */
-
-#include "../../gfx.h"
-
-#if GFX_USE_GWIN && GWIN_NEED_WIDGET
-
-#include <string.h>
-
-#include "gwin_class.h"
-
-// Our listener for events for widgets
-static GListener gl;
-
-#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
- // Our current focus window
- static GHandle _widgetInFocus;
-#endif
-
-// Our default style - a white background theme
-const GWidgetStyle WhiteWidgetStyle = {
- HTML2COLOR(0xFFFFFF), // window background
- HTML2COLOR(0x2A8FCD), // focused
-
- // enabled color set
- {
- HTML2COLOR(0x000000), // text
- HTML2COLOR(0x404040), // edge
- HTML2COLOR(0xE0E0E0), // fill
- HTML2COLOR(0x00E000) // progress - active area
- },
-
- // disabled color set
- {
- HTML2COLOR(0xC0C0C0), // text
- HTML2COLOR(0x808080), // edge
- HTML2COLOR(0xE0E0E0), // fill
- HTML2COLOR(0xC0E0C0) // progress - active area
- },
-
- // pressed color set
- {
- HTML2COLOR(0x404040), // text
- HTML2COLOR(0x404040), // edge
- HTML2COLOR(0x808080), // fill
- HTML2COLOR(0x00E000) // progress - active area
- }
-};
-
-/* Our black style */
-const GWidgetStyle BlackWidgetStyle = {
- HTML2COLOR(0x000000), // window background
- HTML2COLOR(0x2A8FCD), // focused
-
- // enabled color set
- {
- HTML2COLOR(0xC0C0C0), // text
- HTML2COLOR(0xC0C0C0), // edge
- HTML2COLOR(0x606060), // fill
- HTML2COLOR(0x008000) // progress - active area
- },
-
- // disabled color set
- {
- HTML2COLOR(0x808080), // text
- HTML2COLOR(0x404040), // edge
- HTML2COLOR(0x404040), // fill
- HTML2COLOR(0x004000) // progress - active area
- },
-
- // pressed color set
- {
- HTML2COLOR(0xFFFFFF), // text
- HTML2COLOR(0xC0C0C0), // edge
- HTML2COLOR(0xE0E0E0), // fill
- HTML2COLOR(0x008000) // progress - active area
- }
-};
-
-static const GWidgetStyle * defaultStyle = &BlackWidgetStyle;
-
-// We use these everywhere in this file
-#define gw ((GWidgetObject *)gh)
-#define wvmt ((gwidgetVMT *)gh->vmt)
-
-// Process an event
-static void gwidgetEvent(void *param, GEvent *pe) {
- #define pme ((GEventMouse *)pe)
- #define pke ((GEventKeyboard *)pe)
- #define pte ((GEventToggle *)pe)
- #define pde ((GEventDial *)pe)
-
- GHandle h;
- GHandle gh;
- #if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
- uint16_t role;
- #endif
- (void) param;
-
- // Process various events
- switch (pe->type) {
-
- #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- case GEVENT_MOUSE:
- case GEVENT_TOUCH:
- // Cycle through all windows
- for (gh = 0, h = gwinGetNextWindow(0); h; h = gwinGetNextWindow(h)) {
-
- // The window must be on this display and visible to be relevant
- if (h->display != pme->display || !(h->flags & GWIN_FLG_SYSVISIBLE))
- continue;
-
- // Is the mouse currently captured by this widget?
- if ((h->flags & (GWIN_FLG_WIDGET|GWIN_FLG_MOUSECAPTURE)) == (GWIN_FLG_WIDGET|GWIN_FLG_MOUSECAPTURE)) {
- gh = h;
- if ((pme->buttons & GMETA_MOUSE_UP)) {
- gh->flags &= ~GWIN_FLG_MOUSECAPTURE;
- if (wvmt->MouseUp)
- wvmt->MouseUp(gw, pme->x - gh->x, pme->y - gh->y);
- } else if (wvmt->MouseMove)
- wvmt->MouseMove(gw, pme->x - gh->x, pme->y - gh->y);
-
- // There is only ever one captured mouse. Prevent normal mouse processing if there is a captured mouse
- gh = 0;
-
- break;
- }
-
- // Save the highest z-order window that the mouse is over
- if (pme->x >= h->x && pme->x < h->x + h->width && pme->y >= h->y && pme->y < h->y + h->height)
- gh = h;
- }
-
- // Process any mouse down over the highest order window if it is an enabled widget
- if (gh && (gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) == (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) {
- if ((pme->buttons & GMETA_MOUSE_DOWN)) {
- gh->flags |= GWIN_FLG_MOUSECAPTURE;
-
- #if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
- // We should try and capture the focus on this window.
- // If we can't then we don't change the focus
- gwinSetFocus(gh);
- #endif
-
- if (wvmt->MouseDown)
- wvmt->MouseDown(gw, pme->x - gh->x, pme->y - gh->y);
- }
- }
- break;
- #endif
-
- #if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
- case GEVENT_KEYBOARD:
- // If Tab key pressed then set focus to next widget
- if (pke->bytecount == 1 && pke->c[0] == GKEY_TAB) {
- if (!(pke->keystate & GKEYSTATE_KEYUP))
- _gwinMoveFocus();
- break;
- }
-
- // Otherwise, send keyboard events only to widget in focus
- if (_widgetInFocus)
- ((gwidgetVMT*)_widgetInFocus->vmt)->KeyboardEvent((GWidgetObject*)_widgetInFocus, pke);
- break;
- #endif
-
- #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
- case GEVENT_TOGGLE:
- // Cycle through all windows
- for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
-
- // check if it a widget that is enabled and visible
- if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE))
- continue;
-
- for(role = 0; role < wvmt->toggleroles; role++) {
- if (wvmt->ToggleGet(gw, role) == pte->instance) {
- if (pte->on) {
- if (wvmt->ToggleOn)
- wvmt->ToggleOn(gw, role);
- } else {
- if (wvmt->ToggleOff)
- wvmt->ToggleOff(gw, role);
- }
- }
- }
- }
- break;
- #endif
-
- #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
- case GEVENT_DIAL:
- // Cycle through all windows
- for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
-
- // check if it a widget that is enabled and visible
- if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE))
- continue;
-
- for(role = 0; role < wvmt->dialroles; role++) {
- if (wvmt->DialGet(gw, role) == pte->instance) {
- if (wvmt->DialMove)
- wvmt->DialMove(gw, role, pde->value, pde->maxvalue);
- }
- }
- }
- break;
- #endif
-
- default:
- break;
- }
-
- #undef pme
- #undef pte
- #undef pke
- #undef pde
-}
-
-#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
- GHandle gwinGetFocus(void) {
- return _widgetInFocus;
- }
-
- bool_t gwinSetFocus(GHandle gh) {
- GHandle oldFocus;
-
- // Do we already have the focus?
- if (gh == _widgetInFocus)
- return TRUE;
-
- // The new window must be NULLL or a visible enabled widget with a keyboard handler
- if (!gh || ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
- && ((gwidgetVMT*)gh->vmt)->KeyboardEvent)) {
- // Move the current focus
- oldFocus = _widgetInFocus;
- _widgetInFocus = gh;
- if (oldFocus) _gwinUpdate(oldFocus);
- if (gh) _gwinUpdate(gh);
- return TRUE;
- }
- return FALSE;
- }
-
- void _gwinMoveFocus(void) {
- GHandle gh;
- bool_t looponce;
-
- // Find a new focus window (one may or may not exist).
- looponce = FALSE;
- for(gh = gwinGetNextWindow(_widgetInFocus); ; gh = gwinGetNextWindow(gh)) {
- if (!gh && !looponce) {
- looponce = TRUE;
- gh = gwinGetNextWindow(0);
- }
- if (gwinSetFocus(gh))
- break;
- }
- }
-
- void _gwinFixFocus(GHandle gh) {
- GHandle oldFocus;
-
- if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
- && ((gwidgetVMT*)gh->vmt)->KeyboardEvent) {
-
- // We are a candidate to be able to claim the focus
-
- // Claim the focus if no-one else has
- if (!_widgetInFocus)
- _widgetInFocus = gh;
-
- return;
- }
-
- // We have lost any right to the focus
-
- // Did we have the focus
- if (gh != _widgetInFocus)
- return;
-
- // We did - we need to find a new focus window
- oldFocus = _widgetInFocus;
- for(gh = gwinGetNextWindow(oldFocus); gh && gh != oldFocus; gh = gwinGetNextWindow(gh)) {
-
- // Must be a visible enabled widget with a keyboard handler
- if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
- && ((gwidgetVMT*)gh->vmt)->KeyboardEvent) {
-
- // Grab the focus for the new window
- _widgetInFocus = gh;
-
- // This new window still needs to be marked for redraw (but don't actually do it yet).
- gh->flags |= GWIN_FLG_NEEDREDRAW;
- // RedrawPending |= DOREDRAW_VISIBLES; - FIX LATER
- return;
- }
- }
-
- // No-one has the right to the focus
- _widgetInFocus = 0;
- }
-
- void _gwidgetDrawFocusRect(GWidgetObject *gx, coord_t x, coord_t y, coord_t cx, coord_t cy) {
- coord_t i;
-
- // Don't do anything if we don't have the focus
- if (&gx->g != _widgetInFocus)
- return;
-
- // Use the very simplest possible focus rectangle for now
- for (i = 0; i < GWIN_FOCUS_HIGHLIGHT_WIDTH; i++) {
- gdispGDrawBox(gx->g.display, gx->g.x+x+i, gx->g.y+y+i, cx-2*i, cy-2*i, gx->pstyle->focus);
- }
- }
-
-#endif
-
-#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
- static GHandle FindToggleUser(uint16_t instance) {
- GHandle gh;
- uint16_t role;
-
- for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
- if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
- continue;
-
- for(role = 0; role < wvmt->toggleroles; role++) {
- if (wvmt->ToggleGet(gw, role) == instance)
- return gh;
- }
- }
- return 0;
- }
-#endif
-
-#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
- static GHandle FindDialUser(uint16_t instance) {
- GHandle gh;
- uint16_t role;
-
- for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
- if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
- continue;
-
- for(role = 0; role < wvmt->dialroles; role++) {
- if (wvmt->DialGet(gw, role) == instance)
- return gh;
- }
- }
- return 0;
- }
-#endif
-
-void _gwidgetInit(void)
-{
- geventListenerInit(&gl);
- geventRegisterCallback(&gl, gwidgetEvent, 0);
- #if GINPUT_NEED_MOUSE
- geventAttachSource(&gl, ginputGetMouse(GMOUSE_ALL_INSTANCES), GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
- #endif
- #if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
- geventAttachSource(&gl, ginputGetKeyboard(GKEYBOARD_ALL_INSTANCES), GLISTEN_KEYUP);
- #endif
-}
-
-void _gwidgetDeinit(void)
-{
- /* ToDo */
-}
-
-GHandle _gwidgetCreate(GDisplay *g, GWidgetObject *pgw, const GWidgetInit *pInit, const gwidgetVMT *vmt) {
- if (!(pgw = (GWidgetObject *)_gwindowCreate(g, &pgw->g, &pInit->g, &vmt->g, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED)))
- return 0;
-
- #if GWIN_NEED_CONTAINERS
- // This window can't be system enabled if the parent is not enabled
- if (pgw->g.parent && !(pgw->g.parent->flags & GWIN_FLG_SYSENABLED))
- pgw->g.flags &= ~GWIN_FLG_SYSENABLED;
- #endif
- pgw->text = pInit->text ? pInit->text : "";
- pgw->fnDraw = pInit->customDraw ? pInit->customDraw : vmt->DefaultDraw;
- pgw->fnParam = pInit->customParam;
- pgw->pstyle = pInit->customStyle ? pInit->customStyle : defaultStyle;
- #if GWIN_WIDGET_TAGS
- pgw->tag = pInit->tag;
- #endif
-
- return &pgw->g;
-}
-
-void _gwidgetDestroy(GHandle gh) {
- #if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
- uint16_t role, instance;
- #endif
-
- // Make the window is invisible so it is not eligible for focus
- gh->flags &= ~GWIN_FLG_VISIBLE;
- _gwinFixFocus(gh);
-
- // Deallocate the text (if necessary)
- if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
- gh->flags &= ~GWIN_FLG_ALLOCTXT;
- gfxFree((void *)gw->text);
- }
-
- #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
- // Detach any toggles from this object
- for(role = 0; role < wvmt->toggleroles; role++) {
- instance = wvmt->ToggleGet(gw, role);
- if (instance != GWIDGET_NO_INSTANCE) {
- wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
- if (!FindToggleUser(instance))
- geventDetachSource(&gl, ginputGetToggle(instance));
- }
- }
- #endif
-
- #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
- // Detach any dials from this object
- for(role = 0; role < wvmt->dialroles; role++) {
- instance = wvmt->DialGet(gw, role);
- if (instance != GWIDGET_NO_INSTANCE) {
- wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
- if (!FindDialUser(instance))
- geventDetachSource(&gl, ginputGetDial(instance));
- }
- }
- #endif
-
- // Remove any listeners on this object.
- geventDetachSourceListeners((GSourceHandle)gh);
-}
-
-void _gwidgetRedraw(GHandle gh) {
- if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
- return;
-
- gw->fnDraw(gw, gw->fnParam);
-}
-
-void _gwinSendEvent(GHandle gh, GEventType type) {
- GSourceListener * psl;
- GEventGWin * pge;
-
- // Trigger a GWIN Event
- psl = 0;
- while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
- if (!(pge = (GEventGWin *)geventGetEventBuffer(psl)))
- continue;
- pge->type = type;
- pge->gwin = gh;
- #if GWIN_WIDGET_TAGS
- pge->tag = (gh->flags & GWIN_FLG_WIDGET) ? ((GWidgetObject *)gh)->tag : 0;
- #endif
- geventSendEvent(psl);
- }
-}
-
-void gwinWidgetClearInit(GWidgetInit *pwi) {
- char *p;
- unsigned len;
-
- for(p = (char *)pwi, len = sizeof(GWidgetInit); len; len--)
- *p++ = 0;
-}
-
-void gwinSetDefaultStyle(const GWidgetStyle *pstyle, bool_t updateAll) {
- if (!pstyle)
- pstyle = &BlackWidgetStyle;
-
- if (updateAll) {
- GHandle gh;
-
- for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
- if ((gh->flags & GWIN_FLG_WIDGET) && ((GWidgetObject *)gh)->pstyle == defaultStyle)
- gwinSetStyle(gh, pstyle);
- else
- gwinRedraw(gh);
- }
- }
- gwinSetDefaultBgColor(pstyle->background);
- defaultStyle = pstyle;
-}
-
-/**
- * @brief Get the current default style.
- *
- * @api
- */
-const GWidgetStyle *gwinGetDefaultStyle(void) {
- return defaultStyle;
-}
-
-void gwinSetText(GHandle gh, const char *text, bool_t useAlloc) {
- if (!(gh->flags & GWIN_FLG_WIDGET))
- return;
-
- // Dispose of the old string
- if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
- gh->flags &= ~GWIN_FLG_ALLOCTXT;
- if (gw->text) {
- gfxFree((void *)gw->text);
- gw->text = "";
- }
- }
-
- // Alloc the new text if required
- if (!text || !*text)
- gw->text = "";
- else if (useAlloc) {
- char *str;
-
- if ((str = gfxAlloc(strlen(text)+1))) {
- gh->flags |= GWIN_FLG_ALLOCTXT;
- strcpy(str, text);
- }
- gw->text = (const char *)str;
- } else
- gw->text = text;
- _gwinUpdate(gh);
-}
-
-#if GFX_USE_GFILE && GFILE_NEED_PRINTG && GFILE_NEED_STRINGS
- #include <stdarg.h>
-
- void gwinPrintg(GHandle gh, const char * fmt, ...) {
- char *str;
- va_list va;
- int size;
-
- if (!(gh->flags & GWIN_FLG_WIDGET))
- return;
-
- // Dispose of the old string
- if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
- gh->flags &= ~GWIN_FLG_ALLOCTXT;
- if (gw->text) {
- gfxFree((void *)gw->text);
- gw->text = "";
- }
- }
-
- // Alloc the new text
- va_start (va, fmt);
-
- size = vsnprintg(0, 0, fmt, va) + 1; //determine the buffer size required
-
- if ((str = gfxAlloc(size))) {
- gh->flags |= GWIN_FLG_ALLOCTXT;
- vsnprintg(str, size, fmt, va);
- gw->text = (const char *)str;
- } else
- gw->text = "";
-
- va_end (va);
-
- _gwinUpdate(gh);
- }
-#endif
-
-const char *gwinGetText(GHandle gh) {
- if (!(gh->flags & GWIN_FLG_WIDGET))
- return 0;
-
- return gw->text;
-}
-
-bool_t gwinIsWidget(GHandle gh) {
- if (gh->flags & GWIN_FLG_WIDGET) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-void gwinSetStyle(GHandle gh, const GWidgetStyle *pstyle) {
- if (!(gh->flags & GWIN_FLG_WIDGET))
- return;
-
- gw->pstyle = pstyle ? pstyle : defaultStyle;
- gh->bgcolor = gw->pstyle->background;
- gh->color = gw->pstyle->enabled.text;
-
- _gwinUpdate(gh);
-}
-
-const GWidgetStyle *gwinGetStyle(GHandle gh) {
- if (!(gh->flags & GWIN_FLG_WIDGET))
- return 0;
-
- return gw->pstyle;
-}
-
-void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param) {
- if (!(gh->flags & GWIN_FLG_WIDGET))
- return;
-
- gw->fnDraw = fn ? fn : wvmt->DefaultDraw;
- gw->fnParam = param;
- _gwinUpdate(gh);
-}
-
-bool_t gwinAttachListener(GListener *pl) {
- return geventAttachSource(pl, GWIDGET_SOURCE, 0);
-}
-
-#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- bool_t DEPRECATED("This call can now be removed. Attaching the mouse to GWIN is now automatic.") gwinAttachMouse(uint16_t instance) {
- // This is now a NULL event because we automatically attach to all mice in the system.
- (void) instance;
- return TRUE;
- }
-#endif
-
-#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
- bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance) {
- GSourceHandle gsh;
- uint16_t oi;
-
- // Is this a widget
- if (!(gh->flags & GWIN_FLG_WIDGET))
- return FALSE;
-
- // Is the role valid
- if (role >= wvmt->toggleroles)
- return FALSE;
-
- // Is this a valid device
- if (!(gsh = ginputGetToggle(instance)))
- return FALSE;
-
- // Is this already done?
- oi = wvmt->ToggleGet(gw, role);
- if (instance == oi)
- return TRUE;
-
- // Remove the old instance
- if (oi != GWIDGET_NO_INSTANCE) {
- wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
- if (!FindToggleUser(oi))
- geventDetachSource(&gl, ginputGetToggle(oi));
- }
-
- // Assign the new
- wvmt->ToggleAssign(gw, role, instance);
- return geventAttachSource(&gl, gsh, GLISTEN_TOGGLE_ON|GLISTEN_TOGGLE_OFF);
- }
-
- bool_t gwinDetachToggle(GHandle gh, uint16_t role) {
- uint16_t oi;
-
- // Is this a widget
- if (!(gh->flags & GWIN_FLG_WIDGET))
- return FALSE;
-
- // Is the role valid
- if (role >= ((gwidgetVMT *)gh->vmt)->toggleroles)
- return FALSE;
-
- oi = ((gwidgetVMT *)gh->vmt)->ToggleGet(gw, role);
-
- // Remove the instance
- if (oi != GWIDGET_NO_INSTANCE) {
- ((gwidgetVMT *)gh->vmt)->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
- if (!FindToggleUser(oi))
- geventDetachSource(&gl, ginputGetToggle(oi));
- }
- return TRUE;
- }
-
-#endif
-
-#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
- bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance) {
- GSourceHandle gsh;
- uint16_t oi;
-
- if (!(gh->flags & GWIN_FLG_WIDGET))
- return FALSE;
-
- // Is the role valid
- if (role >= wvmt->dialroles)
- return FALSE;
-
- // Is this a valid device
- if (!(gsh = ginputGetDial(instance)))
- return FALSE;
-
- // Is this already done?
- oi = wvmt->DialGet(gw, role);
- if (instance == oi)
- return TRUE;
-
- // Remove the old instance
- if (oi != GWIDGET_NO_INSTANCE) {
- wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
- if (!FindDialUser(oi))
- geventDetachSource(&gl, ginputGetDial(oi));
- }
-
- // Assign the new
- wvmt->DialAssign(gw, role, instance);
- return geventAttachSource(&gl, gsh, 0);
- }
-#endif
-
-#if GWIN_WIDGET_TAGS
- void gwinSetTag(GHandle gh, WidgetTag tag) {
- if ((gh->flags & GWIN_FLG_WIDGET))
- gw->tag = tag;
- }
-
- WidgetTag gwinGetTag(GHandle gh) {
- return ((gh->flags & GWIN_FLG_WIDGET)) ? gw->tag : 0;
- }
-#endif
-
-#undef gw
-#undef wvmt
-#endif /* GFX_USE_GWIN && GWIN_NEED_WIDGET */
-/** @} */
+/*
+ * 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_widget.c
+ * @brief GWIN sub-system widget code
+ */
+
+#include "../../gfx.h"
+
+#if GFX_USE_GWIN && GWIN_NEED_WIDGET
+
+#include <string.h>
+
+#include "gwin_class.h"
+
+// Our listener for events for widgets
+static GListener gl;
+
+#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
+ // Our current focus window
+ static GHandle _widgetInFocus;
+#endif
+
+// Our default style - a white background theme
+const GWidgetStyle WhiteWidgetStyle = {
+ HTML2COLOR(0xFFFFFF), // window background
+ HTML2COLOR(0x2A8FCD), // focused
+
+ // enabled color set
+ {
+ HTML2COLOR(0x000000), // text
+ HTML2COLOR(0x404040), // edge
+ HTML2COLOR(0xE0E0E0), // fill
+ HTML2COLOR(0x00E000) // progress - active area
+ },
+
+ // disabled color set
+ {
+ HTML2COLOR(0xC0C0C0), // text
+ HTML2COLOR(0x808080), // edge
+ HTML2COLOR(0xE0E0E0), // fill
+ HTML2COLOR(0xC0E0C0) // progress - active area
+ },
+
+ // pressed color set
+ {
+ HTML2COLOR(0x404040), // text
+ HTML2COLOR(0x404040), // edge
+ HTML2COLOR(0x808080), // fill
+ HTML2COLOR(0x00E000) // progress - active area
+ }
+};
+
+/* Our black style */
+const GWidgetStyle BlackWidgetStyle = {
+ HTML2COLOR(0x000000), // window background
+ HTML2COLOR(0x2A8FCD), // focused
+
+ // enabled color set
+ {
+ HTML2COLOR(0xC0C0C0), // text
+ HTML2COLOR(0xC0C0C0), // edge
+ HTML2COLOR(0x606060), // fill
+ HTML2COLOR(0x008000) // progress - active area
+ },
+
+ // disabled color set
+ {
+ HTML2COLOR(0x808080), // text
+ HTML2COLOR(0x404040), // edge
+ HTML2COLOR(0x404040), // fill
+ HTML2COLOR(0x004000) // progress - active area
+ },
+
+ // pressed color set
+ {
+ HTML2COLOR(0xFFFFFF), // text
+ HTML2COLOR(0xC0C0C0), // edge
+ HTML2COLOR(0xE0E0E0), // fill
+ HTML2COLOR(0x008000) // progress - active area
+ }
+};
+
+static const GWidgetStyle * defaultStyle = &BlackWidgetStyle;
+
+// We use these everywhere in this file
+#define gw ((GWidgetObject *)gh)
+#define wvmt ((gwidgetVMT *)gh->vmt)
+
+// Process an event
+static void gwidgetEvent(void *param, GEvent *pe) {
+ #define pme ((GEventMouse *)pe)
+ #define pke ((GEventKeyboard *)pe)
+ #define pte ((GEventToggle *)pe)
+ #define pde ((GEventDial *)pe)
+
+ #if GFX_USE_GINPUT
+ #if GINPUT_NEED_MOUSE
+ GHandle h;
+ #endif
+ #if GINPUT_NEED_MOUSE || GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL || GINPUT_NEED_KEYBOARD
+ GHandle gh;
+ #endif
+ #if GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL
+ uint16_t role;
+ #endif
+ #endif
+
+ (void) param;
+
+ // Process various events
+ switch (pe->type) {
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
+ case GEVENT_MOUSE:
+ case GEVENT_TOUCH:
+ // Cycle through all windows
+ for (gh = 0, h = gwinGetNextWindow(0); h; h = gwinGetNextWindow(h)) {
+
+ // The window must be on this display and visible to be relevant
+ if (h->display != pme->display || !(h->flags & GWIN_FLG_SYSVISIBLE))
+ continue;
+
+ // Is the mouse currently captured by this widget?
+ if ((h->flags & (GWIN_FLG_WIDGET|GWIN_FLG_MOUSECAPTURE)) == (GWIN_FLG_WIDGET|GWIN_FLG_MOUSECAPTURE)) {
+ gh = h;
+ if ((pme->buttons & GMETA_MOUSE_UP)) {
+ gh->flags &= ~GWIN_FLG_MOUSECAPTURE;
+ if (wvmt->MouseUp)
+ wvmt->MouseUp(gw, pme->x - gh->x, pme->y - gh->y);
+ } else if (wvmt->MouseMove)
+ wvmt->MouseMove(gw, pme->x - gh->x, pme->y - gh->y);
+
+ // There is only ever one captured mouse. Prevent normal mouse processing if there is a captured mouse
+ gh = 0;
+
+ break;
+ }
+
+ // Save the highest z-order window that the mouse is over
+ if (pme->x >= h->x && pme->x < h->x + h->width && pme->y >= h->y && pme->y < h->y + h->height)
+ gh = h;
+ }
+
+ // Process any mouse down over the highest order window if it is an enabled widget
+ if (gh && (gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) == (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED)) {
+ if ((pme->buttons & GMETA_MOUSE_DOWN)) {
+ gh->flags |= GWIN_FLG_MOUSECAPTURE;
+
+ #if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
+ // We should try and capture the focus on this window.
+ // If we can't then we don't change the focus
+ gwinSetFocus(gh);
+ #endif
+
+ if (wvmt->MouseDown)
+ wvmt->MouseDown(gw, pme->x - gh->x, pme->y - gh->y);
+ }
+ }
+ break;
+ #endif
+
+ #if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
+ case GEVENT_KEYBOARD:
+ // If Tab key pressed then set focus to next widget
+ if (pke->bytecount == 1 && pke->c[0] == GKEY_TAB) {
+ if (!(pke->keystate & GKEYSTATE_KEYUP))
+ _gwinMoveFocus();
+ break;
+ }
+
+ // Otherwise, send keyboard events only to widget in focus
+ if (_widgetInFocus)
+ ((gwidgetVMT*)_widgetInFocus->vmt)->KeyboardEvent((GWidgetObject*)_widgetInFocus, pke);
+ break;
+ #endif
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+ case GEVENT_TOGGLE:
+ // Cycle through all windows
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
+
+ // check if it a widget that is enabled and visible
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE))
+ continue;
+
+ for(role = 0; role < wvmt->toggleroles; role++) {
+ if (wvmt->ToggleGet(gw, role) == pte->instance) {
+ if (pte->on) {
+ if (wvmt->ToggleOn)
+ wvmt->ToggleOn(gw, role);
+ } else {
+ if (wvmt->ToggleOff)
+ wvmt->ToggleOff(gw, role);
+ }
+ }
+ }
+ }
+ break;
+ #endif
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ case GEVENT_DIAL:
+ // Cycle through all windows
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
+
+ // check if it a widget that is enabled and visible
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_SYSENABLED|GWIN_FLG_SYSVISIBLE))
+ continue;
+
+ for(role = 0; role < wvmt->dialroles; role++) {
+ if (wvmt->DialGet(gw, role) == pte->instance) {
+ if (wvmt->DialMove)
+ wvmt->DialMove(gw, role, pde->value, pde->maxvalue);
+ }
+ }
+ }
+ break;
+ #endif
+
+ default:
+ break;
+ }
+
+ #undef pme
+ #undef pte
+ #undef pke
+ #undef pde
+}
+
+#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD
+ GHandle gwinGetFocus(void) {
+ return _widgetInFocus;
+ }
+
+ bool_t gwinSetFocus(GHandle gh) {
+ GHandle oldFocus;
+
+ // Do we already have the focus?
+ if (gh == _widgetInFocus)
+ return TRUE;
+
+ // The new window must be NULLL or a visible enabled widget with a keyboard handler
+ if (!gh || ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
+ && ((gwidgetVMT*)gh->vmt)->KeyboardEvent)) {
+ // Move the current focus
+ oldFocus = _widgetInFocus;
+ _widgetInFocus = gh;
+ if (oldFocus) _gwinUpdate(oldFocus);
+ if (gh) _gwinUpdate(gh);
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ void _gwinMoveFocus(void) {
+ GHandle gh;
+ bool_t looponce;
+
+ // Find a new focus window (one may or may not exist).
+ looponce = FALSE;
+ for(gh = gwinGetNextWindow(_widgetInFocus); ; gh = gwinGetNextWindow(gh)) {
+ if (!gh && !looponce) {
+ looponce = TRUE;
+ gh = gwinGetNextWindow(0);
+ }
+ if (gwinSetFocus(gh))
+ break;
+ }
+ }
+
+ void _gwinFixFocus(GHandle gh) {
+ GHandle oldFocus;
+
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
+ && ((gwidgetVMT*)gh->vmt)->KeyboardEvent) {
+
+ // We are a candidate to be able to claim the focus
+
+ // Claim the focus if no-one else has
+ if (!_widgetInFocus)
+ _widgetInFocus = gh;
+
+ return;
+ }
+
+ // We have lost any right to the focus
+
+ // Did we have the focus
+ if (gh != _widgetInFocus)
+ return;
+
+ // We did - we need to find a new focus window
+ oldFocus = _widgetInFocus;
+ for(gh = gwinGetNextWindow(oldFocus); gh && gh != oldFocus; gh = gwinGetNextWindow(gh)) {
+
+ // Must be a visible enabled widget with a keyboard handler
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)) == (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED|GWIN_FLG_VISIBLE|GWIN_FLG_SYSVISIBLE)
+ && ((gwidgetVMT*)gh->vmt)->KeyboardEvent) {
+
+ // Grab the focus for the new window
+ _widgetInFocus = gh;
+
+ // This new window still needs to be marked for redraw (but don't actually do it yet).
+ gh->flags |= GWIN_FLG_NEEDREDRAW;
+ // RedrawPending |= DOREDRAW_VISIBLES; - FIX LATER
+ return;
+ }
+ }
+
+ // No-one has the right to the focus
+ _widgetInFocus = 0;
+ }
+
+ void _gwidgetDrawFocusRect(GWidgetObject *gx, coord_t x, coord_t y, coord_t cx, coord_t cy) {
+ coord_t i;
+
+ // Don't do anything if we don't have the focus
+ if (&gx->g != _widgetInFocus)
+ return;
+
+ // Use the very simplest possible focus rectangle for now
+ for (i = 0; i < GWIN_FOCUS_HIGHLIGHT_WIDTH; i++) {
+ gdispGDrawBox(gx->g.display, gx->g.x+x+i, gx->g.y+y+i, cx-2*i, cy-2*i, gx->pstyle->focus);
+ }
+ }
+
+#endif
+
+#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+ static GHandle FindToggleUser(uint16_t instance) {
+ GHandle gh;
+ uint16_t role;
+
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
+ if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
+ continue;
+
+ for(role = 0; role < wvmt->toggleroles; role++) {
+ if (wvmt->ToggleGet(gw, role) == instance)
+ return gh;
+ }
+ }
+ return 0;
+ }
+#endif
+
+#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ static GHandle FindDialUser(uint16_t instance) {
+ GHandle gh;
+ uint16_t role;
+
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
+ if (!(gh->flags & GWIN_FLG_WIDGET)) // check if it a widget
+ continue;
+
+ for(role = 0; role < wvmt->dialroles; role++) {
+ if (wvmt->DialGet(gw, role) == instance)
+ return gh;
+ }
+ }
+ return 0;
+ }
+#endif
+
+void _gwidgetInit(void)
+{
+ geventListenerInit(&gl);
+ geventRegisterCallback(&gl, gwidgetEvent, 0);
+ #if GINPUT_NEED_MOUSE
+ geventAttachSource(&gl, ginputGetMouse(GMOUSE_ALL_INSTANCES), GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
+ #endif
+ #if GINPUT_NEED_KEYBOARD || GWIN_NEED_KEYBOARD
+ geventAttachSource(&gl, ginputGetKeyboard(GKEYBOARD_ALL_INSTANCES), GLISTEN_KEYUP);
+ #endif
+}
+
+void _gwidgetDeinit(void)
+{
+ /* ToDo */
+}
+
+GHandle _gwidgetCreate(GDisplay *g, GWidgetObject *pgw, const GWidgetInit *pInit, const gwidgetVMT *vmt) {
+ if (!(pgw = (GWidgetObject *)_gwindowCreate(g, &pgw->g, &pInit->g, &vmt->g, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_SYSENABLED)))
+ return 0;
+
+ #if GWIN_NEED_CONTAINERS
+ // This window can't be system enabled if the parent is not enabled
+ if (pgw->g.parent && !(pgw->g.parent->flags & GWIN_FLG_SYSENABLED))
+ pgw->g.flags &= ~GWIN_FLG_SYSENABLED;
+ #endif
+ pgw->text = pInit->text ? pInit->text : "";
+ pgw->fnDraw = pInit->customDraw ? pInit->customDraw : vmt->DefaultDraw;
+ pgw->fnParam = pInit->customParam;
+ pgw->pstyle = pInit->customStyle ? pInit->customStyle : defaultStyle;
+ #if GWIN_WIDGET_TAGS
+ pgw->tag = pInit->tag;
+ #endif
+
+ return &pgw->g;
+}
+
+void _gwidgetDestroy(GHandle gh) {
+ #if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
+ uint16_t role, instance;
+ #endif
+
+ // Make the window is invisible so it is not eligible for focus
+ gh->flags &= ~GWIN_FLG_VISIBLE;
+ _gwinFixFocus(gh);
+
+ // Deallocate the text (if necessary)
+ if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
+ gh->flags &= ~GWIN_FLG_ALLOCTXT;
+ gfxFree((void *)gw->text);
+ }
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+ // Detach any toggles from this object
+ for(role = 0; role < wvmt->toggleroles; role++) {
+ instance = wvmt->ToggleGet(gw, role);
+ if (instance != GWIDGET_NO_INSTANCE) {
+ wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindToggleUser(instance))
+ geventDetachSource(&gl, ginputGetToggle(instance));
+ }
+ }
+ #endif
+
+ #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ // Detach any dials from this object
+ for(role = 0; role < wvmt->dialroles; role++) {
+ instance = wvmt->DialGet(gw, role);
+ if (instance != GWIDGET_NO_INSTANCE) {
+ wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindDialUser(instance))
+ geventDetachSource(&gl, ginputGetDial(instance));
+ }
+ }
+ #endif
+
+ // Remove any listeners on this object.
+ geventDetachSourceListeners((GSourceHandle)gh);
+}
+
+void _gwidgetRedraw(GHandle gh) {
+ if (!(gh->flags & GWIN_FLG_SYSVISIBLE))
+ return;
+
+ gw->fnDraw(gw, gw->fnParam);
+}
+
+void _gwinSendEvent(GHandle gh, GEventType type) {
+ GSourceListener * psl;
+ GEventGWin * pge;
+
+ // Trigger a GWIN Event
+ psl = 0;
+ while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
+ if (!(pge = (GEventGWin *)geventGetEventBuffer(psl)))
+ continue;
+ pge->type = type;
+ pge->gwin = gh;
+ #if GWIN_WIDGET_TAGS
+ pge->tag = (gh->flags & GWIN_FLG_WIDGET) ? ((GWidgetObject *)gh)->tag : 0;
+ #endif
+ geventSendEvent(psl);
+ }
+}
+
+void gwinWidgetClearInit(GWidgetInit *pwi) {
+ char *p;
+ unsigned len;
+
+ for(p = (char *)pwi, len = sizeof(GWidgetInit); len; len--)
+ *p++ = 0;
+}
+
+void gwinSetDefaultStyle(const GWidgetStyle *pstyle, bool_t updateAll) {
+ if (!pstyle)
+ pstyle = &BlackWidgetStyle;
+
+ if (updateAll) {
+ GHandle gh;
+
+ for(gh = gwinGetNextWindow(0); gh; gh = gwinGetNextWindow(gh)) {
+ if ((gh->flags & GWIN_FLG_WIDGET) && ((GWidgetObject *)gh)->pstyle == defaultStyle)
+ gwinSetStyle(gh, pstyle);
+ else
+ gwinRedraw(gh);
+ }
+ }
+ gwinSetDefaultBgColor(pstyle->background);
+ defaultStyle = pstyle;
+}
+
+/**
+ * @brief Get the current default style.
+ *
+ * @api
+ */
+const GWidgetStyle *gwinGetDefaultStyle(void) {
+ return defaultStyle;
+}
+
+void gwinSetText(GHandle gh, const char *text, bool_t useAlloc) {
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return;
+
+ // Dispose of the old string
+ if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
+ gh->flags &= ~GWIN_FLG_ALLOCTXT;
+ if (gw->text) {
+ gfxFree((void *)gw->text);
+ gw->text = "";
+ }
+ }
+
+ // Alloc the new text if required
+ if (!text || !*text)
+ gw->text = "";
+ else if (useAlloc) {
+ char *str;
+
+ if ((str = gfxAlloc(strlen(text)+1))) {
+ gh->flags |= GWIN_FLG_ALLOCTXT;
+ strcpy(str, text);
+ }
+ gw->text = (const char *)str;
+ } else
+ gw->text = text;
+ _gwinUpdate(gh);
+}
+
+#if GFX_USE_GFILE && GFILE_NEED_PRINTG && GFILE_NEED_STRINGS
+ #include <stdarg.h>
+
+ void gwinPrintg(GHandle gh, const char * fmt, ...) {
+ char *str;
+ va_list va;
+ int size;
+
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return;
+
+ // Dispose of the old string
+ if ((gh->flags & GWIN_FLG_ALLOCTXT)) {
+ gh->flags &= ~GWIN_FLG_ALLOCTXT;
+ if (gw->text) {
+ gfxFree((void *)gw->text);
+ gw->text = "";
+ }
+ }
+
+ // Alloc the new text
+ va_start (va, fmt);
+
+ size = vsnprintg(0, 0, fmt, va) + 1; //determine the buffer size required
+
+ if ((str = gfxAlloc(size))) {
+ gh->flags |= GWIN_FLG_ALLOCTXT;
+ vsnprintg(str, size, fmt, va);
+ gw->text = (const char *)str;
+ } else
+ gw->text = "";
+
+ va_end (va);
+
+ _gwinUpdate(gh);
+ }
+#endif
+
+const char *gwinGetText(GHandle gh) {
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return 0;
+
+ return gw->text;
+}
+
+bool_t gwinIsWidget(GHandle gh) {
+ if (gh->flags & GWIN_FLG_WIDGET) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void gwinSetStyle(GHandle gh, const GWidgetStyle *pstyle) {
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return;
+
+ gw->pstyle = pstyle ? pstyle : defaultStyle;
+ gh->bgcolor = gw->pstyle->background;
+ gh->color = gw->pstyle->enabled.text;
+
+ _gwinUpdate(gh);
+}
+
+const GWidgetStyle *gwinGetStyle(GHandle gh) {
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return 0;
+
+ return gw->pstyle;
+}
+
+void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param) {
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return;
+
+ gw->fnDraw = fn ? fn : wvmt->DefaultDraw;
+ gw->fnParam = param;
+ _gwinUpdate(gh);
+}
+
+bool_t gwinAttachListener(GListener *pl) {
+ return geventAttachSource(pl, GWIDGET_SOURCE, 0);
+}
+
+#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
+ bool_t DEPRECATED("This call can now be removed. Attaching the mouse to GWIN is now automatic.") gwinAttachMouse(uint16_t instance) {
+ // This is now a NULL event because we automatically attach to all mice in the system.
+ (void) instance;
+ return TRUE;
+ }
+#endif
+
+#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+ bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance) {
+ GSourceHandle gsh;
+ uint16_t oi;
+
+ // Is this a widget
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return FALSE;
+
+ // Is the role valid
+ if (role >= wvmt->toggleroles)
+ return FALSE;
+
+ // Is this a valid device
+ if (!(gsh = ginputGetToggle(instance)))
+ return FALSE;
+
+ // Is this already done?
+ oi = wvmt->ToggleGet(gw, role);
+ if (instance == oi)
+ return TRUE;
+
+ // Remove the old instance
+ if (oi != GWIDGET_NO_INSTANCE) {
+ wvmt->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindToggleUser(oi))
+ geventDetachSource(&gl, ginputGetToggle(oi));
+ }
+
+ // Assign the new
+ wvmt->ToggleAssign(gw, role, instance);
+ return geventAttachSource(&gl, gsh, GLISTEN_TOGGLE_ON|GLISTEN_TOGGLE_OFF);
+ }
+
+ bool_t gwinDetachToggle(GHandle gh, uint16_t role) {
+ uint16_t oi;
+
+ // Is this a widget
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return FALSE;
+
+ // Is the role valid
+ if (role >= ((gwidgetVMT *)gh->vmt)->toggleroles)
+ return FALSE;
+
+ oi = ((gwidgetVMT *)gh->vmt)->ToggleGet(gw, role);
+
+ // Remove the instance
+ if (oi != GWIDGET_NO_INSTANCE) {
+ ((gwidgetVMT *)gh->vmt)->ToggleAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindToggleUser(oi))
+ geventDetachSource(&gl, ginputGetToggle(oi));
+ }
+ return TRUE;
+ }
+
+#endif
+
+#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance) {
+ GSourceHandle gsh;
+ uint16_t oi;
+
+ if (!(gh->flags & GWIN_FLG_WIDGET))
+ return FALSE;
+
+ // Is the role valid
+ if (role >= wvmt->dialroles)
+ return FALSE;
+
+ // Is this a valid device
+ if (!(gsh = ginputGetDial(instance)))
+ return FALSE;
+
+ // Is this already done?
+ oi = wvmt->DialGet(gw, role);
+ if (instance == oi)
+ return TRUE;
+
+ // Remove the old instance
+ if (oi != GWIDGET_NO_INSTANCE) {
+ wvmt->DialAssign(gw, role, GWIDGET_NO_INSTANCE);
+ if (!FindDialUser(oi))
+ geventDetachSource(&gl, ginputGetDial(oi));
+ }
+
+ // Assign the new
+ wvmt->DialAssign(gw, role, instance);
+ return geventAttachSource(&gl, gsh, 0);
+ }
+#endif
+
+#if GWIN_WIDGET_TAGS
+ void gwinSetTag(GHandle gh, WidgetTag tag) {
+ if ((gh->flags & GWIN_FLG_WIDGET))
+ gw->tag = tag;
+ }
+
+ WidgetTag gwinGetTag(GHandle gh) {
+ return ((gh->flags & GWIN_FLG_WIDGET)) ? gw->tag : 0;
+ }
+#endif
+
+#undef gw
+#undef wvmt
+#endif /* GFX_USE_GWIN && GWIN_NEED_WIDGET */
+/** @} */