From 9cc16f87e225d4f9f4ca002b2c33a6fda3da5c25 Mon Sep 17 00:00:00 2001
From: Dmitry Plastinin <Uncellon@yandex.ru>
Date: Sat, 6 May 2023 00:05:30 +0300
Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=B8=20TS35=20portrait=20display=20(#25?=
 =?UTF-8?q?629)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Marlin/src/inc/Conditionals_LCD.h |  11 ++-
 Marlin/src/lcd/tft/ui_480x320.cpp | 143 +++++++++++++++++-------------
 Marlin/src/lcd/tft/ui_480x320.h   |  65 ++++++++++++++
 3 files changed, 155 insertions(+), 64 deletions(-)

diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h
index 44072ef4a2a..bee4abf7a70 100644
--- a/Marlin/src/inc/Conditionals_LCD.h
+++ b/Marlin/src/inc/Conditionals_LCD.h
@@ -1686,8 +1686,13 @@
   #define TFT_HEIGHT 272
   #define GRAPHICAL_TFT_UPSCALE 2
 #elif ENABLED(TFT_RES_480x320)
-  #define TFT_WIDTH  480
-  #define TFT_HEIGHT 320
+  #if ENABLED(TFT_COLOR_UI_PORTRAIT)
+    #define TFT_WIDTH  320
+    #define TFT_HEIGHT 480
+  #else
+    #define TFT_WIDTH  480
+    #define TFT_HEIGHT 320
+  #endif
   #define GRAPHICAL_TFT_UPSCALE 3
 #elif ENABLED(TFT_RES_1024x600)
   #define TFT_WIDTH  1024
@@ -1708,7 +1713,7 @@
     #elif ENABLED(TFT_INTERFACE_FSMC)
       #define TFT_320x240
     #endif
-  #elif TFT_HEIGHT == 320
+  #elif TFT_HEIGHT == 320 || (TFT_HEIGHT == 480 && ENABLED(TFT_COLOR_UI_PORTRAIT))
     #if ENABLED(TFT_INTERFACE_SPI)
       #define TFT_480x320_SPI
     #elif ENABLED(TFT_INTERFACE_FSMC)
