GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_horizontal_list_scroll.c Lines: 64 66 97.0 %
Date: 2026-03-06 19:21:09 Branches: 57 62 91.9 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
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
/**************************************************************************/
67
4
static VOID _gx_horizontal_list_invisible_page_scroll(GX_HORIZONTAL_LIST *list, INT num_pages)
68
{
69
INT maximum_scroll_pages;
70
71
4
    if (!(list -> gx_widget_style & GX_STYLE_WRAP))
72
    {
73
74
        /* Wrap style is not applied, need to calculate scroll limit.  */
75
2
        if (num_pages < 0)
76
        {
77
78
            /* Calculate maximum up scroll num_pages.  */
79
1
            maximum_scroll_pages = (list -> gx_horizontal_list_total_columns - list -> gx_horizontal_list_top_index - list -> gx_horizontal_list_child_count);
80
1
            maximum_scroll_pages /= list -> gx_horizontal_list_child_count;
81
82
            /* Remain one page for normal scroll routine. */
83
1
            if (maximum_scroll_pages >= 1)
84
            {
85
                maximum_scroll_pages--;
86
            }
87
88
1
            if (maximum_scroll_pages < (-num_pages))
89
            {
90
1
                num_pages = (-maximum_scroll_pages);
91
            }
92
        }
93
        else
94
        {
95
96
            /* Calculate maximum down scroll num_pages.   */
97
1
            maximum_scroll_pages = list -> gx_horizontal_list_top_index / list -> gx_horizontal_list_child_count;
98
99
            /* Remain one page for normal scroll routine. */
100
1
            if (maximum_scroll_pages >= 1)
101
            {
102
                maximum_scroll_pages--;
103
            }
104
105
1
            if (maximum_scroll_pages < num_pages)
106
            {
107
1
                num_pages = maximum_scroll_pages;
108
            }
109
        }
110
    }
111
112
4
    if (num_pages)
113
    {
114
115
        /* Update top index according to scroll num_pages.  */
116
2
        list -> gx_horizontal_list_top_index -= num_pages * list -> gx_horizontal_list_child_count;
117
118
2
        if (list -> gx_widget_style & GX_STYLE_WRAP)
119
        {
120
121
            /* Wrap page index.  */
122
2
            if (num_pages < 0)
123
            {
124
97
                while (list -> gx_horizontal_list_top_index >= list -> gx_horizontal_list_total_columns)
125
                {
126
96
                    list -> gx_horizontal_list_top_index -= list -> gx_horizontal_list_total_columns;
127
                }
128
            }
129
            else
130
            {
131
98
                while (list -> gx_horizontal_list_top_index < 0)
132
                {
133
97
                    list -> gx_horizontal_list_top_index += list -> gx_horizontal_list_total_columns;
134
                }
135
            }
136
        }
137
    }
138
4
}
139
140
/**************************************************************************/
141
/*                                                                        */
142
/*  FUNCTION                                               RELEASE        */
143
/*                                                                        */
144
/*    _gx_horizontal_list_scroll                          PORTABLE C      */
145
/*                                                           6.1.8        */
146
/*  AUTHOR                                                                */
147
/*                                                                        */
148
/*    Kenneth Maxwell, Microsoft Corporation                              */
149
/*                                                                        */
150
/*  DESCRIPTION                                                           */
151
/*                                                                        */
152
/*    This function moves up or down the scrollbar.                       */
153
/*                                                                        */
154
/*  INPUT                                                                 */
155
/*                                                                        */
156
/*    list                                  Horizontal list widget control*/
157
/*                                            block                       */
158
/*    amount                                Shifting value                */
159
/*                                                                        */
160
/*  OUTPUT                                                                */
161
/*                                                                        */
162
/*    None                                                                */
163
/*                                                                        */
164
/*  CALLS                                                                 */
165
/*                                                                        */
166
/*    _gx_window_client_scroll              Scroll the window client      */
167
/*    _gx_horizontal_list_left_wrap         Scroll the horizontal list    */
168
/*                                            to the left                 */
169
/*    _gx_horizontal_list_right_wrap        Scroll the horizontal list    */
170
/*                                            to the right                */
171
/*                                                                        */
172
/*  CALLED BY                                                             */
173
/*                                                                        */
174
/*    _gx_horizontal_list_event_process                                   */
175
/*                                                                        */
176
/**************************************************************************/
177
425
VOID _gx_horizontal_list_scroll(GX_HORIZONTAL_LIST *list, INT amount)
178
{
179
GX_WIDGET    *child;
180
GX_WIDGET    *last_child;
181
GX_RECTANGLE  block;
182
GX_SCROLLBAR *scroll;
183
425
GX_BOOL       do_block_move = GX_TRUE;
184
425
GX_BOOL       reuse_child_widgets = GX_FALSE;
185
INT           page_size;
186
INT           num_pages;
187
188
425
    if (!amount)
189
    {
190
18
        return;
191
    }
192
193
409
    if ((list -> gx_horizontal_list_callback != GX_NULL) &&
194
402
        (list -> gx_horizontal_list_visible_columns < list -> gx_horizontal_list_total_columns) &&
195

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