1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** GUIX Component                                                        */
17 /**                                                                       */
18 /**   Tree View Management (View)                                         */
19 /**                                                                       */
20 /**************************************************************************/
21 
22 #define GX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "gx_api.h"
28 #include "gx_tree_view.h"
29 #include "gx_widget.h"
30 #include "gx_window.h"
31 #include "gx_system.h"
32 #include "gx_utility.h"
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _tree_view_selected_detect                          PORTABLE C      */
39 /*                                                           6.1          */
40 /*  AUTHOR                                                                */
41 /*                                                                        */
42 /*    Kenneth Maxwell, Microsoft Corporation                              */
43 /*                                                                        */
44 /*  DESCRIPTION                                                           */
45 /*                                                                        */
46 /*    Internal helper function to test if a menu contain selected item.   */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    tree                                  Pointer to the tree view      */
51 /*                                            control block               */
52 /*    test_menu                             Menu for test                 */
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    status                                Completion status             */
57 /*                                                                        */
58 /*  CALLS                                                                 */
59 /*                                                                        */
60 /*    _tree_view_selected_detect            Detect if a menu contain      */
61 /*                                             selected item              */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    _gx_tree_menu_pen_down_event_process                                */
66 /*                                                                        */
67 /*  RELEASE HISTORY                                                       */
68 /*                                                                        */
69 /*    DATE              NAME                      DESCRIPTION             */
70 /*                                                                        */
71 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
72 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
73 /*                                            resulting in version 6.1    */
74 /*                                                                        */
75 /**************************************************************************/
_tree_view_selected_detect(GX_TREE_VIEW * tree,GX_MENU * test_menu)76 static GX_BOOL _tree_view_selected_detect(GX_TREE_VIEW *tree, GX_MENU *test_menu)
77 {
78 GX_MENU_LIST *list = &test_menu -> gx_menu_list;
79 GX_WIDGET    *child;
80 GX_BOOL       found = GX_FALSE;
81 
82     if (!tree -> gx_tree_view_selected)
83     {
84         return found;
85     }
86     child = list -> gx_widget_first_child;
87 
88     while (child)
89     {
90         if (child == tree -> gx_tree_view_selected)
91         {
92             found = GX_TRUE;
93             break;
94         }
95 
96         if (child -> gx_widget_type == GX_TYPE_MENU)
97         {
98             found = _tree_view_selected_detect(tree, (GX_MENU *)child);
99 
100             if (found)
101             {
102                 break;
103             }
104         }
105         child = child -> gx_widget_next;
106     }
107 
108     return found;
109 }
110 
111 /**************************************************************************/
112 /*                                                                        */
113 /*  FUNCTION                                               RELEASE        */
114 /*                                                                        */
115 /*    _gx_tree_view_item_find                             PORTABLE C      */
116 /*                                                           6.1          */
117 /*  AUTHOR                                                                */
118 /*                                                                        */
119 /*    Kenneth Maxwell, Microsoft Corporation                              */
120 /*                                                                        */
121 /*  DESCRIPTION                                                           */
122 /*                                                                        */
123 /*    Internal helper function to find a tree view item that is           */
124 /*    intersecting the specified horizontal line.                         */
125 /*                                                                        */
126 /*  INPUT                                                                 */
127 /*                                                                        */
128 /*    start                                  Widget to start searching    */
129 /*    line_y                                 Y coordinate of the          */
130 /*                                             horizontal line            */
131 /*    returned_item                          Pointer to retrieved item    */
132 /*                                                                        */
133 /*  OUTPUT                                                                */
134 /*                                                                        */
135 /*    status                                Completion status             */
136 /*                                                                        */
137 /*  CALLS                                                                 */
138 /*                                                                        */
139 /*    _gx_widget_first_client_child_get     Get the first client child    */
140 /*    _gx_widget_next_client_child_get      Get the next client child     */
141 /*    _gx_tree_view_item_find               Find tree view item with test */
142 /*                                            point                       */
143 /*                                                                        */
144 /*  CALLED BY                                                             */
145 /*                                                                        */
146 /*    _gx_tree_menu_pen_down_event_process                                */
147 /*                                                                        */
148 /*  RELEASE HISTORY                                                       */
149 /*                                                                        */
150 /*    DATE              NAME                      DESCRIPTION             */
151 /*                                                                        */
152 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
153 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
154 /*                                            resulting in version 6.1    */
155 /*                                                                        */
156 /**************************************************************************/
_gx_tree_view_item_find(GX_WIDGET * start,GX_VALUE line_y,GX_WIDGET ** returned_item)157 static UINT _gx_tree_view_item_find(GX_WIDGET *start, GX_VALUE line_y, GX_WIDGET **returned_item)
158 {
159 UINT          status = GX_SUCCESS;
160 GX_WIDGET    *child;
161 GX_WIDGET    *next;
162 GX_WIDGET    *found = NULL;
163 GX_MENU_LIST *list;
164 GX_BOOL       search_child;
165 
166     child = _gx_widget_first_client_child_get((GX_WIDGET *)start);
167 
168     while (child && child -> gx_widget_type == GX_TYPE_MENU_LIST)
169     {
170         child = _gx_widget_next_client_child_get(child);
171     }
172 
173     while (child)
174     {
175         /* Pick up next client child. */
176         next = _gx_widget_next_client_child_get(child);
177 
178         while (next && next -> gx_widget_type == GX_TYPE_MENU_LIST)
179         {
180             next = _gx_widget_next_client_child_get(next);
181         }
182 
183         /* Check if the widget if intersecting the specified horizontal line. */
184         if ((line_y >= child -> gx_widget_size.gx_rectangle_top) &&
185             (line_y <= child -> gx_widget_size.gx_rectangle_bottom))
186         {
187             /* Line y is in current item. */
188             found = child;
189             break;
190         }
191 
192         search_child = GX_FALSE;
193 
194         if (next)
195         {
196             if (line_y < next -> gx_widget_size.gx_rectangle_top)
197             {
198                 search_child = GX_TRUE;
199             }
200             else if (line_y <= next -> gx_widget_size.gx_rectangle_bottom)
201             {
202                 /* Line y is inside next item. */
203                 found = next;
204                 break;
205             }
206         }
207         else
208         {
209             search_child = GX_TRUE;
210         }
211 
212         if (search_child)
213         {
214             /* Line y is before next item. */
215             if (child -> gx_widget_type == GX_TYPE_MENU)
216             {
217                 list = &((GX_MENU *)child) -> gx_menu_list;
218 
219                 if (list -> gx_widget_status & GX_STATUS_VISIBLE)
220                 {
221                     child = list -> gx_widget_first_child;
222                     continue;
223                 }
224             }
225             else
226             {
227                 /* Not found. */
228                 break;
229             }
230         }
231 
232         child = next;
233     }
234 
235     *returned_item = found;
236 
237     return status;
238 }
239 
240 /**************************************************************************/
241 /*                                                                        */
242 /*  FUNCTION                                               RELEASE        */
243 /*                                                                        */
244 /*    _gx_tree_view_root_icon_rect_get                    PORTABLE C      */
245 /*                                                           6.1          */
246 /*  AUTHOR                                                                */
247 /*                                                                        */
248 /*    Kenneth Maxwell, Microsoft Corporation                              */
249 /*                                                                        */
250 /*  DESCRIPTION                                                           */
251 /*                                                                        */
252 /*    Internal helper function to get the root icon draw area of a tree   */
253 /*    view item.                                                          */
254 /*                                                                        */
255 /*  INPUT                                                                 */
256 /*                                                                        */
257 /*    tree                                  Pointer to the tree view      */
258 /*                                            control block               */
259 /*    item                                  Pointer to the tree view item */
260 /*                                            whose root icon draw area is*/
261 /*                                            retrieved                   */
262 /*    root_rect                             Retrieved root icon draw area */
263 /*                                                                        */
264 /*  OUTPUT                                                                */
265 /*                                                                        */
266 /*    status                                Completion status             */
267 /*                                                                        */
268 /*  CALLS                                                                 */
269 /*                                                                        */
270 /*    _gx_widget_pixelmap_get               Get pixelmap by supplied ID   */
271 /*                                                                        */
272 /*  CALLED BY                                                             */
273 /*                                                                        */
274 /*    _gx_tree_menu_pen_down_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 /*                                                                        */
284 /**************************************************************************/
_gx_tree_view_root_icon_rect_get(GX_TREE_VIEW * tree,GX_WIDGET * item,GX_RECTANGLE * root_rect)285 static UINT _gx_tree_view_root_icon_rect_get(GX_TREE_VIEW *tree, GX_WIDGET *item, GX_RECTANGLE *root_rect)
286 {
287 GX_PIXELMAP *map;
288 
289     _gx_widget_pixelmap_get((GX_WIDGET *)tree, tree -> gx_tree_view_expand_pixelmap_id, &map);
290 
291     if (map)
292     {
293         root_rect -> gx_rectangle_left = (GX_VALUE)(item -> gx_widget_size.gx_rectangle_left - (tree -> gx_tree_view_indentation >> 1));
294         root_rect -> gx_rectangle_left = (GX_VALUE)(root_rect -> gx_rectangle_left - (map -> gx_pixelmap_width >> 1));
295         root_rect -> gx_rectangle_top = (GX_VALUE)(item -> gx_widget_size.gx_rectangle_top + item -> gx_widget_size.gx_rectangle_bottom - 1);
296         root_rect -> gx_rectangle_top = (GX_VALUE)(root_rect -> gx_rectangle_top >> 1);
297         root_rect -> gx_rectangle_top = (GX_VALUE)(root_rect -> gx_rectangle_top - (map -> gx_pixelmap_height >> 1));
298         root_rect -> gx_rectangle_right = (GX_VALUE)((root_rect -> gx_rectangle_left + map -> gx_pixelmap_width - 1));
299         root_rect -> gx_rectangle_bottom = (GX_VALUE)((root_rect -> gx_rectangle_top + map -> gx_pixelmap_height - 1));
300     }
301     else
302     {
303         memset(root_rect, 0, sizeof(GX_RECTANGLE));
304     }
305 
306     return GX_SUCCESS;
307 }
308 
309 /**************************************************************************/
310 /*                                                                        */
311 /*  FUNCTION                                               RELEASE        */
312 /*                                                                        */
313 /*    _gx_tree_menu_pen_down_event_process                PORTABLE C      */
314 /*                                                           6.1          */
315 /*  AUTHOR                                                                */
316 /*                                                                        */
317 /*    Kenneth Maxwell, Microsoft Corporation                              */
318 /*                                                                        */
319 /*  DESCRIPTION                                                           */
320 /*                                                                        */
321 /*    Internal helper function to process pen down event for the tree     */
322 /*    view.                                                               */
323 /*                                                                        */
324 /*  INPUT                                                                 */
325 /*                                                                        */
326 /*    tree                                  Pointer to tree view control  */
327 /*                                            block                       */
328 /*    event_ptr                             Pointer to event to process   */
329 /*                                                                        */
330 /*  OUTPUT                                                                */
331 /*                                                                        */
332 /*    status                                Completion status             */
333 /*                                                                        */
334 /*  CALLS                                                                 */
335 /*                                                                        */
336 /*    _gx_tree_view_item_find               Find tree view item with test */
337 /*                                            point                       */
338 /*    _gx_tree_view_root_icon_rect_get      Retrieve root icon rectangle  */
339 /*                                            of specified tree view item */
340 /*    _tree_view_selected_detect            Detect if a menu contain      */
341 /*                                            selected item               */
342 /*    _gx_tree_view_selected_set            Set new selected item         */
343 /*    _gx_tree_view_position                Position a tree view          */
344 /*    _gx_system_dirty_partial_add          Mark partial area of a widget */
345 /*                                            as dirty                    */
346 /*    _gx_system_top_widget_find            Find top widget that contain  */
347 /*                                            test point                  */
348 /*    _gx_utility_rectangle_point_detect    Test if the point is resides  */
349 /*                                            in the rectangle.           */
350 /*    _gx_window_event_process              Default window event process  */
351 /*                                                                        */
352 /*  CALLED BY                                                             */
353 /*                                                                        */
354 /*    _gx_tree_view_event_process                                         */
355 /*                                                                        */
356 /*  RELEASE HISTORY                                                       */
357 /*                                                                        */
358 /*    DATE              NAME                      DESCRIPTION             */
359 /*                                                                        */
360 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
361 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
362 /*                                            resulting in version 6.1    */
363 /*                                                                        */
364 /**************************************************************************/
_gx_tree_menu_pen_down_event_process(GX_TREE_VIEW * tree,GX_EVENT * event_ptr)365 static VOID _gx_tree_menu_pen_down_event_process(GX_TREE_VIEW *tree, GX_EVENT *event_ptr)
366 {
367 GX_WIDGET   *widget = (GX_WIDGET *)tree;
368 GX_WIDGET   *child = GX_NULL;
369 GX_RECTANGLE root_rect;
370 GX_POINT    *point;
371 GX_BOOL      check_selection = GX_FALSE;
372 
373     point = &event_ptr -> gx_event_payload.gx_event_pointdata;
374 
375     /* Find tree view item that is intersecting the horizontal line of the click point. */
376     _gx_tree_view_item_find((GX_WIDGET *)tree, point -> gx_point_y, &child);
377 
378     if (child && (child -> gx_widget_type == GX_TYPE_MENU) &&
379         ((GX_MENU *)child) -> gx_menu_list.gx_widget_first_child)
380     {
381         _gx_tree_view_root_icon_rect_get(tree, child, &root_rect);
382 
383         if (_gx_utility_rectangle_point_detect(&root_rect, *point))
384         {
385             if (child -> gx_widget_style & GX_STYLE_MENU_EXPANDED)
386             {
387                 child -> gx_widget_style &= (ULONG)(~GX_STYLE_MENU_EXPANDED);
388 
389                 if (_tree_view_selected_detect(tree, (GX_MENU *)child))
390                 {
391                     _gx_tree_view_selected_set(tree, child);
392                 }
393             }
394             else
395             {
396                 child -> gx_widget_style |= GX_STYLE_MENU_EXPANDED;
397             }
398 
399             _gx_tree_view_position(tree);
400 
401             root_rect = tree -> gx_window_client;
402             if (!(tree -> gx_widget_style & GX_STYLE_TREE_VIEW_SHOW_ROOT_LINES))
403             {
404                 root_rect.gx_rectangle_top = child -> gx_widget_size.gx_rectangle_top;
405             }
406 
407             _gx_system_dirty_partial_add((GX_WIDGET *)tree, &root_rect);
408         }
409         else
410         {
411             check_selection = GX_TRUE;
412         }
413     }
414     else
415     {
416         check_selection = GX_TRUE;
417         _gx_window_event_process((GX_WINDOW *)widget, event_ptr);
418     }
419 
420     if (check_selection)
421     {
422         child = _gx_system_top_widget_find((GX_WIDGET *)tree, *point, GX_STATUS_SELECTABLE);
423 
424         if (child)
425         {
426             if ((child -> gx_widget_type == GX_TYPE_MENU) ||
427                 (child -> gx_widget_parent -> gx_widget_type == GX_TYPE_MENU_LIST))
428             {
429                 _gx_tree_view_selected_set(tree, child);
430             }
431         }
432     }
433 }
434 
435 /**************************************************************************/
436 /*                                                                        */
437 /*  FUNCTION                                               RELEASE        */
438 /*                                                                        */
439 /*    _gx_tree_view_event_process                         PORTABLE C      */
440 /*                                                           6.1          */
441 /*  AUTHOR                                                                */
442 /*                                                                        */
443 /*    Kenneth Maxwell, Microsoft Corporation                              */
444 /*                                                                        */
445 /*  DESCRIPTION                                                           */
446 /*                                                                        */
447 /*    This function processes an event for the tree menu.                 */
448 /*                                                                        */
449 /*  INPUT                                                                 */
450 /*                                                                        */
451 /*    tree                                  Pointer to tree menu control  */
452 /*                                            block                       */
453 /*    event_ptr                             Pointer to event to process   */
454 /*                                                                        */
455 /*  OUTPUT                                                                */
456 /*                                                                        */
457 /*    status                                Completion status             */
458 /*                                                                        */
459 /*  CALLS                                                                 */
460 /*                                                                        */
461 /*    _gx_window_event_process              Default window event process  */
462 /*    _gx_tree_view_position                Position the children of the  */
463 /*                                            tree view                   */
464 /*    _gx_tree_menu_pen_down_event_process  Handle pen down event         */
465 /*    _gx_tree_view_scroll                  Scroll tree view client area  */
466 /*                                                                        */
467 /*  CALLED BY                                                             */
468 /*                                                                        */
469 /*    Application Code                                                    */
470 /*    GUIX Internal Code                                                  */
471 /*                                                                        */
472 /*  RELEASE HISTORY                                                       */
473 /*                                                                        */
474 /*    DATE              NAME                      DESCRIPTION             */
475 /*                                                                        */
476 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
477 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
478 /*                                            resulting in version 6.1    */
479 /*                                                                        */
480 /**************************************************************************/
_gx_tree_view_event_process(GX_TREE_VIEW * tree,GX_EVENT * event_ptr)481 UINT _gx_tree_view_event_process(GX_TREE_VIEW *tree, GX_EVENT *event_ptr)
482 {
483     switch (event_ptr -> gx_event_type)
484     {
485     case GX_EVENT_SHOW:
486         _gx_window_event_process((GX_WINDOW *)tree, event_ptr);
487         if (tree -> gx_widget_parent && (tree -> gx_widget_parent -> gx_widget_type != GX_TYPE_MENU_LIST))
488         {
489             _gx_tree_view_position(tree);
490         }
491         break;
492 
493     case GX_EVENT_PEN_DOWN:
494         _gx_tree_menu_pen_down_event_process(tree, event_ptr);
495         break;
496 
497     case GX_EVENT_VERTICAL_SCROLL:
498         _gx_tree_view_scroll(tree, 0, (GX_VALUE)(event_ptr -> gx_event_payload.gx_event_intdata[1] - event_ptr -> gx_event_payload.gx_event_intdata[0]));
499         break;
500 
501     case GX_EVENT_HORIZONTAL_SCROLL:
502         _gx_tree_view_scroll(tree, (GX_VALUE)(event_ptr -> gx_event_payload.gx_event_intdata[1] - event_ptr -> gx_event_payload.gx_event_intdata[0]), 0);
503         break;
504 
505     default:
506         return _gx_window_event_process((GX_WINDOW *)tree, event_ptr);
507     }
508 
509     return(GX_SUCCESS);
510 }
511 
512