001: /*******************************************************************************
002: * Copyright (c) 2004, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jface.bindings.keys.formatting;
011:
012: import java.util.Enumeration;
013: import java.util.HashSet;
014: import java.util.ResourceBundle;
015: import java.util.Set;
016:
017: import org.eclipse.jface.bindings.keys.IKeyLookup;
018: import org.eclipse.jface.bindings.keys.KeyLookupFactory;
019: import org.eclipse.jface.bindings.keys.KeySequence;
020: import org.eclipse.jface.bindings.keys.KeyStroke;
021: import org.eclipse.jface.util.Util;
022:
023: /**
024: * <p>
025: * An abstract implementation of a key formatter that provides a lot of common
026: * key formatting functionality. It is recommended that implementations of
027: * <code>IKeyFormatter</code> subclass from here, rather than implementing
028: * <code>IKeyFormatter</code> directly.
029: * </p>
030: *
031: * @since 3.1
032: */
033: public abstract class AbstractKeyFormatter implements IKeyFormatter {
034:
035: /**
036: * The key for the delimiter between keys. This is used in the
037: * internationalization bundles.
038: */
039: protected static final String KEY_DELIMITER_KEY = "KEY_DELIMITER"; //$NON-NLS-1$
040:
041: /**
042: * The key for the delimiter between key strokes. This is used in the
043: * internationalization bundles.
044: */
045: protected static final String KEY_STROKE_DELIMITER_KEY = "KEY_STROKE_DELIMITER"; //$NON-NLS-1$
046:
047: /**
048: * An empty integer array that can be used in
049: * <code>sortModifierKeys(int)</code>.
050: */
051: protected static final int[] NO_MODIFIER_KEYS = new int[0];
052:
053: /**
054: * The bundle in which to look up the internationalized text for all of the
055: * individual keys in the system. This is the platform-agnostic version of
056: * the internationalized strings. Some platforms (namely Carbon) provide
057: * special Unicode characters and glyphs for some keys.
058: */
059: private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
060: .getBundle(AbstractKeyFormatter.class.getName());
061:
062: /**
063: * The keys in the resource bundle. This is used to avoid missing resource
064: * exceptions when they aren't necessary.
065: */
066: private static final Set resourceBundleKeys = new HashSet();
067:
068: static {
069: final Enumeration keyEnumeration = RESOURCE_BUNDLE.getKeys();
070: while (keyEnumeration.hasMoreElements()) {
071: final Object element = keyEnumeration.nextElement();
072: resourceBundleKeys.add(element);
073: }
074: }
075:
076: /*
077: * (non-Javadoc)
078: *
079: * @see org.eclipse.jface.bindings.keysKeyFormatter#format(org.eclipse.jface.bindings.keys.KeySequence)
080: */
081: public String format(final int key) {
082: final IKeyLookup lookup = KeyLookupFactory.getDefault();
083: final String name = lookup.formalNameLookup(key);
084:
085: if (resourceBundleKeys.contains(name)) {
086: return Util.translateString(RESOURCE_BUNDLE, name, name);
087: }
088:
089: return name;
090: }
091:
092: /*
093: * (non-Javadoc)
094: *
095: * @see org.eclipse.jface.bindings.keys.KeyFormatter#format(org.eclipse.jface.bindings.keys.KeySequence)
096: */
097: public String format(KeySequence keySequence) {
098: StringBuffer stringBuffer = new StringBuffer();
099:
100: final KeyStroke[] keyStrokes = keySequence.getKeyStrokes();
101: final int keyStrokesLength = keyStrokes.length;
102: for (int i = 0; i < keyStrokesLength; i++) {
103: stringBuffer.append(format(keyStrokes[i]));
104:
105: if (i + 1 < keyStrokesLength) {
106: stringBuffer.append(getKeyStrokeDelimiter());
107: }
108: }
109:
110: return stringBuffer.toString();
111: }
112:
113: /*
114: * (non-Javadoc)
115: *
116: * @see org.eclipse.jface.bindings.keys.KeyFormatter#formatKeyStroke(org.eclipse.jface.bindings.keys.KeyStroke)
117: */
118: public String format(final KeyStroke keyStroke) {
119: final String keyDelimiter = getKeyDelimiter();
120:
121: // Format the modifier keys, in sorted order.
122: final int modifierKeys = keyStroke.getModifierKeys();
123: final int[] sortedModifierKeys = sortModifierKeys(modifierKeys);
124: final StringBuffer stringBuffer = new StringBuffer();
125: if (sortedModifierKeys != null) {
126: for (int i = 0; i < sortedModifierKeys.length; i++) {
127: final int modifierKey = sortedModifierKeys[i];
128: if (modifierKey != KeyStroke.NO_KEY) {
129: stringBuffer.append(format(modifierKey));
130: stringBuffer.append(keyDelimiter);
131: }
132: }
133: }
134:
135: // Format the natural key, if any.
136: final int naturalKey = keyStroke.getNaturalKey();
137: if (naturalKey != 0) {
138: stringBuffer.append(format(naturalKey));
139: }
140:
141: return stringBuffer.toString();
142:
143: }
144:
145: /**
146: * An accessor for the delimiter you wish to use between keys. This is used
147: * by the default format implementations to determine the key delimiter.
148: *
149: * @return The delimiter to use between keys; should not be
150: * <code>null</code>.
151: */
152: protected abstract String getKeyDelimiter();
153:
154: /**
155: * An accessor for the delimiter you wish to use between key strokes. This
156: * used by the default format implementations to determine the key stroke
157: * delimiter.
158: *
159: * @return The delimiter to use between key strokes; should not be
160: * <code>null</code>.
161: */
162: protected abstract String getKeyStrokeDelimiter();
163:
164: /**
165: * Separates the modifier keys from each other, and then places them in an
166: * array in some sorted order. The sort order is dependent on the type of
167: * formatter.
168: *
169: * @param modifierKeys
170: * The modifier keys from the key stroke.
171: * @return An array of modifier key values -- separated and sorted in some
172: * order. Any values in this array that are
173: * <code>KeyStroke.NO_KEY</code> should be ignored.
174: */
175: protected abstract int[] sortModifierKeys(final int modifierKeys);
176: }
|