text: import {mxUtils} from '@js/mxDependencies.js';
  import {mxEvent} from '@js/mxDependencies.js';
  import {mxClient} from '@js/mxDependencies.js';
  /**
   * Copyright (c) 2006-2015, JGraph Ltd
   * Copyright (c) 2006-2015, Gaudenz Alder
   */
  /**
   * Class: mxKeyHandler
   *
   * Event handler that listens to keystroke events. This is not a singleton,
   * however, it is normally only required once if the target is the document
   * element (default).
   * 
   * This handler installs a key event listener in the topmost DOM node and
   * processes all events that originate from descandants of <mxGraph.container>
   * or from the topmost DOM node. The latter means that all unhandled keystrokes
   * are handled by this object regardless of the focused state of the <graph>.
   * 
   * Example:
   * 
   * The following example creates a key handler that listens to the delete key
   * (46) and deletes the selection cells if the graph is enabled.
   * 
   * (code)
   * var keyHandler = new mxKeyHandler(graph);
   * keyHandler.bindKey(46, function(evt)
   * {
   *   if (graph.isEnabled())
   *   {
   *     graph.removeCells();
   *   }
   * });
   * (end)
   * 
   * Keycodes:
   * 
   * See http://tinyurl.com/yp8jgl or http://tinyurl.com/229yqw for a list of
   * keycodes or install a key event listener into the document element and print
   * the key codes of the respective events to the console.
   * 
   * To support the Command key and the Control key on the Mac, the following
   * code can be used.
   *
   * (code)
   * keyHandler.getFunction = function(evt)
   * {
   *   if (evt != null)
   *   {
   *     return (mxEvent.isControlDown(evt) || (mxClient.IS_MAC && evt.metaKey)) ? this.controlKeys[evt.keyCode] : this.normalKeys[evt.keyCode];
   *   }
   *   
   *   return null;
   * };
   * (end)
   * 
   * Constructor: mxKeyHandler
   *
   * Constructs an event handler that executes functions bound to specific
   * keystrokes.
   * 
   * Parameters:
   * 
   * graph - Reference to the associated <mxGraph>.
   * target - Optional reference to the event target. If null, the document
   * element is used as the event target, that is, the object where the key
   * event listener is installed.
   */
  function mxKeyHandler(graph, target)
  {
  	if (graph != null)
  	{
  		this.graph = graph;
  		this.target = target || document.documentElement;
  		
  		// Creates the arrays to map from keycodes to functions
  		this.normalKeys = [];
  		this.shiftKeys = [];
  		this.controlKeys = [];
  		this.controlShiftKeys = [];
  		
  		this.keydownHandler = mxUtils.bind(this, function(evt)
  		{
  			this.keyDown(evt);
  		});
  
  		// Installs the keystroke listener in the target
  		mxEvent.addListener(this.target, 'keydown', this.keydownHandler);
  		
  		// Automatically deallocates memory in IE
  		if (mxClient.IS_IE)
  		{
  			mxEvent.addListener(window, 'unload',
  				mxUtils.bind(this, function()
  				{
  					this.destroy();
  				})
  			);
  		}
  	}
  };
  
  /**
   * Variable: graph
   * 
   * Reference to the <mxGraph> associated with this handler.
   */
  mxKeyHandler.prototype.graph = null;
  
  /**
   * Variable: target
   * 
   * Reference to the target DOM, that is, the DOM node where the key event
   * listeners are installed.
   */
  mxKeyHandler.prototype.target = null;
  
  /**
   * Variable: normalKeys
   * 
   * Maps from keycodes to functions for non-pressed control keys.
   */
  mxKeyHandler.prototype.normalKeys = null;
  
  /**
   * Variable: shiftKeys
   * 
   * Maps from keycodes to functions for pressed shift keys.
   */
  mxKeyHandler.prototype.shiftKeys = null;
  
  /**
   * Variable: controlKeys
   * 
   * Maps from keycodes to functions for pressed control keys.
   */
  mxKeyHandler.prototype.controlKeys = null;
  
  /**
   * Variable: controlShiftKeys
   * 
   * Maps from keycodes to functions for pressed control and shift keys.
   */
  mxKeyHandler.prototype.controlShiftKeys = null;
  
  /**
   * Variable: enabled
   * 
   * Specifies if events are handled. Default is true.
   */
  mxKeyHandler.prototype.enabled = true;
  
  /**
   * Function: isEnabled
   * 
   * Returns true if events are handled. This implementation returns
   * <enabled>.
   */
  mxKeyHandler.prototype.isEnabled = function()
  {
  	return this.enabled;
  };
  
  /**
   * Function: setEnabled
   * 
   * Enables or disables event handling by updating <enabled>.
   * 
   * Parameters:
   * 
   * enabled - Boolean that specifies the new enabled state.
   */
  mxKeyHandler.prototype.setEnabled = function(enabled)
  {
  	this.enabled = enabled;
  };
  
  /**
   * Function: bindKey
   * 
   * Binds the specified keycode to the given function. This binding is used
   * if the control key is not pressed.
   * 
   * Parameters:
   *
   * code - Integer that specifies the keycode.
   * funct - JavaScript function that takes the key event as an argument.
   */
  mxKeyHandler.prototype.bindKey = function(code, funct)
  {
  	this.normalKeys[code] = funct;
  };
  
  /**
   * Function: bindShiftKey
   * 
   * Binds the specified keycode to the given function. This binding is used
   * if the shift key is pressed.
   * 
   * Parameters:
   *
   * code - Integer that specifies the keycode.
   * funct - JavaScript function that takes the key event as an argument.
   */
  mxKeyHandler.prototype.bindShiftKey = function(code, funct)
  {
  	this.shiftKeys[code] = funct;
  };
  
  /**
   * Function: bindControlKey
   * 
   * Binds the specified keycode to the given function. This binding is used
   * if the control key is pressed.
   * 
   * Parameters:
   *
   * code - Integer that specifies the keycode.
   * funct - JavaScript function that takes the key event as an argument.
   */
  mxKeyHandler.prototype.bindControlKey = function(code, funct)
  {
  	this.controlKeys[code] = funct;
  };
  
  /**
   * Function: bindControlShiftKey
   * 
   * Binds the specified keycode to the given function. This binding is used
   * if the control and shift key are pressed.
   * 
   * Parameters:
   *
   * code - Integer that specifies the keycode.
   * funct - JavaScript function that takes the key event as an argument.
   */
  mxKeyHandler.prototype.bindControlShiftKey = function(code, funct)
  {
  	this.controlShiftKeys[code] = funct;
  };
  
  /**
   * Function: isControlDown
   * 
   * Returns true if the control key is pressed. This uses <mxEvent.isControlDown>.
   * 
   * Parameters:
   * 
   * evt - Key event whose control key pressed state should be returned.
   */
  mxKeyHandler.prototype.isControlDown = function(evt)
  {
  	return mxEvent.isControlDown(evt);
  };
  
  /**
   * Function: getFunction
   * 
   * Returns the function associated with the given key event or null if no
   * function is associated with the given event.
   * 
   * Parameters:
   * 
   * evt - Key event whose associated function should be returned.
   */
  mxKeyHandler.prototype.getFunction = function(evt)
  {
  	if (evt != null && !mxEvent.isAltDown(evt))
  	{
  		if (this.isControlDown(evt))
  		{
  			if (mxEvent.isShiftDown(evt))
  			{
  				return this.controlShiftKeys[evt.keyCode];
  			}
  			else
  			{
  				return this.controlKeys[evt.keyCode];
  			}
  		}
  		else
  		{
  			if (mxEvent.isShiftDown(evt))
  			{
  				return this.shiftKeys[evt.keyCode];
  			}
  			else
  			{
  				return this.normalKeys[evt.keyCode];
  			}
  		}
  	}
  	
  	return null;
  };
  	
  /**
   * Function: isGraphEvent
   * 
   * Returns true if the event should be processed by this handler, that is,
   * if the event source is either the target, one of its direct children, a
   * descendant of the <mxGraph.container>, or the <mxGraph.cellEditor> of the
   * <graph>.
   * 
   * Parameters:
   * 
   * evt - Key event that represents the keystroke.
   */
  mxKeyHandler.prototype.isGraphEvent = function(evt)
  {
  	var source = mxEvent.getSource(evt);
  	
  	// Accepts events from the target object or
  	// in-place editing inside graph
  	if ((source == this.target || source.parentNode == this.target) ||
  		(this.graph.cellEditor != null && this.graph.cellEditor.isEventSource(evt)))
  	{
  		return true;
  	}
  	
  	// Accepts events from inside the container
  	return mxUtils.isAncestorNode(this.graph.container, source);
  };
  
  /**
   * Function: keyDown
   * 
   * Handles the event by invoking the function bound to the respective keystroke
   * if <isEnabledForEvent> returns true for the given event and if
   * <isEventIgnored> returns false, except for escape for which
   * <isEventIgnored> is not invoked.
   * 
   * Parameters:
   * 
   * evt - Key event that represents the keystroke.
   */
  mxKeyHandler.prototype.keyDown = function(evt)
  {
  	if (this.isEnabledForEvent(evt))
  	{
  		// Cancels the editing if escape is pressed
  		if (evt.keyCode == 27 /* Escape */)
  		{
  			this.escape(evt);
  		}
  		
  		// Invokes the function for the keystroke
  		else if (!this.isEventIgnored(evt))
  		{
  			var boundFunction = this.getFunction(evt);
  			
  			if (boundFunction != null)
  			{
  				boundFunction(evt);
  				mxEvent.consume(evt);
  			}
  		}
  	}
  };
  
  /**
   * Function: isEnabledForEvent
   * 
   * Returns true if the given event should be handled. <isEventIgnored> is
   * called later if the event is not an escape key stroke, in which case
   * <escape> is called. This implementation returns true if <isEnabled>
   * returns true for both, this handler and <graph>, if the event is not
   * consumed and if <isGraphEvent> returns true.
   * 
   * Parameters:
   * 
   * evt - Key event that represents the keystroke.
   */
  mxKeyHandler.prototype.isEnabledForEvent = function(evt)
  {
  	return (this.graph.isEnabled() && !mxEvent.isConsumed(evt) &&
  		this.isGraphEvent(evt) && this.isEnabled());
  };
  
  /**
   * Function: isEventIgnored
   * 
   * Returns true if the given keystroke should be ignored. This returns
   * graph.isEditing().
   * 
   * Parameters:
   * 
   * evt - Key event that represents the keystroke.
   */
  mxKeyHandler.prototype.isEventIgnored = function(evt)
  {
  	return this.graph.isEditing();
  };
  
  /**
   * Function: escape
   * 
   * Hook to process ESCAPE keystrokes. This implementation invokes
   * <mxGraph.stopEditing> to cancel the current editing, connecting
   * and/or other ongoing modifications.
   * 
   * Parameters:
   * 
   * evt - Key event that represents the keystroke. Possible keycode in this
   * case is 27 (ESCAPE).
   */
  mxKeyHandler.prototype.escape = function(evt)
  {
  	if (this.graph.isEscapeEnabled())
  	{
  		this.graph.escape(evt);
  	}
  };
  
  /**
   * Function: destroy
   * 
   * Destroys the handler and all its references into the DOM. This does
   * normally not need to be called, it is called automatically when the
   * window unloads (in IE).
   */
  mxKeyHandler.prototype.destroy = function()
  {
  	if (this.target != null && this.keydownHandler != null)
  	{
  		mxEvent.removeListener(this.target, 'keydown', this.keydownHandler);
  		this.keydownHandler = null;
  	}
  	
  	this.target = null;
  };
  export {
  mxKeyHandler,
  };