package org.eclipse.uml2.diagram.sequence.edit.policies;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Polyline;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.editpolicies.GraphicalEditPolicy;
import org.eclipse.gef.requests.DropRequest;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.uml2.diagram.sequence.edit.create.arcas.AnchoredDiagramTarget;
public class TargetFeedbackHelper {
public TargetFeedbackHelper(GraphicalEditPolicy policy) {
myPolicy = policy;
}
private GraphicalEditPolicy myPolicy;
private TargetFeedback myTargetFeedback;
//ASSERT:myPolicy.getHost() is container, request contains ANCHOR
public void showFeedback(Request request) {
Command command = myPolicy.getCommand(request);
if (command == null || !command.canExecute()) {
return;
}
if (myPolicy.getHost() == myPolicy.getHost().getViewer().getContents()) {
return;
}
if (request instanceof DropRequest) {
AnchoredDiagramTarget target = new AnchoredDiagramTarget((GraphicalEditPart) myPolicy.getHost(), request);
target = findVisibleTargetUptree(target);
if (myTargetFeedback == null || !myTargetFeedback.getTarget().equals(target)) {
if (myTargetFeedback != null) {
myAccess.removeFeedback(myTargetFeedback.getFigure());
}
if (target != null) {
myTargetFeedback = new TargetFeedback(target);
myAccess.addFeedback(myTargetFeedback.getFigure());
}
}
Point diagramPoint = getDiagramPoint((DropRequest)request);
myTargetFeedback.layout(diagramPoint);
}
}
private AnchoredDiagramTarget findVisibleTargetUptree(AnchoredDiagramTarget target) {
if (!isHidden(target.getContainer())) {
return target;
}
if (false == target.getContainer().getParent() instanceof GraphicalEditPart){
return null;
}
GraphicalEditPart walker = (GraphicalEditPart)target.getContainer().getParent();
while (walker != myPolicy.getHost().getViewer().getContents()) {
if (!isHidden(walker)) {
return new AnchoredDiagramTarget(walker);
}
walker = (GraphicalEditPart)walker.getParent();
}
return null;
}
public void eraseFeedback() {
if (myTargetFeedback != null) {
myAccess.removeFeedback(myTargetFeedback.getFigure());
myTargetFeedback = null;
}
}
private Point getDiagramPoint(DropRequest request) {
Point diagramPoint = new Point ((request).getLocation());
((GraphicalEditPart) myPolicy.getHost()).getFigure().translateToRelative(diagramPoint);
return diagramPoint;
}
//TODO [COPY/PASTE] from EditPartUtil
public static boolean isHidden(GraphicalEditPart editPart) {
GraphicalViewer viewer = (GraphicalViewer) editPart.getViewer();
if (viewer == null) {
return true;
}
IFigure rootFigure = ((DiagramRootEditPart) viewer.getRootEditPart()).getFigure();
for (IFigure figure = editPart.getFigure();; figure = figure.getParent()) {
if (figure == null) {
return true;
} else if (figure == rootFigure) {
return false;
}
}
}
private static class TargetFeedback{
IFigure myFigure;
AnchoredDiagramTarget myTarget;
public TargetFeedback(AnchoredDiagramTarget target) {
myTarget = target;
}
public IFigure getFigure() {
if (myFigure == null) {
if (myTarget.getAnchor() == null) {
if (myTarget.getContainer().getFigure() instanceof PolylineConnection) {
Polyline line = new Polyline();
line.setLineWidth(5);
line.setFill(false);
line.setPoints(((PolylineConnection) myTarget.getContainer().getFigure()).getPoints());
myFigure = line;
}
else {
RectangleFigure r= new RectangleFigure();
r.setFill(false);
r.setOutline(true);
r.setForegroundColor(ColorConstants.blue);
myFigure = r;
}
}
else {
RectangleFigure r= new RectangleFigure();
r.setFill(false);
r.setBackgroundColor(ColorConstants.black);//TODO: which color?
myFigure = r;
}
}
return myFigure;
}
public void layout(Point diagramPoint) {
IFigure containerFigure = myTarget.getContainer().getFigure();
IFigure anchorFigure = myTarget.getAnchor() == null ? null : myTarget.getAnchor().getFigure();
boolean isBefore = myTarget.isBeforeAnchor();
if (anchorFigure == null) {
myFigure.setBounds(containerFigure.getBounds().getExpanded(5, 5));
}
else {
Rectangle ab = anchorFigure.getBounds();
Rectangle pb = containerFigure.getBounds();
Rectangle b = new Rectangle();
b.x = pb.x;
b.width = pb.width;
int top;
int bottom;
if (isBefore) {
IFigure prevChild = AnchorUtil.findPrevFigure(myTarget.getAnchor());
if (prevChild == null) {
top = pb.y;
}
else {
Rectangle prevb = prevChild.getBounds();
top = prevb.y + prevb.height;
}
bottom = ab.y;
}
else {
top = ab.y + ab.height;
IFigure nextChild = AnchorUtil.findNextFigure(myTarget.getAnchor());
if (nextChild == null) {
bottom = pb.y + pb.height;
}
else {
bottom = nextChild.getBounds().y;
}
}
b.y = diagramPoint.y;
if (b.y < top) {
b.y = top;
}
else if (b.y > bottom) {
b.y = bottom;
}
b.height = 2;
myFigure.setBounds(b);
}
}
public AnchoredDiagramTarget getTarget() {
return myTarget;
}
}
private GraphicalEditPolicyAccess myAccess = new GraphicalEditPolicyAccess();
private class GraphicalEditPolicyAccess extends GraphicalEditPolicy {
public EditPart getHost() {
return myPolicy.getHost();
}
public void addFeedback(IFigure figure) {
super.addFeedback(figure);
}
public void removeFeedback(IFigure figure) {
if (figure.getParent() != null){
super.removeFeedback(figure);
}
}
protected IFigure getFeedbackLayer() {
return getLayer(LayerConstants.FEEDBACK_LAYER);
}
}
}