GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_vertical_list_scroll.c Lines: 66 66 100.0 %
Date: 2024-12-05 08:52:37 Branches: 62 62 100.0 %

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
/**   Vertical 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_vertical_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 up or down the vertical list by pages.          */
45
/*                                                                        */
46
/*  INPUT                                                                 */
47
/*                                                                        */
48
/*    list                                  Vertical 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_vertical_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
6
static VOID _gx_vertical_list_invisible_page_scroll(GX_VERTICAL_LIST *list, INT num_pages)
73
{
74
INT maximum_scroll_pages;
75
76
6
    if (!(list -> gx_widget_style & GX_STYLE_WRAP))
77
    {
78
79
        /* Wrap style is not applied, need to calculate scroll limit.  */
80
4
        if (num_pages < 0)
81
        {
82
83
            /* Calculate maximum up scroll num_pages.  */
84
2
            maximum_scroll_pages = (list -> gx_vertical_list_total_rows - list -> gx_vertical_list_top_index - list -> gx_vertical_list_child_count);
85
2
            maximum_scroll_pages /= list -> gx_vertical_list_child_count;
86
87
            /* Remain one page for normal scroll routine. */
88
2
            if (maximum_scroll_pages >= 1)
89
            {
90
1
                maximum_scroll_pages--;
91
            }
92
93
2
            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
2
            maximum_scroll_pages = list -> gx_vertical_list_top_index / list -> gx_vertical_list_child_count;
103
104
            /* Remain one page for normal scroll routine. */
105
2
            if (maximum_scroll_pages >= 1)
106
            {
107
1
                maximum_scroll_pages--;
108
            }
109
110
2
            if (maximum_scroll_pages < num_pages)
111
            {
112
1
                num_pages = maximum_scroll_pages;
113
            }
114
        }
115
    }
116
117
6
    if (num_pages)
118
    {
119
120
        /* Update top index according to scroll num_pages.  */
121
4
        list -> gx_vertical_list_top_index -= num_pages * list -> gx_vertical_list_child_count;
122
123
4
        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_vertical_list_top_index >= list -> gx_vertical_list_total_rows)
130
                {
131
96
                    list -> gx_vertical_list_top_index -= list -> gx_vertical_list_total_rows;
132
                }
133
            }
134
            else
135
            {
136
98
                while (list -> gx_vertical_list_top_index < 0)
137
                {
138
97
                    list -> gx_vertical_list_top_index += list -> gx_vertical_list_total_rows;
139
                }
140
            }
141
        }
142
    }
