blob: 8826a118677decb689fb3e97b746bb01c72be950 [file] [log] [blame]
/*******************************************************************************
* 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);
}
}