diff options
author | Andre Dietisheim | 2010-03-12 23:52:37 +0000 |
---|---|---|
committer | Andre Dietisheim | 2010-03-12 23:52:37 +0000 |
commit | 53f9a3ff24f528c6e51a558f09e03bd3b2cf12a2 (patch) | |
tree | 110d6fadcc23f9b7e0e7adea0b6d3d29b3e7b07c /plugins/org.eclipse.emf.cdo.ui.branch | |
parent | e387193cb4fcc784313a8756377ffee327f38582 (diff) | |
download | cdo-53f9a3ff24f528c6e51a558f09e03bd3b2cf12a2.tar.gz cdo-53f9a3ff24f528c6e51a558f09e03bd3b2cf12a2.tar.xz cdo-53f9a3ff24f528c6e51a558f09e03bd3b2cf12a2.zip |
endless recursion bug fixed
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.ui.branch')
9 files changed, 529 insertions, 206 deletions
diff --git a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/BranchViewPart.java b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/BranchViewPart.java index 5b794644b0..791cde8d86 100644 --- a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/BranchViewPart.java +++ b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/BranchViewPart.java @@ -17,6 +17,7 @@ import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.ui.internal.branch.figure.BranchPointFigure; import org.eclipse.emf.cdo.ui.internal.branch.figure.BranchRootFigure; import org.eclipse.emf.cdo.ui.internal.branch.item.BranchPointNode; +import org.eclipse.emf.cdo.ui.internal.branch.item.NewBranchConnection; import org.eclipse.emf.cdo.ui.internal.branch.item.RootNode; import org.eclipse.emf.cdo.ui.internal.branch.item.SameBranchConnection; import org.eclipse.emf.cdo.ui.internal.branch.layout.BranchTreeLayoutAlgorithm; @@ -51,8 +52,6 @@ public class BranchViewPart extends ViewPart { public static final String VIEW_ID = "org.eclipse.emf.cdo.ui.branch"; //$NON-NLS-1$ - // private static final String RES_NAME = "/res1"; - private IManagedContainer container; private IConnector connector; @@ -228,15 +227,25 @@ public class BranchViewPart extends ViewPart CDOBranch mainBranch = session.getBranchManager().getMainBranch(); RootNode rootNode = new RootNode(mainBranch.getBase(), graph, SWT.NONE, new BranchRootFigure()); - CDOBranch subBranch = mainBranch.createBranch(mainBranch.getID() + "-1", mainBranch.getBase().getTimeStamp() + 100); - BranchPointNode branchNode1 = new BranchPointNode(subBranch.getBase(), graph, SWT.NONE, new BranchPointFigure( + CDOBranch subBranch1 = mainBranch.createBranch("1"); + BranchPointNode branchNode1 = new BranchPointNode(subBranch1.getBase(), graph, SWT.NONE, new BranchPointFigure( "branch point 1")); new SameBranchConnection(graph, SWT.NONE, rootNode, branchNode1); - subBranch = mainBranch.createBranch(mainBranch.getID() + "-2", mainBranch.getBase().getTimeStamp() + 301); - BranchPointNode branchNode2 = new BranchPointNode(subBranch.getBase(), graph, SWT.NONE, new BranchPointFigure( + CDOBranch subBranch2 = mainBranch.createBranch("2", subBranch1.getBase().getTimeStamp() + 30000000); + BranchPointNode branchNode2 = new BranchPointNode(subBranch2.getBase(), graph, SWT.NONE, new BranchPointFigure( "branch point 2")); new SameBranchConnection(graph, SWT.NONE, branchNode1, branchNode2); + + CDOBranch subBranch3 = mainBranch.createBranch("3", subBranch2.getBase().getTimeStamp() + 30000000); + BranchPointNode branchNode3 = new BranchPointNode(subBranch3.getBase(), graph, SWT.NONE, new BranchPointFigure( + "branch point 3")); + new SameBranchConnection(graph, SWT.NONE, branchNode2, branchNode3); + + CDOBranch subBranch1_1 = subBranch1.createBranch("1-1"); + BranchPointNode branchNode1_1 = new BranchPointNode(subBranch1_1.getBase(), graph, SWT.NONE, new BranchPointFigure( + "branch point 1-1")); + new NewBranchConnection(graph, SWT.NONE, branchNode1, branchNode1_1); } private void init() diff --git a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/geometry/GeometryUtils.java b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/geometry/GeometryUtils.java index b5e195da8d..cfc9bd677d 100644 --- a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/geometry/GeometryUtils.java +++ b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/geometry/GeometryUtils.java @@ -107,6 +107,6 @@ public class GeometryUtils public static DisplayIndependentRectangle union(DisplayIndependentRectangle thisRectangle, DisplayIndependentRectangle thatRectangle) { - return union(thisRectangle, thatRectangle); + return union(thisRectangle, thatRectangle.x, thatRectangle.y, thatRectangle.width, thatRectangle.height); } } diff --git a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/item/BranchPointNode.java b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/item/BranchPointNode.java index 268b56bd41..2a9ddc72b4 100644 --- a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/item/BranchPointNode.java +++ b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/item/BranchPointNode.java @@ -50,11 +50,11 @@ public class BranchPointNode extends AbstractBranchPointNode public List<NewBranchConnection> getNewBranchSourceConnections() { List<NewBranchConnection> connectionList = new ArrayList<NewBranchConnection>(); - for (Object targetConnection : getSourceConnections()) + for (Object sourceConnection : getSourceConnections()) { - if (targetConnection instanceof NewBranchConnection) + if (sourceConnection instanceof NewBranchConnection) { - connectionList.add((NewBranchConnection)targetConnection); + connectionList.add((NewBranchConnection)sourceConnection); } } diff --git a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/AbstractBranchViewLayoutStrategy.java b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/AbstractBranchViewLayoutStrategy.java index 9979cfd161..1dafa210c6 100644 --- a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/AbstractBranchViewLayoutStrategy.java +++ b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/AbstractBranchViewLayoutStrategy.java @@ -28,7 +28,7 @@ import org.eclipse.zest.layouts.dataStructures.InternalNode; * * @author Andre Dietisheim */ -public abstract class AbstractBranchViewLayoutStrategy +public abstract class AbstractBranchViewLayoutStrategy implements BranchViewLayoutStrategy { protected AbstractBranchViewLayoutStrategy() { @@ -70,9 +70,8 @@ public abstract class AbstractBranchViewLayoutStrategy */ protected void setBaselineNodeLocation(AbstractBranchPointNode node) { - long baseTimeStamp = node.getBranch().getBase().getTimeStamp(); - double y = node.getTimeStamp() - baseTimeStamp; - double x = 0; + double y = node.getTimeStamp(); + double x = 0 * 100; BranchTreeUtils.setInternalLocation(node, x, y); } @@ -81,8 +80,7 @@ public abstract class AbstractBranchViewLayoutStrategy */ protected void setSiblingNodeLocation(AbstractBranchPointNode node, AbstractBranchPointNode previousNode) { - long baseTimeStamp = node.getBranch().getBase().getTimeStamp(); - double y = node.getTimeStamp() - baseTimeStamp; + double y = node.getTimeStamp(); BranchTreeUtils.centerHorizontally(node, previousNode, y); } @@ -117,12 +115,12 @@ public abstract class AbstractBranchViewLayoutStrategy { if (subBranchView != null) { - doSetBranchViewLocation(branchView, subBranchView, branchPointNode); + setBranchViewLocation(branchView, subBranchView, branchPointNode); GeometryUtils.union(branchView.getBounds(), subBranchView.getBounds()); } } - protected abstract void doSetBranchViewLocation(BranchView branchView, BranchView subBranchView, + protected abstract void setBranchViewLocation(BranchView branchView, BranchView subBranchView, BranchPointNode branchPointNode); /** diff --git a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/BranchTreeLayoutAlgorithm.java b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/BranchTreeLayoutAlgorithm.java index 618c2c4dc5..6467937a47 100644 --- a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/BranchTreeLayoutAlgorithm.java +++ b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/BranchTreeLayoutAlgorithm.java @@ -16,6 +16,9 @@ import org.eclipse.emf.cdo.ui.internal.branch.item.RootNode; import org.eclipse.zest.layouts.LayoutStyles; import org.eclipse.zest.layouts.algorithms.AbstractLayoutAlgorithm; +import org.eclipse.zest.layouts.dataStructures.BendPoint; +import org.eclipse.zest.layouts.dataStructures.DisplayIndependentDimension; +import org.eclipse.zest.layouts.dataStructures.DisplayIndependentPoint; import org.eclipse.zest.layouts.dataStructures.DisplayIndependentRectangle; import org.eclipse.zest.layouts.dataStructures.InternalNode; import org.eclipse.zest.layouts.dataStructures.InternalRelationship; @@ -35,6 +38,8 @@ public class BranchTreeLayoutAlgorithm extends AbstractLayoutAlgorithm private DisplayIndependentRectangle layoutBounds = null; + private double widthToHeightRatio; + /** * Constructs a new TreeLayoutAlgorithm object. */ @@ -72,12 +77,11 @@ public class BranchTreeLayoutAlgorithm extends AbstractLayoutAlgorithm protected void preLayoutAlgorithm(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider, double x, double y, double width, double height) { - layoutBounds = new DisplayIndependentRectangle(x, y, width, height); - if (entitiesToLayout.length > 0) { initRootNode(entitiesToLayout); } + layoutBounds = new DisplayIndependentRectangle(x, y, width, height); } /** @@ -107,9 +111,10 @@ public class BranchTreeLayoutAlgorithm extends AbstractLayoutAlgorithm protected void applyLayoutInternal(InternalNode[] entitiesToLayout, InternalRelationship[] relationshipsToConsider, double boundsX, double boundsY, double boundsWidth, double boundsHeight) { + if (entitiesToLayout.length > 0) { - buildBranch(rootNode); + BranchView branchView = buildBranch(rootNode); fireProgressEvent(1, LAYOUT_STEPS); defaultFitWithinBounds(entitiesToLayout, layoutBounds); } @@ -117,7 +122,7 @@ public class BranchTreeLayoutAlgorithm extends AbstractLayoutAlgorithm private BranchView buildBranch(AbstractBranchPointNode branchRootNode) { - return new BranchView(branchRootNode, VerticallyDistributingLayoutStrategy.SPROUT_RIGHT); + return new BranchView(branchRootNode, new VerticallyDistributedSubBranches()); } @Override @@ -150,4 +155,260 @@ public class BranchTreeLayoutAlgorithm extends AbstractLayoutAlgorithm return false; } + /** + * @COPIED methods + */ + + /** + * Find an appropriate size for the given nodes, then fit them into the given bounds. The relative locations of the + * nodes to each other must be preserved. Child classes should set flag reresizeEntitiesAfterLayout to false if they + * want to preserve node sizes. + */ + @Override + protected void defaultFitWithinBounds(InternalNode[] entitiesToLayout, InternalRelationship[] relationships, + DisplayIndependentRectangle realBounds) + { + + DisplayIndependentRectangle layoutBounds; + + if (resizeEntitiesAfterLayout) + { + layoutBounds = getLayoutBounds(entitiesToLayout, false); + + // Convert node x,y to be in percent rather than absolute coords + convertPositionsToPercentage(entitiesToLayout, relationships, layoutBounds, false /* do not update size */); + + // Resize and shift nodes + resizeAndShiftNodes(entitiesToLayout); + } + + // Recalculate layout, allowing for the node width, which we now know + layoutBounds = getLayoutBounds(entitiesToLayout, true); + + // adjust node positions again, to the new coordinate system (still as a percentage) + convertPositionsToPercentage(entitiesToLayout, relationships, layoutBounds, true /* update node size */); + + DisplayIndependentRectangle screenBounds = calcScreenBounds(realBounds, layoutBounds); + + // Now convert to real screen coordinates + convertPositionsToCoords(entitiesToLayout, relationships, screenBounds); + } + + /** + * Convert all node positions into a percentage of the screen. If includeNodeSize is true then this also updates the + * node's internal size. + * + * @param entitiesToLayout + */ + private void convertPositionsToPercentage(InternalNode[] entitiesToLayout, InternalRelationship[] relationships, + DisplayIndependentRectangle layoutBounds, boolean includeNodeSize) + { + + // Adjust node positions and sizes + for (int i = 0; i < entitiesToLayout.length; i++) + { + InternalNode node = entitiesToLayout[i]; + DisplayIndependentPoint location = node.getInternalLocation().convertToPercent(layoutBounds); + node.setInternalLocation(location.x, location.y); + if (includeNodeSize) + { // adjust node sizes + double width = node.getInternalWidth() / layoutBounds.width; + double height = node.getInternalHeight() / layoutBounds.height; + node.setInternalSize(width, height); + } + } + + // Adjust bendpoint positions + for (int i = 0; i < relationships.length; i++) + { + InternalRelationship rel = relationships[i]; + for (int j = 0; j < rel.getBendPoints().size(); j++) + { + BendPoint bp = (BendPoint)rel.getBendPoints().get(j); + DisplayIndependentPoint toPercent = bp.convertToPercent(layoutBounds); + bp.setX(toPercent.x); + bp.setY(toPercent.y); + } + } + } + + /** + * Convert the positions from a percentage of bounds area to fixed coordinates. NOTE: ALL OF THE POSITIONS OF NODES + * UNTIL NOW WERE FOR THE CENTER OF THE NODE - Convert it to the left top corner. + * + * @param entitiesToLayout + * @param relationships + * @param realBounds + */ + private void convertPositionsToCoords(InternalNode[] entitiesToLayout, InternalRelationship[] relationships, + DisplayIndependentRectangle screenBounds) + { + + // Adjust node positions and sizes + for (int i = 0; i < entitiesToLayout.length; i++) + { + InternalNode node = entitiesToLayout[i]; + double width = node.getInternalWidth() * screenBounds.width; + double height = node.getInternalHeight() * screenBounds.height; + DisplayIndependentPoint location = node.getInternalLocation().convertFromPercent(screenBounds); + node.setInternalLocation(location.x - width / 2, location.y - height / 2); + if (resizeEntitiesAfterLayout) + { + adjustNodeSizeAndPos(node, height, width); + } + else + { + node.setInternalSize(width, height); + } + } + + // Adjust bendpoint positions and shift based on source node size + for (int i = 0; i < relationships.length; i++) + { + InternalRelationship rel = relationships[i]; + for (int j = 0; j < rel.getBendPoints().size(); j++) + { + BendPoint bp = (BendPoint)rel.getBendPoints().get(j); + DisplayIndependentPoint fromPercent = bp.convertFromPercent(screenBounds); + bp.setX(fromPercent.x); + bp.setY(fromPercent.y); + } + } + } + + /** + * Adjust node size to take advantage of space. Reset position to top left corner of node. + * + * @param node + * @param height + * @param width + */ + private void adjustNodeSizeAndPos(InternalNode node, double height, double width) + { + double widthUsingHeight = height * widthToHeightRatio; + if (widthToHeightRatio <= 1.0 && widthUsingHeight <= width) + { + double widthToUse = height * widthToHeightRatio; + double leftOut = width - widthToUse; + node.setInternalSize(Math.max(height * widthToHeightRatio, MIN_ENTITY_SIZE), Math.max(height, MIN_ENTITY_SIZE)); + node.setInternalLocation(node.getInternalX() + leftOut / 2, node.getInternalY()); + + } + else + { + double heightToUse = height / widthToHeightRatio; + double leftOut = height - heightToUse; + + node.setInternalSize(Math.max(width, MIN_ENTITY_SIZE), Math.max(width / widthToHeightRatio, MIN_ENTITY_SIZE)); + node.setInternalLocation(node.getInternalX(), node.getInternalY() + leftOut / 2); + } + } + + /** + * Find and set the node size - shift the nodes to the right and down to make room for the width and height. + * + * @param entitiesToLayout + * @param relationships + */ + private void resizeAndShiftNodes(InternalNode[] entitiesToLayout) + { + // get maximum node size as percent of screen dimmensions + double nodeSize = getNodeSize(entitiesToLayout); + double halfNodeSize = nodeSize / 2; + + // Resize and shift nodes + for (int i = 0; i < entitiesToLayout.length; i++) + { + InternalNode node = entitiesToLayout[i]; + node.setInternalSize(nodeSize, nodeSize); + node.setInternalLocation(node.getInternalX() + halfNodeSize, node.getInternalY() + halfNodeSize); + } + } + + /** + * Returns the maximum possible node size as a percentage of the width or height in current coord system. + */ + private double getNodeSize(InternalNode[] entitiesToLayout) + { + double width, height; + if (entitiesToLayout.length == 1) + { + width = 0.8; + height = 0.8; + } + else + { + DisplayIndependentDimension minimumDistance = getMinimumDistance(entitiesToLayout); + width = 0.8 * minimumDistance.width; + height = 0.8 * minimumDistance.height; + } + return Math.max(width, height); + } + + /** + * minDistance is the closest that any two points are together. These two points become the center points for the two + * closest nodes, which we wish to make them as big as possible without overlapping. This will be the maximum of + * minDistanceX and minDistanceY minus a bit, lets say 20% We make the recommended node size a square for convenience. + * _______ | | | | | + | | |\ | |___|_\_|_____ | | \ | | | \ | +-|---+ | | | |_______| + */ + private DisplayIndependentDimension getMinimumDistance(InternalNode[] entitiesToLayout) + { + DisplayIndependentDimension horAndVertdistance = new DisplayIndependentDimension(Double.MAX_VALUE, Double.MAX_VALUE); + double minDistance = Double.MAX_VALUE; // the minimum distance between all the nodes + // TODO: Very Slow! + for (int i = 0; i < entitiesToLayout.length; i++) + { + InternalNode layoutEntity1 = entitiesToLayout[i]; + double x1 = layoutEntity1.getInternalX(); + double y1 = layoutEntity1.getInternalY(); + for (int j = i + 1; j < entitiesToLayout.length; j++) + { + InternalNode layoutEntity2 = entitiesToLayout[j]; + double x2 = layoutEntity2.getInternalX(); + double y2 = layoutEntity2.getInternalY(); + double distanceX = Math.abs(x1 - x2); + double distanceY = Math.abs(y1 - y2); + double distance = Math.sqrt(Math.pow(distanceX, 2) + Math.pow(distanceY, 2)); + + if (distance < minDistance) + { + minDistance = distance; + horAndVertdistance.width = distanceX; + horAndVertdistance.height = distanceY; + } + } + } + return horAndVertdistance; + } + + /** + * Calculate the screen bounds, maintaining the + * + * @param realBounds + * @return + */ + private DisplayIndependentRectangle calcScreenBounds(DisplayIndependentRectangle realBounds, + DisplayIndependentRectangle layoutBounds) + { + if (resizeEntitiesAfterLayout) + { // OK to alter aspect ratio + double borderWidth = Math.min(realBounds.width, realBounds.height) / 10.0; // use 10% for the border - 5% on each + // side + return new DisplayIndependentRectangle(realBounds.x + borderWidth / 2.0, realBounds.y + borderWidth / 2.0, + realBounds.width - borderWidth, realBounds.height - borderWidth); + } + else + { // retain layout aspect ratio + double heightAdjustment = realBounds.height / layoutBounds.height; + double widthAdjustment = realBounds.width / layoutBounds.width; + double ratio = Math.min(heightAdjustment, widthAdjustment); + double adjustedHeight = layoutBounds.height * ratio; + double adjustedWidth = layoutBounds.width * ratio; + double adjustedX = realBounds.x + (realBounds.width - adjustedWidth) / 2.0; + double adjustedY = realBounds.y + (realBounds.height - adjustedHeight) / 2.0; + double borderWidth = Math.min(adjustedWidth, adjustedHeight) / 10.0; // use 10% for the border - 5% on each side + return new DisplayIndependentRectangle(adjustedX + borderWidth / 2.0, adjustedY + borderWidth / 2.0, + adjustedWidth - borderWidth, adjustedHeight - borderWidth); + } + } } diff --git a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/BranchView.java b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/BranchView.java index b67ad09f37..44a5cdc253 100644 --- a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/BranchView.java +++ b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/BranchView.java @@ -26,7 +26,7 @@ import java.util.Collection; * second step all branches are positioned while beginning with the latest one (in terms of time stamp). * * @author Andre Dietisheim - * @see VerticallyDistributingLayoutStrategy + * @see VerticallyDistributedSubBranches */ public class BranchView { @@ -40,9 +40,9 @@ public class BranchView private DisplayIndependentRectangle bounds; - private VerticallyDistributingLayoutStrategy layoutStrategy; + private BranchViewLayoutStrategy layoutStrategy; - public BranchView(AbstractBranchPointNode baselineNode, VerticallyDistributingLayoutStrategy layoutStrategy) + public BranchView(AbstractBranchPointNode baselineNode, BranchViewLayoutStrategy layoutStrategy) { branch = baselineNode.getBranch(); this.baselineNode = baselineNode; @@ -55,7 +55,7 @@ public class BranchView { // add a branch to this node BranchPointNode branchpointNode = (BranchPointNode)baselineNode; - addBranchView(branch, branchpointNode.getNextChild(), branchpointNode); + addBranchView(branchpointNode.getNextChild(), branchpointNode); } } @@ -74,7 +74,7 @@ public class BranchView return nodes; } - public VerticallyDistributingLayoutStrategy getLayoutStrategy() + public BranchViewLayoutStrategy getLayoutStrategy() { return layoutStrategy; } @@ -102,7 +102,7 @@ public class BranchView { // add a branch to this node BranchPointNode branchpointNode = (BranchPointNode)node; - addBranchView(branch, branchpointNode.getNextChild(), branchpointNode); + addBranchView(branchpointNode.getNextChild(), branchpointNode); } } } @@ -110,7 +110,7 @@ public class BranchView /** * Adds a sub-branch to the given branch point node with the given baseline node. */ - private void addBranchView(CDOBranch branch, AbstractBranchPointNode baselineNode, BranchPointNode branchPointNode) + private void addBranchView(AbstractBranchPointNode baselineNode, BranchPointNode branchPointNode) { if (baselineNode != null) { diff --git a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/BranchViewLayoutStrategy.java b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/BranchViewLayoutStrategy.java new file mode 100644 index 0000000000..0794c0f359 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/BranchViewLayoutStrategy.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2004 - 2010 Eike Stepper (Berlin, Germany) 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: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.ui.internal.branch.layout; + +import org.eclipse.emf.cdo.ui.internal.branch.item.AbstractBranchPointNode; +import org.eclipse.emf.cdo.ui.internal.branch.item.BranchPointNode; + +import org.eclipse.zest.layouts.dataStructures.DisplayIndependentDimension; + +/** + * @author Eike Stepper + */ +public interface BranchViewLayoutStrategy +{ + + public abstract void layoutBaselineNode(BranchView branchView, AbstractBranchPointNode node); + + /** + * Layout the given node as sibling node to the baseline node (and its siblings). + * + * @param branchView + * the branch view to layout the node to + * @param node + * the node to layout + */ + public abstract void layoutNode(BranchView branchView, AbstractBranchPointNode node, + AbstractBranchPointNode previousNode); + + /** + * Adds the given sub branch to this branch. This strategy distributes the sub-branches equally to the left and to the + * right of this branch. It starts by putting the last sub branch to the right of the current branch and puts the + * previous one to the left etc. . + * + * @param branchPointNode + * the node on the current branch view that the sub-branch view shall be attached to + * @param subBranchView + * the sub branch view to add + * @param branchView + * the branch view + */ + public abstract void layoutSubBranchView(BranchView branchView, BranchView subBranchView, + BranchPointNode branchPointNode); + + /** + * Translates this branch by the given dimension. + */ + public abstract void translate(BranchView branchView, DisplayIndependentDimension dimension); + +} diff --git a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/VerticallyDistributedSubBranches.java b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/VerticallyDistributedSubBranches.java new file mode 100644 index 0000000000..84dbdfda11 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/VerticallyDistributedSubBranches.java @@ -0,0 +1,175 @@ +/** + * Copyright (c) 2004 - 2010 Eike Stepper (Berlin, Germany) 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: + * Andre Dietisheim - initial API and implementation + */ +package org.eclipse.emf.cdo.ui.internal.branch.layout; + +import org.eclipse.emf.cdo.ui.internal.branch.geometry.GeometryUtils; +import org.eclipse.emf.cdo.ui.internal.branch.item.BranchPointNode; +import org.eclipse.emf.cdo.ui.internal.branch.item.BranchTreeUtils; + +import org.eclipse.zest.layouts.dataStructures.DisplayIndependentDimension; +import org.eclipse.zest.layouts.dataStructures.DisplayIndependentRectangle; +import org.eclipse.zest.layouts.dataStructures.InternalNode; + +/** + * A strategy that layouts a branch. A branch centers its (sibling) nodes below each other while using their time stamp + * to set the y coordinate. Sub-Branches are displaced to the right or to the left (left and right sub branches are + * distributed equally). + * <p> + * The current implementation may only layout vertically. + * + * @author Andre Dietisheim + */ +public class VerticallyDistributedSubBranches extends AbstractBranchViewLayoutStrategy +{ + private static final VerticallyDistributedSubBranches RIGHT = new VerticallyDistributedSubBranches() + { + @Override + protected DisplayIndependentDimension getTranslationToBranchPoint(BranchView subBranch, + BranchPointNode branchPointNode) + { + InternalNode branchPointInternalNode = BranchTreeUtils.getInternalNode(branchPointNode); + return new DisplayIndependentDimension( // + // translate branch completely to visible area + Math.abs(subBranch.getBounds().x) + // add branch point position and its width + + branchPointInternalNode.getInternalX() + branchPointInternalNode.getInternalWidth() // + // add padding + + getBranchPadding(), 0); + } + + @Override + protected DisplayIndependentDimension getTranslationToLatterBranch(BranchView subBranch, BranchView latterBranch) + { + DisplayIndependentRectangle latterBranchBounds = latterBranch.getBounds(); + return new DisplayIndependentDimension(// + latterBranchBounds.x + latterBranchBounds.width, 0); + } + }; + + private static final VerticallyDistributedSubBranches LEFT = new VerticallyDistributedSubBranches() + { + @Override + protected DisplayIndependentDimension getTranslationToBranchPoint(BranchView subBranch, + BranchPointNode branchPointNode) + { + InternalNode branchPointInternalNode = BranchTreeUtils.getInternalNode(branchPointNode); + DisplayIndependentRectangle subBranchBounds = subBranch.getBounds(); + return new DisplayIndependentDimension(-( // + // translate completely to invisible area + subBranchBounds.width + subBranchBounds.x + // add branch point position + + branchPointInternalNode.getInternalX() + // add branch padding + + getBranchPadding()), 0); + } + + @Override + protected DisplayIndependentDimension getTranslationToLatterBranch(BranchView subBranch, BranchView latterBranchView) + { + DisplayIndependentRectangle latterBranchBounds = latterBranchView.getBounds(); + return new DisplayIndependentDimension( // + latterBranchBounds.x - getBranchPadding(), 0); + } + }; + + protected VerticallyDistributedSubBranches currentSubBranchStrategy = null; + + @Override + protected void setBranchViewLocation(BranchView branchView, BranchView subBranchView, BranchPointNode branchPointNode) + { + currentSubBranchStrategy = getSubBranchStrategy(currentSubBranchStrategy); + currentSubBranchStrategy.setSubBranchLocation(branchView, subBranchView, branchPointNode); + } + + /** + * Returns the current sub branch strategy. + * + * @return the current sub branch strategy + */ + private VerticallyDistributedSubBranches getSubBranchStrategy(VerticallyDistributedSubBranches currentStrategy) + { + if (currentStrategy == null || currentStrategy == LEFT) + { + return RIGHT; + } + else + { + return LEFT; + } + } + + /** + * Sets the location of the given sub branch in the current branch. Branches are created and located with their + * baseline node at x == 0, y == 0. The bounds of the sub branch (and its sub sub-branches) are from negative + * x-coordinates up to positive x-coordinates. The purpose of this method is to translate the whole sub branch to the + * correct location to the right or to the left of its branch point. + * + * @param subBranchView + * the sub branch to layout in the current branch + * @param branchPointNode + * the branch point node the given sub branch is attached to + * @param branchView + * the branch view + */ + public void setSubBranchLocation(BranchView subBranchView, BranchView branchView, BranchPointNode branchPointNode) + { + // translate branch off the branchPointNode (to the right or to the left) + DisplayIndependentDimension translation = getTranslationToBranchPoint(subBranchView, branchPointNode); + BranchView latterBranch = branchView.getSecondToLastSubBranchView(); + if (latterBranch != null && !GeometryUtils.bottomEndsBefore(subBranchView.getBounds(), latterBranch.getBounds())) + { + // collides vertically with latter sub-branch -> additionally translate off latter branch (to the right or to + // the left) + translation = GeometryUtils.union(translation, getTranslationToLatterBranch(subBranchView, latterBranch)); + } + translate(subBranchView, translation); + branchView.addSubBranchView(subBranchView); + } + + /** + * Returns the offset that's needed to translate the given branch so that it does not collide with the branch point. + * + * @param branchPointNode + * the branch point node + * @param subBranch + * the sub branch + * @return the branch point translation + */ + protected DisplayIndependentDimension getTranslationToBranchPoint(BranchView subBranch, + BranchPointNode branchPointNode) + { + return currentSubBranchStrategy.getTranslationToBranchPoint(subBranch, branchPointNode); + } + + /** + * Returns the offset that's needed to translate the given branch so that it does not collide with the latter branch. + * + * @param subBranch + * the sub branch + * @param latterBranch + * the latter branch + * @return the latter branch translation + */ + protected DisplayIndependentDimension getTranslationToLatterBranch(BranchView subBranch, BranchView latterBranch) + { + return currentSubBranchStrategy.getTranslationToLatterBranch(subBranch, latterBranch); + } + + /** + * Returns the branch padding that shall be applied betweend branches. + * + * @return the branch padding + */ + protected double getBranchPadding() + { + return 60; + } +} diff --git a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/VerticallyDistributingLayoutStrategy.java b/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/VerticallyDistributingLayoutStrategy.java deleted file mode 100644 index 0ae4d287f0..0000000000 --- a/plugins/org.eclipse.emf.cdo.ui.branch/src/org/eclipse/emf/cdo/ui/internal/branch/layout/VerticallyDistributingLayoutStrategy.java +++ /dev/null @@ -1,177 +0,0 @@ -/** - * Copyright (c) 2004 - 2010 Eike Stepper (Berlin, Germany) 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: - * Andre Dietisheim - initial API and implementation - */ -package org.eclipse.emf.cdo.ui.internal.branch.layout; - -import org.eclipse.emf.cdo.ui.internal.branch.geometry.GeometryUtils; -import org.eclipse.emf.cdo.ui.internal.branch.item.BranchPointNode; -import org.eclipse.emf.cdo.ui.internal.branch.item.BranchTreeUtils; - -import org.eclipse.zest.layouts.dataStructures.DisplayIndependentDimension; -import org.eclipse.zest.layouts.dataStructures.DisplayIndependentRectangle; -import org.eclipse.zest.layouts.dataStructures.InternalNode; - -/** - * A strategy that layouts a branch. A branch centers its (sibling) nodes below each other while using their time stamp - * to set the y coordinate. Sub-Branches are displaced to the right or to the left (left and right sub branches are - * distributed equally). - * <p> - * The current implementation may only layout vertically. - * - * @author Andre Dietisheim - */ -public abstract class VerticallyDistributingLayoutStrategy extends AbstractBranchViewLayoutStrategy -{ - public static final SubBranchSproutingStrategy SPROUT_RIGHT = new SubBranchSproutingStrategy() - { - @Override - protected DisplayIndependentDimension getTranslationToBranchPoint(BranchView subBranch, - BranchPointNode branchPointNode) - { - InternalNode branchPointInternalNode = BranchTreeUtils.getInternalNode(branchPointNode); - return new DisplayIndependentDimension( // - // translate branch completely to visible area - Math.abs(subBranch.getBounds().x) - // add branch point position and its width - + branchPointInternalNode.getInternalX() + branchPointInternalNode.getInternalWidth() // - // add padding - + getBranchPadding(), 0); - } - - @Override - protected DisplayIndependentDimension getTranslationToLatterBranch(BranchView subBranch, BranchView latterBranch) - { - DisplayIndependentRectangle latterBranchBounds = latterBranch.getBounds(); - return new DisplayIndependentDimension(// - latterBranchBounds.x + latterBranchBounds.width, 0); - } - - @Override - protected void switchSproutingStrategy() - { - currentSproutingStrategy = SPROUT_LEFT; - } - }; - - public static final SubBranchSproutingStrategy SPROUT_LEFT = new SubBranchSproutingStrategy() - { - @Override - protected DisplayIndependentDimension getTranslationToBranchPoint(BranchView subBranch, - BranchPointNode branchPointNode) - { - InternalNode branchPointInternalNode = BranchTreeUtils.getInternalNode(branchPointNode); - DisplayIndependentRectangle subBranchBounds = subBranch.getBounds(); - return new DisplayIndependentDimension(-( // - // translate completely to invisible area - subBranchBounds.width + subBranchBounds.x - // add branch point position - + branchPointInternalNode.getInternalX() - // add branch padding - + getBranchPadding()), 0); - } - - @Override - protected DisplayIndependentDimension getTranslationToLatterBranch(BranchView subBranch, BranchView latterBranchView) - { - DisplayIndependentRectangle latterBranchBounds = latterBranchView.getBounds(); - return new DisplayIndependentDimension( // - latterBranchBounds.x - getBranchPadding(), 0); - } - - @Override - protected void switchSproutingStrategy() - { - currentSproutingStrategy = SPROUT_RIGHT; - } - }; - - private static SubBranchSproutingStrategy currentSproutingStrategy = null; - - @Override - protected void doSetBranchViewLocation(BranchView branchView, BranchView subBranchView, - BranchPointNode branchPointNode) - { - currentSproutingStrategy.setSubBranchLocation(branchView, subBranchView, branchPointNode); - currentSproutingStrategy.switchSproutingStrategy(); - } - - /** - * A layout strategy that handles the layout of sub branches in this branch - */ - protected static abstract class SubBranchSproutingStrategy extends VerticallyDistributingLayoutStrategy - { - /** - * Sets the location of the given sub branch in the current branch. Branches are created and located with their - * baseline node at x == 0, y == 0. The bounds of the sub branch (and its sub sub-branches) are from negative - * x-coordinates up to positive x-coordinates. The purpose of this method is to translate the whole sub branch to - * the correct location to the right or to the left of its branch point. - * - * @param subBranchView - * the sub branch to layout in the current branch - * @param subBranchView2 - * @param branchPointNode - * the branch point node the given sub branch is attached to - */ - void setSubBranchLocation(BranchView subBranchView, BranchView branchView, BranchPointNode branchPointNode) - { - // translate branch off the branchPointNode (to the right or to the left) - DisplayIndependentDimension translation = getTranslationToBranchPoint(subBranchView, branchPointNode); - BranchView latterBranch = branchView.getSecondToLastSubBranchView(); - if (latterBranch != null && !GeometryUtils.bottomEndsBefore(subBranchView.getBounds(), latterBranch.getBounds())) - { - // collides vertically with latter sub-branch -> additionally translate off latter branch (to the right or to - // the left) - translation = GeometryUtils.union(translation, getTranslationToLatterBranch(subBranchView, latterBranch)); - } - translate(subBranchView, translation); - branchView.addSubBranchView(subBranchView); - } - - /** - * Returns the offset that's needed to translate the given branch so that it does not collide with the branch point. - * - * @param branchPointNode - * the branch point node - * @param subBranch - * the sub branch - * @return the branch point translation - */ - protected abstract DisplayIndependentDimension getTranslationToBranchPoint(BranchView subBranch, - BranchPointNode branchPointNode); - - /** - * Returns the offset that's needed to translate the given branch so that it does not collide with the latter - * branch. - * - * @param subBranch - * the sub branch - * @param latterBranch - * the latter branch - * @return the latter branch translation - */ - protected abstract DisplayIndependentDimension getTranslationToLatterBranch(BranchView subBranch, - BranchView latterBranch); - - /** - * Switches the current sprouting strategy to the next strategy to apply after the current one . - */ - protected abstract void switchSproutingStrategy(); - - /** - * Returns the branch padding that shall be applied betweend branches. - * - * @return the branch padding - */ - protected double getBranchPadding() - { - return 60; - } - } -} |