/*******************************************************************************
 * Copyright (c) 2000, 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 java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.text.Collator;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import org.eclipse.core.commands.Category;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.CommandManager;
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.core.commands.contexts.Context;
import org.eclipse.core.commands.contexts.ContextManager;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.bindings.Binding;
import org.eclipse.jface.bindings.BindingManager;
import org.eclipse.jface.bindings.Scheme;
import org.eclipse.jface.bindings.TriggerSequence;
import org.eclipse.jface.bindings.keys.KeyBinding;
import org.eclipse.jface.bindings.keys.KeySequence;
import org.eclipse.jface.bindings.keys.KeySequenceText;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.contexts.IContextIds;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.activities.IActivityManager;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.internal.IPreferenceConstants;
import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.internal.util.Util;
import org.eclipse.ui.keys.IBindingService;

/**
 * The preference page for defining keyboard shortcuts. While some of its
 * underpinning have been made generic to "bindings" rather than "key bindings",
 * it will still take some work to remove the link entirely.
 * 
 * @since 3.0
 */
public final class KeysPreferencePage extends PreferencePage implements
		IWorkbenchPreferencePage {

	/**
	 * A selection listener to be used on the columns in the table on the view
	 * tab. This selection listener modifies the sort order so that the
	 * appropriate column is in the first position.
	 * 
	 * @since 3.1
	 */
	private class SortOrderSelectionListener extends SelectionAdapter {

		/**
		 * The column to be put in the first position. This value should be one
		 * of the constants defined by <code>SORT_COLUMN_</code>.
		 */
		private final int columnSelected;

		/**
		 * Constructs a new instance of <code>SortOrderSelectionListener</code>.
		 * 
		 * @param columnSelected
		 *            The column to be given first priority in the sort order;
		 *            this value should be one of the constants defined as
		 *            <code>SORT_COLUMN_</code>.
		 */
		private SortOrderSelectionListener(final int columnSelected) {
			this.columnSelected = columnSelected;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
		 */
		public void widgetSelected(SelectionEvent e) {
			// Change the column titles.
			final int oldSortIndex = sortOrder[0];
			final TableColumn oldSortColumn = tableBindings
					.getColumn(oldSortIndex);
			oldSortColumn.setText(UNSORTED_COLUMN_NAMES[oldSortIndex]);
			final TableColumn newSortColumn = tableBindings
					.getColumn(columnSelected);
			newSortColumn.setText(SORTED_COLUMN_NAMES[columnSelected]);

			// Change the sort order.
			boolean columnPlaced = false;
			boolean enoughRoom = false;
			int bumpedColumn = -1;
			for (int i = 0; i < sortOrder.length; i++) {
				if (sortOrder[i] == columnSelected) {
					/*
					 * We've found the place where the column existing in the
					 * old sort order. No matter what at this point, we have
					 * completed the reshuffling.
					 */
					enoughRoom = true;
					if (bumpedColumn != -1) {
						// We have already started bumping things around, so
						// drop the last bumped column here.
						sortOrder[i] = bumpedColumn;
					} else {
						// The order has not changed.
						columnPlaced = true;
					}
					break;

				} else if (columnPlaced) {
					// We are currently bumping, so just bump another.
					int temp = sortOrder[i];
					sortOrder[i] = bumpedColumn;
					bumpedColumn = temp;

				} else {
					/*
					 * We are not currently bumping, so drop the column and
					 * start bumping.
					 */
					bumpedColumn = sortOrder[i];
					sortOrder[i] = columnSelected;
					columnPlaced = true;
				}
			}

			// Grow the sort order.
			if (!enoughRoom) {
				final int[] newSortOrder = new int[sortOrder.length + 1];
				System.arraycopy(sortOrder, 0, newSortOrder, 0,
						sortOrder.length);
				newSortOrder[sortOrder.length] = bumpedColumn;
				sortOrder = newSortOrder;
			}

			// Update the view tab.
			updateViewTab();
		}
	}

	/**
	 * 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 image associate with a binding that exists as part of the system
	 * definition.
	 */
	private static final Image IMAGE_BLANK = ImageFactory.getImage("blank"); //$NON-NLS-1$

	/**
	 * The image associated with a binding changed by the user.
	 */
	private static final Image IMAGE_CHANGE = ImageFactory.getImage("change"); //$NON-NLS-1$

	/**
	 * The data key at which the <code>Binding</code> instance for a table
	 * item is stored.
	 */
	private static final String ITEM_DATA_KEY = "org.eclipse.jface.bindings"; //$NON-NLS-1$

	/**
	 * The number of items to show in the combo boxes.
	 */
	private static final int ITEMS_TO_SHOW = 9;

	/**
	 * The resource bundle from which translations can be retrieved.
	 */
	private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
			.getBundle(KeysPreferencePage.class.getName());

	/**
	 * The total number of columns on the view tab.
	 */
	private static final int VIEW_TOTAL_COLUMNS = 4;

	/**
	 * The translated names for the columns when they are the primary sort key
	 * (e.g., ">Category<").
	 */
	private static final String[] SORTED_COLUMN_NAMES = new String[VIEW_TOTAL_COLUMNS];

	/**
	 * The index of the modify tab.
	 * 
	 * @since 3.1
	 */
	private static final int TAB_INDEX_MODIFY = 1;

	/**
	 * The translated names for the columns when they are not the primary sort
	 * key (e.g., "Category").
	 */
	private static final String[] UNSORTED_COLUMN_NAMES = new String[VIEW_TOTAL_COLUMNS];

	/**
	 * The index of the column on the view tab containing the category name.
	 */
	private static final int VIEW_CATEGORY_COLUMN_INDEX = 0;

	/**
	 * The index of the column on the view tab containing the command name.
	 */
	private static final int VIEW_COMMAND_COLUMN_INDEX = 1;

	/**
	 * The index of the column on the view tab containing the context name.
	 */
	private static final int VIEW_CONTEXT_COLUMN_INDEX = 3;

	/**
	 * The index of the column on the view tab containing the key sequence.
	 */
	private static final int VIEW_KEY_SEQUENCE_COLUMN_INDEX = 2;

	static {
		UNSORTED_COLUMN_NAMES[VIEW_CATEGORY_COLUMN_INDEX] = Util
				.translateString(RESOURCE_BUNDLE, "tableColumnCategory"); //$NON-NLS-1$
		UNSORTED_COLUMN_NAMES[VIEW_COMMAND_COLUMN_INDEX] = Util
				.translateString(RESOURCE_BUNDLE, "tableColumnCommand"); //$NON-NLS-1$
		UNSORTED_COLUMN_NAMES[VIEW_KEY_SEQUENCE_COLUMN_INDEX] = Util
				.translateString(RESOURCE_BUNDLE, "tableColumnKeySequence"); //$NON-NLS-1$
		UNSORTED_COLUMN_NAMES[VIEW_CONTEXT_COLUMN_INDEX] = Util
				.translateString(RESOURCE_BUNDLE, "tableColumnContext"); //$NON-NLS-1$

		SORTED_COLUMN_NAMES[VIEW_CATEGORY_COLUMN_INDEX] = Util.translateString(
				RESOURCE_BUNDLE, "tableColumnCategorySorted"); //$NON-NLS-1$
		SORTED_COLUMN_NAMES[VIEW_COMMAND_COLUMN_INDEX] = Util.translateString(
				RESOURCE_BUNDLE, "tableColumnCommandSorted"); //$NON-NLS-1$
		SORTED_COLUMN_NAMES[VIEW_KEY_SEQUENCE_COLUMN_INDEX] = Util
				.translateString(RESOURCE_BUNDLE,
						"tableColumnKeySequenceSorted"); //$NON-NLS-1$
		SORTED_COLUMN_NAMES[VIEW_CONTEXT_COLUMN_INDEX] = Util.translateString(
				RESOURCE_BUNDLE, "tableColumnContextSorted"); //$NON-NLS-1$
	}

	/**
	 * The workbench's activity manager. This activity manager is used to see if
	 * certain commands should be filtered from the user interface.
	 */
	private IActivityManager activityManager;

	/**
	 * The workbench's binding service. This binding service is used to access
	 * the current set of bindings, and to persist changes.
	 */
	private IBindingService bindingService;

	/**
	 * The add button located on the bottom left of the preference page. This
	 * button adds the current trigger sequence to the currently selected
	 * command.
	 */
	private Button buttonAdd;

	/**
	 * The remove button located on the bottom left of the preference page. This
	 * button removes the current trigger sequence from the current command.
	 */
	private Button buttonRemove;

	/**
	 * The restore button located on the bottom left of the preference page.
	 * This button attempts to restore the currently trigger sequence to its
	 * initial (i.e., Binding.SYSTEM) state -- undoing all user modifications.
	 */
	private Button buttonRestore;

	/**
	 * A map of all the category identifiers indexed by the names that appear in
	 * the user interface. This look-up table is built during initialization.
	 */
	private Map categoryIdsByUniqueName;

	/**
	 * A map of all the category names in the user interface indexed by their
	 * identifiers. This look-up table is built during initialization.
	 */
	private Map categoryUniqueNamesById;

	/**
	 * The combo box containing the list of all categories for commands.
	 */
	private Combo comboCategory;

	/**
	 * The combo box containing the list of commands relevent for the currently
	 * selected category.
	 */
	private Combo comboCommand;

	/**
	 * The combo box containing the list of contexts in the system.
	 */
	private Combo comboContext;

	/**
	 * The combo box containing the list of schemes in the system.
	 */
	private Combo comboScheme;

	/**
	 * A map of all the command identifiers indexed by the categories to which
	 * they belong. This look-up table is built during initialization.
	 */
	private Map commandIdsByCategoryId;

	/**
	 * The parameterized commands corresponding to the current contents of
	 * <code>comboCommand</code>. The commands in this array are in the same
	 * order as in the combo. This value can be <code>null</code> if nothing
	 * is selected in the combo.
	 */
	private ParameterizedCommand[] commands = null;

	/**
	 * The workbench's command service. This command service is used to access
	 * the list of commands.
	 */
	private ICommandService commandService;

	/**
	 * A map of all the context identifiers indexed by the names that appear in
	 * the user interface. This look-up table is built during initialization.
	 */
	private Map contextIdsByUniqueName;

	/**
	 * The workbench's context service. This context service is used to access
	 * the list of contexts.
	 */
	private IContextService contextService;

	/**
	 * A map of all the category names in the user interface indexed by their
	 * identifiers. This look-up table is built during initialization.
	 */
	private Map contextUniqueNamesById;

	/**
	 * The workbench's help system. This is used to register the page with the
	 * help system.
	 * 
	 * TODO Add a help context
	 */
	// private IWorkbenchHelpSystem helpSystem;
	/**
	 * This is the label next to the table showing the bindings matching a
	 * particular command. The label is disabled if there isn't a selected
	 * command identifier.
	 */
	private Label labelBindingsForCommand;

	/**
	 * This is the label next to the table showing the bindings matching a
	 * particular trigger sequence. The label is disabled if there isn't a
	 * current key sequence.
	 */
	private Label labelBindingsForTriggerSequence;

	/**
	 * The label next to the context combo box. This label indicates whether the
	 * context is a child of another context. If the current context is not a
	 * child, then this label is blank.
	 */
	private Label labelContextExtends;

	/**
	 * The label next to the scheme combo box. This label indicates whether the
	 * scheme is a child of another scheme. If the current scheme is not a
	 * child, then this label is blank.
	 */
	private Label labelSchemeExtends;

	/**
	 * A binding manager local to this preference page. When the page is
	 * initialized, the current bindings are read out from the binding service
	 * and placed in this manager. This manager is then updated as the user
	 * makes changes. When the user has finished, the contents of this manager
	 * are compared with the contents of the binding service. The changes are
	 * then persisted.
	 */
	private final BindingManager localChangeManager = new BindingManager(
			new ContextManager(), new CommandManager());

	/**
	 * A map of all the scheme identifiers indexed by the names that appear in
	 * the user interface. This look-up table is built during initialization.
	 */
	private Map schemeIdsByUniqueName;

	/**
	 * A map of all the scheme names in the user interface indexed by their
	 * identifiers. This look-up table is built during initialization.
	 */
	private Map schemeUniqueNamesById;

	/**
	 * The sort order to be used on the view tab to display all of the key
	 * bindings. This sort order can be changed by the user. This array is never
	 * <code>null</code>, but may be empty.
	 */
	private int[] sortOrder = { VIEW_CATEGORY_COLUMN_INDEX,
			VIEW_COMMAND_COLUMN_INDEX, VIEW_KEY_SEQUENCE_COLUMN_INDEX,
			VIEW_CONTEXT_COLUMN_INDEX };

	/**
	 * The top-most tab folder for the preference page -- containing a view and
	 * a modify tab.
	 */
	private TabFolder tabFolder;

	/**
	 * A table of the key bindings currently defined. This table appears on the
	 * view tab; it is intended to be an easy way for users to learn the key
	 * bindings in Eclipse. This value is only <code>null</code> until the
	 * controls are first created.
	 */
	private Table tableBindings;

	/**
	 * The table containing all of the bindings matching the selected command.
	 */
	private Table tableBindingsForCommand;

	/**
	 * The table containing all of the bindings matching the current trigger
	 * sequence.
	 */
	private Table tableBindingsForTriggerSequence;

	/**
	 * The text widget where keys are entered. This widget is managed by
	 * <code>textTriggerSequenceManager</code>, which provides its special
	 * behaviour.
	 */
	private Text textTriggerSequence;

	/**
	 * The manager for the text widget that traps incoming key events. This
	 * manager should be used to access the widget, rather than accessing the
	 * widget directly.
	 */
	private KeySequenceText textTriggerSequenceManager;

	
	/* (non-Javadoc)
	 * @see org.eclipse.jface.preference.PreferencePage#applyData(java.lang.Object)
	 */
	public void applyData(Object data) {
		if(data instanceof Binding) {
			editBinding((Binding) data);
		}
	}
	protected final Control createContents(final Composite parent) {
		
		PlatformUI.getWorkbench().getHelpSystem()
			.setHelp(parent, IWorkbenchHelpContextIds.KEYS_PREFERENCE_PAGE);
		
		tabFolder = new TabFolder(parent, SWT.NULL);

		// View tab
		final TabItem viewTab = new TabItem(tabFolder, SWT.NULL);
		viewTab.setText(Util.translateString(RESOURCE_BUNDLE, "viewTab.Text")); //$NON-NLS-1$
		viewTab.setControl(createViewTab(tabFolder));

		// Modify tab
		final TabItem modifyTab = new TabItem(tabFolder, SWT.NULL);
		modifyTab.setText(Util.translateString(RESOURCE_BUNDLE,
				"modifyTab.Text")); //$NON-NLS-1$
		modifyTab.setControl(createModifyTab(tabFolder));

		// Do some fancy stuff.
		applyDialogFont(tabFolder);
		final IPreferenceStore store = getPreferenceStore();
		final int selectedTab = store
				.getInt(IPreferenceConstants.KEYS_PREFERENCE_SELECTED_TAB);
		if ((tabFolder.getItemCount() > selectedTab) && (selectedTab > 0)) {
			tabFolder.setSelection(selectedTab);
		}
		
		return tabFolder;
	}

	/**
	 * Creates the tab that allows the user to change the keyboard shortcuts.
	 * 
	 * @param parent
	 *            The tab folder in which the tab should be created; must not be
	 *            <code>null</code>.
	 * @return The composite which represents the contents of the tab; never
	 *         <code>null</code>.
	 */
	private final Composite createModifyTab(final TabFolder parent) {
		final Composite composite = new Composite(parent, SWT.NULL);
		composite.setLayout(new GridLayout());
		GridData gridData = new GridData(GridData.FILL_BOTH);
		composite.setLayoutData(gridData);
		final Composite compositeKeyConfiguration = new Composite(composite,
				SWT.NULL);
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 3;
		compositeKeyConfiguration.setLayout(gridLayout);
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		compositeKeyConfiguration.setLayoutData(gridData);
		final Label labelKeyConfiguration = new Label(
				compositeKeyConfiguration, SWT.LEFT);
		labelKeyConfiguration.setText(Util.translateString(RESOURCE_BUNDLE,
				"labelScheme")); //$NON-NLS-1$
		comboScheme = new Combo(compositeKeyConfiguration, SWT.READ_ONLY);
		gridData = new GridData();
		gridData.widthHint = 200;
		comboScheme.setLayoutData(gridData);
		comboScheme.setVisibleItemCount(ITEMS_TO_SHOW);

		comboScheme.addSelectionListener(new SelectionAdapter() {
			public final void widgetSelected(final SelectionEvent e) {
				selectedComboScheme();
			}
		});

		labelSchemeExtends = new Label(compositeKeyConfiguration, SWT.LEFT);
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		labelSchemeExtends.setLayoutData(gridData);
		final Control spacer = new Composite(composite, SWT.NULL);
		gridData = new GridData();
		gridData.heightHint = 10;
		gridData.widthHint = 10;
		spacer.setLayoutData(gridData);
		final Group groupCommand = new Group(composite, SWT.SHADOW_NONE);
		gridLayout = new GridLayout();
		gridLayout.numColumns = 3;
		groupCommand.setLayout(gridLayout);
		gridData = new GridData(GridData.FILL_BOTH);
		groupCommand.setLayoutData(gridData);
		groupCommand.setText(Util.translateString(RESOURCE_BUNDLE,
				"groupCommand")); //$NON-NLS-1$	
		final Label labelCategory = new Label(groupCommand, SWT.LEFT);
		gridData = new GridData();
		labelCategory.setLayoutData(gridData);
		labelCategory.setText(Util.translateString(RESOURCE_BUNDLE,
				"labelCategory")); //$NON-NLS-1$
		comboCategory = new Combo(groupCommand, SWT.READ_ONLY);
		gridData = new GridData();
		gridData.horizontalSpan = 2;
		gridData.widthHint = 200;
		comboCategory.setLayoutData(gridData);
		comboCategory.setVisibleItemCount(ITEMS_TO_SHOW);

		comboCategory.addSelectionListener(new SelectionAdapter() {
			public final void widgetSelected(final SelectionEvent e) {
				update();
			}
		});

		final Label labelCommand = new Label(groupCommand, SWT.LEFT);
		gridData = new GridData();
		labelCommand.setLayoutData(gridData);
		labelCommand.setText(Util.translateString(RESOURCE_BUNDLE,
				"labelCommand")); //$NON-NLS-1$
		comboCommand = new Combo(groupCommand, SWT.READ_ONLY);
		gridData = new GridData();
		gridData.horizontalSpan = 2;
		gridData.widthHint = 300;
		comboCommand.setLayoutData(gridData);
		comboCommand.setVisibleItemCount(9);

		comboCommand.addSelectionListener(new SelectionAdapter() {
			public final void widgetSelected(final SelectionEvent e) {
				update();
			}
		});

		labelBindingsForCommand = new Label(groupCommand, SWT.LEFT);
		gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
		gridData.verticalAlignment = GridData.FILL_VERTICAL;
		labelBindingsForCommand.setLayoutData(gridData);
		labelBindingsForCommand.setText(Util.translateString(RESOURCE_BUNDLE,
				"labelAssignmentsForCommand")); //$NON-NLS-1$
		tableBindingsForCommand = new Table(groupCommand, SWT.BORDER
				| SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL);
		tableBindingsForCommand.setHeaderVisible(true);
		gridData = new GridData(GridData.FILL_BOTH);
		gridData.heightHint = 60;
		gridData.horizontalSpan = 2;
		gridData.widthHint = "carbon".equals(SWT.getPlatform()) ? 620 : 520; //$NON-NLS-1$
		tableBindingsForCommand.setLayoutData(gridData);
		TableColumn tableColumnDelta = new TableColumn(tableBindingsForCommand,
				SWT.NULL, 0);
		tableColumnDelta.setResizable(false);
		tableColumnDelta.setText(Util.ZERO_LENGTH_STRING);
		tableColumnDelta.setWidth(20);
		TableColumn tableColumnContext = new TableColumn(
				tableBindingsForCommand, SWT.NULL, 1);
		tableColumnContext.setResizable(true);
		tableColumnContext.setText(Util.translateString(RESOURCE_BUNDLE,
				"tableColumnContext")); //$NON-NLS-1$
		tableColumnContext.pack();
		tableColumnContext.setWidth(200);
		final TableColumn tableColumnKeySequence = new TableColumn(
				tableBindingsForCommand, SWT.NULL, 2);
		tableColumnKeySequence.setResizable(true);
		tableColumnKeySequence.setText(Util.translateString(RESOURCE_BUNDLE,
				"tableColumnKeySequence")); //$NON-NLS-1$
		tableColumnKeySequence.pack();
		tableColumnKeySequence.setWidth(300);

		tableBindingsForCommand.addMouseListener(new MouseAdapter() {

			public void mouseDoubleClick(MouseEvent mouseEvent) {
				update();
			}
		});

		tableBindingsForCommand.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(SelectionEvent selectionEvent) {
				selectedTableBindingsForCommand();
			}
		});

		final Group groupKeySequence = new Group(composite, SWT.SHADOW_NONE);
		gridLayout = new GridLayout();
		gridLayout.numColumns = 4;
		groupKeySequence.setLayout(gridLayout);
		gridData = new GridData(GridData.FILL_BOTH);
		groupKeySequence.setLayoutData(gridData);
		groupKeySequence.setText(Util.translateString(RESOURCE_BUNDLE,
				"groupKeySequence")); //$NON-NLS-1$	
		final Label labelKeySequence = new Label(groupKeySequence, SWT.LEFT);
		gridData = new GridData();
		labelKeySequence.setLayoutData(gridData);
		labelKeySequence.setText(Util.translateString(RESOURCE_BUNDLE,
				"labelKeySequence")); //$NON-NLS-1$

		// The text widget into which the key strokes will be entered.
		textTriggerSequence = new Text(groupKeySequence, SWT.BORDER);
		// On MacOS X, this font will be changed by KeySequenceText
		textTriggerSequence.setFont(groupKeySequence.getFont());
		gridData = new GridData();
		gridData.horizontalSpan = 2;
		gridData.widthHint = 300;
		textTriggerSequence.setLayoutData(gridData);
		textTriggerSequence.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				update();
			}
		});
		textTriggerSequence.addFocusListener(new FocusListener() {
			public void focusGained(FocusEvent e) {
				bindingService.setKeyFilterEnabled(false);
			}

			public void focusLost(FocusEvent e) {
				bindingService.setKeyFilterEnabled(true);
			}
		});
		textTriggerSequence.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				if (!bindingService.isKeyFilterEnabled()) {
					bindingService.setKeyFilterEnabled(true);
				}
			}
		});

		// The manager for the key sequence text widget.
		textTriggerSequenceManager = new KeySequenceText(textTriggerSequence);
		textTriggerSequenceManager.setKeyStrokeLimit(4);

		// Button for adding trapped key strokes
		final Button buttonAddKey = new Button(groupKeySequence, SWT.LEFT
				| SWT.ARROW);
		buttonAddKey.setToolTipText(Util.translateString(RESOURCE_BUNDLE,
				"buttonAddKey.ToolTipText")); //$NON-NLS-1$
		gridData = new GridData();
		gridData.heightHint = comboCategory.getTextHeight();
		buttonAddKey.setLayoutData(gridData);

		// Arrow buttons aren't normally added to the tab list. Let's fix that.
		final Control[] tabStops = groupKeySequence.getTabList();
		final ArrayList newTabStops = new ArrayList();
		for (int i = 0; i < tabStops.length; i++) {
			Control tabStop = tabStops[i];
			newTabStops.add(tabStop);
			if (textTriggerSequence.equals(tabStop)) {
				newTabStops.add(buttonAddKey);
			}
		}
		final Control[] newTabStopArray = (Control[]) newTabStops
				.toArray(new Control[newTabStops.size()]);
		groupKeySequence.setTabList(newTabStopArray);

		// Construct the menu to attach to the above button.
		final Menu menuButtonAddKey = new Menu(buttonAddKey);
		final Iterator trappedKeyItr = KeySequenceText.TRAPPED_KEYS.iterator();
		while (trappedKeyItr.hasNext()) {
			final KeyStroke trappedKey = (KeyStroke) trappedKeyItr.next();
			final MenuItem menuItem = new MenuItem(menuButtonAddKey, SWT.PUSH);
			menuItem.setText(trappedKey.format());
			menuItem.addSelectionListener(new SelectionAdapter() {

				public void widgetSelected(SelectionEvent e) {
					textTriggerSequenceManager.insert(trappedKey);
					textTriggerSequence.setFocus();
					textTriggerSequence.setSelection(textTriggerSequence
							.getTextLimit());
				}
			});
		}
		buttonAddKey.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(SelectionEvent selectionEvent) {
				Point buttonLocation = buttonAddKey.getLocation();
				buttonLocation = groupKeySequence.toDisplay(buttonLocation.x,
						buttonLocation.y);
				Point buttonSize = buttonAddKey.getSize();
				menuButtonAddKey.setLocation(buttonLocation.x, buttonLocation.y
						+ buttonSize.y);
				menuButtonAddKey.setVisible(true);
			}
		});

		labelBindingsForTriggerSequence = new Label(groupKeySequence, SWT.LEFT);
		gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
		gridData.verticalAlignment = GridData.FILL_VERTICAL;
		labelBindingsForTriggerSequence.setLayoutData(gridData);
		labelBindingsForTriggerSequence.setText(Util.translateString(
				RESOURCE_BUNDLE, "labelAssignmentsForKeySequence")); //$NON-NLS-1$
		tableBindingsForTriggerSequence = new Table(groupKeySequence,
				SWT.BORDER | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL);
		tableBindingsForTriggerSequence.setHeaderVisible(true);
		gridData = new GridData(GridData.FILL_BOTH);
		gridData.heightHint = 60;
		gridData.horizontalSpan = 3;
		gridData.widthHint = "carbon".equals(SWT.getPlatform()) ? 620 : 520; //$NON-NLS-1$
		tableBindingsForTriggerSequence.setLayoutData(gridData);
		tableColumnDelta = new TableColumn(tableBindingsForTriggerSequence,
				SWT.NULL, 0);
		tableColumnDelta.setResizable(false);
		tableColumnDelta.setText(Util.ZERO_LENGTH_STRING);
		tableColumnDelta.setWidth(20);
		tableColumnContext = new TableColumn(tableBindingsForTriggerSequence,
				SWT.NULL, 1);
		tableColumnContext.setResizable(true);
		tableColumnContext.setText(Util.translateString(RESOURCE_BUNDLE,
				"tableColumnContext")); //$NON-NLS-1$
		tableColumnContext.pack();
		tableColumnContext.setWidth(200);
		final TableColumn tableColumnCommand = new TableColumn(
				tableBindingsForTriggerSequence, SWT.NULL, 2);
		tableColumnCommand.setResizable(true);
		tableColumnCommand.setText(Util.translateString(RESOURCE_BUNDLE,
				"tableColumnCommand")); //$NON-NLS-1$
		tableColumnCommand.pack();
		tableColumnCommand.setWidth(300);

		tableBindingsForTriggerSequence.addMouseListener(new MouseAdapter() {

			public void mouseDoubleClick(MouseEvent mouseEvent) {
				update();
			}
		});

		tableBindingsForTriggerSequence
				.addSelectionListener(new SelectionAdapter() {

					public void widgetSelected(SelectionEvent selectionEvent) {
						selectedTableBindingsForTriggerSequence();
					}
				});

		final Composite compositeContext = new Composite(composite, SWT.NULL);
		gridLayout = new GridLayout();
		gridLayout.numColumns = 3;
		compositeContext.setLayout(gridLayout);
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		compositeContext.setLayoutData(gridData);
		final Label labelContext = new Label(compositeContext, SWT.LEFT);
		labelContext.setText(Util.translateString(RESOURCE_BUNDLE,
				"labelContext")); //$NON-NLS-1$
		comboContext = new Combo(compositeContext, SWT.READ_ONLY);
		gridData = new GridData();
		gridData.widthHint = 250;
		comboContext.setLayoutData(gridData);
		comboContext.setVisibleItemCount(ITEMS_TO_SHOW);

		comboContext.addSelectionListener(new SelectionAdapter() {
			public final void widgetSelected(final SelectionEvent e) {
				update();
			}
		});

		labelContextExtends = new Label(compositeContext, SWT.LEFT);
		gridData = new GridData(GridData.FILL_HORIZONTAL);
		labelContextExtends.setLayoutData(gridData);
		final Composite compositeButton = new Composite(composite, SWT.NULL);
		gridLayout = new GridLayout();
		gridLayout.marginHeight = 20;
		gridLayout.marginWidth = 0;
		gridLayout.numColumns = 3;
		compositeButton.setLayout(gridLayout);
		gridData = new GridData();
		compositeButton.setLayoutData(gridData);
		buttonAdd = new Button(compositeButton, SWT.CENTER | SWT.PUSH);
		gridData = new GridData();
		int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
		buttonAdd.setText(Util.translateString(RESOURCE_BUNDLE, "buttonAdd")); //$NON-NLS-1$
		gridData.widthHint = Math.max(widthHint, buttonAdd.computeSize(
				SWT.DEFAULT, SWT.DEFAULT, true).x) + 5;
		buttonAdd.setLayoutData(gridData);

		buttonAdd.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(SelectionEvent selectionEvent) {
				selectedButtonAdd();
			}
		});

		buttonRemove = new Button(compositeButton, SWT.CENTER | SWT.PUSH);
		gridData = new GridData();
		widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
		buttonRemove.setText(Util.translateString(RESOURCE_BUNDLE,
				"buttonRemove")); //$NON-NLS-1$
		gridData.widthHint = Math.max(widthHint, buttonRemove.computeSize(
				SWT.DEFAULT, SWT.DEFAULT, true).x) + 5;
		buttonRemove.setLayoutData(gridData);

		buttonRemove.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(SelectionEvent selectionEvent) {
				selectedButtonRemove();
			}
		});

		buttonRestore = new Button(compositeButton, SWT.CENTER | SWT.PUSH);
		gridData = new GridData();
		widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
		buttonRestore.setText(Util.translateString(RESOURCE_BUNDLE,
				"buttonRestore")); //$NON-NLS-1$
		gridData.widthHint = Math.max(widthHint, buttonRestore.computeSize(
				SWT.DEFAULT, SWT.DEFAULT, true).x) + 5;
		buttonRestore.setLayoutData(gridData);

		buttonRestore.addSelectionListener(new SelectionAdapter() {

			public void widgetSelected(SelectionEvent selectionEvent) {
				selectedButtonRestore();
			}
		});

		return composite;
	}

	/**
	 * Creates a tab on the main page for displaying an uneditable list of the
	 * current key bindings. This is intended as a discovery tool for new users.
	 * It shows all of the key bindings for the current key configuration,
	 * platform and locale.
	 * 
	 * @param parent
	 *            The tab folder in which the tab should be created; must not be
	 *            <code>null</code>.
	 * @return The newly created composite containing all of the controls; never
	 *         <code>null</code>.
	 * @since 3.1
	 */
	private final Composite createViewTab(final TabFolder parent) {
		GridData gridData = null;
		int widthHint;

		// Create the composite for the tab.
		final Composite composite = new Composite(parent, SWT.NONE);
		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
		composite.setLayout(new GridLayout());

		// Place a table inside the tab.
		tableBindings = new Table(composite, SWT.BORDER | SWT.FULL_SELECTION
				| SWT.H_SCROLL | SWT.V_SCROLL);
		tableBindings.setHeaderVisible(true);
		gridData = new GridData(GridData.FILL_BOTH);
		gridData.heightHint = 400;
		gridData.horizontalSpan = 2;
		tableBindings.setLayoutData(gridData);
		final TableColumn tableColumnCategory = new TableColumn(tableBindings,
				SWT.NONE, VIEW_CATEGORY_COLUMN_INDEX);
		tableColumnCategory
				.setText(SORTED_COLUMN_NAMES[VIEW_CATEGORY_COLUMN_INDEX]);
		tableColumnCategory
				.addSelectionListener(new SortOrderSelectionListener(
						VIEW_CATEGORY_COLUMN_INDEX));
		final TableColumn tableColumnCommand = new TableColumn(tableBindings,
				SWT.NONE, VIEW_COMMAND_COLUMN_INDEX);
		tableColumnCommand
				.setText(UNSORTED_COLUMN_NAMES[VIEW_COMMAND_COLUMN_INDEX]);
		tableColumnCommand.addSelectionListener(new SortOrderSelectionListener(
				VIEW_COMMAND_COLUMN_INDEX));
		final TableColumn tableColumnKeySequence = new TableColumn(
				tableBindings, SWT.NONE, VIEW_KEY_SEQUENCE_COLUMN_INDEX);
		tableColumnKeySequence
				.setText(UNSORTED_COLUMN_NAMES[VIEW_KEY_SEQUENCE_COLUMN_INDEX]);
		tableColumnKeySequence
				.addSelectionListener(new SortOrderSelectionListener(
						VIEW_KEY_SEQUENCE_COLUMN_INDEX));
		final TableColumn tableColumnContext = new TableColumn(tableBindings,
				SWT.NONE, VIEW_CONTEXT_COLUMN_INDEX);
		tableColumnContext
				.setText(UNSORTED_COLUMN_NAMES[VIEW_CONTEXT_COLUMN_INDEX]);
		tableColumnContext.addSelectionListener(new SortOrderSelectionListener(
				VIEW_CONTEXT_COLUMN_INDEX));
		tableBindings.addSelectionListener(new SelectionAdapter() {
			public final void widgetDefaultSelected(final SelectionEvent e) {
				selectedTableKeyBindings();
			}
		});

		// A composite for the buttons.
		final Composite buttonBar = new Composite(composite, SWT.NONE);
		buttonBar.setLayout(new GridLayout(2, false));
		gridData = new GridData();
		gridData.horizontalAlignment = GridData.END;
		buttonBar.setLayoutData(gridData);

		// A button for editing the current selection.
		final Button editButton = new Button(buttonBar, SWT.PUSH);
		gridData = new GridData();
		widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
		gridData.widthHint = Math.max(widthHint, editButton.computeSize(
				SWT.DEFAULT, SWT.DEFAULT, true).x) + 5;
		editButton.setLayoutData(gridData);
		editButton.setText(Util.translateString(RESOURCE_BUNDLE, "buttonEdit")); //$NON-NLS-1$
		editButton.addSelectionListener(new SelectionListener() {

			/*
			 * (non-Javadoc)
			 * 
			 * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
			 */
			public final void widgetDefaultSelected(final SelectionEvent event) {
				selectedTableKeyBindings();
			}

			/*
			 * (non-Javadoc)
			 * 
			 * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
			 */
			public void widgetSelected(SelectionEvent e) {
				widgetDefaultSelected(e);
			}
		});

		// A button for exporting the contents to a file.
		final Button buttonExport = new Button(buttonBar, SWT.PUSH);
		gridData = new GridData();
		widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
		gridData.widthHint = Math.max(widthHint, buttonExport.computeSize(
				SWT.DEFAULT, SWT.DEFAULT, true).x) + 5;
		buttonExport.setLayoutData(gridData);
		buttonExport.setText(Util.translateString(RESOURCE_BUNDLE,
				"buttonExport")); //$NON-NLS-1$
		buttonExport.addSelectionListener(new SelectionListener() {

			/*
			 * (non-Javadoc)
			 * 
			 * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
			 */
			public final void widgetDefaultSelected(final SelectionEvent event) {
				selectedButtonExport();
			}

			/*
			 * (non-Javadoc)
			 * 
			 * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
			 */
			public void widgetSelected(SelectionEvent e) {
				widgetDefaultSelected(e);
			}
		});

		return composite;
	}

	protected IPreferenceStore doGetPreferenceStore() {
		return PrefUtil.getInternalPreferenceStore();
	}

	/**
	 * Allows the user to change the key bindings for a particular command.
	 * Switches the tab to the modify tab, and then selects the category and
	 * command that corresponds with the given command name. It then selects the
	 * given key sequence and gives focus to the key sequence text widget.
	 * 
	 * @param binding
	 *            The binding to be edited; if <code>null</code>, then just
	 *            switch to the modify tab. If the <code>binding</code> does
	 *            not correspond to anything in the keys preference page, then
	 *            this also just switches to the modify tab.
	 * @since 3.1
	 */
	public final void editBinding(final Binding binding) {
		// Switch to the modify tab.
		tabFolder.setSelection(TAB_INDEX_MODIFY);

		// If there is no command name, stop here.
		if (binding == null) {
			return;
		}

		/*
		 * Get the corresponding category and command names. If either is
		 * undefined, then we can just stop now. We won't be able to find their
		 * name.
		 */
		final ParameterizedCommand command = binding.getParameterizedCommand();
		String categoryName = null;
		String commandName = null;
		try {
			categoryName = command.getCommand().getCategory().getName();
			commandName = command.getName();
		} catch (final NotDefinedException e) {
			return; // no name
		}

		// Update the category combo box.
		final String[] categoryNames = comboCategory.getItems();
		int i = 0;
		for (; i < categoryNames.length; i++) {
			if (categoryName.equals(categoryNames[i])) {
				break;
			}
		}
		if (i >= comboCategory.getItemCount()) {
			// Couldn't find the category, so abort.
			return;
		}
		comboCategory.select(i);

		// Update the commands combo box.
		updateComboCommand();

		// Update the command combo box.
		final String[] commandNames = comboCommand.getItems();
		int j = 0;
		for (; j < commandNames.length; j++) {
			if (commandName.equals(commandNames[j])) {
				if (comboCommand.getSelectionIndex() != j) {
					comboCommand.select(j);
				}
				break;
			}
		}
		if (j >= comboCommand.getItemCount()) {
			// Couldn't find the command, so just select the first and then stop
			if (comboCommand.getSelectionIndex() != 0) {
				comboCommand.select(0);
			}
			update();
			return;
		}

		/*
		 * Update and validate the state of the modify tab in response to these
		 * selection changes.
		 */
		update();

		// Select the right key binding, if possible.
		final TableItem[] items = tableBindingsForCommand.getItems();
		int k = 0;
		for (; k < items.length; k++) {
			final String currentKeySequence = items[k].getText(2);
			if (binding.getTriggerSequence().format()
					.equals(currentKeySequence)) {
				break;
			}
		}
		if (k < tableBindingsForCommand.getItemCount()) {
			tableBindingsForCommand.select(k);
			tableBindingsForCommand.notifyListeners(SWT.Selection, null);
			textTriggerSequence.setFocus();
		}
	}

	/**
	 * Returns the identifier for the currently selected category.
	 * 
	 * @return The selected category; <code>null</code> if none.
	 */
	private final String getCategoryId() {
		return !commandIdsByCategoryId.containsKey(null)
				|| comboCategory.getSelectionIndex() > 0 ? (String) categoryIdsByUniqueName
				.get(comboCategory.getText())
				: null;
	}

	/**
	 * Returns the identifier for the currently selected context.
	 * 
	 * @return The selected context; <code>null</code> if none.
	 */
	private final String getContextId() {
		return comboContext.getSelectionIndex() >= 0 ? (String) contextIdsByUniqueName
				.get(comboContext.getText())
				: null;
	}

	/**
	 * Returns the current trigger sequence.
	 * 
	 * @return The trigger sequence; may be empty, but never <code>null</code>.
	 */
	private final KeySequence getKeySequence() {
		return textTriggerSequenceManager.getKeySequence();
	}

	/**
	 * Returns the currently-selected fully-parameterized command.
	 * 
	 * @return The selected fully-parameterized command; <code>null</code> if
	 *         none.
	 */
	private final ParameterizedCommand getParameterizedCommand() {
		final int selectionIndex = comboCommand.getSelectionIndex();
		if ((selectionIndex >= 0) && (commands != null)
				&& (selectionIndex < commands.length)) {
			return commands[selectionIndex];
		}

		return null;
	}

	/**
	 * Returns the identifier for the currently selected scheme.
	 * 
	 * @return The selected scheme; <code>null</code> if none.
	 */
	private final String getSchemeId() {
		return comboScheme.getSelectionIndex() >= 0 ? (String) schemeIdsByUniqueName
				.get(comboScheme.getText())
				: null;
	}

	public final void init(final IWorkbench workbench) {
		activityManager = workbench.getActivitySupport().getActivityManager();
		bindingService = (IBindingService) workbench
				.getAdapter(IBindingService.class);
		commandService = (ICommandService) workbench
				.getAdapter(ICommandService.class);
		contextService = (IContextService) workbench
				.getAdapter(IContextService.class);
	}

	/**
	 * Checks whether the activity manager knows anything about this command
	 * identifier. If the activity manager is currently filtering this command,
	 * then it does not appear in the user interface.
	 * 
	 * @param command
	 *            The command which should be checked against the activities;
	 *            must not be <code>null</code>.
	 * @return <code>true</code> if the command identifier is not filtered;
	 *         <code>false</code> if it is
	 */
	private final boolean isActive(final Command command) {
		return activityManager.getIdentifier(command.getId()).isEnabled();
	}

	/**
	 * Logs the given exception, and opens an error dialog saying that something
	 * went wrong. The exception is assumed to have something to do with the
	 * preference store.
	 * 
	 * @param exception
	 *            The exception to be logged; must not be <code>null</code>.
	 */
	private final void logPreferenceStoreException(final Throwable exception) {
		final String message = Util.translateString(RESOURCE_BUNDLE,
				"PreferenceStoreError.Message"); //$NON-NLS-1$
		final String title = Util.translateString(RESOURCE_BUNDLE,
				"PreferenceStoreError.Title"); //$NON-NLS-1$
		String exceptionMessage = exception.getMessage();
		if (exceptionMessage == null) {
			exceptionMessage = message;
		}
		final IStatus status = new Status(IStatus.ERROR,
				WorkbenchPlugin.PI_WORKBENCH, 0, exceptionMessage, exception);
		WorkbenchPlugin.log(message, status);
		ErrorDialog.openError(tabFolder.getShell(), title, message, status);
	}

	public final boolean performCancel() {
		// Save the selected tab for future reference.
		persistSelectedTab();

		return super.performCancel();
	}

	protected final void performDefaults() {
		// Ask the user to confirm
		final String title = Util.translateString(RESOURCE_BUNDLE,
				"restoreDefaultsMessageBoxText"); //$NON-NLS-1$
		final String message = Util.translateString(RESOURCE_BUNDLE,
				"restoreDefaultsMessageBoxMessage"); //$NON-NLS-1$
		final boolean confirmed = MessageDialog.openConfirm(getShell(), title,
				message);

		if (confirmed) {
			// Fix the scheme in the local changes.
			final String defaultSchemeId = bindingService.getDefaultSchemeId();
			final Scheme defaultScheme = localChangeManager
					.getScheme(defaultSchemeId);
			try {
				localChangeManager.setActiveScheme(defaultScheme);
			} catch (final NotDefinedException e) {
				// At least we tried....
			}

			// Fix the bindings in the local changes.
			final Binding[] currentBindings = localChangeManager.getBindings();
			final int currentBindingsLength = currentBindings.length;
			final Set trimmedBindings = new HashSet();
			for (int i = 0; i < currentBindingsLength; i++) {
				final Binding binding = currentBindings[i];
				if (binding.getType() != Binding.USER) {
					trimmedBindings.add(binding);
				}
			}
			final Binding[] trimmedBindingArray = (Binding[]) trimmedBindings
					.toArray(new Binding[trimmedBindings.size()]);
			localChangeManager.setBindings(trimmedBindingArray);

			// Apply the changes.
			try {
				bindingService.savePreferences(defaultScheme,
						trimmedBindingArray);
			} catch (final IOException e) {
				logPreferenceStoreException(e);
			}
		}

		setScheme(localChangeManager.getActiveScheme()); // update the scheme
		update(true);
		super.performDefaults();
	}

	public final boolean performOk() {
		// Save the preferences.
		try {
			bindingService.savePreferences(
					localChangeManager.getActiveScheme(), localChangeManager
							.getBindings());
		} catch (final IOException e) {
			logPreferenceStoreException(e);
		}

		// Save the selected tab for future reference.
		persistSelectedTab();

		return super.performOk();
	}

	/**
	 * Remembers the currently selected tab for when the preference page next
	 * opens.
	 */
	private final void persistSelectedTab() {
		final IPreferenceStore store = getPreferenceStore();
		store.setValue(IPreferenceConstants.KEYS_PREFERENCE_SELECTED_TAB,
				tabFolder.getSelectionIndex());
	}

	/**
	 * Handles the selection event on the add button. This removes all
	 * user-defined bindings matching the given key sequence, scheme and
	 * context. It then adds a new binding with the current selections.
	 */
	private final void selectedButtonAdd() {
		final ParameterizedCommand command = getParameterizedCommand();
		final String contextId = getContextId();
		final String schemeId = getSchemeId();
		final KeySequence keySequence = getKeySequence();
		localChangeManager.removeBindings(keySequence, schemeId, contextId,
				null, null, null, Binding.USER);
		localChangeManager.addBinding(new KeyBinding(keySequence, command,
				schemeId, contextId, null, null, null, Binding.USER));
		update(true);
	}

	/**
	 * Provides a facility for exporting the viewable list of key bindings to a
	 * file. Currently, this only supports exporting to a list of
	 * comma-separated values. The user is prompted for which file should
	 * receive our bounty.
	 * 
	 * @since 3.1
	 */
	private final void selectedButtonExport() {
		final FileDialog fileDialog = new FileDialog(getShell(), SWT.SAVE);
		fileDialog.setFilterExtensions(new String[] { "*.csv" }); //$NON-NLS-1$
		fileDialog.setFilterNames(new String[] { Util.translateString(
				RESOURCE_BUNDLE, "csvFilterName") }); //$NON-NLS-1$
		final String filePath = fileDialog.open();
		if (filePath == null) {
			return;
		}

		final SafeRunnable runnable = new SafeRunnable() {
			public final void run() throws IOException {
				Writer fileWriter = null;
				try {
					fileWriter = new BufferedWriter(new FileWriter(filePath));
					final TableItem[] items = tableBindings.getItems();
					final int numColumns = tableBindings.getColumnCount();
					for (int i = 0; i < items.length; i++) {
						final TableItem item = items[i];
						for (int j = 0; j < numColumns; j++) {
							fileWriter.write(item.getText(j));
							if (j < numColumns - 1) {
								fileWriter.write(',');
							}
						}
						fileWriter.write(System.getProperty("line.separator")); //$NON-NLS-1$
					}

				} finally {
					if (fileWriter != null) {
						try {
							fileWriter.close();
						} catch (final IOException e) {
							// At least I tried.
						}
					}

				}
			}
		};
		Platform.run(runnable);
	}

	/**
	 * Handles the selection event on the remove button. This removes all
	 * user-defined bindings matching the given key sequence, scheme and
	 * context. It then adds a new deletion binding for the selected trigger
	 * sequence.
	 */
	private final void selectedButtonRemove() {
		final String contextId = getContextId();
		final String schemeId = getSchemeId();
		final KeySequence keySequence = getKeySequence();
		localChangeManager.removeBindings(keySequence, schemeId, contextId,
				null, null, null, Binding.USER);
		localChangeManager.addBinding(new KeyBinding(keySequence, null,
				schemeId, contextId, null, null, null, Binding.USER));
		update(true);
	}

	/**
	 * Handles the selection event on the restore button. This removes all
	 * user-defined bindings matching the given key sequence, scheme and
	 * context.
	 */
	private final void selectedButtonRestore() {
		String contextId = getContextId();
		String schemeId = getSchemeId();
		KeySequence keySequence = getKeySequence();
		localChangeManager.removeBindings(keySequence, schemeId, contextId,
				null, null, null, Binding.USER);
		update(true);
	}

	/**
	 * Updates the local managers active scheme, and then updates the interface.
	 */
	private final void selectedComboScheme() {
		final String activeSchemeId = getSchemeId();
		final Scheme activeScheme = localChangeManager
				.getScheme(activeSchemeId);
		try {
			localChangeManager.setActiveScheme(activeScheme);
		} catch (final NotDefinedException e) {
			// Oh, well.
		}
		update(true);
	}

	/**
	 * Handles the selection event on the table containing the bindings for a
	 * particular command. This updates the context and trigger sequence based
	 * on the selected binding.
	 */
	private final void selectedTableBindingsForCommand() {
		final int selection = tableBindingsForCommand.getSelectionIndex();
		if ((selection >= 0)
				&& (selection < tableBindingsForCommand.getItemCount())) {
			final TableItem item = tableBindingsForCommand.getItem(selection);
			final KeyBinding binding = (KeyBinding) item.getData(ITEM_DATA_KEY);
			setContextId(binding.getContextId());
			setKeySequence(binding.getKeySequence());
		}

		update();
	}

	/**
	 * Handles the selection event on the table containing the bindings for a
	 * particular trigger sequence. This updates the context based on the
	 * selected binding.
	 */
	private final void selectedTableBindingsForTriggerSequence() {
		final int selection = tableBindingsForTriggerSequence
				.getSelectionIndex();
		if ((selection >= 0)
				&& (selection < tableBindingsForTriggerSequence.getItemCount())) {
			final TableItem item = tableBindingsForTriggerSequence
					.getItem(selection);
			final Binding binding = (Binding) item.getData(ITEM_DATA_KEY);
			setContextId(binding.getContextId());
		}

		update();
	}

	/**
	 * Responds to some kind of trigger on the View tab by taking the current
	 * selection on the key bindings table and selecting the appropriate items
	 * in the Modify tab.
	 * 
	 * @since 3.1
	 */
	private final void selectedTableKeyBindings() {
		final int selectionIndex = tableBindings.getSelectionIndex();
		if (selectionIndex != -1) {
			final TableItem item = tableBindings.getItem(selectionIndex);
			final Binding binding = (Binding) item.getData(BINDING_KEY);
			editBinding(binding);

		} else {
			editBinding(null);
		}
	}

	/**
	 * Changes the selected context name in the context combo box. The context
	 * selected is either the one matching the identifier provided (if
	 * possible), or the default context identifier. If no matching name can be
	 * found in the combo, then the first item is selected.
	 * 
	 * @param contextId
	 *            The context identifier for the context to be selected in the
	 *            combo box; may be <code>null</code>.
	 */
	private final void setContextId(final String contextId) {
		// Clear the current selection.
		comboContext.clearSelection();
		comboContext.deselectAll();

		// Figure out which name to look for.
		String contextName = (String) contextUniqueNamesById.get(contextId);
		if (contextName == null) {
			contextName = (String) contextUniqueNamesById
					.get(IContextIds.CONTEXT_ID_WINDOW);
		}
		if (contextName == null) {
			contextName = Util.ZERO_LENGTH_STRING;
		}

		// Scan the list for the selection we're looking for.
		final String[] items = comboContext.getItems();
		boolean found = false;
		for (int i = 0; i < items.length; i++) {
			if (contextName.equals(items[i])) {
				comboContext.select(i);
				found = true;
				break;
			}
		}

		// If we didn't find an item, then set the first item as selected.
		if ((!found) && (items.length > 0)) {
			comboContext.select(0);
		}
	}

	/**
	 * Sets the current trigger sequence.
	 * 
	 * @param keySequence
	 *            The trigger sequence; may be <code>null</code>.
	 */
	private final void setKeySequence(final KeySequence keySequence) {
		textTriggerSequenceManager.setKeySequence(keySequence);
	}

	/**
	 * Changes the selection in the command combo box.
	 * 
	 * @param command
	 *            The fully-parameterized command to select; may be
	 *            <code>null</code>.
	 */
	private final void setParameterizedCommand(
			final ParameterizedCommand command) {
		int i = 0;
		if (commands != null) {
			final int commandCount = commands.length;
			for (; i < commandCount; i++) {
				if (commands[i].equals(command)) {
					if ((comboCommand.getSelectionIndex() != i)
							&& (i < comboCommand.getItemCount())) {
						comboCommand.select(i);
					}
					break;
				}
			}
			if ((i >= comboCommand.getItemCount())
					&& (comboCommand.getSelectionIndex() != 0)) {
				comboCommand.select(0);
			}
		}
	}

	/**
	 * Sets the currently selected scheme
	 * 
	 * @param scheme
	 *            The scheme to select; may be <code>null</code>.
	 */
	private final void setScheme(final Scheme scheme) {
		comboScheme.clearSelection();
		comboScheme.deselectAll();
		final String schemeUniqueName = (String) schemeUniqueNamesById
				.get(scheme.getId());

		if (schemeUniqueName != null) {
			final String items[] = comboScheme.getItems();

			for (int i = 0; i < items.length; i++) {
				if (schemeUniqueName.equals(items[i])) {
					comboScheme.select(i);
					break;
				}
			}
		}
	}

	/**
	 * Builds the internal look-up tables before allowing the page to become
	 * visible.
	 */
	public final void setVisible(final boolean visible) {
		if (visible == true) {
			Map contextsByName = new HashMap();

			for (Iterator iterator = contextService.getDefinedContextIds()
					.iterator(); iterator.hasNext();) {
				Context context = contextService.getContext((String) iterator
						.next());
				try {
					String name = context.getName();
					Collection contexts = (Collection) contextsByName.get(name);

					if (contexts == null) {
						contexts = new HashSet();
						contextsByName.put(name, contexts);
					}

					contexts.add(context);
				} catch (final NotDefinedException e) {
					// Do nothing.
				}
			}

			Map categoriesByName = new HashMap();

			for (Iterator iterator = commandService.getDefinedCategoryIds()
					.iterator(); iterator.hasNext();) {
				Category category = commandService
						.getCategory((String) iterator.next());

				try {
					String name = category.getName();
					Collection categories = (Collection) categoriesByName
							.get(name);

					if (categories == null) {
						categories = new HashSet();
						categoriesByName.put(name, categories);
					}

					categories.add(category);
				} catch (NotDefinedException eNotDefined) {
					// Do nothing
				}
			}

			Map commandsByName = new HashMap();

			for (Iterator iterator = commandService.getDefinedCommandIds()
					.iterator(); iterator.hasNext();) {
				Command command = commandService.getCommand((String) iterator
						.next());
				if (!isActive(command)) {
					continue;
				}

				try {
					String name = command.getName();
					Collection commands = (Collection) commandsByName.get(name);

					if (commands == null) {
						commands = new HashSet();
						commandsByName.put(name, commands);
					}

					commands.add(command);
				} catch (NotDefinedException eNotDefined) {
					// Do nothing
				}
			}

			Map schemesByName = new HashMap();

			final Scheme[] definedSchemes = bindingService.getDefinedSchemes();
			for (int i = 0; i < definedSchemes.length; i++) {
				final Scheme scheme = definedSchemes[i];
				try {
					String name = scheme.getName();
					Collection schemes = (Collection) schemesByName.get(name);

					if (schemes == null) {
						schemes = new HashSet();
						schemesByName.put(name, schemes);
					}

					schemes.add(scheme);
				} catch (final NotDefinedException e) {
					// Do nothing.
				}
			}

			contextIdsByUniqueName = new HashMap();
			contextUniqueNamesById = new HashMap();

			for (Iterator iterator = contextsByName.entrySet().iterator(); iterator
					.hasNext();) {
				Map.Entry entry = (Map.Entry) iterator.next();
				String name = (String) entry.getKey();
				Set contexts = (Set) entry.getValue();
				Iterator iterator2 = contexts.iterator();

				if (contexts.size() == 1) {
					Context context = (Context) iterator2.next();
					contextIdsByUniqueName.put(name, context.getId());
					contextUniqueNamesById.put(context.getId(), name);
				} else {
					while (iterator2.hasNext()) {
						Context context = (Context) iterator2.next();
						String uniqueName = MessageFormat.format(
								Util.translateString(RESOURCE_BUNDLE,
										"uniqueName"), new Object[] { name, //$NON-NLS-1$
										context.getId() });
						contextIdsByUniqueName.put(uniqueName, context.getId());
						contextUniqueNamesById.put(context.getId(), uniqueName);
					}
				}
			}

			categoryIdsByUniqueName = new HashMap();
			categoryUniqueNamesById = new HashMap();

			for (Iterator iterator = categoriesByName.entrySet().iterator(); iterator
					.hasNext();) {
				Map.Entry entry = (Map.Entry) iterator.next();
				String name = (String) entry.getKey();
				Set categories = (Set) entry.getValue();
				Iterator iterator2 = categories.iterator();

				if (categories.size() == 1) {
					Category category = (Category) iterator2.next();
					categoryIdsByUniqueName.put(name, category.getId());
					categoryUniqueNamesById.put(category.getId(), name);
				} else {
					while (iterator2.hasNext()) {
						Category category = (Category) iterator2.next();
						String uniqueName = MessageFormat.format(
								Util.translateString(RESOURCE_BUNDLE,
										"uniqueName"), new Object[] { name, //$NON-NLS-1$
										category.getId() });
						categoryIdsByUniqueName.put(uniqueName, category
								.getId());
						categoryUniqueNamesById.put(category.getId(),
								uniqueName);
					}
				}
			}

			schemeIdsByUniqueName = new HashMap();
			schemeUniqueNamesById = new HashMap();

			for (Iterator iterator = schemesByName.entrySet().iterator(); iterator
					.hasNext();) {
				Map.Entry entry = (Map.Entry) iterator.next();
				String name = (String) entry.getKey();
				Set keyConfigurations = (Set) entry.getValue();
				Iterator iterator2 = keyConfigurations.iterator();

				if (keyConfigurations.size() == 1) {
					Scheme scheme = (Scheme) iterator2.next();
					schemeIdsByUniqueName.put(name, scheme.getId());
					schemeUniqueNamesById.put(scheme.getId(), name);
				} else {
					while (iterator2.hasNext()) {
						Scheme scheme = (Scheme) iterator2.next();
						String uniqueName = MessageFormat.format(
								Util.translateString(RESOURCE_BUNDLE,
										"uniqueName"), new Object[] { name, //$NON-NLS-1$
										scheme.getId() });
						schemeIdsByUniqueName.put(uniqueName, scheme.getId());
						schemeUniqueNamesById.put(scheme.getId(), uniqueName);
					}
				}
			}

			Scheme activeScheme = bindingService.getActiveScheme();
			commandIdsByCategoryId = new HashMap();

			for (Iterator iterator = commandService.getDefinedCommandIds()
					.iterator(); iterator.hasNext();) {
				final Command command = commandService
						.getCommand((String) iterator.next());
				if (!isActive(command)) {
					continue;
				}

				try {
					String categoryId = command.getCategory().getId();
					Collection commandIds = (Collection) commandIdsByCategoryId
							.get(categoryId);

					if (commandIds == null) {
						commandIds = new HashSet();
						commandIdsByCategoryId.put(categoryId, commandIds);
					}

					commandIds.add(command.getId());
				} catch (NotDefinedException eNotDefined) {
					// Do nothing
				}
			}

			// Make an internal copy of the binding manager, for local changes.
			try {
				for (int i = 0; i < definedSchemes.length; i++) {
					final Scheme scheme = definedSchemes[i];
					final Scheme copy = localChangeManager.getScheme(scheme
							.getId());
					copy.define(scheme.getName(), scheme.getDescription(),
							scheme.getParentId());
				}
				localChangeManager.setActiveScheme(bindingService
						.getActiveScheme());
			} catch (final NotDefinedException e) {
				throw new Error(
						"There is a programmer error in the keys preference page"); //$NON-NLS-1$
			}
			localChangeManager.setLocale(bindingService.getLocale());
			localChangeManager.setPlatform(bindingService.getPlatform());
			localChangeManager.setBindings(bindingService.getBindings());

			// Populate the category combo box.
			List categoryNames = new ArrayList(categoryIdsByUniqueName.keySet());
			Collections.sort(categoryNames, Collator.getInstance());
			if (commandIdsByCategoryId.containsKey(null)) {
				categoryNames.add(0, Util.translateString(RESOURCE_BUNDLE,
						"other")); //$NON-NLS-1$
			}
			comboCategory.setItems((String[]) categoryNames
					.toArray(new String[categoryNames.size()]));
			comboCategory.clearSelection();
			comboCategory.deselectAll();
			if (commandIdsByCategoryId.containsKey(null)
					|| !categoryNames.isEmpty()) {
				comboCategory.select(0);
			}

			// Populate the scheme combo box.
			List schemeNames = new ArrayList(schemeIdsByUniqueName.keySet());
			Collections.sort(schemeNames, Collator.getInstance());
			comboScheme.setItems((String[]) schemeNames
					.toArray(new String[schemeNames.size()]));
			setScheme(activeScheme);

			// Update the entire page.
			update(true);
		}

		super.setVisible(visible);
	}

	/**
	 * Updates the entire preference page -- except the view tab -- based on
	 * current selection sate. This preference page is written so that
	 * everything can be made consistent simply by inspecting the state of its
	 * widgets. A change is triggered by the user, and an event is fired. The
	 * event triggers an update. It is possible for extra work to be done by
	 * this page before calling update.
	 */
	private final void update() {
		update(false);
	}

	/**
	 * Updates the entire preference page based on current changes. This
	 * preference page is written so that everything can be made consistent
	 * simply by inspecting the state of its widgets. A change is triggered by
	 * the user, and an event is fired. The event triggers an update. It is
	 * possible for extra work to be done by this page before calling update.
	 * 
	 * @param updateViewTab
	 *            Whether the view tab should be updated as well.
	 */
	private final void update(final boolean updateViewTab) {
		if (updateViewTab) {
			updateViewTab();
		}
		updateComboCommand();
		updateComboContext();
		final TriggerSequence triggerSequence = getKeySequence();
		updateTableBindingsForTriggerSequence(triggerSequence);
		final ParameterizedCommand command = getParameterizedCommand();
		updateTableBindingsForCommand(command);
		final String contextId = getContextId();
		updateSelection(tableBindingsForTriggerSequence, contextId,
				triggerSequence);
		updateSelection(tableBindingsForCommand, contextId, triggerSequence);
		updateLabelSchemeExtends();
		updateLabelContextExtends();
		updateEnabled(triggerSequence, command);
	}

	/**
	 * Updates the contents of the commands combo box, based on the current
	 * selection in the category combo box.
	 */
	private final void updateComboCommand() {
		// Remember the current selection, so we can restore it later.
		final ParameterizedCommand command = getParameterizedCommand();

		// Figure out where command identifiers apply to the selected category.
		final String categoryId = getCategoryId();
		final Set commandIds = (Set) commandIdsByCategoryId.get(categoryId);

		/*
		 * Generate an array of parameterized commands based on these
		 * identifiers. The parameterized commands will be sorted based on their
		 * names.
		 */
		final SortedSet commands = new TreeSet();
		final Iterator commandIdItr = commandIds.iterator();
		while (commandIdItr.hasNext()) {
			final String currentCommandId = (String) commandIdItr.next();
			final Command currentCommand = commandService
					.getCommand(currentCommandId);
			try {
				commands.addAll(ParameterizedCommand
						.generateCombinations(currentCommand));
			} catch (final NotDefinedException e) {
				// It is safe to just ignore undefined commands.
			}
		}
		final int commandCount = commands.size();
		this.commands = (ParameterizedCommand[]) commands
				.toArray(new ParameterizedCommand[commandCount]);

		/*
		 * Generate an array of command names based on this array of
		 * parameterized commands.
		 */
		final String[] commandNames = new String[commandCount];
		for (int i = 0; i < commandCount; i++) {
			try {
				commandNames[i] = this.commands[i].getName();
			} catch (final NotDefinedException e) {
				throw new Error(
						"Concurrent modification of the command's defined state"); //$NON-NLS-1$
			}
		}

		/*
		 * Copy the command names into the combo box, but only if they've
		 * changed. We do this to try to avoid unnecessary calls out to the
		 * operating system, as well as to defend against bugs in SWT's event
		 * mechanism.
		 */
		final String[] currentItems = comboCommand.getItems();
		if (!Arrays.equals(currentItems, commandNames)) {
			comboCommand.setItems(commandNames);
		}

		// Try to restore the selection.
		setParameterizedCommand(command);

		/*
		 * Just to be extra careful, make sure that we have a selection at this
		 * point. This line could probably be removed, but it makes the code a
		 * bit more robust.
		 */
		if ((comboCommand.getSelectionIndex() == -1) && (commandCount > 0)) {
			comboCommand.select(0);
		}
	}

	/**
	 * Updates the contents of the context combo box, as well as its selection.
	 */
	private final void updateComboContext() {
		final String contextId = getContextId();
		final Map contextIdsByName = new HashMap(contextIdsByUniqueName);

		final List contextNames = new ArrayList(contextIdsByName.keySet());
		Collections.sort(contextNames, Collator.getInstance());

		comboContext.setItems((String[]) contextNames
				.toArray(new String[contextNames.size()]));
		setContextId(contextId);

		if (comboContext.getSelectionIndex() == -1 && !contextNames.isEmpty()) {
			comboContext.select(0);
		}
	}

	/**
	 * Updates the enabled state of the various widgets on this page. The
	 * decision is based on the current trigger sequence and the currently
	 * selected command.
	 * 
	 * @param triggerSequence
	 *            The current trigger sequence; may be empty, but never
	 *            <code>null</code>.
	 * @param command
	 *            The currently selected command, if any; <code>null</code>
	 *            otherwise.
	 */
	private final void updateEnabled(final TriggerSequence triggerSequence,
			final ParameterizedCommand command) {
		final boolean commandSelected = command != null;
		labelBindingsForCommand.setEnabled(commandSelected);
		tableBindingsForCommand.setEnabled(commandSelected);

		final boolean triggerSequenceSelected = !triggerSequence.isEmpty();
		labelBindingsForTriggerSequence.setEnabled(triggerSequenceSelected);
		tableBindingsForTriggerSequence.setEnabled(triggerSequenceSelected);

		/*
		 * TODO Do some better button enablement.
		 */
		final boolean buttonsEnabled = commandSelected
				&& triggerSequenceSelected;
		buttonAdd.setEnabled(buttonsEnabled);
		buttonRemove.setEnabled(buttonsEnabled);
		buttonRestore.setEnabled(buttonsEnabled);
	}

	/**
	 * Updates the label next to the context that says "extends" if the context
	 * is a child of another context. If the context is not a child of another
	 * context, then the label is simply blank.
	 */
	private final void updateLabelContextExtends() {
		final String contextId = getContextId();

		if (contextId != null) {
			final Context context = contextService.getContext(getContextId());
			if (context.isDefined()) {
				try {
					final String parentId = context.getParentId();
					if (parentId != null) {
						final String name = (String) contextUniqueNamesById
								.get(parentId);
						if (name != null) {
							labelContextExtends.setText(MessageFormat.format(
									Util.translateString(RESOURCE_BUNDLE,
											"extends"), //$NON-NLS-1$
									new Object[] { name }));
							return;
						}
					}
				} catch (final NotDefinedException e) {
					// Do nothing
				}
			}
		}

		labelContextExtends.setText(Util.ZERO_LENGTH_STRING);
	}

	/**
	 * Updates the label next to the scheme that says "extends" if the scheme is
	 * a child of another scheme. If the scheme is not a child of another
	 * scheme, then the label is simply blank.
	 */
	private final void updateLabelSchemeExtends() {
		final String schemeId = getSchemeId();

		if (schemeId != null) {
			final Scheme scheme = bindingService.getScheme(schemeId);
			try {
				final String name = (String) schemeUniqueNamesById.get(scheme
						.getParentId());
				if (name != null) {
					labelSchemeExtends.setText(MessageFormat.format(Util
							.translateString(RESOURCE_BUNDLE, "extends"), //$NON-NLS-1$
							new Object[] { name }));
					return;
				}
			} catch (final NotDefinedException e) {
				// Do nothing
			}
		}

		labelSchemeExtends.setText(Util.ZERO_LENGTH_STRING);
	}

	/**
	 * Tries to select the correct entry in table based on the currently
	 * selected context and trigger sequence. If the table hasn't really
	 * changed, then this method is essentially trying to restore the selection.
	 * If it has changed, then it is trying to select the most entry based on
	 * the context.
	 * 
	 * @param table
	 *            The table to be changed; must not be <code>null</code>.
	 * @param contextId
	 *            The currently selected context; should not be
	 *            <code>null</code>.
	 * @param triggerSequence
	 *            The current trigger sequence; should not be <code>null</code>.
	 */
	private final void updateSelection(final Table table,
			final String contextId, final TriggerSequence triggerSequence) {
		if (table.getSelectionCount() > 1) {
			table.deselectAll();
		}

		final TableItem[] items = table.getItems();
		int selection = -1;
		for (int i = 0; i < items.length; i++) {
			final Binding binding = (Binding) items[i].getData(ITEM_DATA_KEY);
			if ((Util.equals(contextId, binding.getContextId()))
					&& (Util.equals(triggerSequence, binding
							.getTriggerSequence()))) {
				selection = i;
				break;
			}
		}

		if (selection != -1) {
			table.select(selection);
		}
	}

	/**
	 * Updates the contents of the table showing the bindings for the currently
	 * selected command. The selection is destroyed by this process.
	 * 
	 * @param parameterizedCommand
	 *            The currently selected fully-parameterized command; may be
	 *            <code>null</code>.
	 */
	private final void updateTableBindingsForCommand(
			final ParameterizedCommand parameterizedCommand) {
		// Clear the table of existing items.
		tableBindingsForCommand.removeAll();

		// Add each of the bindings, if the command identifier matches.
		final Collection bindings = localChangeManager
				.getActiveBindingsDisregardingContextFlat();
		final Iterator bindingItr = bindings.iterator();
		while (bindingItr.hasNext()) {
			final Binding binding = (Binding) bindingItr.next();
			if (!Util.equals(parameterizedCommand, binding
					.getParameterizedCommand())) {
				continue; // binding does not match
			}

			final TableItem tableItem = new TableItem(tableBindingsForCommand,
					SWT.NULL);
			tableItem.setData(ITEM_DATA_KEY, binding);

			/*
			 * Set the associated image based on the type of binding. Either it
			 * is a user binding or a system binding.
			 * 
			 * TODO Identify more image types.
			 */
			if (binding.getType() == Binding.SYSTEM) {
				tableItem.setImage(0, IMAGE_BLANK);
			} else {
				tableItem.setImage(0, IMAGE_CHANGE);
			}

			tableItem.setText(1, (String) contextUniqueNamesById.get(binding
					.getContextId()));
			tableItem.setText(2, binding.getTriggerSequence().format());
		}
	}

	/**
	 * Updates the contents of the table showing the bindings for the current
	 * trigger sequence. The selection is destroyed by this process.
	 * 
	 * @param triggerSequence
	 *            The current trigger sequence; may be <code>null</code> or
	 *            empty.
	 */
	private final void updateTableBindingsForTriggerSequence(
			final TriggerSequence triggerSequence) {
		// Clear the table of its existing items.
		tableBindingsForTriggerSequence.removeAll();

		// Get the collection of bindings for the current command.
		final Map activeBindings = localChangeManager
				.getActiveBindingsDisregardingContext();
		final Collection bindings = (Collection) activeBindings
				.get(triggerSequence);
		if (bindings == null) {
			return;
		}

		// Add each of the bindings.
		final Iterator bindingItr = bindings.iterator();
		while (bindingItr.hasNext()) {
			final Binding binding = (Binding) bindingItr.next();
			final Context context = contextService.getContext(binding
					.getContextId());
			final ParameterizedCommand parameterizedCommand = binding
					.getParameterizedCommand();
			final Command command = parameterizedCommand.getCommand();
			if ((!context.isDefined()) && (!command.isDefined())) {
				continue;
			}

			final TableItem tableItem = new TableItem(
					tableBindingsForTriggerSequence, SWT.NULL);
			tableItem.setData(ITEM_DATA_KEY, binding);

			/*
			 * Set the associated image based on the type of binding. Either it
			 * is a user binding or a system binding.
			 * 
			 * TODO Identify more image types.
			 */
			if (binding.getType() == Binding.SYSTEM) {
				tableItem.setImage(0, IMAGE_BLANK);
			} else {
				tableItem.setImage(0, IMAGE_CHANGE);
			}

			try {
				tableItem.setText(1, context.getName());
				tableItem.setText(2, parameterizedCommand.getName());
			} catch (final NotDefinedException e) {
				throw new Error(
						"Context or command became undefined on a non-UI thread will the UI thread was processing."); //$NON-NLS-1$
			}
		}
	}

	/**
	 * Updates the contents of the view tab. This queries the command manager
	 * for a list of key sequence binding definitions, and these definitions are
	 * then added to the table.
	 * 
	 * @since 3.1
	 */
	private final void updateViewTab() {
		// Clear out the existing table contents.
		tableBindings.removeAll();

		// Get a sorted list of key binding contents.
		final List bindings = new ArrayList(localChangeManager
				.getActiveBindingsDisregardingContextFlat());
		Collections.sort(bindings, new Comparator() {
			/**
			 * Compares two instances of <code>Binding</code> based on the
			 * current sort order.
			 * 
			 * @param object1
			 *            The first object to compare; must be an instance of
			 *            <code>Binding</code> (i.e., not <code>null</code>).
			 * @param object2
			 *            The second object to compare; must be an instance of
			 *            <code>Binding</code> (i.e., not <code>null</code>).
			 * @return The integer value representing the comparison. The
			 *         comparison is based on the current sort order.
			 * @since 3.1
			 */
			public final int compare(final Object object1, final Object object2) {
				final Binding binding1 = (Binding) object1;
				final Binding binding2 = (Binding) object2;

				/*
				 * Get the category name, command name, formatted key sequence
				 * and context name for the first binding.
				 */
				final Command command1 = binding1.getParameterizedCommand()
						.getCommand();
				String categoryName1 = Util.ZERO_LENGTH_STRING;
				String commandName1 = Util.ZERO_LENGTH_STRING;
				try {
					commandName1 = command1.getName();
					categoryName1 = command1.getCategory().getName();
				} catch (final NotDefinedException e) {
					// Just use the zero-length string.
				}
				final String triggerSequence1 = binding1.getTriggerSequence()
						.format();
				final String contextId1 = binding1.getContextId();
				String contextName1 = Util.ZERO_LENGTH_STRING;
				if (contextId1 != null) {
					final Context context = contextService
							.getContext(contextId1);
					try {
						contextName1 = context.getName();
					} catch (final org.eclipse.core.commands.common.NotDefinedException e) {
						// Just use the zero-length string.
					}
				}

				/*
				 * Get the category name, command name, formatted key sequence
				 * and context name for the first binding.
				 */
				final Command command2 = binding2.getParameterizedCommand()
						.getCommand();
				String categoryName2 = Util.ZERO_LENGTH_STRING;
				String commandName2 = Util.ZERO_LENGTH_STRING;
				try {
					commandName2 = command2.getName();
					categoryName2 = command2.getCategory().getName();
				} catch (final org.eclipse.core.commands.common.NotDefinedException e) {
					// Just use the zero-length string.
				}
				final String keySequence2 = binding2.getTriggerSequence()
						.format();
				final String contextId2 = binding2.getContextId();
				String contextName2 = Util.ZERO_LENGTH_STRING;
				if (contextId2 != null) {
					final Context context = contextService
							.getContext(contextId2);
					try {
						contextName2 = context.getName();
					} catch (final org.eclipse.core.commands.common.NotDefinedException e) {
						// Just use the zero-length string.
					}
				}

				// Compare the items in the current sort order.
				int compare = 0;
				for (int i = 0; i < sortOrder.length; i++) {
					switch (sortOrder[i]) {
					case VIEW_CATEGORY_COLUMN_INDEX:
						compare = Util.compare(categoryName1, categoryName2);
						if (compare != 0) {
							return compare;
						}
						break;
					case VIEW_COMMAND_COLUMN_INDEX:
						compare = Util.compare(commandName1, commandName2);
						if (compare != 0) {
							return compare;
						}
						break;
					case VIEW_KEY_SEQUENCE_COLUMN_INDEX:
						compare = Util.compare(triggerSequence1, keySequence2);
						if (compare != 0) {
							return compare;
						}
						break;
					case VIEW_CONTEXT_COLUMN_INDEX:
						compare = Util.compare(contextName1, contextName2);
						if (compare != 0) {
							return compare;
						}
						break;
					default:
						throw new Error(
								"Programmer error: added another sort column without modifying the comparator."); //$NON-NLS-1$
					}
				}

				return compare;
			}

			/**
			 * @see Object#equals(java.lang.Object)
			 */
			public final boolean equals(final Object object) {
				return super.equals(object);
			}
		});

		// Add a table item for each item in the list.
		final Iterator keyBindingItr = bindings.iterator();
		while (keyBindingItr.hasNext()) {
			final Binding binding = (Binding) keyBindingItr.next();

			// Get the command and category name.
			final ParameterizedCommand command = binding
					.getParameterizedCommand();
			String commandName = Util.ZERO_LENGTH_STRING;
			String categoryName = Util.ZERO_LENGTH_STRING;
			try {
				commandName = command.getName();
				categoryName = command.getCommand().getCategory().getName();
			} catch (final org.eclipse.core.commands.common.NotDefinedException e) {
				// Just use the zero-length string.
			}

			// Ignore items with a meaningless command name.
			if ((commandName == null) || (commandName.length() == 0)) {
				continue;
			}

			// Get the context name.
			final String contextId = binding.getContextId();
			String contextName = Util.ZERO_LENGTH_STRING;
			if (contextId != null) {
				final Context context = contextService.getContext(contextId);
				try {
					contextName = context.getName();
				} catch (final org.eclipse.core.commands.common.NotDefinedException e) {
					// Just use the zero-length string.
				}
			}

			// Create the table item.
			final TableItem item = new TableItem(tableBindings, SWT.NONE);
			item.setText(VIEW_CATEGORY_COLUMN_INDEX, categoryName);
			item.setText(VIEW_COMMAND_COLUMN_INDEX, commandName);
			item.setText(VIEW_KEY_SEQUENCE_COLUMN_INDEX, binding
					.getTriggerSequence().format());
			item.setText(VIEW_CONTEXT_COLUMN_INDEX, contextName);
			item.setData(BINDING_KEY, binding);
		}

		// Pack the columns.
		for (int i = 0; i < tableBindings.getColumnCount(); i++) {
			tableBindings.getColumn(i).pack();
		}
	}
	
	
}
