forked from len0rd/rockbox
gui lists add callback for owner drawn items
allow the guts of gui_sync_list to be used with owner drawn items WIP printcell_helper-- goal: allow data to be displayed in a spreadsheet format with an easy to use interface printcell_set_columns(gui_synclist, title, icon) sets title and calculates cell widths each column is identified by '$' character ex 3 columns title = "Col1$Col2$Col3" also accepts $*WIDTH$ ex 3 columns varying width title = "$*64$Col1$*128$Col2$Col3 printcell_enable(gui_synclist, enable) sets the printcell function enabled After setting the columns and enabling the printcell function items can be added to the list like normal column items are supplied delimited by '$' ex item = "Item1$item2$item3" they will be placed in cells defined by set_columns and scroll if the cell is too small --Fixed for 1 bit & 2 bit displays Change-Id: I49bd7903005d7a54e93af4379b0cdea63c860656
This commit is contained in:
parent
edc68b0657
commit
a7703e4926
7 changed files with 764 additions and 50 deletions
|
@ -90,11 +90,57 @@ static int list_icon_width(enum screen_type screen)
|
||||||
return get_icon_width(screen) + ICON_PADDING * 2;
|
return get_icon_width(screen) + ICON_PADDING * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool draw_title(struct screen *display, struct gui_synclist *list)
|
static void _default_listdraw_fn(struct list_putlineinfo_t *list_info)
|
||||||
|
{
|
||||||
|
struct screen *display = list_info->display;
|
||||||
|
int x = list_info->x;
|
||||||
|
int y = list_info->y;
|
||||||
|
int item_indent = list_info->item_indent;
|
||||||
|
int item_offset = list_info->item_offset;
|
||||||
|
int icon = list_info->icon;
|
||||||
|
bool is_selected = list_info->is_selected;
|
||||||
|
bool is_title = list_info->is_title;
|
||||||
|
bool show_cursor = list_info->show_cursor;
|
||||||
|
bool have_icons = list_info->have_icons;
|
||||||
|
struct line_desc *linedes = list_info->linedes;
|
||||||
|
char *dsp_text = list_info->dsp_text;
|
||||||
|
|
||||||
|
if (is_title)
|
||||||
|
{
|
||||||
|
if (have_icons)
|
||||||
|
display->put_line(x, y, linedes, "$"ICON_PADDING_S"I$t",
|
||||||
|
icon, dsp_text);
|
||||||
|
else
|
||||||
|
display->put_line(x, y, linedes, "$t", dsp_text);
|
||||||
|
}
|
||||||
|
else if (show_cursor && have_icons)
|
||||||
|
{
|
||||||
|
/* the list can have both, one of or neither of cursor and item icons,
|
||||||
|
* if both don't apply icon padding twice between the icons */
|
||||||
|
display->put_line(x, y,
|
||||||
|
linedes, "$*s$"ICON_PADDING_S"I$i$"ICON_PADDING_S"s$*t",
|
||||||
|
item_indent, is_selected ? Icon_Cursor : Icon_NOICON,
|
||||||
|
icon, item_offset, dsp_text);
|
||||||
|
}
|
||||||
|
else if (show_cursor || have_icons)
|
||||||
|
{
|
||||||
|
display->put_line(x, y, linedes, "$*s$"ICON_PADDING_S"I$*t", item_indent,
|
||||||
|
show_cursor ? (is_selected ? Icon_Cursor:Icon_NOICON):icon,
|
||||||
|
item_offset, dsp_text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
display->put_line(x, y, linedes, "$*s$*t", item_indent, item_offset, dsp_text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool draw_title(struct screen *display,
|
||||||
|
struct gui_synclist *list,
|
||||||
|
list_draw_item *callback_draw_item)
|
||||||
{
|
{
|
||||||
const int screen = display->screen_type;
|
const int screen = display->screen_type;
|
||||||
struct viewport *title_text_vp = &title_text[screen];
|
struct viewport *title_text_vp = &title_text[screen];
|
||||||
struct line_desc line = LINE_DESC_DEFINIT;
|
struct line_desc linedes = LINE_DESC_DEFINIT;
|
||||||
|
|
||||||
if (sb_set_title_text(list->title, list->title_icon, screen))
|
if (sb_set_title_text(list->title, list->title_icon, screen))
|
||||||
return false; /* the sbs is handling the title */
|
return false; /* the sbs is handling the title */
|
||||||
|
@ -102,29 +148,39 @@ static bool draw_title(struct screen *display, struct gui_synclist *list)
|
||||||
if (!list_display_title(list, screen))
|
if (!list_display_title(list, screen))
|
||||||
return false;
|
return false;
|
||||||
*title_text_vp = *(list->parent[screen]);
|
*title_text_vp = *(list->parent[screen]);
|
||||||
line.height = list->line_height[screen];
|
linedes.height = list->line_height[screen];
|
||||||
title_text_vp->height = line.height;
|
title_text_vp->height = linedes.height;
|
||||||
|
|
||||||
#if LCD_DEPTH > 1
|
#if LCD_DEPTH > 1
|
||||||
/* XXX: Do we want to support the separator on remote displays? */
|
/* XXX: Do we want to support the separator on remote displays? */
|
||||||
if (display->screen_type == SCREEN_MAIN && global_settings.list_separator_height != 0)
|
if (display->screen_type == SCREEN_MAIN && global_settings.list_separator_height != 0)
|
||||||
line.separator_height = abs(global_settings.list_separator_height)
|
linedes.separator_height = abs(global_settings.list_separator_height)
|
||||||
+ (lcd_get_dpi() > 200 ? 2 : 1);
|
+ (lcd_get_dpi() > 200 ? 2 : 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LCD_COLOR
|
#ifdef HAVE_LCD_COLOR
|
||||||
if (list->title_color >= 0)
|
if (list->title_color >= 0)
|
||||||
line.style |= (STYLE_COLORED|list->title_color);
|
linedes.style |= (STYLE_COLORED|list->title_color);
|
||||||
#endif
|
#endif
|
||||||
line.scroll = true;
|
linedes.scroll = true;
|
||||||
|
|
||||||
display->set_viewport(title_text_vp);
|
display->set_viewport(title_text_vp);
|
||||||
|
int icon = list->title_icon;
|
||||||
|
int icon_w = list_icon_width(display->screen_type);
|
||||||
|
bool have_icons = false;
|
||||||
|
if (icon != Icon_NOICON && global_settings.show_icons)
|
||||||
|
have_icons = true;
|
||||||
|
|
||||||
if (list->title_icon != Icon_NOICON && global_settings.show_icons)
|
struct list_putlineinfo_t list_info =
|
||||||
put_line(display, 0, 0, &line, "$"ICON_PADDING_S"I$t",
|
{
|
||||||
list->title_icon, list->title);
|
.x = 0, .y = 0, .item_indent = 0, .item_offset = 0,
|
||||||
else
|
.line = -1, .icon = icon, .icon_width = icon_w,
|
||||||
put_line(display, 0, 0, &line, "$t", list->title);
|
.display = display, .vp = title_text_vp, .linedes = &linedes, .list = list,
|
||||||
|
.dsp_text = list->title,
|
||||||
|
.is_selected = false, .is_title = true, .show_cursor = false,
|
||||||
|
.have_icons = have_icons
|
||||||
|
};
|
||||||
|
callback_draw_item(&list_info);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -133,6 +189,8 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
||||||
{
|
{
|
||||||
int start, end, item_offset, i;
|
int start, end, item_offset, i;
|
||||||
const int screen = display->screen_type;
|
const int screen = display->screen_type;
|
||||||
|
list_draw_item *callback_draw_item;
|
||||||
|
|
||||||
const int list_start_item = list->start_item[screen];
|
const int list_start_item = list->start_item[screen];
|
||||||
const bool scrollbar_in_left = (global_settings.scrollbar == SCROLLBAR_LEFT);
|
const bool scrollbar_in_left = (global_settings.scrollbar == SCROLLBAR_LEFT);
|
||||||
const bool scrollbar_in_right = (global_settings.scrollbar == SCROLLBAR_RIGHT);
|
const bool scrollbar_in_right = (global_settings.scrollbar == SCROLLBAR_RIGHT);
|
||||||
|
@ -145,11 +203,16 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
||||||
struct viewport *list_text_vp = &list_text[screen];
|
struct viewport *list_text_vp = &list_text[screen];
|
||||||
int indent = 0;
|
int indent = 0;
|
||||||
|
|
||||||
|
if (list->callback_draw_item != NULL)
|
||||||
|
callback_draw_item = list->callback_draw_item;
|
||||||
|
else
|
||||||
|
callback_draw_item = _default_listdraw_fn;
|
||||||
|
|
||||||
struct viewport * last_vp = display->set_viewport(parent);
|
struct viewport * last_vp = display->set_viewport(parent);
|
||||||
display->clear_viewport();
|
display->clear_viewport();
|
||||||
display->scroll_stop_viewport(list_text_vp);
|
display->scroll_stop_viewport(list_text_vp);
|
||||||
*list_text_vp = *parent;
|
*list_text_vp = *parent;
|
||||||
if ((show_title = draw_title(display, list)))
|
if ((show_title = draw_title(display, list, callback_draw_item)))
|
||||||
{
|
{
|
||||||
int title_height = title_text[screen].height;
|
int title_height = title_text[screen].height;
|
||||||
list_text_vp->y += title_height;
|
list_text_vp->y += title_height;
|
||||||
|
@ -244,6 +307,16 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
||||||
}
|
}
|
||||||
|
|
||||||
display->set_viewport(list_text_vp);
|
display->set_viewport(list_text_vp);
|
||||||
|
int icon_w = list_icon_width(screen);
|
||||||
|
int character_width = display->getcharwidth();
|
||||||
|
|
||||||
|
struct list_putlineinfo_t list_info =
|
||||||
|
{
|
||||||
|
.x = 0, .y = 0, .vp = list_text_vp, .list = list,
|
||||||
|
.icon_width = icon_w, .is_title = false, .show_cursor = show_cursor,
|
||||||
|
.have_icons = have_icons, .linedes = &linedes, .display = display
|
||||||
|
};
|
||||||
|
|
||||||
for (i=start; i<end && i<list->nb_items; i++)
|
for (i=start; i<end && i<list->nb_items; i++)
|
||||||
{
|
{
|
||||||
/* do the text */
|
/* do the text */
|
||||||
|
@ -251,7 +324,7 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
||||||
unsigned const char *s;
|
unsigned const char *s;
|
||||||
char entry_buffer[MAX_PATH];
|
char entry_buffer[MAX_PATH];
|
||||||
unsigned char *entry_name;
|
unsigned char *entry_name;
|
||||||
int text_pos = 0;
|
const int text_pos = 0; /* UNUSED */
|
||||||
int line = i - start;
|
int line = i - start;
|
||||||
int line_indent = 0;
|
int line_indent = 0;
|
||||||
int style = STYLE_DEFAULT;
|
int style = STYLE_DEFAULT;
|
||||||
|
@ -268,9 +341,9 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
||||||
if (line_indent)
|
if (line_indent)
|
||||||
{
|
{
|
||||||
if (global_settings.show_icons)
|
if (global_settings.show_icons)
|
||||||
line_indent *= list_icon_width(screen);
|
line_indent *= icon_w;
|
||||||
else
|
else
|
||||||
line_indent *= display->getcharwidth();
|
line_indent *= character_width;
|
||||||
}
|
}
|
||||||
line_indent += indent;
|
line_indent += indent;
|
||||||
|
|
||||||
|
@ -345,27 +418,22 @@ void list_draw(struct screen *display, struct gui_synclist *list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
linedes.style = style;
|
linedes.style = style;
|
||||||
linedes.scroll = is_selected ? true : list->scroll_all;
|
linedes.scroll = is_selected ? true : list->scroll_all;
|
||||||
linedes.line = i % list->selected_size;
|
linedes.line = i % list->selected_size;
|
||||||
icon = list->callback_get_item_icon ?
|
icon = list->callback_get_item_icon ?
|
||||||
list->callback_get_item_icon(i, list->data) : Icon_NOICON;
|
list->callback_get_item_icon(i, list->data) : Icon_NOICON;
|
||||||
/* the list can have both, one of or neither of cursor and item icons,
|
|
||||||
* if both don't apply icon padding twice between the icons */
|
|
||||||
if (show_cursor && have_icons)
|
list_info.y = line * linedes.height + draw_offset;
|
||||||
put_line(display, 0, line * linedes.height + draw_offset,
|
list_info.is_selected = is_selected;
|
||||||
&linedes, "$*s$"ICON_PADDING_S"I$i$"ICON_PADDING_S"s$*t",
|
list_info.item_indent = line_indent;
|
||||||
line_indent, is_selected ? Icon_Cursor : Icon_NOICON,
|
list_info.line = i;
|
||||||
icon, item_offset, entry_name);
|
list_info.icon = icon;
|
||||||
else if (show_cursor || have_icons)
|
list_info.dsp_text = entry_name;
|
||||||
put_line(display, 0, line * linedes.height + draw_offset,
|
list_info.item_offset = item_offset;
|
||||||
&linedes, "$*s$"ICON_PADDING_S"I$*t", line_indent,
|
|
||||||
show_cursor ? (is_selected ? Icon_Cursor:Icon_NOICON):icon,
|
callback_draw_item(&list_info);
|
||||||
item_offset, entry_name);
|
|
||||||
else
|
|
||||||
put_line(display, 0, line * linedes.height + draw_offset,
|
|
||||||
&linedes, "$*s$*t", line_indent, item_offset, entry_name);
|
|
||||||
}
|
}
|
||||||
display->set_viewport(parent);
|
display->set_viewport(parent);
|
||||||
display->update_viewport();
|
display->update_viewport();
|
||||||
|
|
|
@ -150,6 +150,7 @@ void gui_synclist_init(struct gui_synclist * gui_list,
|
||||||
gui_list->callback_get_item_icon = NULL;
|
gui_list->callback_get_item_icon = NULL;
|
||||||
gui_list->callback_get_item_name = callback_get_item_name;
|
gui_list->callback_get_item_name = callback_get_item_name;
|
||||||
gui_list->callback_speak_item = NULL;
|
gui_list->callback_speak_item = NULL;
|
||||||
|
gui_list->callback_draw_item = NULL;
|
||||||
gui_list->nb_items = 0;
|
gui_list->nb_items = 0;
|
||||||
gui_list->selected_item = 0;
|
gui_list->selected_item = 0;
|
||||||
#ifdef HAVE_TOUCHSCREEN
|
#ifdef HAVE_TOUCHSCREEN
|
||||||
|
|
|
@ -68,6 +68,35 @@ typedef enum themable_icons list_get_icon(int selected_item, void * data);
|
||||||
*/
|
*/
|
||||||
typedef const char * list_get_name(int selected_item, void * data,
|
typedef const char * list_get_name(int selected_item, void * data,
|
||||||
char * buffer, size_t buffer_len);
|
char * buffer, size_t buffer_len);
|
||||||
|
/*
|
||||||
|
* Draw callback
|
||||||
|
* - display : functions supplied depends on the screen call originated from (typ: MAIN)
|
||||||
|
* - list_info : a pointer to an internal struct containing item display information
|
||||||
|
*/
|
||||||
|
/* owner drawn lists need to know this info */
|
||||||
|
struct list_putlineinfo_t {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int item_indent;
|
||||||
|
int item_offset;
|
||||||
|
int line;
|
||||||
|
|
||||||
|
int icon;
|
||||||
|
int icon_width;
|
||||||
|
|
||||||
|
struct screen *display;
|
||||||
|
struct viewport *vp;
|
||||||
|
struct line_desc *linedes;
|
||||||
|
struct gui_synclist * list;
|
||||||
|
char *dsp_text;
|
||||||
|
|
||||||
|
bool is_selected;
|
||||||
|
bool is_title;
|
||||||
|
bool show_cursor;
|
||||||
|
bool have_icons;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void list_draw_item(struct list_putlineinfo_t *list_info);
|
||||||
/*
|
/*
|
||||||
* Voice callback
|
* Voice callback
|
||||||
* - selected_item : an integer that tells the number of the item to speak
|
* - selected_item : an integer that tells the number of the item to speak
|
||||||
|
@ -133,6 +162,7 @@ struct gui_synclist
|
||||||
list_get_icon *callback_get_item_icon;
|
list_get_icon *callback_get_item_icon;
|
||||||
list_get_name *callback_get_item_name;
|
list_get_name *callback_get_item_name;
|
||||||
list_speak_item *callback_speak_item;
|
list_speak_item *callback_speak_item;
|
||||||
|
list_draw_item *callback_draw_item;
|
||||||
|
|
||||||
/* The data that will be passed to the callback function YOU implement */
|
/* The data that will be passed to the callback function YOU implement */
|
||||||
void * data;
|
void * data;
|
||||||
|
|
|
@ -14,6 +14,7 @@ rgb_hsv.c
|
||||||
highscore.c
|
highscore.c
|
||||||
simple_viewer.c
|
simple_viewer.c
|
||||||
display_text.c
|
display_text.c
|
||||||
|
printcell_helper.c
|
||||||
strncpy.c
|
strncpy.c
|
||||||
stdio_compat.c
|
stdio_compat.c
|
||||||
|
|
||||||
|
|
493
apps/plugins/lib/printcell_helper.c
Normal file
493
apps/plugins/lib/printcell_helper.c
Normal file
|
@ -0,0 +1,493 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 by William Wilgus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
/* spreadsheet cells for rockbox lists */
|
||||||
|
#include "plugin.h"
|
||||||
|
#include "lib/printcell_helper.h"
|
||||||
|
|
||||||
|
#ifndef PRINTCELL_MAX_COLUMNS
|
||||||
|
#define PRINTCELL_MAX_COLUMNS 16
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define COLUMN_ENDLEN 3
|
||||||
|
#define TITLE_FLAG 0xFF
|
||||||
|
#define SELECTED_FLAG 0x1
|
||||||
|
|
||||||
|
#if LCD_DEPTH == 1
|
||||||
|
#define BAR_WIDTH (1)
|
||||||
|
#else
|
||||||
|
#define BAR_WIDTH (COLUMN_ENDLEN)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct printcell_info_t {
|
||||||
|
int offw[NB_SCREENS];
|
||||||
|
int iconw[NB_SCREENS];
|
||||||
|
int selcol_offw[NB_SCREENS];
|
||||||
|
int totalcolw[NB_SCREENS];
|
||||||
|
uint16_t colw[NB_SCREENS][PRINTCELL_MAX_COLUMNS];
|
||||||
|
int ncols;
|
||||||
|
int selcol;
|
||||||
|
int selcol_index;
|
||||||
|
char title[PRINTCELL_MAXLINELEN];
|
||||||
|
bool separator;
|
||||||
|
};
|
||||||
|
static struct printcell_info_t printcell;
|
||||||
|
|
||||||
|
static void parse_dsptext(int ncols, const char *dsp_text, char* buffer, uint16_t *sidx)
|
||||||
|
{
|
||||||
|
/*Internal function loads sidx with split offsets indexing
|
||||||
|
the buffer of null terminated strings, splits on '$'
|
||||||
|
_assumptions_:
|
||||||
|
dsp_text[len - 1] = \0,
|
||||||
|
buffer[PRINTCELL_MAXLINELEN],
|
||||||
|
sidx[PRINTCELL_MAX_COLUMNS]
|
||||||
|
*/
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
int ch = '$'; /* first column $ is optional */
|
||||||
|
if (*dsp_text == '$')
|
||||||
|
dsp_text++;
|
||||||
|
/* add null to the start of the text buffer */
|
||||||
|
buffer[j++] = '\0';
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (ch == '$')
|
||||||
|
{
|
||||||
|
sidx[i] = j;
|
||||||
|
if (*dsp_text == '$') /* $$ escaped user must want to display $*/
|
||||||
|
buffer[j++] = *dsp_text++;
|
||||||
|
while (*dsp_text != '\0' && *dsp_text != '$' && j < PRINTCELL_MAXLINELEN - 1)
|
||||||
|
buffer[j++] = *dsp_text++;
|
||||||
|
buffer[j++] = '\0';
|
||||||
|
i++;
|
||||||
|
if (i >= ncols || j >= (PRINTCELL_MAXLINELEN - 1))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ch = *dsp_text++;
|
||||||
|
} while (ch != '\0');
|
||||||
|
while (i < ncols)
|
||||||
|
sidx[i++] = 0; /* point to null */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_selector(struct screen *display, struct line_desc *linedes,
|
||||||
|
int selected_flag, int selected_col,
|
||||||
|
int separator_height, int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
/* Internal function draws the currently selected items row & column styling */
|
||||||
|
if (!(separator_height > 0 || (selected_flag & SELECTED_FLAG)))
|
||||||
|
return;
|
||||||
|
y--;
|
||||||
|
h++;
|
||||||
|
int linestyle = linedes->style & _STYLE_DECO_MASK;
|
||||||
|
bool invert = (selected_flag == SELECTED_FLAG && linestyle >= STYLE_COLORBAR);
|
||||||
|
if (invert || (linestyle & STYLE_INVERT) == STYLE_INVERT)
|
||||||
|
{
|
||||||
|
display->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selected_col == printcell.selcol)
|
||||||
|
{
|
||||||
|
if (selected_flag & SELECTED_FLAG)
|
||||||
|
{
|
||||||
|
/* expand left and right bars to show selected column */
|
||||||
|
display->fillrect(x, y, BAR_WIDTH, h);
|
||||||
|
display->fillrect(x + w - BAR_WIDTH + 1, y, BAR_WIDTH, h);
|
||||||
|
display->set_drawmode(DRMODE_FG);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* only draw left and right bars */
|
||||||
|
display->drawrect(x + 1, y, 1, h);
|
||||||
|
display->drawrect(x + w - 1, y, 1, h);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* draw whole rect outline */
|
||||||
|
display->drawrect(x + 1, y, w - 1, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_cell_width(struct viewport *vp, int max_w, int new_w)
|
||||||
|
{
|
||||||
|
/* Internal function sets cell width if less than the max width */
|
||||||
|
if (new_w > max_w)
|
||||||
|
vp->width = max_w;
|
||||||
|
else
|
||||||
|
vp->width = new_w;
|
||||||
|
vp->width -= COLUMN_ENDLEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int printcells(struct screen *display, char* buffer, uint16_t *sidx,
|
||||||
|
struct line_desc *linedes, struct viewport *vp, int vp_w,
|
||||||
|
int separator, int x, int y, int offw, int selected_flag)
|
||||||
|
{
|
||||||
|
/* Internal function prints remaining cells */
|
||||||
|
int text_offset = offw + offw;
|
||||||
|
int ncols = printcell.ncols;
|
||||||
|
int screen = display->screen_type;
|
||||||
|
int height = linedes->height;
|
||||||
|
int selsep = (selected_flag == 0) ? 0: separator;
|
||||||
|
uint16_t *screencolwidth = printcell.colw[screen];
|
||||||
|
|
||||||
|
for(int i = 1; i < ncols; i++)
|
||||||
|
{
|
||||||
|
int ny = y;
|
||||||
|
int nw = screencolwidth[i] + text_offset;
|
||||||
|
int nx = x + nw;
|
||||||
|
char *buftext;
|
||||||
|
if (nx > 0 && x < vp_w)
|
||||||
|
{
|
||||||
|
set_cell_width(vp, vp_w, nx);
|
||||||
|
|
||||||
|
if (i == printcell.selcol)
|
||||||
|
linedes->separator_height = selsep;
|
||||||
|
else
|
||||||
|
linedes->separator_height = separator;
|
||||||
|
|
||||||
|
buftext = &buffer[sidx[i]];
|
||||||
|
display->put_line(x + offw, ny, linedes, "$t", buftext);
|
||||||
|
vp->width += COLUMN_ENDLEN + 1;
|
||||||
|
draw_selector(display, linedes, selected_flag, i, separator, x, ny, nw, height);
|
||||||
|
}
|
||||||
|
x = nx;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int calcvisible(int screen, int vp_w, int text_offset, int sbwidth)
|
||||||
|
{
|
||||||
|
/* Internal function determine how many of the previous colums can be shown */
|
||||||
|
uint16_t *screencolwidth = printcell.colw[screen];
|
||||||
|
int screenicnwidth = printcell.iconw[screen];
|
||||||
|
int offset = 0;
|
||||||
|
int selcellw = screencolwidth[printcell.selcol] + text_offset;
|
||||||
|
int maxw = vp_w - (sbwidth + selcellw + 1);
|
||||||
|
|
||||||
|
for (int i = printcell.selcol - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
int cw = screencolwidth[i] + text_offset;
|
||||||
|
if (i == 0)
|
||||||
|
cw += screenicnwidth;
|
||||||
|
if (offset > 0 || cw > maxw)
|
||||||
|
offset += cw; /* can not display this cell -- everything left goes here too */
|
||||||
|
else
|
||||||
|
maxw -= cw; /* can display this cell subtract from the max width */
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info)
|
||||||
|
{
|
||||||
|
/* Internal function callback from the list, draws items as they are requested */
|
||||||
|
#define ICON_PADDING 1
|
||||||
|
#define ICON_PADDING_S "1"
|
||||||
|
struct screen *display = list_info->display;
|
||||||
|
int screen = display->screen_type;
|
||||||
|
int col_offset_width = printcell.offw[screen];
|
||||||
|
int text_offset = col_offset_width + col_offset_width;
|
||||||
|
|
||||||
|
static char printcell_buffer[PRINTCELL_MAXLINELEN];
|
||||||
|
static uint16_t sidx[PRINTCELL_MAX_COLUMNS]; /*indexes zero terminated strings in buffer*/
|
||||||
|
|
||||||
|
int offset_pos = list_info->list->offset_position[screen];
|
||||||
|
int x = list_info->x - offset_pos;
|
||||||
|
int y = list_info->y;
|
||||||
|
int line_indent = list_info->item_indent;
|
||||||
|
int item_offset = list_info->item_offset;
|
||||||
|
int icon = list_info->icon;
|
||||||
|
int icon_w = list_info->icon_width;
|
||||||
|
bool is_title = list_info->is_title;
|
||||||
|
bool is_selected = list_info->is_selected;
|
||||||
|
bool show_cursor = list_info->show_cursor;
|
||||||
|
bool have_icons = list_info->have_icons;
|
||||||
|
struct line_desc *linedes = list_info->linedes;
|
||||||
|
char *dsp_text = list_info->dsp_text;
|
||||||
|
struct viewport *vp = list_info->vp;
|
||||||
|
|
||||||
|
int selected_flag = ((is_selected || is_title) ?
|
||||||
|
(is_title ? TITLE_FLAG : SELECTED_FLAG) : 0);
|
||||||
|
int vp_w = vp->width;/* save for restore */
|
||||||
|
int saved_separator_height = linedes->separator_height;/* save for restore */
|
||||||
|
|
||||||
|
linedes->separator_height = 0;
|
||||||
|
int separator = saved_separator_height;
|
||||||
|
|
||||||
|
if (printcell.separator || (selected_flag & SELECTED_FLAG))
|
||||||
|
separator = 1;
|
||||||
|
|
||||||
|
int nx = x;
|
||||||
|
int nw, colxw;
|
||||||
|
|
||||||
|
printcell_buffer[0] = '\0';
|
||||||
|
parse_dsptext(printcell.ncols, dsp_text, printcell_buffer, sidx);
|
||||||
|
char *buftext = &printcell_buffer[sidx[0]];
|
||||||
|
uint16_t *screencolwidth = printcell.colw[screen];
|
||||||
|
|
||||||
|
if (is_title)
|
||||||
|
{
|
||||||
|
int sbwidth = 0;
|
||||||
|
if (rb->global_settings->scrollbar == SCROLLBAR_LEFT)
|
||||||
|
sbwidth = rb->global_settings->scrollbar_width;
|
||||||
|
|
||||||
|
printcell.iconw[screen] = have_icons ? ICON_PADDING + icon_w : 0;
|
||||||
|
|
||||||
|
if (printcell.selcol_offw[screen] == 0 && printcell.selcol > 0)
|
||||||
|
printcell.selcol_offw[screen] = calcvisible(screen, vp_w, text_offset, sbwidth);
|
||||||
|
nx -= printcell.selcol_offw[screen];
|
||||||
|
|
||||||
|
nw = screencolwidth[0] + printcell.iconw[screen] + text_offset;
|
||||||
|
nw += sbwidth;
|
||||||
|
|
||||||
|
colxw = nx + nw;
|
||||||
|
if (colxw > 0)
|
||||||
|
{
|
||||||
|
set_cell_width(vp, vp_w, colxw);
|
||||||
|
linedes->separator_height = separator;
|
||||||
|
|
||||||
|
if (have_icons)
|
||||||
|
{
|
||||||
|
display->put_line(nx + (COLUMN_ENDLEN/2), y, linedes,
|
||||||
|
"$"ICON_PADDING_S"I$t", icon, buftext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
display->put_line(nx + col_offset_width, y, linedes, "$t", buftext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int cursor = Icon_NOICON;
|
||||||
|
nx -= printcell.selcol_offw[screen];
|
||||||
|
|
||||||
|
if (selected_flag & SELECTED_FLAG)
|
||||||
|
{
|
||||||
|
printcell.selcol_index = sidx[printcell.selcol]; /* save the item offset*/
|
||||||
|
cursor = Icon_Cursor;
|
||||||
|
/* limit length of selection if columns don't reach end */
|
||||||
|
int maxw = nx + printcell.totalcolw[screen] + printcell.iconw[screen];
|
||||||
|
maxw += text_offset * printcell.ncols;
|
||||||
|
if (vp_w > maxw)
|
||||||
|
vp->width = maxw;
|
||||||
|
/* display a blank line first to draw selector across all cells */
|
||||||
|
display->put_line(x, y, linedes, "$t", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
nw = screencolwidth[0] + printcell.iconw[screen] + text_offset;
|
||||||
|
colxw = nx + nw;
|
||||||
|
if (colxw > 0)
|
||||||
|
{
|
||||||
|
set_cell_width(vp, vp_w, colxw);
|
||||||
|
if (printcell.selcol == 0 && selected_flag == 0)
|
||||||
|
linedes->separator_height = 0;
|
||||||
|
else
|
||||||
|
linedes->separator_height = separator;
|
||||||
|
|
||||||
|
if (show_cursor && have_icons)
|
||||||
|
{
|
||||||
|
/* the list can have both, one of or neither of cursor and item icons,
|
||||||
|
* if both don't apply icon padding twice between the icons */
|
||||||
|
display->put_line(nx, y,
|
||||||
|
linedes, "$*s$"ICON_PADDING_S"I$i$"ICON_PADDING_S"s$*t",
|
||||||
|
line_indent, cursor, icon, item_offset, buftext);
|
||||||
|
}
|
||||||
|
else if (show_cursor || have_icons)
|
||||||
|
{
|
||||||
|
display->put_line(nx, y, linedes, "$*s$"ICON_PADDING_S"I$*t", line_indent,
|
||||||
|
show_cursor ? cursor:icon, item_offset, buftext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
display->put_line(nx + col_offset_width, y, linedes,
|
||||||
|
"$*s$*t", line_indent, item_offset, buftext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colxw > 0) /* draw selector for first column (title or items) */
|
||||||
|
{
|
||||||
|
vp->width += COLUMN_ENDLEN + 1;
|
||||||
|
draw_selector(display, linedes, selected_flag, 0,
|
||||||
|
separator, nx, y, nw, linedes->height);
|
||||||
|
}
|
||||||
|
nx += nw;
|
||||||
|
/* display remaining cells */
|
||||||
|
printcells(display, printcell_buffer, sidx, linedes,
|
||||||
|
vp, vp_w, separator, nx, y, col_offset_width, selected_flag);
|
||||||
|
/* restore settings */
|
||||||
|
linedes->separator_height = saved_separator_height;
|
||||||
|
display->set_drawmode(DRMODE_FG);
|
||||||
|
vp->width = vp_w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printcell_enable(struct gui_synclist *gui_list, bool enable, bool separator)
|
||||||
|
{
|
||||||
|
printcell.separator = separator;
|
||||||
|
#ifdef HAVE_LCD_COLOR
|
||||||
|
static int list_sep_color = INT_MIN;
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
list_sep_color = rb->global_settings->list_separator_color;
|
||||||
|
rb->global_settings->list_separator_color = rb->global_settings->fg_color;
|
||||||
|
gui_list->callback_draw_item = printcell_listdraw_fn;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gui_list->callback_draw_item = NULL;
|
||||||
|
if (list_sep_color != INT_MIN)
|
||||||
|
rb->global_settings->list_separator_color = list_sep_color;
|
||||||
|
list_sep_color = INT_MIN;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (enable)
|
||||||
|
gui_list->callback_draw_item = printcell_listdraw_fn;
|
||||||
|
else
|
||||||
|
gui_list->callback_draw_item = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int printcell_increment_column(struct gui_synclist *gui_list, int increment, bool wrap)
|
||||||
|
{
|
||||||
|
int item = printcell.selcol + increment;
|
||||||
|
int imin = -1;
|
||||||
|
int imax = printcell.ncols - 1;
|
||||||
|
if(wrap)
|
||||||
|
{
|
||||||
|
imin = imax;
|
||||||
|
imax = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item < -1)
|
||||||
|
item = imin;
|
||||||
|
else if (item >= printcell.ncols)
|
||||||
|
item = imax;
|
||||||
|
|
||||||
|
if (item != printcell.selcol)
|
||||||
|
{
|
||||||
|
FOR_NB_SCREENS(n) /* offset needs recalculated */
|
||||||
|
printcell.selcol_offw[n] = 0;
|
||||||
|
printcell.selcol = item;
|
||||||
|
printcell.selcol_index = 0;
|
||||||
|
rb->gui_synclist_draw(gui_list);
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
int printcell_set_columns(struct gui_synclist *gui_list,
|
||||||
|
char * title, enum themable_icons icon)
|
||||||
|
{
|
||||||
|
if (title == NULL)
|
||||||
|
title = "$PRINTCELL NOT SETUP";
|
||||||
|
uint16_t sidx[PRINTCELL_MAX_COLUMNS]; /* starting position of column in title string */
|
||||||
|
int width, height, user_minwidth;
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
int ch = '$'; /* first column $ is optional */
|
||||||
|
|
||||||
|
rb->memset(&printcell, 0, sizeof(struct printcell_info_t));
|
||||||
|
|
||||||
|
FOR_NB_SCREENS(n)
|
||||||
|
{
|
||||||
|
rb->screens[n]->getstringsize("W", &width, &height);
|
||||||
|
printcell.offw[n] = width; /* set column text offset */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*title == '$')
|
||||||
|
title++;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (ch == '$')
|
||||||
|
{
|
||||||
|
printcell.title[j++] = ch;
|
||||||
|
user_minwidth = 0;
|
||||||
|
if (*title == '*')/* user wants a minimum size for this column */
|
||||||
|
{
|
||||||
|
char *dspst = title++; /* store starting position in case this is wrong */
|
||||||
|
while(isdigit(*title))
|
||||||
|
{
|
||||||
|
user_minwidth = 10*user_minwidth + *title - '0';
|
||||||
|
title++;
|
||||||
|
}
|
||||||
|
if (*title != '$') /* user forgot $ or wants to display '*' */
|
||||||
|
{
|
||||||
|
title = dspst;
|
||||||
|
user_minwidth = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
title++;
|
||||||
|
}
|
||||||
|
|
||||||
|
sidx[i] = j;
|
||||||
|
if (*title == '$') /* $$ escaped user must want to display $*/
|
||||||
|
printcell.title[j++] = *title++;
|
||||||
|
|
||||||
|
while (*title != '\0' && *title != '$' && j < PRINTCELL_MAXLINELEN - 1)
|
||||||
|
printcell.title[j++] = *title++;
|
||||||
|
|
||||||
|
FOR_NB_SCREENS(n)
|
||||||
|
{
|
||||||
|
rb->screens[n]->getstringsize(&printcell.title[sidx[i]], &width, &height);
|
||||||
|
if (width < user_minwidth)
|
||||||
|
width = user_minwidth;
|
||||||
|
printcell.colw[n][i] = width;
|
||||||
|
printcell.totalcolw[n] += width;
|
||||||
|
}
|
||||||
|
if (++i >= PRINTCELL_MAX_COLUMNS - 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ch = *title++;
|
||||||
|
} while (ch != '\0');
|
||||||
|
printcell.ncols = i;
|
||||||
|
printcell.title[j] = '\0';
|
||||||
|
printcell.selcol = -1;
|
||||||
|
printcell.selcol_index = 0;
|
||||||
|
|
||||||
|
rb->gui_synclist_set_title(gui_list, printcell.title, icon);
|
||||||
|
return printcell.ncols;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *printcell_get_selected_column_text(struct gui_synclist *gui_list, char *buf, size_t bufsz)
|
||||||
|
{
|
||||||
|
int selected = gui_list->selected_item;
|
||||||
|
int index = printcell.selcol_index - 1;
|
||||||
|
|
||||||
|
if (index < 0)
|
||||||
|
index = 0;
|
||||||
|
char *bpos;
|
||||||
|
|
||||||
|
if (gui_list->callback_get_item_name(selected, gui_list->data, buf, bufsz) == buf)
|
||||||
|
{
|
||||||
|
bpos = &buf[index];
|
||||||
|
if (printcell.selcol < 0) /* return entire string incld col formatting '$'*/
|
||||||
|
return bpos;
|
||||||
|
while(bpos < &buf[bufsz - 1])
|
||||||
|
{
|
||||||
|
if (*bpos == '$' || *bpos == '\0')
|
||||||
|
goto success;
|
||||||
|
bpos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*failure*/
|
||||||
|
bpos = buf;
|
||||||
|
index = 0;
|
||||||
|
success:
|
||||||
|
*bpos = '\0';
|
||||||
|
return &buf[index];
|
||||||
|
}
|
45
apps/plugins/lib/printcell_helper.h
Normal file
45
apps/plugins/lib/printcell_helper.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 William Wilgus
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _PRINTCELL_LIST_H_
|
||||||
|
#define _PRINTCELL_LIST_H_
|
||||||
|
#define PRINTCELL_MAXLINELEN MAX_PATH
|
||||||
|
|
||||||
|
/* sets the printcell function enabled */
|
||||||
|
void printcell_enable(struct gui_synclist *gui_list, bool enable, bool separator);
|
||||||
|
|
||||||
|
/* sets title and calculates cell widths each column is identified by '$' character
|
||||||
|
ex 3 columns title = "Col1$Col2$Col3" also accepts $*WIDTH$
|
||||||
|
ex 3 columns varying width title = "$*64$Col1$*128$Col2$Col3
|
||||||
|
returns number of columns
|
||||||
|
*/
|
||||||
|
int printcell_set_columns(struct gui_synclist *gui_list,
|
||||||
|
char * title, enum themable_icons icon);
|
||||||
|
|
||||||
|
/* increments the current selected column negative increment is allowed
|
||||||
|
returns the selected column
|
||||||
|
range: -1(no selection) to ncols - 1 */
|
||||||
|
int printcell_increment_column(struct gui_synclist *gui_list, int increment, bool wrap);
|
||||||
|
|
||||||
|
/* return the text of currently selected column buffer should be sized
|
||||||
|
* for max item len, buf[PRINTCELL_MAXLINELEN] is a safe bet */
|
||||||
|
char *printcell_get_selected_column_text(struct gui_synclist *gui_list, char *buf, size_t bufsz);
|
||||||
|
#endif /*_PRINTCELL_LIST_H_*/
|
|
@ -29,8 +29,9 @@
|
||||||
#include "lib/action_helper.h"
|
#include "lib/action_helper.h"
|
||||||
#include "lib/button_helper.h"
|
#include "lib/button_helper.h"
|
||||||
#include "lib/pluginlib_actions.h"
|
#include "lib/pluginlib_actions.h"
|
||||||
|
#include "lib/printcell_helper.h"
|
||||||
|
|
||||||
#define MENU_ID(x) (((void*)&"RPBUTACNGX\0" + x))
|
#define MENU_ID(x) (((void*)&"RPBUTACNGSX\0" + x))
|
||||||
enum {
|
enum {
|
||||||
M_ROOT = 0,
|
M_ROOT = 0,
|
||||||
M_PATHS,
|
M_PATHS,
|
||||||
|
@ -41,6 +42,7 @@ enum {
|
||||||
M_CONTEXTS,
|
M_CONTEXTS,
|
||||||
M_ACTTEST,
|
M_ACTTEST,
|
||||||
M_PLUGINS,
|
M_PLUGINS,
|
||||||
|
M_TESTPUT,
|
||||||
M_EXIT,
|
M_EXIT,
|
||||||
M_LAST_ITEM //ITEM COUNT
|
M_LAST_ITEM //ITEM COUNT
|
||||||
};
|
};
|
||||||
|
@ -96,7 +98,8 @@ static const struct paths paths[] = {
|
||||||
{"Fm Presets", ""FMPRESET_PATH},
|
{"Fm Presets", ""FMPRESET_PATH},
|
||||||
{"MAX_PATH", ""MACROVAL(MAX_PATH)" bytes"},
|
{"MAX_PATH", ""MACROVAL(MAX_PATH)" bytes"},
|
||||||
};
|
};
|
||||||
|
#define TESTPUT_HEADER "$*64$col1$col2$*128$col3$col4$col5$col6$*64$col7$col8"
|
||||||
|
static int testput_cols = 0;
|
||||||
struct mainmenu { const char *name; void *menuid; int items;};
|
struct mainmenu { const char *name; void *menuid; int items;};
|
||||||
static struct mainmenu mainmenu[M_LAST_ITEM] = {
|
static struct mainmenu mainmenu[M_LAST_ITEM] = {
|
||||||
#define MENU_ITEM(ID, NAME, COUNT) [ID]{NAME, MENU_ID(ID), (int)COUNT}
|
#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),
|
||||||
MENU_ITEM(M_CONTEXTS, "Contexts", LAST_CONTEXT_PLACEHOLDER ),
|
MENU_ITEM(M_CONTEXTS, "Contexts", LAST_CONTEXT_PLACEHOLDER ),
|
||||||
MENU_ITEM(M_ACTTEST, "Action test", 3),
|
MENU_ITEM(M_ACTTEST, "Action test", 3),
|
||||||
MENU_ITEM(M_PLUGINS, ID2P(LANG_PLUGINS), MENU_ID_PLUGINS_ITEMS),
|
MENU_ITEM(M_PLUGINS, ID2P(LANG_PLUGINS), MENU_ID_PLUGINS_ITEMS),
|
||||||
|
MENU_ITEM(M_TESTPUT, "Printcell test", 36),
|
||||||
MENU_ITEM(M_EXIT, ID2P(LANG_MENU_QUIT), 0),
|
MENU_ITEM(M_EXIT, ID2P(LANG_MENU_QUIT), 0),
|
||||||
#undef MENU_ITEM
|
#undef MENU_ITEM
|
||||||
};
|
};
|
||||||
|
@ -125,9 +129,17 @@ static const struct mainmenu *mainitem(int selected_item)
|
||||||
static void cleanup(void *parameter)
|
static void cleanup(void *parameter)
|
||||||
{
|
{
|
||||||
(void)parameter;
|
(void)parameter;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static enum themable_icons menu_icon_cb(int selected_item, void * data)
|
||||||
|
{
|
||||||
|
(void)data;
|
||||||
|
(void)selected_item;
|
||||||
|
return Icon_NOICON;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char *menu_plugin_name_cb(int selected_item, void* data,
|
static const char *menu_plugin_name_cb(int selected_item, void* data,
|
||||||
char* buf, size_t buf_len)
|
char* buf, size_t buf_len)
|
||||||
{
|
{
|
||||||
|
@ -247,7 +259,7 @@ static const char* list_get_name_cb(int selected_item, void* data,
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
if (data == MENU_ID(M_ROOT))
|
if (data == MENU_ID(M_ROOT))
|
||||||
return mainitem(selected_item)->name;
|
return mainitem(selected_item)->name;
|
||||||
else if (selected_item == 0) /*header text*/
|
else if (selected_item == 0 && data != MENU_ID(M_TESTPUT)) /*header text*/
|
||||||
return mainitem(main_last_sel)->name;
|
return mainitem(main_last_sel)->name;
|
||||||
else if (selected_item >= mainitem(main_last_sel)->items - 1)
|
else if (selected_item >= mainitem(main_last_sel)->items - 1)
|
||||||
return ID2P(LANG_BACK);
|
return ID2P(LANG_BACK);
|
||||||
|
@ -286,6 +298,11 @@ static const char* list_get_name_cb(int selected_item, void* data,
|
||||||
{
|
{
|
||||||
return menu_plugin_name_cb(selected_item - 1, data, buf, buf_len);
|
return menu_plugin_name_cb(selected_item - 1, data, buf, buf_len);
|
||||||
}
|
}
|
||||||
|
else if (data == MENU_ID(M_TESTPUT))
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,16 +348,38 @@ static int list_voice_cb(int list_index, void* data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclist *lists)
|
int menu_action_cb(int *action, int selected_item, bool* exit, struct gui_synclist *lists)
|
||||||
{
|
{
|
||||||
if (lists->data == MENU_ID(M_ACTTEST))
|
if (lists->data == MENU_ID(M_TESTPUT) && (selected_item < (mainitem(M_TESTPUT)->items) - 1)/*back*/)
|
||||||
|
{
|
||||||
|
if (*action == ACTION_STD_OK)
|
||||||
|
{
|
||||||
|
printcell_increment_column(lists, 1, true);
|
||||||
|
*action = ACTION_NONE;
|
||||||
|
}
|
||||||
|
else if (*action == ACTION_STD_CANCEL)
|
||||||
|
{
|
||||||
|
if (printcell_increment_column(lists, -1, true) != testput_cols - 1)
|
||||||
|
{
|
||||||
|
*action = ACTION_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (*action == ACTION_STD_CONTEXT)
|
||||||
|
{
|
||||||
|
char buf[PRINTCELL_MAXLINELEN];
|
||||||
|
char* bufp = buf;
|
||||||
|
bufp = printcell_get_selected_column_text(lists, bufp, PRINTCELL_MAXLINELEN);
|
||||||
|
rb->splashf(HZ * 2, "Item: %s", bufp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lists->data == MENU_ID(M_ACTTEST))
|
||||||
{
|
{
|
||||||
if (selected_item == 2) /* context */
|
if (selected_item == 2) /* context */
|
||||||
{
|
{
|
||||||
int ctx = m_test.context;
|
int ctx = m_test.context;
|
||||||
if (action == ACTION_STD_OK)
|
if (*action == ACTION_STD_OK)
|
||||||
m_test.context++;
|
m_test.context++;
|
||||||
else if (action == ACTION_STD_CANCEL)
|
else if (*action == ACTION_STD_CANCEL)
|
||||||
m_test.context--;
|
m_test.context--;
|
||||||
|
|
||||||
if (m_test.context < 0)
|
if (m_test.context < 0)
|
||||||
|
@ -353,7 +392,7 @@ int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclis
|
||||||
|
|
||||||
goto default_handler;
|
goto default_handler;
|
||||||
}
|
}
|
||||||
if (action == ACTION_STD_OK)
|
if (*action == ACTION_STD_OK)
|
||||||
{
|
{
|
||||||
if (selected_item == 1 || selected_item == 3)
|
if (selected_item == 1 || selected_item == 3)
|
||||||
{
|
{
|
||||||
|
@ -364,7 +403,7 @@ int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclis
|
||||||
}
|
}
|
||||||
else if (lists->data == MENU_ID(M_BTNTEST))
|
else if (lists->data == MENU_ID(M_BTNTEST))
|
||||||
{
|
{
|
||||||
if (action == ACTION_STD_OK)
|
if (*action == ACTION_STD_OK)
|
||||||
{
|
{
|
||||||
if (selected_item == 1 || selected_item == 2)
|
if (selected_item == 1 || selected_item == 2)
|
||||||
{
|
{
|
||||||
|
@ -373,18 +412,38 @@ int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclis
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (action == ACTION_STD_OK)
|
/* common */
|
||||||
|
if (*action == ACTION_STD_OK)
|
||||||
{
|
{
|
||||||
if (lists->data == MENU_ID(M_ROOT))
|
if (lists->data == MENU_ID(M_ROOT))
|
||||||
{
|
{
|
||||||
rb->memset(&m_test, 0, sizeof(struct menu_test_t));
|
rb->memset(&m_test, 0, sizeof(struct menu_test_t));
|
||||||
const struct mainmenu *cur = mainitem(selected_item);
|
const struct mainmenu *cur = mainitem(selected_item);
|
||||||
|
|
||||||
if (cur->menuid == NULL || cur->menuid == MENU_ID(M_EXIT))
|
if (cur->menuid == NULL || cur->menuid == MENU_ID(M_EXIT))
|
||||||
*exit = true;
|
*exit = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
main_last_sel = selected_item;
|
main_last_sel = selected_item;
|
||||||
|
|
||||||
|
if (cur->menuid == MENU_ID(M_TESTPUT))
|
||||||
|
{
|
||||||
|
//rb->gui_list_screen_scroll_out_of_view(true);
|
||||||
|
synclist_set(cur->menuid, 0, cur->items, 1);
|
||||||
|
#if LCD_DEPTH > 1
|
||||||
|
/* If line sep is set to automatic then outline cells */
|
||||||
|
bool showlinesep = (rb->global_settings->list_separator_height < 0);
|
||||||
|
#else
|
||||||
|
bool showlinesep = (rb->global_settings->cursor_style == 0);
|
||||||
|
#endif
|
||||||
|
printcell_enable(lists, true, showlinesep);
|
||||||
|
//lists->callback_draw_item = test_listdraw_fn;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printcell_enable(lists, false, false);
|
||||||
synclist_set(cur->menuid, 1, cur->items, 1);
|
synclist_set(cur->menuid, 1, cur->items, 1);
|
||||||
|
}
|
||||||
rb->gui_synclist_draw(lists);
|
rb->gui_synclist_draw(lists);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -394,7 +453,11 @@ int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclis
|
||||||
}
|
}
|
||||||
else if (selected_item >= (mainitem(main_last_sel)->items) - 1)/*back*/
|
else if (selected_item >= (mainitem(main_last_sel)->items) - 1)/*back*/
|
||||||
{
|
{
|
||||||
action = ACTION_STD_CANCEL;
|
*action = ACTION_STD_CANCEL;
|
||||||
|
}
|
||||||
|
else if (lists->data == MENU_ID(M_TESTPUT))
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (lists->data == MENU_ID(M_ACTIONS) ||
|
else if (lists->data == MENU_ID(M_ACTIONS) ||
|
||||||
lists->data == MENU_ID(M_CONTEXTS))
|
lists->data == MENU_ID(M_CONTEXTS))
|
||||||
|
@ -406,8 +469,14 @@ int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclis
|
||||||
rb->button_get(true);
|
rb->button_get(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (action == ACTION_STD_CANCEL)
|
if (*action == ACTION_STD_CANCEL)
|
||||||
{
|
{
|
||||||
|
if (lists->data == MENU_ID(M_TESTPUT))
|
||||||
|
{
|
||||||
|
//rb->gui_list_screen_scroll_out_of_view(false);
|
||||||
|
//lists->callback_draw_item = NULL;
|
||||||
|
printcell_enable(lists, false, false);
|
||||||
|
}
|
||||||
if (lists->data != MENU_ID(M_ROOT))
|
if (lists->data != MENU_ID(M_ROOT))
|
||||||
{
|
{
|
||||||
const struct mainmenu *mainm = &mainmenu[0];
|
const struct mainmenu *mainm = &mainmenu[0];
|
||||||
|
@ -418,7 +487,7 @@ int menu_action_cb(int action, int selected_item, bool* exit, struct gui_synclis
|
||||||
*exit = true;
|
*exit = true;
|
||||||
}
|
}
|
||||||
default_handler:
|
default_handler:
|
||||||
if (rb->default_event_handler_ex(action, cleanup, NULL) == SYS_USB_CONNECTED)
|
if (rb->default_event_handler_ex(*action, cleanup, NULL) == SYS_USB_CONNECTED)
|
||||||
{
|
{
|
||||||
*exit = true;
|
*exit = true;
|
||||||
return PLUGIN_USB_CONNECTED;
|
return PLUGIN_USB_CONNECTED;
|
||||||
|
@ -436,7 +505,14 @@ static void synclist_set(char* menu_id, int selected_item, int items, int sel_si
|
||||||
list_voice_cb(0, menu_id);
|
list_voice_cb(0, menu_id);
|
||||||
rb->gui_synclist_init(&lists,list_get_name_cb,
|
rb->gui_synclist_init(&lists,list_get_name_cb,
|
||||||
menu_id, false, sel_size, NULL);
|
menu_id, false, sel_size, NULL);
|
||||||
|
if (menu_id == MENU_ID(M_TESTPUT))
|
||||||
|
{
|
||||||
|
testput_cols = printcell_set_columns(&lists, TESTPUT_HEADER, Icon_Rockbox);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rb->gui_synclist_set_title(&lists, NULL,-1);
|
||||||
|
}
|
||||||
rb->gui_synclist_set_icon_callback(&lists,NULL);
|
rb->gui_synclist_set_icon_callback(&lists,NULL);
|
||||||
rb->gui_synclist_set_voice_callback(&lists, list_voice_cb);
|
rb->gui_synclist_set_voice_callback(&lists, list_voice_cb);
|
||||||
rb->gui_synclist_set_nb_items(&lists,items);
|
rb->gui_synclist_set_nb_items(&lists,items);
|
||||||
|
@ -460,7 +536,7 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
/* add header and back item to each submenu */
|
/* add header and back item to each submenu */
|
||||||
for (int i = 1; i < M_LAST_ITEM; i++)
|
for (int i = 1; i < M_LAST_ITEM; i++)
|
||||||
mainmenu[i].items += 2;
|
mainmenu[i].items += 2;
|
||||||
|
mainmenu[M_TESTPUT].items -= 1;
|
||||||
if (!exit)
|
if (!exit)
|
||||||
{
|
{
|
||||||
const struct mainmenu *mainm = &mainmenu[0];
|
const struct mainmenu *mainm = &mainmenu[0];
|
||||||
|
@ -483,10 +559,10 @@ enum plugin_status plugin_start(const void* parameter)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
redraw = true;
|
redraw = true;
|
||||||
|
ret = menu_action_cb(&action, selected_item, &exit, &lists);
|
||||||
if (rb->gui_synclist_do_button(&lists,&action,LIST_WRAP_UNLESS_HELD))
|
if (rb->gui_synclist_do_button(&lists,&action,LIST_WRAP_UNLESS_HELD))
|
||||||
continue;
|
continue;
|
||||||
selected_item = rb->gui_synclist_get_sel_pos(&lists);
|
selected_item = rb->gui_synclist_get_sel_pos(&lists);
|
||||||
ret = menu_action_cb(action, selected_item, &exit, &lists);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue