/******************************************************************************* * Copyright (c) 2005, 2012 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.bpel.ui.util; import java.util.Collection; import java.util.List; import org.eclipse.bpel.ui.editparts.FlowEditPart; import org.eclipse.draw2d.Cursors; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Point; import org.eclipse.gef.AccessibleAnchorProvider; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPartViewer; import org.eclipse.gef.commands.Command; import org.eclipse.gef.requests.CreateConnectionRequest; import org.eclipse.gef.requests.CreationFactory; import org.eclipse.gef.tools.AbstractConnectionCreationTool; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Scrollable; /** * This class allows an EditPart to have initial source anchor for * the ConnectionCreationTool. */ public class BPELConnectionCreationTool extends AbstractConnectionCreationTool { private EditPartViewer viewer; private EditPart source; private EditPart proposedTarget; private boolean lastProposedTargetConnectable; public BPELConnectionCreationTool(CreationFactory factory) { super(factory); setDefaultCursor(Cursors.ARROW); // don't use the plug // setDisabledCursor(); TODO: need cursor with arrow and no drop setFactory(factory); setUnloadWhenFinished(true); } @Override protected boolean handleKeyDown(KeyEvent event) { boolean ret = ourHandleKeyDown(event); if (getDomain().getActiveTool() != this) { //set.setLockOut(false); } return ret; } @Override protected void handleFinished() { super.handleFinished(); //set.setLockOut(false); } public void setInitialAnchor(EditPart part, EditPartViewer curViewer) { setViewer(curViewer); setTargetEditPart(part); updateTargetRequest(); setConnectionSource(part); Command command = getCommand(); ((CreateConnectionRequest)getTargetRequest()).setSourceEditPart(part); source = part; proposedTarget = null; lastProposedTargetConnectable = false; if (command != null) { setState(STATE_CONNECTION_STARTED); setCurrentCommand(command); viewer = getCurrentViewer(); } if (isInState(STATE_CONNECTION_STARTED)) { updateTargetRequest(); updateTargetUnderMouse(); showSourceFeedback(); showTargetFeedback(); setCurrentCommand(getCommand()); } return; } @Override protected boolean handleButtonDown(int button) { if (button == 1 && stateTransition(STATE_CONNECTION_STARTED, STATE_TERMINAL)) { boolean ret = handleCreateConnection(); if (getCommand() != null) handleFinished(); return ret; } if (isInState(STATE_INITIAL) && button == 1) { updateTargetRequest(); updateTargetUnderMouse(); setConnectionSource(getTargetEditPart()); Command command = getCommand(); ((CreateConnectionRequest)getTargetRequest()).setSourceEditPart( getTargetEditPart()); if (command != null) { setState(STATE_CONNECTION_STARTED); setCurrentCommand(command); viewer = getCurrentViewer(); } } if (isInState(STATE_INITIAL) && button != 1) { setState(STATE_INVALID); handleInvalidInput(); } if (isInState(STATE_CONNECTION_STARTED)) { //Fake a drag to cause feedback to be displayed immediately on mouse down. handleDrag(); } return true; } @Override public void deactivate() { viewer = null; super.deactivate(); } @Override protected boolean handleMove() { if (isInState(STATE_CONNECTION_STARTED) && viewer != getCurrentViewer()) return false; if (isInState(STATE_CONNECTION_STARTED | STATE_INITIAL | STATE_ACCESSIBLE_DRAG_IN_PROGRESS)) { updateTargetRequest(); updateTargetUnderMouse(); showSourceFeedback(); showTargetFeedback(); setCurrentCommand(getCommand()); } return true; } @Override protected boolean updateTargetUnderMouse() { if (!isTargetLocked()) { Collection exclude = getExclusionSet(); EditPart editPart = getCurrentViewer().findObjectAtExcluding( getLocation(), exclude, getTargetingConditional()); if (editPart != null) { editPart = editPart.getTargetEditPart(getTargetRequest()); } boolean changed = getTargetEditPart() != editPart; setTargetEditPart(editPart); return changed; } return false; } @Override protected EditPartViewer.Conditional getTargetingConditional() { return new EditPartViewer.Conditional() { public boolean evaluate(EditPart editpart) { EditPart target = editpart.getTargetEditPart(getTargetRequest()); if (target == null) return false; if (target == proposedTarget) return lastProposedTargetConnectable; if (target.getParent() instanceof FlowEditPart) { lastProposedTargetConnectable = ((FlowEditPart)(target.getParent())).detectImpendingCycle(source, target); } else { lastProposedTargetConnectable = true; } proposedTarget = target; return lastProposedTargetConnectable; } }; } boolean acceptConnectionFinish(KeyEvent event) { return isInState(STATE_ACCESSIBLE_DRAG_IN_PROGRESS | STATE_CONNECTION_STARTED) && event.character == 13; } boolean acceptConnectionStart(KeyEvent event) { return isInState(STATE_INITIAL) && event.character == 13; } /** * Cleans up feedback and resets the tool when focus is lost. * @return <code>true</code> if this focus lost event was processed */ @Override protected boolean handleFocusLost() { if (isInState(STATE_CONNECTION_STARTED | STATE_ACCESSIBLE_DRAG_IN_PROGRESS)) { eraseSourceFeedback(); eraseTargetFeedback(); setState(STATE_INVALID); handleFinished(); } return super.handleFocusLost(); } private boolean ourAcceptArrowKey(KeyEvent e) { int key = e.keyCode; if (!(isInState(STATE_INITIAL | STATE_CONNECTION_STARTED | STATE_ACCESSIBLE_DRAG | STATE_ACCESSIBLE_DRAG_IN_PROGRESS))) return false; return (key == SWT.ARROW_UP) || (key == SWT.ARROW_RIGHT) || (key == SWT.ARROW_DOWN) || (key == SWT.ARROW_LEFT); } private boolean ourHandleKeyDown(KeyEvent event) { if (ourAcceptArrowKey(event)) { int direction = 0; switch (event.keyCode) { case SWT.ARROW_DOWN : direction = PositionConstants.SOUTH; break; case SWT.ARROW_UP: direction = PositionConstants.NORTH; break; case SWT.ARROW_RIGHT: direction = PositionConstants.EAST; break; case SWT.ARROW_LEFT: direction = PositionConstants.WEST; break; } boolean consumed = false; if (direction != 0 && event.stateMask == 0) consumed = navigateNextAnchor(direction); if (!consumed) { event.stateMask |= SWT.CONTROL; event.stateMask &= ~SWT.SHIFT; if (getCurrentViewer().getKeyHandler().keyPressed(event)) { navigateNextAnchor(0); updateTargetRequest(); updateTargetUnderMouse(); Command command = getCommand(); if (command != null) setCurrentCommand(command); return true; } } } if (acceptConnectionStart(event)) { updateTargetUnderMouse(); setConnectionSource(getTargetEditPart()); ((CreateConnectionRequest)getTargetRequest()) .setSourceEditPart(getTargetEditPart()); setState(STATE_ACCESSIBLE_DRAG_IN_PROGRESS); ourPlaceMouseInViewer(getLocation().getTranslated(6, 6)); return true; } if (acceptConnectionFinish(event)) { Command command = getCommand(); if (command != null && command.canExecute()) { setState(STATE_INITIAL); ourPlaceMouseInViewer(getLocation().getTranslated(6, 6)); eraseSourceFeedback(); eraseTargetFeedback(); setCurrentCommand(command); executeCurrentCommand(); handleFinished(); } return true; } return super.handleKeyDown(event); } boolean navigateNextAnchor(int direction) { EditPart focus = getCurrentViewer().getFocusEditPart(); AccessibleAnchorProvider provider; provider = (AccessibleAnchorProvider)focus.getAdapter(AccessibleAnchorProvider.class); if (provider == null) return false; List list; if (isInState(STATE_ACCESSIBLE_DRAG_IN_PROGRESS)) list = provider.getTargetAnchorLocations(); else list = provider.getSourceAnchorLocations(); Point start = getLocation(); int distance = Integer.MAX_VALUE; Point next = null; for (int i = 0; i < list.size(); i++) { Point p = (Point)list.get(i); if (p.equals(start) || (direction != 0 && (start.getPosition(p) != direction))) continue; int d = p.getDistanceOrthogonal(start); if (d < distance) { distance = d; next = p; } } if (next != null) { ourPlaceMouseInViewer(next); return true; } return false; } void ourPlaceMouseInViewer(Point p) { if (getCurrentViewer() == null) return; Control c = getCurrentViewer().getControl(); Rectangle rect; if (c instanceof Scrollable) rect = ((Scrollable)c).getClientArea(); else rect = c.getBounds(); if (p.x > rect.x + rect.width - 1) p.x = rect.x + rect.width - 1; else if (p.x < rect.x) p.x = rect.x; if (p.y > rect.y + rect.height - 1) p.y = rect.y + rect.height - 1; else if (p.y < rect.y) p.y = rect.y; org.eclipse.swt.graphics.Point swt = new org.eclipse.swt.graphics.Point(p.x, p.y); swt = c.toDisplay(swt); c.getDisplay().setCursorLocation(swt); } }