From 603f87fe3c0557cb31386fb89c0a49fb72102735 Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Sun, 26 Feb 2006 02:48:05 +0000 Subject: [PATCH] Foreground/Background colour settings. Based on patch #3050 by Jonathan Gordon, extended my me. The principle of the patch is that the three sliders contain the native ranges (currently 0..31, 0..63, 0..31), and the equivalent RGB888 colour is displayed underneath. The config block (and global_settings struct) contain the native value for the fg/bg colours (either RGB565 or RGB565SWAPPED), but the text .cfg files contain the RGB888 value written as 6 hex digits. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8840 a1c6a512-1295-4272-9138-f99709370657 --- apps/SOURCES | 1 + apps/gui/color_picker.c | 261 ++++++++++++++++++++++++++++++++++++++++ apps/gui/color_picker.h | 25 ++++ apps/gui/splash.h | 1 + apps/lang/english.lang | 30 +++++ apps/plugin.c | 5 + apps/settings.c | 61 +++++++++- apps/settings.h | 4 + apps/settings_menu.c | 41 +++++++ firmware/export/lcd.h | 9 ++ 10 files changed, 436 insertions(+), 2 deletions(-) create mode 100644 apps/gui/color_picker.c create mode 100644 apps/gui/color_picker.h diff --git a/apps/SOURCES b/apps/SOURCES index ef65789588..f34cac9654 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -58,6 +58,7 @@ recorder/peakmeter.c recorder/widgets.c #ifdef HAVE_LCD_COLOR recorder/backdrop.c +gui/color_picker.c #endif #endif #ifdef CONFIG_TUNER diff --git a/apps/gui/color_picker.c b/apps/gui/color_picker.c new file mode 100644 index 0000000000..2f851d269e --- /dev/null +++ b/apps/gui/color_picker.c @@ -0,0 +1,261 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: + * + * Copyright (C) Jonathan Gordon (2006) + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "stdarg.h" +#include "string.h" +#include "stdio.h" +#include "kernel.h" +#include "system.h" +#include "screen_access.h" +#include "debug.h" +#include "misc.h" +#include "settings.h" +#include "scrollbar.h" +#include "lang.h" + +#define TEXT_MARGIN display->char_width+2 +#define SLIDER_START 20 + +#if (CONFIG_KEYPAD == IRIVER_H300_PAD) +#define SLIDER_UP BUTTON_UP +#define SLIDER_DOWN BUTTON_DOWN +#define SLIDER_LEFT BUTTON_LEFT +#define SLIDER_RIGHT BUTTON_RIGHT +#define SLIDER_OK BUTTON_ON +#define SLIDER_CANCEL BUTTON_OFF + +#define SLIDER_RC_UP BUTTON_RC_REW +#define SLIDER_RC_DOWN BUTTON_RC_FF +#define SLIDER_RC_LEFT BUTTON_RC_SOURCE +#define SLIDER_RC_RIGHT BUTTON_RC_BITRATE +#define SLIDER_RC_OK BUTTON_RC_ON +#define SLIDER_RC_CANCEL BUTTON_RC_STOP + +#elif (CONFIG_KEYPAD == IPOD_4G_PAD) +#define SLIDER_UP BUTTON_LEFT +#define SLIDER_DOWN BUTTON_RIGHT +#define SLIDER_LEFT BUTTON_SCROLL_BACK +#define SLIDER_RIGHT BUTTON_SCROLL_FWD +#define SLIDER_OK BUTTON_SELECT +#define SLIDER_CANCEL BUTTON_MENU +#endif + +static const int max_val[3] = {LCD_MAX_RED,LCD_MAX_GREEN,LCD_MAX_BLUE}; + +static void draw_screen(struct screen *display, char *title, + int *rgb_val, int color, int row) +{ + int i; + char *textrgb = str(LANG_COLOR_RGB_LABELS), rgb_dummy[2] = {0,0}; + int text_top; + int text_centre, bg_col; + char buf[32]; + int slider_width = (display->width-SLIDER_START-(display->char_width*5)); + int background_color = global_settings.bg_color; + int text_color = global_settings.fg_color; + + display->clear_display(); + + if (display->depth > 1) { + display->set_foreground(text_color); + } + + i = display->getstringsize(title,0,0); + display->putsxy((display->width-i)/2,6,title ); + + for (i=0;i<3;i++) + { + text_top =display->char_height*((i*2)+2); + + if (i==row) + { + if (global_settings.invert_cursor) + { + display->fillrect(0,text_top-1,display->width,display->char_height+2); + bg_col = text_color; + } + else + { + display->putsxy(0,text_top,">"); + display->putsxy(display->width-TEXT_MARGIN,text_top,"<"); + bg_col = background_color; + } + if (display->depth > 1) + { + if (i==0) + display->set_foreground(LCD_RGBPACK(255, 0, 0)); + else if (i==1) + display->set_foreground(LCD_RGBPACK(0, 255, 0)); + else if (i==2) + display->set_foreground(LCD_RGBPACK(0 ,0 ,255)); + } + } + else + { + if (display->depth > 1) + display->set_foreground(text_color); + bg_col = background_color; + } + + if (display->depth > 1) + display->set_background(bg_col); + + text_centre = text_top+(display->char_height/2); + rgb_dummy[0] = textrgb[i]; + display->putsxy(TEXT_MARGIN,text_top,rgb_dummy); + snprintf(buf,3,"%02d",rgb_val[i]); + display->putsxy(display->width-(display->char_width*4),text_top,buf); + + text_top += display->char_height/4; + + gui_scrollbar_draw(display,SLIDER_START,text_top,slider_width, + display->char_height/2, + max_val[i],0,rgb_val[i],HORIZONTAL); + } + + if (display->depth > 1) { + display->set_background(background_color); + display->set_foreground(text_color); + } + + if (text_top + (display->char_height*2) < (LCD_HEIGHT-40-display->char_height)) + text_top += (display->char_height*2); + else text_top += (display->char_height); + + /* Display RGB: #rrggbb */ + snprintf(buf,sizeof(buf),str(LANG_COLOR_RGB_VALUE), + RGB_UNPACK_RED(color), + RGB_UNPACK_GREEN(color), + RGB_UNPACK_BLUE(color)); + + display->putsxy((LCD_WIDTH-(display->char_width*21))/2,text_top,buf); + + if (display->depth > 1) { + display->set_foreground(color); + display->fillrect(SLIDER_START,LCD_HEIGHT-40,slider_width,35); + + display->set_foreground(LCD_BLACK); + display->drawrect(SLIDER_START-1,LCD_HEIGHT-41,slider_width+2,37); + } + + display->update(); +} + +/*********** + set_color + returns true if USB was inserted, false otherwise + color is a pointer to the colour (in native format) to modify + ***********/ +bool set_color(struct screen *display,char *title, int* color) +{ + int exit = 0, button, slider=0; + int rgb_val[3]; /* native depth r,g,b*/; + int fgcolor = display->get_foreground(); + int newcolor = *color; + int i; + +#if LCD_PIXELFORMAT == RGB565 + rgb_val[0] = ((*color)&0xf800) >> 11; + rgb_val[1] = ((*color)&0x07e0) >> 5; + rgb_val[2] = ((*color)&0x001f); +#elif LCD_PIXELFORMAT == RGB565SWAPPED + rgb_val[0] = ((swap16(*color))&0xf800) >> 11; + rgb_val[1] = ((swap16(*color))&0x07e0) >> 5; + rgb_val[2] = ((swap16(*color))&0x001f); +#endif + + while (!exit) + { + /* We need to maintain three versions of the colour: + + rgb_val[3] - the native depth RGB values + newcolor - the native format packed colour + */ + +#if LCD_PIXELFORMAT == RGB565 + newcolor = (rgb_val[0] << 11) | (rgb_val[1] << 5) | (rgb_val[2]); +#elif LCD_PIXELFORMAT == RGB565SWAPPED + newcolor = swap16((rgb_val[0] << 11) | (rgb_val[1] << 5) | (rgb_val[2])); +#endif + FOR_NB_SCREENS(i) + draw_screen(&screens[i], title, rgb_val, newcolor, slider); + + button = button_get(true); + switch (button) + { + case SLIDER_UP: +#ifdef HAVE_LCD_REMOTE + case SLIDER_RC_UP: +#endif + slider = (slider+2)%3; + break; + + case SLIDER_DOWN: +#ifdef HAVE_LCD_REMOTE + case SLIDER_RC_DOWN: +#endif + slider = (slider+1)%3; + break; + + case SLIDER_RIGHT: + case SLIDER_RIGHT|BUTTON_REPEAT: +#ifdef HAVE_LCD_REMOTE + case SLIDER_RC_RIGHT: + case SLIDER_RC_RIGHT|BUTTON_REPEAT: +#endif + if (rgb_val[slider] < max_val[slider]) + rgb_val[slider]++; + break; + + case SLIDER_LEFT: + case SLIDER_LEFT|BUTTON_REPEAT: +#ifdef HAVE_LCD_REMOTE + case SLIDER_RC_LEFT: + case SLIDER_RC_LEFT|BUTTON_REPEAT: +#endif + if (rgb_val[slider] > 0) + rgb_val[slider]--; + break; + + case SLIDER_OK: +#ifdef HAVE_LCD_REMOTE + case SLIDER_RC_OK: +#endif + *color = newcolor; + exit = 1; + break; + + case SLIDER_CANCEL: +#ifdef HAVE_LCD_REMOTE + case SLIDER_RC_CANCEL: +#endif + exit = 1; + break; + + default: + if(default_event_handler(button) == SYS_USB_CONNECTED) { + display->set_foreground(fgcolor); + return true; + } + break; + } + } + display->set_foreground(fgcolor); + + return false; +} diff --git a/apps/gui/color_picker.h b/apps/gui/color_picker.h new file mode 100644 index 0000000000..1fa35f0c70 --- /dev/null +++ b/apps/gui/color_picker.h @@ -0,0 +1,25 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) Jonathan Gordon (2006) + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "screen_access.h" + +#ifdef HAVE_LCD_COLOR /* this file is a bit useless on non color lcds.. */ + +bool set_color(struct screen *display,char *title, int* color); + +#endif diff --git a/apps/gui/splash.h b/apps/gui/splash.h index 9d8def16f8..b1ac15c537 100644 --- a/apps/gui/splash.h +++ b/apps/gui/splash.h @@ -20,6 +20,7 @@ #ifndef _GUI_SPLASH_H_ #define _GUI_SPLASH_H_ #include "screen_access.h" + /* * Puts a splash message on the given screen for a given period * - screen : the screen to put the splash on diff --git a/apps/lang/english.lang b/apps/lang/english.lang index dcb7c07cc6..bd7973ef73 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -3748,3 +3748,33 @@ desc: in record settings menu. eng: "Main and remote unit" voice: "Main and remote unit" new: + +id: LANG_COLOR_RGB_LABELS +desc: what to show for the 'R' 'G' 'B' ONE LETTER EACH +eng: "RGB" +voice: +new: + +id: LANG_COLOR_RGB_VALUE +desc: in color screen +eng: "RGB: %02X%02X%02X" +voice: +new: + +id: LANG_BACKGROUND_COLOR +desc: menu entry to set the background color +eng: "Background Colour" +voice: +new: + +id: LANG_FOREGROUND_COLOR +desc: menu entry to set the foreground color +eng: "Foreground Colour" +voice: +new: + +id: LANG_RESET_COLORS +desc: menu +eng: "Reset Colours" +voice: +new: diff --git a/apps/plugin.c b/apps/plugin.c index c9fb0ac8f5..61396b4357 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -515,7 +515,12 @@ int plugin_load(const char* plugin, void* parameter) #ifdef HAVE_LCD_BITMAP #if LCD_DEPTH > 1 +#ifdef HAVE_LCD_COLOR + lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color, + global_settings.bg_color); +#else lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG); +#endif #else /* LCD_DEPTH == 1 */ lcd_set_drawmode(DRMODE_SOLID); #endif /* LCD_DEPTH */ diff --git a/apps/settings.c b/apps/settings.c index 72939e5aac..5a42b17651 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -89,7 +89,7 @@ const char rec_base_directory[] = REC_BASE_DIR; #include "dsp.h" #endif -#define CONFIG_BLOCK_VERSION 36 +#define CONFIG_BLOCK_VERSION 37 #define CONFIG_BLOCK_SIZE 512 #define RTC_BLOCK_SIZE 44 @@ -122,7 +122,7 @@ struct bit_entry int default_val; /* min 15 bit */ /* variable name in a .cfg file, NULL if not to be saved */ const char* cfg_name; - /* set of values, or NULL for a numerical value */ + /* set of values, "rgb" for a color, or NULL for a numerical value */ const char* cfg_val; }; @@ -545,6 +545,10 @@ static const struct bit_entry hd_bits[] = {2, S_O(cliplight), 0, "cliplight", "off,main,both,remote" }, #endif /* CONFIG_BACKLIGHT */ #endif /*HAVE_RECORDING*/ +#ifdef HAVE_LCD_COLOR + {LCD_DEPTH,S_O(fg_color),LCD_DEFAULT_FG,"foreground color","rgb"}, + {LCD_DEPTH,S_O(bg_color),LCD_DEFAULT_BG,"background color","rgb"}, +#endif /* If values are just added to the end, no need to bump the version. */ /* new stuff to be added at the end */ @@ -596,6 +600,39 @@ static void set_bits( p[long_index] = (p[long_index] & ~mask) | (value << bit_index); } +#ifdef HAVE_LCD_COLOR +/* + * Helper function to convert a string of 6 hex digits to a native colour + */ + +#define hex2dec(c) (((c) >= '0' && ((c) <= '9')) ? (toupper(c)) - '0' : \ + (toupper(c)) - 'A' + 10) + +int hex_to_rgb(const char* hex) +{ int ok = 1; + int i; + int red, green, blue; + + if (strlen(hex) == 6) { + for (i=0; i < 6; i++ ) { + if (!isxdigit(hex[i])) { + ok=0; + break; + } + } + + if (ok) { + red = (hex2dec(hex[0]) << 4) | hex2dec(hex[1]); + green = (hex2dec(hex[2]) << 4) | hex2dec(hex[3]); + blue = (hex2dec(hex[4]) << 4) | hex2dec(hex[5]); + return LCD_RGBPACK(red,green,blue); + } + } + + return 0; +} +#endif + /* * Calculates the checksum for the config block and returns it */ @@ -1013,6 +1050,8 @@ void settings_apply(void) } else { lcd_set_backdrop(NULL); } + screens[SCREEN_MAIN].set_foreground(global_settings.fg_color); + screens[SCREEN_MAIN].set_background(global_settings.bg_color); #endif #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) @@ -1225,6 +1264,12 @@ static int load_cfg_table( { /* numerical value, just convert the string */ val = atoi(value); } +#if HAVE_LCD_COLOR + else if (!strncasecmp(p_table[i].cfg_val,"rgb",4)) + { + val = hex_to_rgb(value); + } +#endif else { /* set of string values, find the index */ const char* item; @@ -1410,6 +1455,15 @@ static void save_cfg_table(const struct bit_entry* p_table, int count, int fd) { fdprintf(fd, "%s: %ld\r\n", p_run->cfg_name, value); } +#ifdef HAVE_LCD_COLOR + else if (!strcasecmp(p_run->cfg_val, "rgb")) + { + fdprintf(fd, "%s: %02x%02x%02x\r\n", p_run->cfg_name, + (int)RGB_UNPACK_RED(value), + (int)RGB_UNPACK_GREEN(value), + (int)RGB_UNPACK_BLUE(value)); + } +#endif else /* write as item */ { const char* p = p_run->cfg_val; @@ -1566,6 +1620,9 @@ void settings_reset(void) { global_settings.lang_file[0] = '\0'; #ifdef HAVE_LCD_COLOR global_settings.backdrop_file[0] = '\0'; + + global_settings.fg_color = LCD_DEFAULT_FG; + global_settings.bg_color = LCD_DEFAULT_BG; #endif } diff --git a/apps/settings.h b/apps/settings.h index 753f067234..87020a1094 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -465,6 +465,10 @@ struct user_settings bool warnon_erase_dynplaylist; /* warn when erasing dynamic playlist */ bool scroll_paginated; /* 0=dont 1=do */ +#ifdef HAVE_LCD_COLOR + int bg_color; /* background color native format */ + int fg_color; /* foreground color native format */ +#endif }; enum optiontype { INT, BOOL }; diff --git a/apps/settings_menu.c b/apps/settings_menu.c index 6ac0b6feb2..d089960e9d 100644 --- a/apps/settings_menu.c +++ b/apps/settings_menu.c @@ -54,6 +54,7 @@ #include "splash.h" #include "yesno.h" #include "list.h" +#include "color_picker.h" #ifdef HAVE_LCD_BITMAP #include "peakmeter.h" @@ -319,6 +320,43 @@ static bool clear_main_backdrop(void) lcd_set_backdrop(NULL); return true; } + +/** + * Menu for fore/back colors + */ +static bool set_fg_color(void) +{ + bool res; + + res = set_color(&screens[SCREEN_MAIN],str(LANG_FOREGROUND_COLOR), + &global_settings.fg_color); + + screens[SCREEN_MAIN].set_foreground(global_settings.fg_color); + + return res; +} + +static bool set_bg_color(void) +{ + bool res; + + res = set_color(&screens[SCREEN_MAIN],str(LANG_BACKGROUND_COLOR), + &global_settings.bg_color); + + screens[SCREEN_MAIN].set_background(global_settings.bg_color); + + return res; +} + +static bool reset_color(void) +{ + global_settings.fg_color = LCD_DEFAULT_FG; + global_settings.bg_color = LCD_DEFAULT_BG; + + screens[SCREEN_MAIN].set_foreground(global_settings.fg_color); + screens[SCREEN_MAIN].set_background(global_settings.bg_color); + return false; +} #endif /** @@ -1586,6 +1624,9 @@ static bool lcd_settings_menu(void) #endif #ifdef HAVE_LCD_COLOR { ID2P(LANG_CLEAR_BACKDROP), clear_main_backdrop }, + { ID2P(LANG_BACKGROUND_COLOR), set_bg_color }, + { ID2P(LANG_FOREGROUND_COLOR), set_fg_color }, + { ID2P(LANG_RESET_COLORS), reset_color }, #endif }; diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index ba0e216990..6f7fef94ee 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h @@ -150,6 +150,9 @@ typedef void lcd_fastpixelfunc_type(fb_data *address); #define LCD_MAX_RED 31 #define LCD_MAX_GREEN 63 #define LCD_MAX_BLUE 31 +#define _RGB_UNPACK_RED(x) ((((x) >> 8) & 0xf8) | ((x) >> 13)) +#define _RGB_UNPACK_GREEN(x) ((((x) >> 3) & 0xfc) | (((x) >> 9) & 0x03)) +#define _RGB_UNPACK_BLUE(x) ((((x) << 3) & 0xf8) | (((x) >> 2) & 0x07)) #define _RGBPACK(r, g, b) ( ((((r) * (31*257) + (127*257)) >> 16) << 11) \ |((((g) * (63*257) + (127*257)) >> 16) << 5) \ | (((b) * (31*257) + (127*257)) >> 16)) @@ -158,8 +161,14 @@ typedef void lcd_fastpixelfunc_type(fb_data *address); #if (LCD_PIXELFORMAT == RGB565SWAPPED) #define LCD_RGBPACK(r, g, b) ( ((_RGBPACK((r), (g), (b)) & 0xff00) >> 8) \ |((_RGBPACK((r), (g), (b)) & 0x00ff) << 8)) +#define RGB_UNPACK_RED(x) _RGB_UNPACK_RED(swap16(x)) +#define RGB_UNPACK_GREEN(x) _RGB_UNPACK_GREEN(swap16(x)) +#define RGB_UNPACK_BLUE(x) _RGB_UNPACK_BLUE(swap16(x)) #else #define LCD_RGBPACK(r, g, b) _RGBPACK((r), (g), (b)) +#define RGB_UNPACK_RED(x) _RGB_UNPACK_RED(x) +#define RGB_UNPACK_GREEN(x) _RGB_UNPACK_GREEN(x) +#define RGB_UNPACK_BLUE(x) _RGB_UNPACK_BLUE(x) #endif #elif LCD_DEPTH == 18 #define LCD_MAX_RED 63