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 /**   Horizontal List (List)                                              */
19 /**                                                                       */
20 /**************************************************************************/
21 
22 #define GX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "gx_api.h"
28 #include "gx_widget.h"
29 #include "gx_window.h"
30 #include "gx_system.h"
31 #include "gx_scrollbar.h"
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _gx_horizontal_list_invisible_page_scroll           PORTABLE C      */
38 /*                                                           6.1.8        */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Ting Zhu, Microsoft Corporation                                     */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function moves left or right the horizontal list by pages.     */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    list                                  Horizontal list widget control*/
50 /*                                            block                       */
51 /*    num_pages                             The number of pages to scroll */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    None                                                                */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _gx_widget_first_client_child_get     Get first client child        */
60 /*    _gx_widget_next_client_child_get      Get next client child         */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    _gx_horizontal_list_scroll                                          */
65 /*                                                                        */
66 /*  RELEASE HISTORY                                                       */
67 /*                                                                        */
68 /*    DATE              NAME                      DESCRIPTION             */
69 /*                                                                        */
70 /*  08-02-2021     Ting Zhu                 Initial Version 6.1.8         */
71 /*                                                                        */
72 /**************************************************************************/
_gx_horizontal_list_invisible_page_scroll(GX_HORIZONTAL_LIST * list,INT num_pages)73 static VOID _gx_horizontal_list_invisible_page_scroll(GX_HORIZONTAL_LIST *list, INT num_pages)
74 {
75 INT maximum_scroll_pages;
76 
77     if (!(list -> gx_widget_style & GX_STYLE_WRAP))
78     {
79 
80         /* Wrap style is not applied, need to calculate scroll limit.  */
81         if (num_pages < 0)
82         {
83 
84             /* Calculate maximum up scroll num_pages.  */
85             maximum_scroll_pages = (list -> gx_horizontal_list_total_columns - list -> gx_horizontal_list_top_index - list -> gx_horizontal_list_child_count);
86             maximum_scroll_pages /= list -> gx_horizontal_list_child_count;
87 
88             /* Remain one page for normal scroll routine. */
89             if (maximum_scroll_pages >= 1)
90             {
91                 maximum_scroll_pages--;
92             }
93 
94             if (maximum_scroll_pages < (-num_pages))
95             {
96                 num_pages = (-maximum_scroll_pages);
97             }
98         }
99         else
100         {
101 
102             /* Calculate maximum down scroll num_pages.   */
103             maximum_scroll_pages = list -> gx_horizontal_list_top_index / list -> gx_horizontal_list_child_count;
104 
105             /* Remain one page for normal scroll routine. */
106             if (maximum_scroll_pages >= 1)
107             {
108                 maximum_scroll_pages--;
109             }
110 
111             if (maximum_scroll_pages < num_pages)
112             {
113                 num_pages = maximum_scroll_pages;
114             }
115         }
116     }
117 
118     if (num_pages)
119     {
120 
121         /* Update top index according to scroll num_pages.  */
122         list -> gx_horizontal_list_top_index -= num_pages * list -> gx_horizontal_list_child_count;
123 
124         if (list -> gx_widget_style & GX_STYLE_WRAP)
125         {
126 
127             /* Wrap page index.  */
128             if (num_pages < 0)
129             {
130                 while (list -> gx_horizontal_list_top_index >= list -> gx_horizontal_list_total_columns)
131                 {
132                     list -> gx_horizontal_list_top_index -= list -> gx_horizontal_list_total_columns;
133                 }
134             }
135             else
136             {
137                 while (list -> gx_horizontal_list_top_index < 0)
138                 {
139                     list -> gx_horizontal_list_top_index += list -> gx_horizontal_list_total_columns;
140                 }
141             }
142         }
143     }
144 }
145 
146 /**************************************************************************/
147 /*                                                                        */
148 /*  FUNCTION                                               RELEASE        */
149 /*                                                                        */
150 /*    _gx_horizontal_list_scroll                          PORTABLE C      */
151 /*                                                           6.1.8        */
152 /*  AUTHOR                                                                */
153 /*                                                                        */
154 /*    Kenneth Maxwell, Microsoft Corporation                              */
155 /*                                                                        */
156 /*  DESCRIPTION                                                           */
157 /*                                                                        */
158 /*    This function moves up or down the scrollbar.                       */
159 /*                                                                        */
160 /*  INPUT                                                                 */
161 /*                                                                        */
162 /*    list                                  Horizontal list widget control*/
163 /*                                            block                       */
164 /*    amount                                Shifting value                */
165 /*                                                                        */
166 /*  OUTPUT                                                                */
167 /*                                                                        */
168 /*    None                                                                */
169 /*                                                                        */
170 /*  CALLS                                                                 */
171 /*                                                                        */
172 /*    _gx_window_client_scroll              Scroll the window client      */
173 /*    _gx_horizontal_list_left_wrap         Scroll the horizontal list    */
174 /*                                            to the left                 */
175 /*    _gx_horizontal_list_right_wrap        Scroll the horizontal list    */
176 /*                                            to the right                */
177 /*                                                                        */
178 /*  CALLED BY                                                             */
179 /*                                                                        */
180 /*    _gx_horizontal_list_event_process                                   */
181 /*                                                                        */
182 /*  RELEASE HISTORY                                                       */
183 /*                                                                        */
184 /*    DATE              NAME                      DESCRIPTION             */
185 /*                                                                        */
186 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
187 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
188 /*                                            resulting in version 6.1    */
189 /*  08-02-2021     Ting Zhu                 Modified comment(s),          */
190 /*                                            fixed scroll overflow issue,*/
191 /*                                            resulting in version 6.1.8  */
192 /*                                                                        */
193 /**************************************************************************/
_gx_horizontal_list_scroll(GX_HORIZONTAL_LIST * list,INT amount)194 VOID _gx_horizontal_list_scroll(GX_HORIZONTAL_LIST *list, INT amount)
195 {
196 GX_WIDGET    *child;
197 GX_WIDGET    *last_child;
198 GX_RECTANGLE  block;
199 GX_SCROLLBAR *scroll;
200 GX_BOOL       do_block_move = GX_TRUE;
201 GX_BOOL       reuse_child_widgets = GX_FALSE;
202 INT           page_size;
203 INT           num_pages;
204 
205     if (!amount)
206     {
207         return;
208     }
209 
210     if ((list -> gx_horizontal_list_callback != GX_NULL) &&
211         (list -> gx_horizontal_list_visible_columns < list -> gx_horizontal_list_total_columns) &&
212         ((list -> gx_horizontal_list_child_count < list -> gx_horizontal_list_total_columns) || (list -> gx_widget_style & GX_STYLE_WRAP)))
213     {
214         reuse_child_widgets = GX_TRUE;
215 
216         /* Calculate the page size.  */
217         page_size = (list -> gx_horizontal_list_child_width * list -> gx_horizontal_list_child_count);
218 
219         if (!page_size)
220         {
221             return;
222         }
223 
224         /* Calculate the number of pages to be scrolled.  */
225         if (amount < 0)
226         {
227             num_pages = (amount + page_size) / page_size;
228         }
229         else
230         {
231             num_pages = (amount - page_size) / page_size;
232         }
233 
234         if (num_pages)
235         {
236 
237             /* Calculate the remainning scroll amount.  */
238             amount -= (num_pages * page_size);
239 
240             /* Scroll pages.  */
241             _gx_horizontal_list_invisible_page_scroll(list, num_pages);
242         }
243     }
244 
245     /* first shift my child widgets */
246     child = list -> gx_widget_first_child;
247 
248     while (child)
249     {
250         if (!(child -> gx_widget_status & GX_STATUS_NONCLIENT))
251         {
252             _gx_widget_scroll_shift(child, amount, 0, GX_TRUE);
253         }
254         child = child -> gx_widget_next;
255     }
256 
257 
258     /* now check to see if we need to wrap any child widgets */
259 
260     if (reuse_child_widgets)
261     {
262         /* this means we have fewer children than list rows, so we
263            need to move and re-use the child widgets
264          */
265         if (amount < 0)
266         {
267             _gx_horizontal_list_left_wrap(list);
268         }
269         else
270         {
271             _gx_horizontal_list_right_wrap(list);
272         }
273     }
274 
275     _gx_window_scrollbar_find((GX_WINDOW *)list, GX_TYPE_HORIZONTAL_SCROLL, &scroll);
276 
277     if (scroll)
278     {
279         _gx_scrollbar_reset(scroll, GX_NULL);
280     }
281 
282     if (list -> gx_widget_status & GX_STATUS_VISIBLE)
283     {
284         block = list -> gx_window_client;
285 
286         if (!(list -> gx_widget_style & (GX_STYLE_WRAP | GX_STYLE_TRANSPARENT)) &&
287             (list -> gx_widget_style & GX_STYLE_BORDER_THIN))
288         {
289             child = _gx_widget_first_client_child_get((GX_WIDGET *)list);
290             last_child = _gx_widget_last_client_child_get((GX_WIDGET *)list);
291 
292             if (child)
293             {
294                 if ((child -> gx_widget_size.gx_rectangle_left > block.gx_rectangle_left) ||
295                     (last_child -> gx_widget_size.gx_rectangle_right < block.gx_rectangle_right))
296                 {
297                     /* If the widget has thin border, the round corder of the border
298                        will cover the client area, block move will cause trouble. */
299                     _gx_system_dirty_mark((GX_WIDGET *)list);
300                     do_block_move = GX_FALSE;
301                 }
302             }
303         }
304 
305         if (do_block_move)
306         {
307             _gx_widget_block_move((GX_WIDGET *)list, &block, amount, 0);
308         }
309     }
310 }
311 
312