Browse Source

Extended slider events. Updated the demo to match.
Actually reduced code size :)

inmarket 5 years ago
parent
commit
5bf2b8678a
4 changed files with 149 additions and 67 deletions
  1. 1 0
      demos/modules/gwin/slider/gfxconf.h
  2. 26 7
      demos/modules/gwin/slider/main.c
  3. 102 59
      src/gwin/gwin_slider.c
  4. 20 1
      src/gwin/gwin_slider.h

+ 1 - 0
demos/modules/gwin/slider/gfxconf.h

@@ -56,6 +56,7 @@
56 56
 #define GWIN_NEED_WINDOWMANAGER	TRUE
57 57
 #define GWIN_NEED_WIDGET		TRUE
58 58
 #define GWIN_NEED_SLIDER		TRUE
59
+#define GWIN_NEED_CONSOLE		TRUE
59 60
 
60 61
 /* Features for the GINPUT subsystem. */
61 62
 #define GINPUT_NEED_MOUSE		TRUE

+ 26 - 7
demos/modules/gwin/slider/main.c

@@ -30,7 +30,7 @@
30 30
 #include "gfx.h"
31 31
 
32 32
 static GListener	gl;
33
-static GHandle		ghSlider1, ghSlider2;
33
+static GHandle		ghSlider1, ghSlider2, ghConsole;
34 34
 
35 35
 static void createWidgets(void) {
36 36
 	GWidgetInit	wi;
@@ -40,16 +40,24 @@ static void createWidgets(void) {
40 40
 	wi.g.show = TRUE;
41 41
 
42 42
 	// create Slider1
43
-	wi.g.y = 10; wi.g.x = 10; wi.g.width = 200; wi.g.height = 20; wi.text = "S1";
43
+	wi.g.y = 10; wi.g.x = 10; wi.g.width = gdispGetWidth()-20; wi.g.height = 20; wi.text = "S1";
44 44
 	ghSlider1 = gwinSliderCreate(0, &wi);
45 45
 
46 46
 	// create Slider2
47
-	wi.g.y = 40; wi.g.x = 10; wi.g.width = 20; wi.g.height = 200; wi.text = "S2";
47
+	wi.g.y = 40; wi.g.x = 10; wi.g.width = 20; wi.g.height = gdispGetHeight() - 50; wi.text = "S2";
48 48
 	ghSlider2 = gwinSliderCreate(0, &wi);
49
+
50
+	// Set slider 2 to return extended events
51
+	gwinSliderSendExtendedEvents(ghSlider2, TRUE);
52
+
53
+	// Console to display slider events
54
+	wi.g.y = 40; wi.g.x = 40; wi.g.width = gdispGetWidth()-50; wi.g.height = gdispGetHeight()-50;
55
+	ghConsole = gwinConsoleCreate(0, &wi.g);
49 56
 }
50 57
 
51 58
 int main(void) {
52
-	GEvent* pe;
59
+	GEventGWinSlider *	pe;
60
+	const char *		sAction;
53 61
 
54 62
 	// Initialize the display
55 63
 	gfxInit();
@@ -61,21 +69,32 @@ int main(void) {
61 69
 
62 70
 	// create the widget
63 71
 	createWidgets();
72
+	gwinSetColor(ghConsole, Green);
73
+	gwinSetBgColor(ghConsole, White);
74
+	gwinClear(ghConsole);
64 75
 
65 76
 	// We want to listen for widget events
66 77
 	geventListenerInit(&gl);
67 78
 	gwinAttachListener(&gl);
68 79
 
69 80
 	while(1) {
70
-		// Get an Event
71
-		pe = geventEventWait(&gl, TIME_INFINITE);
81
+		// Get an Event (assume it is a slider event)
82
+		pe = (GEventGWinSlider *)geventEventWait(&gl, TIME_INFINITE);
72 83
 
73 84
 		switch(pe->type) {
74 85
 			case GEVENT_GWIN_SLIDER:
75
-				//printf("Slider %s = %d\n", gwinGetText(((GEventGWinSlider *)pe)->gwin), ((GEventGWinSlider *)pe)->position);
86
+				switch(pe->action) {
87
+				case GSLIDER_EVENT_SET:		sAction = "SET";		break;
88
+				case GSLIDER_EVENT_CANCEL:	sAction = "CANCEL";		break;
89
+				case GSLIDER_EVENT_MOVE:	sAction = "MOVE";		break;
90
+				case GSLIDER_EVENT_START:	sAction = "START";		break;
91
+				default:					sAction = "????";		break;
92
+				}
93
+				gwinPrintf(ghConsole, "Slider %s = %d%% %s\n", gwinGetText(pe->gwin), pe->position, sAction);
76 94
 				break;
77 95
 
78 96
 			default:
97
+				// Oops - not a slider event.
79 98
 				break;
80 99
 		}
81 100
 	}

+ 102 - 59
src/gwin/gwin_slider.c

@@ -16,6 +16,8 @@
16 16
 
17 17
 #include "gwin_class.h"
18 18
 
19
+#define GSLIDER_FLG_EXTENDED_EVENTS		(GWIN_FIRST_CONTROL_FLAG<<0)
20
+
19 21
 #ifndef GWIN_SLIDER_DEAD_BAND
20 22
 	#define GWIN_SLIDER_DEAD_BAND	5
21 23
 #endif
@@ -24,23 +26,58 @@
24 26
 	#define GWIN_SLIDER_TOGGLE_INC	20			// How many toggles to go from minimum to maximum
25 27
 #endif
26 28
 
29
+// Calculate the slider position from the display position
30
+static int CalculatePosFromDPos(GSliderObject *gsw) {
31
+	// Set the new position
32
+	if (gsw->w.g.width < gsw->w.g.height) {
33
+		if (gsw->dpos > gsw->w.g.height-GWIN_SLIDER_DEAD_BAND)
34
+			return gsw->min;
35
+		if (gsw->dpos < GWIN_SLIDER_DEAD_BAND)
36
+			return gsw->max;
37
+		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;
38
+	}
39
+	if (gsw->dpos > gsw->w.g.width-GWIN_SLIDER_DEAD_BAND)
40
+		return gsw->max;
41
+	if (gsw->dpos < GWIN_SLIDER_DEAD_BAND)
42
+		return gsw->min;
43
+	return ((int)(gsw->dpos-GWIN_SLIDER_DEAD_BAND))*(gsw->max-gsw->min)/(gsw->w.g.width-2*GWIN_SLIDER_DEAD_BAND) + gsw->min;
44
+}
45
+
27 46
 // Send the slider event
28
-static void SendSliderEvent(GWidgetObject *gw) {
47
+static void SendSliderEvent(GSliderObject *gsw, uint8_t action) {
29 48
 	GSourceListener	*	psl;
30 49
 	GEvent *			pe;
31 50
 	#define pse			((GEventGWinSlider *)pe)
32 51
 
33
-	// Trigger a GWIN Button Event
52
+	// Does this slider want more than just SET events?
53
+	if (action != GSLIDER_EVENT_SET && !(gsw->w.g.flags & GSLIDER_FLG_EXTENDED_EVENTS))
54
+		return;
55
+
34 56
 	psl = 0;
35 57
 	while ((psl = geventGetSourceListener(GWIDGET_SOURCE, psl))) {
58
+		// Work out which action to send.
59
+		// This precedence order helps provide some protection against missed events.
60
+		// Saving it into srcflags works regardless of if a buffer is available.
61
+		if (psl->srcflags < action)
62
+			psl->srcflags = action;
63
+
64
+		// Skip sending if no buffer is available
36 65
 		if (!(pe = geventGetEventBuffer(psl)))
37 66
 			continue;
67
+
68
+		// Fill in the event
38 69
 		pse->type = GEVENT_GWIN_SLIDER;
39
-		pse->gwin = (GHandle)gw;
40
-		pse->position = ((GSliderObject *)gw)->pos;
70
+		pse->gwin = (GHandle)gsw;
71
+		pse->action = psl->srcflags;
41 72
 		#if GWIN_WIDGET_TAGS
42
-			pse->tag = gw->tag;
73
+			pse->tag = gsw->w.tag;
43 74
 		#endif
75
+
76
+		// If it is a cancel or set use the defined position else use the calculated position.
77
+		pse->position = pse->action >= GSLIDER_EVENT_CANCEL ? gsw->pos : CalculatePosFromDPos(gsw);
78
+
79
+		// Cleanup and send.
80
+		psl->srcflags = 0;
44 81
 		geventSendEvent(psl);
45 82
 	}
46 83
 
@@ -56,76 +93,72 @@ static void ResetDisplayPos(GSliderObject *gsw) {
56 93
 }
57 94
 
58 95
 #if GINPUT_NEED_MOUSE
96
+	// Set the display position from the mouse position
97
+	static void SetDisplayPosFromMouse(GSliderObject *gsw, coord_t x, coord_t y) {
98
+		if (gsw->w.g.width < gsw->w.g.height)
99
+			gsw->dpos = y < 0 ? 0 : (y >= gsw->w.g.height ? gsw->w.g.height-1 : y);
100
+		else
101
+			gsw->dpos = x < 0 ? 0 : (x >= gsw->w.g.width ? gsw->w.g.width-1 : x);
102
+	}
103
+
59 104
 	// A mouse up event
60 105
 	static void MouseUp(GWidgetObject *gw, coord_t x, coord_t y) {
61 106
 		#define gsw		((GSliderObject *)gw)
62
-		#define gh		((GHandle)gw)
63
-
64
-		#if GWIN_BUTTON_LAZY_RELEASE
65
-			// Clip to the slider
66
-			if (x < 0) x = 0;
67
-			else if (x >= gh->width) x = gh->width-1;
68
-			if (y < 0) y = 0;
69
-			else if (y >= gh->height) x = gh->height-1;
70
-		#else
107
+
108
+		#if !GWIN_BUTTON_LAZY_RELEASE
71 109
 			// Are we over the slider?
72
-			if (x < 0 || x >= gh->width || y < 0 || y >= gh->height) {
110
+			if (x < 0 || x >= gsw->w.g.width || y < 0 || y >= gsw->w.g.height) {
73 111
 				// No - restore the slider
74 112
 				ResetDisplayPos(gsw);
75
-				_gwinUpdate(gh);
113
+				_gwinUpdate(&gsw->w.g);
114
+				SendSliderEvent(gsw, GSLIDER_EVENT_CANCEL);
76 115
 				return;
77 116
 			}
78 117
 		#endif
79 118
 
80 119
 		// Set the new position
81
-		if (gh->width < gh->height) {
82
-			if (y > gh->height-GWIN_SLIDER_DEAD_BAND)
83
-				gsw->pos = gsw->min;
84
-			else if (y < GWIN_SLIDER_DEAD_BAND)
85
-				gsw->pos = gsw->max;
86
-			else
87
-				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);
88
-		} else {
89
-			if (x > gh->width-GWIN_SLIDER_DEAD_BAND)
90
-				gsw->pos = gsw->max;
91
-			else if (x < GWIN_SLIDER_DEAD_BAND)
92
-				gsw->pos = gsw->min;
93
-			else
94
-				gsw->pos = (uint16_t)((int32_t)(x-GWIN_SLIDER_DEAD_BAND)*(gsw->max-gsw->min)/(gh->width-2*GWIN_SLIDER_DEAD_BAND) + gsw->min);
95
-		}
120
+		SetDisplayPosFromMouse(gsw, x, y);
121
+		gsw->pos = CalculatePosFromDPos(gsw);
96 122
 
123
+		// Update the display
97 124
 		ResetDisplayPos(gsw);
98
-		_gwinUpdate(gh);
125
+		_gwinUpdate(&gsw->w.g);
99 126
 
100 127
 		// Generate the event
101
-		SendSliderEvent(gw);
102
-		#undef gh
128
+		SendSliderEvent(gsw, GSLIDER_EVENT_SET);
129
+
103 130
 		#undef gsw
104 131
 	}
105 132
 
106
-	// A mouse move (or mouse down) event
133
+	// A mouse down event
134
+	static void MouseDown(GWidgetObject *gw, coord_t x, coord_t y) {
135
+		#define gsw		((GSliderObject *)gw)
136
+
137
+		// Determine the display position
138
+		SetDisplayPosFromMouse(gsw, x, y);
139
+
140
+		// Update the display
141
+		_gwinUpdate(&gsw->w.g);
142
+
143
+		// Send the event
144
+		SendSliderEvent(gsw, GSLIDER_EVENT_START);
145
+
146
+		#undef gsw
147
+	}
148
+
149
+	// A mouse move event
107 150
 	static void MouseMove(GWidgetObject *gw, coord_t x, coord_t y) {
108 151
 		#define gsw		((GSliderObject *)gw)
109 152
 
110
-		// Determine the temporary display position (with range checking)
111
-		if (gw->g.width < gw->g.height) {
112
-			if (y < 0)
113
-				gsw->dpos = 0;
114
-			else if (y >= gw->g.height)
115
-				gsw->dpos = gw->g.height-1;
116
-			else
117
-				gsw->dpos = y;
118
-		} else {
119
-			if (x < 0)
120
-				gsw->dpos = 0;
121
-			else if (x >= gw->g.width)
122
-				gsw->dpos = gw->g.width-1;
123
-			else
124
-				gsw->dpos = x;
125
-		}
153
+		// Determine the display position
154
+		SetDisplayPosFromMouse(gsw, x, y);
126 155
 
127 156
 		// Update the display
128
-		_gwinUpdate(&gw->g);
157
+		_gwinUpdate(&gsw->w.g);
158
+
159
+		// Send the event
160
+		SendSliderEvent(gsw, GSLIDER_EVENT_MOVE);
161
+
129 162
 		#undef gsw
130 163
 	}
131 164
 #endif
@@ -136,11 +169,11 @@ static void ResetDisplayPos(GSliderObject *gsw) {
136 169
 		#define gsw		((GSliderObject *)gw)
137 170
 
138 171
 		if (role) {
139
-			gwinSliderSetPosition((GHandle)gw, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
140
-			SendSliderEvent(gw);
172
+			gwinSliderSetPosition(&gsw->w.g, gsw->pos+(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
173
+			SendSliderEvent(gsw, GSLIDER_EVENT_SET);
141 174
 		} else {
142
-			gwinSliderSetPosition((GHandle)gw, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
143
-			SendSliderEvent(gw);
175
+			gwinSliderSetPosition(&gsw->w.g, gsw->pos-(gsw->max-gsw->min)/GWIN_SLIDER_TOGGLE_INC);
176
+			SendSliderEvent(gsw, GSLIDER_EVENT_SET);
144 177
 		}
145 178
 		#undef gsw
146 179
 	}
@@ -167,10 +200,10 @@ static void ResetDisplayPos(GSliderObject *gsw) {
167 200
 		gsw->pos = (uint16_t)((uint32_t)value*(gsw->max-gsw->min)/max + gsw->min);
168 201
 
169 202
 		ResetDisplayPos(gsw);
170
-		_gwinUpdate((GHandle)gw);
203
+		_gwinUpdate(&gsw->w.g);
171 204
 
172 205
 		// Generate the event
173
-		SendSliderEvent(gw);
206
+		SendSliderEvent(gsw, GSLIDER_EVENT_SET);
174 207
 		#undef gsw
175 208
 	}
176 209
 
@@ -197,7 +230,7 @@ static const gwidgetVMT sliderVMT = {
197 230
 	gwinSliderDraw_Std,			// The default drawing routine
198 231
 	#if GINPUT_NEED_MOUSE
199 232
 		{
200
-			0,						// Process mouse down events (NOT USED)
233
+			MouseDown,				// Process mouse down events
201 234
 			MouseUp,				// Process mouse up events
202 235
 			MouseMove,				// Process mouse move events
203 236
 		},
@@ -275,6 +308,16 @@ void gwinSliderSetPosition(GHandle gh, int pos) {
275 308
 	#undef gsw
276 309
 }
277 310
 
311
+void gwinSliderSendExtendedEvents(GHandle gh, bool_t enabled) {
312
+	if (gh->vmt != (gwinVMT *)&sliderVMT)
313
+		return;
314
+
315
+	if (enabled)
316
+		gh->flags |= GSLIDER_FLG_EXTENDED_EVENTS;
317
+	else
318
+		gh->flags &= ~GSLIDER_FLG_EXTENDED_EVENTS;
319
+}
320
+
278 321
 /*----------------------------------------------------------
279 322
  * Custom Draw Routines
280 323
  *----------------------------------------------------------*/

+ 20 - 1
src/gwin/gwin_slider.h

@@ -27,12 +27,18 @@
27 27
 #define GEVENT_GWIN_SLIDER		(GEVENT_GWIN_CTRL_FIRST+1)
28 28
 
29 29
 typedef struct GEventGWinSlider {
30
-	GEventType		type;				// The type of this event (GEVENT_GWIN_BUTTON)
30
+	GEventType		type;				// The type of this event (GEVENT_GWIN_SLIDER)
31 31
 	GHandle			gwin;				// The slider that is returning results
32 32
 	#if GWIN_WIDGET_TAGS
33 33
 		WidgetTag	tag;				// The slider tag
34 34
 	#endif
35 35
 	int				position;
36
+
37
+	uint8_t			action;
38
+		#define GSLIDER_EVENT_SET		4		/* Slider position is set. This is the only event returned by default   */
39
+		#define GSLIDER_EVENT_CANCEL	3		/* Slider position changing has been cancelled */
40
+		#define GSLIDER_EVENT_START		2		/* Slider position has started changing */
41
+		#define GSLIDER_EVENT_MOVE		1		/* Slider position has been moved */
36 42
 } GEventGWinSlider;
37 43
 
38 44
 // There are currently no GEventGWinSlider listening flags - use 0
@@ -123,6 +129,19 @@ void gwinSliderSetPosition(GHandle gh, int pos);
123 129
  */
124 130
 #define gwinSliderGetPosition(gh)		(((GSliderObject *)(gh))->pos)
125 131
 
132
+/**
133
+ * @brief   Should the slider send extended events.
134
+ *
135
+ * @param[in] gh		The window handle (must be a slider window)
136
+ * @param[in] enabled	TRUE to enable extended events, FALSE to disable them
137
+ *
138
+ * @note	The slider by default will only send slider events with an action of GSLIDER_EVENT_SET.
139
+ * 			This call can be used to enable other slider action's to be sent as events
140
+ *
141
+ * @api
142
+ */
143
+void gwinSliderSendExtendedEvents(GHandle gh, bool_t enabled);
144
+
126 145
 /**
127 146
  * @brief	Some custom slider drawing routines
128 147
  * @details	These function may be passed to @p gwinSetCustomDraw() to get different slider drawing styles