📺 Assorted small FTDI Eve Touch UI fixes (#22273)
This commit is contained in:
		@@ -32,9 +32,7 @@
 | 
			
		||||
class MediaFileReader {
 | 
			
		||||
  private:
 | 
			
		||||
    #if ENABLED(SDSUPPORT)
 | 
			
		||||
      DiskIODriver_SPI_SD card;
 | 
			
		||||
      SdVolume volume;
 | 
			
		||||
      SdFile   root, file;
 | 
			
		||||
      SdFile root, file;
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
 
 | 
			
		||||
@@ -118,7 +118,6 @@ enum {
 | 
			
		||||
#include "../generic/files_screen.h"
 | 
			
		||||
#include "../generic/move_axis_screen.h"
 | 
			
		||||
#include "../generic/flow_percent_screen.h"
 | 
			
		||||
#include "../generic/tune_menu.h"
 | 
			
		||||
#if HAS_JUNCTION_DEVIATION
 | 
			
		||||
  #include "../generic/junction_deviation_screen.h"
 | 
			
		||||
#else
 | 
			
		||||
 
 | 
			
		||||
@@ -294,4 +294,14 @@ void StatusScreen::onIdle() {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StatusScreen::onMediaInserted() {
 | 
			
		||||
  if (AT_SCREEN(StatusScreen))
 | 
			
		||||
    setStatusMessage(GET_TEXT_F(MSG_MEDIA_INSERTED));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void StatusScreen::onMediaRemoved() {
 | 
			
		||||
  if (AT_SCREEN(StatusScreen) || ExtUI::isPrintingFromMedia())
 | 
			
		||||
    setStatusMessage(GET_TEXT_F(MSG_MEDIA_REMOVED));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // COCOA_STATUS_SCREEN
 | 
			
		||||
 
 | 
			
		||||
@@ -52,4 +52,6 @@ class StatusScreen : public BaseScreen, public CachedScreen<STATUS_SCREEN_CACHE>
 | 
			
		||||
    static bool onTouchHeld(uint8_t tag);
 | 
			
		||||
    static bool onTouchEnd(uint8_t tag);
 | 
			
		||||
    static void onIdle();
 | 
			
		||||
    static void onMediaInserted();
 | 
			
		||||
    static void onMediaRemoved();
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -239,9 +239,11 @@ class DeduplicatedPolyReader : public POLY_READER {
 | 
			
		||||
 */
 | 
			
		||||
template<class POLY_READER=DeduplicatedPolyReader<TransformedPolyReader>>
 | 
			
		||||
class GenericPolyUI {
 | 
			
		||||
  private:
 | 
			
		||||
  protected:
 | 
			
		||||
    CommandProcessor &cmd;
 | 
			
		||||
    draw_mode_t mode;
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    // Attributes used to paint buttons
 | 
			
		||||
 | 
			
		||||
    uint32_t btn_fill_color   = 0x000000;
 | 
			
		||||
@@ -250,8 +252,6 @@ class GenericPolyUI {
 | 
			
		||||
    uint32_t btn_stroke_color = 0x000000;
 | 
			
		||||
    uint8_t  btn_stroke_width = 28;
 | 
			
		||||
 | 
			
		||||
    draw_mode_t mode;
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    enum ButtonStyle : uint8_t {
 | 
			
		||||
      FILL    = 1,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										47
									
								
								Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/scripts/file2cpp.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										47
									
								
								Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/scripts/file2cpp.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
# Written By Marcio Teixeira 2021 - SynDaver Labs, Inc.
 | 
			
		||||
#
 | 
			
		||||
# 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.
 | 
			
		||||
#
 | 
			
		||||
# To view a copy of the GNU General Public License, go to the following
 | 
			
		||||
# location: <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
from __future__ import print_function
 | 
			
		||||
import argparse
 | 
			
		||||
import textwrap
 | 
			
		||||
import os
 | 
			
		||||
import zlib
 | 
			
		||||
 | 
			
		||||
def deflate(data):
 | 
			
		||||
  return zlib.compress(data)
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
  parser = argparse.ArgumentParser(description='Converts a file into a packed C array for use as data')
 | 
			
		||||
  parser.add_argument("input")
 | 
			
		||||
  parser.add_argument("-d", "--deflate", action="store_true", help="Packs the data using the deflate algorithm")
 | 
			
		||||
  args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
  varname = os.path.splitext(os.path.basename(args.input))[0];
 | 
			
		||||
  
 | 
			
		||||
  with open(args.input, "rb") as in_file:
 | 
			
		||||
    data = in_file.read()
 | 
			
		||||
  if args.deflate:
 | 
			
		||||
    data = deflate(data)
 | 
			
		||||
  data = bytearray(data)
 | 
			
		||||
  data = list(map(lambda a: "0x" + format(a, '02x'), data))
 | 
			
		||||
  nElements = len(data)
 | 
			
		||||
  data = ', '.join(data)
 | 
			
		||||
  data = textwrap.fill(data, 75, initial_indent = '  ', subsequent_indent = '  ')
 | 
			
		||||
 | 
			
		||||
  print("const unsigned char " + varname + "[" + format(nElements) + "] PROGMEM = {")
 | 
			
		||||
  print(data)
 | 
			
		||||
  print("};")
 | 
			
		||||
							
								
								
									
										108
									
								
								Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/scripts/font2cpp.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										108
									
								
								Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/scripts/font2cpp.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,108 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
# Written By Marcio Teixeira 2019 - Aleph Objects, Inc.
 | 
			
		||||
#
 | 
			
		||||
# 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.
 | 
			
		||||
#
 | 
			
		||||
# To view a copy of the GNU General Public License, go to the following
 | 
			
		||||
# location: <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
from __future__ import print_function
 | 
			
		||||
from PIL import Image
 | 
			
		||||
import argparse
 | 
			
		||||
import textwrap
 | 
			
		||||
 | 
			
		||||
def pack_rle(data):
 | 
			
		||||
  """Use run-length encoding to pack the bytes"""
 | 
			
		||||
  rle = []
 | 
			
		||||
  value = data[0]
 | 
			
		||||
  count = 0
 | 
			
		||||
  for i in data:
 | 
			
		||||
    if i != value or count == 255:
 | 
			
		||||
      rle.append(count)
 | 
			
		||||
      rle.append(value)
 | 
			
		||||
      value = i
 | 
			
		||||
      count = 1
 | 
			
		||||
    else:
 | 
			
		||||
      count += 1
 | 
			
		||||
  rle.append(count)
 | 
			
		||||
  rle.append(value)
 | 
			
		||||
  return rle
 | 
			
		||||
 | 
			
		||||
class WriteSource:
 | 
			
		||||
  def __init__(self, lines_in_blocks):
 | 
			
		||||
    self.blocks      = []
 | 
			
		||||
    self.values      = []
 | 
			
		||||
    self.block_size  = lines_in_blocks
 | 
			
		||||
    self.rows        = 0
 | 
			
		||||
 | 
			
		||||
  def add_pixel(self, value):
 | 
			
		||||
    self.values.append(value)
 | 
			
		||||
 | 
			
		||||
  def convert_to_4bpp(self, data, chunk_size = 0):
 | 
			
		||||
    # Invert the image
 | 
			
		||||
    data = list(map(lambda i: 255 - i, data))
 | 
			
		||||
    # Quanitize 8-bit values into 4-bits
 | 
			
		||||
    data = list(map(lambda i: i >> 4, data))
 | 
			
		||||
    # Make sure there is an even number of elements
 | 
			
		||||
    if (len(data) & 1) == 1:
 | 
			
		||||
      data.append(0)
 | 
			
		||||
    # Combine each two adjacent values into one
 | 
			
		||||
    i = iter(data)
 | 
			
		||||
    data = list(map(lambda a, b: a << 4 | b, i ,i))
 | 
			
		||||
    # Pack the data
 | 
			
		||||
    data = pack_rle(data)
 | 
			
		||||
    # Convert values into hex strings
 | 
			
		||||
    return list(map(lambda a: "0x" + format(a, '02x'), data))
 | 
			
		||||
 | 
			
		||||
  def end_row(self, y):
 | 
			
		||||
    # Pad each row into even number of values
 | 
			
		||||
    if len(self.values) & 1:
 | 
			
		||||
      self.values.append(0)
 | 
			
		||||
 | 
			
		||||
    self.rows += 1
 | 
			
		||||
    if self.block_size and (self.rows % self.block_size) == 0:
 | 
			
		||||
      self.blocks.append(self.values)
 | 
			
		||||
      self.values = []
 | 
			
		||||
 | 
			
		||||
  def write(self):
 | 
			
		||||
    if len(self.values):
 | 
			
		||||
      self.blocks.append(self.values)
 | 
			
		||||
 | 
			
		||||
    block_strs = [];
 | 
			
		||||
    for b in self.blocks:
 | 
			
		||||
      data = self.convert_to_4bpp(b)
 | 
			
		||||
      data = ', '.join(data)
 | 
			
		||||
      data = textwrap.fill(data, 75, initial_indent = '  ', subsequent_indent = '  ')
 | 
			
		||||
      block_strs.append(data)
 | 
			
		||||
 | 
			
		||||
    print("const unsigned char font[] PROGMEM = {")
 | 
			
		||||
    for i, b in enumerate(block_strs):
 | 
			
		||||
      if i:
 | 
			
		||||
        print(',')
 | 
			
		||||
      print('\n  /* {} */'.format(i))
 | 
			
		||||
      print(b, end='')
 | 
			
		||||
    print("\n};")
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
  parser = argparse.ArgumentParser(description='Converts a grayscale bitmap into a 16-level RLE packed C array for use as font data')
 | 
			
		||||
  parser.add_argument("input")
 | 
			
		||||
  parser.add_argument('--char_height', help='Adds a separator every so many lines', type=int)
 | 
			
		||||
  args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
  writer = WriteSource(args.char_height)
 | 
			
		||||
 | 
			
		||||
  img = Image.open(args.input).convert('L')
 | 
			
		||||
  for y in range(img.height):
 | 
			
		||||
    for x in range(img.width):
 | 
			
		||||
      writer.add_pixel(img.getpixel((x,y)))
 | 
			
		||||
    writer.end_row(y)
 | 
			
		||||
  writer.write()
 | 
			
		||||
							
								
								
									
										113
									
								
								Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/scripts/img2cpp.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										113
									
								
								Marlin/src/lcd/extui/ftdi_eve_touch_ui/ftdi_eve_lib/scripts/img2cpp.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,113 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
# Written By Marcio Teixeira 2021 - SynDaver Labs, Inc.
 | 
			
		||||
#
 | 
			
		||||
# 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.
 | 
			
		||||
#
 | 
			
		||||
# To view a copy of the GNU General Public License, go to the following
 | 
			
		||||
# location: <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
from __future__ import print_function
 | 
			
		||||
from PIL import Image
 | 
			
		||||
import argparse
 | 
			
		||||
import textwrap
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
import zlib
 | 
			
		||||
 | 
			
		||||
class WriteSource:
 | 
			
		||||
  def __init__(self, mode):
 | 
			
		||||
    self.values      = []
 | 
			
		||||
    self.mode        = mode
 | 
			
		||||
    self.offset      = 8
 | 
			
		||||
    self.byte        = 0
 | 
			
		||||
    
 | 
			
		||||
  def finish_byte(self):
 | 
			
		||||
    if self.offset != 8:
 | 
			
		||||
      self.values.append(self.byte)
 | 
			
		||||
      self.offset = 8
 | 
			
		||||
      self.byte   = 0
 | 
			
		||||
      
 | 
			
		||||
  def add_bits_to_byte(self, value, size = 1):
 | 
			
		||||
    self.offset -= size
 | 
			
		||||
    self.byte = self.byte | value << self.offset
 | 
			
		||||
    if self.offset == 0:
 | 
			
		||||
      self.finish_byte()
 | 
			
		||||
 | 
			
		||||
  def append_rgb565(self, color):
 | 
			
		||||
    value = ((color[0] & 0xF8) << 8) + ((color[1] & 0xFC) << 3) + ((color[2] & 0xF8) >> 3)
 | 
			
		||||
    self.values.append((value & 0x00FF) >> 0);
 | 
			
		||||
    self.values.append((value & 0xFF00) >> 8);
 | 
			
		||||
 | 
			
		||||
  def append_rgb332(self, color):
 | 
			
		||||
    value = (color[0] & 0xE0) + ((color[1] & 0xE0) >> 3) + ((color[2] & 0xC0) >> 6)
 | 
			
		||||
    self.values.append(value);
 | 
			
		||||
 | 
			
		||||
  def append_grayscale(self, color, bits):
 | 
			
		||||
    luminance = int(0.2126 * color[0] + 0.7152 * color[1] + 0.0722 * color[2])
 | 
			
		||||
    self.add_bits_to_byte(luminance >> (8 - bits), bits)
 | 
			
		||||
 | 
			
		||||
  def deflate(self, data):
 | 
			
		||||
     return zlib.compress(data)
 | 
			
		||||
 | 
			
		||||
  def add_pixel(self, color):
 | 
			
		||||
    if self.mode == "l1":
 | 
			
		||||
      self.append_grayscale(color, 1)
 | 
			
		||||
    elif self.mode == "l2":
 | 
			
		||||
      self.append_grayscale(color, 2)
 | 
			
		||||
    elif self.mode == "l4":
 | 
			
		||||
      self.append_grayscale(color, 4)
 | 
			
		||||
    elif self.mode == "l8":
 | 
			
		||||
      self.append_grayscale(color, 8)
 | 
			
		||||
    elif self.mode == "rgb565":
 | 
			
		||||
      self.append_rgb565(color)
 | 
			
		||||
    elif self.mode == "rgb332":
 | 
			
		||||
      self.append_rgb332(color)
 | 
			
		||||
 | 
			
		||||
  def end_row(self, y):
 | 
			
		||||
    if self.mode in ["l1", "l2", "l3"]:
 | 
			
		||||
       self.finish_byte()
 | 
			
		||||
 | 
			
		||||
  def write(self, varname, deflate):
 | 
			
		||||
    print("Length of uncompressed data: ", len(self.values), file=sys.stderr)
 | 
			
		||||
    data = bytes(bytearray(self.values))
 | 
			
		||||
    if deflate:
 | 
			
		||||
      data = self.deflate(data)
 | 
			
		||||
      print("Length of data after compression: ", len(data), file=sys.stderr)
 | 
			
		||||
    data = bytearray(data)
 | 
			
		||||
    data = list(map(lambda a: "0x" + format(a, '02x'), data))
 | 
			
		||||
    nElements = len(data)
 | 
			
		||||
    data = ', '.join(data)
 | 
			
		||||
    data = textwrap.fill(data, 75, initial_indent = '  ', subsequent_indent = '  ')
 | 
			
		||||
 | 
			
		||||
    print("const unsigned char " + varname + "[" + format(nElements) + "] PROGMEM = {")
 | 
			
		||||
    print(data)
 | 
			
		||||
    print("};")
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
  parser = argparse.ArgumentParser(description='Converts a bitmap into a C array')
 | 
			
		||||
  parser.add_argument("input")
 | 
			
		||||
  parser.add_argument("-d", "--deflate", action="store_true", help="Packs the data using the deflate algorithm")
 | 
			
		||||
  parser.add_argument("-m", "--mode", default="l1", help="Mode, can be l1, l2, l4, l8, rgb332 or rgb565")
 | 
			
		||||
  args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
  varname = os.path.splitext(os.path.basename(args.input))[0];
 | 
			
		||||
 | 
			
		||||
  writer = WriteSource(args.mode)
 | 
			
		||||
 | 
			
		||||
  img = Image.open(args.input)
 | 
			
		||||
  print("Image height: ", img.height, file=sys.stderr)
 | 
			
		||||
  print("Image width:  ", img.width,  file=sys.stderr)
 | 
			
		||||
  for y in range(img.height):
 | 
			
		||||
    for x in range(img.width):
 | 
			
		||||
      writer.add_pixel(img.getpixel((x,y)))
 | 
			
		||||
    writer.end_row(y)
 | 
			
		||||
  writer.write(varname, args.deflate)
 | 
			
		||||
@@ -190,17 +190,11 @@ bool BedMeshEditScreen::onTouchEnd(uint8_t tag) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BedMeshEditScreen::show() {
 | 
			
		||||
  // On entry, home if needed and save current mesh
 | 
			
		||||
  if (!ExtUI::isMachineHomed()) {
 | 
			
		||||
    SpinnerDialogBox::enqueueAndWait_P(F("G28\nG29 S1"));
 | 
			
		||||
    // After the spinner, go to this screen.
 | 
			
		||||
    current_screen.forget();
 | 
			
		||||
    PUSH_SCREEN(BedMeshEditScreen);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    injectCommands_P(PSTR("G29 S1"));
 | 
			
		||||
    GOTO_SCREEN(BedMeshEditScreen);
 | 
			
		||||
  }
 | 
			
		||||
  // On entry, always home (to account for possible Z offset changes) and save current mesh
 | 
			
		||||
  SpinnerDialogBox::enqueueAndWait_P(F("G28\nG29 S1"));
 | 
			
		||||
  // After the spinner, go to this screen.
 | 
			
		||||
  current_screen.forget();
 | 
			
		||||
  PUSH_SCREEN(BedMeshEditScreen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // FTDI_BED_MESH_EDIT_SCREEN
 | 
			
		||||
 
 | 
			
		||||
@@ -132,7 +132,6 @@ void BedMeshViewScreen::onMeshUpdate(const int8_t x, const int8_t y, const ExtUI
 | 
			
		||||
      mydata.count = GRID_MAX_POINTS;
 | 
			
		||||
      break;
 | 
			
		||||
    case ExtUI::G26_START:
 | 
			
		||||
      GOTO_SCREEN(BedMeshViewScreen);
 | 
			
		||||
      mydata.message = nullptr;
 | 
			
		||||
      mydata.count = 0;
 | 
			
		||||
      break;
 | 
			
		||||
@@ -161,7 +160,7 @@ void BedMeshViewScreen::doProbe() {
 | 
			
		||||
void BedMeshViewScreen::doMeshValidation() {
 | 
			
		||||
  mydata.count = 0;
 | 
			
		||||
  GOTO_SCREEN(StatusScreen);
 | 
			
		||||
  injectCommands_P(PSTR("M75\nG28 O\nM117 Heating...\nG26 R X0 Y0\nG27\nM77"));
 | 
			
		||||
  injectCommands_P(PSTR("G28\nM117 Heating...\nG26 R X0 Y0\nG27"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void BedMeshViewScreen::show() {
 | 
			
		||||
 
 | 
			
		||||
@@ -83,8 +83,10 @@ void BootScreen::onIdle() {
 | 
			
		||||
      if (UIData::animations_enabled()) {
 | 
			
		||||
        // If there is a startup video in the flash SPI, play
 | 
			
		||||
        // that, otherwise show a static splash screen.
 | 
			
		||||
        if (!MediaPlayerScreen::playBootMedia())
 | 
			
		||||
          showSplashScreen();
 | 
			
		||||
        #ifdef FTDI_MEDIA_PLAYER_SCREEN
 | 
			
		||||
          if (!MediaPlayerScreen::playBootMedia())
 | 
			
		||||
        #endif
 | 
			
		||||
            showSplashScreen();
 | 
			
		||||
      }
 | 
			
		||||
    #endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -35,12 +35,15 @@ void ConfirmUserRequestAlertBox::onRedraw(draw_mode_t mode) {
 | 
			
		||||
bool ConfirmUserRequestAlertBox::onTouchEnd(uint8_t tag) {
 | 
			
		||||
  switch (tag) {
 | 
			
		||||
    case 1:
 | 
			
		||||
      if (ExtUI::isPrintingPaused()) {
 | 
			
		||||
        // The TuneMenu will call ExtUI::setUserConfirmed()
 | 
			
		||||
        GOTO_SCREEN(TuneMenu);
 | 
			
		||||
        current_screen.forget();
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
      #ifdef FTDI_TUNE_MENU
 | 
			
		||||
        if (ExtUI::isPrintingPaused()) {
 | 
			
		||||
          // The TuneMenu will call ExtUI::setUserConfirmed()
 | 
			
		||||
          GOTO_SCREEN(TuneMenu);
 | 
			
		||||
          current_screen.forget();
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
      #endif
 | 
			
		||||
      {
 | 
			
		||||
        ExtUI::setUserConfirmed();
 | 
			
		||||
        GOTO_PREVIOUS();
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -83,6 +83,7 @@ void LevelingMenu::onRedraw(draw_mode_t what) {
 | 
			
		||||
       .font(font_medium).colors(normal_btn)
 | 
			
		||||
       .enabled(EITHER(Z_STEPPER_AUTO_ALIGN,MECHANICAL_GANTRY_CALIBRATION))
 | 
			
		||||
       .tag(2).button(LEVEL_AXIS_POS, GET_TEXT_F(MSG_LEVEL_X_AXIS))
 | 
			
		||||
       .enabled(ENABLED(HAS_BED_PROBE))
 | 
			
		||||
       .tag(3).button(PROBE_BED_POS, GET_TEXT_F(MSG_PROBE_BED))
 | 
			
		||||
       .enabled(ENABLED(HAS_MESH))
 | 
			
		||||
       .tag(4).button(SHOW_MESH_POS, GET_TEXT_F(MSG_SHOW_MESH))
 | 
			
		||||
@@ -101,30 +102,32 @@ void LevelingMenu::onRedraw(draw_mode_t what) {
 | 
			
		||||
 | 
			
		||||
bool LevelingMenu::onTouchEnd(uint8_t tag) {
 | 
			
		||||
  switch (tag) {
 | 
			
		||||
    case 1: GOTO_PREVIOUS();                   break;
 | 
			
		||||
    case 1: GOTO_PREVIOUS(); break;
 | 
			
		||||
    #if EITHER(Z_STEPPER_AUTO_ALIGN,MECHANICAL_GANTRY_CALIBRATION)
 | 
			
		||||
    case 2: SpinnerDialogBox::enqueueAndWait_P(F("G34")); break;
 | 
			
		||||
      case 2: SpinnerDialogBox::enqueueAndWait_P(F("G34")); break;
 | 
			
		||||
    #endif
 | 
			
		||||
    case 3:
 | 
			
		||||
    #ifndef BED_LEVELING_COMMANDS
 | 
			
		||||
      #define BED_LEVELING_COMMANDS "G29"
 | 
			
		||||
    #if ENABLED(HAS_BED_PROBE)
 | 
			
		||||
      case 3:
 | 
			
		||||
        #ifndef BED_LEVELING_COMMANDS
 | 
			
		||||
          #define BED_LEVELING_COMMANDS "G29"
 | 
			
		||||
        #endif
 | 
			
		||||
        #if ENABLED(AUTO_BED_LEVELING_UBL)
 | 
			
		||||
          BedMeshViewScreen::doProbe();
 | 
			
		||||
        #else
 | 
			
		||||
          SpinnerDialogBox::enqueueAndWait_P(F(BED_LEVELING_COMMANDS));
 | 
			
		||||
        #endif
 | 
			
		||||
        break;
 | 
			
		||||
    #endif
 | 
			
		||||
    #if ENABLED(AUTO_BED_LEVELING_UBL)
 | 
			
		||||
      BedMeshViewScreen::doProbe();
 | 
			
		||||
    #else
 | 
			
		||||
      SpinnerDialogBox::enqueueAndWait_P(F(BED_LEVELING_COMMANDS));
 | 
			
		||||
    #endif
 | 
			
		||||
    break;
 | 
			
		||||
    #if ENABLED(AUTO_BED_LEVELING_UBL)
 | 
			
		||||
    case 4: BedMeshViewScreen::show(); break;
 | 
			
		||||
    case 5: BedMeshEditScreen::show(); break;
 | 
			
		||||
      case 4: BedMeshViewScreen::show(); break;
 | 
			
		||||
      case 5: BedMeshEditScreen::show(); break;
 | 
			
		||||
    #endif
 | 
			
		||||
    #if ENABLED(G26_MESH_VALIDATION)
 | 
			
		||||
    case 6: BedMeshViewScreen::doMeshValidation(); break;
 | 
			
		||||
      case 6: BedMeshViewScreen::doMeshValidation(); break;
 | 
			
		||||
    #endif
 | 
			
		||||
    #if ENABLED(BLTOUCH)
 | 
			
		||||
    case 7: injectCommands_P(PSTR("M280 P0 S60")); break;
 | 
			
		||||
    case 8: SpinnerDialogBox::enqueueAndWait_P(F("M280 P0 S90\nG4 P100\nM280 P0 S120")); break;
 | 
			
		||||
      case 7: injectCommands_P(PSTR("M280 P0 S60")); break;
 | 
			
		||||
      case 8: SpinnerDialogBox::enqueueAndWait_P(F("M280 P0 S90\nG4 P100\nM280 P0 S120")); break;
 | 
			
		||||
    #endif
 | 
			
		||||
    default: return false;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -77,8 +77,11 @@ void TuneMenu::onRedraw(draw_mode_t what) {
 | 
			
		||||
       .tag(3).button(FIL_CHANGE_POS,  GET_TEXT_F(MSG_FILAMENTCHANGE))
 | 
			
		||||
       .enabled(EITHER(LIN_ADVANCE, FILAMENT_RUNOUT_SENSOR))
 | 
			
		||||
       .tag(9).button(FILAMENT_POS, GET_TEXT_F(MSG_FILAMENT))
 | 
			
		||||
       .enabled(BOTH(HAS_LEVELING, HAS_BED_PROBE) || ENABLED(BABYSTEPPING))
 | 
			
		||||
       .tag(4).button(NUDGE_NOZ_POS, GET_TEXT_F(TERN(BABYSTEPPING, MSG_NUDGE_NOZZLE, MSG_ZPROBE_ZOFFSET)))
 | 
			
		||||
       #if ENABLED(BABYSTEPPING) && HAS_MULTI_HOTEND
 | 
			
		||||
         .tag(4).button(NUDGE_NOZ_POS, GET_TEXT_F(MSG_NUDGE_NOZZLE))
 | 
			
		||||
       #elif BOTH(HAS_LEVELING, HAS_BED_PROBE)
 | 
			
		||||
         .tag(4).button(NUDGE_NOZ_POS, GET_TEXT_F(MSG_ZPROBE_ZOFFSET))
 | 
			
		||||
       #endif
 | 
			
		||||
       .tag(5).button(SPEED_POS, GET_TEXT_F(MSG_PRINT_SPEED))
 | 
			
		||||
       .enabled(sdOrHostPrinting)
 | 
			
		||||
       .tag(sdOrHostPaused ? 7 : 6)
 | 
			
		||||
@@ -99,11 +102,11 @@ bool TuneMenu::onTouchEnd(uint8_t tag) {
 | 
			
		||||
  using namespace Theme;
 | 
			
		||||
  using namespace ExtUI;
 | 
			
		||||
  switch (tag) {
 | 
			
		||||
    case  1: GOTO_PREVIOUS();                    break;
 | 
			
		||||
    case  1: SaveSettingsDialogBox::promptToSaveSettings(); break;
 | 
			
		||||
    case  2: GOTO_SCREEN(TemperatureScreen);     break;
 | 
			
		||||
    case  3: GOTO_SCREEN(ChangeFilamentScreen);  break;
 | 
			
		||||
    case  4:
 | 
			
		||||
      #if ENABLED(BABYSTEPPING)
 | 
			
		||||
      #if ENABLED(BABYSTEPPING) && HAS_MULTI_HOTEND
 | 
			
		||||
        GOTO_SCREEN(NudgeNozzleScreen);
 | 
			
		||||
      #elif BOTH(HAS_LEVELING, HAS_BED_PROBE)
 | 
			
		||||
        GOTO_SCREEN(ZOffsetScreen);
 | 
			
		||||
 
 | 
			
		||||
@@ -53,7 +53,7 @@ void ZOffsetScreen::onRedraw(draw_mode_t what) {
 | 
			
		||||
  w.heading(                  GET_TEXT_F(MSG_ZPROBE_ZOFFSET));
 | 
			
		||||
  w.color(z_axis).adjuster(4, GET_TEXT_F(MSG_ZPROBE_ZOFFSET), getZOffset_mm());
 | 
			
		||||
  w.increments();
 | 
			
		||||
  w.button(2, GET_TEXT_F(MSG_PROBE_WIZARD), !isPrinting());
 | 
			
		||||
  w.button(2, GET_TEXT_F(MSG_PROBE_WIZARD), !isPrinting() && !wizardRunning());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ZOffsetScreen::move(float mm, int16_t steps) {
 | 
			
		||||
 
 | 
			
		||||
@@ -130,7 +130,7 @@ namespace Language_en {
 | 
			
		||||
  PROGMEM Language_Str MSG_EEPROM_RESTORED          = u8"Settings restored from backup";
 | 
			
		||||
  PROGMEM Language_Str MSG_EEPROM_RESET             = u8"Settings restored to default";
 | 
			
		||||
  PROGMEM Language_Str MSG_EEPROM_SAVED             = u8"Settings saved!";
 | 
			
		||||
  PROGMEM Language_Str MSG_EEPROM_SAVE_PROMPT       = u8"Do you wish to save these settings for next power-on?";
 | 
			
		||||
  PROGMEM Language_Str MSG_EEPROM_SAVE_PROMPT       = u8"Settings applied. Save these settings for next power-on?";
 | 
			
		||||
  PROGMEM Language_Str MSG_EEPROM_RESET_WARNING     = u8"Are you sure? Customizations will be lost.";
 | 
			
		||||
 | 
			
		||||
  PROGMEM Language_Str MSG_PASSCODE_REJECTED        = u8"Wrong passcode!";
 | 
			
		||||
@@ -146,7 +146,7 @@ namespace Language_en {
 | 
			
		||||
  PROGMEM Language_Str MSG_AXIS_LEVELING            = u8"Axis Leveling";
 | 
			
		||||
  PROGMEM Language_Str MSG_PROBE_BED                = u8"Probe Mesh";
 | 
			
		||||
  PROGMEM Language_Str MSG_SHOW_MESH                = u8"View Mesh";
 | 
			
		||||
  PROGMEM Language_Str MSG_PRINT_TEST               = u8"Print Test";
 | 
			
		||||
  PROGMEM Language_Str MSG_PRINT_TEST               = u8"Print Test (PLA)";
 | 
			
		||||
  PROGMEM Language_Str MSG_MOVE_Z_TO_TOP            = u8"Raise Z to Top";
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(TOUCH_UI_LULZBOT_BIO)
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,7 @@ extern tiny_timer_t refresh_timer;
 | 
			
		||||
#if ENABLED(TOUCH_UI_LULZBOT_BIO)
 | 
			
		||||
  #include "bioprinter/screens.h"
 | 
			
		||||
#elif ENABLED(TOUCH_UI_COCOA_PRESS)
 | 
			
		||||
  #include "cocoapress/screens.h"
 | 
			
		||||
  #include "cocoa_press/screens.h"
 | 
			
		||||
#elif ENABLED(TOUCH_UI_SYNDAVER_LEVEL)
 | 
			
		||||
  #include "syndaver_level/screens.h"
 | 
			
		||||
#else
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@ namespace Theme {
 | 
			
		||||
    .height       = 23,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  constexpr PROGMEM unsigned char Extruder_Icon[] = {
 | 
			
		||||
  constexpr PROGMEM unsigned char Extruder_Icon[69] = {
 | 
			
		||||
    0x3F, 0xFF, 0xFC,
 | 
			
		||||
    0x7F, 0xFF, 0xFE,
 | 
			
		||||
    0xC0, 0x00, 0x03,
 | 
			
		||||
@@ -68,12 +68,12 @@ namespace Theme {
 | 
			
		||||
    .filter       = BILINEAR,
 | 
			
		||||
    .wrapx        = BORDER,
 | 
			
		||||
    .wrapy        = BORDER,
 | 
			
		||||
    .RAMG_offset  = 8100,
 | 
			
		||||
    .RAMG_offset  = 8069,
 | 
			
		||||
    .width        = 32,
 | 
			
		||||
    .height       = 23,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  constexpr PROGMEM unsigned char Bed_Heat_Icon[] = {
 | 
			
		||||
  constexpr PROGMEM unsigned char Bed_Heat_Icon[92] = {
 | 
			
		||||
    0x01, 0x81, 0x81, 0x80,
 | 
			
		||||
    0x01, 0x81, 0x81, 0x80,
 | 
			
		||||
    0x00, 0xC0, 0xC0, 0xC0,
 | 
			
		||||
@@ -105,12 +105,12 @@ namespace Theme {
 | 
			
		||||
    .filter       = BILINEAR,
 | 
			
		||||
    .wrapx        = BORDER,
 | 
			
		||||
    .wrapy        = BORDER,
 | 
			
		||||
    .RAMG_offset  = 8300,
 | 
			
		||||
    .RAMG_offset  = 8161,
 | 
			
		||||
    .width        = 32,
 | 
			
		||||
    .height       = 32,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  constexpr PROGMEM unsigned char Fan_Icon[] = {
 | 
			
		||||
  constexpr PROGMEM unsigned char Fan_Icon[128] = {
 | 
			
		||||
    0xFF, 0xFF, 0xFF, 0xFF,
 | 
			
		||||
    0xFF, 0xFF, 0xFF, 0xFF,
 | 
			
		||||
    0xF8, 0x00, 0x00, 0x1F,
 | 
			
		||||
@@ -151,12 +151,12 @@ namespace Theme {
 | 
			
		||||
    .filter       = BILINEAR,
 | 
			
		||||
    .wrapx        = BORDER,
 | 
			
		||||
    .wrapy        = BORDER,
 | 
			
		||||
    .RAMG_offset  = 9000,
 | 
			
		||||
    .RAMG_offset  = 8289,
 | 
			
		||||
    .width        = 50,
 | 
			
		||||
    .height       = 20,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  constexpr PROGMEM unsigned char TD_Icon[] = {
 | 
			
		||||
  constexpr PROGMEM unsigned char TD_Icon[140] = {
 | 
			
		||||
    0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFC, 0x00,                    // Thumb Drive Widget
 | 
			
		||||
    0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
 | 
			
		||||
    0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x80,
 | 
			
		||||
@@ -179,5 +179,55 @@ namespace Theme {
 | 
			
		||||
    0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFC, 0x00
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  constexpr PROGMEM uint32_t UTF8_FONT_OFFSET = 10000;
 | 
			
		||||
  constexpr PROGMEM bitmap_info_t File_Icon_Info = {
 | 
			
		||||
    .format       = L1,
 | 
			
		||||
    .linestride   = 4,
 | 
			
		||||
    .filter       = BILINEAR,
 | 
			
		||||
    .wrapx        = BORDER,
 | 
			
		||||
    .wrapy        = BORDER,
 | 
			
		||||
    .RAMG_offset  = 8429,
 | 
			
		||||
    .width        = 25,
 | 
			
		||||
    .height       = 32,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const unsigned char File_Icon[128] PROGMEM = {
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00,
 | 
			
		||||
    0x40, 0x02, 0x80, 0x00, 0x40, 0x02, 0x40, 0x00, 0x40, 0x02, 0x20, 0x00,
 | 
			
		||||
    0x40, 0x02, 0x10, 0x00, 0x40, 0x02, 0x08, 0x00, 0x40, 0x02, 0x04, 0x00,
 | 
			
		||||
    0x40, 0x02, 0x02, 0x00, 0x40, 0x03, 0xFF, 0x00, 0x40, 0x00, 0x01, 0x00,
 | 
			
		||||
    0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00,
 | 
			
		||||
    0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00,
 | 
			
		||||
    0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00,
 | 
			
		||||
    0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00,
 | 
			
		||||
    0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00,
 | 
			
		||||
    0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00, 0x40, 0x00, 0x01, 0x00,
 | 
			
		||||
    0x7F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  constexpr PROGMEM bitmap_info_t Clock_Icon_Info = {
 | 
			
		||||
    .format       = L1,
 | 
			
		||||
    .linestride   = 4,
 | 
			
		||||
    .filter       = BILINEAR,
 | 
			
		||||
    .wrapx        = BORDER,
 | 
			
		||||
    .wrapy        = BORDER,
 | 
			
		||||
    .RAMG_offset  = 8557,
 | 
			
		||||
    .width        = 32,
 | 
			
		||||
    .height       = 32,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const unsigned char Clock_Icon[128] PROGMEM = {
 | 
			
		||||
    0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x7E, 0x7E, 0x00,
 | 
			
		||||
    0x00, 0xE0, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x07, 0x01, 0x00, 0xE0,
 | 
			
		||||
    0x0C, 0x01, 0x80, 0x70, 0x0C, 0x01, 0x80, 0x30, 0x18, 0x01, 0x80, 0x18,
 | 
			
		||||
    0x30, 0x01, 0x80, 0x08, 0x30, 0x01, 0x80, 0x0C, 0x20, 0x01, 0x80, 0x0C,
 | 
			
		||||
    0x60, 0x01, 0x80, 0x04, 0x60, 0x01, 0x80, 0x06, 0x60, 0x01, 0x80, 0x06,
 | 
			
		||||
    0x60, 0x01, 0xFF, 0x06, 0x60, 0x01, 0xFF, 0x06, 0x60, 0x00, 0x00, 0x06,
 | 
			
		||||
    0x60, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x0C,
 | 
			
		||||
    0x30, 0x00, 0x00, 0x0C, 0x30, 0x00, 0x00, 0x08, 0x18, 0x00, 0x00, 0x18,
 | 
			
		||||
    0x0C, 0x00, 0x00, 0x30, 0x0E, 0x00, 0x00, 0x70, 0x07, 0x00, 0x00, 0xE0,
 | 
			
		||||
    0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x7F, 0xFE, 0x00,
 | 
			
		||||
    0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  constexpr PROGMEM uint32_t UTF8_FONT_OFFSET  = 10000;
 | 
			
		||||
}; // namespace Theme
 | 
			
		||||
 
 | 
			
		||||
@@ -190,7 +190,11 @@ namespace ExtUI {
 | 
			
		||||
    void setHostResponse(const uint8_t);
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  inline void simulateUserClick() { ui.lcd_clicked = true; }
 | 
			
		||||
  inline void simulateUserClick() {
 | 
			
		||||
    #if EITHER(HAS_LCD_MENU, EXTENSIBLE_UI)
 | 
			
		||||
      ui.lcd_clicked = true;
 | 
			
		||||
    #endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #if ENABLED(PRINTCOUNTER)
 | 
			
		||||
    char* getFailedPrints_str(char buffer[21]);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user