⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eoskeyhandler.java

📁 对eclipse gef进行封装,可以生成图形化编辑器
💻 JAVA
字号:
/*******************************************************************************
 * $Header: /cvsroot/EOS6/work_dir/niegy/com.primeton.studio.gef.ui/src/com/primeton/studio/gef/ui/editor/EosKeyHandler.java,v 1.2 2006/12/05 05:18:59 niegy Exp $
 * $Revision: 1.2 $
 * $Date: 2006/12/05 05:18:59 $
 *
 *==============================================================================
 *
 * Copyright (c) 2001-2006 Primeton Technologies, Ltd.
 * All rights reserved. 
 * 
 * Created on 2006-9-27
 *******************************************************************************/


package com.primeton.studio.gef.ui.editor;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.ConnectionEditPart;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.KeyHandler;
import org.eclipse.gef.KeyStroke;
import org.eclipse.jface.action.IAction;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;

/**
 * TODO此处填写 class 信息
 *
 * @author niegy (mailto:niegy@primeton.com)
 */
/*
 * 修改历史
 * $Log: EosKeyHandler.java,v $
 * Revision 1.2  2006/12/05 05:18:59  niegy
 * 修改模型,增加连线的扩展点
 *
 * Revision 1.1  2006/11/17 03:15:13  niegy
 * create
 * 
 */
public class EosKeyHandler extends KeyHandler {
	int counter;

	/**
	 * When navigating through connections, a "Node" EditPart is used as a reference.
	 */
	private WeakReference cachedNode;
	private GraphicalViewer viewer;

	/**
	 * Constructs a key handler for the given viewer.
	 * @param viewer the viewer
	 */
	public EosKeyHandler(GraphicalViewer viewer) {
		this.viewer = viewer;
	}

	/**
	 * @return	<code>true</code> if key pressed indicates a connection traversal/selection
	 */
	boolean acceptConnection(KeyEvent event) {
		return event.character == '/'
			|| event.character == '?'
			|| event.character == '\\'
			|| event.character == '\u001c'
			|| event.character == '|';
	}

	/**
	 * @return	<code>true</code> if the keys pressed indicate to traverse inside a container
	 */
	boolean acceptIntoContainer(KeyEvent event) {
		return ((event.stateMask & SWT.ALT) != 0) && (event.keyCode == SWT.ARROW_DOWN);
	}

	/**
	 * @return	<code>true</code> if the keys pressed indicate to stop traversing/selecting
	 * 			connection
	 */
	boolean acceptLeaveConnection(KeyEvent event) {
		int key = event.keyCode;
		if (getFocusEditPart() instanceof ConnectionEditPart)
			if ((key == SWT.ARROW_UP)
			  || (key == SWT.ARROW_RIGHT)
			  || (key == SWT.ARROW_DOWN)
			  || (key == SWT.ARROW_LEFT))
				return true;
		return false;
	}

	/**
	 * @return	<code>true</code> if the viewer's contents has focus and one of the arrow
	 * 			keys is pressed
	 */
	boolean acceptLeaveContents(KeyEvent event) {
		int key = event.keyCode;
		return getFocusEditPart() == getViewer().getContents()
			&& ((key == SWT.ARROW_UP)
				|| (key == SWT.ARROW_RIGHT)
				|| (key == SWT.ARROW_DOWN)
				|| (key == SWT.ARROW_LEFT));
	}

	/**
	 * @return	<code>true</code> if the keys pressed indicate to traverse to the parent of
	 * 			the currently focused EditPart
	 */
	boolean acceptOutOf(KeyEvent event) {
		return ((event.stateMask & SWT.ALT) != 0) && (event.keyCode == SWT.ARROW_UP);
	}

	boolean acceptScroll(KeyEvent event) {
		return ((event.stateMask & SWT.CTRL) != 0 && (event.stateMask & SWT.SHIFT) != 0 
				&& (event.keyCode == SWT.ARROW_DOWN || event.keyCode == SWT.ARROW_LEFT
				|| event.keyCode == SWT.ARROW_RIGHT || event.keyCode == SWT.ARROW_UP));
	}

