/*******************************************************************************
* Copyright (c)                                                                *
*           2005   Tristan Allwood,                                            *
*           2005   Daniel Burke,                                               *
*           2005   Marc Hull,                                                  *
*           2005   Ekaterina Itskova,                                          *
*           2005   Steve Zymler                                                *
*                                                                              *
* Permission is hereby granted, free of charge, to any person obtaining a      *
* copy of this software and associated documentation files (the                *
* "Software"), to deal in the Software without restriction, including          *
* without limitation the rights to use, copy, modify, merge, publish,          *
* distribute, sublicense, and/or sell copies of the Software, and to           *
* permit persons to whom the Software is furnished to do so, subject to        *
* the following conditions:                                                    *
*                                                                              *
* The above copyright notice and this permission notice shall be included      *
* in all copies or substantial portions of the Software.                       *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS      *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF                   *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.       *
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY         *
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,         *
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE            *
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                       *
*******************************************************************************/
/*
 * Created on 23-Nov-2004
 *
 */
package uk.ac.ic.doc.kevlar.gui.internal.keyboard;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;

import uk.ac.ic.doc.kevlar.Kevlar;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.AllowKeyPressAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.DebugKeyManagerAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.HideEditAttributeBoxAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.HidePopUpAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.IAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.autocomplete.EditAutoCompleteAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.autocomplete.program.AddProgramFromAutoCompleteAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.autocomplete.program.ShowProgramAutoCompleteAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.autocomplete.programentry.SelectProgramEntryAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.autocomplete.programentry.ShowProgramEntryAutoCompleteAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.dropdownbox.DownAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.dropdownbox.UpAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.findasyoutype.HideFindAsYouTypeAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.findasyoutype.ShowFindAsYouTypeAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.help.HideHelpAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.history.GoToHistoryStateAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.outputpane.MoveSelectedShowTabAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.outputpane.RemoveTabAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.outputpane.ResizeDownOutputPaneAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.outputpane.ResizeUpOutputPaneAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.outputpane.ShowOutputPaneAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.root.ExecutePipelineAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.root.RemoveAllProgramsAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.root.ReverseTabTraverseAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.root.ScrollAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.root.SelectAllAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.root.TabTraverseAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.root.TerminateExecutionAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.root.ToggleExpandContractAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.ShowHistoryPaneAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.directorypane.ShowDirectoryPaneAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.loadpane.ShowLoadPaneAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.programpane.ShowProgramPaneAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.savepane.GoToChooseDirectoryStateAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.savepane.GoToSaveStateAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.savepane.MoveDownDirectoryAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.savepane.MoveUpDirectoryAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.savepane.SaveAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.savepane.SelectDirectoryAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.savepane.ShowSavePaneAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.searchpane.GoToResultsStateAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.searchpane.GoToSearchStateAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.searchpane.MoveDownResultsAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.searchpane.MoveUpResultsAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.searchpane.SearchAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.searchpane.SelectResultAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.searchpane.SelectResultAndSelectProgramAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.searchpane.ShowSearchPaneAction;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.states.HistoryState;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.states.RootState;
import uk.ac.ic.doc.kevlar.gui.internal.keyboard.states.State;

/**
 * @author Marc
 **/
public class KeyboardManager implements KeyListener, TraverseListener {

    public static final Item ROOT_STATE_ID = new Item(0);
    public static final Item PROGRAM_AUTO_COMPLETE_STATE_ID = new Item(1);
    public static final Item PROGRAM_ENTRY_AUTO_COMPLETE_STATE_ID = new Item(2);
    public static final Item PROGRAM_SELECTED_STATE_ID = new Item(3);
    public static final Item FIND_AS_YOU_TYPE_STATE_ID = new Item(4);
    public static final Item EDIT_ATTRIBUTE_STATE_ID = new Item(5);
    public static final Item SWING_INPUT_STATE_ID = new Item(6);
    public static final Item DIRECTORY_PANE_STATE_ID = new Item(7);
    public static final Item PROGRAM_PANE_STATE_ID = new Item(8);
    public static final Item SEARCH_PANE_STATE_ID = new Item(9);
    public static final Item HISTORY_PANE_STATE_ID = new Item(10);
    public static final Item LOAD_PANE_STATE_ID = new Item(11);
    public static final Item TEXT_BOX_STATE_ID = new Item(12);
    public static final Item MULTILINE_TEXT_BOX_STATE_ID = new Item(13);
    public static final Item DROP_DOWN_BOX_STATE_ID = new Item(14);
    public static final Item PROGRAM_MULTI_SELECT_STATE_ID = new Item(15);
    public static final Item SEARCH_RESULTS_STATE_ID = new Item(16);
    public static final Item SAVE_PANE_STATE_ID = new Item(17);
    public static final Item SAVE_CHOOSE_DIR_STATE_ID = new Item(18);
    public static final Item HELP_STATE_ID = new Item(19);
    public static final Item OUTPUT_PANE_STATE_ID = new Item(20);
    
