Selaa lähdekoodia

🚸 ProUI APRIL2022 updates (#24084)

Miguel Risco-Castillo 2 vuotta sitten
vanhempi
commit
a65e4edb1c

+ 1
- 1
Marlin/src/MarlinCore.cpp Näytä tiedosto

@@ -890,7 +890,7 @@ void kill(FSTR_P const lcd_error/*=nullptr*/, FSTR_P const lcd_component/*=nullp
890 890
   // Echo the LCD message to serial for extra context
891 891
   if (lcd_error) { SERIAL_ECHO_START(); SERIAL_ECHOLNF(lcd_error); }
892 892
 
893
-  #if EITHER(HAS_DISPLAY, DWIN_LCD_PROUI)
893
+  #if HAS_DISPLAY
894 894
     ui.kill_screen(lcd_error ?: GET_TEXT_F(MSG_KILLED), lcd_component ?: FPSTR(NUL_STR));
895 895
   #else
896 896
     UNUSED(lcd_error); UNUSED(lcd_component);

+ 2
- 0
Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp Näytä tiedosto

@@ -763,6 +763,7 @@ void unified_bed_leveling::shift_mesh_height() {
763 763
 
764 764
     TERN_(HAS_MARLINUI_MENU, ui.capture());
765 765
     TERN_(EXTENSIBLE_UI, ExtUI::onLevelingStart());
766
+    TERN_(DWIN_LCD_PROUI, DWIN_LevelingStart());
766 767
 
767 768
     save_ubl_active_state_and_disable();  // No bed level correction so only raw data is obtained
768 769
     uint8_t count = GRID_MAX_POINTS;
@@ -826,6 +827,7 @@ void unified_bed_leveling::shift_mesh_height() {
826 827
     );
827 828
 
828 829
     TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone());
830
+    TERN_(DWIN_LCD_PROUI, DWIN_LevelingDone());
829 831
   }
830 832
 
831 833
 #endif // HAS_BED_PROBE

+ 24
- 2
Marlin/src/gcode/probe/G30.cpp Näytä tiedosto

@@ -33,6 +33,10 @@
33 33
   #include "../../feature/probe_temp_comp.h"
34 34
 #endif
35 35
 
36
+#if ENABLED(DWIN_LCD_PROUI)
37
+  #include "../../lcd/marlinui.h"
38
+#endif
39
+
36 40
 /**
37 41
  * G30: Do a single Z probe at the current XY
38 42
  *
@@ -48,20 +52,38 @@ void GcodeSuite::G30() {
48 52
   const xy_pos_t pos = { parser.linearval('X', current_position.x + probe.offset_xy.x),
49 53
                          parser.linearval('Y', current_position.y + probe.offset_xy.y) };
50 54
 
51
-  if (!probe.can_reach(pos)) return;
55
+  if (!probe.can_reach(pos)) {
56
+    #if ENABLED(DWIN_LCD_PROUI)
57
+      SERIAL_ECHOLNF(GET_EN_TEXT_F(MSG_ZPROBE_OUT));
58
+      LCD_MESSAGE(MSG_ZPROBE_OUT);
59
+    #endif
60
+    return;
61
+  }
52 62
 
53 63
   // Disable leveling so the planner won't mess with us
54 64
   TERN_(HAS_LEVELING, set_bed_leveling_enabled(false));
55 65
 
56 66
   remember_feedrate_scaling_off();
57 67
 
68
+  TERN_(DWIN_LCD_PROUI, process_subcommands_now(F("G28O")));
69
+
58 70
   const ProbePtRaise raise_after = parser.boolval('E', true) ? PROBE_PT_STOW : PROBE_PT_NONE;
59 71
 
60 72
   TERN_(HAS_PTC, ptc.set_enabled(!parser.seen('C') || parser.value_bool()));
61 73
   const float measured_z = probe.probe_at_point(pos, raise_after, 1);
62 74
   TERN_(HAS_PTC, ptc.set_enabled(true));
63
-  if (!isnan(measured_z))
75
+  if (!isnan(measured_z)) {
64 76
     SERIAL_ECHOLNPGM("Bed X: ", pos.x, " Y: ", pos.y, " Z: ", measured_z);
77
+    #if ENABLED(DWIN_LCD_PROUI)
78
+      char msg[31], str_1[6], str_2[6], str_3[6];
79
+      sprintf_P(msg, PSTR("X:%s, Y:%s, Z:%s"),
80
+        dtostrf(pos.x, 1, 1, str_1),
81
+        dtostrf(pos.y, 1, 1, str_2),
82
+        dtostrf(measured_z, 1, 2, str_3)
83
+      );
84
+      ui.set_status(msg);
85
+    #endif
86
+  }
65 87
 
66 88
   restore_feedrate_and_scaling();
67 89
 

+ 1
- 1
Marlin/src/gcode/stats/M31.cpp Näytä tiedosto

@@ -33,7 +33,7 @@ void GcodeSuite::M31() {
33 33
   char buffer[22];
34 34
   duration_t(print_job_timer.duration()).toString(buffer);
35 35
 
36
-  ui.set_status(buffer);
36
+  ui.set_status(buffer, ENABLED(DWIN_LCD_PROUI));
37 37
 
38 38
   SERIAL_ECHO_MSG("Print time: ", buffer);
39 39
 }

+ 3
- 1
Marlin/src/lcd/e3v2/common/dwin_api.cpp Näytä tiedosto

@@ -234,7 +234,9 @@ void DWIN_Frame_AreaMove(uint8_t mode, uint8_t dir, uint16_t dis,
234 234
 //  *string: The string
235 235
 //  rlimit: To limit the drawn string length
236 236
 void DWIN_Draw_String(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t x, uint16_t y, const char * const string, uint16_t rlimit/*=0xFFFF*/) {
237
-  DWIN_Draw_Rectangle(1, bColor, x, y, x + (fontWidth(size) * strlen_P(string)), y + fontHeight(size));
237
+  #if DISABLED(DWIN_LCD_PROUI)
238
+    DWIN_Draw_Rectangle(1, bColor, x, y, x + (fontWidth(size) * strlen_P(string)), y + fontHeight(size));
239
+  #endif
238 240
   constexpr uint8_t widthAdjust = 0;
239 241
   size_t i = 0;
240 242
   DWIN_Byte(i, 0x11);

+ 671
- 558
Marlin/src/lcd/e3v2/proui/dwin.cpp
File diff suppressed because it is too large
Näytä tiedosto


+ 65
- 21
Marlin/src/lcd/e3v2/proui/dwin.h Näytä tiedosto

@@ -24,8 +24,8 @@
24 24
 /**
25 25
  * DWIN Enhanced implementation for PRO UI
26 26
  * Author: Miguel A. Risco-Castillo (MRISCOC)
27
- * Version: 3.15.2
28
- * Date: 2022/03/01
27
+ * Version: 3.17.2
28
+ * Date: 2022/04/08
29 29
  */
30 30
 
31 31
 #include "dwin_defines.h"
@@ -73,12 +73,13 @@ enum pidresult_t : uint8_t {
73 73
 typedef struct {
74 74
   int8_t Color[3];                    // Color components
75 75
   pidresult_t pidresult   = PID_DONE;
76
-  int8_t Preheat          = 0;        // Material Select 0: PLA, 1: ABS, 2: Custom
76
+  uint8_t Select          = 0;        // Auxiliary selector variable
77 77
   AxisEnum axis           = X_AXIS;   // Axis Select
78 78
 } HMI_value_t;
79 79
 
80 80
 typedef struct {
81 81
   uint8_t language;
82
+  bool percent_flag:1;  // percent was override by M73
82 83
   bool remain_flag:1;   // remain was override by M73
83 84
   bool pause_flag:1;    // printing is paused
84 85
   bool pause_action:1;  // flag a pause action
@@ -103,9 +104,53 @@ extern millis_t dwin_heat_time;
103 104
   void Popup_PowerLossRecovery();
104 105
 #endif
105 106
 
106
-// SD Card
107
-void HMI_SDCardInit();
108
-void HMI_SDCardUpdate();
107
+// Tool Functions
108
+#if ENABLED(EEPROM_SETTINGS)
109
+  void WriteEeprom();
110
+  void ReadEeprom();
111
+  void ResetEeprom();
112
+  #if HAS_MESH
113
+    void SaveMesh();
114
+  #endif
115
+#endif
116
+void RebootPrinter();
117
+void DisableMotors();
118
+void AutoLev();
119
+void AutoHome();
120
+#if HAS_PREHEAT
121
+  void DoPreheat0();
122
+  void DoPreheat1();
123
+  void DoPreheat2();
124
+#endif
125
+void DoCoolDown();
126
+#if HAS_HOTEND
127
+  void HotendPID();
128
+#endif
129
+#if HAS_HEATED_BED
130
+  void BedPID();
131
+#endif
132
+#if ENABLED(BAUD_RATE_GCODE)
133
+  void HMI_SetBaudRate();
134
+  void SetBaud115K();
135
+  void SetBaud250K();
136
+#endif
137
+#if HAS_LCD_BRIGHTNESS
138
+  void TurnOffBacklight();
139
+#endif
140
+void ApplyExtMinT();
141
+void ParkHead();
142
+#if HAS_ONESTEP_LEVELING
143
+  void Trammingwizard();
144
+#endif
145
+#if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS)
146
+  void ApplyLEDColor();
147
+#endif
148
+#if ENABLED(AUTO_BED_LEVELING_UBL)
149
+  void UBLTiltMesh();
150
+  bool UBLValidMesh();
151
+  void UBLSaveMesh();
152
+  void UBLLoadMesh();
153
+#endif
109 154
 
110 155
 // Other
111 156
 void Goto_PrintProcess();
@@ -115,28 +160,18 @@ void Goto_PowerLossRecovery();
115 160
 void Goto_ConfirmToPrint();
116 161
 void DWIN_Draw_Dashboard(const bool with_update); // Status Area
117 162
 void Draw_Main_Area();      // Redraw main area
163
+void DWIN_DrawStatusLine(const char *text); // Draw simple status text
164
+void DWIN_DrawStatusLine(FSTR_P fstr);
165
+void DWIN_RedrawDash();     // Redraw Dash and Status line
118 166
 void DWIN_RedrawScreen();   // Redraw all screen elements
119 167
 void HMI_MainMenu();        // Main process screen
120 168
 void HMI_SelectFile();      // File page
121 169
 void HMI_Printing();        // Print page
122 170
 void HMI_ReturnScreen();    // Return to previous screen before popups
123
-void ApplyExtMinT();
124
-void HMI_SetLanguageCache(); // Set the language image cache
125
-void RebootPrinter();
126
-#if ENABLED(BAUD_RATE_GCODE)
127
-  void HMI_SetBaudRate();
128
-  void SetBaud115K();
129
-  void SetBaud250K();
130
-#endif
131
-#if ENABLED(EEPROM_SETTINGS)
132
-  void WriteEeprom();
133
-  void ReadEeprom();
134
-  void ResetEeprom();
135
-#endif
136
-
137 171
 void HMI_WaitForUser();
138 172
 void HMI_SaveProcessID(const uint8_t id);
139
-void HMI_AudioFeedback(const bool success=true);
173
+void HMI_SDCardInit();
174
+void HMI_SDCardUpdate();
140 175
 void EachMomentUpdate();
141 176
 void update_variable();
142 177
 void DWIN_InitScreen();
@@ -248,3 +283,12 @@ void Draw_Steps_Menu();
248 283
 #if ENABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU)
249 284
   void Draw_Homing_Menu();
250 285
 #endif
286
+#if ENABLED(FWRETRACT)
287
+  void Draw_FWRetract_Menu();
288
+#endif
289
+#if HAS_MESH
290
+  void Draw_MeshSet_Menu();
291
+  #if ENABLED(MESH_EDIT_MENU)
292
+    void Draw_EditMesh_Menu();
293
+  #endif
294
+#endif

+ 23
- 7
Marlin/src/lcd/e3v2/proui/dwin_defines.h Näytä tiedosto

@@ -34,6 +34,23 @@
34 34
 #include "../../../inc/MarlinConfigPre.h"
35 35
 #include <stddef.h>
36 36
 
37
+#define HAS_ESDIAG 1
38
+#if defined(__STM32F1__) || defined(STM32F1)
39
+  #define DASH_REDRAW 1
40
+#endif
41
+
42
+#if DISABLED(LIMITED_MAX_FR_EDITING)
43
+  #error "LIMITED_MAX_FR_EDITING is required with ProUI."
44
+#endif
45
+#if DISABLED(LIMITED_MAX_ACCEL_EDITING)
46
+  #error "LIMITED_MAX_ACCEL_EDITING is required with ProUI."
47
+#endif
48
+#if ENABLED(CLASSIC_JERK) && DISABLED(LIMITED_JERK_EDITING)
49
+  #error "LIMITED_JERK_EDITING is required with ProUI."
50
+#endif
51
+#if DISABLED(FILAMENT_RUNOUT_SENSOR)
52
+  #error "FILAMENT_RUNOUT_SENSOR is required with ProUI."
53
+#endif
37 54
 #if DISABLED(INDIVIDUAL_AXIS_HOMING_SUBMENU)
38 55
   #error "INDIVIDUAL_AXIS_HOMING_SUBMENU is required with ProUI."
39 56
 #endif
@@ -81,7 +98,7 @@
81 98
 #define HAS_ESDIAG 1
82 99
 
83 100
 #if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS)
84
-  #define Def_Leds_Color      LEDColorWhite()
101
+  #define Def_Leds_Color 0xFFFFFFFF
85 102
 #endif
86 103
 #if ENABLED(CASELIGHT_USES_BRIGHTNESS)
87 104
   #define Def_CaseLight_Brightness 255
@@ -128,14 +145,13 @@ typedef struct {
128 145
   #endif
129 146
   bool FullManualTramming = false;
130 147
   // Led
131
-  #if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS)
132
-    LEDColor Led_Color = Def_Leds_Color;
148
+  #if ENABLED(MESH_BED_LEVELING)
149
+    float ManualZOffset = 0;
133 150
   #endif
134
-  // Case Light
135
-  #if ENABLED(CASELIGHT_USES_BRIGHTNESS)
136
-    uint8_t CaseLight_Brightness = Def_CaseLight_Brightness;
151
+  #if BOTH(LED_CONTROL_MENU, HAS_COLOR_LEDS)
152
+    uint32_t LED_Color = Def_Leds_Color;
137 153
   #endif
138 154
 } HMI_data_t;
139 155
 
140
-static constexpr size_t eeprom_data_size = 64;
156
+static constexpr size_t eeprom_data_size = sizeof(HMI_data_t);
141 157
 extern HMI_data_t HMI_data;

+ 2
- 50
Marlin/src/lcd/e3v2/proui/dwin_lcd.cpp Näytä tiedosto

@@ -23,8 +23,8 @@
23 23
 /**
24 24
  * DWIN Enhanced implementation for PRO UI
25 25
  * Author: Miguel A. Risco-Castillo (MRISCOC)
26
- * Version: 3.9.1
27
- * Date: 2022/02/08
26
+ * Version: 3.10.1
27
+ * Date: 2022/03/06
28 28
  */
29 29
 
30 30
 #include "../../../inc/MarlinConfigPre.h"
@@ -35,54 +35,6 @@
35 35
 
36 36
 #include "dwin_lcd.h"
37 37
 
38
-/*---------------------------------------- Numeric related functions ----------------------------------------*/
39
-
40
-// Draw a numeric value
41
-//  bShow: true=display background color; false=don't display background color
42
-//  zeroFill: true=zero fill; false=no zero fill
43
-//  signedMode: 1=signed; 0=unsigned
44
-//  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
45
-//  size: Font size
46
-//  color: Character color
47
-//  bColor: Background color
48
-//  iNum: Number of digits
49
-//  fNum: Number of decimal digits
50
-//  x/y: Upper-left coordinate
51
-//  value: Integer value
52
-void DWIN_Draw_Value(uint8_t bShow, bool signedMode, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
53
-                          uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value) {
54
-  size_t i = 0;
55
-  DWIN_Byte(i, 0x14);
56
-  // Bit 7: bshow
57
-  // Bit 6: 1 = signed; 0 = unsigned number;
58
-  // Bit 5: zeroFill
59
-  // Bit 4: zeroMode
60
-  // Bit 3-0: size
61
-  DWIN_Byte(i, (bShow * 0x80) | (signedMode * 0x40) | (zeroFill * 0x20) | (zeroMode * 0x10) | size);
62
-  DWIN_Word(i, color);
63
-  DWIN_Word(i, bColor);
64
-  DWIN_Byte(i, signedMode && (value >= 0) ? iNum + 1 : iNum);
65
-  DWIN_Byte(i, fNum);
66
-  DWIN_Word(i, x);
67
-  DWIN_Word(i, y);
68
-  // Write a big-endian 64 bit integer
69
-  const size_t p = i + 1;
70
-  for (size_t count = 8; count--;) { // 7..0
71
-    ++i;
72
-    DWIN_SendBuf[p + count] = value;
73
-    value >>= 8;
74
-  }
75
-  DWIN_Send(i);
76
-}
77
-
78
-// Draw a numeric value
79
-//  value: positive unscaled float value
80
-void DWIN_Draw_Value(uint8_t bShow, bool signedMode, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
81
-                          uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
82
-  const int32_t val = round(value * POW(10, fNum));
83
-  DWIN_Draw_Value(bShow, signedMode, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, val);
84
-}
85
-
86 38
 /*---------------------------------------- Picture related functions ----------------------------------------*/
87 39
 
88 40
 // Display QR code

+ 2
- 20
Marlin/src/lcd/e3v2/proui/dwin_lcd.h Näytä tiedosto

@@ -24,30 +24,12 @@
24 24
 /**
25 25
  * DWIN Enhanced implementation for PRO UI
26 26
  * Author: Miguel A. Risco-Castillo (MRISCOC)
27
- * Version: 3.9.1
28
- * Date: 2022/02/08
27
+ * Version: 3.10.1
28
+ * Date: 2022/03/06
29 29
  */
30 30
 
31 31
 #include "../common/dwin_api.h"
32 32
 
33
-// Draw a numeric value
34
-//  bShow: true=display background color; false=don't display background color
35
-//  zeroFill: true=zero fill; false=no zero fill
36
-//  signedMode: 1=signed; 0=unsigned
37
-//  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
38
-//  size: Font size
39
-//  color: Character color
40
-//  bColor: Background color
41
-//  iNum: Number of digits
42
-//  fNum: Number of decimal digits
43
-//  x/y: Upper-left coordinate
44
-//  value: Integer value
45
-void DWIN_Draw_Value(uint8_t bShow, bool signedMode, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
46
-                          uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, int32_t value);
47
-//  value: positive unscaled float value
48
-void DWIN_Draw_Value(uint8_t bShow, bool signedMode, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color,
49
-                          uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value);
50
-
51 33
 // Display QR code
52 34
 //  The size of the QR code is (46*QR_Pixel)*(46*QR_Pixel) dot matrix
53 35
 //  QR_Pixel: The pixel size occupied by each point of the QR code: 0x01-0x0F (1-16)

+ 51
- 132
Marlin/src/lcd/e3v2/proui/dwinui.cpp Näytä tiedosto

@@ -23,8 +23,8 @@
23 23
 /**
24 24
  * DWIN Enhanced implementation for PRO UI
25 25
  * Author: Miguel A. Risco-Castillo (MRISCOC)
26
- * Version: 3.15.1
27
- * Date: 2022/02/25
26
+ * Version: 3.17.1
27
+ * Date: 2022/04/12
28 28
  */
29 29
 
30 30
 #include "../../../inc/MarlinConfigPre.h"
@@ -39,12 +39,6 @@
39 39
 //#define DEBUG_OUT 1
40 40
 #include "../../../core/debug_out.h"
41 41
 
42
-int8_t MenuItemTotal = 0;
43
-int8_t MenuItemCount = 0;
44
-MenuItemClass** MenuItems = nullptr;
45
-MenuClass *CurrentMenu = nullptr;
46
-MenuClass *PreviousMenu = nullptr;
47
-
48 42
 xy_int_t DWINUI::cursor = { 0 };
49 43
 uint16_t DWINUI::pencolor = Color_White;
50 44
 uint16_t DWINUI::textcolor = Def_Text_Color;
@@ -53,16 +47,15 @@ uint16_t DWINUI::buttoncolor = Def_Button_Color;
53 47
 uint8_t  DWINUI::font = font8x16;
54 48
 FSTR_P const DWINUI::Author = F(STRING_CONFIG_H_AUTHOR);
55 49
 
56
-void (*DWINUI::onCursorErase)(const int8_t line)=nullptr;
57
-void (*DWINUI::onCursorDraw)(const int8_t line)=nullptr;
58
-void (*DWINUI::onTitleDraw)(TitleClass* title)=nullptr;
59
-void (*DWINUI::onMenuDraw)(MenuClass* menu)=nullptr;
50
+void (*DWINUI::onTitleDraw)(TitleClass* title) = nullptr;
60 51
 
61 52
 void DWINUI::init() {
62
-  TERN_(DEBUG_DWIN, SERIAL_ECHOPGM("\r\nDWIN handshake "));
63 53
   delay(750);   // Delay for wait to wakeup screen
64
-  const bool hs = DWIN_Handshake();
65
-  TERN(DEBUG_DWIN, SERIAL_ECHOLNF(hs ? F("ok.") : F("error.")), UNUSED(hs));
54
+  const bool hs = DWIN_Handshake(); UNUSED(hs);
55
+  #if ENABLED(DEBUG_DWIN)
56
+    SERIAL_ECHOPGM("DWIN_Handshake ");
57
+    SERIAL_ECHOLNF(hs ? F("ok.") : F("error."));
58
+  #endif
66 59
   DWIN_Frame_SetDir(1);
67 60
   cursor.reset();
68 61
   pencolor = Color_White;
@@ -164,16 +157,19 @@ void DWINUI::Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint1
164 157
   DWIN_Draw_String(bShow, size, color, bColor, x, y, string);
165 158
 }
166 159
 
167
-// // Draw a Centered string using DWIN_WIDTH
168
-// void DWINUI::Draw_CenteredString(bool bShow, uint8_t size, uint16_t color, uint16_t bColor, uint16_t y, const char * const string) {
169
-//   const int8_t x = _MAX(0U, DWIN_WIDTH - strlen_P(string) * fontWidth(size)) / 2 - 1;
170
-//   DWIN_Draw_String(bShow, size, color, bColor, x, y, string);
171
-// }
160
+// Draw a char
161
+//  color: Character color
162
+//  x: abscissa of the display
163
+//  y: ordinate of the display
164
+//  c: ASCII code of char
165
+void DWINUI::Draw_Char(uint16_t color, uint16_t x, uint16_t y, const char c) {
166
+  const char string[2] = { c, 0};
167
+  DWIN_Draw_String(false, font, color, backcolor, x, y, string, 1);
168
+}
172 169
 
173
-// Draw a char at cursor position
170
+// Draw a char at cursor position and increment cursor
174 171
 void DWINUI::Draw_Char(uint16_t color, const char c) {
175
-  const char string[2] = { c, 0};
176
-  DWIN_Draw_String(false, font, color, backcolor, cursor.x, cursor.y, string, 1);
172
+  Draw_Char(color, cursor.x, cursor.y, c);
177 173
   MoveBy(fontWidth(font), 0);
178 174
 }
179 175
 
@@ -190,6 +186,36 @@ void DWINUI::Draw_String(uint16_t color, const char * const string, uint16_t rli
190 186
   MoveBy(strlen(string) * fontWidth(font), 0);
191 187
 }
192 188
 
189
+// Draw a numeric integer value
190
+//  bShow: true=display background color; false=don't display background color
191
+//  signedMode: 1=signed; 0=unsigned
192
+//  size: Font size
193
+//  color: Character color
194
+//  bColor: Background color
195
+//  iNum: Number of digits
196
+//  x/y: Upper-left coordinate
197
+//  value: Integer value
198
+void DWINUI::Draw_Int(uint8_t bShow, bool signedMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, int32_t value) {
199
+  char nstr[10];
200
+  sprintf_P(nstr, PSTR("%*li"), (signedMode ? iNum + 1 : iNum), value);
201
+  DWIN_Draw_String(bShow, size, color, bColor, x, y, nstr);
202
+}
203
+
204
+// Draw a numeric float value
205
+//  bShow: true=display background color; false=don't display background color
206
+//  signedMode: 1=signed; 0=unsigned
207
+//  size: Font size
208
+//  color: Character color
209
+//  bColor: Background color
210
+//  iNum: Number of digits
211
+//  fNum: Number of decimal digits
212
+//  x/y: Upper-left coordinate
213
+//  value: float value
214
+void DWINUI::Draw_Float(uint8_t bShow, bool signedMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
215
+  char nstr[10];
216
+  DWIN_Draw_String(bShow, size, color, bColor, x, y, dtostrf(value, iNum + (signedMode ? 2:1) + fNum, fNum, nstr));
217
+}
218
+
193 219
 // ------------------------- Buttons ------------------------------//
194 220
 
195 221
 void DWINUI::Draw_Button(uint16_t color, uint16_t bcolor, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, const char * const caption) {
@@ -204,6 +230,7 @@ void DWINUI::Draw_Button(uint8_t id, uint16_t x, uint16_t y) {
204 230
     case BTN_Continue: Draw_Button(GET_TEXT_F(MSG_BUTTON_CONTINUE), x, y); break;
205 231
     case BTN_Print   : Draw_Button(GET_TEXT_F(MSG_BUTTON_PRINT), x, y); break;
206 232
     case BTN_Save    : Draw_Button(GET_TEXT_F(MSG_BUTTON_SAVE), x, y); break;
233
+    case BTN_Purge   : Draw_Button(GET_TEXT_F(MSG_BUTTON_PURGE), x, y); break;
207 234
     default: break;
208 235
   }
209 236
 }
@@ -265,7 +292,7 @@ uint16_t DWINUI::ColorInt(int16_t val, int16_t minv, int16_t maxv, uint16_t colo
265 292
   return RGB(R, G, B);
266 293
 }
267 294
 
268
-// Color Interpolator through Red->Yellow->Green->Blue
295
+// Color Interpolator through Red->Yellow->Green->Blue (Pro UI)
269 296
 //  val : Interpolator minv..maxv
270 297
 //  minv : Minimum value
271 298
 //  maxv : Maximum value
@@ -308,33 +335,6 @@ void DWINUI::ClearMainArea() {
308 335
   DWIN_Draw_Rectangle(1, backcolor, 0, TITLE_HEIGHT, DWIN_WIDTH - 1, STATUS_Y - 1);
309 336
 }
310 337
 
311
-void DWINUI::MenuItemsClear() {
312
-  if (MenuItems == nullptr) return;
313
-  for (int8_t i = 0; i < MenuItemCount; i++) delete MenuItems[i];
314
-  delete[] MenuItems;
315
-  MenuItems = nullptr;
316
-  MenuItemCount = 0;
317
-  MenuItemTotal = 0;
318
-}
319
-
320
-void DWINUI::MenuItemsPrepare(int8_t totalitems) {
321
-  MenuItemsClear();
322
-  MenuItemTotal = totalitems;
323
-  MenuItems = new MenuItemClass*[totalitems];
324
-}
325
-
326
-MenuItemClass* DWINUI::MenuItemsAdd(MenuItemClass* menuitem) {
327
-  if (MenuItemCount < MenuItemTotal) {
328
-    MenuItems[MenuItemCount] = menuitem;
329
-    menuitem->pos = MenuItemCount++;
330
-    return menuitem;
331
-  }
332
-  else {
333
-    delete menuitem;
334
-    return nullptr;
335
-  }
336
-}
337
-
338 338
 /* Title Class ==============================================================*/
339 339
 
340 340
 TitleClass Title;
@@ -375,85 +375,4 @@ void TitleClass::FrameCopy(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
375 375
   FrameCopy(1, x, y, x + w - 1, y + h - 1);
376 376
 }
377 377
 
378
-/* Menu Class ===============================================================*/
379
-
380
-MenuClass::MenuClass() {
381
-  selected = 0;
382
-  topline = 0;
383
-}
384
-
385
-void MenuClass::draw() {
386
-  MenuTitle.draw();
387
-  if (DWINUI::onMenuDraw != nullptr) (*DWINUI::onMenuDraw)(this);
388
-  for (int8_t i = 0; i < MenuItemCount; i++)
389
-    MenuItems[i]->draw(i - topline);
390
-  if (DWINUI::onCursorDraw != nullptr) DWINUI::onCursorDraw(line());
391
-  DWIN_UpdateLCD();
392
-}
393
-
394
-void MenuClass::onScroll(bool dir) {
395
-  int8_t sel = selected;
396
-  if (dir) sel++; else sel--;
397
-  LIMIT(sel, 0, MenuItemCount - 1);
398
-  if (sel != selected) {
399
-    if (DWINUI::onCursorErase != nullptr) DWINUI::onCursorErase(line());
400
-    if ((sel - topline) == TROWS) {
401
-      DWIN_Frame_AreaMove(1, DWIN_SCROLL_UP, MLINE, DWINUI::backcolor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1);
402
-      topline++;
403
-      MenuItems[sel]->draw(TROWS - 1);
404
-    }
405
-    if ((sel < topline)) {
406
-      DWIN_Frame_AreaMove(1, DWIN_SCROLL_DOWN, MLINE, DWINUI::backcolor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1);
407
-      topline--;
408
-      MenuItems[sel]->draw(0);
409
-    }
410
-    selected = sel;
411
-    if (DWINUI::onCursorDraw != nullptr) DWINUI::onCursorDraw(line());
412
-    DWIN_UpdateLCD();
413
-  }
414
-}
415
-
416
-void MenuClass::onClick() {
417
-  if (MenuItems[selected]->onClick != nullptr) (*MenuItems[selected]->onClick)();
418
-}
419
-
420
-MenuItemClass *MenuClass::SelectedItem() {
421
-  return MenuItems[selected];
422
-}
423
-
424
-/* MenuItem Class ===========================================================*/
425
-
426
-MenuItemClass::MenuItemClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)()) {
427
-  icon = cicon;
428
-  onClick = onclick;
429
-  onDraw = ondraw;
430
-  const uint8_t len = _MIN(sizeof(caption) - 1, strlen(text));
431
-  memcpy(&caption[0], text, len);
432
-  caption[len] = '\0';
433
-}
434
-
435
-MenuItemClass::MenuItemClass(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)()) {
436
-  icon = cicon;
437
-  onClick = onclick;
438
-  onDraw = ondraw;
439
-  caption[0] = '\0';
440
-  frameid = id;
441
-  frame = { x1, y1, x2, y2 };
442
-}
443
-
444
-void MenuItemClass::SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
445
-  caption[0] = '\0';
446
-  frameid = id;
447
-  frame = { x1, y1, x2, y2 };
448
-}
449
-
450
-void MenuItemClass::draw(int8_t line) {
451
-  if (line < 0 || line >= TROWS) return;
452
-  if (onDraw != nullptr) (*onDraw)(this, line);
453
-};
454
-
455
-MenuItemPtrClass::MenuItemPtrClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) : MenuItemClass(cicon, text, ondraw, onclick) {
456
-  value = val;
457
-};
458
-
459 378
 #endif // DWIN_LCD_PROUI

