aboutsummaryrefslogtreecommitdiffstats
path: root/src/gwin
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2013-06-10 17:18:01 +1000
committerinmarket <andrewh@inmarket.com.au>2013-06-10 17:18:01 +1000
commit2cb35d6815a0a12035f4792c266b688c77085620 (patch)
tree292ebc4760767d67b41f7f0e0022185afcf05067 /src/gwin
parent777ec6af7c1b594f7b7a9cbaaf7ead90d8fb7e8f (diff)
downloaduGFX-2cb35d6815a0a12035f4792c266b688c77085620.tar.gz
uGFX-2cb35d6815a0a12035f4792c266b688c77085620.tar.bz2
uGFX-2cb35d6815a0a12035f4792c266b688c77085620.zip
Clean up GWIN Event assignment. Optimise event efficiency.
Diffstat (limited to 'src/gwin')
-rw-r--r--src/gwin/button.c58
-rw-r--r--src/gwin/checkbox.c50
-rw-r--r--src/gwin/console.c2
-rw-r--r--src/gwin/graph.c2
-rw-r--r--src/gwin/gwidget.c254
-rw-r--r--src/gwin/gwin.c9
-rw-r--r--src/gwin/slider.c91
7 files changed, 345 insertions, 121 deletions
diff --git a/src/gwin/button.c b/src/gwin/button.c
index 83b81b03..285a406c 100644
--- a/src/gwin/button.c
+++ b/src/gwin/button.c
@@ -32,8 +32,10 @@
// Prototypes for button VMT functions
static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y);
static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y);
-static void ToggleOff(GWidgetObject *gw, uint16_t instance);
-static void ToggleOn(GWidgetObject *gw, uint16_t instance);
+static void ToggleOff(GWidgetObject *gw, uint16_t role);
+static void ToggleOn(GWidgetObject *gw, uint16_t role);
+static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance);
+static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role);
// The button VMT table
static const gwidgetVMT buttonVMT = {
@@ -43,16 +45,25 @@ static const gwidgetVMT buttonVMT = {
_gwidgetRedraw, // The redraw routine
0, // The after-clear routine
},
- gwinButtonDraw_3D, // The default drawing routine
- MouseDown, // Process mouse down events
- MouseUp, // Process mouse up events
- 0, // Process mouse move events (NOT USED)
- ToggleOff, // Process toggle off events
- ToggleOn, // Process toggle on events
- 0, // Process dial move events (NOT USED)
- 0, // Process all events (NOT USED)
- 0, // AssignToggle (NOT USED)
- 0, // AssignDial (NOT USED)
+ gwinButtonDraw_3D, // The default drawing routine
+ {
+ MouseDown, // Process mouse down events
+ MouseUp, // Process mouse up events
+ 0, // Process mouse move events (NOT USED)
+ },
+ {
+ 1, // 1 toggle role
+ ToggleAssign, // Assign Toggles
+ ToggleGet, // Get Toggles
+ ToggleOff, // Process toggle off events
+ ToggleOn, // Process toggle on events
+ },
+ {
+ 0, // No dial roles
+ 0, // Assign Dials (NOT USED)
+ 0, // Get Dials (NOT USED)
+ 0, // Process dial move events (NOT USED)
+ }
};
// Default color scheme
@@ -80,7 +91,7 @@ static void SendButtonEvent(GWidgetObject *gw) {
// Trigger a GWIN Button Event
psl = 0;
- while ((psl = geventGetSourceListener((GSourceHandle)gw, psl))) {
+ while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
pbe->type = GEVENT_GWIN_BUTTON;
@@ -114,25 +125,36 @@ static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
}
// A toggle off has occurred
-static void ToggleOff(GWidgetObject *gw, uint16_t instance) {
- (void) instance;
+static void ToggleOff(GWidgetObject *gw, uint16_t role) {
+ (void) role;
gw->g.flags &= ~GBUTTON_FLG_PRESSED;
_gwidgetRedraw((GHandle)gw);
}
// A toggle on has occurred
-static void ToggleOn(GWidgetObject *gw, uint16_t instance) {
- (void) instance;
+static void ToggleOn(GWidgetObject *gw, uint16_t role) {
+ (void) role;
gw->g.flags |= GBUTTON_FLG_PRESSED;
_gwidgetRedraw((GHandle)gw);
// Trigger the event on button down (different than for mouse/touch)
SendButtonEvent(gw);
}
+static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
+ (void) role;
+ ((GButtonObject *)gw)->toggle = instance;
+}
+
+static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
+ (void) role;
+ return ((GButtonObject *)gw)->toggle;
+}
+
GHandle gwinCreateButton(GButtonObject *gw, coord_t x, coord_t y, coord_t width, coord_t height) {
- if (!(gw = (GButtonObject *)_gwidgetInit((GWidgetObject *)gw, x, y, width, height, sizeof(GButtonObject), &buttonVMT)))
+ if (!(gw = (GButtonObject *)_gwidgetCreate((GWidgetObject *)gw, x, y, width, height, sizeof(GButtonObject), &buttonVMT)))
return 0;
+ gw->toggle = GWIDGET_NO_INSTANCE;
gw->c_up = GButtonDefaultColorsUp;
gw->c_dn = GButtonDefaultColorsDown;
gw->c_dis = GButtonDefaultColorsDisabled;
diff --git a/src/gwin/checkbox.c b/src/gwin/checkbox.c
index 893dab9c..53e99e42 100644
--- a/src/gwin/checkbox.c
+++ b/src/gwin/checkbox.c
@@ -26,7 +26,9 @@
// Prototypes for button VMT functions
static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y);
-static void ToggleOn(GWidgetObject *gw, uint16_t instance);
+static void ToggleOn(GWidgetObject *gw, uint16_t role);
+static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance);
+static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role);
// The button VMT table
static const gwidgetVMT checkboxVMT = {
@@ -37,15 +39,24 @@ static const gwidgetVMT checkboxVMT = {
0, // The after-clear routine
},
gwinCheckboxDraw_CheckOnLeft, // The default drawing routine
- MouseDown, // Process mouse down events
- 0, // Process mouse up events (NOT USED)
- 0, // Process mouse move events (NOT USED)
- 0, // Process toggle off events (NOT USED)
- ToggleOn, // Process toggle on events
- 0, // Process dial move events (NOT USED)
- 0, // Process all events (NOT USED)
- 0, // AssignToggle (NOT USED)
- 0, // AssignDial (NOT USED)
+ {
+ MouseDown, // Process mouse down events
+ 0, // Process mouse up events (NOT USED)
+ 0, // Process mouse move events (NOT USED)
+ },
+ {
+ 1, // 1 toggle role
+ ToggleAssign, // Assign Toggles
+ ToggleGet, // Get Toggles
+ 0, // Process toggle off events (NOT USED)
+ ToggleOn, // Process toggle on events
+ },
+ {
+ 0, // No dial roles
+ 0, // Assign Dials (NOT USED)
+ 0, // Get Dials (NOT USED)
+ 0, // Process dial move events (NOT USED)
+ }
};
static const GCheckboxColors defaultColors = {
@@ -63,7 +74,7 @@ static void SendCheckboxEvent(GWidgetObject *gw) {
// Trigger a GWIN Checkbox Event
psl = 0;
- while ((psl = geventGetSourceListener((GSourceHandle)gw, psl))) {
+ while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
pce->type = GEVENT_GWIN_CHECKBOX;
@@ -84,17 +95,28 @@ static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
}
// A toggle on has occurred
-static void ToggleOn(GWidgetObject *gw, uint16_t instance) {
- (void) instance;
+static void ToggleOn(GWidgetObject *gw, uint16_t role) {
+ (void) role;
gw->g.flags ^= GCHECKBOX_FLG_CHECKED;
_gwidgetRedraw((GHandle)gw);
SendCheckboxEvent(gw);
}
+static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
+ (void) role;
+ ((GCheckboxObject *)gw)->toggle = instance;
+}
+
+static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
+ (void) role;
+ return ((GCheckboxObject *)gw)->toggle;
+}
+
GHandle gwinCreateCheckbox(GCheckboxObject *gb, coord_t x, coord_t y, coord_t width, coord_t height) {
- if (!(gb = (GCheckboxObject *)_gwidgetInit((GWidgetObject *)gb, x, y, width, height, sizeof(GCheckboxObject), &checkboxVMT)))
+ if (!(gb = (GCheckboxObject *)_gwidgetCreate((GWidgetObject *)gb, x, y, width, height, sizeof(GCheckboxObject), &checkboxVMT)))
return 0;
+ gb->toggle = (uint16_t) -1;
gb->c = defaultColors; // assign the default colors
return (GHandle)gb;
}
diff --git a/src/gwin/console.c b/src/gwin/console.c
index c4b2798d..6941295a 100644
--- a/src/gwin/console.c
+++ b/src/gwin/console.c
@@ -66,7 +66,7 @@ static const gwinVMT consoleVMT = {
};
GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t width, coord_t height) {
- if (!(gc = (GConsoleObject *)_gwindowInit((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject), &consoleVMT, GWIN_FLG_VISIBLE)))
+ if (!(gc = (GConsoleObject *)_gwindowCreate((GWindowObject *)gc, x, y, width, height, sizeof(GConsoleObject), &consoleVMT, GWIN_FLG_VISIBLE)))
return 0;
#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM
gc->stream.vmt = &GWindowConsoleVMT;
diff --git a/src/gwin/graph.c b/src/gwin/graph.c
index 393297e7..264c0c2c 100644
--- a/src/gwin/graph.c
+++ b/src/gwin/graph.c
@@ -165,7 +165,7 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t
}
GHandle gwinCreateGraph(GGraphObject *gg, coord_t x, coord_t y, coord_t width, coord_t height) {
- if (!(gg = (GGraphObject *)_gwindowInit((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject), &graphVMT, GWIN_FLG_VISIBLE)))
+ if (!(gg = (GGraphObject *)_gwindowCreate((GWindowObject *)gg, x, y, width, height, sizeof(GGraphObject), &graphVMT, GWIN_FLG_VISIBLE)))
return 0;
gg->xorigin = gg->yorigin = 0;
gg->lastx = gg->lasty = 0;
diff --git a/src/gwin/gwidget.c b/src/gwin/gwidget.c
index 773a715d..ee7986d1 100644
--- a/src/gwin/gwidget.c
+++ b/src/gwin/gwidget.c
@@ -13,23 +13,25 @@
#include "gwin/class_gwin.h"
+/* Our listener for events for widgets */
+static GListener gl;
+
/* 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)
+/* Process an event */
+static void gwidgetEvent(void *param, GEvent *pe) {
+ #define gh QItem2GWindow(qi)
#define pme ((GEventMouse *)pe)
#define pte ((GEventToggle *)pe)
#define pde ((GEventDial *)pe)
- // check if widget is disabled
- if ((gw->g.flags & (GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
- return;
-
- // Process via AllEvents() if it is defined
- if (wvmt->AllEvents)
- wvmt->AllEvents(gw, pe);
+ const gfxQueueASyncItem * qi;
+ #if GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
+ uint16_t role;
+ #endif
+ (void) param;
// Process various events
switch (pe->type) {
@@ -37,76 +39,179 @@ static void gwidgetCallback(void *param, GEvent *pe) {
#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->last_buttons & ~pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) {
- 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->last_buttons & pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
- && 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);
+ // Cycle through all windows
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+
+ // check if it a widget that is enabled and visible
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
+ continue;
+
+ // Are we captured?
+ if ((gw->g.flags & GWIN_FLG_MOUSECAPTURE)) {
+ if ((pme->last_buttons & ~pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)) {
+ gw->g.flags &= ~GWIN_FLG_MOUSECAPTURE;
+ if (wvmt->MouseUp)
+ wvmt->MouseUp(gw, pme->x - gw->g.x, pme->y - gw->g.y);
+ } 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->last_buttons & pme->current_buttons & GINPUT_MOUSE_BTN_LEFT)
+ && 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);
+ // Cycle through all windows
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+
+ // check if it a widget that is enabled and visible
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
+ 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:
- if (wvmt->DialMove)
- wvmt->DialMove(gw, pde->instance, pde->value);
+ // Cycle through all windows
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+
+ // check if it a widget that is enabled and visible
+ if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))
+ 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 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 *)_gwindowInit((GWindowObject *)pgw, x, y, width, height, size, (const gwinVMT *)vmt, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED)))
+#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
+ static GHandle FindToggleUser(uint16_t instance) {
+ #define gh QItem2GWindow(qi)
+ const gfxQueueASyncItem * qi;
+ uint16_t role;
+
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+ 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;
+ #undef gh
+ }
+#endif
+
+#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+ static GHandle FindDialUser(uint16_t instance) {
+ #define gh QItem2GWindow(qi)
+ const gfxQueueASyncItem * qi;
+ uint16_t role;
+
+ for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) {
+ 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;
+ #undef gh
+ }
+#endif
+
+void _gwidgetInit(void) {
+ geventListenerInit(&gl);
+ geventRegisterCallback(&gl, gwidgetEvent, 0);
+}
+
+GHandle _gwidgetCreate(GWidgetObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwidgetVMT *vmt) {
+ if (!(pgw = (GWidgetObject *)_gwindowCreate((GWindowObject *)pgw, x, y, width, height, size, (const gwinVMT *)vmt, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED)))
return 0;
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 GFX_USE_GINPUT && (GINPUT_NEED_TOGGLE || GINPUT_NEED_DIAL)
+ uint16_t role, instance;
+ #endif
+
// 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);
+
+ #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);
}
@@ -183,76 +288,89 @@ void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param) {
_gwidgetRedraw(gh);
}
-bool_t gwinAttachListener(GHandle gh, GListener *pl, unsigned flags) {
- if (!(gh->flags & GWIN_FLG_WIDGET))
- return FALSE;
-
- return geventAttachSource(pl, (GSourceHandle)gh, flags);
+bool_t gwinAttachListener(GListener *pl) {
+ return geventAttachSource(pl, GWIDGET_SOURCE, 0);
}
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
- bool_t gwinAttachMouse(GHandle gh, uint16_t instance) {
+ bool_t gwinAttachMouse(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);
+ return geventAttachSource(&gl, gsh, GLISTEN_MOUSEMETA|GLISTEN_MOUSEDOWNMOVES);
}
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
bool_t gwinAttachToggle(GHandle gh, uint16_t role, uint16_t instance) {
GSourceHandle gsh;
- unsigned flags;
+ uint16_t oi;
+ // Is this a widget
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)
+ // Is the role valid
+ if (role >= wvmt->toggleroles)
return FALSE;
+ // Is this a valid device
if (!(gsh = ginputGetToggle(instance)))
return FALSE;
- if (wvmt->AssignToggle && !wvmt->AssignToggle(gw, role, instance))
- return FALSE;
+ // Is this already done?
+ oi = wvmt->ToggleGet(gw, role);
+ if (instance == oi)
+ return TRUE;
- return geventAttachSource(&gw->listener, gsh, flags);
+ // 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);
}
#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;
- if (!wvmt->DialMove)
+ // Is the role valid
+ if (role >= wvmt->dialroles)
return FALSE;
+ // Is this a valid device
if (!(gsh = ginputGetDial(instance)))
return FALSE;
- if (wvmt->AssignDial && !wvmt->AssignDial(gw, role, instance))
- return FALSE;
+ // Is this already done?
+ oi = wvmt->DialGet(gw, role);
+ if (instance == oi)
+ return TRUE;
- return geventAttachSource(&gw->listener, gsh, 0);
+ // 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
#endif /* GFX_USE_GWIN && GWIN_NEED_WIDGET */
/** @} */
-
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
index 3e790d38..98e61c52 100644
--- a/src/gwin/gwin.c
+++ b/src/gwin/gwin.c
@@ -70,6 +70,11 @@ static color_t defaultBgColor = Black;
*-----------------------------------------------*/
void _gwinInit(void) {
+ #if GWIN_NEED_WIDGET
+ extern void _gwidgetInit(void);
+
+ _gwidgetInit();
+ #endif
#if GWIN_NEED_WINDOWMANAGER
gfxQueueASyncInit(&_GWINList);
cwm = &GNullWindowManager;
@@ -79,7 +84,7 @@ void _gwinInit(void) {
// Internal routine for use by GWIN components only
// Initialise a window creating it dynamically if required.
-GHandle _gwindowInit(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwinVMT *vmt, uint16_t flags) {
+GHandle _gwindowCreate(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height, size_t size, const gwinVMT *vmt, uint16_t flags) {
// Allocate the structure if necessary
if (!pgw) {
if (!(pgw = (GWindowObject *)gfxAlloc(size)))
@@ -146,7 +151,7 @@ void gwinSetDefaultBgColor(color_t bgclr) {
*-----------------------------------------------*/
GHandle gwinCreateWindow(GWindowObject *pgw, coord_t x, coord_t y, coord_t width, coord_t height) {
- return _gwindowInit(pgw, x, y, width, height, sizeof(GWindowObject), &basegwinVMT, GWIN_FLG_VISIBLE);
+ return _gwindowCreate(pgw, x, y, width, height, sizeof(GWindowObject), &basegwinVMT, GWIN_FLG_VISIBLE);
}
void gwinDestroy(GHandle gh) {
diff --git a/src/gwin/slider.c b/src/gwin/slider.c
index 1a1855a9..343973a2 100644
--- a/src/gwin/slider.c
+++ b/src/gwin/slider.c
@@ -25,10 +25,19 @@
#define GWIN_SLIDER_DEAD_BAND 5
#endif
+#ifndef GWIN_SLIDER_TOGGLE_INC
+ #define GWIN_SLIDER_TOGGLE_INC 20 // How many toggles to go from minimum to maximum
+#endif
+
// Prototypes for slider VMT functions
static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y);
static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y);
-static void DialMove(GWidgetObject *gw, uint16_t instance, uint16_t value);
+static void ToggleOn(GWidgetObject *gw, uint16_t role);
+static void DialMove(GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max);
+static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance);
+static void DialAssign(GWidgetObject *gw, uint16_t role, uint16_t instance);
+static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role);
+static uint16_t DialGet(GWidgetObject *gw, uint16_t role);
// The button VMT table
static const gwidgetVMT sliderVMT = {
@@ -38,16 +47,25 @@ static const gwidgetVMT sliderVMT = {
_gwidgetRedraw, // The redraw routine
0, // The after-clear routine
},
- gwinSliderDraw_Std, // The default drawing routine
- MouseMove, // Process mouse down events (AS MOUSEMOVE)
- MouseUp, // Process mouse up events
- MouseMove, // Process mouse move events
- 0, // Process toggle off events (NOT USED)
- 0, // Process toggle on events (NOT USED)
- DialMove, // Process dial move events
- 0, // Process all events (NOT USED)
- 0, // AssignToggle (NOT USED)
- 0, // AssignDial (NOT USED)
+ gwinSliderDraw_Std, // The default drawing routine
+ {
+ 0, // Process mouse down events (NOT USED)
+ MouseUp, // Process mouse up events
+ MouseMove, // Process mouse move events
+ },
+ {
+ 2, // 1 toggle role
+ ToggleAssign, // Assign Toggles
+ ToggleGet, // Get Toggles
+ 0, // Process toggle off events (NOT USED)
+ ToggleOn, // Process toggle on events
+ },
+ {
+ 1, // 1 dial roles
+ DialAssign, // Assign Dials
+ DialGet, // Get Dials
+ DialMove, // Process dial move events
+ }
};
static const GSliderColors GSliderDefaultColors = {
@@ -66,7 +84,7 @@ static void SendSliderEvent(GWidgetObject *gw) {
// Trigger a GWIN Button Event
psl = 0;
- while ((psl = geventGetSourceListener((GSourceHandle)gw, psl))) {
+ while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
if (!(pe = geventGetEventBuffer(psl)))
continue;
pse->type = GEVENT_GWIN_SLIDER;
@@ -75,7 +93,7 @@ static void SendSliderEvent(GWidgetObject *gw) {
geventSendEvent(psl);
}
- #undef pbe
+ #undef pse
}
// Reset the display position back to the value predicted by the saved slider position
@@ -159,13 +177,28 @@ static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y) {
#undef gsw
}
+// A toggle on has occurred
+static void ToggleOn(GWidgetObject *gw, uint16_t role) {
+ #define gsw ((GSliderObject *)gw)
+
+ if (role) {
+ gwinSetSliderPosition((GHandle)gw, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
+ SendSliderEvent(gw);
+ } else {
+ gwinSetSliderPosition((GHandle)gw, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
+ SendSliderEvent(gw);
+ }
+ #undef gsw
+}
+
// A dial move event
-static void DialMove(GWidgetObject *gw, uint16_t instance, uint16_t value) {
+static void DialMove(GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max) {
#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
#define gsw ((GSliderObject *)gw)
+ (void) role;
// Set the new position
- gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/ginputGetDialRange(instance) + gsw->min);
+ gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/max + gsw->min);
ResetDisplayPos(gsw);
gwinDraw(&gw->g);
@@ -174,13 +207,37 @@ static void DialMove(GWidgetObject *gw, uint16_t instance, uint16_t value) {
SendSliderEvent(gw);
#undef gsw
#else
- (void)gw; (void)instance; (void)value;
+ (void)gw; (void)role; (void)value; (void)max;
#endif
}
+static void ToggleAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
+ if (role)
+ ((GSliderObject *)gw)->t_up = instance;
+ else
+ ((GSliderObject *)gw)->t_dn = instance;
+}
+
+static uint16_t ToggleGet(GWidgetObject *gw, uint16_t role) {
+ return role ? ((GSliderObject *)gw)->t_up : ((GSliderObject *)gw)->t_dn;
+}
+
+static void DialAssign(GWidgetObject *gw, uint16_t role, uint16_t instance) {
+ (void) role;
+ ((GSliderObject *)gw)->dial = instance;
+}
+
+static uint16_t DialGet(GWidgetObject *gw, uint16_t role) {
+ (void) role;
+ return ((GSliderObject *)gw)->dial;
+}
+
GHandle gwinCreateSlider(GSliderObject *gs, coord_t x, coord_t y, coord_t width, coord_t height) {
- if (!(gs = (GSliderObject *)_gwidgetInit((GWidgetObject *)gs, x, y, width, height, sizeof(GSliderObject), &sliderVMT)))
+ if (!(gs = (GSliderObject *)_gwidgetCreate((GWidgetObject *)gs, x, y, width, height, sizeof(GSliderObject), &sliderVMT)))
return 0;
+ gs->t_dn = (uint16_t) -1;
+ gs->t_up = (uint16_t) -1;
+ gs->dial = (uint16_t) -1;
gs->c = GSliderDefaultColors;
gs->min = 0;
gs->max = 100;