	/**
	 * Given a connection on a node, this method finds the next (or the previous) connection
	 * of that node.
	 * 
	 * @param	node	The EditPart whose connections are being traversed
	 * @param	current	The connection relative to which the next connection has to be found
	 * @param	forward	<code>true</code> if the next connection has to be found; false otherwise
	 */
	ConnectionEditPart findConnection(GraphicalEditPart node, 
	                                            ConnectionEditPart current, boolean forward) {
		List connections = new ArrayList(node.getSourceConnections());
		connections.addAll(node.getTargetConnections());
		if (connections.isEmpty())
			return null;
		if (forward)
			counter++;
		else
			counter--;
		while (counter < 0)
			counter += connections.size();
		counter %= connections.size();
		return (ConnectionEditPart)connections.get(counter % connections.size());
	}

	/**
	 * Given an absolute point (pStart) and a list of EditParts, this method finds the closest
	 * EditPart (except for the one to be excluded) in the given direction.
	 * 
	 * @param	siblings	List of sibling EditParts
	 * @param	pStart		The starting point (must be in absolute coordinates) from which
	 * 						the next sibling is to be found.
	 * @param	direction	PositionConstants
	 * @param	exclude		The EditPart to be excluded from the search
	 * 
	 */
	GraphicalEditPart findSibling(List siblings, Point pStart, int direction,
	                                        EditPart exclude) {
		GraphicalEditPart epCurrent;
		GraphicalEditPart epFinal = null;
		IFigure figure;
		Point pCurrent;
		int distance = Integer.MAX_VALUE;

		Iterator iter = siblings.iterator();
		while (iter.hasNext()) {
			epCurrent = (GraphicalEditPart)iter.next();
			if (epCurrent == exclude || !epCurrent.isSelectable())
				continue;
			figure = epCurrent.getFigure();
			pCurrent = getNavigationPoint(figure);
			figure.translateToAbsolute(pCurrent);
			if (pStart.getPosition(pCurrent) != direction)
				continue;

			int d = pCurrent.getDistanceOrthogonal(pStart);
			if (d < distance) {
				distance = d;
				epFinal = epCurrent;
			}
		}
		return epFinal;
	}

	/**
	 * Figures' navigation points are used to determine their direction compared to one 
	 * another, and the distance between them.
	 *  
	 * @return	the center of the given figure
	 */
	Point getNavigationPoint(IFigure figure) {
		return figure.getBounds().getCenter();
	}

	/**
	 * Returns the cached node. It is possible that the node is not longer in the viewer but
	 * has not been garbage collected yet.
	 */
	private GraphicalEditPart getCachedNode() {
		if (cachedNode == null)
			return null;
		if (cachedNode.isEnqueued())
			return null;
		return (GraphicalEditPart)cachedNode.get();
	}

	/**
	 * @return	the EditPart that has focus
	 */
	protected GraphicalEditPart getFocusEditPart() {
		return (GraphicalEditPart)getViewer().getFocusEditPart();
	}

	/**
	 * Returns the list of editparts which are conceptually at the same level of navigation as
	 * the currently focused editpart.  By default, this is the siblings of the focused part.
	 * @return a list of navigation editparts
	 */
	List getNavigationSiblings() {
		return getFocusEditPart().getParent().getChildren();
	}

	/**
	 * Returns the viewer on which this key handler was created.
	 * @return the viewer
	 */
	protected GraphicalViewer getViewer() {
		return viewer;
	}

