package org.eclipse.uml2.diagram.timing.edit.policies;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.uml2.diagram.common.editparts.PrimaryShapeEditPart;
import org.eclipse.uml2.diagram.timing.edit.parts.DBlockEditPart;
import org.eclipse.uml2.diagram.timing.edit.parts.DSegmentEditPart;
import org.eclipse.uml2.diagram.timing.edit.parts.DSegmentEndEditPart;
import org.eclipse.uml2.diagram.timing.edit.parts.DSegmentMiddlePointEditPart;
import org.eclipse.uml2.diagram.timing.edit.parts.DSegmentStartEditPart;
import org.eclipse.uml2.diagram.timing.edit.parts.DValueLineEditPart;
import org.eclipse.uml2.diagram.timing.edit.policies.SegmentAnchor.EditPartAndGlobalBounds;
public class SegmentAnchorHelper {
private final DBlockEditPart myBlockEP;
public SegmentAnchorHelper(DBlockEditPart blockEP){
myBlockEP = blockEP;
}
public SegmentAnchor findSegmentAnchor(Point globalPoint){
SegmentAnchorImpl result = new SegmentAnchorImpl();
if (setupOverlappingSegment(result, globalPoint)){
setupLeftAnchor(result, globalPoint);
setupRightAnchor(result, globalPoint);
}
return result;
}
public boolean setupOverlappingSegment(SegmentAnchorImpl anchorData, Point globalPoint){
List<DValueLineEditPart> lineEPs = collectChildEditParts(myBlockEP, DValueLineEditPart.class);
for (DValueLineEditPart next : lineEPs){
for (DSegmentEditPart nextSegment : collectChildEditParts(next, DSegmentEditPart.class)){
IFigure segmentF = nextSegment.getPrimaryShape();
Rectangle nextSegmentGlobalBounds = segmentF.getBounds().getCopy();
segmentF.getParent().translateToAbsolute(nextSegmentGlobalBounds);
if (nextSegmentGlobalBounds.x <= globalPoint.x && nextSegmentGlobalBounds.x + nextSegmentGlobalBounds.width >= globalPoint.x){
anchorData.setOverlappingSegment(nextSegment, nextSegmentGlobalBounds.getCopy());
return true;
}
}
}
return false;
}
public SegmentAnchor.EditPartAndGlobalBounds<PrimaryShapeEditPart> findCloseCircle(Point globalPoint, int threshold){
List<DValueLineEditPart> lineEPs = collectChildEditParts(myBlockEP, DValueLineEditPart.class);
for (DValueLineEditPart next : lineEPs){
for (DSegmentEditPart nextSegment : collectChildEditParts(next, DSegmentEditPart.class)){
List<PrimaryShapeEditPart> circles = new LinkedList<PrimaryShapeEditPart>();
circles.addAll(collectChildEditParts(nextSegment, DSegmentStartEditPart.class));
circles.addAll(collectChildEditParts(nextSegment, DSegmentMiddlePointEditPart.class));
circles.addAll(collectChildEditParts(nextSegment, DSegmentEndEditPart.class));
for (PrimaryShapeEditPart nextCircle : circles){
IFigure figure = nextCircle.getPrimaryShape();
Rectangle nextGlobalBounds = figure.getBounds().getCopy();
figure.getParent().translateToAbsolute(nextGlobalBounds);
int nextCenterX = nextGlobalBounds.x + nextGlobalBounds.width / 2;
int diff = nextCenterX - globalPoint.x;
if (Math.abs(diff) <= threshold){
return new SegmentAnchor.EditPartAndGlobalBounds<PrimaryShapeEditPart>(nextCircle, nextGlobalBounds);
}
}
}
}
return null;
}
public void setupLeftAnchor(SegmentAnchorImpl anchorData, Point global){
if (anchorData.getOverlappingSegmentEditPartData() == null){
return;
}
DSegmentEditPart segmentEP = anchorData.getOverlappingSegmentEditPartData().getEditPart();
if (segmentEP == null){
return;
}
int bestCenterX = Integer.MIN_VALUE;
PrimaryShapeEditPart bestCircle = null;
Rectangle bestBounds = null;
List<PrimaryShapeEditPart> circles = new LinkedList<PrimaryShapeEditPart>();
circles.addAll(collectChildEditParts(segmentEP, DSegmentStartEditPart.class));
circles.addAll(collectChildEditParts(segmentEP, DSegmentMiddlePointEditPart.class));
circles.addAll(collectChildEditParts(segmentEP, DSegmentEndEditPart.class));
for (PrimaryShapeEditPart nextCircle : circles){
IFigure figure = nextCircle.getPrimaryShape();
Rectangle nextGlobalBounds = figure.getBounds().getCopy();
figure.getParent().translateToAbsolute(nextGlobalBounds);
int nextCenterX = nextGlobalBounds.x + nextGlobalBounds.width / 2;
if (nextCenterX <= global.x){
debugOut("Circle at the left found: " + nextCircle + "\n\t " + nextCenterX);
if (bestCircle == null || bestCenterX < nextCenterX){
if (bestCircle != null){
debugOut("And its better than: " + bestCircle + "\n\t" + bestCenterX);
}
bestCircle = nextCircle;
bestCenterX = nextCenterX;
if (bestBounds == null){
bestBounds = new Rectangle();
}
bestBounds.setBounds(nextGlobalBounds);
} else {
debugOut("Not that good, skipped");
}
}
}
if (bestCircle != null){
anchorData.setLeftAnchor(new EditPartAndGlobalBounds<PrimaryShapeEditPart>(bestCircle, bestBounds));
}
}
public void setupRightAnchor(SegmentAnchorImpl anchorData, Point global){
EditPartAndGlobalBounds<DSegmentEditPart> segmentData = anchorData.getOverlappingSegmentEditPartData();
if (segmentData == null){
return;
}
DSegmentEditPart segmentEP = segmentData.getEditPart();
int bestCenterX = Integer.MAX_VALUE;
PrimaryShapeEditPart bestCircle = null;
Rectangle bestBounds = null;
List<PrimaryShapeEditPart> circles = new LinkedList<PrimaryShapeEditPart>();
circles.addAll(collectChildEditParts(segmentEP, DSegmentStartEditPart.class));
circles.addAll(collectChildEditParts(segmentEP, DSegmentMiddlePointEditPart.class));
circles.addAll(collectChildEditParts(segmentEP, DSegmentEndEditPart.class));
for (PrimaryShapeEditPart nextCircle : circles){
IFigure figure = nextCircle.getPrimaryShape();
Rectangle nextGlobalBounds = figure.getBounds().getCopy();
figure.getParent().translateToAbsolute(nextGlobalBounds);
int nextCenterX = nextGlobalBounds.x + nextGlobalBounds.width / 2;
if (nextCenterX >= global.x){
debugOut("Circle at the right found: " + nextCircle + "\n\t " + nextCenterX);
if (bestCircle == null || bestCenterX > nextCenterX){
if (bestCircle != null){
debugOut("And its better than: " + bestCircle + "\n\t" + bestCenterX);
}
bestCircle = nextCircle;
bestCenterX = nextCenterX;
if (bestBounds == null){
bestBounds = new Rectangle();
}
bestBounds.setBounds(nextGlobalBounds);
} else {
debugOut("Not that good, skipped");
}
}
}
if (bestCircle != null){
anchorData.setRightAnchor(new EditPartAndGlobalBounds<PrimaryShapeEditPart>(bestCircle, bestBounds));
}
}
private static <T extends EditPart> List<T> collectChildEditParts(EditPart parent, Class<T> clazz){
List<T> result = new LinkedList<T>();
for (Object next : parent.getChildren()){
if (clazz.isInstance(next)){
result.add(clazz.cast(next));
}
}
return result;
}
private void debugOut(String s){
//System.err.println(s);
}
public static DBlockEditPart findBlockEditPart(IGraphicalEditPart start){
EditPart curr = start;
while (curr != null && false == curr instanceof DiagramEditPart && false == curr instanceof DBlockEditPart){
curr = curr.getParent();
}
return curr instanceof DBlockEditPart ? (DBlockEditPart)curr : null;
}
}