CaRMtl/rene/gui/Keyboard.java

288 lines
8.2 KiB
Java

/*
Copyright 2006 Rene Grothmann, modified by Eric Hakenholz
This file is part of C.a.R. software.
C.a.R. is a 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, version 3 of the License.
C.a.R. 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, see <http://www.gnu.org/licenses/>.
*/
package rene.gui;
/*
This file contains a keyboard translater. It translates key strokes
into text strings. The strings are menu descriptions and key
descriptions. Menu descriptions are used to call menu entries in
EditorFrame, and key descriptions are used in TextDisplay.
<p>
JE supports up to 5 command keys, which may be prepended to other
keys. Those keys are mapped to command.X, where X is from 1 to 5.
There is also a special escape command key, mapped to command.escape.
<p>
Some strings are contained in the properties, others may be defined by
the user, and are contained in the parameter file "je.cfg". There is
also an editor for the keystrokes, which uses the ItemEditor dialog.
*/
import java.awt.Frame;
import java.awt.event.KeyEvent;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;
import rene.dialogs.ItemEditor;
import rene.dialogs.MyFileDialog;
import rene.util.sort.Sorter;
/**
* A static class, which contains tranlations for key events. It keeps the
* translations in a vector of KeyboardItem.
* <p>
* The class will statically generate the list of translations from the default
* local properties and the JE configuration.
*/
public class Keyboard {
static Vector V;
static Hashtable Hmenu, Hcharkey;
static {
makeKeys();
}
/**
* Read the keys from the Global names and parameters, and put into a vector
* and two hash tables for easy access.
*/
public static void makeKeys() {
V = new Vector();
Hmenu = new Hashtable();
Hcharkey = new Hashtable();
// collect all predefined keys
Enumeration e = Global.names();
if (e == null)
return;
while (e.hasMoreElements()) {
final String key = (String) e.nextElement();
if (key.startsWith("key.")) {
final String menu = key.substring(4);
String charkey = Global.getParameter(key, "default");
final String normalcharkey = Global.name(key);
if (charkey.equals("default"))
charkey = normalcharkey;
final KeyboardItem k = new KeyboardItem(menu, charkey);
V.addElement(k);
Hmenu.put(menu, k);
Hcharkey.put(charkey, k);
}
}
// collect all user defined (double defined) keys
e = Global.properties();
while (e.hasMoreElements()) {
final String key = (String) e.nextElement();
if (key.startsWith("key.")) {
final String menu = key.substring(4);
if (findMenu(menu) != null)
continue;
final String charkey = Global.getParameter(key, "default");
if (charkey.equals("default"))
continue;
final KeyboardItem k = new KeyboardItem(menu, charkey);
V.addElement(k);
Hmenu.put(menu, k);
Hcharkey.put(charkey, k);
}
}
}
/**
* Find a menu string in the key definitions
*/
public static KeyboardItem findMenu(final String menu) {
final Object o = Hmenu.get(menu);
if (o == null)
return null;
else
return (KeyboardItem) o;
}
/**
* Generate a shortcut for the menu item.
*/
public static String shortcut(final String tag) {
final Enumeration e = V.elements();
while (e.hasMoreElements()) {
final KeyboardItem item = (KeyboardItem) e.nextElement();
if (item.getMenuString().equals(tag)) {
String shortcut = item.shortcut();
if (!shortcut.equals(""))
shortcut = " (" + shortcut + ")";
return shortcut;
}
}
return "";
}
/**
* See, if the key event matches any of my translations, and get the menu
* entry.
*/
public static String findKey(final KeyEvent event, final int type) {
final Object o = Hcharkey.get(toCharKey(event, type));
if (o == null)
return "";
String s = ((KeyboardItem) o).getMenuString();
while (s.endsWith("*"))
s = s.substring(0, s.length() - 1);
return s;
}
/**
* Make a keychar string from the event.
*/
public static String toCharKey(final KeyEvent e, final int type) {
String s = "";
if (type > 0)
s = s + "esc" + type + ".";
if (e.isShiftDown())
s = s + "shift.";
if (e.isControlDown())
s = s + "control.";
if (e.isAltDown())
s = s + "alt.";
return s + KeyDictionary.translate(e.getKeyCode()).toLowerCase();
}
/**
* Edit the translations.
*/
public static void edit(final Frame f) {
final KeyboardItem keys[] = new KeyboardItem[V.size()];
V.copyInto(keys);
Sorter.sort(keys);
final Vector v = new Vector();
for (final KeyboardItem key2 : keys)
v.addElement(key2);
final KeyboardPanel p = new KeyboardPanel();
final ItemEditor d = new ItemEditor(f, p, v, "keyeditor", Global
.name("keyeditor.prompt"), true, false, true, Global
.name("keyeditor.clearall"));
p.setItemEditor(d);
p.makeCommandChoice();
d.center(f);
d.setVisible(true);
if (d.isAborted())
return;
Global.removeAllParameters("key.");
V = d.getElements();
Enumeration e = V.elements();
while (e.hasMoreElements()) {
final KeyboardItem k = (KeyboardItem) e.nextElement();
if (!k.getCharKey().equals("default")) {
final String keytag = "key." + k.getMenuString();
final String description = k.keyDescription();
if (!Global.name(keytag).toLowerCase().equals(description)) {
Global.setParameter(keytag, description);
}
}
}
makeKeys();
if (d.getAction() == ItemEditor.SAVE) {
final Properties parameters = new Properties();
e = Global.properties();
while (e.hasMoreElements()) {
final String key = (String) e.nextElement();
if (key.startsWith("key."))
parameters.put(key, Global.getParameter(key, "default"));
}
final MyFileDialog save = new MyFileDialog(f, Global.name("save"),
Global.name("save"), true);
save.setPattern("*.keys");
save.center(f);
save.update();
save.setVisible(true);
if (save.isAborted())
return;
final String filename = save.getFilePath();
if (filename.equals(""))
return; // aborted dialog!
try {
final FileOutputStream o = new FileOutputStream(filename);
parameters.store(o, "JE Keyboard Definition");
// parameters.save(o,"JE Keyboard Definition");
} catch (final Exception ex) {
}
} else if (d.getAction() == ItemEditor.LOAD) {
final Properties parameters = new Properties();
final MyFileDialog load = new MyFileDialog(f, Global.name("load"),
Global.name("load"), true);
load.setPattern("*.keys");
load.center(f);
load.update();
load.setVisible(true);
if (load.isAborted())
return;
final String filename = load.getFilePath();
if (filename.equals(""))
return; // aborted dialog!
try {
final FileInputStream in = new FileInputStream(filename);
parameters.load(in);
} catch (final Exception ex) {
}
Global.removeAllParameters("key.");
e = parameters.keys();
while (e.hasMoreElements()) {
final String key = (String) e.nextElement();
Global.setParameter(key, (String) parameters.get(key));
}
makeKeys();
}
}
/**
* Append a list of keyboard shortcuts to a text area.
*/
public static Vector getKeys() {
final Vector keys = new Vector();
Sorter.sort(V);
final Enumeration e = V.elements();
while (e.hasMoreElements()) {
final KeyboardItem k = (KeyboardItem) e.nextElement();
if (!k.getCharKey().equals("none")) {
String shortcut = k.shortcut();
final int n = shortcut.length();
for (int i = 0; i < 30 - n; i++)
shortcut = shortcut + " ";
keys.addElement(shortcut + " = " + k.getActionName());
}
}
return keys;
}
/**
* Find a shortcut for the command.
*/
public static String commandShortcut(final int type) {
final Object o = Hmenu.get("command." + type);
if (o == null)
return "";
return ((KeyboardItem) o).shortcut();
}
}