	/**
	 * Extended to process key events described above.
	 * @see org.eclipse.gef.KeyHandler#keyPressed(org.eclipse.swt.events.KeyEvent)
	 */
	public boolean keyPressed(KeyEvent event) {
//		System.out.println(event.character);
		if (event.character == ' ') {
			processSelect(event);
			return true;
		} else if (acceptIntoContainer(event)) {
			navigateIntoContainer(event);
			return true;
		} else if (acceptOutOf(event)) {
			navigateOut(event);
			return true;
		} else if (acceptConnection(event)) {
			navigateConnections(event);
			return true;
		} else if (acceptScroll(event)) {
			scrollViewer(event);
			return true;
		} else if (acceptLeaveConnection(event)) {
			navigateOutOfConnection(event);
			return true;
		} else if (acceptLeaveContents(event)) {
			navigateIntoContainer(event);
			return true;
		}

		switch (event.keyCode) {
			case SWT.ARROW_LEFT:
				if (navigateNextSibling(event, PositionConstants.WEST))
					return true;
				break;
			case SWT.ARROW_RIGHT:
				if (navigateNextSibling(event, PositionConstants.EAST))
					return true;
				break;
			case SWT.ARROW_UP:
				if (navigateNextSibling(event, PositionConstants.NORTH))
					return true;
				break;
			case SWT.ARROW_DOWN:
				if (navigateNextSibling(event, PositionConstants.SOUTH))
					return true;
				break;

			case SWT.HOME:
				if (navigateJumpSibling(event, PositionConstants.WEST))
					return true;
				break;
			case SWT.END:
				if (navigateJumpSibling(event, PositionConstants.EAST))
					return true;
				break;
			case SWT.PAGE_DOWN:
				if (navigateJumpSibling(event, PositionConstants.SOUTH))
					return true;
				break;
			case SWT.PAGE_UP:
				if (navigateJumpSibling(event, PositionConstants.NORTH))
					return true;
		}
		return super.keyPressed(event);
	}

	/**
	 * This method navigates through connections based on the keys pressed.
	 */
	void navigateConnections(KeyEvent event) {
		GraphicalEditPart focus = getFocusEditPart();
		ConnectionEditPart current = null;
		GraphicalEditPart node = getCachedNode();
		if (focus instanceof ConnectionEditPart) {
			current = (ConnectionEditPart)focus;
			if (node == null
			  || (node != current.getSource() && node != current.getTarget())) {
				node = (GraphicalEditPart)current.getSource();
				counter = 0;
			}
		} else {
			node = focus;
		}

		setCachedNode(node);
		boolean forward = event.character == '/'
			|| event.character == '?';
		ConnectionEditPart next = findConnection(node, current, forward);
		navigateTo(next, event);
	}

	/**
	 * This method traverses to the closest child of the currently focused EditPart, if it has
	 * one.
	 */
	void navigateIntoContainer(KeyEvent event) {
		GraphicalEditPart focus = getFocusEditPart();
		List childList = focus.getChildren();
		Point tl = focus.getContentPane().getBounds().getTopLeft();
		
		int minimum = Integer.MAX_VALUE;
		int current;
		GraphicalEditPart closestPart = null;

		for (int i = 0; i < childList.size(); i++) {	
			GraphicalEditPart ged = (GraphicalEditPart)childList.get(i);
			if (!ged.isSelectable())
				continue;
			Rectangle childBounds = ged.getFigure().getBounds();
			
			current = (childBounds.x - tl.x) + (childBounds.y - tl.y);
			if (current < minimum) {
				minimum = current;
				closestPart = ged;
			}
		}
		if (closestPart != null)
			navigateTo(closestPart, event);
	}

	/**
	 * Not yet implemented.
	 */
	boolean navigateJumpSibling(KeyEvent event, int direction) {
		// TODO: Implement navigateJumpSibling() (for PGUP, PGDN, HOME and END key events)
		return false;
	}

	/**
	 * Traverses to the next sibling in the given direction.
	 * 
	 * @param	event		the KeyEvent for the keys that were pressed to trigger this traversal
	 * @param	direction	PositionConstants.* indicating the direction in which to traverse
	 */
	boolean navigateNextSibling(KeyEvent event, int direction) {
		return navigateNextSibling(event, direction, getNavigationSiblings());
	}

