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 /**   Accordion Menu Management (Menu)                                    */
19 /**                                                                       */
20 /**************************************************************************/
21 
22 #define GX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "gx_api.h"
28 #include "gx_menu.h"
29 #include "gx_widget.h"
30 #include "gx_system.h"
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _gx_accordion_menu_one_level_position               PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Kenneth Maxwell, Microsoft Corporation                              */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function positions first level items for an accordion menu.    */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    accordion                             Accordion menu control block  */
49 /*                                                                        */
50 /*  OUTPUT                                                                */
51 /*                                                                        */
52 /*    status                                Completion status             */
53 /*                                                                        */
54 /*  CALLS                                                                 */
55 /*                                                                        */
56 /*    _gx_widget_border_width_get           Get widget border width       */
57 /*    _gx_widget_client_get                 Get widget client rectangle   */
58 /*    _gx_widget_height_get                 Get widget height             */
59 /*    _gx_widget_shift                      Shift a widget                */
60 /*    _gx_widget_resize                     Resize a widget               */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    _gx_accordion_menu_position                                         */
65 /*                                                                        */
66 /*  RELEASE HISTORY                                                       */
67 /*                                                                        */
68 /*    DATE              NAME                      DESCRIPTION             */
69 /*                                                                        */
70 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
71 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
72 /*                                            resulting in version 6.1    */
73 /*                                                                        */
74 /**************************************************************************/
_gx_accordion_menu_one_level_position(GX_ACCORDION_MENU * accordion)75 static UINT  _gx_accordion_menu_one_level_position(GX_ACCORDION_MENU *accordion)
76 {
77 GX_WIDGET    *child = accordion -> gx_widget_first_child;
78 GX_RECTANGLE  size;
79 GX_RECTANGLE  client;
80 GX_VALUE      height;
81 GX_VALUE      bottom;
82 GX_VALUE      border_width;
83 GX_MENU_LIST *list;
84 
85     _gx_widget_border_width_get((GX_WIDGET *)accordion, &border_width);
86     _gx_widget_client_get((GX_WIDGET *)accordion, border_width, &client);
87 
88     size.gx_rectangle_left = client.gx_rectangle_left;
89     size.gx_rectangle_right = client.gx_rectangle_right;
90     size.gx_rectangle_top = client.gx_rectangle_top;
91     size.gx_rectangle_bottom = (GX_VALUE)(size.gx_rectangle_top - 1);
92 
93     bottom = size.gx_rectangle_bottom;
94     accordion -> gx_accordion_menu_expand_item = GX_NULL;
95 
96     /* Reposition accordion menu items. */
97     while (child)
98     {
99         switch (child -> gx_widget_type)
100         {
101         case GX_TYPE_MENU:
102             list = &((GX_MENU *)child) -> gx_menu_list;
103 
104             if (child -> gx_widget_style & GX_STYLE_MENU_EXPANDED)
105             {
106                 if (!accordion -> gx_accordion_menu_expand_item && list -> gx_widget_first_child)
107                 {
108                     accordion -> gx_accordion_menu_expand_item = child;
109                 }
110                 else
111                 {
112                     child -> gx_widget_style &= (ULONG)(~GX_STYLE_MENU_EXPANDED);
113                     _gx_widget_detach((GX_WIDGET *)list);
114 
115                     list -> gx_widget_size.gx_rectangle_bottom = (GX_VALUE)(list -> gx_widget_size.gx_rectangle_top - 1);
116                 }
117             }
118 
119             _gx_widget_height_get(child, &height);
120 
121             size.gx_rectangle_top = (GX_VALUE)(bottom + 1);
122             size.gx_rectangle_bottom = (GX_VALUE)(size.gx_rectangle_top + height - 1);
123 
124             _gx_widget_resize(child, &size);
125 
126             if (list -> gx_widget_parent)
127             {
128                 _gx_widget_shift((GX_WIDGET *)list,
129                                  (GX_VALUE)(size.gx_rectangle_left - list -> gx_widget_size.gx_rectangle_left),
130                                  (GX_VALUE)(size.gx_rectangle_bottom + 1 - list -> gx_widget_size.gx_rectangle_top), GX_FALSE);
131 
132                 bottom = list -> gx_widget_size.gx_rectangle_bottom;
133             }
134             else
135             {
136                 bottom = size.gx_rectangle_bottom;
137             }
138             break;
139 
140         case GX_TYPE_MENU_LIST:
141             break;
142 
143         default:
144             _gx_widget_height_get(child, &height);
145             size.gx_rectangle_top = (GX_VALUE)(bottom + 1);
146             size.gx_rectangle_bottom = (GX_VALUE)(size.gx_rectangle_top + height - 1);
147 
148             _gx_widget_resize(child, &size);
149             bottom = size.gx_rectangle_bottom;
150             break;
151         }
152 
153         child -> gx_widget_status &= ~GX_STATUS_ACCEPTS_FOCUS;
154         child = child -> gx_widget_next;
155     }
156 
157     size = accordion -> gx_widget_size;
158     size.gx_rectangle_bottom = (GX_VALUE)(bottom + border_width);
159 
160     /* Resize accordion menu. */
161     _gx_widget_resize((GX_WIDGET *)accordion, &size);
162 
163     /* Return completion status code. */
164     return GX_SUCCESS;
165 }
166 
167 /**************************************************************************/
168 /*                                                                        */
169 /*  FUNCTION                                               RELEASE        */
170 /*                                                                        */
171 /*    _gx_accordion_menu_position                         PORTABLE C      */
172 /*                                                           6.1          */
173 /*  AUTHOR                                                                */
174 /*                                                                        */
175 /*    Kenneth Maxwell, Microsoft Corporation                              */
176 /*                                                                        */
177 /*  DESCRIPTION                                                           */
178 /*                                                                        */
179 /*    This function positions an accordion menu and its items.            */
180 /*                                                                        */
181 /*  INPUT                                                                 */
182 /*                                                                        */
183 /*    accordion                             Accordion menu control block  */
184 /*                                                                        */
185 /*  OUTPUT                                                                */
186 /*                                                                        */
187 /*    status                                Completion status             */
188 /*                                                                        */
189 /*  CALLS                                                                 */
190 /*                                                                        */
191 /*    _gx_menu_one_level_position           Position a menu widget        */
192 /*    _gx_accordion_one_levelmenu_position  Position an accordion menu    */
193 /*                                                                        */
194 /*  CALLED BY                                                             */
195 /*                                                                        */
196 /*    Application Code                                                    */
197 /*                                                                        */
198 /*  RELEASE HISTORY                                                       */
199 /*                                                                        */
200 /*    DATE              NAME                      DESCRIPTION             */
201 /*                                                                        */
202 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
203 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
204 /*                                            resulting in version 6.1    */
205 /*                                                                        */
206 /**************************************************************************/
_gx_accordion_menu_position(GX_ACCORDION_MENU * accordion)207 UINT  _gx_accordion_menu_position(GX_ACCORDION_MENU *accordion)
208 {
209 GX_WIDGET    *parent = (GX_WIDGET *)accordion;
210 GX_WIDGET    *child;
211 GX_MENU_LIST *child_list;
212 
213     child = accordion -> gx_widget_first_child;
214 
215     /* Reposition items of menu list. */
216     while (child)
217     {
218         if (child -> gx_widget_type == GX_TYPE_MENU)
219         {
220             child_list = &((GX_MENU *)child) -> gx_menu_list;
221 
222             if (child_list -> gx_widget_first_child)
223             {
224                 child = child_list -> gx_widget_first_child;
225                 continue;
226             }
227             else if (child_list -> gx_widget_parent)
228             {
229                 _gx_widget_detach((GX_WIDGET *)child_list);
230             }
231         }
232         else if (child -> gx_widget_type == GX_TYPE_ACCORDION_MENU)
233         {
234             if (child -> gx_widget_first_child)
235             {
236                 child = child -> gx_widget_first_child;
237                 continue;
238             }
239         }
240 
241         while ((child -> gx_widget_next == GX_NULL) && (child != parent))
242         {
243             child = child -> gx_widget_parent;
244 
245             if (child -> gx_widget_type == GX_TYPE_MENU_LIST)
246             {
247                 child_list = (GX_MENU_LIST *)child;
248                 child = child_list -> gx_menu_list_owner;
249             }
250 
251             if ((child -> gx_widget_type == GX_TYPE_MENU))
252             {
253                 _gx_menu_one_level_position((GX_MENU *)child, 0);
254             }
255             else
256             {
257                 _gx_accordion_menu_one_level_position((GX_ACCORDION_MENU *)child);
258             }
259         }
260 
261         if (child == parent)
262         {
263             break;
264         }
265 
266         child = child -> gx_widget_next;
267     }
268 
269     /* Return completion status code. */
270     return(GX_SUCCESS);
271 }
272 
273