Skip to content

Commit

Permalink
Streamline menu item logic (MarlinFirmware#17664)
Browse files Browse the repository at this point in the history
  • Loading branch information
thinkyhead authored and Emmanuel Viala committed Aug 21, 2020
1 parent 0e44e65 commit 96ce64a
Show file tree
Hide file tree
Showing 17 changed files with 303 additions and 251 deletions.
39 changes: 38 additions & 1 deletion Marlin/src/lcd/menu/menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,33 @@ class MenuItem_bool : public MenuEditItemBase {
////////////////////////////////////////////

/**
* SCREEN_OR_MENU_LOOP generates init code for a screen or menu
* Marlin's native menu screens work by running a loop from the top visible line index
* to the bottom visible line index (according to how much the screen has been scrolled).
* This complete loop is done on every menu screen call.
*
* The menu system is highly dynamic, so it doesn't know ahead of any menu loop which
* items will be visible or hidden, so menu items don't have a fixed index number.
*
* During the loop, each menu item checks to see if its line is the current one. If it is,
* then it checks to see if a click has arrived so it can run its action. If the action
* doesn't redirect to another screen then the menu item calls its draw method.
*
* Menu item add-ons can do whatever they like.
*
* This mixture of drawing and processing inside a loop has the advantage that a single
* line can be used to represent a menu item, and that is the rationale for this design.
*
* One of the pitfalls of this method is that DOGM displays call the screen handler 2x,
* 4x, or 8x per screen update to draw just one segment of the screen. As a result, any
* menu item that exists in two screen segments is drawn and processed twice per screen
* update. With each item processed 5, 10, 20, or 40 times the logic has to be simple.
*
* To keep performance optimal, use the MENU_ITEM_IF/ELSE/ELIF macros. If function calls
* are needed to test conditions, they should come before START_MENU / START_SCREEN.
*/

/**
* SCREEN_OR_MENU_LOOP generates header code for a screen or menu
*
* encoderTopLine is the top menu line to display
* _lcdLineNr is the index of the LCD line (e.g., 0-3)
Expand Down Expand Up @@ -510,6 +536,17 @@ class MenuItem_bool : public MenuEditItemBase {
#define YESNO_ITEM_N_P(N,PLABEL, V...) _CONFIRM_ITEM_N_P(N, PLABEL, ##V)
#define YESNO_ITEM_N(N,LABEL, V...) YESNO_ITEM_N_P(N, GET_TEXT(LABEL), ##V)

/**
* MENU_ITEM_IF/ELSE/ELIF
*
* Apply a condition for a menu item to exist.
* When the condition passes, NEXT_ITEM updates _thisItemNr.
* This cannot be used to wrap multiple menu items.
*/
#define MENU_ITEM_IF(COND) if ((_menuLineNr == _thisItemNr) && (COND))
#define MENU_ITEM_ELIF(COND) else if ((_menuLineNr == _thisItemNr) && (COND))
#define MENU_ITEM_ELSE else if (_menuLineNr == _thisItemNr)

////////////////////////////////////////////
/////////////// Menu Screens ///////////////
////////////////////////////////////////////
Expand Down
81 changes: 44 additions & 37 deletions Marlin/src/lcd/menu/menu_advanced.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@

#if ENABLED(FILAMENT_RUNOUT_SENSOR) && FILAMENT_RUNOUT_DISTANCE_MM
#include "../../feature/runout.h"
float lcd_runout_distance_mm;
#endif

#if ENABLED(EEPROM_SETTINGS) && DISABLED(SLIM_LCD_MENUS)
Expand Down Expand Up @@ -148,9 +147,12 @@ void menu_cancelobject();
#endif

#if ENABLED(FILAMENT_RUNOUT_SENSOR) && FILAMENT_RUNOUT_DISTANCE_MM
EDIT_ITEM(float3, MSG_RUNOUT_DISTANCE_MM, &lcd_runout_distance_mm, 1, 30, []{
runout.set_runout_distance(lcd_runout_distance_mm);
});
MENU_ITEM_IF(1) {
editable.decimal = runout.runout_distance();
EDIT_ITEM(float3, MSG_RUNOUT_DISTANCE_MM, &editable.decimal, 1, 30,
[]{ runout.set_runout_distance(editable.decimal); }, true
);
}
#endif

END_MENU();
Expand Down Expand Up @@ -327,9 +329,6 @@ void menu_cancelobject();

// M203 / M205 Velocity options
void menu_advanced_velocity() {
START_MENU();
BACK_ITEM(MSG_ADVANCED_SETTINGS);

// M203 Max Feedrate
constexpr xyze_feedrate_t max_fr_edit =
#ifdef MAX_FEEDRATE_EDIT_VALUES
Expand All @@ -345,6 +344,10 @@ void menu_cancelobject();
#else
const xyze_feedrate_t &max_fr_edit_scaled = max_fr_edit;
#endif

START_MENU();
BACK_ITEM(MSG_ADVANCED_SETTINGS);

#define EDIT_VMAX(N) EDIT_ITEM_FAST(float3, MSG_VMAX_##N, &planner.settings.max_feedrate_mm_s[_AXIS(N)], 1, max_fr_edit_scaled[_AXIS(N)])
EDIT_VMAX(A);
EDIT_VMAX(B);
Expand All @@ -369,18 +372,7 @@ void menu_cancelobject();

// M201 / M204 Accelerations
void menu_advanced_acceleration() {
START_MENU();
BACK_ITEM(MSG_ADVANCED_SETTINGS);

const float max_accel = _MAX(planner.settings.max_acceleration_mm_per_s2[A_AXIS], planner.settings.max_acceleration_mm_per_s2[B_AXIS], planner.settings.max_acceleration_mm_per_s2[C_AXIS]);
// M204 P Acceleration
EDIT_ITEM_FAST(float5_25, MSG_ACC, &planner.settings.acceleration, 25, max_accel);

// M204 R Retract Acceleration
EDIT_ITEM_FAST(float5, MSG_A_RETRACT, &planner.settings.retract_acceleration, 100, planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(active_extruder)]);

// M204 T Travel Acceleration
EDIT_ITEM_FAST(float5_25, MSG_A_TRAVEL, &planner.settings.travel_acceleration, 25, max_accel);

// M201 settings
constexpr xyze_ulong_t max_accel_edit =
Expand All @@ -398,6 +390,18 @@ void menu_cancelobject();
const xyze_ulong_t &max_accel_edit_scaled = max_accel_edit;
#endif

START_MENU();
BACK_ITEM(MSG_ADVANCED_SETTINGS);

// M204 P Acceleration
EDIT_ITEM_FAST(float5_25, MSG_ACC, &planner.settings.acceleration, 25, max_accel);

// M204 R Retract Acceleration
EDIT_ITEM_FAST(float5, MSG_A_RETRACT, &planner.settings.retract_acceleration, 100, planner.settings.max_acceleration_mm_per_s2[E_AXIS_N(active_extruder)]);

// M204 T Travel Acceleration
EDIT_ITEM_FAST(float5_25, MSG_A_TRAVEL, &planner.settings.travel_acceleration, 25, max_accel);

#define EDIT_AMAX(Q,L) EDIT_ITEM_FAST(long5_25, MSG_AMAX_##Q, &planner.settings.max_acceleration_mm_per_s2[_AXIS(Q)], L, max_accel_edit_scaled[_AXIS(Q)], []{ planner.reset_acceleration_rates(); })
EDIT_AMAX(A, 100);
EDIT_AMAX(B, 100);
Expand All @@ -413,8 +417,10 @@ void menu_cancelobject();

#ifdef XY_FREQUENCY_LIMIT
EDIT_ITEM(int8, MSG_XY_FREQUENCY_LIMIT, &planner.xy_freq_limit_hz, 0, 100, planner.refresh_frequency_limit, true);
editable.uint8 = uint8_t(LROUND(planner.xy_freq_min_speed_factor * 255 * 100)); // percent to u8
EDIT_ITEM(percent, MSG_XY_FREQUENCY_FEEDRATE, &editable.uint8, 3, 255, []{ planner.set_min_speed_factor_u8(editable.uint8); }, true);
MENU_ITEM_IF(1) {
editable.uint8 = uint8_t(LROUND(planner.xy_freq_min_speed_factor * 255 * 100)); // percent to u8
EDIT_ITEM(percent, MSG_XY_FREQUENCY_FEEDRATE, &editable.uint8, 3, 255, []{ planner.set_min_speed_factor_u8(editable.uint8); }, true);
}
#endif

END_MENU();
Expand Down Expand Up @@ -496,9 +502,8 @@ void menu_advanced_steps_per_mm() {
}

void menu_advanced_settings() {
#if ENABLED(FILAMENT_RUNOUT_SENSOR) && FILAMENT_RUNOUT_DISTANCE_MM
lcd_runout_distance_mm = runout.runout_distance();
#endif
const bool is_busy = printer_busy();

START_MENU();
BACK_ITEM(MSG_CONFIGURATION);

Expand All @@ -522,13 +527,13 @@ void menu_advanced_settings() {

// M851 - Z Probe Offsets
#if HAS_BED_PROBE
if (!printer_busy())
SUBMENU(MSG_ZPROBE_OFFSETS, menu_probe_offsets);
if (!is_busy) SUBMENU(MSG_ZPROBE_OFFSETS, menu_probe_offsets);
#endif

#endif // !SLIM_LCD_MENUS

// M92 - Steps Per mm
if (!printer_busy())
if (!is_busy)
SUBMENU(MSG_STEPS_PER_MM, menu_advanced_steps_per_mm);

#if ENABLED(BACKLASH_GCODE)
Expand Down Expand Up @@ -571,17 +576,19 @@ void menu_advanced_settings() {
#endif

#if ENABLED(SD_FIRMWARE_UPDATE)
bool sd_update_state = settings.sd_update_status();
EDIT_ITEM(bool, MSG_MEDIA_UPDATE, &sd_update_state, []{
//
// Toggle the SD Firmware Update state in EEPROM
//
const bool new_state = !settings.sd_update_status(),
didset = settings.set_sd_update_status(new_state);
TERN_(HAS_BUZZER, ui.completion_feedback(didset));
ui.return_to_status();
if (new_state) LCD_MESSAGEPGM(MSG_RESET_PRINTER); else ui.reset_status();
});
MENU_ITEM_IF (1) {
bool sd_update_state = settings.sd_update_status();
EDIT_ITEM(bool, MSG_MEDIA_UPDATE, &sd_update_state, []{
//
// Toggle the SD Firmware Update state in EEPROM
//
const bool new_state = !settings.sd_update_status(),
didset = settings.set_sd_update_status(new_state);
ui.completion_feedback(didset);
ui.return_to_status();
if (new_state) LCD_MESSAGEPGM(MSG_RESET_PRINTER); else ui.reset_status();
});
}
#endif

#if ENABLED(EEPROM_SETTINGS) && DISABLED(SLIM_LCD_MENUS)
Expand Down
21 changes: 8 additions & 13 deletions Marlin/src/lcd/menu/menu_bed_corners.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,19 +79,14 @@ static inline void _lcd_level_bed_corners_homing() {
bed_corner = 0;
ui.goto_screen([]{
MenuItem_confirm::select_screen(
GET_TEXT(MSG_BUTTON_NEXT), GET_TEXT(MSG_BUTTON_DONE),
_lcd_goto_next_corner,
[]{
TERN_(HAS_LEVELING, set_bed_leveling_enabled(leveling_was_active));
ui.goto_previous_screen_no_defer();
},
GET_TEXT(
#if ENABLED(LEVEL_CENTER_TOO)
MSG_LEVEL_BED_NEXT_POINT
#else
MSG_NEXT_CORNER
#endif
), (PGM_P)nullptr, PSTR("?")
GET_TEXT(MSG_BUTTON_NEXT), GET_TEXT(MSG_BUTTON_DONE)
, _lcd_goto_next_corner
, []{
TERN_(HAS_LEVELING, set_bed_leveling_enabled(leveling_was_active));
ui.goto_previous_screen_no_defer();
}
, GET_TEXT(TERN(LEVEL_CENTER_TOO, MSG_LEVEL_BED_NEXT_POINT, MSG_NEXT_CORNER))
, (PGM_P)nullptr, PSTR("?")
);
});
ui.set_selection(true);
Expand Down
18 changes: 10 additions & 8 deletions Marlin/src/lcd/menu/menu_bed_leveling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,11 +224,12 @@
* Save Settings (Req: EEPROM_SETTINGS)
*/
void menu_bed_leveling() {
const bool is_homed = all_axes_known(),
is_valid = leveling_is_valid();

START_MENU();
BACK_ITEM(MSG_MOTION);

const bool is_homed = all_axes_known();

// Auto Home if not using manual probing
#if NONE(PROBE_MANUALLY, MESH_BED_LEVELING)
if (!is_homed) GCODES_ITEM(MSG_AUTO_HOME, G28_STR);
Expand All @@ -244,21 +245,22 @@ void menu_bed_leveling() {
#endif

#if ENABLED(MESH_EDIT_MENU)
if (leveling_is_valid())
SUBMENU(MSG_EDIT_MESH, menu_edit_mesh);
if (is_valid) SUBMENU(MSG_EDIT_MESH, menu_edit_mesh);
#endif

// Homed and leveling is valid? Then leveling can be toggled.
if (is_homed && leveling_is_valid()) {
if (is_homed && is_valid) {
bool show_state = planner.leveling_active;
EDIT_ITEM(bool, MSG_BED_LEVELING, &show_state, _lcd_toggle_bed_leveling);
}

// Z Fade Height
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
// Shadow for editing the fade height
editable.decimal = planner.z_fade_height;
EDIT_ITEM_FAST(float3, MSG_Z_FADE_HEIGHT, &editable.decimal, 0, 100, []{ set_z_fade_height(editable.decimal); });
MENU_ITEM_IF (1) {
// Shadow for editing the fade height
editable.decimal = planner.z_fade_height;
EDIT_ITEM_FAST(float3, MSG_Z_FADE_HEIGHT, &editable.decimal, 0, 100, []{ set_z_fade_height(editable.decimal); });
}
#endif

//
Expand Down
14 changes: 8 additions & 6 deletions Marlin/src/lcd/menu/menu_cancelobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,19 @@ static void lcd_cancel_object_confirm() {
}

void menu_cancelobject() {
const int8_t ao = cancelable.active_object;

START_MENU();
BACK_ITEM(MSG_MAIN);

// Draw cancelable items in a loop
int8_t a = cancelable.active_object;
for (int8_t i = -1; i < cancelable.object_count; i++) {
if (i == a) continue;
int8_t j = i < 0 ? a : i;
if (!cancelable.is_canceled(j))
SUBMENU_N(j, MSG_CANCEL_OBJECT_N, lcd_cancel_object_confirm);
if (i < 0) SKIP_ITEM();
if (i == ao) continue; // Active is drawn on -1 index
const int8_t j = i < 0 ? ao : i; // Active or index item
MENU_ITEM_IF (!cancelable.is_canceled(j)) { // Not canceled already?
SUBMENU_N(j, MSG_CANCEL_OBJECT_N, lcd_cancel_object_confirm); // Offer the option.
if (i < 0) SKIP_ITEM(); // Extra line after active
}
}

END_MENU();
Expand Down
16 changes: 10 additions & 6 deletions Marlin/src/lcd/menu/menu_configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ void menu_advanced_settings();
#include "../../module/motion.h" // for active_extruder

void menu_toolchange_migration() {
PGM_P const msg_migrate = GET_TEXT(MSG_TOOL_MIGRATION_SWAP);

START_MENU();
BACK_ITEM(MSG_CONFIGURATION);

Expand All @@ -134,7 +136,6 @@ void menu_advanced_settings();
EDIT_ITEM(uint8, MSG_TOOL_MIGRATION_END, &migration.last, 0, EXTRUDERS - 1);

// Migrate to a chosen extruder
PGM_P const msg_migrate = GET_TEXT(MSG_TOOL_MIGRATION_SWAP);
LOOP_L_N(s, EXTRUDERS) {
if (s != active_extruder) {
ACTION_ITEM_N_P(s, msg_migrate, []{
Expand Down Expand Up @@ -182,11 +183,12 @@ void menu_advanced_settings();
#if ENABLED(DUAL_X_CARRIAGE)

void menu_idex() {
const bool need_g28 = !(TEST(axis_known_position, Y_AXIS) && TEST(axis_known_position, Z_AXIS));

START_MENU();
BACK_ITEM(MSG_CONFIGURATION);

GCODES_ITEM(MSG_IDEX_MODE_AUTOPARK, PSTR("M605 S1\nG28 X\nG1 X100"));
const bool need_g28 = !(TEST(axis_known_position, Y_AXIS) && TEST(axis_known_position, Z_AXIS));
GCODES_ITEM(MSG_IDEX_MODE_DUPLICATE, need_g28
? PSTR("M605 S1\nT0\nG28\nM605 S2 X200\nG28 X\nG1 X100") // If Y or Z is not homed, do a full G28 first
: PSTR("M605 S1\nT0\nM605 S2 X200\nG28 X\nG1 X100")
Expand Down Expand Up @@ -237,16 +239,18 @@ void menu_advanced_settings();
#endif

#if ENABLED(TOUCH_MI_PROBE)

void menu_touchmi() {
START_MENU();
ui.defer_status_screen();
START_MENU();
BACK_ITEM(MSG_CONFIGURATION);
GCODES_ITEM(MSG_TOUCHMI_INIT, PSTR("M851 Z0\nG28\nG1 F200 Z0"));
SUBMENU(MSG_ZPROBE_ZOFFSET, lcd_babystep_zoffset);
GCODES_ITEM(MSG_TOUCHMI_SAVE, PSTR("M500\nG1 F200 Z10"));
GCODES_ITEM(MSG_TOUCHMI_ZTEST, PSTR("G28\nG1 F200 Z0"));
END_MENU();
}

#endif

#if ENABLED(CONTROLLER_FAN_MENU)
Expand Down Expand Up @@ -342,6 +346,8 @@ void menu_advanced_settings();
#endif

void menu_configuration() {
const bool busy = printer_busy();

START_MENU();
BACK_ITEM(MSG_MAIN);

Expand All @@ -367,7 +373,6 @@ void menu_configuration() {
SUBMENU(MSG_CONTROLLER_FAN, menu_controller_fan);
#endif

const bool busy = printer_busy();
if (!busy) {
#if EITHER(DELTA_CALIBRATION_MENU, DELTA_AUTO_CALIBRATION)
SUBMENU(MSG_DELTA_CALIBRATE, menu_delta_calibrate);
Expand Down Expand Up @@ -435,8 +440,7 @@ void menu_configuration() {

#if ENABLED(EEPROM_SETTINGS)
ACTION_ITEM(MSG_STORE_EEPROM, lcd_store_settings);
if (!busy)
ACTION_ITEM(MSG_LOAD_EEPROM, lcd_load_settings);
if (!busy) ACTION_ITEM(MSG_LOAD_EEPROM, lcd_load_settings);
#endif

if (!busy)
Expand Down
Loading

0 comments on commit 96ce64a

Please sign in to comment.