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 /**   Tree View Management (View)                                         */
18 /**                                                                       */
19 /**************************************************************************/
20 
21 #define GX_SOURCE_CODE
22 
23 
24 /* Include necessary system files.  */
25 
26 #include "gx_api.h"
27 #include "gx_tree_view.h"
28 #include "gx_window.h"
29 #include "gx_widget.h"
30 #include "gx_utility.h"
31 #include "gx_system.h"
32 #include "gx_context.h"
33 #include "gx_canvas.h"
34 
35 /**************************************************************************/
36 /*                                                                        */
37 /*  FUNCTION                                               RELEASE        */
38 /*                                                                        */
39 /*    _gx_tree_view_root_draw_helper                      PORTABLE C      */
40 /*                                                           6.1          */
41 /*  AUTHOR                                                                */
42 /*                                                                        */
43 /*    Kenneth Maxwell, Microsoft Corporation                              */
44 /*                                                                        */
45 /*  DESCRIPTION                                                           */
46 /*                                                                        */
47 /*    Internal helper function to draw the expand/collapse icons and root */
48 /*    lines for one level menu items.                                     */
49 /*                                                                        */
50 /*  INPUT                                                                 */
51 /*                                                                        */
52 /*    tree                                  Pointer the to tree view      */
53 /*                                            control block               */
54 /*    start                                 Pointer to start widget       */
55 /*    owner                                 Parent of the menu item       */
56 /*                                                                        */
57 /*  OUTPUT                                                                */
58 /*                                                                        */
59 /*    status                                Compoletion status            */
60 /*                                                                        */
61 /*  CALLS                                                                 */
62 /*                                                                        */
63 /*    _gx_context_pixelmap_get              Get pixelmap associate with   */
64 /*                                            the supplied id             */
65 /*    _gx_context_brush_get                 Get brush                     */
66 /*    _gx_canvas_pixelmap_draw              Draw a pixelmap to canvas     */
67 /*    _gx_canvas_line_draw                  Draw a line to canvas         */
68 /*    _gx_widget_first_client_child_get     Get the first client child    */
69 /*    _gx_widget_next_client_child_get      Get the next chilent child    */
70 /*                                                                        */
71 /*  CALLED BY                                                             */
72 /*                                                                        */
73 /*    _gx_tree_view_root_draw                                             */
74 /*                                                                        */
75 /*  RELEASE HISTORY                                                       */
76 /*                                                                        */
77 /*    DATE              NAME                      DESCRIPTION             */
78 /*                                                                        */
79 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
80 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
81 /*                                            resulting in version 6.1    */
82 /*                                                                        */
83 /**************************************************************************/
_gx_tree_view_root_draw_helper(GX_TREE_VIEW * tree,GX_WIDGET * start,GX_WIDGET * owner)84 static VOID _gx_tree_view_root_draw_helper(GX_TREE_VIEW *tree, GX_WIDGET *start, GX_WIDGET *owner)
85 {
86 GX_PIXELMAP  *map;
87 GX_PIXELMAP  *collapse_map;
88 GX_PIXELMAP  *expand_map;
89 GX_WIDGET    *child;
90 GX_MENU_LIST *list;
91 GX_VALUE      xpos;
92 GX_VALUE      ypos;
93 GX_VALUE      yend;
94 GX_VALUE      map_width = 0;
95 GX_VALUE      map_height = 0;
96 ULONG         vertical_mask = 0x80000000;
97 GX_BRUSH     *brush;
98 GX_WIDGET    *pre = GX_NULL;
99 
100     _gx_context_pixelmap_get(tree -> gx_tree_view_collapse_pixelmap_id, &collapse_map);
101     _gx_context_pixelmap_get(tree -> gx_tree_view_expand_pixelmap_id, &expand_map);
102 
103     if (collapse_map)
104     {
105         map_width = collapse_map -> gx_pixelmap_width;
106         map_height = collapse_map -> gx_pixelmap_height;
107     }
108 
109     child = _gx_widget_first_client_child_get(start);
110 
111     while (child)
112     {
113         if (child -> gx_widget_type == GX_TYPE_MENU_LIST)
114         {
115             /* Not a valid item type. */
116             child = _gx_widget_next_client_child_get(child);
117             continue;
118         }
119 
120         map = GX_NULL;
121         xpos = (GX_VALUE)(child -> gx_widget_size.gx_rectangle_left - (tree -> gx_tree_view_indentation >> 1));
122         ypos = (GX_VALUE)(child -> gx_widget_size.gx_rectangle_top + child -> gx_widget_size.gx_rectangle_bottom - 1);
123         ypos = (GX_VALUE)(ypos >> 1);
124 
125         if (child -> gx_widget_type == GX_TYPE_MENU)
126         {
127             list = &((GX_MENU *)child) -> gx_menu_list;
128 
129             if (list -> gx_widget_first_child)
130             {
131                 if (child -> gx_widget_style & GX_STYLE_MENU_EXPANDED)
132                 {
133                     map = collapse_map;
134                 }
135                 else
136                 {
137                     map = expand_map;
138                 }
139 
140                 if (map)
141                 {
142                     /* Calculate collapse/expand icon draw area. */
143                     xpos = (GX_VALUE)(xpos - (map_width >> 1));
144                     ypos = (GX_VALUE)(ypos - (map_height >> 1));
145 
146                     /* Draw collapse/expand icons. */
147                     _gx_canvas_pixelmap_draw(xpos, ypos, map);
148                 }
149             }
150         }
151 
152         if (tree -> gx_widget_style & GX_STYLE_TREE_VIEW_SHOW_ROOT_LINES)
153         {
154             /* Draw root lines.*/
155             _gx_context_brush_get(&brush);
156             brush -> gx_brush_pattern_mask = 0x80000000;
157 
158             if (map)
159             {
160                 /* Get right center of the collapse/expand icon. */
161                 xpos = (GX_VALUE)(xpos + map_width);
162                 ypos = (GX_VALUE)(ypos + (map_height >> 1));
163             }
164             else
165             {
166                 xpos = (GX_VALUE)(child -> gx_widget_size.gx_rectangle_left - (tree -> gx_tree_view_indentation >> 1) + 1);
167                 ypos = (GX_VALUE)((child -> gx_widget_size.gx_rectangle_top + child -> gx_widget_size.gx_rectangle_bottom) >> 1);
168             }
169 
170             /* Draw horizontal root line that connection collapse/expand icon with the menu item. */
171             _gx_canvas_line_draw(xpos, ypos, (GX_VALUE)(child -> gx_widget_size.gx_rectangle_left - 1), ypos);
172 
173             if (pre || owner)
174             {
175                 if (map)
176                 {
177                     /* Get top center of the collapse/expand icon. */
178                     xpos = (GX_VALUE)(xpos - (map_width >> 1));
179                     ypos = (GX_VALUE)(ypos - (map_height >> 1) - 1);
180                 }
181                 else
182                 {
183                     xpos = (GX_VALUE)(xpos - 1);
184                 }
185 
186                 if (pre)
187                 {
188                     if ((pre -> gx_widget_type == GX_TYPE_MENU) &&
189                         ((GX_MENU *)pre) -> gx_menu_list.gx_widget_first_child)
190                     {
191                         yend = (GX_VALUE)((pre -> gx_widget_size.gx_rectangle_top + pre -> gx_widget_size.gx_rectangle_bottom) >> 1);
192                         yend = (GX_VALUE)(yend - (map_height >> 1) + map_height);
193                     }
194                     else
195                     {
196                         yend = (GX_VALUE)((pre -> gx_widget_size.gx_rectangle_top + pre -> gx_widget_size.gx_rectangle_bottom) >> 1);
197                         yend = (GX_VALUE)(yend + 1);
198                     }
199                 }
200                 else
201                 {
202                     yend = owner -> gx_widget_size.gx_rectangle_bottom;
203                 }
204 
205                 brush -> gx_brush_pattern_mask = vertical_mask;
206 
207                 /* Draw vertical root line that connect to the previous or parent item. */
208                 _gx_canvas_line_draw(xpos, yend, xpos, ypos);
209 
210                 vertical_mask = brush -> gx_brush_pattern_mask;
211             }
212         }
213 
214         pre = child;
215 
216         /* Pick next client child. */
217         child = _gx_widget_next_client_child_get(child);
218     }
219 }
220 
221 /**************************************************************************/
222 /*                                                                        */
223 /*  FUNCTION                                               RELEASE        */
224 /*                                                                        */
225 /*    _gx_tree_view_root_draw                             PORTABLE C      */
226 /*                                                           6.1          */
227 /*  AUTHOR                                                                */
228 /*                                                                        */
229 /*    Kenneth Maxwell, Microsoft Corporation                              */
230 /*                                                                        */
231 /*  DESCRIPTION                                                           */
232 /*                                                                        */
233 /*    Internal helper function to draw the expand/collapse icons and root */
234 /*    lines.                                                              */
235 /*                                                                        */
236 /*  INPUT                                                                 */
237 /*                                                                        */
238 /*    tree                                  Pointer the to tree view      */
239 /*                                            control block               */
240 /*                                                                        */
241 /*  OUTPUT                                                                */
242 /*                                                                        */
243 /*    status                                Compoletion status            */
244 /*                                                                        */
245 /*  CALLS                                                                 */
246 /*                                                                        */
247 /*    _gx_widget_first_client_child_get     Get the first client child    */
248 /*    _gx_widget_next_client_child_get      Get the next chilent child    */
249 /*    _gx_tree_view_root_draw_helper        Draw tree view root           */
250 /*                                                                        */
251 /*  CALLED BY                                                             */
252 /*                                                                        */
253 /*    _gx_tree_view_draw                                                  */
254 /*                                                                        */
255 /*  RELEASE HISTORY                                                       */
256 /*                                                                        */
257 /*    DATE              NAME                      DESCRIPTION             */
258 /*                                                                        */
259 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
260 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
261 /*                                            resulting in version 6.1    */
262 /*                                                                        */
263 /**************************************************************************/
_gx_tree_view_root_draw(GX_TREE_VIEW * tree)264 static VOID _gx_tree_view_root_draw(GX_TREE_VIEW *tree)
265 {
266 GX_WIDGET    *child;
267 GX_WIDGET    *next;
268 GX_MENU_LIST *list;
269 GX_WIDGET    *parent = (GX_WIDGET *)tree;
270 GX_WIDGET    *owner;
271 
272     child = _gx_widget_first_client_child_get(parent);
273 
274     while (child)
275     {
276         if (child -> gx_widget_type == GX_TYPE_MENU)
277         {
278             list = &((GX_MENU *)child) -> gx_menu_list;
279 
280             if ((list -> gx_widget_first_child) &&
281                 (list -> gx_widget_status & GX_STATUS_VISIBLE))
282             {
283                 child = list -> gx_widget_first_child;
284                 continue;
285             }
286         }
287 
288         /* Pick next client child. */
289         next = _gx_widget_next_client_child_get(child);
290 
291         while ((next == GX_NULL) && (child != parent))
292         {
293             child = child -> gx_widget_parent;
294 
295             if (child -> gx_widget_type == GX_TYPE_MENU_LIST)
296             {
297                 owner = ((GX_MENU_LIST *)child) -> gx_menu_list_owner;
298                 next = owner;
299             }
300             else
301             {
302                 owner = GX_NULL;
303                 next = child;
304             }
305 
306             _gx_tree_view_root_draw_helper(tree, child, owner);
307 
308             child = next;
309             next = _gx_widget_next_client_child_get(next);
310         }
311 
312         if (child == parent)
313         {
314             break;
315         }
316 
317         child = next;
318     }
319 }
320 
321 /**************************************************************************/
322 /*                                                                        */
323 /*  FUNCTION                                               RELEASE        */
324 /*                                                                        */
325 /*    _gx_tree_view_draw                                  PORTABLE C      */
326 /*                                                           6.1          */
327 /*  AUTHOR                                                                */
328 /*                                                                        */
329 /*    Kenneth Maxwell, Microsoft Corporation                              */
330 /*                                                                        */
331 /*  DESCRIPTION                                                           */
332 /*                                                                        */
333 /*    This function draws the specified tree view, which is a special type*/
334 /*    of widget.                                                          */
335 /*                                                                        */
336 /*  INPUT                                                                 */
337 /*                                                                        */
338 /*    tree                                  Pointer the to tree view      */
339 /*                                            control block               */
340 /*                                                                        */
341 /*  OUTPUT                                                                */
342 /*                                                                        */
343 /*    None                                                                */
344 /*                                                                        */
345 /*  CALLS                                                                 */
346 /*                                                                        */
347 /*    _gx_window_background_draw            Draw window background        */
348 /*    _gx_context_brush_pattern_set         Set brush pattern             */
349 /*    _gx_context_brush_width_set           Set brush width               */
350 /*    _gx_context_line_color_set            Set line color                */
351 /*    _gx_utility_rectangle_overlap_detect  Detect overlap of supplied    */
352 /*                                            rectangles                  */
353 /*    _gx_tree_view_root_draw               Draw root lines and icons     */
354 /*    _gx_widget_children_draw              Draw widget children          */
355 /*                                                                        */
356 /*  CALLED BY                                                             */
357 /*                                                                        */
358 /*    Application Code                                                    */
359 /*    GUIX Internal Code                                                  */
360 /*                                                                        */
361 /*  RELEASE HISTORY                                                       */
362 /*                                                                        */
363 /*    DATE              NAME                      DESCRIPTION             */
364 /*                                                                        */
365 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
366 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
367 /*                                            resulting in version 6.1    */
368 /*                                                                        */
369 /**************************************************************************/
_gx_tree_view_draw(GX_TREE_VIEW * tree)370 VOID  _gx_tree_view_draw(GX_TREE_VIEW *tree)
371 {
372 GX_DRAW_CONTEXT *context;
373 GX_RECTANGLE     dirty_area;
374 
375     /* Draw tree menu background. */
376     _gx_window_background_draw((GX_WINDOW *)tree);
377 
378     _gx_context_brush_pattern_set(GX_TREE_VIEW_ROOT_LINE_PATTERN);
379 
380     _gx_context_brush_width_set(1);
381     _gx_context_line_color_set(tree -> gx_tree_view_root_line_color);
382 
383     /* pick up the current context */
384     context = _gx_system_current_draw_context;
385     dirty_area = context -> gx_draw_context_dirty;
386 
387     _gx_utility_rectangle_overlap_detect(&tree -> gx_window_client,
388                                          &context -> gx_draw_context_dirty,
389                                          &context -> gx_draw_context_dirty);
390 
391     /* Draw collapse/expand icons and root lines. */
392     _gx_tree_view_root_draw(tree);
393 
394     context -> gx_draw_context_dirty = dirty_area;
395 
396     _gx_context_brush_pattern_set(0);
397 
398     /* Draw all the child widgets.  */
399     _gx_widget_children_draw((GX_WIDGET *)tree);
400 }
401 
402