    public static final Group TEXT_BOX_STATE_IDS = new Group(PROGRAM_AUTO_COMPLETE_STATE_ID, FIND_AS_YOU_TYPE_STATE_ID, EDIT_ATTRIBUTE_STATE_ID);
    public static final Group AUTO_COMPLETE_STATE_IDS = new Group(PROGRAM_AUTO_COMPLETE_STATE_ID, PROGRAM_ENTRY_AUTO_COMPLETE_STATE_ID);
    
    public static final State ROOT_STATE = new RootState();
    
    private static KeyboardManager singleton;
    private State state;
    
    /* For debugging */
    public static IAction lastAction;
    public static State lastState;
    public static Item lastKey;
    public static Item lastModifiers;
    
    private KeyboardManager() {
        
        KeyBindings.configureCodes();
        
        /* Program auto-complete shown on any alpha-numeric input while in root state */
        KeyBindings.addBinding(ROOT_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ALPHABETIC"), new ShowProgramAutoCompleteAction());
        KeyBindings.addBinding(ROOT_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("ALPHABETIC"), new ShowProgramAutoCompleteAction());
        KeyBindings.addBinding(ROOT_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("NUMERIC"), new ShowProgramAutoCompleteAction());

        /* Currently chosen program can be added by pressing space or enter */
        KeyBindings.addBinding(PROGRAM_AUTO_COMPLETE_STATE_ID, KeyBindings.code("NO_MODIFIER"), new Group(KeyBindings.code("SPACE"), KeyBindings.code("ENTER")), new AddProgramFromAutoCompleteAction());

        /* Currently chosen entry can be selected by pressing space or enter */ 
        KeyBindings.addBinding(PROGRAM_ENTRY_AUTO_COMPLETE_STATE_ID, KeyBindings.code("NO_MODIFIER"), new Group(KeyBindings.code("SPACE"), KeyBindings.code("ENTER")), new SelectProgramEntryAction());
        
        /* Let auto-completes process key presses */
        KeyBindings.addBinding(AUTO_COMPLETE_STATE_IDS, KeyBindings.code("DEFAULT"), KeyBindings.code("DEFAULT"), new EditAutoCompleteAction());
        
        /* Auto-completes can be hidden by pressing escape */
        KeyBindings.addBinding(AUTO_COMPLETE_STATE_IDS, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ESCAPE"), new HidePopUpAction());
        
        /* Execute pipline is CTRL+Enter */
        KeyBindings.addBinding(KeyBindings.code("DEFAULT"), KeyBindings.code("CTRL"), KeyBindings.code("ENTER"), new ExecutePipelineAction());

        /* Terminating execution is CTRL+T */
        KeyBindings.addBinding(KeyBindings.code("DEFAULT"), KeyBindings.code("CTRL"), KeyBindings.code("T"), new TerminateExecutionAction());

        /* Tab traversal */
        KeyBindings.addBinding(new Group(ROOT_STATE_ID,PROGRAM_SELECTED_STATE_ID,PROGRAM_MULTI_SELECT_STATE_ID,FIND_AS_YOU_TYPE_STATE_ID), KeyBindings.code("NO_MODIFIER"), KeyBindings.code("TAB"), new TabTraverseAction());
        KeyBindings.addBinding(new Group(ROOT_STATE_ID,PROGRAM_SELECTED_STATE_ID,PROGRAM_MULTI_SELECT_STATE_ID,FIND_AS_YOU_TYPE_STATE_ID), KeyBindings.code("CTRL"), KeyBindings.code(">"), new TabTraverseAction());
        KeyBindings.addBinding(new Group(ROOT_STATE_ID,PROGRAM_SELECTED_STATE_ID,PROGRAM_MULTI_SELECT_STATE_ID,FIND_AS_YOU_TYPE_STATE_ID), KeyBindings.code("CTRL"), KeyBindings.code("<"), new ReverseTabTraverseAction());
        
        /* Expand/Contract toggle for all/current programs is CTRL+E */ 
        KeyBindings.addBinding(new Group(ROOT_STATE_ID, PROGRAM_SELECTED_STATE_ID), KeyBindings.code("CTRL"), KeyBindings.code("E"), new ToggleExpandContractAction());
        
        /* Remove all programs is CTRL+N */
        KeyBindings.addBinding(KeyBindings.code("DEFAULT"), KeyBindings.code("CTRL"), KeyBindings.code("N"), new RemoveAllProgramsAction());
        
        /* Select all programs is CTRL+A */
        KeyBindings.addBinding(KeyBindings.code("DEFAULT"), KeyBindings.code("CTRL"), KeyBindings.code("A"), new SelectAllAction());
        
        /* Show the History Pane is CTRL+H */
        KeyBindings.addBinding(KeyBindings.code("DEFAULT"), KeyBindings.code("CTRL"), KeyBindings.code("H"), new ShowHistoryPaneAction());
                
        /* Hide the edit attribute box if the user presses escape */
        KeyBindings.addBinding(EDIT_ATTRIBUTE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ESCAPE"), new HideEditAttributeBoxAction());
        
        /* Scroll the window with the cursor keys */
        KeyBindings.addBinding(ROOT_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("UP"), new ScrollAction());
        KeyBindings.addBinding(ROOT_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("DOWN"), new ScrollAction());
        KeyBindings.addBinding(ROOT_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("LEFT"), new ScrollAction());
        KeyBindings.addBinding(ROOT_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("RIGHT"), new ScrollAction());
        
        /* Display debug information */
        KeyBindings.addBinding(KeyBindings.code("DEFAULT"), KeyBindings.code("CTRL"), KeyBindings.code("B"), new DebugKeyManagerAction());
        
        /* Help bindings */
        KeyBindings.addBinding(HELP_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new HideHelpAction());
        KeyBindings.addBinding(HELP_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DEFAULT"), new AllowKeyPressAction());
        
        /* Find as you type bindings */
        KeyBindings.addBinding(new Group(ROOT_STATE_ID, PROGRAM_SELECTED_STATE_ID), KeyBindings.code("CTRL"), KeyBindings.code("F"), new ShowFindAsYouTypeAction());   

        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ESCAPE"), new HideFindAsYouTypeAction());   
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SPACE"), new HideFindAsYouTypeAction());   
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ENTER"), new HideFindAsYouTypeAction());   
        
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new GoToHistoryStateAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("BACKSPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.BackspaceAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DELETE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.DeleteAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("END"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.EndAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("HOME"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.HomeAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.MoveCaretLeftAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.MoveCaretRightAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, new Group(KeyBindings.code("CTRL"), KeyBindings.code("CTRL_ALT")), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.MoveCaretWordLeftAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, new Group(KeyBindings.code("CTRL"), KeyBindings.code("CTRL_ALT")), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.MoveCaretWordRightAction());

        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("END"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionEndAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("HOME"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionHomeAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionMoveCaretLeftAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionMoveCaretRightAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("CTRL_SHIFT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionMoveCaretWordLeftAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("CTRL_SHIFT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionMoveCaretWordRightAction());
        
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("C"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.CopyAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("X"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.CutAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("V"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.PasteAction());

        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ALPHABETIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("ALPHABETIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("NUMERIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("NUMERIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SYMBOLIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("SYMBOLIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());

        KeyBindings.addBinding(KeyBindings.code("RELEASED"), FIND_AS_YOU_TYPE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("SHIFT_KEY"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.EndSelectAction());        
        
        /* Output pane bindings */
        KeyBindings.addBinding(KeyBindings.code("DEFAULT"), KeyBindings.code("CTRL"), KeyBindings.code("O"), new ShowOutputPaneAction());
        KeyBindings.addBinding(OUTPUT_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("DELETE"), new RemoveTabAction());
        KeyBindings.addBinding(OUTPUT_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("LEFT"), new MoveSelectedShowTabAction(-1));
        KeyBindings.addBinding(OUTPUT_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("RIGHT"), new MoveSelectedShowTabAction(1));        
        KeyBindings.addBinding(OUTPUT_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("UP"), new ResizeUpOutputPaneAction());
        KeyBindings.addBinding(OUTPUT_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("DOWN"), new ResizeDownOutputPaneAction());        
                
        /* Show the Program Pane is CTRL+P */
        KeyBindings.addBinding(KeyBindings.code("DEFAULT"), KeyBindings.code("CTRL"), KeyBindings.code("P"), new ShowProgramPaneAction());
        KeyBindings.addBinding(PROGRAM_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new GoToHistoryStateAction());
        KeyBindings.addBinding(PROGRAM_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("UP"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.programpane.MoveUpAction());
        KeyBindings.addBinding(PROGRAM_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DOWN"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.programpane.MoveDownAction());
        KeyBindings.addBinding(PROGRAM_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.programpane.SelectAction());
        KeyBindings.addBinding(PROGRAM_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ENTER"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.programpane.SelectAndSelectProgramAction());
                
        /* Show the Load Pane is CTRL+L */
        KeyBindings.addBinding(KeyBindings.code("DEFAULT"), KeyBindings.code("CTRL"), KeyBindings.code("L"), new ShowLoadPaneAction());
        KeyBindings.addBinding(LOAD_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new GoToHistoryStateAction());
        KeyBindings.addBinding(LOAD_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("UP"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.loadpane.MoveUpAction());
        KeyBindings.addBinding(LOAD_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DOWN"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.loadpane.MoveDownAction());
        KeyBindings.addBinding(LOAD_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.loadpane.SelectAction());
        KeyBindings.addBinding(LOAD_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ENTER"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.loadpane.SelectAndContractAction());
                
        /* Save pane bindings */
        KeyBindings.addBinding(KeyBindings.code("DEFAULT"), KeyBindings.code("CTRL"), KeyBindings.code("S"), new ShowSavePaneAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("TAB"), new GoToChooseDirectoryStateAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ENTER"), new SaveAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new GoToHistoryStateAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("BACKSPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.BackspaceAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DELETE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.DeleteAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("END"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.EndAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("HOME"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.HomeAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.MoveCaretLeftAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.MoveCaretRightAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, new Group(KeyBindings.code("CTRL"), KeyBindings.code("CTRL_ALT")), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.MoveCaretWordLeftAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, new Group(KeyBindings.code("CTRL"), KeyBindings.code("CTRL_ALT")), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.MoveCaretWordRightAction());

        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("END"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionEndAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("HOME"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionHomeAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionMoveCaretLeftAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionMoveCaretRightAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("CTRL_SHIFT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionMoveCaretWordLeftAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("CTRL_SHIFT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionMoveCaretWordRightAction());
        
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("C"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.CopyAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("X"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.CutAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("V"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.PasteAction());

        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ALPHABETIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("ALPHABETIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("NUMERIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("NUMERIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SYMBOLIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("SYMBOLIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(SAVE_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());

        KeyBindings.addBinding(KeyBindings.code("RELEASED"), SAVE_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("SHIFT_KEY"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.EndSelectAction());
        
        /* Choose directory bindings */
        KeyBindings.addBinding(SAVE_CHOOSE_DIR_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new GoToHistoryStateAction());
        KeyBindings.addBinding(SAVE_CHOOSE_DIR_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ENTER"), new SelectDirectoryAction());
        KeyBindings.addBinding(SAVE_CHOOSE_DIR_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("SPACE"), new SelectDirectoryAction());
        KeyBindings.addBinding(SAVE_CHOOSE_DIR_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("TAB"), new GoToSaveStateAction());
        KeyBindings.addBinding(SAVE_CHOOSE_DIR_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("UP"), new MoveUpDirectoryAction());
        KeyBindings.addBinding(SAVE_CHOOSE_DIR_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DOWN"), new MoveDownDirectoryAction());
        
        /* Directory pane bindings */
        KeyBindings.addBinding(KeyBindings.code("DEFAULT"), KeyBindings.code("CTRL"), KeyBindings.code("D"), new ShowDirectoryPaneAction());
        KeyBindings.addBinding(DIRECTORY_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new GoToHistoryStateAction());
        KeyBindings.addBinding(DIRECTORY_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("UP"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.directorypane.MoveUpAction());
        KeyBindings.addBinding(DIRECTORY_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DOWN"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.directorypane.MoveDownAction());
        KeyBindings.addBinding(DIRECTORY_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.directorypane.SelectAction());
        KeyBindings.addBinding(DIRECTORY_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ENTER"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.taskpane.directorypane.SelectAction());
                
        /* Search pane bindings */
        KeyBindings.addBinding(KeyBindings.code("DEFAULT"), KeyBindings.code("ALT"), KeyBindings.code("S"), new ShowSearchPaneAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("TAB"), new GoToResultsStateAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ENTER"), new SearchAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new GoToHistoryStateAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("BACKSPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.BackspaceAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DELETE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.DeleteAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("END"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.EndAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("HOME"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.HomeAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("END"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.CtrlEndAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("HOME"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.CtrlHomeAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("UP"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.MoveCaretUpAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DOWN"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.MoveCaretDownAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.MoveCaretLeftAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.MoveCaretRightAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, new Group(KeyBindings.code("CTRL"), KeyBindings.code("CTRL_ALT")), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.MoveCaretWordLeftAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, new Group(KeyBindings.code("CTRL"), KeyBindings.code("CTRL_ALT")), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.MoveCaretWordRightAction());
        
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("END"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionEndAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("HOME"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionHomeAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("UP"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionMoveCaretUpAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("DOWN"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionMoveCaretDownAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionMoveCaretLeftAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionMoveCaretRightAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("CTRL_SHIFT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionMoveCaretWordLeftAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("CTRL_SHIFT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionMoveCaretWordRightAction());
        
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("C"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.CopyAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("X"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.CutAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("V"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.PasteAction());

        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ALPHABETIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("ALPHABETIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("NUMERIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("NUMERIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SYMBOLIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("SYMBOLIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(SEARCH_PANE_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
                
        /* Search results bindings */
        KeyBindings.addBinding(SEARCH_RESULTS_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new GoToHistoryStateAction());
        KeyBindings.addBinding(SEARCH_RESULTS_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("SPACE"), new SelectResultAction());
        KeyBindings.addBinding(SEARCH_RESULTS_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ENTER"), new SelectResultAndSelectProgramAction());
        KeyBindings.addBinding(SEARCH_RESULTS_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("TAB"), new GoToSearchStateAction());
        KeyBindings.addBinding(SEARCH_RESULTS_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("UP"), new MoveUpResultsAction());
        KeyBindings.addBinding(SEARCH_RESULTS_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DOWN"), new MoveDownResultsAction());
        
        /* Multi select bindings */
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.ClearAction());        
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ENTER"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.ClearAction());        
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("UP"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.ShiftUpAction());        
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DOWN"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.ShiftDownAction());        
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.ShiftLeftAction());        
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.ShiftRightAction());        
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("BACKSPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.DeleteAction());        
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DELETE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.DeleteAction());        
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("E"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.ToggleExpandContractAction());        
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("M"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.CreateMacroAction());        
    
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.PassToProgramAction());        
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ALPHABETIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.PassToProgramAction());
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("ALPHABETIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.PassToProgramAction());
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("NUMERIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.PassToProgramAction());
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("NUMERIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.PassToProgramAction());
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SYMBOLIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.PassToProgramAction());
        KeyBindings.addBinding(PROGRAM_MULTI_SELECT_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("SYMBOLIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.programmultiselect.PassToProgramAction());
        
        /* Program bindings */
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.program.DeselectAction());        
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ENTER"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.program.DeselectAction());        
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("UP"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.program.ShiftUpAction());        
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DOWN"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.program.ShiftDownAction());        
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.program.ShiftLeftAction());        
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.program.ShiftRightAction());        
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.program.ToggleMultiSelectAction());        
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("BACKSPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.program.RemoveAction());        
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DELETE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.program.RemoveAction());        
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("E"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.program.ToggleExpandContractAction());        
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("H"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.program.DisplayHelpAction());        
    
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ALPHABETIC"), new ShowProgramEntryAutoCompleteAction());
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("ALPHABETIC"), new ShowProgramEntryAutoCompleteAction());
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("NUMERIC"), new ShowProgramEntryAutoCompleteAction());
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("NUMERIC"), new ShowProgramEntryAutoCompleteAction());
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SYMBOLIC"), new ShowProgramEntryAutoCompleteAction());
        KeyBindings.addBinding(PROGRAM_SELECTED_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("SYMBOLIC"), new ShowProgramEntryAutoCompleteAction());
        
        /* Drop down box bindings */
        KeyBindings.addBinding(DROP_DOWN_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new GoToHistoryStateAction());
        KeyBindings.addBinding(DROP_DOWN_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ENTER"), new GoToHistoryStateAction());
        KeyBindings.addBinding(DROP_DOWN_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("UP"), new UpAction());
        KeyBindings.addBinding(DROP_DOWN_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DOWN"), new DownAction());
        
        /* Multiline text box bindings */
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new GoToHistoryStateAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ENTER"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertNewlineAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("BACKSPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.BackspaceAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DELETE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.DeleteAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("END"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.EndAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("HOME"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.HomeAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("END"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.CtrlEndAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("HOME"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.CtrlHomeAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("UP"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.MoveCaretUpAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DOWN"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.MoveCaretDownAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.MoveCaretLeftAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.MoveCaretRightAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, new Group(KeyBindings.code("CTRL"), KeyBindings.code("CTRL_ALT")), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.MoveCaretWordLeftAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, new Group(KeyBindings.code("CTRL"), KeyBindings.code("CTRL_ALT")), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.MoveCaretWordRightAction());
        
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("END"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionEndAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("HOME"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionHomeAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("UP"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionMoveCaretUpAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("DOWN"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionMoveCaretDownAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionMoveCaretLeftAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionMoveCaretRightAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("CTRL_SHIFT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionMoveCaretWordLeftAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("CTRL_SHIFT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.SelectionMoveCaretWordRightAction());
        
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("C"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.CopyAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("X"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.CutAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("V"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.PasteAction());

        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ALPHABETIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("ALPHABETIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("NUMERIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("NUMERIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SYMBOLIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("SYMBOLIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());
        KeyBindings.addBinding(MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.InsertAction());

        KeyBindings.addBinding(KeyBindings.code("RELEASED"), MULTILINE_TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("SHIFT_KEY"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.multilinetextbox.EndSelectAction());
        
        /* Text box bindings */
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ENTER"), new GoToHistoryStateAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("ESCAPE"), new GoToHistoryStateAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("BACKSPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.BackspaceAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("DELETE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.DeleteAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("END"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.EndAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("HOME"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.HomeAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.MoveCaretLeftAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.MoveCaretRightAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, new Group(KeyBindings.code("CTRL"), KeyBindings.code("CTRL_ALT")), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.MoveCaretWordLeftAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, new Group(KeyBindings.code("CTRL"), KeyBindings.code("CTRL_ALT")), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.MoveCaretWordRightAction());

        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("END"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionEndAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("HOME"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionHomeAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionMoveCaretLeftAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionMoveCaretRightAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("CTRL_SHIFT"), KeyBindings.code("LEFT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionMoveCaretWordLeftAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("CTRL_SHIFT"), KeyBindings.code("RIGHT"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.SelectionMoveCaretWordRightAction());
        
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("C"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.CopyAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("X"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.CutAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("CTRL"), KeyBindings.code("V"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.PasteAction());

        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("ALPHABETIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("ALPHABETIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("NUMERIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("NUMERIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SYMBOLIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("SYMBOLIC"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("NO_MODIFIER"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());
        KeyBindings.addBinding(TEXT_BOX_STATE_ID, KeyBindings.code("SHIFT"), KeyBindings.code("SPACE"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.InsertAction());

        KeyBindings.addBinding(KeyBindings.code("RELEASED"), TEXT_BOX_STATE_ID, KeyBindings.code("DEFAULT"), KeyBindings.code("SHIFT_KEY"), new uk.ac.ic.doc.kevlar.gui.internal.keyboard.actions.textbox.EndSelectAction());
        
        state = ROOT_STATE;
        
    }
    
    public static void createSingleton() {
        
        if (singleton == null) {
            
            singleton = new KeyboardManager();
            
        }
        
    }
    
    public static KeyboardManager getSingleton() {
        
        return singleton;
        
    }
    
    public State getState() {
        
        return state;
        
    }

    public void setState(State state) {
        
        if (this.state != null) {
            
            this.state.onExit();
            
        }
        
        this.state = state;
        this.state.onEnter();
//        System.err.println("State set to "+state.getClass().getName());
        
    }
    
    public void gotoHistoryState() {
        
        if (state instanceof HistoryState) {
            
            setState(((HistoryState)state).getHistory());
            
        }
        
    }
    
    /* (non-Javadoc)
     * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
     */
    public void keyPressed(KeyEvent arg0) {

        boolean shift = (arg0.stateMask & SWT.SHIFT) == SWT.SHIFT;
        boolean ctrl = (arg0.stateMask & SWT.CTRL) == SWT.CTRL;
        boolean alt = (arg0.stateMask & SWT.ALT) == SWT.ALT;
        Item modifiers = KeyBindings.code("NO_MODIFIER");
        
        if (ctrl && alt && shift) {
            
            modifiers = KeyBindings.code("CTRL_ALT_SHIFT");
            
        } else if (ctrl && alt) {
            
            modifiers = KeyBindings.code("CTRL_ALT");
            
        } else if (ctrl && shift) {
            
            modifiers = KeyBindings.code("CTRL_SHIFT");
            
        } else if (alt && shift) {
            
            modifiers = KeyBindings.code("ALT_SHIFT");
            
        } else if (ctrl) {
            
            modifiers = KeyBindings.code("CTRL");
            
        } else if (alt) {
            
            modifiers = KeyBindings.code("ALT");
            
        } else if (shift) {
            
            modifiers = KeyBindings.code("SHIFT");
            
        }
        
//        System.err.println("Got key "+KeyBindings.name(new Item(arg0.keyCode))+" with character "+arg0.character+" and modifiers "+KeyBindings.name(modifiers));
        
        IAction action = KeyBindings.getBinding(KeyBindings.code("PRESSED"), getState().getStateItem(), modifiers, new Item(arg0.keyCode));
        
        if (action != null) {
        
            if (!(action instanceof DebugKeyManagerAction)) {
            
                lastState = getState();
                
            }
            
            if (Kevlar.DEBUG) {
                            
                System.err.println("Executing action "+action.getClass().getName());
                
            }
            
            arg0.doit = action.perform(KeyBindings.code("PRESSED"), getState(), arg0);
            lastAction = action;
            lastKey = new Item(arg0.keyCode);
            lastModifiers = modifiers;
                                
        } else {
            
            arg0.doit = false;
            
        }
        
    }

    /* (non-Javadoc)
     * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
     */
    public void keyReleased(KeyEvent arg0) {

        boolean shift = (arg0.stateMask & SWT.SHIFT) == SWT.SHIFT;
        boolean ctrl = (arg0.stateMask & SWT.CTRL) == SWT.CTRL;
        boolean alt = (arg0.stateMask & SWT.ALT) == SWT.ALT;
        Item modifiers = KeyBindings.code("NO_MODIFIER");
        
        if (ctrl && alt && shift) {
            
            modifiers = KeyBindings.code("CTRL_ALT_SHIFT");
            
        } else if (ctrl && alt) {
            
            modifiers = KeyBindings.code("CTRL_ALT");
            
        } else if (ctrl && shift) {
            
            modifiers = KeyBindings.code("CTRL_SHIFT");
            
        } else if (alt && shift) {
            
            modifiers = KeyBindings.code("ALT_SHIFT");
            
        } else if (ctrl) {
            
            modifiers = KeyBindings.code("CTRL");
            
        } else if (alt) {
            
            modifiers = KeyBindings.code("ALT");
            
        } else if (shift) {
            
            modifiers = KeyBindings.code("SHIFT");
            
        }
        
        IAction action = KeyBindings.getBinding(KeyBindings.code("RELEASED"), getState().getStateItem(), modifiers, new Item(arg0.keyCode));
        
        if (action != null) {
        
            if (!(action instanceof DebugKeyManagerAction)) {
            
                lastState = getState();
                
            }

            if (Kevlar.DEBUG) {
            
                System.err.println("Executing action "+action.getClass().getName());
                
            }
            
            arg0.doit = action.perform(KeyBindings.code("RELEASED"), getState(), arg0);
            lastAction = action;
            lastKey = new Item(arg0.keyCode);
            lastModifiers = modifiers;
                                
        } else {
            
            arg0.doit = false;
            
        }
                
    }

    public void keyTraversed(TraverseEvent arg0) {
        
//        keyPressed(arg0);
        arg0.doit = false;
        
    }

}
