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 /**   Scroll Management (Scroll)                                          */
18 /**                                                                       */
19 /**************************************************************************/
20 
21 #define GX_SOURCE_CODE
22 
23 /* Include necessary system files.  */
24 
25 #include "gx_api.h"
26 #include "gx_system.h"
27 #include "gx_canvas.h"
28 #include "gx_context.h"
29 #include "gx_widget.h"
30 #include "gx_icon.h"
31 #include "gx_scrollbar.h"
32 #include "gx_utility.h"
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _gx_scrollbar_draw                                  PORTABLE C      */
39 /*                                                           6.3.0        */
40 /*  AUTHOR                                                                */
41 /*                                                                        */
42 /*    Kenneth Maxwell, Microsoft Corporation                              */
43 /*                                                                        */
44 /*  DESCRIPTION                                                           */
45 /*                                                                        */
46 /*    This function draws the specified scroll bar, which is a            */
47 /*      special type of widget.                                           */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    scrollbar                             Scrollbar widget to draw      */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    None                                                                */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _gx_context_brush_define              Define the brush for the      */
60 /*                                            context                     */
61 /*    _gx_context_brush_width_set           Set the width of the brush    */
62 /*    _gx_canvas_rectangle_draw             Draw rectangle                */
63 /*    _gx_context_pixelmap_get              Retrieve pixelmap image       */
64 /*    _gx_canvas_pixelmap_tile              Tile the canvas area with     */
65 /*                                            pixelmap                    */
66 /*    _gx_canvas_pixelmap_draw              Draw pixelmap                 */
67 /*    _gx_widget_width_get                  Retrieve the width of the     */
68 /*                                            widget                      */
69 /*    _gx_widget_height_get                 Retrieve the height of the    */
70 /*                                            widget                      */
71 /*    _gx_widget_children_draw              Draw children widgets         */
72 /*                                                                        */
73 /*  CALLED BY                                                             */
74 /*                                                                        */
75 /*    Application Code                                                    */
76 /*    GUIX Internal Code                                                  */
77 /*                                                                        */
78 /*  RELEASE HISTORY                                                       */
79 /*                                                                        */
80 /*    DATE              NAME                      DESCRIPTION             */
81 /*                                                                        */
82 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
83 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
84 /*                                            resulting in version 6.1    */
85 /*  10-31-2023     Ting Zhu                 Modified comment(s),          */
86 /*                                            improved logic,             */
87 /*                                            resulting in version 6.3.0  */
88 /*                                                                        */
89 /**************************************************************************/
_gx_scrollbar_draw(GX_SCROLLBAR * scrollbar)90 VOID  _gx_scrollbar_draw(GX_SCROLLBAR *scrollbar)
91 {
92 GX_PIXELMAP *map;
93 GX_VALUE     xpos;
94 GX_VALUE     ypos;
95 GX_VALUE     widget_width;
96 GX_VALUE     widget_height;
97 GX_RECTANGLE size;
98 GX_RECTANGLE old_dirty;
99 GX_COLOR     fill_color;
100 
101     if (scrollbar -> gx_widget_style & GX_STYLE_ENABLED)
102     {
103         if (scrollbar -> gx_widget_style & GX_STYLE_DRAW_SELECTED)
104         {
105             fill_color = scrollbar -> gx_widget_selected_fill_color;
106         }
107         else
108         {
109             fill_color = scrollbar -> gx_widget_normal_fill_color;
110         }
111     }
112     else
113     {
114         fill_color = scrollbar -> gx_widget_disabled_fill_color;
115     }
116 
117     if ((scrollbar -> gx_widget_style & GX_STYLE_TRANSPARENT) == 0)
118     {
119         size = scrollbar -> gx_widget_size;
120 
121         /* Draw background.  */
122         if (scrollbar -> gx_widget_style & GX_STYLE_BORDER_THIN)
123         {
124             _gx_context_brush_define(GX_COLOR_ID_SHADOW,
125                                      fill_color,
126                                      GX_BRUSH_SOLID_FILL);
127             _gx_context_brush_width_set(1);
128         }
129         else
130         {
131             _gx_context_brush_define(fill_color,
132                                      fill_color,
133                                      GX_BRUSH_SOLID_FILL);
134             _gx_context_brush_width_set(0);
135             _gx_canvas_rectangle_draw(&size);
136         }
137         _gx_canvas_rectangle_draw(&size);
138 
139         /* Draw pixelmaps.  */
140         _gx_context_pixelmap_get(scrollbar -> gx_scrollbar_appearance.gx_scroll_up_pixelmap, &map);
141 
142         if (map)
143         {
144             if (scrollbar -> gx_widget_type == GX_TYPE_VERTICAL_SCROLL)
145             {
146                 /* Draw up pixelmap.  */
147                 xpos = size.gx_rectangle_left;
148                 _gx_widget_width_get((GX_WIDGET *)scrollbar, &widget_width);
149                 xpos = (GX_VALUE)(xpos + (widget_width - map -> gx_pixelmap_width) / 2);
150 
151                 ypos = size.gx_rectangle_top;
152 
153                 size.gx_rectangle_top = (GX_VALUE)(size.gx_rectangle_top + map -> gx_pixelmap_height);
154             }
155             else
156             {
157                 /* Draw left pixelmap.  */
158                 xpos = size.gx_rectangle_left;
159 
160                 ypos = size.gx_rectangle_top;
161                 _gx_widget_height_get((GX_WIDGET *)scrollbar, &widget_height);
162                 ypos = (GX_VALUE)(ypos + (widget_height - map -> gx_pixelmap_height) / 2);
163 
164                 size.gx_rectangle_left = (GX_VALUE)(size.gx_rectangle_left + map -> gx_pixelmap_width);
165             }
166 
167             _gx_canvas_pixelmap_draw(xpos, ypos, map);
168         }
169 
170         _gx_context_pixelmap_get(scrollbar -> gx_scrollbar_appearance.gx_scroll_down_pixelmap, &map);
171 
172         if (map)
173         {
174             if (scrollbar -> gx_widget_type == GX_TYPE_VERTICAL_SCROLL)
175             {
176                 /* Draw down pixelmap.  */
177                 size.gx_rectangle_bottom = (GX_VALUE)(size.gx_rectangle_bottom - map -> gx_pixelmap_height);
178 
179                 xpos = size.gx_rectangle_left;
180                 _gx_widget_width_get((GX_WIDGET *)scrollbar, &widget_width);
181                 xpos = (GX_VALUE)(xpos + (widget_width - map -> gx_pixelmap_width) / 2);
182 
183                 ypos = size.gx_rectangle_bottom;
184             }
185             else
186             {
187                 /* Draw right pixelmap.  */
188                 size.gx_rectangle_right = (GX_VALUE)(size.gx_rectangle_right - map -> gx_pixelmap_width);
189 
190                 xpos = size.gx_rectangle_right;
191 
192                 ypos = size.gx_rectangle_top;
193                 _gx_widget_height_get((GX_WIDGET *)scrollbar, &widget_height);
194                 ypos = (GX_VALUE)(ypos + (widget_height - map -> gx_pixelmap_height) / 2);
195             }
196 
197             _gx_canvas_pixelmap_draw(xpos, ypos, map);
198         }
199 
200         _gx_context_pixelmap_get(scrollbar -> gx_scrollbar_appearance.gx_scroll_fill_pixelmap, &map);
201 
202         if (map)
203         {
204             /* Draw background pixelmap.  */
205             if (scrollbar -> gx_widget_style & GX_STYLE_TILE_BACKGROUND)
206             {
207                 _gx_canvas_pixelmap_tile(&size, map);
208             }
209             else
210             {
211                 xpos = size.gx_rectangle_left;
212                 _gx_widget_width_get((GX_WIDGET *)scrollbar, &widget_width);
213                 xpos = (GX_VALUE)(xpos + (widget_width - map -> gx_pixelmap_width) / 2);
214 
215                 ypos = size.gx_rectangle_top;
216                 _gx_widget_height_get((GX_WIDGET *)scrollbar, &widget_height);
217                 ypos = (GX_VALUE)(ypos + (widget_height - map -> gx_pixelmap_height) / 2);
218 
219                 /* Reset dirty area temporarily to avoid cover the end pixelmap area. */
220                 old_dirty = _gx_system_current_draw_context -> gx_draw_context_dirty;
221                 if(_gx_utility_rectangle_overlap_detect(&old_dirty, &size, &size) == GX_TRUE)
222                 {
223                     _gx_system_current_draw_context -> gx_draw_context_dirty = size;
224 
225                     _gx_canvas_pixelmap_draw(xpos, ypos, map);
226 
227                     /* Set dirty area back. */
228                     _gx_system_current_draw_context -> gx_draw_context_dirty = old_dirty;
229                 }
230             }
231         }
232     }
233 
234     /* Draw children widgets of prompt widget.  */
235     _gx_widget_children_draw((GX_WIDGET *)scrollbar);
236 }
237 
238