From 90fc3288d77c52b1b5b42ce6978451742d04eea7 Mon Sep 17 00:00:00 2001 From: alfrix Date: Tue, 8 Aug 2023 02:07:06 -0300 Subject: [PATCH] Use callbacks to disable and enable buttons to improve user feedback buttons now show a spinner if watiting for callback --- ks_includes/KlippyGtk.py | 27 +++++++++++++++++++++++++-- panels/bed_level.py | 13 +++++-------- panels/bed_mesh.py | 26 +++++++------------------- panels/extrude.py | 13 ++++++++----- panels/fine_tune.py | 10 ++++++---- panels/gcode_macros.py | 4 ++-- panels/input_shaper.py | 8 +++----- panels/job_status.py | 3 +-- panels/move.py | 16 +++------------- panels/temperature.py | 7 ++++--- panels/zcalibrate.py | 12 +++--------- screen.py | 11 ++++++++++- 12 files changed, 77 insertions(+), 73 deletions(-) diff --git a/ks_includes/KlippyGtk.py b/ks_includes/KlippyGtk.py index 4875eec6..4292eabd 100644 --- a/ks_includes/KlippyGtk.py +++ b/ks_includes/KlippyGtk.py @@ -165,8 +165,13 @@ class KlippyGtk: scale = scale * 1.4 width = height = self.img_scale * scale b.set_image(self.Image(image_name, width, height)) - b.set_image_position(position) - b.set_always_show_image(True) + b.set_image_position(position) + b.set_always_show_image(True) + spinner = Gtk.Spinner.new() + spinner.set_no_show_all(True) + spinner.set_size_request(width, height) + spinner.hide() + b.get_child().get_child().add(spinner) if label is not None: format_label(b, lines) @@ -175,6 +180,24 @@ class KlippyGtk: b.connect("clicked", self.screen.reset_screensaver_timeout) return b + @staticmethod + def Button_busy(widget, busy): + box = widget.get_child().get_child() + if busy: + widget.set_sensitive(False) + widget.set_always_show_image(False) + box.get_children()[0].hide() + if type(box.get_children()[1]) == Gtk.Spinner: + box.get_children()[1].start() + box.get_children()[1].show() + else: + box.get_children()[0].show() + if type(box.get_children()[1]) == Gtk.Spinner: + box.get_children()[1].stop() + box.get_children()[1].hide() + widget.set_always_show_image(True) + widget.set_sensitive(True) + def Dialog(self, screen, buttons, content, callback=None, *args): dialog = Gtk.Dialog() dialog.set_default_size(screen.width, screen.height) diff --git a/panels/bed_level.py b/panels/bed_level.py index 5148a3b0..1a12a4d2 100644 --- a/panels/bed_level.py +++ b/panels/bed_level.py @@ -306,6 +306,7 @@ class Panel(ScreenPanel): self._screen._ws.klippy.gcode_script("Z_TILT_ADJUST") def go_to_position(self, widget, position): + widget.set_sensitive(False) self.home() logging.debug(f"Going to position: {position}") script = [ @@ -314,15 +315,10 @@ class Panel(ScreenPanel): f"G1 X{position[0]} Y{position[1]} F{self.horizontal_speed * 60}\n", f"G1 Z{self.probe_z_height} F{self.lift_speed * 60}\n" ] - - self._screen._ws.klippy.gcode_script( - "\n".join(script) - ) + self._screen._send_action(widget, "printer.gcode.script", {"script": "\n".join(script)}) def disable_motors(self, widget): - self._screen._ws.klippy.gcode_script( - "M18" # Disable motors - ) + self._screen._send_action(widget, "printer.gcode.script", {"script": "M18"}) def process_busy(self, busy): for button in self.buttons: @@ -401,7 +397,8 @@ class Panel(ScreenPanel): return sorted(screws, key=lambda s: (float(s[1]), float(s[0]))) def screws_tilt_calculate(self, widget): + widget.set_sensitive(False) self.home() self.response_count = 0 self.buttons['screws'].set_sensitive(False) - self._screen._ws.klippy.gcode_script("SCREWS_TILT_CALCULATE") + self._screen._send_action(widget, "printer.gcode.script", {"script": "SCREWS_TILT_CALCULATE"}) diff --git a/panels/bed_mesh.py b/panels/bed_mesh.py index f9093b31..5e596fd4 100644 --- a/panels/bed_mesh.py +++ b/panels/bed_mesh.py @@ -172,20 +172,7 @@ class Panel(ScreenPanel): if prof not in bm_profiles: self.remove_profile(prof) - def process_busy(self, busy): - for button in self.buttons: - if button == 'clear': - self.buttons[button].set_sensitive(self.active_mesh is not None) - continue - self.buttons[button].set_sensitive((not busy)) - for profile in self.profiles: - self.profiles[profile]["save"].set_sensitive((not busy)) - self.profiles[profile]["delete"].set_sensitive((not busy)) - def process_update(self, action, data): - if action == "notify_busy": - self.process_busy(data) - return if action != "notify_status_update": return if 'bed_mesh' in data and 'profile_name' in data['bed_mesh']: @@ -257,29 +244,30 @@ class Panel(ScreenPanel): if self.active_mesh is None: self.calibrate_mesh(None) - self._screen._ws.klippy.gcode_script(f"BED_MESH_PROFILE SAVE={name}") + self._screen._send_action(widget, "printer.gcode.script", {"script": f"BED_MESH_PROFILE SAVE={name}"}) self.remove_create() def calibrate_mesh(self, widget): + widget.set_sensitive(False) self._screen.show_popup_message(_("Calibrating"), level=1) if self._printer.get_stat("toolhead", "homed_axes") != "xyz": self._screen._ws.klippy.gcode_script("G28") - self._screen._ws.klippy.gcode_script("BED_MESH_CALIBRATE") + self._screen._send_action(widget, "printer.gcode.script", {"script": "BED_MESH_CALIBRATE"}) # Load zcalibrate to do a manual mesh if not self._printer.get_probe(): self.menu_item_clicked(widget, {"name": _("Mesh calibrate"), "panel": "zcalibrate"}) def send_clear_mesh(self, widget): - self._screen._ws.klippy.gcode_script("BED_MESH_CLEAR") + self._screen._send_action(widget, "printer.gcode.script", {"script": "BED_MESH_CLEAR"}) def send_load_mesh(self, widget, profile): - self._screen._ws.klippy.gcode_script(KlippyGcodes.bed_mesh_load(profile)) + self._screen._send_action(widget, "printer.gcode.script", {"script": KlippyGcodes.bed_mesh_load(profile)}) def send_save_mesh(self, widget, profile): - self._screen._ws.klippy.gcode_script(KlippyGcodes.bed_mesh_save(profile)) + self._screen._send_action(widget, "printer.gcode.script", {"script": KlippyGcodes.bed_mesh_save(profile)}) def send_remove_mesh(self, widget, profile): - self._screen._ws.klippy.gcode_script(KlippyGcodes.bed_mesh_remove(profile)) + self._screen._send_action(widget, "printer.gcode.script", {"script": KlippyGcodes.bed_mesh_remove(profile)}) self.remove_profile(profile) diff --git a/panels/extrude.py b/panels/extrude.py index 5ea99a15..87d94d50 100644 --- a/panels/extrude.py +++ b/panels/extrude.py @@ -216,8 +216,8 @@ class Panel(ScreenPanel): for tool in self._printer.get_tools(): self.labels[tool].get_style_context().remove_class("button_active") self.labels[extruder].get_style_context().add_class("button_active") - - self._screen._ws.klippy.gcode_script(f"T{self._printer.get_tool_number(extruder)}") + self._screen._send_action(widget, "printer.gcode.script", + {"script": f"T{self._printer.get_tool_number(extruder)}"}) def change_speed(self, widget, speed): logging.info(f"### Speed {speed}") @@ -227,19 +227,22 @@ class Panel(ScreenPanel): def extrude(self, widget, direction): self._screen._ws.klippy.gcode_script(KlippyGcodes.EXTRUDE_REL) - self._screen._ws.klippy.gcode_script(f"G1 E{direction}{self.distance} F{self.speed * 60}") + self._screen._send_action(widget, "printer.gcode.script", + {"script": f"G1 E{direction}{self.distance} F{self.speed * 60}"}) def load_unload(self, widget, direction): if direction == "-": if not self.unload_filament: self._screen.show_popup_message("Macro UNLOAD_FILAMENT not found") else: - self._screen._ws.klippy.gcode_script(f"UNLOAD_FILAMENT SPEED={self.speed * 60}") + self._screen._send_action(widget, "printer.gcode.script", + {"script": f"UNLOAD_FILAMENT SPEED={self.speed * 60}"}) if direction == "+": if not self.load_filament: self._screen.show_popup_message("Macro LOAD_FILAMENT not found") else: - self._screen._ws.klippy.gcode_script(f"LOAD_FILAMENT SPEED={self.speed * 60}") + self._screen._send_action(widget, "printer.gcode.script", + {"script": f"LOAD_FILAMENT SPEED={self.speed * 60}"}) def enable_disable_fs(self, switch, gparams, name, x): if switch.get_active(): diff --git a/panels/fine_tune.py b/panels/fine_tune.py index 0f9cd09f..5b323031 100644 --- a/panels/fine_tune.py +++ b/panels/fine_tune.py @@ -144,14 +144,15 @@ class Panel(ScreenPanel): def change_babystepping(self, widget, direction): if direction == "reset": self.labels['zoffset'].set_label(' 0.00mm') - self._screen._ws.klippy.gcode_script("SET_GCODE_OFFSET Z=0 MOVE=1") + self._screen._send_action(widget, "printer.gcode.script", {"script": "SET_GCODE_OFFSET Z=0 MOVE=1"}) return elif direction == "+": self.z_offset += float(self.z_delta) elif direction == "-": self.z_offset -= float(self.z_delta) self.labels['zoffset'].set_label(f' {self.z_offset:.3f}mm') - self._screen._ws.klippy.gcode_script(f"SET_GCODE_OFFSET Z_ADJUST={direction}{self.z_delta} MOVE=1") + self._screen._send_action(widget, "printer.gcode.script", + {"script": f"SET_GCODE_OFFSET Z_ADJUST={direction}{self.z_delta} MOVE=1"}) def change_extrusion(self, widget, direction): if direction == "+": @@ -162,7 +163,8 @@ class Panel(ScreenPanel): self.extrusion = 100 self.extrusion = max(self.extrusion, 1) self.labels['extrudefactor'].set_label(f" {self.extrusion:3}%") - self._screen._ws.klippy.gcode_script(KlippyGcodes.set_extrusion_rate(self.extrusion)) + self._screen._send_action(widget, "printer.gcode.script", + {"script": KlippyGcodes.set_extrusion_rate(self.extrusion)}) def change_speed(self, widget, direction): if direction == "+": @@ -174,7 +176,7 @@ class Panel(ScreenPanel): self.speed = max(self.speed, 1) self.labels['speedfactor'].set_label(f" {self.speed:3}%") - self._screen._ws.klippy.gcode_script(KlippyGcodes.set_speed_rate(self.speed)) + self._screen._send_action(widget, "printer.gcode.script", {"script": KlippyGcodes.set_speed_rate(self.speed)}) def change_percent_delta(self, widget, array, delta): logging.info(f"### Delta {delta}") diff --git a/panels/gcode_macros.py b/panels/gcode_macros.py index fb2f7846..982611ab 100644 --- a/panels/gcode_macros.py +++ b/panels/gcode_macros.py @@ -111,9 +111,9 @@ class Panel(ScreenPanel): for param in self.macros[macro]["params"]: value = self.macros[macro]["params"][param].get_text() if value: - params += f'{param}={value} ' + params += f' {param}={value}' self._screen.show_popup_message(f"{macro} {params}", 1) - self._screen._ws.klippy.gcode_script(f"{macro} {params}") + self._screen._send_action(widget, "printer.gcode.script", {"script": f"{macro}{params}"}) def change_sort(self, widget): self.sort_reverse ^= True diff --git a/panels/input_shaper.py b/panels/input_shaper.py index 63c95dd3..de7a3612 100644 --- a/panels/input_shaper.py +++ b/panels/input_shaper.py @@ -110,14 +110,12 @@ class Panel(ScreenPanel): self._screen._ws.klippy.gcode_script("G28") self.calibrating_axis = method if method == "x": - self._screen._ws.klippy.gcode_script('SHAPER_CALIBRATE AXIS=X') + self._screen._send_action(self.calibrate_btn, "printer.gcode.script", {"script": 'SHAPER_CALIBRATE AXIS=X'}) if method == "y": - self._screen._ws.klippy.gcode_script('SHAPER_CALIBRATE AXIS=Y') + self._screen._send_action(self.calibrate_btn, "printer.gcode.script", {"script": 'SHAPER_CALIBRATE AXIS=Y'}) if method == "both": - self._screen._ws.klippy.gcode_script('SHAPER_CALIBRATE') - + self._screen._send_action(self.calibrate_btn, "printer.gcode.script", {"script": 'SHAPER_CALIBRATE'}) self.calibrate_btn.set_label(_('Calibrating') + '...') - self.calibrate_btn.set_sensitive(False) def set_opt_value(self, widget, opt, *args): shaper_freq_x = self.freq_xy_adj['shaper_freq_x'].get_value() diff --git a/panels/job_status.py b/panels/job_status.py index 16fd88fa..925573b9 100644 --- a/panels/job_status.py +++ b/panels/job_status.py @@ -420,8 +420,7 @@ class Panel(ScreenPanel): if self.filename: self.disable_button("restart") if self.state == "error": - script = {"script": "SDCARD_RESET_FILE"} - self._screen._send_action(None, "printer.gcode.script", script) + self._screen._ws.klippy.gcode_script("SDCARD_RESET_FILE") self._screen._ws.klippy.print_start(self.filename) logging.info(f"Starting print: {self.filename}") self.new_print() diff --git a/panels/move.py b/panels/move.py index 23ebf42a..e7cbee60 100644 --- a/panels/move.py +++ b/panels/move.py @@ -36,7 +36,6 @@ class Panel(ScreenPanel): self.buttons['motors_off'].connect("clicked", self._screen._confirm_send_action, _("Are you sure you wish to disable motors?"), "printer.gcode.script", script) - grid = self._gtk.HomogeneousGrid() if self._screen.vertical_mode: if self._screen.lang_ltr: @@ -135,16 +134,7 @@ class Panel(ScreenPanel): name = list(option)[0] self.add_option('options', self.settings, name, option[name]) - def process_busy(self, busy): - buttons = ("home", "motors_off") - for button in buttons: - if button in self.buttons: - self.buttons[button].set_sensitive(not busy) - def process_update(self, action, data): - if action == "notify_busy": - self.process_busy(data) - return if action != "notify_status_update": return homed_axes = self._printer.get_stat("toolhead", "homed_axes") @@ -186,8 +176,8 @@ class Panel(ScreenPanel): if speed is None: speed = self._config.get_config()['main'].getint(config_key, 20) speed = 60 * max(1, speed) - - self._screen._ws.klippy.gcode_script(f"{KlippyGcodes.MOVE_RELATIVE}\nG0 {axis}{dist} F{speed}") + script = f"{KlippyGcodes.MOVE_RELATIVE}\nG0 {axis}{dist} F{speed}" + self._screen._send_action(widget, "printer.gcode.script", {"script": script}) if self._printer.get_stat("gcode_move", "absolute_coordinates"): self._screen._ws.klippy.gcode_script("G90") @@ -250,7 +240,7 @@ class Panel(ScreenPanel): def home(self, widget): if "delta" in self._printer.get_config_section("printer")['kinematics']: - self._screen._ws.klippy.gcode_script("G28") + self._screen._send_action(widget, "printer.gcode.script", {"script": 'G28'}) return name = "homing" disname = self._screen._config.get_menu_name("move", name) diff --git a/panels/temperature.py b/panels/temperature.py index 3fd1d765..8ed60163 100644 --- a/panels/temperature.py +++ b/panels/temperature.py @@ -257,7 +257,7 @@ class Panel(ScreenPanel): self._screen._ws.klippy.set_temp_fan_temp(name, target) # This small delay is needed to properly update the target if the user configured something above # and then changed the target again using preheat gcode - GLib.timeout_add(250, self.preheat_gcode, setting) + GLib.timeout_add(250, self.preheat_gcode, widget, setting) def validate(self, heater, target=None, max_temp=None): if target is not None and max_temp is not None: @@ -270,9 +270,10 @@ class Panel(ScreenPanel): logging.debug(f"Invalid {heater} Target:{target}/{max_temp}") return False - def preheat_gcode(self, setting): + def preheat_gcode(self, widget, setting): with suppress(KeyError): - self._screen._ws.klippy.gcode_script(self.preheat_options[setting]['gcode']) + script = {"script": self.preheat_options[setting]['gcode']} + self._screen._send_action(widget, "printer.gcode.script", script) return False def add_device(self, device): diff --git a/panels/zcalibrate.py b/panels/zcalibrate.py index 22598a48..f5146b3a 100644 --- a/panels/zcalibrate.py +++ b/panels/zcalibrate.py @@ -125,9 +125,9 @@ class Panel(ScreenPanel): def start_calibration(self, widget, method): self.labels['popover'].popdown() + self.buttons['start'].set_sensitive(False) if self._printer.get_stat("toolhead", "homed_axes") != "xyz": self._screen._ws.klippy.gcode_script("G28") - if method == "probe": self._move_to_position() self._screen._ws.klippy.gcode_script("PROBE_CALIBRATE") @@ -217,19 +217,13 @@ class Panel(ScreenPanel): logging.info(f"Moving to X:{x_position} Y:{y_position}") self._screen._ws.klippy.gcode_script(f'G0 X{x_position} Y{y_position} F3000') - def process_busy(self, busy): - if busy: - for button in self.buttons: - self.buttons[button].set_sensitive(False) - elif self._printer.get_stat("manual_probe", "is_active"): + def activate(self): + if self._printer.get_stat("manual_probe", "is_active"): self.buttons_calibrating() else: self.buttons_not_calibrating() def process_update(self, action, data): - if action == "notify_busy": - self.process_busy(data) - return if action == "notify_status_update": if self._printer.get_stat("toolhead", "homed_axes") != "xyz": self.widgets['zposition'].set_text("Z: ?") diff --git a/screen.py b/screen.py index 4f992f19..c3856dcc 100755 --- a/screen.py +++ b/screen.py @@ -792,7 +792,16 @@ class KlipperScreen(Gtk.Window): def _send_action(self, widget, method, params): logging.info(f"{method}: {params}") - self._ws.send_method(method, params) + if type(widget) == Gtk.Button: + self.gtk.Button_busy(widget, True) + self._ws.send_method(method, params, self.enable_widget, widget) + else: + self._ws.send_method(method, params) + + def enable_widget(self, *args): + for x in args: + if type(x) == Gtk.Button: + GLib.timeout_add(150, self.gtk.Button_busy, x, False) def printer_initializing(self, msg, remove=False): if 'splash_screen' not in self.panels or remove: