🧑‍💻 Extend LCD string substitution (#24278)

This commit is contained in:
Scott Lahteine
2022-06-04 00:15:23 -05:00
parent fcef8d946c
commit 1e127a93c4
83 changed files with 1062 additions and 1281 deletions

View File

@ -94,7 +94,7 @@ class TFT {
static void canvas(uint16_t x, uint16_t y, uint16_t width, uint16_t height) { queue.canvas(x, y, width, height); }
static void set_background(uint16_t color) { queue.set_background(color); }
static void add_text(uint16_t x, uint16_t y, uint16_t color, TFT_String tft_string, uint16_t maxWidth = 0) { queue.add_text(x, y, color, tft_string.string(), maxWidth); }
static void add_text(uint16_t x, uint16_t y, uint16_t color, const char *string, uint16_t maxWidth = 0) { queue.add_text(x, y, color, (uint8_t *)string, maxWidth); }
static void add_text(uint16_t x, uint16_t y, uint16_t color, const char *string, uint16_t maxWidth = 0) { queue.add_text(x, y, color, string, maxWidth); }
static void add_image(int16_t x, int16_t y, MarlinImage image, uint16_t *colors) { queue.add_image(x, y, image, colors); }
static void add_image(int16_t x, int16_t y, MarlinImage image, uint16_t color_main = COLOR_WHITE, uint16_t color_background = COLOR_BACKGROUND, uint16_t color_shadow = COLOR_BLACK) { queue.add_image(x, y, image, color_main, color_background, color_shadow); }
static void add_bar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color) { queue.add_bar(x, y, width, height, color); }

View File

@ -215,13 +215,13 @@ void TFT_Queue::handle_queue_overflow(uint16_t sizeNeeded) {
}
}
void TFT_Queue::add_text(uint16_t x, uint16_t y, uint16_t color, uint8_t *string, uint16_t maxWidth) {
void TFT_Queue::add_text(uint16_t x, uint16_t y, uint16_t color, const uint8_t *string, uint16_t maxWidth) {
handle_queue_overflow(sizeof(parametersCanvasText_t) + maxWidth);
parametersCanvas_t *task_parameters = (parametersCanvas_t *)(((uint8_t *)last_task) + sizeof(queueTask_t));
parametersCanvasText_t *parameters = (parametersCanvasText_t *)end_of_queue;
last_parameter = end_of_queue;
uint8_t *pointer = string;
const uint8_t *pointer = string;
parameters->type = CANVAS_ADD_TEXT;
parameters->x = x;

View File

@ -139,7 +139,10 @@ class TFT_Queue {
static void fill(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color);
static void canvas(uint16_t x, uint16_t y, uint16_t width, uint16_t height);
static void set_background(uint16_t color);
static void add_text(uint16_t x, uint16_t y, uint16_t color, uint8_t *string, uint16_t maxWidth);
static void add_text(uint16_t x, uint16_t y, uint16_t color, const uint8_t *string, uint16_t maxWidth);
static void add_text(uint16_t x, uint16_t y, uint16_t color, const char *string, uint16_t maxWidth) {
add_text(x, y, color, (uint8_t *)string, maxWidth);
}
static void add_image(int16_t x, int16_t y, MarlinImage image, uint16_t *colors);
static void add_image(int16_t x, int16_t y, MarlinImage image, uint16_t color_main, uint16_t color_background, uint16_t color_shadow);

View File

@ -35,7 +35,7 @@
glyph_t *TFT_String::glyphs[256];
font_t *TFT_String::font_header;
uint8_t TFT_String::data[];
char TFT_String::data[];
uint16_t TFT_String::span;
uint8_t TFT_String::length;
@ -84,24 +84,22 @@ void TFT_String::set() {
length = 0;
}
uint8_t read_byte(uint8_t *byte) { return *byte; }
/**
* Add a string, applying substitutions for the following characters:
*
* $ displays an inserted C-string given by the inStr parameter
* $ displays the string given by fstr or cstr
* = displays '0'....'10' for indexes 0 - 10
* ~ displays '1'....'11' for indexes 0 - 10
* * displays 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL)
* @ displays an axis name such as XYZUVW, or E for an extruder
*/
void TFT_String::add(uint8_t *string, int8_t index, uint8_t *inStr/*=nullptr*/) {
void TFT_String::add(const char *tpl, const int8_t index, const char *cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/) {
wchar_t wchar;
while (*string) {
string = get_utf8_value_cb(string, read_byte, &wchar);
while (*tpl) {
tpl = get_utf8_value_cb(tpl, read_byte_ram, &wchar);
if (wchar > 255) wchar |= 0x0080;
uint8_t ch = uint8_t(wchar & 0x00FF);
const uint8_t ch = uint8_t(wchar & 0x00FF);
if (ch == '=' || ch == '~' || ch == '*') {
if (index >= 0) {
@ -111,10 +109,12 @@ void TFT_String::add(uint8_t *string, int8_t index, uint8_t *inStr/*=nullptr*/)
add_character('0' + inum);
}
else
add(index == -2 ? GET_TEXT(MSG_CHAMBER) : GET_TEXT(MSG_BED));
add(index == -2 ? GET_TEXT_F(MSG_CHAMBER) : GET_TEXT_F(MSG_BED));
}
else if (ch == '$' && inStr)
add(inStr);
else if (ch == '$' && fstr)
add(fstr);
else if (ch == '$' && cstr)
add(cstr);
else if (ch == '@')
add_character(axis_codes[index]);
else
@ -123,19 +123,19 @@ void TFT_String::add(uint8_t *string, int8_t index, uint8_t *inStr/*=nullptr*/)
eol();
}
void TFT_String::add(uint8_t *string, uint8_t max_len) {
void TFT_String::add(const char *cstr, uint8_t max_len/*=MAX_STRING_LENGTH*/) {
wchar_t wchar;
while (*string && max_len) {
string = get_utf8_value_cb(string, read_byte, &wchar);
while (*cstr && max_len) {
cstr = get_utf8_value_cb(cstr, read_byte_ram, &wchar);
if (wchar > 255) wchar |= 0x0080;
uint8_t ch = uint8_t(wchar & 0x00FF);
const uint8_t ch = uint8_t(wchar & 0x00FF);
add_character(ch);
max_len--;
}
eol();
}
void TFT_String::add_character(uint8_t character) {
void TFT_String::add_character(const char character) {
if (length < MAX_STRING_LENGTH) {
data[length] = character;
length++;
@ -143,7 +143,7 @@ void TFT_String::add_character(uint8_t character) {
}
}
void TFT_String::rtrim(uint8_t character) {
void TFT_String::rtrim(const char character) {
while (length) {
if (data[length - 1] == 0x20 || data[length - 1] == character) {
length--;
@ -155,7 +155,7 @@ void TFT_String::rtrim(uint8_t character) {
}
}
void TFT_String::ltrim(uint8_t character) {
void TFT_String::ltrim(const char character) {
uint16_t i, j;
for (i = 0; (i < length) && (data[i] == 0x20 || data[i] == character); i++) {
span -= glyph(data[i])->DWidth;
@ -166,7 +166,7 @@ void TFT_String::ltrim(uint8_t character) {
eol();
}
void TFT_String::trim(uint8_t character) {
void TFT_String::trim(const char character) {
rtrim(character);
ltrim(character);
}

View File

@ -21,6 +21,8 @@
*/
#pragma once
// TODO: Make AVR-compatible with separate ROM / RAM string methods
#include <stdint.h>
extern const uint8_t ISO10646_1_5x7[];
@ -67,14 +69,15 @@ class TFT_String {
static glyph_t *glyphs[256];
static font_t *font_header;
static uint8_t data[MAX_STRING_LENGTH + 1];
static char data[MAX_STRING_LENGTH + 1];
static uint16_t span; // in pixels
static uint8_t length; // in characters
static void add_character(uint8_t character);
static void eol() { data[length] = 0x00; }
static void add_character(const char character);
static void eol() { data[length] = '\0'; }
public:
static uint8_t length; // in characters
static void set_font(const uint8_t *font);
static void add_glyphs(const uint8_t *font);
@ -83,31 +86,69 @@ class TFT_String {
static glyph_t *glyph(uint8_t character) { return glyphs[character] ?: glyphs[0x3F]; } /* Use '?' for unknown glyphs */
static glyph_t *glyph(uint8_t *character) { return glyph(*character); }
/**
* @brief Set the string empty
*/
static void set();
static void add(uint8_t character) { add_character(character); eol(); }
static void add(uint8_t *string, uint8_t max_len=MAX_STRING_LENGTH);
static void add(uint8_t *string, int8_t index, uint8_t *inStr=nullptr);
static void set(uint8_t *string) { set(); add(string); };
static void set(uint8_t *string, int8_t index, const char *inStr=nullptr) { set(); add(string, index, (uint8_t *)inStr); };
static void set(const char *string) { set((uint8_t *)string); }
static void set(const char *string, int8_t index, const char *inStr=nullptr) { set((uint8_t *)string, index, inStr); }
static void add(const char *string) { add((uint8_t *)string); }
static void add(FSTR_P const string, uint8_t max_len=MAX_STRING_LENGTH) { add((uint8_t *)FTOP(string), max_len); }
static void add(FSTR_P const string, int8_t index, uint8_t *inStr=nullptr) { add((uint8_t *)FTOP(string), index, inStr); }
static void set(FSTR_P const string) { set((uint8_t *)FTOP(string)); }
static void set(FSTR_P const string, int8_t index, const char *inStr=nullptr) { set((uint8_t *)FTOP(string), index, inStr); }
static void add(FSTR_P const string) { add((uint8_t *)FTOP(string)); }
/**
* @brief Append an ASCII character and EOL
*
* @param character The ASCII character
*/
static void add(const char character) { add_character(character); eol(); }
static void set(wchar_t character) { set(); add(character); }
static void trim(uint8_t character=0x20);
static void rtrim(uint8_t character=0x20);
static void ltrim(uint8_t character=0x20);
/**
* @brief Append / Set C-string
*
* @param cstr The string
* @param max_len Character limit
*/
static void add(const char *cstr, uint8_t max_len=MAX_STRING_LENGTH);
static void set(const char *cstr, uint8_t max_len=MAX_STRING_LENGTH) { set(); add(cstr, max_len); }
static void truncate(uint8_t maxlen) { if (length > maxlen) { length = maxlen; eol(); } }
/**
* @brief Append / Set F-string
*
* @param fstr The string
* @param max_len Character limit
*/
static void add(FSTR_P const fstr, uint8_t max_len=MAX_STRING_LENGTH) { add(FTOP(fstr), max_len); }
static void set(FSTR_P const fstr, uint8_t max_len=MAX_STRING_LENGTH) { set(FTOP(fstr), max_len); }
/**
* @brief Append / Set C-string with optional substitution
*
* @param tpl A string with optional substitution
* @param index An index
* @param cstr An SRAM C-string to use for $ substitution
* @param fstr A ROM F-string to use for $ substitution
*/
static void add(const char *tpl, const int8_t index, const char *cstr=nullptr, FSTR_P const fstr=nullptr);
static void set(const char *tpl, const int8_t index, const char *cstr=nullptr, FSTR_P const fstr=nullptr) { set(); add(tpl, index, cstr, fstr); }
/**
* @brief Append / Set F-string with optional substitution
*
* @param ftpl A ROM F-string with optional substitution
* @param index An index
* @param cstr An SRAM C-string to use for $ substitution
* @param fstr A ROM F-string to use for $ substitution
*/
static void add(FSTR_P const ftpl, const int8_t index, const char *cstr=nullptr, FSTR_P const fstr=nullptr) { add(FTOP(ftpl), index, cstr, fstr); }
static void set(FSTR_P const ftpl, const int8_t index, const char *cstr=nullptr, FSTR_P const fstr=nullptr) { set(); add(ftpl, index, cstr, fstr); }
// Common string ops
static void trim(const char character=' ');
static void rtrim(const char character=' ');
static void ltrim(const char character=' ');
static void truncate(const uint8_t maxlen) { if (length > maxlen) { length = maxlen; eol(); } }
// Accessors
static char *string() { return data; }
static uint16_t width() { return span; }
static uint8_t *string() { return data; }
static uint16_t center(uint16_t width) { return span > width ? 0 : (width - span) / 2; }
static uint16_t center(const uint16_t width) { return span > width ? 0 : (width - span) / 2; }
};
extern TFT_String tft_string;

View File

@ -181,13 +181,13 @@ void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater) {
tft.add_image(8, 28, image, Color);
tft_string.set((uint8_t *)i16tostr3rj(currentTemperature));
tft_string.set(i16tostr3rj(currentTemperature));
tft_string.add(LCD_STR_DEGREE);
tft_string.trim();
tft.add_text(tft_string.center(80) + 2, 82, Color, tft_string);
if (targetTemperature >= 0) {
tft_string.set((uint8_t *)i16tostr3rj(targetTemperature));
tft_string.set(i16tostr3rj(targetTemperature));
tft_string.add(LCD_STR_DEGREE);
tft_string.trim();
tft.add_text(tft_string.center(80) + 2, 8, Color, tft_string);
@ -211,7 +211,7 @@ void draw_fan_status(uint16_t x, uint16_t y, const bool blink) {
tft.add_image(8, 20, image, COLOR_FAN);
tft_string.set((uint8_t *)ui8tostr4pctrj(thermalManager.fan_speed[0]));
tft_string.set(ui8tostr4pctrj(thermalManager.fan_speed[0]));
tft_string.trim();
tft.add_text(tft_string.center(80) + 6, 82, COLOR_FAN, tft_string);
}
@ -359,7 +359,7 @@ void MenuEditItemBase::draw_edit_screen(FSTR_P const fstr, const char * const va
uint16_t line = 1;
menu_line(line++);
tft_string.set(FTOP(fstr), itemIndex, FTOP(itemString));
tft_string.set(fstr, itemIndex, itemStringC, itemStringF);
tft_string.trim();
tft.add_text(tft_string.center(TFT_WIDTH), MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string);
@ -606,7 +606,7 @@ static void quick_feedback() {
#define CUR_STEP_VALUE_WIDTH 104
static void drawCurStepValue() {
tft_string.set((uint8_t *)ftostr52sp(motionAxisState.currentStepSize));
tft_string.set(ftostr52sp(motionAxisState.currentStepSize));
tft_string.add("mm");
tft.canvas(motionAxisState.stepValuePos.x, motionAxisState.stepValuePos.y, CUR_STEP_VALUE_WIDTH, BTN_HEIGHT);
tft.set_background(COLOR_BACKGROUND);

View File

@ -181,13 +181,13 @@ void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater) {
tft.add_image(0, 18, image, Color);
tft_string.set((uint8_t *)i16tostr3rj(currentTemperature));
tft_string.set(i16tostr3rj(currentTemperature));
tft_string.add(LCD_STR_DEGREE);
tft_string.trim();
tft.add_text(tft_string.center(64) + 2, 72, Color, tft_string);
if (targetTemperature >= 0) {
tft_string.set((uint8_t *)i16tostr3rj(targetTemperature));
tft_string.set(i16tostr3rj(targetTemperature));
tft_string.add(LCD_STR_DEGREE);
tft_string.trim();
tft.add_text(tft_string.center(64) + 2, 8, Color, tft_string);
@ -211,7 +211,7 @@ void draw_fan_status(uint16_t x, uint16_t y, const bool blink) {
tft.add_image(0, 10, image, COLOR_FAN);
tft_string.set((uint8_t *)ui8tostr4pctrj(thermalManager.fan_speed[0]));
tft_string.set(ui8tostr4pctrj(thermalManager.fan_speed[0]));
tft_string.trim();
tft.add_text(tft_string.center(64) + 6, 72, COLOR_FAN, tft_string);
}
@ -354,7 +354,7 @@ void MenuEditItemBase::draw_edit_screen(FSTR_P const fstr, const char * const va
uint16_t line = 1;
menu_line(line++);
tft_string.set(FTOP(fstr), itemIndex, FTOP(itemString));
tft_string.set(fstr, itemIndex, itemStringC, itemStringF);
tft_string.trim();
tft.add_text(tft_string.center(TFT_WIDTH), MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string);
@ -588,7 +588,7 @@ static void quick_feedback() {
#define CUR_STEP_VALUE_WIDTH 38
static void drawCurStepValue() {
tft_string.set((uint8_t *)ftostr52sp(motionAxisState.currentStepSize));
tft_string.set(ftostr52sp(motionAxisState.currentStepSize));
tft.canvas(motionAxisState.stepValuePos.x, motionAxisState.stepValuePos.y, CUR_STEP_VALUE_WIDTH, 20);
tft.set_background(COLOR_BACKGROUND);
tft.add_text(CUR_STEP_VALUE_WIDTH - tft_string.width(), 0, COLOR_AXIS_HOMED, tft_string);

View File

@ -181,13 +181,13 @@ void draw_heater_status(uint16_t x, uint16_t y, const int8_t Heater) {
tft.add_image(8, 28, image, Color);
tft_string.set((uint8_t *)i16tostr3rj(currentTemperature));
tft_string.set(i16tostr3rj(currentTemperature));
tft_string.add(LCD_STR_DEGREE);
tft_string.trim();
tft.add_text(tft_string.center(80) + 2, 82, Color, tft_string);
if (targetTemperature >= 0) {
tft_string.set((uint8_t *)i16tostr3rj(targetTemperature));
tft_string.set(i16tostr3rj(targetTemperature));
tft_string.add(LCD_STR_DEGREE);
tft_string.trim();
tft.add_text(tft_string.center(80) + 2, 8, Color, tft_string);
@ -211,7 +211,7 @@ void draw_fan_status(uint16_t x, uint16_t y, const bool blink) {
tft.add_image(8, 20, image, COLOR_FAN);
tft_string.set((uint8_t *)ui8tostr4pctrj(thermalManager.fan_speed[0]));
tft_string.set(ui8tostr4pctrj(thermalManager.fan_speed[0]));
tft_string.trim();
tft.add_text(tft_string.center(80) + 6, 82, COLOR_FAN, tft_string);
}
@ -359,7 +359,7 @@ void MenuEditItemBase::draw_edit_screen(FSTR_P const fstr, const char * const va
uint16_t line = 1;
menu_line(line++);
tft_string.set(FTOP(fstr), itemIndex, FTOP(itemString));
tft_string.set(fstr, itemIndex, itemStringC, itemStringF);
tft_string.trim();
tft.add_text(tft_string.center(TFT_WIDTH), MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string);
@ -593,7 +593,7 @@ static void quick_feedback() {
#define CUR_STEP_VALUE_WIDTH 104
static void drawCurStepValue() {
tft_string.set((uint8_t *)ftostr52sp(motionAxisState.currentStepSize));
tft_string.set(ftostr52sp(motionAxisState.currentStepSize));
tft_string.add("mm");
tft.canvas(motionAxisState.stepValuePos.x, motionAxisState.stepValuePos.y, CUR_STEP_VALUE_WIDTH, BTN_HEIGHT);
tft.set_background(COLOR_BACKGROUND);

View File

@ -96,16 +96,15 @@ void lcd_moveto(const lcd_uint_t col, const lcd_uint_t row) {
lcd_gotopixel(int(col) * (TFT_COL_WIDTH), int(row) * MENU_LINE_HEIGHT);
}
int lcd_put_wchar_max(wchar_t c, pixel_len_t max_length) {
int lcd_put_wchar_max(const wchar_t c, const pixel_len_t max_length) {
if (max_length < 1) return 0;
tft_string.set();
tft_string.add(c);
tft_string.set(c);
tft.add_text(MENU_TEXT_X_OFFSET, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string);
lcd_gotopixel((cursor.x + 1) * (TFT_COL_WIDTH) + tft_string.width(), cursor.y * MENU_LINE_HEIGHT);
return tft_string.width();
}
int lcd_put_u8str_max_P(PGM_P utf8_pstr, pixel_len_t max_length) {
int lcd_put_u8str_max_P(PGM_P utf8_pstr, const pixel_len_t max_length) {
if (max_length < 1) return 0;
tft_string.set(utf8_pstr);
tft_string.trim();
@ -115,7 +114,7 @@ int lcd_put_u8str_max_P(PGM_P utf8_pstr, pixel_len_t max_length) {
return tft_string.width();
}
int lcd_put_u8str_max(const char * utf8_str, pixel_len_t max_length) {
int lcd_put_u8str_max(const char * utf8_str, const pixel_len_t max_length) {
return lcd_put_u8str_max_P(utf8_str, max_length);
}
@ -133,7 +132,7 @@ void lcd_put_int(const int i) {
void MenuItemBase::_draw(const bool sel, const uint8_t row, FSTR_P const fstr, const char pre_char, const char post_char) {
menu_item(row, sel);
uint8_t *string = (uint8_t *)FTOP(fstr);
const char *string = FTOP(fstr);
MarlinImage image = noImage;
switch (*string) {
case 0x01: image = imgRefresh; break; // LCD_STR_REFRESH
@ -147,18 +146,19 @@ void MenuItemBase::_draw(const bool sel, const uint8_t row, FSTR_P const fstr, c
tft.add_image(MENU_ITEM_ICON_X, MENU_ITEM_ICON_Y, image, COLOR_MENU_TEXT, sel ? COLOR_SELECTION_BG : COLOR_BACKGROUND);
}
tft_string.set(string, itemIndex, FTOP(itemString));
tft_string.set(string, itemIndex, itemStringC, itemStringF);
tft.add_text(offset, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string);
}
// Draw a menu item with a (potentially) editable value
void MenuEditItemBase::draw(const bool sel, const uint8_t row, FSTR_P const fstr, const char * const data, const bool pgm) {
void MenuEditItemBase::draw(const bool sel, const uint8_t row, FSTR_P const fstr, const char * const inStr, const bool pgm) {
menu_item(row, sel);
tft_string.set(FTOP(fstr), itemIndex, FTOP(itemString));
tft_string.set(fstr, itemIndex, itemStringC, itemStringF);
tft.add_text(MENU_TEXT_X_OFFSET, MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string);
if (data) {
tft_string.set(data);
if (inStr) {
tft_string.set(inStr);
tft.add_text(TFT_WIDTH - MENU_TEXT_X_OFFSET - tft_string.width(), MENU_TEXT_Y_OFFSET, COLOR_MENU_VALUE, tft_string);
}
}
@ -166,7 +166,7 @@ void MenuEditItemBase::draw(const bool sel, const uint8_t row, FSTR_P const fstr
// Draw a static item with no left-right margin required. Centered by default.
void MenuItem_static::draw(const uint8_t row, FSTR_P const fstr, const uint8_t style/*=SS_DEFAULT*/, const char * const vstr/*=nullptr*/) {
menu_item(row);
tft_string.set(FTOP(fstr), itemIndex, FTOP(itemString));
tft_string.set(fstr, itemIndex, itemStringC, itemStringF);
if (vstr) tft_string.add(vstr);
tft.add_text(tft_string.center(TFT_WIDTH), MENU_TEXT_Y_OFFSET, COLOR_YELLOW, tft_string);
}