/* Copywrite 2016-2017 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 <http://www.gnu.org/licenses/>. */ package com.willwinder.universalgcodesender.uielements.panels; import com.willwinder.universalgcodesender.i18n.Localization; import com.willwinder.universalgcodesender.listeners.ControllerListener; import com.willwinder.universalgcodesender.listeners.ControllerStatus; import com.willwinder.universalgcodesender.listeners.UGSEventListener; import com.willwinder.universalgcodesender.model.BackendAPI; import com.willwinder.universalgcodesender.model.Position; import com.willwinder.universalgcodesender.model.UGSEvent; import com.willwinder.universalgcodesender.services.JogService; import com.willwinder.universalgcodesender.types.GcodeCommand; import com.willwinder.universalgcodesender.uielements.jog.JogPanel; import com.willwinder.universalgcodesender.utils.CommUtils; import com.willwinder.universalgcodesender.utils.FirmwareUtils; import net.miginfocom.swing.MigLayout; import javax.swing.*; import java.awt.*; import java.io.File; import java.util.List; import static com.willwinder.universalgcodesender.utils.GUIHelpers.displayErrorDialog; import java.awt.event.KeyEvent; import java.util.logging.Level; import java.util.logging.Logger; public class ConnectionPanelGroup extends JPanel implements UGSEventListener, ControllerListener { private static final Logger logger = Logger.getLogger(ConnectionPanelGroup.class.getName()); private final JLabel portLabel = new JLabel(Localization.getString("mainWindow.swing.portLabel")); private final JLabel baudLabel = new JLabel(Localization.getString("mainWindow.swing.baudLabel")); private final JLabel firmwareLabel = new JLabel(Localization.getString("mainWindow.swing.firmwareLabel")); private final JComboBox portCombo = new JComboBox(); private final JComboBox baudCombo = new JComboBox(); private final JComboBox firmwareCombo = new JComboBox(); private final JButton refreshButton = new JButton(new javax.swing.ImageIcon(getClass().getResource("/resources/icons/refresh.gif"))); private final JButton openCloseButton = new JButton(Localization.getString("mainWindow.swing.opencloseButton")); private final JButton sendPauseResumeButton = new JButton(Localization.getString("mainWindow.swing.sendButton")); private final JButton browseCancelButton = new JButton(Localization.getString("mainWindow.swing.browseButton")); private final javax.swing.JFileChooser fileChooser; private final JPanel connection = new JPanel(); private final MachineStatusPanel machineStatus; private final JLabel currentFile = new JLabel(); private final SendStatusPanel sendStatusPanel; private final JogPanel jogPanel; private final BackendAPI backend; public ConnectionPanelGroup(BackendAPI backend, JogService jogService) { this.backend = backend; if (this.backend != null) { this.backend.addUGSEventListener(this); } machineStatus = new MachineStatusPanel(backend); machineStatus.setVisible(false); sendStatusPanel = new SendStatusPanel(backend); setName(Localization.getString("mainWindow.swing.connectionPanel")); fileChooser = new JFileChooser(); jogPanel = new JogPanel(backend, jogService, true); initComponents(); addKeyboardListener(); } private void initComponents() { loadFirmwareSelector(); portCombo.setEditable(true); baudCombo.setModel(new javax.swing.DefaultComboBoxModel(new String[]{"2400", "4800", "9600", "19200", "38400", "57600", "115200", "230400"})); baudCombo.setSelectedIndex(2); baudCombo.setToolTipText("Select baudrate to use for the serial port."); openCloseButton.addActionListener(evt -> opencloseButtonActionPerformed(evt)); refreshButton.addActionListener(evt -> loadPortSelector()); sendPauseResumeButton.addActionListener(evt -> sendPauseResumeButtonActionPerformed(evt)); browseCancelButton.addActionListener(evt -> browseCancelButtonActionPerformed(evt)); Font f = currentFile.getFont(); currentFile.setFont(f.deriveFont(f.getStyle() | Font.BOLD)); sendStatusPanel.setBorder(BorderFactory.createTitledBorder("")); this.updateConnectionControlsStateOpen(false); // MigLayout... 3rd party layout library. setLayout(new MigLayout("flowy, hidemode 3")); add(openCloseButton, "wmin button, grow, flowx, split 3"); add(sendPauseResumeButton, "r, wmin button, grow"); add(browseCancelButton, "r, wmin button, grow"); connection.setLayout(new MigLayout("fill, wrap 3")); connection.add(portLabel, "al right"); connection.add(portCombo, "span 3"); connection.add(baudLabel, "al right"); connection.add(baudCombo); connection.add(refreshButton); connection.add(firmwareLabel, "al right"); connection.add(firmwareCombo, "span 3"); add(connection); add(machineStatus, "grow"); add(currentFile, "grow"); add(sendStatusPanel, "grow"); jogPanel.setBorder(BorderFactory.createTitledBorder( Localization.getString("mainWindow.swing.keyboardMovementPanel"))); add(jogPanel, "grow"); } @Override public void UGSEvent(UGSEvent evt) { if (evt.isFileChangeEvent()) { switch(evt.getFileState()) { case FILE_LOADED: updateConnectionControlsStateOpen(backend.isConnected()); updateCurrentFileLabel(new File(evt.getFile())); break; case FILE_LOADING: sendPauseResumeButton.setEnabled(false); currentFile.setText("Loading..."); currentFile.setToolTipText(""); break; } } if (evt.isStateChangeEvent()) { switch (evt.getControlState()) { case COMM_DISCONNECTED: this.updateConnectionControlsStateOpen(false); break; case COMM_IDLE: this.updateConnectionControlsStateOpen(true); sendPauseResumeButton.setText(Localization.getString("mainWindow.swing.sendButton")); browseCancelButton.setText(Localization.getString("mainWindow.swing.browseButton")); break; case COMM_SENDING: sendPauseResumeButton.setText(Localization.getString("mainWindow.swing.pauseButton")); browseCancelButton.setText(Localization.getString("mainWindow.swing.cancelButton")); break; case COMM_SENDING_PAUSED: sendPauseResumeButton.setText(Localization.getString("mainWindow.ui.resumeButton")); break; default: } } } @Override public void controlStateChange(UGSEvent.ControlState state) { } @Override public void fileStreamComplete(String filename, boolean success) { sendPauseResumeButton.setText(Localization.getString("mainWindow.swing.sendButton")); browseCancelButton.setText(Localization.getString("mainWindow.swing.browseButton")); } @Override public void commandSkipped(GcodeCommand command) { } @Override public void commandSent(GcodeCommand command) { } @Override public void commandComplete(GcodeCommand command) { } @Override public void commandComment(String comment) { } @Override public void probeCoordinates(Position p) { } @Override public void messageForConsole(MessageType type, String msg) { } @Override public void statusStringListener(ControllerStatus status) { } @Override public void postProcessData(int numRows) { } private void opencloseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_opencloseButtonActionPerformed if (this.openCloseButton.getText().equalsIgnoreCase(Localization.getString("open"))) { String firmware = this.firmwareCombo.getSelectedItem().toString(); String port = portCombo.getSelectedItem().toString(); int baudRate = Integer.parseInt(baudCombo.getSelectedItem().toString()); try { this.backend.connect(firmware, port, baudRate); } catch (Exception e) { logger.log(Level.WARNING, "Problem during backend.connect.", e); displayErrorDialog(e.getMessage()); } } else { try { this.backend.disconnect(); } catch (Exception e) { displayErrorDialog(e.getMessage()); } } } private void loadPortSelector() { portCombo.removeAllItems(); String[] portList = CommUtils.getSerialPortList(); if (portList.length < 1) { if (backend.getSettings().isShowSerialPortWarning()) { displayErrorDialog(Localization.getString("mainWindow.error.noSerialPort")); } } else { for (String port : portList) { portCombo.addItem(port); } portCombo.setSelectedIndex(0); } } private void loadFirmwareSelector() { firmwareCombo.removeAllItems(); List<String> firmwareList = FirmwareUtils.getFirmwareList(); if (firmwareList.size() < 1) { displayErrorDialog(Localization.getString("mainWindow.error.noFirmware")); } else { java.util.Iterator<String> iter = firmwareList.iterator(); while (iter.hasNext()) { firmwareCombo.addItem(iter.next()); } } } public void saveSettings() { backend.getSettings().setPort(portCombo.getSelectedItem().toString()); backend.getSettings().setPortRate(baudCombo.getSelectedItem().toString()); backend.getSettings().setFirmwareVersion(firmwareCombo.getSelectedItem().toString()); backend.getSettings().setLastOpenedFilename(fileChooser.getSelectedFile().getAbsolutePath()); jogPanel.saveSettings(); } public void loadSettings() { portCombo.setSelectedItem(backend.getSettings().getPort()); baudCombo.setSelectedItem(backend.getSettings().getPortRate()); firmwareCombo.setSelectedItem(backend.getSettings().getFirmwareVersion()); String lastOpenedFilename = backend.getSettings().getLastOpenedFilename(); if (lastOpenedFilename != null && !lastOpenedFilename.isEmpty()) { fileChooser.setSelectedFile(new File(lastOpenedFilename)); } updateCurrentFileLabel(backend.getGcodeFile()); jogPanel.loadSettings(); } private void updateCurrentFileLabel(File lastOpenedFilename) { if (lastOpenedFilename != null) { currentFile.setText(lastOpenedFilename.getName()); currentFile.setToolTipText(lastOpenedFilename.getAbsolutePath()); } else { currentFile.setText(""); currentFile.setToolTipText(""); } } private void updateConnectionControlsStateOpen(boolean isOpen) { connection.setVisible(!isOpen); machineStatus.setVisible(isOpen); sendPauseResumeButton.setEnabled(isOpen && backend != null && backend.getGcodeFile() != null); browseCancelButton.setEnabled(isOpen); if (isOpen) { this.openCloseButton.setText(Localization.getString("close")); } else { this.openCloseButton.setText(Localization.getString("open")); } } private void sendPauseResumeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sendButtonActionPerformed try { if (sendPauseResumeButton.getText().equals(Localization.getString("mainWindow.swing.sendButton"))) { this.backend.send(); } else { this.backend.pauseResume(); } } catch (Exception e) { displayErrorDialog(e.getMessage()); } } private void browseCancelButtonActionPerformed(java.awt.event.ActionEvent evt) { try { if (browseCancelButton.getText().equals(Localization.getString("mainWindow.swing.browseButton"))) { openFileChooser(); } else { backend.cancel(); } } catch (Exception e) { displayErrorDialog(e.getMessage()); } } private void openFileChooser() { int returnVal = fileChooser.showOpenDialog(this); if (returnVal == JFileChooser.APPROVE_OPTION) { try { File gcodeFile = fileChooser.getSelectedFile(); backend.setGcodeFile(gcodeFile); } catch (Exception ex) { displayErrorDialog(ex.getMessage()); } } else { // Canceled file open. } } public String getDuration() { return sendStatusPanel.getDuration(); } private void addKeyboardListener() { KeyboardFocusManager.getCurrentKeyboardFocusManager() .addKeyEventDispatcher(new KeyEventDispatcher() { @Override public boolean dispatchKeyEvent(KeyEvent e) { // Check context. if (((jogPanel.isKeyboardMovementEnabled()) && e.getID() == KeyEvent.KEY_PRESSED)) { switch (e.getKeyCode()) { case KeyEvent.VK_RIGHT: case KeyEvent.VK_KP_RIGHT: case KeyEvent.VK_NUMPAD6: jogPanel.xPlusButtonActionPerformed(); e.consume(); return true; case KeyEvent.VK_LEFT: case KeyEvent.VK_KP_LEFT: case KeyEvent.VK_NUMPAD4: jogPanel.xMinusButtonActionPerformed(); e.consume(); return true; case KeyEvent.VK_UP: case KeyEvent.VK_KP_UP: case KeyEvent.VK_NUMPAD8: jogPanel.yPlusButtonActionPerformed(); e.consume(); return true; case KeyEvent.VK_DOWN: case KeyEvent.VK_KP_DOWN: case KeyEvent.VK_NUMPAD2: jogPanel.yMinusButtonActionPerformed(); e.consume(); return true; case KeyEvent.VK_PAGE_UP: case KeyEvent.VK_NUMPAD9: jogPanel.zPlusButtonActionPerformed(); e.consume(); return true; case KeyEvent.VK_PAGE_DOWN: case KeyEvent.VK_NUMPAD3: jogPanel.zMinusButtonActionPerformed(); e.consume(); return true; case KeyEvent.VK_ADD: jogPanel.increaseStepActionPerformed(); e.consume(); return true; case KeyEvent.VK_SUBTRACT: jogPanel.decreaseStepActionPerformed(); e.consume(); return true; case KeyEvent.VK_DIVIDE: jogPanel.divideStepActionPerformed(); e.consume(); return true; case KeyEvent.VK_MULTIPLY: jogPanel.multiplyStepActionPerformed(); e.consume(); return true; case KeyEvent.VK_INSERT: case KeyEvent.VK_NUMPAD0: //resetCoordinatesButtonActionPerformed(null); e.consume(); return true; default: break; } } return false; } }); } }