🚸 Color UI remaining time (#24843)

This commit is contained in:
mjbogusz 2023-06-23 11:56:34 +02:00 committed by GitHub
parent a58e530f92
commit 2218bab542
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 892 additions and 168 deletions

View file

@ -297,7 +297,6 @@ public:
} }
#endif #endif
#if HAS_PRINT_PROGRESS
#if HAS_PRINT_PROGRESS_PERMYRIAD #if HAS_PRINT_PROGRESS_PERMYRIAD
typedef uint16_t progress_t; typedef uint16_t progress_t;
#define PROGRESS_SCALE 100U #define PROGRESS_SCALE 100U
@ -307,6 +306,8 @@ public:
#define PROGRESS_SCALE 1U #define PROGRESS_SCALE 1U
#define PROGRESS_MASK 0x7F #define PROGRESS_MASK 0x7F
#endif #endif
#if HAS_PRINT_PROGRESS
#if ENABLED(SET_PROGRESS_PERCENT) #if ENABLED(SET_PROGRESS_PERCENT)
static progress_t progress_override; static progress_t progress_override;
static void set_progress(const progress_t p) { progress_override = _MIN(p, 100U * (PROGRESS_SCALE)); } static void set_progress(const progress_t p) { progress_override = _MIN(p, 100U * (PROGRESS_SCALE)); }

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="32"
height="32"
viewBox="0 0 32 32"
version="1.1"
id="svg5"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="time_elapsed.svg"
inkscape:export-filename="time_elapsed_plain.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
inkscape:document-units="px"
showgrid="true"
showguides="true"
inkscape:zoom="32"
inkscape:cx="24.078125"
inkscape:cy="17.125"
inkscape:window-width="3440"
inkscape:window-height="1377"
inkscape:window-x="1912"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="layer4-1">
<sodipodi:guide
position="8.4652079,6.9329007"
orientation="1,0"
id="guide72"
inkscape:locked="false" />
<sodipodi:guide
position="0,32"
orientation="0,32"
id="guide74"
inkscape:locked="false" />
<sodipodi:guide
position="32,32"
orientation="32,0"
id="guide76"
inkscape:locked="false" />
<sodipodi:guide
position="32,0"
orientation="0,-32"
id="guide78"
inkscape:locked="false" />
<sodipodi:guide
position="0,0"
orientation="-32,0"
id="guide80"
inkscape:locked="false" />
<inkscape:grid
type="xygrid"
id="grid82"
spacingx="0.5"
spacingy="0.5" />
<sodipodi:guide
position="15,33.2"
orientation="-1,0"
id="guide136"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" />
<sodipodi:guide
position="-5.8666667,17"
orientation="0,1"
id="guide138"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" />
</sodipodi:namedview>
<defs
id="defs2" />
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="bg"
style="fill:#808080">
<rect
style="fill:#808080"
id="rect1288"
width="32"
height="32"
x="0"
y="0"
sodipodi:insensitive="true" />
</g>
<g
inkscape:label="shadow"
inkscape:groupmode="layer"
id="layer1">
<g
inkscape:groupmode="layer"
id="layer4-1"
inkscape:label="full">
<path
style="display:inline;fill:none;fill-rule:evenodd;stroke:#595959;stroke-width:5;stroke-linecap:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="full-shadow"
sodipodi:type="arc"
sodipodi:cx="16.5"
sodipodi:cy="16.5"
sodipodi:rx="12"
sodipodi:ry="12"
sodipodi:start="4.712389"
sodipodi:end="0"
sodipodi:arc-type="arc"
d="m 16.5,4.5 a 12,12 0 0 1 12,12"
sodipodi:open="true"
sodipodi:insensitive="true" />
</g>
<g
inkscape:groupmode="layer"
id="layer5-2"
inkscape:label="dotted">
<circle
style="fill:none;fill-rule:evenodd;stroke:#595959;stroke-width:5;stroke-linecap:round;stroke-dasharray:0,6.285;stroke-dashoffset:0;stroke-opacity:1"
id="dots-shadow"
cx="16.5"
cy="16.5"
r="12" />
</g>
<g
inkscape:groupmode="layer"
id="layer6-1"
inkscape:label="hand">
<path
style="fill:#595959;fill-opacity:1;stroke:#595959;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-dasharray:none"
d="m 16,15 c -1.5,1.566667 -1.5,1.5 0,3 0.5,0.5 0.5,0.5 9,-1.5 -8.5,-2 -8.5,-2 -9,-1.5 z"
id="hand-shadow"
sodipodi:nodetypes="cccc" />
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="main">
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="full">
<path
style="display:inline;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="full-white"
sodipodi:type="arc"
sodipodi:cx="15.5"
sodipodi:cy="15.5"
sodipodi:rx="12"
sodipodi:ry="12"
sodipodi:start="4.712389"
sodipodi:end="0"
sodipodi:arc-type="arc"
d="m 15.5,3.5 a 12,12 0 0 1 12,12"
sodipodi:open="true" />
</g>
<g
inkscape:groupmode="layer"
id="layer5"
inkscape:label="dotted">
<circle
style="display:inline;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-dasharray:0, 6.284;stroke-dashoffset:0;stroke-opacity:1"
id="dots-white"
cx="15.5"
cy="15.5"
r="12" />
</g>
<g
inkscape:groupmode="layer"
id="layer6"
inkscape:label="hand">
<path
style="fill:#ffffff;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="m 15,14 c -1.5,1.566667 -1.5,1.5 0,3 0.5,0.5 0.5,0.5 9,-1.5 -8.5,-2 -8.5,-2 -9,-1.5 z"
id="hand-white"
sodipodi:nodetypes="cccc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -0,0 +1,189 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="32"
height="32"
viewBox="0 0 32 32"
version="1.1"
id="svg5"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="time_remaining.svg"
inkscape:export-filename="time_remaining_plain.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
inkscape:document-units="px"
showgrid="true"
showguides="true"
inkscape:zoom="32"
inkscape:cx="24.078125"
inkscape:cy="17.125"
inkscape:window-width="3440"
inkscape:window-height="1377"
inkscape:window-x="1912"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="layer6-1">
<sodipodi:guide
position="8.4652079,6.9329007"
orientation="1,0"
id="guide72"
inkscape:locked="false" />
<sodipodi:guide
position="0,32"
orientation="0,32"
id="guide74"
inkscape:locked="false" />
<sodipodi:guide
position="32,32"
orientation="32,0"
id="guide76"
inkscape:locked="false" />
<sodipodi:guide
position="32,0"
orientation="0,-32"
id="guide78"
inkscape:locked="false" />
<sodipodi:guide
position="0,0"
orientation="-32,0"
id="guide80"
inkscape:locked="false" />
<inkscape:grid
type="xygrid"
id="grid82"
spacingx="0.5"
spacingy="0.5" />
<sodipodi:guide
position="15,33.2"
orientation="-1,0"
id="guide136"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" />
<sodipodi:guide
position="-5.8666667,17"
orientation="0,1"
id="guide138"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,134,229)" />
</sodipodi:namedview>
<defs
id="defs2" />
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="bg"
style="fill:#808080">
<rect
style="fill:#808080"
id="rect1288"
width="32"
height="32"
x="0"
y="0"
sodipodi:insensitive="true" />
</g>
<g
inkscape:label="shadow"
inkscape:groupmode="layer"
id="layer1">
<g
inkscape:groupmode="layer"
id="layer4-1"
inkscape:label="full">
<path
style="display:inline;fill:none;fill-rule:evenodd;stroke:#595959;stroke-width:5;stroke-linecap:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="full-shadow"
sodipodi:type="arc"
sodipodi:cx="16.5"
sodipodi:cy="16.5"
sodipodi:rx="12"
sodipodi:ry="12"
sodipodi:start="3.1415927"
sodipodi:end="4.712389"
sodipodi:arc-type="arc"
d="m 4.5,16.5 a 12,12 0 0 1 12,-12"
sodipodi:open="true" />
</g>
<g
inkscape:groupmode="layer"
id="layer5-2"
inkscape:label="dotted">
<circle
style="fill:none;fill-rule:evenodd;stroke:#595959;stroke-width:5;stroke-linecap:round;stroke-dasharray:0,6.285;stroke-dashoffset:0;stroke-opacity:1"
id="dots-shadow"
cx="16.5"
cy="16.5"
r="12" />
</g>
<g
inkscape:groupmode="layer"
id="layer6-1"
inkscape:label="hand">
<path
style="fill:#595959;fill-opacity:1;stroke:#595959;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
d="m 16.874664,18 c 1.5,-1.566667 1.5,-1.5 0,-3 -0.5,-0.5 -0.5,-0.5 -9,1.5 8.5,2 8.5,2 9,1.5 z"
id="hand-shadow"
sodipodi:nodetypes="cccc" />
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="main">
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="full">
<path
style="display:inline;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="full-white"
sodipodi:type="arc"
sodipodi:cx="15.5"
sodipodi:cy="15.5"
sodipodi:rx="12"
sodipodi:ry="12"
sodipodi:start="3.1415927"
sodipodi:end="4.712389"
sodipodi:arc-type="arc"
d="m 3.5,15.5 a 12,12 0 0 1 12,-12"
sodipodi:open="true" />
</g>
<g
inkscape:groupmode="layer"
id="layer5"
inkscape:label="dotted">
<circle
style="display:inline;fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:4;stroke-linecap:round;stroke-dasharray:0, 6.284;stroke-dashoffset:0;stroke-opacity:1"
id="dots-white"
cx="15.5"
cy="15.5"
r="12" />
</g>
<g
inkscape:groupmode="layer"
id="layer6"
inkscape:label="hand">
<path
style="fill:#ffffff;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
d="m 15.874832,17 c 1.5,-1.566667 1.5,-1.5 0,-3 -0.5,-0.5 -0.5,-0.5 -9,1.5 8.5,2 8.5,2 9,1.5 z"
id="hand-white"
sodipodi:nodetypes="cccc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -0,0 +1,57 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
**/
#include "../../../inc/MarlinConfigPre.h"
#if HAS_GRAPHICAL_TFT
extern const uint8_t time_elapsed_32x32x4[512] = {
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xad, 0xca, 0x98, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x8a, 0xff, 0xff, 0xfe, 0xb8, 0x88, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0xce, 0xc8, 0x8d, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x8a, 0xff, 0xfa, 0x6a, 0xff, 0xff, 0xff, 0xff, 0xff, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x8a, 0xff, 0xfa, 0x58, 0x9d, 0xcd, 0xff, 0xff, 0xff, 0xf9, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0xdf, 0xe6, 0x58, 0x85, 0x55, 0x69, 0xff, 0xff, 0xff, 0x88, 0x88, 0x88,
0x88, 0x88, 0xbb, 0x88, 0x66, 0x55, 0x68, 0x88, 0x88, 0x76, 0x6b, 0xff, 0xff, 0xf6, 0x88, 0x88,
0x88, 0x8c, 0xff, 0xe6, 0x87, 0x67, 0x88, 0x88, 0x88, 0x88, 0x86, 0x9f, 0xff, 0xfd, 0x68, 0x88,
0x88, 0x8e, 0xff, 0xf7, 0x68, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x8b, 0xff, 0xff, 0x67, 0x88,
0x88, 0x8b, 0xff, 0xd5, 0x68, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0xff, 0xb6, 0x88,
0x88, 0x88, 0x89, 0x65, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xaf, 0xff, 0xe5, 0x88,
0x88, 0x88, 0x76, 0x56, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x8f, 0xff, 0xf7, 0x78,
0x88, 0x9c, 0x98, 0x88, 0x88, 0x88, 0x88, 0x9e, 0xdb, 0x98, 0x88, 0x88, 0x8d, 0xff, 0xf8, 0x68,
0x89, 0xff, 0xf8, 0x88, 0x88, 0x88, 0x89, 0xff, 0xff, 0xff, 0xec, 0xa9, 0x8d, 0xff, 0xfa, 0x68,
0x8b, 0xff, 0xfa, 0x68, 0x88, 0x88, 0x8c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0xff, 0xfd, 0x58,
0x89, 0xff, 0xf7, 0x58, 0x88, 0x88, 0x89, 0xff, 0xff, 0xff, 0xeb, 0x96, 0x59, 0xff, 0xf9, 0x58,
0x88, 0x89, 0x75, 0x68, 0x88, 0x88, 0x88, 0x8d, 0xda, 0x86, 0x55, 0x55, 0x67, 0x9c, 0x95, 0x58,
0x88, 0x86, 0x56, 0x88, 0x88, 0x88, 0x88, 0x86, 0x55, 0x56, 0x67, 0x88, 0x88, 0x75, 0x55, 0x78,
0x88, 0x88, 0xbb, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x8b, 0xa8, 0x88, 0x88,
0x88, 0x8c, 0xff, 0xe6, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xef, 0xfb, 0x78, 0x88,
0x88, 0x8e, 0xff, 0xf6, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0xfd, 0x58, 0x88,
0x88, 0x8b, 0xff, 0xd5, 0x68, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xef, 0xfa, 0x57, 0x88,
0x88, 0x88, 0x89, 0x65, 0x79, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x89, 0x95, 0x58, 0x88,
0x88, 0x88, 0x76, 0x58, 0xef, 0xe8, 0x88, 0x88, 0x88, 0x88, 0xef, 0xd8, 0x86, 0x55, 0x78, 0x88,
0x88, 0x88, 0x88, 0x8b, 0xff, 0xf9, 0x68, 0x9b, 0x98, 0x8b, 0xff, 0xf9, 0x68, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x8a, 0xff, 0xf8, 0x59, 0xff, 0xf8, 0x8b, 0xff, 0xf8, 0x58, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0xad, 0xa5, 0x5b, 0xff, 0xf9, 0x68, 0xbe, 0xa5, 0x68, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x75, 0x55, 0x79, 0xff, 0xf7, 0x58, 0x75, 0x55, 0x78, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x88, 0x78, 0x88, 0x8a, 0x75, 0x68, 0x88, 0x78, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x86, 0x56, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
};
#endif // HAS_GRAPHICAL_TFT

View file

@ -0,0 +1,57 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
**/
#include "../../../inc/MarlinConfigPre.h"
#if HAS_GRAPHICAL_TFT
extern const uint8_t time_remaining_32x32x4[512] = {
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x9a, 0xbd, 0xb8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x89, 0xce, 0xff, 0xff, 0xf9, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0xef, 0xff, 0xff, 0xff, 0xfd, 0x58, 0xbe, 0xb8, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x5a, 0xff, 0xf9, 0x78, 0x88, 0x88, 0x88,
0x88, 0x88, 0x8a, 0xff, 0xff, 0xff, 0xfd, 0xcd, 0x95, 0x5b, 0xff, 0xfa, 0x58, 0x88, 0x88, 0x88,
0x88, 0x88, 0x9f, 0xff, 0xff, 0xf9, 0x65, 0x55, 0x55, 0x78, 0xef, 0xe6, 0x58, 0x88, 0x88, 0x88,
0x88, 0x88, 0xff, 0xff, 0xfb, 0x55, 0x56, 0x78, 0x88, 0x88, 0x67, 0x55, 0x6a, 0x98, 0x88, 0x88,
0x88, 0x8e, 0xff, 0xff, 0x95, 0x56, 0x88, 0x88, 0x88, 0x88, 0x86, 0x66, 0xdf, 0xfa, 0x78, 0x88,
0x88, 0x9f, 0xff, 0xfb, 0x55, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0xfe, 0x58, 0x88,
0x88, 0xcf, 0xff, 0xf5, 0x57, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xef, 0xfc, 0x57, 0x88,
0x88, 0xef, 0xff, 0x95, 0x68, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x8b, 0xa6, 0x57, 0x88,
0x89, 0xff, 0xff, 0x65, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x86, 0x55, 0x68, 0x88,
0x8a, 0xff, 0xfd, 0x56, 0x88, 0x88, 0xac, 0xdd, 0x88, 0x88, 0x88, 0x88, 0x88, 0x9b, 0x98, 0x88,
0x8c, 0xff, 0xfc, 0x58, 0xbd, 0xef, 0xff, 0xff, 0xf7, 0x88, 0x88, 0x88, 0x89, 0xff, 0xf8, 0x88,
0x8d, 0xff, 0xfd, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x68, 0x88, 0x88, 0x8b, 0xff, 0xfa, 0x68,
0x8a, 0xff, 0xf9, 0x57, 0x9c, 0xef, 0xff, 0xff, 0xf6, 0x58, 0x88, 0x88, 0x89, 0xff, 0xf8, 0x58,
0x88, 0x9c, 0x85, 0x57, 0x65, 0x56, 0x8a, 0xdd, 0x75, 0x68, 0x88, 0x88, 0x88, 0x8a, 0x85, 0x68,
0x88, 0x75, 0x55, 0x88, 0x88, 0x87, 0x66, 0x55, 0x56, 0x88, 0x88, 0x88, 0x88, 0x86, 0x56, 0x88,
0x88, 0x88, 0xbb, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x8b, 0xa8, 0x88, 0x88,
0x88, 0x8c, 0xff, 0xe6, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xef, 0xfb, 0x78, 0x88,
0x88, 0x8e, 0xff, 0xf6, 0x78, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xff, 0xfd, 0x58, 0x88,
0x88, 0x8b, 0xff, 0xd5, 0x68, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xef, 0xfa, 0x57, 0x88,
0x88, 0x88, 0x89, 0x65, 0x79, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x89, 0x95, 0x58, 0x88,
0x88, 0x88, 0x76, 0x58, 0xef, 0xe8, 0x88, 0x88, 0x88, 0x88, 0xef, 0xd8, 0x86, 0x55, 0x78, 0x88,
0x88, 0x88, 0x88, 0x8b, 0xff, 0xf9, 0x68, 0x9b, 0x98, 0x8b, 0xff, 0xf9, 0x68, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x8a, 0xff, 0xf8, 0x59, 0xff, 0xf8, 0x8b, 0xff, 0xf8, 0x58, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0xad, 0xa5, 0x5b, 0xff, 0xf9, 0x68, 0xbe, 0xa5, 0x68, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x75, 0x55, 0x79, 0xff, 0xf7, 0x58, 0x75, 0x55, 0x78, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x88, 0x78, 0x88, 0x8a, 0x75, 0x68, 0x88, 0x78, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x86, 0x56, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
};
#endif // HAS_GRAPHICAL_TFT

