diff --git a/src/main/java/chokistream/ControlButtonsHandler.java b/src/main/java/chokistream/ControlButtonsHandler.java new file mode 100644 index 0000000..d44b37d --- /dev/null +++ b/src/main/java/chokistream/ControlButtonsHandler.java @@ -0,0 +1,64 @@ +package chokistream; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.util.ArrayList; + +import javax.swing.JFrame; +import javax.swing.JToggleButton; + +import chokistream.props.Controls; + +public class ControlButtonsHandler implements KeyListener { + + private ArrayList buttons = new ArrayList<>(Controls.values().length); + private JToggleButton active = null; + private JFrame frame; + + public ControlButtonsHandler(JFrame f) { + frame = f; + } + + public void add(JToggleButton button) { + buttons.add(button); + button.addActionListener(new ClickAction(button)); + } + + @Override + public void keyPressed(KeyEvent e) { + if(active != null && e.getKeyCode() != KeyEvent.VK_SHIFT && e.getKeyCode() != KeyEvent.VK_ALT && e.getKeyCode() != KeyEvent.VK_CONTROL) { + active.setText(new Input(e).toString()); + active.setSelected(false); + active = null; + frame.pack(); + } + } + + // non-static inner class! need to access `active` and `panel` + private class ClickAction implements ActionListener { + private final JToggleButton button; + + public ClickAction(JToggleButton button) { + this.button = button; + } + + @Override + public void actionPerformed(ActionEvent e) { + if(active != null) { + active.setSelected(false); + } + active = button; + frame.requestFocus(); + } + } + + // Ignore + @Override + public void keyTyped(KeyEvent e) {} + + // Ignore + @Override + public void keyReleased(KeyEvent e) {} +} diff --git a/src/main/java/chokistream/Input.java b/src/main/java/chokistream/Input.java index 3a72ae7..93dfc4c 100644 --- a/src/main/java/chokistream/Input.java +++ b/src/main/java/chokistream/Input.java @@ -29,6 +29,11 @@ public Input(int keyCode, int... modifiers) { this.modifiers = 0; for(int m : modifiers) this.modifiers += m; } + + public Input(KeyEvent ke) { + this.keyCode = ke.getKeyCode(); + this.modifiers = ke.getModifiersEx(); + } public Input(String keyRep) throws InputParseException { String[] keys = keyRep.split("\\+"); @@ -91,7 +96,7 @@ private static void constructDownMasks() throws InputParseException { for(Field f : InputEvent.class.getDeclaredFields()) { if(f.getName().endsWith("_DOWN_MASK") && !f.getName().equals("BUTTON_DOWN_MASK")) { try { - downMasks.put(f.getInt(null), f.getName().substring(f.getName().length()-10).toLowerCase()); + downMasks.put(f.getInt(null), f.getName().substring(0, f.getName().length()-10).toLowerCase()); } catch (IllegalArgumentException | IllegalAccessException e) { throw new InputParseException("Error parsing field \""+f.getName()+"\" (shouldn't be possible!)"); } diff --git a/src/main/java/chokistream/SwingGUI.java b/src/main/java/chokistream/SwingGUI.java index 581ad58..b51d81d 100644 --- a/src/main/java/chokistream/SwingGUI.java +++ b/src/main/java/chokistream/SwingGUI.java @@ -27,6 +27,7 @@ import javax.swing.JPanel; import javax.swing.JSeparator; import javax.swing.JTextField; +import javax.swing.JToggleButton; import javax.swing.SwingConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -103,7 +104,7 @@ public class SwingGUI extends SettingsUI { // Controls private JFrame controls; - private EnumMap controlsFields = new EnumMap<>(Controls.class); + private EnumMap controlsFields = new EnumMap<>(Controls.class); private static final Logger logger = Logger.INSTANCE; @@ -185,7 +186,10 @@ public SwingGUI() { controlsButton.addActionListener(new ActionListener() { @Override - public void actionPerformed(ActionEvent e) {controls.setVisible(true);} + public void actionPerformed(ActionEvent e) { + controls.setFocusable(true); + controls.setVisible(true); + controls.requestFocusInWindow();} }); modSettings.addActionListener(new ActionListener() { @@ -523,9 +527,11 @@ public void loadControls() { } catch(IOException | IniParseException e) { displayError(e); // these probably indicate the future ones will fail as well, so stop here } + + controls.pack(); // Needs to resize based on text in buttons } - private static void setControlDefault(INIParser parser, Controls p, JTextField tf) { + private static void setControlDefault(INIParser parser, Controls p, JToggleButton tf) { String val = parser.getProp(p); if(val.length() > 0) { try { @@ -598,25 +604,20 @@ public void createControls() { header.setFont(new Font("System", Font.PLAIN, 20)); add(header, p, c, 0, 0, 2, 1); - add(new JLabel(Controls.SCREENSHOT.getLongName()), p, c, 0, 1); - add(new JLabel(Controls.CLOSE.getLongName()), p, c, 0, 2); - add(new JLabel(Controls.QUALITY_UP.getLongName()), p, c, 0, 3); - add(new JLabel(Controls.QUALITY_DOWN.getLongName()), p, c, 0, 4); - add(new JLabel(Controls.REQ_SCREEN.getLongName()), p, c, 0, 5); - add(new JLabel(Controls.TGA.getLongName()), p, c, 0, 6); - add(new JLabel(Controls.INTERLACE.getLongName()), p, c, 0, 7); - - // Temporary, for layout - controlsFields.put(Controls.SCREENSHOT, add(new JTextField(), p, c, 1, 1)); - controlsFields.put(Controls.CLOSE, add(new JTextField(), p, c, 1, 2)); - controlsFields.put(Controls.QUALITY_UP, add(new JTextField(), p, c, 1, 3)); - controlsFields.put(Controls.QUALITY_DOWN, add(new JTextField(), p, c, 1, 4)); - controlsFields.put(Controls.REQ_SCREEN, add(new JTextField(), p, c, 1, 5)); - controlsFields.put(Controls.TGA, add(new JTextField(), p, c, 1, 6)); - controlsFields.put(Controls.INTERLACE, add(new JTextField(), p, c, 1, 7)); + ControlButtonsHandler cbl = new ControlButtonsHandler(controls); + + int i = 1; + for(Controls control : Controls.class.getEnumConstants()) { + add(new JLabel(control.getLongName()), p, c, 0, i); // add label + JToggleButton tb = new JToggleButton(); + add(tb, p, c, 1, i); // add button + controlsFields.put(control, tb); // remember button is associated with control + cbl.add(tb); // add to key listener, add click listener + i++; + } JButton apply = new JButton("Apply"); - add(apply, p, c, 0, 8, 2, 1); + add(apply, p, c, 0, i, 2, 1); apply.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -625,7 +626,7 @@ public void actionPerformed(ActionEvent e) { } }); - controls.pack(); + controls.addKeyListener(cbl); } public void createVideoSettings() { diff --git a/src/main/java/chokistream/props/Controls.java b/src/main/java/chokistream/props/Controls.java index b237a6a..5550aec 100644 --- a/src/main/java/chokistream/props/Controls.java +++ b/src/main/java/chokistream/props/Controls.java @@ -10,8 +10,8 @@ public enum Controls { CLOSE("close", "Close", new Input(KeyEvent.VK_BACK_SPACE)), QUALITY_UP("quality_up", "Increase Quality", new Input(KeyEvent.VK_UP)), QUALITY_DOWN("quality_down", "Decrease Quality", new Input(KeyEvent.VK_DOWN)), - CPU_UP("cpu_up", "Increase CPU Cap", new Input(KeyEvent.VK_BRACERIGHT)), - CPU_DOWN("cpu_down", "Decrease CPU Cap", new Input(KeyEvent.VK_BRACELEFT)), + CPU_UP("cpu_up", "Increase CPU Cap", new Input(KeyEvent.VK_OPEN_BRACKET)), + CPU_DOWN("cpu_down", "Decrease CPU Cap", new Input(KeyEvent.VK_CLOSE_BRACKET)), REQ_SCREEN("req_screen","Switch requested screen", new Input(KeyEvent.VK_R)), INTERLACE("interlace","Toggle interlacing", new Input(KeyEvent.VK_I)), TGA("tga","Toggle TGA", new Input(KeyEvent.VK_T));