1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) Jonathan Gordon (2006)
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 ****************************************************************************/
27 #include "screen_access.h"
32 #include "scrollbar.h"
37 #include "color_picker.h"
39 /* structure for color info */
42 unsigned color
; /* native color value */
45 unsigned char rgb_val
[6]; /* access to components as array */
48 unsigned char r
; /* native red value */
49 unsigned char g
; /* native green value */
50 unsigned char b
; /* native blue value */
51 unsigned char red
; /* 8 bit red value */
52 unsigned char green
; /* 8 bit green value */
53 unsigned char blue
; /* 8 bit blue value */
54 } __attribute__ ((__packed__
)); /* assume byte packing */
59 /* list of primary colors */
62 static const fb_data prim_rgb
[][3] =
64 /* Foreground colors for sliders */
66 LCD_RGBPACK(255, 0, 0),
67 LCD_RGBPACK( 0, 255, 0),
68 LCD_RGBPACK( 0, 0, 255),
70 /* Fill colors for sliders */
72 LCD_RGBPACK( 85, 0, 0),
73 LCD_RGBPACK( 0, 85, 0),
74 LCD_RGBPACK( 0, 0, 85),
78 /* maximum values for components */
79 static const unsigned char rgb_max
[3] =
86 /* Unpacks the color value into native rgb values and 24 bit rgb values */
87 static void unpack_rgb(struct rgb_pick
*rgb
)
89 unsigned color
= _LCD_UNSWAP_COLOR(rgb
->color
);
90 rgb
->red
= _RGB_UNPACK_RED(color
);
91 rgb
->green
= _RGB_UNPACK_GREEN(color
);
92 rgb
->blue
= _RGB_UNPACK_BLUE(color
);
93 rgb
->r
= _RGB_UNPACK_RED_LCD(color
);
94 rgb
->g
= _RGB_UNPACK_GREEN_LCD(color
);
95 rgb
->b
= _RGB_UNPACK_BLUE_LCD(color
);
98 /* Packs the native rgb colors into a color value */
99 static inline void pack_rgb(struct rgb_pick
*rgb
)
101 rgb
->color
= LCD_RGBPACK_LCD(rgb
->r
, rgb
->g
, rgb
->b
);
104 /* Returns LCD_BLACK if the color is above a threshold brightness
105 else return LCD_WHITE */
106 static inline unsigned get_black_or_white(const struct rgb_pick
*rgb
)
108 return (2*rgb
->red
+ 5*rgb
->green
+ rgb
->blue
) >= 1024 ?
109 LCD_BLACK
: LCD_WHITE
;
112 #define MARGIN_LEFT 0 /* Left margin of screen */
113 #define MARGIN_TOP 2 /* Top margin of screen */
114 #define MARGIN_RIGHT 0 /* Right margin of screen */
115 #define MARGIN_BOTTOM 6 /* Bottom margin of screen */
116 #define SLIDER_MARGIN_LEFT 2 /* Gap to left of sliders */
117 #define SLIDER_MARGIN_RIGHT 2 /* Gap to right of sliders */
118 #define TITLE_MARGIN_BOTTOM 4 /* Space below title bar */
119 #define SELECTOR_LR_MARGIN 0 /* Margin between ">" and text */
120 #define SELECTOR_TB_MARGIN 1 /* Margin on top and bottom of selector */
121 #define SWATCH_TOP_MARGIN 4 /* Space between last slider and swatch */
122 #define SELECTOR_WIDTH get_icon_width(display->screen_type)
123 #define SELECTOR_HEIGHT 8 /* Height of > and < bitmaps */
125 /* dunno why lcd_set_drawinfo should be left out of struct screen */
126 static void set_drawinfo(struct screen
*display
, int mode
,
127 unsigned foreground
, unsigned background
)
129 display
->set_drawmode(mode
);
130 if (display
->depth
> 1)
132 display
->set_foreground(foreground
);
133 display
->set_background(background
);
137 static void draw_screen(struct screen
*display
, char *title
,
138 struct rgb_pick
*rgb
, int row
)
140 unsigned text_color
= LCD_BLACK
;
141 unsigned background_color
= LCD_WHITE
;
145 int slider_left
, slider_width
;
146 bool display_three_rows
;
149 display
->clear_display();
151 if (display
->depth
> 1)
153 text_color
= display
->get_foreground();
154 background_color
= display
->get_background();
157 /* Find out if there's enough room for three sliders or just
158 enough to display the selected slider - calculate total height
159 of display with three sliders present */
161 display
->getheight() >=
163 display
->getcharheight()*4 + /* Title + 3 sliders */
164 TITLE_MARGIN_BOTTOM
+
165 SELECTOR_TB_MARGIN
*6 + /* 2 margins/slider */
168 /* Figure out widest label character in case they vary -
169 this function assumes labels are one character */
170 for (i
= 0, max_label_width
= 0; i
< 3; i
++)
172 buf
[0] = str(LANG_COLOR_RGB_LABELS
)[i
];
174 x
= display
->getstringsize(buf
, NULL
, NULL
);
175 if (x
> max_label_width
)
179 /* Draw title string */
180 set_drawinfo(display
, DRMODE_SOLID
, text_color
, background_color
);
181 display
->getstringsize(title
, &x
, &y
);
182 display
->putsxy((display
->getwidth() - x
) / 2, MARGIN_TOP
, title
);
184 /* Get slider positions and top starting position */
185 text_top
= MARGIN_TOP
+ y
+ TITLE_MARGIN_BOTTOM
+ SELECTOR_TB_MARGIN
;
186 slider_left
= MARGIN_LEFT
+ SELECTOR_WIDTH
+ SELECTOR_LR_MARGIN
+
187 max_label_width
+ SLIDER_MARGIN_LEFT
;
188 slider_width
= display
->getwidth() - slider_left
- SLIDER_MARGIN_RIGHT
-
189 display
->getcharwidth()*2 - SELECTOR_LR_MARGIN
-
190 SELECTOR_WIDTH
- MARGIN_RIGHT
;
192 for (i
= 0; i
< 3; i
++)
194 unsigned sb_flags
= HORIZONTAL
;
195 int mode
= DRMODE_SOLID
;
196 unsigned fg
= text_color
;
197 unsigned bg
= background_color
;
199 if (!display_three_rows
)
204 set_drawinfo(display
, DRMODE_SOLID
, text_color
,
207 if (global_settings
.cursor_style
!= 0)
209 /* Draw solid bar selection bar */
211 text_top
- SELECTOR_TB_MARGIN
,
213 display
->getcharheight() +
214 SELECTOR_TB_MARGIN
*2);
216 if (display
->depth
< 16)
218 sb_flags
|= FOREGROUND
| INNER_FILL
;
219 mode
|= DRMODE_INVERSEVID
;
222 else if (display_three_rows
)
224 /* Draw "> <" around sliders */
225 int top
= text_top
+ (display
->getcharheight() -
226 SELECTOR_HEIGHT
) / 2;
227 screen_put_iconxy(display
, MARGIN_LEFT
, top
, Icon_Cursor
);
228 screen_put_iconxy(display
,
229 display
->getwidth() - MARGIN_RIGHT
-
230 get_icon_width(display
->screen_type
),
234 if (display
->depth
>= 16)
236 sb_flags
|= FOREGROUND
| INNER_BGFILL
;
238 fg
= prim_rgb
[SB_PRIM
][i
];
239 bg
= prim_rgb
[SB_FILL
][i
];
243 set_drawinfo(display
, mode
, fg
, bg
);
246 buf
[0] = str(LANG_COLOR_RGB_LABELS
)[i
];
248 display
->putsxy(slider_left
- display
->getcharwidth() -
249 SLIDER_MARGIN_LEFT
, text_top
, buf
);
251 /* Draw color value */
252 snprintf(buf
, 3, "%02d", rgb
->rgb_val
[i
]);
253 display
->putsxy(slider_left
+ slider_width
+ SLIDER_MARGIN_RIGHT
,
257 gui_scrollbar_draw(display
,
259 text_top
+ display
->getcharheight() / 4,
261 display
->getcharheight() / 2,
267 /* Advance to next line */
268 text_top
+= display
->getcharheight() + 2*SELECTOR_TB_MARGIN
;
270 if (!display_three_rows
)
274 /* Format RGB: #rrggbb */
275 snprintf(buf
, sizeof(buf
), str(LANG_COLOR_RGB_VALUE
),
276 rgb
->red
, rgb
->green
, rgb
->blue
);
278 if (display
->depth
>= 16)
280 /* Display color swatch on color screens only */
281 int left
= MARGIN_LEFT
+ SELECTOR_WIDTH
+ SELECTOR_LR_MARGIN
;
282 int top
= text_top
+ SWATCH_TOP_MARGIN
;
283 int width
= display
->getwidth() - left
- SELECTOR_LR_MARGIN
-
284 SELECTOR_WIDTH
- MARGIN_RIGHT
;
285 int height
= display
->getheight() - top
- MARGIN_BOTTOM
;
287 /* Only draw if room */
288 if (height
>= display
->getcharheight() + 2)
290 display
->set_foreground(rgb
->color
);
291 display
->fillrect(left
, top
, width
, height
);
293 /* Draw RGB: #rrggbb in middle of swatch */
294 display
->set_drawmode(DRMODE_FG
);
295 display
->getstringsize(buf
, &x
, &y
);
296 display
->set_foreground(get_black_or_white(rgb
));
298 x
= left
+ (width
- x
) / 2;
299 y
= top
+ (height
- y
) / 2;
301 display
->putsxy(x
, y
, buf
);
302 display
->set_drawmode(DRMODE_SOLID
);
305 display
->set_foreground(text_color
);
306 display
->drawrect(left
, top
, width
, height
);
311 /* Display RGB value only centered on remaining display if room */
312 display
->getstringsize(buf
, &x
, &y
);
313 i
= text_top
+ SWATCH_TOP_MARGIN
;
315 if (i
+ y
<= display
->getheight() - MARGIN_BOTTOM
)
317 set_drawinfo(display
, DRMODE_SOLID
, text_color
, background_color
);
318 x
= (display
->getwidth() - x
) / 2;
319 y
= (i
+ display
->getheight() - MARGIN_BOTTOM
- y
) / 2;
320 display
->putsxy(x
, y
, buf
);
324 display
->setfont(FONT_UI
);
327 /* Be sure screen mode is reset */
328 set_drawinfo(display
, DRMODE_SOLID
, text_color
, background_color
);
331 #ifdef HAVE_TOUCHSCREEN
332 static int touchscreen_slider(struct rgb_pick
*rgb
, int *selected_slider
)
336 int slider_left
, slider_width
;
337 unsigned button
= action_get_touchscreen_press(&x
, &y
);
338 bool display_three_rows
;
340 struct screen
*display
= &screens
[SCREEN_MAIN
];
344 if (button
== BUTTON_NONE
)
346 /* same logic as draw_screen */
347 /* Figure out widest label character in case they vary -
348 this function assumes labels are one character */
349 for (i
= 0, max_label_width
= 0; i
< 3; i
++)
351 buf
[0] = str(LANG_COLOR_RGB_LABELS
)[i
];
353 x1
= display
->getstringsize(buf
, NULL
, NULL
);
354 if (x1
> max_label_width
)
355 max_label_width
= x1
;
357 /* Get slider positions and top starting position */
358 text_top
= MARGIN_TOP
+ display
->getcharheight() + TITLE_MARGIN_BOTTOM
+
360 slider_left
= MARGIN_LEFT
+ SELECTOR_WIDTH
+ SELECTOR_LR_MARGIN
+
361 max_label_width
+ SLIDER_MARGIN_LEFT
;
362 slider_width
= display
->getwidth() - slider_left
- SLIDER_MARGIN_RIGHT
-
363 display
->getcharwidth()*2 - SELECTOR_LR_MARGIN
-
364 SELECTOR_WIDTH
- MARGIN_RIGHT
;
366 display
->getheight() >=
368 display
->getcharheight()*4 + /* Title + 3 sliders */
369 TITLE_MARGIN_BOTTOM
+
370 SELECTOR_TB_MARGIN
*6 + /* 2 margins/slider */
372 if (y
< MARGIN_TOP
+display
->getcharheight())
374 if (button
== BUTTON_REL
)
375 return ACTION_STD_CANCEL
;
378 pressed_slider
= y
/display
->getcharheight();
379 if (pressed_slider
> (display_three_rows
?2:0))
381 if (button
== BUTTON_REL
)
382 return ACTION_STD_OK
;
384 if (pressed_slider
!= *selected_slider
)
385 *selected_slider
= pressed_slider
;
386 if (x
< slider_left
+slider_width
&&
390 rgb
->rgb_val
[pressed_slider
] =
391 (x
*rgb_max
[pressed_slider
]/(slider_width
-slider_left
));
399 returns true if USB was inserted, false otherwise
400 color is a pointer to the colour (in native format) to modify
401 set banned_color to -1 to allow all
403 bool set_color(struct screen
*display
, char *title
, unsigned *color
,
404 unsigned banned_color
)
406 int exit
= 0, slider
= 0;
419 draw_screen(display
, title
, &rgb
, slider
);
425 draw_screen(&screens
[i
], title
, &rgb
, slider
);
428 button
= get_action(CONTEXT_SETTINGS_COLOURCHOOSER
, TIMEOUT_BLOCK
);
429 #ifdef HAVE_TOUCHSCREEN
430 if (button
== ACTION_TOUCHSCREEN
)
431 button
= touchscreen_slider(&rgb
, &slider
);
436 case ACTION_STD_PREV
:
437 case ACTION_STD_PREVREPEAT
:
438 slider
= (slider
+ 2) % 3;
441 case ACTION_STD_NEXT
:
442 case ACTION_STD_NEXTREPEAT
:
443 slider
= (slider
+ 1) % 3;
446 case ACTION_SETTINGS_INC
:
447 case ACTION_SETTINGS_INCREPEAT
:
448 if (rgb
.rgb_val
[slider
] < rgb_max
[slider
])
449 rgb
.rgb_val
[slider
]++;
453 case ACTION_SETTINGS_DEC
:
454 case ACTION_SETTINGS_DECREPEAT
:
455 if (rgb
.rgb_val
[slider
] > 0)
456 rgb
.rgb_val
[slider
]--;
461 if (banned_color
!= (unsigned)-1 &&
462 banned_color
== rgb
.color
)
464 splash(HZ
*2, ID2P(LANG_COLOR_UNACCEPTABLE
));
471 case ACTION_STD_CANCEL
:
476 if (default_event_handler(button
) == SYS_USB_CONNECTED
)