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_selected_set PORTABLE C */
37 /* 6.1.12 */
38 /* AUTHOR */
39 /* */
40 /* Kenneth Maxwell, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This service sets the list entry at the current list index. */
45 /* */
46 /* INPUT */
47 /* */
48 /* vertical_list Vertical list widget control */
49 /* block */
50 /* index Index based position of new */
51 /* list entry */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* status Completion status */
56 /* */
57 /* CALLS */
58 /* */
59 /* _gx_widget_first_client_child_get */
60 /* _gx_widget_next_client_child_get */
61 /* _gx_vertical_list_page_index_set */
62 /* _gx_widget_event_generate */
63 /* _gx_system_dirty_mark */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* Application Code */
68 /* _gx_drop_list_event_process Process drop list event */
69 /* */
70 /* RELEASE HISTORY */
71 /* */
72 /* DATE NAME DESCRIPTION */
73 /* */
74 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
75 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
76 /* resulting in version 6.1 */
77 /* 07-29-2022 Kenneth Maxwell Added support for GX_STYLE_ */
78 /* REPEAT_SELECT, */
79 /* resulting in version 6.1.12 */
80 /* */
81 /**************************************************************************/
_gx_vertical_list_selected_set(GX_VERTICAL_LIST * vertical_list,INT index)82 UINT _gx_vertical_list_selected_set(GX_VERTICAL_LIST *vertical_list, INT index)
83 {
84 GX_WIDGET *child;
85 GX_WIDGET *found = GX_NULL;
86 INT page_index = vertical_list -> gx_vertical_list_top_index;
87 INT top_index;
88 INT bottom_index;
89
90 if (vertical_list -> gx_vertical_list_selected == index)
91 {
92 if ((vertical_list -> gx_widget_style & GX_STYLE_REPEAT_SELECT) == 0)
93 {
94 return GX_SUCCESS;
95 }
96 }
97
98 if (index < 0)
99 {
100 _gx_vertical_list_selected_widget_get(vertical_list, &child);
101
102 if (child)
103 {
104 child -> gx_widget_style &= ~GX_STYLE_DRAW_SELECTED;
105 _gx_system_dirty_mark(child);
106 }
107 vertical_list -> gx_vertical_list_selected = index;
108 return GX_SUCCESS;
109 }
110
111 child = _gx_widget_first_client_child_get((GX_WIDGET *)vertical_list);
112
113 while (child && (child -> gx_widget_size.gx_rectangle_bottom <= vertical_list -> gx_widget_size.gx_rectangle_top))
114 {
115 page_index++;
116 child = _gx_widget_next_client_child_get(child);
117 }
118
119 top_index = vertical_list -> gx_vertical_list_top_index;
120 bottom_index = top_index + vertical_list -> gx_vertical_list_child_count - 1;
121
122 /* Reset page index when needed and calculate the child count from the top index to new index. */
123 if (bottom_index >= vertical_list -> gx_vertical_list_total_rows)
124 {
125 bottom_index -= vertical_list -> gx_vertical_list_total_rows;
126
127 if (index >= top_index)
128 {
129 page_index = index - vertical_list -> gx_vertical_list_top_index;
130 }
131 else if (index <= bottom_index)
132 {
133 page_index = vertical_list -> gx_vertical_list_total_rows + index - vertical_list -> gx_vertical_list_top_index;
134 }
135 else
136 {
137 _gx_vertical_list_page_index_set(vertical_list, index);
138 page_index = index - vertical_list -> gx_vertical_list_top_index;
139 }
140 }
141 else
142 {
143 if (index < top_index)
144 {
145 _gx_vertical_list_page_index_set(vertical_list, index);
146 }
147 else if (index > bottom_index)
148 {
149 _gx_vertical_list_page_index_set(vertical_list, index - vertical_list -> gx_vertical_list_visible_rows + 1);
150 }
151
152 page_index = index - vertical_list -> gx_vertical_list_top_index;
153 }
154
155 if (page_index < 0)
156 {
157 /* consider the situation that top index is bigger than current select index. */
158 page_index += vertical_list -> gx_vertical_list_total_rows;
159 }
160
161 child = _gx_widget_first_client_child_get((GX_WIDGET *)vertical_list);
162
163 /* Select new index and update widget draw style. */
164 while (child)
165 {
166 if (page_index == 0)
167 {
168 found = child;
169 vertical_list -> gx_vertical_list_selected = index;
170 _gx_vertical_list_selected_visible(vertical_list, found);
171 found -> gx_widget_style |= GX_STYLE_DRAW_SELECTED;
172 _gx_system_dirty_mark(found);
173
174 if (vertical_list -> gx_widget_id)
175 {
176 _gx_widget_event_generate((GX_WIDGET *)vertical_list, GX_EVENT_LIST_SELECT, vertical_list -> gx_vertical_list_selected);
177 }
178 }
179 else
180 {
181 if (child -> gx_widget_style & GX_STYLE_DRAW_SELECTED)
182 {
183 child -> gx_widget_style &= ~GX_STYLE_DRAW_SELECTED;
184 _gx_system_dirty_mark(child);
185 }
186 }
187 child = _gx_widget_next_client_child_get(child);
188 page_index--;
189 }
190
191 if (found)
192 {
193 return GX_SUCCESS;
194 }
195 return GX_FAILURE;
196 }
197
198