From 9df910f368f424ff3a8affb4717f502d9702ec50 Mon Sep 17 00:00:00 2001 From: Joacim Breiler Date: Wed, 20 Mar 2024 12:37:53 +0100 Subject: [PATCH] Added rapid speed overrides (#2489) --- .../G2CoreController.java | 10 -- .../universalgcodesender/GrblController.java | 9 +- .../firmware/AbstractOverrideManager.java | 67 +------- .../firmware/DefaultOverrideManager.java | 45 ++++- .../firmware/IOverrideManager.java | 105 ++++++++++-- .../firmware/fluidnc/FluidNCController.java | 2 +- .../g2core/G2CoreOverrideManager.java | 148 ----------------- .../firmware/grbl/GrblOverrideManager.java | 155 +++++++++++++++++- .../components/OverrideRadioButtons.java | 88 ++++++++++ .../components/OverrideSpeedSlider.java | 68 ++++++++ .../components/OverrideToggleButtons.java | 66 ++++++++ .../uielements/panels/OverridesPanel.java | 98 ++++++----- .../grbl/GrblOverrideManagerTest.java | 51 +++--- .../joystick/action/AnalogOverrideAction.java | 2 +- .../core/control/OverridesTopComponent.java | 24 +-- 15 files changed, 599 insertions(+), 339 deletions(-) delete mode 100644 ugs-core/src/com/willwinder/universalgcodesender/firmware/g2core/G2CoreOverrideManager.java create mode 100644 ugs-core/src/com/willwinder/universalgcodesender/uielements/components/OverrideRadioButtons.java create mode 100644 ugs-core/src/com/willwinder/universalgcodesender/uielements/components/OverrideSpeedSlider.java create mode 100644 ugs-core/src/com/willwinder/universalgcodesender/uielements/components/OverrideToggleButtons.java diff --git a/ugs-core/src/com/willwinder/universalgcodesender/G2CoreController.java b/ugs-core/src/com/willwinder/universalgcodesender/G2CoreController.java index 7f2ce6aa0c..e368013d93 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/G2CoreController.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/G2CoreController.java @@ -20,8 +20,6 @@ This file is part of Universal Gcode Sender (UGS). import com.google.gson.JsonObject; import com.willwinder.universalgcodesender.communicator.ICommunicator; -import com.willwinder.universalgcodesender.firmware.IOverrideManager; -import com.willwinder.universalgcodesender.firmware.g2core.G2CoreOverrideManager; import com.willwinder.universalgcodesender.listeners.ControllerState; import com.willwinder.universalgcodesender.listeners.ControllerStatus; import com.willwinder.universalgcodesender.listeners.ControllerStatusBuilder; @@ -42,16 +40,13 @@ public class G2CoreController extends TinyGController { * A temporary flag for emulating a JOG state when parsing the controller status */ private boolean isJogging = false; - private final IOverrideManager overrideManager; public G2CoreController() { super(); - overrideManager = new G2CoreOverrideManager(this, getCommunicator()); } public G2CoreController(ICommunicator communicator) { super(communicator); - overrideManager = new G2CoreOverrideManager(this, communicator); } @Override @@ -195,9 +190,4 @@ protected ControllerStatus parseControllerStatus(JsonObject jo) { return controllerStatus; } - - @Override - public IOverrideManager getOverrideManager() { - return overrideManager; - } } diff --git a/ugs-core/src/com/willwinder/universalgcodesender/GrblController.java b/ugs-core/src/com/willwinder/universalgcodesender/GrblController.java index 6097105504..68a0ec0b3a 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/GrblController.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/GrblController.java @@ -38,6 +38,7 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.universalgcodesender.model.PartialPosition; import com.willwinder.universalgcodesender.model.Position; import com.willwinder.universalgcodesender.model.UnitUtils.Units; +import com.willwinder.universalgcodesender.services.MessageService; import com.willwinder.universalgcodesender.types.GcodeCommand; import com.willwinder.universalgcodesender.types.GrblFeedbackMessage; import com.willwinder.universalgcodesender.types.GrblSettingMessage; @@ -94,7 +95,7 @@ public GrblController(ICommunicator communicator) { this.firmwareSettings = new GrblFirmwareSettings(this); this.comm.addListener(firmwareSettings); this.initializer = new GrblControllerInitializer(this); - this.overrideManager = new GrblOverrideManager(this, communicator); + this.overrideManager = new GrblOverrideManager(this, communicator, messageService); } public GrblController() { @@ -111,6 +112,12 @@ public IFirmwareSettings getFirmwareSettings() { return firmwareSettings; } + @Override + public void setMessageService(MessageService messageService) { + super.setMessageService(messageService); + overrideManager.setMessageService(messageService); + } + /*********************** * API Implementation. * ***********************/ diff --git a/ugs-core/src/com/willwinder/universalgcodesender/firmware/AbstractOverrideManager.java b/ugs-core/src/com/willwinder/universalgcodesender/firmware/AbstractOverrideManager.java index db0e2adcac..0e5aa2570d 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/firmware/AbstractOverrideManager.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/firmware/AbstractOverrideManager.java @@ -19,14 +19,12 @@ This file is part of Universal Gcode Sender (UGS). package com.willwinder.universalgcodesender.firmware; import com.willwinder.universalgcodesender.IController; -import static com.willwinder.universalgcodesender.Utils.roundToNearestStepValue; import com.willwinder.universalgcodesender.communicator.ICommunicator; import com.willwinder.universalgcodesender.listeners.ControllerState; import com.willwinder.universalgcodesender.listeners.ControllerStatus; import com.willwinder.universalgcodesender.listeners.DefaultControllerListener; import com.willwinder.universalgcodesender.listeners.OverridePercents; import com.willwinder.universalgcodesender.listeners.OverrideType; -import com.willwinder.universalgcodesender.model.Overrides; /** * An abstract override manager with some default implementation of common functions. @@ -41,6 +39,7 @@ public abstract class AbstractOverrideManager implements IOverrideManager { protected int targetFeedSpeed = 100; protected int targetSpindleSpeed = 100; + protected int targetRapidSpeed = 100; private boolean isRunning = false; private long lastSentCommand = 0; @@ -60,6 +59,7 @@ public void onControllerStatus(ControllerStatus controllerStatus) { if (!isRunning) { targetFeedSpeed = controllerStatus.getOverrides().feed(); targetSpindleSpeed = controllerStatus.getOverrides().spindle(); + targetRapidSpeed = controllerStatus.getOverrides().rapid(); return; } @@ -72,59 +72,18 @@ public void onControllerStatus(ControllerStatus controllerStatus) { OverridePercents currentOverridePercents = controllerStatus.getOverrides(); adjustFeedOverride(currentOverridePercents); adjustSpindleOverride(currentOverridePercents); + adjustRapidOverride(currentOverridePercents); if (hasSettled()) { stop(); } } - protected void adjustFeedOverride(OverridePercents currentOverridePercents) { - if (currentOverridePercents.feed() == targetFeedSpeed) { - return; - } - - float currentFeed = currentOverridePercents.feed(); - int majorSteps = (int) ((targetFeedSpeed - currentFeed) / getSpeedMajorStep(OverrideType.FEED_SPEED)); - int minorSteps = (int) ((targetFeedSpeed - currentFeed) / getSpeedMinorStep(OverrideType.FEED_SPEED)); - - try { - if (majorSteps < 0) { - sendOverrideCommand(Overrides.CMD_FEED_OVR_COARSE_MINUS); - } else if (majorSteps > 0) { - sendOverrideCommand(Overrides.CMD_FEED_OVR_COARSE_PLUS); - } else if (minorSteps < 0) { - sendOverrideCommand(Overrides.CMD_FEED_OVR_FINE_MINUS); - } else if (minorSteps > 0) { - sendOverrideCommand(Overrides.CMD_FEED_OVR_FINE_PLUS); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + protected abstract void adjustFeedOverride(OverridePercents currentOverridePercents); - protected void adjustSpindleOverride(OverridePercents currentOverridePercents) { - if (currentOverridePercents.spindle() == targetSpindleSpeed) { - return; - } + protected abstract void adjustSpindleOverride(OverridePercents currentOverridePercents) ; - float currentSpindle = currentOverridePercents.spindle(); - int majorSteps = (int) ((targetSpindleSpeed - currentSpindle) / getSpeedMajorStep(OverrideType.SPINDLE_SPEED)); - int minorSteps = (int) ((targetSpindleSpeed - currentSpindle) / getSpeedMinorStep(OverrideType.SPINDLE_SPEED)); - - try { - if (majorSteps < 0) { - sendOverrideCommand(Overrides.CMD_SPINDLE_OVR_COARSE_MINUS); - } else if (majorSteps > 0) { - sendOverrideCommand(Overrides.CMD_SPINDLE_OVR_COARSE_PLUS); - } else if (minorSteps < 0) { - sendOverrideCommand(Overrides.CMD_SPINDLE_OVR_FINE_MINUS); - } else if (minorSteps > 0) { - sendOverrideCommand(Overrides.CMD_SPINDLE_OVR_FINE_PLUS); - } - } catch (Exception e) { - e.printStackTrace(); - } - } + protected abstract void adjustRapidOverride(OverridePercents currentOverridePercents); protected abstract int getSpeedMinorStep(OverrideType overrideType); @@ -161,18 +120,6 @@ private void stop() { @Override public boolean hasSettled() { OverridePercents overrides = controller.getControllerStatus().getOverrides(); - return overrides.spindle() == targetSpindleSpeed && overrides.feed() == targetFeedSpeed; - } - - @Override - public void setSpeedTarget(OverrideType type, int percent) { - percent = (int) Math.round(roundToNearestStepValue(percent, getSpeedMin(type), getSpeedMax(type), getSpeedStep(type))); - if (type == OverrideType.FEED_SPEED) { - targetFeedSpeed = percent; - } else if (type == OverrideType.SPINDLE_SPEED) { - targetSpindleSpeed = percent; - } - - start(); + return overrides.spindle() == targetSpindleSpeed && overrides.feed() == targetFeedSpeed && overrides.rapid() == targetRapidSpeed; } } diff --git a/ugs-core/src/com/willwinder/universalgcodesender/firmware/DefaultOverrideManager.java b/ugs-core/src/com/willwinder/universalgcodesender/firmware/DefaultOverrideManager.java index 16785ff722..a0e5c55665 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/firmware/DefaultOverrideManager.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/firmware/DefaultOverrideManager.java @@ -20,6 +20,7 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.universalgcodesender.listeners.OverrideType; import com.willwinder.universalgcodesender.model.Overrides; +import com.willwinder.universalgcodesender.services.MessageService; import java.util.List; @@ -31,7 +32,7 @@ This file is part of Universal Gcode Sender (UGS). */ public class DefaultOverrideManager implements IOverrideManager { @Override - public void setSpeedTarget(OverrideType type, int value) { + public void setSliderTarget(OverrideType type, int value) { // Not implemented } @@ -41,17 +42,17 @@ public boolean hasSettled() { } @Override - public int getSpeedMax(OverrideType type) { + public int getSliderMax(OverrideType type) { return 0; } @Override - public int getSpeedMin(OverrideType type) { + public int getSliderMin(OverrideType type) { return 0; } @Override - public int getSpeedStep(OverrideType type) { + public int getSliderStep(OverrideType type) { return 0; } @@ -61,17 +62,17 @@ public void sendOverrideCommand(Overrides command) { } @Override - public int getSpeedDefault(OverrideType overrideType) { + public int getSliderDefault(OverrideType overrideType) { return 0; } @Override - public int getSpeedTargetValue(OverrideType type) { + public int getSliderTargetValue(OverrideType type) { return 0; } @Override - public List getSpeedTypes() { + public List getSliderTypes() { return List.of(); } @@ -80,6 +81,11 @@ public List getToggleTypes() { return List.of(); } + @Override + public List getRadioTypes() { + return List.of(); + } + @Override public boolean isAvailable() { return false; @@ -94,4 +100,29 @@ public void toggle(OverrideType overrideType) { public boolean isToggled(OverrideType overrideType) { return false; } + + @Override + public int getRadioDefault(OverrideType type) { + return 0; + } + + @Override + public void setRadioTarget(OverrideType type, int value) { + // Not implemented + } + + @Override + public void setMessageService(MessageService messageService) { + // Not implemented + } + + @Override + public List getSliderSteps(OverrideType type) { + return List.of(); + } + + @Override + public List getRadioSteps(OverrideType type) { + return List.of(); + } } diff --git a/ugs-core/src/com/willwinder/universalgcodesender/firmware/IOverrideManager.java b/ugs-core/src/com/willwinder/universalgcodesender/firmware/IOverrideManager.java index 6cc2a7fcc2..10ba8ef651 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/firmware/IOverrideManager.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/firmware/IOverrideManager.java @@ -20,43 +20,96 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.universalgcodesender.listeners.OverrideType; import com.willwinder.universalgcodesender.model.Overrides; +import com.willwinder.universalgcodesender.services.MessageService; import java.util.List; /** - * The override manager is used to apply overrides to the controller + * The override manager is used to apply overrides to the controller. There are three types of controls + * available: toggles, sliders and radio buttons. Toggle buttons for turning a feature on and off. + * Radio buttons for selecting fixed values. Sliders for selecting a range of values. * * @author Joacim Breiler */ public interface IOverrideManager { /** - * Sets the new override percents for the given type. If the controller doesn't support given override value + * Sets the new override value for the given type. If the controller doesn't support given override value * the nearest will be used instead. If the override type does not support setting a speed step it is ignored. - * Which {@link OverrideType} that can be used with this function is determined with the {@link #getSpeedTypes}. + * Which {@link OverrideType} that can be used with this function is determined with the {@link #getSliderTypes}. * * @param type the override value to set * @param value new controller override value in percent */ - void setSpeedTarget(OverrideType type, int value); + void setSliderTarget(OverrideType type, int value); - int getSpeedMax(OverrideType type); + /** + * Returns the maximum speed value. Which {@link OverrideType} that can + * be used with this function is determined with the {@link #getSliderTypes()}. + * + * @param type the override value to get + * @return the maximum slider value + */ + int getSliderMax(OverrideType type); - int getSpeedMin(OverrideType type); + /** + * Returns the minimum speed value. Which {@link OverrideType} that can + * be used with this function is determined with the {@link #getSliderTypes()}. + * + * @param type the override value to get + * @return the minimum slider value + */ + int getSliderMin(OverrideType type); - int getSpeedStep(OverrideType type); + /** + * The minimum slider step. Which {@link OverrideType} that can be used with this function is determined with + * the {@link #getSliderTypes()}. + * + * @param type the override type + * @return the minimum slider step that can be set + */ + int getSliderStep(OverrideType type); + /** + * Sends an override command + * + * @param command the command to send. + */ void sendOverrideCommand(Overrides command); - int getSpeedDefault(OverrideType type); + /** + * Returns the default slider value + * + * @param type the override type + * @return the default override value + */ + int getSliderDefault(OverrideType type); /** * Get the target speed for the given override type. Which {@link OverrideType} that can be used with this - * function is determined with the {@link #getSpeedTypes}. + * function is determined with the {@link #getSliderTypes}. * * @param type the override type to get the target speed for. * @return the target speed in percent */ - int getSpeedTargetValue(OverrideType type); + int getSliderTargetValue(OverrideType type); + + /** + * Get a list with speed steps, typically for displaying labels in the slider. Which {@link OverrideType} that can + * be used with this function is determined with the {@link #getSliderTypes()}. + * + * @param type the override type + * @return a list of available slider step values + */ + List getSliderSteps(OverrideType type); + + /** + * Get a list with radio step values. Which {@link OverrideType} that can be used with this + * function is determined with the {@link #getRadioTypes()}. + * + * @param type the override type + * @return a list of available radio step values + */ + List getRadioSteps(OverrideType type); /** * Returns true if the changes to be made with the override manager has settled and are done. @@ -70,7 +123,7 @@ public interface IOverrideManager { * * @return a list of override speed types */ - List getSpeedTypes(); + List getSliderTypes(); /** * Returns the override types that can be toggled @@ -79,6 +132,13 @@ public interface IOverrideManager { */ List getToggleTypes(); + /** + * Returns the override types that can be set with speed settings + * + * @return a list of override speed types + */ + List getRadioTypes(); + /** * Returns true when override functions are available * @@ -95,10 +155,31 @@ public interface IOverrideManager { void toggle(OverrideType type); /** - * Returns if the given override is currently toggled. + * Returns if the given override is currently toggled. Which {@link OverrideType} that can be used with this + * function is determined with the {@link #getToggleTypes()}. * * @param type the override type * @return true if the override is active */ boolean isToggled(OverrideType type); + + /** + * Gets the default value. Which {@link OverrideType} that can be used with this + * function is determined with the {@link #getRadioTypes()}. + * + * @param type the override type + * @return the default value + */ + int getRadioDefault(OverrideType type); + + /** + * Sets the target value. Which {@link OverrideType} that can be used with this + * function is determined with the {@link #getRadioTypes()}. + * + * @param type the override type + * @param value the target value + */ + void setRadioTarget(OverrideType type, int value); + + void setMessageService(MessageService messageService); } diff --git a/ugs-core/src/com/willwinder/universalgcodesender/firmware/fluidnc/FluidNCController.java b/ugs-core/src/com/willwinder/universalgcodesender/firmware/fluidnc/FluidNCController.java index c3a4e9793c..1fa3b873b6 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/firmware/fluidnc/FluidNCController.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/firmware/fluidnc/FluidNCController.java @@ -122,7 +122,7 @@ public FluidNCController(ICommunicator communicator) { this.communicator.addListener(this); this.fileService = new FluidNCFileService(this, positionPollTimer); this.commandCreator = new FluidNCCommandCreator(); - this.overrideManager = new GrblOverrideManager(this, communicator); + this.overrideManager = new GrblOverrideManager(this, communicator, messageService); } @Override diff --git a/ugs-core/src/com/willwinder/universalgcodesender/firmware/g2core/G2CoreOverrideManager.java b/ugs-core/src/com/willwinder/universalgcodesender/firmware/g2core/G2CoreOverrideManager.java deleted file mode 100644 index e2edc10f89..0000000000 --- a/ugs-core/src/com/willwinder/universalgcodesender/firmware/g2core/G2CoreOverrideManager.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - Copyright 2024 Will Winder - - This file is part of Universal Gcode Sender (UGS). - - UGS is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - UGS is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with UGS. If not, see . - */ -package com.willwinder.universalgcodesender.firmware.g2core; - -import com.willwinder.universalgcodesender.IController; -import com.willwinder.universalgcodesender.TinyGUtils; -import com.willwinder.universalgcodesender.communicator.ICommunicator; -import com.willwinder.universalgcodesender.firmware.AbstractOverrideManager; -import com.willwinder.universalgcodesender.firmware.IOverrideManager; -import com.willwinder.universalgcodesender.listeners.OverrideType; -import com.willwinder.universalgcodesender.model.Overrides; -import com.willwinder.universalgcodesender.types.GcodeCommand; - -import java.util.List; -import java.util.Optional; -import java.util.logging.Logger; - -public class G2CoreOverrideManager extends AbstractOverrideManager implements IOverrideManager { - private static final Logger LOGGER = Logger.getLogger(G2CoreOverrideManager.class.getSimpleName()); - private static final int MINOR_STEP = 1; - private static final int MAJOR_STEP = 10; - private static final int FEED_MIN = 10; - private static final int FEED_MAX = 200; - private static final int FEED_DEFAULT = 100; - private static final int SPINDLE_MIN = 10; - private static final int SPINDLE_MAX = 200; - private static final int SPINDLE_DEFAULT = 100; - - public G2CoreOverrideManager(IController controller, ICommunicator communicator) { - super(controller, communicator); - } - - @Override - protected int getSpeedMinorStep(OverrideType overrideType) { - return MINOR_STEP; - } - - @Override - protected int getSpeedMajorStep(OverrideType overrideType) { - return MAJOR_STEP; - } - - public void sendOverrideCommand(Overrides command) { - Optional gcodeCommand = TinyGUtils.createOverrideCommand(controller.getCommandCreator(), controller.getControllerStatus().getOverrides(), command); - if (gcodeCommand.isEmpty()) { - return; - } - - try { - controller.sendCommandImmediately(gcodeCommand.get()); - } catch (Exception e) { - LOGGER.info("Could not send override command " + command); - } - } - - @Override - public int getSpeedDefault(OverrideType type) { - return switch (type) { - case FEED_SPEED -> FEED_DEFAULT; - case SPINDLE_SPEED -> SPINDLE_DEFAULT; - default -> 0; - }; - } - - @Override - public int getSpeedTargetValue(OverrideType type) { - return switch (type) { - case FEED_SPEED -> targetFeedSpeed; - case SPINDLE_SPEED -> targetSpindleSpeed; - default -> 0; - }; - } - - @Override - public List getSpeedTypes() { - return List.of(OverrideType.FEED_SPEED, OverrideType.SPINDLE_SPEED); - } - - @Override - public List getToggleTypes() { - return List.of(OverrideType.SPINDLE_TOGGLE, OverrideType.MIST_TOGGLE, OverrideType.FLOOD_TOGGLE); - } - - @Override - public void toggle(OverrideType type) { - switch (type) { - case SPINDLE_TOGGLE -> sendOverrideCommand(Overrides.CMD_TOGGLE_SPINDLE); - case MIST_TOGGLE -> sendOverrideCommand(Overrides.CMD_TOGGLE_MIST_COOLANT); - case FLOOD_TOGGLE -> sendOverrideCommand(Overrides.CMD_TOGGLE_FLOOD_COOLANT); - default -> throw new IllegalStateException("Unexpected value: " + type); - } - } - - @Override - public boolean isToggled(OverrideType overrideType) { - return switch (overrideType) { - case MIST_TOGGLE -> controller.getControllerStatus().getAccessoryStates().mist(); - case FLOOD_TOGGLE -> controller.getControllerStatus().getAccessoryStates().flood(); - case SPINDLE_TOGGLE -> (controller.getControllerStatus().getSpindleSpeed() > 0); - default -> false; - }; - } - - @Override - public int getSpeedMax(OverrideType type) { - return switch (type) { - case FEED_SPEED -> FEED_MAX; - case SPINDLE_SPEED -> SPINDLE_MAX; - case RAPID_SPEED -> 100; - default -> 0; - }; - } - - @Override - public int getSpeedMin(OverrideType type) { - return switch (type) { - case FEED_SPEED -> FEED_MIN; - case SPINDLE_SPEED -> SPINDLE_MIN; - case RAPID_SPEED -> 25; - default -> 0; - }; - } - - @Override - public int getSpeedStep(OverrideType type) { - return switch (type) { - case FEED_SPEED, SPINDLE_SPEED -> MINOR_STEP; - default -> 0; - }; - } - -} diff --git a/ugs-core/src/com/willwinder/universalgcodesender/firmware/grbl/GrblOverrideManager.java b/ugs-core/src/com/willwinder/universalgcodesender/firmware/grbl/GrblOverrideManager.java index ddefd79805..621ccc7eae 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/firmware/grbl/GrblOverrideManager.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/firmware/grbl/GrblOverrideManager.java @@ -20,12 +20,16 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.universalgcodesender.GrblUtils; import com.willwinder.universalgcodesender.IController; +import static com.willwinder.universalgcodesender.Utils.roundToNearestStepValue; import com.willwinder.universalgcodesender.communicator.ICommunicator; import com.willwinder.universalgcodesender.firmware.AbstractOverrideManager; import com.willwinder.universalgcodesender.firmware.IOverrideManager; import com.willwinder.universalgcodesender.firmware.OverrideException; +import com.willwinder.universalgcodesender.listeners.MessageType; +import com.willwinder.universalgcodesender.listeners.OverridePercents; import com.willwinder.universalgcodesender.listeners.OverrideType; import com.willwinder.universalgcodesender.model.Overrides; +import com.willwinder.universalgcodesender.services.MessageService; import java.util.List; @@ -38,11 +42,88 @@ public class GrblOverrideManager extends AbstractOverrideManager implements IOve private static final int SPINDLE_MIN = 10; private static final int SPINDLE_MAX = 200; private static final int SPINDLE_DEFAULT = 100; + private static final int RAPID_SPEED_MAX = 100; + private static final int RAPID_SPEED_MIN = 25; + private static final int RAPID_SPEED_STEP = 25; + private static final int RAPID_DEFAULT = 100; + private MessageService messageService; - public GrblOverrideManager(IController controller, ICommunicator communicator) { + public GrblOverrideManager(IController controller, ICommunicator communicator, MessageService messageService) { super(controller, communicator); + this.messageService = messageService; } + @Override + protected void adjustRapidOverride(OverridePercents currentOverridePercents) { + if (currentOverridePercents.rapid() == targetRapidSpeed) { + return; + } + + try { + if (targetRapidSpeed <= 25) { + sendOverrideCommand(Overrides.CMD_RAPID_OVR_LOW); + } else if (targetRapidSpeed <= 50) { + sendOverrideCommand(Overrides.CMD_RAPID_OVR_MEDIUM); + } else { + sendOverrideCommand(Overrides.CMD_RAPID_OVR_RESET); + } + } catch (Exception e) { + e.printStackTrace(); + } + + } + + @Override + protected void adjustFeedOverride(OverridePercents currentOverridePercents) { + if (currentOverridePercents.feed() == targetFeedSpeed) { + return; + } + + float currentFeed = currentOverridePercents.feed(); + int majorSteps = (int) ((targetFeedSpeed - currentFeed) / getSpeedMajorStep(OverrideType.FEED_SPEED)); + int minorSteps = (int) ((targetFeedSpeed - currentFeed) / getSpeedMinorStep(OverrideType.FEED_SPEED)); + + try { + if (majorSteps < 0) { + sendOverrideCommand(Overrides.CMD_FEED_OVR_COARSE_MINUS); + } else if (majorSteps > 0) { + sendOverrideCommand(Overrides.CMD_FEED_OVR_COARSE_PLUS); + } else if (minorSteps < 0) { + sendOverrideCommand(Overrides.CMD_FEED_OVR_FINE_MINUS); + } else if (minorSteps > 0) { + sendOverrideCommand(Overrides.CMD_FEED_OVR_FINE_PLUS); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + protected void adjustSpindleOverride(OverridePercents currentOverridePercents) { + if (currentOverridePercents.spindle() == targetSpindleSpeed) { + return; + } + + float currentSpindle = currentOverridePercents.spindle(); + int majorSteps = (int) ((targetSpindleSpeed - currentSpindle) / getSpeedMajorStep(OverrideType.SPINDLE_SPEED)); + int minorSteps = (int) ((targetSpindleSpeed - currentSpindle) / getSpeedMinorStep(OverrideType.SPINDLE_SPEED)); + + try { + if (majorSteps < 0) { + sendOverrideCommand(Overrides.CMD_SPINDLE_OVR_COARSE_MINUS); + } else if (majorSteps > 0) { + sendOverrideCommand(Overrides.CMD_SPINDLE_OVR_COARSE_PLUS); + } else if (minorSteps < 0) { + sendOverrideCommand(Overrides.CMD_SPINDLE_OVR_FINE_MINUS); + } else if (minorSteps > 0) { + sendOverrideCommand(Overrides.CMD_SPINDLE_OVR_FINE_PLUS); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override protected int getSpeedMinorStep(OverrideType overrideType) { return MINOR_STEP; @@ -58,32 +139,39 @@ public void sendOverrideCommand(Overrides command) { if (realTimeCommand != null) { try { communicator.sendByteImmediately(realTimeCommand); + messageService.dispatchMessage(MessageType.VERBOSE, ">>> 0x" + String.format("%02X ", realTimeCommand) + "\n"); } catch (Exception e) { throw new OverrideException("Could not send override command", e); } } } + public void setMessageService(MessageService messageService) { + this.messageService = messageService; + } + @Override - public int getSpeedDefault(OverrideType type) { + public int getSliderDefault(OverrideType type) { return switch (type) { case FEED_SPEED -> FEED_DEFAULT; case SPINDLE_SPEED -> SPINDLE_DEFAULT; + case RAPID_SPEED -> RAPID_DEFAULT; default -> 0; }; } @Override - public int getSpeedTargetValue(OverrideType type) { + public int getSliderTargetValue(OverrideType type) { return switch (type) { case FEED_SPEED -> targetFeedSpeed; case SPINDLE_SPEED -> targetSpindleSpeed; + case RAPID_SPEED -> targetRapidSpeed; default -> 0; }; } @Override - public List getSpeedTypes() { + public List getSliderTypes() { return List.of(OverrideType.FEED_SPEED, OverrideType.SPINDLE_SPEED); } @@ -92,6 +180,11 @@ public List getToggleTypes() { return List.of(OverrideType.SPINDLE_TOGGLE, OverrideType.MIST_TOGGLE, OverrideType.FLOOD_TOGGLE); } + @Override + public List getRadioTypes() { + return List.of(OverrideType.RAPID_SPEED); + } + @Override public void toggle(OverrideType type) { switch (type) { @@ -113,29 +206,77 @@ public boolean isToggled(OverrideType overrideType) { } @Override - public int getSpeedMax(OverrideType type) { + public int getRadioDefault(OverrideType type) { + return getSliderDefault(type); + } + + @Override + public void setRadioTarget(OverrideType type, int value) { + setSliderTarget(type, value); + } + + @Override + public int getSliderMax(OverrideType type) { return switch (type) { case FEED_SPEED -> FEED_MAX; case SPINDLE_SPEED -> SPINDLE_MAX; + case RAPID_SPEED -> RAPID_SPEED_MAX; default -> 0; }; } @Override - public int getSpeedMin(OverrideType type) { + public int getSliderMin(OverrideType type) { return switch (type) { case FEED_SPEED -> FEED_MIN; case SPINDLE_SPEED -> SPINDLE_MIN; + case RAPID_SPEED -> RAPID_SPEED_MIN; default -> 0; }; } @Override - public int getSpeedStep(OverrideType type) { + public int getSliderStep(OverrideType type) { return switch (type) { case FEED_SPEED, SPINDLE_SPEED -> MINOR_STEP; + case RAPID_SPEED -> RAPID_SPEED_STEP; default -> 0; }; } + @Override + public void setSliderTarget(OverrideType type, int percent) { + percent = (int) Math.round(roundToNearestStepValue(percent, getSliderMin(type), getSliderMax(type), getSliderStep(type))); + if (type == OverrideType.FEED_SPEED) { + targetFeedSpeed = percent; + } else if (type == OverrideType.SPINDLE_SPEED) { + targetSpindleSpeed = percent; + } else if (type == OverrideType.RAPID_SPEED) { + if (percent < 50) { + targetRapidSpeed = 25; + } else if (percent < 100) { + targetRapidSpeed = 50; + } else { + targetRapidSpeed = 100; + } + } + + start(); + } + + @Override + public List getSliderSteps(OverrideType type) { + if (type == OverrideType.FEED_SPEED || type == OverrideType.SPINDLE_SPEED) { + return List.of(0, 100, 200); + } + return List.of(); + } + + @Override + public List getRadioSteps(OverrideType type) { + if(type == OverrideType.RAPID_SPEED) { + return List.of(25, 50, 100); + } + return List.of(); + } } diff --git a/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/OverrideRadioButtons.java b/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/OverrideRadioButtons.java new file mode 100644 index 0000000000..fa79e17c0d --- /dev/null +++ b/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/OverrideRadioButtons.java @@ -0,0 +1,88 @@ +/* + Copyright 2024 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ +package com.willwinder.universalgcodesender.uielements.components; + +import com.willwinder.universalgcodesender.firmware.IOverrideManager; +import com.willwinder.universalgcodesender.listeners.OverrideType; +import net.miginfocom.swing.MigLayout; + +import javax.swing.AbstractAction; +import javax.swing.ButtonGroup; +import javax.swing.JPanel; +import javax.swing.JToggleButton; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class OverrideRadioButtons extends JPanel { + private final Map buttons = new HashMap<>(); + private final ButtonGroup buttonGroup; + private final int defaultValue; + private final List listeners = new ArrayList<>(); + + public OverrideRadioButtons(IOverrideManager overrideManager, OverrideType type) { + setLayout(new MigLayout("fill, inset 0")); + List steps = overrideManager.getRadioSteps(type); + buttonGroup = new ButtonGroup(); + defaultValue = overrideManager.getRadioDefault(type); + + steps.forEach(step -> { + JToggleButton button = new JToggleButton(); + button.setAction(new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { + listeners.forEach(l -> l.stateChanged(new ChangeEvent(this))); + } + }); + button.setText(step + "%"); + button.setMargin(new Insets(4, 0, 4, 0)); + + buttonGroup.add(button); + buttons.put(step, button); + + add(button, "growx, sg 1, w 40::"); + }); + + setValue(defaultValue); + } + + public void addChangeListener(ChangeListener l) { + listeners.add(l); + } + + public int getValue() { + return buttons.entrySet() + .stream() + .filter(b -> b.getValue().isSelected()) + .map(Map.Entry::getKey).findFirst() + .orElse(defaultValue); + } + + public void setValue(int value) { + JToggleButton button = buttons.get(value); + if (button != null) { + buttonGroup.setSelected(button.getModel(), true); + } + } +} diff --git a/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/OverrideSpeedSlider.java b/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/OverrideSpeedSlider.java new file mode 100644 index 0000000000..9a2626055a --- /dev/null +++ b/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/OverrideSpeedSlider.java @@ -0,0 +1,68 @@ +/* + Copyright 2024 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ +package com.willwinder.universalgcodesender.uielements.components; + +import com.willwinder.universalgcodesender.firmware.IOverrideManager; +import com.willwinder.universalgcodesender.listeners.OverrideType; +import net.miginfocom.swing.MigLayout; + +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.event.ChangeListener; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; + +public class OverrideSpeedSlider extends JPanel { + private final JSlider slider; + + public OverrideSpeedSlider(IOverrideManager overrideManager, OverrideType type) { + List steps = overrideManager.getSliderSteps(type); + int minValue = steps.stream().min(Integer::compare).orElse(0); + int maxValue = steps.stream().max(Integer::compare).orElse(0); + + slider = new JSlider(minValue, maxValue, overrideManager.getSliderDefault(type)); + slider.setMinorTickSpacing(0); + slider.setMajorTickSpacing(10); + + Dictionary dict = new Hashtable<>(); + steps.forEach(step -> dict.put(step, new JLabel(step + "%"))); + slider.setLabelTable(dict); + slider.setPaintLabels(true); + slider.setPaintTicks(true); + slider.setPaintTrack(true); + + setLayout(new MigLayout("fill, inset 0")); + add(slider, "grow, w 100::"); + } + + public void addChangeListener(ChangeListener l) { + slider.addChangeListener(l); + } + + public int getValue() { + return slider.getValue(); + } + + public void setValue(int value) { + slider.setValue(value); + } +} diff --git a/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/OverrideToggleButtons.java b/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/OverrideToggleButtons.java new file mode 100644 index 0000000000..5c15d45cf3 --- /dev/null +++ b/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/OverrideToggleButtons.java @@ -0,0 +1,66 @@ +/* + Copyright 2024 Will Winder + + This file is part of Universal Gcode Sender (UGS). + + UGS is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + UGS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with UGS. If not, see . + */ +package com.willwinder.universalgcodesender.uielements.components; + +import com.willwinder.universalgcodesender.firmware.IOverrideManager; +import com.willwinder.universalgcodesender.listeners.OverrideType; +import com.willwinder.universalgcodesender.utils.ThreadHelper; +import net.miginfocom.swing.MigLayout; + +import javax.swing.AbstractAction; +import javax.swing.JPanel; +import javax.swing.JToggleButton; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.util.HashMap; +import java.util.Map; + +public class OverrideToggleButtons extends JPanel { + private final IOverrideManager overrideManager; + private Map toggleButtons = new HashMap<>(); + + public OverrideToggleButtons(IOverrideManager overrideManager) { + this.overrideManager = overrideManager; + setLayout(new MigLayout("fillx, inset 0")); + overrideManager.getToggleTypes().forEach(this::createAndAddToggleButtons); + + } + + private void createAndAddToggleButtons(OverrideType overrideType) { + JToggleButton toggleButton = new JToggleButton(overrideType.name()); + toggleButton.setMargin(new Insets(4, 0, 4, 0)); + toggleButton.setAction(new AbstractAction(overrideType.getLabel()) { + @Override + public void actionPerformed(ActionEvent e) { + overrideManager.toggle(overrideType); + toggleButton.setSelected(!overrideManager.isToggled(overrideType)); + ThreadHelper.invokeLater(() -> toggleButton.setSelected(overrideManager.isToggled(overrideType)), 200); + } + }); + add(toggleButton, "growx, sg 1, w 40:40:"); + toggleButtons.put(overrideType, toggleButton); + } + + public void setSelected(OverrideType type, boolean toggled) { + JToggleButton toggleButton = toggleButtons.get(type); + if (toggleButton != null) { + toggleButton.setSelected(toggled); + } + } +} diff --git a/ugs-core/src/com/willwinder/universalgcodesender/uielements/panels/OverridesPanel.java b/ugs-core/src/com/willwinder/universalgcodesender/uielements/panels/OverridesPanel.java index 8718a9aaca..fe0b4ab673 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/uielements/panels/OverridesPanel.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/uielements/panels/OverridesPanel.java @@ -1,5 +1,5 @@ /* - Copyright 2016-2018 Will Winder + Copyright 2016-2024 Will Winder This file is part of Universal Gcode Sender (UGS). @@ -27,21 +27,16 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.universalgcodesender.model.UGSEvent; import com.willwinder.universalgcodesender.model.events.ControllerStateEvent; import com.willwinder.universalgcodesender.model.events.ControllerStatusEvent; +import com.willwinder.universalgcodesender.uielements.components.OverrideRadioButtons; +import com.willwinder.universalgcodesender.uielements.components.OverrideSpeedSlider; +import com.willwinder.universalgcodesender.uielements.components.OverrideToggleButtons; import static com.willwinder.universalgcodesender.uielements.panels.OverrideLabels.TOGGLE_SHORT; -import com.willwinder.universalgcodesender.utils.ThreadHelper; import net.miginfocom.swing.MigLayout; -import javax.swing.AbstractAction; -import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.JSlider; -import javax.swing.JToggleButton; import javax.swing.SwingConstants; -import java.awt.event.ActionEvent; import java.util.Arrays; -import java.util.Dictionary; -import java.util.Hashtable; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -52,13 +47,13 @@ This file is part of Universal Gcode Sender (UGS). */ public final class OverridesPanel extends JPanel implements UGSEventListener { private final transient BackendAPI backend; - private final JPanel overridesControlsPanel = new JPanel(new MigLayout("fillx")); + private final JPanel overridesControlsPanel = new JPanel(new MigLayout("fillx, inset 0")); private final JLabel notConnectedLabel = new JLabel("Not connected", SwingConstants.CENTER); private final JLabel notSupportedLabel = new JLabel("" + OverrideLabels.NOT_SUPPORTED + "", SwingConstants.CENTER); - private final Map speedSliders = new ConcurrentHashMap<>(); - private final Map toggleButtons = new ConcurrentHashMap<>(); - + private final Map speedSliders = new ConcurrentHashMap<>(); + private final Map speedButtons = new ConcurrentHashMap<>(); private boolean overridesPanelInitiated = false; + private OverrideToggleButtons overrideToggleButtons; public OverridesPanel(BackendAPI backend) { this.backend = backend; @@ -77,7 +72,7 @@ public void updateControls() { if (backend.getControllerState() == ControllerState.DISCONNECTED || backend.getControllerState() == ControllerState.CONNECTING) { removeComponents(); return; - } else if (!backend.getController().getCapabilities().hasOverrides() || (backend.getController().getOverrideManager().getSpeedTypes().isEmpty() && backend.getController().getOverrideManager().getToggleTypes().isEmpty())) { + } else if (!backend.getController().getCapabilities().hasOverrides() || (backend.getController().getOverrideManager().getSliderTypes().isEmpty() && backend.getController().getOverrideManager().getToggleTypes().isEmpty())) { showNotSupportedPanel(); return; } else if (!overridesPanelInitiated) { @@ -107,8 +102,16 @@ public void UGSEvent(UGSEvent evt) { } else if (evt instanceof ControllerStatusEvent controllerStatusEvent) { ControllerStatus status = controllerStatusEvent.getStatus(); if (status.getOverrides() != null) { - speedSliders.keySet().forEach(type -> speedSliders.get(type).setValue(backend.getController().getOverrideManager().getSpeedTargetValue(type))); - toggleButtons.keySet().forEach(type -> toggleButtons.get(type).setSelected(backend.getController().getOverrideManager().isToggled(type))); + IOverrideManager overrideManager = backend.getController().getOverrideManager(); + speedSliders.keySet().forEach(type -> { + int speedTargetValue = overrideManager.getSliderTargetValue(type); + speedSliders.get(type).setValue(speedTargetValue); + }); + speedButtons.keySet().forEach(type -> { + int speedTargetValue = overrideManager.getSliderTargetValue(type); + speedButtons.get(type).setValue(speedTargetValue); + }); + overrideManager.getToggleTypes().forEach(type -> overrideToggleButtons.setSelected(type, overrideManager.isToggled(type))); } } } @@ -116,7 +119,6 @@ public void UGSEvent(UGSEvent evt) { private void removeComponents() { overridesControlsPanel.removeAll(); speedSliders.clear(); - toggleButtons.clear(); overridesControlsPanel.setVisible(false); notConnectedLabel.setVisible(true); notSupportedLabel.setVisible(false); @@ -132,57 +134,53 @@ private void initAndShowOverridesPanel() { overridesControlsPanel.removeAll(); IOverrideManager overrideManager = backend.getController().getOverrideManager(); - if (!overrideManager.getToggleTypes().isEmpty()) { - overridesControlsPanel.add(new JLabel(TOGGLE_SHORT), "spanx, grow, wrap, gaptop 10"); - overrideManager.getToggleTypes().forEach(this::createAndAddToggleButtons); - } - - overrideManager.getSpeedTypes().forEach(this::createAndAddSpeedSlider); + createAndAddToggleButtons(overrideManager); + overrideManager.getRadioTypes().forEach(this::createAndAddRadioButtons); + overrideManager.getSliderTypes().forEach(this::createAndAddSpeedSlider); revalidate(); } - private void createAndAddToggleButtons(OverrideType overrideType) { + private void createAndAddToggleButtons(IOverrideManager overrideManager) { + if (overrideManager.getToggleTypes().isEmpty()) { + return; + } + overridesControlsPanel.add(new JLabel(TOGGLE_SHORT), "spanx, grow, wrap, gaptop 10"); + overrideToggleButtons = new OverrideToggleButtons(overrideManager); + overridesControlsPanel.add(overrideToggleButtons, "growx, w 40::"); + } + + private void createAndAddRadioButtons(OverrideType type) { IOverrideManager overrideManager = backend.getController().getOverrideManager(); - JToggleButton toggleSpindle = new JToggleButton(overrideType.name()); - toggleSpindle.setAction(new AbstractAction(overrideType.getLabel()) { - @Override - public void actionPerformed(ActionEvent e) { - overrideManager.toggle(overrideType); - toggleSpindle.setSelected(!overrideManager.isToggled(overrideType)); - ThreadHelper.invokeLater(() -> toggleSpindle.setSelected(overrideManager.isToggled(overrideType)), 200); - } - }); - overridesControlsPanel.add(toggleSpindle, "growx"); - toggleButtons.put(overrideType, toggleSpindle); + OverrideRadioButtons radioButtons = new OverrideRadioButtons(overrideManager, type); + radioButtons.addChangeListener(l -> updateRadio(type, radioButtons.getValue())); + speedButtons.put(type, radioButtons); + overridesControlsPanel.add(new JLabel(type.getLabel()), "newline, spanx, wrap, gaptop 10"); + overridesControlsPanel.add(radioButtons, "spanx, grow, wrap"); } private void createAndAddSpeedSlider(OverrideType type) { IOverrideManager overrideManager = backend.getController().getOverrideManager(); - JSlider speedSlider = new JSlider(0, overrideManager.getSpeedMax(type), overrideManager.getSpeedDefault(type)); - speedSlider.setMinorTickSpacing(0); - speedSlider.setMajorTickSpacing(10); + OverrideSpeedSlider speedSlider = new OverrideSpeedSlider(overrideManager, type); + speedSlider.addChangeListener(l -> updateSpeed(type, speedSlider.getValue())); speedSliders.put(type, speedSlider); + overridesControlsPanel.add(new JLabel(type.getLabel()), "newline, spanx, wrap, gaptop 10"); + overridesControlsPanel.add(speedSlider, "spanx, grow, wrap"); + } - Dictionary dict = new Hashtable<>(); - for (int i = 0; i <= overrideManager.getSpeedMax(type); i += 100) { - dict.put(i, new JLabel(i + "%")); + private void updateSpeed(OverrideType type, int value) { + if (backend.getController() == null || !backend.isConnected()) { + return; } - speedSlider.setLabelTable(dict); - speedSlider.setPaintLabels(true); - speedSlider.setPaintTicks(true); - speedSlider.setPaintTrack(true); - speedSlider.addChangeListener(l -> updateSpeed(type, speedSlider)); - overridesControlsPanel.add(new JLabel(type.getLabel()), "spanx, grow, newline, wrap, gaptop 10"); - overridesControlsPanel.add(speedSlider, "spanx, grow, wrap"); + backend.getController().getOverrideManager().setSliderTarget(type, value); } - private void updateSpeed(OverrideType type, JSlider slider) { + private void updateRadio(OverrideType type, int value) { if (backend.getController() == null || !backend.isConnected()) { return; } - backend.getController().getOverrideManager().setSpeedTarget(type, slider.getValue()); + backend.getController().getOverrideManager().setRadioTarget(type, value); } } diff --git a/ugs-core/test/com/willwinder/universalgcodesender/firmware/grbl/GrblOverrideManagerTest.java b/ugs-core/test/com/willwinder/universalgcodesender/firmware/grbl/GrblOverrideManagerTest.java index dc65a50d24..883aab6e40 100644 --- a/ugs-core/test/com/willwinder/universalgcodesender/firmware/grbl/GrblOverrideManagerTest.java +++ b/ugs-core/test/com/willwinder/universalgcodesender/firmware/grbl/GrblOverrideManagerTest.java @@ -10,6 +10,7 @@ import com.willwinder.universalgcodesender.listeners.OverridePercents; import com.willwinder.universalgcodesender.listeners.OverrideType; import com.willwinder.universalgcodesender.model.Overrides; +import com.willwinder.universalgcodesender.services.MessageService; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -28,7 +29,6 @@ public class GrblOverrideManagerTest { @Mock private IController controller; - @Mock private ICommunicator communicator; private GrblOverrideManager overrideManager; @@ -36,7 +36,7 @@ public class GrblOverrideManagerTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - overrideManager = new GrblOverrideManager(controller, communicator); + overrideManager = new GrblOverrideManager(controller, communicator, new MessageService()); } @Test @@ -90,30 +90,31 @@ public void getSpeedValuesShouldReturnBasedOnOverrideType() { mockOverrideCapabilities(); mockControllerStatus(ControllerState.RUN); - assertEquals(100, overrideManager.getSpeedDefault(OverrideType.SPINDLE_SPEED)); - assertEquals(100, overrideManager.getSpeedDefault(OverrideType.FEED_SPEED)); - assertEquals(0, overrideManager.getSpeedDefault(OverrideType.RAPID_SPEED)); - assertEquals(0, overrideManager.getSpeedDefault(OverrideType.MIST_TOGGLE)); + assertEquals(100, overrideManager.getSliderDefault(OverrideType.SPINDLE_SPEED)); + assertEquals(100, overrideManager.getSliderDefault(OverrideType.FEED_SPEED)); + assertEquals(100, overrideManager.getSliderDefault(OverrideType.RAPID_SPEED)); + assertEquals(100, overrideManager.getRadioDefault(OverrideType.RAPID_SPEED)); + assertEquals(0, overrideManager.getSliderDefault(OverrideType.MIST_TOGGLE)); - assertEquals(200, overrideManager.getSpeedMax(OverrideType.SPINDLE_SPEED)); - assertEquals(200, overrideManager.getSpeedMax(OverrideType.FEED_SPEED)); - assertEquals(0, overrideManager.getSpeedMax(OverrideType.RAPID_SPEED)); - assertEquals(0, overrideManager.getSpeedMax(OverrideType.MIST_TOGGLE)); + assertEquals(200, overrideManager.getSliderMax(OverrideType.SPINDLE_SPEED)); + assertEquals(200, overrideManager.getSliderMax(OverrideType.FEED_SPEED)); + assertEquals(100, overrideManager.getSliderMax(OverrideType.RAPID_SPEED)); + assertEquals(0, overrideManager.getSliderMax(OverrideType.MIST_TOGGLE)); - assertEquals(10, overrideManager.getSpeedMin(OverrideType.SPINDLE_SPEED)); - assertEquals(10, overrideManager.getSpeedMin(OverrideType.FEED_SPEED)); - assertEquals(0, overrideManager.getSpeedMin(OverrideType.RAPID_SPEED)); - assertEquals(0, overrideManager.getSpeedMin(OverrideType.MIST_TOGGLE)); + assertEquals(10, overrideManager.getSliderMin(OverrideType.SPINDLE_SPEED)); + assertEquals(10, overrideManager.getSliderMin(OverrideType.FEED_SPEED)); + assertEquals(25, overrideManager.getSliderMin(OverrideType.RAPID_SPEED)); + assertEquals(0, overrideManager.getSliderMin(OverrideType.MIST_TOGGLE)); - assertEquals(100, overrideManager.getSpeedTargetValue(OverrideType.SPINDLE_SPEED)); - assertEquals(100, overrideManager.getSpeedTargetValue(OverrideType.FEED_SPEED)); - assertEquals(0, overrideManager.getSpeedTargetValue(OverrideType.RAPID_SPEED)); - assertEquals(0, overrideManager.getSpeedTargetValue(OverrideType.MIST_TOGGLE)); + assertEquals(100, overrideManager.getSliderTargetValue(OverrideType.SPINDLE_SPEED)); + assertEquals(100, overrideManager.getSliderTargetValue(OverrideType.FEED_SPEED)); + assertEquals(100, overrideManager.getSliderTargetValue(OverrideType.RAPID_SPEED)); + assertEquals(0, overrideManager.getSliderTargetValue(OverrideType.MIST_TOGGLE)); - assertEquals(1, overrideManager.getSpeedStep(OverrideType.SPINDLE_SPEED)); - assertEquals(1, overrideManager.getSpeedStep(OverrideType.FEED_SPEED)); - assertEquals(0, overrideManager.getSpeedStep(OverrideType.RAPID_SPEED)); - assertEquals(0, overrideManager.getSpeedStep(OverrideType.MIST_TOGGLE)); + assertEquals(1, overrideManager.getSliderStep(OverrideType.SPINDLE_SPEED)); + assertEquals(1, overrideManager.getSliderStep(OverrideType.FEED_SPEED)); + assertEquals(25, overrideManager.getSliderStep(OverrideType.RAPID_SPEED)); + assertEquals(0, overrideManager.getSliderStep(OverrideType.MIST_TOGGLE)); assertEquals(10, overrideManager.getSpeedMajorStep(OverrideType.SPINDLE_SPEED)); assertEquals(10, overrideManager.getSpeedMajorStep(OverrideType.FEED_SPEED)); @@ -121,7 +122,7 @@ public void getSpeedValuesShouldReturnBasedOnOverrideType() { assertEquals(1, overrideManager.getSpeedMinorStep(OverrideType.SPINDLE_SPEED)); assertEquals(1, overrideManager.getSpeedMinorStep(OverrideType.FEED_SPEED)); - assertEquals(List.of(OverrideType.FEED_SPEED, OverrideType.SPINDLE_SPEED), overrideManager.getSpeedTypes()); + assertEquals(List.of(OverrideType.FEED_SPEED, OverrideType.SPINDLE_SPEED), overrideManager.getSliderTypes()); } @Test @@ -129,7 +130,7 @@ public void setSpeedTargetShouldSendCommand() throws Exception { mockControllerStatus(ControllerState.IDLE); mockOverrideCapabilities(); - overrideManager.setSpeedTarget(OverrideType.FEED_SPEED, 10); + overrideManager.setSliderTarget(OverrideType.FEED_SPEED, 10); verify(communicator, times(1)).sendByteImmediately(anyByte()); assertFalse(overrideManager.hasSettled()); @@ -144,7 +145,7 @@ public void hasSettledShouldReturnTrueWhenOverridePercentReachesTarget() { mockControllerStatus(ControllerState.IDLE); mockOverrideCapabilities(); - overrideManager.setSpeedTarget(OverrideType.FEED_SPEED, 10); + overrideManager.setSliderTarget(OverrideType.FEED_SPEED, 10); ControllerStatus controllerStatus = ControllerStatusBuilder.newInstance().setState(ControllerState.RUN).setOverrides(new OverridePercents(10, 100, 100)).build(); when(controller.getControllerStatus()).thenReturn(controllerStatus); overrideManager.onControllerStatus(controllerStatus); diff --git a/ugs-platform/ugs-platform-plugin-joystick/src/main/java/com/willwinder/ugs/nbp/joystick/action/AnalogOverrideAction.java b/ugs-platform/ugs-platform-plugin-joystick/src/main/java/com/willwinder/ugs/nbp/joystick/action/AnalogOverrideAction.java index bb86bb6055..0d64a40422 100644 --- a/ugs-platform/ugs-platform-plugin-joystick/src/main/java/com/willwinder/ugs/nbp/joystick/action/AnalogOverrideAction.java +++ b/ugs-platform/ugs-platform-plugin-joystick/src/main/java/com/willwinder/ugs/nbp/joystick/action/AnalogOverrideAction.java @@ -68,6 +68,6 @@ public void actionPerformed(ActionEvent e) { } IOverrideManager overrideManager = backend.getController().getOverrideManager(); - overrideManager.setSpeedTarget(overrideType, Math.round(value * overrideManager.getSpeedMax(overrideType) + overrideManager.getSpeedDefault(overrideType))); + overrideManager.setSliderTarget(overrideType, Math.round(value * overrideManager.getSliderMax(overrideType) + overrideManager.getSliderDefault(overrideType))); } } diff --git a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/control/OverridesTopComponent.java b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/control/OverridesTopComponent.java index 3ec3f02dae..775b996fb7 100644 --- a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/control/OverridesTopComponent.java +++ b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/control/OverridesTopComponent.java @@ -19,15 +19,19 @@ This file is part of Universal Gcode Sender (UGS). package com.willwinder.ugs.nbp.core.control; import com.willwinder.ugs.nbp.lib.Mode; -import com.willwinder.ugs.nbp.lib.services.LocalizingService; import com.willwinder.ugs.nbp.lib.lookup.CentralLookup; +import com.willwinder.ugs.nbp.lib.services.LocalizingService; import com.willwinder.universalgcodesender.model.BackendAPI; import com.willwinder.universalgcodesender.uielements.panels.OverridesPanel; -import java.awt.BorderLayout; +import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER; +import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.windows.TopComponent; +import javax.swing.JScrollPane; +import java.awt.BorderLayout; + /** * Top component which displays something. */ @@ -48,7 +52,7 @@ public final class OverridesTopComponent extends TopComponent { public OverridesTopComponent() { this.setLayout(new BorderLayout()); BackendAPI backend = CentralLookup.getDefault().lookup(BackendAPI.class); - this.add(new OverridesPanel(backend), BorderLayout.CENTER); + this.add(new JScrollPane(new OverridesPanel(backend), VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.CENTER); } @Override @@ -56,18 +60,4 @@ public void componentOpened() { setName(LocalizingService.OverridesTitle); setToolTipText(LocalizingService.OverridesTooltip); } - - @Override - public void componentClosed() { - // TODO add custom code on component closing - } - - public void writeProperties(java.util.Properties p) { - // better to version settings since initial version as advocated at - // http://wiki.apidesign.org/wiki/PropertyFiles - p.setProperty("version", "1.0"); - } - - public void readProperties(java.util.Properties p) { - } }