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