/*******************************************************************************
* 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.gef;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.jface.action.IAction;
/**
* The KeyHandler should handle all normal keystrokes on an <code>EditPartViewer</code>.
* <I>Normal</i> is simply defined as keystrokes which are not associated with an
* Accelerator on the Menu. The KeyHandler will be forwarded KeyEvents by the active Tool,
* which is usually the SelectionTool. The Tool may be in a state where keystrokes should
* not be processed, in which case it will not forward the keystrokes. For this reason,
* it is important to always handle KeyEvents by using a KeyHandler.
* <P>
* KeyHandlers can be chained by calling {@link #setParent(KeyHandler)}. If this
* KeyHandler does not handle the keystroke, it will pass the keystroke to its
* <i>parent</i> KeyHandler.
* <P>
* KeyHandlers can be implemented using two stragegies. One is to map {@link KeyStroke
* KeyStrokes} to {@link org.eclipse.jface.action.IAction Actions} using the {@link
* #put(KeyStroke, IAction)} and {@link #remove(KeyStroke)} API. The other is to subclass
* KeyHandler, and override various methods. A combination of the two is also useful.
* @since 2.0
*/
public class KeyHandler {
private Map actions;
private KeyHandler parent;
/**
* Processes a <i>key pressed</i> event. This method is called by the Tool whenever a key
* is pressed, and the Tool is in the proper state.
* @param event the KeyEvent
* @return <code>true</code> if KeyEvent was handled in some way
*/
public boolean keyPressed(KeyEvent event) {
if (performStroke(new KeyStroke(event, true))) {
event.doit = false;
return true;
}
return parent != null && parent.keyPressed(event);
}
/**
* Processes a <i>key released</i> event. This method is called by the Tool whenever a key
* is released, and the Tool is in the proper state.
* @param event the KeyEvent
* @return <code>true</code> if KeyEvent was handled in some way
*/
public boolean keyReleased(KeyEvent event) {
if (performStroke(new KeyStroke(event, false)))
return true;
return parent != null && parent.keyReleased(event);
}
private boolean performStroke(KeyStroke key) {
if (actions == null)
return false;
IAction action = (IAction)actions.get(key);
if (action == null)
return false;
if (action.isEnabled())
action.run();
return true;
}
/**
* Maps a specified <code>KeyStroke</code> to an <code>IAction</code>. When a KeyEvent
* occurs matching the given KeyStroke, the Action will be <code>run()</code> iff it is
* enabled.
* @param keystroke the KeyStroke
* @param action the Action to run
*/
public void put(KeyStroke keystroke, IAction action) {
if (actions == null)
actions = new HashMap();
actions.put(keystroke, action);
}
/**
* Removed a mapped <code>IAction</code> for the specified <code>KeyStroke</code>.
* @param keystroke the KeyStroke to be unmapped
*/
public void remove(KeyStroke keystroke) {
if (actions != null)
actions.remove(keystroke);
}
/**
* Sets a <i>parent</i> <code>KeyHandler</code> to which this KeyHandler will forward
* un-consumed KeyEvents. This KeyHandler will first attempt to handle KeyEvents. If it
* does not recognize a given KeyEvent, that event is passed to its <i>parent</i>
* @param parent the <i>parent</i> KeyHandler
* @return <code>this</code> for convenience
*/
public KeyHandler setParent(KeyHandler parent) {
this.parent = parent;
return this;
}
}