A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) Markus Braun (2002)
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "scrollbar.h"
23#include "config.h"
24#include "limits.h"
25#include "bmp.h"
26
27/* calculates the start and size of the knob */
28static void scrollbar_helper(int min_shown, int max_shown, int items,
29 int inner_len, int *size, int *start)
30{
31 int min, max, range;
32
33 /* min should be min */
34 if(min_shown < max_shown) {
35 min = min_shown;
36 max = max_shown;
37 }
38 else {
39 min = max_shown;
40 max = min_shown;
41 }
42
43 /* limit min and max */
44 if(min < 0)
45 min = 0;
46 if(min > items)
47 min = items;
48
49 if(max < 0)
50 max = 0;
51 if(max > items)
52 max = items;
53
54 range = max - min;
55
56 /* avoid overflows */
57 while (items > (INT_MAX / inner_len)) {
58 items >>= 1;
59 range >>= 1;
60 }
61
62 /* calc start and end of the knob */
63 if (items > 0 && items > range) {
64 *size = inner_len * range / items;
65 if (*size == 0) { /* width of knob is null */
66 *size = 1;
67 *start = (inner_len - 1) * min / items;
68 } else {
69 *start = (inner_len - *size) * min / (items - range);
70 }
71 } else { /* if null draw full bar */
72 *size = inner_len;
73 *start = 0;
74 }
75
76 return;
77}
78
79void gui_scrollbar_draw(struct screen * screen, int x, int y,
80 int width, int height, int items,
81 int min_shown, int max_shown,
82 unsigned flags)
83{
84 int inner_x, inner_y, inner_wd, inner_ht, inner_len;
85 int start, size;
86#ifdef HAVE_LCD_COLOR
87 int infill;
88#endif
89
90 if (flags & INVERTFILL)
91 {
92 min_shown = items - max_shown;
93 max_shown = items;
94 }
95
96 if (flags & BORDER_NOFILL)
97 {
98 inner_x = x;
99 inner_y = y;
100 inner_wd = width;
101 inner_ht = height;
102 }
103 else
104 {
105 inner_x = x + 1;
106 inner_y = y + 1;
107 inner_wd = width - 2;
108 inner_ht = height - 2;
109 }
110 /* Boundary check to make sure that height is reasonable, otherwise nothing
111 * to do
112 */
113 if ((inner_wd | inner_ht) < 0)
114 return;
115
116 if (flags & HORIZONTAL)
117 inner_len = inner_wd;
118 else
119 inner_len = inner_ht;
120
121 scrollbar_helper(min_shown, max_shown, items, inner_len, &size, &start);
122
123 /* draw box */
124 if (!(flags & BORDER_NOFILL))
125 {
126#ifdef HAVE_LCD_COLOR
127 /* must avoid corners if case of (flags & FOREGROUND) */
128 screen->hline(inner_x, x + inner_wd, y);
129 screen->hline(inner_x, x + inner_wd, y + height - 1);
130 screen->vline(x, inner_y, y + inner_ht);
131 screen->vline(x + width - 1, inner_y, y + inner_ht);
132#else
133 screen->drawrect(x, y, width, height);
134#endif
135 }
136 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
137
138#ifdef HAVE_LCD_COLOR
139 infill = flags & (screen->depth > 1 ? INNER_FILL_MASK : INNER_FILL);
140
141 if (!(flags & FOREGROUND))
142 {
143#endif
144 /* clear corner pixels */
145 screen->drawpixel(x, y);
146 screen->drawpixel(x + width - 1, y);
147 screen->drawpixel(x, y + height - 1);
148 screen->drawpixel(x + width - 1, y + height - 1);
149
150#ifdef HAVE_LCD_COLOR
151 if (infill != INNER_BGFILL)
152 infill = INNER_FILL;
153 }
154
155 if (infill == INNER_FILL)
156#endif
157 {
158 /* clear pixels in progress bar */
159 screen->fillrect(inner_x, inner_y, inner_wd, inner_ht);
160 }
161
162 screen->set_drawmode(DRMODE_SOLID);
163
164 if (flags & INNER_NOFILL)
165 return;
166
167#ifdef HAVE_LCD_COLOR
168 if (infill == INNER_BGFILL)
169 {
170 /* fill inner area with current background color */
171 unsigned fg = screen->get_foreground();
172 screen->set_foreground(screen->get_background());
173 screen->fillrect(inner_x, inner_y, inner_wd, inner_ht);
174 screen->set_foreground(fg);
175 }
176#endif
177
178 if (flags & HORIZONTAL)
179 {
180 inner_x += start;
181 inner_wd = size;
182 }
183 else
184 {
185 inner_y += start;
186 inner_ht = size;
187 }
188
189 screen->fillrect(inner_x, inner_y, inner_wd, inner_ht);
190}
191
192void gui_bitmap_scrollbar_draw(struct screen * screen, struct bitmap *bm, int x, int y,
193 int width, int height, int items,
194 int min_shown, int max_shown,
195 unsigned flags)
196{
197 int start;
198 int size;
199 int inner_len;
200 int startx = 0, starty = 0;
201
202 screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
203
204 /* clear pixels in progress bar */
205 if ((flags&DONT_CLEAR_EXCESS) == 0)
206 screen->fillrect(x, y, width, height);
207
208 screen->set_drawmode(DRMODE_SOLID);
209
210 if (flags & INNER_NOFILL)
211 return;
212
213 if (flags & INVERTFILL)
214 {
215 min_shown = items - max_shown;
216 max_shown = items;
217 }
218
219 if (flags & HORIZONTAL)
220 inner_len = width;
221 else
222 inner_len = height;
223
224 scrollbar_helper(min_shown, max_shown, items, inner_len, &size, &start);
225
226 if (flags & HORIZONTAL) {
227 x += start;
228 width = size;
229 if (flags & INVERTFILL)
230 startx = start;
231 } else {
232 y += start;
233 height = size;
234 if (flags & INVERTFILL)
235 starty = start;
236 }
237
238 if (bm->width < startx)
239 width = 0;
240 else if (bm->width < startx + width)
241 width = bm->width - startx;
242 if (bm->height < starty)
243 height = 0;
244 else if (bm->height < starty + height)
245 height = bm->height - starty;
246
247 screen->bmp_part(bm, startx, starty, x, y, width, height);
248}
249
250void show_busy_slider(struct screen *s, int x, int y, int width, int height)
251{
252 static int start = 0, dir = 1;
253 gui_scrollbar_draw(s, x, y, width, height, 100,
254 start, start+20, HORIZONTAL);
255#if NB_SCREENS > 1
256 if (s->screen_type == SCREEN_MAIN)
257#endif
258 {
259 start += (dir*2);
260 if (start > 79)
261 dir = -1;
262 else if (start < 1)
263 dir = 1;
264 }
265}