A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 265 lines 6.9 kB view raw
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}