diff options
-rw-r--r-- | apps/gui/bitmap/list.c | 132 | ||||
-rw-r--r-- | apps/gui/list.c | 1 | ||||
-rw-r--r-- | apps/gui/list.h | 30 | ||||
-rw-r--r-- | apps/plugins/lib/SOURCES | 1 | ||||
-rw-r--r-- | apps/plugins/lib/printcell_helper.c | 493 | ||||
-rw-r--r-- | apps/plugins/lib/printcell_helper.h | 45 | ||||
-rw-r--r-- | apps/plugins/rb_info.c | 110 |
7 files changed, 763 insertions, 49 deletions
diff --git a/apps/gui/bitmap/list.c b/apps/gui/bitmap/list.c index 194f4c008b..1b051cd800 100644 --- a/apps/gui/bitmap/list.c +++ b/apps/gui/bitmap/list.c | |||
@@ -90,11 +90,57 @@ static int list_icon_width(enum screen_type screen) | |||
90 | return get_icon_width(screen) + ICON_PADDING * 2; | 90 | return get_icon_width(screen) + ICON_PADDING * 2; |
91 | } | 91 | } |
92 | 92 | ||
93 | static bool draw_title(struct screen *display, struct gui_synclist *list) | 93 | static void _default_listdraw_fn(struct list_putlineinfo_t *list_info) |
94 | { | ||
95 | struct screen *display = list_info->display; | ||
96 | int x = list_info->x; | ||
97 | int y = list_info->y; | ||
98 | int item_indent = list_info->item_indent; | ||
99 | int item_offset = list_info->item_offset; | ||
100 | int icon = list_info->icon; | ||
101 | bool is_selected = list_info->is_selected; | ||
102 | bool is_title = list_info->is_title; | ||
103 | bool show_cursor = list_info->show_cursor; | ||
104 | bool have_icons = list_info->have_icons; | ||
105 | struct line_desc *linedes = list_info->linedes; | ||
106 | char *dsp_text = list_info->dsp_text; | ||
107 | |||
108 | if (is_title) | ||
109 | { | ||
110 | if (have_icons) | ||
111 | display->put_line(x, y, linedes, "$"ICON_PADDING_S"I$t", | ||
112 | icon, dsp_text); | ||
113 | else | ||
114 | display->put_line(x, y, linedes, "$t", dsp_text); | ||
115 | } | ||
116 | else if (show_cursor && have_icons) | ||
117 | { | ||
118 | /* the list can have both, one of or neither of cursor and item icons, | ||
119 | * if both don't apply icon padding twice between the icons */ | ||
120 | display->put_line(x, y, | ||
121 | linedes, "$*s$"ICON_PADDING_S"I$i$"ICON_PADDING_S"s$*t", | ||
122 | item_indent, is_selected ? Icon_Cursor : Icon_NOICON, | ||
123 | icon, item_offset, dsp_text); | ||
124 | } | ||
125 | else if (show_cursor || have_icons) | ||
126 | { | ||
127 | display->put_line(x, y, linedes, "$*s$"ICON_PADDING_S"I$*t", item_indent, | ||
128 | show_cursor ? (is_selected ? Icon_Cursor:Icon_NOICON):icon, | ||
129 | item_offset, dsp_text); | ||
130 | } | ||
131 | else | ||
132 | { | ||
133 | display->put_line(x, y, linedes, "$*s$*t", item_indent, item_offset, dsp_text); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | static bool draw_title(struct screen *display, | ||
138 | struct gui_synclist *list, | ||
139 | list_draw_item *callback_draw_item) | ||
94 | { | 140 | { |
95 | const int screen = display->screen_type; | 141 | const int screen = display->screen_type; |
96 | struct viewport *title_text_vp = &title_text[screen]; | 142 | struct viewport *title_text_vp = &title_text[screen]; |
97 | struct line_desc line = LINE_DESC_DEFINIT; | 143 | struct line_desc linedes = LINE_DESC_DEFINIT; |
98 | 144 | ||
99 | if (sb_set_title_text(list->title, list->title_icon, screen)) | 145 | if (sb_set_title_text(list->title, list->title_icon, screen)) |
100 | return false; /* the sbs is handling the title */ | 146 | return false; /* the sbs is handling the title */ |
@@ -102,29 +148,39 @@ static bool draw_title(struct screen *display, struct gui_synclist *list) | |||
102 | if (!list_display_title(list, screen)) | 148 | if (!list_display_title(list, screen)) |
103 | return false; | 149 | return false; |
104 | *title_text_vp = *(list->parent[screen]); | 150 | *title_text_vp = *(list->parent[screen]); |
105 | line.height = list->line_height[screen]; | 151 | linedes.height = list->line_height[screen]; |
106 | title_text_vp->height = line.height; | 152 | title_text_vp->height = linedes.height; |
107 | 153 | ||
108 | #if LCD_DEPTH > 1 | 154 | #if LCD_DEPTH > 1 |
109 | /* XXX: Do we want to support the separator on remote displays? */ | 155 | /* XXX: Do we want to support the separator on remote displays? */ |
110 | if (display->screen_type == SCREEN_MAIN && global_settings.list_separator_height != 0) | 156 | if (display->screen_type == SCREEN_MAIN && global_settings.list_separator_height != 0) |
111 | line.separator_height = abs(global_settings.list_separator_height) | 157 | linedes.separator_height = abs(global_settings.list_separator_height) |
112 | + (lcd_get_dpi() > 200 ? 2 : 1); | 158 | + (lcd_get_dpi() > 200 ? 2 : 1); |
113 | #endif | 159 | #endif |
114 | 160 | ||
115 | #ifdef HAVE_LCD_COLOR | 161 | #ifdef HAVE_LCD_COLOR |
116 | if (list->title_color >= 0) | 162 | if (list->title_color >= 0) |
117 | line.style |= (STYLE_COLORED|list->title_color); | 163 | linedes.style |= (STYLE_COLORED|list->title_color); |
118 | #endif | 164 | #endif |
119 | line.scroll = true; | 165 | linedes.scroll = true; |
120 | 166 | ||
121 | display->set_viewport(title_text_vp); | 167 | display->set_viewport(title_text_vp); |
168 | int icon = list->title_icon; | ||
169 | int icon_w = list_icon_width(display->screen_type); | ||
170 | bool have_icons = false; | ||
171 | if (icon != Icon_NOICON && global_settings.show_icons) | ||
172 | have_icons = true; | ||
122 | 173 | ||
123 | if (list->title_icon != Icon_NOICON && global_settings.show_icons) | 174 | struct list_putlineinfo_t list_info = |
124 | put_line(display, 0, 0, &line, "$"ICON_PADDING_S"I$t", | 175 | { |
125 | list->title_icon, list->title); | 176 | .x = 0, .y = 0, .item_indent = 0, .item_offset = 0, |
126 | else | 177 | .line = -1, .icon = icon, .icon_width = icon_w, |
127 | put_line(display, 0, 0, &line, "$t", list->title); | 178 | .display = display, .vp = title_text_vp, .linedes = &linedes, .list = list, |
179 | .dsp_text = list->title, | ||
180 | .is_selected = false, .is_title = true, .show_cursor = false, | ||
181 | .have_icons = have_icons | ||
182 | }; | ||
183 | callback_draw_item(&list_info); | ||
128 | 184 | ||
129 | return true; | 185 | return true; |
130 | } | 186 | } |
@@ -133,6 +189,8 @@ void list_draw(struct screen *display, struct gui_synclist *list) | |||
133 | { | 189 | { |
134 | int start, end, item_offset, i; | 190 | int start, end, item_offset, i; |
135 | const int screen = display->screen_type; | 191 | const int screen = display->screen_type; |
192 | list_draw_item *callback_draw_item; | ||
193 | |||
136 | const int list_start_item = list->start_item[screen]; | 194 | const int list_start_item = list->start_item[screen]; |
137 | const bool scrollbar_in_left = (global_settings.scrollbar == SCROLLBAR_LEFT); | 195 | const bool scrollbar_in_left = (global_settings.scrollbar == SCROLLBAR_LEFT); |
138 | const bool scrollbar_in_right = (global_settings.scrollbar == SCROLLBAR_RIGHT); | 196 | const bool scrollbar_in_right = (global_settings.scrollbar == SCROLLBAR_RIGHT); |
@@ -145,11 +203,16 @@ void list_draw(struct screen *display, struct gui_synclist *list) | |||
145 | struct viewport *list_text_vp = &list_text[screen]; | 203 | struct viewport *list_text_vp = &list_text[screen]; |
146 | int indent = 0; | 204 | int indent = 0; |
147 | 205 | ||
206 | if (list->callback_draw_item != NULL) | ||
207 | callback_draw_item = list->callback_draw_item; | ||
208 | else | ||
209 | callback_draw_item = _default_listdraw_fn; | ||
210 | |||
148 | struct viewport * last_vp = display->set_viewport(parent); | 211 | struct viewport * last_vp = display->set_viewport(parent); |
149 | display->clear_viewport(); | 212 | display->clear_viewport(); |
150 | display->scroll_stop_viewport(list_text_vp); | 213 | display->scroll_stop_viewport(list_text_vp); |
151 | *list_text_vp = *parent; | 214 | *list_text_vp = *parent; |
152 | if ((show_title = draw_title(display, list))) | 215 | if ((show_title = draw_title(display, list, callback_draw_item))) |
153 | { | 216 | { |
154 | int title_height = title_text[screen].height; | 217 | int title_height = title_text[screen].height; |
155 | list_text_vp->y += title_height; | 218 | list_text_vp->y += title_height; |
@@ -244,6 +307,16 @@ void list_draw(struct screen *display, struct gui_synclist *list) | |||
244 | } | 307 | } |
245 | 308 | ||
246 | display->set_viewport(list_text_vp); | 309 | display->set_viewport(list_text_vp); |
310 | int icon_w = list_icon_width(screen); | ||
311 | int character_width = display->getcharwidth(); | ||
312 | |||
313 | struct list_putlineinfo_t list_info = | ||
314 | { | ||
315 | .x = 0, .y = 0, .vp = list_text_vp, .list = list, | ||
316 | .icon_width = icon_w, .is_title = false, .show_cursor = show_cursor, | ||
317 | .have_icons = have_icons, .linedes = &linedes, .display = display | ||
318 | }; | ||
319 | |||
247 | for (i=start; i<end && i<list->nb_items; i++) | 320 | for (i=start; i<end && i<list->nb_items; i++) |
248 | { | 321 | { |
249 | /* do the text */ | 322 | /* do the text */ |
@@ -251,7 +324,7 @@ void list_draw(struct screen *display, struct gui_synclist *list) | |||
251 | unsigned const char *s; | 324 | unsigned const char *s; |
252 | char entry_buffer[MAX_PATH]; | 325 | char entry_buffer[MAX_PATH]; |
253 | unsigned char *entry_name; | 326 | unsigned char *entry_name; |
254 | int text_pos = 0; | 327 | const int text_pos = 0; /* UNUSED */ |
255 | int line = i - start; | 328 | int line = i - start; |
256 | int line_indent = 0; | 329 | int line_indent = 0; |
257 | int style = STYLE_DEFAULT; | 330 | int style = STYLE_DEFAULT; |
@@ -268,9 +341,9 @@ void list_draw(struct screen *display, struct gui_synclist *list) | |||
268 | if (line_indent) | 341 | if (line_indent) |
269 | { | 342 | { |
270 | if (global_settings.show_icons) | 343 | if (global_settings.show_icons) |
271 | line_indent *= list_icon_width(screen); | 344 | line_indent *= icon_w; |
272 | else | 345 | else |
273 | line_indent *= display->getcharwidth(); | 346 | line_indent *= character_width; |
274 | } | 347 | } |
275 | line_indent += indent; | 348 | line_indent += indent; |
276 | 349 | ||
@@ -345,27 +418,22 @@ void list_draw(struct screen *display, struct gui_synclist *list) | |||
345 | } | 418 | } |
346 | } | 419 | } |
347 | #endif | 420 | #endif |
348 | |||
349 | linedes.style = style; | 421 | linedes.style = style; |
350 | linedes.scroll = is_selected ? true : list->scroll_all; | 422 | linedes.scroll = is_selected ? true : list->scroll_all; |
351 | linedes.line = i % list->selected_size; | 423 | linedes.line = i % list->selected_size; |
352 | icon = list->callback_get_item_icon ? | 424 | icon = list->callback_get_item_icon ? |
353 | list->callback_get_item_icon(i, list->data) : Icon_NOICON; | 425 | list->callback_get_item_icon(i, list->data) : Icon_NOICON; |
354 | /* the list can have both, one of or neither of cursor and item icons, | 426 | |
355 | * if both don't apply icon padding twice between the icons */ | 427 | |
356 | if (show_cursor && have_icons) | 428 | list_info.y = line * linedes.height + draw_offset; |
357 | put_line(display, 0, line * linedes.height + draw_offset, | 429 | list_info.is_selected = is_selected; |
358 | &linedes, "$*s$"ICON_PADDING_S"I$i$"ICON_PADDING_S"s$*t", | 430 | list_info.item_indent = line_indent; |
359 | line_indent, is_selected ? Icon_Cursor : Icon_NOICON, | 431 | list_info.line = i; |
360 | icon, item_offset, entry_name); | 432 | list_info.icon = icon; |
361 | else if (show_cursor || have_icons) | 433 | list_info.dsp_text = entry_name; |
362 | put_line(display, 0, line * linedes.height + draw_offset, | 434 | list_info.item_offset = item_offset; |
363 | &linedes, "$*s$"ICON_PADDING_S"I$*t", line_indent, | 435 | |
364 | show_cursor ? (is_selected ? Icon_Cursor:Icon_NOICON):icon, | 436 | callback_draw_item(&list_info); |
365 | item_offset, entry_name); | ||
366 | else | ||
367 | put_line(display, 0, line * linedes.height + draw_offset, | ||
368 | &linedes, "$*s$*t", line_indent, item_offset, entry_name); | ||
369 | } | 437 | } |
370 | display->set_viewport(parent); | 438 | display->set_viewport(parent); |
371 | display->update_viewport(); | 439 | display->update_viewport(); |
diff --git a/apps/gui/list.c b/apps/gui/list.c index 8ff075da7e..a8055c4581 100644 --- a/apps/gui/list.c +++ b/apps/gui/list.c | |||
@@ -150,6 +150,7 @@ void gui_synclist_init(struct gui_synclist * gui_list, | |||
150 | gui_list->callback_get_item_icon = NULL; | 150 | gui_list->callback_get_item_icon = NULL; |
151 | gui_list->callback_get_item_name = callback_get_item_name; | 151 | gui_list->callback_get_item_name = callback_get_item_name; |
152 | gui_list->callback_speak_item = NULL; | 152 | gui_list->callback_speak_item = NULL; |
153 | gui_list->callback_draw_item = NULL; | ||
153 | gui_list->nb_items = 0; | 154 | gui_list->nb_items = 0; |
154 | gui_list->selected_item = 0; | 155 | gui_list->selected_item = 0; |
155 | #ifdef HAVE_TOUCHSCREEN | 156 | #ifdef HAVE_TOUCHSCREEN |
diff --git a/apps/gui/list.h b/apps/gui/list.h index 64ff3e3fdd..1f910577a1 100644 --- a/apps/gui/list.h +++ b/apps/gui/list.h | |||
@@ -69,6 +69,35 @@ typedef enum themable_icons list_get_icon(int selected_item, void * data); | |||
69 | typedef const char * list_get_name(int selected_item, void * data, | 69 | typedef const char * list_get_name(int selected_item, void * data, |
70 | char * buffer, size_t buffer_len); | 70 | char * buffer, size_t buffer_len); |
71 | /* | 71 | /* |
72 | * Draw callback | ||
73 | * - display : functions supplied depends on the screen call originated from (typ: MAIN) | ||
74 | * - list_info : a pointer to an internal struct containing item display information | ||
75 | */ | ||
76 | /* owner drawn lists need to know this info */ | ||
77 | struct list_putlineinfo_t { | ||
78 | int x; | ||
79 | int y; | ||
80 | int item_indent; | ||
81 | int item_offset; | ||
82 | int line; | ||
83 | |||
84 | int icon; | ||
85 | int icon_width; | ||
86 | |||
87 | struct screen *display; | ||
88 | struct viewport *vp; | ||
89 | struct line_desc *linedes; | ||
90 | struct gui_synclist * list; | ||
91 | char *dsp_text; | ||
92 | |||
93 | bool is_selected; | ||
94 | bool is_title; | ||
95 | bool show_cursor; | ||
96 | bool have_icons; | ||
97 | }; | ||
98 | |||
99 | typedef void list_draw_item(struct list_putlineinfo_t *list_info); | ||
100 | /* | ||
72 | * Voice callback | 101 | * Voice callback |
73 | * - selected_item : an integer that tells the number of the item to speak | 102 | * - selected_item : an integer that tells the number of the item to speak |
74 | * - data : a void pointer to the data you gave to the list when you | 103 | * - data : a void pointer to the data you gave to the list when you |
@@ -133,6 +162,7 @@ struct gui_synclist | |||
133 | list_get_icon *callback_get_item_icon; | 162 | list_get_icon *callback_get_item_icon; |
134 | list_get_name *callback_get_item_name; | 163 | list_get_name *callback_get_item_name; |
135 | list_speak_item *callback_speak_item; | 164 | list_speak_item *callback_speak_item; |
165 | list_draw_item *callback_draw_item; | ||
136 | 166 | ||
137 | /* The data that will be passed to the callback function YOU implement */ | 167 | /* The data that will be passed to the callback function YOU implement */ |
138 | void * data; | 168 | void * data; |
diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES index 1cd092f8df..bff9017404 100644 --- a/apps/plugins/lib/SOURCES +++ b/apps/plugins/lib/SOURCES | |||
@@ -14,6 +14,7 @@ rgb_hsv.c | |||
14 | highscore.c | 14 | highscore.c |
15 | simple_viewer.c | 15 | simple_viewer.c |
16 | display_text.c | 16 | display_text.c |
17 | printcell_helper.c | ||
17 | strncpy.c | 18 | strncpy.c |
18 | stdio_compat.c | 19 | stdio_compat.c |
19 | 20 | ||
diff --git a/apps/plugins/lib/printcell_helper.c b/apps/plugins/lib/printcell_helper.c new file mode 100644 index 0000000000..27a4b0fc95 --- /dev/null +++ b/apps/plugins/lib/printcell_helper.c | |||
@@ -0,0 +1,493 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2021 by William Wilgus | ||
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 | /* spreadsheet cells for rockbox lists */ | ||
22 | #include "plugin.h" | ||
23 | #include "lib/printcell_helper.h" | ||
24 | |||
25 | #ifndef PRINTCELL_MAX_COLUMNS | ||
26 | #define PRINTCELL_MAX_COLUMNS 16 | ||
27 | #endif | ||
28 | |||
29 | #define COLUMN_ENDLEN 3 | ||
30 | #define TITLE_FLAG 0xFF | ||
31 | #define SELECTED_FLAG 0x1 | ||
32 | |||
33 | #if LCD_DEPTH == 1 | ||
34 | #define BAR_WIDTH (1) | ||
35 | #else | ||
36 | #define BAR_WIDTH (COLUMN_ENDLEN) | ||
37 | #endif | ||
38 | |||
39 | struct printcell_info_t { | ||
40 | int offw[NB_SCREENS]; | ||
41 | int iconw[NB_SCREENS]; | ||
42 | int selcol_offw[NB_SCREENS]; | ||
43 | int totalcolw[NB_SCREENS]; | ||
44 | uint16_t colw[NB_SCREENS][PRINTCELL_MAX_COLUMNS]; | ||
45 | int ncols; | ||
46 | int selcol; | ||
47 | int selcol_index; | ||
48 | char title[PRINTCELL_MAXLINELEN]; | ||
49 | bool separator; | ||
50 | }; | ||
51 | static struct printcell_info_t printcell; | ||
52 | |||
53 | static void parse_dsptext(int ncols, const char *dsp_text, char* buffer, uint16_t *sidx) | ||
54 | { | ||
55 | /*Internal function loads sidx with split offsets indexing | ||
56 | the buffer of null terminated strings, splits on '$' | ||
57 | _assumptions_: | ||
58 | dsp_text[len - 1] = \0, | ||
59 | buffer[PRINTCELL_MAXLINELEN], | ||
60 | sidx[PRINTCELL_MAX_COLUMNS] | ||
61 | */ | ||
62 | int i = 0; | ||
63 | int j = 0; | ||
64 | int ch = '$'; /* first column $ is optional */ | ||
65 | if (*dsp_text == '$') | ||
66 | dsp_text++; | ||
67 | /* add null to the start of the text buffer */ | ||
68 | buffer[j++] = '\0'; | ||
69 | do | ||
70 | { | ||
71 | if (ch == '$') | ||
72 | { | ||
73 | sidx[i] = j; | ||
74 | if (*dsp_text == '$') /* $$ escaped user must want to display $*/ | ||
75 | buffer[j++] = *dsp_text++; | ||
76 | while (*dsp_text != '\0' && *dsp_text != '$' && j < PRINTCELL_MAXLINELEN - 1) | ||
77 | buffer[j++] = *dsp_text++; | ||
78 | buffer[j++] = '\0'; | ||
79 | i++; | ||
80 | if (i >= ncols || j >= (PRINTCELL_MAXLINELEN - 1)) | ||
81 | break; | ||
82 | } | ||
83 | ch = *dsp_text++; | ||
84 | } while (ch != '\0'); | ||
85 | while (i < ncols) | ||
86 | sidx[i++] = 0; /* point to null */ | ||
87 | } | ||
88 | |||
89 | static void draw_selector(struct screen *display, struct line_desc *linedes, | ||
90 | int selected_flag, int selected_col, | ||
91 | int separator_height, int x, int y, int w, int h) | ||
92 | { | ||
93 | /* Internal function draws the currently selected items row & column styling */ | ||
94 | if (!(separator_height > 0 || (selected_flag & SELECTED_FLAG))) | ||
95 | return; | ||
96 | y--; | ||
97 | h++; | ||
98 | int linestyle = linedes->style & _STYLE_DECO_MASK; | ||
99 | bool invert = (selected_flag == SELECTED_FLAG && linestyle >= STYLE_COLORBAR); | ||
100 | if (invert || (linestyle & STYLE_INVERT) == STYLE_INVERT) | ||
101 | { | ||
102 | display->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); | ||
103 | } | ||
104 | |||
105 | if (selected_col == printcell.selcol) | ||
106 | { | ||
107 | if (selected_flag & SELECTED_FLAG) | ||
108 | { | ||
109 | /* expand left and right bars to show selected column */ | ||
110 | display->fillrect(x, y, BAR_WIDTH, h); | ||
111 | display->fillrect(x + w - BAR_WIDTH + 1, y, BAR_WIDTH, h); | ||
112 | display->set_drawmode(DRMODE_FG); | ||
113 | } | ||
114 | else | ||
115 | { | ||
116 | /* only draw left and right bars */ | ||
117 | display->drawrect(x + 1, y, 1, h); | ||
118 | display->drawrect(x + w - 1, y, 1, h); | ||
119 | return; | ||
120 | } | ||
121 | } | ||
122 | /* draw whole rect outline */ | ||
123 | display->drawrect(x + 1, y, w - 1, h); | ||
124 | } | ||
125 | |||
126 | static inline void set_cell_width(struct viewport *vp, int max_w, int new_w) | ||
127 | { | ||
128 | /* Internal function sets cell width if less than the max width */ | ||
129 | if (new_w > max_w) | ||
130 | vp->width = max_w; | ||
131 | else | ||
132 | vp->width = new_w; | ||
133 | vp->width -= COLUMN_ENDLEN; | ||
134 | } | ||
135 | |||
136 | static inline int printcells(struct screen *display, char* buffer, uint16_t *sidx, | ||
137 | struct line_desc *linedes, struct viewport *vp, int vp_w, | ||
138 | int separator, int x, int y, int offw, int selected_flag) | ||
139 | { | ||
140 | /* Internal function prints remaining cells */ | ||
141 | int text_offset = offw + offw; | ||
142 | int ncols = printcell.ncols; | ||
143 | int screen = display->screen_type; | ||
144 | int height = linedes->height; | ||
145 | int selsep = (selected_flag == 0) ? 0: separator; | ||
146 | uint16_t *screencolwidth = printcell.colw[screen]; | ||
147 | |||
148 | for(int i = 1; i < ncols; i++) | ||
149 | { | ||
150 | int ny = y; | ||
151 | int nw = screencolwidth[i] + text_offset; | ||
152 | int nx = x + nw; | ||
153 | char *buftext; | ||
154 | if (nx > 0 && x < vp_w) | ||
155 | { | ||
156 | set_cell_width(vp, vp_w, nx); | ||
157 | |||
158 | if (i == printcell.selcol) | ||
159 | linedes->separator_height = selsep; | ||
160 | else | ||
161 | linedes->separator_height = separator; | ||
162 | |||
163 | buftext = &buffer[sidx[i]]; | ||
164 | display->put_line(x + offw, ny, linedes, "$t", buftext); | ||
165 | vp->width += COLUMN_ENDLEN + 1; | ||
166 | draw_selector(display, linedes, selected_flag, i, separator, x, ny, nw, height); | ||
167 | } | ||
168 | x = nx; | ||
169 | } | ||
170 | return x; | ||
171 | } | ||
172 | |||
173 | static inline int calcvisible(int screen, int vp_w, int text_offset, int sbwidth) | ||
174 | { | ||
175 | /* Internal function determine how many of the previous colums can be shown */ | ||
176 | uint16_t *screencolwidth = printcell.colw[screen]; | ||
177 | int screenicnwidth = printcell.iconw[screen]; | ||
178 | int offset = 0; | ||
179 | int selcellw = screencolwidth[printcell.selcol] + text_offset; | ||
180 | int maxw = vp_w - (sbwidth + selcellw + 1); | ||
181 | |||
182 | for (int i = printcell.selcol - 1; i >= 0; i--) | ||
183 | { | ||
184 | int cw = screencolwidth[i] + text_offset; | ||
185 | if (i == 0) | ||
186 | cw += screenicnwidth; | ||
187 | if (offset > 0 || cw > maxw) | ||
188 | offset += cw; /* can not display this cell -- everything left goes here too */ | ||
189 | else | ||
190 | maxw -= cw; /* can display this cell subtract from the max width */ | ||
191 | } | ||
192 | return offset; | ||
193 | } | ||
194 | |||
195 | static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info) | ||
196 | { | ||
197 | /* Internal function callback from the list, draws items as they are requested */ | ||
198 | #define ICON_PADDING 1 | ||
199 | #define ICON_PADDING_S "1" | ||
200 | struct screen *display = list_info->display; | ||
201 | int screen = display->screen_type; | ||
202 | int col_offset_width = printcell.offw[screen]; | ||
203 | int text_offset = col_offset_width + col_offset_width; | ||
204 | |||
205 | static char printcell_buffer[PRINTCELL_MAXLINELEN]; | ||
206 | static uint16_t sidx[PRINTCELL_MAX_COLUMNS]; /*indexes zero terminated strings in buffer*/ | ||
207 | |||
208 | int offset_pos = list_info->list->offset_position[screen]; | ||
209 | int x = list_info->x - offset_pos; | ||
210 | int y = list_info->y; | ||
211 | int line_indent = list_info->item_indent; | ||
212 | int item_offset = list_info->item_offset; | ||
213 | int icon = list_info->icon; | ||
214 | int icon_w = list_info->icon_width; | ||
215 | bool is_title = list_info->is_title; | ||
216 | bool is_selected = list_info->is_selected; | ||
217 | bool show_cursor = list_info->show_cursor; | ||
218 | bool have_icons = list_info->have_icons; | ||
219 | struct line_desc *linedes = list_info->linedes; | ||
220 | char *dsp_text = list_info->dsp_text; | ||
221 | struct viewport *vp = list_info->vp; | ||
222 | |||
223 | int selected_flag = ((is_selected || is_title) ? | ||
224 | (is_title ? TITLE_FLAG : SELECTED_FLAG) : 0); | ||
225 | int vp_w = vp->width;/* save for restore */ | ||
226 | int saved_separator_height = linedes->separator_height;/* save for restore */ | ||
227 | |||
228 | linedes->separator_height = 0; | ||
229 | int separator = saved_separator_height; | ||
230 | |||
231 | if (printcell.separator || (selected_flag & SELECTED_FLAG)) | ||
232 | separator = 1; | ||
233 | |||
234 | int nx = x; | ||
235 | int nw, colxw; | ||
236 | |||
237 | printcell_buffer[0] = '\0'; | ||
238 | parse_dsptext(printcell.ncols, dsp_text, printcell_buffer, sidx); | ||
239 | char *buftext = &printcell_buffer[sidx[0]]; | ||
240 | uint16_t *screencolwidth = printcell.colw[screen]; | ||
241 | |||
242 | if (is_title) | ||
243 | { | ||
244 | int sbwidth = 0; | ||
245 | if (rb->global_settings->scrollbar == SCROLLBAR_LEFT) | ||
246 | sbwidth = rb->global_settings->scrollbar_width; | ||
247 | |||
248 | printcell.iconw[screen] = have_icons ? ICON_PADDING + icon_w : 0; | ||
249 | |||
250 | if (printcell.selcol_offw[screen] == 0 && printcell.selcol > 0) | ||
251 | printcell.selcol_offw[screen] = calcvisible(screen, vp_w, text_offset, sbwidth); | ||
252 | nx -= printcell.selcol_offw[screen]; | ||
253 | |||
254 | nw = screencolwidth[0] + printcell.iconw[screen] + text_offset; | ||
255 | nw += sbwidth; | ||
256 | |||
257 | colxw = nx + nw; | ||
258 | if (colxw > 0) | ||
259 | { | ||
260 | set_cell_width(vp, vp_w, colxw); | ||
261 | linedes->separator_height = separator; | ||
262 | |||
263 | if (have_icons) | ||
264 | { | ||
265 | display->put_line(nx + (COLUMN_ENDLEN/2), y, linedes, | ||
266 | "$"ICON_PADDING_S"I$t", icon, buftext); | ||
267 | } | ||
268 | else | ||
269 | { | ||
270 | display->put_line(nx + col_offset_width, y, linedes, "$t", buftext); | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | else | ||
275 | { | ||
276 | int cursor = Icon_NOICON; | ||
277 | nx -= printcell.selcol_offw[screen]; | ||
278 | |||
279 | if (selected_flag & SELECTED_FLAG) | ||
280 | { | ||
281 | printcell.selcol_index = sidx[printcell.selcol]; /* save the item offset*/ | ||
282 | cursor = Icon_Cursor; | ||
283 | /* limit length of selection if columns don't reach end */ | ||
284 | int maxw = nx + printcell.totalcolw[screen] + printcell.iconw[screen]; | ||
285 | maxw += text_offset * printcell.ncols; | ||
286 | if (vp_w > maxw) | ||
287 | vp->width = maxw; | ||
288 | /* display a blank line first to draw selector across all cells */ | ||
289 | display->put_line(x, y, linedes, "$t", ""); | ||
290 | } | ||
291 | |||
292 | nw = screencolwidth[0] + printcell.iconw[screen] + text_offset; | ||
293 | colxw = nx + nw; | ||
294 | if (colxw > 0) | ||
295 | { | ||
296 | set_cell_width(vp, vp_w, colxw); | ||
297 | if (printcell.selcol == 0 && selected_flag == 0) | ||
298 | linedes->separator_height = 0; | ||
299 | else | ||
300 | linedes->separator_height = separator; | ||
301 | |||
302 | if (show_cursor && have_icons) | ||
303 | { | ||
304 | /* the list can have both, one of or neither of cursor and item icons, | ||
305 | * if both don't apply icon padding twice between the icons */ | ||
306 | display->put_line(nx, y, | ||
307 | linedes, "$*s$"ICON_PADDING_S"I$i$"ICON_PADDING_S"s$*t", | ||
308 | line_indent, cursor, icon, item_offset, buftext); | ||
309 | } | ||
310 | else if (show_cursor || have_icons) | ||
311 | { | ||
312 | display->put_line(nx, y, linedes, "$*s$"ICON_PADDING_S"I$*t", line_indent, | ||
313 | show_cursor ? cursor:icon, item_offset, buftext); | ||
314 | } | ||
315 | else | ||
316 | { | ||
317 | display->put_line(nx + col_offset_width, y, linedes, | ||
318 | "$*s$*t", line_indent, item_offset, buftext); | ||
319 | } | ||
320 | } | ||
321 | } | ||
322 | |||
323 | if (colxw > 0) /* draw selector for first column (title or items) */ | ||
324 | { | ||
325 | vp->width += COLUMN_ENDLEN + 1; | ||
326 | draw_selector(display, linedes, selected_flag, 0, | ||
327 | separator, nx, y, nw, linedes->height); | ||
328 | } | ||
329 | nx += nw; | ||
330 | /* display remaining cells */ | ||
331 | printcells(display, printcell_buffer, sidx, linedes, | ||
332 | vp, vp_w, separator, nx, y, col_offset_width, selected_flag); | ||
333 | /* restore settings */ | ||
334 | linedes->separator_height = saved_separator_height; | ||
335 | display->set_drawmode(DRMODE_FG); | ||
336 | vp->width = vp_w; | ||
337 | } | ||
338 | |||
339 | void printcell_enable(struct gui_synclist *gui_list, bool enable, bool separator) | ||
340 | { | ||
341 | printcell.separator = separator; | ||
342 | #ifdef HAVE_LCD_COLOR | ||
343 | static int list_sep_color = INT_MIN; | ||
344 | if (enable) | ||
345 | { | ||
346 | list_sep_color = rb->global_settings->list_separator_color; | ||
347 | rb->global_settings->list_separator_color = rb->global_settings->fg_color; | ||
348 | gui_list->callback_draw_item = printcell_listdraw_fn; | ||
349 | } | ||
350 | else | ||
351 | { | ||
352 | gui_list->callback_draw_item = NULL; | ||
353 | if (list_sep_color != INT_MIN) | ||
354 | rb->global_settings->list_separator_color = list_sep_color; | ||
355 | list_sep_color = INT_MIN; | ||
356 | } | ||
357 | #else | ||
358 | if (enable) | ||
359 | gui_list->callback_draw_item = printcell_listdraw_fn; | ||
360 | else | ||
361 | gui_list->callback_draw_item = NULL; | ||
362 | #endif | ||
363 | |||
364 | } | ||
365 | |||
366 | int printcell_increment_column(struct gui_synclist *gui_list, int increment, bool wrap) | ||
367 | { | ||
368 | int item = printcell.selcol + increment; | ||
369 | int imin = -1; | ||
370 | int imax = printcell.ncols - 1; | ||
371 | if(wrap) | ||
372 | { | ||
373 | imin = imax; | ||
374 | imax = -1; | ||
375 | } | ||
376 | |||
377 | if (item < -1) | ||
378 | item = imin; | ||
379 | else if (item >= printcell.ncols) | ||
380 | item = imax; | ||
381 | |||
382 | if (item != printcell.selcol) | ||
383 | { | ||
384 | FOR_NB_SCREENS(n) /* offset needs recalculated */ | ||
385 | printcell.selcol_offw[n] = 0; | ||
386 | printcell.selcol = item; | ||
387 | printcell.selcol_index = 0; | ||
388 | rb->gui_synclist_draw(gui_list); | ||
389 | } | ||
390 | return item; | ||
391 | } | ||
392 | |||
393 | int printcell_set_columns(struct gui_synclist *gui_list, | ||
394 | char * title, enum themable_icons icon) | ||
395 | { | ||
396 | if (title == NULL) | ||
397 | title = "$PRINTCELL NOT SETUP"; | ||
398 | uint16_t sidx[PRINTCELL_MAX_COLUMNS]; /* starting position of column in title string */ | ||
399 | int width, height, user_minwidth; | ||
400 | int i = 0; | ||
401 | int j = 0; | ||
402 | int ch = '$'; /* first column $ is optional */ | ||
403 | |||
404 | rb->memset(&printcell, 0, sizeof(struct printcell_info_t)); | ||
405 | |||
406 | FOR_NB_SCREENS(n) | ||
407 | { | ||
408 | rb->screens[n]->getstringsize("W", &width, &height); | ||
409 | printcell.offw[n] = width; /* set column text offset */ | ||
410 | } | ||
411 | |||
412 | if (*title == '$') | ||
413 | title++; | ||
414 | do | ||
415 | { | ||
416 | if (ch == '$') | ||
417 | { | ||
418 | printcell.title[j++] = ch; | ||
419 | user_minwidth = 0; | ||
420 | if (*title == '*')/* user wants a minimum size for this column */ | ||
421 | { | ||
422 | char *dspst = title++; /* store starting position in case this is wrong */ | ||
423 | while(isdigit(*title)) | ||
424 | { | ||
425 | user_minwidth = 10*user_minwidth + *title - '0'; | ||
426 | title++; | ||
427 | } | ||
428 | if (*title != '$') /* user forgot $ or wants to display '*' */ | ||
429 | { | ||
430 | title = dspst; | ||
431 | user_minwidth = 0; | ||
432 | } | ||
433 | else | ||
434 | title++; | ||
435 | } | ||
436 | |||
437 | sidx[i] = j; | ||
438 | if (*title == '$') /* $$ escaped user must want to display $*/ | ||
439 | printcell.title[j++] = *title++; | ||
440 | |||
441 | while (*title != '\0' && *title != '$' && j < PRINTCELL_MAXLINELEN - 1) | ||
442 | printcell.title[j++] = *title++; | ||
443 | |||
444 | FOR_NB_SCREENS(n) | ||
445 | { | ||
446 | rb->screens[n]->getstringsize(&printcell.title[sidx[i]], &width, &height); | ||
447 | if (width < user_minwidth) | ||
448 | width = user_minwidth; | ||
449 | printcell.colw[n][i] = width; | ||
450 | printcell.totalcolw[n] += width; | ||
451 | } | ||
452 | if (++i >= PRINTCELL_MAX_COLUMNS - 1) | ||
453 | break; | ||
454 | } | ||
455 | ch = *title++; | ||
456 | } while (ch != '\0'); | ||
457 | printcell.ncols = i; | ||
458 | printcell.title[j] = '\0'; | ||
459 | printcell.selcol = -1; | ||
460 | printcell.selcol_index = 0; | ||
461 | |||
462 | rb->gui_synclist_set_title(gui_list, printcell.title, icon); | ||
463 | return printcell.ncols; | ||
464 | } | ||
465 | |||
466 | char *printcell_get_selected_column_text(struct gui_synclist *gui_list, char *buf, size_t bufsz) | ||
467 | { | ||
468 | int selected = gui_list->selected_item; | ||
469 | int index = printcell.selcol_index - 1; | ||
470 | |||
471 | if (index < 0) | ||
472 | index = 0; | ||
473 | char *bpos; | ||
474 | |||
475 | if (gui_list->callback_get_item_name(selected, gui_list->data, buf, bufsz) == buf) | ||
476 | { | ||
477 | bpos = &buf[index]; | ||
478 | if (printcell.selcol < 0) /* return entire string incld col formatting '$'*/ | ||
479 | return bpos; | ||
480 | while(bpos < &buf[bufsz - 1]) | ||
481 | { | ||
482 | if (*bpos == '$' || *bpos == '\0') | ||
483 | goto success; | ||
484 | bpos++; | ||
485 | } | ||
486 | } | ||
487 | /*failure*/ | ||
488 | bpos = buf; | ||
489 | index = 0; | ||
490 | success: | ||
491 | *bpos = '\0'; | ||
492 | return &buf[index]; | ||
493 | } | ||
diff --git a/apps/plugins/lib/printcell_helper.h b/apps/plugins/lib/printcell_helper.h new file mode 100644 index 0000000000..adc98e5a5f --- /dev/null +++ b/apps/plugins/lib/printcell_helper.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2021 William Wilgus | ||
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 | #ifndef _PRINTCELL_LIST_H_ | ||
23 | #define _PRINTCELL_LIST_H_ | ||
24 | #define PRINTCELL_MAXLINELEN MAX_PATH | ||
25 | |||
26 | /* sets the printcell function enabled */ | ||
27 | void printcell_enable(struct gui_synclist *gui_list, bool enable, bool separator); | ||
28 | |||
29 | /* sets title and calculates cell widths each column is identified by '$' character | ||
30 | ex 3 columns title = "Col1$Col2$Col3" also accepts $*WIDTH$ | ||
31 | ex 3 columns varying width title = "$*64$Col1$*128$Col2$Col3 | ||
32 | returns number of columns | ||
33 | */ | ||
34 | int printcell_set_columns(struct gui_synclist *gui_list, | ||
35 | char * title, enum themable_icons icon); | ||
36 | |||
37 | /* increments the current selected column negative increment is allowed | ||
38 | returns the selected column | ||
39 | range: -1(no selection) to ncols - 1 */ | ||
40 | int printcell_increment_column(struct gui_synclist *gui_list, int increment, bool wrap); | ||
41 | |||
42 | /* return the text of currently selected column buffer should be sized | ||
43 | * for max item len, buf[PRINTCELL_MAXLINELEN] is a safe bet */ | ||
44 | char *printcell_get_selected_column_text(struct gui_synclist *gui_list, char *buf, size_t bufsz); | ||
45 | #endif /*_PRINTCELL_LIST_H_*/ | ||
diff --git a/apps/plugins/rb_info.c b/apps/plugins/rb_info.c index f82c80c0cf..e0ec117dfb 100644 --- a/apps/plugins/rb_info.c +++ b/apps/plugins/rb_info.c | |||
@@ -29,8 +29,9 @@ | |||
29 | #include "lib/action_helper.h" | 29 | #include "lib/action_helper.h" |
30 | #include "lib/button_helper.h" | 30 | #include "lib/button_helper.h" |
31 | #include "lib/pluginlib_actions.h" | 31 | #include "lib/pluginlib_actions.h" |
32 | #include "lib/printcell_helper.h" | ||
32 | 33 | ||
33 | #define MENU_ID(x) (((void*)&"RPBUTACNGX\0" + x)) | 34 | #define MENU_ID(x) (((void*)&"RPBUTACNGSX\0" + x)) |
34 | enum { | 35 | enum { |
35 | M_ROOT = 0, | 36 | M_ROOT = 0, |
36 | M_PATHS, | 37 | M_PATHS, |
@@ -41,6 +42,7 @@ enum { | |||
41 | M_CONTEXTS, | 42 | M_CONTEXTS, |
42 | M_ACTTEST, | 43 | M_ACTTEST, |
43 | M_PLUGINS, | 44 | M_PLUGINS, |
45 | M_TESTPUT, | ||
44 | M_EXIT, | 46 | M_EXIT, |
45 | M_LAST_ITEM //ITEM COUNT | 47 | M_LAST_ITEM //ITEM COUNT |
46 | }; | 48 | }; |
@@ -96,7 +98,8 @@ static const struct paths paths[] = { | |||
96 | {"Fm Presets", ""FMPRESET_PATH}, | 98 | {"Fm Presets", ""FMPRESET_PATH}, |
97 | {"MAX_PATH", ""MACROVAL(MAX_PATH)" bytes"}, | 99 | {"MAX_PATH", ""MACROVAL(MAX_PATH)" bytes"}, |
98 | }; | 100 | }; |
99 | 101 | #define TESTPUT_HEADER "$*64$col1$col2$*128$col3$col4$col5$col6$*64$col7$col8" | |
102 | static int testput_cols = 0; | ||
100 | struct mainmenu { const char *name; void *menuid; int items;}; | 103 | struct mainmenu { const char *name; void *menuid; int items;}; |
101 | static struct mainmenu mainmenu[M_LAST_ITEM] = { | 104 | static struct mainmenu mainmenu[M_LAST_ITEM] = { |
102 | #define MENU_ITEM(ID, NAME, COUNT) [ID]{NAME, MENU_ID(ID), (int)COUNT} | 105 | #define MENU_ITEM(ID, NAME, COUNT) [ID]{NAME, MENU_ID(ID), (int)COUNT} |
@@ -109,6 +112,7 @@ MENU_ITEM(M_ACTIONS, "Actions", LAST_ACTION_PLACEHOLDER), | |||
109 | MENU_ITEM(M_CONTEXTS, "Contexts", LAST_CONTEXT_PLACEHOLDER ), | 112 | MENU_ITEM(M_CONTEXTS, "Contexts", LAST_CONTEXT_PLACEHOLDER ), |
110 | MENU_ITEM(M_ACTTEST, "Action test", 3), | 113 | MENU_ITEM(M_ACTTEST, "Action test", 3), |
111 | MENU_ITEM(M_PLUGINS, ID2P(LANG_PLUGINS), MENU_ID_PLUGINS_ITEMS), | 114 | MENU_ITEM(M_PLUGINS, ID2P(LANG_PLUGINS), MENU_ID_PLUGINS_ITEMS), |
115 | MENU_ITEM(M_TESTPUT, "Printcell test", 36), | ||
112 | MENU_ITEM(M_EXIT, ID2P(LANG_MENU_QUIT), 0), | 116 | MENU_ITEM(M_EXIT, ID2P(LANG_MENU_QUIT), 0), |
113 | #undef MENU_ITEM | 117 | #undef MENU_ITEM |
114 | }; | 118 | }; |
@@ -125,8 +129,16 @@ static const struct mainmenu *mainitem(int selected_item) | |||
125 | static void cleanup(void *parameter) | 129 | static void cleanup(void *parameter) |
126 | { | 130 | { |
127 | (void)parameter; | 131 | (void)parameter; |
132 | } | ||
128 | 133 | ||
134 | #if 0 | ||
135 | static enum themable_icons menu_icon_cb(int selected_item, void * data) | ||
136 | { | ||
137 | (void)data; | ||
138 | (void)selected_item; | ||
139 | return Icon_NOICON; | ||
129 | } | 140 | } |
141 | #endif | ||
130 | 142 | ||
131 | static const char *menu_plugin_name_cb(int selected_item, void* data, | 143 | static const char *menu_plugin_name_cb(int selected_item, void* data, |
132 | char* buf, size_t buf_len) | 144 | char* buf, size_t buf_len) |
@@ -247,7 +259,7 @@ static const char* list_get_name_cb(int selected_item, void* data, | |||
247 | buf[0] = '\0'; | 259 | buf[0] = '\0'; |
248 | if (data == MENU_ID(M_ROOT)) | 260 | if (data == MENU_ID(M_ROOT)) |
249 | return mainitem(selected_item)->name; | 261 | return mainitem(selected_item)->name; |
250 | else if (selected_item == 0) /*header text*/ | 262 | else if (selected_item == 0 && data != MENU_ID(M_TESTPUT)) /*header text*/ |
251 | return mainitem(main_last_sel)->name; | 263 | return mainitem(main_last_sel)->name; |
252 | else if (selected_item >= mainitem(main_last_sel)->items - 1) | 264 | else if (selected_item >= mainitem(main_last_sel)->items - 1) |
253 | return ID2P(LANG_BACK); | 265 | return ID2P(LANG_BACK); |
@@ -286,6 +298,11 @@ static const char* list_get_name_cb(int selected_item, void* data, | |||
286 | { | 298 | { |
287 | return menu_plugin_name_cb(selected_item - 1, data, buf, buf_len); | 299 | return menu_plugin_name_cb(selected_item - 1, data, buf, buf_len); |
288 | } | 300 | } |
301 | else if (data == MENU_ID(M_TESTPUT)) | ||
302 | { | ||
303 | rb->snprintf(buf, buf_len, "put_line item: [ %d ]$Text %d$Text LONGER TEST text %d $4$5$6$7$8$9", selected_item, 1, 2); | ||
304 | return buf; | ||
305 | } | ||
289 | return buf; | 306 | return buf; |
290 | } | 307 | } |
291 | 308 | ||
@@ -331,16 +348,38 @@ static int list_voice_cb(int list_index, void* data) | |||
331 | return 0; | 348 | return 0; |
332 | } | 349 | } |
333 | 350 | ||
334 | int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclist *lists) | 351 | int menu_action_cb(int *action, int selected_item, bool* exit, struct gui_synclist *lists) |
335 | { | 352 | { |
336 | if (lists->data == MENU_ID(M_ACTTEST)) | 353 | if (lists->data == MENU_ID(M_TESTPUT) && (selected_item < (mainitem(M_TESTPUT)->items) - 1)/*back*/) |
354 | { | ||
355 | if (*action == ACTION_STD_OK) | ||
356 | { | ||
357 | printcell_increment_column(lists, 1, true); | ||
358 | *action = ACTION_NONE; | ||
359 | } | ||
360 | else if (*action == ACTION_STD_CANCEL) | ||
361 | { | ||
362 | if (printcell_increment_column(lists, -1, true) != testput_cols - 1) | ||
363 | { | ||
364 | *action = ACTION_NONE; | ||
365 | } | ||
366 | } | ||
367 | else if (*action == ACTION_STD_CONTEXT) | ||
368 | { | ||
369 | char buf[PRINTCELL_MAXLINELEN]; | ||
370 | char* bufp = buf; | ||
371 | bufp = printcell_get_selected_column_text(lists, bufp, PRINTCELL_MAXLINELEN); | ||
372 | rb->splashf(HZ * 2, "Item: %s", bufp); | ||
373 | } | ||
374 | } | ||
375 | else if (lists->data == MENU_ID(M_ACTTEST)) | ||
337 | { | 376 | { |
338 | if (selected_item == 2) /* context */ | 377 | if (selected_item == 2) /* context */ |
339 | { | 378 | { |
340 | int ctx = m_test.context; | 379 | int ctx = m_test.context; |
341 | if (action == ACTION_STD_OK) | 380 | if (*action == ACTION_STD_OK) |
342 | m_test.context++; | 381 | m_test.context++; |
343 | else if (action == ACTION_STD_CANCEL) | 382 | else if (*action == ACTION_STD_CANCEL) |
344 | m_test.context--; | 383 | m_test.context--; |
345 | 384 | ||
346 | if (m_test.context < 0) | 385 | if (m_test.context < 0) |
@@ -353,7 +392,7 @@ int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclis | |||
353 | 392 | ||
354 | goto default_handler; | 393 | goto default_handler; |
355 | } | 394 | } |
356 | if (action == ACTION_STD_OK) | 395 | if (*action == ACTION_STD_OK) |
357 | { | 396 | { |
358 | if (selected_item == 1 || selected_item == 3) | 397 | if (selected_item == 1 || selected_item == 3) |
359 | { | 398 | { |
@@ -364,7 +403,7 @@ int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclis | |||
364 | } | 403 | } |
365 | else if (lists->data == MENU_ID(M_BTNTEST)) | 404 | else if (lists->data == MENU_ID(M_BTNTEST)) |
366 | { | 405 | { |
367 | if (action == ACTION_STD_OK) | 406 | if (*action == ACTION_STD_OK) |
368 | { | 407 | { |
369 | if (selected_item == 1 || selected_item == 2) | 408 | if (selected_item == 1 || selected_item == 2) |
370 | { | 409 | { |
@@ -373,18 +412,38 @@ int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclis | |||
373 | } | 412 | } |
374 | } | 413 | } |
375 | } | 414 | } |
376 | if (action == ACTION_STD_OK) | 415 | /* common */ |
416 | if (*action == ACTION_STD_OK) | ||
377 | { | 417 | { |
378 | if (lists->data == MENU_ID(M_ROOT)) | 418 | if (lists->data == MENU_ID(M_ROOT)) |
379 | { | 419 | { |
380 | rb->memset(&m_test, 0, sizeof(struct menu_test_t)); | 420 | rb->memset(&m_test, 0, sizeof(struct menu_test_t)); |
381 | const struct mainmenu *cur = mainitem(selected_item); | 421 | const struct mainmenu *cur = mainitem(selected_item); |
422 | |||
382 | if (cur->menuid == NULL || cur->menuid == MENU_ID(M_EXIT)) | 423 | if (cur->menuid == NULL || cur->menuid == MENU_ID(M_EXIT)) |
383 | *exit = true; | 424 | *exit = true; |
384 | else | 425 | else |
385 | { | 426 | { |
386 | main_last_sel = selected_item; | 427 | main_last_sel = selected_item; |
387 | synclist_set(cur->menuid, 1, cur->items, 1); | 428 | |
429 | if (cur->menuid == MENU_ID(M_TESTPUT)) | ||
430 | { | ||
431 | //rb->gui_list_screen_scroll_out_of_view(true); | ||
432 | synclist_set(cur->menuid, 0, cur->items, 1); | ||
433 | #if LCD_DEPTH > 1 | ||
434 | /* If line sep is set to automatic then outline cells */ | ||
435 | bool showlinesep = (rb->global_settings->list_separator_height < 0); | ||
436 | #else | ||
437 | bool showlinesep = (rb->global_settings->cursor_style == 0); | ||
438 | #endif | ||
439 | printcell_enable(lists, true, showlinesep); | ||
440 | //lists->callback_draw_item = test_listdraw_fn; | ||
441 | } | ||
442 | else | ||
443 | { | ||
444 | printcell_enable(lists, false, false); | ||
445 | synclist_set(cur->menuid, 1, cur->items, 1); | ||
446 | } | ||
388 | rb->gui_synclist_draw(lists); | 447 | rb->gui_synclist_draw(lists); |
389 | } | 448 | } |
390 | } | 449 | } |
@@ -394,7 +453,11 @@ int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclis | |||
394 | } | 453 | } |
395 | else if (selected_item >= (mainitem(main_last_sel)->items) - 1)/*back*/ | 454 | else if (selected_item >= (mainitem(main_last_sel)->items) - 1)/*back*/ |
396 | { | 455 | { |
397 | action = ACTION_STD_CANCEL; | 456 | *action = ACTION_STD_CANCEL; |
457 | } | ||
458 | else if (lists->data == MENU_ID(M_TESTPUT)) | ||
459 | { | ||
460 | |||
398 | } | 461 | } |
399 | else if (lists->data == MENU_ID(M_ACTIONS) || | 462 | else if (lists->data == MENU_ID(M_ACTIONS) || |
400 | lists->data == MENU_ID(M_CONTEXTS)) | 463 | lists->data == MENU_ID(M_CONTEXTS)) |
@@ -406,8 +469,14 @@ int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclis | |||
406 | rb->button_get(true); | 469 | rb->button_get(true); |
407 | } | 470 | } |
408 | } | 471 | } |
409 | if (action == ACTION_STD_CANCEL) | 472 | if (*action == ACTION_STD_CANCEL) |
410 | { | 473 | { |
474 | if (lists->data == MENU_ID(M_TESTPUT)) | ||
475 | { | ||
476 | //rb->gui_list_screen_scroll_out_of_view(false); | ||
477 | //lists->callback_draw_item = NULL; | ||
478 | printcell_enable(lists, false, false); | ||
479 | } | ||
411 | if (lists->data != MENU_ID(M_ROOT)) | 480 | if (lists->data != MENU_ID(M_ROOT)) |
412 | { | 481 | { |
413 | const struct mainmenu *mainm = &mainmenu[0]; | 482 | const struct mainmenu *mainm = &mainmenu[0]; |
@@ -418,7 +487,7 @@ int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclis | |||
418 | *exit = true; | 487 | *exit = true; |
419 | } | 488 | } |
420 | default_handler: | 489 | default_handler: |
421 | if (rb->default_event_handler_ex(action, cleanup, NULL) == SYS_USB_CONNECTED) | 490 | if (rb->default_event_handler_ex(*action, cleanup, NULL) == SYS_USB_CONNECTED) |
422 | { | 491 | { |
423 | *exit = true; | 492 | *exit = true; |
424 | return PLUGIN_USB_CONNECTED; | 493 | return PLUGIN_USB_CONNECTED; |
@@ -436,7 +505,14 @@ static void synclist_set(char* menu_id, int selected_item, int items, int sel_si | |||
436 | list_voice_cb(0, menu_id); | 505 | list_voice_cb(0, menu_id); |
437 | rb->gui_synclist_init(&lists,list_get_name_cb, | 506 | rb->gui_synclist_init(&lists,list_get_name_cb, |
438 | menu_id, false, sel_size, NULL); | 507 | menu_id, false, sel_size, NULL); |
439 | 508 | if (menu_id == MENU_ID(M_TESTPUT)) | |
509 | { | ||
510 | testput_cols = printcell_set_columns(&lists, TESTPUT_HEADER, Icon_Rockbox); | ||
511 | } | ||
512 | else | ||
513 | { | ||
514 | rb->gui_synclist_set_title(&lists, NULL,-1); | ||
515 | } | ||
440 | rb->gui_synclist_set_icon_callback(&lists,NULL); | 516 | rb->gui_synclist_set_icon_callback(&lists,NULL); |
441 | rb->gui_synclist_set_voice_callback(&lists, list_voice_cb); | 517 | rb->gui_synclist_set_voice_callback(&lists, list_voice_cb); |
442 | rb->gui_synclist_set_nb_items(&lists,items); | 518 | rb->gui_synclist_set_nb_items(&lists,items); |
@@ -460,7 +536,7 @@ enum plugin_status plugin_start(const void* parameter) | |||
460 | /* add header and back item to each submenu */ | 536 | /* add header and back item to each submenu */ |
461 | for (int i = 1; i < M_LAST_ITEM; i++) | 537 | for (int i = 1; i < M_LAST_ITEM; i++) |
462 | mainmenu[i].items += 2; | 538 | mainmenu[i].items += 2; |
463 | 539 | mainmenu[M_TESTPUT].items -= 1; | |
464 | if (!exit) | 540 | if (!exit) |
465 | { | 541 | { |
466 | const struct mainmenu *mainm = &mainmenu[0]; | 542 | const struct mainmenu *mainm = &mainmenu[0]; |
@@ -483,10 +559,10 @@ enum plugin_status plugin_start(const void* parameter) | |||
483 | } | 559 | } |
484 | else | 560 | else |
485 | redraw = true; | 561 | redraw = true; |
562 | ret = menu_action_cb(&action, selected_item, &exit, &lists); | ||
486 | if (rb->gui_synclist_do_button(&lists,&action,LIST_WRAP_UNLESS_HELD)) | 563 | if (rb->gui_synclist_do_button(&lists,&action,LIST_WRAP_UNLESS_HELD)) |
487 | continue; | 564 | continue; |
488 | selected_item = rb->gui_synclist_get_sel_pos(&lists); | 565 | selected_item = rb->gui_synclist_get_sel_pos(&lists); |
489 | ret = menu_action_cb(action, selected_item, &exit, &lists); | ||
490 | } | 566 | } |
491 | } | 567 | } |
492 | 568 | ||