Browse Source

LCD menu code refactoring and cleanup (#12308)

Marcio Teixeira 6 years ago
parent
commit
8517d5f915
4 changed files with 223 additions and 194 deletions
  1. 56
    64
      Marlin/src/lcd/menu/menu.cpp
  2. 141
    110
      Marlin/src/lcd/menu/menu.h
  3. 25
    19
      Marlin/src/lcd/menu/menu_sdcard.cpp
  4. 1
    1
      Marlin/src/lcd/ultralcd.h

+ 56
- 64
Marlin/src/lcd/menu/menu.cpp View File

@@ -106,10 +106,7 @@ void lcd_goto_previous_menu_no_defer() {
106 106
 /////////// Common Menu Actions ////////////
107 107
 ////////////////////////////////////////////
108 108
 
109
-void _menu_action_back() { lcd_goto_previous_menu(); }
110
-void menu_action_submenu(screenFunc_t func) { lcd_save_previous_screen(); lcd_goto_screen(func); }
111
-void menu_action_gcode(PGM_P pgcode) { enqueue_and_echo_commands_P(pgcode); }
112
-void menu_action_function(screenFunc_t func) { (*func)(); }
109
+void menu_item_gcode::action(PGM_P pgcode) { enqueue_and_echo_commands_P(pgcode); }
113 110
 
114 111
 ////////////////////////////////////////////
115 112
 /////////// Menu Editing Actions ///////////
@@ -118,76 +115,71 @@ void menu_action_function(screenFunc_t func) { (*func)(); }
118 115
 /**
119 116
  * Functions for editing single values
120 117
  *
121
- * The "DEFINE_MENU_EDIT_TYPE" macro generates the functions needed to edit a numerical value.
118
+ * The "DEFINE_MENU_EDIT_ITEM" macro generates the functions needed to edit a numerical value.
122 119
  *
123
- * For example, DEFINE_MENU_EDIT_TYPE(int16_t, int3, itostr3, 1) expands into these functions:
120
+ * The prerequisite is that in the header the type was already declared:
124 121
  *
125
- *   bool _menu_edit_int3();
126
- *   void menu_edit_int3(); // edit int16_t (interactively)
127
- *   void menu_edit_callback_int3(); // edit int16_t (interactively) with callback on completion
128
- *   void _menu_action_setting_edit_int3(PGM_P const pstr, int16_t * const ptr, const int16_t minValue, const int16_t maxValue);
129
- *   void menu_action_setting_edit_int3(PGM_P const pstr, int16_t * const ptr, const int16_t minValue, const int16_t maxValue);
130
- *   void menu_action_setting_edit_callback_int3(PGM_P const pstr, int16_t * const ptr, const int16_t minValue, const int16_t maxValue, const screenFunc_t callback, const bool live); // edit int16_t with callback
122
+ *   DECLARE_MENU_EDIT_TYPE(int16_t, int3, itostr3, 1)
123
+ *
124
+ * For example, DEFINE_MENU_EDIT_ITEM(int3) expands into these functions:
125
+ *
126
+ *   bool menu_item_int3::_edit();
127
+ *   void menu_item_int3::edit(); // edit int16_t (interactively)
128
+ *   void menu_item_int3::action_setting_edit(PGM_P const pstr, int16_t * const ptr, const int16_t minValue, const int16_t maxValue, const screenFunc_t callback = null, const bool live = false);
131 129
  *
132 130
  * You can then use one of the menu macros to present the edit interface:
133 131
  *   MENU_ITEM_EDIT(int3, MSG_SPEED, &feedrate_percentage, 10, 999)
134 132
  *
135 133
  * This expands into a more primitive menu item:
136
- *   MENU_ITEM(setting_edit_int3, MSG_SPEED, PSTR(MSG_SPEED), &feedrate_percentage, 10, 999)
134
+ *   MENU_ITEM_VARIANT(int3, _setting_edit, MSG_SPEED, PSTR(MSG_SPEED), &feedrate_percentage, 10, 999)
137 135
  *
138 136
  * ...which calls:
139
- *       menu_action_setting_edit_int3(PSTR(MSG_SPEED), &feedrate_percentage, 10, 999)
137
+ *       menu_item_int3::action_setting_edit(PSTR(MSG_SPEED), &feedrate_percentage, 10, 999)
140 138
  */
141
-#define DEFINE_MENU_EDIT_TYPE(TYPE, NAME, STRFUNC, SCALE) \
142
-  bool _menu_edit_ ## NAME() { \
143
-    ENCODER_DIRECTION_NORMAL(); \
144
-    if ((int32_t)encoderPosition < 0) encoderPosition = 0; \
145
-    if ((int32_t)encoderPosition > maxEditValue) encoderPosition = maxEditValue; \
146
-    if (lcdDrawUpdate) \
147
-      lcd_implementation_drawedit(editLabel, STRFUNC(((TYPE)((int32_t)encoderPosition + minEditValue)) * (1.0f / SCALE))); \
148
-    if (lcd_clicked || (liveEdit && lcdDrawUpdate)) { \
149
-      TYPE value = ((TYPE)((int32_t)encoderPosition + minEditValue)) * (1.0f / SCALE); \
150
-      if (editValue != NULL) *((TYPE*)editValue) = value; \
151
-      if (callbackFunc && (liveEdit || lcd_clicked)) (*callbackFunc)(); \
152
-      if (lcd_clicked) lcd_goto_previous_menu(); \
153
-    } \
154
-    return use_click(); \
155
-  } \
156
-  void menu_edit_ ## NAME() { _menu_edit_ ## NAME(); } \
157
-  void _menu_action_setting_edit_ ## NAME(PGM_P const pstr, TYPE* const ptr, const TYPE minValue, const TYPE maxValue) { \
158
-    lcd_save_previous_screen(); \
159
-    lcd_refresh(); \
160
-    \
161
-    editLabel = pstr; \
162
-    editValue = ptr; \
163
-    minEditValue = minValue * SCALE; \
164
-    maxEditValue = maxValue * SCALE - minEditValue; \
165
-    encoderPosition = (*ptr) * SCALE - minEditValue; \
166
-  } \
167
-  void menu_action_setting_edit_callback_ ## NAME(PGM_P const pstr, TYPE * const ptr, const TYPE minValue, const TYPE maxValue, const screenFunc_t callback/*=NULL*/, const bool live/*=false*/) { \
168
-    _menu_action_setting_edit_ ## NAME(pstr, ptr, minValue, maxValue); \
169
-    currentScreen = menu_edit_ ## NAME; \
170
-    callbackFunc = callback; \
171
-    liveEdit = live; \
172
-  } \
173
-  typedef void NAME##_void
174
-
175
-DEFINE_MENU_EDIT_TYPE(int16_t, int3, itostr3, 1);
176
-DEFINE_MENU_EDIT_TYPE(int16_t, int4, itostr4sign, 1);
177
-DEFINE_MENU_EDIT_TYPE(uint8_t, int8, i8tostr3, 1);
178
-DEFINE_MENU_EDIT_TYPE(float, float3, ftostr3, 1);
179
-DEFINE_MENU_EDIT_TYPE(float, float52, ftostr52, 100);
180
-DEFINE_MENU_EDIT_TYPE(float, float43, ftostr43sign, 1000);
181
-DEFINE_MENU_EDIT_TYPE(float, float5, ftostr5rj, 0.01f);
182
-DEFINE_MENU_EDIT_TYPE(float, float51, ftostr51sign, 10);
183
-DEFINE_MENU_EDIT_TYPE(float, float52sign, ftostr52sign, 100);
184
-DEFINE_MENU_EDIT_TYPE(float, float62, ftostr62rj, 100);
185
-DEFINE_MENU_EDIT_TYPE(uint32_t, long5, ftostr5rj, 0.01f);
186
-
187
-void menu_action_setting_edit_bool(PGM_P pstr, bool* ptr) { UNUSED(pstr); *ptr ^= true; lcd_refresh(); }
188
-void menu_action_setting_edit_callback_bool(PGM_P pstr, bool* ptr, screenFunc_t callback) {
189
-  menu_action_setting_edit_bool(pstr, ptr);
190
-  (*callback)();
139
+void menu_item_invariants::edit(strfunc_t strfunc, loadfunc_t loadfunc) {
140
+  ENCODER_DIRECTION_NORMAL();
141
+  if ((int32_t)encoderPosition < 0) encoderPosition = 0;
142
+  if ((int32_t)encoderPosition > maxEditValue) encoderPosition = maxEditValue;
143
+  if (lcdDrawUpdate)
144
+    lcd_implementation_drawedit(editLabel, strfunc(encoderPosition + minEditValue));
145
+  if (lcd_clicked || (liveEdit && lcdDrawUpdate)) {
146
+    if (editValue != NULL) loadfunc(editValue, encoderPosition + minEditValue);
147
+    if (callbackFunc && (liveEdit || lcd_clicked)) (*callbackFunc)();
148
+    if (lcd_clicked) lcd_goto_previous_menu();
149
+    lcd_clicked = false;
150
+  }
151
+}
152
+
153
+void menu_item_invariants::init(PGM_P const el, void * const ev, const int32_t minv, const int32_t maxv, const uint32_t ep, const screenFunc_t cs, const screenFunc_t cb, const bool le) {
154
+  lcd_save_previous_screen();
155
+  lcd_refresh();
156
+  editLabel = el;
157
+  editValue = ev;
158
+  minEditValue = minv;
159
+  maxEditValue = maxv;
160
+  encoderPosition = ep;
161
+  currentScreen = cs;
162
+  callbackFunc = cb;
163
+  liveEdit = le;
164
+}
165
+
166
+#define DEFINE_MENU_EDIT_ITEM(NAME) template class menu_item_template<NAME ## _item_info>;
167
+
168
+DEFINE_MENU_EDIT_ITEM(int3);
169
+DEFINE_MENU_EDIT_ITEM(int4);
170
+DEFINE_MENU_EDIT_ITEM(int8);
171
+DEFINE_MENU_EDIT_ITEM(float3);
172
+DEFINE_MENU_EDIT_ITEM(float52);
173
+DEFINE_MENU_EDIT_ITEM(float43);
174
+DEFINE_MENU_EDIT_ITEM(float5);
175
+DEFINE_MENU_EDIT_ITEM(float51);
176
+DEFINE_MENU_EDIT_ITEM(float52sign);
177
+DEFINE_MENU_EDIT_ITEM(float62);
178
+DEFINE_MENU_EDIT_ITEM(long5);
179
+
180
+void menu_item_bool::action_setting_edit(PGM_P pstr, bool *ptr, screenFunc_t callback) {
181
+  UNUSED(pstr); *ptr ^= true; lcd_refresh();
182
+  if (callback) (*callback)();
191 183
 }
192 184
 
193 185
 ////////////////////////////////////////////

+ 141
- 110
Marlin/src/lcd/menu/menu.h View File

@@ -37,6 +37,30 @@ bool printer_busy();
37 37
 void lcd_completion_feedback(const bool good=true);
38 38
 void lcd_goto_previous_menu();
39 39
 void lcd_goto_previous_menu_no_defer();
40
+void lcd_save_previous_screen();
41
+
42
+////////////////////////////////////////////
43
+////////// Menu Item Numeric Types /////////
44
+////////////////////////////////////////////
45
+
46
+#define DECLARE_MENU_EDIT_TYPE(TYPE, NAME, STRFUNC, SCALE) \
47
+  struct NAME ## _item_info { \
48
+    typedef TYPE type_t; \
49
+    static constexpr float scale = SCALE; \
50
+    static inline char* strfunc(const float value) { return STRFUNC((TYPE) value); } \
51
+  };
52
+
53
+DECLARE_MENU_EDIT_TYPE(int16_t, int3, itostr3, 1);
54
+DECLARE_MENU_EDIT_TYPE(int16_t, int4, itostr4sign, 1);
55
+DECLARE_MENU_EDIT_TYPE(uint8_t, int8, i8tostr3, 1);
56
+DECLARE_MENU_EDIT_TYPE(float, float3, ftostr3, 1);
57
+DECLARE_MENU_EDIT_TYPE(float, float52, ftostr52, 100);
58
+DECLARE_MENU_EDIT_TYPE(float, float43, ftostr43sign, 1000);
59
+DECLARE_MENU_EDIT_TYPE(float, float5, ftostr5rj, 0.01f);
60
+DECLARE_MENU_EDIT_TYPE(float, float51, ftostr51sign, 10);
61
+DECLARE_MENU_EDIT_TYPE(float, float52sign, ftostr52sign, 100);
62
+DECLARE_MENU_EDIT_TYPE(float, float62, ftostr62rj, 100);
63
+DECLARE_MENU_EDIT_TYPE(uint32_t, long5, ftostr5rj, 0.01f);
40 64
 
41 65
 ////////////////////////////////////////////
42 66
 ///////// Menu Item Draw Functions /////////
@@ -54,7 +78,7 @@ void lcd_implementation_drawedit(const char* const pstr, const char* const value
54 78
 #endif
55 79
 #if HAS_GRAPHICAL_LCD
56 80
   void _drawmenu_setting_edit_generic(const bool isSelected, const uint8_t row, const char* pstr, const char* const data, const bool pgm);
57
-  #define lcd_implementation_drawmenu_back(sel, row, pstr, dummy) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
81
+  #define lcd_implementation_drawmenu_back(sel, row, pstr) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
58 82
   #define lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, false)
59 83
   #define lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, true)
60 84
   #define DRAWMENU_SETTING_EDIT_GENERIC(SRC) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, SRC)
@@ -68,7 +92,7 @@ void lcd_implementation_drawedit(const char* const pstr, const char* const value
68 92
     void _lcd_zoffset_overlay_gfx(const float zvalue);
69 93
   #endif
70 94
 #else
71
-  #define lcd_implementation_drawmenu_back(sel, row, pstr, dummy) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_UPLEVEL_CHAR, LCD_UPLEVEL_CHAR)
95
+  #define lcd_implementation_drawmenu_back(sel, row, pstr) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_UPLEVEL_CHAR, LCD_UPLEVEL_CHAR)
72 96
   void lcd_implementation_drawmenu_setting_edit_generic(const bool sel, const uint8_t row, const char* pstr, const char pre_char, const char* const data);
73 97
   void lcd_implementation_drawmenu_setting_edit_generic_P(const bool sel, const uint8_t row, const char* pstr, const char pre_char, const char* const data);
74 98
   #define DRAWMENU_SETTING_EDIT_GENERIC(SRC) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', SRC)
@@ -90,75 +114,103 @@ void lcd_implementation_drawedit(const char* const pstr, const char* const value
90 114
 /////// Edit Setting Draw Functions ////////
91 115
 ////////////////////////////////////////////
92 116
 
93
-#define DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(TYPE, NAME, STRFUNC) \
117
+#define _DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(TYPE, NAME, STRFUNC) \
94 118
   FORCE_INLINE void lcd_implementation_drawmenu_setting_edit_ ## NAME (const bool sel, const uint8_t row, PGM_P pstr, PGM_P pstr2, TYPE * const data, ...) { \
95 119
     UNUSED(pstr2); \
96 120
     DRAWMENU_SETTING_EDIT_GENERIC(STRFUNC(*(data))); \
97 121
   } \
98
-  FORCE_INLINE void lcd_implementation_drawmenu_setting_edit_callback_ ## NAME (const bool sel, const uint8_t row, PGM_P pstr, PGM_P pstr2, TYPE * const data, ...) { \
99
-    UNUSED(pstr2); \
100
-    DRAWMENU_SETTING_EDIT_GENERIC(STRFUNC(*(data))); \
101
-  } \
102 122
   FORCE_INLINE void lcd_implementation_drawmenu_setting_edit_accessor_ ## NAME (const bool sel, const uint8_t row, PGM_P pstr, PGM_P pstr2, TYPE (*pget)(), void (*pset)(TYPE), ...) { \
103 123
     UNUSED(pstr2); UNUSED(pset); \
104 124
     DRAWMENU_SETTING_EDIT_GENERIC(STRFUNC(pget())); \
105 125
   } \
