/*
* GrabKeyDialog.java - Grabs keys from the keyboard
* :tabSize=8:indentSize=8:noTabs=false:
* :folding=explicit:collapseFolds=1:
*
* Copyright (C) 2001, 2002 Slava Pestov
*
* This program 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 2
* of the License, or any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package freemind.preferences.layout;
//{{{ Imports
import java.awt.AWTEvent;
import java.awt.Dialog;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.lang.reflect.Field;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import freemind.main.FreeMindMain;
/**
* A dialog for getting shortcut keys.
*/
public class GrabKeyDialog extends JDialog {
private final FreeMindMain fmMain;
private static class Buffer {
/**
*/
public int getLength() {
// TODO Auto-generated method stub
return 0;
}
/**
*/
public void insert(int length, String string) {
// TODO Auto-generated method stub
}
}
// {{{ toString() method
public static String toString(KeyEvent evt) {
String id;
switch (evt.getID()) {
case KeyEvent.KEY_PRESSED:
id = "KEY_PRESSED";
break;
case KeyEvent.KEY_RELEASED:
id = "KEY_RELEASED";
break;
case KeyEvent.KEY_TYPED:
id = "KEY_TYPED";
break;
default:
id = "unknown type";
break;
}
return id + ",keyCode=0x" + Integer.toString(evt.getKeyCode(), 16)
+ ",keyChar=0x" + Integer.toString(evt.getKeyChar(), 16)
+ ",modifiers=0x" + Integer.toString(evt.getModifiers(), 16);
} // }}}
// {{{ GrabKeyDialog constructor
/**
* Create and show a new modal dialog.
*
* @param parent
* center dialog on this component.
* @param binding
* the action/macro that should get a binding.
* @param allBindings
* all other key bindings.
* @param debugBuffer
* debug info will be dumped to this buffer (may be null)
* @since jEdit 4.1pre7
*/
// private GrabKeyDialog(Dialog parent, KeyBinding binding,
// Vector allBindings, Buffer debugBuffer)
// {
// super(parent,(getText(""grab-key.title")),true);
//
// init(binding,allBindings,debugBuffer);
// } //}}}
// {{{ GrabKeyDialog constructor
/**
* Create and show a new modal dialog.
*
* @param parent
* center dialog on this component.
* @param binding
* the action/macro that should get a binding.
* @param allBindings
* all other key bindings.
* @param debugBuffer
* debug info will be dumped to this buffer (may be null)
* @since jEdit 4.1pre7
*/
public GrabKeyDialog(FreeMindMain fmMain, Dialog parent,
KeyBinding binding, Vector allBindings, Buffer debugBuffer) {
this(fmMain, parent, binding, allBindings, debugBuffer, 0);
}
public GrabKeyDialog(FreeMindMain fmMain, Dialog parent,
KeyBinding binding, Vector allBindings, Buffer debugBuffer,
int modifierMask) {
super(parent, (/* FIXME: getText */("grab-key.title")), true);
this.fmMain = fmMain;
this.modifierMask = modifierMask;
setTitle(getText("grab-key.title"));
init(binding, allBindings, debugBuffer);
} // }}}
// {{{ getShortcut() method
/**
* Returns the shortcut, or null if the current shortcut should be removed
* or the dialog either has been cancelled. Use isOK() to determine if the
* latter is true.
*/
public String getShortcut() {
if (isOK)
return shortcut.getText();
else
return null;
} // }}}
// {{{ isOK() method
/**
* Returns true, if the dialog has not been cancelled.
*
* @since jEdit 3.2pre9
*/
public boolean isOK() {
return isOK;
} // }}}
// {{{ isManagingFocus() method
/**
* Returns if this component can be traversed by pressing the Tab key. This
* returns false.
*/
public boolean isManagingFocus() {
return false;
} // }}}
// {{{ getFocusTraversalKeysEnabled() method
/**
* Makes the tab key work in Java 1.4.
*
* @since jEdit 3.2pre4
*/
public boolean getFocusTraversalKeysEnabled() {
return false;
} // }}}
// {{{ processKeyEvent() method
protected void processKeyEvent(KeyEvent evt) {
shortcut.processKeyEvent(evt);
} // }}}
// {{{ Private members
// {{{ Instance variables
private InputPane shortcut; // this is a bad hack
private JLabel assignedTo;
private JButton ok;
private JButton remove;
private JButton cancel;
private JButton clear;
private boolean isOK;
private KeyBinding binding;
private Vector allBindings;
private Buffer debugBuffer;
private int modifierMask;
// }}}
public final static String MODIFIER_SEPARATOR = " ";
// {{{ init() method
private void init(KeyBinding binding, Vector allBindings, Buffer debugBuffer) {
this.binding = binding;
this.allBindings = allBindings;
this.debugBuffer = debugBuffer;
enableEvents(AWTEvent.KEY_EVENT_MASK);
// create a panel with a BoxLayout. Can't use Box here
// because Box doesn't have setBorder().
JPanel content = new JPanel(new GridLayout(0, 1, 0, 6)) {
/**
* Returns if this component can be traversed by pressing the Tab
* key. This returns false.
*/
public boolean isManagingFocus() {
return false;
}
/**
* Makes the tab key work in Java 1.4.
*
* @since jEdit 3.2pre4
*/
public boolean getFocusTraversalKeysEnabled() {
return false;
}
};
content.setBorder(new EmptyBorder(12, 12, 12, 12));
setContentPane(content);
JLabel label = new JLabel(
debugBuffer == null ? (getText("grab-key.caption") + " " + binding.label)
// FIXME: getText("grab-key.caption")+new String[] {
// binding.label })
: (getText("grab-key.keyboard-test")));
Box input = Box.createHorizontalBox();
shortcut = new InputPane();
input.add(shortcut);
input.add(Box.createHorizontalStrut(12));
clear = new JButton((getText("grab-key.clear")));
clear.addActionListener(new ActionHandler());
input.add(clear);
assignedTo = new JLabel();
if (debugBuffer == null)
updateAssignedTo(null);
Box buttons = Box.createHorizontalBox();
buttons.add(Box.createGlue());
if (debugBuffer == null) {
ok = new JButton(getText("common.ok"));
ok.addActionListener(new ActionHandler());
buttons.add(ok);
buttons.add(Box.createHorizontalStrut(12));
if (binding.isAssigned()) {
// show "remove" button
remove = new JButton((getText("grab-key.remove")));
remove.addActionListener(new ActionHandler());
// FIXME: REACTIVATE buttons.add(remove);
buttons.add(Box.createHorizontalStrut(12));
}
}
cancel = new JButton(getText("common.cancel"));
cancel.addActionListener(new ActionHandler());
buttons.add(cancel);
buttons.add(Box.createGlue());
// FIXME: REACTIVATE content.add(label);
content.add(input);
// if(debugBuffer == null)
// FIXME: REACTIVATE content.add(assignedTo);
content.add(buttons);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
pack();
setLocationRelativeTo(getParent());
setResizable(false);
setVisible(true);
} // }}}
// {{{ getSymbolicName() method
private String getSymbolicName(int keyCode) {
if (keyCode == KeyEvent.VK_UNDEFINED)
return null;
/*
* else if(keyCode == KeyEvent.VK_OPEN_BRACKET) return "["; else
* if(keyCode == KeyEvent.VK_CLOSE_BRACKET) return "]";
*/
if (keyCode >= KeyEvent.VK_A && keyCode <= KeyEvent.VK_Z) {
return String.valueOf(Character.toLowerCase((char) keyCode));
}
try {
Field[] fields = KeyEvent.class.getFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
String name = field.getName();
if (name.startsWith("VK_") && field.getInt(null) == keyCode) {
return name.substring(3);
}
}
} catch (Exception e) {
// Log.log(Log.ERROR,this,e);
}
return null;
} // }}}
// {{{ updateAssignedTo() method
private void updateAssignedTo(String shortcut) {
String text = (getText("grab-key.assigned-to.none"));
KeyBinding kb = getKeyBinding(shortcut);
if (kb != null)
if (kb.isPrefix)
text = getText("grab-key.assigned-to.prefix") + " " + shortcut;
// FIXME: getText("grab-key.assigned-to.prefix")+
// new String[] { shortcut };
else
text = kb.label;
if (ok != null)
ok.setEnabled(kb == null || !kb.isPrefix);
assignedTo.setText((getText("grab-key.assigned-to") + " " + text));
// FIXME: assignedTo.setText(
// (getText("grab-key.assigned-to")+
// new String[] { text }));
} // }}}
// {{{ getKeyBinding() method
private KeyBinding getKeyBinding(String shortcut) {
if (shortcut == null || shortcut.length() == 0)
return null;
String spacedShortcut = shortcut + " ";
Enumeration e = allBindings.elements();
while (e.hasMoreElements()) {
KeyBinding kb = (KeyBinding) e.nextElement();
if (!kb.isAssigned())
continue;
String spacedKbShortcut = kb.shortcut + " ";
// eg, trying to bind C+n C+p if C+n already bound
if (spacedShortcut.startsWith(spacedKbShortcut))
return kb;
// eg, trying to bind C+e if C+e is a prefix
if (spacedKbShortcut.startsWith(spacedShortcut)) {
// create a temporary (synthetic) prefix
// KeyBinding, that won't be saved
return new KeyBinding(kb.name, kb.label, shortcut, true);
}
}
return null;
} // }}}
// }}}
// {{{ KeyBinding class
/**
* A jEdit action or macro with its two possible shortcuts.
*
* @since jEdit 3.2pre8
*/
public static class KeyBinding {
public KeyBinding(String name, String label, String shortcut,
boolean isPrefix) {
this.name = name;
this.label = label;
this.shortcut = shortcut;
this.isPrefix = isPrefix;
}
public String name;
public String label;
public String shortcut;
public boolean isPrefix;
public boolean isAssigned() {
return shortcut != null && shortcut.length() > 0;
}
} // }}}
// {{{ InputPane class
class InputPane extends JTextField {
// {{{ getFocusTraversalKeysEnabled() method
/**
* Makes the tab key work in Java 1.4.
*
* @since jEdit 3.2pre4
*/
public boolean getFocusTraversalKeysEnabled() {
return false;
} // }}}
// {{{ processKeyEvent() method
protected void processKeyEvent(KeyEvent _evt) {
if ((getModifierMask() & _evt.getModifiers()) != 0) {
KeyEvent evt = new KeyEvent(_evt.getComponent(), _evt.getID(),
_evt.getWhen(), ~getModifierMask()
& _evt.getModifiers(), _evt.getKeyCode(),
_evt.getKeyChar(), _evt.getKeyLocation());
processKeyEvent(evt);
if (evt.isConsumed()) {
_evt.consume();
}
return;
}
KeyEvent evt = KeyEventWorkaround.processKeyEvent(_evt);
if (debugBuffer != null) {
debugBuffer.insert(debugBuffer.getLength(), "Event "
+ GrabKeyDialog.toString(_evt)
+ (evt == null ? " filtered\n" : " passed\n"));
}
if (evt == null)
return;
evt.consume();
KeyEventTranslator.Key key = KeyEventTranslator
.translateKeyEvent(evt);
if (key == null)
return;
if (debugBuffer != null) {
debugBuffer.insert(debugBuffer.getLength(),
"==> Translated to " + key + "\n");
}
StringBuffer keyString = new StringBuffer(/* getText() */);
// if(getDocument().getLength() != 0)
// keyString.append(' ');
if (key.modifiers != null)
keyString.append(key.modifiers).append(' '); // TODO: plus ??
// .append('+');
if (key.input == ' ')
keyString.append("SPACE");
else if (key.input != '\0')
keyString.append(key.input);
else {
String symbolicName = getSymbolicName(key.key);
if (symbolicName == null)
return;
keyString.append(symbolicName);
}
setText(keyString.toString());
if (debugBuffer == null)
updateAssignedTo(keyString.toString());
} // }}}
} // }}}
// {{{ ActionHandler class
class ActionHandler implements ActionListener {
// {{{ actionPerformed() method
public void actionPerformed(ActionEvent evt) {
if (evt.getSource() == ok) {
if (canClose())
dispose();
} else if (evt.getSource() == remove) {
shortcut.setText(null);
isOK = true;
dispose();
} else if (evt.getSource() == cancel)
dispose();
else if (evt.getSource() == clear) {
shortcut.setText(null);
if (debugBuffer == null)
updateAssignedTo(null);
shortcut.requestFocus();
}
} // }}}
// {{{ canClose() method
private boolean canClose() {
String shortcutString = shortcut.getText();
if (shortcutString.length() == 0 && binding.isAssigned()) {
// ask whether to remove the old shortcut
int answer = JOptionPane
.showConfirmDialog(GrabKeyDialog.this,
getText("grab-key.remove-ask"), null,
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if (answer == JOptionPane.YES_OPTION) {
shortcut.setText(null);
isOK = true;
} else
return false;
}
// check whether this shortcut already exists
KeyBinding other = getKeyBinding(shortcutString);
if (other == null || other == binding) {
isOK = true;
return true;
}
// check whether the other shortcut is the alt. shortcut
if (other.name == binding.name) {
// we don't need two identical shortcuts
JOptionPane.showMessageDialog(GrabKeyDialog.this,
getText("grab-key.duplicate-alt-shortcut"));
return false;
}
// check whether shortcut is a prefix to others
if (other.isPrefix) {
// can't override prefix shortcuts
JOptionPane.showMessageDialog(GrabKeyDialog.this,
getText("grab-key.prefix-shortcut"));
return false;
}
// ask whether to override that other shortcut
int answer = JOptionPane.showConfirmDialog(GrabKeyDialog.this,
getText("grab-key.duplicate-shortcut")
+ new Object[] { other.label }, null,
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (answer == JOptionPane.YES_OPTION) {
if (other.shortcut != null
&& shortcutString.startsWith(other.shortcut)) {
other.shortcut = null;
}
isOK = true;
return true;
} else
return false;
} // }}}
} // }}}
/**
*/
private String getText(String resourceString) {
return fmMain.getResourceString("GrabKeyDialog." + resourceString);
}
private int getModifierMask() {
return modifierMask;
}
/**
* FIXME: make method here.
*/
public static boolean isMacOS() {
return false;
}
}