diff --git a/config/example-menu.cfg b/config/example-menu.cfg index 0e26a986..3d4a120e 100644 --- a/config/example-menu.cfg +++ b/config/example-menu.cfg @@ -116,6 +116,11 @@ # This is mandatory attribute for input. # It accepts positive integer or float value. Will determine increment # and decrement steps for edit value. +#input_step2: +# This is optional attribute for input. +# It accepts positive integer or float value. Will determine fast rate +# increment and decrement steps for edit value. +# The default is 0 (input_step will be used instead) #[menu list1] #type:list or vsdcard diff --git a/klippy/extras/display/menu.cfg b/klippy/extras/display/menu.cfg index 8774920a..d9c047bc 100644 --- a/klippy/extras/display/menu.cfg +++ b/klippy/extras/display/menu.cfg @@ -379,6 +379,7 @@ parameter: extruder0.target input_min: 0 input_max: 250 input_step: 1 +input_step2: 10 gcode: M104 T0 S{0:.0f} [menu __temp __hotend1_current] @@ -395,6 +396,7 @@ parameter: extruder1.target input_min: 0 input_max: 250 input_step: 1 +input_step2: 10 gcode: M104 T1 S{0:.0f} [menu __temp __hotbed_current] @@ -411,6 +413,7 @@ parameter: heater_bed.target input_min: 0 input_max: 130 input_step: 1 +input_step2: 10 gcode: M140 S{0:.0f} [menu __temp __preheat_pla] diff --git a/klippy/extras/display/menu.py b/klippy/extras/display/menu.py index 84bc10b9..c32d9ed3 100644 --- a/klippy/extras/display/menu.py +++ b/klippy/extras/display/menu.py @@ -495,6 +495,7 @@ class MenuInput(MenuCommand): self._input_min = config.getfloat('input_min', sys.float_info.min) self._input_max = config.getfloat('input_max', sys.float_info.max) self._input_step = config.getfloat('input_step', above=0.) + self._input_step2 = config.getfloat('input_step2', 0, minval=0.) def is_scrollable(self): return False @@ -529,30 +530,34 @@ class MenuInput(MenuCommand): def reset_value(self): self._input_value = None - def inc_value(self): + def inc_value(self, fast_rate=False): last_value = self._input_value + input_step = (self._input_step2 if fast_rate and self._input_step2 > 0 + else self._input_step) if self._input_value is None: return if(self._reverse is True): - self._input_value -= abs(self._input_step) + self._input_value -= abs(input_step) else: - self._input_value += abs(self._input_step) + self._input_value += abs(input_step) self._input_value = min(self._input_max, max( self._input_min, self._input_value)) if self._realtime and last_value != self._input_value: self._onchange() - def dec_value(self): + def dec_value(self, fast_rate=False): last_value = self._input_value + input_step = (self._input_step2 if fast_rate and self._input_step2 > 0 + else self._input_step) if self._input_value is None: return if(self._reverse is True): - self._input_value += abs(self._input_step) + self._input_value += abs(input_step) else: - self._input_value -= abs(self._input_step) + self._input_value -= abs(input_step) self._input_value = min(self._input_max, max( self._input_min, self._input_value)) @@ -607,14 +612,14 @@ class MenuGroup(MenuContainer): s += self._render_item(item, (i == self.selected), True) return s - def _call_selected(self, method=None): + def _call_selected(self, method=None, *args): res = None if self.selected is not None: try: if method is None: res = self[self.selected] else: - res = getattr(self[self.selected], method)() + res = getattr(self[self.selected], method)(*args) except Exception: logging.exception("Call selected error") return res @@ -622,11 +627,11 @@ class MenuGroup(MenuContainer): def is_editing(self): return self._call_selected('is_editing') - def inc_value(self): - self._call_selected('inc_value') + def inc_value(self, fast_rate=False): + self._call_selected('inc_value', fast_rate) - def dec_value(self): - self._call_selected('dec_value') + def dec_value(self, fast_rate=False): + self._call_selected('dec_value', fast_rate) def selected_item(self): return self._call_selected() @@ -918,7 +923,11 @@ class MenuManager: self.up_pin = config.get('up_pin', None) self.down_pin = config.get('down_pin', None) self.kill_pin = config.get('kill_pin', None) - self._last_click_press = 0 + self._last_press = 0 + self._encoder_fast_rate = config.getfloat( + 'encoder_fast_rate', .03, above=0.) + self._last_encoder_cw_eventtime = 0 + self._last_encoder_ccw_eventtime = 0 # printer objects self.buttons = self.printer.try_load_module(config, "buttons") # register itself for a printer_state callback @@ -1215,14 +1224,14 @@ class MenuManager: else: return 0 - def up(self): + def up(self, fast_rate=False): container = self.stack_peek() if self.running and isinstance(container, MenuContainer): self.timer = 0 current = container[self.selected] if (isinstance(current, (MenuInput, MenuGroup)) and current.is_editing()): - current.dec_value() + current.dec_value(fast_rate) elif (isinstance(current, MenuGroup) and current.find_prev_item() is not None): pass @@ -1241,14 +1250,14 @@ class MenuManager: if isinstance(container[self.selected], MenuGroup): container[self.selected].find_prev_item() - def down(self): + def down(self, fast_rate=False): container = self.stack_peek() if self.running and isinstance(container, MenuContainer): self.timer = 0 current = container[self.selected] if (isinstance(current, (MenuInput, MenuGroup)) and current.is_editing()): - current.inc_value() + current.inc_value(fast_rate) elif (isinstance(current, MenuGroup) and current.find_next_item() is not None): pass @@ -1347,6 +1356,7 @@ class MenuManager: reactor = self.printer.get_reactor() reactor.register_callback(self.dispatch_gcode) self.gcode_queue.append(script) + def dispatch_gcode(self, eventtime): while self.gcode_queue: script = self.gcode_queue[0] @@ -1396,10 +1406,16 @@ class MenuManager: # buttons & encoder callbacks def encoder_cw_callback(self, eventtime): - self.up() + fast_rate = ((eventtime - self._last_encoder_cw_eventtime) + <= self._encoder_fast_rate) + self._last_encoder_cw_eventtime = eventtime + self.up(fast_rate) def encoder_ccw_callback(self, eventtime): - self.down() + fast_rate = ((eventtime - self._last_encoder_ccw_eventtime) + <= self._encoder_fast_rate) + self._last_encoder_ccw_eventtime = eventtime + self.down(fast_rate) def click_callback(self, eventtime, state): if self.click_pin: