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