package org.xmind.ui.internal.branch;
import java.util.List;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.xmind.gef.GEF;
import org.xmind.gef.draw2d.IReferencedFigure;
import org.xmind.gef.draw2d.geometry.HorizontalFlipper;
import org.xmind.gef.draw2d.geometry.ITransformer;
import org.xmind.gef.part.IPart;
import org.xmind.ui.branch.AbstractBranchStructure;
import org.xmind.ui.branch.BoundaryLayoutHelper;
import org.xmind.ui.branch.IInsertion;
import org.xmind.ui.branch.Insertion;
import org.xmind.ui.mindmap.IBranchPart;
import org.xmind.ui.mindmap.IBranchRangePart;
import org.xmind.ui.mindmap.IPlusMinusPart;
import org.xmind.ui.mindmap.ISummaryPart;
import org.xmind.ui.mindmap.ITopicPart;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.tools.ParentSearchKey;
public class TimelineVerticalHeadStructure extends AbstractBranchStructure {
private ITransformer t = new HorizontalFlipper();
protected void doFillPlusMinus(IBranchPart branch, IPlusMinusPart plusMinus,
LayoutInfo info) {
Point ref = info.getReference();
int x = ref.x;
Rectangle topicBounds = info.getCheckedClientArea();
int y = topicBounds.bottom();
IFigure pmFigure = plusMinus.getFigure();
Dimension size = pmFigure.getPreferredSize();
Rectangle r = new Rectangle(x - size.width / 2, y, size.width,
size.height);
info.put(pmFigure, r);
}
protected void doFillSubBranches(IBranchPart branch,
List<IBranchPart> subBranches, LayoutInfo info) {
int majorSpacing = getMajorSpacing(branch);
int minorSpacing = getMinorSpacing(branch);
Point ref = info.getReference();
t.setOrigin(ref);
TimelineVerticalData tvd = getCastedData(branch);
Rectangle refBounds = info.getCheckedClientArea();
refBounds = t.tr(refBounds);
int y = refBounds.bottom() + majorSpacing;
IInsertion insertion = getCurrentInsertion(branch);
BoundaryLayoutHelper helper = getBoundaryLayoutHelper(branch);
int num = subBranches.size();
int x = ref.x + majorSpacing;
int yLeftBefore = y;
int yRightBefore = y;
int yLeft = y;
int yRight = y;
for (int i = 0; i < num; i++) {
t.setEnabled(tvd.isLeftwardBranch(i));
if (tvd.isLeftwardBranch(i)) {
y = yRight > yLeftBefore + majorSpacing ? yRight
: yLeftBefore + majorSpacing;
} else {
y = yLeft > yRightBefore + majorSpacing ? yLeft
: yRightBefore + majorSpacing;
}
if (insertion != null && i == insertion.getIndex()) {
Rectangle r = insertion.createRectangle(x, y);
info.add(t.rr(r));
y += r.height + minorSpacing;
}
IBranchPart subBranch = subBranches.get(i);
IFigure subBranchFigure = subBranch.getFigure();
Insets ins = helper.getInsets(subBranch);
ins = t.ti(ins);
Dimension size = subBranchFigure.getPreferredSize();
Rectangle r = new Rectangle(x + ins.left, y + ins.top, size.width,
size.height);
info.put(subBranchFigure, t.rr(r));
IFigure topicFigure = subBranch.getTopicPart().getFigure();
if (tvd.isLeftwardBranch(i)) {
yRightBefore = y + topicFigure.getPreferredSize().height
+ majorSpacing;
yRight = y + size.height + ins.getHeight() + minorSpacing;
} else {
yLeftBefore = y + topicFigure.getPreferredSize().height
+ majorSpacing;
yLeft = y + size.height + ins.getHeight() + minorSpacing;
}
}
if (insertion != null && num == insertion.getIndex()) {
Dimension insSize = insertion.getSize();
if (insSize != null) {
Rectangle r = new Rectangle(x, y, insSize.width,
insSize.height);
info.add(t.rr(r));
}
}
}
public IPart calcNavigation(IBranchPart branch, String navReqType) {
if (!branch.getSubBranches().isEmpty()) {
if (GEF.REQ_NAV_RIGHT.equals(navReqType)) {
return getSubTopicPart(branch, 0);
}
}
return super.calcNavigation(branch, navReqType);
}
public IPart calcChildNavigation(IBranchPart branch,
IBranchPart sourceChild, String navReqType, boolean sequential) {
if (GEF.REQ_NAV_UP.equals(navReqType)) {
return getSubTopicPart(branch, sourceChild.getBranchIndex() - 1);
} else if (GEF.REQ_NAV_DOWN.equals(navReqType)) {
return getSubTopicPart(branch, sourceChild.getBranchIndex() + 1);
} else if (!sequential) {
if (getCastedData(branch)
.isLeftwardBranch(sourceChild.getBranchIndex())) {
if (GEF.REQ_NAV_LEFT.equals(navReqType)) {
return branch.getTopicPart();
}
} else {
if (GEF.REQ_NAV_RIGHT.equals(navReqType)) {
return branch.getTopicPart();
}
}
}
return super.calcChildNavigation(branch, sourceChild, navReqType,
sequential);
}
public int getSourceOrientation(IBranchPart branch) {
return PositionConstants.SOUTH;
}
public int getChildTargetOrientation(IBranchPart branch,
IBranchPart subBranch) {
return calcChildTargetOrientation(subBranch);
}
private int calcChildTargetOrientation(IBranchPart subBranch) {
if (subBranch.getParentBranch() != null
&& getCastedData(subBranch.getParentBranch())
.isLeftwardBranch(subBranch.getBranchIndex()))
return PositionConstants.EAST;
return PositionConstants.WEST;
}
public int calcChildDistance(IBranchPart branch, ParentSearchKey key) {
IReferencedFigure topicFigure = (IReferencedFigure) branch
.getTopicPart().getFigure();
Point ref = topicFigure.getReference();
t.setOrigin(ref);
Point childRef = t.tp(getChildRef(branch, ref, key));
Rectangle topicBounds = t.tr(topicFigure.getBounds());
List<IBranchPart> subBranches = branch.getSubBranches();
int totalHeight = 0;
if (!subBranches.isEmpty()) {
int fy = subBranches.get(0).getFigure().getBounds().y;
int ly = subBranches.get(subBranches.size() - 1).getFigure()
.getBounds().bottom();
int sly = 0;
if (subBranches.size() > 1)
sly = subBranches.get(subBranches.size() - 2).getFigure()
.getBounds().bottom();
totalHeight = ly > sly ? ly - fy : sly - ly;
}
int dy = childRef.y - topicBounds.bottom();
int dx = childRef.x - topicBounds.right();
if (childRef.x >= topicBounds.x - MindMapUI.SEARCH_RANGE / 2
&& childRef.x < topicBounds.right()
+ MindMapUI.SEARCH_RANGE / 2) {
if (dy > 0 && dy < totalHeight + MindMapUI.SEARCH_RANGE) {
return dy;
}
int d = dx * dx + dy * dy;
return d;
}
return super.calcChildDistance(branch, key);
}
protected Object createStructureData(IBranchPart branch) {
return new TimelineVerticalData(branch);
}
protected boolean isValidStructureData(IBranchPart branch, Object data) {
return super.isValidStructureData(branch, data)
&& (data instanceof TimelineVerticalData);
}
private TimelineVerticalData getCastedData(IBranchPart branch) {
return (TimelineVerticalData) super.getStructureData(branch);
}
protected int calcInsIndex(IBranchPart branch, ParentSearchKey key,
boolean withDisabled) {
if (branch.getSubBranches().isEmpty() || branch.isFolded())
return withDisabled ? 0 : -1;
ITopicPart topic = branch.getTopicPart();
if (topic == null)
return withDisabled ? 0 : -1;
IFigure topicFigure = topic.getFigure();
Point ref = ((IReferencedFigure) topicFigure).getReference();
t.setOrigin(ref);
Point childRef = t.tp(getChildRef(branch, ref, key));
List<IBranchPart> subBranches = branch.getSubBranches();
int y = childRef.y - ref.y;
int ret = 0;
for (IBranchPart sub : subBranches) {
IFigure tf = sub.getTopicPart().getFigure();
Point tr = ((IReferencedFigure) tf).getReference();
int d = tr.y - ref.y;
if (y < d)
return ret;
ret++;
}
return withDisabled ? subBranches.size() : -1;
}
private Dimension calcInsSize(IBranchPart branch, ParentSearchKey key) {
return key.getFigure().getSize().scale(0.8);
}
public IInsertion calcInsertion(IBranchPart branch, ParentSearchKey key) {
return new Insertion(branch, calcInsIndex(branch, key, true),
calcInsSize(branch, key));
}
public int getQuickMoveOffset(IBranchPart branch, IBranchPart child,
int direction) {
if (direction == PositionConstants.NORTH)
return 1;
if (direction == PositionConstants.SOUTH)
return -1;
return super.getQuickMoveOffset(branch, child, direction);
}
public int getSummaryDirection(IBranchPart branch, ISummaryPart summary) {
List<IBranchPart> enclosingBranches = summary.getEnclosingBranches();
if (!enclosingBranches.isEmpty()) {
IBranchPart sub = enclosingBranches.get(0);
if (getCastedData(branch).isLeftwardBranch(sub.getBranchIndex()))
return PositionConstants.WEST;
return PositionConstants.EAST;
}
return PositionConstants.WEST;
}
public int getRangeGrowthDirection(IBranchPart branch,
IBranchRangePart range) {
return PositionConstants.SOUTH;
}
public boolean isChildLeftwards(IBranchPart branch, IBranchPart child) {
return getCastedData(branch).isLeftwardBranch(child.getBranchIndex());
}
protected Point calcInsertPosition(IBranchPart branch, IBranchPart child,
ParentSearchKey key) {
List<IBranchPart> subBranches = branch.getSubBranches();
if (subBranches.isEmpty())
return calcFirstChildPosition(branch, key);
TimelineVerticalData tvd = getCastedData(branch);
int majorSpacing = getMajorSpacing(branch);
int index = calcInsIndex(branch, key, true);
Dimension insSize = key.getFigure().getSize();
Dimension inventSize = key.getInvent().getSize();
int x = getFigureLocation(branch.getFigure()).x;
int dx = tvd.isLeftwardBranch(index)
? majorSpacing + inventSize.width / 2
: -majorSpacing - inventSize.width / 2;
if (index < 2 && index != subBranches.size()) {
IBranchPart sub = subBranches.get(index);
Rectangle bounds = sub.getFigure().getBounds();
int y = bounds.y - majorSpacing - insSize.height / 2;
return new Point(x + dx, y);
}
if (index == subBranches.size()) {
IBranchPart sub = subBranches.get(subBranches.size() - 1);
Rectangle bounds = sub.getTopicPart().getFigure().getBounds();
return new Point(x + dx, bounds.bottom() + majorSpacing);
}
return calcInventPosition(subBranches.get(index - 1),
subBranches.get(index - 2), key, tvd.isLeftwardBranch(index));
}
protected Point calcMovePosition(IBranchPart branch, IBranchPart child,
ParentSearchKey key) {
List<IBranchPart> subBranches = branch.getSubBranches();
List<Integer> disables = getDisableBranches(branch);
int index = calcInsIndex(branch, key, true);
int oldIndex = getOldIndex(branch, child);
if (disables != null) {
if (disables.contains(index - 1)) {
index--;
oldIndex = index;
} else if (disables.contains(index)) {
oldIndex = index;
}
}
if (index == oldIndex) {
IBranchPart sub = subBranches.get(index);
return getFigureLocation(sub.getFigure()).getTranslated(0, 0);
}
return calcInsertPosition(branch, child, key);
}
protected Point calcInventPosition(IBranchPart orientation,
IBranchPart assist, ParentSearchKey key, boolean isRightOrUp) {
Dimension insSize = key.getFigure().getSize();
int minorSpacing = getMinorSpacing(orientation.getParentBranch());
int majorSpacing = getMajorSpacing(orientation.getParentBranch());
IFigure tf = assist.getTopicPart().getFigure();
Dimension ts = tf.getSize();
int x = getFigureLocation(assist.getFigure()).x
+ (isRightOrUp ? (-ts.width + insSize.width) / 2
: (ts.width - insSize.width) / 2);
int y1 = assist.getFigure().getBounds().bottom() + minorSpacing;
int y2 = orientation.getTopicPart().getFigure().getBounds().bottom()
+ majorSpacing;
return new Point(x,
y1 > y2 ? y1 + insSize.height / 2 : y2 + insSize.height / 2);
}
protected Point calcFirstChildPosition(IBranchPart branch,
ParentSearchKey key) {
int x = getMajorSpacing(branch) + key.getInvent().getSize().width / 2;
return getFigureLocation(branch.getFigure()).getTranslated(x,
branch.getFigure().getSize().height / 2
+ getMajorSpacing(branch)
+ key.getFigure().getSize().height / 2);
}
}