/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Common Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors: IBM Corporation - initial API and implementation
 ******************************************************************************/

package org.eclipse.ui.internal.keys;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.TreeMap;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
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.Control;
import org.eclipse.swt.widgets.Display;
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.swt.widgets.Widget;

import org.eclipse.jface.preference.IPreferenceStore;

import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.commands.ICommand;
import org.eclipse.ui.commands.ICommandManager;
import org.eclipse.ui.commands.NotDefinedException;
import org.eclipse.ui.keys.KeySequence;
import org.eclipse.ui.keys.KeyStroke;
import org.eclipse.ui.keys.KeySupport;
import org.eclipse.ui.keys.ParseException;

import org.eclipse.ui.internal.IPreferenceConstants;
import org.eclipse.ui.internal.Workbench;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.commands.CommandManager;
import org.eclipse.ui.internal.util.StatusLineContributionItem;
import org.eclipse.ui.internal.util.Util;

/**
 * <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 class WorkbenchKeyboard {

	static {
		initializeOutOfOrderKeys();
	}

	/**
	 * The properties key for the key strokes that should be processed out of
	 * order.
	 */
	static final String OUT_OF_ORDER_KEYS = "OutOfOrderKeys"; //$NON-NLS-1$
	/** 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());

	/**
	 * 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) {
		List keyStrokes = new ArrayList();

		/*
		 * 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.
		KeyStroke keyStroke;
		keyStrokes.add(
			KeySupport.convertAcceleratorToKeyStroke(
				KeySupport.convertEventToUnmodifiedAccelerator(event)));
		keyStroke =
			KeySupport.convertAcceleratorToKeyStroke(
				KeySupport.convertEventToUnshiftedModifiedAccelerator(event));
		if (!keyStrokes.contains(keyStroke)) {
			keyStrokes.add(keyStroke);
		}
		keyStroke =
			KeySupport.convertAcceleratorToKeyStroke(
				KeySupport.convertEventToModifiedAccelerator(event));
		if (!keyStrokes.contains(keyStroke)) {
			keyStrokes.add(keyStroke);
		}
		return keyStrokes;
	}

	/**
	 * Initializes the <code>outOfOrderKeys</code> member variable using the
	 * keys defined in the properties file.
	 */
	private static void initializeOutOfOrderKeys() {
		// Get the key strokes which should be out of order.
		String keysText = WorkbenchMessages.getString(OUT_OF_ORDER_KEYS);
		outOfOrderKeys = KeySequence.getInstance();
		try {
			outOfOrderKeys = KeySequence.getInstance(keysText);
		} catch (ParseException e) {
			String message = "Could not parse out-of-order keys definition: '" + keysText + "'.  Continuing with no out-of-order keys."; //$NON-NLS-1$ //$NON-NLS-2$
			WorkbenchPlugin.log(
				message,
				new Status(IStatus.ERROR, WorkbenchPlugin.PI_WORKBENCH, 0, message, e));
		}
	}

	/**
	 * <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.
		Iterator keyStrokeItr = keyStrokes.iterator();
		while (keyStrokeItr.hasNext()) {
			if (outOfOrderKeys.getKeyStrokes().contains(keyStrokeItr.next())) {
				return true;
			}
		}

		return false;
	}

	/**
	 * The command manager to be used to resolve key bindings. This member
	 * variable should never be <code>null</code>.
	 */
	private final ICommandManager commandManager;
	/**
	 * The listener that runs key events past the global key bindings.
	 */
	final Listener keyDownFilter = new Listener() {
		public void handleEvent(Event event) {
			filterKeySequenceBindings(event);
		}
	};
	/**
	 * The listener that checks to see whether all of the modifier keys have
	 * been released.
	 */
	final Listener keyUpFilter = new Listener() {
		public void handleEvent(Event event) {
			checkModifierKeys(event);
		}
	};
	/**
	 * The <code>Shell</code> displayed to the user to assist them in
	 * completing a multi-stroke keyboard shortcut.
	 */
	private Shell multiKeyAssistShell = null;
	/**
	 * The listener that allows out-of-order key processing to hook back into
	 * the global key bindings.
	 */
	final OutOfOrderListener outOfOrderListener = new OutOfOrderListener(this);
	/**
	 * The listener that allows out-of-order key processing on <code>StyledText</code>
	 * widgets to detect useful work in a verify key listener.
	 */
	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>.
	 */
	public WorkbenchKeyboard(Workbench associatedWorkbench) {
		workbench = associatedWorkbench;
		state = new KeyBindingState(associatedWorkbench);
		commandManager = workbench.getCommandManager();

		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())) {
			state.setCollapseFully(true);
			resetState();
			state.setAssociatedWindow(window);
		}
	}

	/**
	 * Checks to see if the modifier keys are all released now. If they are all
	 * released, then the state will be allowed to collapse fully, and the
	 * state will reset itself.
	 * 
	 * @param event
	 *            The event to check for modifier keys; must not be <code>null</code>.
	 */
	private void checkModifierKeys(Event event) {
		if ((event.type == SWT.KeyUp) && (event.stateMask == event.keyCode)) {
			state.setCollapseFully(true);
			if (state.isSafeToReset()) {
				resetState();
			}
		}
	}

	/**
	 * 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 commandId
	 *            The identifier for the command that should be executed;
	 *            should not be <code>null</code>.
	 * @param event
	 *            The event triggering the execution. This is needed for
	 *            backwards compatability and might be removed in the future.
	 *            This value should not be <code>null</code>.
	 * @return <code>true</code> if there was a handler; <code>false</code>
	 *         otherwise.
	 */
	private boolean executeCommand(String commandId, Event event) {
		// Reset the key binding state (close window, clear status line, etc.)
		resetState();

		// Dispatch to the handler.
		Map actionsById = ((CommandManager) workbench.getCommandManager()).getActionsById();
		org.eclipse.ui.commands.IAction action =
			(org.eclipse.ui.commands.IAction) actionsById.get(commandId);

		if (action != null && action.isEnabled()) {
			try {
				action.execute(event);
			} catch (Exception e) {
				String message = "Action for command '" + commandId + "' failed to execute properly."; //$NON-NLS-1$ //$NON-NLS-2$
				WorkbenchPlugin.log(
					message,
					new Status(IStatus.ERROR, WorkbenchPlugin.PI_WORKBENCH, 0, message, e));
			}
		}

		return (action != null);
	}

	/**
	 * <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;

		// Don't allow dialogs to process key bindings.
		if (event.widget instanceof Control) {
			Shell shell = ((Control) event.widget).getShell();
			if (shell.getParent() != null)
				return;
		}

		// Allow special key out-of-order processing.
		List keyStrokes = generatePossibleKeyStrokes(event);
		if (isOutOfOrderKey(keyStrokes)) {
			if (event.type == SWT.KeyDown) {
				Widget widget = event.widget;
				if (widget instanceof StyledText) {
					/*
					 * KLUDGE. Some people try to do useful work in verify
					 * listeners. The way verify listeners work in SWT, we need
					 * to verify the key as well; otherwise, we can detect that
					 * useful work has been done.
					 */
					 ((StyledText) widget).addVerifyKeyListener(outOfOrderVerifyListener);
				} else {
					widget.addListener(SWT.KeyDown, outOfOrderListener);
				}
			}
			/*
			 * 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 Listener getKeyDownFilter() {
		return keyDownFilter;
	}

	/**
	 * An accessor for the filter that processes key up events on the display.
	 * 
	 * @return The global key up filter; never <code>null</code>.
	 */
	public Listener getKeyUpFilter() {
		return keyUpFilter;
	}

	/**
	 * 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 command identifier for the perfectly matching command;
	 *         <code>null</code> if no command matches.
	 */
	private String getPerfectMatch(KeySequence keySequence) {
		return commandManager.getPerfectMatch(keySequence);
	}

	/**
	 * 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();

		// Update the state.
		state.setCurrentSequence(sequence);
		state.setAssociatedWindow(workbench.getActiveWorkbenchWindow());

		// After 1s, open a shell displaying the possible completions.
		final IPreferenceStore store = WorkbenchPlugin.getDefault().getPreferenceStore();
		if (store.getBoolean(IPreferenceConstants.MULTI_KEY_ASSIST)) {
			final Display display = workbench.getDisplay();
			display
				.timerExec(
					1000 * store.getInt(IPreferenceConstants.MULTI_KEY_ASSIST_TIME),
					new Runnable() {
				public void run() {
					if (System.currentTimeMillis() > (startTime - 1000L)) {
						openMultiKeyAssistShell(display);
					}
				}
			});
		}
	}

	/**
	 * 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 commandManager.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 commandManager.isPerfectMatch(keySequence);
	}

	/**
	 * Opens a <code>Shell</code> to assist the user in completing a
	 * multi-stroke key binding. After this method completes, <code>multiKeyAssistShell</code>
	 * should point at the newly opened window.
	 * 
	 * @param display
	 *            The display on which the shell should be opened; must not be
	 *            <code>null</code>.
	 */
	private void openMultiKeyAssistShell(final Display display) {
		// Get the status line. If none, then abort.
		StatusLineContributionItem statusLine = state.getStatusLine();
		if (statusLine == null) {
			return;
		}
		Point statusLineLocation = statusLine.getDisplayLocation();
		if (statusLineLocation == null) {
			return;
		}

		// Set up the shell.
		multiKeyAssistShell = new Shell(display, SWT.NO_TRIM);
		GridLayout layout = new GridLayout();
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		multiKeyAssistShell.setLayout(layout);
		multiKeyAssistShell.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));

		// Get the list of items.
		Map partialMatches = new TreeMap(new Comparator() {
			public int compare(Object a, Object b) {
				KeySequence sequenceA = (KeySequence) a;
				KeySequence sequenceB = (KeySequence) b;
				return sequenceA.format().compareTo(sequenceB.format());
			}
		});
		partialMatches.putAll(commandManager.getPartialMatches(state.getCurrentSequence()));
		Iterator partialMatchItr = partialMatches.entrySet().iterator();
		while (partialMatchItr.hasNext()) {
			Map.Entry entry = (Map.Entry) partialMatchItr.next();
			String commandId = (String) entry.getValue();
			ICommand command = commandManager.getCommand(commandId);
			// TODO The enabled property of ICommand is broken.
			if (!command.isDefined() || !command.isActive() // ||
			// !command.isEnabled()
			) {
				partialMatchItr.remove();
			}
		}

		// Layout the partial matches.
		if (partialMatches.isEmpty()) {
			Label noMatchesLabel = new Label(multiKeyAssistShell, SWT.NULL);
			noMatchesLabel.setText(Util.translateString(RESOURCE_BUNDLE, "NoMatches.Message")); //$NON-NLS-1$
			noMatchesLabel.setLayoutData(new GridData(GridData.FILL_BOTH));
			noMatchesLabel.setBackground(multiKeyAssistShell.getBackground());
		} else {
			final Table completionsTable = new Table(multiKeyAssistShell, SWT.SINGLE);
			completionsTable.setBackground(multiKeyAssistShell.getBackground());
			
			// Initialize the rows.
			final List commands = new ArrayList(); // remember commands
			completionsTable.setLayoutData(new GridData(GridData.FILL_BOTH));
			new TableColumn(completionsTable, SWT.LEFT);
			new TableColumn(completionsTable, SWT.LEFT);
			Iterator itemsItr = partialMatches.entrySet().iterator();
			while (itemsItr.hasNext()) {
				Map.Entry entry = (Map.Entry) itemsItr.next();
				KeySequence sequence = (KeySequence) entry.getKey();
				String commandId = (String) entry.getValue();
				ICommand command = commandManager.getCommand(commandId);
				try {
					String[] text = { sequence.format(), command.getName()};
					TableItem item = new TableItem(completionsTable, SWT.NULL);
					item.setText(text);
					commands.add(command);
				} catch (NotDefinedException e) {
					// Not much to do, but this shouldn't really happen.
				}
			}

			// If you double-click on the table, it should execute the selected
			// command.
			completionsTable.addSelectionListener(new SelectionListener() {
				public void widgetDefaultSelected(SelectionEvent e) {
					int selectionIndex = completionsTable.getSelectionIndex();
					if (selectionIndex >= 0) {
						ICommand command = (ICommand) commands.get(selectionIndex);
						executeCommand(command.getId(), new Event());
					}
				}

				public void widgetSelected(SelectionEvent e) {
					// Do nothing
				}
			});
		}

		// Size the shell.
		multiKeyAssistShell.pack();
		Point assistShellSize = multiKeyAssistShell.getSize();
		if (assistShellSize.x > 300) {
			assistShellSize.x = 300;
		}
		if (assistShellSize.y > 200) {
			assistShellSize.y = 200;
		}
		multiKeyAssistShell.setSize(assistShellSize);

		// Position the shell.
		Point assistShellLocation =
			new Point(statusLineLocation.x, statusLineLocation.y - assistShellSize.y);
		Rectangle displayBounds = display.getBounds();
		final int displayRightEdge = displayBounds.x + displayBounds.width;
		if (assistShellLocation.x < displayBounds.x) {
			assistShellLocation.x = displayBounds.x;
		} else if ((assistShellLocation.x + assistShellSize.x) > displayRightEdge) {
			assistShellLocation.x = displayRightEdge - assistShellSize.x;
		}
		final int displayBottomEdge = displayBounds.y + displayBounds.height;
		if (assistShellLocation.y < displayBounds.y) {
			assistShellLocation.y = displayBounds.y;
		} else if ((assistShellLocation.y + assistShellSize.y) > displayBottomEdge) {
			assistShellLocation.y = displayBottomEdge - assistShellSize.y;
		}
		multiKeyAssistShell.setLocation(assistShellLocation);

		// If the shell loses focus, it should be closed.
		multiKeyAssistShell.addListener(SWT.Deactivate, new Listener() {
			public void handleEvent(Event event) {
				multiKeyAssistShell.close();
				multiKeyAssistShell = null;
			}
		});

		// Open the shell.
		multiKeyAssistShell.open();
	}

	/**
	 * 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 to pass to the action; 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) {
		// TODO remove event parameter once key-modified actions are removed

		KeySequence sequenceBeforeKeyStroke = state.getCurrentSequence();
		for (Iterator iterator = potentialKeyStrokes.iterator(); iterator.hasNext();) {
			KeySequence sequenceAfterKeyStroke =
				KeySequence.getInstance(sequenceBeforeKeyStroke, (KeyStroke) iterator.next());

			if (isPartialMatch(sequenceAfterKeyStroke)) {
				final IPreferenceStore store = WorkbenchPlugin.getDefault().getPreferenceStore();
				state.setCollapseFully(!store.getBoolean(IPreferenceConstants.MULTI_KEY_ROCKER));
				incrementState(sequenceAfterKeyStroke);
				return true;

			} else if (isPerfectMatch(sequenceAfterKeyStroke)) {
				String commandId = getPerfectMatch(sequenceAfterKeyStroke);
				return (executeCommand(commandId, event) || sequenceBeforeKeyStroke.isEmpty());
			}
		}

		resetState();
		return false;
	}

	/**
	 * <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.
		if ((!keyStrokes.isEmpty()) && (press(keyStrokes, event))) {
			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.
	 */
	private void resetState() {
		startTime = Long.MAX_VALUE;
		state.reset();
		if ((multiKeyAssistShell != null) && (!multiKeyAssistShell.isDisposed())) {
			multiKeyAssistShell.close();
			multiKeyAssistShell.dispose();
			multiKeyAssistShell = null;
		}
	}
}
