GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_horizontal_list_scroll.c Lines: 64 66 97.0 %
Date: 2024-12-05 08:52:37 Branches: 57 62 91.9 %

Line Branch Exec Source
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
/**   Horizontal List (List)                                              */
18
/**                                                                       */
19
/**************************************************************************/
20
21
#define GX_SOURCE_CODE
22
23
24
/* Include necessary system files.  */
25
26
#include "gx_api.h"
27
#include "gx_widget.h"
28
#include "gx_window.h"
29
#include "gx_system.h"
30
#include "gx_scrollbar.h"
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _gx_horizontal_list_invisible_page_scroll           PORTABLE C      */
37
/*                                                           6.1.8        */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Ting Zhu, Microsoft Corporation                                     */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function moves left or right the horizontal list by pages.     */
45
/*                                                                        */
46
/*  INPUT                                                                 */
47
/*                                                                        */
48
/*    list                                  Horizontal list widget control*/
49
/*                                            block                       */
50
/*    num_pages                             The number of pages to scroll */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    None                                                                */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    _gx_widget_first_client_child_get     Get first client child        */
59
/*    _gx_widget_next_client_child_get      Get next client child         */
60
/*                                                                        */
61
/*  CALLED BY                                                             */
62
/*                                                                        */
63
/*    _gx_horizontal_list_scroll                                          */
64
/*                                                                        */
65
/*  RELEASE HISTORY                                                       */
66
/*                                                                        */
67
/*    DATE              NAME                      DESCRIPTION             */
68
/*                                                                        */
69
/*  08-02-2021     Ting Zhu                 Initial Version 6.1.8         */
70
/*                                                                        */
71
/**************************************************************************/
72
4
static VOID _gx_horizontal_list_invisible_page_scroll(GX_HORIZONTAL_LIST *list, INT num_pages)
73
{
74
INT maximum_scroll_pages;
75
76
4
    if (!(list -> gx_widget_style & GX_STYLE_WRAP))
77
    {
78
79
        /* Wrap style is not applied, need to calculate scroll limit.  */
80
2
        if (num_pages < 0)
81
        {
82
83
            /* Calculate maximum up scroll num_pages.  */
84
1
            maximum_scroll_pages = (list -> gx_horizontal_list_total_columns - list -> gx_horizontal_list_top_index - list -> gx_horizontal_list_child_count);
85
1
            maximum_scroll_pages /= list -> gx_horizontal_list_child_count;
86
87
            /* Remain one page for normal scroll routine. */
88
1
            if (maximum_scroll_pages >= 1)
89
            {
90
                maximum_scroll_pages--;
91
            }
92
93
1
            if (maximum_scroll_pages < (-num_pages))
94
            {
95
1
                num_pages = (-maximum_scroll_pages);
96
            }
97
        }
98
        else
99
        {
100
101
            /* Calculate maximum down scroll num_pages.   */
102
1
            maximum_scroll_pages = list -> gx_horizontal_list_top_index / list -> gx_horizontal_list_child_count;
103
104
            /* Remain one page for normal scroll routine. */
105
1
            if (maximum_scroll_pages >= 1)
106
            {
107
                maximum_scroll_pages--;
108
            }
109
110
1
            if (maximum_scroll_pages < num_pages)
111
            {
112
1
                num_pages = maximum_scroll_pages;
113
            }
114
        }
115
    }
116
117
4
    if (num_pages)
118
    {
119
120
        /* Update top index according to scroll num_pages.  */
121
2
        list -> gx_horizontal_list_top_index -= num_pages * list -> gx_horizontal_list_child_count;
122
123
2
        if (list -> gx_widget_style & GX_STYLE_WRAP)
124
        {
125
126
            /* Wrap page index.  */
127
2
            if (num_pages < 0)
128
            {
129
97
                while (list -> gx_horizontal_list_top_index >= list -> gx_horizontal_list_total_columns)
130
                {
131
96
                    list -> gx_horizontal_list_top_index -= list -> gx_horizontal_list_total_columns;
132
                }
133
            }
134
            else
135
            {
136
98
                while (list -> gx_horizontal_list_top_index < 0)
137
                {
138
97
                    list -> gx_horizontal_list_top_index += list -> gx_horizontal_list_total_columns;
139
                }
140
            }
141
        }
142
    }
143
4
}
144
145
/**************************************************************************/
146
/*                                                                        */
147
/*  FUNCTION                                               RELEASE        */
148
/*                                                                        */
149
/*    _gx_horizontal_list_scroll                          PORTABLE C      */
150
/*                                                           6.1.8        */
151
/*  AUTHOR                                                                */
152
/*                                                                        */
153
/*    Kenneth Maxwell, Microsoft Corporation                              */
154
/*                                                                        */
155
/*  DESCRIPTION                                                           */
156
/*                                                                        */
157
/*    This function moves up or down the scrollbar.                       */
158
/*                                                                        */
159
/*  INPUT                                                                 */
160
/*                                                                        */
161
/*    list                                  Horizontal list widget control*/
162
/*                                            block                       */
163
/*    amount                                Shifting value                */
164
/*                                                                        */
165
/*  OUTPUT                                                                */
166
/*                                                                        */
167
/*    None                                                                */
168
/*                                                                        */
169
/*  CALLS                                                                 */
170
/*                                                                        */
171
/*    _gx_window_client_scroll              Scroll the window client      */
172
/*    _gx_horizontal_list_left_wrap         Scroll the horizontal list    */
173
/*                                            to the left                 */
174
/*    _gx_horizontal_list_right_wrap        Scroll the horizontal list    */
175
/*                                            to the right                */
176
/*                                                                        */
177
/*  CALLED BY                                                             */
178
/*                                                                        */
179
/*    _gx_horizontal_list_event_process                                   */
180
/*                                                                        */
181
/*  RELEASE HISTORY                                                       */
182
/*                                                                        */
183
/*    DATE              NAME                      DESCRIPTION             */
184
/*                                                                        */
185
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
186
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
187
/*                                            resulting in version 6.1    */
188
/*  08-02-2021     Ting Zhu                 Modified comment(s),          */
189
/*                                            fixed scroll overflow issue,*/
190
/*                                            resulting in version 6.1.8  */
191
/*                                                                        */
192
/**************************************************************************/
193
425
VOID _gx_horizontal_list_scroll(GX_HORIZONTAL_LIST *list, INT amount)
194
{
195
GX_WIDGET    *child;
196
GX_WIDGET    *last_child;
197
GX_RECTANGLE  block;
198
GX_SCROLLBAR *scroll;
199
425
GX_BOOL       do_block_move = GX_TRUE;
200
425
GX_BOOL       reuse_child_widgets = GX_FALSE;
201
INT           page_size;
202
INT           num_pages;
203
204
425
    if (!amount)
205
    {
206
18
        return;
207
    }
208
209
409
    if ((list -> gx_horizontal_list_callback != GX_NULL) &&
210
402
        (list -> gx_horizontal_list_visible_columns < list -> gx_horizontal_list_total_columns) &&
211

400
        ((list -> gx_horizontal_list_child_count < list -> gx_horizontal_list_total_columns) || (list -> gx_widget_style & GX_STYLE_WRAP)))
212
    {
213
396
        reuse_child_widgets = GX_TRUE;
214
215
        /* Calculate the page size.  */
216
396
        page_size = (list -> gx_horizontal_list_child_width * list -> gx_horizontal_list_child_count);
217
218
396
        if (!page_size)
219
        {
220
2
            return;
221
        }
222
223
        /* Calculate the number of pages to be scrolled.  */
224
394
        if (amount < 0)
225
        {
226
227
            num_pages = (amount + page_size) / page_size;
227
        }
228
        else
229
        {
230
167
            num_pages = (amount - page_size) / page_size;
231
        }
232
233
394
        if (num_pages)
234
        {
235
236
            /* Calculate the remainning scroll amount.  */
237
4
            amount -= (num_pages * page_size);
238
239
            /* Scroll pages.  */
240
4
            _gx_horizontal_list_invisible_page_scroll(list, num_pages);
241
        }
242
    }
243
244
    /* first shift my child widgets */
245
407
    child = list -> gx_widget_first_child;
246
247
5090
    while (child)
248
    {
249
4683
        if (!(child -> gx_widget_status & GX_STATUS_NONCLIENT))
250
        {
251
4383
            _gx_widget_scroll_shift(child, amount, 0, GX_TRUE);
252
        }
253
4683
        child = child -> gx_widget_next;
254
    }
255
256
257
    /* now check to see if we need to wrap any child widgets */
258
259
407
    if (reuse_child_widgets)
260
    {
261
        /* this means we have fewer children than list rows, so we
262
           need to move and re-use the child widgets
263
         */
264
394
        if (amount < 0)
265
        {
266
227
            _gx_horizontal_list_left_wrap(list);
267
        }
268
        else
269
        {
270
167
            _gx_horizontal_list_right_wrap(list);
271
        }
272
    }
273
274
407
    _gx_window_scrollbar_find((GX_WINDOW *)list, GX_TYPE_HORIZONTAL_SCROLL, &scroll);
275
276
407
    if (scroll)
277
    {
278
300
        _gx_scrollbar_reset(scroll, GX_NULL);
279
    }
280
281
407
    if (list -> gx_widget_status & GX_STATUS_VISIBLE)
282
    {
283
405
        block = list -> gx_window_client;
284
285
405
        if (!(list -> gx_widget_style & (GX_STYLE_WRAP | GX_STYLE_TRANSPARENT)) &&
286
306
            (list -> gx_widget_style & GX_STYLE_BORDER_THIN))
287
        {
288
278
            child = _gx_widget_first_client_child_get((GX_WIDGET *)list);
289
278
            last_child = _gx_widget_last_client_child_get((GX_WIDGET *)list);
290
291
278
            if (child)
292
            {
293
277
                if ((child -> gx_widget_size.gx_rectangle_left > block.gx_rectangle_left) ||
294
200
                    (last_child -> gx_widget_size.gx_rectangle_right < block.gx_rectangle_right))
295
                {
296
                    /* If the widget has thin border, the round corder of the border
297
                       will cover the client area, block move will cause trouble. */
298
132
                    _gx_system_dirty_mark((GX_WIDGET *)list);
299
132
                    do_block_move = GX_FALSE;
300
                }
301
            }
302
        }
303
304
405
        if (do_block_move)
305
        {
306
273
            _gx_widget_block_move((GX_WIDGET *)list, &block, amount, 0);
307
        }
308
    }
309
}
310