Android:
[maemo-rb.git] / apps / gui / scrollbar.c
blob70d34176e122ad01abdb5ce090087335e4ac003b
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) Markus Braun (2002)
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "scrollbar.h"
23 #ifdef HAVE_LCD_BITMAP
24 #include "config.h"
25 #include "limits.h"
26 #include "bmp.h"
28 /* calculates the start and size of the knob */
29 static void scrollbar_helper(int min_shown, int max_shown, int items,
30 int inner_len, int *size, int *start)
32 int min, max, range;
34 /* min should be min */
35 if(min_shown < max_shown) {
36 min = min_shown;
37 max = max_shown;
39 else {
40 min = max_shown;
41 max = min_shown;
44 /* limit min and max */
45 if(min < 0)
46 min = 0;
47 if(min > items)
48 min = items;
50 if(max < 0)
51 max = 0;
52 if(max > items)
53 max = items;
55 range = max - min;
57 /* avoid overflows */
58 while (items > (INT_MAX / inner_len)) {
59 items >>= 1;
60 range >>= 1;
63 /* calc start and end of the knob */
64 if (items > 0 && items > range) {
65 *size = inner_len * range / items;
66 if (*size == 0) { /* width of knob is null */
67 *size = 1;
68 *start = (inner_len - 1) * min / items;
69 } else {
70 *start = (inner_len - *size) * min / (items - range);
72 } else { /* if null draw full bar */
73 *size = inner_len;
74 *start = 0;
77 return;
80 void gui_scrollbar_draw(struct screen * screen, int x, int y,
81 int width, int height, int items,
82 int min_shown, int max_shown,
83 unsigned flags)
85 int inner_x, inner_y, inner_wd, inner_ht, inner_len;
86 int start, size;
87 #ifdef HAVE_LCD_COLOR
88 int infill;
89 #endif
91 if (flags & INVERTFILL)
93 min_shown = items - max_shown;
94 max_shown = items;
97 inner_x = x + 1;
98 inner_y = y + 1;
99 inner_wd = width - 2;
100 inner_ht = height - 2;
102 /* Boundary check to make sure that height is reasonable, otherwise nothing
103 * to do
105 if ((inner_wd | inner_ht) < 0)
106 return;
108 if (flags & HORIZONTAL)
109 inner_len = inner_wd;
110 else
111 inner_len = inner_ht;
113 scrollbar_helper(min_shown, max_shown, items, inner_len, &size, &start);
115 /* draw box */
116 #ifdef HAVE_LCD_COLOR
117 /* must avoid corners if case of (flags & FOREGROUND) */
118 screen->hline(inner_x, x + inner_wd, y);
119 screen->hline(inner_x, x + inner_wd, y + height - 1);
120 screen->vline(x, inner_y, y + inner_ht);
121 screen->vline(x + width - 1, inner_y, y + inner_ht);
122 #else
123 screen->drawrect(x, y, width, height);
124 #endif
126 screen->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
128 #ifdef HAVE_LCD_COLOR
129 infill = flags & (screen->depth > 1 ? INNER_FILL_MASK : INNER_FILL);
131 if (!(flags & FOREGROUND))
133 #endif
134 /* clear corner pixels */
135 screen->drawpixel(x, y);
136 screen->drawpixel(x + width - 1, y);
137 screen->drawpixel(x, y + height - 1);
138 screen->drawpixel(x + width - 1, y + height - 1);
140 #ifdef HAVE_LCD_COLOR
141 if (infill != INNER_BGFILL)
142 infill = INNER_FILL;
145 if (infill == INNER_FILL)
146 #endif
148 /* clear pixels in progress bar */
149 screen->fillrect(inner_x, inner_y, inner_wd, inner_ht);
152 screen->set_drawmode(DRMODE_SOLID);
154 if (flags & INNER_NOFILL)
155 return;
157 #ifdef HAVE_LCD_COLOR
158 if (infill == INNER_BGFILL)
160 /* fill inner area with current background color */
161 unsigned fg = screen->get_foreground();
162 screen->set_foreground(screen->get_background());
163 screen->fillrect(inner_x, inner_y, inner_wd, inner_ht);
164 screen->set_foreground(fg);
166 #endif
168 if (flags & HORIZONTAL)
170 inner_x += start;
171 inner_wd = size;
173 else
175 inner_y += start;
176 inner_ht = size;
179 screen->fillrect(inner_x, inner_y, inner_wd, inner_ht);
182 void gui_bitmap_scrollbar_draw(struct screen * screen, struct bitmap *bm, int x, int y,
183 int width, int height, int items,
184 int min_shown, int max_shown,
185 unsigned flags)
187 int start;
188 int size;
189 int inner_len;
190 int startx = 0, starty = 0;
192 screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
194 /* clear pixels in progress bar */
195 if ((flags&DONT_CLEAR_EXCESS) == 0)
196 screen->fillrect(x, y, width, height);
198 screen->set_drawmode(DRMODE_SOLID);
200 if (flags & INNER_NOFILL)
201 return;
203 if (flags & INVERTFILL)
205 min_shown = items - max_shown;
206 max_shown = items;
209 if (flags & HORIZONTAL)
210 inner_len = width;
211 else
212 inner_len = height;
214 scrollbar_helper(min_shown, max_shown, items, inner_len, &size, &start);
216 if (flags & HORIZONTAL) {
217 x += start;
218 width = size;
219 if (flags & INVERTFILL)
220 startx = start;
221 } else {
222 y += start;
223 height = size;
224 if (flags & INVERTFILL)
225 starty = start;
228 if (bm->width < startx)
229 width = 0;
230 else if (bm->width < startx + width)
231 width = bm->width - startx;
232 if (bm->height < starty)
233 height = 0;
234 else if (bm->height < starty + height)
235 height = bm->height - starty;
237 #if LCD_DEPTH > 1
238 if (bm->format == FORMAT_MONO)
239 #endif
240 screen->mono_bitmap_part(bm->data, startx, starty,
241 bm->width, x, y, width, height);
242 #if LCD_DEPTH > 1
243 else
244 screen->transparent_bitmap_part((fb_data *)bm->data, startx, starty,
245 STRIDE(screen->screen_type,
246 bm->width, bm->height),
247 x, y, width, height);
248 #endif
251 void show_busy_slider(struct screen *s, int x, int y, int width, int height)
253 static int start = 0, dir = 1;
254 gui_scrollbar_draw(s, x, y, width, height, 100,
255 start, start+20, HORIZONTAL);
256 #if NB_SCREENS > 1
257 if (s->screen_type == SCREEN_MAIN)
258 #endif
260 start += (dir*2);
261 if (start > 79)
262 dir = -1;
263 else if (start < 1)
264 dir = 1;
268 #endif /* HAVE_LCD_BITMAP */