📄 keybindingmanager.java
字号:
/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: KeyBindingManager.java * * Copyright (c) 2003 Sun Microsystems and Static Free Software * * Electric(tm) 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 3 of the License, or * (at your option) any later version. * * Electric(tm) 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 Electric(tm); see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, Mass 02111-1307, USA. */package com.sun.electric.tool.user;import com.sun.electric.tool.user.ui.KeyBindings;import com.sun.electric.tool.user.ui.KeyStrokePair;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.InputEvent;import java.awt.event.KeyEvent;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import java.util.prefs.Preferences;import javax.swing.AbstractAction;import javax.swing.ActionMap;import javax.swing.InputMap;import javax.swing.KeyStroke;/** * The KeyBindingManager manages key bindings and their associated actions. It * implements a <code>KeyListener</code> so it can be added as a key listener * to any component. * <p><p> * The <i>inputMap</i> uses <code>KeyStrokes</code> as it's keys, and stores Objects * of type Set. The Set contains Strings and the set will guarantee they are not repetead. * <p> * Each String is then used as a key into the HashMap <i>actionMap</i> to retrieve * a KeyBindings object. Each key bindings object has a list of actions which can then be * performed. * <p> * This model is similar to jawa.swing.InputMap and java.swing.ActionMap. * However, secondary InputMaps allow two-stroke key bindings. Additionally, * the KeybindingManager has been enveloped in an object which can * then be inserted into the event hierarchy in different ways, instead of having * to set a Component's InputMap and ActionMap. * <p><p> * Two-stroke bindings:<p> * The KeyBindingManager has a HashMap <i>prefixedInputMapMaps</i>. A prefixStroke * is used as a key to this table to obtain an inputMap (HashMap) based on the prefixStroke. * From here it is the same as before with the inputMap and actionMap: * A KeyStroke is then used as a key to find a List of Strings. The Strings are * then used as a key into <i>actionMap</i> to get a KeyBindings object and * perform the associated action. There is only one actionMap. * <p> * * @author gainsley */public class KeyBindingManager { // ----------------------------- object stuff --------------------------------- /** Hash table of lists all key bindings */ private Map<KeyStroke,Set<String>> inputMap; /** Hash table of all actions */ private Map<String,Object> actionMap; /** last prefix key pressed */ private KeyStroke lastPrefix; /** Hash table of hash of lists of prefixed key bindings */ private Map<KeyStroke,Map<KeyStroke,Set<String>>> prefixedInputMapMaps; /** action to take on prefix key hit */ private PrefixAction prefixAction; /** where to store Preferences */ private Preferences prefs; /** prefix on pref key, if desired */ private String prefPrefix; // ----------------------------- global stuff ---------------------------------- /** Listener to register for catching keys */ //public static KeyBindingListener listener = new KeyBindingListener(); /** All key binding manangers */ private static List<KeyBindingManager> allManagers = new ArrayList<KeyBindingManager>(); /** debug preference saving */ private static final boolean debugPrefs = false; /** debug key bindings */ private static final boolean DEBUG = false; /** * Construct a new KeyBindingManager that can act as a KeyListener * on a Component. */ public KeyBindingManager(String prefPrefix, Preferences prefs) { inputMap = new HashMap<KeyStroke,Set<String>>(); actionMap = new HashMap<String,Object>(); prefixedInputMapMaps = new HashMap<KeyStroke,Map<KeyStroke,Set<String>>>(); lastPrefix = null; prefixAction = new PrefixAction(this); this.prefs = prefs; this.prefPrefix = prefPrefix; // add prefix action to action map actionMap.put(PrefixAction.actionDesc, prefixAction); // register this with KeyboardFocusManager // so we receive all KeyEvents //KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this); //KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventPostProcessor(this); // add to list of all managers synchronized(allManagers) { allManagers.add(this); } initialize(); } /** * Called when disposing of this manager, allows memory used to * be reclaimed by removing static references to this. */ public void finished() { synchronized(allManagers) { allManagers.remove(this); } //KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventPostProcessor(this); } private boolean initialized = false; /** * Initialize: Reads all stored key bindings from preferences */ private synchronized void initialize() {/* String [] allKeys; try { allKeys = prefs.keys(); } catch (BackingStoreException e) { e.printStackTrace(); return; } for (int i = 0; i < allKeys.length; i++) { // read bindings String key = allKeys[i].replaceFirst(prefPrefix, ""); // old binding format and new format conflict, add check to avoid duplicates if (actionMap.containsKey(key)) continue; if (debugPrefs) System.out.println("looking for prefs key "+key); KeyBindings keys = new KeyBindings(key); List pairs = getBindingsFromPrefs(key); // if any bindings, set usingDefaults false, and add them if (pairs != null) { keys.setUsingDefaultKeys(false); // set usingDefaults false actionMap.put(key, keys); for (Iterator it = pairs.iterator(); it.hasNext(); ) { KeyStrokePair pair = (KeyStrokePair)it.next(); if (pair == null) continue; addKeyBinding(key, pair); } } }*/ } private static class KeyBindingColumn { int hits = 0; // how many key bindings use this modifier int maxLength = 0; String name; KeyBindingColumn(String n) { name = n; } public String toString() { return name; } public String getHeader() { String n = name; for (int l = name.length(); l < maxLength; l++) n += " "; return n + " | "; } public String getColumn(Object value) { String column = ""; int fillStart = 0; if (value != null) { String n = value.toString(); fillStart = n.length(); column += n; } // filling for (int l = fillStart; l < maxLength; l++) column +=" "; return column + " | "; } public void addHit(Set<String> set) { hits++; int len = set.toString().length(); if (len > maxLength) maxLength = len; } public boolean equals(Object obj) { String key = obj.toString(); boolean found = key.equals(name); return found; } } private static class KeyBindingColumnSort implements Comparator<KeyBindingColumn> { public int compare(KeyBindingColumn s1, KeyBindingColumn s2) { int bb1 = s1.hits; int bb2 = s2.hits; if (bb1 < bb2) return 1; // sorting from max to min else if (bb1 > bb2) return -1; return (0); // identical } } /** Method to print existing KeyStrokes in std output for help */ public void printKeyBindings() { Map<String,Map<String,Set<String>>> set = new HashMap<String,Map<String,Set<String>>>(); List<String> keyList = new ArrayList<String>(); // has to be a list so it could be sorted. List<KeyBindingColumn> columnList = new ArrayList<KeyBindingColumn>(); // has to be a list so it could be sorted. KeyBindingColumn row = new KeyBindingColumn("Keys"); Set<String> tmpSet = new HashSet<String>(); columnList.add(row); // inserting the first row with key names as column for (Map.Entry<KeyStroke,Set<String>> map : inputMap.entrySet()) { KeyStroke keyS = map.getKey(); String key = KeyStrokePair.getStringFromKeyStroke(keyS); Map<String,Set<String>> m = set.get(key); if (m == null) { m = new HashMap<String,Set<String>>(); set.put(key, m); keyList.add(key); tmpSet.clear(); tmpSet.add(key); row.addHit(tmpSet); } String modifier = KeyEvent.getKeyModifiersText(keyS.getModifiers()); KeyBindingColumn newCol = new KeyBindingColumn(modifier); int index = columnList.indexOf(newCol); KeyBindingColumn col = (index > -1) ? columnList.get(index) : null; if (col == null) { col = newCol; columnList.add(col); } col.addHit(map.getValue()); m.put(modifier, map.getValue()); } Collections.sort(keyList); Collections.sort(columnList, new KeyBindingColumnSort()); // Header String headerLine = "\n"; for (KeyBindingColumn column : columnList) { String header = column.getHeader(); System.out.print(header); for (int i = 0; i < header.length(); i++) headerLine += "-"; } System.out.println(headerLine); for (String key : keyList) {// System.out.print(key); for (KeyBindingColumn column : columnList) { Object value = (column == row) ? key : (Object)set.get(key).get(column.name); System.out.print(column.getColumn(value)); } System.out.println(); } } // ---------------------------- Prefix Action Class ----------------------------- /** * Class PrefixAction is an action performed when a prefix key is hit. * This then registers that prefix key with the KeyBindingManager. * This allows key bindings to consist of two-key sequences. */ private static class PrefixAction extends AbstractAction { /** The action description analagous to KeyBinding */ public static final String actionDesc = "KeyBindingManager prefix action"; /** the key binding manager using this aciton */ private KeyBindingManager manager; public PrefixAction(KeyBindingManager manager) { super(); this.manager = manager; } public void actionPerformed(ActionEvent e) { KeyEvent keyEvent = (KeyEvent)e.getSource(); KeyStroke stroke = KeyStroke.getKeyStrokeForEvent(keyEvent); manager.setPrefixKey(stroke); if (DEBUG) System.out.println("prefix key '"+KeyStrokePair.keyStrokeToString(stroke)+"' hit..."); } } /** * Called by the KeyBindingManager's prefixAction to register * that a prefix key has been hit. * @param prefix the prefix key */ private synchronized void setPrefixKey(KeyStroke prefix) { this.lastPrefix = prefix; } // ------------------------------ Key Processing ---------------------------------/* public static class KeyBindingListener implements KeyListener { public void keyPressed(KeyEvent e) { for (Iterator it = allManagers.iterator(); it.hasNext(); ) { KeyBindingManager m = (KeyBindingManager)it.next(); if (m.processKeyEvent(e)) return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -