View | Details | Raw Unified | Return to bug 42035 | Differences between
and this patch

Collapse All | Expand All

(-)Eclipse UI/org/eclipse/ui/internal/Workbench.java (-63 / +82 lines)
Lines 208-219 Link Here
208
				if (shell.getParent() != null)
208
				if (shell.getParent() != null)
209
					return;
209
					return;
210
			}
210
			}
211
			
212
			KeyStroke[] keyStrokes = new KeyStroke[3];
213
			keyStrokes[0] = KeySupport.convertAcceleratorToKeyStroke(KeySupport.convertEventToUnmodifiedAccelerator(event));
214
			keyStrokes[1] = KeySupport.convertAcceleratorToKeyStroke(KeySupport.convertEventToUnshiftedModifiedAccelerator(event));
215
			keyStrokes[2] = KeySupport.convertAcceleratorToKeyStroke(KeySupport.convertEventToModifiedAccelerator(event));
211
216
212
			KeyStroke keyStroke =
217
			if (press(keyStrokes, event)) {
213
				KeySupport.convertAcceleratorToKeyStroke(
214
					KeySupport.convertEventToAccelerator(event));
215
216
			if (press(keyStroke, event)) {
217
				switch (event.type) {
218
				switch (event.type) {
218
					case SWT.KeyDown :
219
					case SWT.KeyDown :
219
						event.doit = false;
220
						event.doit = false;
Lines 413-481 Link Here
413
		return true;
414
		return true;
414
	}
415
	}
415
416
416
	// TODO move this method to CommandManager once getMode() is added to ICommandManager (and triggers and change event)
417
	/**
417
	// TODO remove event parameter once key-modified actions are removed
418
	 * Processes a key press with respect to the key binding architecture.  This
418
	public final boolean press(KeyStroke keyStroke, Event event) {
419
	 * updates the mode of the command manager, and runs the current handler for
419
		final KeySequence modeBeforeKeyStroke = commandManager.getMode();
420
	 * the command that matches the key sequence, if any.
420
		final List keyStrokes =
421
	 * 
421
			new ArrayList(modeBeforeKeyStroke.getKeyStrokes());
422
	 * @param potentialKeyStrokes The key strokes that could potentially match,
422
		keyStrokes.add(keyStroke);
423
	 * in the order of priority; must not be <code>null</code>.
423
		final KeySequence modeAfterKeyStroke =
424
	 * @param event The event to pass to the action; may be <code>null</code>.
424
			KeySequence.getInstance(keyStrokes);
425
	 * 
425
		final Map matchesByKeySequenceForModeBeforeKeyStroke =
426
	 * @return <code>true</code> if a command is executed; <code>false</code>
426
			commandManager.getMatchesByKeySequenceForMode();
427
	 * otherwise.
427
		commandManager.setMode(modeAfterKeyStroke);
428
	 */
428
		final Map matchesByKeySequenceForModeAfterKeyStroke =
429
	public boolean press(KeyStroke[] potentialKeyStrokes, Event event) {
429
			commandManager.getMatchesByKeySequenceForMode();
430
		// TODO move this method to CommandManager once getMode() is added to ICommandManager (and triggers and change event)
430
		boolean consumeKeyStroke = false;
431
		// TODO remove event parameter once key-modified actions are removed
431
432
		
432
		if (!matchesByKeySequenceForModeAfterKeyStroke.isEmpty()) {
433
		// Check every potential key stroke until one matches.
433
			// this key stroke is part of one or more possible completions: consume the keystroke
434
		for (int i = 0; i < potentialKeyStrokes.length; i++) {
434
			updateModeLines(modeAfterKeyStroke);
435
			KeySequence modeBeforeKeyStroke = commandManager.getMode();
435
			consumeKeyStroke = true;
436
			List keyStrokes = new ArrayList(modeBeforeKeyStroke.getKeyStrokes());
436
		} else {
437
			keyStrokes.add(potentialKeyStrokes[i]);
437
			// there are no possible longer multi-stroke sequences, allow a completion now if possible
438
			KeySequence modeAfterKeyStroke = KeySequence.getInstance(keyStrokes);
438
			final Match match =
439
			Map matchesByKeySequenceForModeBeforeKeyStroke = commandManager.getMatchesByKeySequenceForMode();
439
				(Match) matchesByKeySequenceForModeBeforeKeyStroke.get(
440
			commandManager.setMode(modeAfterKeyStroke);
440
					modeAfterKeyStroke);
441
			Map matchesByKeySequenceForModeAfterKeyStroke = commandManager.getMatchesByKeySequenceForMode();
441
442
			boolean consumeKeyStroke = false;
442
			if (match != null) {
443
443
				// a completion was found. 
444
			if (!matchesByKeySequenceForModeAfterKeyStroke.isEmpty()) {
444
				final String commandId = match.getCommandId();
445
				// this key stroke is part of one or more possible completions: consume the keystroke
445
				final Map actionsById = commandManager.getActionsById();
446
				updateModeLines(modeAfterKeyStroke);
446
				org.eclipse.ui.commands.IAction action =
447
				consumeKeyStroke = true;
447
					(org.eclipse.ui.commands.IAction) actionsById.get(
448
			} else {
448
						commandId);
449
				// there are no possible longer multi-stroke sequences, allow a completion now if possible
449
450
				Match match = (Match) matchesByKeySequenceForModeBeforeKeyStroke.get(modeAfterKeyStroke);
450
				if (action != null) {
451
451
					// an action was found corresponding to the completion
452
				if (match != null) {
452
453
					// a completion was found. 
453
					if (action.isEnabled()) {
454
					String commandId = match.getCommandId();
454
						updateModeLines(modeAfterKeyStroke);
455
					Map actionsById = commandManager.getActionsById();
455
						try {
456
					org.eclipse.ui.commands.IAction action = (org.eclipse.ui.commands.IAction) actionsById.get(commandId);
456
							action.execute(event);
457
457
						} catch (final Exception e) {
458
					if (action != null) {
458
							// TODO 						
459
						// an action was found corresponding to the completion
460
461
						if (action.isEnabled()) {
462
							updateModeLines(modeAfterKeyStroke);
463
							try {
464
								action.execute(event);
465
							} catch (Exception e) {
466
								// TODO 						
467
							}
459
						}
468
						}
469
	
470
						// consume the keystroke
471
						consumeKeyStroke = true;
460
					}
472
					}
461
462
					// consume the keystroke
463
					consumeKeyStroke = true;
464
				}
473
				}
474
	
475
				// 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.									
476
				if (modeBeforeKeyStroke.getKeyStrokes().size() >= 1)
477
					consumeKeyStroke = true;
478
	
479
				// clear mode			
480
				commandManager.setMode(KeySequence.getInstance());
481
				updateModeLines(KeySequence.getInstance());
482
			}
483
	
484
			// TODO is this necessary?		
485
			updateActiveContextIds();
486
			
487
			if (consumeKeyStroke) {
488
				// We found a match, so stop now.
489
				return consumeKeyStroke;
490
			} else {
491
				// Restore the mode, so we can try again.
492
				commandManager.setMode(modeBeforeKeyStroke);
465
			}
493
			}
466
467
			// 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.									
468
			if (modeBeforeKeyStroke.getKeyStrokes().size() >= 1)
469
				consumeKeyStroke = true;
470
471
			// clear mode			
472
			commandManager.setMode(KeySequence.getInstance());
473
			updateModeLines(KeySequence.getInstance());
474
		}
494
		}
475
495
		
476
		// TODO is this necessary?		
496
		// No key strokes match.
477
		updateActiveContextIds();
497
		return false;
478
		return consumeKeyStroke;
479
	}	
498
	}	
480
	
499
	
481
	/**
500
	/**
(-)Eclipse UI/org/eclipse/ui/internal/keys/KeySequenceText.java (-2 / +2 lines)
Lines 369-375 Link Here
369
					}
369
					}
370
				} else {
370
				} else {
371
					// Handles the key pressed event.
371
					// Handles the key pressed event.
372
					final int key = KeySupport.convertEventToAccelerator(event);
372
					final int key = KeySupport.convertEventToUnmodifiedAccelerator(event);
373
					final KeyStroke stroke = KeySupport.convertAcceleratorToKeyStroke(key);
373
					final KeyStroke stroke = KeySupport.convertAcceleratorToKeyStroke(key);
374
					setKeySequence(getKeySequence(), stroke);
374
					setKeySequence(getKeySequence(), stroke);
375
				}
375
				}
Lines 395-401 Link Here
395
				/* Get a reasonable facsimile of the stroke that is still
395
				/* Get a reasonable facsimile of the stroke that is still
396
				 * pressed.
396
				 * pressed.
397
				 */
397
				 */
398
				final int key = KeySupport.convertEventToAccelerator(mockEvent);
398
				final int key = KeySupport.convertEventToUnmodifiedAccelerator(mockEvent);
399
				final KeyStroke remainingStroke = KeySupport.convertAcceleratorToKeyStroke(key);
399
				final KeyStroke remainingStroke = KeySupport.convertAcceleratorToKeyStroke(key);
400
400
401
				if (remainingStroke.getModifierKeys().isEmpty()) {
401
				if (remainingStroke.getModifierKeys().isEmpty()) {
(-)Eclipse UI/org/eclipse/ui/internal/keys/KeySupport.java (-19 / +82 lines)
Lines 28-52 Link Here
28
28
29
public final class KeySupport {
29
public final class KeySupport {
30
30
31
	public static int convertEventToAccelerator(Event event) {
32
		int key = event.character;
33
34
		if (key == 0)
35
			key = event.keyCode;
36
		else {
37
			if (0 <= key && key <= 0x1F) {
38
				if ((event.stateMask & SWT.CTRL) != 0 && event.keyCode != event.character)
39
					key += 0x40;
40
			} else {
41
				if ('a' <= key && key <= 'z')
42
					key -= 'a' - 'A';
43
			}
44
		}
45
46
		int modifiers = event.stateMask & SWT.MODIFIER_MASK;
47
		return modifiers + key;
48
	}
49
50
	public static KeyStroke convertAcceleratorToKeyStroke(int accelerator) {
31
	public static KeyStroke convertAcceleratorToKeyStroke(int accelerator) {
51
		final SortedSet modifierKeys = new TreeSet();
32
		final SortedSet modifierKeys = new TreeSet();
52
		NaturalKey naturalKey = null;
33
		NaturalKey naturalKey = null;
Lines 135-140 Link Here
135
116
136
		return KeyStroke.getInstance(modifierKeys, naturalKey);
117
		return KeyStroke.getInstance(modifierKeys, naturalKey);
137
	}
118
	}
119
	
120
	/**
121
	 * Converts the given event into an SWT accelerator value -- considering the
122
	 * modified character with the shift modifier.  This is the third
123
	 * accelerator value that should be checked.
124
	 * 
125
	 * @param event The event to be converted; must not be <code>null</code>.
126
	 * @return The combination of the state mask and the unmodified character.
127
	 */
128
	public static int convertEventToModifiedAccelerator(Event event) {
129
		int modifiers = event.stateMask & SWT.MODIFIER_MASK;
130
		int modifiedCharacter = topKey(event);
131
		return modifiers + modifiedCharacter;
132
	}
133
	
134
	/**
135
	 * Converts the given event into an SWT accelerator value -- considering the
136
	 * unmodified character with all modifier keys.  This is the first 
137
	 * accelerator value that should be checked.  However, all alphabetic 
138
	 * characters are considered as their uppercase equivalents.
139
	 *  
140
	 * @param event The event to be converted; must not be <code>null</code>.
141
	 * @return The combination of the state mask and the unmodified character.
142
	 */
143
	public static int convertEventToUnmodifiedAccelerator(Event event) {
144
		int modifiers = event.stateMask & SWT.MODIFIER_MASK;
145
		int unmodifiedCharacter = upperCase(event.keyCode); 
146
		
147
		return modifiers + unmodifiedCharacter;
148
	}
149
	
150
	/**
151
	 * Converts the given event into an SWT accelerator value -- considering the
152
	 * modified character without the shift modifier.  This is the second
153
	 * accelerator value that should be checked.
154
	 * 
155
	 * @param event The event to be converted; must not be <code>null</code>.
156
	 * @return The combination of the state mask without shift, and the modified
157
	 * character.
158
	 */
159
	public static int convertEventToUnshiftedModifiedAccelerator(Event event) {
160
		int modifiers = event.stateMask & (SWT.MODIFIER_MASK ^ SWT.SHIFT);
161
		int modifiedCharacter = topKey(event);
162
		return modifiers + modifiedCharacter;
163
	}
138
164
139
	public static final int convertKeyStrokeToAccelerator(final KeyStroke keyStroke) {
165
	public static final int convertKeyStrokeToAccelerator(final KeyStroke keyStroke) {
140
		if (keyStroke == null)
166
		if (keyStroke == null)
Lines 273-278 Link Here
273
			stringBuffer.append(KeyStroke.getInstance(naturalKey).format());
299
			stringBuffer.append(KeyStroke.getInstance(naturalKey).format());
274
					
300
					
275
		return stringBuffer.toString();
301
		return stringBuffer.toString();
302
	}
303
	
304
	/**
305
	 * Makes sure that a fully-modified character is converted to the normal
306
	 * form.  This means that "Ctrl+" key strokes must reverse the modification
307
	 * caused by control-escaping.  Also, all lower case letters are converted
308
	 * to uppercase.
309
	 * 
310
	 * @param event The event from which the fully-modified character should be
311
	 * pulled.
312
	 * 
313
	 * @return The modified character, uppercase and without control-escaping.
314
	 */
315
	private static int topKey(Event event) {
316
		boolean ctrlDown = (event.stateMask & SWT.CTRL) != 0;
317
		char modifiedCharacter;
318
		if ((ctrlDown) && (event.character != event.keyCode) && (event.character < 0x20)) {
319
			modifiedCharacter = (char) (event.character + 0x40);
320
		} else {
321
			modifiedCharacter = event.character;
322
		}
323
		
324
		return upperCase(modifiedCharacter);
325
	}
326
	
327
	/**
328
	 * Makes the given character uppercase if it is a letter.
329
	 * @param character The character to convert.
330
	 * @return The uppercase equivalent, if any; otherwise, the character
331
	 * itself.
332
	 */
333
	private static int upperCase(int character) {
334
		if (Character.isLetter((char) character)) {
335
			return Character.toUpperCase((char) character);
336
		}
337
		
338
		return character;
276
	}
339
	}
277
340
278
	private KeySupport() {
341
	private KeySupport() {

Return to bug 42035