LCD menu code refactoring and cleanup (#12308)

This commit is contained in:
Marcio Teixeira 2018-11-05 21:51:10 -07:00 committed by Scott Lahteine
parent b3b4e6dc45
commit 8517d5f915
4 changed files with 218 additions and 189 deletions

View file

@ -106,10 +106,7 @@ void lcd_goto_previous_menu_no_defer() {
/////////// Common Menu Actions //////////// /////////// Common Menu Actions ////////////
//////////////////////////////////////////// ////////////////////////////////////////////
void _menu_action_back() { lcd_goto_previous_menu(); } void menu_item_gcode::action(PGM_P pgcode) { enqueue_and_echo_commands_P(pgcode); }
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)(); }
//////////////////////////////////////////// ////////////////////////////////////////////
/////////// Menu Editing Actions /////////// /////////// Menu Editing Actions ///////////
@ -118,76 +115,71 @@ void menu_action_function(screenFunc_t func) { (*func)(); }
/** /**
* Functions for editing single values * 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(); * DECLARE_MENU_EDIT_TYPE(int16_t, int3, itostr3, 1)
* void menu_edit_int3(); // edit int16_t (interactively) *
* void menu_edit_callback_int3(); // edit int16_t (interactively) with callback on completion * For example, DEFINE_MENU_EDIT_ITEM(int3) expands into these functions:
* 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); * bool menu_item_int3::_edit();
* 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 * 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: * You can then use one of the menu macros to present the edit interface:
* MENU_ITEM_EDIT(int3, MSG_SPEED, &feedrate_percentage, 10, 999) * MENU_ITEM_EDIT(int3, MSG_SPEED, &feedrate_percentage, 10, 999)
* *
* This expands into a more primitive menu item: * 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: * ...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) \ void menu_item_invariants::edit(strfunc_t strfunc, loadfunc_t loadfunc) {
bool _menu_edit_ ## NAME() { \ ENCODER_DIRECTION_NORMAL();
ENCODER_DIRECTION_NORMAL(); \ if ((int32_t)encoderPosition < 0) encoderPosition = 0;
if ((int32_t)encoderPosition < 0) encoderPosition = 0; \ if ((int32_t)encoderPosition > maxEditValue) encoderPosition = maxEditValue;
if ((int32_t)encoderPosition > maxEditValue) encoderPosition = maxEditValue; \ if (lcdDrawUpdate)
if (lcdDrawUpdate) \ lcd_implementation_drawedit(editLabel, strfunc(encoderPosition + minEditValue));
lcd_implementation_drawedit(editLabel, STRFUNC(((TYPE)((int32_t)encoderPosition + minEditValue)) * (1.0f / SCALE))); \ if (lcd_clicked || (liveEdit && lcdDrawUpdate)) {
if (lcd_clicked || (liveEdit && lcdDrawUpdate)) { \ if (editValue != NULL) loadfunc(editValue, encoderPosition + minEditValue);
TYPE value = ((TYPE)((int32_t)encoderPosition + minEditValue)) * (1.0f / SCALE); \ if (callbackFunc && (liveEdit || lcd_clicked)) (*callbackFunc)();
if (editValue != NULL) *((TYPE*)editValue) = value; \ if (lcd_clicked) lcd_goto_previous_menu();
if (callbackFunc && (liveEdit || lcd_clicked)) (*callbackFunc)(); \ lcd_clicked = false;
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
DEFINE_MENU_EDIT_TYPE(int16_t, int3, itostr3, 1); 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) {
DEFINE_MENU_EDIT_TYPE(int16_t, int4, itostr4sign, 1); lcd_save_previous_screen();
DEFINE_MENU_EDIT_TYPE(uint8_t, int8, i8tostr3, 1); lcd_refresh();
DEFINE_MENU_EDIT_TYPE(float, float3, ftostr3, 1); editLabel = el;
DEFINE_MENU_EDIT_TYPE(float, float52, ftostr52, 100); editValue = ev;
DEFINE_MENU_EDIT_TYPE(float, float43, ftostr43sign, 1000); minEditValue = minv;
DEFINE_MENU_EDIT_TYPE(float, float5, ftostr5rj, 0.01f); maxEditValue = maxv;
DEFINE_MENU_EDIT_TYPE(float, float51, ftostr51sign, 10); encoderPosition = ep;
DEFINE_MENU_EDIT_TYPE(float, float52sign, ftostr52sign, 100); currentScreen = cs;
DEFINE_MENU_EDIT_TYPE(float, float62, ftostr62rj, 100); callbackFunc = cb;
DEFINE_MENU_EDIT_TYPE(uint32_t, long5, ftostr5rj, 0.01f); liveEdit = le;
}
void menu_action_setting_edit_bool(PGM_P pstr, bool* ptr) { UNUSED(pstr); *ptr ^= true; lcd_refresh(); } #define DEFINE_MENU_EDIT_ITEM(NAME) template class menu_item_template<NAME ## _item_info>;
void menu_action_setting_edit_callback_bool(PGM_P pstr, bool* ptr, screenFunc_t callback) {
menu_action_setting_edit_bool(pstr, ptr); DEFINE_MENU_EDIT_ITEM(int3);
(*callback)(); 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)();
} }
//////////////////////////////////////////// ////////////////////////////////////////////

View file

@ -37,6 +37,30 @@ bool printer_busy();
void lcd_completion_feedback(const bool good=true); void lcd_completion_feedback(const bool good=true);
void lcd_goto_previous_menu(); void lcd_goto_previous_menu();
void lcd_goto_previous_menu_no_defer(); 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 ///////// ///////// Menu Item Draw Functions /////////
@ -54,7 +78,7 @@ void lcd_implementation_drawedit(const char* const pstr, const char* const value
#endif #endif
#if HAS_GRAPHICAL_LCD #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); 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(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 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) #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); void _lcd_zoffset_overlay_gfx(const float zvalue);
#endif #endif
#else #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(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); 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) #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 //////// /////// 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, ...) { \ 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); \ UNUSED(pstr2); \
DRAWMENU_SETTING_EDIT_GENERIC(STRFUNC(*(data))); \ 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), ...) { \ 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); \ UNUSED(pstr2); UNUSED(pset); \
DRAWMENU_SETTING_EDIT_GENERIC(STRFUNC(pget())); \ DRAWMENU_SETTING_EDIT_GENERIC(STRFUNC(pget())); \
} \ } \
typedef void NAME##_void typedef void NAME##_void
DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(int16_t, int3, itostr3); #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_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 lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data) DRAW_BOOL_SETTING(sel, row, pstr, data) DEFINE_LCD_IMPLEMENTATION_DRAWMENU_SETTING_EDIT_TYPE(int3);
#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_TYPE(int4);
#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(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 /////////////// /////////////// Menu Actions ///////////////
//////////////////////////////////////////// ////////////////////////////////////////////
#define menu_action_back(dummy) _menu_action_back() class menu_item_back {
void _menu_action_back(); public:
void menu_action_submenu(screenFunc_t data); static inline void action() { lcd_goto_previous_menu(); }
void menu_action_function(menuAction_t data); };
void menu_action_gcode(const char* pgcode);
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 /////////// /////////// Menu Editing Actions ///////////
//////////////////////////////////////////// ////////////////////////////////////////////
#define DECLARE_MENU_EDIT_TYPE(TYPE, NAME) \ class menu_item_invariants {
bool _menu_edit_ ## NAME(); \ protected:
void menu_edit_ ## NAME(); \ typedef char* (*strfunc_t)(const int32_t);
void menu_edit_callback_ ## NAME(); \ typedef void (*loadfunc_t)(void *, const int32_t);
void _menu_action_setting_edit_ ## NAME(PGM_P const pstr, TYPE* const ptr, const TYPE minValue, const TYPE maxValue); \ 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);
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); \ static void edit(strfunc_t, loadfunc_t);
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
DECLARE_MENU_EDIT_TYPE(int16_t, int3); template<typename NAME>
DECLARE_MENU_EDIT_TYPE(int16_t, int4); class menu_item_template : menu_item_invariants {
DECLARE_MENU_EDIT_TYPE(uint8_t, int8); private:
DECLARE_MENU_EDIT_TYPE(float, float3); typedef typename NAME::type_t type_t;
DECLARE_MENU_EDIT_TYPE(float, float52); inline static float unscale(const float value) {return value * (1.0f / NAME::scale);}
DECLARE_MENU_EDIT_TYPE(float, float43); inline static float scale(const float value) {return value * NAME::scale;}
DECLARE_MENU_EDIT_TYPE(float, float5); static void load(void *ptr, const int32_t value) {*((type_t*)ptr) = unscale(value);}
DECLARE_MENU_EDIT_TYPE(float, float51); static char* to_string(const int32_t value) {return NAME::strfunc(unscale(value));}
DECLARE_MENU_EDIT_TYPE(float, float52sign); public:
DECLARE_MENU_EDIT_TYPE(float, float62); 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) {
DECLARE_MENU_EDIT_TYPE(uint32_t, long5); 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); #define DECLARE_MENU_EDIT_ITEM(NAME) typedef menu_item_template<NAME ## _item_info> menu_item_ ## NAME;
void menu_action_setting_edit_callback_bool(PGM_P pstr, bool* ptr, screenFunc_t callbackFunc);
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 //////////// //////////// Menu System Macros ////////////
@ -226,67 +278,63 @@ void menu_action_setting_edit_callback_bool(PGM_P pstr, bool* ptr, screenFunc_t
extern bool encoderRateMultiplierEnabled; extern bool encoderRateMultiplierEnabled;
#define ENCODER_RATE_MULTIPLY(F) (encoderRateMultiplierEnabled = F) #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 //#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 #else // !ENCODER_RATE_MULTIPLIER
#define ENCODER_RATE_MULTIPLY(F) NOOP #define ENCODER_RATE_MULTIPLY(F) NOOP
#define _MENU_ITEM_MULTIPLIER_CHECK(USE_MULTIPLIER)
#endif // !ENCODER_RATE_MULTIPLIER #endif // !ENCODER_RATE_MULTIPLIER
/** /**
* MENU_ITEM generates draw & handler code for a menu item, potentially calling: * MENU_ITEM generates draw & handler code for a menu item, potentially calling:
* *
* lcd_implementation_drawmenu_[type](sel, row, label, arg3...) * lcd_implementation_drawmenu_<type>[_variant](sel, row, label, arg3...)
* menu_action_[type](arg3...) * menu_item_<type>::action[_variant](arg3...)
* *
* Examples: * Examples:
* MENU_ITEM(back, MSG_WATCH, 0 [dummy parameter] ) * MENU_ITEM(back, MSG_WATCH, 0 [dummy parameter] )
* or * or
* MENU_BACK(MSG_WATCH) * MENU_BACK(MSG_WATCH)
* lcd_implementation_drawmenu_back(sel, row, PSTR(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) * MENU_ITEM(function, MSG_PAUSE_PRINT, lcd_sdcard_pause)
* lcd_implementation_drawmenu_function(sel, row, PSTR(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_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) * 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, ...) \ #define _MENU_ITEM_VARIANT_P(TYPE, VARIANT, USE_MULTIPLIER, PLABEL, ...) do { \
if (_menuLineNr == _thisItemNr) { \ _skipStatic = false; \
if (encoderLine == _thisItemNr && lcd_clicked) { \ if (_menuLineNr == _thisItemNr) { \
lcd_clicked = false 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, ...) \ // Used to print static text with no visible cursor.
menu_action_ ## TYPE(__VA_ARGS__); \ // Parameters: label [, bool center [, bool invert [, char *value] ] ]
if (screen_changed) return; \ #define STATIC_ITEM_P(PLABEL, ...) do{ \
if (_menuLineNr == _thisItemNr) { \
if (_skipStatic && encoderLine <= _thisItemNr) { \
encoderPosition += ENCODER_STEPS_PER_MENU_ITEM; \
++encoderLine; \
} \ } \
if (lcdDrawUpdate) \ if (lcdDrawUpdate) \
lcd_implementation_drawmenu_ ## TYPE(encoderLine == _thisItemNr, _lcdLineNr, PLABEL, ## __VA_ARGS__); \ lcd_implementation_drawmenu_static(_lcdLineNr, PLABEL, ## __VA_ARGS__); \
} \ } \
++_thisItemNr ++_thisItemNr; \
} while(0)
#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__)
#define MENU_ITEM_ADDON_START(X) \ #define MENU_ITEM_ADDON_START(X) \
if (lcdDrawUpdate && _menuLineNr == _thisItemNr - 1) { \ 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_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 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_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_P(TYPE, PLABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, , 0, PLABEL, ## __VA_ARGS__)
#define MENU_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) MENU_ITEM(_CAT(setting_edit_callback_,TYPE), LABEL, PSTR(LABEL), ## __VA_ARGS__) #define MENU_ITEM(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, , 0, PSTR(LABEL), ## __VA_ARGS__)
#if ENABLED(ENCODER_RATE_MULTIPLIER) #define MENU_ITEM_EDIT(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 0, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
#define MENU_MULTIPLIER_ITEM_EDIT(TYPE, LABEL, ...) MENU_MULTIPLIER_ITEM(_CAT(setting_edit_,TYPE), 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_CALLBACK(TYPE, LABEL, ...) MENU_MULTIPLIER_ITEM(_CAT(setting_edit_callback_,TYPE), 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__)
#else // !ENCODER_RATE_MULTIPLIER #define MENU_MULTIPLIER_ITEM_EDIT_CALLBACK(TYPE, LABEL, ...) _MENU_ITEM_VARIANT_P(TYPE, _setting_edit, 1, PSTR(LABEL), PSTR(LABEL), ## __VA_ARGS__)
#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
//////////////////////////////////////////// ////////////////////////////////////////////
/////////////// Menu Screens /////////////// /////////////// Menu Screens ///////////////

View file

@ -71,25 +71,31 @@ void lcd_sd_updir() {
} }
#endif #endif
void menu_action_sdfile(CardReader &theCard) { class menu_item_sdfile {
#if ENABLED(SD_REPRINT_LAST_SELECTED_FILE) public:
last_sdfile_encoderPosition = encoderPosition; // Save which file was selected for later use static void action(CardReader &theCard) {
#endif #if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
card.openAndPrintFile(theCard.filename); last_sdfile_encoderPosition = encoderPosition; // Save which file was selected for later use
lcd_return_to_status(); #endif
lcd_reset_status(); card.openAndPrintFile(theCard.filename);
} lcd_return_to_status();
lcd_reset_status();
}
};
void menu_action_sddirectory(CardReader &theCard) { class menu_item_sddirectory {
card.chdir(theCard.filename); public:
encoderTopLine = 0; static void action(CardReader &theCard) {
encoderPosition = 2 * ENCODER_STEPS_PER_MENU_ITEM; card.chdir(theCard.filename);
screen_changed = true; encoderTopLine = 0;
#if HAS_GRAPHICAL_LCD encoderPosition = 2 * ENCODER_STEPS_PER_MENU_ITEM;
drawing_screen = false; screen_changed = true;
#endif #if HAS_GRAPHICAL_LCD
lcd_refresh(); drawing_screen = false;
} #endif
lcd_refresh();
}
};
void menu_sdcard() { void menu_sdcard() {
ENCODER_DIRECTION_MENUS(); ENCODER_DIRECTION_MENUS();

View file

@ -279,7 +279,7 @@
typedef void (*screenFunc_t)(); typedef void (*screenFunc_t)();
typedef void (*menuAction_t)(); typedef void (*menuAction_t)();
extern screenFunc_t currentScreen; 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; extern bool lcd_clicked, defer_return_to_status;