+ 75
- 121
Marlin/src/lcd/e3v2/proui/dwinui.h Näytä tiedosto

@@ -24,8 +24,8 @@
24 24
 /**
25 25
  * DWIN Enhanced implementation for PRO UI
26 26
  * Author: Miguel A. Risco-Castillo (MRISCOC)
27
- * Version: 3.15.1
28
- * Date: 2022/02/25
27
+ * Version: 3.17.1
28
+ * Date: 2022/04/12
29 29
  */
30 30
 
31 31
 #include "dwin_lcd.h"
@@ -37,6 +37,7 @@
37 37
 #define ICON_AdvSet               ICON_Language
38 38
 #define ICON_BedSizeX             ICON_PrintSize
39 39
 #define ICON_BedSizeY             ICON_PrintSize
40
+#define ICON_BedTramming          ICON_SetHome
40 41
 #define ICON_Binary               ICON_Contact
41 42
 #define ICON_Brightness           ICON_Motion
42 43
 #define ICON_Cancel               ICON_StockConfiguration
@@ -50,10 +51,12 @@
50 51
 #define ICON_FilUnload            ICON_ReadEEPROM
51 52
 #define ICON_Flow                 ICON_StepE
52 53
 #define ICON_Folder               ICON_More
54
+#define ICON_FWRetract            ICON_StepE
53 55
 #define ICON_FWRetLength          ICON_StepE
54 56
 #define ICON_FWRetSpeed           ICON_Setspeed
55 57
 #define ICON_FWRetZRaise          ICON_MoveZ
56 58
 #define ICON_FWRecSpeed           ICON_Setspeed
59
+#define ICON_FWRecExtra           ICON_StepE
57 60
 #define ICON_HomeX                ICON_MoveX
58 61
 #define ICON_HomeY                ICON_MoveY
59 62
 #define ICON_HomeZ                ICON_MoveZ
@@ -102,6 +105,9 @@
102 105
 #define ICON_SetBaudRate          ICON_Setspeed
103 106
 #define ICON_SetCustomPreheat     ICON_SetEndTemp
104 107
 #define ICON_Sound                ICON_Cool
108
+#define ICON_TBSetup              ICON_Contact
109
+#define ICON_UBLActive            ICON_HotendTemp
110
+
105 111
 #define ICON_CaseLight            ICON_Motion
106 112
 #define ICON_LedControl           ICON_Motion
107 113
 
@@ -111,12 +117,27 @@
111 117
 #define BTN_Confirm           89
112 118
 #define BTN_Print             90
113 119
 #define BTN_Save              91
120
+#define BTN_Purge             92
114 121
 
115 122
 // Extended and default UI Colors
116 123
 #define Color_Black           0
117 124
 #define Color_Green           RGB(0,63,0)
118 125
 #define Color_Aqua            RGB(0,63,31)
119 126
 #define Color_Blue            RGB(0,0,31)
127
+#define Color_Light_White     0xBDD7
128
+#define Color_Light_Green     0x3460
129
+#define Color_Cyan            0x07FF
130
+#define Color_Light_Cyan      0x04F3
131
+#define Color_Light_Blue      0x3A6A
132
+#define Color_Magenta         0xF81F
133
+#define Color_Light_Magenta   0x9813
134
+#define Color_Light_Red       0x8800
135
+#define Color_Orange          0xFA20
136
+#define Color_Light_Orange    0xFBC0
137
+#define Color_Light_Yellow    0x8BE0
138
+#define Color_Brown           0xCC27
139
+#define Color_Light_Brown     0x6204
140
+#define Color_Grey            0x18E3
120 141
 
121 142
 // UI element defines and constants
122 143
 #define DWIN_FONT_MENU font8x16
@@ -130,7 +151,7 @@
130 151
 #define UNITFDIGITS 1
131 152
 #define MINUNITMULT POW(10, UNITFDIGITS)
132 153
 
133
-constexpr uint16_t TITLE_HEIGHT = 30,                          // Title bar height
154
+constexpr uint8_t  TITLE_HEIGHT = 30,                          // Title bar height
134 155
                    MLINE = 53,                                 // Menu line height
135 156
                    TROWS = (STATUS_Y - TITLE_HEIGHT) / MLINE,  // Total rows
136 157
                    MROWS = TROWS - 1,                          // Other-than-Back
@@ -149,10 +170,6 @@ constexpr uint16_t TITLE_HEIGHT = 30,                          // Title bar heig
149 170
 // Menuitem caption Y position
150 171
 #define MBASE(L) (MYPOS(L) + CAPOFF)
151 172
 
152
-// Create and add a MenuItem object to the menu array
153
-#define MENU_ITEM(V...) DWINUI::MenuItemsAdd(new MenuItemClass(V))
154
-#define EDIT_ITEM(V...) DWINUI::MenuItemsAdd(new MenuItemPtrClass(V))
155
-
156 173
 typedef struct { uint16_t left, top, right, bottom; } rect_t;
157 174
 typedef struct { uint16_t x, y, w, h; } frame_rect_t;
158 175
 
@@ -173,49 +190,6 @@ public:
173 190
 };
174 191
 extern TitleClass Title;
175 192
 
176
-class MenuItemClass {
177
-protected:
178
-public:
179
-  int8_t pos = 0;
180
-  uint8_t icon = 0;
181
-  char caption[32] = "";
182
-  uint8_t frameid = 0;
183
-  rect_t frame = {0};
184
-  void (*onDraw)(MenuItemClass* menuitem, int8_t line) = nullptr;
185
-  void (*onClick)() = nullptr;
186
-  MenuItemClass() {};
187
-  MenuItemClass(uint8_t cicon, const char * const text=nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr);
188
-  MenuItemClass(uint8_t cicon, FSTR_P text = nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr) : MenuItemClass(cicon, FTOP(text), ondraw, onclick){}
189
-  MenuItemClass(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr);
190
-  void SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
191
-  virtual ~MenuItemClass(){};
192
-  virtual void draw(int8_t line);
193
-};
194
-
195
-class MenuItemPtrClass: public MenuItemClass {
196
-public:
197
-  void *value = nullptr;
198
-  using MenuItemClass::MenuItemClass;
199
-  MenuItemPtrClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val);
200
-  MenuItemPtrClass(uint8_t cicon, FSTR_P text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) : MenuItemPtrClass(cicon, FTOP(text), ondraw, onclick, val){}
201
-};
202
-
203
-class MenuClass {
204
-public:
205
-  int8_t topline = 0;
206
-  int8_t selected = 0;
207
-  TitleClass MenuTitle;
208
-  MenuClass();
209
-  virtual ~MenuClass(){};
210
-  inline int8_t line() { return selected - topline; };
211
-  inline int8_t line(uint8_t pos) {return pos - topline; };
212
-  void draw();
213
-  void onScroll(bool dir);
214
-  void onClick();
215
-  MenuItemClass* SelectedItem();
216
-};
217
-extern MenuClass *CurrentMenu;
218
-
219 193
 namespace DWINUI {
220 194
   extern xy_int_t cursor;
221 195
   extern uint16_t pencolor;
@@ -225,10 +199,7 @@ namespace DWINUI {
225 199
   extern uint8_t  font;
226 200
   extern FSTR_P const Author;
227 201
 
228
-  extern void (*onCursorErase)(const int8_t line);
229
-  extern void (*onCursorDraw)(const int8_t line);
230 202
   extern void (*onTitleDraw)(TitleClass* title);
231
-  extern void (*onMenuDraw)(MenuClass* menu);
232 203
 
233 204
   // DWIN LCD Initialization
234 205
   void init();
@@ -304,129 +275,121 @@ namespace DWINUI {
304 275
     DWIN_ICON_Show(true, false, false, ICON, icon, x, y);
305 276
   }
306 277
 
307
-  // Draw a positive integer
278
+  // Draw a numeric integer value
308 279
   //  bShow: true=display background color; false=don't display background color
309
-  //  zeroFill: true=zero fill; false=no zero fill
310
-  //  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
280
+  //  signedMode: 1=signed; 0=unsigned
311 281
   //  size: Font size
312 282
   //  color: Character color
313 283
   //  bColor: Background color
314 284
   //  iNum: Number of digits
315 285
   //  x/y: Upper-left coordinate
316 286
   //  value: Integer value
317
-  inline void Draw_Int(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
318
-    DWIN_Draw_Value(bShow, 0, zeroFill, zeroMode, size, color, bColor, iNum, 0, x, y, value);
287
+  void Draw_Int(uint8_t bShow, bool signedMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, int32_t value);
288
+
289
+  // Draw a positive integer
290
+  inline void Draw_Int(uint8_t bShow, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
291
+    Draw_Int(bShow, 0, size, color, bColor, iNum, x, y, value);
319 292
   }
320 293
   inline void Draw_Int(uint8_t iNum, long value) {
321
-    DWIN_Draw_Value(false, 0, true, 0, font, textcolor, backcolor, iNum, 0, cursor.x, cursor.y, value);
294
+    Draw_Int(false, 0, font, textcolor, backcolor, iNum, cursor.x, cursor.y, value);
322 295
     MoveBy(iNum * fontWidth(font), 0);
323 296
   }
324 297
   inline void Draw_Int(uint8_t iNum, uint16_t x, uint16_t y, long value) {
325
-    DWIN_Draw_Value(false, 0, true, 0, font, textcolor, backcolor, iNum, 0, x, y, value);
298
+    Draw_Int(false, 0, font, textcolor, backcolor, iNum, x, y, value);
326 299
   }
327 300
   inline void Draw_Int(uint16_t color, uint8_t iNum, uint16_t x, uint16_t y, long value) {
328
-    DWIN_Draw_Value(false, 0, true, 0, font, color, backcolor, iNum, 0, x, y, value);
301
+    Draw_Int(false, 0, font, color, backcolor, iNum, x, y, value);
329 302
   }
330 303
   inline void Draw_Int(uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
331
-    DWIN_Draw_Value(true, 0, true, 0, font, color, bColor, iNum, 0, x, y, value);
304
+    Draw_Int(true, 0, font, color, bColor, iNum, x, y, value);
332 305
   }
333 306
   inline void Draw_Int(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
334
-    DWIN_Draw_Value(true, 0, true, 0, size, color, bColor, iNum, 0, x, y, value);
307
+    Draw_Int(true, 0, size, color, bColor, iNum, x, y, value);
335 308
   }
336 309
 
337 310
   // Draw a signed integer
338
-  //  bShow: true=display background color; false=don't display background color
339
-  //  zeroFill: true=zero fill; false=no zero fill
340
-  //  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
341
-  //  size: Font size
342
-  //  color: Character color
343
-  //  bColor: Background color
344
-  //  iNum: Number of digits
345
-  //  x/y: Upper-left coordinate
346
-  //  value: Integer value
347
-  inline void Draw_Signed_Int(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
348
-    DWIN_Draw_Value(bShow, 1, zeroFill, zeroMode, size, color, bColor, iNum, 0, x, y, value);
311
+  inline void Draw_Signed_Int(uint8_t bShow, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
312
+    Draw_Int(bShow, 1, size, color, bColor, iNum, x, y, value);
349 313
   }
350 314
   inline void Draw_Signed_Int(uint8_t iNum, long value) {
351
-    DWIN_Draw_Value(false, 1, true, 0, font, textcolor, backcolor, iNum, 0, cursor.x, cursor.y, value);
315
+    Draw_Int(false, 1, font, textcolor, backcolor, iNum, cursor.x, cursor.y, value);
352 316
     MoveBy(iNum * fontWidth(font), 0);
353 317
   }
354 318
   inline void Draw_Signed_Int(uint8_t iNum, uint16_t x, uint16_t y, long value) {
355
-    DWIN_Draw_Value(false, 1, true, 0, font, textcolor, backcolor, iNum, 0, x, y, value);
319
+    Draw_Int(false, 1, font, textcolor, backcolor, iNum, x, y, value);
356 320
   }
357 321
   inline void Draw_Signed_Int(uint16_t color, uint8_t iNum, uint16_t x, uint16_t y, long value) {
358
-    DWIN_Draw_Value(false, 1, true, 0, font, color, backcolor, iNum, 0, x, y, value);
322
+    Draw_Int(false, 1, font, color, backcolor, iNum, x, y, value);
359 323
   }
360 324
   inline void Draw_Signed_Int(uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
361
-    DWIN_Draw_Value(true, 1, true, 0, font, color, bColor, iNum, 0, x, y, value);
325
+    Draw_Int(true, 1, font, color, bColor, iNum, x, y, value);
362 326
   }
363 327
   inline void Draw_Signed_Int(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint16_t x, uint16_t y, long value) {
364
-    DWIN_Draw_Value(true, 1, true, 0, size, color, bColor, iNum, 0, x, y, value);
328
+    Draw_Int(true, 1, size, color, bColor, iNum, x, y, value);
365 329
   }
366 330
 
367
-  // Draw a positive floating point number
331
+  // Draw a numeric float value
368 332
   //  bShow: true=display background color; false=don't display background color
369
-  //  zeroFill: true=zero fill; false=no zero fill
370
-  //  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
333
+  //  signedMode: 1=signed; 0=unsigned
371 334
   //  size: Font size
372 335
   //  color: Character color
373 336
   //  bColor: Background color
374
-  //  iNum: Number of whole digits
337
+  //  iNum: Number of digits
375 338
   //  fNum: Number of decimal digits
376
-  //  x/y: Upper-left point
377
-  //  value: Float value
378
-  inline void Draw_Float(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
379
-    DWIN_Draw_Value(bShow, 0, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, value);
339
+  //  x/y: Upper-left coordinate
340
+  //  value: float value
341
+  void Draw_Float(uint8_t bShow, bool signedMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value);
342
+
343
+  // Draw a positive floating point number
344
+  inline void Draw_Float(uint8_t bShow, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
345
+    Draw_Float(bShow, 0, size, color, bColor, iNum, fNum, x, y, value);
380 346
   }
381 347
   inline void Draw_Float(uint8_t iNum, uint8_t fNum, float value) {
382
-    DWIN_Draw_Value(false, 0, true, 0, font, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value);
348
+    Draw_Float(false, 0, font, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value);
383 349
     MoveBy((iNum + fNum + 1) * fontWidth(font), 0);
384 350
   }
385 351
   inline void Draw_Float(uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
386
-    DWIN_Draw_Value(false, 0, true, 0, font, textcolor, backcolor, iNum, fNum, x, y, value);
352
+    Draw_Float(false, 0, font, textcolor, backcolor, iNum, fNum, x, y, value);
387 353
   }
388
-  inline void Draw_Float(uint16_t color, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
389
-    DWIN_Draw_Value(false, 0, true, 0, font, color, backcolor, iNum, fNum, x, y, value);
354
+  inline void Draw_Float(uint8_t size, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
355
+    Draw_Float(false, 0, size, textcolor, backcolor, iNum, fNum, x, y, value);
390 356
   }
391 357
   inline void Draw_Float(uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
392
-    DWIN_Draw_Value(true, 0, true, 0, font, color, bColor, iNum, fNum, x, y, value);
358
+    Draw_Float(true, 0, font, color, bColor, iNum, fNum, x, y, value);
393 359
   }
394 360
   inline void Draw_Float(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
395
-    DWIN_Draw_Value(true, 0, true, 0, size, color, bColor, iNum, fNum, x, y, value);
361
+    Draw_Float(true, 0, size, color, bColor, iNum, fNum, x, y, value);
396 362
   }
397 363
 
398 364
   // Draw a signed floating point number
399
-  //  bShow: true=display background color; false=don't display background color
400
-  //  zeroFill: true=zero fill; false=no zero fill
401
-  //  zeroMode: 1=leading 0 displayed as 0; 0=leading 0 displayed as a space
402
-  //  size: Font size
403
-  //  color: Character color
404
-  //  bColor: Background color
405
-  //  iNum: Number of whole digits
406
-  //  fNum: Number of decimal digits
407
-  //  x/y: Upper-left point
408
-  //  value: Float value
409
-  inline void Draw_Signed_Float(uint8_t bShow, bool zeroFill, uint8_t zeroMode, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
410
-    DWIN_Draw_Value(bShow, 1, zeroFill, zeroMode, size, color, bColor, iNum, fNum, x, y, value);
365
+  inline void Draw_Signed_Float(uint8_t bShow, uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
366
+    Draw_Float(bShow, 1, size, color, bColor, iNum, fNum, x, y, value);
411 367
   }
412 368
   inline void Draw_Signed_Float(uint8_t iNum, uint8_t fNum, float value) {
413
-    DWIN_Draw_Value(false, 1, true, 0, font, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value);
369
+    Draw_Float(false, 1, font, textcolor, backcolor, iNum, fNum, cursor.x, cursor.y, value);
414 370
     MoveBy((iNum + fNum + 1) * fontWidth(font), 0);
415 371
   }
416 372
   inline void Draw_Signed_Float(uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
417
-    DWIN_Draw_Value(false, 1, true, 0, font, textcolor, backcolor, iNum, fNum, x, y, value);
373
+    Draw_Float(false, 1, font, textcolor, backcolor, iNum, fNum, x, y, value);
418 374
   }
419 375
   inline void Draw_Signed_Float(uint8_t size, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
420
-    DWIN_Draw_Value(false, 1, true, 0, size, textcolor, backcolor, iNum, fNum, x, y, value);
376
+    Draw_Float(false, 1, size, textcolor, backcolor, iNum, fNum, x, y, value);
421 377
   }
422 378
   inline void Draw_Signed_Float(uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
423
-    DWIN_Draw_Value(true, 1, true, 0, font, color, bColor, iNum, fNum, x, y, value);
379
+    Draw_Float(true, 1, font, color, bColor, iNum, fNum, x, y, value);
424 380
   }
425 381
   inline void Draw_Signed_Float(uint8_t size, uint16_t color, uint16_t bColor, uint8_t iNum, uint8_t fNum, uint16_t x, uint16_t y, float value) {
426
-    DWIN_Draw_Value(true, 1, true, 0, size, color, bColor, iNum, fNum, x, y, value);
382
+    Draw_Float(true, 1, size, color, bColor, iNum, fNum, x, y, value);
427 383
   }
428 384
 
429
-  // Draw a char at cursor position
385
+  // Draw a char
386
+  //  color: Character color
387
+  //  x: abscissa of the display
388
+  //  y: ordinate of the display
389
+  //  c: ASCII code of char
390
+  void Draw_Char(uint16_t color, uint16_t x, uint16_t y, const char c);
391
+  inline void Draw_Char(uint16_t x, uint16_t y, const char c) { Draw_Char(textcolor, x, y, c); };
392
+  // Draw a char at cursor position and increment cursor
430 393
   void Draw_Char(uint16_t color, const char c);
431 394
   inline void Draw_Char(const char c) { Draw_Char(textcolor, c); }
432 395
 
@@ -591,17 +554,8 @@ namespace DWINUI {
591 554
     DWIN_WriteToMem(0xA5, addr, length, data);
592 555
   }
593 556
 
594
-  // Clear Menu by filling the area with background color
557
+  // Clear by filling the area with background color
595 558
   // Area (0, TITLE_HEIGHT, DWIN_WIDTH, STATUS_Y - 1)
596 559
   void ClearMainArea();
597 560
 
598
-  // Clear MenuItems array and free MenuItems elements
599
-  void MenuItemsClear();
600
-
601
-  // Prepare MenuItems array
602
-  void MenuItemsPrepare(int8_t totalitems);
603
-
604
-  // Add elements to the MenuItems array
605
-  MenuItemClass* MenuItemsAdd(MenuItemClass* menuitem);
606
-
607 561
 };

+ 3
- 2
Marlin/src/lcd/e3v2/proui/lockscreen.cpp Näytä tiedosto

@@ -23,8 +23,8 @@
23 23
 /**
24 24
  * Lock screen implementation for PRO UI
25 25
  * Author: Miguel A. Risco-Castillo (MRISCOC)
26
- * Version: 2.1
27
- * Date: 2021/11/09
26
+ * Version: 2.2.0
27
+ * Date: 2022/04/11
28 28
  */
29 29
 
30 30
 #include "../../../inc/MarlinConfigPre.h"
@@ -50,6 +50,7 @@ void LockScreenClass::init() {
50 50
 }
51 51
 
52 52
 void LockScreenClass::draw() {
53
+  Title.SetCaption(GET_TEXT_F(MSG_LOCKSCREEN));
53 54
   DWINUI::ClearMainArea();
54 55
   DWINUI::Draw_Icon(ICON_LOGO, 71, 120);  // CREALITY logo
55 56
   DWINUI::Draw_CenteredString(Color_White, 180, GET_TEXT_F(MSG_LOCKSCREEN_LOCKED));

+ 2
- 2
Marlin/src/lcd/e3v2/proui/lockscreen.h Näytä tiedosto

@@ -24,8 +24,8 @@
24 24
 /**
25 25
  * Lock screen implementation for PRO UI
26 26
  * Author: Miguel A. Risco-Castillo (MRISCOC)
27
- * Version: 2.1
28
- * Date: 2021/11/09
27
+ * Version: 2.2.0
28
+ * Date: 2022/04/11
29 29
  */
30 30
 
31 31
 #include "../common/encoder.h"

+ 190
- 8
Marlin/src/lcd/e3v2/proui/menus.cpp Näytä tiedosto

@@ -23,8 +23,8 @@
23 23
 /**
24 24
  * Menu functions for ProUI
25 25
  * Author: Miguel A. Risco-Castillo
26
- * Version: 1.2.1
27
- * Date: 2022/02/25
26
+ * Version: 1.4.1
27
+ * Date: 2022/04/14
28 28
  *
29 29
  * This program is free software: you can redistribute it and/or modify
30 30
  * it under the terms of the GNU Lesser General Public License as
@@ -51,6 +51,14 @@
51 51
 #include "dwin.h"
52 52
 #include "menus.h"
53 53
 
54
+int8_t MenuItemTotal = 0;
55
+int8_t MenuItemCount = 0;
56
+MenuItemClass** MenuItems = nullptr;
57
+MenuClass *CurrentMenu = nullptr;
58
+MenuClass *PreviousMenu = nullptr;
59
+void (*onMenuDraw)(MenuClass* menu) = nullptr;
60
+void (*onCursorErase)(const int8_t line) = nullptr;
61
+void (*onCursorDraw)(const int8_t line) = nullptr;
54 62
 MenuData_t MenuData;
55 63
 
56 64
 // Menuitem Drawing functions =================================================
@@ -69,11 +77,13 @@ void Draw_Menu(MenuClass* menu) {
69 77
 }
70 78
 
71 79
 void Draw_Menu_Cursor(const int8_t line) {
72
-  DWIN_Draw_Rectangle(1, HMI_data.Cursor_color, 0, MBASE(line) - 18, 14, MBASE(line + 1) - 20);
80
+  const uint16_t ypos = MYPOS(line);
81
+  DWINUI::Draw_Box(1, HMI_data.Cursor_color, {0, ypos, 15, MLINE - 1});
73 82
 }
74 83
 
75 84
 void Erase_Menu_Cursor(const int8_t line) {
76
-  DWIN_Draw_Rectangle(1, HMI_data.Background_Color, 0, MBASE(line) - 18, 14, MBASE(line + 1) - 20);
85
+  const uint16_t ypos = MYPOS(line);
86
+  DWINUI::Draw_Box(1, HMI_data.Background_Color, {0, ypos, 15, MLINE - 1});
77 87
 }
78 88
 
79 89
 void Draw_Menu_Line(const uint8_t line, const uint8_t icon /*=0*/, const char * const label /*=nullptr*/, bool more /*=false*/) {
@@ -84,7 +94,7 @@ void Draw_Menu_Line(const uint8_t line, const uint8_t icon /*=0*/, const char *
84 94
 }
85 95
 
86 96
 void Draw_Chkb_Line(const uint8_t line, const bool checked) {
87
-  DWINUI::Draw_Checkbox(HMI_data.Text_Color, HMI_data.Background_Color, VALX + 16, MBASE(line) - 1, checked);
97
+  DWINUI::Draw_Checkbox(HMI_data.Text_Color, HMI_data.Background_Color, VALX + 3 * DWINUI::fontWidth(), MBASE(line) - 1, checked);
88 98
 }
89 99
 
90 100
 void Draw_Menu_IntValue(uint16_t bcolor, const uint8_t line, uint8_t iNum, const int32_t value /*=0*/) {
@@ -141,11 +151,21 @@ void onDrawPFloat2Menu(MenuItemClass* menuitem, int8_t line) {
141 151
   onDrawFloatMenu(menuitem, line, 2, value);
142 152
 }
143 153
 
154
+void onDrawPFloat3Menu(MenuItemClass* menuitem, int8_t line) {
155
+  const float value = *(float*)static_cast<MenuItemPtrClass*>(menuitem)->value;
156
+  onDrawFloatMenu(menuitem, line, 3, value);
157
+}
158
+
144 159
 void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line, bool checked) {
145 160
   onDrawMenuItem(menuitem, line);
146 161
   Draw_Chkb_Line(line, checked);
147 162
 }
148 163
 
164
+void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line) {
165
+  const bool val = *(bool*)static_cast<MenuItemPtrClass*>(menuitem)->value;
166
+  onDrawChkbMenu(menuitem, line, val);
167
+}
168
+
149 169
 //-----------------------------------------------------------------------------
150 170
 // On click functions
151 171
 //-----------------------------------------------------------------------------
@@ -165,7 +185,7 @@ void SetOnClick(uint8_t process, const int32_t lo, const int32_t hi, uint8_t dp,
165 185
   MenuData.dp = dp;
166 186
   MenuData.Apply = Apply;
167 187
   MenuData.LiveUpdate = LiveUpdate;
168
-  MenuData.Value = val;
188
+  MenuData.Value = constrain(val, lo, hi);
169 189
   EncoderRate.enabled = true;
170 190
 }
171 191
 
@@ -257,6 +277,7 @@ void HMI_Menu() {
257 277
 //  1 : live change
258 278
 //  2 : apply change
259 279
 int8_t HMI_GetIntNoDraw(const int32_t lo, const int32_t hi) {
280
+  const int32_t cval = MenuData.Value;
260 281
   EncoderState encoder_diffState = Encoder_ReceiveAnalyze();
261 282
   if (encoder_diffState != ENCODER_DIFF_NO) {
262 283
     if (Apply_Encoder(encoder_diffState, MenuData.Value)) {
@@ -265,9 +286,8 @@ int8_t HMI_GetIntNoDraw(const int32_t lo, const int32_t hi) {
265 286
       return 2;
266 287
     }
267 288
     LIMIT(MenuData.Value, lo, hi);
268
-    return 1;
269 289
   }
270
-  return 0;
290
+  return int8_t(cval != MenuData.Value);
271 291
 }
272 292
 
273 293
 // Get an integer value using the encoder
@@ -367,4 +387,166 @@ void HMI_SetPFloat() {
367 387
   }
368 388
 }
369 389
 
390
+// Menu Classes ===============================================================
391
+
392
+MenuClass::MenuClass() {
393
+  selected = 0;
394
+  topline = 0;
395
+}
396
+
397
+void MenuClass::draw() {
398
+  MenuTitle.draw();
399
+  if (onMenuDraw != nullptr) onMenuDraw(this);
400
+  for (int8_t i = 0; i < MenuItemCount; i++)
401
+    MenuItems[i]->draw(i - topline);
402
+  if (onCursorDraw != nullptr) onCursorDraw(line());
403
+  DWIN_UpdateLCD();
404
+}
405
+
406
+void MenuClass::onScroll(bool dir) {
407
+  int8_t sel = selected;
408
+  if (dir) sel++; else sel--;
409
+  LIMIT(sel, 0, MenuItemCount - 1);
410
+  if (sel != selected) {
411
+    if (onCursorErase != nullptr) onCursorErase(line());
412
+    DWIN_UpdateLCD();
413
+    if ((sel - topline) == TROWS) {
414
+      DWIN_Frame_AreaMove(1, DWIN_SCROLL_UP, MLINE, DWINUI::backcolor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1);
415
+      topline++;
416
+      MenuItems[sel]->draw(TROWS - 1);
417
+    }
418
+    if ((sel < topline)) {
419
+      DWIN_Frame_AreaMove(1, DWIN_SCROLL_DOWN, MLINE, DWINUI::backcolor, 0, TITLE_HEIGHT + 1, DWIN_WIDTH, STATUS_Y - 1);
420
+      topline--;
421
+      MenuItems[sel]->draw(0);
422
+    }
423
+    selected = sel;
424
+    if (onCursorDraw != nullptr) onCursorDraw(line());
425
+    DWIN_UpdateLCD();
426
+  }
427
+}
428
+
429
+void MenuClass::onClick() {
430
+  if (MenuItems[selected]->onClick != nullptr) (*MenuItems[selected]->onClick)();
431
+}
432
+
433
+MenuItemClass *MenuClass::SelectedItem() {
434
+  return MenuItems[selected];
435
+}
436
+
437
+MenuItemClass** MenuClass::Items() {
438
+  return MenuItems;
439
+}
440
+
441
+int8_t MenuClass::count() {
442
+  return MenuItemCount;
443
+};
444
+
445
+/* MenuItem Class ===========================================================*/
446
+
447
+MenuItemClass::MenuItemClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)()) {
448
+  icon = cicon;
449
+  onClick = onclick;
450
+  onDraw = ondraw;
451
+  const uint8_t len = _MIN(sizeof(caption) - 1, strlen(text));
452
+  memcpy(&caption[0], text, len);
453
+  caption[len] = '\0';
454
+}
455
+
456
+MenuItemClass::MenuItemClass(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)()) {
457
+  icon = cicon;
458
+  onClick = onclick;
459
+  onDraw = ondraw;
460
+  caption[0] = '\0';
461
+  frameid = id;
462
+  frame = { x1, y1, x2, y2 };
463
+}
464
+
465
+void MenuItemClass::SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) {
466
+  caption[0] = '\0';
467
+  frameid = id;
468
+  frame = { x1, y1, x2, y2 };
469
+}
470
+
471
+void MenuItemClass::draw(int8_t line) {
472
+  if (line < 0 || line >= TROWS) return;
473
+  if (onDraw != nullptr) (*onDraw)(this, line);
474
+};
475
+
476
+void MenuItemClass::redraw() {
477
+  draw(CurrentMenu->line(this->pos));
478
+}
479
+
480
+MenuItemPtrClass::MenuItemPtrClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) : MenuItemClass(cicon, text, ondraw, onclick) {
481
+  value = val;
482
+};
483
+
484
+// Menu auxiliary functions ===================================================
485
+
486
+void MenuItemsClear() {
487
+  if (MenuItems == nullptr) return;
488
+  for (int8_t i = 0; i < MenuItemCount; i++) delete MenuItems[i];
489
+  delete[] MenuItems;
490
+  MenuItems = nullptr;
491
+  MenuItemCount = 0;
492
+  MenuItemTotal = 0;
493
+}
494
+
495
+void MenuItemsPrepare(int8_t totalitems) {
496
+  MenuItemsClear();
497
+  MenuItemTotal = totalitems;
498
+  MenuItems = new MenuItemClass*[totalitems];
499
+}
500
+
501
+MenuItemClass* MenuItemsAdd(MenuItemClass* menuitem) {
502
+  MenuItems[MenuItemCount] = menuitem;
503
+  menuitem->pos = MenuItemCount++;
504
+  return menuitem;
505
+}
506
+
507
+MenuItemClass* MenuItemsAdd(uint8_t cicon, const char * const text/*=nullptr*/, void (*ondraw)(MenuItemClass* menuitem, int8_t line)/*=nullptr*/, void (*onclick)()/*=nullptr*/) {
508
+  if (MenuItemCount < MenuItemTotal) {
509
+    MenuItemClass* menuitem = new MenuItemClass(cicon, text, ondraw, onclick);
510
+    return MenuItemsAdd(menuitem);
511
+  }
512
+  else return nullptr;
513
+}
514
+
515
+MenuItemClass* MenuItemsAdd(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line)/*=nullptr*/, void (*onclick)()/*=nullptr*/) {
516
+  if (MenuItemCount < MenuItemTotal) {
517
+    MenuItemClass* menuitem = new MenuItemClass(cicon, id, x1, y1, x2, y2, ondraw, onclick);
518
+    return MenuItemsAdd(menuitem);
519
+  }
520
+  else return nullptr;
521
+}
522
+
523
+MenuItemClass* MenuItemsAdd(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) {
524
+  if (MenuItemCount < MenuItemTotal) {
525
+    MenuItemClass* menuitem = new MenuItemPtrClass(cicon, text, ondraw, onclick, val);
526
+    return MenuItemsAdd(menuitem);
527
+  }
528
+  else return nullptr;
529
+}
530
+
531
+bool SetMenu(MenuClass* &menu, FSTR_P title, int8_t totalitems) {
532
+  if (!menu) menu = new MenuClass();
533
+  const bool NotCurrent = (CurrentMenu != menu);
534
+  if (NotCurrent) {
535
+    menu->MenuTitle.SetCaption(title);
536
+    MenuItemsPrepare(totalitems);
537
+  }
538
+  return NotCurrent;
539
+}
540
+
541
+void UpdateMenu(MenuClass* &menu) {
542
+  if (!menu) return;
543
+  if (CurrentMenu != menu) {
544
+    PreviousMenu = CurrentMenu;
545
+    CurrentMenu = menu;
546
+  }
547
+  menu->draw();
548
+}
549
+
550
+void ReDrawMenu() { if (CurrentMenu && checkkey==Menu) CurrentMenu->draw(); }
551
+
370 552
 #endif // DWIN_LCD_PROUI

+ 96
- 2
Marlin/src/lcd/e3v2/proui/menus.h Näytä tiedosto

@@ -23,8 +23,8 @@
23 23
 /**
24 24
  * Menu functions for ProUI
25 25
  * Author: Miguel A. Risco-Castillo
26
- * Version: 1.2.1
27
- * Date: 2022/02/25
26
+ * Version: 1.4.1
27
+ * Date: 2022/04/14
28 28
  *
29 29
  * This program is free software: you can redistribute it and/or modify
30 30
  * it under the terms of the GNU Lesser General Public License as
@@ -56,8 +56,70 @@ typedef struct {
56 56
 } MenuData_t;
57 57
 
58 58
 extern MenuData_t MenuData;
59
+extern void (*onCursorErase)(const int8_t line);
60
+extern void (*onCursorDraw)(const int8_t line);
61
+
62
+// Auxiliary Macros ===========================================================
63
+
64
+// Create and add a MenuItem object to the menu array
65
+#define BACK_ITEM(H) MenuItemsAdd(ICON_Back, GET_TEXT_F(MSG_BUTTON_BACK), onDrawMenuItem, H)
66
+#define MENU_ITEM(V...) MenuItemsAdd(V)
67
+#define EDIT_ITEM(V...) MenuItemsAdd(V)
68
+#define MENU_ITEM_F(I,L,V...) MenuItemsAdd(I, GET_TEXT_F(L), V)
69
+#define EDIT_ITEM_F(I,L,V...) MenuItemsAdd(I, GET_TEXT_F(L), V)
70
+
71
+// Menu Classes ===============================================================
72
+
73
+class MenuItemClass {
74
+protected:
75
+public:
76
+  int8_t pos = 0;
77
+  uint8_t icon = 0;
78
+  char caption[32] = "";
79
+  uint8_t frameid = 0;
80
+  rect_t frame = {0};
81
+  void (*onDraw)(MenuItemClass* menuitem, int8_t line) = nullptr;
82
+  void (*onClick)() = nullptr;
83
+  MenuItemClass() {};
84
+  MenuItemClass(uint8_t cicon, const char * const text=nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr);
85
+  // MenuItemClass(uint8_t cicon, FSTR_P text = nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr) : MenuItemClass(cicon, FTOP(text), ondraw, onclick){}
86
+  MenuItemClass(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr);
87
+  void SetFrame(uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
88
+  virtual ~MenuItemClass(){};
89
+  virtual void draw(int8_t line);
90
+  void redraw();
91
+};
92
+
93
+class MenuItemPtrClass: public MenuItemClass {
94
+public:
95
+  void *value = nullptr;
96
+  using MenuItemClass::MenuItemClass;
97
+  MenuItemPtrClass(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val);
98
+  MenuItemPtrClass(uint8_t cicon, FSTR_P text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) : MenuItemPtrClass(cicon, FTOP(text), ondraw, onclick, val){}
99
+};
100
+
101
+class MenuClass {
102
+public:
103
+  int8_t topline = 0;
104
+  int8_t selected = 0;
105
+  TitleClass MenuTitle;
106
+  MenuClass();
107
+  virtual ~MenuClass(){};
108
+  inline int8_t line() { return selected - topline; };
109
+  inline int8_t line(uint8_t pos) {return pos - topline; };
110
+  int8_t count();
111
+  virtual void draw();
112
+  virtual void onScroll(bool dir);
113
+  void onClick();
114
+  MenuItemClass* SelectedItem();
115
+  static MenuItemClass** Items();
116
+};
117
+extern MenuClass *CurrentMenu;
118
+extern MenuClass *PreviousMenu;
119
+extern void (*onMenuDraw)(MenuClass* menu);
59 120
 
60 121
 // Menuitem Drawing functions =================================================
122
+
61 123
 void Draw_Title(TitleClass* title);
62 124
 void Draw_Menu(MenuClass* menu);
63 125
 void Draw_Menu_Cursor(const int8_t line);
@@ -74,9 +136,12 @@ void onDrawPInt32Menu(MenuItemClass* menuitem, int8_t line);
74 136
 void onDrawFloatMenu(MenuItemClass* menuitem, int8_t line, uint8_t dp, const float value);
75 137
 void onDrawPFloatMenu(MenuItemClass* menuitem, int8_t line);
76 138
 void onDrawPFloat2Menu(MenuItemClass* menuitem, int8_t line);
139
+void onDrawPFloat3Menu(MenuItemClass* menuitem, int8_t line);
77 140
 void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line, bool checked);
141
+void onDrawChkbMenu(MenuItemClass* menuitem, int8_t line);
78 142
 
79 143
 // On click functions =========================================================
144
+
80 145
 void SetOnClick(uint8_t process, const int32_t lo, const int32_t hi, uint8_t dp, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr);
81 146
 void SetValueOnClick(uint8_t process, const int32_t lo, const int32_t hi, const int32_t val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr);
82 147
 void SetValueOnClick(uint8_t process, const float lo, const float hi, uint8_t dp, const float val, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr);
@@ -86,9 +151,38 @@ void SetFloatOnClick(const float lo, const float hi, uint8_t dp, const float val
86 151
 void SetPFloatOnClick(const float lo, const float hi, uint8_t dp, void (*Apply)() = nullptr, void (*LiveUpdate)() = nullptr);
87 152
 
88 153
 // HMI user control functions =================================================
154
+
89 155
 void HMI_Menu();
90 156
 void HMI_SetInt();
91 157
 void HMI_SetPInt();
92 158
 void HMI_SetIntNoDraw();
93 159
 void HMI_SetFloat();
94 160
 void HMI_SetPFloat();
161
+
162
+// Menu auxiliary functions ===================================================
163
+
164
+// Create a new menu
165
+bool SetMenu(MenuClass* &menu, FSTR_P title, int8_t totalitems);
166
+
167
+//Update the Menu and Draw if it is valid
168
+void UpdateMenu(MenuClass* &menu);
169
+
170
+//Redraw the current Menu if it is valid
171
+void ReDrawMenu();
172
+
173
+// Clear MenuItems array and free MenuItems elements
174
+void MenuItemsClear();
175
+
176
+// Prepare MenuItems array
177
+void MenuItemsPrepare(int8_t totalitems);
178
+
179
+// Add elements to the MenuItems array
180
+MenuItemClass* MenuItemsAdd(uint8_t cicon, const char * const text=nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr);
181
+inline MenuItemClass* MenuItemsAdd(uint8_t cicon, FSTR_P text = nullptr, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr) {
182
+  return MenuItemsAdd(cicon, FTOP(text), ondraw, onclick);
183
+}
184
+MenuItemClass* MenuItemsAdd(uint8_t cicon, uint8_t id, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, void (*ondraw)(MenuItemClass* menuitem, int8_t line)=nullptr, void (*onclick)()=nullptr);
185
+MenuItemClass* MenuItemsAdd(uint8_t cicon, const char * const text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val);
186
+inline MenuItemClass* MenuItemsAdd(uint8_t cicon, FSTR_P text, void (*ondraw)(MenuItemClass* menuitem, int8_t line), void (*onclick)(), void* val) {
187
+  return MenuItemsAdd(cicon, FTOP(text), ondraw, onclick, val);
188
+}

+ 29
- 15
Marlin/src/lcd/e3v2/proui/meshviewer.cpp Näytä tiedosto

@@ -23,8 +23,8 @@
23 23
 /**
24 24
  * Mesh Viewer for PRO UI
25 25
  * Author: Miguel A. Risco-Castillo (MRISCOC)
26
- * version: 3.12.1
27
- * Date: 2022/02/24
26
+ * version: 3.14.1
27
+ * Date: 2022/04/11
28 28
  */
29 29
 
30 30
 #include "../../../inc/MarlinConfigPre.h"
@@ -41,6 +41,10 @@
41 41
 #include "dwin_popup.h"
42 42
 #include "../../../feature/bedlevel/bedlevel.h"
43 43
 
44
+#if ENABLED(AUTO_BED_LEVELING_UBL)
45
+  #include "ubl_tools.h"
46
+#endif
47
+
44 48
 MeshViewerClass MeshViewer;
45 49
 
46 50
 void MeshViewerClass::DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8_t sizey) {
@@ -56,17 +60,15 @@ void MeshViewerClass::DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8
56 60
   #define DrawMeshValue(xp, yp, zv) DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(xp) - 18, py(yp) - 6, zv)
57 61
   #define DrawMeshHLine(yp) DWIN_Draw_HLine(HMI_data.SplitLine_Color, px(0), py(yp), DWIN_WIDTH - 2 * mx)
58 62
   #define DrawMeshVLine(xp) DWIN_Draw_VLine(HMI_data.SplitLine_Color, px(xp), py(sizey - 1), DWIN_WIDTH - 2 * my)
59
-  int16_t maxz =-32000; int16_t minz = 32000; avg = 0;
63
+  int16_t maxz =-32000; int16_t minz = 32000;
60 64
   LOOP_L_N(y, sizey) LOOP_L_N(x, sizex) {
61 65
     const float v = isnan(zval[x][y]) ? 0 : round(zval[x][y] * 100);
62 66
     zmesh[x][y] = v;
63
-    avg += v;
64 67
     NOLESS(maxz, v);
65 68
     NOMORE(minz, v);
66 69
   }
67 70
   max = (float)maxz / 100;
68 71
   min = (float)minz / 100;
69
-  avg = avg / (100 * sizex * sizey);
70 72
   DWINUI::ClearMainArea();
71 73
   DWIN_Draw_Rectangle(0, HMI_data.SplitLine_Color, px(0), py(0), px(sizex - 1), py(sizey - 1));
72 74
   LOOP_S_L_N(x, 1, sizex - 1) DrawMeshVLine(x);
@@ -77,8 +79,10 @@ void MeshViewerClass::DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8
77 79
       uint16_t color = DWINUI::RainbowInt(zmesh[x][y], _MIN(-5, minz), _MAX(5, maxz));
78 80
       uint8_t radius = rm(zmesh[x][y]);
79 81
       DWINUI::Draw_FillCircle(color, px(x), py(y), radius);
80
-      if (sizex < 9)
81
-        DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(x) - 18, py(y) - 6, zval[x][y]);
82
+      if (sizex < 9) {
83
+        if (zmesh[x][y] == 0) DWINUI::Draw_Float(font6x12, 1, 2, px(x) - 12, py(y) - 6, 0);
84
+        else DWINUI::Draw_Signed_Float(font6x12, 1, 2, px(x) - 18, py(y) - 6, zval[x][y]);
85
+      }
82 86
       else {
83 87
         char str_1[9];
84 88
         str_1[0] = 0;
@@ -108,7 +112,13 @@ void MeshViewerClass::DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8
108 112
 
109 113
 void MeshViewerClass::Draw(bool withsave /*= false*/) {
110 114
   Title.ShowCaption(GET_TEXT_F(MSG_MESH_VIEWER));
111
-  DrawMesh(Z_VALUES_ARR, GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y);
115
+  #if ENABLED(USE_UBL_VIEWER)
116
+    DWINUI::ClearMainArea();
117
+    ubl_tools.viewer_print_value = true;
118
+    ubl_tools.Draw_Bed_Mesh(-1, 1, 8, 10 + TITLE_HEIGHT);
119
+  #else
120
+    DrawMesh(Z_VALUES_ARR, GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y);
121
+  #endif
112 122
   if (withsave) {
113 123
     DWINUI::Draw_Button(BTN_Save, 26, 305);
114 124
     DWINUI::Draw_Button(BTN_Continue, 146, 305);
@@ -117,15 +127,19 @@ void MeshViewerClass::Draw(bool withsave /*= false*/) {
117 127
   else
118 128
     DWINUI::Draw_Button(BTN_Continue, 86, 305);
119 129
 
120
-  char str_1[6], str_2[6] = "";
121
-  ui.status_printf(0, F("Mesh minZ: %s, maxZ: %s"),
122
-    dtostrf(min, 1, 2, str_1),
123
-    dtostrf(max, 1, 2, str_2)
124
-  );
130
+  #if ENABLED(USE_UBL_VIEWER)
131
+    ubl_tools.Set_Mesh_Viewer_Status();
132
+  #else
133
+    char str_1[6], str_2[6] = "";
134
+    ui.status_printf(0, F("Mesh minZ: %s, maxZ: %s"),
135
+      dtostrf(min, 1, 2, str_1),
136
+      dtostrf(max, 1, 2, str_2)
137
+    );
138
+  #endif
125 139
 }
126 140
 
127 141
 void Draw_MeshViewer() { MeshViewer.Draw(true); }
128
-void onClick_MeshViewer() { if (HMI_flag.select_flag) WriteEeprom(); HMI_ReturnScreen(); }
129
-void Goto_MeshViewer() { if (leveling_is_valid()) Goto_Popup(Draw_MeshViewer, onClick_MeshViewer);  else HMI_ReturnScreen(); }
142
+void onClick_MeshViewer() { if (HMI_flag.select_flag) SaveMesh(); HMI_ReturnScreen(); }
143
+void Goto_MeshViewer() { if (leveling_is_valid()) Goto_Popup(Draw_MeshViewer, onClick_MeshViewer); else HMI_ReturnScreen(); }
130 144
 
131 145
 #endif // DWIN_LCD_PROUI && HAS_MESH

+ 3
- 3
Marlin/src/lcd/e3v2/proui/meshviewer.h Näytä tiedosto

@@ -27,13 +27,13 @@
27 27
 /**
28 28
  * Mesh Viewer for PRO UI
29 29
  * Author: Miguel A. Risco-Castillo (MRISCOC)
30
- * version: 3.12.1
31
- * Date: 2022/02/24
30
+ * version: 3.14.1
31
+ * Date: 2022/04/11
32 32
  */
33 33
 
34 34
 class MeshViewerClass {
35 35
 public:
36
-  float avg, max, min;
36
+  float max, min;
37 37
   void Draw(bool withsave = false);
38 38
   void DrawMesh(bed_mesh_t zval, const uint8_t sizex, const uint8_t sizey);
39 39
 };

+ 1
- 1
Marlin/src/lcd/e3v2/proui/printstats.cpp Näytä tiedosto

@@ -71,7 +71,7 @@ void PrintStatsClass::Draw() {
71 71
 
72 72
 void PrintStatsClass::Reset() {
73 73
   print_job_timer.initStats();
74
-  HMI_AudioFeedback();
74
+  DONE_BUZZ(true);
75 75
 }
76 76
 
77 77
 void Goto_PrintStats() {

+ 255
- 0
Marlin/src/lcd/e3v2/proui/ubl_tools.cpp Näytä tiedosto

@@ -0,0 +1,255 @@
1
+/**
2
+ * UBL Tools and Mesh Viewer for Pro UI
3
+ * Version: 1.0.0
4
+ * Date: 2022/04/13
5
+ *
6
+ * Original Author: Henri-J-Norden
7
+ * Original Source: https://github.com/Jyers/Marlin/pull/126
8
+ *
9
+ * This program is free software: you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation, either version 3 of the License, or
12
+ * (at your option) any later version.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+#include "../../../inc/MarlinConfigPre.h"
25
+#include "ubl_tools.h"
26
+
27
+#if ENABLED(DWIN_LCD_PROUI)
28
+
29
+#include "../../marlinui.h"
30
+#include "../../../core/types.h"
31
+#include "dwin.h"
32
+#include "dwinui.h"
33
+#include "dwin_popup.h"
34
+#include "../../../feature/bedlevel/bedlevel.h"
35
+#include "../../../module/probe.h"
36
+#include "../../../gcode/gcode.h"
37
+#include "../../../module/planner.h"
38
+#include "../../../gcode/queue.h"
39
+#include "../../../libs/least_squares_fit.h"
40
+#include "../../../libs/vector_3.h"
41
+
42
+UBLMeshToolsClass ubl_tools;
43
+
44
+#if ENABLED(USE_UBL_VIEWER)
45
+  bool UBLMeshToolsClass::viewer_asymmetric_range = false;
46
+  bool UBLMeshToolsClass::viewer_print_value = false;
47
+#endif
48
+bool UBLMeshToolsClass::goto_mesh_value = false;
49
+uint8_t UBLMeshToolsClass::tilt_grid = 1;
50
+
51
+bool drawing_mesh = false;
52
+char cmd[MAX_CMD_SIZE+16], str_1[16], str_2[16], str_3[16];
53
+
54
+#if ENABLED(AUTO_BED_LEVELING_UBL)
55
+
56
+  void UBLMeshToolsClass::manual_value_update(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined/*=false*/) {
57
+    sprintf_P(cmd, PSTR("M421 I%i J%i Z%s %s"), mesh_x, mesh_y, dtostrf(current_position.z, 1, 3, str_1), undefined ? "N" : "");
58
+    gcode.process_subcommands_now(cmd);
59
+    planner.synchronize();
60
+  }
61
+
62
+  bool UBLMeshToolsClass::create_plane_from_mesh() {
63
+    struct linear_fit_data lsf_results;
64
+    incremental_LSF_reset(&lsf_results);
65
+    GRID_LOOP(x, y) {
66
+      if (!isnan(Z_VALUES_ARR[x][y])) {
67
+        xy_pos_t rpos;
68
+        rpos.x = ubl.mesh_index_to_xpos(x);
69
+        rpos.y = ubl.mesh_index_to_ypos(y);
70
+        incremental_LSF(&lsf_results, rpos, Z_VALUES_ARR[x][y]);
71
+      }
72
+    }
73
+
74
+    if (finish_incremental_LSF(&lsf_results)) {
75
+      SERIAL_ECHOPGM("Could not complete LSF!");
76
+      return true;
77
+    }
78
+
79
+    ubl.set_all_mesh_points_to_value(0);
80
+
81
+    matrix_3x3 rotation = matrix_3x3::create_look_at(vector_3(lsf_results.A, lsf_results.B, 1));
82
+    GRID_LOOP(i, j) {
83
+      float mx = ubl.mesh_index_to_xpos(i),
84
+            my = ubl.mesh_index_to_ypos(j),
85
+            mz = Z_VALUES_ARR[i][j];
86
+
87
+      if (DEBUGGING(LEVELING)) {
88
+        DEBUG_ECHOPAIR_F("before rotation = [", mx, 7);
89
+        DEBUG_CHAR(',');
90
+        DEBUG_ECHO_F(my, 7);
91
+        DEBUG_CHAR(',');
92
+        DEBUG_ECHO_F(mz, 7);
93
+        DEBUG_ECHOPGM("]   ---> ");
94
+        DEBUG_DELAY(20);
95
+      }
96
+
97
+      rotation.apply_rotation_xyz(mx, my, mz);
98
+
99
+      if (DEBUGGING(LEVELING)) {
100
+        DEBUG_ECHOPAIR_F("after rotation = [", mx, 7);
101
+        DEBUG_CHAR(',');
102
+        DEBUG_ECHO_F(my, 7);
103
+        DEBUG_CHAR(',');
104
+        DEBUG_ECHO_F(mz, 7);
105
+        DEBUG_ECHOLNPGM("]");
106
+        DEBUG_DELAY(20);
107
+      }
108
+
109
+      Z_VALUES_ARR[i][j] = mz - lsf_results.D;
110
+    }
111
+    return false;
112
+  }
113
+
114
+#else
115
+
116
+  void UBLMeshToolsClass::manual_value_update(const uint8_t mesh_x, const uint8_t mesh_y) {
117
+    sprintf_P(cmd, PSTR("G29 I%i J%i Z%s"), mesh_x, mesh_y, dtostrf(current_position.z, 1, 3, str_1));
118
+    gcode.process_subcommands_now(cmd);
119
+    planner.synchronize();
120
+  }
121
+
122
+#endif
123
+
124
+void UBLMeshToolsClass::manual_move(const uint8_t mesh_x, const uint8_t mesh_y, bool zmove/*=false*/) {
125
+  if (zmove) {
126
+    planner.synchronize();
127
+    current_position.z = goto_mesh_value ? Z_VALUES_ARR[mesh_x][mesh_y] : Z_CLEARANCE_BETWEEN_PROBES;
128
+    planner.buffer_line(current_position, homing_feedrate(Z_AXIS), active_extruder);
129
+    planner.synchronize();
130
+  }
131
+  else {
132
+    DWIN_Show_Popup(ICON_BLTouch, F("Moving to Point"), F("Please wait until done."));
133
+    HMI_SaveProcessID(NothingToDo);
134
+    sprintf_P(cmd, PSTR("G0 F300 Z%s"), dtostrf(Z_CLEARANCE_BETWEEN_PROBES, 1, 3, str_1));
135
+    gcode.process_subcommands_now(cmd);
136
+    sprintf_P(cmd, PSTR("G42 F4000 I%i J%i"), mesh_x, mesh_y);
137
+    gcode.process_subcommands_now(cmd);
138
+    planner.synchronize();
139
+    current_position.z = goto_mesh_value ? Z_VALUES_ARR[mesh_x][mesh_y] : Z_CLEARANCE_BETWEEN_PROBES;
140
+    planner.buffer_line(current_position, homing_feedrate(Z_AXIS), active_extruder);
141
+    planner.synchronize();
142
+    HMI_ReturnScreen();
143
+  }
144
+}
145
+
146
+float UBLMeshToolsClass::get_max_value() {
147
+  float max = __FLT_MIN__;
148
+  GRID_LOOP(x, y) {
149
+    if (!isnan(Z_VALUES_ARR[x][y]) && Z_VALUES_ARR[x][y] > max)
150
+      max = Z_VALUES_ARR[x][y];
151
+  }
152
+  return max;
153
+}
154
+
155
+float UBLMeshToolsClass::get_min_value() {
156
+  float min = __FLT_MAX__;
157
+  GRID_LOOP(x, y) {
158
+    if (!isnan(Z_VALUES_ARR[x][y]) && Z_VALUES_ARR[x][y] < min)
159
+      min = Z_VALUES_ARR[x][y];
160
+  }
161
+  return min;
162
+}
163
+
164
+bool UBLMeshToolsClass::validate() {
165
+  float min = __FLT_MAX__;
166
+  float max = __FLT_MIN__;
167
+
168
+  GRID_LOOP(x, y) {
169
+    if (isnan(Z_VALUES_ARR[x][y])) return false;
170
+    if (Z_VALUES_ARR[x][y] < min) min = Z_VALUES_ARR[x][y];
171
+    if (Z_VALUES_ARR[x][y] > max) max = Z_VALUES_ARR[x][y];
172
+  }
173
+  return max <= UBL_Z_OFFSET_MAX && min >= UBL_Z_OFFSET_MIN;
174
+}
175
+
176
+#if ENABLED(USE_UBL_VIEWER)
177
+  void UBLMeshToolsClass::Draw_Bed_Mesh(int16_t selected /*= -1*/, uint8_t gridline_width /*= 1*/, uint16_t padding_x /*= 8*/, uint16_t padding_y_top /*= 40 + 53 - 7*/) {
178
+    drawing_mesh = true;
179
+    const uint16_t total_width_px = DWIN_WIDTH - padding_x - padding_x;
180
+    const uint16_t cell_width_px  = total_width_px / GRID_MAX_POINTS_X;
181
+    const uint16_t cell_height_px = total_width_px / GRID_MAX_POINTS_Y;
182
+    const float v_max = abs(get_max_value()), v_min = abs(get_min_value()), range = _MAX(v_min, v_max);
183
+
184
+    // Clear background from previous selection and select new square
185
+    DWIN_Draw_Rectangle(1, Color_Bg_Black, _MAX(0, padding_x - gridline_width), _MAX(0, padding_y_top - gridline_width), padding_x + total_width_px, padding_y_top + total_width_px);
186
+    if (selected >= 0) {
187
+      const auto selected_y = selected / GRID_MAX_POINTS_X;
188
+      const auto selected_x = selected - (GRID_MAX_POINTS_X * selected_y);
189
+      const auto start_y_px = padding_y_top + selected_y * cell_height_px;
190
+      const auto start_x_px = padding_x + selected_x * cell_width_px;
191
+      DWIN_Draw_Rectangle(1, Color_White, _MAX(0, start_x_px - gridline_width), _MAX(0, start_y_px - gridline_width), start_x_px + cell_width_px, start_y_px + cell_height_px);
192
+    }
193
+
194
+    // Draw value square grid
195
+    char buf[8];
196
+    GRID_LOOP(x, y) {
197
+      const auto start_x_px = padding_x + x * cell_width_px;
198
+      const auto end_x_px   = start_x_px + cell_width_px - 1 - gridline_width;
199
+      const auto start_y_px = padding_y_top + (GRID_MAX_POINTS_Y - y - 1) * cell_height_px;
200
+      const auto end_y_px   = start_y_px + cell_height_px - 1 - gridline_width;
201
+      DWIN_Draw_Rectangle(1,                                                                                 // RGB565 colors: http://www.barth-dev.de/online/rgb565-color-picker/
202
+        isnan(Z_VALUES_ARR[x][y]) ? Color_Grey : (                                                           // gray if undefined
203
+          (Z_VALUES_ARR[x][y] < 0 ?
204
+            (uint16_t)round(0x1F * -Z_VALUES_ARR[x][y] / (!viewer_asymmetric_range ? range : v_min)) << 11 : // red if mesh point value is negative
205
+            (uint16_t)round(0x3F *  Z_VALUES_ARR[x][y] / (!viewer_asymmetric_range ? range : v_max)) << 5) | // green if mesh point value is positive
206
+              _MIN(0x1F, (((uint8_t)abs(Z_VALUES_ARR[x][y]) / 10) * 4))),                                    // + blue stepping for every mm
207
+        start_x_px, start_y_px, end_x_px, end_y_px
208
+      );
209
+
210
+      safe_delay(10);
211
+      LCD_SERIAL.flushTX();
212
+
213
+      // Draw value text on
214
+      if (viewer_print_value) {
215
+        int8_t offset_x, offset_y = cell_height_px / 2 - 6;
216
+        if (isnan(Z_VALUES_ARR[x][y])) {  // undefined
217
+          DWIN_Draw_String(false, font6x12, Color_White, Color_Bg_Blue, start_x_px + cell_width_px / 2 - 5, start_y_px + offset_y, F("X"));
218
+        }
219
+        else {                          // has value
220
+          if (GRID_MAX_POINTS_X < 10)
221
+            sprintf_P(buf, PSTR("%s"), dtostrf(abs(Z_VALUES_ARR[x][y]), 1, 2, str_1));
222
+          else
223
+            sprintf_P(buf, PSTR("%02i"), (uint16_t)(abs(Z_VALUES_ARR[x][y] - (int16_t)Z_VALUES_ARR[x][y]) * 100));
224
+          offset_x = cell_width_px / 2 - 3 * (strlen(buf)) - 2;
225
+          if (!(GRID_MAX_POINTS_X < 10))
226
+            DWIN_Draw_String(false, font6x12, Color_White, Color_Bg_Blue, start_x_px - 2 + offset_x, start_y_px + offset_y /*+ square / 2 - 6*/, F("."));
227
+          DWIN_Draw_String(false, font6x12, Color_White, Color_Bg_Blue, start_x_px + 1 + offset_x, start_y_px + offset_y /*+ square / 2 - 6*/, buf);
228
+        }
229
+        safe_delay(10);
230
+        LCD_SERIAL.flushTX();
231
+      }
232
+    }
233
+  }
234
+
235
+  void UBLMeshToolsClass::Set_Mesh_Viewer_Status() { // TODO: draw gradient with values as a legend instead
236
+    float v_max = abs(get_max_value()), v_min = abs(get_min_value()), range = _MAX(v_min, v_max);
237
+    if (v_min > 3e+10F) v_min = 0.0000001;
238
+    if (v_max > 3e+10F) v_max = 0.0000001;
239
+    if (range > 3e+10F) range = 0.0000001;
240
+    char msg[46];
241
+    if (viewer_asymmetric_range) {
242
+      dtostrf(-v_min, 1, 3, str_1);
243
+      dtostrf( v_max, 1, 3, str_2);
244
+    }
245
+    else {
246
+      dtostrf(-range, 1, 3, str_1);
247
+      dtostrf( range, 1, 3, str_2);
248
+    }
249
+    sprintf_P(msg, PSTR("Red %s..0..%s Green"), str_1, str_2);
250
+    ui.set_status(msg);
251
+    drawing_mesh = false;
252
+  }
253
+#endif
254
+
255
+#endif // DWIN_LCD_PROUI

+ 59
- 0
Marlin/src/lcd/e3v2/proui/ubl_tools.h Näytä tiedosto

@@ -0,0 +1,59 @@
1
+/**
2
+ * UBL Tools and Mesh Viewer for Pro UI
3
+ * Version: 1.0.0
4
+ * Date: 2022/04/13
5
+ *
6
+ * Original Author: Henri-J-Norden (https://github.com/Henri-J-Norden)
7
+ * Original Source: https://github.com/Jyers/Marlin/pull/135
8
+ *
9
+ * This program is free software: you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation, either version 3 of the License, or
12
+ * (at your option) any later version.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+#pragma once
24
+
25
+#include "../../../inc/MarlinConfigPre.h"
26
+
27
+//#define USE_UBL_VIEWER 1
28
+
29
+#define UBL_Z_OFFSET_MIN -3.0
30
+#define UBL_Z_OFFSET_MAX  3.0
31
+
32
+class UBLMeshToolsClass {
33
+public:
34
+  #if ENABLED(USE_UBL_VIEWER)
35
+    static bool viewer_asymmetric_range;
36
+    static bool viewer_print_value;
37
+  #endif
38
+  static bool goto_mesh_value;
39
+  static uint8_t tilt_grid;
40
+
41
+  #if ENABLED(AUTO_BED_LEVELING_UBL)
42
+    static void manual_value_update(const uint8_t mesh_x, const uint8_t mesh_y, bool undefined=false);
43
+    static bool create_plane_from_mesh();
44
+  #else
45
+    static void manual_value_update(const uint8_t mesh_x, const uint8_t mesh_y);
46
+  #endif
47
+  static void manual_move(const uint8_t mesh_x, const uint8_t mesh_y, bool zmove=false);
48
+  static float get_max_value();
49
+  static float get_min_value();
50
+  static bool validate();
51
+  #if ENABLED(USE_UBL_VIEWER)
52
+    static void Draw_Bed_Mesh(int16_t selected = -1, uint8_t gridline_width = 1, uint16_t padding_x = 8, uint16_t padding_y_top = 40 + 53 - 7);
53
+    static void Set_Mesh_Viewer_Status();
54
+  #endif
55
+};
56
+
57
+extern UBLMeshToolsClass ubl_tools;
58
+
59
+void Goto_MeshViewer();

+ 54
- 11
Marlin/src/lcd/language/language_en.h Näytä tiedosto

@@ -53,6 +53,8 @@ namespace Language_en {
53 53
   LSTR WELCOME_MSG                        = MACHINE_NAME _UxGT(" Ready.");
54 54
   LSTR MSG_YES                            = _UxGT("YES");
55 55
   LSTR MSG_NO                             = _UxGT("NO");
56
+  LSTR MSG_HIGH                           = _UxGT("HIGH");
57
+  LSTR MSG_LOW                            = _UxGT("LOW");
56 58
   LSTR MSG_BACK                           = _UxGT("Back");
57 59
   LSTR MSG_ERROR                          = _UxGT("Error");
58 60
   LSTR MSG_MEDIA_ABORTING                 = _UxGT("Aborting...");
@@ -68,6 +70,8 @@ namespace Language_en {
68 70
   LSTR MSG_LCD_SOFT_ENDSTOPS              = _UxGT("Soft Endstops");
69 71
   LSTR MSG_MAIN                           = _UxGT("Main");
70 72
   LSTR MSG_ADVANCED_SETTINGS              = _UxGT("Advanced Settings");
73
+  LSTR MSG_TOOLBAR_SETUP                  = _UxGT("Toolbar Setup");
74
+  LSTR MSG_OPTION_DISABLED                = _UxGT("Option Disabled");
71 75
   LSTR MSG_CONFIGURATION                  = _UxGT("Configuration");
72 76
   LSTR MSG_RUN_AUTO_FILES                 = _UxGT("Run Auto Files");
73 77
   LSTR MSG_DISABLE_STEPPERS               = _UxGT("Disable Steppers");
@@ -81,6 +85,7 @@ namespace Language_en {
81 85
   LSTR MSG_AUTO_HOME_Z                    = _UxGT("Home Z");
82 86
   LSTR MSG_FILAMENT_SET                   = _UxGT("Filament Settings");
83 87
   LSTR MSG_FILAMENT_MAN                   = _UxGT("Filament Management");
88
+  LSTR MSG_MANUAL_LEVELING                = _UxGT("Manual Leveling");
84 89
   LSTR MSG_LEVBED_FL                      = _UxGT("Front Left");
85 90
   LSTR MSG_LEVBED_FR                      = _UxGT("Front Right");
86 91
   LSTR MSG_LEVBED_C                       = _UxGT("Center");
@@ -119,7 +124,14 @@ namespace Language_en {
119 124
     LSTR MSG_PREHEAT_1_ALL                = _UxGT("Preheat ") PREHEAT_1_LABEL _UxGT(" All");
120 125
     LSTR MSG_PREHEAT_1_BEDONLY            = _UxGT("Preheat ") PREHEAT_1_LABEL _UxGT(" Bed");
121 126
     LSTR MSG_PREHEAT_1_SETTINGS           = _UxGT("Preheat ") PREHEAT_1_LABEL _UxGT(" Conf");
122
-
127
+    #ifdef PREHEAT_2_LABEL
128
+      LSTR MSG_PREHEAT_2                  = _UxGT("Preheat ") PREHEAT_2_LABEL;
129
+      LSTR MSG_PREHEAT_2_SETTINGS         = _UxGT("Preheat ") PREHEAT_2_LABEL _UxGT(" Conf");
130
+    #endif
131
+    #ifdef PREHEAT_3_LABEL
132
+      LSTR MSG_PREHEAT_3                  = _UxGT("Preheat ") PREHEAT_3_LABEL;
133
+      LSTR MSG_PREHEAT_3_SETTINGS         = _UxGT("Preheat ") PREHEAT_3_LABEL _UxGT(" Conf");
134
+    #endif
123 135
     LSTR MSG_PREHEAT_M                    = _UxGT("Preheat $");
124 136
     LSTR MSG_PREHEAT_M_H                  = _UxGT("Preheat $ ~");
125 137
     LSTR MSG_PREHEAT_M_END                = _UxGT("Preheat $ End");
@@ -166,10 +178,19 @@ namespace Language_en {
166 178
   LSTR MSG_MESH_VIEW                      = _UxGT("View Mesh");
167 179
   LSTR MSG_EDITING_STOPPED                = _UxGT("Mesh Editing Stopped");
168 180
   LSTR MSG_NO_VALID_MESH                  = _UxGT("No valid mesh");
181
+  LSTR MSG_ACTIVATE_MESH                  = _UxGT("Activate Leveling");
169 182
   LSTR MSG_PROBING_POINT                  = _UxGT("Probing Point");
170 183
   LSTR MSG_MESH_X                         = _UxGT("Index X");
171 184
   LSTR MSG_MESH_Y                         = _UxGT("Index Y");
185
+  LSTR MSG_MESH_INSET                     = _UxGT("Mesh Inset");
186
+  LSTR MSG_MESH_MIN_X                     = _UxGT("Mesh X Minimum");
187
+  LSTR MSG_MESH_MAX_X                     = _UxGT("Mesh X Maximum");
188
+  LSTR MSG_MESH_MIN_Y                     = _UxGT("Mesh Y Minimum");
189
+  LSTR MSG_MESH_MAX_Y                     = _UxGT("Mesh Y Maximum");
190
+  LSTR MSG_MESH_AMAX                      = _UxGT("Maximize Area");
191
+  LSTR MSG_MESH_CENTER                    = _UxGT("Center Area");
172 192
   LSTR MSG_MESH_EDIT_Z                    = _UxGT("Z Value");
193
+  LSTR MSG_MESH_CANCEL                    = _UxGT("Mesh cancelled");
173 194
   LSTR MSG_CUSTOM_COMMANDS                = _UxGT("Custom Commands");
174 195
   LSTR MSG_M48_TEST                       = _UxGT("M48 Probe Test");
175 196
   LSTR MSG_M48_POINT                      = _UxGT("M48 Point");
@@ -188,6 +209,9 @@ namespace Language_en {
188 209
   LSTR MSG_UBL_TOOLS                      = _UxGT("UBL Tools");
189 210
   LSTR MSG_UBL_LEVEL_BED                  = _UxGT("Unified Bed Leveling");
190 211
   LSTR MSG_LCD_TILTING_MESH               = _UxGT("Tilting Point");
212
+  LSTR MSG_UBL_TILT_MESH                  = _UxGT("Tilt Mesh");
213
+  LSTR MSG_UBL_TILTING_GRID               = _UxGT("Tilting Grid Size");
214
+  LSTR MSG_UBL_MESH_TILTED                = _UxGT("Mesh Tilted");
191 215
   LSTR MSG_UBL_MANUAL_MESH                = _UxGT("Manually Build Mesh");
192 216
   LSTR MSG_UBL_MESH_WIZARD                = _UxGT("UBL Mesh Wizard");
193 217
   LSTR MSG_UBL_BC_INSERT                  = _UxGT("Place Shim & Measure");
@@ -236,6 +260,7 @@ namespace Language_en {
236 260
   LSTR MSG_UBL_MANUAL_FILLIN              = _UxGT("Manual Fill-in");
237 261
   LSTR MSG_UBL_SMART_FILLIN               = _UxGT("Smart Fill-in");
238 262
   LSTR MSG_UBL_FILLIN_MESH                = _UxGT("Fill-in Mesh");
263
+  LSTR MSG_UBL_MESH_FILLED                = _UxGT("Missing Points Filled");
239 264
   LSTR MSG_UBL_INVALIDATE_ALL             = _UxGT("Invalidate All");
240 265
   LSTR MSG_UBL_INVALIDATE_CLOSEST         = _UxGT("Invalidate Closest");
241 266
   LSTR MSG_UBL_FINE_TUNE_ALL              = _UxGT("Fine Tune All");
@@ -244,6 +269,7 @@ namespace Language_en {
244 269
   LSTR MSG_UBL_STORAGE_SLOT               = _UxGT("Memory Slot");
245 270
   LSTR MSG_UBL_LOAD_MESH                  = _UxGT("Load Bed Mesh");
246 271
   LSTR MSG_UBL_SAVE_MESH                  = _UxGT("Save Bed Mesh");
272
+  LSTR MSG_UBL_INVALID_SLOT               = _UxGT("First Select a Mesh Slot");
247 273
   LSTR MSG_MESH_LOADED                    = _UxGT("Mesh %i Loaded");
248 274
   LSTR MSG_MESH_SAVED                     = _UxGT("Mesh %i Saved");
249 275
   LSTR MSG_UBL_NO_STORAGE                 = _UxGT("No Storage");
@@ -350,6 +376,7 @@ namespace Language_en {
350 376
   LSTR MSG_PID_AUTOTUNE_FAILED            = _UxGT("PID Autotune failed!");
351 377
   LSTR MSG_BAD_EXTRUDER_NUM               = _UxGT("Bad extruder.");
352 378
   LSTR MSG_TEMP_TOO_HIGH                  = _UxGT("Temperature too high.");
379
+  LSTR MSG_TIMEOUT                        = _UxGT("Timeout.");
353 380
   LSTR MSG_PID_BAD_EXTRUDER_NUM           = _UxGT("Autotune failed! Bad extruder.");
354 381
   LSTR MSG_PID_TEMP_TOO_HIGH              = _UxGT("Autotune failed! Temperature too high.");
355 382
   LSTR MSG_PID_TIMEOUT                    = _UxGT("Autotune failed! Timeout.");
@@ -447,6 +474,10 @@ namespace Language_en {
447 474
   LSTR MSG_RESET_PRINTER                  = _UxGT("Reset Printer");
448 475
   LSTR MSG_REFRESH                        = LCD_STR_REFRESH _UxGT("Refresh");
449 476
   LSTR MSG_INFO_SCREEN                    = _UxGT("Info Screen");
477
+  LSTR MSG_INFO_MACHINENAME               = _UxGT("Machine Name");
478
+  LSTR MSG_INFO_SIZE                      = _UxGT("Size");
479
+  LSTR MSG_INFO_FWVERSION                 = _UxGT("Firmware Version");
480
+  LSTR MSG_INFO_BUILD                     = _UxGT("Build Datetime");
450 481
   LSTR MSG_PREPARE                        = _UxGT("Prepare");
451 482
   LSTR MSG_TUNE                           = _UxGT("Tune");
452 483
   LSTR MSG_POWER_MONITOR                  = _UxGT("Power monitor");
@@ -473,6 +504,7 @@ namespace Language_en {
473 504
   LSTR MSG_BUTTON_RESUME                  = _UxGT("Resume");
474 505
   LSTR MSG_BUTTON_ADVANCED                = _UxGT("Advanced");
475 506
   LSTR MSG_BUTTON_SAVE                    = _UxGT("Save");
507
+  LSTR MSG_BUTTON_PURGE                   = _UxGT("Purge");
476 508
   LSTR MSG_PAUSING                        = _UxGT("Pausing...");
477 509
   LSTR MSG_PAUSE_PRINT                    = _UxGT("Pause Print");
478 510
   LSTR MSG_ADVANCED_PAUSE                 = _UxGT("Advanced Pause");
@@ -495,9 +527,12 @@ namespace Language_en {
495 527
   LSTR MSG_REMAINING_TIME                 = _UxGT("Remaining");
496 528
   LSTR MSG_PRINT_ABORTED                  = _UxGT("Print Aborted");
497 529
   LSTR MSG_PRINT_DONE                     = _UxGT("Print Done");
530
+  LSTR MSG_PRINTER_KILLED                 = _UxGT("Printer killed!");
531
+  LSTR MSG_TURN_OFF                       = _UxGT("Turn off the printer");
498 532
   LSTR MSG_NO_MOVE                        = _UxGT("No Move.");
499 533
   LSTR MSG_KILLED                         = _UxGT("KILLED. ");
500 534
   LSTR MSG_STOPPED                        = _UxGT("STOPPED. ");
535
+  LSTR MSG_FWRETRACT                      = _UxGT("Firmware Retract");
501 536
   LSTR MSG_CONTROL_RETRACT                = _UxGT("Retract mm");
502 537
   LSTR MSG_CONTROL_RETRACT_SWAP           = _UxGT("Swap Re.mm");
503 538
   LSTR MSG_CONTROL_RETRACTF               = _UxGT("Retract V");
@@ -563,6 +598,9 @@ namespace Language_en {
563 598
   LSTR MSG_ZPROBE_XOFFSET                 = _UxGT("Probe X Offset");
564 599
   LSTR MSG_ZPROBE_YOFFSET                 = _UxGT("Probe Y Offset");
565 600
   LSTR MSG_ZPROBE_ZOFFSET                 = _UxGT("Probe Z Offset");
601
+  LSTR MSG_ZPROBE_MARGIN                  = _UxGT("Probe Margin");
602
+  LSTR MSG_Z_FEED_RATE                    = _UxGT("Z Feed Rate");
603
+  LSTR MSG_ENABLE_HS_MODE                 = _UxGT("Enable HS mode");
566 604
   LSTR MSG_MOVE_NOZZLE_TO_BED             = _UxGT("Move Nozzle to Bed");
567 605
   LSTR MSG_BABYSTEP_X                     = _UxGT("Babystep X");
568 606
   LSTR MSG_BABYSTEP_Y                     = _UxGT("Babystep Y");
@@ -633,27 +671,28 @@ namespace Language_en {
633 671
   LSTR MSG_CASE_LIGHT_BRIGHTNESS          = _UxGT("Light Brightness");
634 672
   LSTR MSG_KILL_EXPECTED_PRINTER          = _UxGT("INCORRECT PRINTER");
635 673
 
674
+  LSTR MSG_COLORS_GET                     = _UxGT("Get Color");
675
+  LSTR MSG_COLORS_SELECT                  = _UxGT("Select Colors");
676
+  LSTR MSG_COLORS_APPLIED                 = _UxGT("Colors applied");
677
+  LSTR MSG_COLORS_RED                     = _UxGT("Red");
678
+  LSTR MSG_COLORS_GREEN                   = _UxGT("Green");
679
+  LSTR MSG_COLORS_BLUE                    = _UxGT("Blue");
680
+  LSTR MSG_COLORS_WHITE                   = _UxGT("White");
681
+  LSTR MSG_UI_LANGUAGE                    = _UxGT("UI Language");
682
+  LSTR MSG_SOUND_ENABLE                   = _UxGT("Enable sound");
636 683
   LSTR MSG_LOCKSCREEN                     = _UxGT("Lock Screen");
637 684
   LSTR MSG_LOCKSCREEN_LOCKED              = _UxGT("Printer is Locked,");
638 685
   LSTR MSG_LOCKSCREEN_UNLOCK              = _UxGT("Scroll to unlock.");
686
+  LSTR MSG_PLEASE_WAIT_REBOOT             = _UxGT("Please wait until reboot.");
687
+
639 688
   #if LCD_WIDTH >= 20 || HAS_DWIN_E3V2
640 689
     LSTR MSG_MEDIA_NOT_INSERTED           = _UxGT("No media inserted.");
641
-    LSTR MSG_PLEASE_WAIT_REBOOT           = _UxGT("Please wait until reboot. ");
642 690
     LSTR MSG_PLEASE_PREHEAT               = _UxGT("Please preheat the hot end.");
643 691
     LSTR MSG_INFO_PRINT_COUNT_RESET       = _UxGT("Reset Print Count");
644 692
     LSTR MSG_INFO_PRINT_COUNT             = _UxGT("Print Count");
645 693
     LSTR MSG_INFO_PRINT_TIME              = _UxGT("Print Time");
646 694
     LSTR MSG_INFO_PRINT_LONGEST           = _UxGT("Longest Job Time");
647 695
     LSTR MSG_INFO_PRINT_FILAMENT          = _UxGT("Extruded Total");
648
-    LSTR MSG_COLORS_GET                   = _UxGT("Get Color");
649
-    LSTR MSG_COLORS_SELECT                = _UxGT("Select Colors");
650
-    LSTR MSG_COLORS_APPLIED               = _UxGT("Colors applied");
651
-    LSTR MSG_COLORS_RED                   = _UxGT("Red");
652
-    LSTR MSG_COLORS_GREEN                 = _UxGT("Green");
653
-    LSTR MSG_COLORS_BLUE                  = _UxGT("Blue");
654
-    LSTR MSG_COLORS_WHITE                 = _UxGT("White");
655
-    LSTR MSG_UI_LANGUAGE                  = _UxGT("UI Language");
656
-    LSTR MSG_SOUND_ENABLE                 = _UxGT("Enable sound");
657 696
   #else
658 697
     LSTR MSG_MEDIA_NOT_INSERTED           = _UxGT("No Media");
659 698
     LSTR MSG_PLEASE_PREHEAT               = _UxGT("Please Preheat");
@@ -687,10 +726,14 @@ namespace Language_en {
687 726
   LSTR MSG_FILAMENT_CHANGE_OPTION_HEADER  = _UxGT("RESUME OPTIONS:");
688 727
   LSTR MSG_FILAMENT_CHANGE_OPTION_PURGE   = _UxGT("Purge more");
689 728
   LSTR MSG_FILAMENT_CHANGE_OPTION_RESUME  = _UxGT("Continue");
729
+  LSTR MSG_FILAMENT_CHANGE_PURGE_CONTINUE = _UxGT("Purge or Continue?");
690 730
   LSTR MSG_FILAMENT_CHANGE_NOZZLE         = _UxGT("  Nozzle: ");
691 731
   LSTR MSG_RUNOUT_SENSOR                  = _UxGT("Runout Sensor");
692 732
   LSTR MSG_RUNOUT_DISTANCE_MM             = _UxGT("Runout Dist mm");
693 733
   LSTR MSG_RUNOUT_ENABLE                  = _UxGT("Enable Runout");
734
+  LSTR MSG_RUNOUT_ACTIVE                  = _UxGT("Runout Active");
735
+  LSTR MSG_INVERT_EXTRUDER                = _UxGT("Invert Extruder");
736
+  LSTR MSG_EXTRUDER_MIN_TEMP              = _UxGT("Extruder Min Temp.");
694 737
   LSTR MSG_FANCHECK                       = _UxGT("Fan Tacho Check");
695 738
   LSTR MSG_KILL_HOMING_FAILED             = _UxGT("Homing Failed");
696 739
   LSTR MSG_LCD_PROBING_FAILED             = _UxGT("Probing Failed");

Loading…
Peruuta
Tallenna