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