/*
* PropertiesKeyShortcuts.java
*
* Copyright (C) 2002, 2003, 2004, 2005, 2006 Takis Diakoumis
*
* 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 org.executequery.gui.prefs;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Vector;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.table.AbstractTableModel;
import org.executequery.Constants;
import org.executequery.GUIUtilities;
import org.underworldlabs.swing.actions.BaseActionCommand;
import org.underworldlabs.swing.actions.ActionBuilder;
import org.executequery.util.SystemResources;
import org.underworldlabs.util.MiscUtils;
/* ----------------------------------------------------------
* CVS NOTE: Changes to the CVS repository prior to the
* release of version 3.0.0beta1 has meant a
* resetting of CVS revision numbers.
* ----------------------------------------------------------
*/
/** <p>Query Editor syntax highlighting preferences panel.
*
* @author Takis Diakoumis
* @version $Revision: 1.4 $
* @date $Date: 2006/05/14 06:56:52 $
*/
public class PropertiesKeyShortcuts extends PropertiesBase
implements Constants {
private JTable table;
private Properties userDefinedShortcuts;
private ShortcutsTableModel tableModel;
private static String NONE = "<none>";
private static String delimiter = "+";
/** <p>Constructs a new instance. */
public PropertiesKeyShortcuts() {
try {
jbInit();
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* Initializes the state of this instance.
*/
private void jbInit() throws Exception {
Vector shortcuts = formatValues(ActionBuilder.getActions());
tableModel = new ShortcutsTableModel(shortcuts);
table = new JTable(tableModel);
table.setFont(PropertiesBase.panelFont);
table.addMouseListener(new MouseHandler());
table.setRowHeight(20);
table.setCellSelectionEnabled(true);
table.setColumnSelectionAllowed(false);
table.setRowSelectionAllowed(false);
table.getTableHeader().setResizingAllowed(false);
table.getTableHeader().setReorderingAllowed(false);
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets.left = 5;
gbc.anchor = GridBagConstraints.NORTHWEST;
panel.add(new JLabel("Keyboard Shortcuts:"), gbc);
gbc.fill = GridBagConstraints.BOTH;
gbc.insets.top = 10;
gbc.gridy = 1;
gbc.weighty = 1.0;
gbc.weightx = 1.0;
panel.add(new JScrollPane(table), gbc);
addContent(panel);
userDefinedShortcuts = SystemResources.getUserActionShortcuts();
if (userDefinedShortcuts != null) {
tableModel.loadUserDefined();
}
}
private Vector formatValues(Map actionMap) {
Set set = actionMap.keySet();
BaseActionCommand command = null;
Vector shortcuts = new Vector(actionMap.size());
for (Iterator i = set.iterator(); i.hasNext();) {
command = (BaseActionCommand)actionMap.get(i.next());
if (command.isAcceleratorEditable()) {
shortcuts.add(
new ShortcutKey(
command.getActionId(),
(String)command.getValue(Action.NAME),
(KeyStroke)command.getValue(Action.ACCELERATOR_KEY)));
}
}
Collections.sort(shortcuts, new ShortcutKeyComparator());
return shortcuts;
}
public void restoreDefaults() {
Vector shortcuts = formatValues(
ActionBuilder.reloadActions(Constants.ACTION_CONF_PATH));
tableModel.setShortcuts(shortcuts);
}
public void save() {
if (userDefinedShortcuts == null) {
userDefinedShortcuts = new Properties();
}
Vector shortcuts = tableModel.getShortcuts();
for (int i = 0, k = shortcuts.size(); i < k; i++) {
ShortcutKey shortcut = (ShortcutKey)shortcuts.elementAt(i);
if (!MiscUtils.isNull(shortcut.keyStrokeText)) {
userDefinedShortcuts.setProperty(
shortcut.key, shortcut.keyStrokeText);
}
}
SystemResources.setUserActionShortcuts(userDefinedShortcuts);
}
class ShortcutsTableModel extends AbstractTableModel {
private Vector shortcuts;
private String[] columnHeaders = {"Command", "Shortcut"};
ShortcutsTableModel(Vector shortcuts) {
this.shortcuts = shortcuts;
}
public void loadUserDefined() {
if (userDefinedShortcuts == null) {
return;
}
KeyStroke keyStroke = null;
for (int i = 0, k = shortcuts.size(); i < k; i++) {
ShortcutKey shortcut = (ShortcutKey)shortcuts.elementAt(i);
if (userDefinedShortcuts.containsKey(shortcut.key)) {
keyStroke = KeyStroke.getKeyStroke(
userDefinedShortcuts.getProperty(shortcut.key));
shortcut.value = MiscUtils.keyStrokeToString(keyStroke);
}
}
}
public void setShortcuts(Vector shortcuts) {
this.shortcuts = shortcuts;
fireTableDataChanged();
}
public int getColumnCount() {
return 2;
}
public int getRowCount() {
return shortcuts.size();
}
public Object getValueAt(int row, int col) {
ShortcutKey shortcut = (ShortcutKey)shortcuts.elementAt(row);
switch(col) {
case 0:
return shortcut.label;
case 1:
return shortcut.value;
default:
return null;
}
}
public ShortcutKey getShortcut(int index) {
return (ShortcutKey)shortcuts.elementAt(index);
}
public void updateShortcut(ShortcutKey shortcut, int row) {
shortcuts.set(row, shortcut);
fireTableRowsUpdated(row, row);
}
public void setValueAt(Object value, int row, int col) {
ShortcutKey shortcut = (ShortcutKey)shortcuts.elementAt(row);
switch(col) {
case 0:
shortcut.label = (String)value;
break;
case 1:
shortcut.value = (String)value;
break;
}
fireTableRowsUpdated(row, row);
}
public boolean isCellEditable(int nRow, int nCol) {
return false;
}
public String getColumnName(int col) {
return columnHeaders[col];
}
public Vector getShortcuts() {
return shortcuts;
}
} // ShortcutsTableModel
class ShortcutDialog extends JDialog
implements ActionListener {
private int row;
private ShortcutInputField shortcutField;
private ShortcutKey shortcutKey;
public ShortcutDialog(int row) {
super(GUIUtilities.getParentFrame(), "Select Shortcut", true);
this.row = row;
shortcutKey = (ShortcutKey)tableModel.getShortcut(row);
JButton okButton = new JButton("OK");
JButton clearButton = new JButton("Clear");
JButton cancelButton = new JButton("Cancel");
okButton.addActionListener(this);
clearButton.addActionListener(this);
cancelButton.addActionListener(this);
shortcutField = new ShortcutInputField();
shortcutField.setPreferredSize(new Dimension(300, 20));
Container c = this.getContentPane();
c.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridy++;
gbc.insets = new Insets(10,10,5,10);
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
c.add(new JLabel("Enter a new shortcut for \"" +
shortcutKey.label + "\":"), gbc);
gbc.gridy++;
gbc.insets.top = 0;
c.add(shortcutField, gbc);
gbc.gridy++;
c.add(new JLabel("Current assignment: " +
(MiscUtils.isNull(shortcutKey.value) ? NONE :
shortcutKey.value)), gbc);
gbc.gridy++;
JPanel buttonPanel = new JPanel();
buttonPanel.add(okButton);
buttonPanel.add(clearButton);
buttonPanel.add(cancelButton);
gbc.weighty = 1.0;
gbc.insets.bottom = 10;
gbc.fill = GridBagConstraints.BOTH;
c.add(buttonPanel, gbc);
pack();
this.setLocation(GUIUtilities.getLocationForDialog(this.getSize()));
shortcutField.requestFocusInWindow();
this.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("Clear")) {
shortcutField.reset();
shortcutField.setText(Constants.EMPTY);
shortcutField.requestFocusInWindow();
}
else if (command.equals("OK")) {
shortcutKey.value = shortcutField.getText();
shortcutKey.keyStrokeText = shortcutField.getKeyStrokeText();
tableModel.updateShortcut(shortcutKey, row);
dispose();
}
else if (command.equals("Cancel")) {
dispose();
}
}
}
class ShortcutInputField extends JTextField {
private int keyCode;
private StringBuffer keyStrokeText;
public void reset() {
if (keyStrokeText != null) {
keyStrokeText.delete(0, keyStrokeText.length());
}
}
public boolean getFocusTraversalKeysEnabled() {
return false;
}
protected void processKeyEvent(KeyEvent evt) {
evt.consume();
if (evt.getID() == KeyEvent.KEY_PRESSED) {
int _keyCode = evt.getKeyCode();
if (_keyCode == keyCode) {
return;
}
keyCode = _keyCode;
StringBuffer keyString = new StringBuffer(getText());
String modifiers = KeyEvent.getKeyText(evt.getKeyCode());
boolean nullModifiers = MiscUtils.isNull(modifiers);
if (keyStrokeText == null) {
keyStrokeText = new StringBuffer();
}
if (getDocument().getLength() != 0) {
keyString.append('+');
keyStrokeText.append(' ');
}
if (!nullModifiers) {
keyString.append(modifiers);
}
if (((keyCode >= KeyEvent.VK_A && keyCode <= KeyEvent.VK_Z)
|| (keyCode >= KeyEvent.VK_0 && keyCode <= KeyEvent.VK_9))
&& nullModifiers) {
keyStrokeText.append(modifiers);
}
else {
keyStrokeText.append(getKeyText(keyCode));
}
setText(keyString.toString());
}
}
public String getKeyStrokeText() {
return keyStrokeText.toString();
}
private String getKeyText(int keyCode) {
if (keyCode >= KeyEvent.VK_0 && keyCode <= KeyEvent.VK_9 ||
keyCode >= KeyEvent.VK_A && keyCode <= KeyEvent.VK_Z) {
return String.valueOf((char)keyCode);
}
switch(keyCode) {
case KeyEvent.VK_COMMA: return "COMMA";
case KeyEvent.VK_PERIOD: return "PERIOD";
case KeyEvent.VK_SLASH: return "SLASH";
case KeyEvent.VK_SEMICOLON: return "SEMICOLON";
case KeyEvent.VK_EQUALS: return "EQUALS";
case KeyEvent.VK_OPEN_BRACKET: return "OPEN_BRACKET";
case KeyEvent.VK_BACK_SLASH: return "BACK_SLASH";
case KeyEvent.VK_CLOSE_BRACKET: return "CLOSE_BRACKET";
case KeyEvent.VK_ENTER: return "ENTER";
case KeyEvent.VK_BACK_SPACE: return "BACK_SPACE";
case KeyEvent.VK_TAB: return "TAB";
case KeyEvent.VK_CANCEL: return "CANCEL";
case KeyEvent.VK_CLEAR: return "CLEAR";
case KeyEvent.VK_SHIFT: return "shift";
case KeyEvent.VK_CONTROL: return "control";
case KeyEvent.VK_ALT: return "alt";
case KeyEvent.VK_PAUSE: return "PAUSE";
case KeyEvent.VK_CAPS_LOCK: return "CAPS_LOCK";
case KeyEvent.VK_ESCAPE: return "ESCAPE";
case KeyEvent.VK_SPACE: return "SPACE";
case KeyEvent.VK_PAGE_UP: return "PAGE_UP";
case KeyEvent.VK_PAGE_DOWN: return "PAGE_DOWN";
case KeyEvent.VK_END: return "END";
case KeyEvent.VK_HOME: return "HOME";
case KeyEvent.VK_LEFT: return "LEFT";
case KeyEvent.VK_UP: return "UP";
case KeyEvent.VK_RIGHT: return "RIGHT";
case KeyEvent.VK_DOWN: return "DOWN";
// numpad numeric keys handled below
case KeyEvent.VK_MULTIPLY: return "MULTIPLY";
case KeyEvent.VK_ADD: return "ADD";
case KeyEvent.VK_SEPARATOR: return "SEPARATOR";
case KeyEvent.VK_SUBTRACT: return "SUBTRACT";
case KeyEvent.VK_DECIMAL: return "DECIMAL";
case KeyEvent.VK_DIVIDE: return "DIVIDE";
case KeyEvent.VK_DELETE: return "DELETE";
case KeyEvent.VK_NUM_LOCK: return "NUM_LOCK";
case KeyEvent.VK_SCROLL_LOCK: return "SCROLL_LOCK";
case KeyEvent.VK_F1: return "F1";
case KeyEvent.VK_F2: return "F2";
case KeyEvent.VK_F3: return "F3";
case KeyEvent.VK_F4: return "F4";
case KeyEvent.VK_F5: return "F5";
case KeyEvent.VK_F6: return "F6";
case KeyEvent.VK_F7: return "F7";
case KeyEvent.VK_F8: return "F8";
case KeyEvent.VK_F9: return "F9";
case KeyEvent.VK_F10: return "F10";
case KeyEvent.VK_F11: return "F11";
case KeyEvent.VK_F12: return "F12";
case KeyEvent.VK_F13: return "F13";
case KeyEvent.VK_F14: return "F14";
case KeyEvent.VK_F15: return "F15";
case KeyEvent.VK_F16: return "F16";
case KeyEvent.VK_F17: return "F17";
case KeyEvent.VK_F18: return "F18";
case KeyEvent.VK_F19: return "F19";
case KeyEvent.VK_F20: return "F20";
case KeyEvent.VK_F21: return "F21";
case KeyEvent.VK_F22: return "F22";
case KeyEvent.VK_F23: return "F23";
case KeyEvent.VK_F24: return "F24";
case KeyEvent.VK_PRINTSCREEN: return "PRINTSCREEN";
case KeyEvent.VK_INSERT: return "INSERT";
case KeyEvent.VK_HELP: return "HELP";
case KeyEvent.VK_META: return "META";
case KeyEvent.VK_BACK_QUOTE: return "BACK_QUOTE";
case KeyEvent.VK_QUOTE: return "QUOTE";
case KeyEvent.VK_KP_UP: return "KP_UP";
case KeyEvent.VK_KP_DOWN: return "KP_DOWN";
case KeyEvent.VK_KP_LEFT: return "KP_LEFT";
case KeyEvent.VK_KP_RIGHT: return "KP_RIGHT";
case KeyEvent.VK_DEAD_GRAVE: return "DEAD_GRAVE";
case KeyEvent.VK_DEAD_ACUTE: return "DEAD_ACUTE";
case KeyEvent.VK_DEAD_CIRCUMFLEX: return "DEAD_CIRCUMFLEX";
case KeyEvent.VK_DEAD_TILDE: return "DEAD_TILDE";
case KeyEvent.VK_DEAD_MACRON: return "DEAD_MACRON";
case KeyEvent.VK_DEAD_BREVE: return "DEAD_BREVE";
case KeyEvent.VK_DEAD_ABOVEDOT: return "DEAD_ABOVEDOT";
case KeyEvent.VK_DEAD_DIAERESIS: return "DEAD_DIAERESIS";
case KeyEvent.VK_DEAD_ABOVERING: return "DEAD_ABOVERING";
case KeyEvent.VK_DEAD_DOUBLEACUTE: return "DEAD_DOUBLEACUTE";
case KeyEvent.VK_DEAD_CARON: return "DEAD_CARON";
case KeyEvent.VK_DEAD_CEDILLA: return "DEAD_CEDILLA";
case KeyEvent.VK_DEAD_OGONEK: return "DEAD_OGONEK";
case KeyEvent.VK_DEAD_IOTA: return "DEAD_IOTA";
case KeyEvent.VK_DEAD_VOICED_SOUND: return "DEAD_VOICED_SOUND";
case KeyEvent.VK_DEAD_SEMIVOICED_SOUND: return "DEAD_SEMIVOICED_SOUND";
case KeyEvent.VK_AMPERSAND: return "AMPERSAND";
case KeyEvent.VK_ASTERISK: return "ASTERISK";
case KeyEvent.VK_QUOTEDBL: return "QUOTEDBL";
case KeyEvent.VK_LESS: return "LESS";
case KeyEvent.VK_GREATER: return "GREATER";
case KeyEvent.VK_BRACELEFT: return "BRACELEFT";
case KeyEvent.VK_BRACERIGHT: return "BRACERIGHT";
case KeyEvent.VK_AT: return "AT";
case KeyEvent.VK_COLON: return "COLON";
case KeyEvent.VK_CIRCUMFLEX: return "CIRCUMFLEX";
case KeyEvent.VK_DOLLAR: return "DOLLAR";
case KeyEvent.VK_EURO_SIGN: return "EURO_SIGN";
case KeyEvent.VK_EXCLAMATION_MARK: return "EXCLAMATION_MARK";
case KeyEvent.VK_INVERTED_EXCLAMATION_MARK:
return "INVERTED_EXCLAMATION_MARK";
case KeyEvent.VK_LEFT_PARENTHESIS: return "LEFT_PARENTHESIS";
case KeyEvent.VK_NUMBER_SIGN: return "NUMBER_SIGN";
case KeyEvent.VK_MINUS: return "MINUS";
case KeyEvent.VK_PLUS: return "PLUS";
case KeyEvent.VK_RIGHT_PARENTHESIS: return "RIGHT_PARENTHESIS";
case KeyEvent.VK_UNDERSCORE: return "UNDERSCORE";
case KeyEvent.VK_FINAL: return "FINAL";
case KeyEvent.VK_CONVERT: return "CONVERT";
case KeyEvent.VK_NONCONVERT: return "NONCONVERT";
case KeyEvent.VK_ACCEPT: return "ACCEPT";
case KeyEvent.VK_MODECHANGE: return "MODECHANGE";
case KeyEvent.VK_KANA: return "KANA";
case KeyEvent.VK_KANJI: return "KANJI";
case KeyEvent.VK_ALPHANUMERIC: return "ALPHANUMERIC";
case KeyEvent.VK_KATAKANA: return "KATAKANA";
case KeyEvent.VK_HIRAGANA: return "HIRAGANA";
case KeyEvent.VK_FULL_WIDTH: return "FULL_WIDTH";
case KeyEvent.VK_HALF_WIDTH: return "HALF_WIDTH";
case KeyEvent.VK_ROMAN_CHARACTERS: return "ROMAN_CHARACTERS";
case KeyEvent.VK_ALL_CANDIDATES: return "ALL_CANDIDATES";
case KeyEvent.VK_PREVIOUS_CANDIDATE: return "PREVIOUS_CANDIDATE";
case KeyEvent.VK_CODE_INPUT: return "CODE_INPUT";
case KeyEvent.VK_JAPANESE_KATAKANA: return "JAPANESE_KATAKANA";
case KeyEvent.VK_JAPANESE_HIRAGANA: return "JAPANESE_HIRAGANA";
case KeyEvent.VK_JAPANESE_ROMAN: return "JAPANESE_ROMAN";
case KeyEvent.VK_KANA_LOCK: return "KANA_LOCK";
case KeyEvent.VK_INPUT_METHOD_ON_OFF: return "INPUT_METHOD_ON_OFF";
case KeyEvent.VK_AGAIN: return "AGAIN";
case KeyEvent.VK_UNDO: return "UNDO";
case KeyEvent.VK_COPY: return "COPY";
case KeyEvent.VK_PASTE: return "PASTE";
case KeyEvent.VK_CUT: return "CUT";
case KeyEvent.VK_FIND: return "FIND";
case KeyEvent.VK_PROPS: return "PROPS";
case KeyEvent.VK_STOP: return "STOP";
case KeyEvent.VK_COMPOSE: return "COMPOSE";
case KeyEvent.VK_ALT_GRAPH: return "ALT_GRAPH";
}
if (keyCode >= KeyEvent.VK_NUMPAD0 && keyCode <= KeyEvent.VK_NUMPAD9) {
char c = (char)(keyCode - KeyEvent.VK_NUMPAD0 + '0');
return "NUMPAD"+c;
}
return null;
}
}
static class ShortcutKey {
String key;
String value;
String label;
String keyStrokeText;
KeyStroke keyStroke;
ShortcutKey(String key, String label, KeyStroke keyStroke) {
this.key = key;
this.label = label;
this.keyStroke = keyStroke;
value = MiscUtils.keyStrokeToString(keyStroke);
}
public String toString() {
return value;
}
} // ShortcutKey
class ShortcutKeyComparator implements Comparator {
public int compare(Object obj1, Object obj2) {
ShortcutKey key1 = (ShortcutKey)obj1;
ShortcutKey key2 = (ShortcutKey)obj2;
int result = key1.label.compareTo(key2.label);
if (result < 0)
return -1;
else if (result > 0)
return 1;
else
return 0;
}
} // ShortcutKeyComparator
class MouseHandler extends MouseAdapter {
public void mouseClicked(MouseEvent evt) {
int row = table.rowAtPoint(evt.getPoint());
if (row == -1) {
return;
}
int col = table.columnAtPoint(evt.getPoint());
if (col == 1) {
new ShortcutDialog(row);
}
}
} // MouseHandler
}
|