1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** GUIX Component */
16 /** */
17 /** Radial Slider Management (Slider) */
18 /** */
19 /**************************************************************************/
20
21 #define GX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "gx_api.h"
27 #include "gx_widget.h"
28 #include "gx_utility.h"
29 #include "gx_system.h"
30 #include "gx_radial_slider.h"
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _gx_radial_slider_pen_down_event_process PORTABLE C */
37 /* 6.1.4 */
38 /* AUTHOR */
39 /* */
40 /* Kenneth Maxwell, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This service processes pen down event for radial slider. */
45 /* */
46 /* INPUT */
47 /* */
48 /* slider Radial slider control block */
49 /* event_ptr Pointer to event to process */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* status Completion status */
54 /* */
55 /* CALLS */
56 /* */
57 /* _gx_radial_slider_needle_rectangle_calculate */
58 /* Calcualte needle bounding */
59 /* rectangle */
60 /* _gx_utility_rectangle_point_detect Test is a point inside a */
61 /* rectangle */
62 /* _gx_utility_math_sqrt Compute sqrt value */
63 /* _gx_system_input_capture Direct all inputs to the */
64 /* specified widget */
65 /* */
66 /* CALLED BY */
67 /* */
68 /* _gx_radial_slider_event_process */
69 /* */
70 /* RELEASE HISTORY */
71 /* */
72 /* DATE NAME DESCRIPTION */
73 /* */
74 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
75 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
76 /* resulting in version 6.1 */
77 /* 02-02-2021 Kenneth Maxwell Modified comment(s), */
78 /* renamed */
79 /* GX_STATUS_TRACKING_START to */
80 /* GX_STATUS_TRACKING_PEN, */
81 /* resulting in version 6.1.4 */
82 /* */
83 /**************************************************************************/
_gx_radial_slider_pen_down_event_process(GX_RADIAL_SLIDER * slider,GX_EVENT * event_ptr)84 static UINT _gx_radial_slider_pen_down_event_process(GX_RADIAL_SLIDER *slider, GX_EVENT *event_ptr)
85 {
86 INT xpos;
87 INT ypos;
88 INT dist;
89 GX_RADIAL_SLIDER_INFO *info = &slider -> gx_radial_slider_info;
90 GX_POINT *point;
91 GX_RECTANGLE rectangle;
92
93 if ((slider -> gx_widget_style & GX_STYLE_ENABLED) &&
94 (slider -> gx_widget_status & GX_STATUS_ANIMATION_NONE))
95 {
96 point = &event_ptr -> gx_event_payload.gx_event_pointdata;
97
98 /* Record pen down point. */
99 slider -> gx_radial_slider_pendown_point = *point;
100
101 /* Get current needle bounding rectangle. */
102 _gx_radial_slider_needle_rectangle_calculate(slider, &rectangle);
103
104 /* Check if click point is inside needle area. */
105 if (_gx_utility_rectangle_point_detect(&rectangle, *point))
106 {
107 slider -> gx_widget_status |= GX_STATUS_TRACKING_PEN;
108
109 _gx_system_input_capture((GX_WIDGET *)slider);
110 }
111 else
112 {
113 /* Check if the click down point is inside tracking area. */
114 xpos = point -> gx_point_x - slider -> gx_widget_size.gx_rectangle_left;
115 ypos = point -> gx_point_y - slider -> gx_widget_size.gx_rectangle_top;
116
117
118 /* Calculate the distacnce from click point to tracking center. */
119 dist = (INT)_gx_utility_math_sqrt((UINT)((xpos - info -> gx_radial_slider_info_xcenter) * (xpos - info -> gx_radial_slider_info_xcenter) +
120 (ypos - info -> gx_radial_slider_info_ycenter) * (ypos - info -> gx_radial_slider_info_ycenter)));
121
122 if ((info -> gx_radial_slider_info_radius - info -> gx_radial_slider_info_track_width / 2 <= dist) &&
123 (dist <= info -> gx_radial_slider_info_radius + info -> gx_radial_slider_info_track_width / 2))
124 {
125 /* Click point is inside tracking area. */
126 _gx_system_input_capture((GX_WIDGET *)slider);
127 }
128 }
129 }
130 else
131 {
132 _gx_widget_event_to_parent((GX_WIDGET *)slider, event_ptr);
133 }
134
135 return GX_SUCCESS;
136 }
137
138 /**************************************************************************/
139 /* */
140 /* FUNCTION RELEASE */
141 /* */
142 /* _gx_radial_slider_pen_drag_event_process PORTABLE C */
143 /* 6.1.4 */
144 /* AUTHOR */
145 /* */
146 /* Kenneth Maxwell, Microsoft Corporation */
147 /* */
148 /* DESCRIPTION */
149 /* */
150 /* This service processes pen drag event for radial slider. */
151 /* */
152 /* INPUT */
153 /* */
154 /* slider Radial slider control block */
155 /* event_ptr Pointer to event process */
156 /* */
157 /* OUTPUT */
158 /* */
159 /* status Completion status */
160 /* */
161 /* CALLS */
162 /* */
163 /* _gx_radial_slider_value_calculate Calculate needle value */
164 /* according to point value */
165 /* _gx_system_dirty_mark Mark widget as dirty */
166 /* */
167 /* CALLED BY */
168 /* */
169 /* _gx_radial_slider_event_process */
170 /* */
171 /* RELEASE HISTORY */
172 /* */
173 /* DATE NAME DESCRIPTION */
174 /* */
175 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
176 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
177 /* resulting in version 6.1 */
178 /* 02-02-2021 Kenneth Maxwell Modified comment(s), */
179 /* renamed */
180 /* GX_STATUS_TRACKING_START to */
181 /* GX_STATUS_TRACKING_PEN, */
182 /* resulting in version 6.1.4 */
183 /* */
184 /**************************************************************************/
_gx_radial_slider_pen_drag_event_process(GX_RADIAL_SLIDER * slider,GX_EVENT * event_ptr)185 static UINT _gx_radial_slider_pen_drag_event_process(GX_RADIAL_SLIDER *slider, GX_EVENT *event_ptr)
186 {
187 GX_VALUE new_value;
188 GX_VALUE previous_value;
189 GX_RADIAL_SLIDER_INFO *info = &slider -> gx_radial_slider_info;
190 GX_BOOL update = GX_FALSE;
191
192 /* move my needle */
193 if (slider -> gx_widget_status & GX_STATUS_TRACKING_PEN)
194 {
195 /* Calcualte new slider value. */
196 _gx_radial_slider_angle_calculate(slider, event_ptr -> gx_event_payload.gx_event_pointdata, &new_value);
197
198 /* Check if the new value is inside valide range. */
199 if ((new_value >= info -> gx_radial_slider_info_min_angle) &&
200 (new_value <= info -> gx_radial_slider_info_max_angle))
201 {
202 /* Calculate previous value. */
203 _gx_radial_slider_angle_calculate(slider, slider -> gx_radial_slider_pendown_point, &previous_value);
204
205 if ((previous_value < new_value) && ((new_value - previous_value) < 180))
206 {
207 //anti-clockwise
208 if (info -> gx_radial_slider_info_current_angle < new_value)
209 {
210 update = GX_TRUE;
211 }
212 }
213 else if (previous_value > new_value)
214 {
215 //clockwise
216 if (info -> gx_radial_slider_info_current_angle > new_value)
217 {
218 update = GX_TRUE;
219 }
220 }
221
222 if (update)
223 {
224 _gx_radial_slider_angle_set(slider, new_value);
225 }
226 }
227
228 slider -> gx_radial_slider_pendown_point = event_ptr -> gx_event_payload.gx_event_pointdata;
229 }
230 else
231 {
232 _gx_widget_event_to_parent((GX_WIDGET *)slider, event_ptr);
233 }
234
235 return GX_SUCCESS;
236 }
237
238 /**************************************************************************/
239 /* */
240 /* FUNCTION RELEASE */
241 /* */
242 /* _gx_radial_slider_pen_up_event_process PORTABLE C */
243 /* 6.1.4 */
244 /* AUTHOR */
245 /* */
246 /* Kenneth Maxwell, Microsoft Corporation */
247 /* */
248 /* DESCRIPTION */
249 /* */
250 /* This service processes pen up event for radial slider. */
251 /* */
252 /* INPUT */
253 /* */
254 /* slider Radial slider control block */
255 /* event_ptr Pointer to event process */
256 /* */
257 /* OUTPUT */
258 /* */
259 /* status Completion status */
260 /* */
261 /* CALLS */
262 /* */
263 /* _gx_system_input_release Release previously captured */
264 /* input events */
265 /* Process pen down event */
266 /* _gx_radial_slider_value_calculate Calculate needle value */
267 /* according to point value */
268 /* _gx_radial_slider_value_set Set new slider value */
269 /* _gx_widget_event_process Default widget event process */
270 /* _gx_radial_slider_animation_update Update needle position */
271 /* */
272 /* CALLED BY */
273 /* */
274 /* _gx_radial_slider_event_process */
275 /* */
276 /* RELEASE HISTORY */
277 /* */
278 /* DATE NAME DESCRIPTION */
279 /* */
280 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
281 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
282 /* resulting in version 6.1 */
283 /* 02-02-2021 Kenneth Maxwell Modified comment(s), */
284 /* renamed */
285 /* GX_STATUS_TRACKING_START to */
286 /* GX_STATUS_TRACKING_PEN, */
287 /* resulting in version 6.1.4 */
288 /* */
289 /**************************************************************************/
_gx_radial_slider_pen_up_event_process(GX_RADIAL_SLIDER * slider,GX_EVENT * event_ptr)290 static UINT _gx_radial_slider_pen_up_event_process(GX_RADIAL_SLIDER *slider, GX_EVENT *event_ptr)
291 {
292 GX_RADIAL_SLIDER_INFO *info = &slider -> gx_radial_slider_info;
293 GX_VALUE new_value;
294 GX_POINT *point;
295
296 if (slider -> gx_widget_status & GX_STATUS_OWNS_INPUT)
297 {
298 _gx_system_input_release((GX_WIDGET *)slider);
299
300 point = &event_ptr -> gx_event_payload.gx_event_pointdata;
301
302 if (slider -> gx_widget_status & GX_STATUS_TRACKING_PEN ||
303 ((GX_ABS(point -> gx_point_x - slider -> gx_radial_slider_pendown_point.gx_point_x) < 5) &&
304 (GX_ABS(point -> gx_point_y - slider -> gx_radial_slider_pendown_point.gx_point_y) < 5)))
305 {
306 if (slider -> gx_widget_status & GX_STATUS_TRACKING_PEN)
307 {
308 new_value = info -> gx_radial_slider_info_current_angle;
309 }
310 else
311 {
312 /* Calculate new angle value with current point. */
313 _gx_radial_slider_angle_calculate(slider, *point, &new_value);
314 }
315
316 _gx_radial_slider_anchor_angle_calculate(slider, &new_value);
317 _gx_radial_slider_animation_start(slider, new_value);
318 }
319
320 slider -> gx_widget_status |= GX_STATUS_ANIMATION_NONE;
321 slider -> gx_widget_status &= ~GX_STATUS_TRACKING_PEN;
322 }
323 else
324 {
325 _gx_widget_event_to_parent((GX_WIDGET *)slider, event_ptr);
326 }
327
328 return GX_SUCCESS;
329 }
330
331 /**************************************************************************/
332 /* */
333 /* FUNCTION RELEASE */
334 /* */
335 /* _gx_radial_slider_event_process PORTABLE C */
336 /* 6.1 */
337 /* AUTHOR */
338 /* */
339 /* Kenneth Maxwell, Microsoft Corporation */
340 /* */
341 /* DESCRIPTION */
342 /* */
343 /* This service processes a radial slider event. */
344 /* */
345 /* INPUT */
346 /* */
347 /* slider Radial slider control block */
348 /* event_ptr Pointer to event process */
349 /* */
350 /* OUTPUT */
351 /* */
352 /* status Completion status */
353 /* */
354 /* CALLS */
355 /* */
356 /* _gx_radial_slider_pen_down_event_process */
357 /* Process pen down event */
358 /* _gx_radial_slider_pen_drag_event_process */
359 /* Process pen drag event */
360 /* _gx_radial_slider_pen_up_event_process */
361 /* Process pen up event */
362 /* _gx_widget_event_process Default widget event process */
363 /* _gx_radial_slider_animation_update Update needle position */
364 /* */
365 /* CALLED BY */
366 /* */
367 /* Application Code */
368 /* GUIX Internal Code */
369 /* */
370 /* RELEASE HISTORY */
371 /* */
372 /* DATE NAME DESCRIPTION */
373 /* */
374 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
375 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
376 /* resulting in version 6.1 */
377 /* */
378 /**************************************************************************/
_gx_radial_slider_event_process(GX_RADIAL_SLIDER * slider,GX_EVENT * event_ptr)379 UINT _gx_radial_slider_event_process(GX_RADIAL_SLIDER *slider, GX_EVENT *event_ptr)
380 {
381 switch (event_ptr -> gx_event_type)
382 {
383 case GX_EVENT_PEN_DOWN:
384 _gx_radial_slider_pen_down_event_process(slider, event_ptr);
385 break;
386
387 case GX_EVENT_PEN_DRAG:
388 _gx_radial_slider_pen_drag_event_process(slider, event_ptr);
389 break;
390
391 case GX_EVENT_PEN_UP:
392 _gx_radial_slider_pen_up_event_process(slider, event_ptr);
393 break;
394
395 case GX_EVENT_TIMER:
396 if (event_ptr -> gx_event_payload.gx_event_timer_id == GX_RADIAL_SLIDER_TIMER)
397 {
398 /* Update needle position. */
399 _gx_radial_slider_animation_update(slider);
400 }
401 else
402 {
403 /* Process default event process. */
404 _gx_widget_event_process((GX_WIDGET *)slider, event_ptr);
405 }
406 break;
407
408 default:
409 /* Process default event process. */
410 return _gx_widget_event_process((GX_WIDGET *)slider, event_ptr);
411 }
412
413 return GX_SUCCESS;
414 }
415
416