LCD menu code refactoring and cleanup (#12308)
This commit is contained in:
		
				
					committed by
					
						 Scott Lahteine
						Scott Lahteine
					
				
			
			
				
	
			
			
			
						parent
						
							b3b4e6dc45
						
					
				
				
					commit
					8517d5f915
				
			| @@ -106,10 +106,7 @@ void lcd_goto_previous_menu_no_defer() { | ||||
| /////////// Common Menu Actions //////////// | ||||
| //////////////////////////////////////////// | ||||
|  | ||||
| void _menu_action_back() { lcd_goto_previous_menu(); } | ||||
| void menu_action_submenu(screenFunc_t func) { lcd_save_previous_screen(); lcd_goto_screen(func); } | ||||
| void menu_action_gcode(PGM_P pgcode) { enqueue_and_echo_commands_P(pgcode); } | ||||
| void menu_action_function(screenFunc_t func) { (*func)(); } | ||||
| void menu_item_gcode::action(PGM_P pgcode) { enqueue_and_echo_commands_P(pgcode); } | ||||
|  | ||||
| //////////////////////////////////////////// | ||||
| /////////// Menu Editing Actions /////////// | ||||
| @@ -118,76 +115,71 @@ void menu_action_function(screenFunc_t func) { (*func)(); } | ||||
| /** | ||||
|  * Functions for editing single values | ||||
|  * | ||||
|  * The "DEFINE_MENU_EDIT_TYPE" macro generates the functions needed to edit a numerical value. | ||||
|  * The "DEFINE_MENU_EDIT_ITEM" macro generates the functions needed to edit a numerical value. | ||||
|  * | ||||
|  * For example, DEFINE_MENU_EDIT_TYPE(int16_t, int3, itostr3, 1) expands into these functions: | ||||
|  * The prerequisite is that in the header the type was already declared: | ||||
|  * | ||||
|  *   bool _menu_edit_int3(); | ||||
|  *   void menu_edit_int3(); // edit int16_t (interactively) | ||||
|  *   void menu_edit_callback_int3(); // edit int16_t (interactively) with callback on completion | ||||
|  *   void _menu_action_setting_edit_int3(PGM_P const pstr, int16_t * const ptr, const int16_t minValue, const int16_t maxValue); | ||||
|  *   void menu_action_setting_edit_int3(PGM_P const pstr, int16_t * const ptr, const int16_t minValue, const int16_t maxValue); | ||||
|  *   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 | ||||
|  *   DECLARE_MENU_EDIT_TYPE(int16_t, int3, itostr3, 1) | ||||
|  * | ||||
|  * For example, DEFINE_MENU_EDIT_ITEM(int3) expands into these functions: | ||||
|  * | ||||
|  *   bool menu_item_int3::_edit(); | ||||
|  *   void menu_item_int3::edit(); // edit int16_t (interactively) | ||||
|  *   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); | ||||
|  * | ||||
|  * You can then use one of the menu macros to present the edit interface: | ||||
|  *   MENU_ITEM_EDIT(int3, MSG_SPEED, &feedrate_percentage, 10, 999) | ||||
|  * | ||||
|  * This expands into a more primitive menu item: | ||||
|  *   MENU_ITEM(setting_edit_int3, MSG_SPEED, PSTR(MSG_SPEED), &feedrate_percentage, 10, 999) | ||||
|  *   MENU_ITEM_VARIANT(int3, _setting_edit, MSG_SPEED, PSTR(MSG_SPEED), &feedrate_percentage, 10, 999) | ||||
|  * | ||||
|  * ...which calls: | ||||
|  *       menu_action_setting_edit_int3(PSTR(MSG_SPEED), &feedrate_percentage, 10, 999) | ||||
|  *       menu_item_int3::action_setting_edit(PSTR(MSG_SPEED), &feedrate_percentage, 10, 999) | ||||
|  */ | ||||
| #define DEFINE_MENU_EDIT_TYPE(TYPE, NAME, STRFUNC, SCALE) \ | ||||
|   bool _menu_edit_ ## NAME() { \ | ||||
|     ENCODER_DIRECTION_NORMAL(); \ | ||||
|     if ((int32_t)encoderPosition < 0) encoderPosition = 0; \ | ||||
|     if ((int32_t)encoderPosition > maxEditValue) encoderPosition = maxEditValue; \ | ||||
|     if (lcdDrawUpdate) \ | ||||
|       lcd_implementation_drawedit(editLabel, STRFUNC(((TYPE)((int32_t)encoderPosition + minEditValue)) * (1.0f / SCALE))); \ | ||||
|     if (lcd_clicked || (liveEdit && lcdDrawUpdate)) { \ | ||||
|       TYPE value = ((TYPE)((int32_t)encoderPosition + minEditValue)) * (1.0f / SCALE); \ | ||||
|       if (editValue != NULL) *((TYPE*)editValue) = value; \ | ||||
|       if (callbackFunc && (liveEdit || lcd_clicked)) (*callbackFunc)(); \ | ||||
|       if (lcd_clicked) lcd_goto_previous_menu(); \ | ||||
|     } \ | ||||
|     return use_click(); \ | ||||
|   } \ | ||||
|   void menu_edit_ ## NAME() { _menu_edit_ ## NAME(); } \ | ||||
|   void _menu_action_setting_edit_ ## NAME(PGM_P const pstr, TYPE* const ptr, const TYPE minValue, const TYPE maxValue) { \ | ||||
|     lcd_save_previous_screen(); \ | ||||
|     lcd_refresh(); \ | ||||
|     \ | ||||
|     editLabel = pstr; \ | ||||
|     editValue = ptr; \ | ||||
|     minEditValue = minValue * SCALE; \ | ||||
|     maxEditValue = maxValue * SCALE - minEditValue; \ | ||||
|     encoderPosition = (*ptr) * SCALE - minEditValue; \ | ||||
|   } \ | ||||
|   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*/) { \ | ||||
|     _menu_action_setting_edit_ ## NAME(pstr, ptr, minValue, maxValue); \ | ||||
|     currentScreen = menu_edit_ ## NAME; \ | ||||
|     callbackFunc = callback; \ | ||||
|     liveEdit = live; \ | ||||
|   } \ | ||||
|   typedef void NAME##_void | ||||
| void menu_item_invariants::edit(strfunc_t strfunc, loadfunc_t loadfunc) { | ||||
|   ENCODER_DIRECTION_NORMAL(); | ||||
|   if ((int32_t)encoderPosition < 0) encoderPosition = 0; | ||||
|   if ((int32_t)encoderPosition > maxEditValue) encoderPosition = maxEditValue; | ||||
|   if (lcdDrawUpdate) | ||||
|     lcd_implementation_drawedit(editLabel, strfunc(encoderPosition + minEditValue)); | ||||
|   if (lcd_clicked || (liveEdit && lcdDrawUpdate)) { | ||||
|     if (editValue != NULL) loadfunc(editValue, encoderPosition + minEditValue); | ||||
|     if (callbackFunc && (liveEdit || lcd_clicked)) (*callbackFunc)(); | ||||
|     if (lcd_clicked) lcd_goto_previous_menu(); | ||||
|     lcd_clicked = false; | ||||
|   } | ||||
| } | ||||
|  | ||||
| DEFINE_MENU_EDIT_TYPE(int16_t, int3, itostr3, 1); | ||||
| DEFINE_MENU_EDIT_TYPE(int16_t, int4, itostr4sign, 1); | ||||
| DEFINE_MENU_EDIT_TYPE(uint8_t, int8, i8tostr3, 1); | ||||
| DEFINE_MENU_EDIT_TYPE(float, float3, ftostr3, 1); | ||||
| DEFINE_MENU_EDIT_TYPE(float, float52, ftostr52, 100); | ||||
| DEFINE_MENU_EDIT_TYPE(float, float43, ftostr43sign, 1000); | ||||
| DEFINE_MENU_EDIT_TYPE(float, float5, ftostr5rj, 0.01f); | ||||
| DEFINE_MENU_EDIT_TYPE(float, float51, ftostr51sign, 10); | ||||
| DEFINE_MENU_EDIT_TYPE(float, float52sign, ftostr52sign, 100); | ||||
| DEFINE_MENU_EDIT_TYPE(float, float62, ftostr62rj, 100); | ||||
| DEFINE_MENU_EDIT_TYPE(uint32_t, long5, ftostr5rj, 0.01f); | ||||
| 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) { | ||||
|   lcd_save_previous_screen(); | ||||
|   lcd_refresh(); | ||||
|   editLabel = el; | ||||
|   editValue = ev; | ||||
|   minEditValue = minv; | ||||
|   maxEditValue = maxv; | ||||
|   encoderPosition = ep; | ||||
|   currentScreen = cs; | ||||
|   callbackFunc = cb; | ||||
|   liveEdit = le; | ||||
| } | ||||
|  | ||||
| void menu_action_setting_edit_bool(PGM_P pstr, bool* ptr) { UNUSED(pstr); *ptr ^= true; lcd_refresh(); } | ||||
| void menu_action_setting_edit_callback_bool(PGM_P pstr, bool* ptr, screenFunc_t callback) { | ||||
|   menu_action_setting_edit_bool(pstr, ptr); | ||||
|   (*callback)(); | ||||
| #define DEFINE_MENU_EDIT_ITEM(NAME) template class menu_item_template<NAME ## _item_info>; | ||||
|  | ||||
| DEFINE_MENU_EDIT_ITEM(int3); | ||||
| DEFINE_MENU_EDIT_ITEM(int4); | ||||
| DEFINE_MENU_EDIT_ITEM(int8); | ||||
| DEFINE_MENU_EDIT_ITEM(float3); | ||||
| DEFINE_MENU_EDIT_ITEM(float52); | ||||
| DEFINE_MENU_EDIT_ITEM(float43); | ||||
| DEFINE_MENU_EDIT_ITEM(float5); | ||||
| DEFINE_MENU_EDIT_ITEM(float51); | ||||
| DEFINE_MENU_EDIT_ITEM(float52sign); | ||||
| DEFINE_MENU_EDIT_ITEM(float62); | ||||
| DEFINE_MENU_EDIT_ITEM(long5); | ||||
|  | ||||
| void menu_item_bool::action_setting_edit(PGM_P pstr, bool *ptr, screenFunc_t callback) { | ||||
|   UNUSED(pstr); *ptr ^= true; lcd_refresh(); | ||||
|   if (callback) (*callback)(); | ||||
| } | ||||
|  | ||||
| //////////////////////////////////////////// | ||||
|   | ||||
| @@ -37,6 +37,30 @@ bool printer_busy(); | ||||
| void lcd_completion_feedback(const bool good=true); | ||||
| void lcd_goto_previous_menu(); | ||||
| void lcd_goto_previous_menu_no_defer(); | ||||
| void lcd_save_previous_screen(); | ||||
|  | ||||
| //////////////////////////////////////////// | ||||
| ////////// Menu Item Numeric Types ///////// | ||||
| //////////////////////////////////////////// | ||||
|  | ||||
| #define DECLARE_MENU_EDIT_TYPE(TYPE, NAME, STRFUNC, SCALE) \ | ||||
|   struct NAME ## _item_info { \ | ||||
|     typedef TYPE type_t; \ | ||||
|     static constexpr float scale = SCALE; \ | ||||
|     static inline char* strfunc(const float value) { return STRFUNC((TYPE) value); } \ | ||||
|   }; | ||||
|  | ||||
| DECLARE_MENU_EDIT_TYPE(int16_t, int3, itostr3, 1); | ||||
| DECLARE_MENU_EDIT_TYPE(int16_t, int4, itostr4sign, 1); | ||||
| DECLARE_MENU_EDIT_TYPE(uint8_t, int8, i8tostr3, 1); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float3, ftostr3, 1); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float52, ftostr52, 100); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float43, ftostr43sign, 1000); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float5, ftostr5rj, 0.01f); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float51, ftostr51sign, 10); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float52sign, ftostr52sign, 100); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float62, ftostr62rj, 100); | ||||
| DECLARE_MENU_EDIT_TYPE(uint32_t, long5, ftostr5rj, 0.01f); | ||||
|  | ||||
| //////////////////////////////////////////// | ||||
| ///////// Menu Item Draw Functions ///////// | ||||
| @@ -54,7 +78,7 @@ void lcd_implementation_drawedit(const char* const pstr, const char* const value | ||||
| #endif | ||||
| #if HAS_GRAPHICAL_LCD | ||||
|   void _drawmenu_setting_edit_generic(const bool isSelected, const uint8_t row, const char* pstr, const char* const data, const bool pgm); | ||||
|   #define lcd_implementation_drawmenu_back(sel, row, pstr, dummy) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0]) | ||||
|   #define lcd_implementation_drawmenu_back(sel, row, pstr) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0]) | ||||
|   #define lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, false) | ||||
|   #define lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, true) | ||||
|   #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 | ||||
|     void _lcd_zoffset_overlay_gfx(const float zvalue); | ||||
|   #endif | ||||
| #else | ||||
|   #define lcd_implementation_drawmenu_back(sel, row, pstr, dummy) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_UPLEVEL_CHAR, LCD_UPLEVEL_CHAR) | ||||
|   #define lcd_implementation_drawmenu_back(sel, row, pstr) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_UPLEVEL_CHAR, LCD_UPLEVEL_CHAR) | ||||
|   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); | ||||
|   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); | ||||
|   #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 | ||||
| /////// Edit Setting Draw Functions //////// | ||||
| //////////////////////////////////////////// | ||||
|  | ||||
| #define DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(TYPE, NAME, STRFUNC) \ | ||||
| #define _DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(TYPE, NAME, STRFUNC) \ | ||||
|   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, ...) { \ | ||||
|     UNUSED(pstr2); \ | ||||
|     DRAWMENU_SETTING_EDIT_GENERIC(STRFUNC(*(data))); \ | ||||
|   } \ | ||||
|   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, ...) { \ | ||||
|     UNUSED(pstr2); \ | ||||
|     DRAWMENU_SETTING_EDIT_GENERIC(STRFUNC(*(data))); \ | ||||
|   } \ | ||||
|   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), ...) { \ | ||||
|     UNUSED(pstr2); UNUSED(pset); \ | ||||
|     DRAWMENU_SETTING_EDIT_GENERIC(STRFUNC(pget())); \ | ||||
|   } \ | ||||
|   typedef void NAME##_void | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(int16_t, int3, itostr3); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(int16_t, int4, itostr4sign); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(uint8_t, int8, i8tostr3); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float3, ftostr3); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float52, ftostr52); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float43, ftostr43sign); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float5, ftostr5rj); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float51, ftostr51sign); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float52sign, ftostr52sign); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float, float62, ftostr62rj); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(uint32_t, long5, ftostr5rj); | ||||
| #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) | ||||
|  | ||||
| #define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data)                    DRAW_BOOL_SETTING(sel, row, pstr, data) | ||||
| #define lcd_implementation_drawmenu_setting_edit_callback_bool(sel, row, pstr, pstr2, data, callback) DRAW_BOOL_SETTING(sel, row, pstr, data) | ||||
| #define lcd_implementation_drawmenu_setting_edit_accessor_bool(sel, row, pstr, pstr2, pget, pset)     DRAW_BOOL_SETTING(sel, row, pstr, data) | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(int3); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(int4); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(int8); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float3); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float52); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float43); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float5); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float51); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float52sign); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(float62); | ||||
| DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(long5); | ||||
|  | ||||
| #define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data, ...)           DRAW_BOOL_SETTING(sel, row, pstr, data) | ||||
| #define lcd_implementation_drawmenu_setting_edit_accessor_bool(sel, row, pstr, pstr2, pget, pset) DRAW_BOOL_SETTING(sel, row, pstr, data) | ||||
|  | ||||
| //////////////////////////////////////////// | ||||
| /////////////// Menu Actions /////////////// | ||||
| //////////////////////////////////////////// | ||||
|  | ||||
| #define menu_action_back(dummy) _menu_action_back() | ||||
| void _menu_action_back(); | ||||
| void menu_action_submenu(screenFunc_t data); | ||||
| void menu_action_function(menuAction_t data); | ||||
| void menu_action_gcode(const char* pgcode); | ||||
| class menu_item_back { | ||||
|   public: | ||||
|     static inline void action() { lcd_goto_previous_menu(); } | ||||
| }; | ||||
|  | ||||
| class menu_item_submenu { | ||||
|   public: | ||||
|     static inline void action(const screenFunc_t func) { lcd_save_previous_screen(); lcd_goto_screen(func); } | ||||
| }; | ||||
|  | ||||
| class menu_item_gcode { | ||||
|   public: | ||||
|     static void action(const char * const pgcode); | ||||
| }; | ||||
|  | ||||
| class menu_item_function { | ||||
|   public: | ||||
|     static inline void action(const menuAction_t func) { (*func)(); }; | ||||
| }; | ||||
|  | ||||
| //////////////////////////////////////////// | ||||
| /////////// Menu Editing Actions /////////// | ||||
| //////////////////////////////////////////// | ||||
|  | ||||
| #define DECLARE_MENU_EDIT_TYPE(TYPE, NAME) \ | ||||
|   bool _menu_edit_ ## NAME(); \ | ||||
|   void menu_edit_ ## NAME(); \ | ||||
|   void menu_edit_callback_ ## NAME(); \ | ||||
|   void _menu_action_setting_edit_ ## NAME(PGM_P const pstr, TYPE* const ptr, const TYPE minValue, const TYPE maxValue); \ | ||||
|   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); \ | ||||
|   FORCE_INLINE void menu_action_setting_edit_ ## NAME(PGM_P const pstr, TYPE * const ptr, const TYPE minValue, const TYPE maxValue) { \ | ||||
|     menu_action_setting_edit_callback_ ## NAME(pstr, ptr, minValue, maxValue); \ | ||||
|   } \ | ||||
|   typedef void NAME##_void | ||||
| class menu_item_invariants { | ||||
|   protected: | ||||
|     typedef char* (*strfunc_t)(const int32_t); | ||||
|     typedef void (*loadfunc_t)(void *, const int32_t); | ||||
|     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); | ||||
|     static void edit(strfunc_t, loadfunc_t); | ||||
| }; | ||||
|  | ||||
| DECLARE_MENU_EDIT_TYPE(int16_t, int3); | ||||
| DECLARE_MENU_EDIT_TYPE(int16_t, int4); | ||||
| DECLARE_MENU_EDIT_TYPE(uint8_t, int8); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float3); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float52); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float43); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float5); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float51); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float52sign); | ||||
| DECLARE_MENU_EDIT_TYPE(float, float62); | ||||
| DECLARE_MENU_EDIT_TYPE(uint32_t, long5); | ||||
| template<typename NAME> | ||||
| class menu_item_template : menu_item_invariants { | ||||
|   private: | ||||
|     typedef typename NAME::type_t type_t; | ||||
|     inline static float unscale(const float value)    {return value * (1.0f / NAME::scale);} | ||||
|     inline static float scale(const float value)      {return value * NAME::scale;} | ||||
|     static void  load(void *ptr, const int32_t value) {*((type_t*)ptr) = unscale(value);} | ||||
|     static char* to_string(const int32_t value)       {return NAME::strfunc(unscale(value));} | ||||
|   public: | ||||
|     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) { | ||||
|       const int32_t minv = scale(minValue); | ||||
|       init(pstr, ptr, minv, int32_t(scale(maxValue)) - minv, int32_t(scale(*ptr)) - minv, edit, callback, live); | ||||
|     } | ||||
|     static void edit() {menu_item_invariants::edit(to_string, load);} | ||||
| }; | ||||
|  | ||||
| void menu_action_setting_edit_bool(PGM_P pstr, bool* ptr); | ||||
| void menu_action_setting_edit_callback_bool(PGM_P pstr, bool* ptr, screenFunc_t callbackFunc); | ||||
| #define DECLARE_MENU_EDIT_ITEM(NAME) typedef menu_item_template<NAME ## _item_info> menu_item_ ## NAME; | ||||
|  | ||||
| DECLARE_MENU_EDIT_ITEM(int3); | ||||
| DECLARE_MENU_EDIT_ITEM(int4); | ||||
| DECLARE_MENU_EDIT_ITEM(int8); | ||||
| DECLARE_MENU_EDIT_ITEM(float3); | ||||
| DECLARE_MENU_EDIT_ITEM(float52); | ||||
| DECLARE_MENU_EDIT_ITEM(float43); | ||||
| DECLARE_MENU_EDIT_ITEM(float5); | ||||
| DECLARE_MENU_EDIT_ITEM(float51); | ||||
| DECLARE_MENU_EDIT_ITEM(float52sign); | ||||
| DECLARE_MENU_EDIT_ITEM(float62); | ||||
| DECLARE_MENU_EDIT_ITEM(long5); | ||||
|  | ||||
| class menu_item_bool { | ||||
|   public: | ||||
|     static void action_setting_edit(PGM_P pstr, bool* ptr, const screenFunc_t callbackFunc=NULL); | ||||
| }; | ||||
|  | ||||
| //////////////////////////////////////////// | ||||
| //////////// Menu System Macros //////////// | ||||
| @@ -226,67 +278,63 @@ void menu_action_setting_edit_callback_bool(PGM_P pstr, bool* ptr, screenFunc_t | ||||
|  | ||||
|   extern bool encoderRateMultiplierEnabled; | ||||
|   #define ENCODER_RATE_MULTIPLY(F) (encoderRateMultiplierEnabled = F) | ||||
|  | ||||
|   #define _MENU_ITEM_MULTIPLIER_CHECK(USE_MULTIPLIER) if(USE_MULTIPLIER) {encoderRateMultiplierEnabled = true; lastEncoderMovementMillis = 0;} | ||||
|   //#define ENCODER_RATE_MULTIPLIER_DEBUG  // If defined, output the encoder steps per second value | ||||
|  | ||||
|   /** | ||||
|    * MENU_MULTIPLIER_ITEM generates drawing and handling code for a multiplier menu item | ||||
|    */ | ||||
|   #define MENU_MULTIPLIER_ITEM(TYPE, LABEL, ...) do { \ | ||||
|       _MENU_ITEM_PART_1(TYPE, ## __VA_ARGS__); \ | ||||
|       encoderRateMultiplierEnabled = true; \ | ||||
|       lastEncoderMovementMillis = 0; \ | ||||
|       _MENU_ITEM_PART_2(TYPE, PSTR(LABEL), ## __VA_ARGS__); \ | ||||
|     }while(0) | ||||
|  | ||||
| #else // !ENCODER_RATE_MULTIPLIER | ||||
|   #define ENCODER_RATE_MULTIPLY(F) NOOP | ||||
|   #define _MENU_ITEM_MULTIPLIER_CHECK(USE_MULTIPLIER) | ||||
| #endif // !ENCODER_RATE_MULTIPLIER | ||||
|  | ||||
| /** | ||||
|  * MENU_ITEM generates draw & handler code for a menu item, potentially calling: | ||||
|  * | ||||
|  *   lcd_implementation_drawmenu_[type](sel, row, label, arg3...) | ||||
|  *   menu_action_[type](arg3...) | ||||
|  *   lcd_implementation_drawmenu_<type>[_variant](sel, row, label, arg3...) | ||||
|  *   menu_item_<type>::action[_variant](arg3...) | ||||
|  * | ||||
|  * Examples: | ||||
|  *   MENU_ITEM(back, MSG_WATCH, 0 [dummy parameter] ) | ||||
|  *   or | ||||
|  *   MENU_BACK(MSG_WATCH) | ||||
|  *     lcd_implementation_drawmenu_back(sel, row, PSTR(MSG_WATCH)) | ||||
|  *     menu_action_back() | ||||
|  *     menu_item_back::action() | ||||
|  * | ||||
|  *   MENU_ITEM(function, MSG_PAUSE_PRINT, lcd_sdcard_pause) | ||||
|  *     lcd_implementation_drawmenu_function(sel, row, PSTR(MSG_PAUSE_PRINT), lcd_sdcard_pause) | ||||
|  *     menu_action_function(lcd_sdcard_pause) | ||||
|  *     menu_item_function::action(lcd_sdcard_pause) | ||||
|  * | ||||
|  *   MENU_ITEM_EDIT(int3, MSG_SPEED, &feedrate_percentage, 10, 999) | ||||
|  *   MENU_ITEM(setting_edit_int3, MSG_SPEED, PSTR(MSG_SPEED), &feedrate_percentage, 10, 999) | ||||
|  *     lcd_implementation_drawmenu_setting_edit_int3(sel, row, PSTR(MSG_SPEED), PSTR(MSG_SPEED), &feedrate_percentage, 10, 999) | ||||
|  *     menu_action_setting_edit_int3(PSTR(MSG_SPEED), &feedrate_percentage, 10, 999) | ||||
|  *     menu_item_int3::action_setting_edit(PSTR(MSG_SPEED), &feedrate_percentage, 10, 999) | ||||
|  * | ||||
|  */ | ||||
| #define _MENU_ITEM_PART_1(TYPE, ...) \ | ||||
|   if (_menuLineNr == _thisItemNr) { \ | ||||
|     if (encoderLine == _thisItemNr && lcd_clicked) { \ | ||||
|       lcd_clicked = false | ||||
| #define _MENU_ITEM_VARIANT_P(TYPE, VARIANT, USE_MULTIPLIER, PLABEL, ...) do { \ | ||||
|     _skipStatic = false; \ | ||||
|     if (_menuLineNr == _thisItemNr) { \ | ||||
|       if (encoderLine == _thisItemNr && lcd_clicked) { \ | ||||
|         lcd_clicked = false; \ | ||||
|         _MENU_ITEM_MULTIPLIER_CHECK(USE_MULTIPLIER); \ | ||||
|         menu_item_ ## TYPE ::action ## VARIANT(__VA_ARGS__); \ | ||||
|         if (screen_changed) return; \ | ||||
|       } \ | ||||
|       if (lcdDrawUpdate) \ | ||||
|         lcd_implementation_drawmenu ## VARIANT ## _ ## TYPE(encoderLine == _thisItemNr, _lcdLineNr, PLABEL, ## __VA_ARGS__); \ | ||||
|     } \ | ||||
|   ++_thisItemNr; \ | ||||
| }while(0) | ||||
|  | ||||
| #define _MENU_ITEM_PART_2(TYPE, PLABEL, ...) \ | ||||
|       menu_action_ ## TYPE(__VA_ARGS__); \ | ||||
|       if (screen_changed) return; \ | ||||
| // Used to print static text with no visible cursor. | ||||
| // Parameters: label [, bool center [, bool invert [, char *value] ] ] | ||||
| #define STATIC_ITEM_P(PLABEL, ...) do{ \ | ||||
|   if (_menuLineNr == _thisItemNr) { \ | ||||
|     if (_skipStatic && encoderLine <= _thisItemNr) { \ | ||||
|       encoderPosition += ENCODER_STEPS_PER_MENU_ITEM; \ | ||||
|       ++encoderLine; \ | ||||
|     } \ | ||||
|     if (lcdDrawUpdate) \ | ||||
|       lcd_implementation_drawmenu_ ## TYPE(encoderLine == _thisItemNr, _lcdLineNr, PLABEL, ## __VA_ARGS__); \ | ||||
|       lcd_implementation_drawmenu_static(_lcdLineNr, PLABEL, ## __VA_ARGS__); \ | ||||
|   } \ | ||||
|   ++_thisItemNr | ||||
|  | ||||
| #define MENU_ITEM_P(TYPE, PLABEL, ...) do { \ | ||||
|     _skipStatic = false; \ | ||||
|     _MENU_ITEM_PART_1(TYPE, ## __VA_ARGS__); \ | ||||
|     _MENU_ITEM_PART_2(TYPE, PLABEL, ## __VA_ARGS__); \ | ||||
|   }while(0) | ||||
|  | ||||
| #define MENU_ITEM(TYPE, LABEL, ...) MENU_ITEM_P(TYPE, PSTR(LABEL), ## __VA_ARGS__) | ||||
|   ++_thisItemNr; \ | ||||
| } while(0) | ||||
|  | ||||
| #define MENU_ITEM_ADDON_START(X) \ | ||||
|   if (lcdDrawUpdate && _menuLineNr == _thisItemNr - 1) { \ | ||||
| @@ -294,33 +342,16 @@ void menu_action_setting_edit_callback_bool(PGM_P pstr, bool* ptr, screenFunc_t | ||||
|  | ||||
| #define MENU_ITEM_ADDON_END() } (0) | ||||
|  | ||||
| #define MENU_BACK(LABEL) MENU_ITEM(back, LABEL, 0) | ||||
|  | ||||
| // Used to print static text with no visible cursor. | ||||
| // Parameters: label [, bool center [, bool invert [, char *value] ] ] | ||||
| #define STATIC_ITEM_P(LABEL, ...) do{ \ | ||||
|   if (_menuLineNr == _thisItemNr) { \ | ||||
|     if (_skipStatic && encoderLine <= _thisItemNr) { \ | ||||
|       encoderPosition += ENCODER_STEPS_PER_MENU_ITEM; \ | ||||
|       ++encoderLine; \ | ||||
|     } \ | ||||
|     if (lcdDrawUpdate) \ | ||||
|       lcd_implementation_drawmenu_static(_lcdLineNr, LABEL, ## __VA_ARGS__); \ | ||||
|   } \ | ||||
|   ++_thisItemNr; } while(0) | ||||
|  | ||||
| #define STATIC_ITEM(LABEL, ...) STATIC_ITEM_P(PSTR(LABEL), ## __VA_ARGS__) | ||||
|  | ||||
| #define MENU_BACK(LABEL) MENU_ITEM(back, LABEL) | ||||
| #define MENU_ITEM_DUMMY() do { _thisItemNr++; }while(0) | ||||
| #define MENU_ITEM_EDIT(TYPE, LABEL, ...) MENU_ITEM(_CAT(setting_edit_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__) | ||||
| #define MENU_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) MENU_ITEM(_CAT(setting_edit_callback_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__) | ||||
| #if ENABLED(ENCODER_RATE_MULTIPLIER) | ||||
|   #define MENU_MULTIPLIER_ITEM_EDIT(TYPE, LABEL, ...) MENU_MULTIPLIER_ITEM(_CAT(setting_edit_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__) | ||||
|   #define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) MENU_MULTIPLIER_ITEM(_CAT(setting_edit_callback_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__) | ||||
| #else // !ENCODER_RATE_MULTIPLIER | ||||
|   #define MENU_MULTIPLIER_ITEM_EDIT(TYPE, LABEL, ...) MENU_ITEM(_CAT(setting_edit_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__) | ||||
|   #define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) MENU_ITEM(_CAT(setting_edit_callback_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__) | ||||
| #endif // !ENCODER_RATE_MULTIPLIER | ||||
| #define MENU_ITEM_P(TYPE, PLABEL, ...)                       _MENU_ITEM_VARIANT_P(TYPE,              , 0, PLABEL,                   ## __VA_ARGS__) | ||||
| #define MENU_ITEM(TYPE, LABEL, ...)                          _MENU_ITEM_VARIANT_P(TYPE,              , 0, PSTR(LABEL),              ## __VA_ARGS__) | ||||
| #define MENU_ITEM_EDIT(TYPE, LABEL, ...)                     _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 0, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__) | ||||
| #define MENU_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...)            _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 0, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__) | ||||
| #define MENU_MULTIPLIER_ITEM_EDIT(TYPE, LABEL, ...)          _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 1, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__) | ||||
| #define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 1, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__) | ||||
|  | ||||
| //////////////////////////////////////////// | ||||
| /////////////// Menu Screens /////////////// | ||||
|   | ||||
| @@ -71,25 +71,31 @@ void lcd_sd_updir() { | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| void menu_action_sdfile(CardReader &theCard) { | ||||
|   #if ENABLED(SD_REPRINT_LAST_SELECTED_FILE) | ||||
|     last_sdfile_encoderPosition = encoderPosition;  // Save which file was selected for later use | ||||
|   #endif | ||||
|   card.openAndPrintFile(theCard.filename); | ||||
|   lcd_return_to_status(); | ||||
|   lcd_reset_status(); | ||||
| } | ||||
| class menu_item_sdfile { | ||||
|   public: | ||||
|     static void action(CardReader &theCard) { | ||||
|       #if ENABLED(SD_REPRINT_LAST_SELECTED_FILE) | ||||
|         last_sdfile_encoderPosition = encoderPosition;  // Save which file was selected for later use | ||||
|       #endif | ||||
|       card.openAndPrintFile(theCard.filename); | ||||
|       lcd_return_to_status(); | ||||
|       lcd_reset_status(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| void menu_action_sddirectory(CardReader &theCard) { | ||||
|   card.chdir(theCard.filename); | ||||
|   encoderTopLine = 0; | ||||
|   encoderPosition = 2 * ENCODER_STEPS_PER_MENU_ITEM; | ||||
|   screen_changed = true; | ||||
|   #if HAS_GRAPHICAL_LCD | ||||
|     drawing_screen = false; | ||||
|   #endif | ||||
|   lcd_refresh(); | ||||
| } | ||||
| class menu_item_sddirectory { | ||||
|   public: | ||||
|     static void action(CardReader &theCard) { | ||||
|       card.chdir(theCard.filename); | ||||
|       encoderTopLine = 0; | ||||
|       encoderPosition = 2 * ENCODER_STEPS_PER_MENU_ITEM; | ||||
|       screen_changed = true; | ||||
|       #if HAS_GRAPHICAL_LCD | ||||
|         drawing_screen = false; | ||||
|       #endif | ||||
|       lcd_refresh(); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| void menu_sdcard() { | ||||
|   ENCODER_DIRECTION_MENUS(); | ||||
|   | ||||
| @@ -279,7 +279,7 @@ | ||||
|     typedef void (*screenFunc_t)(); | ||||
|     typedef void (*menuAction_t)(); | ||||
|     extern screenFunc_t currentScreen; | ||||
|     void lcd_goto_screen(screenFunc_t screen, const uint32_t encoder=0); | ||||
|     void lcd_goto_screen(const screenFunc_t screen, const uint32_t encoder=0); | ||||
|  | ||||
|     extern bool lcd_clicked, defer_return_to_status; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user