Skip to content

Commit 6847bcc

Browse files
authored
Added 3D orientation cube and new jog controllers (#2779)
1 parent d7543d5 commit 6847bcc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+17551
-145
lines changed

ugs-core/src/resources/MessagesBundle_en_US.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,3 +772,4 @@ settings.firmware = Firmware
772772
settings.metric = Metric
773773
settings.imperial = Imperial
774774
settings.probe = Probe
775+
settings.pendant.clear = Clear

ugs-fx/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# UGS FX
2+
3+
This is a variant of the application that is intended to supersede the classic edition
4+
and with time, maybe also the platform edition.
5+
6+
The motivation for using JavaFX is that it is getting harder to create flexible and nice looking UI:s
7+
with Java Swing. There are also a simplistic 3D scene graph and rendering API which is
8+
needed to create a more interactive visualizer.
9+
10+
The platform edition utilizes the Netbeans Platform which provides a ton of cool features, but is
11+
quite heavy to work with. We are also constrained to the NetBeans way of doing things.
12+
13+
## Icons
14+
15+
Whenever I need a new icon I look at the filled Phosphor icons:
16+
https://phosphoricons.com/
17+
18+
Simply add them as SVG:s and use the SvgLoader to take care of the loading. It will also
19+
take care of the color tinting and sizing.

ugs-fx/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@
6969
<version>1.7.1</version>
7070
</dependency>
7171

72+
<!-- For text editor and terminal -->
73+
<dependency>
74+
<groupId>org.fxmisc.richtext</groupId>
75+
<artifactId>richtextfx</artifactId>
76+
<version>0.11.5</version>
77+
</dependency>
78+
7279
<!-- For styling swing components -->
7380
<dependency>
7481
<groupId>com.formdev</groupId>

ugs-fx/src/main/java/com/willwinder/universalgcodesender/fx/Main.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
import com.willwinder.ugs.nbp.lib.lookup.CentralLookup;
55
import com.willwinder.universalgcodesender.fx.actions.ActionRegistry;
66
import com.willwinder.universalgcodesender.fx.actions.StartAction;
7-
import com.willwinder.universalgcodesender.fx.component.JogPane;
87
import com.willwinder.universalgcodesender.fx.component.MachineStatusPane;
98
import com.willwinder.universalgcodesender.fx.component.ToolBarMenu;
10-
import com.willwinder.universalgcodesender.fx.component.overlay.OverlayPane;
9+
import com.willwinder.universalgcodesender.fx.component.drawer.DrawerPane;
10+
import com.willwinder.universalgcodesender.fx.component.jog.JogPane;
1111
import com.willwinder.universalgcodesender.fx.helper.SvgLoader;
12+
import com.willwinder.universalgcodesender.fx.service.MacroActionService;
13+
import com.willwinder.universalgcodesender.fx.service.PendantService;
1214
import com.willwinder.universalgcodesender.fx.visualizer.Visualizer;
1315
import com.willwinder.universalgcodesender.model.BackendAPI;
1416
import com.willwinder.universalgcodesender.pendantui.PendantUI;
@@ -57,6 +59,7 @@ public void start(Stage primaryStage) {
5759

5860
VBox root = new VBox();
5961
Scene scene = new Scene(root);
62+
scene.getStylesheets().add(Main.class.getResource("/styles/root.css").toExternalForm());
6063
root.getChildren().addAll(toolBarMenu, contentSplitPane);
6164

6265
primaryStage.setTitle("Universal G-code Sender - " + Version.getVersion());
@@ -116,9 +119,9 @@ private void createContentPanel() {
116119
contentPanel = new StackPane();
117120
contentPanel.getChildren().add(new Visualizer());
118121

119-
OverlayPane overlayPane = new OverlayPane();
120-
contentPanel.getChildren().add(overlayPane);
121-
StackPane.setAlignment(overlayPane, Pos.BOTTOM_RIGHT);
122+
DrawerPane drawerPane = new DrawerPane();
123+
contentPanel.getChildren().add(drawerPane);
124+
StackPane.setAlignment(drawerPane, Pos.BOTTOM_RIGHT);
122125
}
123126

124127

@@ -135,6 +138,8 @@ private void createContentPane() {
135138

136139
private void createLeftPane() {
137140
leftSplitPane = new SplitPane();
141+
leftSplitPane.setStyle("-fx-border-color: transparent;");
142+
138143
leftSplitPane.setMinWidth(200);
139144
leftSplitPane.setOrientation(Orientation.VERTICAL);
140145
leftSplitPane.getItems().addAll(new MachineStatusPane(), new JogPane());
@@ -173,6 +178,9 @@ private void initialize() {
173178
PendantUI pendantUI = new PendantUI(backend);
174179
pendantUI.start();
175180
}
181+
182+
PendantService.getInstance();
183+
MacroActionService.registerMacros();
176184
}
177185

178186
public static void main(String[] args) {

ugs-fx/src/main/java/com/willwinder/universalgcodesender/fx/actions/ActionRegistry.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import java.util.Map;
1212
import java.util.Optional;
1313
import java.util.concurrent.ConcurrentHashMap;
14+
import java.util.stream.Collectors;
1415

1516
public class ActionRegistry {
1617
private static ActionRegistry instance;
@@ -39,12 +40,12 @@ private static void loadActionsOfClass() {
3940

4041
try {
4142
Constructor<? extends Action> declaredConstructor = ((Class<? extends Action>) classInfo).getDeclaredConstructor();
42-
4343
Action action = declaredConstructor.newInstance();
4444
actions.put(action.getId(), action);
45-
} catch (InstantiationException | IllegalAccessException | InvocationTargetException |
46-
NoSuchMethodException e) {
45+
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
4746
throw new RuntimeException(e);
47+
} catch (NoSuchMethodException e) {
48+
// Ignore
4849
}
4950
}
5051
}
@@ -86,4 +87,16 @@ public Collection<Action> getActions() {
8687
public Optional<Action> getAction(String id) {
8788
return Optional.ofNullable(actions.get(id));
8889
}
90+
91+
public void registerAction(Action action) {
92+
actions.put(action.getId(), action);
93+
}
94+
95+
public List<Action> getAllActionsOfClass(Class<? extends Action> clazz) {
96+
return actions
97+
.values()
98+
.stream()
99+
.filter(action -> clazz.isAssignableFrom(action.getClass()))
100+
.collect(Collectors.toUnmodifiableList());
101+
}
89102
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.willwinder.universalgcodesender.fx.actions;
2+
3+
import com.willwinder.ugs.nbp.lib.lookup.CentralLookup;
4+
import com.willwinder.universalgcodesender.MacroHelper;
5+
import com.willwinder.universalgcodesender.model.BackendAPI;
6+
import com.willwinder.universalgcodesender.model.UGSEvent;
7+
import com.willwinder.universalgcodesender.model.events.ControllerStateEvent;
8+
import com.willwinder.universalgcodesender.types.Macro;
9+
import com.willwinder.universalgcodesender.utils.GUIHelpers;
10+
import org.openide.util.Exceptions;
11+
12+
import java.awt.EventQueue;
13+
14+
public class MacroAction extends BaseAction {
15+
private final Macro macro;
16+
private final BackendAPI backend;
17+
18+
public MacroAction(Macro macro) {
19+
this.macro = macro;
20+
backend = CentralLookup.getDefault().lookup(BackendAPI.class);
21+
backend.addUGSEventListener(this::onEvent);
22+
enabledProperty().set(backend.isConnected() && backend.isIdle());
23+
titleProperty().set(macro.getName());
24+
}
25+
26+
private void onEvent(UGSEvent event) {
27+
if (event instanceof ControllerStateEvent) {
28+
enabledProperty().set(backend.isConnected() && backend.isIdle());
29+
}
30+
}
31+
32+
@Override
33+
public void handle(javafx.event.ActionEvent event) {
34+
if (macro == null || macro.getGcode() == null) {
35+
return;
36+
}
37+
38+
EventQueue.invokeLater(() -> {
39+
try {
40+
MacroHelper.executeCustomGcode(macro.getGcode(), backend);
41+
} catch (Exception ex) {
42+
GUIHelpers.displayErrorDialog(ex.getMessage());
43+
Exceptions.printStackTrace(ex);
44+
}
45+
});
46+
}
47+
48+
@Override
49+
public String getId() {
50+
return MacroAction.class.getSimpleName() + "_" + macro.getUuid();
51+
}
52+
}

ugs-fx/src/main/java/com/willwinder/universalgcodesender/fx/component/JogPane.java

Lines changed: 0 additions & 11 deletions
This file was deleted.

ugs-fx/src/main/java/com/willwinder/universalgcodesender/fx/component/MacrosPane.java

Lines changed: 0 additions & 13 deletions
This file was deleted.

ugs-fx/src/main/java/com/willwinder/universalgcodesender/fx/component/PortComboBoxCell.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import javafx.geometry.Pos;
88
import javafx.scene.control.Label;
99
import javafx.scene.control.ListCell;
10-
import javafx.scene.effect.ColorAdjust;
1110
import javafx.scene.image.Image;
1211
import javafx.scene.image.ImageView;
1312
import javafx.scene.layout.HBox;
@@ -20,7 +19,6 @@ public class PortComboBoxCell extends ListCell<IConnectionDevice> {
2019
private final Label manufacturerLabel = new Label();
2120
private final VBox textBox = new VBox(addressLabel, descriptionLabel, manufacturerLabel);
2221
private final HBox hbox = new HBox(8, icon, textBox);
23-
private final ColorAdjust invert;
2422

2523
public PortComboBoxCell() {
2624
icon.setFitWidth(24);
@@ -29,10 +27,6 @@ public PortComboBoxCell() {
2927
textBox.setSpacing(2);
3028
hbox.setPadding(new Insets(5, 5, 5, 5));
3129
hbox.setAlignment(Pos.CENTER_LEFT);
32-
33-
invert = new ColorAdjust();
34-
invert.setBrightness(1.0);
35-
invert.setContrast(-1.0); // kind of a cheap invert
3630
}
3731

3832
@Override
@@ -44,7 +38,6 @@ protected void updateItem(IConnectionDevice item, boolean empty) {
4438
setText(null);
4539
} else {
4640
icon.setImage(getDeviceIcon(item));
47-
icon.setEffect(isSelected() ? invert : null);
4841
addressLabel.setText(item.getAddress());
4942
descriptionLabel.setText(item.getDescription().orElse(null));
5043
manufacturerLabel.setText(item.getManufacturer().orElse(null));

ugs-fx/src/main/java/com/willwinder/universalgcodesender/fx/component/ToolBarMenu.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import com.willwinder.ugs.nbp.core.actions.UnlockAction;
66
import com.willwinder.universalgcodesender.fx.actions.ActionRegistry;
77
import com.willwinder.universalgcodesender.fx.actions.ConnectDisconnectAction;
8-
import com.willwinder.universalgcodesender.fx.actions.OpenFileAction;
98
import com.willwinder.universalgcodesender.fx.actions.OpenSettingsAction;
109
import com.willwinder.universalgcodesender.fx.control.ActionButton;
1110
import javafx.scene.Node;
@@ -26,8 +25,6 @@ public ToolBarMenu() {
2625
List<Node> children = getChildren();
2726
createButton(ConnectDisconnectAction.class).ifPresent(children::add);
2827
children.add(new Separator());
29-
createButton(OpenFileAction.class).ifPresent(children::add);
30-
children.add(new Separator());
3128
createButton(UnlockAction.class).ifPresent(children::add);
3229
createButton(SoftResetAction.class).ifPresent(children::add);
3330
createButton(HomingAction.class).ifPresent(children::add);

ugs-fx/src/main/java/com/willwinder/universalgcodesender/fx/component/overlay/OverlayPane.java renamed to ugs-fx/src/main/java/com/willwinder/universalgcodesender/fx/component/drawer/DrawerPane.java

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
package com.willwinder.universalgcodesender.fx.component.overlay;
1+
package com.willwinder.universalgcodesender.fx.component.drawer;
22

3-
import com.willwinder.universalgcodesender.fx.component.JobControlsPane;
4-
import com.willwinder.universalgcodesender.fx.component.MacrosPane;
5-
import com.willwinder.universalgcodesender.fx.component.TerminalPane;
63
import com.willwinder.universalgcodesender.fx.helper.Colors;
74
import com.willwinder.universalgcodesender.fx.helper.SvgLoader;
85
import com.willwinder.universalgcodesender.i18n.Localization;
96
import javafx.animation.TranslateTransition;
7+
import javafx.geometry.Insets;
108
import javafx.scene.Node;
9+
import javafx.scene.control.Button;
1110
import javafx.scene.control.Label;
1211
import javafx.scene.control.ToggleButton;
1312
import javafx.scene.control.ToggleGroup;
@@ -16,14 +15,16 @@
1615
import javafx.scene.layout.VBox;
1716
import javafx.util.Duration;
1817

19-
public class OverlayPane extends BorderPane {
18+
public class DrawerPane extends BorderPane {
2019

2120
private final ToggleGroup toggleGroup;
2221
private final VBox buttonBox;
2322

24-
public OverlayPane() {
25-
getStylesheets().add(getClass().getResource("/styles/overlay-pane.css").toExternalForm());
26-
getStyleClass().add("overlay-pane");
23+
public DrawerPane() {
24+
getStylesheets().add(getClass().getResource("/styles/drawer-pane.css").toExternalForm());
25+
getStyleClass().add("drawer-pane");
26+
setMaxWidth(600);
27+
setMaxHeight(120);
2728

2829
toggleGroup = new ToggleGroup();
2930

@@ -40,12 +41,22 @@ public OverlayPane() {
4041
setCenter(jobControlsPane);
4142
setLeft(buttonBox);
4243

43-
toggleGroup.selectedToggleProperty().addListener((obs, oldToggle, newToggle) -> {
44-
toggleDrawer(newToggle != null);
45-
});
44+
VBox rightBox = new VBox(createCollapseButton());
45+
rightBox.setPadding(new Insets(5));
46+
setRight(rightBox);
4647

47-
setMaxWidth(500);
48-
setMaxHeight(100);
48+
toggleGroup.selectedToggleProperty().addListener((obs, oldToggle, newToggle) -> toggleDrawer(newToggle != null));
49+
50+
}
51+
52+
private Button createCollapseButton() {
53+
Button collapseButton = new Button("", SvgLoader.loadImageIcon("icons/caret-double-right.svg", 24).orElse(null));
54+
collapseButton.getStyleClass().add("collapse-button");
55+
collapseButton.setOnAction(event -> toggleGroup.selectToggle(null));
56+
Tooltip tooltip = new Tooltip(Localization.getString("close"));
57+
tooltip.setShowDelay(Duration.millis(100));
58+
collapseButton.setTooltip(tooltip);
59+
return collapseButton;
4960
}
5061

5162
private void toggleDrawer(boolean drawerVisible) {

ugs-fx/src/main/java/com/willwinder/universalgcodesender/fx/component/JobControlsPane.java renamed to ugs-fx/src/main/java/com/willwinder/universalgcodesender/fx/component/drawer/JobControlsPane.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
package com.willwinder.universalgcodesender.fx.component;
1+
package com.willwinder.universalgcodesender.fx.component.drawer;
22

33
import com.willwinder.ugs.nbp.core.actions.PauseAction;
44
import com.willwinder.ugs.nbp.core.actions.StopAction;
55
import com.willwinder.ugs.nbp.lib.lookup.CentralLookup;
66
import com.willwinder.universalgcodesender.Utils;
77
import com.willwinder.universalgcodesender.fx.actions.Action;
88
import com.willwinder.universalgcodesender.fx.actions.ActionRegistry;
9+
import com.willwinder.universalgcodesender.fx.actions.OpenFileAction;
910
import com.willwinder.universalgcodesender.fx.actions.StartAction;
1011
import com.willwinder.universalgcodesender.fx.control.ActionButton;
1112
import com.willwinder.universalgcodesender.fx.helper.Colors;
@@ -40,9 +41,15 @@ public JobControlsPane() {
4041
super(10);
4142
getStylesheets().add(getClass().getResource("/styles/job-controls-pane.css").toExternalForm());
4243

44+
HBox hBox = new HBox();
45+
hBox.setAlignment(Pos.CENTER);
46+
hBox.setSpacing(10);
47+
hBox.setPadding(new Insets(10, 10, 10, 10));
4348
loadedFileLabel = new Label("No file loaded");
4449
loadedFileLabel.setStyle("-fx-font-weight: bold;");
45-
getChildren().add(loadedFileLabel);
50+
ActionRegistry.getInstance().getAction(OpenFileAction.class.getCanonicalName()).ifPresent(action -> hBox.getChildren().add(createActionButton(action)));
51+
hBox.getChildren().add(loadedFileLabel);
52+
getChildren().add(hBox);
4653

4754
progressLabel = new Label("");
4855
getChildren().add(progressLabel);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.willwinder.universalgcodesender.fx.component.drawer;
2+
3+
import com.willwinder.universalgcodesender.fx.actions.ActionRegistry;
4+
import com.willwinder.universalgcodesender.fx.actions.MacroAction;
5+
import com.willwinder.universalgcodesender.fx.control.ActionButton;
6+
import javafx.geometry.Insets;
7+
import javafx.scene.control.Button;
8+
import javafx.scene.layout.FlowPane;
9+
10+
public class MacrosPane extends FlowPane {
11+
public MacrosPane() {
12+
setHgap(10);
13+
setVgap(10);
14+
setPadding(new Insets(10));
15+
16+
17+
ActionRegistry.getInstance().getAllActionsOfClass(MacroAction.class)
18+
.forEach(macroAction -> {
19+
Button button = new ActionButton(macroAction, 24);
20+
button.setPrefWidth(120);
21+
button.setPrefHeight(38);
22+
getChildren().add(button);
23+
});
24+
}
25+
}

0 commit comments

Comments
 (0)