aboutsummaryrefslogtreecommitdiffstats
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
parent777ec6af7c1b594f7b7a9cbaaf7ead90d8fb7e8f (diff)
downloaduGFX-2cb35d6815a0a12035f4792c266b688c77085620.tar.gz
uGFX-2cb35d6815a0a12035f4792c266b688c77085620.tar.bz2
uGFX-2cb35d6815a0a12035f4792c266b688c77085620.zip
Clean up GWIN Event assignment. Optimise event efficiency.
-rw-r--r--demos/modules/gadc/gwinosc.c2
-rw-r--r--demos/modules/gaudin/gwinosc.c2
-rw-r--r--demos/modules/gwin/widgets/gfxconf.h4
-rw-r--r--demos/modules/gwin/widgets/main.c70
-rw-r--r--drivers/multiple/Win32/gdisp_lld.c4
-rw-r--r--drivers/multiple/Win32/ginput_lld_toggle_config.h30
-rw-r--r--include/gfx_rules.h43
-rw-r--r--include/ginput/dial.h1
-rw-r--r--include/gqueue/gqueue.h44
-rw-r--r--include/gwin/button.h6
-rw-r--r--include/gwin/checkbox.h15
-rw-r--r--include/gwin/class_gwin.h61
-rw-r--r--include/gwin/gwidget.h14
-rw-r--r--include/gwin/gwin.h1
-rw-r--r--include/gwin/options.h4
-rw-r--r--include/gwin/slider.h24
-rw-r--r--src/ginput/dial.c2
-rw-r--r--src/gqueue/gqueue.c8
-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
25 files changed, 560 insertions, 241 deletions
diff --git a/demos/modules/gadc/gwinosc.c b/demos/modules/gadc/gwinosc.c
index 88e61334..60a08686 100644
--- a/demos/modules/gadc/gwinosc.c
+++ b/demos/modules/gadc/gwinosc.c
@@ -47,7 +47,7 @@
GHandle gwinCreateScope(GScopeObject *gs, coord_t x, coord_t y, coord_t cx, coord_t cy, uint32_t physdev, uint32_t frequency) {
/* Initialise the base class GWIN */
- if (!(gs = (GScopeObject *)_gwindowInit((GWindowObject *)gs, x, y, cx, cy, sizeof(GScopeObject))))
+ if (!(gs = (GScopeObject *)_gwindowCreate((GWindowObject *)gs, x, y, cx, cy, sizeof(GScopeObject))))
return 0;
/* Initialise the scope object members and allocate memory for buffers */
diff --git a/demos/modules/gaudin/gwinosc.c b/demos/modules/gaudin/gwinosc.c
index e90430d3..975c2c06 100644
--- a/demos/modules/gaudin/gwinosc.c
+++ b/demos/modules/gaudin/gwinosc.c
@@ -54,7 +54,7 @@
GHandle gwinCreateScope(GScopeObject *gs, coord_t x, coord_t y, coord_t cx, coord_t cy, uint16_t channel, uint32_t frequency) {
/* Initialise the base class GWIN */
- if (!(gs = (GScopeObject *)_gwindowInit((GWindowObject *)gs, x, y, cx, cy, sizeof(GScopeObject))))
+ if (!(gs = (GScopeObject *)_gwindowCreate((GWindowObject *)gs, x, y, cx, cy, sizeof(GScopeObject))))
return 0;
/* Initialise the scope object members and allocate memory for buffers */
diff --git a/demos/modules/gwin/widgets/gfxconf.h b/demos/modules/gwin/widgets/gfxconf.h
index b4574149..411d829e 100644
--- a/demos/modules/gwin/widgets/gfxconf.h
+++ b/demos/modules/gwin/widgets/gfxconf.h
@@ -51,15 +51,17 @@
#define GDISP_NEED_IMAGE_PNG FALSE
/* Features for the GWIN sub-system. */
+#define GWIN_NEED_WINDOWMANAGER TRUE
#define GWIN_NEED_CONSOLE TRUE
#define GWIN_NEED_GRAPH FALSE
+#define GWIN_NEED_WIDGET TRUE
#define GWIN_NEED_BUTTON TRUE
#define GWIN_NEED_SLIDER TRUE
#define GWIN_NEED_CHECKBOX TRUE
/* Features for the GINPUT sub-system. */
#define GINPUT_NEED_MOUSE TRUE
-#define GINPUT_NEED_TOGGLE FALSE
+#define GINPUT_NEED_TOGGLE TRUE
#define GINPUT_NEED_DIAL FALSE
#endif /* _GFXCONF_H */
diff --git a/demos/modules/gwin/widgets/main.c b/demos/modules/gwin/widgets/main.c
index 2102d3a2..1c34b9fa 100644
--- a/demos/modules/gwin/widgets/main.c
+++ b/demos/modules/gwin/widgets/main.c
@@ -49,11 +49,20 @@ int main(void) {
gfxInit();
gdispClear(White);
- // Set the font and defalt colors
+ // Set the widget defaults
gwinSetDefaultFont(gdispOpenFont("UI2"));
gwinSetDefaultColor(Black);
gwinSetDefaultBgColor(White);
+ // We want to listen for widget events
+ geventListenerInit(&gl);
+ gwinAttachListener(&gl);
+
+ // Connect the mouse
+ #if GINPUT_NEED_MOUSE
+ gwinAttachMouse(0);
+ #endif
+
// Create out gwin windows/widgets
ghConsole = gwinCreateConsole(NULL, ScrWidth/2+1, ScrHeight/2+1, ScrWidth/2-1, ScrHeight/2-1);
ghButton1 = gwinCreateButton(NULL, 0+0*(BUTTON_WIDTH+1), 0, BUTTON_WIDTH, BUTTON_HEIGHT);
@@ -84,49 +93,28 @@ int main(void) {
gwinSetText(ghCheckbox1, "C1", FALSE);
gwinSetText(ghCheckbox2, "C2", FALSE);
- // Assign the mouse and dials to the buttons & sliders etc.
-#if GINPUT_NEED_MOUSE
- gwinAttachMouse(ghButton1, 0);
- gwinAttachMouse(ghButton2, 0);
- gwinAttachMouse(ghButton3, 0);
- gwinAttachMouse(ghButton4, 0);
- gwinAttachMouse(ghSlider1, 0);
- gwinAttachMouse(ghSlider2, 0);
- gwinAttachMouse(ghSlider3, 0);
- gwinAttachMouse(ghSlider4, 0);
- gwinAttachMouse(ghCheckbox1, 0);
- gwinAttachMouse(ghCheckbox2, 0);
-#endif
-#if GINPUT_NEED_DIAL
- gwinAttachSliderDial(ghSlider1, 0);
- gwinAttachSliderDial(ghSlider3, 1);
-#endif
-
- // We want to listen for widget events
- geventListenerInit(&gl);
- gwinAttachListener(ghButton1, &gl, 0);
- gwinAttachListener(ghButton2, &gl, 0);
- gwinAttachListener(ghButton3, &gl, 0);
- gwinAttachListener(ghButton4, &gl, 0);
- gwinAttachListener(ghSlider1, &gl, 0);
- gwinAttachListener(ghSlider2, &gl, 0);
- gwinAttachListener(ghSlider3, &gl, 0);
- gwinAttachListener(ghSlider4, &gl, 0);
- gwinAttachListener(ghCheckbox1, &gl, 0);
- gwinAttachListener(ghCheckbox2, &gl, 0);
+ // Assign toggles and dials to the buttons & sliders etc.
+ #if GINPUT_NEED_TOGGLE
+ gwinAttachToggle(ghButton1, 0, 0);
+ gwinAttachToggle(ghButton2, 0, 1);
+ #endif
+ #if GINPUT_NEED_DIAL
+ gwinAttachDial(ghSlider1, 0, 0);
+ gwinAttachDial(ghSlider3, 0, 1);
+ #endif
// Draw everything on the screen
gwinClear(ghConsole);
- gwinDraw(ghButton1);
- gwinDraw(ghButton2);
- gwinDraw(ghButton3);
- gwinDraw(ghButton4);
- gwinDraw(ghSlider1);
- gwinDraw(ghSlider2);
- gwinDraw(ghSlider3);
- gwinDraw(ghSlider4);
- gwinDraw(ghCheckbox1);
- gwinDraw(ghCheckbox2);
+ gwinSetVisible(ghButton1, TRUE);
+ gwinSetVisible(ghButton2, TRUE);
+ gwinSetVisible(ghButton3, TRUE);
+ gwinSetVisible(ghButton4, TRUE);
+ gwinSetVisible(ghSlider1, TRUE);
+ gwinSetVisible(ghSlider2, TRUE);
+ gwinSetVisible(ghSlider3, TRUE);
+ gwinSetVisible(ghSlider4, TRUE);
+ gwinSetVisible(ghCheckbox1, TRUE);
+ gwinSetVisible(ghCheckbox2, TRUE);
while(1) {
// Get an Event
diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index a41954a7..b53b3632 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -119,8 +119,8 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
break;
case WM_LBUTTONUP:
#if GINPUT_NEED_TOGGLE
- if ((toggles & 0xF0)) {
- toggles &= 0x0F;
+ if ((toggles & 0x0F)) {
+ toggles &= ~0x0F;
rect.left = 0;
rect.right = wWidth;
rect.top = wHeight;
diff --git a/drivers/multiple/Win32/ginput_lld_toggle_config.h b/drivers/multiple/Win32/ginput_lld_toggle_config.h
index e96380d3..d487ca42 100644
--- a/drivers/multiple/Win32/ginput_lld_toggle_config.h
+++ b/drivers/multiple/Win32/ginput_lld_toggle_config.h
@@ -1,9 +1,9 @@
-/*
- * 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
- */
+/*
+ * 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
+ */
/**
* @file drivers/multiple/Win32/ginput_lld_toggle_config.h
@@ -20,19 +20,19 @@
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
-#define GINPUT_TOGGLE_POLL_PERIOD TIME_INFINITE // We are interrupt driven (or polled - ether works here)
+#define GINPUT_TOGGLE_POLL_PERIOD TIME_INFINITE // We are interrupt driven (or polled - either works here)
#define GINPUT_TOGGLE_NUM_PORTS 8 // The total number of toggle inputs
#define GINPUT_TOGGLE_CONFIG_ENTRIES 1 // The total number of GToggleConfig entries
-#define GINPUT_TOGGLE_SW1 0 // Switch 1 - Toggle
-#define GINPUT_TOGGLE_SW2 1 // Switch 2 - Toggle
-#define GINPUT_TOGGLE_SW3 2 // Switch 3 - Toggle
-#define GINPUT_TOGGLE_SW4 3 // Switch 4 - Toggle
+#define GINPUT_TOGGLE_MOMENTARY1 0 // Switch 5 - Momentary
+#define GINPUT_TOGGLE_MOMENTARY2 1 // Switch 6 - Momentary
+#define GINPUT_TOGGLE_MOMENTARY3 2 // Switch 7 - Momentary
+#define GINPUT_TOGGLE_MOMENTARY4 3 // Switch 8 - Momentary
-#define GINPUT_TOGGLE_MOMENTARY1 4 // Switch 5 - Momentary
-#define GINPUT_TOGGLE_MOMENTARY2 5 // Switch 6 - Momentary
-#define GINPUT_TOGGLE_MOMENTARY3 6 // Switch 7 - Momentary
-#define GINPUT_TOGGLE_MOMENTARY4 7 // Switch 8 - Momentary
+#define GINPUT_TOGGLE_SW1 4 // Switch 1 - Toggle
+#define GINPUT_TOGGLE_SW2 5 // Switch 2 - Toggle
+#define GINPUT_TOGGLE_SW3 6 // Switch 3 - Toggle
+#define GINPUT_TOGGLE_SW4 7 // Switch 4 - Toggle
#endif /* GFX_USE_GDISP && GINPUT_NEED_TOGGLE */
diff --git a/include/gfx_rules.h b/include/gfx_rules.h
index 7e14ef9d..6c0dc756 100644
--- a/include/gfx_rules.h
+++ b/include/gfx_rules.h
@@ -46,24 +46,6 @@
#warning "GWIN: Drawing can occur outside the defined windows as GDISP_NEED_CLIP is FALSE"
#endif
#endif
- #if GWIN_NEED_WINDOWMANAGER
- #if !GFX_USE_GQUEUE || !GQUEUE_NEED_ASYNC
- #if GFX_DISPLAY_RULE_WARNINGS
- #warning "GWIN: GFX_USE_GQUEUE and GQUEUE_NEED_ASYNC is required if GWIN_NEED_WINDOWMANAGER is TRUE. It has been turned on for you."
- #endif
- #undef GFX_USE_GQUEUE
- #undef GQUEUE_NEED_ASYNC
- #define GFX_USE_GQUEUE TRUE
- #define GQUEUE_NEED_ASYNC TRUE
- #endif
- #endif
- #if GWIN_NEED_CONSOLE
- #if !GDISP_NEED_TEXT
- #error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE."
- #endif
- #endif
- #if GWIN_NEED_GRAPH
- #endif
#if GWIN_NEED_BUTTON || GWIN_NEED_SLIDER || GWIN_NEED_CHECKBOX
#if !GWIN_NEED_WIDGET
#if GFX_DISPLAY_RULE_WARNINGS
@@ -81,6 +63,13 @@
// This test also ensures that GFX_USE_GEVENT is set
#error "GWIN: GFX_USE_GINPUT (and one or more input sources) is required if GWIN_NEED_WIDGET is TRUE"
#endif
+ #if !GWIN_NEED_WINDOWMANAGER
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GWIN: GWIN_NEED_WINDOWMANAGER is required if GWIN_NEED_WIDGET is TRUE. It has been turned on for you."
+ #endif
+ #undef GWIN_NEED_WINDOWMANAGER
+ #define GWIN_NEED_WINDOWMANAGER TRUE
+ #endif
#if !GDISP_NEED_MULTITHREAD && !GDISP_NEED_ASYNC
#if GFX_DISPLAY_RULE_WARNINGS
#warning "GWIN: Either GDISP_NEED_MULTITHREAD or GDISP_NEED_ASYNC is required if GWIN_NEED_WIDGET is TRUE."
@@ -90,6 +79,24 @@
#define GDISP_NEED_MULTITHREAD TRUE
#endif
#endif
+ #if GWIN_NEED_WINDOWMANAGER
+ #if !GFX_USE_GQUEUE || !GQUEUE_NEED_ASYNC
+ #if GFX_DISPLAY_RULE_WARNINGS
+ #warning "GWIN: GFX_USE_GQUEUE and GQUEUE_NEED_ASYNC is required if GWIN_NEED_WINDOWMANAGER is TRUE. It has been turned on for you."
+ #endif
+ #undef GFX_USE_GQUEUE
+ #undef GQUEUE_NEED_ASYNC
+ #define GFX_USE_GQUEUE TRUE
+ #define GQUEUE_NEED_ASYNC TRUE
+ #endif
+ #endif
+ #if GWIN_NEED_CONSOLE
+ #if !GDISP_NEED_TEXT
+ #error "GWIN: GDISP_NEED_TEXT is required if GWIN_NEED_CONSOLE is TRUE."
+ #endif
+ #endif
+ #if GWIN_NEED_GRAPH
+ #endif
#endif
#if GFX_USE_GINPUT
diff --git a/include/ginput/dial.h b/include/ginput/dial.h
index af54952a..8b4f9d3c 100644
--- a/include/ginput/dial.h
+++ b/include/ginput/dial.h
@@ -36,6 +36,7 @@ typedef struct GEventDial_t {
GEventType type; // The type of this event (GEVENT_DIAL)
uint16_t instance; // The dial instance
uint16_t value; // The dial value
+ uint16_t maxvalue; // The maximum dial value
} GEventDial;
/*===========================================================================*/
diff --git a/include/gqueue/gqueue.h b/include/gqueue/gqueue.h
index 38c1908d..399042d9 100644
--- a/include/gqueue/gqueue.h
+++ b/include/gqueue/gqueue.h
@@ -103,7 +103,7 @@ void gfxQueueFSyncInit(gfxQueueFSync *pqueue);
/* @} */
/**
- * @brief Get an item from the head of the queue.
+ * @brief Get an item from the head of the queue (and remove it from the queue).
* @return NULL if the timeout expires before an item is available
*
* @param[in] pqueue A pointer to the queue
@@ -139,7 +139,7 @@ bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delayti
/* @} */
/**
- * @brief Pop an item from the head of the queue.
+ * @brief Pop an item from the head of the queue (and remove it from the queue).
* @detail This is exactly the same as the Get operation above.
*
* @api
@@ -220,6 +220,46 @@ bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem);
bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem);
/* @} */
+/**
+ * @brief Get the first item from the head of the queue but do not remove it from the queue.
+ * @return NULL if no item is available.
+ *
+ * @param[in] pqueue A pointer to the queue
+ *
+ * @note This call does not block.
+ * @note This can be used as the first call to iterate all the elements in the queue.
+ * @note As that item is still on the queue, it should be treated as read-only. It could
+ * also be removed from the queue at any time by another thread (thereby altering the
+ * queue item).
+ *
+ * @api
+ * @{
+ */
+#define gfxQueueASyncPeek(pqueue) ((const gfxQueueASyncItem *)((pqueue)->head))
+#define gfxQueueGSyncPeek(pqueue) ((const gfxQueueGSyncItem *)((pqueue)->head))
+#define gfxQueueFSyncPeek(pqueue) ((const gfxQueueFSyncItem *)((pqueue)->head))
+/* @} */
+
+/**
+ * @brief Get the next item in the queue (but do not remove it from the queue).
+ * @return NULL if no item is available.
+ *
+ * @param[in] pitem The previous item in the queue
+ *
+ * @note This call does not block.
+ * @note This can be used as subsequent calls to iterate all the elements in the queue.
+ * @note As that item is still on the queue, it should be treated as read-only. It could
+ * also be removed from the queue at any time by another thread (thereby altering the
+ * queue item).
+ *
+ * @api
+ * @{
+ */
+#define gfxQueueASyncNext(pitem) ((const gfxQueueASyncItem *)((pitem)->next))
+#define gfxQueueGSyncNext(pitem) ((const gfxQueueGSyncItem *)((pitem)->next))
+#define gfxQueueFSyncNext(pitem) ((const gfxQueueFSyncItem *)((pitem)->next))
+/* @} */
+
#ifdef __cplusplus
}
#endif
diff --git a/include/gwin/button.h b/include/gwin/button.h
index 53096ea3..20fd6df7 100644
--- a/include/gwin/button.h
+++ b/include/gwin/button.h
@@ -55,6 +55,7 @@ typedef struct GButtonColors {
*/
typedef struct GButtonObject_t {
GWidgetObject w;
+ uint16_t toggle;
GButtonColors c_up;
GButtonColors c_dn;
GButtonColors c_dis;
@@ -78,10 +79,13 @@ extern "C" {
* @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
* is no default font and text drawing operations will no nothing.
* @note The dimensions and position may be changed to fit on the real screen.
- * @note A button remembers its normal button state. If there is a window manager then it is automatically
+ * @note A button remembers its normal drawing state. If there is a window manager then it is automatically
* redrawn if the window is moved or its visibility state is changed.
* @note The button is initially marked as invisible so that more properties can be set before display.
* Call @p gwinSetVisible() to display it when ready.
+ * @note A button supports mouse and a toggle input.
+ * @note When assigning a toggle, only one toggle is supported. If you try to assign more than one toggle it will
+ * forget the previous toggle. When assigning a toggle the role parameter must be 0.
*
* @api
*/
diff --git a/include/gwin/checkbox.h b/include/gwin/checkbox.h
index de49fa01..6f151218 100644
--- a/include/gwin/checkbox.h
+++ b/include/gwin/checkbox.h
@@ -50,6 +50,7 @@ typedef struct GCheckboxColors {
/* A Checkbox window */
typedef struct GCheckboxObject_t {
GWidgetObject w;
+ uint16_t toggle;
GCheckboxColors c;
} GCheckboxObject;
@@ -62,10 +63,18 @@ typedef struct GCheckboxObject_t {
* @param[in] width The width of the window
* @param[in] height The height of the window
*
- * @note The drawing color gets set to White and the background drawing color to Black.
- * @note Don't forget to set the font using @p gwinSetFont() or @p gwinSetDefaultFont()
+ * @note The drawing color and the background color get set to the current defaults. If you haven't called
+ * @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
+ * @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
+ * is no default font and text drawing operations will no nothing.
* @note The dimensions and position may be changed to fit on the real screen.
- * @note The checkbox is not automatically drawn. Call gwinDraw() to draw it.
+ * @note A checkbox remembers its normal drawing state. If there is a window manager then it is automatically
+ * redrawn if the window is moved or its visibility state is changed.
+ * @note The checkbox is initially marked as invisible so that more properties can be set before display.
+ * Call @p gwinSetVisible() to display it when ready.
+ * @note A checkbox supports mouse and a toggle input.
+ * @note When assigning a toggle, only one toggle is supported. If you try to assign more than one toggle it will
+ * forget the previous toggle. When assigning a toggle the role parameter must be 0.
*
* @api
*/
diff --git a/include/gwin/class_gwin.h b/include/gwin/class_gwin.h
index 5e3cb01f..1c640c0c 100644
--- a/include/gwin/class_gwin.h
+++ b/include/gwin/class_gwin.h
@@ -52,37 +52,58 @@ typedef struct gwinVMT {
/* @} */
#if GWIN_NEED_WIDGET || defined(__DOXYGEN__)
+
+ /**
+ * @brief An toggle/dial instance is not being used
+ */
+ #define GWIDGET_NO_INSTANCE ((uint16_t)-1)
+
+ /**
+ * @brief The source handle that widgets use when sending events
+ */
+ #define GWIDGET_SOURCE ((GSourceHandle)(void *)_gwidgetCreate)
+
/**
* @brief The Virtual Method Table for a widget
* @note A widget must have a destroy function. Either use @p _gwidgetDestroy() or use your own function
* which internally calls @p _gwidgetDestroy().
* @note A widget must have a redraw function. Use @p _gwidgetRedraw().
- * @note If no MouseDown(), MouseUp() or MouseMove() function is provided, the widget will not accept being attached to a mouse input source.
- * @note If no ToggleOn() or ToggleOff() function is provided, the widget will not accept being attached to a toggle input source.
- * @note If no DialMove() function is provided, the widget will not accept being attached to a dial input source.
- * @note AssignToggle() and AssignDial() enable a widget to handle more than one toggle/dial device attached to the widget.
- * For example, a slider might accept two toggles, one for slider-down and one for slider-up.
- * The function enables the widget to record that a particular device instance performs each particular role.
- * (eg toggle0 = slider-down, toggle1 = slider-up).
+ * @note If toggleroles != 0, ToggleAssign(), ToggleGet() and one or both of ToggleOff() and ToggleOn() must be specified.
+ * @note If dialroles != 0, DialAssign(), DialGet() and DialMove() must be specified.
* @{
*/
typedef struct gwidgetVMT {
- struct gwinVMT g; // @< This is still a GWIN
- void (*DefaultDraw) (GWidgetObject *gw, void *param); // @< The default drawing routine (mandatory)
- void (*MouseDown) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse down events (optional)
- void (*MouseUp) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse up events (optional)
- void (*MouseMove) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse move events (optional)
- void (*ToggleOff) (GWidgetObject *gw, uint16_t instance); // @< Process toggle off events (optional)
- void (*ToggleOn) (GWidgetObject *gw, uint16_t instance); // @< Process toggle on events (optional)
- void (*DialMove) (GWidgetObject *gw, uint16_t instance, uint16_t value); // @< Process dial move events (optional)
- void (*AllEvents) (GWidgetObject *gw, GEvent *pe); // @< Process all events (optional)
- bool_t (*AssignToggle) (GWidgetObject *gw, uint16_t role, uint16_t instance); // @< Test the role and save the toggle instance handle (optional)
- bool_t (*AssignDial) (GWidgetObject *gw, uint16_t role, uint16_t instance); // @< Test the role and save the dial instance handle (optional)
+ struct gwinVMT g; // @< This is still a GWIN
+ void (*DefaultDraw) (GWidgetObject *gw, void *param); // @< The default drawing routine (mandatory)
+ struct {
+ void (*MouseDown) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse down events (optional)
+ void (*MouseUp) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse up events (optional)
+ void (*MouseMove) (GWidgetObject *gw, coord_t x, coord_t y); // @< Process mouse move events (optional)
+ };
+ struct {
+ uint16_t toggleroles; // @< The roles supported for toggles (0->toggleroles-1)
+ void (*ToggleAssign) (GWidgetObject *gw, uint16_t role, uint16_t instance); // @< Assign a toggle to a role (optional)
+ uint16_t (*ToggleGet) (GWidgetObject *gw, uint16_t role); // @< Return the instance for a particular role (optional)
+ void (*ToggleOff) (GWidgetObject *gw, uint16_t role); // @< Process toggle off events (optional)
+ void (*ToggleOn) (GWidgetObject *gw, uint16_t role); // @< Process toggle on events (optional)
+ };
+ struct {
+ uint16_t dialroles; // @< The roles supported for dials (0->dialroles-1)
+ void (*DialAssign) (GWidgetObject *gw, uint16_t role, uint16_t instance); // @< Test the role and save the dial instance handle (optional)
+ uint16_t (*DialGet) (GWidgetObject *gw, uint16_t role); // @< Return the instance for a particular role (optional)
+ void (*DialMove) (GWidgetObject *gw, uint16_t role, uint16_t value, uint16_t max); // @< Process dial move events (optional)
+ };
} gwidgetVMT;
/* @} */
#endif
#if GWIN_NEED_WINDOWMANAGER || defined(__DOXYGEN__)
+ #if 1 // When we know that wmq is the first element of the GWindowObject structure
+ #define QItem2GWindow(qi) ((GHandle)qi)
+ #else
+ #define QItem2GWindow(qi) ((GHandle)(((char *)(qi)) - (size_t)(&(((GWindowObject *)0)->wmq))))
+ #endif
+
// @note There is only ever one instance of each GWindowManager type
typedef struct GWindowManager {
const struct gwmVMT *vmt;
@@ -126,7 +147,7 @@ extern "C" {
*
* @notapi
*/
-GHandle _gwindowInit(GWindowObject *pgw, coord_t x, coord_t y, coord_t w, coord_t h, size_t size, const gwinVMT *vmt, uint16_t flags);
+GHandle _gwindowCreate(GWindowObject *pgw, coord_t x, coord_t y, coord_t w, coord_t h, size_t size, const gwinVMT *vmt, uint16_t flags);
#if GWIN_NEED_WIDGET || defined(__DOXYGEN__)
/**
@@ -140,7 +161,7 @@ GHandle _gwindowInit(GWindowObject *pgw, coord_t x, coord_t y, coord_t w, coord_
*
* @notapi
*/
- GHandle _gwidgetInit(GWidgetObject *pgw, coord_t x, coord_t y, coord_t w, coord_t h, size_t size, const gwidgetVMT *vmt);
+ GHandle _gwidgetCreate(GWidgetObject *pgw, coord_t x, coord_t y, coord_t w, coord_t h, size_t size, const gwidgetVMT *vmt);
/**
* @brief Destroy the Widget object
diff --git a/include/gwin/gwidget.h b/include/gwin/gwidget.h
index 21cfd4ac..a022ab13 100644
--- a/include/gwin/gwidget.h
+++ b/include/gwin/gwidget.h
@@ -46,7 +46,6 @@ typedef void (*CustomWidgetDrawFunction)(struct GWidgetObject *gw, void *param);
*/
typedef struct GWidgetObject {
GWindowObject g; // @< This is still a GWIN
- GListener listener; // @< The widget listener
const char * txt; // @< The widget text
CustomWidgetDrawFunction fnDraw; // @< The current draw function
void * fnParam; // @< A parameter for the current draw function
@@ -120,28 +119,27 @@ const char *gwinGetText(GHandle gh);
void gwinSetCustomDraw(GHandle gh, CustomWidgetDrawFunction fn, void *param);
/**
- * @brief Attach a Listener to this widget
+ * @brief Attach a Listener to listen for widget events
* @return TRUE on success
*
- * @param[in] gh The widget handle
* @param[in] pl The listener
- * @param[in] flags Flags to use for listening. For most widgets this should be 0.
*
* @api
*/
-bool_t gwinAttachListener(GHandle gh, GListener *pl, unsigned flags);
+bool_t gwinAttachListener(GListener *pl);
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
/**
- * @brief Attach a mouse to a widget
+ * @brief Set the mouse to be used to control the widgets
* @return TRUE on success
*
- * @param[in] gh The widget handle
* @param[in] instance The mouse instance
*
+ * @note Every widget uses the same mouse.
+ *
* @api
*/
- bool_t gwinAttachMouse(GHandle gh, uint16_t instance);
+ bool_t gwinAttachMouse(uint16_t instance);
#endif
#if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
diff --git a/include/gwin/gwin.h b/include/gwin/gwin.h
index d915a4f0..96d7be97 100644
--- a/include/gwin/gwin.h
+++ b/include/gwin/gwin.h
@@ -35,6 +35,7 @@
*/
typedef struct GWindowObject {
#if GWIN_NEED_WINDOWMANAGER
+ // This MUST be the first member of the struct
gfxQueueASyncItem wmq; // @< The next window (for the window manager)
#endif
const struct gwinVMT *vmt; // @< The VMT for this GWIN
diff --git a/include/gwin/options.h b/include/gwin/options.h
index 3619e075..db4ae69b 100644
--- a/include/gwin/options.h
+++ b/include/gwin/options.h
@@ -21,11 +21,11 @@
* @{
*/
/**
- * @brief Should a window manager be used.
+ * @brief Should window manager support be included
* @details Defaults to FALSE
*/
#ifndef GWIN_NEED_WINDOWMANAGER
- #define GWIN_NEED_WINDOWMANAGER FALSE
+ #define GWIN_NEED_WIDGET FALSE
#endif
/**
* @brief Should widget functions be included. Needed for any widget (eg Buttons, Sliders etc)
diff --git a/include/gwin/slider.h b/include/gwin/slider.h
index 41894305..45618114 100644
--- a/include/gwin/slider.h
+++ b/include/gwin/slider.h
@@ -45,11 +45,14 @@ typedef struct GSliderColors {
// A slider window
typedef struct GSliderObject_t {
GWidgetObject w;
- GSliderColors c;
+ uint16_t t_dn;
+ uint16_t t_up;
+ uint16_t dial;
coord_t dpos;
int min;
int max;
int pos;
+ GSliderColors c;
} GSliderObject;
#ifdef __cplusplus
@@ -65,11 +68,22 @@ extern "C" {
* @param[in] width The width of the window
* @param[in] height The height of the window
*
- * @note The drawing color gets set to White and the background drawing color to Black.
- * @note Don't forget to set the font using @p gwinSetFont() or @p gwinSetDefaultFont()
+ * @note The drawing color and the background color get set to the current defaults. If you haven't called
+ * @p gwinSetDefaultColor() or @p gwinSetDefaultBgColor() then these are White and Black respectively.
+ * @note The font gets set to the current default font. If you haven't called @p gwinSetDefaultFont() then there
+ * is no default font and text drawing operations will no nothing.
* @note The dimensions and position may be changed to fit on the real screen.
- * @note The slider is not automatically drawn. Call gwinDraw() to draw it.
- * @note Sets the slider range from 0 to 100 with an initial position of 0
+ * @note A slider remembers its normal drawing state. If there is a window manager then it is automatically
+ * redrawn if the window is moved or its visibility state is changed.
+ * @note The slider is initially marked as invisible so that more properties can be set before display.
+ * Call @p gwinSetVisible() to display it when ready.
+ * @note The initial slider range is from 0 to 100 with an initial position of 0.
+ * @note A slider supports mouse, toggle and dial input.
+ * @note When assigning a toggle, only one toggle is supported per role. If you try to assign more than
+ * one toggle to a role it will forget the previous toggle. Two roles are supported:
+ * Role 0 = toggle for down, Role 1 = toggle for up.
+ * @note When assigning a dial, only one dial is supported. If you try to assign more than one dial
+ * it will forget the previous dial. Only dial role 0 is supported.
*
* @api
*/
diff --git a/src/ginput/dial.c b/src/ginput/dial.c
index 24836910..2e52c224 100644
--- a/src/ginput/dial.c
+++ b/src/ginput/dial.c
@@ -57,6 +57,7 @@ static void DialCallback(uint16_t instance, uint16_t rawvalue) {
pe->type = GEVENT_DIAL;
pe->instance = instance;
pe->value = pds->lastvalue;
+ pe->maxvalue = pds->max;
geventSendEvent(psl);
}
}
@@ -144,6 +145,7 @@ bool_t ginputGetDialStatus(uint16_t instance, GEventDial *pdial) {
pdial->type = GEVENT_DIAL;
pdial->instance = instance;
pdial->value = DialStatus[instance].lastvalue;
+ pdial->maxvalue = DialStatus[instance].max;
return TRUE;
}
diff --git a/src/gqueue/gqueue.c b/src/gqueue/gqueue.c
index 11d10c0a..002378b3 100644
--- a/src/gqueue/gqueue.c
+++ b/src/gqueue/gqueue.c
@@ -37,6 +37,7 @@
gfxSystemLock();
if ((pi = pqueue->head))
pqueue->head = pi->next;
+ pi->next = 0;
gfxSystemUnlock();
return pi;
}
@@ -68,12 +69,14 @@
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
+ pitem->next = 0;
} else {
for(pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
pqueue->tail = pi;
+ pitem->next = 0;
break;
}
}
@@ -111,6 +114,7 @@
gfxSystemLock();
pi = pqueue->head;
pqueue->head = pi->next;
+ pi->next = 0;
gfxSytemUnlock();
return pi;
}
@@ -146,12 +150,14 @@
if (pqueue->head) {
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
+ pitem->next = 0;
} else {
for(pi = pqueue->head; pi->next; pi = pi->next) {
if (pi->next == pitem) {
pi->next = pitem->next;
if (pqueue->tail == pitem)
pqueue->tail = pi;
+ pitem->next = 0;
break;
}
}
@@ -189,6 +195,7 @@
gfxSystemLock();
pi = pqueue->head;
pqueue->head = pi->next;
+ pi->next = 0;
gfxSytemUnlock();
gfxSemSignalI(&pi->sem);
@@ -233,6 +240,7 @@
if (pqueue->head == pitem) {
pqueue->head = pitem->next;
found:
+ pitem->next = 0;
gfxSystemUnlock();
gfxSemSignal(&pitem->sem);
gfxSemDestroy(&pitem->sem);
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;