diff --git a/pom.xml b/pom.xml index d6bc2e3260..cdb6427d33 100644 --- a/pom.xml +++ b/pom.xml @@ -50,16 +50,16 @@ UTF-8 9.4.41.v20210516 2.29.1 - 2.5.0-rc-20230523 - 2.5.0-rc-20230523 + 2.5.0 + 2.5.0 3.7.4 28.1-jre 2.8.0 2.9.2 3.12.0 - 2.11.0 + 2.14.0 1.9.0 - 2.10 + 2.10.1 2.1.1e 3.4.0 1.4 @@ -68,8 +68,7 @@ 3.0.0-M5 1.3.0 3.2.4 - 1.16 - 0.1a + 1.17 1.19.0 3.1.0 3.2.0 diff --git a/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/CommandTextArea.java b/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/CommandTextArea.java index dad07d2c4c..37e44e851e 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/CommandTextArea.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/CommandTextArea.java @@ -39,6 +39,7 @@ This file is part of Universal Gcode Sender (UGS). * @author wwinder */ public class CommandTextArea extends JTextField implements KeyEventDispatcher, UGSEventListener { + public static final String PLACEHOLDER_TEXT = " >\t"; private final transient CommandHistory commandHistory = new CommandHistory(); // This is needed for unit testing. protected boolean focusNotNeeded = false; @@ -58,6 +59,7 @@ public CommandTextArea(BackendAPI backend) { // Make it possible to send multiple lines getDocument().putProperty("filterNewlines", Boolean.FALSE); + addFocusListener(new TextFieldPlaceholderFocusListener(this, PLACEHOLDER_TEXT)); } public final void init(BackendAPI backend) { @@ -118,13 +120,10 @@ private void sendCommands(String[] commands) throws Exception { } private boolean isArrowKey(KeyEvent e) { - switch (e.getKeyCode()) { - case KeyEvent.VK_UP: - case KeyEvent.VK_DOWN: - return true; - default: - return false; - } + return switch (e.getKeyCode()) { + case KeyEvent.VK_UP, KeyEvent.VK_DOWN -> true; + default -> false; + }; } /** diff --git a/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/TextFieldPlaceholderFocusListener.java b/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/TextFieldPlaceholderFocusListener.java new file mode 100644 index 0000000000..ab7744885b --- /dev/null +++ b/ugs-core/src/com/willwinder/universalgcodesender/uielements/components/TextFieldPlaceholderFocusListener.java @@ -0,0 +1,41 @@ +package com.willwinder.universalgcodesender.uielements.components; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +/** + * Register this as a listener to a text field and it will show a placeholder + */ +public class TextFieldPlaceholderFocusListener implements FocusListener { + + private final JTextField textField; + private final Color textColor; + private final Color placeholderColor; + private final String placeholderText; + + public TextFieldPlaceholderFocusListener(JTextField textArea, String placeholderText) { + this.textField = textArea; + textColor = textArea.getForeground(); + placeholderColor = textArea.getDisabledTextColor(); + this.placeholderText = placeholderText; + focusLost(null); + } + + @Override + public void focusGained(FocusEvent e) { + if (textField.getText().equals(placeholderText)) { + textField.setText(""); + textField.setForeground(textColor); + } + } + + @Override + public void focusLost(FocusEvent e) { + if (textField.getText().isEmpty()) { + textField.setForeground(placeholderColor); + textField.setText(placeholderText); + } + } +} diff --git a/ugs-core/src/com/willwinder/universalgcodesender/utils/GUIHelpers.java b/ugs-core/src/com/willwinder/universalgcodesender/utils/GUIHelpers.java index 339c112311..25df742c8c 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/utils/GUIHelpers.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/utils/GUIHelpers.java @@ -20,12 +20,18 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.universalgcodesender.i18n.Localization; import com.willwinder.universalgcodesender.model.BackendAPI; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; + +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.Window; import java.io.File; import java.util.logging.Level; import java.util.logging.Logger; -import javax.swing.JOptionPane; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.exception.ExceptionUtils; /** * @@ -63,19 +69,29 @@ public static void displayErrorDialog(final String errorMessage, boolean modal) LOGGER.warning("Something tried to display an error message with an empty message: " + ExceptionUtils.getStackTrace(new Throwable())); return; } + String title = Localization.getString("error"); + displayMessageDialog(new JPanel(), title, errorMessage, JOptionPane.ERROR_MESSAGE, modal); + } - Runnable r = () -> { - //JOptionPane.showMessageDialog(new JFrame(), errorMessage, - // Localization.getString("error"), JOptionPane.ERROR_MESSAGE); - NarrowOptionPane.showNarrowDialog(250, errorMessage.replaceAll("\\.\\.", "\\."), - Localization.getString("error"), - JOptionPane.ERROR_MESSAGE); - }; + /** + * Displays a message dialog + * + * @param parent the parent component + * @param title the title string for the dialog + * @param message the Object to display + * @param messageType the type of message to be displayed: ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE, or PLAIN_MESSAGE + * @param modal toggle whether the message should block or fire and forget. + */ + public static void displayMessageDialog(Component parent, String title, String message, int messageType, boolean modal) { + Window windowAncestor = SwingUtilities.getWindowAncestor(parent == null ? new JPanel() : parent); + Runnable r = () -> NarrowOptionPane.showNarrowDialog(windowAncestor, 250, StringUtils.defaultString(message).replaceAll("\\.\\.", "\\."), + title, + messageType); if (modal) { r.run(); } else { - java.awt.EventQueue.invokeLater(r); + EventQueue.invokeLater(r); } } @@ -83,8 +99,6 @@ public static void displayHelpDialog(final String helpMessage) { java.awt.EventQueue.invokeLater(() -> { NarrowOptionPane.showNarrowConfirmDialog(250, helpMessage, Localization.getString("help"), JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE); - //JOptionPane.showMessageDialog(new JFrame(), helpMessage, - // Localization.getString("help"), JOptionPane.INFORMATION_MESSAGE); }); } diff --git a/ugs-core/src/com/willwinder/universalgcodesender/utils/NarrowOptionPane.java b/ugs-core/src/com/willwinder/universalgcodesender/utils/NarrowOptionPane.java index 0636e00503..760547859f 100644 --- a/ugs-core/src/com/willwinder/universalgcodesender/utils/NarrowOptionPane.java +++ b/ugs-core/src/com/willwinder/universalgcodesender/utils/NarrowOptionPane.java @@ -22,9 +22,9 @@ This file is part of Universal Gcode Sender (UGS). import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; +import java.awt.Component; /** * @author wwinder @@ -33,10 +33,10 @@ public class NarrowOptionPane extends JOptionPane { public static String pattern = "

%s

"; - public static void showNarrowDialog(int textWidthInPixels, + public static void showNarrowDialog(Component parentComponent, int textWidthInPixels, String message, String title, int messageType) throws HeadlessException { - JOptionPane.showMessageDialog(new JFrame(), + JOptionPane.showMessageDialog(parentComponent, String.format(pattern, textWidthInPixels, message.replaceAll("\n", "
")), title, messageType); } diff --git a/ugs-core/src/resources/MessagesBundle_cs_CZ.properties b/ugs-core/src/resources/MessagesBundle_cs_CZ.properties index a646413d37..2e2d139c18 100644 --- a/ugs-core/src/resources/MessagesBundle_cs_CZ.properties +++ b/ugs-core/src/resources/MessagesBundle_cs_CZ.properties @@ -390,7 +390,7 @@ autoleveler.option.offset-y = Posun měřící sondy Y autoleveler.option.offset-z = Posun měřící sondy Z experimental.feature = Toto je experimentální funkce. Prosím buďte opatrní a nahlaste všechny chyby, které najdete na GitHubu. # Window title for platform GUI -platform-title = Universal Gcode Platform\n +platform-title = Universal Gcode Sender\n mainWindow.swing.alarmLock = Odemnout mainWindow.swing.checkMode = Režim kontroly mainWindow.swing.getState = Stav diff --git a/ugs-core/src/resources/MessagesBundle_en_US.properties b/ugs-core/src/resources/MessagesBundle_en_US.properties index 76adb5af10..db1d2ab85b 100644 --- a/ugs-core/src/resources/MessagesBundle_en_US.properties +++ b/ugs-core/src/resources/MessagesBundle_en_US.properties @@ -241,7 +241,12 @@ platform.menu.jog.feed = Feed rate platform.menu.actions = Actions platform.menu.macros = Macros platform.menu.machine = Machine +platform.actions.program.not.saved.message = You must save the file first +platform.actions.program.not.saved.title = Not saved +platform.actions.homing.enabled.tooltip = Use this to perform a homing operation to find the machine zero position platform.actions.homing.disabled.tooltip = Homing needs to be enabled in the firmware settings +platform.actions.unlock.tooltip = Clear the alarm state and unlock the machine +platform.actions.softreset.tooltip = Reboot the controller incomplete.localization.title = Not fully translated incomplete.localization = Universal Gcode Sender is not fully localized for this language. \nPlease visit https://translate.universalgcodesender.com to see how you can help. incomplete.localization.doNotShowAgain = Do not show this message again @@ -498,7 +503,7 @@ autoleveler.probe-failed = Probe failed autoleveler.panel.clear = Clear scan experimental.feature = This is an experimental feature. Please use caution and report any bugs you find on GitHub. # Window title for platform GUI -platform-title = Universal Gcode Platform +platform-title = Universal Gcode Sender mainWindow.swing.alarmLock = Unlock mainWindow.swing.checkMode = Check Mode mainWindow.swing.getState = Get State @@ -660,6 +665,8 @@ platform.plugin.jog.stealKeyboardFocus = Making sure that keyboard controls are platform.window.edit.macros = Edit macros... platform.action.outline = Outline platform.action.outline.tooltip = Move the machine around the model using the current depth +platform.action.openLogDirectory = Open log directory +platform.action.createShortcut = Create shortcut platform.plugin.joystick.activate = Activate joystick platform.plugin.joystick.buttonControls = Button controls: platform.plugin.joystick.analogControls = Analog controls: diff --git a/ugs-platform/application/pom.xml b/ugs-platform/application/pom.xml index d38734d435..a9f6d6a99e 100644 --- a/ugs-platform/application/pom.xml +++ b/ugs-platform/application/pom.xml @@ -308,9 +308,16 @@ + + + + + + + @@ -382,9 +389,16 @@ + + + + + + + @@ -686,6 +700,9 @@ + + + @@ -766,6 +783,9 @@ + + + @@ -846,6 +866,9 @@ + + + diff --git a/ugs-platform/application/src/main/app-resources/icon.ico b/ugs-platform/application/src/main/app-resources/icon.ico new file mode 100644 index 0000000000..23f0323169 Binary files /dev/null and b/ugs-platform/application/src/main/app-resources/icon.ico differ diff --git a/ugs-platform/application/src/main/app-resources/icon.svg b/ugs-platform/application/src/main/app-resources/icon.svg new file mode 100644 index 0000000000..a51e0d7d3d --- /dev/null +++ b/ugs-platform/application/src/main/app-resources/icon.svg @@ -0,0 +1,365 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/ugs-platform/application/src/main/app-resources/ugsplatform.icns b/ugs-platform/application/src/main/app-resources/ugsplatform.icns index 67a185f1f7..a9712c647d 100644 Binary files a/ugs-platform/application/src/main/app-resources/ugsplatform.icns and b/ugs-platform/application/src/main/app-resources/ugsplatform.icns differ diff --git a/ugs-platform/application/src/main/resources/Info.plist b/ugs-platform/application/src/main/resources/Info.plist index 7739b5a3b8..5abdf0d908 100644 --- a/ugs-platform/application/src/main/resources/Info.plist +++ b/ugs-platform/application/src/main/resources/Info.plist @@ -3,7 +3,7 @@ CFBundleName - Universal Gcode Platform + Universal Gcode Sender CFBundleVersion ${project.version} diff --git a/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index 934cedbbd1..338e014700 100644 --- a/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ -currentVersion=Universal Gcode Platform {0} -LBL_splash_window_title=Starting Universal Gcode Platform +currentVersion=Universal Gcode Sender {0} +LBL_splash_window_title=Starting Universal Gcode Sender SPLASH_HEIGHT=295 SPLASH_WIDTH=600 SplashProgressBarBounds=0,270,600,6 diff --git a/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame.gif b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame.gif index b888c65316..911c0d87e5 100644 Binary files a/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame.gif and b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame.gif differ diff --git a/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame.png b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame.png new file mode 100644 index 0000000000..a862e5cafa Binary files /dev/null and b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame.png differ diff --git a/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame32.gif b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame32.gif index 7bf36ab5c9..f7db388c3a 100644 Binary files a/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame32.gif and b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame32.gif differ diff --git a/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame32.png b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame32.png new file mode 100644 index 0000000000..4e3f69b197 Binary files /dev/null and b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame32.png differ diff --git a/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame48.gif b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame48.gif index 314b512f13..90f063b8a1 100644 Binary files a/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame48.gif and b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame48.gif differ diff --git a/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame48.png b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame48.png new file mode 100644 index 0000000000..e4d0355876 Binary files /dev/null and b/ugs-platform/branding/src/main/nbm-branding/core/core.jar/org/netbeans/core/startup/frame48.png differ diff --git a/ugs-platform/branding/src/main/nbm-branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/ugs-platform/branding/src/main/nbm-branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index e0fe05cc5d..3f9f562543 100644 --- a/ugs-platform/branding/src/main/nbm-branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/ugs-platform/branding/src/main/nbm-branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,2 +1,2 @@ -CTL_MainWindow_Title=Universal Gcode Platform {0} -CTL_MainWindow_Title_No_Project=Universal Gcode Platform {0} +CTL_MainWindow_Title=Universal Gcode Sender {0} +CTL_MainWindow_Title_No_Project=Universal Gcode Sender {0} diff --git a/ugs-platform/branding/src/main/nbm-branding/modules/org-netbeans-core.jar/org/netbeans/core/ui/Bundle.properties b/ugs-platform/branding/src/main/nbm-branding/modules/org-netbeans-core.jar/org/netbeans/core/ui/Bundle.properties index 73b108d836..4385558905 100644 --- a/ugs-platform/branding/src/main/nbm-branding/modules/org-netbeans-core.jar/org/netbeans/core/ui/Bundle.properties +++ b/ugs-platform/branding/src/main/nbm-branding/modules/org-netbeans-core.jar/org/netbeans/core/ui/Bundle.properties @@ -1 +1 @@ -LBL_ProductInformation=Universal Gcode Platform +LBL_ProductInformation=Universal Gcode Sender diff --git a/ugs-platform/pom.xml b/ugs-platform/pom.xml index 0c95f60149..9a3422dfb5 100644 --- a/ugs-platform/pom.xml +++ b/ugs-platform/pom.xml @@ -16,8 +16,8 @@ yyyy.MM.dd.HH.mm RELEASE180 - Universal Gcode Platform ${project.version} - Universal Gcode Platform + Universal Gcode Sender ${project.version} + Universal Gcode Sender 2 0 0 diff --git a/ugs-platform/ugs-platform-gcode-editor/src/main/java/com/willwinder/ugs/nbp/editor/actions/NewGcodeAction.java b/ugs-platform/ugs-platform-gcode-editor/src/main/java/com/willwinder/ugs/nbp/editor/actions/NewGcodeAction.java index 142d897b76..44ff2de399 100644 --- a/ugs-platform/ugs-platform-gcode-editor/src/main/java/com/willwinder/ugs/nbp/editor/actions/NewGcodeAction.java +++ b/ugs-platform/ugs-platform-gcode-editor/src/main/java/com/willwinder/ugs/nbp/editor/actions/NewGcodeAction.java @@ -44,6 +44,7 @@ This file is part of Universal Gcode Sender (UGS). import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.util.Optional; @ActionID( category = LocalizingService.OpenCategory, @@ -80,7 +81,12 @@ public void actionPerformed(ActionEvent e) { } try { - File file = chooseFile(); + Optional optional = chooseFile(); + if (optional.isEmpty()) { + return; + } + + File file = optional.get(); if (!file.createNewFile()) { throw new IOException("Could not create temporary file " + file); } @@ -92,7 +98,7 @@ public void actionPerformed(ActionEvent e) { } } - private File chooseFile() throws IOException { + private Optional chooseFile() throws IOException { FileChooserBuilder fcb = new FileChooserBuilder(NewGcodeAction.class); fcb.setTitle("Create Gcode file"); fcb.setFileFilter(new GcodeFileTypeFilter()); @@ -100,7 +106,7 @@ private File chooseFile() throws IOException { fileChooser.setFileHidingEnabled(true); if (fileChooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION) { - throw new IOException(); + return Optional.empty(); } // Removing the old file @@ -109,10 +115,10 @@ private File chooseFile() throws IOException { if (JOptionPane.showConfirmDialog(null, "Are you sure you want to overwrite the file " + file.getName(), "Overwrite existing file", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { file.delete(); } else { - throw new IOException(); + return Optional.empty(); } } - return file; + return Optional.of(file); } private void writeExampleToFile(File file) throws IOException { diff --git a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/platform/PlatformUtils.java b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/platform/PlatformUtils.java index 513ca88c4f..1053731367 100644 --- a/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/platform/PlatformUtils.java +++ b/ugs-platform/ugs-platform-plugin-designer/src/main/java/com/willwinder/ugs/nbp/designer/platform/PlatformUtils.java @@ -46,6 +46,8 @@ public class PlatformUtils { public static final String UNDO_KEY = "undo"; public static final String REDO_KEY = "redo"; public static final String DELETE_KEY = "delete"; + public static final String ERASE_KEY = "erase"; + private static final DeleteAction DELETE_ACTION = new DeleteAction(); private static final SelectAllAction SELECT_ALL_ACTION = new SelectAllAction(); @@ -59,6 +61,7 @@ private PlatformUtils() { public static void registerActions(ActionMap actionMap, TopComponent component) { actionMap.put(DELETE_KEY, DELETE_ACTION); + actionMap.put(ERASE_KEY, DELETE_ACTION); actionMap.put(DefaultEditorKit.selectAllAction, SELECT_ALL_ACTION); actionMap.put(DefaultEditorKit.copyAction, COPY_ACTION); actionMap.put(DefaultEditorKit.pasteAction, PASTE_ACTION); @@ -67,7 +70,8 @@ public static void registerActions(ActionMap actionMap, TopComponent component) // Need to make special input maps as this normally is handled by the texteditor InputMap inputMap = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); - inputMap.put(Utilities.stringToKey("BACK_SPACE"), DELETE_KEY); + inputMap.put(Utilities.stringToKey("BACK_SPACE"), ERASE_KEY); + inputMap.put(Utilities.stringToKey("DELETE"), DELETE_KEY); inputMap.put(Utilities.stringToKey("D-C"), DefaultEditorKit.copyAction); inputMap.put(Utilities.stringToKey("D-V"), DefaultEditorKit.pasteAction); inputMap.put(Utilities.stringToKey("D-A"), DefaultEditorKit.selectAllAction); diff --git a/ugs-platform/ugs-platform-ugscore/pom.xml b/ugs-platform/ugs-platform-ugscore/pom.xml index 7be15ce610..e901ce55e6 100644 --- a/ugs-platform/ugs-platform-ugscore/pom.xml +++ b/ugs-platform/ugs-platform-ugscore/pom.xml @@ -48,6 +48,13 @@ jar + + + com.github.vatbub + mslinks + 1.0.6.2 + + org.netbeans.api org-openide-filesystems diff --git a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/CreateShortcutAction.java b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/CreateShortcutAction.java new file mode 100644 index 0000000000..fdfd9c9f7e --- /dev/null +++ b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/CreateShortcutAction.java @@ -0,0 +1,97 @@ +package com.willwinder.ugs.nbp.core.actions; + +import com.willwinder.ugs.nbp.lib.services.LocalizingService; +import com.willwinder.universalgcodesender.i18n.Localization; +import mslinks.ShellLink; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.SystemUtils; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionReferences; +import org.openide.awt.ActionRegistration; + +import javax.swing.AbstractAction; +import java.awt.event.ActionEvent; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; + +@ActionID( + category = LocalizingService.CATEGORY_TOOLS, + id = "com.willwinder.ugs.nbp.core.actions.CreateShortcutAction") +@ActionRegistration( + displayName = "resources.MessagesBundle#platform.action.createShortcut", + lazy = false) +@ActionReferences({ + @ActionReference( + path = LocalizingService.MENU_TOOLS, + position = 2110) +}) +public class CreateShortcutAction extends AbstractAction { + + public static final String LINUX_DESKTOP_FILE = System.getProperty("user.home") + "/.local/share/applications/ugs.desktop"; + + public CreateShortcutAction() { + setEnabled(isEnabled()); + putValue(NAME, Localization.getString("platform.action.createShortcut")); + } + + private static void createLinuxShortcut() { + Path currentRelativePath = Paths.get(""); + String ugsDirectory = currentRelativePath.toAbsolutePath().toString(); + String desktopFile = "[Desktop Entry]\n" + + "Type=Application\n" + + "Version=1.0\n" + + "Name=Universal Gcode Sender\n" + + "Comment=Control your CNC machine\n" + + "Path=" + ugsDirectory + "\n" + + "Exec=" + ugsDirectory + File.separator + "ugsplatform %F\n" + + "Icon=" + ugsDirectory + File.separator + "icon.svg\n" + + "MimeType=text/x-gcode\n" + + "Terminal=false\n" + + "StartupWMClass=Universal Gcode Sender\n" + + "Categories=Engineering\n" + + "Keywords=ugs\n"; + try { + FileUtils.write(new File(LINUX_DESKTOP_FILE), desktopFile, StandardCharsets.UTF_8); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + @Override + public void actionPerformed(ActionEvent e) { + if (SystemUtils.IS_OS_LINUX) { + createLinuxShortcut(); + } else if (SystemUtils.IS_OS_WINDOWS) { + createWindowsShortcut(); + } + } + + private static void createWindowsShortcut() { + try { + String shortcutPath = System.getProperty("user.home") + File.separator + "Desktop" + File.separator + "Universal Gcode Sender.lnk"; + Path currentRelativePath = Paths.get(""); + + String basePath = currentRelativePath.toAbsolutePath() + File.separator + "bin" + File.separator; + String executablePath = basePath + "ugsplatform64.exe"; + if (!new File(executablePath).exists()) { + executablePath = basePath + "ugsplatform.exe"; + } + + ShellLink.createLink(executablePath) + .setWorkingDir(currentRelativePath.toAbsolutePath().toString()) + .setIconLocation(basePath + "icon.ico") + .saveTo(shortcutPath); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean isEnabled() { + return SystemUtils.IS_OS_LINUX || SystemUtils.IS_OS_WINDOWS; + } +} diff --git a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/HomingAction.java b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/HomingAction.java index ab2d8234ed..07ad7e992d 100644 --- a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/HomingAction.java +++ b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/HomingAction.java @@ -68,6 +68,7 @@ public HomingAction() { putValue("menuText", LocalizingService.HomeTitle); putValue(NAME, LocalizingService.HomeTitle); setEnabled(isEnabled()); + updateToolTip(); } @Override @@ -113,7 +114,7 @@ private void updateToolTip() { !isHomingEnabled()) { putValue(Action.SHORT_DESCRIPTION, Localization.getString("platform.actions.homing.disabled.tooltip")); } else { - putValue(Action.SHORT_DESCRIPTION, LocalizingService.HomeTitle); + putValue(Action.SHORT_DESCRIPTION, Localization.getString("platform.actions.homing.enabled.tooltip")); } } } diff --git a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/OpenLogDirectoryAction.java b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/OpenLogDirectoryAction.java new file mode 100644 index 0000000000..d7b0848964 --- /dev/null +++ b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/OpenLogDirectoryAction.java @@ -0,0 +1,46 @@ +package com.willwinder.ugs.nbp.core.actions; + +import com.willwinder.ugs.nbp.lib.services.LocalizingService; +import com.willwinder.universalgcodesender.i18n.Localization; +import org.openide.awt.ActionID; +import org.openide.awt.ActionReference; +import org.openide.awt.ActionReferences; +import org.openide.awt.ActionRegistration; +import org.openide.modules.Places; + +import javax.swing.AbstractAction; +import java.awt.Desktop; +import java.awt.event.ActionEvent; +import java.io.File; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +@ActionID( + category = LocalizingService.CATEGORY_TOOLS, + id = "com.willwinder.ugs.nbp.core.actions.OpenLogDirectoryAction") +@ActionRegistration( + displayName = "resources.MessagesBundle#platform.action.openLogDirectory", + lazy = false) +@ActionReferences({ + @ActionReference( + path = LocalizingService.MENU_TOOLS, + position = 2100) +}) +public class OpenLogDirectoryAction extends AbstractAction { + private static final Logger LOGGER = Logger.getLogger(OpenLogDirectoryAction.class.getName()); + + public OpenLogDirectoryAction() { + putValue(NAME, Localization.getString("platform.action.openLogDirectory")); + } + + + @Override + public void actionPerformed(ActionEvent actionEvent) { + try { + Desktop.getDesktop().open(new File(Places.getUserDirectory().getAbsolutePath() + File.separator + "var" + File.separator + "log")); + } catch (IOException ex) { + LOGGER.log(Level.SEVERE, "Could not open the log directory", ex); + } + } +} diff --git a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/OutlineAction.java b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/OutlineAction.java index 36a6d1509f..73df3aab63 100644 --- a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/OutlineAction.java +++ b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/OutlineAction.java @@ -57,7 +57,6 @@ This file is part of Universal Gcode Sender (UGS). import java.io.IOException; import java.util.List; import java.util.logging.Logger; -import java.util.stream.Collectors; /** * An action that will parse the loaded gcode file and generate a movement path for outlining @@ -109,12 +108,11 @@ public void UGSEvent(UGSEvent cse) { public boolean isEnabled() { return backend != null && backend.getControllerState() == ControllerState.IDLE && - backend.getGcodeFile() != null && - super.isEnabled(); + backend.getGcodeFile() != null; } @Override - public void actionPerformed(ActionEvent e) { + public void execute(ActionEvent e) { ThreadHelper.invokeLater(() -> { try { LOGGER.finest("Generating the outline of the gcode model"); @@ -141,7 +139,7 @@ public List generateOutlineCommands(File gcodeFile) throws IOExcep .filter(lineSegment -> !lineSegment.isFastTraverse()) .flatMap(new LineSegmentToPartialPositionMapper()) .distinct() - .collect(Collectors.toList()); + .toList(); return generateConvexHullCommands(pointList); } @@ -151,7 +149,7 @@ private List generateConvexHullCommands(List poin ICommandCreator commandCreator = backend.getCommandCreator(); return outline.stream() .map(point -> commandCreator.createCommand(GcodeUtils.generateMoveToCommand(Code.G90.name() + Code.G1.name(), point, getJogFeedRate()))) - .collect(Collectors.toList()); + .toList(); } private double getJogFeedRate() { diff --git a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/ProgramAction.java b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/ProgramAction.java index 65d4bf9bb1..55e9bfb64b 100644 --- a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/ProgramAction.java +++ b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/ProgramAction.java @@ -18,21 +18,25 @@ This file is part of Universal Gcode Sender (UGS). */ package com.willwinder.ugs.nbp.core.actions; +import com.willwinder.universalgcodesender.i18n.Localization; +import com.willwinder.universalgcodesender.utils.GUIHelpers; import org.openide.cookies.SaveCookie; import org.openide.nodes.Node; +import static org.openide.nodes.Node.PROP_COOKIE; import org.openide.nodes.NodeEvent; import org.openide.nodes.NodeListener; import org.openide.nodes.NodeMemberEvent; import org.openide.nodes.NodeReorderEvent; import org.openide.windows.TopComponent; +import static org.openide.windows.TopComponent.Registry.PROP_ACTIVATED_NODES; import javax.swing.AbstractAction; +import javax.swing.JOptionPane; import javax.swing.SwingUtilities; +import java.awt.Component; +import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; -import static org.openide.nodes.Node.PROP_COOKIE; -import static org.openide.windows.TopComponent.Registry.PROP_ACTIVATED_NODES; - /** * An abstract action that will be active only if the current program contains unsaved * changes. @@ -40,6 +44,8 @@ This file is part of Universal Gcode Sender (UGS). * @author Joacim Breiler */ public abstract class ProgramAction extends AbstractAction implements NodeListener { + private final String notSavedText = Localization.getString("platform.actions.program.not.saved.message"); + private final String notSavedTitle = Localization.getString("platform.actions.program.not.saved.title"); /** * If the current document contains unsaved changes this will become false. */ @@ -56,6 +62,7 @@ public void propertyChange(PropertyChangeEvent evt) { SwingUtilities.invokeLater(() -> setEnabled(isEnabled())); } else if (evt.getPropertyName().equals(PROP_ACTIVATED_NODES)) { registerNodeListener(evt); + SwingUtilities.invokeLater(() -> setEnabled(isEnabled())); } } @@ -69,6 +76,7 @@ private void registerNodeListener(PropertyChangeEvent event) { if (event.getOldValue() != null && ((Node[]) event.getOldValue()).length > 0) { Node oldNode = ((Node[]) event.getOldValue())[0]; oldNode.removeNodeListener(this); + isSaved = true; } if (event.getNewValue() != null && ((Node[]) event.getNewValue()).length > 0) { @@ -78,10 +86,18 @@ private void registerNodeListener(PropertyChangeEvent event) { } @Override - public boolean isEnabled() { - return isSaved; + public final void actionPerformed(ActionEvent e) { + if (!isSaved) { + Component source = e != null ? (Component) e.getSource() : null; + GUIHelpers.displayMessageDialog(source, notSavedTitle, notSavedText, JOptionPane.INFORMATION_MESSAGE, true); + return; + } + + execute(e); } + public abstract void execute(ActionEvent e); + @Override public void childrenAdded(NodeMemberEvent ev) { // Not used diff --git a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/SoftResetAction.java b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/SoftResetAction.java index 17fafb5278..021fd6ea61 100644 --- a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/SoftResetAction.java +++ b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/SoftResetAction.java @@ -21,6 +21,7 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.ugs.nbp.lib.lookup.CentralLookup; import com.willwinder.ugs.nbp.lib.services.LocalizingService; +import com.willwinder.universalgcodesender.i18n.Localization; import com.willwinder.universalgcodesender.listeners.ControllerState; import com.willwinder.universalgcodesender.listeners.UGSEventListener; import com.willwinder.universalgcodesender.model.BackendAPI; @@ -66,6 +67,7 @@ public SoftResetAction() { putValue(SMALL_ICON, ImageUtilities.loadImageIcon(ICON_BASE, false)); putValue("menuText", LocalizingService.SoftResetTitle); putValue(NAME, LocalizingService.SoftResetTitle); + putValue(Action.SHORT_DESCRIPTION, Localization.getString("platform.actions.softreset.tooltip")); setEnabled(isEnabled()); } diff --git a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/StartAction.java b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/StartAction.java index 87e24be638..41df1ef39c 100644 --- a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/StartAction.java +++ b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/StartAction.java @@ -80,11 +80,11 @@ public void UGSEvent(UGSEvent cse) { @Override public boolean isEnabled() { - return (backend.canSend() && super.isEnabled()) || backend.isPaused(); + return backend.canSend() || backend.isPaused(); } @Override - public void actionPerformed(ActionEvent e) { + public void execute(ActionEvent e) { try { if (backend.isPaused()) { backend.pauseResume(); diff --git a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/UnlockAction.java b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/UnlockAction.java index 08d0c3c55d..cc1fc2a020 100644 --- a/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/UnlockAction.java +++ b/ugs-platform/ugs-platform-ugscore/src/main/java/com/willwinder/ugs/nbp/core/actions/UnlockAction.java @@ -21,6 +21,7 @@ This file is part of Universal Gcode Sender (UGS). import com.willwinder.ugs.nbp.lib.lookup.CentralLookup; import com.willwinder.ugs.nbp.lib.services.LocalizingService; +import com.willwinder.universalgcodesender.i18n.Localization; import com.willwinder.universalgcodesender.listeners.ControllerState; import com.willwinder.universalgcodesender.listeners.UGSEventListener; import com.willwinder.universalgcodesender.model.BackendAPI; @@ -34,6 +35,7 @@ This file is part of Universal Gcode Sender (UGS). import org.openide.util.ImageUtilities; import javax.swing.*; +import java.awt.EventQueue; import java.awt.event.ActionEvent; @ActionID( @@ -55,7 +57,7 @@ public final class UnlockAction extends AbstractAction implements UGSEventListen public static final String ICON_BASE = "resources/icons/lock.svg"; - private BackendAPI backend; + private final transient BackendAPI backend; public UnlockAction() { this.backend = CentralLookup.getDefault().lookup(BackendAPI.class); @@ -65,13 +67,14 @@ public UnlockAction() { putValue(SMALL_ICON, ImageUtilities.loadImageIcon(ICON_BASE, false)); putValue("menuText", LocalizingService.UnlockTitle); putValue(NAME, LocalizingService.UnlockTitle); + putValue(Action.SHORT_DESCRIPTION, Localization.getString("platform.actions.unlock.tooltip")); setEnabled(isEnabled()); } @Override public void UGSEvent(UGSEvent cse) { if (cse instanceof ControllerStateEvent) { - java.awt.EventQueue.invokeLater(() -> setEnabled(isEnabled())); + EventQueue.invokeLater(() -> setEnabled(isEnabled())); } } diff --git a/ugs-platform/ugs-platform-ugscore/src/main/resources/resources/MessagesBundle.properties b/ugs-platform/ugs-platform-ugscore/src/main/resources/resources/MessagesBundle.properties index 754b6af4eb..7b1d273550 100644 --- a/ugs-platform/ugs-platform-ugscore/src/main/resources/resources/MessagesBundle.properties +++ b/ugs-platform/ugs-platform-ugscore/src/main/resources/resources/MessagesBundle.properties @@ -4,6 +4,8 @@ platform.menu.reload = Reload platform.menu.toggleUnit = Toggle units platform.window.edit.macros = Edit Macros platform.action.outline = Outline +platform.action.openLogDirectory = Open log directory +platform.action.createShortcut = Create shortcut mainWindow.swing.pauseButton = Pause mainWindow.swing.sendButton = Send mainWindow.swing.stopButton = Stop diff --git a/ugs-platform/ugs-platform-ugscore/src/test/java/com/willwinder/ugs/nbp/core/actions/StartActionTest.java b/ugs-platform/ugs-platform-ugscore/src/test/java/com/willwinder/ugs/nbp/core/actions/StartActionTest.java index 67b8a1aaaa..f48b3cabea 100644 --- a/ugs-platform/ugs-platform-ugscore/src/test/java/com/willwinder/ugs/nbp/core/actions/StartActionTest.java +++ b/ugs-platform/ugs-platform-ugscore/src/test/java/com/willwinder/ugs/nbp/core/actions/StartActionTest.java @@ -7,7 +7,6 @@ import java.beans.PropertyChangeEvent; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -32,7 +31,7 @@ public void isEnabledShouldReturnFalseOnUnsavedChanges() { StartAction startAction = new StartAction(backendAPI); startAction.propertyChange(createUnsavedChangesEvent()); - assertFalse(startAction.isEnabled()); + assertTrue(startAction.isEnabled()); } @Test @@ -56,7 +55,6 @@ private PropertyChangeEvent createUnsavedChangesEvent() { Node node = mock(Node.class); SaveCookie saveCookie = mock(SaveCookie.class); when(node.getCookie(SaveCookie.class)).thenReturn(saveCookie); - PropertyChangeEvent event = new PropertyChangeEvent(node, PROP_COOKIE, null, null); - return event; + return new PropertyChangeEvent(node, PROP_COOKIE, null, null); } } diff --git a/ugs-platform/ugs-platform-ugslib/src/main/java/com/willwinder/ugs/nbp/lib/options/package-info.java b/ugs-platform/ugs-platform-ugslib/src/main/java/com/willwinder/ugs/nbp/lib/options/package-info.java index 11a3dc24f9..4c33878e83 100644 --- a/ugs-platform/ugs-platform-ugslib/src/main/java/com/willwinder/ugs/nbp/lib/options/package-info.java +++ b/ugs-platform/ugs-platform-ugslib/src/main/java/com/willwinder/ugs/nbp/lib/options/package-info.java @@ -20,7 +20,7 @@ This file is part of Universal Gcode Sender (UGS). @OptionsPanelController.ContainerRegistration( id = "UGS", categoryName = "UGS", - iconBase = "com/willwinder/ugs/nbp/lib/options/CNC.png", + iconBase = "com/willwinder/ugs/nbp/lib/options/CNC.svg", keywords = "UGS", keywordsCategory = "UGS") package com.willwinder.ugs.nbp.lib.options; diff --git a/ugs-platform/ugs-platform-ugslib/src/main/java/com/willwinder/ugs/nbp/lib/services/LocalizingService.java b/ugs-platform/ugs-platform-ugslib/src/main/java/com/willwinder/ugs/nbp/lib/services/LocalizingService.java index 1d2382d1d1..34927fef89 100644 --- a/ugs-platform/ugs-platform-ugslib/src/main/java/com/willwinder/ugs/nbp/lib/services/LocalizingService.java +++ b/ugs-platform/ugs-platform-ugslib/src/main/java/com/willwinder/ugs/nbp/lib/services/LocalizingService.java @@ -37,6 +37,7 @@ public class LocalizingService { public static final String MENU_WINDOW_CLASSIC = MENU_WINDOW + "/Classic"; public static final String MENU_FILE = "Menu/File"; public static final String MENU_EDIT = "Menu/Edit"; + public static final String MENU_TOOLS = "Menu/Tools"; public static final String MENU_MACHINE = "Menu/Machine"; public static final String MENU_MACHINE_PROBE = "Menu/Machine/Probe"; public static final String MENU_PROGRAM = "Menu/Program"; @@ -53,6 +54,7 @@ public class LocalizingService { public static final String CATEGORY_VISUALIZER = "Visualizer"; public static final String CATEGORY_EDIT = "Edit"; public static final String CATEGORY_DESIGNER = "Designer"; + public static final String CATEGORY_TOOLS = "Tools"; // Initialize backend (locale setting) before we load localized strings. public static final String lang = CentralLookup.getDefault().lookup(BackendAPI.class).getSettings().getLanguage(); diff --git a/ugs-platform/ugs-platform-ugslib/src/main/resources/com/willwinder/ugs/nbp/lib/options/CNC.png b/ugs-platform/ugs-platform-ugslib/src/main/resources/com/willwinder/ugs/nbp/lib/options/CNC.png deleted file mode 100644 index 3ae3a2b53c..0000000000 Binary files a/ugs-platform/ugs-platform-ugslib/src/main/resources/com/willwinder/ugs/nbp/lib/options/CNC.png and /dev/null differ diff --git a/ugs-platform/ugs-platform-ugslib/src/main/resources/com/willwinder/ugs/nbp/lib/options/CNC.svg b/ugs-platform/ugs-platform-ugslib/src/main/resources/com/willwinder/ugs/nbp/lib/options/CNC.svg new file mode 100644 index 0000000000..e99f3808b3 --- /dev/null +++ b/ugs-platform/ugs-platform-ugslib/src/main/resources/com/willwinder/ugs/nbp/lib/options/CNC.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/Visualizer2TopComponent.java b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/Visualizer2TopComponent.java index 286578728d..560205b566 100644 --- a/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/Visualizer2TopComponent.java +++ b/ugs-platform/ugs-platform-visualizer/src/main/java/com/willwinder/ugs/nbm/visualizer/Visualizer2TopComponent.java @@ -19,12 +19,15 @@ This file is part of Universal Gcode Sender (UGS). package com.willwinder.ugs.nbm.visualizer; import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLException; import com.jogamp.opengl.awt.GLJPanel; import com.jogamp.opengl.util.FPSAnimator; import com.willwinder.ugs.nbm.visualizer.options.VisualizerOptionsPanel; import com.willwinder.ugs.nbm.visualizer.shared.GcodeRenderer; +import com.willwinder.ugs.nbp.core.actions.OpenLogDirectoryAction; import com.willwinder.ugs.nbp.lib.lookup.CentralLookup; import com.willwinder.ugs.nbp.lib.services.LocalizingService; +import static com.willwinder.ugs.nbp.lib.services.LocalizingService.lang; import com.willwinder.ugs.nbp.lib.services.TopComponentLocalizer; import com.willwinder.universalgcodesender.i18n.Localization; import com.willwinder.universalgcodesender.model.BackendAPI; @@ -40,13 +43,13 @@ This file is part of Universal Gcode Sender (UGS). import javax.swing.*; import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.io.File; import java.util.logging.Level; import java.util.logging.Logger; import java.util.prefs.Preferences; -import static com.willwinder.ugs.nbp.lib.services.LocalizingService.lang; - /** * Setup JOGL canvas, GcodeRenderer and RendererInputHandler. */ @@ -61,28 +64,19 @@ This file is part of Universal Gcode Sender (UGS). preferredID = "VisualizerTopComponent" ) public final class Visualizer2TopComponent extends TopComponent { - private static final Logger logger = Logger.getLogger(Visualizer2TopComponent.class.getName()); - - private GLJPanel panel; - private RendererInputHandler rih; - private final BackendAPI backend; - public final static String VisualizerTitle = Localization.getString("platform.window.visualizer", lang); public final static String VisualizerTooltip = Localization.getString("platform.window.visualizer.tooltip", lang); public final static String VisualizerWindowPath = LocalizingService.MENU_WINDOW; public final static String VisualizerActionId = "com.willwinder.ugs.nbm.visualizer.Visualizer2TopComponent"; public final static String VisualizerCategory = LocalizingService.CATEGORY_WINDOW; - - @OnStart - public static class Localizer extends TopComponentLocalizer { - public Localizer() { - super(VisualizerCategory, VisualizerActionId, VisualizerTitle); - } - } + private static final Logger logger = Logger.getLogger(Visualizer2TopComponent.class.getName()); + private final BackendAPI backend; + private GLJPanel panel; + private RendererInputHandler rih; public Visualizer2TopComponent() { backend = CentralLookup.getDefault().lookup(BackendAPI.class); - + setMinimumSize(new java.awt.Dimension(50, 50)); setPreferredSize(new java.awt.Dimension(200, 200)); setLayout(new java.awt.BorderLayout()); @@ -109,15 +103,30 @@ protected void componentOpened() { removeAll(); add(new VisualizerToolBar(), BorderLayout.NORTH); - panel = makeWindow(); JPanel borderedPanel = new JPanel(); borderedPanel.setLayout(new BorderLayout()); borderedPanel.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1)); - borderedPanel.add(panel, BorderLayout.CENTER); + borderedPanel.add(initializeVisualizationPanel(), BorderLayout.CENTER); add(borderedPanel, BorderLayout.CENTER); } + private JComponent initializeVisualizationPanel() { + try { + panel = makeWindow(); + return panel; + } catch (GLException exception) { + JLabel errorMessage = new JLabel("Could not initialize OpenGL visualization, please check the log file for details messages.log", JLabel.CENTER); + errorMessage.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + new OpenLogDirectoryAction().actionPerformed(null); + } + }); + return errorMessage; + } + } + @Override protected void componentClosed() { super.componentClosed(); @@ -149,8 +158,8 @@ protected void componentActivated() { } } } - - private GLJPanel makeWindow() { + + private GLJPanel makeWindow() throws GLException { GLCapabilities glCaps = new GLCapabilities(null); final GLJPanel p = new GLJPanel(glCaps); @@ -190,4 +199,11 @@ private GLJPanel makeWindow() { return p; } + + @OnStart + public static class Localizer extends TopComponentLocalizer { + public Localizer() { + super(VisualizerCategory, VisualizerActionId, VisualizerTitle); + } + } }