106 126
   typedef void NAME##_void
107
-DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(int16_t, int3, itostr3);
108
-DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(int16_t, int4, itostr4sign);
109
-DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(uint8_t, int8, i8tostr3);
110
-DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float3, ftostr3);
111
-DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float52, ftostr52);
112
-DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float43, ftostr43sign);
113
-DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float5, ftostr5rj);
114
-DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float51, ftostr51sign);
115
-DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float52sign, ftostr52sign);
116
-DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float62, ftostr62rj);
117
-DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(uint32_t, long5, ftostr5rj);
118
-
119
-#define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data)                    DRAW_BOOL_SETTING(sel, row, pstr, data)
120
-#define lcd_implementation_drawmenu_setting_edit_callback_bool(sel, row, pstr, pstr2, data, callback) DRAW_BOOL_SETTING(sel, row, pstr, data)
121
-#define lcd_implementation_drawmenu_setting_edit_accessor_bool(sel, row, pstr, pstr2, pget, pset)     DRAW_BOOL_SETTING(sel, row, pstr, data)
127
+#define DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(NAME) _DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(NAME ## _item_info::type_t, NAME, NAME ## _item_info::strfunc)
128
+
129
+DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(int3);
130
+DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(int4);
131
+DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(int8);
132
+DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float3);
133
+DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float52);
134
+DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float43);
135
+DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float5);
136
+DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float51);
137
+DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float52sign);
138
+DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float62);
139
+DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(long5);
140
+
141
+#define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data, ...)           DRAW_BOOL_SETTING(sel, row, pstr, data)
142
+#define lcd_implementation_drawmenu_setting_edit_accessor_bool(sel, row, pstr, pstr2, pget, pset) DRAW_BOOL_SETTING(sel, row, pstr, data)
122 143
 
