aboutsummaryrefslogtreecommitdiffstats
path: root/src/gwin
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-12-06 15:48:47 +1000
committerinmarket <andrewh@inmarket.com.au>2014-12-06 15:48:47 +1000
commit5bf2b8678a5a58059baffe780d00cd570781cea7 (patch)
tree001a4d387ecfb39b79c1863a643e36966fd39638 /src/gwin
parent4931f39a0d26f53a03834cfdc65d5e365a928652 (diff)
downloaduGFX-5bf2b8678a5a58059baffe780d00cd570781cea7.tar.gz
uGFX-5bf2b8678a5a58059baffe780d00cd570781cea7.tar.bz2
uGFX-5bf2b8678a5a58059baffe780d00cd570781cea7.zip
Extended slider events. Updated the demo to match.
Actually reduced code size :)
Diffstat (limited to 'src/gwin')
-rw-r--r--src/gwin/gwin_slider.c161
-rw-r--r--src/gwin/gwin_slider.h21
2 files changed, 122 insertions, 60 deletions
diff --git a/src/gwin/gwin_slider.c b/src/gwin/gwin_slider.c
index f1230d5a..9652e6df 100644
--- a/src/gwin/gwin_slider.c
+++ b/src/gwin/gwin_slider.c
@@ -16,6 +16,8 @@
#include "gwin_class.h"
+#define GSLIDER_FLG_EXTENDED_EVENTS (GWIN_FIRST_CONTROL_FLAG<<0)
+
#ifndef GWIN_SLIDER_DEAD_BAND
#define GWIN_SLIDER_DEAD_BAND 5
#endif
@@ -24,23 +26,58 @@
#define GWIN_SLIDER_TOGGLE_INC 20 // How many toggles to go from minimum to maximum
#endif
+// Calculate the slider position from the display position
+static int CalculatePosFromDPos(GSliderObject *gsw) {
+ // Set the new position
+ if (gsw->w.g.width < gsw->w.g.height) {
+ if (gsw->dpos > gsw->w.g.height-GWIN_SLIDER_DEAD_BAND)
+ return gsw->min;
+ if (gsw->dpos < GWIN_SLIDER_DEAD_BAND)
+ return gsw->max;
+ return ((int)(gsw->w.g.height-1-gsw->dpos-GWIN_SLIDER_DEAD_BAND))*(gsw->max-gsw->min)/(gsw->w.g.height-2*GWIN_SLIDER_DEAD_BAND) + gsw->min;
+ }
+ if (gsw->dpos > gsw->w.g.width-GWIN_SLIDER_DEAD_BAND)
+ return gsw->max;
+ if (gsw->dpos < GWIN_SLIDER_DEAD_BAND)
+ return gsw->min;
+ return ((int)(gsw->dpos-GWIN_SLIDER_DEAD_BAND))*(gsw->max-gsw->min)/(gsw->w.g.width-2*GWIN_SLIDER_DEAD_BAND) + gsw->min;
+}
+
// Send the slider event
-static void SendSliderEvent(GWidgetObject *gw) {
+static void SendSliderEvent(GSliderObject *gsw, uint8_t action) {
GSourceListener * psl;
GEvent * pe;
#define pse ((GEventGWinSlider *)pe)
- // Trigger a GWIN Button Event
+ // Does this slider want more than just SET events?
+ if (action != GSLIDER_EVENT_SET && !(gsw->w.g.flags & GSLIDER_FLG_EXTENDED_EVENTS))
+ return;
+
psl = 0;
while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
+ // Work out which action to send.
+ // This precedence order helps provide some protection against missed events.
+ // Saving it into srcflags works regardless of if a buffer is available.
+ if (psl->srcflags < action)
+ psl->srcflags = action;
+
+ // Skip sending if no buffer is available
if (!(pe = geventGetEventBuffer(psl)))
continue;
+
+ // Fill in the event
pse->type = GEVENT_GWIN_SLIDER;
- pse->gwin = (GHandle)gw;
- pse->position = ((GSliderObject *)gw)->pos;
+ pse->gwin = (GHandle)gsw;
+ pse->action = psl->srcflags;
#if GWIN_WIDGET_TAGS
- pse->tag = gw->tag;
+ pse->tag = gsw->w.tag;
#endif
+
+ // If it is a cancel or set use the defined position else use the calculated position.
+ pse->position = pse->action >= GSLIDER_EVENT_CANCEL ? gsw->pos : CalculatePosFromDPos(gsw);
+
+ // Cleanup and send.
+ psl->srcflags = 0;
geventSendEvent(psl);
}
@@ -56,76 +93,72 @@ static void ResetDisplayPos(GSliderObject *gsw) {
}
#if GINPUT_NEED_MOUSE
+ // Set the display position from the mouse position
+ static void SetDisplayPosFromMouse(GSliderObject *gsw, coord_t x, coord_t y) {
+ if (gsw->w.g.width < gsw->w.g.height)
+ gsw->dpos = y < 0 ? 0 : (y >= gsw->w.g.height ? gsw->w.g.height-1 : y);
+ else
+ gsw->dpos = x < 0 ? 0 : (x >= gsw->w.g.width ? gsw->w.g.width-1 : x);
+ }
+
// A mouse up event
static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
#define gsw ((GSliderObject *)gw)
- #define gh ((GHandle)gw)
-
- #if GWIN_BUTTON_LAZY_RELEASE
- // Clip to the slider
- if (x < 0) x = 0;
- else if (x >= gh->width) x = gh->width-1;
- if (y < 0) y = 0;
- else if (y >= gh->height) x = gh->height-1;
- #else
+
+ #if !GWIN_BUTTON_LAZY_RELEASE
// Are we over the slider?
- if (x < 0 || x >= gh->width || y < 0 || y >= gh->height) {
+ if (x < 0 || x >= gsw->w.g.width || y < 0 || y >= gsw->w.g.height) {
// No - restore the slider
ResetDisplayPos(gsw);
- _gwinUpdate(gh);
+ _gwinUpdate(&gsw->w.g);
+ SendSliderEvent(gsw, GSLIDER_EVENT_CANCEL);
return;
}
#endif
// Set the new position
- if (gh->width < gh->height) {
- if (y > gh->height-GWIN_SLIDER_DEAD_BAND)
- gsw->pos = gsw->min;
- else if (y < GWIN_SLIDER_DEAD_BAND)
- gsw->pos = gsw->max;
- else
- gsw->pos = (uint16_t)((int32_t)(gh->height-1-y-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->height-2*GWIN_SLIDER_DEAD_BAND) + gsw->min);
- } else {
- if (x > gh->width-GWIN_SLIDER_DEAD_BAND)
- gsw->pos = gsw->max;
- else if (x < GWIN_SLIDER_DEAD_BAND)
- gsw->pos = gsw->min;
- else
- gsw->pos = (uint16_t)((int32_t)(x-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->width-2*GWIN_SLIDER_DEAD_BAND) + gsw->min);
- }
+ SetDisplayPosFromMouse(gsw, x, y);
+ gsw->pos = CalculatePosFromDPos(gsw);
+ // Update the display
ResetDisplayPos(gsw);
- _gwinUpdate(gh);
+ _gwinUpdate(&gsw->w.g);
// Generate the event
- SendSliderEvent(gw);
- #undef gh
+ SendSliderEvent(gsw, GSLIDER_EVENT_SET);
+
#undef gsw
}
- // A mouse move (or mouse down) event
+ // A mouse down event
+ static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
+ #define gsw ((GSliderObject *)gw)
+
+ // Determine the display position
+ SetDisplayPosFromMouse(gsw, x, y);
+
+ // Update the display
+ _gwinUpdate(&gsw->w.g);
+
+ // Send the event
+ SendSliderEvent(gsw, GSLIDER_EVENT_START);
+
+ #undef gsw
+ }
+
+ // A mouse move event
static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y) {
#define gsw ((GSliderObject *)gw)
- // Determine the temporary display position (with range checking)
- if (gw->g.width < gw->g.height) {
- if (y < 0)
- gsw->dpos = 0;
- else if (y >= gw->g.height)
- gsw->dpos = gw->g.height-1;
- else
- gsw->dpos = y;
- } else {
- if (x < 0)
- gsw->dpos = 0;
- else if (x >= gw->g.width)
- gsw->dpos = gw->g.width-1;
- else
- gsw->dpos = x;
- }
+ // Determine the display position
+ SetDisplayPosFromMouse(gsw, x, y);
// Update the display
- _gwinUpdate(&gw->g);
+ _gwinUpdate(&gsw->w.g);
+
+ // Send the event
+ SendSliderEvent(gsw, GSLIDER_EVENT_MOVE);
+
#undef gsw
}
#endif
@@ -136,11 +169,11 @@ static void ResetDisplayPos(GSliderObject *gsw) {
#define gsw ((GSliderObject *)gw)
if (role) {
- gwinSliderSetPosition((GHandle)gw, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
- SendSliderEvent(gw);
+ gwinSliderSetPosition(&gsw->w.g, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
+ SendSliderEvent(gsw, GSLIDER_EVENT_SET);
} else {
- gwinSliderSetPosition((GHandle)gw, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
- SendSliderEvent(gw);
+ gwinSliderSetPosition(&gsw->w.g, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
+ SendSliderEvent(gsw, GSLIDER_EVENT_SET);
}
#undef gsw
}
@@ -167,10 +200,10 @@ static void ResetDisplayPos(GSliderObject *gsw) {
gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/max + gsw->min);
ResetDisplayPos(gsw);
- _gwinUpdate((GHandle)gw);
+ _gwinUpdate(&gsw->w.g);
// Generate the event
- SendSliderEvent(gw);
+ SendSliderEvent(gsw, GSLIDER_EVENT_SET);
#undef gsw
}
@@ -197,7 +230,7 @@ static const gwidgetVMT sliderVMT = {
gwinSliderDraw_Std, // The default drawing routine
#if GINPUT_NEED_MOUSE
{
- 0, // Process mouse down events (NOT USED)
+ MouseDown, // Process mouse down events
MouseUp, // Process mouse up events
MouseMove, // Process mouse move events
},
@@ -275,6 +308,16 @@ void gwinSliderSetPosition(GHandle gh, int pos) {
#undef gsw
}
+void gwinSliderSendExtendedEvents(GHandle gh, bool_t enabled) {
+ if (gh->vmt != (gwinVMT *)&sliderVMT)
+ return;
+
+ if (enabled)
+ gh->flags |= GSLIDER_FLG_EXTENDED_EVENTS;
+ else
+ gh->flags &= ~GSLIDER_FLG_EXTENDED_EVENTS;
+}
+
/*----------------------------------------------------------
* Custom Draw Routines
*----------------------------------------------------------*/
diff --git a/src/gwin/gwin_slider.h b/src/gwin/gwin_slider.h
index b88d6dfd..91a381a5 100644
--- a/src/gwin/gwin_slider.h
+++ b/src/gwin/gwin_slider.h
@@ -27,12 +27,18 @@
#define GEVENT_GWIN_SLIDER (GEVENT_GWIN_CTRL_FIRST+1)
typedef struct GEventGWinSlider {
- GEventType type; // The type of this event (GEVENT_GWIN_BUTTON)
+ GEventType type; // The type of this event (GEVENT_GWIN_SLIDER)
GHandle gwin; // The slider that is returning results
#if GWIN_WIDGET_TAGS
WidgetTag tag; // The slider tag
#endif
int position;
+
+ uint8_t action;
+ #define GSLIDER_EVENT_SET 4 /* Slider position is set. This is the only event returned by default */
+ #define GSLIDER_EVENT_CANCEL 3 /* Slider position changing has been cancelled */
+ #define GSLIDER_EVENT_START 2 /* Slider position has started changing */
+ #define GSLIDER_EVENT_MOVE 1 /* Slider position has been moved */
} GEventGWinSlider;
// There are currently no GEventGWinSlider listening flags - use 0
@@ -124,6 +130,19 @@ void gwinSliderSetPosition(GHandle gh, int pos);
#define gwinSliderGetPosition(gh) (((GSliderObject *)(gh))->pos)
/**
+ * @brief Should the slider send extended events.
+ *
+ * @param[in] gh The window handle (must be a slider window)
+ * @param[in] enabled TRUE to enable extended events, FALSE to disable them
+ *
+ * @note The slider by default will only send slider events with an action of GSLIDER_EVENT_SET.
+ * This call can be used to enable other slider action's to be sent as events
+ *
+ * @api
+ */
+void gwinSliderSendExtendedEvents(GHandle gh, bool_t enabled);
+
+/**
* @brief Some custom slider drawing routines
* @details These function may be passed to @p gwinSetCustomDraw() to get different slider drawing styles
*