diff --git a/Marlin/src/lcd/tft/ui_480x320.cpp b/Marlin/src/lcd/tft/ui_480x320.cpp
index efb58754c79..bc4ea0e5e22 100644
--- a/Marlin/src/lcd/tft/ui_480x320.cpp
+++ b/Marlin/src/lcd/tft/ui_480x320.cpp
@@ -49,9 +49,9 @@ void MarlinUI::tft_idle() {
   #if ENABLED(TOUCH_SCREEN)
     if (TERN0(HAS_TOUCH_SLEEP, lcd_sleep_task())) return;
     if (draw_menu_navigation) {
-      add_control(104, TFT_HEIGHT - 34, PAGE_UP, imgPageUp, encoderTopLine > 0);
-      add_control(344, TFT_HEIGHT - 34, PAGE_DOWN, imgPageDown, encoderTopLine + LCD_HEIGHT < screen_items);
-      add_control(224, TFT_HEIGHT - 34, BACK, imgBack);
+      add_control(TFT_WIDTH / 6 - 16, TFT_HEIGHT - 34, PAGE_UP, imgPageUp, encoderTopLine > 0);
+      add_control(TFT_WIDTH / 2 - 16, TFT_HEIGHT - 34, PAGE_DOWN, imgPageDown, encoderTopLine + LCD_HEIGHT < screen_items);
+      add_control(5 * TFT_WIDTH / 6 - 16, TFT_HEIGHT - 34, BACK, imgBack);
       draw_menu_navigation = false;
     }
   #endif
@@ -222,11 +222,10 @@ void MarlinUI::draw_status_screen() {
 
   TERN_(TOUCH_SCREEN, touch.clear());
 
-  // heaters and fan
-  uint16_t i, x, y = TFT_STATUS_TOP_Y;
-
-  for (i = 0 ; i < ITEMS_COUNT; i++) {
-    x = (TFT_WIDTH / ITEMS_COUNT - 80) / 2  + (TFT_WIDTH * i / ITEMS_COUNT);
+  // Statuses of heaters and fans
+  uint16_t y = STATUS_MARGIN_SIZE;
+  for (uint16_t i = 0; i < ITEMS_COUNT; i++) {
+    uint16_t x = (TFT_WIDTH / ITEMS_COUNT - 80) / 2  + (TFT_WIDTH * i / ITEMS_COUNT);
     switch (i) {
       #if HAS_EXTRUDERS
         case ITEM_E0: draw_heater_status(x, y, H_E0); break;
@@ -252,12 +251,13 @@ void MarlinUI::draw_status_screen() {
     }
   }
 
-  y += TERN(HAS_UI_480x272, 120, 128);
+  y += STATUS_MARGIN_SIZE + 114;
 
-  // coordinates
-  tft.canvas(4, y, TFT_WIDTH - 8, FONT_LINE_HEIGHT);
+  // Coordinates
+  constexpr uint16_t coords_width = TFT_WIDTH - 8;
+  tft.canvas((TFT_WIDTH - coords_width) / 2, y, coords_width, FONT_LINE_HEIGHT);
   tft.set_background(COLOR_BACKGROUND);
-  tft.add_rectangle(0, 0, TFT_WIDTH - 8, FONT_LINE_HEIGHT, COLOR_AXIS_HOMED);
+  tft.add_rectangle(0, 0, coords_width, FONT_LINE_HEIGHT, COLOR_AXIS_HOMED);
 
   if (TERN0(LCD_SHOW_E_TOTAL, printingIsActive())) {
     #if ENABLED(LCD_SHOW_E_TOTAL)
@@ -270,67 +270,86 @@ void MarlinUI::draw_status_screen() {
     #endif
   }
   else {
-    tft.add_text( 16, tft_string.vcenter(FONT_LINE_HEIGHT), COLOR_AXIS_HOMED , "X");
+    // Coords in mask "X____Y____Z____"
+    tft_string.set("X");
+    tft.add_text(coords_width / 30 - tft_string.width() / 2, tft_string.vcenter(FONT_LINE_HEIGHT), COLOR_AXIS_HOMED, tft_string);
+
     const bool nhx = axis_should_home(X_AXIS);
     tft_string.set(blink && nhx ? "?" : ftostr4sign(LOGICAL_X_POSITION(current_position.x)));
-    tft.add_text(102 - tft_string.width(), tft_string.vcenter(FONT_LINE_HEIGHT), nhx ? COLOR_AXIS_NOT_HOMED : COLOR_AXIS_HOMED, tft_string);
+    tft_string.ltrim();
+    tft.add_text(coords_width / 5 - tft_string.width() / 2, tft_string.vcenter(FONT_LINE_HEIGHT), nhx ? COLOR_AXIS_NOT_HOMED : COLOR_AXIS_HOMED, tft_string);
+
+    tft_string.set("Y");
+    tft.add_text(11 * coords_width / 30 - tft_string.width() / 2, tft_string.vcenter(FONT_LINE_HEIGHT), COLOR_AXIS_HOMED, tft_string);
 
-    tft.add_text(192, tft_string.vcenter(FONT_LINE_HEIGHT), COLOR_AXIS_HOMED , "Y");
     const bool nhy = axis_should_home(Y_AXIS);
     tft_string.set(blink && nhy ? "?" : ftostr4sign(LOGICAL_Y_POSITION(current_position.y)));
-    tft.add_text(280 - tft_string.width(), tft_string.vcenter(FONT_LINE_HEIGHT), nhy ? COLOR_AXIS_NOT_HOMED : COLOR_AXIS_HOMED, tft_string);
+    tft_string.ltrim();
+    tft.add_text(8 * coords_width / 15 - tft_string.width() / 2, tft_string.vcenter(FONT_LINE_HEIGHT), nhy ? COLOR_AXIS_NOT_HOMED : COLOR_AXIS_HOMED, tft_string);
   }
-  tft.add_text(330, tft_string.vcenter(FONT_LINE_HEIGHT), COLOR_AXIS_HOMED , "Z");
-  uint16_t offset = 32;
-  const bool nhz = axis_should_home(Z_AXIS);
-  if (blink && nhz)
-    tft_string.set('?');
-  else {
-    const float z = LOGICAL_Z_POSITION(current_position.z);
-    tft_string.set(ftostr52sp((int16_t)z));
-    tft_string.rtrim();
-    offset += tft_string.width();
 
-    tft_string.set(ftostr52sp(z));
-    offset -= tft_string.width();
-  }
-  tft.add_text(455 - tft_string.width() - offset, tft_string.vcenter(FONT_LINE_HEIGHT), nhz ? COLOR_AXIS_NOT_HOMED : COLOR_AXIS_HOMED, tft_string);
+  tft_string.set("Z");
+  tft.add_text(7 * coords_width / 10 - tft_string.width() / 2, tft_string.vcenter(FONT_LINE_HEIGHT), COLOR_AXIS_HOMED, tft_string);
+
+  const bool nhz = axis_should_home(Z_AXIS);
+  tft_string.set(blink && nhz ? "?" : ftostr52sp(LOGICAL_Z_POSITION(current_position.z)));
+  tft_string.ltrim();
+  tft_string.rtrim();
+  tft.add_text(13 * coords_width / 15 - tft_string.width() / 2, tft_string.vcenter(FONT_LINE_HEIGHT), nhz ? COLOR_AXIS_NOT_HOMED : COLOR_AXIS_HOMED, tft_string);
+
   TERN_(TOUCH_SCREEN, touch.add_control(MOVE_AXIS, 4, y, TFT_WIDTH - 8, FONT_LINE_HEIGHT));
 
-  y += TERN(HAS_UI_480x272, 34, 48);
-  // feed rate
-  tft.canvas(96, y, 128, 32);
-  tft.set_background(COLOR_BACKGROUND);
-  uint16_t color = feedrate_percentage == 100 ? COLOR_RATE_100 : COLOR_RATE_ALTERED;
-  tft.add_image(0, 0, imgFeedRate, color);
-  tft_string.set(i16tostr3rj(feedrate_percentage));
-  tft_string.add('%');
-  tft.add_text(36, tft_string.vcenter(30), color , tft_string);
-  TERN_(TOUCH_SCREEN, touch.add_control(FEEDRATE, 96, y, 128, 32));
+  y += STATUS_MARGIN_SIZE + 34;
 
-  // flow rate
-  tft.canvas(284, y, 128, 32);
+  // Feed rate (preparing)
+  tft_string.set(i16tostr3rj(feedrate_percentage));
+  tft_string.add("%");
+  uint16_t component_width = 36 + tft_string.width(); // 32px icon size + 4px margin before text
+  uint16_t color = feedrate_percentage == 100 ? COLOR_RATE_100 : COLOR_RATE_ALTERED;
+  uint16_t x = FEEDRATE_X(component_width);
+
+  // Feed rate (drawing)
+  tft.canvas(x, y, component_width, 32);
   tft.set_background(COLOR_BACKGROUND);
-  color = planner.flow_percentage[0] == 100 ? COLOR_RATE_100 : COLOR_RATE_ALTERED;
-  tft.add_image(0, 0, imgFlowRate, color);
+  tft.add_image(0, 0, imgFeedRate, color);
+  tft.add_text(36, tft_string.vcenter(30), color , tft_string);
+  TERN_(TOUCH_SCREEN, touch.add_control(FEEDRATE, x, y, component_width, 32));
+
+  // Flow rate (preparing)
   tft_string.set(i16tostr3rj(planner.flow_percentage[active_extruder]));
   tft_string.add('%');
+  component_width = 36 + tft_string.width();
+  color = planner.flow_percentage[0] == 100 ? COLOR_RATE_100 : COLOR_RATE_ALTERED;
+  x = FLOWRATE_X(component_width);
+
+  // Flow rate (drawing)
+  tft.canvas(x, y, component_width, 32);
+  tft.set_background(COLOR_BACKGROUND);
+  tft.add_image(0, 0, imgFlowRate, color);
   tft.add_text(36, tft_string.vcenter(30), color , tft_string);
-  TERN_(TOUCH_SCREEN, touch.add_control(FLOWRATE, 284, y, 128, 32, active_extruder));
+  TERN_(TOUCH_SCREEN, touch.add_control(FLOWRATE, x, y, component_width, 32, active_extruder));
+
+  #if TFT_COLOR_UI_PORTRAIT || DISABLED(TOUCH_SCREEN)
+    y += STATUS_MARGIN_SIZE + 32;
+  #endif
 
   #if ENABLED(TOUCH_SCREEN)
-    add_control(404, y, menu_main, imgSettings);
+    // Settings button
+    add_control(SETTINGS_X, y, menu_main, imgSettings);
+
+    // SD-card button / Cancel button
     #if HAS_MEDIA
       const bool cm = card.isMounted(), pa = printingIsActive();
       if (cm && pa)
-        add_control(12, y, STOP, imgCancel, true, COLOR_CONTROL_CANCEL);
+        add_control(SDCARD_X, y, STOP, imgCancel, true, COLOR_CONTROL_CANCEL);
       else
-        add_control(12, y, menu_media, imgSD, cm && !pa, COLOR_CONTROL_ENABLED, COLOR_CONTROL_DISABLED);
+        add_control(SDCARD_X, y, menu_media, imgSD, cm && !pa, COLOR_CONTROL_ENABLED, COLOR_CONTROL_DISABLED); // 64px icon size
     #endif
+
+    y += STATUS_MARGIN_SIZE + TERN(TFT_COLOR_UI_PORTRAIT, 64, 44);
   #endif
 
-  y += TERN(HAS_UI_480x272, 39, 44);
-  // print duration
+  // Print duration
   char buffer[14];
   duration_t elapsed = print_job_timer.duration();
   elapsed.toDigital(buffer);
@@ -340,8 +359,9 @@ void MarlinUI::draw_status_screen() {
   tft_string.set(buffer);
   tft.add_text(tft_string.center(128), tft_string.vcenter(29), COLOR_PRINT_TIME, tft_string);
 
-  y += TERN(HAS_UI_480x272, 29, 36);
-  // progress bar
+  y += STATUS_MARGIN_SIZE + 29;
+
+  // Progress bar
   const uint8_t progress = ui.get_progress_percent();
   tft.canvas(4, y, TFT_WIDTH - 8, 9);
   tft.set_background(COLOR_PROGRESS_BG);
@@ -349,8 +369,9 @@ void MarlinUI::draw_status_screen() {
   if (progress)
     tft.add_bar(1, 1, ((TFT_WIDTH - 10) * progress) / 100, 7, COLOR_PROGRESS_BAR);
 
-  y += 15;
-  // status message
+  y += STATUS_MARGIN_SIZE + 7;
+
+  // Status message
   tft.canvas(0, y, TFT_WIDTH, FONT_LINE_HEIGHT);
   tft.set_background(COLOR_BACKGROUND);
   tft_string.set(status_message);
@@ -397,7 +418,7 @@ void MenuEditItemBase::draw_edit_screen(FSTR_P const fstr, const char * const va
 
   if (ui.can_show_slider()) {
 
-    #define SLIDER_LENGTH 336
+    #define SLIDER_LENGTH TFT_WIDTH * 0.7
     #define SLIDER_Y_POSITION 186
 
     tft.canvas((TFT_WIDTH - SLIDER_LENGTH) / 2, SLIDER_Y_POSITION, SLIDER_LENGTH, 16);
@@ -420,9 +441,9 @@ void MenuEditItemBase::draw_edit_screen(FSTR_P const fstr, const char * const va
 
 void TFT::draw_edit_screen_buttons() {
   #if ENABLED(TOUCH_SCREEN)
-    add_control(64, TFT_HEIGHT - 64, DECREASE, imgDecrease);
-    add_control(352, TFT_HEIGHT - 64, INCREASE, imgIncrease);
-    add_control(208, TFT_HEIGHT - 64, CLICK, imgConfirm);
+    add_control((TFT_WIDTH - 3 * 64) / 6, TFT_HEIGHT - 64, DECREASE, imgDecrease);
+    add_control((TFT_WIDTH - 64) / 2, TFT_HEIGHT - 64, INCREASE, imgIncrease);
+    add_control((TFT_WIDTH * 5 - 3 * 64) / 6, TFT_HEIGHT - 64, CLICK, imgConfirm);
   #endif
 }
 
@@ -451,8 +472,8 @@ void MenuItem_confirm::draw_select_screen(FSTR_P const yes, FSTR_P const no, con
     tft.add_text(tft_string.center(TFT_WIDTH), 0, COLOR_MENU_TEXT, tft_string);
   }
   #if ENABLED(TOUCH_SCREEN)
-    if (no)  add_control( 88, TFT_HEIGHT - 64, CANCEL,  imgCancel,  true, yesno ? HALF(COLOR_CONTROL_CANCEL) : COLOR_CONTROL_CANCEL);
-    if (yes) add_control(328, TFT_HEIGHT - 64, CONFIRM, imgConfirm, true, yesno ? COLOR_CONTROL_CONFIRM : HALF(COLOR_CONTROL_CONFIRM));
+    if (no)  add_control(TFT_WIDTH / 4 - 32, TFT_HEIGHT - 64, CANCEL,  imgCancel,  true, yesno ? HALF(COLOR_CONTROL_CANCEL) : COLOR_CONTROL_CANCEL);
+    if (yes) add_control(TFT_WIDTH * 3 / 4 - 32, TFT_HEIGHT - 64, CONFIRM, imgConfirm, true, yesno ? COLOR_CONTROL_CONFIRM : HALF(COLOR_CONTROL_CONFIRM));
   #endif
 }
 
@@ -898,7 +919,7 @@ void MarlinUI::move_axis_screen() {
   drawAxisValue(Z_AXIS);
 
   // ROW 4 -> step_size  disable steppers back
-  y = TFT_HEIGHT - Y_MARGIN - 32; //
+  y = TFT_HEIGHT - Y_MARGIN - 32;
   x = TFT_WIDTH / 2 - CUR_STEP_VALUE_WIDTH / 2;
   motionAxisState.stepValuePos.x = x;
   motionAxisState.stepValuePos.y = y;
diff --git a/Marlin/src/lcd/tft/ui_480x320.h b/Marlin/src/lcd/tft/ui_480x320.h
index d63ae02c09f..00341650c12 100644
--- a/Marlin/src/lcd/tft/ui_480x320.h
+++ b/Marlin/src/lcd/tft/ui_480x320.h
@@ -63,4 +63,69 @@
 
 #define MENU_LINE_HEIGHT      (MENU_ITEM_HEIGHT + 2)
 
+/**
+ * Status screen - portrait layout:
+ *
+ * | FAN   E0   BED   .. | - 120px
+ * |     Coordinates     | - FONT_LINE_HEIGHT
+ * | Feedrate   Flowrate | - 32px
+ * | SD         Settings | - 64px if ENABLED(TOUCHSCREEN), else 0px
+ * | Print duration time | - 29px
+ * |     Progress bar    | - 7px
+ * |    Status message   | - FONT_LINE_HEIGHT
+ *
+ * Summary with touchscreen:
+ * - Total height: 252px + 2 * FONT_LINE_HEIGHT (320px if FONT_LINE_HEIGHT is 34px)
+ * - Rows count: 7
+ * - Margins count: 8
+ *
+ * Summary without touchscreen:
+ * - Total height: 188px + 2 * FONT_LINE_HEIGHT (256px if FONT_LINE_HEIGHT is 34px)
+ * - Rows count: 6
+ * - Margins count: 7
+ *
+ * Status screen - landscape layout:
+ *
+ * |          FAN   E0   BED   ...          | - 120px
+ * |              Coordinates               | - FONT_LINE_HEIGHT
+ * | SD    Flowrate    Feedrate    Settings | - 44px for TOUCHSCREEN, else 32px
+ * |          Print duration time           | - 29px
+ * |              Progress bar              | - 7px
+ * |             Status message             | - FONT_LINE_HEIGHT
+ *
+ * Summary with touchscreen:
+ * - Total height: 200px (268px if FONT_LINE_HEIGHT is 34px)
+ * - Rows count: 6
+ * - Margins count: 7
+ *
+ * Summary without touchscreen:
+ * - Total height: 188px + 2 * FONT_LINE_HEIGHT (256px if FONT_LINE_HEIGHT is 34px)
+ * - Rows count: 6
+ * - Margins count: 7
+ */
+#ifdef TFT_COLOR_UI_PORTRAIT
+  #if ENABLED(TOUCH_SCREEN)
+    #define STATUS_TOTAL_ROWS_HEIGHT (2 * FONT_LINE_HEIGHT + 120 + 32 + 64 + 29 + 7)
+    #define STATUS_MARGINS_REGIONS 8
+  #else
+    #define STATUS_TOTAL_ROWS_HEIGHT (2 * FONT_LINE_HEIGHT + 120 + 32 + 29 + 7)
+    #define STATUS_MARGINS_REGIONS 7
+  #endif
+
+  #define FEEDRATE_X(W) ((TFT_WIDTH - 2 * (W)) / 4)
+  #define FLOWRATE_X(W) ((3 * TFT_WIDTH - 2 * (W)) / 4)
+  #define SETTINGS_X (3 * TFT_WIDTH / 4 - 32)
+  #define SDCARD_X (TFT_WIDTH / 4 - 32)
+#else
+  #define STATUS_TOTAL_ROWS_HEIGHT (2 * FONT_LINE_HEIGHT + 120 + TERN(TOUCH_SCREEN, 44, 32) + 29 + 7)
+  #define STATUS_MARGINS_REGIONS 7
+
+  #define FEEDRATE_X(W) (3 * TFT_WIDTH / 8 - (W) / 2)
+  #define FLOWRATE_X(W) (5 * TFT_WIDTH / 8 - (W) / 2)
+  #define SETTINGS_X (TFT_WIDTH / 8 - 32)
+  #define SDCARD_X (7 * TFT_WIDTH / 8 - 32)
+#endif
+
+#define STATUS_MARGIN_SIZE ((TFT_HEIGHT - STATUS_TOTAL_ROWS_HEIGHT) / STATUS_MARGINS_REGIONS)
+
 #include "tft_font.h"