123 144
 ////////////////////////////////////////////
124 145
 /////////////// Menu Actions ///////////////
125 146
 ////////////////////////////////////////////
126 147
 
127
-#define menu_action_back(dummy) _menu_action_back()
128
-void _menu_action_back();
129
-void menu_action_submenu(screenFunc_t data);
130
-void menu_action_function(menuAction_t data);
131
-void menu_action_gcode(const char* pgcode);
148
+class menu_item_back {
149
+  public:
150
+    static inline void action() { lcd_goto_previous_menu(); }
151
+};
152
+
153
+class menu_item_submenu {
154
+  public:
155
+    static inline void action(const screenFunc_t func) { lcd_save_previous_screen(); lcd_goto_screen(func); }
156
+};
157
+
158
+class menu_item_gcode {
159
+  public:
160
+    static void action(const char * const pgcode);
161
+};
162
+
163
+class menu_item_function {
164
+  public:
165
+    static inline void action(const menuAction_t func) { (*func)(); };
166
+};
132 167
 
133 168
 ////////////////////////////////////////////
134 169
 /////////// Menu Editing Actions ///////////
135 170
 ////////////////////////////////////////////
136 171
 
137
-#define DECLARE_MENU_EDIT_TYPE(TYPE, NAME) \
138
-  bool _menu_edit_ ## NAME(); \
139
-  void menu_edit_ ## NAME(); \
140
-  void menu_edit_callback_ ## NAME(); \
141
-  void _menu_action_setting_edit_ ## NAME(PGM_P const pstr, TYPE* const ptr, const TYPE minValue, const TYPE maxValue); \
142
-  void menu_action_setting_edit_callback_ ## NAME(PGM_P const pstr, TYPE * const ptr, const TYPE minValue, const TYPE maxValue, const screenFunc_t callback=NULL, const bool live=false); \
143
-  FORCE_INLINE void menu_action_setting_edit_ ## NAME(PGM_P const pstr, TYPE * const ptr, const TYPE minValue, const TYPE maxValue) { \
144
-    menu_action_setting_edit_callback_ ## NAME(pstr, ptr, minValue, maxValue); \
145
-  } \
146
-  typedef void NAME##_void
147
-
148
-DECLARE_MENU_EDIT_TYPE(int16_t, int3);
149
-DECLARE_MENU_EDIT_TYPE(int16_t, int4);
150
-DECLARE_MENU_EDIT_TYPE(uint8_t, int8);
151
-DECLARE_MENU_EDIT_TYPE(float, float3);
152
-DECLARE_MENU_EDIT_TYPE(float, float52);
153
-DECLARE_MENU_EDIT_TYPE(float, float43);
154
-DECLARE_MENU_EDIT_TYPE(float, float5);
155
-DECLARE_MENU_EDIT_TYPE(float, float51);
156
-DECLARE_MENU_EDIT_TYPE(float, float52sign);
157
-DECLARE_MENU_EDIT_TYPE(float, float62);
158
-DECLARE_MENU_EDIT_TYPE(uint32_t, long5);
159
-
160
-void menu_action_setting_edit_bool(PGM_P pstr, bool* ptr);
161
-void menu_action_setting_edit_callback_bool(PGM_P pstr, bool* ptr, screenFunc_t callbackFunc);
172
+class menu_item_invariants {
173
+  protected:
174
+    typedef char* (*strfunc_t)(const int32_t);
175
+    typedef void (*loadfunc_t)(void *, const int32_t);
176
+    static void init(PGM_P const el, void * const ev, const int32_t minv, const int32_t maxv, const uint32_t ep, const screenFunc_t cs, const screenFunc_t cb, const bool le);
177
+    static void edit(strfunc_t, loadfunc_t);
178
+};
179
+
180
+template<typename NAME>
181
+class menu_item_template : menu_item_invariants {
182
+  private:
183
+    typedef typename NAME::type_t type_t;
184
+    inline static float unscale(const float value)    {return value * (1.0f / NAME::scale);}
185
+    inline static float scale(const float value)      {return value * NAME::scale;}
186
+    static void  load(void *ptr, const int32_t value) {*((type_t*)ptr) = unscale(value);}
187
+    static char* to_string(const int32_t value)       {return NAME::strfunc(unscale(value));}
188
+  public:
189
+    static void action_setting_edit(PGM_P const pstr, type_t * const ptr, const type_t minValue, const type_t maxValue, const screenFunc_t callback=NULL, const bool live=false) {
190
+      const int32_t minv = scale(minValue);
191
+      init(pstr, ptr, minv, int32_t(scale(maxValue)) - minv, int32_t(scale(*ptr)) - minv, edit, callback, live);
192
+    }
193
+    static void edit() {menu_item_invariants::edit(to_string, load);}
194
+};
195
+
196
+#define DECLARE_MENU_EDIT_ITEM(NAME) typedef menu_item_template<NAME ## _item_info> menu_item_ ## NAME;
197
+
198
+DECLARE_MENU_EDIT_ITEM(int3);
199
+DECLARE_MENU_EDIT_ITEM(int4);
200
+DECLARE_MENU_EDIT_ITEM(int8);
201
+DECLARE_MENU_EDIT_ITEM(float3);
202
+DECLARE_MENU_EDIT_ITEM(float52);
203
+DECLARE_MENU_EDIT_ITEM(float43);
204
+DECLARE_MENU_EDIT_ITEM(float5);
205
+DECLARE_MENU_EDIT_ITEM(float51);
206
+DECLARE_MENU_EDIT_ITEM(float52sign);
207
+DECLARE_MENU_EDIT_ITEM(float62);
208
+DECLARE_MENU_EDIT_ITEM(long5);
209
+
210
+class menu_item_bool {
211
+  public:
212
+    static void action_setting_edit(PGM_P pstr, bool* ptr, const screenFunc_t callbackFunc=NULL);
213
+};
162 214
 
