summaryrefslogtreecommitdiffstats
path: root/apps/plugins/lib/printcell_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/lib/printcell_helper.c')
-rw-r--r--apps/plugins/lib/printcell_helper.c297
1 files changed, 222 insertions, 75 deletions
diff --git a/apps/plugins/lib/printcell_helper.c b/apps/plugins/lib/printcell_helper.c
index 42de444c57..48b8b2c9d2 100644
--- a/apps/plugins/lib/printcell_helper.c
+++ b/apps/plugins/lib/printcell_helper.c
@@ -22,10 +22,6 @@
#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
@@ -37,48 +33,54 @@
#endif
struct printcell_info_t {
- int offw[NB_SCREENS];
- int iconw[NB_SCREENS];
- int selcol_offw[NB_SCREENS];
- int totalcolw[NB_SCREENS];
- int firstcolxw[NB_SCREENS];
- uint16_t colw[NB_SCREENS][PRINTCELL_MAX_COLUMNS];
- int ncols;
- int selcol;
- int selcol_index;
- char title[PRINTCELL_MAXLINELEN];
- bool separator;
+ struct gui_synclist *gui_list; /* list to display */
+ int offw[NB_SCREENS]; /* padding between column boundries and text */
+ int iconw[NB_SCREENS]; /* width of an icon */
+ int selcol_offw[NB_SCREENS]; /* offset width calculated for selected item */
+ int totalcolw[NB_SCREENS]; /* total width of all columns */
+ int firstcolxw[NB_SCREENS]; /* first column x + width, save recalculating */
+ int ncols; /* number of columns */
+ int selcol; /* selected column (-1 to ncols-1) */
+ uint32_t hidecol_flags; /*bits 0-31 set bit to 1 to hide a column (1<<col#) */
+ uint16_t colw[NB_SCREENS][PRINTCELL_MAX_COLUMNS]; /* width of title text
+ or MIN(or user defined width / screen width) */
+ char title[PRINTCELL_MAXLINELEN]; /* title buffer */
+ char titlesep; /* character that separates title column items (ex '$') */
+ char colsep; /* character that separates text column items (ex ',') */
+ bool separator; /* draw grid */
};
+
static struct printcell_info_t printcell;
-static void parse_dsptext(int ncols, const char *dsp_text, char* buffer, uint16_t *sidx)
+static void parse_dsptext(char splitchr, int ncols, const char *dsp_text,
+ char* buffer, size_t bufsz, uint16_t *sidx)
{
/*Internal function loads sidx with split offsets indexing
- the buffer of null terminated strings, splits on '$'
+ the buffer of null terminated strings, splits on 'splitchr'
_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 == '$')
+ size_t j = 0;
+ int ch = splitchr; /* first column $ is optional */
+ if (*dsp_text == splitchr)
dsp_text++;
/* add null to the start of the text buffer */
buffer[j++] = '\0';
do
{
- if (ch == '$')
+ if (ch == splitchr)
{
- 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)
+ sidx[i] = j; /* save start index and copy next column to the buffer */
+ while (*dsp_text != '\0' && *dsp_text != splitchr && j < (bufsz - 1))
+ {
buffer[j++] = *dsp_text++;
+ }
buffer[j++] = '\0';
+
i++;
- if (i >= ncols || j >= (PRINTCELL_MAXLINELEN - 1))
+ if (i >= ncols || j >= (bufsz - 1))
break;
}
ch = *dsp_text++;
@@ -146,23 +148,39 @@ static inline void set_cell_width(struct viewport *vp, int max_w, int new_w)
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, bool scroll)
+ int x, int y, int offw, int selected_flag, int last_col,
+ bool scroll, bool is_title)
{
/* 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++)
+ for(int i = 1; i <= last_col; i++)
{
int ny = y;
int nw = screencolwidth[i] + text_offset;
+ int offx = 0;
+
+ if (i == last_col || x + nw >= vp_w - offw + 1)
+ { /* not enough space for next column use up excess */
+ if (nw < (vp_w - x))
+ {
+ if (is_title)
+ offx = ((vp_w - x) - nw) / 2;
+ nw = vp_w - x;
+ }
+ }
+
+ if (!PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, i))
+ nw = 0;
+
int nx = x + nw;
char *buftext;
- if (nx > 0 && x < vp_w)
+
+ if (nx > 0 && nw > offw && x < vp_w)
{
set_cell_width(vp, vp_w, nx);
@@ -173,11 +191,15 @@ static inline int printcells(struct screen *display, char* buffer,
}
else
{
+ if (vp_w < x + text_offset)
+ {
+ scroll = false;
+ }
linedes->scroll = scroll;
linedes->separator_height = separator;
}
buftext = &buffer[sidx[i]];
- display->put_line(x + offw, ny, linedes, "$t", buftext);
+ display->put_line(x + offw + offx, ny, linedes, "$t", buftext);
vp->width += COLUMN_ENDLEN + 1;
draw_selector(display, linedes, selected_flag, i, separator, x, ny, nw, height);
}
@@ -200,6 +222,10 @@ static inline int calcvisible(int screen, int vp_w, int text_offset, int sbwidth
for (int i = printcell.selcol - 1; i >= 0; i--)
{
int cw = screencolwidth[i] + text_offset;
+
+ if (!PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, i))
+ cw = 0;
+
if (i == 0)
cw += screenicnwidth;
if (offset > 0 || cw > maxw)
@@ -257,15 +283,30 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info)
separator = 1;
int nx = x;
+ int last_col = printcell.ncols - 1;
+ int hidden_w = 0;
int nw, colxw;
-
+ char *buftext;
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 (printcell.hidecol_flags > 0)
+ {
+ for (int i = 0; i < printcell.ncols; i++)
+ {
+ if (PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, i))
+ last_col = i;
+ else
+ hidden_w += (screencolwidth[i] + text_offset);
+ }
+ }
if (is_title)
{
+ parse_dsptext(printcell.titlesep, printcell.ncols, dsp_text,
+ printcell_buffer, sizeof(printcell_buffer), sidx);
+
+ buftext = &printcell_buffer[sidx[0]]; /* set to first column text */
int sbwidth = 0;
if (rb->global_settings->scrollbar == SCROLLBAR_LEFT)
sbwidth = rb->global_settings->scrollbar_width;
@@ -278,6 +319,9 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info)
nx -= printcell.selcol_offw[screen];
nw = screencolwidth[0] + printcell.iconw[screen] + text_offset;
+
+ if (!PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, 0))
+ nw = printcell.iconw[screen] - 1;
nw += sbwidth;
colxw = nx + nw;
@@ -301,20 +345,21 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info)
}
else
{
+ parse_dsptext(printcell.colsep, printcell.ncols, dsp_text,
+ printcell_buffer, sizeof(printcell_buffer), sidx);
+
+ buftext = &printcell_buffer[sidx[0]]; /* set to first column text */
int cursor = Icon_NOICON;
nx -= printcell.selcol_offw[screen];
if (selected_flag & SELECTED_FLAG)
{
- if (printcell.selcol >= 0)
- printcell.selcol_index = sidx[printcell.selcol]; /* save the item offset*/
- else
- printcell.selcol_index = -1;
-
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;
+ maxw -= hidden_w;
+
if (vp_w > maxw)
vp->width = maxw;
/* display a blank line first to draw selector across all cells */
@@ -364,7 +409,7 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info)
nx += nw;
/* display remaining cells */
printcells(display, printcell_buffer, sidx, linedes, vp, vp_w, separator,
- nx, y, col_offset_width, selected_flag, scroll_items);
+ nx, y, col_offset_width, selected_flag, last_col, scroll_items, is_title);
/* draw a line at the bottom of the list */
if (separator > 0 && line == list->nb_items - 1)
@@ -377,14 +422,17 @@ static void printcell_listdraw_fn(struct list_putlineinfo_t *list_info)
vp->width = vp_w;
}
-void printcell_enable(struct gui_synclist *gui_list, bool enable, bool separator)
+void printcell_enable(bool enable)
{
- printcell.separator = separator;
+ if (!printcell.gui_list)
+ return;
+ struct gui_synclist *gui_list = printcell.gui_list;
#ifdef HAVE_LCD_COLOR
static int list_sep_color = INT_MIN;
if (enable)
{
- list_sep_color = rb->global_settings->list_separator_color;
+ if (list_sep_color == INT_MIN)
+ 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;
}
@@ -404,8 +452,11 @@ void printcell_enable(struct gui_synclist *gui_list, bool enable, bool separator
}
-int printcell_increment_column(struct gui_synclist *gui_list, int increment, bool wrap)
+int printcell_increment_column(int increment, bool wrap)
{
+ if (!printcell.gui_list)
+ return -1;
+ struct gui_synclist *gui_list = printcell.gui_list;
int item = printcell.selcol + increment;
int imin = -1;
int imax = printcell.ncols - 1;
@@ -425,36 +476,94 @@ int printcell_increment_column(struct gui_synclist *gui_list, int increment, boo
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);
+ rb->gui_synclist_speak_item(gui_list);
}
return item;
}
+int printcell_get_column_selected(void)
+{
+ if (!printcell.gui_list)
+ return -1;
+ return printcell.selcol;
+}
+
+uint32_t printcell_get_column_visibility(int col)
+{
+ if (col >= 0)
+ return (PRINTCELL_COLUMN_IS_VISIBLE(printcell.hidecol_flags, col) ? 0:1);
+ else /* return flag of all columns */
+ return printcell.hidecol_flags;
+}
+
+void printcell_set_column_visible(int col, bool visible)
+{
+ /* visible columns have 0 for the column bit hidden columns have the bit set */
+ if (col >= 0)
+ {
+ if (visible)
+ printcell.hidecol_flags &= ~(PRINTCELL_COLUMN_FLAG(col));
+ else
+ printcell.hidecol_flags |= PRINTCELL_COLUMN_FLAG(col);
+ }
+ else
+ {
+ if (visible) /* set to everything visible */
+ printcell.hidecol_flags = 0;
+ else /* set to everything hidden */
+ printcell.hidecol_flags = ((uint32_t)-1);
+ }
+}
+
int printcell_set_columns(struct gui_synclist *gui_list,
- char * title, enum themable_icons icon)
+ struct printcell_settings * pcs,
+ char * title, enum themable_icons icon)
{
+
if (title == NULL)
title = "$PRINTCELL NOT SETUP";
+
+ if (pcs == NULL) /* DEFAULTS */
+ {
+#if LCD_DEPTH > 1
+ /* If line sep is set to automatic then outline cells */
+ bool sep = (rb->global_settings->list_separator_height < 0);
+#else
+ bool sep = (rb->global_settings->cursor_style == 0);
+#endif
+ pcs = &(struct printcell_settings){ .cell_separator = sep,
+ .title_delimeter = '$',
+ .text_delimeter = '$',
+ .hidecol_flags = 0};
+ }
+
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 */
-
+ size_t j = 0;
rb->memset(&printcell, 0, sizeof(struct printcell_info_t));
+ printcell.gui_list = gui_list;
+ printcell.separator = pcs->cell_separator;
+ printcell.titlesep = pcs->title_delimeter;
+ printcell.colsep = pcs->text_delimeter;
+ printcell.hidecol_flags = pcs->hidecol_flags;
+
+ int ch = printcell.titlesep; /* first column $ is optional */
+
FOR_NB_SCREENS(n)
{
rb->screens[n]->getstringsize("W", &width, &height);
printcell.offw[n] = width; /* set column text offset */
}
- if (*title == '$')
+ if (*title == printcell.titlesep)
title++;
do
{
- if (ch == '$')
+ if (ch == printcell.titlesep)
{
printcell.title[j++] = ch;
user_minwidth = 0;
@@ -466,7 +575,7 @@ int printcell_set_columns(struct gui_synclist *gui_list,
user_minwidth = 10*user_minwidth + *title - '0';
title++;
}
- if (*title != '$') /* user forgot $ or wants to display '*' */
+ if (*title != printcell.titlesep) /* user forgot titlesep or wants to display '*' */
{
title = dspst;
user_minwidth = 0;
@@ -476,17 +585,25 @@ int printcell_set_columns(struct gui_synclist *gui_list,
}
sidx[i] = j;
- if (*title == '$') /* $$ escaped user must want to display $*/
- printcell.title[j++] = *title++;
- while (*title != '\0' && *title != '$' && j < PRINTCELL_MAXLINELEN - 1)
+ while (*title != '\0'
+ && *title != printcell.titlesep
+ && j < PRINTCELL_MAXLINELEN - 1)
+ {
printcell.title[j++] = *title++;
+ }
FOR_NB_SCREENS(n)
{
- rb->screens[n]->getstringsize(&printcell.title[sidx[i]], &width, &height);
+ rb->screens[n]->getstringsize(&printcell.title[sidx[i]],
+ &width, &height);
+
if (width < user_minwidth)
width = user_minwidth;
+
+ if (width > LCD_WIDTH)
+ width = LCD_WIDTH;
+
printcell.colw[n][i] = width;
printcell.totalcolw[n] += width;
}
@@ -498,37 +615,67 @@ int printcell_set_columns(struct gui_synclist *gui_list,
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)
+char *printcell_get_title_text(int selcol, char *buf, size_t bufsz)
{
- int selected = gui_list->selected_item;
- int index = printcell.selcol_index - 1;
+ /* note offsets are calculated everytime this function is called
+ * shouldn't be used in hot code paths */
+ int index = 0;
+ buf[0] = '\0';
+ if (selcol < 0) /* return entire string incld col formatting '$'*/
+ return printcell.title;
+
+ if (selcol < printcell.ncols)
+ {
+ uint16_t sidx[PRINTCELL_MAX_COLUMNS]; /*indexes zero terminated strings in buffer*/
+ parse_dsptext(printcell.titlesep, selcol + 1, printcell.title, buf, bufsz, sidx);
+ index = sidx[selcol];
+ }
+ return &buf[index];
+}
- if (index < 0)
- index = 0;
+char *printcell_get_column_text(int selcol, char *buf, size_t bufsz)
+{
+ int index = 0;
char *bpos;
+ struct gui_synclist *gui_list = printcell.gui_list;
- if (gui_list->callback_get_item_name(selected, gui_list->data, buf, bufsz) == buf)
+ if (gui_list && gui_list->callback_draw_item == printcell_listdraw_fn)
{
- bpos = &buf[index];
- if (printcell.selcol < 0) /* return entire string incld col formatting '$'*/
- return bpos;
- while(bpos < &buf[bufsz - 1])
+ int col = selcol;
+ int item = gui_list->selected_item;
+ void *data = gui_list->data;
+
+ if (col < printcell.ncols
+ && gui_list->callback_get_item_name(item, data, buf, bufsz) == buf)
{
- if (*bpos == '$' || *bpos == '\0')
- goto success;
- bpos++;
+ bpos = buf;
+ if (col < 0) /* return entire string incld col formatting '$'*/
+ {
+ return bpos;
+ }
+ bpos++; /* Skip sep/NULL */
+
+ while(bpos < &buf[bufsz - 1])
+ {
+ if (*bpos == printcell.colsep || *bpos == '\0')
+ {
+ if (col-- == 0)
+ goto success;
+ index = bpos - buf + 1; /* Skip sep/NULL */
+ }
+ bpos++;
+ }
}
}
/*failure*/
- bpos = buf;
- index = 0;
+ bpos = buf;
+ index = 0;
success:
- *bpos = '\0';
- return &buf[index];
+ *bpos = '\0';
+ return &buf[index];
}