View file

@ -72,6 +72,8 @@ const tImage Left_32x32x4 = { (void *)left_32x32x4, 32, 32, GREYSCALE4
const tImage Right_32x32x4 = { (void *)right_32x32x4, 32, 32, GREYSCALE4 }; const tImage Right_32x32x4 = { (void *)right_32x32x4, 32, 32, GREYSCALE4 };
const tImage Refresh_32x32x4 = { (void *)refresh_32x32x4, 32, 32, GREYSCALE4 }; const tImage Refresh_32x32x4 = { (void *)refresh_32x32x4, 32, 32, GREYSCALE4 };
const tImage Leveling_32x32x4 = { (void *)leveling_32x32x4, 32, 32, GREYSCALE4 }; const tImage Leveling_32x32x4 = { (void *)leveling_32x32x4, 32, 32, GREYSCALE4 };
const tImage Time_Elapsed_32x32x4 = { (void *)time_elapsed_32x32x4, 32, 32, GREYSCALE4 };
const tImage Time_Remaining_32x32x4 = { (void *)time_remaining_32x32x4, 32, 32, GREYSCALE4 };
const tImage Slider8x16x4 = { (void *)slider_8x16x4, 8, 16, GREYSCALE4 }; const tImage Slider8x16x4 = { (void *)slider_8x16x4, 8, 16, GREYSCALE4 };
@ -108,6 +110,8 @@ const tImage images[imgCount] = {
Home_64x64x4, Home_64x64x4,
BtnRounded_64x52x4, BtnRounded_64x52x4,
BtnRounded_42x39x4, BtnRounded_42x39x4,
Time_Elapsed_32x32x4,
Time_Remaining_32x32x4,
}; };
#endif // HAS_GRAPHICAL_TFT #endif // HAS_GRAPHICAL_TFT

View file

