import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.FlowLayout; import java.awt.Font; import java.awt.GridLayout; import java.awt.KeyEventDispatcher; import java.awt.KeyboardFocusManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.border.Border; public class Interface extends JFrame implements ActionListener, FocusListener { private static final long serialVersionUID = 1L; private static final Font titleFont = new Font(new JLabel().getFont().getName(), Font.BOLD, 14); private static final Font defaultFont = new Font(new JLabel().getFont().getName(), Font.PLAIN, new JLabel().getFont().getSize()); private static final Border defaultJTextFieldBorder = new JTextField().getBorder(); private JTextArea logs; private JButton[][] moveButtons = new JButton[3][3]; private JTextField stepsField; private JButton waitButton; private JButton nextButton; private JButton revertButton; private JButton exportButton; private JButton importButton; private boolean keyboardWait = false; private ActionList actionList; public Interface(ActionList actionList) { super("PercTeacher"); this.actionList = actionList; setResizable(false); populateWindow(); pack(); setLocationRelativeTo(null); // center window KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new CustomDispatcher()); getContentPane().requestFocusInWindow(); } private void populateWindow() { JPanel mainPanel = new JPanel(new BorderLayout()); addLogPanel(mainPanel); JPanel centerPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0)); addMoveCommandsPanel(centerPanel); JPanel optionCommandsPanel = new JPanel(); addOptionCommandsPanel(centerPanel, optionCommandsPanel); addExportImportPanel(optionCommandsPanel); mainPanel.add(centerPanel, BorderLayout.CENTER); add(mainPanel); updateLogs(); } private void addLogPanel(JPanel parent) { JPanel logPanel = new JPanel(new BorderLayout()); logPanel.setBorder(BorderFactory.createMatteBorder(2, 0, 0, 0, Color.LIGHT_GRAY)); JLabel loglabel = new JLabel("Actions"); loglabel.setFont(titleFont); logPanel.add(loglabel, BorderLayout.NORTH); logs = new JTextArea(6, 0); logs.setEditable(false); JScrollPane logScroll = new JScrollPane(logs, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); logPanel.add(logScroll, BorderLayout.CENTER); parent.add(logPanel, BorderLayout.SOUTH); } private void addMoveCommandsPanel(JPanel parent) { JPanel moveCommandsPanel = new JPanel(new GridLayout(3, 3)); moveCommandsPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 2, Color.LIGHT_GRAY)); for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { if(i == 1 && j == 1) { // central component is an image of the robot JLabel label = new JLabel(new ImageIcon(getClass().getResource("/icons/robot.png"))); moveButtons[i][j] = null; moveCommandsPanel.add(label); } else { JButton button = new JButton(new ImageIcon(getClass().getResource("/icons/move" + String.valueOf(j) + String.valueOf(i) + ".png"))); button.addActionListener(this); moveButtons[i][j] = button; moveCommandsPanel.add(button); } } } parent.add(moveCommandsPanel, BorderLayout.CENTER); } private void addOptionCommandsPanel(JPanel parent, JPanel optionCommandsPanel) { optionCommandsPanel.setLayout(new BoxLayout(optionCommandsPanel, BoxLayout.PAGE_AXIS)); // title JLabel title = new JLabel("Options"); title.setFont(titleFont); title.setAlignmentX(Component.LEFT_ALIGNMENT); optionCommandsPanel.add(title); // steps JPanel stepPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0)); stepPanel.setAlignmentX(Component.LEFT_ALIGNMENT); JLabel stepLabel = new JLabel("Steps : "); stepLabel.setFont(defaultFont); stepPanel.add(stepLabel); stepsField = new JTextField(10); stepsField.setText("10"); stepsField.addFocusListener(this); stepPanel.add(stepsField); optionCommandsPanel.add(stepPanel); //buttons JPanel buttonsPanel = new JPanel(new GridLayout(0, 1)); buttonsPanel.setAlignmentX(Component.LEFT_ALIGNMENT); // wait button waitButton = new JButton("Add a pause"); waitButton.addActionListener(this); buttonsPanel.add(waitButton); // next action button nextButton = new JButton("Next action"); nextButton.addActionListener(this); buttonsPanel.add(nextButton); // revert action button revertButton = new JButton("Revert last action"); revertButton.addActionListener(this); buttonsPanel.add(revertButton); optionCommandsPanel.add(buttonsPanel); // separator JSeparator sep = new JSeparator(); sep.setForeground(Color.LIGHT_GRAY); sep.setBackground(Color.LIGHT_GRAY); optionCommandsPanel.add(sep); parent.add(optionCommandsPanel, BorderLayout.EAST); } private void addExportImportPanel(JPanel parent) { JPanel exportImportPanel = new JPanel(new GridLayout(0, 1)); exportImportPanel.setAlignmentX(Component.LEFT_ALIGNMENT); // export exportButton = new JButton("Export actions"); exportButton.addActionListener(this); exportImportPanel.add(exportButton); // import importButton = new JButton("Import actions"); importButton.addActionListener(this); exportImportPanel.add(importButton); parent.add(exportImportPanel); } @Override public void actionPerformed(ActionEvent e) { keyboardWait = true; for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { if(e.getSource() == moveButtons[i][j]) { String str = stepsField.getText(); try { if(str != null && !str.equals("")) { long step = Long.parseLong(str); actionList.addToActionList(i, j, step); } } catch (NumberFormatException ignored) { stepsField.setBorder(BorderFactory.createLineBorder(Color.RED)); } } } } if(e.getSource() == waitButton) { String str = JOptionPane.showInputDialog(null, "Pause duration (in miliseconds) :"); try { if(str != null && !str.equals("")) { long delai = Long.parseLong(str) * 1000; actionList.completeActionAndAddPause(delai); } } catch (NumberFormatException ignored) {} } else if(e.getSource() == nextButton) { actionList.completeAction(); } else if(e.getSource() == revertButton) { actionList.revertLastAction(); } else if(e.getSource() == exportButton) { ImportExport.exportWithDialog(actionList); } else if(e.getSource() == importButton) { ActionList newActionList = ImportExport.importsWithDialog(); if(newActionList != null) actionList = newActionList; } updateLogs(); keyboardWait = false; } private void updateLogs() { if(actionList != null) logs.setText(actionList.toString()); } @Override public void focusGained(FocusEvent e) { keyboardWait = true; if(e.getSource() == stepsField) { stepsField.setBorder(defaultJTextFieldBorder); stepsField.setCaretPosition(stepsField.getDocument().getLength()); } } @Override public void focusLost(FocusEvent e) { keyboardWait = false; } private class CustomDispatcher implements KeyEventDispatcher { @Override public boolean dispatchKeyEvent(KeyEvent e) { if(keyboardWait && Interface.this.getFocusOwner() == stepsField && e.getKeyCode() == KeyEvent.VK_ENTER) { Interface.this.getContentPane().requestFocusInWindow(); return true; } if(e.getID() != KeyEvent.KEY_RELEASED || keyboardWait) return false; if(e.getKeyCode() == KeyEvent.VK_NUMPAD1) actionPerformed(new ActionEvent(moveButtons[2][0], 0, null)); else if(e.getKeyCode() == KeyEvent.VK_NUMPAD2) actionPerformed(new ActionEvent(moveButtons[2][1], 0, null)); else if(e.getKeyCode() == KeyEvent.VK_NUMPAD3) actionPerformed(new ActionEvent(moveButtons[2][2], 0, null)); else if(e.getKeyCode() == KeyEvent.VK_NUMPAD4) actionPerformed(new ActionEvent(moveButtons[1][0], 0, null)); else if(e.getKeyCode() == KeyEvent.VK_NUMPAD6) actionPerformed(new ActionEvent(moveButtons[1][2], 0, null)); else if(e.getKeyCode() == KeyEvent.VK_NUMPAD7) actionPerformed(new ActionEvent(moveButtons[0][0], 0, null)); else if(e.getKeyCode() == KeyEvent.VK_NUMPAD8) actionPerformed(new ActionEvent(moveButtons[0][1], 0, null)); else if(e.getKeyCode() == KeyEvent.VK_NUMPAD9) actionPerformed(new ActionEvent(moveButtons[0][2], 0, null)); else if(e.getKeyCode() == KeyEvent.VK_SPACE) actionPerformed(new ActionEvent(nextButton, 0, null)); else if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE) actionPerformed(new ActionEvent(revertButton, 0, null)); else if(e.getKeyCode() == KeyEvent.VK_NUMPAD0) actionPerformed(new ActionEvent(waitButton, 0, null)); return true; } } }