143
6
}
144
145
/**************************************************************************/
146
/*                                                                        */
147
/*  FUNCTION                                               RELEASE        */
148
/*                                                                        */
149
/*    _gx_vertical_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
/*    vertical_list                         Vertical list widget control  */
162
/*                                            block                       */
163
/*    amount                                Shifting value                */
164
/*                                                                        */
165
/*  OUTPUT                                                                */
166
/*                                                                        */
167
/*    None                                                                */
168
/*                                                                        */
169
/*  CALLS                                                                 */
170
/*                                                                        */
171
/*    _gx_widget_scroll_shift               Shift a widget                */
172
/*    _gx_vertical_list_up_wrap             Scroll up the vertical list   */
173
/*    _gx_vertical_list_down_wrap           Scroll down the vertical list */
174
/*    _gx_widget_block_move                 Widget block move             */
175
/*                                                                        */
176
/*  CALLED BY                                                             */
177
/*                                                                        */
178
/*    _gx_vertical_list_event_process       Vertical list event process   */
179
/*                                                                        */
180
/*  RELEASE HISTORY                                                       */
181
/*                                                                        */
182
/*    DATE              NAME                      DESCRIPTION             */
183
/*                                                                        */
184
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
185
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
186
/*                                            resulting in version 6.1    */
187
/*  08-02-2021     Ting Zhu                 Modified comment(s),          */
188
/*                                            fixed scroll overflow issue,*/
189
/*                                            resulting in version 6.1.8  */
190
/*                                                                        */
191
/**************************************************************************/
192
711
VOID _gx_vertical_list_scroll(GX_VERTICAL_LIST *list, INT amount)
193
{
194
GX_WIDGET    *child;
195
GX_WIDGET    *last_child;
196
GX_RECTANGLE  block;
197
GX_SCROLLBAR *scroll;
198
711
GX_BOOL       do_block_move = GX_TRUE;
199
711
GX_BOOL       reuse_child_widgets = GX_FALSE;
200
INT           page_size;
201
INT           num_pages;
202
203
711
    if (!amount)
204
    {
205
18
        return;
206
    }
207
208
695
    if ((list -> gx_vertical_list_callback != GX_NULL) &&
209
686
        (list -> gx_vertical_list_visible_rows < list -> gx_vertical_list_total_rows) &&
210

684
        ((list -> gx_vertical_list_child_count < list -> gx_vertical_list_total_rows) || (list -> gx_widget_style & GX_STYLE_WRAP)))
211
    {
212
680
        reuse_child_widgets = GX_TRUE;
213
214
        /* Calculate the page size.  */
215
680
        page_size = (list -> gx_vertical_list_child_height * list -> gx_vertical_list_child_count);
216
217
680
        if (!page_size)
218
        {
219
2
            return;
220
        }
221
222
        /* Calculate the number of pages to be scrolled.  */
223
678
        if (amount < 0)
224
        {
225
500
            num_pages = (amount + page_size) / page_size;
226
        }
227
        else
228
        {
229
178
            num_pages = (amount - page_size) / page_size;
230
        }
231
232
678
        if (num_pages)
233
        {
234
235
            /* Calculate the remainning scroll amount.  */
236
6
            amount -= (num_pages * page_size);
237
238
            /* Scroll pages.  */
239
6
            _gx_vertical_list_invisible_page_scroll(list, num_pages);
240
        }
241
    }
242
243
    /* first shift my child widgets */
244
693
    child = list -> gx_widget_first_child;
245
246
7281
    while (child)
247
    {
248
6588
        if (!(child -> gx_widget_status & GX_STATUS_NONCLIENT))
249
        {
250
6002
            _gx_widget_scroll_shift(child, 0, amount, GX_TRUE);
251
        }
252
6588
        child = child -> gx_widget_next;
253
    }
254
255
    /* next check to see if we need to wrap any child widgets */
256
257
693
    if (reuse_child_widgets)
258
    {
259
        /* this means we have fewer children than list rows, so we
260
           need to move and re-use the child widgets
261
         */
262
678
        if (amount < 0)
263
        {
264
500
            _gx_vertical_list_up_wrap(list);
265
        }
266
        else
267
        {
268
178
            _gx_vertical_list_down_wrap(list);
269
        }
270
    }
271
272
693
    _gx_window_scrollbar_find((GX_WINDOW *)list, GX_TYPE_VERTICAL_SCROLL, &scroll);
273
274
693
    if (scroll)
275
    {
276
586
        _gx_scrollbar_reset(scroll, GX_NULL);
277
    }
278
279
693
    if (list -> gx_widget_status & GX_STATUS_VISIBLE)
280
    {
281
687
        block = list -> gx_window_client;
282
283
687
        if (!(list -> gx_widget_style & (GX_STYLE_WRAP | GX_STYLE_TRANSPARENT)) &&
284
586
            (list -> gx_widget_style & GX_STYLE_BORDER_THIN))
285
        {
286
552
            child = _gx_widget_first_client_child_get((GX_WIDGET *)list);
287
552
            last_child = _gx_widget_last_client_child_get((GX_WIDGET *)list);
288
289
552
            if (child)
290
            {
291
551
                if ((child -> gx_widget_size.gx_rectangle_top > block.gx_rectangle_top ||
292
466
                     last_child -> gx_widget_size.gx_rectangle_bottom < block.gx_rectangle_bottom))
293
                {
294
                    /* If the widget has thin border, the round corder of the border
295
                       will cover the client area, block move will cause trouble. */
296
140
                    _gx_system_dirty_mark((GX_WIDGET *)list);
297
140
                    do_block_move = GX_FALSE;
298
                }
299
            }
300
        }
301
302
687
        if (do_block_move)
303
        {
304
547
            _gx_widget_block_move((GX_WIDGET *)list, &block, 0, amount);
305
        }
306
    }
307
}
308