@ -61,6 +61,8 @@ extern const uint8_t left_32x32x4[];
extern const uint8_t right_32x32x4[]; extern const uint8_t right_32x32x4[];
extern const uint8_t refresh_32x32x4[]; extern const uint8_t refresh_32x32x4[];
extern const uint8_t leveling_32x32x4[]; extern const uint8_t leveling_32x32x4[];
extern const uint8_t time_elapsed_32x32x4[];
extern const uint8_t time_remaining_32x32x4[];
extern const uint8_t slider_8x16x4[]; extern const uint8_t slider_8x16x4[];
@ -97,6 +99,9 @@ enum MarlinImage : uint8_t {
imgHome, imgHome,
imgBtn52Rounded, imgBtn52Rounded,
imgBtn39Rounded, imgBtn39Rounded,
imgTimeElapsed,
imgTimeRemaining,
// Special values - must be at the end!
imgCount, imgCount,
noImage = imgCount, noImage = imgCount,
imgPageUp = imgLeft, imgPageUp = imgLeft,
@ -172,6 +177,8 @@ extern const tImage Left_32x32x4;
extern const tImage Right_32x32x4; extern const tImage Right_32x32x4;
extern const tImage Refresh_32x32x4; extern const tImage Refresh_32x32x4;
extern const tImage Leveling_32x32x4; extern const tImage Leveling_32x32x4;
extern const tImage Time_Elapsed_32x32x4;
extern const tImage Time_Remaining_32x32x4;
extern const tImage Slider8x16x4; extern const tImage Slider8x16x4;

View file

@ -315,14 +315,14 @@ void MarlinUI::draw_status_screen() {
y += 100; y += 100;
// Feed rate // Feed rate
tft.canvas(274, y, 128, 32); tft.canvas(274, y, 200, 32);
tft.set_background(COLOR_BACKGROUND); tft.set_background(COLOR_BACKGROUND);
uint16_t color = feedrate_percentage == 100 ? COLOR_RATE_100 : COLOR_RATE_ALTERED; uint16_t color = feedrate_percentage == 100 ? COLOR_RATE_100 : COLOR_RATE_ALTERED;
tft.add_image(0, 0, imgFeedRate, color); tft.add_image(0, 0, imgFeedRate, color);
tft_string.set(i16tostr3rj(feedrate_percentage)); tft_string.set(i16tostr3rj(feedrate_percentage));
tft_string.add('%'); tft_string.add('%');
tft.add_text(36, 1, color, tft_string); tft.add_text(36, 1, color, tft_string);
TERN_(TOUCH_SCREEN, touch.add_control(FEEDRATE, 274, y, 128, 32)); TERN_(TOUCH_SCREEN, touch.add_control(FEEDRATE, 274, y, 200, 32));
// Flow rate // Flow rate
#if HAS_EXTRUDERS #if HAS_EXTRUDERS
@ -333,7 +333,7 @@ void MarlinUI::draw_status_screen() {
tft_string.set(i16tostr3rj(planner.flow_percentage[active_extruder])); tft_string.set(i16tostr3rj(planner.flow_percentage[active_extruder]));
tft_string.add('%'); tft_string.add('%');
tft.add_text(36, 1, color, tft_string); tft.add_text(36, 1, color, tft_string);
TERN_(TOUCH_SCREEN, touch.add_control(FLOWRATE, 650, y, 128, 32, active_extruder)); TERN_(TOUCH_SCREEN, touch.add_control(FLOWRATE, 650, y, 200, 32, active_extruder));
#endif #endif
#if ENABLED(TOUCH_SCREEN) #if ENABLED(TOUCH_SCREEN)
@ -348,32 +348,115 @@ void MarlinUI::draw_status_screen() {
#endif #endif
y += 100; y += 100;
// Print duration const progress_t progress = TERN(HAS_PRINT_PROGRESS_PERMYRIAD, get_progress_permyriad, get_progress_percent)();
char buffer[14]; #if ENABLED(SHOW_ELAPSED_TIME) && DISABLED(SHOW_REMAINING_TIME)
// Print duration so far (time elapsed) - centered
char elapsed_str[22];
duration_t elapsed = print_job_timer.duration(); duration_t elapsed = print_job_timer.duration();
elapsed.toDigital(buffer); elapsed.toString(elapsed_str);
tft.canvas((TFT_WIDTH - 128) / 2, y, 128, 29); // Same width constraints as feedrate/flowrate controls
constexpr uint16_t time_str_width = 476, image_width = 36;
tft.canvas((TFT_WIDTH - time_str_width) / 2, y, time_str_width, 32);
tft.set_background(COLOR_BACKGROUND); tft.set_background(COLOR_BACKGROUND);
tft_string.set(buffer); tft_string.set(elapsed_str);
tft.add_text(tft_string.center(128), 0, COLOR_PRINT_TIME, tft_string); uint16_t text_pos_x = tft_string.center(time_str_width - image_width);
tft.add_image(text_pos_x, 0, imgTimeElapsed, COLOR_PRINT_TIME);
tft.add_text(text_pos_x + image_width, 1, COLOR_PRINT_TIME, tft_string);
#elif DISABLED(SHOW_ELAPSED_TIME) && ENABLED(SHOW_REMAINING_TIME)
// Print time remaining estimation - centered
char estimate_str[22];
duration_t elapsed = print_job_timer.duration();
// Get the estimate, first from M73
uint32_t estimate_remaining = (0
#if ALL(SET_PROGRESS_MANUALLY, SET_REMAINING_TIME)
+ get_remaining_time()
#endif
);
// If no M73 estimate is available but we have progress data, calculate time remaining assuming time elapsed is linear with progress
if (!estimate_remaining && progress > 0)
estimate_remaining = elapsed.value * (100 * (PROGRESS_SCALE) - progress) / progress;
// Generate estimate string
if (!estimate_remaining)
tft_string.set("-");
else {
duration_t estimation = estimate_remaining;
estimation.toString(estimate_str);
tft_string.set(estimate_str);
}
// Same width constraints as feedrate/flowrate controls
constexpr uint16_t time_str_width = 476, image_width = 36;
tft.canvas((TFT_WIDTH - time_str_width) / 2, y, time_str_width, 32);
tft.set_background(COLOR_BACKGROUND);
color = printingIsActive() ? COLOR_PRINT_TIME : COLOR_INACTIVE;
uint16_t text_pos_x = tft_string.center(time_str_width - image_width);
tft.add_image(text_pos_x, 0, imgTimeRemaining, color);
tft.add_text(text_pos_x + image_width, 1, color, tft_string);
#elif ALL(SHOW_REMAINING_TIME, SHOW_ELAPSED_TIME)
// Print duration so far (time elapsed) - aligned under feed rate
char elapsed_str[22];
duration_t elapsed = print_job_timer.duration();
elapsed.toString(elapsed_str);
tft.canvas(274, y, 200, 32);
tft.set_background(COLOR_BACKGROUND);
tft.add_image(0, 0, imgTimeElapsed, COLOR_PRINT_TIME);
tft_string.set(elapsed_str);
tft.add_text(36, 1, COLOR_PRINT_TIME, tft_string);
// Print time remaining estimation - aligned under flow rate
char estimate_str[22];
// Get the estimate, first from M73
uint32_t estimate_remaining = (0
#if ALL(SET_PROGRESS_MANUALLY, SET_REMAINING_TIME)
+ get_remaining_time()
#endif
);
// If no M73 estimate is available but we have progress data, calculate time remaining assuming time elapsed is linear with progress
if (!estimate_remaining && progress > 0)
estimate_remaining = elapsed.value * (100 * (PROGRESS_SCALE) - progress) / progress;
// Generate estimate string
if (!estimate_remaining)
tft_string.set("-");
else {
duration_t estimation = estimate_remaining;
estimation.toString(estimate_str);
tft_string.set(estimate_str);
}
// Push out the estimate to the screen
tft.canvas(650, y, 200, 32);
tft.set_background(COLOR_BACKGROUND);
color = printingIsActive() ? COLOR_PRINT_TIME : COLOR_INACTIVE;
tft.add_image(0, 0, imgTimeRemaining, color);
tft.add_text(36, 1, color, tft_string);
#endif
y += 50; y += 50;
// Progress bar // Progress bar
const uint8_t progress = ui.get_progress_percent();
tft.canvas(4, y, TFT_WIDTH - 8, 9); tft.canvas(4, y, TFT_WIDTH - 8, 9);
tft.set_background(COLOR_PROGRESS_BG); tft.set_background(COLOR_PROGRESS_BG);
tft.add_rectangle(0, 0, TFT_WIDTH - 8, 9, COLOR_PROGRESS_FRAME); tft.add_rectangle(0, 0, TFT_WIDTH - 8, 9, COLOR_PROGRESS_FRAME);
if (progress) if (progress)
tft.add_bar(1, 1, ((TFT_WIDTH - 10) * progress) / 100, 7, COLOR_PROGRESS_BAR); tft.add_bar(1, 1, ((TFT_WIDTH - 10) * progress / (PROGRESS_SCALE)) / 100, 7, COLOR_PROGRESS_BAR);
y += 50; y += 50;
// Status message // Status message
tft.canvas(0, y, TFT_WIDTH, FONT_LINE_HEIGHT); const uint16_t status_height = TFT_HEIGHT - y;
tft.canvas(0, y, TFT_WIDTH, status_height);
tft.set_background(COLOR_BACKGROUND); tft.set_background(COLOR_BACKGROUND);
tft_string.set(status_message); tft_string.set(status_message);
tft_string.trim(); tft_string.trim();
tft.add_text(tft_string.center(TFT_WIDTH), 0, COLOR_STATUS_MESSAGE, tft_string); tft.add_text(tft_string.center(TFT_WIDTH), (status_height - FONT_LINE_HEIGHT) / 2, COLOR_STATUS_MESSAGE, tft_string);
} }
// Low-level draw_edit_screen can be used to draw an edit screen from anyplace // Low-level draw_edit_screen can be used to draw an edit screen from anyplace

View file

@ -228,7 +228,7 @@ void MarlinUI::draw_status_screen() {
TERN_(TOUCH_SCREEN, touch.clear()); TERN_(TOUCH_SCREEN, touch.clear());
// Statuses of heaters and fans // Statuses of heaters and fans
const uint16_t y = TFT_STATUS_TOP_Y; constexpr uint16_t y = TFT_STATUS_TOP_Y;
for (uint16_t i = 0 ; i < ITEMS_COUNT; i++) { for (uint16_t i = 0 ; i < ITEMS_COUNT; i++) {
const uint16_t x = (TFT_WIDTH / ITEMS_COUNT - 64) / 2 + (TFT_WIDTH * i / ITEMS_COUNT); const uint16_t x = (TFT_WIDTH / ITEMS_COUNT - 64) / 2 + (TFT_WIDTH * i / ITEMS_COUNT);
switch (i) { switch (i) {
@ -278,14 +278,9 @@ void MarlinUI::draw_status_screen() {
tft.add_text(TERN(TFT_COLOR_UI_PORTRAIT, 32, 10), tft_string.vcenter(FONT_LINE_HEIGHT), COLOR_AXIS_HOMED, "X"); tft.add_text(TERN(TFT_COLOR_UI_PORTRAIT, 32, 10), tft_string.vcenter(FONT_LINE_HEIGHT), COLOR_AXIS_HOMED, "X");
const bool nhx = axis_should_home(X_AXIS); const bool nhx = axis_should_home(X_AXIS);
tft_string.set(blink && nhx ? "?" : ftostr4sign(LOGICAL_X_POSITION(current_position.x))); tft_string.set(blink && nhx ? "?" : ftostr4sign(LOGICAL_X_POSITION(current_position.x)));
tft.add_text( uint16_t pos_x = TERN(TFT_COLOR_UI_PORTRAIT, 32 - tft_string.width() / 2, 68 - tft_string.width()),
#if ENABLED(TFT_COLOR_UI_PORTRAIT) pos_y = SUM_TERN(TFT_COLOR_UI_PORTRAIT, tft_string.vcenter(FONT_LINE_HEIGHT), FONT_LINE_HEIGHT);
32 - tft_string.width() / 2, FONT_LINE_HEIGHT + tft_string.vcenter(FONT_LINE_HEIGHT), tft.add_text(pos_x, pos_y, nhx ? COLOR_AXIS_NOT_HOMED : COLOR_AXIS_HOMED, tft_string);
#else
68 - tft_string.width(), tft_string.vcenter(FONT_LINE_HEIGHT),
#endif
nhx ? COLOR_AXIS_NOT_HOMED : COLOR_AXIS_HOMED, tft_string
);
#endif #endif
#if HAS_Y_AXIS #if HAS_Y_AXIS
@ -318,31 +313,30 @@ void MarlinUI::draw_status_screen() {
tft_string.set(ftostr52sp(z)); tft_string.set(ftostr52sp(z));
offset -= tft_string.width(); offset -= tft_string.width();
} }
tft.add_text(
#if ENABLED(TFT_COLOR_UI_PORTRAIT)
192 - tft_string.width() / 2, FONT_LINE_HEIGHT + tft_string.vcenter(FONT_LINE_HEIGHT),
#else
301 - tft_string.width() - offset, tft_string.vcenter(FONT_LINE_HEIGHT),
#endif
nhz ? COLOR_AXIS_NOT_HOMED : COLOR_AXIS_HOMED, tft_string);
#endif #endif
TERN_(TOUCH_SCREEN, touch.add_control(MOVE_AXIS, 0, 103, uint16_t pos_x = TERN(TFT_COLOR_UI_PORTRAIT, 192 - tft_string.width() / 2, 301 - tft_string.width() - offset),
#if ENABLED(TFT_COLOR_UI_PORTRAIT) pos_y = SUM_TERN(TFT_COLOR_UI_PORTRAIT, tft_string.vcenter(FONT_LINE_HEIGHT), FONT_LINE_HEIGHT);
232, FONT_LINE_HEIGHT * 2 tft.add_text(pos_x, pos_y, nhz ? COLOR_AXIS_NOT_HOMED : COLOR_AXIS_HOMED, tft_string);
#else
312, FONT_LINE_HEIGHT // 3rd horizontal group - controls and times (height = 64, top margin = 3)
// 3rd group, subgroup A - controls (on the sides)
#if ENABLED(TOUCH_SCREEN)
width = TERN(TFT_COLOR_UI_PORTRAIT, 232, 312);
height = TERN(TFT_COLOR_UI_PORTRAIT, FONT_LINE_HEIGHT * 2, FONT_LINE_HEIGHT);
touch.add_control(MOVE_AXIS, 0, 103, width, height);
add_control(256, 130, menu_main, imgSettings);
TERN_(SDSUPPORT, add_control(0, 130, menu_media, imgSD, !printingIsActive(), COLOR_CONTROL_ENABLED, card.isMounted() && printingIsActive() ? COLOR_BUSY : COLOR_CONTROL_DISABLED));
#endif #endif
));
// 3rd group, subgroup B - speeds (center, top half)
// Feed rate // Feed rate
tft.canvas( tft.canvas(
#if ENABLED(TFT_COLOR_UI_PORTRAIT) TERN(TFT_COLOR_UI_PORTRAIT, 30, 70),
30, 172, 80 TERN(TFT_COLOR_UI_PORTRAIT, 172, 132),
#else TERN(TFT_COLOR_UI_PORTRAIT, 80, 88),
70, 136, 84 MENU_ITEM_HEIGHT
#endif
, 32
); );
tft.set_background(COLOR_BACKGROUND); tft.set_background(COLOR_BACKGROUND);
uint16_t color = feedrate_percentage == 100 ? COLOR_RATE_100 : COLOR_RATE_ALTERED; uint16_t color = feedrate_percentage == 100 ? COLOR_RATE_100 : COLOR_RATE_ALTERED;
@ -351,23 +345,17 @@ void MarlinUI::draw_status_screen() {
tft_string.add('%'); tft_string.add('%');
tft.add_text(32, tft_string.vcenter(30), color, tft_string); tft.add_text(32, tft_string.vcenter(30), color, tft_string);
TERN_(TOUCH_SCREEN, touch.add_control(FEEDRATE, TERN_(TOUCH_SCREEN, touch.add_control(FEEDRATE,
#if ENABLED(TFT_COLOR_UI_PORTRAIT) TERN(TFT_COLOR_UI_PORTRAIT, 30, 70),
30, 172, 80 TERN(TFT_COLOR_UI_PORTRAIT, 172, 132),
#else 80, MENU_ITEM_HEIGHT
70, 136, 84
#endif
, 32
)); ));
// Flow rate // Flow rate
#if HAS_EXTRUDERS
tft.canvas( tft.canvas(
#if ENABLED(TFT_COLOR_UI_PORTRAIT) TERN(TFT_COLOR_UI_PORTRAIT, 140, 162),
140, 172, 80 TERN(TFT_COLOR_UI_PORTRAIT, 172, 132),
#else TERN(TFT_COLOR_UI_PORTRAIT, 80, 88),
170, 136, 84 MENU_ITEM_HEIGHT
#endif
, 32
); );
tft.set_background(COLOR_BACKGROUND); tft.set_background(COLOR_BACKGROUND);
color = planner.flow_percentage[0] == 100 ? COLOR_RATE_100 : COLOR_RATE_ALTERED; color = planner.flow_percentage[0] == 100 ? COLOR_RATE_100 : COLOR_RATE_ALTERED;
@ -375,64 +363,116 @@ void MarlinUI::draw_status_screen() {
tft_string.set(i16tostr3rj(planner.flow_percentage[active_extruder])); tft_string.set(i16tostr3rj(planner.flow_percentage[active_extruder]));
tft_string.add('%'); tft_string.add('%');
tft.add_text(32, tft_string.vcenter(30), color, tft_string); tft.add_text(32, tft_string.vcenter(30), color, tft_string);
TERN_(TOUCH_SCREEN, touch.add_control(FLOWRATE, #if ENABLED(TOUCH_SCREEN)
#if ENABLED(TFT_COLOR_UI_PORTRAIT) touch.add_control(FLOWRATE,
140, 172, 80 TERN(TFT_COLOR_UI_PORTRAIT, 140, 170),
#else TERN(TFT_COLOR_UI_PORTRAIT, 172, 132),
170, 136, 84 80, MENU_ITEM_HEIGHT, active_extruder
);
#endif #endif
, 32, active_extruder
));
#endif // HAS_EXTRUDERS
// Print duration // 3rd group, subgroup C - times (center, bottom half)
char buffer[14]; const progress_t progress = TERN(HAS_PRINT_PROGRESS_PERMYRIAD, get_progress_permyriad, get_progress_percent)();
const uint16_t time_str_width = 180, image_width = 34;
pos_x = (TFT_WIDTH - time_str_width) / 2;
pos_y = TERN(TFT_COLOR_UI_PORTRAIT, 256, 164);
#if ENABLED(SHOW_ELAPSED_TIME) && DISABLED(SHOW_REMAINING_TIME)
// Print duration so far (time elapsed) - centered
char elapsed_str[18];
duration_t elapsed = print_job_timer.duration(); duration_t elapsed = print_job_timer.duration();
elapsed.toDigital(buffer); elapsed.toCompactString(elapsed_str);
tft.canvas( tft.canvas(pos_x, pos_y, time_str_width, MENU_ITEM_HEIGHT);
#if ENABLED(TFT_COLOR_UI_PORTRAIT)
56, 256, 128
#else
96, 173, 128
#endif
, FONT_LINE_HEIGHT
);
tft.set_background(COLOR_BACKGROUND); tft.set_background(COLOR_BACKGROUND);
tft_string.set(buffer); tft_string.set(elapsed_str);
tft.add_text(tft_string.center(128), tft_string.vcenter(FONT_LINE_HEIGHT), COLOR_PRINT_TIME, tft_string); uint16_t text_pos_x = tft_string.center(time_str_width - image_width);
tft.add_image(text_pos_x, 0, imgTimeElapsed, COLOR_PRINT_TIME);
tft.add_text(text_pos_x + image_width, tft_string.vcenter(FONT_LINE_HEIGHT), COLOR_PRINT_TIME, tft_string);
// Progress bar #elif DISABLED(SHOW_ELAPSED_TIME) && ENABLED(SHOW_REMAINING_TIME)
const uint8_t progress = ui.get_progress_percent(); // Print time remaining estimation - centered
tft.canvas( char estimate_str[18];
#if ENABLED(TFT_COLOR_UI_PORTRAIT) duration_t elapsed = print_job_timer.duration();
4, 278, 232
#else // Get the estimate, first from M73
4, 198, 312 uint32_t estimate_remaining = (0
#if ALL(SET_PROGRESS_MANUALLY, SET_REMAINING_TIME)
+ get_remaining_time()
#endif #endif
, 9
); );
// If no M73 estimate is available but we have progress data, calculate time remaining assuming time elapsed is linear with progress
if (!estimate_remaining && progress > 0)
estimate_remaining = elapsed.value * (100 * (PROGRESS_SCALE) - progress) / progress;
// Generate estimate string
if (!estimate_remaining)
tft_string.set("-");
else {
duration_t estimation = estimate_remaining;
estimation.toCompactString(estimate_str);
tft_string.set(estimate_str);
}
tft.canvas(pos_x, pos_y, time_str_width, MENU_ITEM_HEIGHT);
tft.set_background(COLOR_BACKGROUND);
color = printingIsActive() ? COLOR_PRINT_TIME : COLOR_INACTIVE;
uint16_t text_pos_x = tft_string.center(time_str_width - image_width);
tft.add_image(text_pos_x, 0, imgTimeRemaining, color);
tft.add_text(text_pos_x + image_width, tft_string.vcenter(FONT_LINE_HEIGHT), color, tft_string);
#elif ALL(SHOW_REMAINING_TIME, SHOW_ELAPSED_TIME)
// Print duration so far (time elapsed) - aligned under feed rate
char elapsed_str[18];
duration_t elapsed = print_job_timer.duration();
elapsed.toCompactString(elapsed_str);
tft.canvas(pos_x, pos_y, time_str_width / 2 - 2, MENU_ITEM_HEIGHT);
tft.set_background(COLOR_BACKGROUND);
tft.add_image(0, 0, imgTimeElapsed, COLOR_PRINT_TIME);
tft_string.set(elapsed_str);
tft.add_text(32, tft_string.vcenter(FONT_LINE_HEIGHT), COLOR_PRINT_TIME, tft_string);
// Print time remaining estimation - aligned under flow rate
char estimate_str[18];
// Get the estimate, first from M73
uint32_t estimate_remaining = (0
#if ALL(SET_PROGRESS_MANUALLY, SET_REMAINING_TIME)
+ get_remaining_time()
#endif
);
// If no M73 estimate is available but we have progress data, calculate time remaining assuming time elapsed is linear with progress
if (!estimate_remaining && progress > 0)
estimate_remaining = elapsed.value * (100 * (PROGRESS_SCALE) - progress) / progress;
// Generate estimate string
if (!estimate_remaining)
tft_string.set("-");
else {
duration_t estimation = estimate_remaining;
estimation.toCompactString(estimate_str);
tft_string.set(estimate_str);
}
// Push out the estimate to the screen
tft.canvas(pos_x + time_str_width / 2 + 2, pos_y, time_str_width / 2 - 2, MENU_ITEM_HEIGHT);
tft.set_background(COLOR_BACKGROUND);
color = printingIsActive() ? COLOR_PRINT_TIME : COLOR_INACTIVE;
tft.add_image(0, 0, imgTimeRemaining, color);
tft.add_text(32, tft_string.vcenter(FONT_LINE_HEIGHT), color, tft_string);
#endif
// Fourth horizontal group - progress bar (height = 9, top margin = 4)
pos_y = TERN(TFT_COLOR_UI_PORTRAIT, 278, 198);
tft.canvas(4, pos_y, TFT_WIDTH - 8, 9);
tft.set_background(COLOR_PROGRESS_BG); tft.set_background(COLOR_PROGRESS_BG);
tft.add_rectangle(0, 0, tft.add_rectangle(0, 0, TFT_WIDTH - 8, 9, COLOR_PROGRESS_FRAME);
#if ENABLED(TFT_COLOR_UI_PORTRAIT)
232, 9
#else
312, 9
#endif
, COLOR_PROGRESS_FRAME
);
if (progress) if (progress)
tft.add_bar(1, 1, ((TFT_WIDTH - 10) * progress) / 100, 7, COLOR_PROGRESS_BAR); tft.add_bar(1, 1, ((TFT_WIDTH - 10) * progress / (PROGRESS_SCALE)) / 100, 7, COLOR_PROGRESS_BAR);
// Status message // Status message
tft.canvas( pos_y += 9 + 7;
#if ENABLED(TFT_COLOR_UI_PORTRAIT) tft.canvas(0, pos_y, TFT_WIDTH, TFT_HEIGHT - pos_y);
0, 296, 240
#else
0, 212, 320
#endif
, FONT_LINE_HEIGHT
);
tft.set_background(COLOR_BACKGROUND); tft.set_background(COLOR_BACKGROUND);
tft_string.set(status_message); tft_string.set(status_message);
tft_string.trim(); tft_string.trim();
@ -441,12 +481,9 @@ void MarlinUI::draw_status_screen() {
#if ENABLED(TOUCH_SCREEN) #if ENABLED(TOUCH_SCREEN)
{ {
add_control( add_control(
#if ENABLED(TFT_COLOR_UI_PORTRAIT) TERN(TFT_COLOR_UI_PORTRAIT, 176, 256),
176, 210 TERN(TFT_COLOR_UI_PORTRAIT, 210, 130),
#else menu_main, imgSettings
256, 130
#endif
, menu_main, imgSettings
); );
#if HAS_MEDIA #if HAS_MEDIA
const bool cm = card.isMounted(), pa = printingIsActive(); const bool cm = card.isMounted(), pa = printingIsActive();
@ -552,8 +589,8 @@ void MenuItem_confirm::draw_select_screen(FSTR_P const yes, FSTR_P const no, con
tft.add_text(tft_string.center(TFT_WIDTH), MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string); tft.add_text(tft_string.center(TFT_WIDTH), MENU_TEXT_Y_OFFSET, COLOR_MENU_TEXT, tft_string);
} }
#if ENABLED(TOUCH_SCREEN) #if ENABLED(TOUCH_SCREEN)
if (no) add_control(TERN(TFT_COLOR_UI_PORTRAIT, 16, 48), TFT_HEIGHT - 64, CANCEL, imgCancel, true, yesno ? HALF(COLOR_CONTROL_CANCEL) : COLOR_CONTROL_CANCEL); if (no) add_control(TERN(TFT_COLOR_UI_PORTRAIT, 32,48), TFT_HEIGHT - 64, CANCEL, imgCancel, true, yesno ? HALF(COLOR_CONTROL_CANCEL) : COLOR_CONTROL_CANCEL);
if (yes) add_control(TERN(TFT_COLOR_UI_PORTRAIT, 160, 208), TFT_HEIGHT - 64, CONFIRM, imgConfirm, true, yesno ? COLOR_CONTROL_CONFIRM : HALF(COLOR_CONTROL_CONFIRM)); if (yes) add_control(TERN(TFT_COLOR_UI_PORTRAIT, 172, 208), TFT_HEIGHT - 64, CONFIRM, imgConfirm, true, yesno ? COLOR_CONTROL_CONFIRM : HALF(COLOR_CONTROL_CONFIRM));
#endif #endif
} }

View file

@ -37,6 +37,7 @@
#define MENU_ITEM_HEIGHT 32 #define MENU_ITEM_HEIGHT 32
#define MENU_LINE_HEIGHT (MENU_ITEM_HEIGHT + 2) #define MENU_LINE_HEIGHT (MENU_ITEM_HEIGHT + 2)
#define FONT_LINE_HEIGHT 24
#if (TFT_FONT == NOTOSANS) || (TFT_FONT == HELVETICA) #if (TFT_FONT == NOTOSANS) || (TFT_FONT == HELVETICA)
#define FONT_SIZE 14 #define FONT_SIZE 14

View file

@ -340,50 +340,116 @@ void MarlinUI::draw_status_screen() {
TERN_(TOUCH_SCREEN, touch.add_control(FLOWRATE, x, y, component_width, 32, active_extruder)); TERN_(TOUCH_SCREEN, touch.add_control(FLOWRATE, x, y, component_width, 32, active_extruder));
#endif #endif
#if TFT_COLOR_UI_PORTRAIT || DISABLED(TOUCH_SCREEN) y += TERN(HAS_UI_480x272, 36, 44);
y += STATUS_MARGIN_SIZE + 32;
#endif
#if ENABLED(TOUCH_SCREEN) const progress_t progress = TERN(HAS_PRINT_PROGRESS_PERMYRIAD, get_progress_permyriad, get_progress_percent)();
// Settings button #if ENABLED(SHOW_ELAPSED_TIME) && DISABLED(SHOW_REMAINING_TIME)
add_control(SETTINGS_X, y, menu_main, imgSettings); // Print duration so far (time elapsed) - centered
char elapsed_str[22];
// SD-card button / Cancel button
#if HAS_MEDIA
const bool cm = card.isMounted(), pa = printingIsActive();
if (cm && pa)
add_control(SDCARD_X, y, STOP, imgCancel, true, COLOR_CONTROL_CANCEL);
else
add_control(SDCARD_X, y, menu_media, imgSD, cm && !pa, COLOR_CONTROL_ENABLED, COLOR_CONTROL_DISABLED); // 64px icon size
#endif
y += STATUS_MARGIN_SIZE + TERN(TFT_COLOR_UI_PORTRAIT, 64, 44);
#endif
// Print duration
char buffer[14];
duration_t elapsed = print_job_timer.duration(); duration_t elapsed = print_job_timer.duration();
elapsed.toDigital(buffer); elapsed.toString(elapsed_str);
tft.canvas((TFT_WIDTH - 128) / 2, y, 128, 29); // Same width constraints as feedrate/flowrate controls
constexpr uint16_t time_str_width = 288, image_width = 36;
tft.canvas((TFT_WIDTH - time_str_width) / 2, y, time_str_width, 32);
tft.set_background(COLOR_BACKGROUND); tft.set_background(COLOR_BACKGROUND);
tft_string.set(buffer); tft_string.set(elapsed_str);
tft.add_text(tft_string.center(128), tft_string.vcenter(29), COLOR_PRINT_TIME, tft_string); uint16_t text_pos_x = tft_string.center(time_str_width - image_width);
tft.add_image(text_pos_x, 0, imgTimeElapsed, COLOR_PRINT_TIME);
tft.add_text(text_pos_x + image_width, tft_string.vcenter(29), COLOR_PRINT_TIME, tft_string);
y += STATUS_MARGIN_SIZE + 29; #elif DISABLED(SHOW_ELAPSED_TIME) && ENABLED(SHOW_REMAINING_TIME)
// Print time remaining estimation - centered
char estimate_str[22];
duration_t elapsed = print_job_timer.duration();
// Get the estimate, first from M73
uint32_t estimate_remaining = (0
#if ALL(SET_PROGRESS_MANUALLY, SET_REMAINING_TIME)
+ get_remaining_time()
#endif
);
// If no M73 estimate is available but we have progress data, calculate time remaining assuming time elapsed is linear with progress
if (!estimate_remaining && progress > 0)
estimate_remaining = elapsed.value * (100 * (PROGRESS_SCALE) - progress) / progress;
// Generate estimate string
if (!estimate_remaining)
tft_string.set("-");
else {
duration_t estimation = estimate_remaining;
estimation.toString(estimate_str);
tft_string.set(estimate_str);
}
// Same width constraints as feedrate/flowrate controls
constexpr uint16_t time_str_width = 288, image_width = 36;
tft.canvas((TFT_WIDTH - time_str_width) / 2, y, time_str_width, 32);
tft.set_background(COLOR_BACKGROUND);
color = printingIsActive() ? COLOR_PRINT_TIME : COLOR_INACTIVE;
uint16_t text_pos_x = tft_string.center(time_str_width - image_width);
tft.add_image(text_pos_x, 0, imgTimeRemaining, color);
tft.add_text(text_pos_x + image_width, tft_string.vcenter(29), color, tft_string);
#elif ALL(SHOW_REMAINING_TIME, SHOW_ELAPSED_TIME)
// Print duration so far (time elapsed) - aligned under feed rate
char elapsed_str[18];
duration_t elapsed = print_job_timer.duration();
elapsed.toCompactString(elapsed_str);
tft.canvas(96, y, 144, 32);
tft.set_background(COLOR_BACKGROUND);
tft.add_image(0, 0, imgTimeElapsed, COLOR_PRINT_TIME);
tft_string.set(elapsed_str);
tft.add_text(36, tft_string.vcenter(29), COLOR_PRINT_TIME, tft_string);
// Print time remaining estimation - aligned under flow rate
char estimate_str[18];
// Get the estimate, first from M73
uint32_t estimate_remaining = (0
#if ALL(SET_PROGRESS_MANUALLY, SET_REMAINING_TIME)
+ get_remaining_time()
#endif
);
// If no M73 estimate is available but we have progress data, calculate time remaining assuming time elapsed is linear with progress
if (!estimate_remaining && progress > 0)
estimate_remaining = elapsed.value * (100 * (PROGRESS_SCALE) - progress) / progress;
// Generate estimate string
if (!estimate_remaining)
tft_string.set("-");
else {
duration_t estimation = estimate_remaining;
estimation.toCompactString(estimate_str);
tft_string.set(estimate_str);
}
// Push out the estimate to the screen
tft.canvas(256, y, 144, 32);
tft.set_background(COLOR_BACKGROUND);
color = printingIsActive() ? COLOR_PRINT_TIME : COLOR_INACTIVE;
tft.add_image(0, 0, imgTimeRemaining, color);
tft.add_text(36, tft_string.vcenter(29), color, tft_string);
#endif
y += TERN(HAS_UI_480x272, 36, 44);
// Progress bar // Progress bar
const uint8_t progress = ui.get_progress_percent(); // TODO: print percentage text for SHOW_PROGRESS_PERCENT
tft.canvas(4, y, TFT_WIDTH - 8, 9); tft.canvas(4, y, TFT_WIDTH - 8, 9);
tft.set_background(COLOR_PROGRESS_BG); tft.set_background(COLOR_PROGRESS_BG);
tft.add_rectangle(0, 0, TFT_WIDTH - 8, 9, COLOR_PROGRESS_FRAME); tft.add_rectangle(0, 0, TFT_WIDTH - 8, 9, COLOR_PROGRESS_FRAME);
if (progress) if (progress)
tft.add_bar(1, 1, ((TFT_WIDTH - 10) * progress) / 100, 7, COLOR_PROGRESS_BAR); tft.add_bar(1, 1, ((TFT_WIDTH - 10) * progress / (PROGRESS_SCALE)) / 100, 7, COLOR_PROGRESS_BAR);
y += STATUS_MARGIN_SIZE + 7;
y += 12;
// Status message // Status message
tft.canvas(0, y, TFT_WIDTH, FONT_LINE_HEIGHT); // Canvas height should be 40px on 480x320 and 28 on 480x272
const uint16_t status_height = TFT_HEIGHT - y;
tft.canvas(0, y, TFT_WIDTH, status_height);
tft.set_background(COLOR_BACKGROUND); tft.set_background(COLOR_BACKGROUND);
tft_string.set(status_message); tft_string.set(status_message);
tft_string.trim(); tft_string.trim();
@ -878,9 +944,8 @@ static void drawBtn(const int x, const int y, const char *label, intptr_t data,
tft_string.trim(); tft_string.trim();
tft.add_text(tft_string.center(width), height / 2 - tft_string.font_height() / 2, bgColor, tft_string); tft.add_text(tft_string.center(width), height / 2 - tft_string.font_height() / 2, bgColor, tft_string);
} }
else { else
tft.add_image(0, 0, img, bgColor, COLOR_BACKGROUND, COLOR_DARKGREY); tft.add_image(0, 0, img, bgColor, COLOR_BACKGROUND, COLOR_DARKGREY);
}
TERN_(TOUCH_SCREEN, if (enabled) touch.add_control(BUTTON, x, y, width, height, data)); TERN_(TOUCH_SCREEN, if (enabled) touch.add_control(BUTTON, x, y, width, height, data));
} }

View file

@ -117,6 +117,7 @@ struct duration_t {
* *
* @param buffer The array pointed to must be able to accommodate 22 bytes * @param buffer The array pointed to must be able to accommodate 22 bytes
* (21 for the string, 1 more for the terminating nul) * (21 for the string, 1 more for the terminating nul)
* @param dense Whether to skip spaces in the resulting string
* *
* Output examples: * Output examples:
* 123456789012345678901 (strlen) * 123456789012345678901 (strlen)
@ -141,11 +142,43 @@ struct duration_t {
return buffer; return buffer;
} }
/**
* @brief Format the duration as a compact string
* @details String will be formatted using a "full" representation of duration
*
* @param buffer The array pointed to must be able to accommodate 18 bytes
* (17 for the string, 1 more for the terminating nul)
* @param dense Whether to skip spaces in the resulting string
*
* Output examples:
* 12345678901234567 (strlen)
* 135y364d23h59m59s
* 364d23h59m59s
* 23h59m59s
* 59m59s
* 59s
*/
char* toCompactString(char * const buffer) const {
const uint16_t y = this->year(),
d = this->day() % 365,
h = this->hour() % 24,
m = this->minute() % 60,
s = this->second() % 60;
if (y) sprintf_P(buffer, PSTR("%iy%id%ih%im%is"), y, d, h, m, s);
else if (d) sprintf_P(buffer, PSTR("%id%ih%im%is"), d, h, m, s);
else if (h) sprintf_P(buffer, PSTR("%ih%im%is"), h, m, s);
else if (m) sprintf_P(buffer, PSTR("%im%is"), m, s);
else sprintf_P(buffer, PSTR("%is"), s);
return buffer;
}
/** /**
* @brief Format the duration as a string * @brief Format the duration as a string
* @details String will be formatted using a "digital" representation of duration * @details String will be formatted using a "digital" representation of duration
* *
* @param buffer The array pointed to must be able to accommodate 10 bytes * @param buffer The array pointed to must be able to accommodate 10 bytes
* @return length of the formatted string (without terminating nul)
* *
* Output examples: * Output examples:
* 123456789 (strlen) * 123456789 (strlen)