ugfx/src/gwin/gwidget.c

255 lines
5.8 KiB
C

/*
* 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 */
/** @} */