163 215
 ////////////////////////////////////////////
164 216
 //////////// Menu System Macros ////////////
@@ -226,101 +278,80 @@ void menu_action_setting_edit_callback_bool(PGM_P pstr, bool* ptr, screenFunc_t
226 278
 
227 279
   extern bool encoderRateMultiplierEnabled;
228 280
   #define ENCODER_RATE_MULTIPLY(F) (encoderRateMultiplierEnabled = F)
229
-
281
+  #define _MENU_ITEM_MULTIPLIER_CHECK(USE_MULTIPLIER) if(USE_MULTIPLIER) {encoderRateMultiplierEnabled = true; lastEncoderMovementMillis = 0;}
230 282
   //#define ENCODER_RATE_MULTIPLIER_DEBUG  // If defined, output the encoder steps per second value
231
-
232
-  /**
233
-   * MENU_MULTIPLIER_ITEM generates drawing and handling code for a multiplier menu item
234
-   */
235
-  #define MENU_MULTIPLIER_ITEM(TYPE, LABEL, ...) do { \
236
-      _MENU_ITEM_PART_1(TYPE, ## __VA_ARGS__); \
237
-      encoderRateMultiplierEnabled = true; \
238
-      lastEncoderMovementMillis = 0; \
239
-      _MENU_ITEM_PART_2(TYPE, PSTR(LABEL), ## __VA_ARGS__); \
240
-    }while(0)
241
-
242 283
 #else // !ENCODER_RATE_MULTIPLIER
243 284
   #define ENCODER_RATE_MULTIPLY(F) NOOP
285
+  #define _MENU_ITEM_MULTIPLIER_CHECK(USE_MULTIPLIER)
244 286
 #endif // !ENCODER_RATE_MULTIPLIER
245 287
 
246 288
 /**
247 289
  * MENU_ITEM generates draw & handler code for a menu item, potentially calling:
248 290
  *
249
- *   lcd_implementation_drawmenu_[type](sel, row, label, arg3...)
250
- *   menu_action_[type](arg3...)
291
+ *   lcd_implementation_drawmenu_<type>[_variant](sel, row, label, arg3...)
292
+ *   menu_item_<type>::action[_variant](arg3...)
251 293
  *
252 294
  * Examples:
253 295
  *   MENU_ITEM(back, MSG_WATCH, 0 [dummy parameter] )
254 296
  *   or
255 297
  *   MENU_BACK(MSG_WATCH)
256 298
  *     lcd_implementation_drawmenu_back(sel, row, PSTR(MSG_WATCH))
257
- *     menu_action_back()
299
+ *     menu_item_back::action()
258 300
  *
259 301
  *   MENU_ITEM(function, MSG_PAUSE_PRINT, lcd_sdcard_pause)
260 302
  *     lcd_implementation_drawmenu_function(sel, row, PSTR(MSG_PAUSE_PRINT), lcd_sdcard_pause)
261
- *     menu_action_function(lcd_sdcard_pause)
303
+ *     menu_item_function::action(lcd_sdcard_pause)
262 304
  *
263 305
  *   MENU_ITEM_EDIT(int3, MSG_SPEED, &feedrate_percentage, 10, 999)
264
- *   MENU_ITEM(setting_edit_int3, MSG_SPEED, PSTR(MSG_SPEED), &feedrate_percentage, 10, 999)
265 306
  *     lcd_implementation_drawmenu_setting_edit_int3(sel, row, PSTR(MSG_SPEED), PSTR(MSG_SPEED), &feedrate_percentage, 10, 999)
266
- *     menu_action_setting_edit_int3(PSTR(MSG_SPEED), &feedrate_percentage, 10, 999)
307
+ *     menu_item_int3::action_setting_edit(PSTR(MSG_SPEED), &feedrate_percentage, 10, 999)
267 308
  *
268 309
  */
269
-#define _MENU_ITEM_PART_1(TYPE, ...) \
270
-  if (_menuLineNr == _thisItemNr) { \
271
-    if (encoderLine == _thisItemNr && lcd_clicked) { \
272
-      lcd_clicked = false
273
-
274
-#define _MENU_ITEM_PART_2(TYPE, PLABEL, ...) \
275
-      menu_action_ ## TYPE(__VA_ARGS__); \
276
-      if (screen_changed) return; \
277
-    } \
278
-    if (lcdDrawUpdate) \
279
-      lcd_implementation_drawmenu_ ## TYPE(encoderLine == _thisItemNr, _lcdLineNr, PLABEL, ## __VA_ARGS__); \
280
-  } \
281
-  ++_thisItemNr
282
-
283
-#define MENU_ITEM_P(TYPE, PLABEL, ...) do { \
310
+#define _MENU_ITEM_VARIANT_P(TYPE, VARIANT, USE_MULTIPLIER, PLABEL, ...) do { \
284 311
     _skipStatic = false; \
285
-    _MENU_ITEM_PART_1(TYPE, ## __VA_ARGS__); \
286
-    _MENU_ITEM_PART_2(TYPE, PLABEL, ## __VA_ARGS__); \
287
-  }while(0)
288
-
289
-#define MENU_ITEM(TYPE, LABEL, ...) MENU_ITEM_P(TYPE, PSTR(LABEL), ## __VA_ARGS__)
290
-
291
-#define MENU_ITEM_ADDON_START(X) \
292
-  if (lcdDrawUpdate && _menuLineNr == _thisItemNr - 1) { \
293
-    SETCURSOR(X, _lcdLineNr)
294
-
295
-#define MENU_ITEM_ADDON_END() } (0)
296
-
297
-#define MENU_BACK(LABEL) MENU_ITEM(back, LABEL, 0)
312
+    if (_menuLineNr == _thisItemNr) { \
313
+      if (encoderLine == _thisItemNr && lcd_clicked) { \
314
+        lcd_clicked = false; \
315
+        _MENU_ITEM_MULTIPLIER_CHECK(USE_MULTIPLIER); \
316
+        menu_item_ ## TYPE ::action ## VARIANT(__VA_ARGS__); \
317
+        if (screen_changed) return; \
318
+      } \
319
+      if (lcdDrawUpdate) \
320
+        lcd_implementation_drawmenu ## VARIANT ## _ ## TYPE(encoderLine == _thisItemNr, _lcdLineNr, PLABEL, ## __VA_ARGS__); \
321
+    } \
322
+  ++_thisItemNr; \
323
+}while(0)
298 324
 
299 325
 // Used to print static text with no visible cursor.
300 326
 // Parameters: label [, bool center [, bool invert [, char *value] ] ]
301
-#define STATIC_ITEM_P(LABEL, ...) do{ \
327
+#define STATIC_ITEM_P(PLABEL, ...) do{ \
302 328
   if (_menuLineNr == _thisItemNr) { \
303 329
     if (_skipStatic && encoderLine <= _thisItemNr) { \
304 330
       encoderPosition += ENCODER_STEPS_PER_MENU_ITEM; \
305 331
       ++encoderLine; \
306 332
     } \
307 333
     if (lcdDrawUpdate) \
308
-      lcd_implementation_drawmenu_static(_lcdLineNr, LABEL, ## __VA_ARGS__); \
334
+      lcd_implementation_drawmenu_static(_lcdLineNr, PLABEL, ## __VA_ARGS__); \
309 335
   } \
310
-  ++_thisItemNr; } while(0)
336
+  ++_thisItemNr; \
337
+} while(0)
338
+
339
+#define MENU_ITEM_ADDON_START(X) \
340
+  if (lcdDrawUpdate && _menuLineNr == _thisItemNr - 1) { \
341
+    SETCURSOR(X, _lcdLineNr)
342
+
343
+#define MENU_ITEM_ADDON_END() } (0)
311 344
 
312 345
 #define STATIC_ITEM(LABEL, ...) STATIC_ITEM_P(PSTR(LABEL), ## __VA_ARGS__)
313 346
 
347
+#define MENU_BACK(LABEL) MENU_ITEM(back, LABEL)
314 348
 #define MENU_ITEM_DUMMY() do { _thisItemNr++; }while(0)
315
-#define MENU_ITEM_EDIT(TYPE, LABEL, ...) MENU_ITEM(_CAT(setting_edit_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__)
316
-#define MENU_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) MENU_ITEM(_CAT(setting_edit_callback_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__)
317
-#if ENABLED(ENCODER_RATE_MULTIPLIER)
318
-  #define MENU_MULTIPLIER_ITEM_EDIT(TYPE, LABEL, ...) MENU_MULTIPLIER_ITEM(_CAT(setting_edit_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__)
319
-  #define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) MENU_MULTIPLIER_ITEM(_CAT(setting_edit_callback_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__)
320
-#else // !ENCODER_RATE_MULTIPLIER
321
-  #define MENU_MULTIPLIER_ITEM_EDIT(TYPE, LABEL, ...) MENU_ITEM(_CAT(setting_edit_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__)
322
-  #define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) MENU_ITEM(_CAT(setting_edit_callback_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__)
323
-#endif // !ENCODER_RATE_MULTIPLIER
349
+#define MENU_ITEM_P(TYPE, PLABEL, ...)                       _MENU_ITEM_VARIANT_P(TYPE,              , 0, PLABEL,                   ## __VA_ARGS__)
350
+#define MENU_ITEM(TYPE, LABEL, ...)                          _MENU_ITEM_VARIANT_P(TYPE,              , 0, PSTR(LABEL),              ## __VA_ARGS__)
351
+#define MENU_ITEM_EDIT(TYPE, LABEL, ...)                     _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 0, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
352
+#define MENU_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...)            _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 0, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
353
+#define MENU_MULTIPLIER_ITEM_EDIT(TYPE, LABEL, ...)          _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 1, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
354
+#define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 1, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
324 355
 
325 356
 ////////////////////////////////////////////
326 357
 /////////////// Menu Screens ///////////////

+ 25
- 19
Marlin/src/lcd/menu/menu_sdcard.cpp View File

@@ -71,25 +71,31 @@ void lcd_sd_updir() {
71 71
   }
72 72
 #endif
73 73
 
74
-void menu_action_sdfile(CardReader &theCard) {
75
-  #if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
76
-    last_sdfile_encoderPosition = encoderPosition;  // Save which file was selected for later use
77
-  #endif
78
-  card.openAndPrintFile(theCard.filename);
79
-  lcd_return_to_status();
80
-  lcd_reset_status();
81
-}
82
-
83
-void menu_action_sddirectory(CardReader &theCard) {
84
-  card.chdir(theCard.filename);
85
-  encoderTopLine = 0;
86
-  encoderPosition = 2 * ENCODER_STEPS_PER_MENU_ITEM;
87
-  screen_changed = true;
88
-  #if HAS_GRAPHICAL_LCD
89
-    drawing_screen = false;
90
-  #endif
91
-  lcd_refresh();
92
-}
74
+class menu_item_sdfile {
75
+  public:
76
+    static void action(CardReader &theCard) {
77
+      #if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
78
+        last_sdfile_encoderPosition = encoderPosition;  // Save which file was selected for later use
79
+      #endif
80
+      card.openAndPrintFile(theCard.filename);
81
+      lcd_return_to_status();
82
+      lcd_reset_status();
83
+    }
84
+};
85
+
86
+class menu_item_sddirectory {
87
+  public:
88
+    static void action(CardReader &theCard) {
89
+      card.chdir(theCard.filename);
90
+      encoderTopLine = 0;
91
+      encoderPosition = 2 * ENCODER_STEPS_PER_MENU_ITEM;
92
+      screen_changed = true;
93
+      #if HAS_GRAPHICAL_LCD
94
+        drawing_screen = false;
95
+      #endif
96
+      lcd_refresh();
97
+    }
98
+};
93 99
 
94 100
 void menu_sdcard() {
95 101
   ENCODER_DIRECTION_MENUS();

+ 1
- 1
Marlin/src/lcd/ultralcd.h View File

@@ -279,7 +279,7 @@
279 279
     typedef void (*screenFunc_t)();
280 280
     typedef void (*menuAction_t)();
281 281
     extern screenFunc_t currentScreen;
282
-    void lcd_goto_screen(screenFunc_t screen, const uint32_t encoder=0);
282
+    void lcd_goto_screen(const screenFunc_t screen, const uint32_t encoder=0);
283 283
 
284 284
     extern bool lcd_clicked, defer_return_to_status;
285 285
 

Loading…
Cancel
Save