	/**
	 * Traverses to the closest EditPart in the given list that is also in the given direction.
	 * 
	 * @param	event		the KeyEvent for the keys that were pressed to trigger this traversal
	 * @param	direction	PositionConstants.* indicating the direction in which to traverse
	 */
	boolean navigateNextSibling(KeyEvent event, int direction, List list) {
		if((event.stateMask & SWT.CONTROL) != 0) return false;
		
		
		GraphicalEditPart epStart = getFocusEditPart();
		IFigure figure = epStart.getFigure();
		Point pStart = getNavigationPoint(figure);
		figure.translateToAbsolute(pStart);
		EditPart next = findSibling(list, pStart, direction, epStart);
		if (next == null)
			return false;
		navigateTo(next, event);
		return true;
	}

	/**
	 * Navigates to the parent of the currently focused EditPart.
	 */
	void navigateOut(KeyEvent event) {
		if (getFocusEditPart() == null
			|| getFocusEditPart() == getViewer().getContents()
			|| getFocusEditPart().getParent() == getViewer().getContents())
			return;
		navigateTo(getFocusEditPart().getParent(), event);
	}

	/**
	 * Navigates to the source or target of the currently focused ConnectionEditPart.
	 */
	void navigateOutOfConnection(KeyEvent event) {
		GraphicalEditPart cached = getCachedNode();
		ConnectionEditPart conn = (ConnectionEditPart)getFocusEditPart();
		if (cached != null
			&& (cached == conn.getSource()
				|| cached == conn.getTarget()))
			navigateTo(cached, event);
		else
			navigateTo(conn.getSource(), event);
	}

	/**
	 * Navigates to the given EditPart
	 * 
	 * @param	part	the EditPart to navigate to
	 * @param	event	the KeyEvent that triggered this traversal
	 */
	protected void navigateTo(EditPart part, KeyEvent event) {
		if (part == null)
			return;
		if ((event.stateMask & SWT.SHIFT) != 0) {
			getViewer().appendSelection(part);
			getViewer().setFocus(part);
		} else if ((event.stateMask & SWT.CONTROL) != 0)
			getViewer().setFocus(part);
		else
			getViewer().select(part);
		getViewer().reveal(part);
	}

	/**
	 * This method is invoked when the user presses the space bar.  It toggles the selection
	 * of the EditPart that currently has focus.
	 * @param event the key event received
	 */
	protected void processSelect(KeyEvent event) {
		EditPart part = getViewer().getFocusEditPart();
		if ((event.stateMask & SWT.CONTROL) != 0
		  && part.getSelected() != EditPart.SELECTED_NONE)
			getViewer().deselect(part);
		else
			getViewer().appendSelection(part);

		getViewer().setFocus(part);
	}

	void scrollViewer(KeyEvent event) {
		if (!(getViewer().getControl() instanceof FigureCanvas))
			return;
		FigureCanvas figCanvas = (FigureCanvas)getViewer().getControl();
		Point loc = figCanvas.getViewport().getViewLocation();
		Rectangle area = figCanvas.getViewport().getClientArea(Rectangle.SINGLETON).scale(.1); 
		switch (event.keyCode) {
			case SWT.ARROW_DOWN:
				figCanvas.scrollToY(loc.y + area.height);
				break;
			case SWT.ARROW_UP:
				figCanvas.scrollToY(loc.y - area.height);
				break;
			case SWT.ARROW_LEFT:
				figCanvas.scrollToX(loc.x - area.width);
				break;
			case SWT.ARROW_RIGHT:
				figCanvas.scrollToX(loc.x + area.width);
		}
	}

	private void setCachedNode(GraphicalEditPart node) {
		if (node == null)
			cachedNode = null;
		else 
			cachedNode = new WeakReference(node);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -