diff --git a/apps/filetypes.c b/apps/filetypes.c index e826efc7dc..a6ccff32ba 100644 --- a/apps/filetypes.c +++ b/apps/filetypes.c @@ -34,12 +34,11 @@ #include "plugin.h" #include "filetypes.h" #include "screens.h" -#include "icons.h" #include "dir.h" #include "file.h" -#include "icons.h" #include "splash.h" #include "buffer.h" +#include "icons.h" /* max filetypes (plugins & icons stored here) */ #if CONFIG_CODEC == SWCODEC @@ -125,6 +124,9 @@ struct file_type { static struct file_type filetypes[MAX_FILETYPES]; static int custom_filetype_icons[MAX_FILETYPES]; static bool custom_icons_loaded = false; +#ifdef HAVE_LCD_COLOR +static int custom_colors[MAX_FILETYPES]; +#endif static int filetype_count = 0; static unsigned char heighest_attr = 0; @@ -136,6 +138,41 @@ static char *filetypes_strdup(char* string) } static void read_builtin_types(void); static void read_config(char* config_file); +#ifdef HAVE_LCD_COLOR +/* Colors file format is similar to icons: + * ext:hex_color + * load a colors file from a theme with: + * filetype colors: filename.colors */ +void read_color_theme_file(void) { + char buffer[MAX_PATH]; + int fd; + char *ext, *color; + int i; + for (i = 0; i < filetype_count; i++) { + custom_colors[i] = -1; + } + snprintf(buffer, MAX_PATH, "%s/%s.colors", THEME_DIR, + global_settings.colors_file); + fd = open(buffer, O_RDONLY); + if (fd < 0) + return; + while (read_line(fd, buffer, MAX_PATH) > 0) + { + if (!settings_parseline(buffer, &ext, &color)) + continue; + for (i=0; ilast_displayed_selected_item = -1 ; gui_list->last_displayed_start_item = -1 ; gui_list->show_selection_marker = true; + +#ifdef HAVE_LCD_COLOR + gui_list->title_color = -1; + gui_list->callback_get_item_color = NULL; +#endif } /* this toggles the selection bar or cursor */ @@ -274,13 +279,23 @@ static void gui_list_draw_smart(struct gui_list *gui_list) } #ifdef HAVE_LCD_BITMAP + int title_style = STYLE_DEFAULT; +#ifdef HAVE_LCD_COLOR + if (gui_list->title_color >= 0) + { + title_style |= STYLE_COLORED; + title_style |= gui_list->title_color; + } +#endif screen_set_xmargin(display, text_pos); /* margin for title */ item_offset = gui_list_get_item_offset(gui_list, gui_list->title_width, text_pos); if (item_offset > gui_list->title_width - (display->width - text_pos)) - display->puts_offset(0, 0, gui_list->title, item_offset); + display->puts_style_offset(0, 0, gui_list->title, + title_style, item_offset); else - display->puts_scroll_offset(0, 0, gui_list->title, item_offset); + display->puts_scroll_style_offset(0, 0, gui_list->title, + title_style, item_offset); #else display->puts_scroll(text_pos, 0, gui_list->title); #endif @@ -333,6 +348,7 @@ static void gui_list_draw_smart(struct gui_list *gui_list) unsigned char *entry_name; int current_item = gui_list->start_item + (SHOW_LIST_TITLE ? i-1 : i); + int style = STYLE_DEFAULT; /* When there are less items to display than the * current available space on the screen, we stop*/ @@ -350,6 +366,21 @@ static void gui_list_draw_smart(struct gui_list *gui_list) item_offset = gui_list_get_item_offset(gui_list, item_width, text_pos); #endif +#ifdef HAVE_LCD_COLOR + /* if the list has a color callback */ + if (gui_list->callback_get_item_color) + { + int color = gui_list->callback_get_item_color(current_item, + gui_list->data); + /* if color selected */ + if (color >= 0) + { + style |= STYLE_COLORED; + style |= color; + } + } +#endif + if(gui_list->show_selection_marker && current_item >= gui_list->selected_item && current_item < gui_list->selected_item + gui_list->selected_size) @@ -357,29 +388,25 @@ static void gui_list_draw_smart(struct gui_list *gui_list) #ifdef HAVE_LCD_BITMAP if (global_settings.invert_cursor)/* Display inverted-line-style*/ { - /* if text got out of view */ - if (item_offset > item_width - (display->width - text_pos)) - { - /* don't scroll */ - display->puts_style_offset(0, i, entry_name, - STYLE_INVERT,item_offset); - } - else - { - display->puts_scroll_style_offset(0, i, entry_name, - STYLE_INVERT, - item_offset); - } + style |= STYLE_INVERT; } else /* if (!global_settings.invert_cursor) */ { - if (item_offset > item_width - (display->width - text_pos)) - display->puts_offset(0, i, entry_name,item_offset); - else - display->puts_scroll_offset(0, i, entry_name,item_offset); if (current_item % gui_list->selected_size != 0) draw_cursor = false; } + /* if the text is smaller than the viewport size */ + if (item_offset > item_width - (display->width - text_pos)) + { + /* don't scroll */ + display->puts_style_offset(0, i, entry_name, + style, item_offset); + } + else + { + display->puts_scroll_style_offset(0, i, entry_name, + style, item_offset); + } #else display->puts_scroll(text_pos, i, entry_name); #endif @@ -397,7 +424,8 @@ static void gui_list_draw_smart(struct gui_list *gui_list) if(gui_list->scroll_all) { #ifdef HAVE_LCD_BITMAP - display->puts_scroll_offset(0, i, entry_name,item_offset); + display->puts_scroll_style_offset(0, i, entry_name, + style, item_offset); #else display->puts_scroll(text_pos, i, entry_name); #endif @@ -405,7 +433,8 @@ static void gui_list_draw_smart(struct gui_list *gui_list) else { #ifdef HAVE_LCD_BITMAP - display->puts_offset(0, i, entry_name,item_offset); + display->puts_style_offset(0, i, entry_name, + style, item_offset); #else display->puts(text_pos, i, entry_name); #endif diff --git a/apps/gui/list.h b/apps/gui/list.h index 021f55ef94..d0bc59b7bc 100644 --- a/apps/gui/list.h +++ b/apps/gui/list.h @@ -36,34 +36,43 @@ enum list_wrap { * The gui_list is based on callback functions, if you want the list * to display something you have to provide it a function that * tells it what to display. - * There are two callback function : - * one to get the text and one to get the icon + * There are three callback function : + * one to get the text, one to get the icon and one to get the color */ /* * Icon callback * - selected_item : an integer that tells the number of the item to display - * - data : a void pointer to the data you gave to the list when - * you initialized it - * - icon : a pointer to the icon, the value inside it is used to display - * the icon after the function returns. + * - data : a void pointer to the data you gave to the list when you + * initialized it + * Returns a pointer to the icon, the value inside it is used to display the + * icon after the function returns. * Note : we use the ICON type because the real type depends of the plateform */ typedef enum themable_icons list_get_icon(int selected_item, void * data); /* * Text callback * - selected_item : an integer that tells the number of the item to display - * - data : a void pointer to the data you gave to the list when - * you initialized it + * - data : a void pointer to the data you gave to the list when you + * initialized it * - buffer : a buffer to put the resulting text on it * (The content of the buffer may not be used by the list, we use * the return value of the function in all cases to avoid filling * a buffer when it's not necessary) * Returns a pointer to a string that contains the text to display */ -typedef char * list_get_name(int selected_item, - void * data, - char *buffer); +typedef char * list_get_name(int selected_item, void * data, char * buffer); +#ifdef HAVE_LCD_COLOR +/* + * Color callback + * - selected_item : an integer that tells the number of the item to display + * - data : a void pointer to the data you gave to the list when you + * initialized it + * Returns an int with the lower 16 bits representing the color to display the + * selected item, negative value for default coloring. + */ +typedef int list_get_color(int selected_item, void * data); +#endif struct gui_list { @@ -101,6 +110,11 @@ struct gui_list /* Optional title icon */ enum themable_icons title_icon; bool show_selection_marker; /* set to true by default */ + +#ifdef HAVE_LCD_COLOR + int title_color; + list_get_color *callback_get_item_color; +#endif }; /* @@ -127,6 +141,16 @@ struct gui_list #define gui_list_set_icon_callback(gui_list, _callback) \ (gui_list)->callback_get_item_icon=_callback +#ifdef HAVE_LCD_COLOR +/* + * Sets the color callback function + * - gui_list : the list structure + * - _callback : the callback function + */ +#define gui_list_set_color_callback(gui_list, _callback) \ + (gui_list)->callback_get_item_color=_callback +#endif + /* * Gives the position of the selected item * - gui_list : the list structure diff --git a/apps/misc.c b/apps/misc.c index 0113825ac4..6187cf425b 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -984,3 +984,36 @@ void setvol(void) settings_save(); } +#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 /* HAVE_LCD_COLOR */ + diff --git a/apps/misc.h b/apps/misc.h index 926170ebe5..b0adb92a0e 100644 --- a/apps/misc.h +++ b/apps/misc.h @@ -109,4 +109,8 @@ void check_bootfile(bool do_rolo); /* check range, set volume and save settings */ void setvol(void); +#ifdef HAVE_LCD_COLOR +int hex_to_rgb(const char* hex); +#endif + #endif /* MISC_H */ diff --git a/apps/settings.c b/apps/settings.c index 09c90af066..11d719f3f3 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -227,38 +227,6 @@ void settings_load(int which) settings_load_config(FIXEDSETTINGSFILE,false); } } -#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) - -static 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 /* HAVE_LCD_COLOR */ static bool cfg_string_to_int(int setting_id, int* out, char* str) { @@ -891,6 +859,11 @@ void settings_apply(void) #endif /* load the icon set */ icons_init(); + +#ifdef HAVE_LCD_COLOR + if (global_settings.colors_file) + read_color_theme_file(); +#endif } diff --git a/apps/settings.h b/apps/settings.h index 4761ba4bfc..05e3ada41d 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -725,6 +725,9 @@ struct user_settings unsigned char remote_icon_file[MAX_FILENAME+1]; unsigned char remote_viewers_icon_file[MAX_FILENAME+1]; #endif +#ifdef HAVE_LCD_COLOR + unsigned char colors_file[MAX_FILENAME+1]; +#endif #ifdef HAVE_BUTTON_LIGHT int button_light_timeout; #endif diff --git a/apps/settings_list.c b/apps/settings_list.c index 91c4cabe1b..fb9ac17539 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -1214,6 +1214,10 @@ const struct settings_list settings[] = { "remote viewers iconset", "", ICON_DIR "/", ".bmp", MAX_FILENAME+1), #endif /* HAVE_REMOTE_LCD */ +#ifdef HAVE_LCD_COLOR + FILENAME_SETTING(F_THEMESETTING, colors_file, "filetype colors", "", + THEME_DIR "/", ".colors", MAX_FILENAME+1), +#endif #ifdef HAVE_BUTTON_LIGHT INT_SETTING_W_CFGVALS(F_FLIPLIST, button_light_timeout, LANG_BUTTONLIGHT_TIMEOUT, 6, diff --git a/apps/tree.c b/apps/tree.c index 1f76994968..a790400754 100644 --- a/apps/tree.c +++ b/apps/tree.c @@ -165,6 +165,15 @@ static char * tree_get_filename(int selected_item, void * data, char *buffer) return(name); } +#ifdef HAVE_LCD_COLOR +static int tree_get_filecolor(int selected_item, void * data) +{ + struct tree_context * local_tc=(struct tree_context *)data; + struct entry* dc = local_tc->dircache; + struct entry* e = &dc[selected_item]; + return filetype_get_color(e->attr); +} +#endif static int tree_get_fileicon(int selected_item, void * data) { @@ -223,6 +232,10 @@ void tree_gui_init(void) #endif gui_synclist_init(&tree_lists, &tree_get_filename, &tc, false, 1); gui_synclist_set_icon_callback(&tree_lists, &tree_get_fileicon); +#ifdef HAVE_LCD_COLOR + gui_list_set_color_callback(&tree_lists.gui_list[SCREEN_MAIN], + &tree_get_filecolor); +#endif } diff --git a/docs/FILES b/docs/FILES index 6eab98d824..80e27a2e51 100644 --- a/docs/FILES +++ b/docs/FILES @@ -14,3 +14,4 @@ README TECH UISIMULATOR KNOWN_ISSUES +sample.colors diff --git a/docs/sample.colors b/docs/sample.colors new file mode 100644 index 0000000000..2f90dee125 --- /dev/null +++ b/docs/sample.colors @@ -0,0 +1,4 @@ +mp3:904010 +ogg:D04040 +txt:FF0000 +cfg:00FF00 diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index 44e42ad617..16c97c9e99 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c @@ -807,6 +807,7 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str, int style, { int xpos,ypos,w,h,xrect; int lastmode = drawmode; + int oldcolor = fg_pattern; /* make sure scrolling is turned off on the line we are updating */ scrolling_lines &= ~(1 << y); @@ -819,11 +820,15 @@ void lcd_puts_style_offset(int x, int y, const unsigned char *str, int style, ypos = ymargin + y*h; drawmode = (style & STYLE_INVERT) ? (DRMODE_SOLID|DRMODE_INVERSEVID) : DRMODE_SOLID; + if (drawmode == DRMODE_SOLID && style & STYLE_COLORED) { + fg_pattern = style & STYLE_COLOR_MASK; + } lcd_putsxyofs(xpos, ypos, offset, str); drawmode ^= DRMODE_INVERSEVID; xrect = xpos + MAX(w - offset, 0); lcd_fillrect(xrect, ypos, LCD_WIDTH - xrect, h); drawmode = lastmode; + fg_pattern = oldcolor; } /*** scrolling ***/ @@ -896,10 +901,8 @@ void lcd_puts_scroll_style_offset(int x, int y, const unsigned char *string, s->invert = false; if (style & STYLE_INVERT) { s->invert = true; - lcd_puts_style_offset(x,y,string,STYLE_INVERT,offset); } - else - lcd_puts_offset(x,y,string,offset); + lcd_puts_style_offset(x,y,string,style,offset); lcd_getstringsize(string, &w, &h); diff --git a/firmware/export/lcd-remote.h b/firmware/export/lcd-remote.h index ad311a8255..cfb643ff96 100644 --- a/firmware/export/lcd-remote.h +++ b/firmware/export/lcd-remote.h @@ -43,8 +43,8 @@ int remote_type(void); extern struct event_queue remote_scroll_queue; #endif -#define STYLE_DEFAULT 0 -#define STYLE_INVERT 1 +#define STYLE_DEFAULT 0x00000000 +#define STYLE_INVERT 0x20000000 #if LCD_REMOTE_DEPTH <= 8 #if (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) \ diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index 077664040e..cebcf54c9b 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h @@ -24,8 +24,10 @@ #include "cpu.h" #include "config.h" -#define STYLE_DEFAULT 0 -#define STYLE_INVERT 1 +#define STYLE_DEFAULT 0x00000000 +#define STYLE_INVERT 0x20000000 +#define STYLE_COLORED 0x10000000 +#define STYLE_COLOR_MASK 0x0000FFFF #ifdef SIMULATOR #ifndef MAX_PATH