diff --git a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp index 716d1341db..ce19cb35ed 100644 --- a/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp +++ b/Marlin/src/lcd/HD44780/marlinui_HD44780.cpp @@ -1170,23 +1170,38 @@ void MarlinUI::draw_status_screen() { int8_t n = LCD_WIDTH; const bool center = bool(style & SS_CENTER), full = bool(style & SS_FULL); - const int8_t plen = ftpl ? utf8_strlen(ftpl) : 0, - vlen = vstr ? utf8_strlen(vstr) : 0; - int8_t pad = (center || full) ? n - plen - vlen : 0; + + // Value length, if any + int8_t vlen = vstr ? utf8_strlen(vstr) : 0; + + // Expanded label string and width in chars + char estr[calculateWidth(ftpl) + 3] = "\0"; + int8_t llen = ftpl ? expand_u8str(estr, ftpl, itemIndex, itemStringC, itemStringF, n - vlen) : 0; + + bool mv_colon = false; + if (vlen) { + // Move the leading colon from the value to the label below + mv_colon = (*vstr == ':'); + // Shorter value, wider label + if (mv_colon) { vstr++; vlen--; llen++; } + // Remove leading spaces from the value and shorten + while (*vstr == ' ') { vstr++; vlen--; } + } + + // Padding for center or full justification + int8_t pad = (center || full) ? n - llen - vlen : 0; // SS_CENTER: Pad with half of the unused space first - if (center) for (int8_t lpad = pad / 2; lpad > 0; --lpad) { lcd_put_u8str(F(" ")); n--; } + if (center) for (int8_t lpad = pad / 2; lpad > 0; --lpad, --pad, --n) lcd_put_u8str(F(" ")); - // Draw as much of the label as fits - if (plen) n -= lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, n - vlen); + // Draw as much of the label as fits (without the relocated colon, drawn below) + if (llen) n -= lcd_put_u8str_max(estr, n - vlen); if (vlen && n > 0) { // SS_FULL: Pad with enough space to justify the value if (full && !center) { // Move the leading colon from the value to the label - if (*vstr == ':') { n -= lcd_put_u8str(F(":")); vstr++; } - // Move spaces to the padding - while (*vstr == ' ') { vstr++; pad++; } + if (mv_colon) n -= lcd_put_u8str(F(":")); // Pad in-between for (; pad > 0; --pad) { lcd_put_u8str(F(" ")); n--; } } diff --git a/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp b/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp index 419088c4c7..a4d358c063 100644 --- a/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp +++ b/Marlin/src/lcd/TFTGLCD/marlinui_TFTGLCD.cpp @@ -975,23 +975,36 @@ void MarlinUI::draw_status_screen() { uint8_t n = LCD_WIDTH; const bool center = bool(style & SS_CENTER), full = bool(style & SS_FULL); - const int8_t plen = ftpl ? utf8_strlen(ftpl) : 0, - vlen = vstr ? utf8_strlen(vstr) : 0; - int8_t pad = (center || full) ? n - plen - vlen : 0; + + // Value length, if any + int8_t vlen = vstr ? utf8_strlen(vstr) : 0; + + char estr[utf8_strlen(ftpl) + 3] = "\0"; + int8_t llen = ftpl ? expand_u8str(estr, ftpl, itemIndex, itemStringC, itemStringF, n - vlen) : 0; + + bool mv_colon = false; + if (vlen) { + // Move the leading colon from the value to the label below + mv_colon = (*vstr == ':'); + // Shorter value, wider label + if (mv_colon) { vstr++; vlen--; llen++; } + // Remove leading spaces from the value and shorten + while (*vstr == ' ') { vstr++; vlen--; } + } + + int8_t pad = (center || full) ? n - llen - vlen : 0; // SS_CENTER: Pad with half of the unused space first if (center) for (int8_t lpad = pad / 2; lpad > 0; --lpad) { lcd.write(' '); n--; } // Draw as much of the label as fits - if (plen) n -= lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, n - vlen); + if (llen) n -= lcd_put_u8str_max(estr, n - vlen); if (vlen && n > 0) { // SS_FULL: Pad with enough space to justify the value if (full && !center) { // Move the leading colon from the value to the label - if (*vstr == ':') { lcd.write(':'); vstr++; n--; } - // Move spaces to the padding - while (*vstr == ' ') { vstr++; pad++; } + if (mv_colon) { lcd.write(':'); n--; } // Pad in-between for (; pad > 0; --pad) { lcd.write(' '); n--; } } diff --git a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp index 6c15572f04..1b608bcf58 100644 --- a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp +++ b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp @@ -414,30 +414,46 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop if (!mark_as_selected(row, style & SS_INVERT)) return; pixel_len_t n = LCD_PIXEL_WIDTH; // pixel width of string allowed - const bool center = bool(style & SS_CENTER), full = bool(style & SS_FULL); - const int pwide = ftpl ? calculateWidth(ftpl) : 0, - vlen = vstr ? utf8_strlen(vstr) : 0; - int pad = (center || full) ? ((LCD_PIXEL_WIDTH) - pwide - vlen * (MENU_FONT_WIDTH)) / (MENU_FONT_WIDTH) : 0; + + char estr[calculateWidth(ftpl) + 3] = "\0"; + pixel_len_t lwide = ftpl ? (MENU_FONT_WIDTH) * expand_u8str(estr, ftpl, itemIndex, itemStringC, itemStringF, (LCD_PIXEL_WIDTH) / (MENU_FONT_WIDTH)) : 0; + + // Value length, if any + int8_t vlen = vstr ? utf8_strlen(vstr) : 0; + + bool mv_colon = false; + if (vlen) { + // Move the leading colon from the value to the label below + mv_colon = (*vstr == ':'); + // Shorter value, wider label + if (mv_colon) { vstr++; vlen--; lwide += MENU_FONT_WIDTH; } + // Remove leading spaces from the value and shorten + while (*vstr == ' ') { vstr++; vlen--; } + } + + // Padding for center or full justification + int8_t pad = (center || full) ? ((LCD_PIXEL_WIDTH) - lwide - vlen * (MENU_FONT_WIDTH)) / (MENU_FONT_WIDTH) : 0; // SS_CENTER: Pad with half of the unused space first - if (center) for (int lpad = pad / 2; lpad > 0; --lpad) n -= lcd_put_u8str(F(" ")); + if (center) for (int8_t lpad = pad / 2; lpad > 0; --lpad) n -= lcd_put_u8str(F(" ")); - // Draw as much of the label as fits - if (pwide) n -= lcd_put_u8str(ftpl, itemIndex, itemStringC, itemStringF, n / (MENU_FONT_WIDTH)) * (MENU_FONT_WIDTH); + // Draw as much of the label as fits (without the relocated colon, drawn below) + if (lwide) lcd_put_u8str_max(estr, n); + // Value string? if (vlen) { // SS_FULL: Pad with enough space to justify the value if (full && !center && n > MENU_FONT_WIDTH) { - // Move the leading colon from the value to the label - if (*vstr == ':') { n -= lcd_put_u8str(F(":")); vstr++; } - // Move spaces to the padding - while (*vstr == ' ') { vstr++; pad++; } + // Draw the leading colon moved from the value to the label + if (mv_colon) n -= lcd_put_u8str(F(":")); // Pad in-between for (; pad > 0; --pad) n -= lcd_put_u8str(F(" ")); } + // Draw the value string n -= lcd_put_u8str_max(vstr, n); } + // Always fill out the rest with spaces while (n > MENU_FONT_WIDTH) n -= lcd_put_u8str(F(" ")); } diff --git a/Marlin/src/lcd/e3v2/marlinui/ui_common.cpp b/Marlin/src/lcd/e3v2/marlinui/ui_common.cpp index c0bf0a75d6..f6804acac7 100644 --- a/Marlin/src/lcd/e3v2/marlinui/ui_common.cpp +++ b/Marlin/src/lcd/e3v2/marlinui/ui_common.cpp @@ -317,26 +317,39 @@ void MarlinUI::draw_status_message(const bool blink) { dwin_string.set(); const bool center = bool(style & SS_CENTER), full = bool(style & SS_FULL); - const int8_t plen = ftpl ? utf8_strlen(ftpl) : 0, - vlen = vstr ? utf8_strlen(vstr) : 0; + int8_t plen = ftpl ? utf8_strlen(ftpl) : 0; + const int8_t olen = plen; + + // Value length, if any + int8_t vlen = vstr ? utf8_strlen(vstr) : 0; + + bool mv_colon = false; + if (vlen) { + // Move the leading colon from the value to the label below + mv_colon = (*vstr == ':'); + // Shorter value, wider label + if (mv_colon) { vstr++; vlen--; plen++; } + // Remove leading spaces from the value and shorten + while (*vstr == ' ') { vstr++; vlen--; } + } + int8_t pad = (center || full) ? (LCD_WIDTH) - 1 - plen - vlen : 0; // SS_CENTER: Pad with half of the unused space first - if (center) for (int8_t lpad = pad / 2; lpad > 0; --lpad) dwin_string.add(' '); + if (center) for (int8_t lpad = pad / 2; lpad > 0; --lpad, --pad) dwin_string.add(' '); - // Append the templated label string if (plen) { + // Append the templated label string dwin_string.add(ftpl, itemIndex, itemStringC, itemStringF); - pad -= dwin_string.length - plen; + // Remove padding if the string was expanded + pad -= dwin_string.length - olen; } // SS_FULL: Pad with enough space to justify the value if (vlen) { if (full && !center) { - // Move the leading colon from the value to the label - if (*vstr == ':') { dwin_string.add(':'); vstr++; } - // Move spaces to the padding - while (*vstr == ' ') { vstr++; pad++; } + // Append the leading colon moved from the value to the label + if (mv_colon) dwin_string.add(':'); // Pad in-between for (; pad > 0; --pad) dwin_string.add(' '); } @@ -345,7 +358,7 @@ void MarlinUI::draw_status_message(const bool blink) { } // SS_CENTER: Pad the rest of the string - if (center) for (int8_t rpad = pad - (pad / 2); rpad > 0; --rpad) dwin_string.add(' '); + if (center) while (pad--) dwin_string.add(' '); lcd_moveto(1, row); lcd_put_dwin_string(); diff --git a/Marlin/src/lcd/lcdprint.cpp b/Marlin/src/lcd/lcdprint.cpp index 70e4e73269..2b524e983f 100644 --- a/Marlin/src/lcd/lcdprint.cpp +++ b/Marlin/src/lcd/lcdprint.cpp @@ -123,50 +123,10 @@ lcd_uint_t expand_u8str_P(char * const outstr, PGM_P const ptpl, const int8_t in * Return the number of characters emitted */ lcd_uint_t lcd_put_u8str_P(PGM_P const ptpl, const int8_t ind, const char *cstr/*=nullptr*/, FSTR_P const fstr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) { - const uint8_t prop = USE_WIDE_GLYPH ? 2 : 1; - const uint8_t *p = (uint8_t*)ptpl; - int8_t n = maxlen; - while (n > 0) { - lchar_t wc; - p = get_utf8_value_cb(p, read_byte_rom, wc); - if (!wc) break; - if (wc == '{' || wc == '~' || wc == '*') { - if (ind >= 0) { - if (wc == '*') { lcd_put_u8str(F("E")); n--; } - if (n) { - int8_t inum = ind + ((wc == '{') ? 0 : LCD_FIRST_TOOL); - if (inum >= 10) { - lcd_put_lchar('0' + (inum / 10)); n--; - inum %= 10; - } - if (n) { lcd_put_lchar('0' + inum); n--; } - } - } - else { - PGM_P const b = ind == -2 ? GET_TEXT(MSG_CHAMBER) : GET_TEXT(MSG_BED); - n -= lcd_put_u8str_max_P(b, n * (MENU_FONT_WIDTH)) / (MENU_FONT_WIDTH); - } - if (n) { - n -= lcd_put_u8str_max_P((PGM_P)p, n * (MENU_FONT_WIDTH)) / (MENU_FONT_WIDTH); - break; - } - } - else if (wc == '$' && fstr) { - n -= lcd_put_u8str_max_P(FTOP(fstr), n * (MENU_FONT_WIDTH)) / (MENU_FONT_WIDTH); - } - else if (wc == '$' && cstr) { - n -= lcd_put_u8str_max(cstr, n * (MENU_FONT_WIDTH)) / (MENU_FONT_WIDTH); - } - else if (wc == '@') { - lcd_put_lchar(AXIS_CHAR(ind)); - n--; - } - else { - lcd_put_lchar(wc); - n -= wc > 255 ? prop : 1; - } - } - return maxlen - n; + char estr[maxlen + 2]; + const lcd_uint_t outlen = expand_u8str_P(estr, ptpl, ind, cstr, fstr, maxlen); + lcd_put_u8str_max(estr, maxlen * (MENU_FONT_WIDTH)); + return outlen; } // Calculate UTF8 width with a simple check diff --git a/Marlin/src/lcd/menu/menu_configuration.cpp b/Marlin/src/lcd/menu/menu_configuration.cpp index 293067b15c..63b7c527e0 100644 --- a/Marlin/src/lcd/menu/menu_configuration.cpp +++ b/Marlin/src/lcd/menu/menu_configuration.cpp @@ -104,7 +104,14 @@ void menu_advanced_settings(); #define __STOP_ITEM(F,S) PSTRING_ITEM_F_P(F, TEST(stops, S) ? PSTR(STR_ENDSTOP_HIT) : PSTR(STR_ENDSTOP_OPEN), SS_FULL); #define _STOP_ITEM(L,S) __STOP_ITEM(F(L), S) - #define STOP_ITEM(A,I,M,L) TERN(HAS_##A##I##_##M##_STATE, _STOP_ITEM, _IF_1_ELSE)(STRINGIFY(A) STRINGIFY(I) " " STRINGIFY(L), A##I##_##M) + #if HAS_X2_STATE || HAS_Y2_STATE || HAS_Z2_STATE + #define _S1_EXP_ ~, + #define _S1_SP_(I) THIRD(I, " ", "") + #define S1_SPACE(I) _S1_SP_(_CAT(_S1_EXP_,I)) + #else + #define S1_SPACE(I) + #endif + #define STOP_ITEM(A,I,M,L) TERN(HAS_##A##I##_##M##_STATE, _STOP_ITEM, _IF_1_ELSE)(STRINGIFY(A) STRINGIFY(I) S1_SPACE(I) " " L, A##I##_##M) #define STOP_MINMAX(A,I) STOP_ITEM(A,I,MIN,"Min") STOP_ITEM(A,I,MAX,"Max") #define FIL_ITEM(N) PSTRING_ITEM_N_P(N-1, MSG_FILAMENT_EN, (READ(FIL_RUNOUT##N##_PIN) != FIL_RUNOUT##N##_STATE) ? PSTR("PRESENT") : PSTR("out"), SS_FULL);