Ver código fonte

Touch UI long filenames fixes (#19262)

* Improvements to FTDI DLCache functionality.
* Better handling of long file names in Touch UI
- Long file names now truncated and shown with ellipsis.
- Increased display cache buffer to allow for longer filenames.
- Visual error message when display cache is exceeded.
Marcio T 4 anos atrás
pai
commit
2b789ddab9
Nenhuma conta vinculada ao e-mail do autor do commit

+ 1
- 0
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/basic/commands.h Ver arquivo

@@ -133,6 +133,7 @@ class CLCD {
133 133
     static void set_brightness (uint8_t brightness);
134 134
     static uint8_t get_brightness();
135 135
     static void host_cmd (unsigned char host_command, unsigned char byte2);
136
+    static uint32_t dl_size() {return CLCD::mem_read_32(REG::CMD_DL) & 0x1FFF;}
136 137
 
137 138
     static void get_font_metrics (uint8_t font, struct FontMetrics &fm);
138 139
     static uint16_t get_text_width(const uint8_t font, const char *str);

+ 42
- 38
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/dl_cache.cpp Ver arquivo

@@ -32,7 +32,8 @@
32 32
  *
33 33
  * The cache memory begins with a table at
34 34
  * DL_CACHE_START: each table entry contains
35
- * an address and size for a cached DL slot.
35
+ * an address, size and used bytes for a cached
36
+ * DL slot.
36 37
  *
37 38
  * Immediately following the table is the
38 39
  * DL_FREE_ADDR, which points to free cache
@@ -44,11 +45,14 @@
44 45
  *
45 46
  *  DL_CACHE_START  slot0_addr     4
46 47
  *                  slot0_size     4
48
+ *                  slot0_used     4
47 49
  *                  slot1_addr     4
48 50
  *                  slot1_size     4
51
+ *                  slot1_used     4
49 52
  *                      ...
50 53
  *                  slotN_addr     4
51 54
  *                  slotN_size     4
55
+ *                  slotN_used     4
52 56
  *  DL_FREE_ADDR    dl_free_ptr    4
53 57
  *                  cached data
54 58
  *                      ...
@@ -57,7 +61,7 @@
57 61
  */
58 62
 
59 63
 #define DL_CACHE_START   MAP::RAM_G_SIZE - 0xFFFF
60
-#define DL_FREE_ADDR     DL_CACHE_START + DL_CACHE_SLOTS * 8
64
+#define DL_FREE_ADDR     DL_CACHE_START + DL_CACHE_SLOTS * 12
61 65
 
62 66
 using namespace FTDI;
63 67
 
@@ -66,12 +70,12 @@ using namespace FTDI;
66 70
 void DLCache::init() {
67 71
   CLCD::mem_write_32(DL_FREE_ADDR, DL_FREE_ADDR + 4);
68 72
   for(uint8_t slot = 0; slot < DL_CACHE_SLOTS; slot++) {
69
-    save_slot(slot, 0, 0);
73
+    save_slot(slot, 0, 0, 0);
70 74
   }
71 75
 }
72 76
 
73 77
 bool DLCache::has_data() {
74
-  return dl_size != 0;
78
+  return dl_slot_size != 0;
75 79
 }
76 80
 
77 81
 bool DLCache::wait_until_idle() {
@@ -93,12 +97,12 @@ bool DLCache::wait_until_idle() {
93 97
  * that it can be appended later. The memory is
94 98
  * dynamically allocated following DL_FREE_ADDR.
95 99
  *
96
- * If num_bytes is provided, then that many bytes
100
+ * If min_bytes is provided, then that many bytes
97 101
  * will be reserved so that the cache may be re-written
98 102
  * later with potentially a bigger DL.
99 103
  */
100 104
 
101
-bool DLCache::store(uint32_t num_bytes /* = 0*/) {
105
+bool DLCache::store(uint32_t min_bytes /* = 0*/) {
102 106
   CLCD::CommandFifo cmd;
103 107
 
104 108
   // Execute any commands already in the FIFO
@@ -107,67 +111,67 @@ bool DLCache::store(uint32_t num_bytes /* = 0*/) {
107 111
     return false;
108 112
 
109 113
   // Figure out how long the display list is
110
-  uint32_t new_dl_size = CLCD::mem_read_32(REG::CMD_DL) & 0x1FFF;
111
-  uint32_t free_space  = 0;
112
-  uint32_t dl_alloc    = 0;
114
+  const uint32_t dl_size = CLCD::dl_size();
113 115
 
114
-  if (dl_addr == 0) {
116
+  if (dl_slot_addr == 0) {
115 117
     // If we are allocating new space...
116
-    dl_addr     = CLCD::mem_read_32(DL_FREE_ADDR);
117
-    free_space  = MAP::RAM_G_SIZE - dl_addr;
118
-    dl_alloc    = num_bytes ?: new_dl_size;
119
-    dl_size     = new_dl_size;
120
-  } else {
121
-    // Otherwise, we can only store as much space
122
-    // as was previously allocated.
123
-    free_space  = num_bytes ?: dl_size;
124
-    dl_alloc    = 0;
125
-    dl_size     = new_dl_size;
118
+    dl_slot_addr = CLCD::mem_read_32(DL_FREE_ADDR);
119
+    dl_slot_size = max(dl_size, min_bytes);
120
+    
121
+    const uint32_t free_space = MAP::RAM_G_SIZE - dl_slot_addr;
122
+    if(dl_slot_size <= free_space) {
123
+      CLCD::mem_write_32(DL_FREE_ADDR, dl_slot_addr + dl_slot_size);
124
+    } else {
125
+      dl_slot_addr = 0;
126
+      dl_slot_size = 0;
127
+      dl_slot_used = 0;
128
+    }
126 129
   }
127 130
 
128
-  if (dl_size > free_space) {
131
+  if (dl_size > dl_slot_size) {
129 132
     // Not enough memory to cache the display list.
130 133
     #if ENABLED(TOUCH_UI_DEBUG)
131 134
       SERIAL_ECHO_START();
132
-      SERIAL_ECHOPAIR  ("Not enough space in GRAM to cache display list, free space: ", free_space);
135
+      SERIAL_ECHOPAIR  ("Not enough space in GRAM to cache display list, free space: ", dl_slot_size);
133 136
       SERIAL_ECHOLNPAIR(" Required: ", dl_size);
134 137
     #endif
138
+    dl_slot_used = 0;
139
+    save_slot();
135 140
     return false;
136 141
   } else {
137 142
     #if ENABLED(TOUCH_UI_DEBUG)
138 143
       SERIAL_ECHO_START();
139
-      SERIAL_ECHOPAIR  ("Saving DL to RAMG cache, bytes: ", dl_size);
140
-      SERIAL_ECHOLNPAIR(" Free space: ", free_space);
144
+      SERIAL_ECHOPAIR  ("Saving DL to RAMG cache, bytes: ", dl_slot_used);
145
+      SERIAL_ECHOLNPAIR(" Free space: ", dl_slot_size);
141 146
     #endif
142
-    cmd.memcpy(dl_addr, MAP::RAM_DL, dl_size);
147
+    dl_slot_used = dl_size;
148
+    save_slot();
149
+    cmd.memcpy(dl_slot_addr, MAP::RAM_DL, dl_slot_used);
143 150
     cmd.execute();
144
-    save_slot(dl_slot, dl_addr, dl_size);
145
-    if (dl_alloc > 0) {
146
-      // If we allocated space dynamically, then adjust dl_free_addr.
147
-      CLCD::mem_write_32(DL_FREE_ADDR, dl_addr + dl_alloc);
148
-    }
149 151
     return true;
150 152
   }
151 153
 }
152 154
 
153
-void DLCache::save_slot(uint8_t dl_slot, uint32_t dl_addr, uint32_t dl_size) {
154
-  CLCD::mem_write_32(DL_CACHE_START + dl_slot * 8 + 0, dl_addr);
155
-  CLCD::mem_write_32(DL_CACHE_START + dl_slot * 8 + 4, dl_size);
155
+void DLCache::save_slot(uint8_t indx, uint32_t addr, uint16_t size, uint16_t used) {
156
+  CLCD::mem_write_32(DL_CACHE_START + indx * 12 + 0, addr);
157
+  CLCD::mem_write_32(DL_CACHE_START + indx * 12 + 4, size);
158
+  CLCD::mem_write_32(DL_CACHE_START + indx * 12 + 8, used);
156 159
 }
157 160
 
158
-void DLCache::load_slot() {
159
-  dl_addr  = CLCD::mem_read_32(DL_CACHE_START + dl_slot * 8 + 0);
160
-  dl_size  = CLCD::mem_read_32(DL_CACHE_START + dl_slot * 8 + 4);
161
+void DLCache::load_slot(uint8_t indx, uint32_t &addr, uint16_t &size, uint16_t &used) {
162
+  addr  = CLCD::mem_read_32(DL_CACHE_START + indx * 12 + 0);
163
+  size  = CLCD::mem_read_32(DL_CACHE_START + indx * 12 + 4);
164
+  used  = CLCD::mem_read_32(DL_CACHE_START + indx * 12 + 8);
161 165
 }
162 166
 
163 167
 void DLCache::append() {
164 168
   CLCD::CommandFifo cmd;
165
-  cmd.append(dl_addr, dl_size);
169
+  cmd.append(dl_slot_addr, dl_slot_used);
166 170
   #if ENABLED(TOUCH_UI_DEBUG)
167 171
     cmd.execute();
168 172
     wait_until_idle();
169 173
     SERIAL_ECHO_START();
170
-    SERIAL_ECHOPAIR  ("Appending to DL from RAMG cache, bytes: ", dl_size);
174
+    SERIAL_ECHOPAIR  ("Appending to DL from RAMG cache, bytes: ", dl_slot_used);
171 175
     SERIAL_ECHOLNPAIR(" REG_CMD_DL: ", CLCD::mem_read_32(REG::CMD_DL));
172 176
   #endif
173 177
 }

+ 11
- 7
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/dl_cache.h Ver arquivo

@@ -44,12 +44,16 @@ class DLCache {
44 44
     typedef FTDI::ftdi_registers  REG;
45 45
     typedef FTDI::ftdi_memory_map MAP;
46 46
 
47
-    uint8_t  dl_slot;
48
-    uint32_t dl_addr;
49
-    uint16_t dl_size;
47
+    uint8_t  dl_slot_indx;
48
+    uint32_t dl_slot_addr;
49
+    uint16_t dl_slot_size;
50
+    uint16_t dl_slot_used;
50 51
 
51
-    void load_slot();
52
-    static void save_slot(uint8_t dl_slot, uint32_t dl_addr, uint32_t dl_size);
52
+    void load_slot() {load_slot(dl_slot_indx, dl_slot_addr, dl_slot_size, dl_slot_used);}
53
+    void save_slot() {save_slot(dl_slot_indx, dl_slot_addr, dl_slot_size, dl_slot_used);}
54
+    
55
+    static void load_slot(uint8_t indx, uint32_t &addr, uint16_t &size, uint16_t &used);
56
+    static void save_slot(uint8_t indx, uint32_t  addr, uint16_t  size, uint16_t  used);
53 57
 
54 58
     bool wait_until_idle();
55 59
 
@@ -57,12 +61,12 @@ class DLCache {
57 61
     static void init();
58 62
 
59 63
     DLCache(uint8_t slot) {
60
-      dl_slot = slot;
64
+      dl_slot_indx = slot;
61 65
       load_slot();
62 66
     }
63 67
 
64 68
     bool has_data();
65
-    bool store(uint32_t num_bytes = 0);
69
+    bool store(uint32_t min_bytes = 0);
66 70
     void append();
67 71
 };
68 72
 

+ 1
- 0
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/ftdi_extended.h Ver arquivo

@@ -47,4 +47,5 @@
47 47
   #include "sound_list.h"
48 48
   #include "polygon.h"
49 49
   #include "text_box.h"
50
+  #include "text_ellipsis.h"
50 51
 #endif

+ 11
- 0
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/screen_types.h Ver arquivo

@@ -173,10 +173,21 @@ class UncachedScreen {
173 173
 template<uint8_t DL_SLOT,uint32_t DL_SIZE = 0>
174 174
 class CachedScreen {
175 175
   protected:
176
+    static void gfxError() {
177
+      using namespace FTDI;
178
+      CommandProcessor cmd;
179
+      cmd.cmd(CMD_DLSTART)
180
+         .cmd(CLEAR(true,true,true))
181
+         .font(30)
182
+         .text(0, 0, display_width, display_height, F("GFX MEM FULL"));
183
+    }
184
+
176 185
     static bool storeBackground() {
177 186
       DLCache dlcache(DL_SLOT);
178 187
       if (!dlcache.store(DL_SIZE)) {
179 188
         SERIAL_ECHO_MSG("CachedScreen::storeBackground() failed: not enough DL cache space");
189
+        gfxError(); // Try to cache a shorter error message instead.
190
+        dlcache.store(DL_SIZE);
180 191
         return false;
181 192
       }
182 193
       return true;

+ 80
- 0
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.cpp Ver arquivo

@@ -0,0 +1,80 @@
1
+/*********************
2
+ * text_ellipsis.cpp *
3
+ *********************/
4
+
5
+/****************************************************************************
6
+ *   Written By Marcio Teixeira 2019 - Aleph Objects, Inc.                  *
7
+ *                                                                          *
8
+ *   This program is free software: you can redistribute it and/or modify   *
9
+ *   it under the terms of the GNU General Public License as published by   *
10
+ *   the Free Software Foundation, either version 3 of the License, or      *
11
+ *   (at your option) any later version.                                    *
12
+ *                                                                          *
13
+ *   This program is distributed in the hope that it will be useful,        *
14
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
15
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
16
+ *   GNU General Public License for more details.                           *
17
+ *                                                                          *
18
+ *   To view a copy of the GNU General Public License, go to the following  *
19
+ *   location: <https://www.gnu.org/licenses/>.                              *
20
+ ****************************************************************************/
21
+
22
+#include "ftdi_extended.h"
23
+
24
+#ifdef FTDI_EXTENDED
25
+
26
+namespace FTDI {
27
+
28
+  /**
29
+   * Helper function for drawing text with ellipses. The str buffer may be modified and should have space for up to two extra characters.
30
+   */
31
+  static void _draw_text_with_ellipsis(CommandProcessor& cmd, int16_t x, int16_t y, int16_t w, int16_t h, char *str, uint16_t options, uint8_t font) {
32
+    FontMetrics fm(font);
33
+    const uint16_t ellipsisWidth = fm.get_char_width('.') * 3;
34
+
35
+    // Compute the total line length, as well as
36
+    // the location in the string where it can
37
+    // split and still allow the ellipsis to fit.
38
+    uint16_t lineWidth = 0;
39
+    char *breakPoint   = str;
40
+    for(char* c = str; *c; c++) {
41
+      lineWidth += fm.get_char_width(*c);
42
+      if(lineWidth + ellipsisWidth < w)
43
+        breakPoint = c;
44
+    }
45
+
46
+    if(lineWidth > w) {
47
+      *breakPoint = '\0';
48
+      strcpy_P(breakPoint,PSTR("..."));
49
+    }
50
+
51
+    cmd.apply_text_alignment(x, y, w, h, options);
52
+    #ifdef TOUCH_UI_USE_UTF8
53
+      if (has_utf8_chars(str)) {
54
+        draw_utf8_text(cmd, x, y, str, font_size_t::from_romfont(font), options);
55
+      } else
56
+    #endif
57
+      {
58
+        cmd.CLCD::CommandFifo::text(x, y, font, options);
59
+        cmd.CLCD::CommandFifo::str(str);
60
+      }
61
+  }
62
+
63
+  /**
64
+    * These functions draws text inside a bounding box, truncating the text and
65
+    * adding ellipsis if the text does not fit.
66
+    */
67
+  void draw_text_with_ellipsis(CommandProcessor& cmd, int x, int y, int w, int h, const char *str, uint16_t options, uint8_t font) {
68
+    char tmp[strlen(str) + 3];
69
+    strcpy(tmp, str);
70
+    _draw_text_with_ellipsis(cmd, x, y, w, h, tmp, options, font);
71
+  }
72
+
73
+  void draw_text_with_ellipsis(CommandProcessor& cmd, int x, int y, int w, int h, progmem_str pstr, uint16_t options, uint8_t font) {
74
+    char tmp[strlen_P((const char*)pstr) + 3];
75
+    strcpy_P(tmp, (const char*)pstr);
76
+    _draw_text_with_ellipsis(cmd, x, y, w, h, tmp, options, font);
77
+  }
78
+} // namespace FTDI
79
+
80
+#endif // FTDI_EXTENDED

+ 31
- 0
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/ftdi_eve_lib/extended/text_ellipsis.h Ver arquivo

@@ -0,0 +1,31 @@
1
+/*******************
2
+ * text_ellipsis.h *
3
+ *******************/
4
+
5
+/****************************************************************************
6
+ *   Written By Marcio Teixeira 2020 - SynDaver Labs, Inc.                  *
7
+ *                                                                          *
8
+ *   This program is free software: you can redistribute it and/or modify   *
9
+ *   it under the terms of the GNU General Public License as published by   *
10
+ *   the Free Software Foundation, either version 3 of the License, or      *
11
+ *   (at your option) any later version.                                    *
12
+ *                                                                          *
13
+ *   This program is distributed in the hope that it will be useful,        *
14
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
15
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
16
+ *   GNU General Public License for more details.                           *
17
+ *                                                                          *
18
+ *   To view a copy of the GNU General Public License, go to the following  *
19
+ *   location: <https://www.gnu.org/licenses/>.                              *
20
+ ****************************************************************************/
21
+
22
+#pragma once
23
+
24
+/**
25
+ * This function draws text inside a bounding box, truncating the text and
26
+ * showing ellipsis if it does not fit.
27
+ */
28
+namespace FTDI {
29
+  void draw_text_with_ellipsis(class CommandProcessor& cmd, int x, int y, int w, int h, progmem_str str, uint16_t options = 0, uint8_t font = 31);
30
+  void draw_text_with_ellipsis(class CommandProcessor& cmd, int x, int y, int w, int h, const char *str, uint16_t options = 0, uint8_t font = 31);
31
+}

+ 9
- 6
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/files_screen.cpp Ver arquivo

@@ -83,15 +83,19 @@ void FilesScreen::drawFileButton(const char* filename, uint8_t tag, bool is_dir,
83 83
   cmd.font(font_medium)
84 84
      .rectangle( 0, BTN_Y(header_h+line), display_width, BTN_H(1));
85 85
   cmd.cmd(COLOR_RGB(is_highlighted ? normal_btn.rgb : bg_text_enabled));
86
+  constexpr uint16_t dim[2] = {BTN_SIZE(6,1)};
87
+  #define POS_AND_SHORTEN(SHORTEN) BTN_POS(1,header_h+line), dim[0] - (SHORTEN), dim[1]
88
+  #define POS_AND_SIZE             POS_AND_SHORTEN(0)
86 89
   #if ENABLED(SCROLL_LONG_FILENAMES)
87 90
     if (is_highlighted) {
88 91
       cmd.cmd(SAVE_CONTEXT());
89 92
       cmd.cmd(MACRO(0));
90
-    }
93
+      cmd.text(POS_AND_SIZE, filename, OPT_CENTERY | OPT_NOFIT);
94
+    } else
91 95
   #endif
92
-  cmd.text  (BTN_POS(1,header_h+line), BTN_SIZE(6,1), filename, OPT_CENTERY | TERN0(SCROLL_LONG_FILENAMES, OPT_NOFIT));
93
-  if (is_dir) {
94
-    cmd.text(BTN_POS(1,header_h+line), BTN_SIZE(6,1), F("> "),  OPT_CENTERY | OPT_RIGHTX);
96
+  draw_text_with_ellipsis(cmd, POS_AND_SHORTEN(is_dir ? 20 : 0), filename, OPT_CENTERY, font_medium);
97
+  if (is_dir && !is_highlighted) {
98
+    cmd.text(POS_AND_SIZE, F("> "),  OPT_CENTERY | OPT_RIGHTX);
95 99
   }
96 100
   #if ENABLED(SCROLL_LONG_FILENAMES)
97 101
     if (is_highlighted) {
@@ -102,7 +106,7 @@ void FilesScreen::drawFileButton(const char* filename, uint8_t tag, bool is_dir,
102 106
 
103 107
 void FilesScreen::drawFileList() {
104 108
   FileList files;
105
-  screen_data.FilesScreen.num_page = max(1,(ceil)(float(files.count()) / files_per_page));
109
+  screen_data.FilesScreen.num_page = max(1,ceil(float(files.count()) / files_per_page));
106 110
   screen_data.FilesScreen.cur_page = min(screen_data.FilesScreen.cur_page, screen_data.FilesScreen.num_page-1);
107 111
   screen_data.FilesScreen.flags.is_root  = files.isAtRootDir();
108 112
 
@@ -134,7 +138,6 @@ void FilesScreen::drawHeader() {
134 138
   sprintf_P(str, PSTR("Page %d of %d"),
135 139
     screen_data.FilesScreen.cur_page + 1, screen_data.FilesScreen.num_page);
136 140
 
137
-
138 141
   CommandProcessor cmd;
139 142
   cmd.colors(normal_btn)
140 143
      .font(font_small)

+ 1
- 1
Marlin/src/lcd/extui/lib/ftdi_eve_touch_ui/screens/screens.h Ver arquivo

@@ -96,7 +96,7 @@ enum {
96 96
 #define STATUS_SCREEN_DL_SIZE        2048
97 97
 #define ALERT_BOX_DL_SIZE            3072
98 98
 #define SPINNER_DL_SIZE              3072
99
-#define FILE_SCREEN_DL_SIZE          3072
99
+#define FILE_SCREEN_DL_SIZE          4160
100 100
 #define PRINTING_SCREEN_DL_SIZE      2048
101 101
 
102 102
 /************************* MENU SCREEN DECLARATIONS *************************/

Carregando…
Cancelar
Salvar