/* * $Id$ * * Copyright (c) 2008 by Rodney Kinney, Brent Easton * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.configure; import java.awt.Dimension; import java.awt.Window; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.BoxLayout; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import VASSAL.tools.NamedKeyManager; import VASSAL.tools.NamedKeyStroke; /** * A Configurer for {@link NamedKeyStroke} values */ public class NamedHotKeyConfigurer extends Configurer implements KeyListener { private JTextField tf = new JTextField(16); private JPanel p; private boolean named; private JTextField keyName = new JTextField(16); private char lastChar; public NamedHotKeyConfigurer(String key, String name) { this(key, name, new NamedKeyStroke()); } public NamedHotKeyConfigurer(String key, String name, NamedKeyStroke val) { super(key, name, val); named = val != null && val.isNamed(); } public void setValue(Object o) { super.setValue(o); named = value != null && ((NamedKeyStroke) value).isNamed(); if (! named) { if (tf != null && !tf.getText().equals(keyToString())) { tf.setText(keyToString()); } } } public String keyToString() { return getString((NamedKeyStroke) getValue()); } public Object getValue() { return super.getValue(); } public String getValueString() { return encode((NamedKeyStroke) getValue()); } public NamedKeyStroke getValueNamedKeyStroke() { return (NamedKeyStroke) value; } public void setValue(String s) { setValue(s == null ? null : decode(s)); } public void setEnabled(boolean b) { tf.setEnabled(b); keyName.setEnabled(b); } public java.awt.Component getControls() { if (p == null) { p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); tf.setMaximumSize(new Dimension(tf.getMaximumSize().width,tf.getPreferredSize().height)); tf.setText(keyToString()); tf.addKeyListener(this); p.add(new JLabel(getName())); p.add(tf); keyName.setText(getValueNamedKeyStroke() == null ? null : getValueNamedKeyStroke().getName()); keyName.setMaximumSize(new Dimension(keyName.getMaximumSize().width,keyName.getPreferredSize().height)); keyName.addKeyListener(new KeyListener() { public void keyReleased(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_DELETE: case KeyEvent.VK_BACK_SPACE: if (keyName.getText().length() == 0) { named = false; setValue(NamedKeyStroke.NULL_KEYSTROKE); updateVisibility(); } else { setValue(new NamedKeyStroke(NamedKeyManager.getMarkerKeyStroke(), keyName.getText())); } break; case KeyEvent.VK_SHIFT: case KeyEvent.VK_CONTROL: case KeyEvent.VK_META: case KeyEvent.VK_ALT: break; default: if (isPrintableAscii(e.getKeyChar())) { setValue(new NamedKeyStroke(NamedKeyManager.getMarkerKeyStroke(), keyName.getText())); } else { named = false; setValue(NamedKeyStroke.getKeyStrokeForEvent(e)); updateVisibility(); } } } public void keyPressed(KeyEvent e) { } public void keyTyped(KeyEvent e) { } }); p.add(keyName); updateVisibility(); } return p; } protected void updateVisibility() { tf.setVisible(!isNamed()); keyName.setVisible(isNamed()); lastChar = 0; Window w = SwingUtilities.getWindowAncestor(p); if (w != null) { w.pack(); } } public boolean isNamed() { return named; } public void keyTyped(KeyEvent e) { lastChar = e.getKeyChar(); } public void keyPressed(KeyEvent e) { switch (e.getKeyCode()) { case KeyEvent.VK_DELETE: case KeyEvent.VK_BACK_SPACE: setValue(NamedKeyStroke.NULL_KEYSTROKE); break; case KeyEvent.VK_SHIFT: case KeyEvent.VK_CONTROL: case KeyEvent.VK_META: case KeyEvent.VK_ALT: break; default: final NamedKeyStroke namedStroke = getValueNamedKeyStroke(); if (namedStroke != null) { final int thisChar = e.getKeyChar(); if (isPrintableAscii(lastChar) && isPrintableAscii(thisChar)) { final String name = "" + lastChar + e.getKeyChar(); named = true; keyName.setText(name); setValue(new NamedKeyStroke(name)); updateVisibility(); keyName.requestFocus(); break; } } setValue(NamedKeyStroke.getKeyStrokeForEvent(e)); } } public void keyReleased(KeyEvent e) { if (!named) { tf.setText(getString((NamedKeyStroke) getValue())); } } protected boolean isPrintableAscii (char c) { return isPrintableAscii((int) c); } protected boolean isPrintableAscii(int i) { return i >= ' ' && i <= '~'; } /** * A plain text representation of a KeyStroke. Doesn't differ much * from {@link KeyEvent#getKeyText} */ public static String getString(NamedKeyStroke k) { return (k == null || k.isNull()) ? "" : getString(k.getStroke()); } public static String getFancyString(NamedKeyStroke k) { String s = getString(k); if (s.length() > 0) { s = "[" + s + "]"; } return s; } public static String getString(KeyStroke k) { return NamedKeyManager.isNamed(k) ? "" : HotKeyConfigurer.getString(k); } /** * Decode a String into a NamedKeyStroke */ public static NamedKeyStroke decode(String s) { if (s == null) { return NamedKeyStroke.NULL_KEYSTROKE; } String[] parts = s.split(","); if (parts.length < 2) { return NamedKeyStroke.NULL_KEYSTROKE; } try { KeyStroke stroke = KeyStroke.getKeyStroke (Integer.parseInt(parts[0]), Integer.parseInt(parts[1])); String name = null; if (parts.length > 2) { name = parts[2]; } return new NamedKeyStroke(stroke, name); } catch (Exception e) { return NamedKeyStroke.NULL_KEYSTROKE; } } /** * Encode a NamedKeyStroke into a String */ public static String encode(NamedKeyStroke stroke) { if (stroke == null) { return ""; } KeyStroke key = stroke.getStroke(); if (key == null) { return ""; } String s = key.getKeyCode() + "," + key.getModifiers(); if (stroke.isNamed()) { s += "," + stroke.getName(); } return s; } }