Index: Eclipse UI/org/eclipse/ui/internal/Workbench.java
===================================================================
RCS file: /home/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java,v
retrieving revision 1.102
diff -u -r1.102 Workbench.java
--- Eclipse UI/org/eclipse/ui/internal/Workbench.java 23 Sep 2003 03:07:16 -0000 1.102
+++ Eclipse UI/org/eclipse/ui/internal/Workbench.java 23 Sep 2003 20:25:49 -0000
@@ -208,12 +208,13 @@
if (shell.getParent() != null)
return;
}
+
+ KeyStroke[] keyStrokes = new KeyStroke[3];
+ keyStrokes[0] = KeySupport.convertAcceleratorToKeyStroke(KeySupport.convertEventToUnmodifiedAccelerator(event));
+ keyStrokes[1] = KeySupport.convertAcceleratorToKeyStroke(KeySupport.convertEventToUnshiftedModifiedAccelerator(event));
+ keyStrokes[2] = KeySupport.convertAcceleratorToKeyStroke(KeySupport.convertEventToModifiedAccelerator(event));
- KeyStroke keyStroke =
- KeySupport.convertAcceleratorToKeyStroke(
- KeySupport.convertEventToAccelerator(event));
-
- if (press(keyStroke, event)) {
+ if (press(keyStrokes, event)) {
switch (event.type) {
case SWT.KeyDown :
event.doit = false;
@@ -413,69 +414,87 @@
return true;
}
- // TODO move this method to CommandManager once getMode() is added to ICommandManager (and triggers and change event)
- // TODO remove event parameter once key-modified actions are removed
- public final boolean press(KeyStroke keyStroke, Event event) {
- final KeySequence modeBeforeKeyStroke = commandManager.getMode();
- final List keyStrokes =
- new ArrayList(modeBeforeKeyStroke.getKeyStrokes());
- keyStrokes.add(keyStroke);
- final KeySequence modeAfterKeyStroke =
- KeySequence.getInstance(keyStrokes);
- final Map matchesByKeySequenceForModeBeforeKeyStroke =
- commandManager.getMatchesByKeySequenceForMode();
- commandManager.setMode(modeAfterKeyStroke);
- final Map matchesByKeySequenceForModeAfterKeyStroke =
- commandManager.getMatchesByKeySequenceForMode();
- boolean consumeKeyStroke = false;
-
- if (!matchesByKeySequenceForModeAfterKeyStroke.isEmpty()) {
- // this key stroke is part of one or more possible completions: consume the keystroke
- updateModeLines(modeAfterKeyStroke);
- consumeKeyStroke = true;
- } else {
- // there are no possible longer multi-stroke sequences, allow a completion now if possible
- final Match match =
- (Match) matchesByKeySequenceForModeBeforeKeyStroke.get(
- modeAfterKeyStroke);
-
- if (match != null) {
- // a completion was found.
- final String commandId = match.getCommandId();
- final Map actionsById = commandManager.getActionsById();
- org.eclipse.ui.commands.IAction action =
- (org.eclipse.ui.commands.IAction) actionsById.get(
- commandId);
-
- if (action != null) {
- // an action was found corresponding to the completion
-
- if (action.isEnabled()) {
- updateModeLines(modeAfterKeyStroke);
- try {
- action.execute(event);
- } catch (final Exception e) {
- // TODO
+ /**
+ * Processes a key press with respect to the key binding architecture. This
+ * updates the mode of the command manager, and runs the current handler for
+ * the command that matches the key sequence, if any.
+ *
+ * @param potentialKeyStrokes The key strokes that could potentially match,
+ * in the order of priority; must not be null
.
+ * @param event The event to pass to the action; may be null
.
+ *
+ * @return true
if a command is executed; false
+ * otherwise.
+ */
+ public boolean press(KeyStroke[] potentialKeyStrokes, Event event) {
+ // TODO move this method to CommandManager once getMode() is added to ICommandManager (and triggers and change event)
+ // TODO remove event parameter once key-modified actions are removed
+
+ // Check every potential key stroke until one matches.
+ for (int i = 0; i < potentialKeyStrokes.length; i++) {
+ KeySequence modeBeforeKeyStroke = commandManager.getMode();
+ List keyStrokes = new ArrayList(modeBeforeKeyStroke.getKeyStrokes());
+ keyStrokes.add(potentialKeyStrokes[i]);
+ KeySequence modeAfterKeyStroke = KeySequence.getInstance(keyStrokes);
+ Map matchesByKeySequenceForModeBeforeKeyStroke = commandManager.getMatchesByKeySequenceForMode();
+ commandManager.setMode(modeAfterKeyStroke);
+ Map matchesByKeySequenceForModeAfterKeyStroke = commandManager.getMatchesByKeySequenceForMode();
+ boolean consumeKeyStroke = false;
+
+ if (!matchesByKeySequenceForModeAfterKeyStroke.isEmpty()) {
+ // this key stroke is part of one or more possible completions: consume the keystroke
+ updateModeLines(modeAfterKeyStroke);
+ consumeKeyStroke = true;
+ } else {
+ // there are no possible longer multi-stroke sequences, allow a completion now if possible
+ Match match = (Match) matchesByKeySequenceForModeBeforeKeyStroke.get(modeAfterKeyStroke);
+
+ if (match != null) {
+ // a completion was found.
+ String commandId = match.getCommandId();
+ Map actionsById = commandManager.getActionsById();
+ org.eclipse.ui.commands.IAction action = (org.eclipse.ui.commands.IAction) actionsById.get(commandId);
+
+ if (action != null) {
+ // an action was found corresponding to the completion
+
+ if (action.isEnabled()) {
+ updateModeLines(modeAfterKeyStroke);
+ try {
+ action.execute(event);
+ } catch (Exception e) {
+ // TODO
+ }
}
+
+ // consume the keystroke
+ consumeKeyStroke = true;
}
-
- // consume the keystroke
- consumeKeyStroke = true;
}
+
+ // possibly no completion was found, or no action was found corresponding to the completion, but if we were already in a mode consume the keystroke anyway.
+ if (modeBeforeKeyStroke.getKeyStrokes().size() >= 1)
+ consumeKeyStroke = true;
+
+ // clear mode
+ commandManager.setMode(KeySequence.getInstance());
+ updateModeLines(KeySequence.getInstance());
+ }
+
+ // TODO is this necessary?
+ updateActiveContextIds();
+
+ if (consumeKeyStroke) {
+ // We found a match, so stop now.
+ return consumeKeyStroke;
+ } else {
+ // Restore the mode, so we can try again.
+ commandManager.setMode(modeBeforeKeyStroke);
}
-
- // possibly no completion was found, or no action was found corresponding to the completion, but if we were already in a mode consume the keystroke anyway.
- if (modeBeforeKeyStroke.getKeyStrokes().size() >= 1)
- consumeKeyStroke = true;
-
- // clear mode
- commandManager.setMode(KeySequence.getInstance());
- updateModeLines(KeySequence.getInstance());
}
-
- // TODO is this necessary?
- updateActiveContextIds();
- return consumeKeyStroke;
+
+ // No key strokes match.
+ return false;
}
/**
Index: Eclipse UI/org/eclipse/ui/internal/keys/KeySequenceText.java
===================================================================
RCS file: /home/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeySequenceText.java,v
retrieving revision 1.12
diff -u -r1.12 KeySequenceText.java
--- Eclipse UI/org/eclipse/ui/internal/keys/KeySequenceText.java 23 Sep 2003 03:12:37 -0000 1.12
+++ Eclipse UI/org/eclipse/ui/internal/keys/KeySequenceText.java 23 Sep 2003 20:25:49 -0000
@@ -369,7 +369,7 @@
}
} else {
// Handles the key pressed event.
- final int key = KeySupport.convertEventToAccelerator(event);
+ final int key = KeySupport.convertEventToUnmodifiedAccelerator(event);
final KeyStroke stroke = KeySupport.convertAcceleratorToKeyStroke(key);
setKeySequence(getKeySequence(), stroke);
}
@@ -395,7 +395,7 @@
/* Get a reasonable facsimile of the stroke that is still
* pressed.
*/
- final int key = KeySupport.convertEventToAccelerator(mockEvent);
+ final int key = KeySupport.convertEventToUnmodifiedAccelerator(mockEvent);
final KeyStroke remainingStroke = KeySupport.convertAcceleratorToKeyStroke(key);
if (remainingStroke.getModifierKeys().isEmpty()) {
Index: Eclipse UI/org/eclipse/ui/internal/keys/KeySupport.java
===================================================================
RCS file: /home/eclipse/org.eclipse.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeySupport.java,v
retrieving revision 1.8
diff -u -r1.8 KeySupport.java
--- Eclipse UI/org/eclipse/ui/internal/keys/KeySupport.java 25 Aug 2003 22:49:27 -0000 1.8
+++ Eclipse UI/org/eclipse/ui/internal/keys/KeySupport.java 23 Sep 2003 20:25:49 -0000
@@ -28,25 +28,6 @@
public final class KeySupport {
- public static int convertEventToAccelerator(Event event) {
- int key = event.character;
-
- if (key == 0)
- key = event.keyCode;
- else {
- if (0 <= key && key <= 0x1F) {
- if ((event.stateMask & SWT.CTRL) != 0 && event.keyCode != event.character)
- key += 0x40;
- } else {
- if ('a' <= key && key <= 'z')
- key -= 'a' - 'A';
- }
- }
-
- int modifiers = event.stateMask & SWT.MODIFIER_MASK;
- return modifiers + key;
- }
-
public static KeyStroke convertAcceleratorToKeyStroke(int accelerator) {
final SortedSet modifierKeys = new TreeSet();
NaturalKey naturalKey = null;
@@ -135,6 +116,51 @@
return KeyStroke.getInstance(modifierKeys, naturalKey);
}
+
+ /**
+ * Converts the given event into an SWT accelerator value -- considering the
+ * modified character with the shift modifier. This is the third
+ * accelerator value that should be checked.
+ *
+ * @param event The event to be converted; must not be null
.
+ * @return The combination of the state mask and the unmodified character.
+ */
+ public static int convertEventToModifiedAccelerator(Event event) {
+ int modifiers = event.stateMask & SWT.MODIFIER_MASK;
+ int modifiedCharacter = topKey(event);
+ return modifiers + modifiedCharacter;
+ }
+
+ /**
+ * Converts the given event into an SWT accelerator value -- considering the
+ * unmodified character with all modifier keys. This is the first
+ * accelerator value that should be checked. However, all alphabetic
+ * characters are considered as their uppercase equivalents.
+ *
+ * @param event The event to be converted; must not be null
.
+ * @return The combination of the state mask and the unmodified character.
+ */
+ public static int convertEventToUnmodifiedAccelerator(Event event) {
+ int modifiers = event.stateMask & SWT.MODIFIER_MASK;
+ int unmodifiedCharacter = upperCase(event.keyCode);
+
+ return modifiers + unmodifiedCharacter;
+ }
+
+ /**
+ * Converts the given event into an SWT accelerator value -- considering the
+ * modified character without the shift modifier. This is the second
+ * accelerator value that should be checked.
+ *
+ * @param event The event to be converted; must not be null
.
+ * @return The combination of the state mask without shift, and the modified
+ * character.
+ */
+ public static int convertEventToUnshiftedModifiedAccelerator(Event event) {
+ int modifiers = event.stateMask & (SWT.MODIFIER_MASK ^ SWT.SHIFT);
+ int modifiedCharacter = topKey(event);
+ return modifiers + modifiedCharacter;
+ }
public static final int convertKeyStrokeToAccelerator(final KeyStroke keyStroke) {
if (keyStroke == null)
@@ -273,6 +299,43 @@
stringBuffer.append(KeyStroke.getInstance(naturalKey).format());
return stringBuffer.toString();
+ }
+
+ /**
+ * Makes sure that a fully-modified character is converted to the normal
+ * form. This means that "Ctrl+" key strokes must reverse the modification
+ * caused by control-escaping. Also, all lower case letters are converted
+ * to uppercase.
+ *
+ * @param event The event from which the fully-modified character should be
+ * pulled.
+ *
+ * @return The modified character, uppercase and without control-escaping.
+ */
+ private static int topKey(Event event) {
+ boolean ctrlDown = (event.stateMask & SWT.CTRL) != 0;
+ char modifiedCharacter;
+ if ((ctrlDown) && (event.character != event.keyCode) && (event.character < 0x20)) {
+ modifiedCharacter = (char) (event.character + 0x40);
+ } else {
+ modifiedCharacter = event.character;
+ }
+
+ return upperCase(modifiedCharacter);
+ }
+
+ /**
+ * Makes the given character uppercase if it is a letter.
+ * @param character The character to convert.
+ * @return The uppercase equivalent, if any; otherwise, the character
+ * itself.
+ */
+ private static int upperCase(int character) {
+ if (Character.isLetter((char) character)) {
+ return Character.toUpperCase((char) character);
+ }
+
+ return character;
}
private KeySupport() {