diff options
Diffstat (limited to 'src/gwin/gwidget.c')
-rw-r--r-- | src/gwin/gwidget.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/src/gwin/gwidget.c b/src/gwin/gwidget.c new file mode 100644 index 00000000..464210b7 --- /dev/null +++ b/src/gwin/gwidget.c @@ -0,0 +1,254 @@ +/* + * This file is subject to the terms of the GFX License, v1.0. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://chibios-gfx.com/license.html + */ + +#include "gfx.h" + +#if GFX_USE_GWIN + +#include <string.h> + +#include "gwin/class_gwin.h" + +/* We use these everywhere in this file */ +#define gw ((GWidgetObject *)gh) +#define wvmt ((gwidgetVMT *)gh->vmt) + +static void gwidgetCallback(void *param, GEvent *pe) { + #define gh ((GWindowObject *)param) + #define pme ((GEventMouse *)pe) + #define pte ((GEventToggle *)pe) + #define pde ((GEventDial *)pe) + + // check if widget is disabled + if (!(gw->g.flags & GWIN_FLG_ENABLED)) + return; + + // Process via AllEvents() if it is defined + if (wvmt->AllEvents) + wvmt->AllEvents(gw, pe); + + // Process various events + switch (pe->type) { + + #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE + case GEVENT_MOUSE: + case GEVENT_TOUCH: + // Are we captured? + if ((gw->g.flags & GWIN_FLG_MOUSECAPTURE)) { + if (pme->meta == GMETA_MOUSE_UP) { + gw->g.flags &= ~GWIN_FLG_MOUSECAPTURE; + if (wvmt->MouseUp) + wvmt->MouseUp(gw, pme->x - gw->g.x, pme->y - gw->g.y); + return; + } else if (wvmt->MouseMove) + wvmt->MouseMove(gw, pme->x - gw->g.x, pme->y - gw->g.y); + + // We are not captured - look for mouse downs over the widget + } else if (pme->meta == GMETA_MOUSE_DOWN + && pme->x >= gw->g.x && pme->x < gw->g.x + gw->g.width + && pme->y >= gw->g.y && pme->y < gw->g.y + gw->g.height) { + gw->g.flags |= GWIN_FLG_MOUSECAPTURE; + if (wvmt->MouseDown) + wvmt->MouseDown(gw, pme->x - gw->g.x, pme->y - gw->g.y); + } + break; + #endif + + #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE + case GEVENT_TOGGLE: + if (pte->on) { + if (wvmt->ToggleOn) + wvmt->ToggleOn(gw, pte->instance); + } else { + if (wvmt->ToggleOff) + wvmt->ToggleOff(gw, pte->instance); + } + break; + #endif + + #if GFX_USE_GINPUT && GINPUT_NEED_DIAL + case GEVENT_DIAL: + if (wvmt->DialMove) + wvmt->DialMove(gw, pde->instance, pde->value); + break; + #endif + + default: + break; + } + #undef gh + #undef pme + #undef pte + #undef pde +} + +GHandle _gwidgetInit(GWidgetObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwidgetVMT *vmt) { + if (!(pgw = (GWidgetObject *)_gwinInit((GWindowObject *)pgw, x, y, width, height, size, (const gwinVMT *)vmt))) + return 0; + + pgw->g.flags |= (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED); + pgw->txt = ""; + pgw->fnDraw = vmt->DefaultDraw; + pgw->fnParam = 0; + geventListenerInit(&pgw->listener); + geventRegisterCallback(&pgw->listener, gwidgetCallback, pgw); + + return (GHandle)pgw; +} + +void _gwidgetDestroy(GHandle gh) { + if (!(gh->flags & GWIN_FLG_WIDGET)) + return; + + // Deallocate the text (if necessary) + if ((gh->flags & GWIN_FLG_ALLOCTXT)) { + gh->flags &= ~GWIN_FLG_ALLOCTXT; + gfxFree((void *)gw->txt); + } + // Untangle the listeners (both on us and to us). + geventDetachSource(&gw->listener, 0); + geventDetachSourceListeners((GSourceHandle)gh); + gh->flags &= ~GWIN_FLG_WIDGET; +} + +void gwinSetEnabled(GHandle gh, bool_t enabled) { + if (!(gh->flags & GWIN_FLG_WIDGET)) + return; + + if (enabled) + gh->flags |= GWIN_FLG_ENABLED; + else + gh->flags &= ~GWIN_FLG_ENABLED; +} + +void gwinDraw(GHandle gh) { + if (!(gh->flags & GWIN_FLG_WIDGET)) + return; + + #if GDISP_NEED_CLIP + gdispSetClip(gh->x, gh->y, gh->width, gh->height); + #endif + + gw->fnDraw(gw, gw->fnParam); +} + +void gwinSetText(GHandle gh, const char *txt, 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->txt) { + gfxFree((void *)gw->txt); + gw->txt = ""; + } + } + + // Alloc the new text if required + if (txt && !*txt) txt = 0; + if (txt && useAlloc) { + char *str; + + if ((str = (char *)gfxAlloc(strlen(txt)+1))) { + gh->flags |= GWIN_FLG_ALLOCTXT; + strcpy(str, txt); + } + txt = (const char *)str; + } + + gw->txt = txt ? txt : ""; +} + +const char *gwinGetText(GHandle gh) { + if (!(gh->flags & GWIN_FLG_WIDGET)) + return 0; + + return gw->txt; +} + +void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param) { + if (!(gh->flags & GWIN_FLG_WIDGET)) + return; + + gw->fnDraw = fn ? fn : wvmt->DefaultDraw; + gw->fnParam = param; +} + +bool_t gwinAttachListener(GHandle gh, GListener *pl, unsigned flags) { + if (!(gh->flags & GWIN_FLG_WIDGET)) + return FALSE; + + return geventAttachSource(pl, (GSourceHandle)gh, flags); +} + +#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE + bool_t gwinAttachMouse(GHandle gh, uint16_t instance) { + GSourceHandle gsh; + unsigned flags; + + if (!(gh->flags & GWIN_FLG_WIDGET)) + return FALSE; + + if (!wvmt->MouseDown && !wvmt->MouseMove && !wvmt->MouseUp) + return FALSE; + + if (!(gsh = ginputGetMouse(instance))) + return FALSE; + + flags = wvmt->MouseMove ? (GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES) : GLISTEN_MOUSEMETA; + return geventAttachSource(&gw->listener, gsh, flags); + } +#endif + +#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE + bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance) { + GSourceHandle gsh; + unsigned flags; + + if (!(gh->flags & GWIN_FLG_WIDGET)) + return FALSE; + + flags = 0; + if (wvmt->ToggleOff) flags |= GLISTEN_TOGGLE_OFF; + if (wvmt->ToggleOn) flags |= GLISTEN_TOGGLE_ON; + if (!flags) + return FALSE; + + if (!(gsh = ginputGetToggle(instance))) + return FALSE; + + if (wvmt->AssignToggle && !wvmt->AssignToggle(gw, role, instance)) + return FALSE; + + return geventAttachSource(&gw->listener, gsh, flags); + } +#endif + +#if GFX_USE_GINPUT && GINPUT_NEED_DIAL + bool_t gwinAttachDial(GHandle gh, uint16_t role, uint16_t instance) { + GSourceHandle gsh; + + if (!(gh->flags & GWIN_FLG_WIDGET)) + return FALSE; + + if (!wvmt->DialMove) + return FALSE; + + if (!(gsh = ginputGetDial(instance))) + return FALSE; + + if (wvmt->AssignDial && !wvmt->AssignDial(gw, role, instance)) + return FALSE; + + return geventAttachSource(&gw->listener, gsh, 0); + } +#endif + +#endif /* GFX_USE_GWIN */ +/** @} */ + |