diff options
author | Ralf Sternberg | 2011-01-27 17:35:54 +0000 |
---|---|---|
committer | Ralf Sternberg | 2011-01-27 17:35:54 +0000 |
commit | e0a5784a90f93ebd6370976948cdef5e079a729b (patch) | |
tree | 5c67141256c7d4228b6adf78cd6d525c065ade1d /bundles | |
parent | 4eb80bbe3926e94c21592d4891ef2e8b95119c68 (diff) | |
download | org.eclipse.rap-e0a5784a90f93ebd6370976948cdef5e079a729b.tar.gz org.eclipse.rap-e0a5784a90f93ebd6370976948cdef5e079a729b.tar.xz org.eclipse.rap-e0a5784a90f93ebd6370976948cdef5e079a729b.zip |
Fixed bug 282449: Keybindings in RAP
https://bugs.eclipse.org/bugs/show_bug.cgi?id=282449
Diffstat (limited to 'bundles')
15 files changed, 4444 insertions, 3858 deletions
diff --git a/bundles/org.eclipse.rap.jface/src/org/eclipse/jface/bindings/BindingManager.java b/bundles/org.eclipse.rap.jface/src/org/eclipse/jface/bindings/BindingManager.java index dfaf5dbe15..4363cf13b0 100755 --- a/bundles/org.eclipse.rap.jface/src/org/eclipse/jface/bindings/BindingManager.java +++ b/bundles/org.eclipse.rap.jface/src/org/eclipse/jface/bindings/BindingManager.java @@ -39,11 +39,14 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.bindings.keys.IKeyLookup; +import org.eclipse.jface.bindings.keys.KeyBinding; import org.eclipse.jface.bindings.keys.KeyLookupFactory; +import org.eclipse.jface.bindings.keys.KeySequence; import org.eclipse.jface.bindings.keys.KeyStroke; import org.eclipse.jface.contexts.IContextIds; import org.eclipse.jface.util.Policy; import org.eclipse.jface.util.Util; +import org.eclipse.swt.internal.widgets.displaykit.KeyBindingUtil; /** * <p> @@ -60,7 +63,7 @@ import org.eclipse.jface.util.Util; * though it might get faster. Where possible, we have also tried to be memory * efficient. * </p> - * + * * @since 1.4 */ public final class BindingManager extends HandleObjectManager implements @@ -93,7 +96,7 @@ public final class BindingManager extends HandleObjectManager implements * If no such entry exists, then a collection is created, and the value * added to the collection. * </p> - * + * * @param map * The map to modify; if this value is <code>null</code>, then * this method simply returns. @@ -128,7 +131,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method runs in linear time (O(n)) over the length of the string. * </p> - * + * * @param string * The string to break apart into its less specific components; * should not be <code>null</code>. @@ -182,7 +185,7 @@ public final class BindingManager extends HandleObjectManager implements * Otherwise, this value may be empty. */ private Map activeBindingsByParameterizedCommand = null; - + private Set triggerConflicts = new HashSet(); /** @@ -282,7 +285,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method completes in amortized constant time (O(1)). * </p> - * + * * @param contextManager * The context manager that will support this binding manager. * This value must not be <code>null</code>. @@ -316,7 +319,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method completes in amortized <code>O(1)</code>. * </p> - * + * * @param binding * The binding to be added; must not be <code>null</code>. */ @@ -345,7 +348,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method completes in amortized constant time (<code>O(1)</code>). * </p> - * + * * @param listener * The listener to attach; must not be <code>null</code>. */ @@ -363,7 +366,7 @@ public final class BindingManager extends HandleObjectManager implements * length of the trigger sequences and <code>n</code> is the number of * bindings. * </p> - * + * * @param activeBindings * The map of triggers (<code>TriggerSequence</code>) to * command ids (<code>String</code>) which are currently @@ -446,7 +449,7 @@ public final class BindingManager extends HandleObjectManager implements * Compares the identifier of two schemes, and decides which scheme is the * youngest (i.e., the child) of the two. Both schemes should be active * schemes. - * + * * @param schemeId1 * The identifier of the first scheme; must not be * <code>null</code>. @@ -489,7 +492,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the number of bindings. * </p> - * + * * @param activeContextTree * The map representing the tree of active contexts. The map is * one of child to parent, each being a context id ( @@ -511,7 +514,7 @@ public final class BindingManager extends HandleObjectManager implements * computed). */ private final void computeBindings(final Map activeContextTree, - final Map bindingsByTrigger, final Map triggersByCommandId, + final Map bindingsByTrigger, final Map triggersByCommandId, final Map conflictsByTrigger) { /* * FIRST PASS: Remove all of the bindings that are marking deletions. @@ -694,7 +697,7 @@ public final class BindingManager extends HandleObjectManager implements * there is one natural key per trigger. The strokes are counted based on * the type of key. Natural keys are worth one; ctrl is worth two; shift is * worth four; and alt is worth eight. - * + * * @param triggers * The triggers on which to count strokes; must not be * <code>null</code>. @@ -738,7 +741,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the height of the context tree. * </p> - * + * * @param contextIds * The set of context identifiers to be converted into a tree; * must not be <code>null</code>. @@ -786,7 +789,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n^2)</code>, where <code>n</code> * is the height of the context tree. * </p> - * + * * @param contextIds * The set of context identifiers to be converted into a tree; * must not be <code>null</code>. @@ -882,7 +885,7 @@ public final class BindingManager extends HandleObjectManager implements * The time this method takes to complete is dependent on external * listeners. * </p> - * + * * @param event * The event to send to all of the listeners; must not be * <code>null</code>. @@ -908,7 +911,7 @@ public final class BindingManager extends HandleObjectManager implements * not yet computed, then this completes in <code>O(nn)</code>, where * <code>n</code> is the number of bindings. * </p> - * + * * @return The map of triggers (<code>TriggerSequence</code>) to * bindings (<code>Binding</code>) which are currently active. * This value may be <code>null</code> if there are no active @@ -932,7 +935,7 @@ public final class BindingManager extends HandleObjectManager implements * not yet computed, then this completes in <code>O(nn)</code>, where * <code>n</code> is the number of bindings. * </p> - * + * * @return The map of fully-parameterized commands (<code>ParameterizedCommand</code>) * to triggers (<code>TriggerSequence</code>) which are * currently active. This value may be <code>null</code> if there @@ -956,7 +959,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the number of bindings. * </p> - * + * * @return A map of trigger (<code>TriggerSequence</code>) to bindings ( * <code>Collection</code> containing <code>Binding</code>). * This map may be empty, but it is never <code>null</code>. @@ -1017,7 +1020,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the number of bindings. * </p> - * + * * @return A map of trigger (<code>TriggerSequence</code>) to bindings ( * <code>Collection</code> containing <code>Binding</code>). * This map may be empty, but it is never <code>null</code>. @@ -1080,7 +1083,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the number of bindings. * </p> - * + * * @return All of the active bindings (<code>Binding</code>), not sorted * in any fashion. This collection may be empty, but it is never * <code>null</code>. @@ -1112,7 +1115,7 @@ public final class BindingManager extends HandleObjectManager implements * not yet computed, then this completes in <code>O(nn)</code>, where * <code>n</code> is the number of bindings. * </p> - * + * * @param parameterizedCommand * The fully-parameterized command whose bindings are requested. * This argument may be <code>null</code>. @@ -1143,7 +1146,7 @@ public final class BindingManager extends HandleObjectManager implements * not yet computed, then this completes in <code>O(nn)</code>, where * <code>n</code> is the number of bindings. * </p> - * + * * @param parameterizedCommand * The fully-parameterized command whose bindings are requested. * This argument may be <code>null</code>. @@ -1174,7 +1177,7 @@ public final class BindingManager extends HandleObjectManager implements * not yet computed, then this completes in <code>O(nn)</code>, where * <code>n</code> is the number of bindings. * </p> - * + * * @param commandId * The identifier of the command whose bindings are requested. * This argument may be <code>null</code>. It is assumed that @@ -1193,7 +1196,7 @@ public final class BindingManager extends HandleObjectManager implements * A variation on {@link BindingManager#getActiveBindingsFor(String)} that * returns an array of bindings, rather than trigger sequences. This method * is needed for doing "best" calculations on the active bindings. - * + * * @param commandId * The identifier of the command for which the active bindings * should be retrieved; must not be <code>null</code>. @@ -1228,7 +1231,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method completes in <code>O(1)</code>. * </p> - * + * * @return The active scheme; may be <code>null</code> if there is no * active scheme. If a scheme is returned, it is guaranteed to be * defined. @@ -1246,7 +1249,7 @@ public final class BindingManager extends HandleObjectManager implements * most on various concepts of "length", as well as giving some modifier * keys preference (e.g., <code>Alt</code> is less likely to appear than * <code>Ctrl</code>). - * + * * @param commandId * The identifier of the command for which the best active * binding should be retrieved; must not be <code>null</code>. @@ -1257,7 +1260,7 @@ public final class BindingManager extends HandleObjectManager implements public final TriggerSequence getBestActiveBindingFor(final String commandId) { return getBestActiveBindingFor(new ParameterizedCommand(commandManager.getCommand(commandId), null)); } - + /** * @param command * @return @@ -1363,7 +1366,7 @@ public final class BindingManager extends HandleObjectManager implements * based most on various concepts of "length", as well as giving some * modifier keys preference (e.g., <code>Alt</code> is less likely to * appear than <code>Ctrl</code>). - * + * * @param commandId * The identifier of the command for which the best active * binding should be retrieved; must not be <code>null</code>. @@ -1386,7 +1389,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method completes in <code>O(1)</code>. * </p> - * + * * @return The array of all bindings. This value may be <code>null</code> * and it may be empty. */ @@ -1407,7 +1410,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method completes in <code>O(1)</code>. * </p> - * + * * @return The array of defined schemes; this value may be empty or * <code>null</code>. */ @@ -1424,7 +1427,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method completes in <code>O(1)</code>. * </p> - * + * * @return The active locale; never <code>null</code>. */ public final String getLocale() { @@ -1441,7 +1444,7 @@ public final class BindingManager extends HandleObjectManager implements * currently computed, then this completes in <code>O(n)</code>, where * <code>n</code> is the number of bindings. * </p> - * + * * @param trigger * The prefix to look for; must not be <code>null</code>. * @return A map of triggers (<code>TriggerSequence</code>) to bindings (<code>Binding</code>). @@ -1466,7 +1469,7 @@ public final class BindingManager extends HandleObjectManager implements * currently computed, then this completes in <code>O(n)</code>, where * <code>n</code> is the number of bindings. * </p> - * + * * @param trigger * The trigger to match; may be <code>null</code>. * @return The binding that matches, if any; <code>null</code> otherwise. @@ -1483,7 +1486,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method completes in <code>O(1)</code>. * </p> - * + * * @return The active platform; never <code>null</code>. */ public final String getPlatform() { @@ -1499,7 +1502,7 @@ public final class BindingManager extends HandleObjectManager implements * not yet computed, then this completes in <code>O(n)</code>, where * <code>n</code> is the number of bindings. * </p> - * + * * @return A map of prefixes (<code>TriggerSequence</code>) to a map of * available completions (possibly <code>null</code>, which means * there is an exact match). The available completions is a map of @@ -1523,7 +1526,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method completes in amortized <code>O(1)</code>. * </p> - * + * * @param schemeId * The identifier for the scheme to retrieve; must not be * <code>null</code>. @@ -1550,7 +1553,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the height of the context tree. * </p> - * + * * @param schemeId * The id of the scheme for which the parents should be found; * may be <code>null</code>. @@ -1585,7 +1588,7 @@ public final class BindingManager extends HandleObjectManager implements * currently computed, then this completes in <code>O(n)</code>, where * <code>n</code> is the number of bindings. * </p> - * + * * @param trigger * The sequence which should be the prefix for some binding; * should not be <code>null</code>. @@ -1606,7 +1609,7 @@ public final class BindingManager extends HandleObjectManager implements * currently computed, then this completes in <code>O(n)</code>, where * <code>n</code> is the number of bindings. * </p> - * + * * @param trigger * The sequence which should match exactly; should not be * <code>null</code>. @@ -1626,7 +1629,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the number of active locales. * </p> - * + * * @param binding * The binding with which to test; must not be <code>null</code>. * @return <code>true</code> if the binding's locale matches; @@ -1659,7 +1662,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the number of active platforms. * </p> - * + * * @param binding * The binding with which to test; must not be <code>null</code>. * @return <code>true</code> if the binding's platform matches; @@ -1766,7 +1769,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the number of bindings. * </p> - * + * * @param binding * The binding to be removed; must not be <code>null</code>. */ @@ -1801,7 +1804,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method completes in amortized <code>O(1)</code>. * </p> - * + * * @param listener * The listener to be removed; must not be <code>null</code>. */ @@ -1819,7 +1822,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the number of bindings. * </p> - * + * * @param sequence * The sequence to match; may be <code>null</code>. * @param schemeId @@ -1835,7 +1838,7 @@ public final class BindingManager extends HandleObjectManager implements * Currently ignored. * @param type * The type to look for. - * + * */ public final void removeBindings(final TriggerSequence sequence, final String schemeId, final String contextId, final String locale, @@ -1878,7 +1881,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the number of bindings. * </p> - * + * * @param bindings * The bindings from which the deleted items should be removed. * This array should not be <code>null</code>, but may be @@ -1972,7 +1975,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the number of bindings. * </p> - * + * * @param bindings * The bindings which all match the same trigger sequence; must * not be <code>null</code>, and should contain at least two @@ -2100,7 +2103,7 @@ public final class BindingManager extends HandleObjectManager implements * This method calls out to listeners, and so the time it takes to complete * is dependent on third-party code. * </p> - * + * * @param schemeEvent * An event describing the change in the scheme. */ @@ -2136,7 +2139,7 @@ public final class BindingManager extends HandleObjectManager implements * Sets the active bindings and the prefix table. This ensures that the two * values change at the same time, and that any listeners are notified * appropriately. - * + * * @param activeBindings * This is a map of triggers ( <code>TriggerSequence</code>) * to bindings (<code>Binding</code>). This value will only @@ -2167,13 +2170,44 @@ public final class BindingManager extends HandleObjectManager implements fireBindingManagerChanged(new BindingManagerEvent(this, true, previousBindingsByParameterizedCommand, false, null, false, false, false)); + + // RAP [if] Update client key binding list + updateKeyBindingList(); + // ENDRAP [if] } - /** + // RAP [if] Update client key binding list + private void updateKeyBindingList() { + if( activeBindings != null ) { + List keyBindingList = new ArrayList(); + final Iterator bindingItr = activeBindings.entrySet().iterator(); + while( bindingItr.hasNext() ) { + final Map.Entry entry = ( Map.Entry )bindingItr.next(); + Binding binding = ( Binding )entry.getValue(); + if( binding instanceof KeyBinding ) { + KeyBinding keyBinding = ( KeyBinding )binding; + KeySequence keySequence = keyBinding.getKeySequence(); + KeyStroke[] keyStroke = keySequence.getKeyStrokes(); + if( keyStroke.length > 0 ) { + String stroke = keyStroke[ 0 ].getModifierKeys() + + "," //$NON-NLS-1$ + + keyStroke[ 0 ].getNaturalKey(); + keyBindingList.add( stroke ); + } + } + } + String[] array = new String[ keyBindingList.size() ]; + keyBindingList.toArray( array ); + KeyBindingUtil.setKeyBindings( array ); + } + } + // ENDRAP [if] + + /** * Provides the current conflicts in the bindings as a Map The key will * be {@link TriggerSequence} and the value will be the {@link Collection} of * {@link Binding} - * + * * @return Read-only {@link Map} of the current conflicts. If no conflicts, * then return an empty map. Never <code>null</code> */ @@ -2182,13 +2216,13 @@ public final class BindingManager extends HandleObjectManager implements return Collections.EMPTY_MAP; return Collections.unmodifiableMap(currentConflicts); } - + /** - * Provides the current conflicts in the keybindings for the given + * Provides the current conflicts in the keybindings for the given * TriggerSequence as a {@link Collection} of {@link Binding} - * + * * @param sequence The sequence for which conflict info is required - * + * * @return Collection of KeyBinding. If no conflicts, * then returns a <code>null</code> */ @@ -2206,7 +2240,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the height of the context tree. * </p> - * + * * @param scheme * The scheme to become active; must not be <code>null</code>. * @throws NotDefinedException @@ -2247,7 +2281,7 @@ public final class BindingManager extends HandleObjectManager implements * This method completes in <code>O(n)</code>, where <code>n</code> is * the number of bindings. * </p> - * + * * @param bindings * The new array of bindings; may be <code>null</code>. This * set is copied into a local data structure. @@ -2280,7 +2314,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method completes in <code>O(1)</code>. * </p> - * + * * @param locale * The new locale; must not be <code>null</code>. * @see Locale#getDefault() @@ -2310,7 +2344,7 @@ public final class BindingManager extends HandleObjectManager implements * <p> * This method completes in <code>O(1)</code>. * </p> - * + * * @param platform * The new platform; must not be <code>null</code>. * @see org.eclipse.swt.SWT#getPlatform() diff --git a/bundles/org.eclipse.rap.rwt.q07/js/org/eclipse/rwt/KeyEventUtil.js b/bundles/org.eclipse.rap.rwt.q07/js/org/eclipse/rwt/KeyEventUtil.js index 26ff0dabf0..fcf00c2c5d 100644 --- a/bundles/org.eclipse.rap.rwt.q07/js/org/eclipse/rwt/KeyEventUtil.js +++ b/bundles/org.eclipse.rap.rwt.q07/js/org/eclipse/rwt/KeyEventUtil.js @@ -15,24 +15,43 @@ qx.Class.define( "org.eclipse.rwt.KeyEventUtil", { construct : function() { this.base( arguments ); org.eclipse.rwt.EventHandler.setKeyEventFilter( this._onKeyEvent, this ); + this._keyBindings = {}; }, members : { cancelEvent : function() { - this._getInstance().cancelEvent(); + this._getDelegate().cancelEvent(); }, allowEvent : function() { - this._getInstance().allowEvent(); + this._getDelegate().allowEvent(); }, + setKeyBindings : function( value ) { + this._keyBindings = value; + }, + _onKeyEvent : function( eventType, keyCode, charCode, domEvent ) { - var util = this._getInstance(); - return !util.intercept( eventType, keyCode, charCode, domEvent ); + var result; + if( this._isKeyBinding( domEvent, keyCode, charCode ) ) { + result = false; + if( eventType === "keydown" ) { + // TODO [tb] : use keypress (repeats) instead? + org.eclipse.rwt.EventHandlerUtil.stopDomEvent( domEvent ); +// TODO [rst] Pass focused widget instead of null +// var widget = this._getTargetControl(); + this._attachKeyDown( null, keyCode, charCode, domEvent ); + org.eclipse.swt.Request.getInstance().send(); + } + } else { + var util = this._getDelegate(); + result = !util.intercept( eventType, keyCode, charCode, domEvent ); + } + return result; }, - _getInstance : function() { + _getDelegate : function() { var util; if( qx.core.Variant.isSet( "qx.client", "gecko" ) ) { util = org.eclipse.rwt.AsyncKeyEventUtil.getInstance(); @@ -45,6 +64,34 @@ qx.Class.define( "org.eclipse.rwt.KeyEventUtil", { ////////////////////////////////////////////////////////////// // Helper, also used by AsyncKeyEventUtil and SyncKeyEventUtil + _isKeyBinding : function( domEvent, keyCode, charCode ) { + var identifier + = this._getKeyBindingIdentifier( domEvent, keyCode, charCode ); + var result = this._keyBindings[ identifier ] === true; + return result; + }, + + _getKeyBindingIdentifier : function( domEvent, keyCode, charCode ) { + var result = []; + if( domEvent.altKey ) { + result.push( "ALT" ); + } + if( domEvent.ctrlKey ) { + result.push( "CTRL" );//TODO Command @ apple? + } + if( domEvent.shiftKey ) { + result.push( "SHIFT" ); + } + if( !isNaN( keyCode ) && keyCode > 0 ) { + result.push( keyCode.toString() ); + } else if( !isNaN( charCode ) && charCode > 0 ) { + // Usually, the keyCode matches the charcode of the upper-case character + var charStr = String.fromCharCode( charCode ); + result.push( charStr.toUpperCase().charCodeAt( 0 ) ); + } + return result.join( "+" ); + }, + _isRelevantEvent : function( eventType, keyCode ) { var result; if( qx.core.Variant.isSet( "qx.client", "mshtml" ) ) { @@ -94,11 +141,16 @@ qx.Class.define( "org.eclipse.rwt.KeyEventUtil", { } return result; }, - + _attachKeyDown : function( widget, keyCode, charCode, domEvent ) { var req = org.eclipse.swt.Request.getInstance(); - var id - = org.eclipse.swt.WidgetManager.getInstance().findIdByWidget( widget ); + var id; + if( widget === null ) { + id = "w1"; + } else { + var wm = org.eclipse.swt.WidgetManager.getInstance(); + id = wm.findIdByWidget( widget ); + } req.addEvent( "org.eclipse.swt.events.keyDown", id ); req.addParameter( "org.eclipse.swt.events.keyDown.keyCode", keyCode ); req.addParameter( "org.eclipse.swt.events.keyDown.charCode", charCode ); @@ -118,4 +170,3 @@ qx.Class.define( "org.eclipse.rwt.KeyEventUtil", { } } ); - diff --git a/bundles/org.eclipse.rap.rwt.q07/src/org/eclipse/swt/internal/widgets/displaykit/DisplayLCA.java b/bundles/org.eclipse.rap.rwt.q07/src/org/eclipse/swt/internal/widgets/displaykit/DisplayLCA.java index 0ef9a54d23..f7461bca5c 100644 --- a/bundles/org.eclipse.rap.rwt.q07/src/org/eclipse/swt/internal/widgets/displaykit/DisplayLCA.java +++ b/bundles/org.eclipse.rap.rwt.q07/src/org/eclipse/swt/internal/widgets/displaykit/DisplayLCA.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2002, 2010 Innoopract Informationssysteme GmbH. + * Copyright (c) 2002, 2011 Innoopract Informationssysteme GmbH. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -146,6 +146,7 @@ public class DisplayLCA implements IDisplayLifeCycleAdapter { writeFocus( display ); writeUICallBackActivation( display ); markInitialized( display ); + KeyBindingUtil.writeKeyBindings( display ); } } @@ -314,6 +315,7 @@ public class DisplayLCA implements IDisplayLifeCycleAdapter { readBounds( display ); readCursorLocation( display ); readFocusControl( display ); + KeyBindingUtil.readKeyBindingEvents( display ); WidgetTreeVisitor visitor = new AllWidgetTreeVisitor() { public boolean doVisit( final Widget widget ) { IWidgetLifeCycleAdapter adapter = WidgetUtil.getLCA( widget ); @@ -429,7 +431,7 @@ public class DisplayLCA implements IDisplayLifeCycleAdapter { } } - private static void writeUICallBackActivation( final Display display ) + private static void writeUICallBackActivation( final Display display ) throws IOException { if( !display.isDisposed() ) { diff --git a/bundles/org.eclipse.rap.rwt.q07/src/org/eclipse/swt/internal/widgets/displaykit/KeyBindingUtil.java b/bundles/org.eclipse.rap.rwt.q07/src/org/eclipse/swt/internal/widgets/displaykit/KeyBindingUtil.java new file mode 100644 index 0000000000..c0dcbf8729 --- /dev/null +++ b/bundles/org.eclipse.rap.rwt.q07/src/org/eclipse/swt/internal/widgets/displaykit/KeyBindingUtil.java @@ -0,0 +1,496 @@ +/******************************************************************************* + * Copyright (c) 2011 EclipseSource and others. All rights reserved. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * EclipseSource - initial API and implementation + ******************************************************************************/ +package org.eclipse.swt.internal.widgets.displaykit; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; + +import org.eclipse.rwt.internal.lifecycle.HtmlResponseWriter; +import org.eclipse.rwt.internal.lifecycle.JSConst; +import org.eclipse.rwt.internal.service.ContextProvider; +import org.eclipse.rwt.internal.service.IServiceStateInfo; +import org.eclipse.rwt.lifecycle.ProcessActionRunner; +import org.eclipse.swt.SWT; +import org.eclipse.swt.internal.events.EventLCAUtil; +import org.eclipse.swt.internal.widgets.IDisplayAdapter; +import org.eclipse.swt.internal.widgets.IDisplayAdapter.IFilterEntry; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; + + +public final class KeyBindingUtil { + + private static final String JSFUNC_SET_KEYBINDING_LIST + = "org.eclipse.rwt.KeyEventUtil.getInstance().setKeyBindings"; + + static final String KEYBINDING_LIST + = Display.class.getName() + "#keyBindingList"; + + private KeyBindingUtil() { + // prevent instantiation + } + + public static void setKeyBindings( final String[] keyBindings ) { + IServiceStateInfo stateInfo = ContextProvider.getStateInfo(); + stateInfo.setAttribute( KEYBINDING_LIST, keyBindings ); + } + + static void readKeyBindingEvents( final Display display ) { + if( wasEventSent( JSConst.EVENT_KEY_DOWN ) ) { + final int keyCode = readIntParam( JSConst.EVENT_KEY_DOWN_KEY_CODE ); + final int charCode = readIntParam( JSConst.EVENT_KEY_DOWN_CHAR_CODE ); + final int stateMask + = EventLCAUtil.readStateMask( JSConst.EVENT_KEY_DOWN_MODIFIER ); + ProcessActionRunner.add( new Runnable() { + public void run() { + Event event = createEvent( display, keyCode, charCode, stateMask ); + processEvent( display, event ); + } + } ); + } + } + + static void writeKeyBindings( final Display display ) + throws IOException + { + IServiceStateInfo stateInfo = ContextProvider.getStateInfo(); + String[] keyBindingList + = ( String[] )stateInfo.getAttribute( KEYBINDING_LIST ); + if( keyBindingList != null ) { + HtmlResponseWriter writer = stateInfo.getResponseWriter(); + StringBuffer content = new StringBuffer(); + content.append( JSFUNC_SET_KEYBINDING_LIST ); + content.append( "(" ); + content.append( toJson( keyBindingList ) ); + content.append( ");" ); + writer.write( content.toString() ); + } + } + + private static String toJson( final String[] keyBindingList ) { + StringBuffer json = new StringBuffer(); + json.append( "{" ); + for( int i = 0; i < keyBindingList.length; i++ ) { + json.append( "\"" ); + json.append( getModifierKeys( keyBindingList[ i ] ) ); + json.append( getNaturalKey( keyBindingList[ i ] ) ); + json.append( "\":true" ); + if( i < keyBindingList.length - 1 ) { + json.append( "," ); + } + } + json.append( "}" ); + return json.toString(); + } + + private static String getModifierKeys( final String keyBinding ) { + String modifierPart = keyBinding.substring( 0, keyBinding.indexOf( ',' ) ); + int modifierKeys = Integer.parseInt( modifierPart ); + StringBuffer result = new StringBuffer(); + if( ( modifierKeys & SWT.ALT ) != 0 ) { + result.append( "ALT+" ); + } + if( ( modifierKeys & SWT.CTRL ) != 0 ) { + result.append( "CTRL+" ); + } + if( ( modifierKeys & SWT.SHIFT ) != 0 ) { + result.append( "SHIFT+" ); + } + return result.toString(); + } + + private static int getNaturalKey( final String keyBinding ) { + String keyPart = keyBinding.substring( keyBinding.indexOf( ',' ) + 1 ); + int naturalKey = Integer.parseInt( keyPart ); + return translateNaturalKey( naturalKey ); + } + + private static Event createEvent( final Display display, + final int keyCode, + final int charCode, + final int stateMask ) + { + Event event = new Event(); + event.display = display; + event.type = SWT.KeyDown; + if( charCode == 0 ) { + event.keyCode = translateKeyCode( keyCode ); + if( ( event.keyCode & SWT.KEYCODE_BIT ) == 0 ) { + event.character = translateCharacter( event.keyCode ); + } + } else { + event.keyCode = charCode; + event.character = translateCharacter( charCode ); + } + event.stateMask = stateMask; + return event; + } + + private static void processEvent( final Display display, final Event event ) { + IFilterEntry[] filters = getFilterEntries( display ); + for( int i = 0; i < filters.length; i++ ) { + if( filters[ i ].getType() == event.type ) { + filters[ i ].getListener().handleEvent( event ); + } + } + } + + private static IFilterEntry[] getFilterEntries( final Display display ) { + IDisplayAdapter adapter + = ( IDisplayAdapter )display.getAdapter( IDisplayAdapter.class ); + return adapter.getFilters(); + } + + private static boolean wasEventSent( final String eventName ) { + HttpServletRequest request = ContextProvider.getRequest(); + String widgetId = request.getParameter( eventName ); + return "w1".equals( widgetId ); + } + + private static int readIntParam( final String paramName ) { + String value = readStringParam( paramName ); + return Integer.parseInt( value ); + } + + private static String readStringParam( final String paramName ) { + HttpServletRequest request = ContextProvider.getRequest(); + return request.getParameter( paramName ); + } + + // translates key code qooxdoo -> SWT + private static int translateKeyCode( final int keyCode ) { + int result; + switch( keyCode ) { + case 20: + result = SWT.CAPS_LOCK; + break; + case 38: + result = SWT.ARROW_UP; + break; + case 37: + result = SWT.ARROW_LEFT; + break; + case 39: + result = SWT.ARROW_RIGHT; + break; + case 40: + result = SWT.ARROW_DOWN; + break; + case 33: + result = SWT.PAGE_UP; + break; + case 34: + result = SWT.PAGE_DOWN; + break; + case 35: + result = SWT.END; + break; + case 36: + result = SWT.HOME; + break; + case 45: + result = SWT.INSERT; + break; + case 46: + result = SWT.DEL; + break; + case 112: + result = SWT.F1; + break; + case 113: + result = SWT.F2; + break; + case 114: + result = SWT.F3; + break; + case 115: + result = SWT.F4; + break; + case 116: + result = SWT.F5; + break; + case 117: + result = SWT.F6; + break; + case 118: + result = SWT.F7; + break; + case 119: + result = SWT.F8; + break; + case 120: + result = SWT.F9; + break; + case 121: + result = SWT.F10; + break; + case 122: + result = SWT.F11; + break; + case 123: + result = SWT.F12; + break; + case 144: + result = SWT.NUM_LOCK; + break; + case 44: + result = SWT.PRINT_SCREEN; + break; + case 145: + result = SWT.SCROLL_LOCK; + break; + case 19: + result = SWT.PAUSE; + break; + case 96: + result = SWT.KEYPAD_0; + break; + case 97: + result = SWT.KEYPAD_1; + break; + case 98: + result = SWT.KEYPAD_2; + break; + case 99: + result = SWT.KEYPAD_3; + break; + case 100: + result = SWT.KEYPAD_4; + break; + case 101: + result = SWT.KEYPAD_5; + break; + case 102: + result = SWT.KEYPAD_6; + break; + case 103: + result = SWT.KEYPAD_7; + break; + case 104: + result = SWT.KEYPAD_8; + break; + case 105: + result = SWT.KEYPAD_9; + break; + case 106: + result = SWT.KEYPAD_MULTIPLY; + break; + case 107: + result = SWT.KEYPAD_ADD; + break; + case 109: + result = SWT.KEYPAD_SUBTRACT; + break; + case 110: + result = SWT.KEYPAD_DECIMAL; + break; + case 111: + result = SWT.KEYPAD_DIVIDE; + break; + case 188: + result = ','; + break; + case 190: + result = '.'; + break; + case 191: + result = '/'; + break; + case 192: + result = '`'; + break; + case 219: + result = '['; + break; + case 220: + result = '\\'; + break; + case 221: + result = ']'; + break; + case 222: + result = '\''; + break; + default: + result = keyCode; + } + return result; + } + + // translate key codes SWT -> qooxdoo + private static int translateNaturalKey( final int naturalKey ) { + int result; + switch( naturalKey ) { + case SWT.CAPS_LOCK: + result = 20; + break; + case SWT.ARROW_UP: + result = 38; + break; + case SWT.ARROW_LEFT: + result = 37; + break; + case SWT.ARROW_RIGHT: + result = 39; + break; + case SWT.ARROW_DOWN: + result = 40; + break; + case SWT.PAGE_UP: + result = 33; + break; + case SWT.PAGE_DOWN: + result = 34; + break; + case SWT.END: + result = 35; + break; + case SWT.HOME: + result = 36; + break; + case SWT.INSERT: + result = 45; + break; + case SWT.DEL: + result = 46; + break; + case SWT.F1: + result = 112; + break; + case SWT.F2: + result = 113; + break; + case SWT.F3: + result = 114; + break; + case SWT.F4: + result = 115; + break; + case SWT.F5: + result = 116; + break; + case SWT.F6: + result = 117; + break; + case SWT.F7: + result = 118; + break; + case SWT.F8: + result = 119; + break; + case SWT.F9: + result = 120; + break; + case SWT.F10: + result = 121; + break; + case SWT.F11: + result = 122; + break; + case SWT.F12: + result = 123; + break; + case SWT.NUM_LOCK: + result = 144; + break; + case SWT.PRINT_SCREEN: + result = 44; + break; + case SWT.SCROLL_LOCK: + result = 145; + break; + case SWT.PAUSE: + result = 19; + break; + case SWT.KEYPAD_0: + result = 96; + break; + case SWT.KEYPAD_1: + result = 97; + break; + case SWT.KEYPAD_2: + result = 98; + break; + case SWT.KEYPAD_3: + result = 99; + break; + case SWT.KEYPAD_4: + result = 100; + break; + case SWT.KEYPAD_5: + result = 101; + break; + case SWT.KEYPAD_6: + result = 102; + break; + case SWT.KEYPAD_7: + result = 103; + break; + case SWT.KEYPAD_8: + result = 104; + break; + case SWT.KEYPAD_9: + result = 105; + break; + case SWT.KEYPAD_MULTIPLY: + result = 106; + break; + case SWT.KEYPAD_ADD: + result = 107; + break; + case SWT.KEYPAD_SUBTRACT: + result = 109; + break; + case SWT.KEYPAD_DECIMAL: + result = 110; + break; + case SWT.KEYPAD_DIVIDE: + result = 111; + break; + case ',': + result = 188; + break; + case '.': + result = 190; + break; + case '/': + result = 191; + break; + case '`': + result = 192; + break; + case '[': + result = 219; + break; + case '\\': + result = 220; + break; + case ']': + result = 221; + break; + case '\'': + result = 222; + break; + default: + result = naturalKey; + } + return result; + } + + private static char translateCharacter( final int keyCode ) { + char result = ( char )0; + if( Character.isDefined( ( char )keyCode ) ) { + result = ( char )keyCode; + } + return result; + } + +} diff --git a/bundles/org.eclipse.rap.rwt/META-INF/MANIFEST.MF b/bundles/org.eclipse.rap.rwt/META-INF/MANIFEST.MF index 2f442f68a7..4d1d0a7b02 100644 --- a/bundles/org.eclipse.rap.rwt/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.rap.rwt/META-INF/MANIFEST.MF @@ -25,7 +25,7 @@ Export-Package: org.eclipse.rwt, org.eclipse.rwt.internal.events;x-friends:="org.eclipse.rap.rwt.test,org.eclipse.rap.jface", org.eclipse.rwt.internal.lifecycle;x-friends:="org.eclipse.rap.rwt.test,org.eclipse.rap.ui.workbench,org.eclipse.rap.jface", org.eclipse.rwt.internal.resources;x-friends:="org.eclipse.rap.rwt.test,org.eclipse.rap.ui.workbench", - org.eclipse.rwt.internal.service;x-friends:="org.eclipse.rap.rwt.test,org.eclipse.rap.ui.workbench,org.eclipse.rap.ui", + org.eclipse.rwt.internal.service;x-friends:="org.eclipse.rap.rwt.test,org.eclipse.rap.ui.workbench,org.eclipse.rap.ui,org.eclipse.rap.jface", org.eclipse.rwt.internal.theme;x-friends:="org.eclipse.rap.ui.workbench", org.eclipse.rwt.internal.theme.css;x-friends:="org.eclipse.rap.ui.workbench", org.eclipse.rwt.internal.util;x-friends:="org.eclipse.rap.rwt.test,org.eclipse.rap.ui.workbench", @@ -62,7 +62,7 @@ Export-Package: org.eclipse.rwt, org.eclipse.swt.internal.widgets.coolbarkit;x-friends:="org.eclipse.rap.rwt.test", org.eclipse.swt.internal.widgets.coolitemkit;x-friends:="org.eclipse.rap.rwt.test", org.eclipse.swt.internal.widgets.datetimekit;x-friends:="org.eclipse.rap.rwt.test", - org.eclipse.swt.internal.widgets.displaykit;x-friends:="org.eclipse.rap.rwt.test", + org.eclipse.swt.internal.widgets.displaykit;x-friends:="org.eclipse.rap.rwt.test,org.eclipse.rap.jface", org.eclipse.swt.internal.widgets.expandbarkit;x-friends:="org.eclipse.rap.rwt.test", org.eclipse.swt.internal.widgets.groupkit;x-friends:="org.eclipse.rap.rwt.test", org.eclipse.swt.internal.widgets.labelkit;x-friends:="org.eclipse.rap.rwt.test", diff --git a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/IWorkbenchPreferenceConstants.java b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/IWorkbenchPreferenceConstants.java index 84163879cd..03e68dc803 100755 --- a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/IWorkbenchPreferenceConstants.java +++ b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/IWorkbenchPreferenceConstants.java @@ -21,7 +21,7 @@ import org.eclipse.swt.SWT; * <p> * <b>Note:</b>This interface should not be implemented or extended. * </p> - * + * * @see PlatformUI#PLUGIN_ID * @see PlatformUI#getPreferenceStore() * @since 1.1 @@ -43,10 +43,10 @@ public interface IWorkbenchPreferenceConstants { * A named preference for how a new perspective is opened. * <p> * Value is of type <code>String</code>. The possible values are defined - * by <code>OPEN_PERSPECTIVE_WINDOW, OPEN_PERSPECTIVE_PAGE and + * by <code>OPEN_PERSPECTIVE_WINDOW, OPEN_PERSPECTIVE_PAGE and * OPEN_PERSPECTIVE_REPLACE</code>. * </p> - * + * * <!-- @see #OPEN_PERSPECTIVE_WINDOW --> * <!-- @see #OPEN_PERSPECTIVE_PAGE --> * @see #OPEN_PERSPECTIVE_REPLACE @@ -61,10 +61,10 @@ public interface IWorkbenchPreferenceConstants { // * dependent. // * <p> // * Value is of type <code>String</code>. The possible values are defined -// * by <code>OPEN_PERSPECTIVE_WINDOW, OPEN_PERSPECTIVE_PAGE and +// * by <code>OPEN_PERSPECTIVE_WINDOW, OPEN_PERSPECTIVE_PAGE and // * OPEN_PERSPECTIVE_REPLACE</code>. // * </p> -// * +// * // * @deprecated Workbench no longer supports alternate key modifier to open a // * new perspective. Callers should use // * IWorkbench.showPerspective methods. @@ -77,10 +77,10 @@ public interface IWorkbenchPreferenceConstants { // * modifier is pressed. // * <p> // * Value is of type <code>String</code>. The possible values are defined -// * by <code>OPEN_PERSPECTIVE_WINDOW, OPEN_PERSPECTIVE_PAGE and +// * by <code>OPEN_PERSPECTIVE_WINDOW, OPEN_PERSPECTIVE_PAGE and // * OPEN_PERSPECTIVE_REPLACE</code>. // * </p> -// * +// * // * @deprecated Workbench no longer supports shift key modifier to open a new // * perspective. Callers should use IWorkbench.showPerspective // * methods. @@ -93,10 +93,10 @@ public interface IWorkbenchPreferenceConstants { // * project is created. // * <p> // * Value is of type <code>String</code>. The possible values are defined -// * by the constants <code>OPEN_PERSPECTIVE_WINDOW, OPEN_PERSPECTIVE_PAGE, +// * by the constants <code>OPEN_PERSPECTIVE_WINDOW, OPEN_PERSPECTIVE_PAGE, // * OPEN_PERSPECTIVE_REPLACE, and NO_NEW_PERSPECTIVE</code>. // * </p> -// * +// * // * @see #OPEN_PERSPECTIVE_WINDOW // * @see #OPEN_PERSPECTIVE_PAGE // * @see #OPEN_PERSPECTIVE_REPLACE @@ -109,20 +109,20 @@ public interface IWorkbenchPreferenceConstants { // */ // public static final String PROJECT_OPEN_NEW_PERSPECTIVE = "PROJECT_OPEN_NEW_PERSPECTIVE"; //$NON-NLS-1$ - // RAP [bm]: + // RAP [bm]: // /** // * A preference value indicating that an action should open a new // * perspective in a new window. -// * +// * // * @see #PROJECT_OPEN_NEW_PERSPECTIVE // */ // public static final String OPEN_PERSPECTIVE_WINDOW = "OPEN_PERSPECTIVE_WINDOW"; //$NON-NLS-1$ - // RAP [bm]: + // RAP [bm]: // /** // * A preference value indicating that an action should open a new // * perspective in a new page. -// * +// * // * @see #PROJECT_OPEN_NEW_PERSPECTIVE // * @deprecated Opening a Perspective in a new page is no longer supported // * functionality as of 2.0. @@ -132,7 +132,7 @@ public interface IWorkbenchPreferenceConstants { /** * A preference value indicating that an action should open a new * perspective by replacing the current perspective. - * + * * @see #PROJECT_OPEN_NEW_PERSPECTIVE */ public static final String OPEN_PERSPECTIVE_REPLACE = "OPEN_PERSPECTIVE_REPLACE"; //$NON-NLS-1$ @@ -140,7 +140,7 @@ public interface IWorkbenchPreferenceConstants { /** * A preference value indicating that an action should not open a new * perspective. - * + * * @see #PROJECT_OPEN_NEW_PERSPECTIVE */ public static final String NO_NEW_PERSPECTIVE = "NO_NEW_PERSPECTIVE"; //$NON-NLS-1$ @@ -166,18 +166,18 @@ public interface IWorkbenchPreferenceConstants { * </p> */ public static String DOCK_PERSPECTIVE_BAR = "DOCK_PERSPECTIVE_BAR"; //$NON-NLS-1$ - + /** * A preference indication the initial size of the perspective bar. The default value is 160. * This preference only works when <code>configurer.setShowPerspectiveBar(true)</code> is set in * WorkbenchWindowAdvisor#preWindowOpen() - * + * * This preference only uses integer values * bug 84603: [RCP] [PerspectiveBar] New API or pref to set default perspective bar size - * + * * @since 1.4 */ - public static String PERSPECTIVE_BAR_SIZE = "PERSPECTIVE_BAR_SIZE"; //$NON-NLS-1$ + public static String PERSPECTIVE_BAR_SIZE = "PERSPECTIVE_BAR_SIZE"; //$NON-NLS-1$ /** * A named preference indicating where the fast view bar should be docked in @@ -186,7 +186,7 @@ public interface IWorkbenchPreferenceConstants { * workbench. This preference is intended for applications that want the * initial docking location to be somewhere specific. The default value * (when this preference is not set) is the bottom. - * + * * @see #LEFT * @see #BOTTOM * @see #RIGHT @@ -196,7 +196,7 @@ public interface IWorkbenchPreferenceConstants { /** * Constant to be used when referring to the top right of the workbench * window. - * + * * @see #DOCK_PERSPECTIVE_BAR */ public static final String TOP_RIGHT = "topRight"; //$NON-NLS-1$ @@ -204,7 +204,7 @@ public interface IWorkbenchPreferenceConstants { /** * Constant to be used when referring to the top left of the workbench * window. - * + * * @see #DOCK_PERSPECTIVE_BAR */ public static final String TOP_LEFT = "topLeft"; //$NON-NLS-1$ @@ -212,7 +212,7 @@ public interface IWorkbenchPreferenceConstants { /** * Constant to be used when referring to the left side of the workbench * window. - * + * * @see #DOCK_PERSPECTIVE_BAR * @see #INITIAL_FAST_VIEW_BAR_LOCATION */ @@ -220,7 +220,7 @@ public interface IWorkbenchPreferenceConstants { /** * Constant to be used when referring to the bottom of the workbench window. - * + * * @see #INITIAL_FAST_VIEW_BAR_LOCATION */ public static final String BOTTOM = "bottom"; //$NON-NLS-1$ @@ -228,7 +228,7 @@ public interface IWorkbenchPreferenceConstants { /** * Constant to be used when referring to the right side of the workbench * window. - * + * * @see #INITIAL_FAST_VIEW_BAR_LOCATION */ public static final String RIGHT = "right"; //$NON-NLS-1$ @@ -236,12 +236,12 @@ public interface IWorkbenchPreferenceConstants { /** * A named preference indicating whether the workbench should show the * introduction component (if available) on startup. - * + * * <p> * The default value for this preference is: <code>true</code> (show * intro) * </p> - * + * * @see org.eclipse.ui.application.WorkbenchWindowAdvisor#openIntro() * @since 1.2 */ @@ -251,7 +251,7 @@ public interface IWorkbenchPreferenceConstants { // /** // * A named preference for whether the workbench should show traditional // * style tabs in editors and views. -// * +// * // * Boolean-valued: <code>true</code> if editors and views should use a // * traditional style of tab and <code>false</code> if editors should show // * new style tab (3.0 style) @@ -264,7 +264,7 @@ public interface IWorkbenchPreferenceConstants { /** * A named preference for whether the workbench should show text on the * perspective bar. - * + * * Boolean-valued: <code>true</code>, if editors should show text on the * perspective bar, <code>false</code> otherwise. * <p> @@ -277,7 +277,7 @@ public interface IWorkbenchPreferenceConstants { /** * A named preference for whether the workbench should show the "open * perspective" button on the perspective bar. - * + * * Boolean-valued: <code>true</code>, if editors should show "open * perspective" button on the perspective bar, <code>false</code> * otherwise. @@ -285,7 +285,7 @@ public interface IWorkbenchPreferenceConstants { * The default value for this preference is: <code>true</code> (show "open * perspective" button on the perspective bar) * </p> - * + * * @since 1.1 */ public static String SHOW_OPEN_ON_PERSPECTIVE_BAR = "SHOW_OPEN_ON_PERSPECTIVE_BAR"; //$NON-NLS-1$ @@ -293,50 +293,50 @@ public interface IWorkbenchPreferenceConstants { /** * A named preference for whether the workbench should show the "Other..." * menu item in the perspective menu. - * + * * Boolean-valued: <code>true</code>, if editors should show text on the * "Other..." menu item, <code>false</code> otherwise. * <p> * The default value for this preference is: <code>true</code> (show the * "Other..." menu item in the perspective menu) * </p> - * + * * @since 1.1 */ public static String SHOW_OTHER_IN_PERSPECTIVE_MENU = "SHOW_OTHER_IN_PERSPECTIVE_MENU"; //$NON-NLS-1$ /** * A named preference for the text of the Help Contents action. - * + * * String-valued. If not specified, <code>"&Help Contents"</code> is used. * <p> * The default value for this preference is: <code>null</code> * </p> - * + * * @since 1.3 */ public static String HELP_CONTENTS_ACTION_TEXT = "helpContentsActionText"; //$NON-NLS-1$ /** * A named preference for the text of the Help Search action. - * + * * String-valued. If not specified, <code>"S&earch"</code> is used. * <p> * The default value for this preference is: <code>null</code> * </p> - * + * * @since 1.3 */ public static String HELP_SEARCH_ACTION_TEXT = "helpSearchActionText"; //$NON-NLS-1$ /** * A named preference for the text of the Dynamic Help action. - * + * * String-valued. If not specified, <code>"&Dynamic Help"</code> is used. * <p> * The default value for this preference is: <code>null</code> * </p> - * + * * @since 1.3 */ public static String DYNAMIC_HELP_ACTION_TEXT = "dynamicHelpActionText"; //$NON-NLS-1$ @@ -351,33 +351,32 @@ public interface IWorkbenchPreferenceConstants { // * </p> // */ // public static final String ENABLE_ANIMATIONS = "ENABLE_ANIMATIONS"; //$NON-NLS-1$ - + // RAP [bm]: no colored labels // /** // * A named preference that view implementors can used to determine whether // * or not they should utilize colored labels. -// * +// * // * <p> // * The default value for this preference is: <code>true</code> (show // * colored labels) // * </p> -// * +// * // * @since 1.1 // */ // public static final String USE_COLORED_LABELS = "USE_COLORED_LABELS"; //$NON-NLS-1$ - // RAP [bm]: no key configurations -// /** -// * <p> -// * Workbench preference id for the key configuration identifier to be -// * treated as the default. -// * </p> -// * <p> -// * The default value for this preference is -// * <code>"org.eclipse.ui.defaultAcceleratorConfiguration"</code>. -// * <p> -// */ -// public static final String KEY_CONFIGURATION_ID = "KEY_CONFIGURATION_ID"; //$NON-NLS-1$ + /** + * <p> + * Workbench preference id for the key configuration identifier to be + * treated as the default. + * </p> + * <p> + * The default value for this preference is + * <code>"org.eclipse.ui.defaultAcceleratorConfiguration"</code>. + * <p> + */ + public static final String KEY_CONFIGURATION_ID = "KEY_CONFIGURATION_ID"; //$NON-NLS-1$ /** * <p> @@ -457,7 +456,7 @@ public interface IWorkbenchPreferenceConstants { * editor or view is closed, but the Saveable objects are still open in * other parts. If <code>true</code> (default), the user will be prompted. * If <code>false</code>, there will be no prompt. - * + * * @see Saveable */ public static final String PROMPT_WHEN_SAVEABLE_STILL_OPEN = "PROMPT_WHEN_SAVEABLE_STILL_OPEN"; //$NON-NLS-1$ @@ -514,7 +513,7 @@ public interface IWorkbenchPreferenceConstants { * <p> * The default value for this preference is: <code>SWT.TOP</code>. * </p> - * + * * @since 1.1 */ public static final String VIEW_TAB_POSITION = "VIEW_TAB_POSITION"; //$NON-NLS-1$ @@ -525,7 +524,7 @@ public interface IWorkbenchPreferenceConstants { * <p> * The default value for this preference is: <code>SWT.TOP</code>. * </p> - * + * * @since 1.1 */ public static final String EDITOR_TAB_POSITION = "EDITOR_TAB_POSITION"; //$NON-NLS-1$ @@ -533,31 +532,31 @@ public interface IWorkbenchPreferenceConstants { /** * Workbench preference id for whether the workbench should show multiple * editor tabs. - * + * * Boolean-valued: <code>true</code> if editors should show multiple * editor tabs, and <code>false</code> if editors should show a single * editor tab. * <p> * The default value for this preference is: <code>true</code> * </p> - * + * * @since 1.1 */ - public static final String SHOW_MULTIPLE_EDITOR_TABS = "SHOW_MULTIPLE_EDITOR_TABS"; //$NON-NLS-1$ - + public static final String SHOW_MULTIPLE_EDITOR_TABS = "SHOW_MULTIPLE_EDITOR_TABS"; //$NON-NLS-1$ + /** * Workbench preference id for whether the workbench may open editors * in-place. Note that editors will only be opened in-place if this * preference is <code>false</code> and if the current platform supports * in-place editing. - * + * * Boolean-valued: <code>false</code> if editors may be opened in-place, * and <code>true</code> if editors should never be opened in-place. * <p> * The default value for this preference is: <code>false</code> * </p> - * + * * @since 1.1 */ - public static final String DISABLE_OPEN_EDITOR_IN_PLACE = "DISABLE_OPEN_EDITOR_IN_PLACE"; //$NON-NLS-1$ + public static final String DISABLE_OPEN_EDITOR_IN_PLACE = "DISABLE_OPEN_EDITOR_IN_PLACE"; //$NON-NLS-1$ } diff --git a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java index 27e0ab6af6..3ac2901f3d 100755 --- a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java +++ b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/Workbench.java @@ -1861,9 +1861,8 @@ public final class Workbench extends EventManager implements IWorkbench { }}); - // RAP [bm] Bindings -// bindingService[0].readRegistryAndPreferences(commandService[0]); -// serviceLocator.registerService(IBindingService.class, bindingService[0]); + bindingService[0].readRegistryAndPreferences(commandService[0]); + serviceLocator.registerService(IBindingService.class, bindingService[0]); final CommandImageManager commandImageManager = new CommandImageManager(); final CommandImageService commandImageService = new CommandImageService( diff --git a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/BindingPersistence.java b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/BindingPersistence.java index e928453c2d..f7ed6a2c8b 100755 --- a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/BindingPersistence.java +++ b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/BindingPersistence.java @@ -1,1417 +1,1416 @@ -// RAP [bm]: Completeley disabled as BindingService is just a dummy -///******************************************************************************* -// * Copyright (c) 2005, 2009 IBM Corporation and others. -// * All rights reserved. This program and the accompanying materials -// * are made available under the terms of the Eclipse Public License v1.0 -// * which accompanies this distribution, and is available at -// * http://www.eclipse.org/legal/epl-v10.html -// * -// * Contributors: -// * IBM Corporation - initial API and implementation -// *******************************************************************************/ -//package org.eclipse.ui.internal.keys; -// -//import java.io.IOException; -//import java.io.Reader; -//import java.io.StringReader; -//import java.io.StringWriter; -//import java.io.Writer; -//import java.util.ArrayList; -//import java.util.Collection; -//import java.util.HashMap; -//import java.util.HashSet; -//import java.util.Iterator; -//import java.util.List; -//import java.util.Map; -//import java.util.StringTokenizer; -//import org.eclipse.core.commands.Command; -//import org.eclipse.core.commands.ParameterizedCommand; -//import org.eclipse.core.commands.common.HandleObject; -//import org.eclipse.core.commands.common.NotDefinedException; -//import org.eclipse.core.commands.util.Tracing; -//import org.eclipse.core.runtime.IConfigurationElement; -//import org.eclipse.core.runtime.IExtension; -//import org.eclipse.core.runtime.IExtensionDelta; -//import org.eclipse.core.runtime.IExtensionRegistry; -//import org.eclipse.core.runtime.IRegistryChangeEvent; -//import org.eclipse.core.runtime.Platform; -//import org.eclipse.jface.bindings.Binding; -//import org.eclipse.jface.bindings.BindingManager; -//import org.eclipse.jface.bindings.Scheme; -//import org.eclipse.jface.bindings.keys.IKeyLookup; -//import org.eclipse.jface.bindings.keys.KeyBinding; -//import org.eclipse.jface.bindings.keys.KeyLookupFactory; -//import org.eclipse.jface.bindings.keys.KeySequence; -//import org.eclipse.jface.bindings.keys.KeyStroke; -//import org.eclipse.jface.bindings.keys.ParseException; -//import org.eclipse.jface.bindings.keys.SWTKeySupport; -//import org.eclipse.jface.contexts.IContextIds; -//import org.eclipse.jface.preference.IPreferenceStore; -//import org.eclipse.jface.util.PropertyChangeEvent; -//import org.eclipse.jface.util.Util; -//import org.eclipse.swt.SWT; -//import org.eclipse.ui.IMemento; -//import org.eclipse.ui.IWorkbenchCommandConstants; -//import org.eclipse.ui.IWorkbenchPreferenceConstants; -//import org.eclipse.ui.PlatformUI; -//import org.eclipse.ui.WorkbenchException; -//import org.eclipse.ui.XMLMemento; -//import org.eclipse.ui.commands.ICommandService; -//import org.eclipse.ui.internal.ShowViewMenu; -//import org.eclipse.ui.internal.WorkbenchPlugin; -//import org.eclipse.ui.internal.misc.Policy; -//import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants; -//import org.eclipse.ui.internal.services.PreferencePersistence; -//import org.eclipse.ui.keys.IBindingService; -//import org.eclipse.ui.views.IViewRegistry; -// -///** -// * <p> -// * A static class for accessing the registry and the preference store. -// * </p> -// * -// * @since 3.1 -// */ -//public final class BindingPersistence extends PreferencePersistence { -// -// /** -// * Whether this class should print out debugging information when it reads -// * in data, or writes to the preference store. -// */ -// private static final boolean DEBUG = Policy.DEBUG_KEY_BINDINGS; -// -// /** -// * The index of the active scheme configuration elements in the indexed -// * array. -// * -// * @see BindingPersistence#read() -// */ -// private static final int INDEX_ACTIVE_SCHEME = 0; -// -// /** -// * The index of the binding definition configuration elements in the indexed -// * array. -// * -// * @see BindingPersistence#read() -// */ -// private static final int INDEX_BINDING_DEFINITIONS = 1; -// -// /** -// * The index of the scheme definition configuration elements in the indexed -// * array. -// * -// * @see BindingPersistence#read() -// */ -// private static final int INDEX_SCHEME_DEFINITIONS = 2; -// -// /** -// * The name of the default scope in 2.1.x. -// */ -// private static final String LEGACY_DEFAULT_SCOPE = "org.eclipse.ui.globalScope"; //$NON-NLS-1$ -// -// /** -// * A look-up map for 2.1.x style <code>string</code> keys on a -// * <code>keyBinding</code> element. -// */ -// private static final Map r2_1KeysByName = new HashMap(); -// -// static { -// final IKeyLookup lookup = KeyLookupFactory.getDefault(); -// r2_1KeysByName.put(IKeyLookup.BACKSPACE_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.BACKSPACE_NAME)); -// r2_1KeysByName.put(IKeyLookup.TAB_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.TAB_NAME)); -// r2_1KeysByName.put(IKeyLookup.RETURN_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.RETURN_NAME)); -// r2_1KeysByName.put(IKeyLookup.ENTER_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.ENTER_NAME)); -// r2_1KeysByName.put(IKeyLookup.ESCAPE_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.ESCAPE_NAME)); -// r2_1KeysByName.put(IKeyLookup.ESC_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.ESC_NAME)); -// r2_1KeysByName.put(IKeyLookup.DELETE_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.DELETE_NAME)); -// r2_1KeysByName.put(IKeyLookup.SPACE_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.SPACE_NAME)); -// r2_1KeysByName.put(IKeyLookup.ARROW_UP_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.ARROW_UP_NAME)); -// r2_1KeysByName.put(IKeyLookup.ARROW_DOWN_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.ARROW_DOWN_NAME)); -// r2_1KeysByName.put(IKeyLookup.ARROW_LEFT_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.ARROW_LEFT_NAME)); -// r2_1KeysByName.put(IKeyLookup.ARROW_RIGHT_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.ARROW_RIGHT_NAME)); -// r2_1KeysByName.put(IKeyLookup.PAGE_UP_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.PAGE_UP_NAME)); -// r2_1KeysByName.put(IKeyLookup.PAGE_DOWN_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.PAGE_DOWN_NAME)); -// r2_1KeysByName.put(IKeyLookup.HOME_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.HOME_NAME)); -// r2_1KeysByName.put(IKeyLookup.END_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.END_NAME)); -// r2_1KeysByName.put(IKeyLookup.INSERT_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.INSERT_NAME)); -// r2_1KeysByName.put(IKeyLookup.F1_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F1_NAME)); -// r2_1KeysByName.put(IKeyLookup.F2_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F2_NAME)); -// r2_1KeysByName.put(IKeyLookup.F3_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F3_NAME)); -// r2_1KeysByName.put(IKeyLookup.F4_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F4_NAME)); -// r2_1KeysByName.put(IKeyLookup.F5_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F5_NAME)); -// r2_1KeysByName.put(IKeyLookup.F6_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F6_NAME)); -// r2_1KeysByName.put(IKeyLookup.F7_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F7_NAME)); -// r2_1KeysByName.put(IKeyLookup.F8_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F8_NAME)); -// r2_1KeysByName.put(IKeyLookup.F9_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F9_NAME)); -// r2_1KeysByName.put(IKeyLookup.F10_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F10_NAME)); -// r2_1KeysByName.put(IKeyLookup.F11_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F11_NAME)); -// r2_1KeysByName.put(IKeyLookup.F12_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F12_NAME)); -// r2_1KeysByName.put(IKeyLookup.F13_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F13_NAME)); -// r2_1KeysByName.put(IKeyLookup.F14_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F14_NAME)); -// r2_1KeysByName.put(IKeyLookup.F15_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F15_NAME)); -// r2_1KeysByName.put(IKeyLookup.F16_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F16_NAME)); -// r2_1KeysByName.put(IKeyLookup.F17_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F17_NAME)); -// r2_1KeysByName.put(IKeyLookup.F18_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F18_NAME)); -// r2_1KeysByName.put(IKeyLookup.F19_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F19_NAME)); -// r2_1KeysByName.put(IKeyLookup.F20_NAME, lookup -// .formalKeyLookupInteger(IKeyLookup.F20_NAME)); -// } -// -// /** -// * Converts a 2.1.x style key sequence (as parsed from the -// * <code>string</code> attribute of the <code>keyBinding</code>) to a -// * 3.1 key sequence. -// * -// * @param r21KeySequence -// * The sequence of 2.1.x key strokes that should be converted -// * into a 3.1 key sequence; never <code>null</code>. -// * @return A 3.1 key sequence; never <code>null</code>. -// */ -// private static final KeySequence convert2_1Sequence(int[] r21KeySequence) { -// final int r21KeySequenceLength = r21KeySequence.length; -// final KeyStroke[] keyStrokes = new KeyStroke[r21KeySequenceLength]; -// for (int i = 0; i < r21KeySequenceLength; i++) { -// keyStrokes[i] = convert2_1Stroke(r21KeySequence[i]); -// } -// -// return KeySequence.getInstance(keyStrokes); -// } -// -// /** -// * Converts a 2.1.x style key stroke (as parsed from the <code>string</code> -// * attribute of the <code>keyBinding</code> to a 3.1 key stroke. -// * -// * @param r21Stroke -// * The 2.1.x stroke to convert; must never be <code>null</code>. -// * @return A 3.1 key stroke; never <code>null</code>. -// */ -// private static final KeyStroke convert2_1Stroke(final int r21Stroke) { -// return SWTKeySupport.convertAcceleratorToKeyStroke(r21Stroke); -// } -// -// /** -// * Returns the default scheme identifier for the currently running -// * application. -// * -// * @return The default scheme identifier (<code>String</code>); never -// * <code>null</code>, but may be empty or point to an undefined -// * scheme. -// */ -// static final String getDefaultSchemeId() { -// final IPreferenceStore store = PlatformUI.getPreferenceStore(); -// return store -// .getDefaultString(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID); -// } -// -// /** -// * Parses a 2.1.x <code>string</code> attribute of the -// * <code>keyBinding</code> element. -// * -// * @param string -// * The string to parse; must not be <code>null</code>. -// * @return An array of integer values -- each integer representing a single -// * key stroke. This array may be empty, but it is never -// * <code>null</code>. -// */ -// private static final int[] parse2_1Sequence(final String string) { -// final StringTokenizer stringTokenizer = new StringTokenizer(string); -// final int length = stringTokenizer.countTokens(); -// final int[] strokes = new int[length]; -// -// for (int i = 0; i < length; i++) { -// strokes[i] = parse2_1Stroke(stringTokenizer.nextToken()); -// } -// -// return strokes; -// } -// -// /** -// * Parses a single 2.1.x key stroke string, as provided by -// * <code>parse2_1Sequence</code>. -// * -// * @param string -// * The string to parse; must not be <code>null</code>. -// * @return An single integer value representing this key stroke. -// */ -// private static final int parse2_1Stroke(final String string) { -// final StringTokenizer stringTokenizer = new StringTokenizer(string, -// KeyStroke.KEY_DELIMITER, true); -// -// // Copy out the tokens so we have random access. -// final int size = stringTokenizer.countTokens(); -// final String[] tokens = new String[size]; -// for (int i = 0; stringTokenizer.hasMoreTokens(); i++) { -// tokens[i] = stringTokenizer.nextToken(); -// } -// -// int value = 0; -// if (size % 2 == 1) { -// String token = tokens[size - 1]; -// final Integer integer = (Integer) r2_1KeysByName.get(token -// .toUpperCase()); -// -// if (integer != null) { -// value = integer.intValue(); -// } else if (token.length() == 1) { -// value = token.toUpperCase().charAt(0); -// } -// -// if (value != 0) { -// for (int i = 0; i < size - 1; i++) { -// token = tokens[i]; -// -// if (i % 2 == 0) { -// if (token.equalsIgnoreCase(IKeyLookup.CTRL_NAME)) { -// if ((value & SWT.CTRL) != 0) { -// return 0; -// } -// -// value |= SWT.CTRL; -// -// } else if (token.equalsIgnoreCase(IKeyLookup.ALT_NAME)) { -// if ((value & SWT.ALT) != 0) { -// return 0; -// } -// -// value |= SWT.ALT; -// -// } else if (token -// .equalsIgnoreCase(IKeyLookup.SHIFT_NAME)) { -// if ((value & SWT.SHIFT) != 0) { -// return 0; -// } -// -// value |= SWT.SHIFT; -// -// } else if (token -// .equalsIgnoreCase(IKeyLookup.COMMAND_NAME)) { -// if ((value & SWT.COMMAND) != 0) { -// return 0; -// } -// -// value |= SWT.COMMAND; -// -// } else { -// return 0; -// -// } -// -// } else if (!KeyStroke.KEY_DELIMITER.equals(token)) { -// return 0; -// } -// } -// } -// } -// -// return value; -// } -// -// /** -// * <p> -// * Reads the registry and the preference store, and determines the -// * identifier for the scheme that should be active. There is a complicated -// * order of priorities for this. The registry will only be read if there is -// * no user preference, and the default active scheme id is different than -// * the default default active scheme id. -// * </p> -// * <ol> -// * <li>A non-default preference.</li> -// * <li>The legacy preference XML memento.</li> -// * <li>A default preference value that is different than the default -// * default active scheme id.</li> -// * <li>The registry.</li> -// * <li>The default default active scheme id.</li> -// * </ol> -// * -// * @param configurationElements -// * The configuration elements from the commands extension point; -// * must not be <code>null</code>. -// * @param configurationElementCount -// * The number of configuration elements that are really in the -// * array. -// * @param preferences -// * The memento wrapping the commands preference key; may be -// * <code>null</code>. -// * @param bindingManager -// * The binding manager that should be updated with the active -// * scheme. This binding manager must already have its schemes -// * defined. This value must not be <code>null</code>. -// */ -// private static final void readActiveScheme( -// final IConfigurationElement[] configurationElements, -// final int configurationElementCount, final IMemento preferences, -// final BindingManager bindingManager) { -// // A non-default preference. -// final IPreferenceStore store = PlatformUI.getPreferenceStore(); -// final String defaultActiveSchemeId = store -// .getDefaultString(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID); -// final String preferenceActiveSchemeId = store -// .getString(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID); -// if ((preferenceActiveSchemeId != null) -// && (!preferenceActiveSchemeId.equals(defaultActiveSchemeId))) { -// try { -// bindingManager.setActiveScheme(bindingManager -// .getScheme(preferenceActiveSchemeId)); -// return; -// } catch (final NotDefinedException e) { -// // Let's keep looking.... -// } -// } -// -// // A legacy preference XML memento. -// if (preferences != null) { -// final IMemento[] preferenceMementos = preferences -// .getChildren(TAG_ACTIVE_KEY_CONFIGURATION); -// int preferenceMementoCount = preferenceMementos.length; -// for (int i = preferenceMementoCount - 1; i >= 0; i--) { -// final IMemento memento = preferenceMementos[i]; -// String id = memento.getString(ATT_KEY_CONFIGURATION_ID); -// if (id != null) { -// try { -// bindingManager.setActiveScheme(bindingManager -// .getScheme(id)); -// return; -// } catch (final NotDefinedException e) { -// // Let's keep looking.... -// } -// } -// } -// } -// -// // A default preference value that is different than the default. -// if ((defaultActiveSchemeId != null && defaultActiveSchemeId.length() > 0) -// && (!defaultActiveSchemeId -// .equals(IBindingService.DEFAULT_DEFAULT_ACTIVE_SCHEME_ID))) { -// try { -// bindingManager.setActiveScheme(bindingManager -// .getScheme(defaultActiveSchemeId)); -// return; -// } catch (final NotDefinedException e) { -// // Let's keep looking.... -// } -// } -// -// // The registry. -// for (int i = configurationElementCount - 1; i >= 0; i--) { -// final IConfigurationElement configurationElement = configurationElements[i]; -// -// String id = configurationElement -// .getAttribute(ATT_KEY_CONFIGURATION_ID); -// if (id != null) { -// try { -// bindingManager -// .setActiveScheme(bindingManager.getScheme(id)); -// return; -// } catch (final NotDefinedException e) { -// // Let's keep looking.... -// } -// } -// -// id = configurationElement.getAttribute(ATT_VALUE); -// if (id != null) { -// try { -// bindingManager -// .setActiveScheme(bindingManager.getScheme(id)); -// return; -// } catch (final NotDefinedException e) { -// // Let's keep looking.... -// } -// } -// } -// -// // The default default active scheme id. -// try { -// bindingManager -// .setActiveScheme(bindingManager -// .getScheme(IBindingService.DEFAULT_DEFAULT_ACTIVE_SCHEME_ID)); -// } catch (final NotDefinedException e) { -// //this is bad - the default default scheme should always exist -// throw new Error( -// "The default default active scheme id is not defined."); //$NON-NLS-1$ -// } -// } -// -// /** -// * Reads all of the binding definitions from the preferences. -// * -// * @param preferences -// * The memento for the commands preferences key. -// * @param bindingManager -// * The binding manager to which the bindings should be added; -// * must not be <code>null</code>. -// * @param commandService -// * The command service for the workbench; must not be -// * <code>null</code>. -// */ -// private static final void readBindingsFromPreferences( -// final IMemento preferences, final BindingManager bindingManager, -// final ICommandService commandService) { -// List warningsToLog = new ArrayList(1); -// -// if (preferences != null) { -// IViewRegistry viewRegistry = PlatformUI.getWorkbench().getViewRegistry(); -// final IMemento[] preferenceMementos = preferences -// .getChildren(TAG_KEY_BINDING); -// int preferenceMementoCount = preferenceMementos.length; -// for (int i = preferenceMementoCount - 1; i >= 0; i--) { -// final IMemento memento = preferenceMementos[i]; -// -// // Read out the command id. -// String commandId = readOptional(memento, ATT_COMMAND_ID); -// if (commandId == null) { -// commandId = readOptional(memento, ATT_COMMAND); -// } -// String viewParameter = null; -// final Command command; -// if (commandId != null) { -// if (viewRegistry.find(commandId) == null) { -// command = commandService.getCommand(commandId); -// } else { -// // we must be able to translate old view commands to the new -// // parameterized command -// viewParameter = commandId; -// command = commandService.getCommand(IWorkbenchCommandConstants.VIEWS_SHOW_VIEW); -// } -// } else { -// command = null; -// } -// -// // Read out the scheme id. -// String schemeId = readOptional(memento, -// ATT_KEY_CONFIGURATION_ID); -// if (schemeId == null) { -// schemeId = readRequired(memento, ATT_CONFIGURATION, -// warningsToLog, -// "Key bindings need a scheme or key configuration"); //$NON-NLS-1$ -// if (schemeId == null) { -// continue; -// } -// } -// -// // Read out the context id. -// String contextId = readOptional(memento, ATT_CONTEXT_ID); -// if (contextId == null) { -// contextId = readOptional(memento, ATT_SCOPE); -// } -// if (LEGACY_DEFAULT_SCOPE.equals(contextId)) { -// contextId = null; -// } -// if (contextId == null) { -// contextId = IContextIds.CONTEXT_ID_WINDOW; -// } -// -// // Read out the key sequence. -// String keySequenceText = readOptional(memento, ATT_KEY_SEQUENCE); -// KeySequence keySequence = null; -// if (keySequenceText == null) { -// keySequenceText = readRequired(memento, ATT_STRING, -// warningsToLog, -// "Key bindings need a key sequence or string"); //$NON-NLS-1$ -// if (keySequenceText == null) { -// continue; -// } -// -// // The key sequence is in the old-style format. -// keySequence = convert2_1Sequence(parse2_1Sequence(keySequenceText)); -// -// } else { -// // The key sequence is in the new-style format. -// try { -// keySequence = KeySequence.getInstance(keySequenceText); -// } catch (final ParseException e) { -// addWarning(warningsToLog, "Could not parse", null, //$NON-NLS-1$ -// commandId, "keySequence", keySequenceText); //$NON-NLS-1$ -// continue; -// } -// if (keySequence.isEmpty() || !keySequence.isComplete()) { -// addWarning( -// warningsToLog, -// "Key bindings cannot use an empty or incomplete key sequence", //$NON-NLS-1$ -// null, commandId, "keySequence", keySequence //$NON-NLS-1$ -// .toString()); -// continue; -// } -// -// } -// -// // Read out the locale and platform. -// final String locale = readOptional(memento, ATT_LOCALE); -// final String platform = readOptional(memento, ATT_PLATFORM); -// -// // Read out the parameters -// final ParameterizedCommand parameterizedCommand; -// if (command == null) { -// parameterizedCommand = null; -// } else if (viewParameter != null) { -// HashMap parms = new HashMap(); -// parms.put(ShowViewMenu.VIEW_ID_PARM, viewParameter); -// parameterizedCommand = ParameterizedCommand.generateCommand(command, parms); -// } else { -// parameterizedCommand = readParameters(memento, -// warningsToLog, command); -// } -// -// final Binding binding = new KeyBinding(keySequence, -// parameterizedCommand, schemeId, contextId, locale, -// platform, null, Binding.USER); -// bindingManager.addBinding(binding); -// } -// } -// -// // If there were any warnings, then log them now. -// logWarnings(warningsToLog, -// "Warnings while parsing the key bindings from the preference store"); //$NON-NLS-1$ -// } -// -// /** -// * Reads all of the binding definitions from the commands extension point. -// * -// * @param configurationElements -// * The configuration elements in the commands extension point; -// * must not be <code>null</code>, but may be empty. -// * @param configurationElementCount -// * The number of configuration elements that are really in the -// * array. -// * @param bindingManager -// * The binding manager to which the bindings should be added; -// * must not be <code>null</code>. -// * @param commandService -// * The command service for the workbench; must not be -// * <code>null</code>. -// */ -// private static final void readBindingsFromRegistry( -// final IConfigurationElement[] configurationElements, -// final int configurationElementCount, -// final BindingManager bindingManager, -// final ICommandService commandService) { -// final Collection bindings = new ArrayList(configurationElementCount); -// final List warningsToLog = new ArrayList(1); -// -// HashSet cocoaTempList = new HashSet(); -// IViewRegistry viewRegistry = PlatformUI.getWorkbench().getViewRegistry(); -// -// // the local cache for the sequence modifiers -// IConfigurationElement[] sequenceModifiers = new IConfigurationElement[0]; -// if(configurationElementCount >0) -// sequenceModifiers = getSequenceModifierElements(configurationElements[0]); -// -// for (int i = 0; i < configurationElementCount; i++) { -// final IConfigurationElement configurationElement = configurationElements[i]; -// -// // different extension. update the cache ... -// if( i>0 && !configurationElement.getDeclaringExtension().equals(configurationElements[i-1].getDeclaringExtension())) -// sequenceModifiers = getSequenceModifierElements(configurationElement); -// -// /* -// * Read out the command id. Doing this before determining if the key -// * binding is actually valid is a bit wasteful. However, it is -// * helpful to have the command identifier when logging syntax -// * errors. -// */ -// String commandId = readCommandId(configurationElement); -// -// String viewParameter = null; -// final Command command; -// if (commandId != null) { -// if (viewRegistry.find(commandId) == null) { -// command = commandService.getCommand(commandId); -// if (!command.isDefined()) { -// // Reference to an undefined command. This is invalid. -// addWarning(warningsToLog, -// "Cannot bind to an undefined command", //$NON-NLS-1$ -// configurationElement, commandId); -// continue; -// } -// } else { -// // we must be able to translate old view commands to the new -// // parameterized command -// viewParameter = commandId; -// command = commandService.getCommand(IWorkbenchCommandConstants.VIEWS_SHOW_VIEW); -// if (DEBUG) { -// Tracing.printTrace("BINDINGS", "Command '" //$NON-NLS-1$ //$NON-NLS-2$ -// + commandId + "\' should be migrated to " //$NON-NLS-1$ -// + IWorkbenchCommandConstants.VIEWS_SHOW_VIEW); -// } -// if (!command.isDefined()) { -// // Reference to an undefined command. This is invalid. -// addWarning(warningsToLog, -// "Cannot bind to an undefined command", //$NON-NLS-1$ -// configurationElement, commandId); -// continue; -// } -// } -// } else { -// command = null; -// } -// -// // Read out the scheme id. -// String schemeId = readSchemeId(configurationElement, warningsToLog, commandId); -// if(isEmpty(schemeId)) -// continue; -// -// // Read out the context id. -// String contextId = readContextId(configurationElement); -// -// String keySequenceText = readKeySequenceText(configurationElement); -// if(isEmpty(keySequenceText)) { -// // The key sequence should never be null. This is pointless -// addWarning( -// warningsToLog, -// "Defining a key binding with no key sequence has no effect", //$NON-NLS-1$ -// configurationElement, commandId); -// continue; -// } -// -// -// -// // Read out the key sequence. -// KeySequence keySequence = readKeySequence(configurationElement, warningsToLog, commandId, keySequenceText); -// if(keySequence == null) -// continue; -// -// // Read out the locale and platform. -// -// String locale = readNonEmptyAttribute(configurationElement, ATT_LOCALE); -// String platform = readNonEmptyAttribute(configurationElement, ATT_PLATFORM); -// -// // Read out the parameters, if any. -// ParameterizedCommand parameterizedCommand = -// readParameterizedCommand(warningsToLog, configurationElement, viewParameter, command); -// -// List modifiedBindings = applyModifiers(keySequence, keySequenceText, platform, sequenceModifiers, parameterizedCommand, schemeId, contextId, locale, warningsToLog); -// -// KeyBinding binding = (KeyBinding) modifiedBindings.get(0); -// if(modifiedBindings.size() > 1) { -// for (int j = 1; j < modifiedBindings.size(); j++) { -// bindings.add(modifiedBindings.get(j)); -// } -// } -// -// if (Util.WS_COCOA.equals(platform)) { -// cocoaTempList.add(binding); -// } else if (Util.WS_CARBON.equals(platform)) { -// bindings.add(binding); -// // temp work around ... simply honour the carbon -// // bindings for cocoa. -// cocoaTempList.add(new KeyBinding(keySequence, -// parameterizedCommand, schemeId, contextId, locale, -// Util.WS_COCOA, null, Binding.SYSTEM)); -// } else { -// bindings.add(binding); -// } -// } -// if (cocoaTempList.size() > 0) { -// bindings.addAll(cocoaTempList); -// } -// -// final Binding[] bindingArray = (Binding[]) bindings -// .toArray(new Binding[bindings.size()]); -// bindingManager.setBindings(bindingArray); -// -// logWarnings( -// warningsToLog, -// "Warnings while parsing the key bindings from the 'org.eclipse.ui.commands' extension point"); //$NON-NLS-1$ -// } -// -// private static List applyModifiers(KeySequence keySequence, String keySequenceText, -// String platform, IConfigurationElement[] sequenceModifiers, -// ParameterizedCommand parameterizedCommand, String schemeId, -// String contextId, String locale, List warningsToLog) { -// -// List bindings = new ArrayList(); -// -// for (int i = 0; i < sequenceModifiers.length; i++) { -// -// IConfigurationElement sequenceModifier = sequenceModifiers[i]; -// String findSequence = sequenceModifier.getAttribute(ATT_FIND); -// -// if (keySequenceText.startsWith(findSequence)) { -// String replaceSequence = sequenceModifier.getAttribute(ATT_REPLACE); -// String modifiedSequence = replaceSequence + keySequenceText.substring(findSequence.length()); -// String platformsString = sequenceModifier.getAttribute(ATT_PLATFORMS); -// -// String[] platforms = parseCommaSeparatedString(platformsString); -// -// try { -// if (platform == null) { -// addGenericBindings(keySequence, parameterizedCommand, schemeId, contextId, locale, -// bindings, modifiedSequence, platforms); -// -// } else { -// getBindingForPlatform(keySequence, platform, -// parameterizedCommand, schemeId, contextId, locale, -// bindings, modifiedSequence, platforms); -// } -// }catch(ParseException e) { -// bindings.clear(); -// addWarning( -// warningsToLog, -// "Cannot create modified sequence for key binding", //$NON-NLS-1$ -// sequenceModifier, parameterizedCommand.getId(), ATT_REPLACE, -// replaceSequence); -// -// } -// break; -// } -// } -// -// if(bindings.size() == 0) { -// // no modifier was applied/error occurred ... -// KeyBinding binding = new KeyBinding(keySequence, -// parameterizedCommand, schemeId, contextId, locale, -// platform, null, Binding.SYSTEM); -// bindings.add(binding); -// } -// -// return bindings; -// } -// -// private static void getBindingForPlatform(KeySequence keySequence, -// String platform, ParameterizedCommand parameterizedCommand, -// String schemeId, String contextId, String locale, List bindings, -// String modifiedSequence, String[] platforms) throws ParseException { -// -// int j = 0; -// for (; j < platforms.length; j++) { -// if(platforms[j].equals(SWT.getPlatform())) { -// KeyBinding newBinding = new KeyBinding(KeySequence -// .getInstance(modifiedSequence), -// parameterizedCommand, schemeId, contextId, -// locale, platforms[j], null, Binding.SYSTEM); -// bindings.add(newBinding); -// break; -// } -// } -// if(j == platforms.length) { -// // platform doesn't match. use the unmodified sequence -// KeyBinding newBinding = new KeyBinding(keySequence, -// parameterizedCommand, schemeId, contextId, -// locale, null, null, Binding.SYSTEM); -// bindings.add(newBinding); -// } -// } -// -// private static void addGenericBindings(KeySequence keySequence, ParameterizedCommand parameterizedCommand, -// String schemeId, String contextId, String locale, List bindings, -// String modifiedSequence, String[] platforms) throws ParseException { -// -// -// KeyBinding originalBinding = new KeyBinding(keySequence, -// parameterizedCommand, schemeId, contextId, locale, null, null, -// Binding.SYSTEM); -// bindings.add(originalBinding); -// -// String platform = SWT.getPlatform(); -// boolean modifierExists = false; -// for (int i = 0; i < platforms.length; i++) { -// if(platforms[i].equals(platform)) { -// modifierExists = true; -// break; -// } -// } -// -// if(modifierExists) { -// KeyBinding newBinding = new KeyBinding(KeySequence.getInstance(modifiedSequence), -// parameterizedCommand, schemeId, contextId, -// locale, SWT.getPlatform(), null, Binding.SYSTEM); -// -// KeyBinding deleteBinding = new KeyBinding(keySequence, -// null, schemeId, contextId, -// locale, SWT.getPlatform(), null, Binding.SYSTEM); -// -// bindings.add(newBinding); -// bindings.add(deleteBinding); -// } -// -// } -// -// private static IConfigurationElement[] getSequenceModifierElements(IConfigurationElement configurationElement) { -// -// IExtension extension = configurationElement.getDeclaringExtension(); -// IConfigurationElement[] configurationElements = extension.getConfigurationElements(); -// List modifierElements = new ArrayList(); -// for (int i = 0; i < configurationElements.length; i++) { -// final IConfigurationElement anElement = configurationElements[i]; -// if(TAG_SEQUENCE_MODIFIER.equals(anElement.getName())) -// modifierElements.add(anElement); -// } -// return (IConfigurationElement[]) modifierElements.toArray(new IConfigurationElement[modifierElements.size()]); -// } -// -// public static String[] parseCommaSeparatedString(String commaSeparatedString) { -// StringTokenizer tokenizer = new StringTokenizer(commaSeparatedString, ", "); //$NON-NLS-1$ -// int count = tokenizer.countTokens(); -// String[] tokens = new String[count]; -// for (int i = 0; i < tokens.length; i++) { -// tokens[i] = tokenizer.nextToken(); -// } -// return tokens; -// } -// -// -// private static String readKeySequenceText(IConfigurationElement configurationElement) { -// -// String keySequenceText = configurationElement.getAttribute(ATT_SEQUENCE); -// if (isEmpty(keySequenceText)) { -// keySequenceText = configurationElement.getAttribute(ATT_KEY_SEQUENCE); -// } -// if (isEmpty(keySequenceText)) -// keySequenceText = configurationElement.getAttribute(ATT_STRING); -// -// return keySequenceText; -// -// } -// -// private static KeySequence readKeySequence(IConfigurationElement configurationElement, List warningsToLog, String commandId, String keySequenceText) { -// -// KeySequence keySequence = null; -// if(keySequenceText.equals(configurationElement.getAttribute(ATT_STRING))){ -// // The key sequence is in the old-style format. -// try { -// keySequence = convert2_1Sequence(parse2_1Sequence(keySequenceText)); -// } catch (final IllegalArgumentException e) { -// addWarning(warningsToLog, "Could not parse key sequence", //$NON-NLS-1$ -// configurationElement, commandId, "keySequence", //$NON-NLS-1$ -// keySequenceText); -// return null; -// } -// } else { -// // The key sequence is in the new-style format. -// try { -// keySequence = KeySequence.getInstance(keySequenceText); -// } catch (final ParseException e) { -// addWarning(warningsToLog, "Could not parse key sequence", //$NON-NLS-1$ -// configurationElement, commandId, "keySequence", //$NON-NLS-1$ -// keySequenceText); -// return null; -// } -// if (keySequence.isEmpty() || !keySequence.isComplete()) { -// addWarning( -// warningsToLog, -// "Key bindings should not have an empty or incomplete key sequence", //$NON-NLS-1$ -// configurationElement, commandId, "keySequence", //$NON-NLS-1$ -// keySequence.toString()); -// return null; -// } -// -// } -// return keySequence; -// } -// -// private static ParameterizedCommand readParameterizedCommand( -// final List warningsToLog, -// final IConfigurationElement configurationElement, -// String viewParameter, final Command command) { -// final ParameterizedCommand parameterizedCommand; -// if (command == null) { -// parameterizedCommand = null; -// } else if (viewParameter != null) { -// HashMap parms = new HashMap(); -// parms.put(ShowViewMenu.VIEW_ID_PARM, viewParameter); -// parameterizedCommand = ParameterizedCommand.generateCommand(command, parms); -// } else { -// parameterizedCommand = readParameters(configurationElement, -// warningsToLog, command); -// } -// return parameterizedCommand; -// } -// -// /** -// * Reads the specified attribute from the configuration element. -// * If the value is an empty string, will return null. -// * -// * @param configurationElement -// * @return the attribute value -// */ -// private static String readNonEmptyAttribute(IConfigurationElement configurationElement, String attribute) { -// String attributeValue = configurationElement.getAttribute(attribute); -// if ((attributeValue != null) && (attributeValue.length() == 0)) { -// attributeValue = null; -// } -// return attributeValue; -// } -// -// -// private static String readContextId( -// final IConfigurationElement configurationElement) { -// String contextId = configurationElement -// .getAttribute(ATT_CONTEXT_ID); -// if (LEGACY_DEFAULT_SCOPE.equals(contextId)) { -// contextId = null; -// } else if ((contextId == null) || (contextId.length() == 0)) { -// contextId = configurationElement.getAttribute(ATT_SCOPE); -// if (LEGACY_DEFAULT_SCOPE.equals(contextId)) { -// contextId = null; -// } -// } -// if ((contextId == null) || (contextId.length() == 0)) { -// contextId = IContextIds.CONTEXT_ID_WINDOW; -// } -// return contextId; -// } -// -// -// private static String readSchemeId(IConfigurationElement configurationElement, List warningsToLog, String commandId) { -// -// String schemeId = configurationElement.getAttribute(ATT_SCHEME_ID); -// if ((schemeId == null) || (schemeId.length() == 0)) { -// schemeId = configurationElement -// .getAttribute(ATT_KEY_CONFIGURATION_ID); -// if ((schemeId == null) || (schemeId.length() == 0)) { -// schemeId = configurationElement -// .getAttribute(ATT_CONFIGURATION); -// if ((schemeId == null) || (schemeId.length() == 0)) { -// // The scheme id should never be null. This is invalid. -// addWarning(warningsToLog, "Key bindings need a scheme", //$NON-NLS-1$ -// configurationElement, commandId); -// } -// } -// } -// return schemeId; -// } -// -// private static String readCommandId( -// final IConfigurationElement configurationElement) { -// String commandId = configurationElement -// .getAttribute(ATT_COMMAND_ID); -// if ((commandId == null) || (commandId.length() == 0)) { -// commandId = configurationElement.getAttribute(ATT_COMMAND); -// } -// if ((commandId != null) && (commandId.length() == 0)) { -// commandId = null; -// } -// return commandId; -// } -// -// private static boolean isEmpty(String string) { -// return string == null || string.length() == 0; -// } -// -// /** -// * Reads all of the scheme definitions from the registry. -// * -// * @param configurationElements -// * The configuration elements in the commands extension point; -// * must not be <code>null</code>, but may be empty. -// * @param configurationElementCount -// * The number of configuration elements that are really in the -// * array. -// * @param bindingManager -// * The binding manager to which the schemes should be added; must -// * not be <code>null</code>. -// */ -// private static final void readSchemesFromRegistry( -// final IConfigurationElement[] configurationElements, -// final int configurationElementCount, -// final BindingManager bindingManager) { -// // Undefine all the previous handle objects. -// final HandleObject[] handleObjects = bindingManager.getDefinedSchemes(); -// if (handleObjects != null) { -// for (int i = 0; i < handleObjects.length; i++) { -// handleObjects[i].undefine(); -// } -// } -// -// final List warningsToLog = new ArrayList(1); -// -// for (int i = 0; i < configurationElementCount; i++) { -// final IConfigurationElement configurationElement = configurationElements[i]; -// -// // Read out the attributes. -// final String id = readRequired(configurationElement, ATT_ID, -// warningsToLog, "Schemes need an id"); //$NON-NLS-1$ -// if (id == null) { -// continue; -// } -// final String name = readRequired(configurationElement, ATT_NAME, -// warningsToLog, "A scheme needs a name", id); //$NON-NLS-1$ -// if (name == null) { -// continue; -// } -// final String description = readOptional(configurationElement, -// ATT_DESCRIPTION); -// -// String parentId = configurationElement.getAttribute(ATT_PARENT_ID); -// if ((parentId != null) && (parentId.length() == 0)) { -// parentId = configurationElement.getAttribute(ATT_PARENT); -// if ((parentId != null) && (parentId.length() == 0)) { -// parentId = null; -// } -// } -// -// // Define the scheme. -// final Scheme scheme = bindingManager.getScheme(id); -// scheme.define(name, description, parentId); -// } -// -// logWarnings( -// warningsToLog, -// "Warnings while parsing the key bindings from the 'org.eclipse.ui.bindings', 'org.eclipse.ui.acceleratorConfigurations' and 'org.eclipse.ui.commands' extension point"); //$NON-NLS-1$ -// } -// -// /** -// * Writes the given active scheme and bindings to the preference store. Only -// * bindings that are of the <code>Binding.USER</code> type will be -// * written; the others will be ignored. -// * -// * @param activeScheme -// * The scheme which should be persisted; may be <code>null</code>. -// * @param bindings -// * The bindings which should be persisted; may be -// * <code>null</code> -// * @throws IOException -// * If something happens while trying to write to the workbench -// * preference store. -// */ -// static final void write(final Scheme activeScheme, final Binding[] bindings) -// throws IOException { -// // Print out debugging information, if requested. -// if (DEBUG) { -// Tracing.printTrace("BINDINGS", "Persisting active scheme '" //$NON-NLS-1$ //$NON-NLS-2$ -// + activeScheme.getId() + '\''); -// Tracing.printTrace("BINDINGS", "Persisting bindings"); //$NON-NLS-1$ //$NON-NLS-2$ -// } -// -// // Write the simple preference key to the UI preference store. -// writeActiveScheme(activeScheme); -// -// // Build the XML block for writing the bindings and active scheme. -// final XMLMemento xmlMemento = XMLMemento -// .createWriteRoot(EXTENSION_COMMANDS); -// if (activeScheme != null) { -// writeActiveSchemeToPreferences(xmlMemento, activeScheme); -// } -// if (bindings != null) { -// final int bindingsLength = bindings.length; -// for (int i = 0; i < bindingsLength; i++) { -// final Binding binding = bindings[i]; -// if (binding.getType() == Binding.USER) { -// writeBindingToPreferences(xmlMemento, binding); -// } -// } -// } -// -// // Write the XML block to the workbench preference store. -// final IPreferenceStore preferenceStore = WorkbenchPlugin.getDefault() -// .getPreferenceStore(); -// final Writer writer = new StringWriter(); -// try { -// xmlMemento.save(writer); -// preferenceStore.setValue(EXTENSION_COMMANDS, writer.toString()); -// } finally { -// writer.close(); -// } -// } -// -// /** -// * Writes the active scheme to its own preference key. This key is used by -// * RCP applications as part of their plug-in customization. -// * -// * @param scheme -// * The scheme to write to the preference store. If the scheme is -// * <code>null</code>, then it is removed. -// */ -// private static final void writeActiveScheme(final Scheme scheme) { -// final IPreferenceStore store = PlatformUI.getPreferenceStore(); -// final String schemeId = (scheme == null) ? null : scheme.getId(); -// final String defaultSchemeId = store -// .getDefaultString(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID); -// if ((defaultSchemeId == null) ? (scheme != null) : (!defaultSchemeId -// .equals(schemeId))) { -// store.setValue(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID, -// scheme.getId()); -// } else { -// store -// .setToDefault(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID); -// } -// } -// -// /** -// * Writes the active scheme to the memento. If the scheme is -// * <code>null</code>, then all schemes in the memento are removed. -// * -// * @param memento -// * The memento to which the scheme should be written; must not be -// * <code>null</code>. -// * @param scheme -// * The scheme that should be written; must not be -// * <code>null</code>. -// */ -// private static final void writeActiveSchemeToPreferences( -// final IMemento memento, final Scheme scheme) { -// // Add this active scheme, if it is not the default. -// final IPreferenceStore store = PlatformUI.getPreferenceStore(); -// final String schemeId = scheme.getId(); -// final String defaultSchemeId = store -// .getDefaultString(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID); -// if ((defaultSchemeId == null) ? (schemeId != null) : (!defaultSchemeId -// .equals(schemeId))) { -// final IMemento child = memento -// .createChild(TAG_ACTIVE_KEY_CONFIGURATION); -// child.putString(ATT_KEY_CONFIGURATION_ID, schemeId); -// } -// } -// -// /** -// * Writes the binding to the memento. This creates a new child element on -// * the memento, and places the properties of the binding as its attributes. -// * -// * @param parent -// * The parent memento for the binding element; must not be -// * <code>null</code>. -// * @param binding -// * The binding to write; must not be <code>null</code>. -// */ -// private static final void writeBindingToPreferences(final IMemento parent, -// final Binding binding) { -// final IMemento element = parent.createChild(TAG_KEY_BINDING); -// element.putString(ATT_CONTEXT_ID, binding.getContextId()); -// final ParameterizedCommand parameterizedCommand = binding -// .getParameterizedCommand(); -// final String commandId = (parameterizedCommand == null) ? null -// : parameterizedCommand.getId(); -// element.putString(ATT_COMMAND_ID, commandId); -// element.putString(ATT_KEY_CONFIGURATION_ID, binding.getSchemeId()); -// element.putString(ATT_KEY_SEQUENCE, binding.getTriggerSequence() -// .toString()); -// element.putString(ATT_LOCALE, binding.getLocale()); -// element.putString(ATT_PLATFORM, binding.getPlatform()); -// if (parameterizedCommand != null) { -// final Map parameterizations = parameterizedCommand -// .getParameterMap(); -// final Iterator parameterizationItr = parameterizations.entrySet() -// .iterator(); -// while (parameterizationItr.hasNext()) { -// final Map.Entry entry = (Map.Entry) parameterizationItr.next(); -// final String id = (String) entry.getKey(); -// final String value = (String) entry.getValue(); -// final IMemento parameterElement = element -// .createChild(TAG_PARAMETER); -// parameterElement.putString(ATT_ID, id); -// parameterElement.putString(ATT_VALUE, value); -// } -// } -// } -// -// /** -// * The binding manager which should be populated with the values from the -// * registry and preference store; must not be <code>null</code>. -// */ -// private final BindingManager bindingManager; -// -// /** -// * The command service for the workbench; must not be <code>null</code>. -// */ -// private final ICommandService commandService; -// -// /** -// * Constructs a new instance of <code>BindingPersistence</code>. -// * -// * @param bindingManager -// * The binding manager which should be populated with the values -// * from the registry and preference store; must not be -// * <code>null</code>. -// * @param commandService -// * The command service for the workbench; must not be -// * <code>null</code>. -// */ -// BindingPersistence(final BindingManager bindingManager, -// final ICommandService commandService) { -// this.bindingManager = bindingManager; -// this.commandService = commandService; -// } -// -// protected final boolean isChangeImportant(final IRegistryChangeEvent event) { -// return false; -// } -// -// public boolean bindingsNeedUpdating(final IRegistryChangeEvent event) { -// final IExtensionDelta[] acceleratorConfigurationDeltas = event -// .getExtensionDeltas( -// PlatformUI.PLUGIN_ID, -// IWorkbenchRegistryConstants.PL_ACCELERATOR_CONFIGURATIONS); -// if (acceleratorConfigurationDeltas.length == 0) { -// final IExtensionDelta[] bindingDeltas = event.getExtensionDeltas( -// PlatformUI.PLUGIN_ID, -// IWorkbenchRegistryConstants.PL_BINDINGS); -// if (bindingDeltas.length == 0) { -// final IExtensionDelta[] commandDeltas = event -// .getExtensionDeltas(PlatformUI.PLUGIN_ID, -// IWorkbenchRegistryConstants.PL_COMMANDS); -// if (commandDeltas.length == 0) { -// final IExtensionDelta[] acceleratorScopeDeltas = event -// .getExtensionDeltas( -// PlatformUI.PLUGIN_ID, -// IWorkbenchRegistryConstants.PL_ACCELERATOR_SCOPES); -// if (acceleratorScopeDeltas.length == 0) { -// final IExtensionDelta[] contextDeltas = event -// .getExtensionDeltas(PlatformUI.PLUGIN_ID, -// IWorkbenchRegistryConstants.PL_CONTEXTS); -// if (contextDeltas.length == 0) { -// final IExtensionDelta[] actionDefinitionDeltas = event -// .getExtensionDeltas( -// PlatformUI.PLUGIN_ID, -// IWorkbenchRegistryConstants.PL_ACTION_DEFINITIONS); -// if (actionDefinitionDeltas.length == 0) { -// return false; -// } -// } -// } -// } -// } -// } -// -// return true; -// } -// -// protected final boolean isChangeImportant(final PropertyChangeEvent event) { -// return EXTENSION_COMMANDS.equals(event.getProperty()); -// } -// -// /** -// * Reads all of the binding information from the registry and from the -// * preference store. -// */ -// protected final void read() { -// super.read(); -// reRead(); -// } -// -// public void reRead() { -// // Create the extension registry mementos. -// final IExtensionRegistry registry = Platform.getExtensionRegistry(); -// int activeSchemeElementCount = 0; -// int bindingDefinitionCount = 0; -// int schemeDefinitionCount = 0; -// final IConfigurationElement[][] indexedConfigurationElements = new IConfigurationElement[3][]; -// -// // Sort the bindings extension point based on element name. -// final IConfigurationElement[] bindingsExtensionPoint = registry -// .getConfigurationElementsFor(EXTENSION_BINDINGS); -// for (int i = 0; i < bindingsExtensionPoint.length; i++) { -// final IConfigurationElement configurationElement = bindingsExtensionPoint[i]; -// final String name = configurationElement.getName(); -// -// // Check if it is a binding definition. -// if (TAG_KEY.equals(name)) { -// addElementToIndexedArray(configurationElement, -// indexedConfigurationElements, -// INDEX_BINDING_DEFINITIONS, bindingDefinitionCount++); -// } else -// // Check to see if it is a scheme definition. -// if (TAG_SCHEME.equals(name)) { -// addElementToIndexedArray(configurationElement, -// indexedConfigurationElements, INDEX_SCHEME_DEFINITIONS, -// schemeDefinitionCount++); -// } -// -// } -// -// // Sort the commands extension point based on element name. -// final IConfigurationElement[] commandsExtensionPoint = registry -// .getConfigurationElementsFor(EXTENSION_COMMANDS); -// for (int i = 0; i < commandsExtensionPoint.length; i++) { -// final IConfigurationElement configurationElement = commandsExtensionPoint[i]; -// final String name = configurationElement.getName(); -// -// // Check if it is a binding definition. -// if (TAG_KEY_BINDING.equals(name)) { -// addElementToIndexedArray(configurationElement, -// indexedConfigurationElements, -// INDEX_BINDING_DEFINITIONS, bindingDefinitionCount++); -// -// // Check if it is a scheme defintion. -// } else if (TAG_KEY_CONFIGURATION.equals(name)) { -// addElementToIndexedArray(configurationElement, -// indexedConfigurationElements, INDEX_SCHEME_DEFINITIONS, -// schemeDefinitionCount++); -// -// // Check if it is an active scheme identifier. -// } else if (TAG_ACTIVE_KEY_CONFIGURATION.equals(name)) { -// addElementToIndexedArray(configurationElement, -// indexedConfigurationElements, INDEX_ACTIVE_SCHEME, -// activeSchemeElementCount++); -// } -// } -// -// /* -// * Sort the accelerator configuration extension point into the scheme -// * definitions. -// */ -// final IConfigurationElement[] acceleratorConfigurationsExtensionPoint = registry -// .getConfigurationElementsFor(EXTENSION_ACCELERATOR_CONFIGURATIONS); -// for (int i = 0; i < acceleratorConfigurationsExtensionPoint.length; i++) { -// final IConfigurationElement configurationElement = acceleratorConfigurationsExtensionPoint[i]; -// final String name = configurationElement.getName(); -// -// // Check if the name matches the accelerator configuration element -// if (TAG_ACCELERATOR_CONFIGURATION.equals(name)) { -// addElementToIndexedArray(configurationElement, -// indexedConfigurationElements, INDEX_SCHEME_DEFINITIONS, -// schemeDefinitionCount++); -// } -// } -// -// // Create the preference memento. -// final IPreferenceStore store = WorkbenchPlugin.getDefault() -// .getPreferenceStore(); -// final String preferenceString = store.getString(EXTENSION_COMMANDS); -// IMemento preferenceMemento = null; -// if ((preferenceString != null) && (preferenceString.length() > 0)) { -// final Reader reader = new StringReader(preferenceString); -// try { -// preferenceMemento = XMLMemento.createReadRoot(reader); -// } catch (final WorkbenchException e) { -// // Could not initialize the preference memento. -// } -// } -// -// // Read the scheme definitions. -// readSchemesFromRegistry( -// indexedConfigurationElements[INDEX_SCHEME_DEFINITIONS], -// schemeDefinitionCount, bindingManager); -// readActiveScheme(indexedConfigurationElements[INDEX_ACTIVE_SCHEME], -// activeSchemeElementCount, preferenceMemento, bindingManager); -// readBindingsFromRegistry( -// indexedConfigurationElements[INDEX_BINDING_DEFINITIONS], -// bindingDefinitionCount, bindingManager, commandService); -// readBindingsFromPreferences(preferenceMemento, bindingManager, -// commandService); -// } -//} +/******************************************************************************* + * Copyright (c) 2005, 2009 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.keys; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.ParameterizedCommand; +import org.eclipse.core.commands.common.HandleObject; +import org.eclipse.core.commands.common.NotDefinedException; +import org.eclipse.core.commands.util.Tracing; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtension; +import org.eclipse.core.runtime.IExtensionDelta; +import org.eclipse.core.runtime.IExtensionRegistry; +import org.eclipse.core.runtime.IRegistryChangeEvent; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.bindings.Binding; +import org.eclipse.jface.bindings.BindingManager; +import org.eclipse.jface.bindings.Scheme; +import org.eclipse.jface.bindings.keys.IKeyLookup; +import org.eclipse.jface.bindings.keys.KeyBinding; +import org.eclipse.jface.bindings.keys.KeyLookupFactory; +import org.eclipse.jface.bindings.keys.KeySequence; +import org.eclipse.jface.bindings.keys.KeyStroke; +import org.eclipse.jface.bindings.keys.ParseException; +import org.eclipse.jface.bindings.keys.SWTKeySupport; +import org.eclipse.jface.contexts.IContextIds; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.jface.util.Util; +import org.eclipse.swt.SWT; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.IWorkbenchCommandConstants; +import org.eclipse.ui.IWorkbenchPreferenceConstants; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.WorkbenchException; +import org.eclipse.ui.XMLMemento; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.internal.ShowViewMenu; +import org.eclipse.ui.internal.WorkbenchPlugin; +import org.eclipse.ui.internal.misc.Policy; +import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants; +import org.eclipse.ui.internal.services.PreferencePersistence; +import org.eclipse.ui.keys.IBindingService; +import org.eclipse.ui.views.IViewRegistry; + +/** + * <p> + * A static class for accessing the registry and the preference store. + * </p> + * + * @since 3.1 + */ +public final class BindingPersistence extends PreferencePersistence { + + /** + * Whether this class should print out debugging information when it reads + * in data, or writes to the preference store. + */ + private static final boolean DEBUG = Policy.DEBUG_KEY_BINDINGS; + + /** + * The index of the active scheme configuration elements in the indexed + * array. + * + * @see BindingPersistence#read() + */ + private static final int INDEX_ACTIVE_SCHEME = 0; + + /** + * The index of the binding definition configuration elements in the indexed + * array. + * + * @see BindingPersistence#read() + */ + private static final int INDEX_BINDING_DEFINITIONS = 1; + + /** + * The index of the scheme definition configuration elements in the indexed + * array. + * + * @see BindingPersistence#read() + */ + private static final int INDEX_SCHEME_DEFINITIONS = 2; + + /** + * The name of the default scope in 2.1.x. + */ + private static final String LEGACY_DEFAULT_SCOPE = "org.eclipse.ui.globalScope"; //$NON-NLS-1$ + + /** + * A look-up map for 2.1.x style <code>string</code> keys on a + * <code>keyBinding</code> element. + */ + private static final Map r2_1KeysByName = new HashMap(); + + static { + final IKeyLookup lookup = KeyLookupFactory.getDefault(); + r2_1KeysByName.put(IKeyLookup.BACKSPACE_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.BACKSPACE_NAME)); + r2_1KeysByName.put(IKeyLookup.TAB_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.TAB_NAME)); + r2_1KeysByName.put(IKeyLookup.RETURN_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.RETURN_NAME)); + r2_1KeysByName.put(IKeyLookup.ENTER_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.ENTER_NAME)); + r2_1KeysByName.put(IKeyLookup.ESCAPE_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.ESCAPE_NAME)); + r2_1KeysByName.put(IKeyLookup.ESC_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.ESC_NAME)); + r2_1KeysByName.put(IKeyLookup.DELETE_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.DELETE_NAME)); + r2_1KeysByName.put(IKeyLookup.SPACE_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.SPACE_NAME)); + r2_1KeysByName.put(IKeyLookup.ARROW_UP_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.ARROW_UP_NAME)); + r2_1KeysByName.put(IKeyLookup.ARROW_DOWN_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.ARROW_DOWN_NAME)); + r2_1KeysByName.put(IKeyLookup.ARROW_LEFT_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.ARROW_LEFT_NAME)); + r2_1KeysByName.put(IKeyLookup.ARROW_RIGHT_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.ARROW_RIGHT_NAME)); + r2_1KeysByName.put(IKeyLookup.PAGE_UP_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.PAGE_UP_NAME)); + r2_1KeysByName.put(IKeyLookup.PAGE_DOWN_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.PAGE_DOWN_NAME)); + r2_1KeysByName.put(IKeyLookup.HOME_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.HOME_NAME)); + r2_1KeysByName.put(IKeyLookup.END_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.END_NAME)); + r2_1KeysByName.put(IKeyLookup.INSERT_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.INSERT_NAME)); + r2_1KeysByName.put(IKeyLookup.F1_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F1_NAME)); + r2_1KeysByName.put(IKeyLookup.F2_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F2_NAME)); + r2_1KeysByName.put(IKeyLookup.F3_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F3_NAME)); + r2_1KeysByName.put(IKeyLookup.F4_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F4_NAME)); + r2_1KeysByName.put(IKeyLookup.F5_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F5_NAME)); + r2_1KeysByName.put(IKeyLookup.F6_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F6_NAME)); + r2_1KeysByName.put(IKeyLookup.F7_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F7_NAME)); + r2_1KeysByName.put(IKeyLookup.F8_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F8_NAME)); + r2_1KeysByName.put(IKeyLookup.F9_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F9_NAME)); + r2_1KeysByName.put(IKeyLookup.F10_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F10_NAME)); + r2_1KeysByName.put(IKeyLookup.F11_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F11_NAME)); + r2_1KeysByName.put(IKeyLookup.F12_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F12_NAME)); + r2_1KeysByName.put(IKeyLookup.F13_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F13_NAME)); + r2_1KeysByName.put(IKeyLookup.F14_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F14_NAME)); + r2_1KeysByName.put(IKeyLookup.F15_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F15_NAME)); + r2_1KeysByName.put(IKeyLookup.F16_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F16_NAME)); + r2_1KeysByName.put(IKeyLookup.F17_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F17_NAME)); + r2_1KeysByName.put(IKeyLookup.F18_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F18_NAME)); + r2_1KeysByName.put(IKeyLookup.F19_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F19_NAME)); + r2_1KeysByName.put(IKeyLookup.F20_NAME, lookup + .formalKeyLookupInteger(IKeyLookup.F20_NAME)); + } + + /** + * Converts a 2.1.x style key sequence (as parsed from the + * <code>string</code> attribute of the <code>keyBinding</code>) to a + * 3.1 key sequence. + * + * @param r21KeySequence + * The sequence of 2.1.x key strokes that should be converted + * into a 3.1 key sequence; never <code>null</code>. + * @return A 3.1 key sequence; never <code>null</code>. + */ + private static final KeySequence convert2_1Sequence(int[] r21KeySequence) { + final int r21KeySequenceLength = r21KeySequence.length; + final KeyStroke[] keyStrokes = new KeyStroke[r21KeySequenceLength]; + for (int i = 0; i < r21KeySequenceLength; i++) { + keyStrokes[i] = convert2_1Stroke(r21KeySequence[i]); + } + + return KeySequence.getInstance(keyStrokes); + } + + /** + * Converts a 2.1.x style key stroke (as parsed from the <code>string</code> + * attribute of the <code>keyBinding</code> to a 3.1 key stroke. + * + * @param r21Stroke + * The 2.1.x stroke to convert; must never be <code>null</code>. + * @return A 3.1 key stroke; never <code>null</code>. + */ + private static final KeyStroke convert2_1Stroke(final int r21Stroke) { + return SWTKeySupport.convertAcceleratorToKeyStroke(r21Stroke); + } + + /** + * Returns the default scheme identifier for the currently running + * application. + * + * @return The default scheme identifier (<code>String</code>); never + * <code>null</code>, but may be empty or point to an undefined + * scheme. + */ + static final String getDefaultSchemeId() { + final IPreferenceStore store = PlatformUI.getPreferenceStore(); + return store + .getDefaultString(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID); + } + + /** + * Parses a 2.1.x <code>string</code> attribute of the + * <code>keyBinding</code> element. + * + * @param string + * The string to parse; must not be <code>null</code>. + * @return An array of integer values -- each integer representing a single + * key stroke. This array may be empty, but it is never + * <code>null</code>. + */ + private static final int[] parse2_1Sequence(final String string) { + final StringTokenizer stringTokenizer = new StringTokenizer(string); + final int length = stringTokenizer.countTokens(); + final int[] strokes = new int[length]; + + for (int i = 0; i < length; i++) { + strokes[i] = parse2_1Stroke(stringTokenizer.nextToken()); + } + + return strokes; + } + + /** + * Parses a single 2.1.x key stroke string, as provided by + * <code>parse2_1Sequence</code>. + * + * @param string + * The string to parse; must not be <code>null</code>. + * @return An single integer value representing this key stroke. + */ + private static final int parse2_1Stroke(final String string) { + final StringTokenizer stringTokenizer = new StringTokenizer(string, + KeyStroke.KEY_DELIMITER, true); + + // Copy out the tokens so we have random access. + final int size = stringTokenizer.countTokens(); + final String[] tokens = new String[size]; + for (int i = 0; stringTokenizer.hasMoreTokens(); i++) { + tokens[i] = stringTokenizer.nextToken(); + } + + int value = 0; + if (size % 2 == 1) { + String token = tokens[size - 1]; + final Integer integer = (Integer) r2_1KeysByName.get(token + .toUpperCase()); + + if (integer != null) { + value = integer.intValue(); + } else if (token.length() == 1) { + value = token.toUpperCase().charAt(0); + } + + if (value != 0) { + for (int i = 0; i < size - 1; i++) { + token = tokens[i]; + + if (i % 2 == 0) { + if (token.equalsIgnoreCase(IKeyLookup.CTRL_NAME)) { + if ((value & SWT.CTRL) != 0) { + return 0; + } + + value |= SWT.CTRL; + + } else if (token.equalsIgnoreCase(IKeyLookup.ALT_NAME)) { + if ((value & SWT.ALT) != 0) { + return 0; + } + + value |= SWT.ALT; + + } else if (token + .equalsIgnoreCase(IKeyLookup.SHIFT_NAME)) { + if ((value & SWT.SHIFT) != 0) { + return 0; + } + + value |= SWT.SHIFT; + + } else if (token + .equalsIgnoreCase(IKeyLookup.COMMAND_NAME)) { + if ((value & SWT.COMMAND) != 0) { + return 0; + } + + value |= SWT.COMMAND; + + } else { + return 0; + + } + + } else if (!KeyStroke.KEY_DELIMITER.equals(token)) { + return 0; + } + } + } + } + + return value; + } + + /** + * <p> + * Reads the registry and the preference store, and determines the + * identifier for the scheme that should be active. There is a complicated + * order of priorities for this. The registry will only be read if there is + * no user preference, and the default active scheme id is different than + * the default default active scheme id. + * </p> + * <ol> + * <li>A non-default preference.</li> + * <li>The legacy preference XML memento.</li> + * <li>A default preference value that is different than the default + * default active scheme id.</li> + * <li>The registry.</li> + * <li>The default default active scheme id.</li> + * </ol> + * + * @param configurationElements + * The configuration elements from the commands extension point; + * must not be <code>null</code>. + * @param configurationElementCount + * The number of configuration elements that are really in the + * array. + * @param preferences + * The memento wrapping the commands preference key; may be + * <code>null</code>. + * @param bindingManager + * The binding manager that should be updated with the active + * scheme. This binding manager must already have its schemes + * defined. This value must not be <code>null</code>. + */ + private static final void readActiveScheme( + final IConfigurationElement[] configurationElements, + final int configurationElementCount, final IMemento preferences, + final BindingManager bindingManager) { + // A non-default preference. + final IPreferenceStore store = PlatformUI.getPreferenceStore(); + final String defaultActiveSchemeId = store + .getDefaultString(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID); + final String preferenceActiveSchemeId = store + .getString(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID); + if ((preferenceActiveSchemeId != null) + && (!preferenceActiveSchemeId.equals(defaultActiveSchemeId))) { + try { + bindingManager.setActiveScheme(bindingManager + .getScheme(preferenceActiveSchemeId)); + return; + } catch (final NotDefinedException e) { + // Let's keep looking.... + } + } + + // A legacy preference XML memento. + if (preferences != null) { + final IMemento[] preferenceMementos = preferences + .getChildren(TAG_ACTIVE_KEY_CONFIGURATION); + int preferenceMementoCount = preferenceMementos.length; + for (int i = preferenceMementoCount - 1; i >= 0; i--) { + final IMemento memento = preferenceMementos[i]; + String id = memento.getString(ATT_KEY_CONFIGURATION_ID); + if (id != null) { + try { + bindingManager.setActiveScheme(bindingManager + .getScheme(id)); + return; + } catch (final NotDefinedException e) { + // Let's keep looking.... + } + } + } + } + + // A default preference value that is different than the default. + if ((defaultActiveSchemeId != null && defaultActiveSchemeId.length() > 0) + && (!defaultActiveSchemeId + .equals(IBindingService.DEFAULT_DEFAULT_ACTIVE_SCHEME_ID))) { + try { + bindingManager.setActiveScheme(bindingManager + .getScheme(defaultActiveSchemeId)); + return; + } catch (final NotDefinedException e) { + // Let's keep looking.... + } + } + + // The registry. + for (int i = configurationElementCount - 1; i >= 0; i--) { + final IConfigurationElement configurationElement = configurationElements[i]; + + String id = configurationElement + .getAttribute(ATT_KEY_CONFIGURATION_ID); + if (id != null) { + try { + bindingManager + .setActiveScheme(bindingManager.getScheme(id)); + return; + } catch (final NotDefinedException e) { + // Let's keep looking.... + } + } + + id = configurationElement.getAttribute(ATT_VALUE); + if (id != null) { + try { + bindingManager + .setActiveScheme(bindingManager.getScheme(id)); + return; + } catch (final NotDefinedException e) { + // Let's keep looking.... + } + } + } + + // The default default active scheme id. + try { + bindingManager + .setActiveScheme(bindingManager + .getScheme(IBindingService.DEFAULT_DEFAULT_ACTIVE_SCHEME_ID)); + } catch (final NotDefinedException e) { + //this is bad - the default default scheme should always exist + throw new Error( + "The default default active scheme id is not defined."); //$NON-NLS-1$ + } + } + + /** + * Reads all of the binding definitions from the preferences. + * + * @param preferences + * The memento for the commands preferences key. + * @param bindingManager + * The binding manager to which the bindings should be added; + * must not be <code>null</code>. + * @param commandService + * The command service for the workbench; must not be + * <code>null</code>. + */ + private static final void readBindingsFromPreferences( + final IMemento preferences, final BindingManager bindingManager, + final ICommandService commandService) { + List warningsToLog = new ArrayList(1); + + if (preferences != null) { + IViewRegistry viewRegistry = PlatformUI.getWorkbench().getViewRegistry(); + final IMemento[] preferenceMementos = preferences + .getChildren(TAG_KEY_BINDING); + int preferenceMementoCount = preferenceMementos.length; + for (int i = preferenceMementoCount - 1; i >= 0; i--) { + final IMemento memento = preferenceMementos[i]; + + // Read out the command id. + String commandId = readOptional(memento, ATT_COMMAND_ID); + if (commandId == null) { + commandId = readOptional(memento, ATT_COMMAND); + } + String viewParameter = null; + final Command command; + if (commandId != null) { + if (viewRegistry.find(commandId) == null) { + command = commandService.getCommand(commandId); + } else { + // we must be able to translate old view commands to the new + // parameterized command + viewParameter = commandId; + command = commandService.getCommand(IWorkbenchCommandConstants.VIEWS_SHOW_VIEW); + } + } else { + command = null; + } + + // Read out the scheme id. + String schemeId = readOptional(memento, + ATT_KEY_CONFIGURATION_ID); + if (schemeId == null) { + schemeId = readRequired(memento, ATT_CONFIGURATION, + warningsToLog, + "Key bindings need a scheme or key configuration"); //$NON-NLS-1$ + if (schemeId == null) { + continue; + } + } + + // Read out the context id. + String contextId = readOptional(memento, ATT_CONTEXT_ID); + if (contextId == null) { + contextId = readOptional(memento, ATT_SCOPE); + } + if (LEGACY_DEFAULT_SCOPE.equals(contextId)) { + contextId = null; + } + if (contextId == null) { + contextId = IContextIds.CONTEXT_ID_WINDOW; + } + + // Read out the key sequence. + String keySequenceText = readOptional(memento, ATT_KEY_SEQUENCE); + KeySequence keySequence = null; + if (keySequenceText == null) { + keySequenceText = readRequired(memento, ATT_STRING, + warningsToLog, + "Key bindings need a key sequence or string"); //$NON-NLS-1$ + if (keySequenceText == null) { + continue; + } + + // The key sequence is in the old-style format. + keySequence = convert2_1Sequence(parse2_1Sequence(keySequenceText)); + + } else { + // The key sequence is in the new-style format. + try { + keySequence = KeySequence.getInstance(keySequenceText); + } catch (final ParseException e) { + addWarning(warningsToLog, "Could not parse", null, //$NON-NLS-1$ + commandId, "keySequence", keySequenceText); //$NON-NLS-1$ + continue; + } + if (keySequence.isEmpty() || !keySequence.isComplete()) { + addWarning( + warningsToLog, + "Key bindings cannot use an empty or incomplete key sequence", //$NON-NLS-1$ + null, commandId, "keySequence", keySequence //$NON-NLS-1$ + .toString()); + continue; + } + + } + + // Read out the locale and platform. + final String locale = readOptional(memento, ATT_LOCALE); + final String platform = readOptional(memento, ATT_PLATFORM); + + // Read out the parameters + final ParameterizedCommand parameterizedCommand; + if (command == null) { + parameterizedCommand = null; + } else if (viewParameter != null) { + HashMap parms = new HashMap(); + parms.put(ShowViewMenu.VIEW_ID_PARM, viewParameter); + parameterizedCommand = ParameterizedCommand.generateCommand(command, parms); + } else { + parameterizedCommand = readParameters(memento, + warningsToLog, command); + } + + final Binding binding = new KeyBinding(keySequence, + parameterizedCommand, schemeId, contextId, locale, + platform, null, Binding.USER); + bindingManager.addBinding(binding); + } + } + + // If there were any warnings, then log them now. + logWarnings(warningsToLog, + "Warnings while parsing the key bindings from the preference store"); //$NON-NLS-1$ + } + + /** + * Reads all of the binding definitions from the commands extension point. + * + * @param configurationElements + * The configuration elements in the commands extension point; + * must not be <code>null</code>, but may be empty. + * @param configurationElementCount + * The number of configuration elements that are really in the + * array. + * @param bindingManager + * The binding manager to which the bindings should be added; + * must not be <code>null</code>. + * @param commandService + * The command service for the workbench; must not be + * <code>null</code>. + */ + private static final void readBindingsFromRegistry( + final IConfigurationElement[] configurationElements, + final int configurationElementCount, + final BindingManager bindingManager, + final ICommandService commandService) { + final Collection bindings = new ArrayList(configurationElementCount); + final List warningsToLog = new ArrayList(1); + + HashSet cocoaTempList = new HashSet(); + IViewRegistry viewRegistry = PlatformUI.getWorkbench().getViewRegistry(); + + // the local cache for the sequence modifiers + IConfigurationElement[] sequenceModifiers = new IConfigurationElement[0]; + if(configurationElementCount >0) + sequenceModifiers = getSequenceModifierElements(configurationElements[0]); + + for (int i = 0; i < configurationElementCount; i++) { + final IConfigurationElement configurationElement = configurationElements[i]; + + // different extension. update the cache ... + if( i>0 && !configurationElement.getDeclaringExtension().equals(configurationElements[i-1].getDeclaringExtension())) + sequenceModifiers = getSequenceModifierElements(configurationElement); + + /* + * Read out the command id. Doing this before determining if the key + * binding is actually valid is a bit wasteful. However, it is + * helpful to have the command identifier when logging syntax + * errors. + */ + String commandId = readCommandId(configurationElement); + + String viewParameter = null; + final Command command; + if (commandId != null) { + if (viewRegistry.find(commandId) == null) { + command = commandService.getCommand(commandId); + if (!command.isDefined()) { + // Reference to an undefined command. This is invalid. + addWarning(warningsToLog, + "Cannot bind to an undefined command", //$NON-NLS-1$ + configurationElement, commandId); + continue; + } + } else { + // we must be able to translate old view commands to the new + // parameterized command + viewParameter = commandId; + command = commandService.getCommand(IWorkbenchCommandConstants.VIEWS_SHOW_VIEW); + if (DEBUG) { + Tracing.printTrace("BINDINGS", "Command '" //$NON-NLS-1$ //$NON-NLS-2$ + + commandId + "\' should be migrated to " //$NON-NLS-1$ + + IWorkbenchCommandConstants.VIEWS_SHOW_VIEW); + } + if (!command.isDefined()) { + // Reference to an undefined command. This is invalid. + addWarning(warningsToLog, + "Cannot bind to an undefined command", //$NON-NLS-1$ + configurationElement, commandId); + continue; + } + } + } else { + command = null; + } + + // Read out the scheme id. + String schemeId = readSchemeId(configurationElement, warningsToLog, commandId); + if(isEmpty(schemeId)) + continue; + + // Read out the context id. + String contextId = readContextId(configurationElement); + + String keySequenceText = readKeySequenceText(configurationElement); + if(isEmpty(keySequenceText)) { + // The key sequence should never be null. This is pointless + addWarning( + warningsToLog, + "Defining a key binding with no key sequence has no effect", //$NON-NLS-1$ + configurationElement, commandId); + continue; + } + + + + // Read out the key sequence. + KeySequence keySequence = readKeySequence(configurationElement, warningsToLog, commandId, keySequenceText); + if(keySequence == null) + continue; + + // Read out the locale and platform. + + String locale = readNonEmptyAttribute(configurationElement, ATT_LOCALE); + String platform = readNonEmptyAttribute(configurationElement, ATT_PLATFORM); + + // Read out the parameters, if any. + ParameterizedCommand parameterizedCommand = + readParameterizedCommand(warningsToLog, configurationElement, viewParameter, command); + + List modifiedBindings = applyModifiers(keySequence, keySequenceText, platform, sequenceModifiers, parameterizedCommand, schemeId, contextId, locale, warningsToLog); + + KeyBinding binding = (KeyBinding) modifiedBindings.get(0); + if(modifiedBindings.size() > 1) { + for (int j = 1; j < modifiedBindings.size(); j++) { + bindings.add(modifiedBindings.get(j)); + } + } + + if (Util.WS_COCOA.equals(platform)) { + cocoaTempList.add(binding); + } else if (Util.WS_CARBON.equals(platform)) { + bindings.add(binding); + // temp work around ... simply honour the carbon + // bindings for cocoa. + cocoaTempList.add(new KeyBinding(keySequence, + parameterizedCommand, schemeId, contextId, locale, + Util.WS_COCOA, null, Binding.SYSTEM)); + } else { + bindings.add(binding); + } + } + if (cocoaTempList.size() > 0) { + bindings.addAll(cocoaTempList); + } + + final Binding[] bindingArray = (Binding[]) bindings + .toArray(new Binding[bindings.size()]); + bindingManager.setBindings(bindingArray); + + logWarnings( + warningsToLog, + "Warnings while parsing the key bindings from the 'org.eclipse.ui.commands' extension point"); //$NON-NLS-1$ + } + + private static List applyModifiers(KeySequence keySequence, String keySequenceText, + String platform, IConfigurationElement[] sequenceModifiers, + ParameterizedCommand parameterizedCommand, String schemeId, + String contextId, String locale, List warningsToLog) { + + List bindings = new ArrayList(); + + for (int i = 0; i < sequenceModifiers.length; i++) { + + IConfigurationElement sequenceModifier = sequenceModifiers[i]; + String findSequence = sequenceModifier.getAttribute(ATT_FIND); + + if (keySequenceText.startsWith(findSequence)) { + String replaceSequence = sequenceModifier.getAttribute(ATT_REPLACE); + String modifiedSequence = replaceSequence + keySequenceText.substring(findSequence.length()); + String platformsString = sequenceModifier.getAttribute(ATT_PLATFORMS); + + String[] platforms = parseCommaSeparatedString(platformsString); + + try { + if (platform == null) { + addGenericBindings(keySequence, parameterizedCommand, schemeId, contextId, locale, + bindings, modifiedSequence, platforms); + + } else { + getBindingForPlatform(keySequence, platform, + parameterizedCommand, schemeId, contextId, locale, + bindings, modifiedSequence, platforms); + } + }catch(ParseException e) { + bindings.clear(); + addWarning( + warningsToLog, + "Cannot create modified sequence for key binding", //$NON-NLS-1$ + sequenceModifier, parameterizedCommand.getId(), ATT_REPLACE, + replaceSequence); + + } + break; + } + } + + if(bindings.size() == 0) { + // no modifier was applied/error occurred ... + KeyBinding binding = new KeyBinding(keySequence, + parameterizedCommand, schemeId, contextId, locale, + platform, null, Binding.SYSTEM); + bindings.add(binding); + } + + return bindings; + } + + private static void getBindingForPlatform(KeySequence keySequence, + String platform, ParameterizedCommand parameterizedCommand, + String schemeId, String contextId, String locale, List bindings, + String modifiedSequence, String[] platforms) throws ParseException { + + int j = 0; + for (; j < platforms.length; j++) { + if(platforms[j].equals(SWT.getPlatform())) { + KeyBinding newBinding = new KeyBinding(KeySequence + .getInstance(modifiedSequence), + parameterizedCommand, schemeId, contextId, + locale, platforms[j], null, Binding.SYSTEM); + bindings.add(newBinding); + break; + } + } + if(j == platforms.length) { + // platform doesn't match. use the unmodified sequence + KeyBinding newBinding = new KeyBinding(keySequence, + parameterizedCommand, schemeId, contextId, + locale, null, null, Binding.SYSTEM); + bindings.add(newBinding); + } + } + + private static void addGenericBindings(KeySequence keySequence, ParameterizedCommand parameterizedCommand, + String schemeId, String contextId, String locale, List bindings, + String modifiedSequence, String[] platforms) throws ParseException { + + + KeyBinding originalBinding = new KeyBinding(keySequence, + parameterizedCommand, schemeId, contextId, locale, null, null, + Binding.SYSTEM); + bindings.add(originalBinding); + + String platform = SWT.getPlatform(); + boolean modifierExists = false; + for (int i = 0; i < platforms.length; i++) { + if(platforms[i].equals(platform)) { + modifierExists = true; + break; + } + } + + if(modifierExists) { + KeyBinding newBinding = new KeyBinding(KeySequence.getInstance(modifiedSequence), + parameterizedCommand, schemeId, contextId, + locale, SWT.getPlatform(), null, Binding.SYSTEM); + + KeyBinding deleteBinding = new KeyBinding(keySequence, + null, schemeId, contextId, + locale, SWT.getPlatform(), null, Binding.SYSTEM); + + bindings.add(newBinding); + bindings.add(deleteBinding); + } + + } + + private static IConfigurationElement[] getSequenceModifierElements(IConfigurationElement configurationElement) { + + IExtension extension = configurationElement.getDeclaringExtension(); + IConfigurationElement[] configurationElements = extension.getConfigurationElements(); + List modifierElements = new ArrayList(); + for (int i = 0; i < configurationElements.length; i++) { + final IConfigurationElement anElement = configurationElements[i]; + if(TAG_SEQUENCE_MODIFIER.equals(anElement.getName())) + modifierElements.add(anElement); + } + return (IConfigurationElement[]) modifierElements.toArray(new IConfigurationElement[modifierElements.size()]); + } + + public static String[] parseCommaSeparatedString(String commaSeparatedString) { + StringTokenizer tokenizer = new StringTokenizer(commaSeparatedString, ", "); //$NON-NLS-1$ + int count = tokenizer.countTokens(); + String[] tokens = new String[count]; + for (int i = 0; i < tokens.length; i++) { + tokens[i] = tokenizer.nextToken(); + } + return tokens; + } + + + private static String readKeySequenceText(IConfigurationElement configurationElement) { + + String keySequenceText = configurationElement.getAttribute(ATT_SEQUENCE); + if (isEmpty(keySequenceText)) { + keySequenceText = configurationElement.getAttribute(ATT_KEY_SEQUENCE); + } + if (isEmpty(keySequenceText)) + keySequenceText = configurationElement.getAttribute(ATT_STRING); + + return keySequenceText; + + } + + private static KeySequence readKeySequence(IConfigurationElement configurationElement, List warningsToLog, String commandId, String keySequenceText) { + + KeySequence keySequence = null; + if(keySequenceText.equals(configurationElement.getAttribute(ATT_STRING))){ + // The key sequence is in the old-style format. + try { + keySequence = convert2_1Sequence(parse2_1Sequence(keySequenceText)); + } catch (final IllegalArgumentException e) { + addWarning(warningsToLog, "Could not parse key sequence", //$NON-NLS-1$ + configurationElement, commandId, "keySequence", //$NON-NLS-1$ + keySequenceText); + return null; + } + } else { + // The key sequence is in the new-style format. + try { + keySequence = KeySequence.getInstance(keySequenceText); + } catch (final ParseException e) { + addWarning(warningsToLog, "Could not parse key sequence", //$NON-NLS-1$ + configurationElement, commandId, "keySequence", //$NON-NLS-1$ + keySequenceText); + return null; + } + if (keySequence.isEmpty() || !keySequence.isComplete()) { + addWarning( + warningsToLog, + "Key bindings should not have an empty or incomplete key sequence", //$NON-NLS-1$ + configurationElement, commandId, "keySequence", //$NON-NLS-1$ + keySequence.toString()); + return null; + } + + } + return keySequence; + } + + private static ParameterizedCommand readParameterizedCommand( + final List warningsToLog, + final IConfigurationElement configurationElement, + String viewParameter, final Command command) { + final ParameterizedCommand parameterizedCommand; + if (command == null) { + parameterizedCommand = null; + } else if (viewParameter != null) { + HashMap parms = new HashMap(); + parms.put(ShowViewMenu.VIEW_ID_PARM, viewParameter); + parameterizedCommand = ParameterizedCommand.generateCommand(command, parms); + } else { + parameterizedCommand = readParameters(configurationElement, + warningsToLog, command); + } + return parameterizedCommand; + } + + /** + * Reads the specified attribute from the configuration element. + * If the value is an empty string, will return null. + * + * @param configurationElement + * @return the attribute value + */ + private static String readNonEmptyAttribute(IConfigurationElement configurationElement, String attribute) { + String attributeValue = configurationElement.getAttribute(attribute); + if ((attributeValue != null) && (attributeValue.length() == 0)) { + attributeValue = null; + } + return attributeValue; + } + + + private static String readContextId( + final IConfigurationElement configurationElement) { + String contextId = configurationElement + .getAttribute(ATT_CONTEXT_ID); + if (LEGACY_DEFAULT_SCOPE.equals(contextId)) { + contextId = null; + } else if ((contextId == null) || (contextId.length() == 0)) { + contextId = configurationElement.getAttribute(ATT_SCOPE); + if (LEGACY_DEFAULT_SCOPE.equals(contextId)) { + contextId = null; + } + } + if ((contextId == null) || (contextId.length() == 0)) { + contextId = IContextIds.CONTEXT_ID_WINDOW; + } + return contextId; + } + + + private static String readSchemeId(IConfigurationElement configurationElement, List warningsToLog, String commandId) { + + String schemeId = configurationElement.getAttribute(ATT_SCHEME_ID); + if ((schemeId == null) || (schemeId.length() == 0)) { + schemeId = configurationElement + .getAttribute(ATT_KEY_CONFIGURATION_ID); + if ((schemeId == null) || (schemeId.length() == 0)) { + schemeId = configurationElement + .getAttribute(ATT_CONFIGURATION); + if ((schemeId == null) || (schemeId.length() == 0)) { + // The scheme id should never be null. This is invalid. + addWarning(warningsToLog, "Key bindings need a scheme", //$NON-NLS-1$ + configurationElement, commandId); + } + } + } + return schemeId; + } + + private static String readCommandId( + final IConfigurationElement configurationElement) { + String commandId = configurationElement + .getAttribute(ATT_COMMAND_ID); + if ((commandId == null) || (commandId.length() == 0)) { + commandId = configurationElement.getAttribute(ATT_COMMAND); + } + if ((commandId != null) && (commandId.length() == 0)) { + commandId = null; + } + return commandId; + } + + private static boolean isEmpty(String string) { + return string == null || string.length() == 0; + } + + /** + * Reads all of the scheme definitions from the registry. + * + * @param configurationElements + * The configuration elements in the commands extension point; + * must not be <code>null</code>, but may be empty. + * @param configurationElementCount + * The number of configuration elements that are really in the + * array. + * @param bindingManager + * The binding manager to which the schemes should be added; must + * not be <code>null</code>. + */ + private static final void readSchemesFromRegistry( + final IConfigurationElement[] configurationElements, + final int configurationElementCount, + final BindingManager bindingManager) { + // Undefine all the previous handle objects. + final HandleObject[] handleObjects = bindingManager.getDefinedSchemes(); + if (handleObjects != null) { + for (int i = 0; i < handleObjects.length; i++) { + handleObjects[i].undefine(); + } + } + + final List warningsToLog = new ArrayList(1); + + for (int i = 0; i < configurationElementCount; i++) { + final IConfigurationElement configurationElement = configurationElements[i]; + + // Read out the attributes. + final String id = readRequired(configurationElement, ATT_ID, + warningsToLog, "Schemes need an id"); //$NON-NLS-1$ + if (id == null) { + continue; + } + final String name = readRequired(configurationElement, ATT_NAME, + warningsToLog, "A scheme needs a name", id); //$NON-NLS-1$ + if (name == null) { + continue; + } + final String description = readOptional(configurationElement, + ATT_DESCRIPTION); + + String parentId = configurationElement.getAttribute(ATT_PARENT_ID); + if ((parentId != null) && (parentId.length() == 0)) { + parentId = configurationElement.getAttribute(ATT_PARENT); + if ((parentId != null) && (parentId.length() == 0)) { + parentId = null; + } + } + + // Define the scheme. + final Scheme scheme = bindingManager.getScheme(id); + scheme.define(name, description, parentId); + } + + logWarnings( + warningsToLog, + "Warnings while parsing the key bindings from the 'org.eclipse.ui.bindings', 'org.eclipse.ui.acceleratorConfigurations' and 'org.eclipse.ui.commands' extension point"); //$NON-NLS-1$ + } + + /** + * Writes the given active scheme and bindings to the preference store. Only + * bindings that are of the <code>Binding.USER</code> type will be + * written; the others will be ignored. + * + * @param activeScheme + * The scheme which should be persisted; may be <code>null</code>. + * @param bindings + * The bindings which should be persisted; may be + * <code>null</code> + * @throws IOException + * If something happens while trying to write to the workbench + * preference store. + */ + static final void write(final Scheme activeScheme, final Binding[] bindings) + throws IOException { + // Print out debugging information, if requested. + if (DEBUG) { + Tracing.printTrace("BINDINGS", "Persisting active scheme '" //$NON-NLS-1$ //$NON-NLS-2$ + + activeScheme.getId() + '\''); + Tracing.printTrace("BINDINGS", "Persisting bindings"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + // Write the simple preference key to the UI preference store. + writeActiveScheme(activeScheme); + + // Build the XML block for writing the bindings and active scheme. + final XMLMemento xmlMemento = XMLMemento + .createWriteRoot(EXTENSION_COMMANDS); + if (activeScheme != null) { + writeActiveSchemeToPreferences(xmlMemento, activeScheme); + } + if (bindings != null) { + final int bindingsLength = bindings.length; + for (int i = 0; i < bindingsLength; i++) { + final Binding binding = bindings[i]; + if (binding.getType() == Binding.USER) { + writeBindingToPreferences(xmlMemento, binding); + } + } + } + + // Write the XML block to the workbench preference store. + final IPreferenceStore preferenceStore = WorkbenchPlugin.getDefault() + .getPreferenceStore(); + final Writer writer = new StringWriter(); + try { + xmlMemento.save(writer); + preferenceStore.setValue(EXTENSION_COMMANDS, writer.toString()); + } finally { + writer.close(); + } + } + + /** + * Writes the active scheme to its own preference key. This key is used by + * RCP applications as part of their plug-in customization. + * + * @param scheme + * The scheme to write to the preference store. If the scheme is + * <code>null</code>, then it is removed. + */ + private static final void writeActiveScheme(final Scheme scheme) { + final IPreferenceStore store = PlatformUI.getPreferenceStore(); + final String schemeId = (scheme == null) ? null : scheme.getId(); + final String defaultSchemeId = store + .getDefaultString(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID); + if ((defaultSchemeId == null) ? (scheme != null) : (!defaultSchemeId + .equals(schemeId))) { + store.setValue(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID, + scheme.getId()); + } else { + store + .setToDefault(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID); + } + } + + /** + * Writes the active scheme to the memento. If the scheme is + * <code>null</code>, then all schemes in the memento are removed. + * + * @param memento + * The memento to which the scheme should be written; must not be + * <code>null</code>. + * @param scheme + * The scheme that should be written; must not be + * <code>null</code>. + */ + private static final void writeActiveSchemeToPreferences( + final IMemento memento, final Scheme scheme) { + // Add this active scheme, if it is not the default. + final IPreferenceStore store = PlatformUI.getPreferenceStore(); + final String schemeId = scheme.getId(); + final String defaultSchemeId = store + .getDefaultString(IWorkbenchPreferenceConstants.KEY_CONFIGURATION_ID); + if ((defaultSchemeId == null) ? (schemeId != null) : (!defaultSchemeId + .equals(schemeId))) { + final IMemento child = memento + .createChild(TAG_ACTIVE_KEY_CONFIGURATION); + child.putString(ATT_KEY_CONFIGURATION_ID, schemeId); + } + } + + /** + * Writes the binding to the memento. This creates a new child element on + * the memento, and places the properties of the binding as its attributes. + * + * @param parent + * The parent memento for the binding element; must not be + * <code>null</code>. + * @param binding + * The binding to write; must not be <code>null</code>. + */ + private static final void writeBindingToPreferences(final IMemento parent, + final Binding binding) { + final IMemento element = parent.createChild(TAG_KEY_BINDING); + element.putString(ATT_CONTEXT_ID, binding.getContextId()); + final ParameterizedCommand parameterizedCommand = binding + .getParameterizedCommand(); + final String commandId = (parameterizedCommand == null) ? null + : parameterizedCommand.getId(); + element.putString(ATT_COMMAND_ID, commandId); + element.putString(ATT_KEY_CONFIGURATION_ID, binding.getSchemeId()); + element.putString(ATT_KEY_SEQUENCE, binding.getTriggerSequence() + .toString()); + element.putString(ATT_LOCALE, binding.getLocale()); + element.putString(ATT_PLATFORM, binding.getPlatform()); + if (parameterizedCommand != null) { + final Map parameterizations = parameterizedCommand + .getParameterMap(); + final Iterator parameterizationItr = parameterizations.entrySet() + .iterator(); + while (parameterizationItr.hasNext()) { + final Map.Entry entry = (Map.Entry) parameterizationItr.next(); + final String id = (String) entry.getKey(); + final String value = (String) entry.getValue(); + final IMemento parameterElement = element + .createChild(TAG_PARAMETER); + parameterElement.putString(ATT_ID, id); + parameterElement.putString(ATT_VALUE, value); + } + } + } + + /** + * The binding manager which should be populated with the values from the + * registry and preference store; must not be <code>null</code>. + */ + private final BindingManager bindingManager; + + /** + * The command service for the workbench; must not be <code>null</code>. + */ + private final ICommandService commandService; + + /** + * Constructs a new instance of <code>BindingPersistence</code>. + * + * @param bindingManager + * The binding manager which should be populated with the values + * from the registry and preference store; must not be + * <code>null</code>. + * @param commandService + * The command service for the workbench; must not be + * <code>null</code>. + */ + BindingPersistence(final BindingManager bindingManager, + final ICommandService commandService) { + this.bindingManager = bindingManager; + this.commandService = commandService; + } + + protected final boolean isChangeImportant(final IRegistryChangeEvent event) { + return false; + } + + public boolean bindingsNeedUpdating(final IRegistryChangeEvent event) { + final IExtensionDelta[] acceleratorConfigurationDeltas = event + .getExtensionDeltas( + PlatformUI.PLUGIN_ID, + IWorkbenchRegistryConstants.PL_ACCELERATOR_CONFIGURATIONS); + if (acceleratorConfigurationDeltas.length == 0) { + final IExtensionDelta[] bindingDeltas = event.getExtensionDeltas( + PlatformUI.PLUGIN_ID, + IWorkbenchRegistryConstants.PL_BINDINGS); + if (bindingDeltas.length == 0) { + final IExtensionDelta[] commandDeltas = event + .getExtensionDeltas(PlatformUI.PLUGIN_ID, + IWorkbenchRegistryConstants.PL_COMMANDS); + if (commandDeltas.length == 0) { + final IExtensionDelta[] acceleratorScopeDeltas = event + .getExtensionDeltas( + PlatformUI.PLUGIN_ID, + IWorkbenchRegistryConstants.PL_ACCELERATOR_SCOPES); + if (acceleratorScopeDeltas.length == 0) { + final IExtensionDelta[] contextDeltas = event + .getExtensionDeltas(PlatformUI.PLUGIN_ID, + IWorkbenchRegistryConstants.PL_CONTEXTS); + if (contextDeltas.length == 0) { + final IExtensionDelta[] actionDefinitionDeltas = event + .getExtensionDeltas( + PlatformUI.PLUGIN_ID, + IWorkbenchRegistryConstants.PL_ACTION_DEFINITIONS); + if (actionDefinitionDeltas.length == 0) { + return false; + } + } + } + } + } + } + + return true; + } + + protected final boolean isChangeImportant(final PropertyChangeEvent event) { + return EXTENSION_COMMANDS.equals(event.getProperty()); + } + + /** + * Reads all of the binding information from the registry and from the + * preference store. + */ + protected final void read() { + super.read(); + reRead(); + } + + public void reRead() { + // Create the extension registry mementos. + final IExtensionRegistry registry = Platform.getExtensionRegistry(); + int activeSchemeElementCount = 0; + int bindingDefinitionCount = 0; + int schemeDefinitionCount = 0; + final IConfigurationElement[][] indexedConfigurationElements = new IConfigurationElement[3][]; + + // Sort the bindings extension point based on element name. + final IConfigurationElement[] bindingsExtensionPoint = registry + .getConfigurationElementsFor(EXTENSION_BINDINGS); + for (int i = 0; i < bindingsExtensionPoint.length; i++) { + final IConfigurationElement configurationElement = bindingsExtensionPoint[i]; + final String name = configurationElement.getName(); + + // Check if it is a binding definition. + if (TAG_KEY.equals(name)) { + addElementToIndexedArray(configurationElement, + indexedConfigurationElements, + INDEX_BINDING_DEFINITIONS, bindingDefinitionCount++); + } else + // Check to see if it is a scheme definition. + if (TAG_SCHEME.equals(name)) { + addElementToIndexedArray(configurationElement, + indexedConfigurationElements, INDEX_SCHEME_DEFINITIONS, + schemeDefinitionCount++); + } + + } + + // Sort the commands extension point based on element name. + final IConfigurationElement[] commandsExtensionPoint = registry + .getConfigurationElementsFor(EXTENSION_COMMANDS); + for (int i = 0; i < commandsExtensionPoint.length; i++) { + final IConfigurationElement configurationElement = commandsExtensionPoint[i]; + final String name = configurationElement.getName(); + + // Check if it is a binding definition. + if (TAG_KEY_BINDING.equals(name)) { + addElementToIndexedArray(configurationElement, + indexedConfigurationElements, + INDEX_BINDING_DEFINITIONS, bindingDefinitionCount++); + + // Check if it is a scheme defintion. + } else if (TAG_KEY_CONFIGURATION.equals(name)) { + addElementToIndexedArray(configurationElement, + indexedConfigurationElements, INDEX_SCHEME_DEFINITIONS, + schemeDefinitionCount++); + + // Check if it is an active scheme identifier. + } else if (TAG_ACTIVE_KEY_CONFIGURATION.equals(name)) { + addElementToIndexedArray(configurationElement, + indexedConfigurationElements, INDEX_ACTIVE_SCHEME, + activeSchemeElementCount++); + } + } + + /* + * Sort the accelerator configuration extension point into the scheme + * definitions. + */ + final IConfigurationElement[] acceleratorConfigurationsExtensionPoint = registry + .getConfigurationElementsFor(EXTENSION_ACCELERATOR_CONFIGURATIONS); + for (int i = 0; i < acceleratorConfigurationsExtensionPoint.length; i++) { + final IConfigurationElement configurationElement = acceleratorConfigurationsExtensionPoint[i]; + final String name = configurationElement.getName(); + + // Check if the name matches the accelerator configuration element + if (TAG_ACCELERATOR_CONFIGURATION.equals(name)) { + addElementToIndexedArray(configurationElement, + indexedConfigurationElements, INDEX_SCHEME_DEFINITIONS, + schemeDefinitionCount++); + } + } + + // Create the preference memento. + final IPreferenceStore store = WorkbenchPlugin.getDefault() + .getPreferenceStore(); + final String preferenceString = store.getString(EXTENSION_COMMANDS); + IMemento preferenceMemento = null; + if ((preferenceString != null) && (preferenceString.length() > 0)) { + final Reader reader = new StringReader(preferenceString); + try { + preferenceMemento = XMLMemento.createReadRoot(reader); + } catch (final WorkbenchException e) { + // Could not initialize the preference memento. + } + } + + // Read the scheme definitions. + readSchemesFromRegistry( + indexedConfigurationElements[INDEX_SCHEME_DEFINITIONS], + schemeDefinitionCount, bindingManager); + readActiveScheme(indexedConfigurationElements[INDEX_ACTIVE_SCHEME], + activeSchemeElementCount, preferenceMemento, bindingManager); + readBindingsFromRegistry( + indexedConfigurationElements[INDEX_BINDING_DEFINITIONS], + bindingDefinitionCount, bindingManager, commandService); + readBindingsFromPreferences(preferenceMemento, bindingManager, + commandService); + } +} diff --git a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/BindingService.java b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/BindingService.java index 32aed5222e..34a482ef20 100755 --- a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/BindingService.java +++ b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/BindingService.java @@ -11,18 +11,24 @@ package org.eclipse.ui.internal.keys; import java.io.IOException; +import java.util.Collection; import java.util.Map; import org.eclipse.core.commands.ParameterizedCommand; +import org.eclipse.core.commands.common.NotDefinedException; import org.eclipse.jface.bindings.Binding; import org.eclipse.jface.bindings.BindingManager; +import org.eclipse.jface.bindings.IBindingManagerListener; import org.eclipse.jface.bindings.Scheme; import org.eclipse.jface.bindings.TriggerSequence; +import org.eclipse.jface.bindings.keys.SWTKeySupport; +import org.eclipse.jface.bindings.keys.formatting.KeyFormatterFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Listener; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.internal.WorkbenchPlugin; import org.eclipse.ui.keys.IBindingService; /** @@ -41,24 +47,22 @@ public final class BindingService implements IBindingService { */ private final BindingManager bindingManager; - // RAP [bm]: -// /** -// * The persistence class responsible for bindings. -// */ -// private final BindingPersistence bindingPersistence; -// -// /** -// * The key binding support for the contexts. In the workbench, key bindings -// * are intimately tied to the context mechanism. -// */ -// private WorkbenchKeyboard keyboard; - // RAPEND: [bm] + /** + * The persistence class responsible for bindings. + */ + private final BindingPersistence bindingPersistence; + + /** + * The key binding support for the contexts. In the workbench, key bindings + * are intimately tied to the context mechanism. + */ + private WorkbenchKeyboard keyboard; private IWorkbench workbench; /** * Constructs a new instance of <code>BindingService</code> using a JFace * binding manager. - * + * * @param bindingManager * The bind ing manager to use; must not be <code>null</code>. * @param commandService @@ -82,19 +86,17 @@ public final class BindingService implements IBindingService { this.workbench = workbench; // Hook up the key binding support. - // RAP [bm]: -// this.bindingPersistence = new BindingPersistence(bindingManager, -// commandService); -// keyboard = new WorkbenchKeyboard(workbench); -// final Display display = workbench.getDisplay(); -// final Listener listener = keyboard.getKeyDownFilter(); -// display.addFilter(SWT.KeyDown, listener); -// display.addFilter(SWT.Traverse, listener); -// -// // Initialize the key formatter. -// KeyFormatterFactory.setDefault(SWTKeySupport -// .getKeyFormatterForPlatform()); - // RAPEND: [bm] + this.bindingPersistence = new BindingPersistence(bindingManager, + commandService); + keyboard = new WorkbenchKeyboard(workbench); + final Display display = workbench.getDisplay(); + final Listener listener = keyboard.getKeyDownFilter(); + display.addFilter(SWT.KeyDown, listener); + display.addFilter(SWT.Traverse, listener); + + // Initialize the key formatter. + KeyFormatterFactory.setDefault(SWTKeySupport + .getKeyFormatterForPlatform()); } @@ -108,26 +110,27 @@ public final class BindingService implements IBindingService { * <p> * This method completes in amortized <code>O(1)</code>. * </p> - * + * * @param binding * The binding to be added; must not be <code>null</code>. */ public final void addBinding(final Binding binding) { bindingManager.addBinding(binding); } - + public final void dispose() { - workbench = null; - // RAP [bm]: no keyboard -// final Listener listener = keyboard.getKeyDownFilter(); -// final Display display = workbench.getDisplay(); -// if (display != null) { -// display.removeFilter(SWT.KeyDown, listener); -// display.removeFilter(SWT.Traverse, listener); -// } -// keyboard = null; -// bindingPersistence.dispose(); - // RAPEND: [bm] + // RAP [rst] safeguard against NPE + if( keyboard == null || workbench == null ) return; + // RAP [rst] move "workbench = null" down to prevent NPE + final Listener listener = keyboard.getKeyDownFilter(); + final Display display = workbench.getDisplay(); + if (display != null) { + display.removeFilter(SWT.KeyDown, listener); + display.removeFilter(SWT.Traverse, listener); + } + workbench = null; + keyboard = null; + bindingPersistence.dispose(); } public final TriggerSequence[] getActiveBindingsFor( @@ -146,7 +149,7 @@ public final class BindingService implements IBindingService { public final TriggerSequence getBestActiveBindingFor(final String commandId) { return bindingManager.getBestActiveBindingFor(commandId); } - + /* (non-Javadoc) * @see org.eclipse.ui.keys.IBindingService#getBestActiveBindingFor(org.eclipse.core.commands.ParameterizedCommand) */ @@ -162,31 +165,28 @@ public final class BindingService implements IBindingService { return bindingManager.getBindings(); } - // RAP [bm]: -// public final TriggerSequence getBuffer() { -// return keyboard.getBuffer(); -// } -// -// public final String getDefaultSchemeId() { -// return BindingPersistence.getDefaultSchemeId(); -// } - // RAPEND: [bm] + public final TriggerSequence getBuffer() { + return keyboard.getBuffer(); + } + + public final String getDefaultSchemeId() { + return BindingPersistence.getDefaultSchemeId(); + } public final Scheme[] getDefinedSchemes() { return bindingManager.getDefinedSchemes(); } - // RAP [bm]: Bindings -// /** -// * Returns the key binding architecture for the workbench. This method is -// * internal, and is only intended for testing. This must not be used by -// * clients. -// * -// * @return The key binding support; never <code>null</code>. -// */ -// public final WorkbenchKeyboard getKeyboard() { -// return keyboard; -// } + /** + * Returns the key binding architecture for the workbench. This method is + * internal, and is only intended for testing. This must not be used by + * clients. + * + * @return The key binding support; never <code>null</code>. + */ + public final WorkbenchKeyboard getKeyboard() { + return keyboard; + } public final String getLocale() { return bindingManager.getLocale(); @@ -208,10 +208,9 @@ public final class BindingService implements IBindingService { return bindingManager.getScheme(schemeId); } - // RAP [bm]: -// public final boolean isKeyFilterEnabled() { -// return keyboard.getKeyDownFilter().isEnabled(); -// } + public final boolean isKeyFilterEnabled() { + return keyboard.getKeyDownFilter().isEnabled(); + } public final boolean isPartialMatch(final TriggerSequence sequence) { return bindingManager.isPartialMatch(sequence); @@ -221,22 +220,19 @@ public final class BindingService implements IBindingService { return bindingManager.isPerfectMatch(sequence); } - // RAP [bm]: Bindings -// public final void openKeyAssistDialog() { -// keyboard.openMultiKeyAssistShell(); -// } + public final void openKeyAssistDialog() { + keyboard.openMultiKeyAssistShell(); + } public final void readRegistryAndPreferences( final ICommandService commandService) { - // RAP [bm]: Bindings -// bindingPersistence.read(); - // RAPEND: [bm] + bindingPersistence.read(); } /** * Remove the specific binding by identity. Does nothing if the binding is * not in the manager. - * + * * @param binding * The binding to be removed; must not be <code>null</code>. */ @@ -246,62 +242,58 @@ public final class BindingService implements IBindingService { public final void savePreferences(final Scheme activeScheme, final Binding[] bindings) throws IOException { - // RAP [bm]: -// BindingPersistence.write(activeScheme, bindings); -// try { -// bindingManager.setActiveScheme(activeScheme); -// } catch (final NotDefinedException e) { -// WorkbenchPlugin.log("The active scheme is not currently defined.", //$NON-NLS-1$ -// WorkbenchPlugin.getStatus(e)); -// } - // RAPEND: [bm] + BindingPersistence.write(activeScheme, bindings); + try { + bindingManager.setActiveScheme(activeScheme); + } catch (final NotDefinedException e) { + WorkbenchPlugin.log("The active scheme is not currently defined.", //$NON-NLS-1$ + WorkbenchPlugin.getStatus(e)); + } bindingManager.setBindings(bindings); } - // RAP [bm]: -// public final void setKeyFilterEnabled(final boolean enabled) { -// keyboard.getKeyDownFilter().setEnabled(enabled); -// } - - // RAP [bm]: Bindings -// /** -// * @return Returns the bindingPersistence. -// */ -// public BindingPersistence getBindingPersistence() { -// return bindingPersistence; -// } -// -// public BindingManager getBindingManager() { -// return bindingManager; -// } -// -// /* -// * (non-Javadoc) -// * -// * @see -// * org.eclipse.ui.keys.IBindingService#addBindingManagerListener(org.eclipse -// * .jface.bindings.IBindingManagerListener) -// */ -// public void addBindingManagerListener(IBindingManagerListener listener) { -// bindingManager.addBindingManagerListener(listener); -// } -// -// /* -// * (non-Javadoc) -// * -// * @see -// * org.eclipse.ui.keys.IBindingService#removeBindingManagerListener(org. -// * eclipse.jface.bindings.IBindingManagerListener) -// */ -// public void removeBindingManagerListener(IBindingManagerListener listener) { -// bindingManager.removeBindingManagerListener(listener); -// } -// -// /* (non-Javadoc) -// * @see org.eclipse.ui.keys.IBindingService#getConflictsFor(org.eclipse.jface.bindings.TriggerSequence) -// */ -// public Collection getConflictsFor(TriggerSequence sequence) { -// return bindingManager.getConflictsFor(sequence); -// } + public final void setKeyFilterEnabled(final boolean enabled) { + keyboard.getKeyDownFilter().setEnabled(enabled); + } + + /** + * @return Returns the bindingPersistence. + */ + public BindingPersistence getBindingPersistence() { + return bindingPersistence; + } + + public BindingManager getBindingManager() { + return bindingManager; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.keys.IBindingService#addBindingManagerListener(org.eclipse + * .jface.bindings.IBindingManagerListener) + */ + public void addBindingManagerListener(IBindingManagerListener listener) { + bindingManager.addBindingManagerListener(listener); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.keys.IBindingService#removeBindingManagerListener(org. + * eclipse.jface.bindings.IBindingManagerListener) + */ + public void removeBindingManagerListener(IBindingManagerListener listener) { + bindingManager.removeBindingManagerListener(listener); + } + + /* (non-Javadoc) + * @see org.eclipse.ui.keys.IBindingService#getConflictsFor(org.eclipse.jface.bindings.TriggerSequence) + */ + public Collection getConflictsFor(TriggerSequence sequence) { + return bindingManager.getConflictsFor(sequence); + } } diff --git a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeyAssistDialog.java b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeyAssistDialog.java index e55339d7b7..a290170d76 100755 --- a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeyAssistDialog.java +++ b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeyAssistDialog.java @@ -1,739 +1,742 @@ -// RAP [rh] Keys completely disabled as not implemented in RWT -///******************************************************************************* -// * Copyright (c) 2004, 2010 IBM Corporation and others. -// * All rights reserved. This program and the accompanying materials -// * are made available under the terms of the Eclipse Public License v1.0 -// * which accompanies this distribution, and is available at -// * http://www.eclipse.org/legal/epl-v10.html -// * -// * Contributors: -// * IBM Corporation - initial API and implementation -// *******************************************************************************/ -// -//package org.eclipse.ui.internal.keys; -// -//import java.util.ArrayList; -//import java.util.Collection; -//import java.util.Comparator; -//import java.util.Iterator; -//import java.util.List; -//import java.util.Map; -//import java.util.SortedMap; -//import java.util.TreeMap; -//import org.eclipse.core.commands.Command; -//import org.eclipse.core.commands.ParameterizedCommand; -//import org.eclipse.core.commands.common.CommandException; -//import org.eclipse.core.commands.common.NotDefinedException; -//import org.eclipse.jface.bindings.Binding; -//import org.eclipse.jface.bindings.TriggerSequence; -//import org.eclipse.jface.bindings.keys.KeySequence; -//import org.eclipse.jface.bindings.keys.KeyStroke; -//import org.eclipse.jface.dialogs.Dialog; -//import org.eclipse.jface.dialogs.PopupDialog; -//import org.eclipse.jface.preference.PreferenceDialog; -//import org.eclipse.jface.window.Window; -//import org.eclipse.osgi.util.NLS; -//import org.eclipse.swt.SWT; -//import org.eclipse.swt.graphics.Point; -//import org.eclipse.swt.graphics.Rectangle; -//import org.eclipse.swt.layout.GridData; -//import org.eclipse.swt.layout.GridLayout; -//import org.eclipse.swt.widgets.Composite; -//import org.eclipse.swt.widgets.Control; -//import org.eclipse.swt.widgets.Event; -//import org.eclipse.swt.widgets.Label; -//import org.eclipse.swt.widgets.Listener; -//import org.eclipse.swt.widgets.Shell; -//import org.eclipse.swt.widgets.Table; -//import org.eclipse.swt.widgets.TableColumn; -//import org.eclipse.swt.widgets.TableItem; -//import org.eclipse.ui.IWorkbench; -//import org.eclipse.ui.IWorkbenchCommandConstants; -//import org.eclipse.ui.activities.IActivityManager; -//import org.eclipse.ui.commands.ICommandService; -//import org.eclipse.ui.contexts.IContextService; -//import org.eclipse.ui.dialogs.PreferencesUtil; -//import org.eclipse.ui.keys.IBindingService; -// -///** -// * <p> -// * A dialog displaying a list of key bindings. The dialog will execute a command -// * if it is selected. -// * </p> -// * <p> -// * The methods on this class are not thread-safe and must be run from the UI -// * thread. -// * </p> -// * -// * @since 3.1 -// */ -//final class KeyAssistDialog extends PopupDialog { -// -// /** -// * The data key for the binding stored on an SWT widget. The key is a -// * fully-qualified name, but in reverse order. This is so that the equals -// * method will detect misses faster. -// */ -// private static final String BINDING_KEY = "Binding.bindings.jface.eclipse.org"; //$NON-NLS-1$ -// -// /** -// * The value of <code>previousWidth</code> to set if there is no -// * remembered width. -// */ -// private static final int NO_REMEMBERED_WIDTH = -1; -// -// /** -// * The activity manager for the associated workbench. -// */ -// private final IActivityManager activityManager; -// -// /** -// * The binding service for the associated workbench. -// */ -// private final IBindingService bindingService; -// -// /** -// * The binding that was selected when the key assist dialog last closed. -// * This is only remembered until <code>clearRememberedState()</code> is -// * called. -// */ -// private Binding binding = null; -// -// /** -// * The ordered list of command identifiers corresponding to the table. -// */ -// private final List bindings = new ArrayList(); -// -// /** -// * The command service for the associated workbench. -// */ -// private final ICommandService commandService; -// -// /** -// * The table containing of the possible completions. This value is -// * <code>null</code> until the dialog is created. -// */ -// private Table completionsTable = null; -// -// /** -// * Whether this dialog is currently holding some remembered state. -// */ -// private boolean hasRememberedState = false; -// -// /** -// * The key binding state for the associated workbench. -// */ -// private final KeyBindingState keyBindingState; -// -// /** -// * The width of the shell when it was previously open. This is only -// * remembered until <code>clearRememberedState()</code> is called. -// */ -// private int previousWidth = NO_REMEMBERED_WIDTH; -// -// /** -// * The key binding listener for the associated workbench. -// */ -// private final WorkbenchKeyboard workbenchKeyboard; -// -// /** -// * A sorted map of conflicts to be used when the dialog pops up. -// * -// * @since 3.3 -// */ -// private SortedMap conflictMatches; -// -// /** -// * Constructs a new instance of <code>KeyAssistDialog</code>. When the -// * dialog is first constructed, it contains no widgets. The dialog is first -// * created with no parent. If a parent is required, call -// * <code>setParentShell()</code>. Also, between uses, it might be -// * necessary to call <code>setParentShell()</code> as well. -// * -// * @param workbench -// * The workbench in which this dialog is created; must not be -// * <code>null</code>. -// * @param associatedKeyboard -// * The key binding listener for the workbench; must not be -// * <code>null</code>. -// * @param associatedState -// * The key binding state associated with the workbench; must not -// * be <code>null</code>. -// */ -// KeyAssistDialog(final IWorkbench workbench, -// final WorkbenchKeyboard associatedKeyboard, -// final KeyBindingState associatedState) { -// super((Shell) null, PopupDialog.INFOPOPUP_SHELLSTYLE, true, false, -// false, false, null, null); -// -// this.activityManager = workbench.getActivitySupport() -// .getActivityManager(); -// this.bindingService = (IBindingService) workbench -// .getService(IBindingService.class); -// this.commandService = (ICommandService) workbench -// .getService(ICommandService.class); -// this.keyBindingState = associatedState; -// this.workbenchKeyboard = associatedKeyboard; -// -// this.setInfoText(getKeySequenceString()); -// } -// -// /** -// * Clears out the remembered state of the key assist dialog. This includes -// * its width, as well as the selected binding. -// */ -// final void clearRememberedState() { -// previousWidth = NO_REMEMBERED_WIDTH; -// binding = null; -// hasRememberedState = false; -// } -// -// /** -// * Closes this shell, but first remembers some state of the dialog. This way -// * it will have a response if asked to open the dialog again or if asked to -// * open the keys preference page. This does not remember the internal state. -// * -// * @return Whether the shell was already closed. -// */ -// public final boolean close() { -// return close(false); -// } -// -// /** -// * Closes this shell, but first remembers some state of the dialog. This way -// * it will have a response if asked to open the dialog again or if asked to -// * open the keys preference page. -// * -// * @param rememberState -// * Whether the internal state should be remembered. -// * @return Whether the shell was already closed. -// */ -// public final boolean close(final boolean rememberState) { -// return close(rememberState, true); -// } -// -// /** -// * Closes this shell, but first remembers some state of the dialog. This way -// * it will have a response if asked to open the dialog again or if asked to -// * open the keys preference page. -// * -// * @param rememberState -// * Whether the internal state should be remembered. -// * @param resetState -// * Whether the state should be reset. -// * @return Whether the shell was already closed. -// */ -// private final boolean close(final boolean rememberState, -// final boolean resetState) { -// final Shell shell = getShell(); -// if (rememberState) { -// // Remember the previous width. -// final int widthToRemember; -// if ((shell != null) && (!shell.isDisposed())) { -// widthToRemember = getShell().getSize().x; -// } else { -// widthToRemember = NO_REMEMBERED_WIDTH; -// } -// -// // Remember the selected command name and key sequence. -// final Binding bindingToRemember; -// if ((completionsTable != null) && (!completionsTable.isDisposed())) { -// final int selectedIndex = completionsTable.getSelectionIndex(); -// if (selectedIndex != -1) { -// final TableItem selectedItem = completionsTable -// .getItem(selectedIndex); -// bindingToRemember = (Binding) selectedItem -// .getData(BINDING_KEY); -// } else { -// bindingToRemember = null; -// } -// } else { -// bindingToRemember = null; -// } -// -// rememberState(widthToRemember, bindingToRemember); -// completionsTable = null; -// } -// -// if (resetState) { -// keyBindingState.reset(); -// } -// return super.close(); -// } -// -// /** -// * Sets the position for the dialog based on the position of the workbench -// * window. The dialog is flush with the bottom right corner of the workbench -// * window. However, the dialog will not appear outside of the display's -// * client area. -// * -// * @param size -// * The final size of the dialog; must not be <code>null</code>. -// */ -// private final void configureLocation(final Point size) { -// final Shell shell = getShell(); -// -// final Shell workbenchWindowShell = keyBindingState -// .getAssociatedWindow().getShell(); -// final int xCoord; -// final int yCoord; -// if (workbenchWindowShell != null) { -// /* -// * Position the shell at the bottom right corner of the workbench -// * window -// */ -// final Rectangle workbenchWindowBounds = workbenchWindowShell -// .getBounds(); -// xCoord = workbenchWindowBounds.x + workbenchWindowBounds.width -// - size.x - 10; -// yCoord = workbenchWindowBounds.y + workbenchWindowBounds.height -// - size.y - 10; -// -// } else { -// xCoord = 0; -// yCoord = 0; -// -// } -// final Rectangle bounds = new Rectangle(xCoord, yCoord, size.x, size.y); -// shell.setBounds(getConstrainedShellBounds(bounds)); -// } -// -// /** -// * Sets the size for the dialog based on its previous size. The width of the -// * dialog is its previous width, if it exists. Otherwise, it is simply the -// * packed width of the dialog. The maximum width is 40% of the workbench -// * window's width. The dialog's height is the packed height of the dialog to -// * a maximum of half the height of the workbench window. -// * -// * @return The size of the dialog -// */ -// private final Point configureSize() { -// final Shell shell = getShell(); -// -// // Get the packed size of the shell. -// shell.pack(); -// final Point size = shell.getSize(); -// -// // Use the previous width if appropriate. -// if ((previousWidth != NO_REMEMBERED_WIDTH) && (previousWidth > size.x)) { -// size.x = previousWidth; -// } -// -// // Enforce maximum sizing. -// final Shell workbenchWindowShell = keyBindingState -// .getAssociatedWindow().getShell(); -// if (workbenchWindowShell != null) { -// final Point workbenchWindowSize = workbenchWindowShell.getSize(); -// final int maxWidth = workbenchWindowSize.x * 2 / 5; -// final int maxHeight = workbenchWindowSize.y / 2; -// if (size.x > maxWidth) { -// size.x = maxWidth; -// } -// if (size.y > maxHeight) { -// size.y = maxHeight; -// } -// } -// -// // Set the size for the shell. -// shell.setSize(size); -// return size; -// } -// -// /** -// * Returns a string representing the key sequence used to open this dialog. -// * -// * @return the string describing the key sequence, or <code>null</code> if -// * it cannot be determined. -// */ -// private String getKeySequenceString() { -// final Command command = commandService -// .getCommand(IWorkbenchCommandConstants.WINDOW_SHOW_KEY_ASSIST); -// final TriggerSequence[] keyBindings = bindingService -// .getActiveBindingsFor(new ParameterizedCommand(command, null)); -// final int keyBindingsCount = keyBindings.length; -// final KeySequence currentState = keyBindingState.getCurrentSequence(); -// final int prefixSize = currentState.getKeyStrokes().length; -// -// // Try to find the first possible matching key binding. -// KeySequence keySequence = null; -// for (int i = 0; i < keyBindingsCount; i++) { -// keySequence = (KeySequence) keyBindings[i]; -// -// // Now just double-check to make sure the key is still possible. -// if (prefixSize > 0) { -// if (keySequence.startsWith(currentState, false)) { -// /* -// * Okay, so we have a partial match. Replace the key binding -// * with the required suffix completion. -// */ -// final KeyStroke[] oldKeyStrokes = keySequence -// .getKeyStrokes(); -// final int newSize = oldKeyStrokes.length - prefixSize; -// final KeyStroke[] newKeyStrokes = new KeyStroke[newSize]; -// System.arraycopy(oldKeyStrokes, prefixSize, newKeyStrokes, -// 0, newSize); -// keySequence = KeySequence.getInstance(newKeyStrokes); -// break; -// } -// -// /* -// * The prefix doesn't match, so null out the key binding and try -// * again. -// */ -// keySequence = null; -// continue; -// -// } -// -// // There is no prefix, so just grab the first. -// break; -// } -// if (keySequence == null) { -// return null; // couldn't find a suitable key binding -// } -// +/******************************************************************************* + * Copyright (c) 2004, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.keys; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.ParameterizedCommand; +import org.eclipse.core.commands.common.CommandException; +import org.eclipse.core.commands.common.NotDefinedException; +import org.eclipse.jface.bindings.Binding; +import org.eclipse.jface.bindings.TriggerSequence; +import org.eclipse.jface.bindings.keys.KeySequence; +import org.eclipse.jface.bindings.keys.KeyStroke; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.PopupDialog; +import org.eclipse.jface.preference.PreferenceDialog; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchCommandConstants; +import org.eclipse.ui.activities.IActivityManager; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.contexts.IContextService; +import org.eclipse.ui.dialogs.PreferencesUtil; +import org.eclipse.ui.keys.IBindingService; + +/** + * <p> + * A dialog displaying a list of key bindings. The dialog will execute a command + * if it is selected. + * </p> + * <p> + * The methods on this class are not thread-safe and must be run from the UI + * thread. + * </p> + * + * @since 3.1 + */ +final class KeyAssistDialog extends PopupDialog { + + /** + * The data key for the binding stored on an SWT widget. The key is a + * fully-qualified name, but in reverse order. This is so that the equals + * method will detect misses faster. + */ + private static final String BINDING_KEY = "Binding.bindings.jface.eclipse.org"; //$NON-NLS-1$ + + /** + * The value of <code>previousWidth</code> to set if there is no + * remembered width. + */ + private static final int NO_REMEMBERED_WIDTH = -1; + + /** + * The activity manager for the associated workbench. + */ + private final IActivityManager activityManager; + + /** + * The binding service for the associated workbench. + */ + private final IBindingService bindingService; + + /** + * The binding that was selected when the key assist dialog last closed. + * This is only remembered until <code>clearRememberedState()</code> is + * called. + */ + private Binding binding = null; + + /** + * The ordered list of command identifiers corresponding to the table. + */ + private final List bindings = new ArrayList(); + + /** + * The command service for the associated workbench. + */ + private final ICommandService commandService; + + /** + * The table containing of the possible completions. This value is + * <code>null</code> until the dialog is created. + */ + private Table completionsTable = null; + + /** + * Whether this dialog is currently holding some remembered state. + */ + private boolean hasRememberedState = false; + + /** + * The key binding state for the associated workbench. + */ + private final KeyBindingState keyBindingState; + + /** + * The width of the shell when it was previously open. This is only + * remembered until <code>clearRememberedState()</code> is called. + */ + private int previousWidth = NO_REMEMBERED_WIDTH; + + /** + * The key binding listener for the associated workbench. + */ + private final WorkbenchKeyboard workbenchKeyboard; + + /** + * A sorted map of conflicts to be used when the dialog pops up. + * + * @since 3.3 + */ + private SortedMap conflictMatches; + + /** + * Constructs a new instance of <code>KeyAssistDialog</code>. When the + * dialog is first constructed, it contains no widgets. The dialog is first + * created with no parent. If a parent is required, call + * <code>setParentShell()</code>. Also, between uses, it might be + * necessary to call <code>setParentShell()</code> as well. + * + * @param workbench + * The workbench in which this dialog is created; must not be + * <code>null</code>. + * @param associatedKeyboard + * The key binding listener for the workbench; must not be + * <code>null</code>. + * @param associatedState + * The key binding state associated with the workbench; must not + * be <code>null</code>. + */ + KeyAssistDialog(final IWorkbench workbench, + final WorkbenchKeyboard associatedKeyboard, + final KeyBindingState associatedState) { + super((Shell) null, PopupDialog.INFOPOPUP_SHELLSTYLE, true, false, + false, false, null, null); + + this.activityManager = workbench.getActivitySupport() + .getActivityManager(); + this.bindingService = (IBindingService) workbench + .getService(IBindingService.class); + this.commandService = (ICommandService) workbench + .getService(ICommandService.class); + this.keyBindingState = associatedState; + this.workbenchKeyboard = associatedKeyboard; + + this.setInfoText(getKeySequenceString()); + } + + /** + * Clears out the remembered state of the key assist dialog. This includes + * its width, as well as the selected binding. + */ + final void clearRememberedState() { + previousWidth = NO_REMEMBERED_WIDTH; + binding = null; + hasRememberedState = false; + } + + /** + * Closes this shell, but first remembers some state of the dialog. This way + * it will have a response if asked to open the dialog again or if asked to + * open the keys preference page. This does not remember the internal state. + * + * @return Whether the shell was already closed. + */ + public final boolean close() { + return close(false); + } + + /** + * Closes this shell, but first remembers some state of the dialog. This way + * it will have a response if asked to open the dialog again or if asked to + * open the keys preference page. + * + * @param rememberState + * Whether the internal state should be remembered. + * @return Whether the shell was already closed. + */ + public final boolean close(final boolean rememberState) { + return close(rememberState, true); + } + + /** + * Closes this shell, but first remembers some state of the dialog. This way + * it will have a response if asked to open the dialog again or if asked to + * open the keys preference page. + * + * @param rememberState + * Whether the internal state should be remembered. + * @param resetState + * Whether the state should be reset. + * @return Whether the shell was already closed. + */ + private final boolean close(final boolean rememberState, + final boolean resetState) { + final Shell shell = getShell(); + if (rememberState) { + // Remember the previous width. + final int widthToRemember; + if ((shell != null) && (!shell.isDisposed())) { + widthToRemember = getShell().getSize().x; + } else { + widthToRemember = NO_REMEMBERED_WIDTH; + } + + // Remember the selected command name and key sequence. + final Binding bindingToRemember; + if ((completionsTable != null) && (!completionsTable.isDisposed())) { + final int selectedIndex = completionsTable.getSelectionIndex(); + if (selectedIndex != -1) { + final TableItem selectedItem = completionsTable + .getItem(selectedIndex); + bindingToRemember = (Binding) selectedItem + .getData(BINDING_KEY); + } else { + bindingToRemember = null; + } + } else { + bindingToRemember = null; + } + + rememberState(widthToRemember, bindingToRemember); + completionsTable = null; + } + + if (resetState) { + keyBindingState.reset(); + } + return super.close(); + } + + /** + * Sets the position for the dialog based on the position of the workbench + * window. The dialog is flush with the bottom right corner of the workbench + * window. However, the dialog will not appear outside of the display's + * client area. + * + * @param size + * The final size of the dialog; must not be <code>null</code>. + */ + private final void configureLocation(final Point size) { + final Shell shell = getShell(); + + final Shell workbenchWindowShell = keyBindingState + .getAssociatedWindow().getShell(); + final int xCoord; + final int yCoord; + if (workbenchWindowShell != null) { + /* + * Position the shell at the bottom right corner of the workbench + * window + */ + final Rectangle workbenchWindowBounds = workbenchWindowShell + .getBounds(); + xCoord = workbenchWindowBounds.x + workbenchWindowBounds.width + - size.x - 10; + yCoord = workbenchWindowBounds.y + workbenchWindowBounds.height + - size.y - 10; + + } else { + xCoord = 0; + yCoord = 0; + + } + final Rectangle bounds = new Rectangle(xCoord, yCoord, size.x, size.y); + shell.setBounds(getConstrainedShellBounds(bounds)); + } + + /** + * Sets the size for the dialog based on its previous size. The width of the + * dialog is its previous width, if it exists. Otherwise, it is simply the + * packed width of the dialog. The maximum width is 40% of the workbench + * window's width. The dialog's height is the packed height of the dialog to + * a maximum of half the height of the workbench window. + * + * @return The size of the dialog + */ + private final Point configureSize() { + final Shell shell = getShell(); + + // Get the packed size of the shell. + shell.pack(); + final Point size = shell.getSize(); + + // Use the previous width if appropriate. + if ((previousWidth != NO_REMEMBERED_WIDTH) && (previousWidth > size.x)) { + size.x = previousWidth; + } + + // Enforce maximum sizing. + final Shell workbenchWindowShell = keyBindingState + .getAssociatedWindow().getShell(); + if (workbenchWindowShell != null) { + final Point workbenchWindowSize = workbenchWindowShell.getSize(); + final int maxWidth = workbenchWindowSize.x * 2 / 5; + final int maxHeight = workbenchWindowSize.y / 2; + if (size.x > maxWidth) { + size.x = maxWidth; + } + if (size.y > maxHeight) { + size.y = maxHeight; + } + } + + // Set the size for the shell. + shell.setSize(size); + return size; + } + + /** + * Returns a string representing the key sequence used to open this dialog. + * + * @return the string describing the key sequence, or <code>null</code> if + * it cannot be determined. + */ + private String getKeySequenceString() { + final Command command = commandService + .getCommand(IWorkbenchCommandConstants.WINDOW_SHOW_KEY_ASSIST); + final TriggerSequence[] keyBindings = bindingService + .getActiveBindingsFor(new ParameterizedCommand(command, null)); + final int keyBindingsCount = keyBindings.length; + final KeySequence currentState = keyBindingState.getCurrentSequence(); + final int prefixSize = currentState.getKeyStrokes().length; + + // Try to find the first possible matching key binding. + KeySequence keySequence = null; + for (int i = 0; i < keyBindingsCount; i++) { + keySequence = (KeySequence) keyBindings[i]; + + // Now just double-check to make sure the key is still possible. + if (prefixSize > 0) { + if (keySequence.startsWith(currentState, false)) { + /* + * Okay, so we have a partial match. Replace the key binding + * with the required suffix completion. + */ + final KeyStroke[] oldKeyStrokes = keySequence + .getKeyStrokes(); + final int newSize = oldKeyStrokes.length - prefixSize; + final KeyStroke[] newKeyStrokes = new KeyStroke[newSize]; + System.arraycopy(oldKeyStrokes, prefixSize, newKeyStrokes, + 0, newSize); + keySequence = KeySequence.getInstance(newKeyStrokes); + break; + } + + /* + * The prefix doesn't match, so null out the key binding and try + * again. + */ + keySequence = null; + continue; + + } + + // There is no prefix, so just grab the first. + break; + } + if (keySequence == null) { + return null; // couldn't find a suitable key binding + } +// RAP [if]: need session aware messages // return NLS.bind(KeyAssistMessages.openPreferencePage, keySequence // .format()); -// } -// -// /** -// * Creates the content area for the key assistant. This creates a table and -// * places it inside the composite. The composite will contain a list of all -// * the key bindings. -// * -// * @param parent -// * The parent composite to contain the dialog area; must not be -// * <code>null</code>. -// */ -// protected final Control createDialogArea(final Composite parent) { -// // First, register the shell type with the context support -// registerShellType(); -// -// // Create a composite for the dialog area. -// final Composite composite = new Composite(parent, SWT.NONE); -// final GridLayout compositeLayout = new GridLayout(); -// compositeLayout.marginHeight = 0; -// compositeLayout.marginWidth = 0; -// composite.setLayout(compositeLayout); -// composite.setLayoutData(new GridData(GridData.FILL_BOTH)); -// composite.setBackground(parent.getBackground()); -// -// // Layout the partial matches. -// final SortedMap partialMatches; -// if (conflictMatches != null) { -// partialMatches = conflictMatches; -// conflictMatches = null; -// } else { -// partialMatches = getPartialMatches(); -// } -// -// if (partialMatches.isEmpty()) { -// createEmptyDialogArea(composite); -// } else { -// createTableDialogArea(composite, partialMatches); -// } -// return composite; -// } -// -// /** -// * Creates an empty dialog area with a simple message saying there were no -// * matches. This is used if no partial matches could be found. This should -// * not really ever happen, but might be possible if the commands are -// * changing while waiting for this dialog to open. -// * -// * @param parent -// * The parent composite for the dialog area; must not be -// * <code>null</code>. -// */ -// private final void createEmptyDialogArea(final Composite parent) { -// final Label noMatchesLabel = new Label(parent, SWT.NULL); + return NLS.bind(KeyAssistMessages.get().openPreferencePage, keySequence + .format()); + } + + /** + * Creates the content area for the key assistant. This creates a table and + * places it inside the composite. The composite will contain a list of all + * the key bindings. + * + * @param parent + * The parent composite to contain the dialog area; must not be + * <code>null</code>. + */ + protected final Control createDialogArea(final Composite parent) { + // First, register the shell type with the context support + registerShellType(); + + // Create a composite for the dialog area. + final Composite composite = new Composite(parent, SWT.NONE); + final GridLayout compositeLayout = new GridLayout(); + compositeLayout.marginHeight = 0; + compositeLayout.marginWidth = 0; + composite.setLayout(compositeLayout); + composite.setLayoutData(new GridData(GridData.FILL_BOTH)); + composite.setBackground(parent.getBackground()); + + // Layout the partial matches. + final SortedMap partialMatches; + if (conflictMatches != null) { + partialMatches = conflictMatches; + conflictMatches = null; + } else { + partialMatches = getPartialMatches(); + } + + if (partialMatches.isEmpty()) { + createEmptyDialogArea(composite); + } else { + createTableDialogArea(composite, partialMatches); + } + return composite; + } + + /** + * Creates an empty dialog area with a simple message saying there were no + * matches. This is used if no partial matches could be found. This should + * not really ever happen, but might be possible if the commands are + * changing while waiting for this dialog to open. + * + * @param parent + * The parent composite for the dialog area; must not be + * <code>null</code>. + */ + private final void createEmptyDialogArea(final Composite parent) { + final Label noMatchesLabel = new Label(parent, SWT.NULL); +// RAP [if]: need session aware messages // noMatchesLabel.setText(KeyAssistMessages.NoMatches_Message); -// noMatchesLabel.setLayoutData(new GridData(GridData.FILL_BOTH)); -// noMatchesLabel.setBackground(parent.getBackground()); -// } -// -// /** -// * Creates a dialog area with a table of the partial matches for the current -// * key binding state. The table will be either the minimum width, or -// * <code>previousWidth</code> if it is not -// * <code>NO_REMEMBERED_WIDTH</code>. -// * -// * @param parent -// * The parent composite for the dialog area; must not be -// * <code>null</code>. -// * @param partialMatches -// * The lexicographically sorted map of partial matches for the -// * current state; must not be <code>null</code> or empty. -// */ -// private final void createTableDialogArea(final Composite parent, -// final SortedMap partialMatches) { -// // Layout the table. -// completionsTable = new Table(parent, SWT.FULL_SELECTION | SWT.SINGLE); -// final GridData gridData = new GridData(GridData.FILL_BOTH); -// completionsTable.setLayoutData(gridData); -// completionsTable.setBackground(parent.getBackground()); -// completionsTable.setLinesVisible(true); -// -// // Initialize the columns and rows. -// bindings.clear(); -// final TableColumn columnCommandName = new TableColumn(completionsTable, -// SWT.LEFT, 0); -// final TableColumn columnKeySequence = new TableColumn(completionsTable, -// SWT.LEFT, 1); -// final Iterator itemsItr = partialMatches.entrySet().iterator(); -// while (itemsItr.hasNext()) { -// final Map.Entry entry = (Map.Entry) itemsItr.next(); -// final String sequence = (String) entry.getValue(); -// final Binding binding = (Binding) entry.getKey(); -// final ParameterizedCommand command = binding -// .getParameterizedCommand(); -// try { -// final String[] text = { command.getName(), sequence }; -// final TableItem item = new TableItem(completionsTable, SWT.NULL); -// item.setText(text); -// item.setData(BINDING_KEY, binding); -// bindings.add(binding); -// } catch (NotDefinedException e) { -// // Not much to do, but this shouldn't really happen. -// } -// } -// -// Dialog.applyDialogFont(parent); -// columnKeySequence.pack(); -// if (previousWidth != NO_REMEMBERED_WIDTH) { -// columnKeySequence.setWidth(previousWidth); -// } -// columnCommandName.pack(); -// if (completionsTable.getItems().length > 0) { -// completionsTable.setSelection(0); -// } -// -// /* -// * If you double-click on the table, it should execute the selected -// * command. -// */ -// completionsTable.addListener(SWT.DefaultSelection, new Listener() { -// public final void handleEvent(final Event event) { -// executeKeyBinding(event); -// } -// }); -// } -// -// /** -// * Edits the remembered selection in the preference dialog. -// */ -// private final void editKeyBinding() { -// // Create a preference dialog on the keys preference page. -// final String keysPageId = "org.eclipse.ui.preferencePages.Keys"; //$NON-NLS-1$ -// final PreferenceDialog dialog = PreferencesUtil -// .createPreferenceDialogOn(getShell(), keysPageId, null, binding); -// -// /* -// * Forget the remembered state (so we don't get stuck editing -// * preferences). -// */ -// clearRememberedState(); -// -// // Open the dialog (blocking). -// dialog.open(); -// } -// -// /** -// * Handles the default selection event on the table of possible completions. -// * This attempts to execute the given command. -// */ -// private final void executeKeyBinding(final Event trigger) { -// // Try to execute the corresponding command. -// final int selectionIndex = completionsTable.getSelectionIndex(); -// if (selectionIndex >= 0) { -// final Binding binding = (Binding) bindings.get(selectionIndex); -// try { -// workbenchKeyboard.updateShellKludge(null); -// workbenchKeyboard.executeCommand(binding, trigger); -// } catch (final CommandException e) { -// workbenchKeyboard.logException(e, binding -// .getParameterizedCommand()); -// } -// } -// } -// -// /** -// * Gets the list of key bindings that are partial matches to the current key -// * binding state. -// * -// * @return A sorted map of key sequences (KeySequence) to command identifier -// * (String) representing the list of enabled commands that could -// * possibly complete the current key sequence. -// */ -// private final SortedMap getPartialMatches() { -// // Put all partial matches into the matches into the map. -// final Map partialMatches = bindingService -// .getPartialMatches(keyBindingState.getCurrentSequence()); -// -// // Create a sorted map that sorts based on lexicographical order. -// final SortedMap sortedMatches = new TreeMap(new Comparator() { -// public final int compare(final Object a, final Object b) { -// final Binding bindingA = (Binding) a; -// final Binding bindingB = (Binding) b; -// final ParameterizedCommand commandA = bindingA -// .getParameterizedCommand(); -// final ParameterizedCommand commandB = bindingB -// .getParameterizedCommand(); -// try { -// return commandA.getName().compareTo(commandB.getName()); -// } catch (final NotDefinedException e) { -// // should not happen -// return 0; -// } -// } -// }); -// -// /* -// * Remove those partial matches for which either the command is not -// * identified or the activity manager believes the command is not -// * enabled. -// */ -// final Iterator partialMatchItr = partialMatches.entrySet().iterator(); -// while (partialMatchItr.hasNext()) { -// final Map.Entry entry = (Map.Entry) partialMatchItr.next(); -// final Binding binding = (Binding) entry.getValue(); -// final Command command = binding.getParameterizedCommand() -// .getCommand(); -// if (command.isDefined() -// && activityManager.getIdentifier(command.getId()) -// .isEnabled()) { -// TriggerSequence bestActiveBindingFor = bindingService.getBestActiveBindingFor(binding.getParameterizedCommand()); -// sortedMatches.put(binding, bestActiveBindingFor==null?null:bestActiveBindingFor.format()); -// } -// } -// -// return sortedMatches; -// -// } -// -// /** -// * Returns whether the dialog is currently holding some remembered state. -// * -// * @return <code>true</code> if the dialog has remembered state; -// * <code>false</code> otherwise. -// */ -// private final boolean hasRememberedState() { -// return hasRememberedState; -// } -// -// /** -// * Opens this dialog. This method can be called multiple times on the same -// * dialog. This only opens the dialog if there is no remembered state; if -// * there is remembered state, then it tries to open the preference page -// * instead. -// * -// * @return The return code from this dialog. -// */ -// public final int open() { -// // If there is remember state, open the preference page. -// if (hasRememberedState()) { -// editKeyBinding(); -// clearRememberedState(); -// return Window.OK; -// } -// -// // If the dialog is already open, dispose the shell and recreate it. -// final Shell shell = getShell(); -// if (shell != null) { -// close(false, false); -// } -// create(); -// -// // Configure the size and location. -// final Point size = configureSize(); -// configureLocation(size); -// -// // Call the super method. -// return super.open(); -// } -// -// /** -// * Opens this dialog with the list of bindings for the user to select from. -// * -// * @return The return code from this dialog. -// * @since 3.3 -// */ -// public final int open(Collection bindings) { -// conflictMatches = new TreeMap(new Comparator() { -// public final int compare(final Object a, final Object b) { -// final Binding bindingA = (Binding) a; -// final Binding bindingB = (Binding) b; -// final ParameterizedCommand commandA = bindingA -// .getParameterizedCommand(); -// final ParameterizedCommand commandB = bindingB -// .getParameterizedCommand(); -// try { -// return commandA.getName().compareTo(commandB.getName()); -// } catch (final NotDefinedException e) { -// // should not happen -// return 0; -// } -// } -// }); -// Iterator i = bindings.iterator(); -// while (i.hasNext()) { -// Binding b = (Binding) i.next(); -// TriggerSequence bestActiveBindingFor = bindingService.getBestActiveBindingFor(b.getParameterizedCommand()); -// conflictMatches.put(b, bestActiveBindingFor==null?null:bestActiveBindingFor.format()); -// } -// -// // If the dialog is already open, dispose the shell and recreate it. -// final Shell shell = getShell(); -// if (shell != null) { -// close(false, false); -// } -// create(); -// -// // Configure the size and location. -// final Point size = configureSize(); -// configureLocation(size); -// -// // Call the super method. -// return super.open(); -// } -// -// /** -// * Registers the shell as the same type as its parent with the context -// * support. This ensures that it does not modify the current state of the -// * application. -// */ -// private final void registerShellType() { -// final Shell shell = getShell(); -// final IContextService contextService = (IContextService) keyBindingState -// .getAssociatedWindow().getWorkbench().getService( -// IContextService.class); -// contextService.registerShell(shell, contextService -// .getShellType((Shell) shell.getParent())); -// } -// -// /** -// * Remembers the current state of this dialog. -// * -// * @param previousWidth -// * The previous width of the dialog. -// * @param binding -// * The binding to remember, may be <code>null</code> if none. -// */ -// private final void rememberState(final int previousWidth, -// final Binding binding) { -// this.previousWidth = previousWidth; -// this.binding = binding; -// hasRememberedState = true; -// } -// -// /** -// * Exposing this within the keys package. -// * -// * @param newParentShell -// * The new parent shell; this value may be <code>null</code> if -// * there is to be no parent. -// */ -// protected final void setParentShell(final Shell newParentShell) { -// super.setParentShell(newParentShell); -// } -//} + noMatchesLabel.setText(KeyAssistMessages.get().NoMatches_Message); + noMatchesLabel.setLayoutData(new GridData(GridData.FILL_BOTH)); + noMatchesLabel.setBackground(parent.getBackground()); + } + + /** + * Creates a dialog area with a table of the partial matches for the current + * key binding state. The table will be either the minimum width, or + * <code>previousWidth</code> if it is not + * <code>NO_REMEMBERED_WIDTH</code>. + * + * @param parent + * The parent composite for the dialog area; must not be + * <code>null</code>. + * @param partialMatches + * The lexicographically sorted map of partial matches for the + * current state; must not be <code>null</code> or empty. + */ + private final void createTableDialogArea(final Composite parent, + final SortedMap partialMatches) { + // Layout the table. + completionsTable = new Table(parent, SWT.FULL_SELECTION | SWT.SINGLE); + final GridData gridData = new GridData(GridData.FILL_BOTH); + completionsTable.setLayoutData(gridData); + completionsTable.setBackground(parent.getBackground()); + completionsTable.setLinesVisible(true); + + // Initialize the columns and rows. + bindings.clear(); + final TableColumn columnCommandName = new TableColumn(completionsTable, + SWT.LEFT, 0); + final TableColumn columnKeySequence = new TableColumn(completionsTable, + SWT.LEFT, 1); + final Iterator itemsItr = partialMatches.entrySet().iterator(); + while (itemsItr.hasNext()) { + final Map.Entry entry = (Map.Entry) itemsItr.next(); + final String sequence = (String) entry.getValue(); + final Binding binding = (Binding) entry.getKey(); + final ParameterizedCommand command = binding + .getParameterizedCommand(); + try { + final String[] text = { command.getName(), sequence }; + final TableItem item = new TableItem(completionsTable, SWT.NULL); + item.setText(text); + item.setData(BINDING_KEY, binding); + bindings.add(binding); + } catch (NotDefinedException e) { + // Not much to do, but this shouldn't really happen. + } + } + + Dialog.applyDialogFont(parent); + columnKeySequence.pack(); + if (previousWidth != NO_REMEMBERED_WIDTH) { + columnKeySequence.setWidth(previousWidth); + } + columnCommandName.pack(); + if (completionsTable.getItems().length > 0) { + completionsTable.setSelection(0); + } + + /* + * If you double-click on the table, it should execute the selected + * command. + */ + completionsTable.addListener(SWT.DefaultSelection, new Listener() { + public final void handleEvent(final Event event) { + executeKeyBinding(event); + } + }); + } + + /** + * Edits the remembered selection in the preference dialog. + */ + private final void editKeyBinding() { + // Create a preference dialog on the keys preference page. + final String keysPageId = "org.eclipse.ui.preferencePages.Keys"; //$NON-NLS-1$ + final PreferenceDialog dialog = PreferencesUtil + .createPreferenceDialogOn(getShell(), keysPageId, null, binding); + + /* + * Forget the remembered state (so we don't get stuck editing + * preferences). + */ + clearRememberedState(); + + // Open the dialog (blocking). + dialog.open(); + } + + /** + * Handles the default selection event on the table of possible completions. + * This attempts to execute the given command. + */ + private final void executeKeyBinding(final Event trigger) { + // Try to execute the corresponding command. + final int selectionIndex = completionsTable.getSelectionIndex(); + if (selectionIndex >= 0) { + final Binding binding = (Binding) bindings.get(selectionIndex); + try { + workbenchKeyboard.updateShellKludge(null); + workbenchKeyboard.executeCommand(binding, trigger); + } catch (final CommandException e) { + workbenchKeyboard.logException(e, binding + .getParameterizedCommand()); + } + } + } + + /** + * Gets the list of key bindings that are partial matches to the current key + * binding state. + * + * @return A sorted map of key sequences (KeySequence) to command identifier + * (String) representing the list of enabled commands that could + * possibly complete the current key sequence. + */ + private final SortedMap getPartialMatches() { + // Put all partial matches into the matches into the map. + final Map partialMatches = bindingService + .getPartialMatches(keyBindingState.getCurrentSequence()); + + // Create a sorted map that sorts based on lexicographical order. + final SortedMap sortedMatches = new TreeMap(new Comparator() { + public final int compare(final Object a, final Object b) { + final Binding bindingA = (Binding) a; + final Binding bindingB = (Binding) b; + final ParameterizedCommand commandA = bindingA + .getParameterizedCommand(); + final ParameterizedCommand commandB = bindingB + .getParameterizedCommand(); + try { + return commandA.getName().compareTo(commandB.getName()); + } catch (final NotDefinedException e) { + // should not happen + return 0; + } + } + }); + + /* + * Remove those partial matches for which either the command is not + * identified or the activity manager believes the command is not + * enabled. + */ + final Iterator partialMatchItr = partialMatches.entrySet().iterator(); + while (partialMatchItr.hasNext()) { + final Map.Entry entry = (Map.Entry) partialMatchItr.next(); + final Binding binding = (Binding) entry.getValue(); + final Command command = binding.getParameterizedCommand() + .getCommand(); + if (command.isDefined() + && activityManager.getIdentifier(command.getId()) + .isEnabled()) { + TriggerSequence bestActiveBindingFor = bindingService.getBestActiveBindingFor(binding.getParameterizedCommand()); + sortedMatches.put(binding, bestActiveBindingFor==null?null:bestActiveBindingFor.format()); + } + } + + return sortedMatches; + + } + + /** + * Returns whether the dialog is currently holding some remembered state. + * + * @return <code>true</code> if the dialog has remembered state; + * <code>false</code> otherwise. + */ + private final boolean hasRememberedState() { + return hasRememberedState; + } + + /** + * Opens this dialog. This method can be called multiple times on the same + * dialog. This only opens the dialog if there is no remembered state; if + * there is remembered state, then it tries to open the preference page + * instead. + * + * @return The return code from this dialog. + */ + public final int open() { + // If there is remember state, open the preference page. + if (hasRememberedState()) { + editKeyBinding(); + clearRememberedState(); + return Window.OK; + } + + // If the dialog is already open, dispose the shell and recreate it. + final Shell shell = getShell(); + if (shell != null) { + close(false, false); + } + create(); + + // Configure the size and location. + final Point size = configureSize(); + configureLocation(size); + + // Call the super method. + return super.open(); + } + + /** + * Opens this dialog with the list of bindings for the user to select from. + * + * @return The return code from this dialog. + * @since 3.3 + */ + public final int open(Collection bindings) { + conflictMatches = new TreeMap(new Comparator() { + public final int compare(final Object a, final Object b) { + final Binding bindingA = (Binding) a; + final Binding bindingB = (Binding) b; + final ParameterizedCommand commandA = bindingA + .getParameterizedCommand(); + final ParameterizedCommand commandB = bindingB + .getParameterizedCommand(); + try { + return commandA.getName().compareTo(commandB.getName()); + } catch (final NotDefinedException e) { + // should not happen + return 0; + } + } + }); + Iterator i = bindings.iterator(); + while (i.hasNext()) { + Binding b = (Binding) i.next(); + TriggerSequence bestActiveBindingFor = bindingService.getBestActiveBindingFor(b.getParameterizedCommand()); + conflictMatches.put(b, bestActiveBindingFor==null?null:bestActiveBindingFor.format()); + } + + // If the dialog is already open, dispose the shell and recreate it. + final Shell shell = getShell(); + if (shell != null) { + close(false, false); + } + create(); + + // Configure the size and location. + final Point size = configureSize(); + configureLocation(size); + + // Call the super method. + return super.open(); + } + + /** + * Registers the shell as the same type as its parent with the context + * support. This ensures that it does not modify the current state of the + * application. + */ + private final void registerShellType() { + final Shell shell = getShell(); + final IContextService contextService = (IContextService) keyBindingState + .getAssociatedWindow().getWorkbench().getService( + IContextService.class); + contextService.registerShell(shell, contextService + .getShellType((Shell) shell.getParent())); + } + + /** + * Remembers the current state of this dialog. + * + * @param previousWidth + * The previous width of the dialog. + * @param binding + * The binding to remember, may be <code>null</code> if none. + */ + private final void rememberState(final int previousWidth, + final Binding binding) { + this.previousWidth = previousWidth; + this.binding = binding; + hasRememberedState = true; + } + + /** + * Exposing this within the keys package. + * + * @param newParentShell + * The new parent shell; this value may be <code>null</code> if + * there is to be no parent. + */ + protected final void setParentShell(final Shell newParentShell) { + super.setParentShell(newParentShell); + } +} diff --git a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeyAssistMessages.java b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeyAssistMessages.java index b6934a082f..41e74e699a 100755 --- a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeyAssistMessages.java +++ b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeyAssistMessages.java @@ -1,34 +1,47 @@ -// RAP [rh] Keys completely disabled as not implemented in RWT -///******************************************************************************* -// * Copyright (c) 2005 IBM Corporation and others. -// * All rights reserved. This program and the accompanying materials -// * are made available under the terms of the Eclipse Public License v1.0 -// * which accompanies this distribution, and is available at -// * http://www.eclipse.org/legal/epl-v10.html -// * -// * Contributors: -// * IBM Corporation - initial API and implementation -// *******************************************************************************/ -//package org.eclipse.ui.internal.keys; -// +/******************************************************************************* + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.keys; + +import org.eclipse.rwt.RWT; + //import org.eclipse.osgi.util.NLS; -// -// -// -///** -// * The KeyAssistMessages class is the class that manages the messages -// * used in the KeyAssistDialog. -// * -// */ + + + +/** + * The KeyAssistMessages class is the class that manages the messages + * used in the KeyAssistDialog. + * + */ +// RAP [if]: need session aware NLS //public class KeyAssistMessages extends NLS { -// private static final String BUNDLE_NAME = "org.eclipse.ui.internal.keys.KeyAssistDialog";//$NON-NLS-1$ -// -// public static String NoMatches_Message; -// public static String openPreferencePage; -// -// +public class KeyAssistMessages { + private static final String BUNDLE_NAME = "org.eclipse.ui.internal.keys.KeyAssistDialog";//$NON-NLS-1$ + + public String NoMatches_Message; + public String openPreferencePage; + +// RAP [if]: need session aware NLS // static { // // load message values from bundle file // NLS.initializeMessages(BUNDLE_NAME, KeyAssistMessages.class); // } -//} + + /** + * Load message values from bundle file + * @return localized message + */ + public static KeyAssistMessages get() { + Class clazz = KeyAssistMessages.class; + Object result = RWT.NLS.getISO8859_1Encoded( BUNDLE_NAME, clazz ); + return ( KeyAssistMessages )result; + } +} diff --git a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeyBindingState.java b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeyBindingState.java index b491a37ab3..60a9bfecdc 100755 --- a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeyBindingState.java +++ b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/KeyBindingState.java @@ -1,173 +1,172 @@ -// RAP [rh] Keys completely disabled as not implemented in RWT -///******************************************************************************* -// * Copyright (c) 2000, 2007 IBM Corporation and others. -// * All rights reserved. This program and the accompanying materials -// * are made available under the terms of the Eclipse Public License v1.0 -// * which accompanies this distribution, and is available at -// * http://www.eclipse.org/legal/epl-v10.html -// * -// * Contributors: -// * IBM Corporation - initial API and implementation -// *******************************************************************************/ -// -//package org.eclipse.ui.internal.keys; -// -//import org.eclipse.jface.action.IContributionItem; -//import org.eclipse.jface.action.IStatusLineManager; -//import org.eclipse.jface.action.StatusLineContributionItem; -//import org.eclipse.jface.bindings.keys.KeySequence; -//import org.eclipse.ui.IWorkbench; -//import org.eclipse.ui.IWorkbenchWindow; -//import org.eclipse.ui.internal.WorkbenchWindow; -// -///** -// * <p> -// * The mutable state of the key binding architecture. This is the only piece of -// * the key binding architecture that changes (internally). It keeps track of -// * what partial key strokes the user has entered. In the case of functional -// * groups of key bindings, it allows the user to keep part of the key sequence -// * even after a match has been made. Only after releasing all of the modifier -// * keys would the sequence reset itself. -// * </p> -// * <p> -// * In the current implementation, a partial reset results in only one key -// * stroke being left in the sequence. However, this may change in the future. -// * </p> -// * -// * @since 3.0 -// */ -//class KeyBindingState { -// -// /** -// * The workbench window associated with this state. The state can only -// * exist for one window. When the focus leaves this window then the mode -// * must automatically be reset. -// */ -// private IWorkbenchWindow associatedWindow; -// -// /** -// * This is the current extent of the sequence entered by the user. In an -// * application with only single-stroke key bindings, this will also be -// * empty. However, in applications with multi-stroke key bindings, this is -// * the sequence entered by the user that partially matches another one of -// * the application's active key bindings. -// */ -// private KeySequence currentSequence; -// -// /** -// * The workbench that should be notified of changes to the key binding -// * state. This is done by updating one of the contribution items on the -// * status line. -// */ -// private final IWorkbench workbench; -// -// /** -// * Constructs a new instance of <code>KeyBindingState</code> with an -// * empty key sequence, set to reset fully. -// * -// * @param workbenchToNotify -// * The workbench that this state should keep advised of changes -// * to the key binding state; must not be <code>null</code>. -// */ -// KeyBindingState(IWorkbench workbenchToNotify) { -// currentSequence = KeySequence.getInstance(); -// workbench = workbenchToNotify; -// associatedWindow = workbench.getActiveWorkbenchWindow(); -// } -// -// /** -// * An accessor for the workbench window associated with this state. This -// * should never be <code>null</code>, as the setting follows the last -// * workbench window to have focus. -// * -// * @return The workbench window to which the key binding architecture is -// * currently attached; should never be <code>null</code>. -// */ -// IWorkbenchWindow getAssociatedWindow() { -// return associatedWindow; -// } -// -// /** -// * An accessor for the current key sequence waiting for completion. -// * -// * @return The current incomplete key sequence; never <code>null</code>, -// * but may be empty. -// */ -// KeySequence getCurrentSequence() { -// return currentSequence; -// } -// -// /** -// * Gets the status line contribution item which the key binding -// * architecture uses to keep the user up-to-date as to the current state. -// * -// * @return The status line contribution item, if any; <code>null</code>, -// * if none. -// */ -// StatusLineContributionItem getStatusLine() { -// if (associatedWindow instanceof WorkbenchWindow) { -// WorkbenchWindow window = (WorkbenchWindow) associatedWindow; -// IStatusLineManager statusLine = window.getStatusLineManager(); -// // TODO implicit dependency on IDE's action builder -// // @issue implicit dependency on IDE's action builder -// if (statusLine != null) { // this can be null if we're exiting -// IContributionItem item = statusLine -// .find("ModeContributionItem"); //$NON-NLS-1$ -// if (item instanceof StatusLineContributionItem) { -// return ((StatusLineContributionItem) item); -// } -// } -// } -// -// return null; -// } -// -// /** -// * <p> -// * Resets the state based on the current properties. If the state is to -// * collapse fully or if there are no key strokes, then it sets the state to -// * have an empty key sequence. Otherwise, it leaves the first key stroke in -// * the sequence. -// * </p> -// * <p> -// * The workbench's status lines are updated, if appropriate. -// * </p> -// */ -// void reset() { -// currentSequence = KeySequence.getInstance(); -// updateStatusLines(); -// } -// -// /** -// * A mutator for the workbench window to which this state is associated. -// * -// * @param window -// * The workbench window to associated; should never be <code>null</code>. -// */ -// void setAssociatedWindow(IWorkbenchWindow window) { -// associatedWindow = window; -// } -// -// /** -// * A mutator for the partial sequence entered by the user. -// * -// * @param sequence -// * The current key sequence; should not be <code>null</code>, -// * but may be empty. -// */ -// void setCurrentSequence(KeySequence sequence) { -// currentSequence = sequence; -// updateStatusLines(); -// } -// -// /** -// * Updates the text of the status line of the associated shell with the -// * current sequence. -// */ -// private void updateStatusLines() { -// StatusLineContributionItem statusLine = getStatusLine(); -// if (statusLine != null) { -// statusLine.setText(getCurrentSequence().format()); -// } -// } -//} +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.ui.internal.keys; + +import org.eclipse.jface.action.IContributionItem; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.jface.action.StatusLineContributionItem; +import org.eclipse.jface.bindings.keys.KeySequence; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.internal.WorkbenchWindow; + +/** + * <p> + * The mutable state of the key binding architecture. This is the only piece of + * the key binding architecture that changes (internally). It keeps track of + * what partial key strokes the user has entered. In the case of functional + * groups of key bindings, it allows the user to keep part of the key sequence + * even after a match has been made. Only after releasing all of the modifier + * keys would the sequence reset itself. + * </p> + * <p> + * In the current implementation, a partial reset results in only one key + * stroke being left in the sequence. However, this may change in the future. + * </p> + * + * @since 3.0 + */ +class KeyBindingState { + + /** + * The workbench window associated with this state. The state can only + * exist for one window. When the focus leaves this window then the mode + * must automatically be reset. + */ + private IWorkbenchWindow associatedWindow; + + /** + * This is the current extent of the sequence entered by the user. In an + * application with only single-stroke key bindings, this will also be + * empty. However, in applications with multi-stroke key bindings, this is + * the sequence entered by the user that partially matches another one of + * the application's active key bindings. + */ + private KeySequence currentSequence; + + /** + * The workbench that should be notified of changes to the key binding + * state. This is done by updating one of the contribution items on the + * status line. + */ + private final IWorkbench workbench; + + /** + * Constructs a new instance of <code>KeyBindingState</code> with an + * empty key sequence, set to reset fully. + * + * @param workbenchToNotify + * The workbench that this state should keep advised of changes + * to the key binding state; must not be <code>null</code>. + */ + KeyBindingState(IWorkbench workbenchToNotify) { + currentSequence = KeySequence.getInstance(); + workbench = workbenchToNotify; + associatedWindow = workbench.getActiveWorkbenchWindow(); + } + + /** + * An accessor for the workbench window associated with this state. This + * should never be <code>null</code>, as the setting follows the last + * workbench window to have focus. + * + * @return The workbench window to which the key binding architecture is + * currently attached; should never be <code>null</code>. + */ + IWorkbenchWindow getAssociatedWindow() { + return associatedWindow; + } + + /** + * An accessor for the current key sequence waiting for completion. + * + * @return The current incomplete key sequence; never <code>null</code>, + * but may be empty. + */ + KeySequence getCurrentSequence() { + return currentSequence; + } + + /** + * Gets the status line contribution item which the key binding + * architecture uses to keep the user up-to-date as to the current state. + * + * @return The status line contribution item, if any; <code>null</code>, + * if none. + */ + StatusLineContributionItem getStatusLine() { + if (associatedWindow instanceof WorkbenchWindow) { + WorkbenchWindow window = (WorkbenchWindow) associatedWindow; + IStatusLineManager statusLine = window.getStatusLineManager(); + // TODO implicit dependency on IDE's action builder + // @issue implicit dependency on IDE's action builder + if (statusLine != null) { // this can be null if we're exiting + IContributionItem item = statusLine + .find("ModeContributionItem"); //$NON-NLS-1$ + if (item instanceof StatusLineContributionItem) { + return ((StatusLineContributionItem) item); + } + } + } + + return null; + } + + /** + * <p> + * Resets the state based on the current properties. If the state is to + * collapse fully or if there are no key strokes, then it sets the state to + * have an empty key sequence. Otherwise, it leaves the first key stroke in + * the sequence. + * </p> + * <p> + * The workbench's status lines are updated, if appropriate. + * </p> + */ + void reset() { + currentSequence = KeySequence.getInstance(); + updateStatusLines(); + } + + /** + * A mutator for the workbench window to which this state is associated. + * + * @param window + * The workbench window to associated; should never be <code>null</code>. + */ + void setAssociatedWindow(IWorkbenchWindow window) { + associatedWindow = window; + } + + /** + * A mutator for the partial sequence entered by the user. + * + * @param sequence + * The current key sequence; should not be <code>null</code>, + * but may be empty. + */ + void setCurrentSequence(KeySequence sequence) { + currentSequence = sequence; + updateStatusLines(); + } + + /** + * Updates the text of the status line of the associated shell with the + * current sequence. + */ + private void updateStatusLines() { + StatusLineContributionItem statusLine = getStatusLine(); + if (statusLine != null) { + statusLine.setText(getCurrentSequence().format()); + } + } +} diff --git a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/WorkbenchKeyboard.java b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/WorkbenchKeyboard.java index 66a9846482..d7282ea077 100755 --- a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/WorkbenchKeyboard.java +++ b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/internal/keys/WorkbenchKeyboard.java @@ -1,295 +1,295 @@ -// RAP [rh] Keys completely disabled as not implemented in RWT -///******************************************************************************* -// * Copyright (c) 2000, 2010 IBM Corporation and others. -// * All rights reserved. This program and the accompanying materials -// * are made available under the terms of the Eclipse Public License v1.0 -// * which accompanies this distribution, and is available at -// * http://www.eclipse.org/legal/epl-v10.html -// * -// * Contributors: -// * IBM Corporation - initial API and implementation -// *******************************************************************************/ -//package org.eclipse.ui.internal.keys; -// -//import com.ibm.icu.text.MessageFormat; -//import java.util.ArrayList; -//import java.util.Collection; -//import java.util.Iterator; -//import java.util.List; -//import java.util.ResourceBundle; -//import org.eclipse.core.commands.Command; -//import org.eclipse.core.commands.NotEnabledException; -//import org.eclipse.core.commands.NotHandledException; -//import org.eclipse.core.commands.ParameterizedCommand; -//import org.eclipse.core.commands.common.CommandException; -//import org.eclipse.core.commands.common.NotDefinedException; -//import org.eclipse.core.commands.util.Tracing; -//import org.eclipse.core.runtime.IStatus; -//import org.eclipse.core.runtime.Status; -//import org.eclipse.jface.bindings.Binding; -//import org.eclipse.jface.bindings.keys.KeySequence; -//import org.eclipse.jface.bindings.keys.KeyStroke; -//import org.eclipse.jface.bindings.keys.ParseException; -//import org.eclipse.jface.bindings.keys.SWTKeySupport; -//import org.eclipse.swt.SWT; -//import org.eclipse.swt.browser.Browser; +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.internal.keys; + +import com.ibm.icu.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ResourceBundle; +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.NotEnabledException; +import org.eclipse.core.commands.NotHandledException; +import org.eclipse.core.commands.ParameterizedCommand; +import org.eclipse.core.commands.common.CommandException; +import org.eclipse.core.commands.common.NotDefinedException; +import org.eclipse.core.commands.util.Tracing; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.bindings.Binding; +import org.eclipse.jface.bindings.keys.KeySequence; +import org.eclipse.jface.bindings.keys.KeyStroke; +import org.eclipse.jface.bindings.keys.ParseException; +import org.eclipse.jface.bindings.keys.SWTKeySupport; +import org.eclipse.swt.SWT; +import org.eclipse.swt.browser.Browser; //import org.eclipse.swt.custom.StyledText; -//import org.eclipse.swt.widgets.Combo; -//import org.eclipse.swt.widgets.Control; -//import org.eclipse.swt.widgets.Display; -//import org.eclipse.swt.widgets.Event; -//import org.eclipse.swt.widgets.Listener; -//import org.eclipse.swt.widgets.Shell; -//import org.eclipse.swt.widgets.Text; -//import org.eclipse.swt.widgets.Widget; -//import org.eclipse.ui.IWindowListener; -//import org.eclipse.ui.IWorkbench; -//import org.eclipse.ui.IWorkbenchWindow; -//import org.eclipse.ui.contexts.IContextService; -//import org.eclipse.ui.handlers.IHandlerService; -//import org.eclipse.ui.internal.WorkbenchPlugin; -//import org.eclipse.ui.internal.contexts.ContextService; -//import org.eclipse.ui.internal.handlers.HandlerService; -//import org.eclipse.ui.internal.misc.Policy; -//import org.eclipse.ui.internal.misc.StatusUtil; -//import org.eclipse.ui.internal.util.Util; -//import org.eclipse.ui.keys.IBindingService; -//import org.eclipse.ui.statushandlers.StatusManager; -// -///** -// * <p> -// * Controls the keyboard input into the workbench key binding architecture. This -// * allows key events to be programmatically pushed into the key binding -// * architecture -- potentially triggering the execution of commands. It is used -// * by the <code>Workbench</code> to listen for events on the -// * <code>Display</code>. -// * </p> -// * <p> -// * This class is not designed to be thread-safe. It is assumed that all access -// * to the <code>press</code> method is done through the event loop. Accessing -// * this method outside the event loop can cause corruption of internal state. -// * </p> -// * -// * @since 3.0 -// */ -//public final class WorkbenchKeyboard { -// -// /** -// * A display filter for handling key bindings. This filter can either be -// * enabled or disabled. If disabled, the filter does not process incoming -// * events. The filter starts enabled. -// * -// * @since 3.1 -// */ -// public final class KeyDownFilter implements Listener { -// -// /** -// * Whether the filter is enabled. -// */ -// private transient boolean enabled = true; -// -// /** -// * Handles an incoming traverse or key down event. -// * -// * @param event -// * The event to process; must not be <code>null</code>. -// */ -// public final void handleEvent(final Event event) { -// if (!enabled) { -// return; -// } -// -// if (DEBUG && DEBUG_VERBOSE) { -// final StringBuffer buffer = new StringBuffer( -// "Listener.handleEvent(type = "); //$NON-NLS-1$ -// switch (event.type) { -// case SWT.KeyDown: -// buffer.append("KeyDown"); //$NON-NLS-1$ -// break; -// case SWT.Traverse: -// buffer.append("Traverse"); //$NON-NLS-1$ -// break; -// default: -// buffer.append(event.type); -// } -// buffer.append(", stateMask = 0x" //$NON-NLS-1$ -// + Integer.toHexString(event.stateMask) -// + ", keyCode = 0x" //$NON-NLS-1$ -// + Integer.toHexString(event.keyCode) + ", time = " //$NON-NLS-1$ -// + event.time + ", character = 0x" //$NON-NLS-1$ -// + Integer.toHexString(event.character) + ")"); //$NON-NLS-1$ -// Tracing.printTrace("KEYS", buffer.toString()); //$NON-NLS-1$ -// } -// -// filterKeySequenceBindings(event); -// } -// -// /** -// * Returns whether the key binding filter is enabled. -// * -// * @return Whether the key filter is enabled. -// */ -// public final boolean isEnabled() { -// return enabled; -// } -// -// /** -// * Sets whether this filter should be enabled or disabled. -// * -// * @param enabled -// * Whether key binding filter should be enabled. -// */ -// public final void setEnabled(final boolean enabled) { -// this.enabled = enabled; -// } -// } -// -// /** -// * Whether the keyboard should kick into debugging mode. This causes real -// * key bindings trapped by the key binding architecture to be reported. -// */ -// private static final boolean DEBUG = Policy.DEBUG_KEY_BINDINGS; -// -// /** -// * Whether the keyboard should report every event received by its global -// * filter. -// */ -// private static final boolean DEBUG_VERBOSE = Policy.DEBUG_KEY_BINDINGS_VERBOSE; -// -// /** -// * The time in milliseconds to wait after pressing a key before displaying -// * the key assist dialog. -// */ -// private static final int DELAY = 1000; -// -// /** The collection of keys that are to be processed out-of-order. */ -// static KeySequence outOfOrderKeys; -// -// /** -// * The translation bundle in which to look up internationalized text. -// */ -// private final static ResourceBundle RESOURCE_BUNDLE = ResourceBundle -// .getBundle(WorkbenchKeyboard.class.getName()); -// -// static { -// -// try { -// outOfOrderKeys = KeySequence.getInstance("ESC DEL"); //$NON-NLS-1$ -// } catch (ParseException e) { -// outOfOrderKeys = KeySequence.getInstance(); -// String message = "Could not parse out-of-order keys definition: 'ESC DEL'. Continuing with no out-of-order keys."; //$NON-NLS-1$ -// WorkbenchPlugin.log(message, new Status(IStatus.ERROR, -// WorkbenchPlugin.PI_WORKBENCH, 0, message, e)); -// } -// } -// -// /** -// * Generates any key strokes that are near matches to the given event. The -// * first such key stroke is always the exactly matching key stroke. -// * -// * @param event -// * The event from which the key strokes should be generated; must -// * not be <code>null</code>. -// * @return The set of nearly matching key strokes. It is never -// * <code>null</code>, but may be empty. -// */ -// public static List generatePossibleKeyStrokes(Event event) { -// final List keyStrokes = new ArrayList(3); -// -// /* -// * If this is not a keyboard event, then there are no key strokes. This -// * can happen if we are listening to focus traversal events. -// */ -// if ((event.stateMask == 0) && (event.keyCode == 0) -// && (event.character == 0)) { -// return keyStrokes; -// } -// -// // Add each unique key stroke to the list for consideration. -// final int firstAccelerator = SWTKeySupport -// .convertEventToUnmodifiedAccelerator(event); -// keyStrokes.add(SWTKeySupport -// .convertAcceleratorToKeyStroke(firstAccelerator)); -// -// // We shouldn't allow delete to undergo shift resolution. -// if (event.character == SWT.DEL) { -// return keyStrokes; -// } -// -// final int secondAccelerator = SWTKeySupport -// .convertEventToUnshiftedModifiedAccelerator(event); -// if (secondAccelerator != firstAccelerator) { -// keyStrokes.add(SWTKeySupport -// .convertAcceleratorToKeyStroke(secondAccelerator)); -// } -// -// final int thirdAccelerator = SWTKeySupport -// .convertEventToModifiedAccelerator(event); -// if ((thirdAccelerator != secondAccelerator) -// && (thirdAccelerator != firstAccelerator)) { -// keyStrokes.add(SWTKeySupport -// .convertAcceleratorToKeyStroke(thirdAccelerator)); -// } -// -// return keyStrokes; -// } -// -// /** -// * <p> -// * Determines whether the given event represents a key press that should be -// * handled as an out-of-order event. An out-of-order key press is one that -// * is passed to the focus control first. Only if the focus control fails to -// * respond will the regular key bindings get applied. -// * </p> -// * <p> -// * Care must be taken in choosing which keys are chosen as out-of-order -// * keys. This method has only been designed and test to work with the -// * unmodified "Escape" key stroke. -// * </p> -// * -// * @param keyStrokes -// * The key stroke in which to look for out-of-order keys; must -// * not be <code>null</code>. -// * @return <code>true</code> if the key is an out-of-order key; -// * <code>false</code> otherwise. -// */ -// private static boolean isOutOfOrderKey(List keyStrokes) { -// // Compare to see if one of the possible key strokes is out of order. -// final KeyStroke[] outOfOrderKeyStrokes = outOfOrderKeys.getKeyStrokes(); -// final int outOfOrderKeyStrokesLength = outOfOrderKeyStrokes.length; -// for (int i = 0; i < outOfOrderKeyStrokesLength; i++) { -// if (keyStrokes.contains(outOfOrderKeyStrokes[i])) { -// return true; -// } -// } -// return false; -// } -// -// /** -// * The binding manager to be used to resolve key bindings. This member -// * variable will be <code>null</code> if it has not yet been initialized. -// */ -// private IBindingService bindingService = null; -// -// /** -// * The <code>KeyAssistDialog</code> displayed to the user to assist them -// * in completing a multi-stroke keyboard shortcut. -// * -// * @since 3.1 -// */ -// private KeyAssistDialog keyAssistDialog = null; -// -// /** -// * The listener that runs key events past the global key bindings. -// */ -// private final KeyDownFilter keyDownFilter = new KeyDownFilter(); -// +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Widget; +import org.eclipse.ui.IWindowListener; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.contexts.IContextService; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.internal.WorkbenchPlugin; +import org.eclipse.ui.internal.contexts.ContextService; +import org.eclipse.ui.internal.handlers.HandlerService; +import org.eclipse.ui.internal.misc.Policy; +import org.eclipse.ui.internal.misc.StatusUtil; +import org.eclipse.ui.internal.util.Util; +import org.eclipse.ui.keys.IBindingService; +import org.eclipse.ui.statushandlers.StatusManager; + +/** + * <p> + * Controls the keyboard input into the workbench key binding architecture. This + * allows key events to be programmatically pushed into the key binding + * architecture -- potentially triggering the execution of commands. It is used + * by the <code>Workbench</code> to listen for events on the + * <code>Display</code>. + * </p> + * <p> + * This class is not designed to be thread-safe. It is assumed that all access + * to the <code>press</code> method is done through the event loop. Accessing + * this method outside the event loop can cause corruption of internal state. + * </p> + * + * @since 3.0 + */ +public final class WorkbenchKeyboard { + + /** + * A display filter for handling key bindings. This filter can either be + * enabled or disabled. If disabled, the filter does not process incoming + * events. The filter starts enabled. + * + * @since 3.1 + */ + public final class KeyDownFilter implements Listener { + + /** + * Whether the filter is enabled. + */ + private transient boolean enabled = true; + + /** + * Handles an incoming traverse or key down event. + * + * @param event + * The event to process; must not be <code>null</code>. + */ + public final void handleEvent(final Event event) { + if (!enabled) { + return; + } + + if (DEBUG && DEBUG_VERBOSE) { + final StringBuffer buffer = new StringBuffer( + "Listener.handleEvent(type = "); //$NON-NLS-1$ + switch (event.type) { + case SWT.KeyDown: + buffer.append("KeyDown"); //$NON-NLS-1$ + break; + case SWT.Traverse: + buffer.append("Traverse"); //$NON-NLS-1$ + break; + default: + buffer.append(event.type); + } + buffer.append(", stateMask = 0x" //$NON-NLS-1$ + + Integer.toHexString(event.stateMask) + + ", keyCode = 0x" //$NON-NLS-1$ + + Integer.toHexString(event.keyCode) + ", time = " //$NON-NLS-1$ + + event.time + ", character = 0x" //$NON-NLS-1$ + + Integer.toHexString(event.character) + ")"); //$NON-NLS-1$ + Tracing.printTrace("KEYS", buffer.toString()); //$NON-NLS-1$ + } + + filterKeySequenceBindings(event); + } + + /** + * Returns whether the key binding filter is enabled. + * + * @return Whether the key filter is enabled. + */ + public final boolean isEnabled() { + return enabled; + } + + /** + * Sets whether this filter should be enabled or disabled. + * + * @param enabled + * Whether key binding filter should be enabled. + */ + public final void setEnabled(final boolean enabled) { + this.enabled = enabled; + } + } + + /** + * Whether the keyboard should kick into debugging mode. This causes real + * key bindings trapped by the key binding architecture to be reported. + */ + private static final boolean DEBUG = Policy.DEBUG_KEY_BINDINGS; + + /** + * Whether the keyboard should report every event received by its global + * filter. + */ + private static final boolean DEBUG_VERBOSE = Policy.DEBUG_KEY_BINDINGS_VERBOSE; + + /** + * The time in milliseconds to wait after pressing a key before displaying + * the key assist dialog. + */ + private static final int DELAY = 1000; + + /** The collection of keys that are to be processed out-of-order. */ + static KeySequence outOfOrderKeys; + + /** + * The translation bundle in which to look up internationalized text. + */ + private final static ResourceBundle RESOURCE_BUNDLE = ResourceBundle + .getBundle(WorkbenchKeyboard.class.getName()); + + static { + + try { + outOfOrderKeys = KeySequence.getInstance("ESC DEL"); //$NON-NLS-1$ + } catch (ParseException e) { + outOfOrderKeys = KeySequence.getInstance(); + String message = "Could not parse out-of-order keys definition: 'ESC DEL'. Continuing with no out-of-order keys."; //$NON-NLS-1$ + WorkbenchPlugin.log(message, new Status(IStatus.ERROR, + WorkbenchPlugin.PI_WORKBENCH, 0, message, e)); + } + } + + /** + * Generates any key strokes that are near matches to the given event. The + * first such key stroke is always the exactly matching key stroke. + * + * @param event + * The event from which the key strokes should be generated; must + * not be <code>null</code>. + * @return The set of nearly matching key strokes. It is never + * <code>null</code>, but may be empty. + */ + public static List generatePossibleKeyStrokes(Event event) { + final List keyStrokes = new ArrayList(3); + + /* + * If this is not a keyboard event, then there are no key strokes. This + * can happen if we are listening to focus traversal events. + */ + if ((event.stateMask == 0) && (event.keyCode == 0) + && (event.character == 0)) { + return keyStrokes; + } + + // Add each unique key stroke to the list for consideration. + final int firstAccelerator = SWTKeySupport + .convertEventToUnmodifiedAccelerator(event); + keyStrokes.add(SWTKeySupport + .convertAcceleratorToKeyStroke(firstAccelerator)); + + // We shouldn't allow delete to undergo shift resolution. + if (event.character == SWT.DEL) { + return keyStrokes; + } + + final int secondAccelerator = SWTKeySupport + .convertEventToUnshiftedModifiedAccelerator(event); + if (secondAccelerator != firstAccelerator) { + keyStrokes.add(SWTKeySupport + .convertAcceleratorToKeyStroke(secondAccelerator)); + } + + final int thirdAccelerator = SWTKeySupport + .convertEventToModifiedAccelerator(event); + if ((thirdAccelerator != secondAccelerator) + && (thirdAccelerator != firstAccelerator)) { + keyStrokes.add(SWTKeySupport + .convertAcceleratorToKeyStroke(thirdAccelerator)); + } + + return keyStrokes; + } + + /** + * <p> + * Determines whether the given event represents a key press that should be + * handled as an out-of-order event. An out-of-order key press is one that + * is passed to the focus control first. Only if the focus control fails to + * respond will the regular key bindings get applied. + * </p> + * <p> + * Care must be taken in choosing which keys are chosen as out-of-order + * keys. This method has only been designed and test to work with the + * unmodified "Escape" key stroke. + * </p> + * + * @param keyStrokes + * The key stroke in which to look for out-of-order keys; must + * not be <code>null</code>. + * @return <code>true</code> if the key is an out-of-order key; + * <code>false</code> otherwise. + */ + private static boolean isOutOfOrderKey(List keyStrokes) { + // Compare to see if one of the possible key strokes is out of order. + final KeyStroke[] outOfOrderKeyStrokes = outOfOrderKeys.getKeyStrokes(); + final int outOfOrderKeyStrokesLength = outOfOrderKeyStrokes.length; + for (int i = 0; i < outOfOrderKeyStrokesLength; i++) { + if (keyStrokes.contains(outOfOrderKeyStrokes[i])) { + return true; + } + } + return false; + } + + /** + * The binding manager to be used to resolve key bindings. This member + * variable will be <code>null</code> if it has not yet been initialized. + */ + private IBindingService bindingService = null; + + /** + * The <code>KeyAssistDialog</code> displayed to the user to assist them + * in completing a multi-stroke keyboard shortcut. + * + * @since 3.1 + */ + private KeyAssistDialog keyAssistDialog = null; + + /** + * The listener that runs key events past the global key bindings. + */ + private final KeyDownFilter keyDownFilter = new KeyDownFilter(); + +// RAP [if] No out-of-order key processing // /** // * The single out-of-order listener used by the workbench. This listener is // * attached to one widget at a time, and is used to catch key down events // * after all processing is done. This technique is used so that some keys // * will have their native behaviour happen first. -// * +// * // * @since 3.1 // */ // private final OutOfOrderListener outOfOrderListener = new OutOfOrderListener( @@ -300,240 +300,240 @@ // * listener is attached to one</code> StyledText</code> at a time, and is // * used to catch verify events after all processing is done. This technique // * is used so that some keys will have their native behaviour happen first. -// * +// * // * @since 3.1 // */ // private final OutOfOrderVerifyListener outOfOrderVerifyListener = new OutOfOrderVerifyListener( // outOfOrderListener); -// -// /** -// * The time at which the last timer was started. This is used to judge if a -// * sufficient amount of time has elapsed. This is simply the output of -// * <code>System.currentTimeMillis()</code>. -// */ -// private long startTime = Long.MAX_VALUE; -// -// /** -// * The mode is the current state of the key binding architecture. In the -// * case of multi-stroke key bindings, this can be a partially complete key -// * binding. -// */ -// private final KeyBindingState state; -// -// /** -// * The window listener responsible for maintaining internal state as the -// * focus moves between windows on the desktop. -// */ -// private final IWindowListener windowListener = new IWindowListener() { -// -// /* -// * (non-Javadoc) -// * -// * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow) -// */ -// public void windowActivated(IWorkbenchWindow window) { -// checkActiveWindow(window); -// } -// -// /* -// * (non-Javadoc) -// * -// * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow) -// */ -// public void windowClosed(IWorkbenchWindow window) { -// // Do nothing. -// } -// -// /* -// * (non-Javadoc) -// * -// * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow) -// */ -// public void windowDeactivated(IWorkbenchWindow window) { -// // Do nothing -// } -// -// /* -// * (non-Javadoc) -// * -// * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow) -// */ -// public void windowOpened(IWorkbenchWindow window) { -// // Do nothing. -// } -// }; -// -// /** -// * The workbench on which this keyboard interface should act. -// */ -// private final IWorkbench workbench; -// -// /** -// * Constructs a new instance of <code>WorkbenchKeyboard</code> associated -// * with a particular workbench. -// * -// * @param associatedWorkbench -// * The workbench with which this keyboard interface should work; -// * must not be <code>null</code>. -// * @since 3.1 -// */ -// public WorkbenchKeyboard(IWorkbench associatedWorkbench) { -// workbench = associatedWorkbench; -// state = new KeyBindingState(associatedWorkbench); -// workbench.addWindowListener(windowListener); -// } -// -// /** -// * Verifies that the active workbench window is the same as the workbench -// * window associated with the state. This is used to verify that the state -// * is properly reset as focus changes. When they are not the same, the state -// * is reset and associated with the newly activated window. -// * -// * @param window -// * The activated window; must not be <code>null</code>. -// */ -// private void checkActiveWindow(IWorkbenchWindow window) { -// if (!window.equals(state.getAssociatedWindow())) { -// resetState(true); -// state.setAssociatedWindow(window); -// } -// } -// -// /** -// * Closes the multi-stroke key binding assistant shell, if it exists and -// * isn't already disposed. -// */ -// private void closeMultiKeyAssistShell() { -// if (keyAssistDialog != null) { -// final Shell shell = keyAssistDialog.getShell(); -// if ((shell != null) && (!shell.isDisposed()) && (shell.isVisible())) { -// keyAssistDialog.close(true); -// } -// } -// } -// -// /** -// * Performs the actual execution of the command by looking up the current -// * handler from the command manager. If there is a handler and it is -// * enabled, then it tries the actual execution. Execution failures are -// * logged. When this method completes, the key binding state is reset. -// * -// * @param binding -// * The binding that should be executed; should not be -// * <code>null</code>. -// * @param trigger -// * The triggering event; may be <code>null</code>. -// * @return <code>true</code> if there was a handler; <code>false</code> -// * otherwise. -// * @throws CommandException -// * if the handler does not complete execution for some reason. -// * It is up to the caller of this method to decide whether to -// * log the message, display a dialog, or ignore this exception -// * entirely. -// */ -// final boolean executeCommand(final Binding binding, final Event trigger) -// throws CommandException { -// final ParameterizedCommand parameterizedCommand = binding -// .getParameterizedCommand(); -// -// if (DEBUG) { -// Tracing.printTrace("KEYS", //$NON-NLS-1$ -// "WorkbenchKeyboard.executeCommand(commandId = '" //$NON-NLS-1$ -// + parameterizedCommand.getId() + "', parameters = " //$NON-NLS-1$ -// + parameterizedCommand.getParameterMap() + ')'); -// } -// -// // Reset the key binding state (close window, clear status line, etc.) -// resetState(false); -// -// // Dispatch to the handler. -// final IHandlerService handlerService = (IHandlerService) workbench -// .getService(IHandlerService.class); -// final Command command = parameterizedCommand.getCommand(); -// final boolean commandDefined = command.isDefined(); -// final boolean commandHandled = command.isHandled(); -// command.setEnabled(handlerService.getCurrentState()); -// final boolean commandEnabled = command.isEnabled(); -// -// if (DEBUG && DEBUG_VERBOSE) { -// if (!commandDefined) { -// Tracing.printTrace("KEYS", " not defined"); //$NON-NLS-1$ //$NON-NLS-2$ -// } else if (!commandHandled) { -// Tracing.printTrace("KEYS", " not handled"); //$NON-NLS-1$ //$NON-NLS-2$ -// } else if (!commandEnabled) { -// Tracing.printTrace("KEYS", " not enabled"); //$NON-NLS-1$ //$NON-NLS-2$ -// } -// } -// -// try { -// handlerService.executeCommand(parameterizedCommand, trigger); -// } catch (final NotDefinedException e) { -// // The command is not defined. Forwarded to the IExecutionListener. -// } catch (final NotEnabledException e) { -// // The command is not enabled. Forwarded to the IExecutionListener. -// } catch (final NotHandledException e) { -// // There is no handler. Forwarded to the IExecutionListener. -// } -// -// /* -// * Now that the command has executed (and had the opportunity to use the -// * remembered state of the dialog), it is safe to delete that -// * information. -// */ -// if (keyAssistDialog != null) { -// keyAssistDialog.clearRememberedState(); -// } -// -// return (commandDefined && commandHandled); -// } -// -// /** -// * <p> -// * Launches the command matching a the typed key. This filter an incoming -// * <code>SWT.KeyDown</code> or <code>SWT.Traverse</code> event at the -// * level of the display (i.e., before it reaches the widgets). It does not -// * allow processing in a dialog or if the key strokes does not contain a -// * natural key. -// * </p> -// * <p> -// * Some key strokes (defined as a property) are declared as out-of-order -// * keys. This means that they are processed by the widget <em>first</em>. -// * Only if the other widget listeners do no useful work does it try to -// * process key bindings. For example, "ESC" can cancel the current widget -// * action, if there is one, without triggering key bindings. -// * </p> -// * -// * @param event -// * The incoming event; must not be <code>null</code>. -// */ -// private void filterKeySequenceBindings(Event event) { -// /* -// * Only process key strokes containing natural keys to trigger key -// * bindings. -// */ -// if ((event.keyCode & SWT.MODIFIER_MASK) != 0) { -// return; -// } -// -// // Allow special key out-of-order processing. -// List keyStrokes = generatePossibleKeyStrokes(event); -// if (isOutOfOrderKey(keyStrokes)) { -// Widget widget = event.widget; -// if ((event.character == SWT.DEL) -// && ((event.stateMask & SWT.MODIFIER_MASK) == 0) -// && ((widget instanceof Text) || (widget instanceof Combo) -// || (widget instanceof Browser))) { -// /* -// * KLUDGE. Bug 54654. The text widget relies on no listener -// * doing any work before dispatching the native delete event. -// * This does not work, as we are restricted to listeners. -// * However, it can be said that pressing a delete key in a text -// * widget will never use key bindings. This can be shown be -// * considering how the event dispatching is expected to work in -// * a text widget. So, we should do nothing ... ever. -// */ -// return; -// + + /** + * The time at which the last timer was started. This is used to judge if a + * sufficient amount of time has elapsed. This is simply the output of + * <code>System.currentTimeMillis()</code>. + */ + private long startTime = Long.MAX_VALUE; + + /** + * The mode is the current state of the key binding architecture. In the + * case of multi-stroke key bindings, this can be a partially complete key + * binding. + */ + private final KeyBindingState state; + + /** + * The window listener responsible for maintaining internal state as the + * focus moves between windows on the desktop. + */ + private final IWindowListener windowListener = new IWindowListener() { + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow) + */ + public void windowActivated(IWorkbenchWindow window) { + checkActiveWindow(window); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow) + */ + public void windowClosed(IWorkbenchWindow window) { + // Do nothing. + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow) + */ + public void windowDeactivated(IWorkbenchWindow window) { + // Do nothing + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow) + */ + public void windowOpened(IWorkbenchWindow window) { + // Do nothing. + } + }; + + /** + * The workbench on which this keyboard interface should act. + */ + private final IWorkbench workbench; + + /** + * Constructs a new instance of <code>WorkbenchKeyboard</code> associated + * with a particular workbench. + * + * @param associatedWorkbench + * The workbench with which this keyboard interface should work; + * must not be <code>null</code>. + * @since 3.1 + */ + public WorkbenchKeyboard(IWorkbench associatedWorkbench) { + workbench = associatedWorkbench; + state = new KeyBindingState(associatedWorkbench); + workbench.addWindowListener(windowListener); + } + + /** + * Verifies that the active workbench window is the same as the workbench + * window associated with the state. This is used to verify that the state + * is properly reset as focus changes. When they are not the same, the state + * is reset and associated with the newly activated window. + * + * @param window + * The activated window; must not be <code>null</code>. + */ + private void checkActiveWindow(IWorkbenchWindow window) { + if (!window.equals(state.getAssociatedWindow())) { + resetState(true); + state.setAssociatedWindow(window); + } + } + + /** + * Closes the multi-stroke key binding assistant shell, if it exists and + * isn't already disposed. + */ + private void closeMultiKeyAssistShell() { + if (keyAssistDialog != null) { + final Shell shell = keyAssistDialog.getShell(); + if ((shell != null) && (!shell.isDisposed()) && (shell.isVisible())) { + keyAssistDialog.close(true); + } + } + } + + /** + * Performs the actual execution of the command by looking up the current + * handler from the command manager. If there is a handler and it is + * enabled, then it tries the actual execution. Execution failures are + * logged. When this method completes, the key binding state is reset. + * + * @param binding + * The binding that should be executed; should not be + * <code>null</code>. + * @param trigger + * The triggering event; may be <code>null</code>. + * @return <code>true</code> if there was a handler; <code>false</code> + * otherwise. + * @throws CommandException + * if the handler does not complete execution for some reason. + * It is up to the caller of this method to decide whether to + * log the message, display a dialog, or ignore this exception + * entirely. + */ + final boolean executeCommand(final Binding binding, final Event trigger) + throws CommandException { + final ParameterizedCommand parameterizedCommand = binding + .getParameterizedCommand(); + + if (DEBUG) { + Tracing.printTrace("KEYS", //$NON-NLS-1$ + "WorkbenchKeyboard.executeCommand(commandId = '" //$NON-NLS-1$ + + parameterizedCommand.getId() + "', parameters = " //$NON-NLS-1$ + + parameterizedCommand.getParameterMap() + ')'); + } + + // Reset the key binding state (close window, clear status line, etc.) + resetState(false); + + // Dispatch to the handler. + final IHandlerService handlerService = (IHandlerService) workbench + .getService(IHandlerService.class); + final Command command = parameterizedCommand.getCommand(); + final boolean commandDefined = command.isDefined(); + final boolean commandHandled = command.isHandled(); + command.setEnabled(handlerService.getCurrentState()); + final boolean commandEnabled = command.isEnabled(); + + if (DEBUG && DEBUG_VERBOSE) { + if (!commandDefined) { + Tracing.printTrace("KEYS", " not defined"); //$NON-NLS-1$ //$NON-NLS-2$ + } else if (!commandHandled) { + Tracing.printTrace("KEYS", " not handled"); //$NON-NLS-1$ //$NON-NLS-2$ + } else if (!commandEnabled) { + Tracing.printTrace("KEYS", " not enabled"); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + try { + handlerService.executeCommand(parameterizedCommand, trigger); + } catch (final NotDefinedException e) { + // The command is not defined. Forwarded to the IExecutionListener. + } catch (final NotEnabledException e) { + // The command is not enabled. Forwarded to the IExecutionListener. + } catch (final NotHandledException e) { + // There is no handler. Forwarded to the IExecutionListener. + } + + /* + * Now that the command has executed (and had the opportunity to use the + * remembered state of the dialog), it is safe to delete that + * information. + */ + if (keyAssistDialog != null) { + keyAssistDialog.clearRememberedState(); + } + + return (commandDefined && commandHandled); + } + + /** + * <p> + * Launches the command matching a the typed key. This filter an incoming + * <code>SWT.KeyDown</code> or <code>SWT.Traverse</code> event at the + * level of the display (i.e., before it reaches the widgets). It does not + * allow processing in a dialog or if the key strokes does not contain a + * natural key. + * </p> + * <p> + * Some key strokes (defined as a property) are declared as out-of-order + * keys. This means that they are processed by the widget <em>first</em>. + * Only if the other widget listeners do no useful work does it try to + * process key bindings. For example, "ESC" can cancel the current widget + * action, if there is one, without triggering key bindings. + * </p> + * + * @param event + * The incoming event; must not be <code>null</code>. + */ + private void filterKeySequenceBindings(Event event) { + /* + * Only process key strokes containing natural keys to trigger key + * bindings. + */ + if ((event.keyCode & SWT.MODIFIER_MASK) != 0) { + return; + } + + // Allow special key out-of-order processing. + List keyStrokes = generatePossibleKeyStrokes(event); + if (isOutOfOrderKey(keyStrokes)) { + Widget widget = event.widget; + if ((event.character == SWT.DEL) + && ((event.stateMask & SWT.MODIFIER_MASK) == 0) + && ((widget instanceof Text) || (widget instanceof Combo) + || (widget instanceof Browser))) { + /* + * KLUDGE. Bug 54654. The text widget relies on no listener + * doing any work before dispatching the native delete event. + * This does not work, as we are restricted to listeners. + * However, it can be said that pressing a delete key in a text + * widget will never use key bindings. This can be shown be + * considering how the event dispatching is expected to work in + * a text widget. So, we should do nothing ... ever. + */ + return; +// RAP [if] StyledText is missing // } else if (widget instanceof StyledText) { // // if (event.type == SWT.KeyDown) { @@ -549,372 +549,372 @@ // outOfOrderVerifyListener.setActive(event.time); // } // } -// +// RAP [if] No out-of-order key processing // } else { // if (!outOfOrderListener.isActive(event.time)) { // widget.addListener(SWT.KeyDown, outOfOrderListener); // outOfOrderListener.setActive(event.time); // } -// -// } -// -// /* -// * Otherwise, we count on a key down arriving eventually. Expecting -// * out of order handling on Ctrl+Tab, for example, is a bad idea -// * (stick to keys that are not window traversal keys). -// */ -// -// } else { -// processKeyEvent(keyStrokes, event); -// -// } -// } -// -// /** -// * An accessor for the filter that processes key down and traverse events on -// * the display. -// * -// * @return The global key down and traverse filter; never <code>null</code>. -// */ -// public KeyDownFilter getKeyDownFilter() { -// return keyDownFilter; -// } -// -// /** -// * Determines whether the key sequence is a perfect match for any command. -// * If there is a match, then the corresponding command identifier is -// * returned. -// * -// * @param keySequence -// * The key sequence to check for a match; must never be -// * <code>null</code>. -// * @return The binding for the perfectly matching command; <code>null</code> -// * if no command matches. -// */ -// private Binding getPerfectMatch(KeySequence keySequence) { -// return getBindingService().getPerfectMatch(keySequence); -// } -// -// /** -// * @return -// * -// */ -// private IBindingService getBindingService() { -// if (bindingService == null) { -// bindingService = (IBindingService) workbench -// .getService(IBindingService.class); -// } -// return bindingService; -// } -// -// final KeySequence getBuffer() { -// return state.getCurrentSequence(); -// } -// -// /** -// * Changes the key binding state to the given value. This should be an -// * incremental change, but there are no checks to guarantee this is so. It -// * also sets up a <code>Shell</code> to be displayed after one second has -// * elapsed. This shell will show the user the possible completions for what -// * they have typed. -// * -// * @param sequence -// * The new key sequence for the state; should not be -// * <code>null</code>. -// */ -// private void incrementState(KeySequence sequence) { -// // Record the starting time. -// startTime = System.currentTimeMillis(); -// final long myStartTime = startTime; -// -// // Update the state. -// state.setCurrentSequence(sequence); -// state.setAssociatedWindow(workbench.getActiveWorkbenchWindow()); -// -// // After some time, open a shell displaying the possible completions. -// final Display display = workbench.getDisplay(); -// display.timerExec(DELAY, new Runnable() { -// public void run() { -// if ((System.currentTimeMillis() > (myStartTime - DELAY)) -// && (startTime == myStartTime)) { -// openMultiKeyAssistShell(); -// } -// } -// }); -// } -// -// /** -// * Determines whether the key sequence partially matches on of the active -// * key bindings. -// * -// * @param keySequence -// * The key sequence to check for a partial match; must never be -// * <code>null</code>. -// * @return <code>true</code> if there is a partial match; -// * <code>false</code> otherwise. -// */ -// private boolean isPartialMatch(KeySequence keySequence) { -// return getBindingService().isPartialMatch(keySequence); -// } -// -// /** -// * Determines whether the key sequence perfectly matches on of the active -// * key bindings. -// * -// * @param keySequence -// * The key sequence to check for a perfect match; must never be -// * <code>null</code>. -// * @return <code>true</code> if there is a perfect match; -// * <code>false</code> otherwise. -// */ -// private boolean isPerfectMatch(KeySequence keySequence) { -// return getBindingService().isPerfectMatch(keySequence); -// } -// -// /** -// * Logs the given exception, and opens a dialog explaining the failure. -// * -// * @param e -// * The exception to log; must not be <code>null</code>. -// * @param command -// * The parameterized command for the binding to execute; may be -// * <code>null</code>. -// */ -// final void logException(final CommandException e, -// final ParameterizedCommand command) { -// Throwable nestedException = e.getCause(); -// Throwable exception = (nestedException == null) ? e : nestedException; -// -// // If we can, include the command name in the exception. -// String message = null; -// if (command != null) { -// try { -// final String name = command.getCommand().getName(); -// message = MessageFormat.format(Util.translateString( -// RESOURCE_BUNDLE, "ExecutionError.MessageCommandName"), //$NON-NLS-1$ -// new Object[] { name }); -// } catch (final NotDefinedException nde) { -// // Fall through (message == null) -// } -// } -// if (message == null) { -// message = Util.translateString(RESOURCE_BUNDLE, -// "ExecutionError.Message"); //$NON-NLS-1$ -// } -// -// String exceptionMessage = exception.getMessage(); -// if (exceptionMessage == null) { -// exceptionMessage = exception.getClass().getName(); -// } -// IStatus status = new Status(IStatus.ERROR, -// WorkbenchPlugin.PI_WORKBENCH, 0, exceptionMessage, exception); -// WorkbenchPlugin.log(message, status); -// StatusUtil.handleStatus(message, exception, StatusManager.SHOW); -// } -// -// /** -// * Opens a <code>KeyAssistDialog</code> to assist the user in completing a -// * multi-stroke key binding. This method lazily creates a -// * <code>keyAssistDialog</code> and shares it between executions. -// */ -// public final void openMultiKeyAssistShell() { -// if (keyAssistDialog == null) { -// keyAssistDialog = new KeyAssistDialog(workbench, this, state); -// } -// if (keyAssistDialog.getShell() == null) { -// keyAssistDialog.setParentShell(Util.getShellToParentOn()); -// } -// keyAssistDialog.open(); -// } -// -// /** -// * Opens the key assist dialog to offer the user the choice of a binding to -// * pick from the collection of bindings. -// * -// * @param bindings -// * a collection of Binding objects -// * @since 3.3 -// */ -// public final void openKeyAssistShell(final Collection bindings) { -// if (keyAssistDialog == null) { -// keyAssistDialog = new KeyAssistDialog(workbench, -// WorkbenchKeyboard.this, state); -// } -// if (keyAssistDialog.getShell() == null) { -// keyAssistDialog.setParentShell(Util.getShellToParentOn()); -// } -// keyAssistDialog.open(bindings); -// } -// -// /** -// * 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 <code>null</code>. -// * @param event -// * The event; may be <code>null</code>. -// * @return <code>true</code> if a command is executed; <code>false</code> -// * otherwise. -// */ -// public boolean press(List potentialKeyStrokes, Event event) { -// if (DEBUG && DEBUG_VERBOSE) { -// Tracing.printTrace("KEYS", //$NON-NLS-1$ -// "WorkbenchKeyboard.press(potentialKeyStrokes = " //$NON-NLS-1$ -// + potentialKeyStrokes + ')'); -// } -// final Widget widget = event.widget; -// -// updateShellKludge(widget); -// -// KeySequence errorSequence = null; -// Collection errorMatch = null; -// -// KeySequence sequenceBeforeKeyStroke = state.getCurrentSequence(); -// for (Iterator iterator = potentialKeyStrokes.iterator(); iterator -// .hasNext();) { -// KeySequence sequenceAfterKeyStroke = KeySequence.getInstance( -// sequenceBeforeKeyStroke, (KeyStroke) iterator.next()); -// if (isPartialMatch(sequenceAfterKeyStroke)) { -// incrementState(sequenceAfterKeyStroke); -// return true; -// -// } else if (isPerfectMatch(sequenceAfterKeyStroke)) { -// final Binding binding = getPerfectMatch(sequenceAfterKeyStroke); -// try { -// return executeCommand(binding, event) -// || !sequenceBeforeKeyStroke.isEmpty(); -// } catch (final CommandException e) { -// logException(e, binding.getParameterizedCommand()); -// return true; -// } -// -// } else if ((keyAssistDialog != null) -// && (keyAssistDialog.getShell() != null) -// && ((event.keyCode == SWT.ARROW_DOWN) -// || (event.keyCode == SWT.ARROW_UP) -// || (event.keyCode == SWT.ARROW_LEFT) -// || (event.keyCode == SWT.ARROW_RIGHT) -// || (event.keyCode == SWT.CR) -// || (event.keyCode == SWT.PAGE_UP) || (event.keyCode == SWT.PAGE_DOWN))) { -// // We don't want to swallow keyboard navigation keys. -// return false; -// -// } else { -// Collection match = getBindingService().getConflictsFor(sequenceAfterKeyStroke); -// if (match != null) { -// errorSequence = sequenceAfterKeyStroke; -// errorMatch = match; -// } -// } -// } -// -// resetState(true); -// if (sequenceBeforeKeyStroke.isEmpty() && errorSequence != null) { -// openKeyAssistShell(errorMatch); -// } -// return !sequenceBeforeKeyStroke.isEmpty(); -// } -// -// /** -// * KLUDGE. This works around a couple of specific problems in how GTK+ -// * works. The first problem is the ordering of key press events with respect -// * to shell activation events. If on the event thread a dialog is about to -// * open, and the user presses a key, the key press event will arrive before -// * the shell activation event. From the perspective of Eclipse, this means -// * that things like two "Open Type" dialogs can appear if "Ctrl+Shift+T" is -// * pressed twice rapidly. For more information, please see Bug 95792. The -// * second problem is simply a bug in GTK+, for which an incomplete -// * workaround currently exists in SWT. This makes shell activation events -// * unreliable. Please see Bug 56231 and Bug 95222 for more information. -// * -// * @param widget -// * the widget that has focus in the main window. May be -// * <code>null</code> -// */ -// void updateShellKludge(final Widget widget) { -// if (org.eclipse.jface.util.Util.isGtk()) { -// -// // Update the contexts. -// final ContextService contextService = (ContextService) workbench -// .getService(IContextService.class); -// if ((widget instanceof Control) && (!widget.isDisposed())) { -// final Shell shell = ((Control) widget).getShell(); -// contextService.updateShellKludge(shell); -// } else { -// contextService.updateShellKludge(); -// } -// -// // Update the handlers. -// Object hs = workbench.getService(IHandlerService.class); -// if (hs instanceof HandlerService) { -// final HandlerService handlerService = (HandlerService) hs; -// if ((widget instanceof Control) && (!widget.isDisposed())) { -// final Shell shell = ((Control) widget).getShell(); -// handlerService.updateShellKludge(shell); -// } else { -// handlerService.updateShellKludge(); -// } -// } -// } -// } -// -// /** -// * <p> -// * Actually performs the processing of the key event by interacting with the -// * <code>ICommandManager</code>. If work is carried out, then the event is -// * stopped here (i.e., <code>event.doit = false</code>). It does not do any -// * processing if there are no matching key strokes. -// * </p> -// * <p> -// * If the active <code>Shell</code> is not the same as the one to which the -// * state is associated, then a reset occurs. -// * </p> -// * -// * @param keyStrokes -// * The set of all possible matching key strokes; must not be -// * <code>null</code>. -// * @param event -// * The event to process; must not be <code>null</code>. -// */ -// void processKeyEvent(List keyStrokes, Event event) { -// // Dispatch the keyboard shortcut, if any. -// boolean eatKey = false; -// if (!keyStrokes.isEmpty()) { -// eatKey = press(keyStrokes, event); -// } -// -// if (eatKey) { -// switch (event.type) { -// case SWT.KeyDown: -// event.doit = false; -// break; -// case SWT.Traverse: -// event.detail = SWT.TRAVERSE_NONE; -// event.doit = true; -// break; -// default: -// } -// event.type = SWT.NONE; -// } -// } -// -// /** -// * Resets the state, and cancels any running timers. If there is a -// * <code>Shell</code> currently open, then it closes it. -// * -// * @param clearRememberedState -// * Whether the remembered state (dialog bounds) of the key assist -// * should be forgotten immediately as well. -// */ -// private final void resetState(final boolean clearRememberedState) { -// startTime = Long.MAX_VALUE; -// state.reset(); -// closeMultiKeyAssistShell(); -// if ((keyAssistDialog != null) && clearRememberedState) { -// keyAssistDialog.clearRememberedState(); -// } -// } -//} + + } + + /* + * Otherwise, we count on a key down arriving eventually. Expecting + * out of order handling on Ctrl+Tab, for example, is a bad idea + * (stick to keys that are not window traversal keys). + */ + + } else { + processKeyEvent(keyStrokes, event); + + } + } + + /** + * An accessor for the filter that processes key down and traverse events on + * the display. + * + * @return The global key down and traverse filter; never <code>null</code>. + */ + public KeyDownFilter getKeyDownFilter() { + return keyDownFilter; + } + + /** + * Determines whether the key sequence is a perfect match for any command. + * If there is a match, then the corresponding command identifier is + * returned. + * + * @param keySequence + * The key sequence to check for a match; must never be + * <code>null</code>. + * @return The binding for the perfectly matching command; <code>null</code> + * if no command matches. + */ + private Binding getPerfectMatch(KeySequence keySequence) { + return getBindingService().getPerfectMatch(keySequence); + } + + /** + * @return + * + */ + private IBindingService getBindingService() { + if (bindingService == null) { + bindingService = (IBindingService) workbench + .getService(IBindingService.class); + } + return bindingService; + } + + final KeySequence getBuffer() { + return state.getCurrentSequence(); + } + + /** + * Changes the key binding state to the given value. This should be an + * incremental change, but there are no checks to guarantee this is so. It + * also sets up a <code>Shell</code> to be displayed after one second has + * elapsed. This shell will show the user the possible completions for what + * they have typed. + * + * @param sequence + * The new key sequence for the state; should not be + * <code>null</code>. + */ + private void incrementState(KeySequence sequence) { + // Record the starting time. + startTime = System.currentTimeMillis(); + final long myStartTime = startTime; + + // Update the state. + state.setCurrentSequence(sequence); + state.setAssociatedWindow(workbench.getActiveWorkbenchWindow()); + + // After some time, open a shell displaying the possible completions. + final Display display = workbench.getDisplay(); + display.timerExec(DELAY, new Runnable() { + public void run() { + if ((System.currentTimeMillis() > (myStartTime - DELAY)) + && (startTime == myStartTime)) { + openMultiKeyAssistShell(); + } + } + }); + } + + /** + * Determines whether the key sequence partially matches on of the active + * key bindings. + * + * @param keySequence + * The key sequence to check for a partial match; must never be + * <code>null</code>. + * @return <code>true</code> if there is a partial match; + * <code>false</code> otherwise. + */ + private boolean isPartialMatch(KeySequence keySequence) { + return getBindingService().isPartialMatch(keySequence); + } + + /** + * Determines whether the key sequence perfectly matches on of the active + * key bindings. + * + * @param keySequence + * The key sequence to check for a perfect match; must never be + * <code>null</code>. + * @return <code>true</code> if there is a perfect match; + * <code>false</code> otherwise. + */ + private boolean isPerfectMatch(KeySequence keySequence) { + return getBindingService().isPerfectMatch(keySequence); + } + + /** + * Logs the given exception, and opens a dialog explaining the failure. + * + * @param e + * The exception to log; must not be <code>null</code>. + * @param command + * The parameterized command for the binding to execute; may be + * <code>null</code>. + */ + final void logException(final CommandException e, + final ParameterizedCommand command) { + Throwable nestedException = e.getCause(); + Throwable exception = (nestedException == null) ? e : nestedException; + + // If we can, include the command name in the exception. + String message = null; + if (command != null) { + try { + final String name = command.getCommand().getName(); + message = MessageFormat.format(Util.translateString( + RESOURCE_BUNDLE, "ExecutionError.MessageCommandName"), //$NON-NLS-1$ + new Object[] { name }); + } catch (final NotDefinedException nde) { + // Fall through (message == null) + } + } + if (message == null) { + message = Util.translateString(RESOURCE_BUNDLE, + "ExecutionError.Message"); //$NON-NLS-1$ + } + + String exceptionMessage = exception.getMessage(); + if (exceptionMessage == null) { + exceptionMessage = exception.getClass().getName(); + } + IStatus status = new Status(IStatus.ERROR, + WorkbenchPlugin.PI_WORKBENCH, 0, exceptionMessage, exception); + WorkbenchPlugin.log(message, status); + StatusUtil.handleStatus(message, exception, StatusManager.SHOW); + } + + /** + * Opens a <code>KeyAssistDialog</code> to assist the user in completing a + * multi-stroke key binding. This method lazily creates a + * <code>keyAssistDialog</code> and shares it between executions. + */ + public final void openMultiKeyAssistShell() { + if (keyAssistDialog == null) { + keyAssistDialog = new KeyAssistDialog(workbench, this, state); + } + if (keyAssistDialog.getShell() == null) { + keyAssistDialog.setParentShell(Util.getShellToParentOn()); + } + keyAssistDialog.open(); + } + + /** + * Opens the key assist dialog to offer the user the choice of a binding to + * pick from the collection of bindings. + * + * @param bindings + * a collection of Binding objects + * @since 3.3 + */ + public final void openKeyAssistShell(final Collection bindings) { + if (keyAssistDialog == null) { + keyAssistDialog = new KeyAssistDialog(workbench, + WorkbenchKeyboard.this, state); + } + if (keyAssistDialog.getShell() == null) { + keyAssistDialog.setParentShell(Util.getShellToParentOn()); + } + keyAssistDialog.open(bindings); + } + + /** + * 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 <code>null</code>. + * @param event + * The event; may be <code>null</code>. + * @return <code>true</code> if a command is executed; <code>false</code> + * otherwise. + */ + public boolean press(List potentialKeyStrokes, Event event) { + if (DEBUG && DEBUG_VERBOSE) { + Tracing.printTrace("KEYS", //$NON-NLS-1$ + "WorkbenchKeyboard.press(potentialKeyStrokes = " //$NON-NLS-1$ + + potentialKeyStrokes + ')'); + } + final Widget widget = event.widget; + + updateShellKludge(widget); + + KeySequence errorSequence = null; + Collection errorMatch = null; + + KeySequence sequenceBeforeKeyStroke = state.getCurrentSequence(); + for (Iterator iterator = potentialKeyStrokes.iterator(); iterator + .hasNext();) { + KeySequence sequenceAfterKeyStroke = KeySequence.getInstance( + sequenceBeforeKeyStroke, (KeyStroke) iterator.next()); + if (isPartialMatch(sequenceAfterKeyStroke)) { + incrementState(sequenceAfterKeyStroke); + return true; + + } else if (isPerfectMatch(sequenceAfterKeyStroke)) { + final Binding binding = getPerfectMatch(sequenceAfterKeyStroke); + try { + return executeCommand(binding, event) + || !sequenceBeforeKeyStroke.isEmpty(); + } catch (final CommandException e) { + logException(e, binding.getParameterizedCommand()); + return true; + } + + } else if ((keyAssistDialog != null) + && (keyAssistDialog.getShell() != null) + && ((event.keyCode == SWT.ARROW_DOWN) + || (event.keyCode == SWT.ARROW_UP) + || (event.keyCode == SWT.ARROW_LEFT) + || (event.keyCode == SWT.ARROW_RIGHT) + || (event.keyCode == SWT.CR) + || (event.keyCode == SWT.PAGE_UP) || (event.keyCode == SWT.PAGE_DOWN))) { + // We don't want to swallow keyboard navigation keys. + return false; + + } else { + Collection match = getBindingService().getConflictsFor(sequenceAfterKeyStroke); + if (match != null) { + errorSequence = sequenceAfterKeyStroke; + errorMatch = match; + } + } + } + + resetState(true); + if (sequenceBeforeKeyStroke.isEmpty() && errorSequence != null) { + openKeyAssistShell(errorMatch); + } + return !sequenceBeforeKeyStroke.isEmpty(); + } + + /** + * KLUDGE. This works around a couple of specific problems in how GTK+ + * works. The first problem is the ordering of key press events with respect + * to shell activation events. If on the event thread a dialog is about to + * open, and the user presses a key, the key press event will arrive before + * the shell activation event. From the perspective of Eclipse, this means + * that things like two "Open Type" dialogs can appear if "Ctrl+Shift+T" is + * pressed twice rapidly. For more information, please see Bug 95792. The + * second problem is simply a bug in GTK+, for which an incomplete + * workaround currently exists in SWT. This makes shell activation events + * unreliable. Please see Bug 56231 and Bug 95222 for more information. + * + * @param widget + * the widget that has focus in the main window. May be + * <code>null</code> + */ + void updateShellKludge(final Widget widget) { + if (org.eclipse.jface.util.Util.isGtk()) { + + // Update the contexts. + final ContextService contextService = (ContextService) workbench + .getService(IContextService.class); + if ((widget instanceof Control) && (!widget.isDisposed())) { + final Shell shell = ((Control) widget).getShell(); + contextService.updateShellKludge(shell); + } else { + contextService.updateShellKludge(); + } + + // Update the handlers. + Object hs = workbench.getService(IHandlerService.class); + if (hs instanceof HandlerService) { + final HandlerService handlerService = (HandlerService) hs; + if ((widget instanceof Control) && (!widget.isDisposed())) { + final Shell shell = ((Control) widget).getShell(); + handlerService.updateShellKludge(shell); + } else { + handlerService.updateShellKludge(); + } + } + } + } + + /** + * <p> + * Actually performs the processing of the key event by interacting with the + * <code>ICommandManager</code>. If work is carried out, then the event is + * stopped here (i.e., <code>event.doit = false</code>). It does not do any + * processing if there are no matching key strokes. + * </p> + * <p> + * If the active <code>Shell</code> is not the same as the one to which the + * state is associated, then a reset occurs. + * </p> + * + * @param keyStrokes + * The set of all possible matching key strokes; must not be + * <code>null</code>. + * @param event + * The event to process; must not be <code>null</code>. + */ + void processKeyEvent(List keyStrokes, Event event) { + // Dispatch the keyboard shortcut, if any. + boolean eatKey = false; + if (!keyStrokes.isEmpty()) { + eatKey = press(keyStrokes, event); + } + + if (eatKey) { + switch (event.type) { + case SWT.KeyDown: + event.doit = false; + break; + case SWT.Traverse: + event.detail = SWT.TRAVERSE_NONE; + event.doit = true; + break; + default: + } + event.type = SWT.NONE; + } + } + + /** + * Resets the state, and cancels any running timers. If there is a + * <code>Shell</code> currently open, then it closes it. + * + * @param clearRememberedState + * Whether the remembered state (dialog bounds) of the key assist + * should be forgotten immediately as well. + */ + private final void resetState(final boolean clearRememberedState) { + startTime = Long.MAX_VALUE; + state.reset(); + closeMultiKeyAssistShell(); + if ((keyAssistDialog != null) && clearRememberedState) { + keyAssistDialog.clearRememberedState(); + } + } +} diff --git a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/keys/IBindingService.java b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/keys/IBindingService.java index ff2ffd16b0..e2e78907e9 100755 --- a/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/keys/IBindingService.java +++ b/bundles/org.eclipse.rap.ui.workbench/Eclipse UI/org/eclipse/ui/keys/IBindingService.java @@ -10,16 +10,16 @@ *******************************************************************************/ package org.eclipse.ui.keys; -//import java.io.IOException; -//import java.util.Collection; -//import java.util.Map; -// -//import org.eclipse.core.commands.ParameterizedCommand; -//import org.eclipse.jface.bindings.Binding; -//import org.eclipse.jface.bindings.IBindingManagerListener; -//import org.eclipse.jface.bindings.Scheme; -//import org.eclipse.jface.bindings.TriggerSequence; -//import org.eclipse.ui.commands.ICommandService; +import java.io.IOException; +import java.util.Collection; +import java.util.Map; + +import org.eclipse.core.commands.ParameterizedCommand; +import org.eclipse.jface.bindings.Binding; +import org.eclipse.jface.bindings.IBindingManagerListener; +import org.eclipse.jface.bindings.Scheme; +import org.eclipse.jface.bindings.TriggerSequence; +import org.eclipse.ui.commands.ICommandService; import org.eclipse.ui.services.IDisposable; /** @@ -38,345 +38,345 @@ import org.eclipse.ui.services.IDisposable; * <li>This service is available globally.</li> * </ul> * </p> - * + * * @noimplement This interface is not intended to be implemented by clients. * @noextend This interface is not intended to be extended by clients. - * + * * @since 1.1 */ public interface IBindingService extends IDisposable { -// RAP [bm] disabled due to missing keybinding support -// /** -// * The default default value for the active scheme id. This value can be -// * overridden using the "plugin_customization.ini" file. The -// * <code>BindingPersistence</code> code needs to know this value so it can -// * try to decide if someone overrode the default. -// */ -// public static final String DEFAULT_DEFAULT_ACTIVE_SCHEME_ID = "org.eclipse.ui.defaultAcceleratorConfiguration"; //$NON-NLS-1$ -// -// /** -// * <p> -// * Adds a listener to this binding service. The listener will be notified -// * when the set of defined schemes or bindings changes. This can be used to -// * track the global appearance and disappearance of bindings. -// * </p> -// * <p> -// * This method completes in amortized constant time (<code>O(1)</code>). -// * </p> -// * -// * @param listener -// * The listener to attach; must not be <code>null</code>. -// * -// * @since 3.5 -// */ -// public void addBindingManagerListener(IBindingManagerListener listener); -// -// /** -// * <p> -// * Removes a listener from this binding service. -// * </p> -// * <p> -// * This method completes in amortized <code>O(1)</code>. -// * </p> -// * -// * @param listener -// * The listener to be removed; must not be <code>null</code>. -// * -// * @since 3.5 -// */ -// public void removeBindingManagerListener(IBindingManagerListener listener); -// -// /** -// * Gets the active bindings for a given parameterized command. -// * -// * @param parameterizedCommand -// * The fully-parameterized command for which the active bindings -// * should be found; must not be <code>null</code>. -// * @return The array of all active bindings for the given command. This -// * collection may be empty, but it is never <code>null</code>. -// */ -// public TriggerSequence[] getActiveBindingsFor( -// ParameterizedCommand parameterizedCommand); -// -// /** -// * Gets the active bindings for a given command identifier. It is assumed -// * that the command has no parameters. -// * -// * @param commandId -// * The id of the command for which the active bindings should be -// * found; must not be <code>null</code>. -// * @return The array of all active bindings for the given command. This -// * collection may be empty, but it is never <code>null</code>. -// */ -// public TriggerSequence[] getActiveBindingsFor(String commandId); -// -// /** -// * Returns the currently active scheme. -// * -// * @return The currently active scheme. This value may (in certain rare -// * circumstances) be <code>null</code>. -// */ -// public Scheme getActiveScheme(); -// -// /** -// * Gets the best active binding for a command. The best binding is the one -// * that would be most appropriate to show in a menu. Bindings which belong -// * to a child scheme are given preference over those in a parent scheme. -// * Bindings which belong to a particular locale or platform are given -// * preference over those that do not. The rest of the calculation is based -// * most on various concepts of "length", as well as giving some modifier -// * keys preference (e.g., <code>Alt</code> is less likely to appear than -// * <code>Ctrl</code>). -// * -// * @param command -// * The command for which the best active binding should be -// * retrieved; must not be <code>null</code>. -// * @return The trigger sequence for the best binding; may be -// * <code>null</code> if no bindings are active for the given -// * command. -// * @since 3.4 -// */ -// public TriggerSequence getBestActiveBindingFor(ParameterizedCommand command); -// -// /** -// * Gets the best active binding for a command. The best binding is the one -// * that would be most appropriate to show in a menu. Bindings which belong -// * to a child scheme are given preference over those in a parent scheme. -// * Bindings which belong to a particular locale or platform are given -// * preference over those that do not. The rest of the calculaton is based -// * most on various concepts of "length", as well as giving some modifier -// * keys preference (e.g., <code>Alt</code> is less likely to appear than -// * <code>Ctrl</code>). -// * -// * @param commandId -// * The identifier of the command for which the best active -// * binding should be retrieved; must not be <code>null</code>. -// * @return The trigger sequence for the best binding; may be -// * <code>null</code> if no bindings are active for the given -// * command. -// * @since 3.2 -// * @see #getBestActiveBindingFor(ParameterizedCommand) -// */ -// public TriggerSequence getBestActiveBindingFor(String commandId); -// -// /** -// * Gets the formatted string representing the best active binding for a -// * command. The best binding is the one that would be most appropriate to -// * show in a menu. Bindings which belong to a child scheme are given -// * preference over those in a parent scheme. The rest of the calculaton is -// * based most on various concepts of "length", as well as giving some -// * modifier keys preference (e.g., <code>Alt</code> is less likely to -// * appear than <code>Ctrl</code>). -// * -// * @param commandId -// * The identifier of the command for which the best active -// * binding should be retrieved; must not be <code>null</code>. -// * @return The formatted string for the best binding; may be -// * <code>null</code> if no bindings are active for the given -// * command. -// * @since 3.2 -// * @see #getBestActiveBindingFor(ParameterizedCommand) -// */ -// public String getBestActiveBindingFormattedFor(String commandId); -// -// /** -// * Returns the current set of bindings. -// * -// * @return The current array of bindings (<code>Binding</code>). -// */ -// public Binding[] getBindings(); -// -// /** -// * Returns the current state of the key binding buffer. This will contain -// * all of the keys currently awaiting processing. If the system is currently -// * executing a command (as a result of a key press), then this will contain -// * the trigger sequence used to execute the command. If the key binding -// * architecture has seen part of multi-key binding, then this will contain -// * the part that it has seen. Otherwise, this will return nothing. -// * -// * @return The trigger sequence indicating the current state of the key -// * binding buffer; never <code>null</code>, but may be empty if -// * there is nothing in the buffer. -// * @since 3.2 -// */ -// public TriggerSequence getBuffer(); -// -// /** -// * Returns the default scheme identifier for the currently running -// * application. -// * -// * @return The default scheme identifier (<code>String</code>); never -// * <code>null</code>, but may be empty or point to an undefined -// * scheme. -// */ -// public String getDefaultSchemeId(); -// -// /** -// * Returns the array of defined schemes in the workbench. -// * -// * @return The array of schemes (<code>Scheme</code>) that are defined; -// * it may be <code>null</code>, and it may be empty. -// */ -// public Scheme[] getDefinedSchemes(); -// -// /** -// * Returns the currently active locale. -// * -// * @return The current locale. -// */ -// public String getLocale(); -// -// /** -// * Returns all of the possible bindings that start with the given trigger -// * (but are not equal to the given trigger). -// * -// * @param trigger -// * The prefix to look for; must not be <code>null</code>. -// * @return A map of triggers (<code>TriggerSequence</code>) to bindings (<code>Binding</code>). -// * This map may be empty, but it is never <code>null</code>. -// */ -// public Map getPartialMatches(TriggerSequence trigger); -// -// /** -// * Returns the command identifier for the active binding matching this -// * trigger, if any. -// * -// * @param trigger -// * The trigger to match; may be <code>null</code>. -// * @return The binding that matches, if any; <code>null</code> otherwise. -// */ -// public Binding getPerfectMatch(TriggerSequence trigger); -// -// /** -// * Returns the currently active platform. -// * -// * @return The current platform. -// */ -// public String getPlatform(); -// -// /** -// * Retrieves the scheme with the given identifier. If no such scheme exists, -// * then an undefined scheme with the given id is created. -// * -// * @param schemeId -// * The identifier to find; must not be <code>null</code>. -// * @return A scheme with the given identifier, either defined or undefined. -// */ -// public Scheme getScheme(String schemeId); -// -// /** -// * Tests whether the global key binding architecture is currently active. -// * -// * @return <code>true</code> if the key bindings are active; -// * <code>false</code> otherwise. -// */ -// public boolean isKeyFilterEnabled(); -// -// /** -// * Returns whether the given trigger sequence is a partial match for the -// * given sequence. -// * -// * @param trigger -// * The sequence which should be the prefix for some binding; -// * should not be <code>null</code>. -// * @return <code>true</code> if the trigger can be found in the active -// * bindings; <code>false</code> otherwise. -// */ -// public boolean isPartialMatch(TriggerSequence trigger); -// -// /** -// * Returns whether the given trigger sequence is a perfect match for the -// * given sequence. -// * -// * @param trigger -// * The sequence which should match exactly; should not be -// * <code>null</code>. -// * @return <code>true</code> if the trigger can be found in the active -// * bindings; <code>false</code> otherwise. -// */ -// public boolean isPerfectMatch(TriggerSequence trigger); -// -// /** -// * Opens the key assistant dialog positioned near the key binding entry in -// * the status bar. -// */ -// public void openKeyAssistDialog(); -// -// /** -// * <p> -// * Reads the binding information from the registry and the preferences. This -// * will overwrite any of the existing information in the binding service. -// * This method is intended to be called during start-up. When this method -// * completes, this binding service will reflect the current state of the -// * registry and preference store. -// * </p> -// * -// * @param commandService -// * Ignored. -// */ -// public void readRegistryAndPreferences(ICommandService commandService); -// -// /** -// * <p> -// * Writes the given active scheme and bindings to the preference store. Only -// * the bindings that are of the <code>Binding.USER</code> type will be -// * written; the others will be ignored. This should only be used by -// * applications trying to persist user preferences. If you are trying to -// * change the active scheme as an RCP application, then you should be using -// * the <code>plugin_customization.ini</code> file. If you are trying to -// * switch between groups of bindings dynamically, you should be using -// * contexts. -// * </p> -// * <p> -// * This method also updates the active scheme and bindings in the system to -// * match those written to the preference store. -// * </p> -// * -// * @param activeScheme -// * The scheme which should be persisted; may be <code>null</code>. -// * @param bindings -// * The bindings which should be persisted; may be -// * <code>null</code>. -// * @throws IOException -// * If something goes wrong while writing to the preference -// * store. -// * @see org.eclipse.ui.IWorkbenchPreferenceConstants -// * @see org.eclipse.ui.contexts.IContextService -// */ -// public void savePreferences(Scheme activeScheme, Binding[] bindings) -// throws IOException; -// -// /** -// * <p> -// * Enables or disables the global key binding architecture. The architecture -// * should be enabled by default. -// * </p> -// * <p> -// * When enabled, keyboard shortcuts are active, and that key events can -// * trigger commands. This also means that widgets may not see all key events -// * (as they might be trapped as a keyboard shortcut). -// * </p> -// * <p> -// * When disabled, no key events will trapped as keyboard shortcuts, and that -// * no commands can be triggered by keyboard events. (Exception: it is -// * possible that someone listening for key events on a widget could trigger -// * a command.) -// * </p> -// * -// * @param enabled -// * Whether the key filter should be enabled. -// */ -// public void setKeyFilterEnabled(boolean enabled); -// -// /** -// * Provides the current conflicts in the keybindings for the given -// * TriggerSequence as a {@link Collection} of {@link Binding} -// * -// * @param sequence The sequence for which conflict info is required -// * -// * @return Collection of Bindings. If no conflicts, -// * then returns a <code>null</code> -// * @since 3.5 -// */ -// public Collection getConflictsFor(TriggerSequence sequence); + + /** + * The default default value for the active scheme id. This value can be + * overridden using the "plugin_customization.ini" file. The + * <code>BindingPersistence</code> code needs to know this value so it can + * try to decide if someone overrode the default. + */ + public static final String DEFAULT_DEFAULT_ACTIVE_SCHEME_ID = "org.eclipse.ui.defaultAcceleratorConfiguration"; //$NON-NLS-1$ + + /** + * <p> + * Adds a listener to this binding service. The listener will be notified + * when the set of defined schemes or bindings changes. This can be used to + * track the global appearance and disappearance of bindings. + * </p> + * <p> + * This method completes in amortized constant time (<code>O(1)</code>). + * </p> + * + * @param listener + * The listener to attach; must not be <code>null</code>. + * + * @since 3.5 + */ + public void addBindingManagerListener(IBindingManagerListener listener); + + /** + * <p> + * Removes a listener from this binding service. + * </p> + * <p> + * This method completes in amortized <code>O(1)</code>. + * </p> + * + * @param listener + * The listener to be removed; must not be <code>null</code>. + * + * @since 3.5 + */ + public void removeBindingManagerListener(IBindingManagerListener listener); + + /** + * Gets the active bindings for a given parameterized command. + * + * @param parameterizedCommand + * The fully-parameterized command for which the active bindings + * should be found; must not be <code>null</code>. + * @return The array of all active bindings for the given command. This + * collection may be empty, but it is never <code>null</code>. + */ + public TriggerSequence[] getActiveBindingsFor( + ParameterizedCommand parameterizedCommand); + + /** + * Gets the active bindings for a given command identifier. It is assumed + * that the command has no parameters. + * + * @param commandId + * The id of the command for which the active bindings should be + * found; must not be <code>null</code>. + * @return The array of all active bindings for the given command. This + * collection may be empty, but it is never <code>null</code>. + */ + public TriggerSequence[] getActiveBindingsFor(String commandId); + + /** + * Returns the currently active scheme. + * + * @return The currently active scheme. This value may (in certain rare + * circumstances) be <code>null</code>. + */ + public Scheme getActiveScheme(); + + /** + * Gets the best active binding for a command. The best binding is the one + * that would be most appropriate to show in a menu. Bindings which belong + * to a child scheme are given preference over those in a parent scheme. + * Bindings which belong to a particular locale or platform are given + * preference over those that do not. The rest of the calculation is based + * most on various concepts of "length", as well as giving some modifier + * keys preference (e.g., <code>Alt</code> is less likely to appear than + * <code>Ctrl</code>). + * + * @param command + * The command for which the best active binding should be + * retrieved; must not be <code>null</code>. + * @return The trigger sequence for the best binding; may be + * <code>null</code> if no bindings are active for the given + * command. + * @since 3.4 + */ + public TriggerSequence getBestActiveBindingFor(ParameterizedCommand command); + + /** + * Gets the best active binding for a command. The best binding is the one + * that would be most appropriate to show in a menu. Bindings which belong + * to a child scheme are given preference over those in a parent scheme. + * Bindings which belong to a particular locale or platform are given + * preference over those that do not. The rest of the calculaton is based + * most on various concepts of "length", as well as giving some modifier + * keys preference (e.g., <code>Alt</code> is less likely to appear than + * <code>Ctrl</code>). + * + * @param commandId + * The identifier of the command for which the best active + * binding should be retrieved; must not be <code>null</code>. + * @return The trigger sequence for the best binding; may be + * <code>null</code> if no bindings are active for the given + * command. + * @since 3.2 + * @see #getBestActiveBindingFor(ParameterizedCommand) + */ + public TriggerSequence getBestActiveBindingFor(String commandId); + + /** + * Gets the formatted string representing the best active binding for a + * command. The best binding is the one that would be most appropriate to + * show in a menu. Bindings which belong to a child scheme are given + * preference over those in a parent scheme. The rest of the calculaton is + * based most on various concepts of "length", as well as giving some + * modifier keys preference (e.g., <code>Alt</code> is less likely to + * appear than <code>Ctrl</code>). + * + * @param commandId + * The identifier of the command for which the best active + * binding should be retrieved; must not be <code>null</code>. + * @return The formatted string for the best binding; may be + * <code>null</code> if no bindings are active for the given + * command. + * @since 3.2 + * @see #getBestActiveBindingFor(ParameterizedCommand) + */ + public String getBestActiveBindingFormattedFor(String commandId); + + /** + * Returns the current set of bindings. + * + * @return The current array of bindings (<code>Binding</code>). + */ + public Binding[] getBindings(); + + /** + * Returns the current state of the key binding buffer. This will contain + * all of the keys currently awaiting processing. If the system is currently + * executing a command (as a result of a key press), then this will contain + * the trigger sequence used to execute the command. If the key binding + * architecture has seen part of multi-key binding, then this will contain + * the part that it has seen. Otherwise, this will return nothing. + * + * @return The trigger sequence indicating the current state of the key + * binding buffer; never <code>null</code>, but may be empty if + * there is nothing in the buffer. + * @since 3.2 + */ + public TriggerSequence getBuffer(); + + /** + * Returns the default scheme identifier for the currently running + * application. + * + * @return The default scheme identifier (<code>String</code>); never + * <code>null</code>, but may be empty or point to an undefined + * scheme. + */ + public String getDefaultSchemeId(); + + /** + * Returns the array of defined schemes in the workbench. + * + * @return The array of schemes (<code>Scheme</code>) that are defined; + * it may be <code>null</code>, and it may be empty. + */ + public Scheme[] getDefinedSchemes(); + + /** + * Returns the currently active locale. + * + * @return The current locale. + */ + public String getLocale(); + + /** + * Returns all of the possible bindings that start with the given trigger + * (but are not equal to the given trigger). + * + * @param trigger + * The prefix to look for; must not be <code>null</code>. + * @return A map of triggers (<code>TriggerSequence</code>) to bindings (<code>Binding</code>). + * This map may be empty, but it is never <code>null</code>. + */ + public Map getPartialMatches(TriggerSequence trigger); + + /** + * Returns the command identifier for the active binding matching this + * trigger, if any. + * + * @param trigger + * The trigger to match; may be <code>null</code>. + * @return The binding that matches, if any; <code>null</code> otherwise. + */ + public Binding getPerfectMatch(TriggerSequence trigger); + + /** + * Returns the currently active platform. + * + * @return The current platform. + */ + public String getPlatform(); + + /** + * Retrieves the scheme with the given identifier. If no such scheme exists, + * then an undefined scheme with the given id is created. + * + * @param schemeId + * The identifier to find; must not be <code>null</code>. + * @return A scheme with the given identifier, either defined or undefined. + */ + public Scheme getScheme(String schemeId); + + /** + * Tests whether the global key binding architecture is currently active. + * + * @return <code>true</code> if the key bindings are active; + * <code>false</code> otherwise. + */ + public boolean isKeyFilterEnabled(); + + /** + * Returns whether the given trigger sequence is a partial match for the + * given sequence. + * + * @param trigger + * The sequence which should be the prefix for some binding; + * should not be <code>null</code>. + * @return <code>true</code> if the trigger can be found in the active + * bindings; <code>false</code> otherwise. + */ + public boolean isPartialMatch(TriggerSequence trigger); + + /** + * Returns whether the given trigger sequence is a perfect match for the + * given sequence. + * + * @param trigger + * The sequence which should match exactly; should not be + * <code>null</code>. + * @return <code>true</code> if the trigger can be found in the active + * bindings; <code>false</code> otherwise. + */ + public boolean isPerfectMatch(TriggerSequence trigger); + + /** + * Opens the key assistant dialog positioned near the key binding entry in + * the status bar. + */ + public void openKeyAssistDialog(); + + /** + * <p> + * Reads the binding information from the registry and the preferences. This + * will overwrite any of the existing information in the binding service. + * This method is intended to be called during start-up. When this method + * completes, this binding service will reflect the current state of the + * registry and preference store. + * </p> + * + * @param commandService + * Ignored. + */ + public void readRegistryAndPreferences(ICommandService commandService); + + /** + * <p> + * Writes the given active scheme and bindings to the preference store. Only + * the bindings that are of the <code>Binding.USER</code> type will be + * written; the others will be ignored. This should only be used by + * applications trying to persist user preferences. If you are trying to + * change the active scheme as an RCP application, then you should be using + * the <code>plugin_customization.ini</code> file. If you are trying to + * switch between groups of bindings dynamically, you should be using + * contexts. + * </p> + * <p> + * This method also updates the active scheme and bindings in the system to + * match those written to the preference store. + * </p> + * + * @param activeScheme + * The scheme which should be persisted; may be <code>null</code>. + * @param bindings + * The bindings which should be persisted; may be + * <code>null</code>. + * @throws IOException + * If something goes wrong while writing to the preference + * store. + * @see org.eclipse.ui.IWorkbenchPreferenceConstants + * @see org.eclipse.ui.contexts.IContextService + */ + public void savePreferences(Scheme activeScheme, Binding[] bindings) + throws IOException; + + /** + * <p> + * Enables or disables the global key binding architecture. The architecture + * should be enabled by default. + * </p> + * <p> + * When enabled, keyboard shortcuts are active, and that key events can + * trigger commands. This also means that widgets may not see all key events + * (as they might be trapped as a keyboard shortcut). + * </p> + * <p> + * When disabled, no key events will trapped as keyboard shortcuts, and that + * no commands can be triggered by keyboard events. (Exception: it is + * possible that someone listening for key events on a widget could trigger + * a command.) + * </p> + * + * @param enabled + * Whether the key filter should be enabled. + */ + public void setKeyFilterEnabled(boolean enabled); + + /** + * Provides the current conflicts in the keybindings for the given + * TriggerSequence as a {@link Collection} of {@link Binding} + * + * @param sequence The sequence for which conflict info is required + * + * @return Collection of Bindings. If no conflicts, + * then returns a <code>null</code> + * @since 3.5 + */ + public Collection getConflictsFor(TriggerSequence sequence); } diff --git a/bundles/org.eclipse.rap.ui/plugin.xml b/bundles/org.eclipse.rap.ui/plugin.xml index 1bbf2c503e..2e554b85e8 100755 --- a/bundles/org.eclipse.rap.ui/plugin.xml +++ b/bundles/org.eclipse.rap.ui/plugin.xml @@ -27,9 +27,7 @@ <extension-point id="org.eclipse.ui.activitySupport" name="%ExtPoint.activitySupport" schema="schema/activitySupport.exsd"/> <extension-point id="org.eclipse.ui.actionSetPartAssociations" name="%ExtPoint.actionSetPartAssociations" schema="schema/actionSetPartAssociations.exsd"/> <extension-point id="org.eclipse.ui.actionSets" name="%ExtPoint.actionSets" schema="schema/actionSets.exsd"/> - <!-- RAP [bm] not used <extension-point id="org.eclipse.ui.bindings" name="%ExtPoint.bindings" schema="schema/bindings.exsd"/> - --> <extension-point id="org.eclipse.ui.commands" name="%ExtPoint.commands" schema="schema/commands.exsd"/> <extension-point id="org.eclipse.ui.commandImages" name="%ExtPoint.commandImages" schema="schema/commandImages.exsd"/> <extension-point id="org.eclipse.ui.contexts" name="%ExtPoint.contexts" schema="schema/contexts.exsd"/> @@ -119,7 +117,6 @@ </context> </extension> - <!-- RAP [bm] Bindings <extension point="org.eclipse.ui.bindings"> <key commandId="org.eclipse.ui.newWizard" @@ -300,7 +297,7 @@ commandId="org.eclipse.ui.window.activateEditor" sequence="F12" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" /> - < !- - F12 is the Dashboard on carbon - - > + <!-- F12 is the Dashboard on carbon --> <key platform="carbon" sequence="F12" @@ -393,15 +390,15 @@ commandId="org.eclipse.ui.edit.text.contentAssist.proposals" contextId="org.eclipse.ui.contexts.dialogAndWindow" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" - sequence="CTRL+SPACE"/> <!- - Command+SPACE+* is reserved on carbon, hardcode to CTRL - - > + sequence="CTRL+SPACE"/> <!-- Command+SPACE+* is reserved on carbon, hardcode to CTRL --> <key commandId="org.eclipse.ui.edit.text.contentAssist.contextInformation" contextId="org.eclipse.ui.contexts.dialogAndWindow" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" - sequence="CTRL+M2+SPACE"/> <!- - Command+SPACE+* is reserved on carbon, hardcode to CTRL - - > + sequence="CTRL+M2+SPACE"/> <!-- Command+SPACE+* is reserved on carbon, hardcode to CTRL --> - <!- - Special content assist key bindings for the Chinese language to prevent conflict with IME - - > + <!-- Special content assist key bindings for the Chinese language to prevent conflict with IME --> <key locale="zh" contextId="org.eclipse.ui.contexts.dialogAndWindow" @@ -429,7 +426,7 @@ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="M2+M3+?"/> - <!- - Content assist key binding for the Japanese language to prevent conflict with IME on GTK - - > + <!-- Content assist key binding for the Japanese language to prevent conflict with IME on GTK --> <key locale="ja" platform="gtk" @@ -462,7 +459,7 @@ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="M2+M3+?"/> - <!- - Content assist key binding for the Korean language to prevent conflict with IME on GTK - - > + <!-- Content assist key binding for the Korean language to prevent conflict with IME on GTK --> <key locale="ko" platform="gtk" @@ -495,7 +492,7 @@ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="M2+M3+?"/> - < !- - Content assist key binding for the Japanese language to prevent conflict with IME on Motif - - > + <!-- Content assist key binding for the Japanese language to prevent conflict with IME on Motif --> <key locale="ja" platform="motif" @@ -528,7 +525,7 @@ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="M2+M3+?"/> - <!- - Content assist key binding for the Korean language to prevent conflict with IME on Motif - - > + <!-- Content assist key binding for the Korean language to prevent conflict with IME on Motif --> <key locale="ko" platform="motif" @@ -560,7 +557,7 @@ commandId="org.eclipse.ui.edit.text.contentAssist.contextInformation" schemeId="org.eclipse.ui.defaultAcceleratorConfiguration" sequence="M2+M3+?"/> - +<!-- RAP [if] key sequences not supported (emacsAcceleratorConfiguration) <key commandId="org.eclipse.ui.file.close" sequence="CTRL+X K" @@ -663,17 +660,20 @@ commandId="org.eclipse.ui.window.switchToEditor" sequence="CTRL+X CTRL+B" schemeId="org.eclipse.ui.emacsAcceleratorConfiguration" /> +--> <scheme name="%keyConfiguration.default.name" description="%keyConfiguration.default.description" id="org.eclipse.ui.defaultAcceleratorConfiguration"> </scheme> +<!-- RAP [if] key sequences not supported (emacsAcceleratorConfiguration) <scheme name="%keyConfiguration.emacs.name" description="%keyConfiguration.emacs.description" parentId="org.eclipse.ui.defaultAcceleratorConfiguration" id="org.eclipse.ui.emacsAcceleratorConfiguration"> </scheme> +--> <key commandId="org.eclipse.ui.navigate.collapseAll" contextId="org.eclipse.ui.contexts.window" @@ -709,7 +709,6 @@ sequence="M2+M3+F7"> </key> </extension> - --> <extension point="org.eclipse.ui.commands"> <category |