blob: 5d67eb7d023ce741152a3ccda269c257df801efe [file] [log] [blame]
/*******************************************************************************
* Copyright 2005-2007, CHISEL Group, University of Victoria, Victoria, BC,
* Canada. 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: The Chisel Group, University of Victoria
******************************************************************************/
package org.eclipse.zest.core.widgets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.draw2d.Animation;
import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.FreeformViewport;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.LayoutAnimator;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.ScrollPane;
import org.eclipse.draw2d.Viewport;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.graphics.Image;
import org.eclipse.zest.core.widgets.internal.AspectRatioFreeformLayer;
import org.eclipse.zest.core.widgets.internal.ContainerFigure;
import org.eclipse.zest.core.widgets.internal.ExpandGraphLabel;
import org.eclipse.zest.core.widgets.internal.ZestRootLayer;
import org.eclipse.zest.layouts.InvalidLayoutConfiguration;
import org.eclipse.zest.layouts.LayoutAlgorithm;
import org.eclipse.zest.layouts.LayoutEntity;
import org.eclipse.zest.layouts.LayoutRelationship;
import org.eclipse.zest.layouts.LayoutStyles;
import org.eclipse.zest.layouts.algorithms.TreeLayoutAlgorithm;
/*
* A Container than can be added to a Graph. Nodes can be added to this
* container. The container supports collapsing and expanding and has the same
* properties as the nodes. Containers cannot have custom figures.
*
* @author Ian Bull
*/
public class GraphContainer extends GraphNode implements IContainer {
//private static final double CONTAINER_SCALE = 0.75;
private static final double scaledWidth = 300;
private static final double scaledHeight = 200;
private static final int CONTAINER_HEIGHT = 200;
private static final int MIN_WIDTH = 250;
private static final int ANIMATION_TIME = 100;
private static final int SUBLAYER_OFFSET = 2;
private ExpandGraphLabel expandGraphLabel;
//private FreeformLayer container;
//private FreeformLayer edgeLayer;
private List childNodes = null;
private int childAreaHeight = CONTAINER_HEIGHT;
public ZestRootLayer zestLayer;
private ScrollPane scrollPane;
private LayoutAlgorithm layoutAlgorithm;
private boolean isExpanded = false;
//private ScalableFreeformLayeredPane scalledLayer;
private AspectRatioFreeformLayer scalledLayer;
/**
* Creates a new GraphContainer. A GraphContainer may contain nodes,
* and has many of the same properties as a graph node.
* @param graph The graph that the container is being added to
* @param style
*/
public GraphContainer(IContainer graph, int style) {
this(graph, style, "");
}
public GraphContainer(IContainer graph, int style, String text) {
this(graph, style, text, null);
}
public GraphContainer(IContainer graph, int style, String text, Image image) {
super(graph, style, text, image);
initModel(graph, text, image);
close(false);
childNodes = new ArrayList();
}
/**
* Custom figures cannot be set on a GraphContainer.
*/
public void setCustomFigure(IFigure nodeFigure) {
throw new RuntimeException("Operation not supported: Containers cannot have custom figures");
}
/*
* (non-Javadoc)
* @see org.eclipse.mylar.zest.core.widgets.GraphItem#getItemType()
public int getItemType() {
return GraphItem.CONTAINER;
}
/**
* Gets the figure for this container.
*/
public IFigure getNodeFigure() {
return this.nodeFigure;
}
/**
* Close this node.
* @param animate
*/
public void close(boolean animate) {
if (animate) {
Animation.markBegin();
}
isExpanded = false;
expandGraphLabel.setExpandedState(ExpandGraphLabel.CLOSED);
Rectangle newBounds = scrollPane.getBounds().getCopy();
newBounds.height = 0;
//this.nodeFigure.setConstraint(scrollPane, newBounds);
//this.nodeFigure.revalidate();
scrollPane.setSize(scrollPane.getSize().width, 0);
updateFigureForModel(this.zestLayer);
scrollPane.setVisible(false);
//setSize(expandGraphLabel.getSize().width, expandGraphLabel.getSize().height);
List children = this.zestLayer.getChildren();
for (Iterator iterator = children.iterator(); iterator.hasNext();) {
IFigure child = (IFigure) iterator.next();
GraphItem item = getGraph().getGraphItem(child);
item.setVisible(false);
}
Rectangle containerBounds = new Rectangle(this.getLocation(), new Dimension(this.getSize().width, CONTAINER_HEIGHT + this.expandGraphLabel.getSize().height));
moveNodesUp(containerBounds, this);
if (animate) {
Animation.run(ANIMATION_TIME);
}
//this.nodeFigure.getUpdateManager().performUpdate();
updateFigureForModel(nodeFigure);
}
private static void addNodeToOrderedList(List orderedNodeList, GraphNode node) {
Iterator orderedNodeIterator = orderedNodeList.iterator();
int counter = 0;
while (orderedNodeIterator.hasNext()) {
// Look through the list of nodes below and find the right spot for this
GraphNode nextOrderedNode = (GraphNode) orderedNodeIterator.next();
if (nextOrderedNode.getLocation().y + nextOrderedNode.getBounds().height > node.getLocation().y + node.getBounds().height) {
break;
}
counter++;
}
// Place this in the right location
orderedNodeList.add(counter, node);
}
/**
* Gets all the nodes below the yValue. The nodes are returned in order.
* @param nodes
* @param yValue
* @return
*/
private static List getOrderedNodesBelowY(List nodes, int yValue, GraphNode yValueNode) {
Iterator iterator = nodes.iterator();
LinkedList orderedNode = new LinkedList();
while (iterator.hasNext()) {
GraphNode node = (GraphNode) iterator.next();
if (node == yValueNode) {
continue;
}
if (node.getLocation().y + node.getBounds().height > yValue) {
// This node is below the container
addNodeToOrderedList(orderedNode, node);
}
}
// Convert this to an arrayList for faster access
List arrayList = new ArrayList();
iterator = orderedNode.iterator();
while (iterator.hasNext()) {
arrayList.add(iterator.next());
}
return arrayList;
}
/**
* Checks if the node intersects the stripe between left and right
* @param left
* @param right
* @param node
* @return
*/
private static boolean nodeInStripe(int left, int right, GraphNode node) {
return (node.getBounds().x < right && node.getBounds().x + node.getBounds().width > left);
}
void pack(Graph g) {
GraphNode highestNode = getHighestNode(g);
moveNodesUp(highestNode.getBounds(), highestNode);
}
/**
*
* @param g
* @return
*/
static GraphNode getHighestNode(Graph g) {
Iterator iterator = g.getNodes().iterator();
GraphNode lowest /* highest on the screen */= null;
while (iterator.hasNext()) {
GraphNode node = (GraphNode) iterator.next();
if (lowest == null || lowest.getBounds().y > node.getBounds().y) {
lowest = node;
}
}
return lowest;
}
/**
* Move the nodes below this node up
* @param containerBounds
* @param graphContainer
*/
private void moveNodesUp(Rectangle containerBounds, GraphNode graphContainer) {
// Get all nodes below this container, in order
List orderedNodesBelowY = getOrderedNodesBelowY(parent.getNodes(), containerBounds.y, graphContainer);
int leftSide = containerBounds.x;
int rightSide = containerBounds.x + containerBounds.width;
List nodesToConsider = new LinkedList();
for (int i = 0; i < orderedNodesBelowY.size(); i++) {
nodesToConsider.add(orderedNodesBelowY.get(i));
}
addNodeToOrderedList(orderedNodesBelowY, graphContainer);
while (nodesToConsider.size() > 0) {
GraphNode node = (GraphNode) nodesToConsider.get(0);
if (nodeInStripe(leftSide, rightSide, node)) {
leftSide = Math.min(leftSide, node.getBounds().x);
rightSide = Math.max(rightSide, node.getBounds().x + node.getBounds().width);
// If this node is in the stripe, move it up
// the previous node
GraphNode previousNode = null;
int i = 0;
for (; i < orderedNodesBelowY.size(); i++) {
if (orderedNodesBelowY.get(i) == node) {
break;
}
}
int j = i - 1;
while (j >= 0) {
GraphNode pastNode = (GraphNode) orderedNodesBelowY.get(j);
//if (nodeInStripe(leftSide, rightSide, pastNode)) {
if (nodeInStripe(node.getBounds().x, node.getBounds().x + node.getBounds().width, pastNode)) {
previousNode = pastNode;
break;
}
j--;
}
if (previousNode == null) {
previousNode = graphContainer;
}
int previousLocation = previousNode.getBounds().y + previousNode.getBounds().height + 2;
orderedNodesBelowY.remove(i);
node.setLocation(node.getLocation().x, previousLocation);
addNodeToOrderedList(orderedNodesBelowY, node);
}
nodesToConsider.remove(node);
}
}
/**
* Open the container. This opens the graph container to
* show the nodes within and update the twistie
*/
public void open(boolean animate) {
if (animate) {
Animation.markBegin();
}
isExpanded = true;
expandGraphLabel.setExpandedState(ExpandGraphLabel.OPEN);
scrollPane.setSize(computeChildArea());
scrollPane.setVisible(true);
//setSize(expandGraphLabel.getSize().width, expandGraphLabel.getSize().height + expandedHeight - SUBLAYER_OFFSET);
List children = this.zestLayer.getChildren();
for (Iterator iterator = children.iterator(); iterator.hasNext();) {
IFigure child = (IFigure) iterator.next();
GraphItem item = getGraph().getGraphItem(child);
item.setVisible(true);
}
updateFigureForModel(nodeFigure);
Rectangle containerBounds = new Rectangle(this.getLocation(), new Dimension(this.getSize().width, CONTAINER_HEIGHT + this.expandGraphLabel.getSize().height));
//moveIntersectedNodes(containerBounds, this);
moveNodesDown(containerBounds, this);
moveNodesUp(containerBounds, this);
//pack(graph);
if (animate) {
Animation.run(ANIMATION_TIME);
}
this.getFigure().getUpdateManager().performValidation();
//this.nodeFigure.getUpdateManager().performUpdate();
}
/**
*
* @param containerBounds
* @param graphContainer
*/
private void moveNodesDown(Rectangle containerBounds, GraphContainer graphContainer) {
// Find all nodes below here
List nodesBelowHere = getOrderedNodesBelowY(parent.getNodes(), containerBounds.y, graphContainer);
Iterator nodesBelowHereIterator = nodesBelowHere.iterator();
List nodesToMove = new LinkedList();
int left = containerBounds.x;
int right = containerBounds.x + containerBounds.width;
while (nodesBelowHereIterator.hasNext()) {
GraphNode node = (GraphNode) nodesBelowHereIterator.next();
if (nodeInStripe(left, right, node)) {
nodesToMove.add(node);
left = Math.min(left, node.getBounds().x);
right = Math.max(right, node.getBounds().x + node.getBounds().width);
}
}
List intersectingNodes = intersectingNodes(containerBounds, nodesToMove, graphContainer);
int delta = getMaxMovement(containerBounds, intersectingNodes);
if (delta > 0) {
shiftNodesDown(nodesToMove, delta);
}
}
void highlightNode(GraphNode node) {
}
void highlightEdge(GraphConnection connection) {
}
void highlightNode(GraphContainer container) {
}
void unhighlightNode(GraphNode node) {
}
void unhighlightNode(GraphContainer container) {
}
// /**
// * Gets a list of nodes below the given node
// * @param node
// * @return
// */
// private List getNodesBelow(int y, List nodes) {
// Iterator allNodes = nodes.iterator();
// LinkedList result = new LinkedList();
// while (allNodes.hasNext()) {
// GraphNode nextNode = (GraphNode) allNodes.next();
// int top = nextNode.getLocation().y;
// if (top > y) {
// result.add(nextNode);
// }
// }
// return result;
// }
/**
* Checks all the nodes in the list of nodesToCheck to see if they intersect with the bounds set
* @param node
* @param nodesToCheck
* @return
*/
private List intersectingNodes(Rectangle bounds, List nodesToCheck, GraphNode node) {
List result = new LinkedList();
Iterator nodes = nodesToCheck.iterator();
while (nodes.hasNext()) {
GraphNode nodeToCheck = (GraphNode) nodes.next();
if (node == nodeToCheck) {
continue;
}
if (bounds.intersects(nodeToCheck.getBounds())) {
result.add(nodeToCheck);
}
}
return result;
}
/**
* Gets the max distance the intersecting nodes need to be shifted to make room for the expanding node
* @param bounds
* @param nodesToMove
* @return
*/
private int getMaxMovement(Rectangle bounds, List nodesToMove) {
Iterator iterator = nodesToMove.iterator();
int maxMovement = 0;
while (iterator.hasNext()) {
GraphNode node = (GraphNode) iterator.next();
int yValue = node.getLocation().y;
int distanceFromBottom = (bounds.y + bounds.height) - yValue;
maxMovement = Math.max(maxMovement, distanceFromBottom);
}
return maxMovement + 3;
}
/**
* Shifts a collection of nodes down.
* @param nodesToShift
* @param amount
*/
private void shiftNodesDown(List nodesToShift, int amount) {
Iterator iterator = nodesToShift.iterator();
while (iterator.hasNext()) {
GraphNode node = (GraphNode) iterator.next();
node.setLocation(node.getLocation().x, node.getLocation().y + amount);
}
}
// /**
// * This finds the highest Y Value of a set of nodes.
// * @param nodes
// * @return
// */
// private int findSmallestYValue(List nodes) {
// Iterator iterator = nodes.iterator();
// int lowestNode /*highest on the screen*/= Integer.MAX_VALUE - 100; // Subtract 100 so we don't overflow
// while (iterator.hasNext()) {
// GraphNode node = (GraphNode) iterator.next();
// int y = node.getLocation().y;
// lowestNode = Math.min(lowestNode, y);
// }
// return lowestNode;
// }
// /**
// * Clears the nodes that the container intersects as it expands
// * @param containerBounds
// * @param graphContainer
// */
// private void moveIntersectedNodes(Rectangle containerBounds, GraphNode graphContainer) {
//
// List nodesBelowHere = getNodesBelow(this.getLocation().y, graphContainer.getGraphModel().getNodes());
// List intersectingNodes = intersectingNodes(containerBounds, nodesBelowHere, graphContainer);
// int delta = getMaxMovement(containerBounds, intersectingNodes);
// shiftNodesDown(intersectingNodes, delta);
//
// int lowestNode /*highest on the screen*/= findSmallestYValue(intersectingNodes);
// nodesBelowHere = getNodesBelow(lowestNode, nodesBelowHere);
//
// while (nodesBelowHere.size() > 0) {
// Iterator intersectingNodeIterator = intersectingNodes.iterator();
// List nodesMovedInLastIteration = new LinkedList();
// while (intersectingNodeIterator.hasNext()) {
// GraphNode node = (GraphNode) intersectingNodeIterator.next();
// intersectingNodes = intersectingNodes(node.getBounds(), nodesBelowHere, node);
// delta = getMaxMovement(node.getBounds(), intersectingNodes);
// if (delta > 0) {
// shiftNodesDown(intersectingNodes, delta);
// nodesMovedInLastIteration.addAll(intersectingNodes);
// }
// }
// lowestNode /*highest on the screen*/= findSmallestYValue(nodesMovedInLastIteration);
// nodesBelowHere = getNodesBelow(lowestNode, nodesBelowHere);
// intersectingNodes = nodesMovedInLastIteration;
// }
// }
/**
* Gets the graph that this container has been added to.
*/
public Graph getGraph() {
return this.graph.getGraph();
}
public int getItemType() {
return CONTAINER;
}
/**
*
*/
public void setLayoutAlgorithm(LayoutAlgorithm algorithm, boolean applyLayout) {
this.layoutAlgorithm = algorithm;
if (applyLayout) {
applyLayout();
}
}
public void applyLayout() {
if ((this.getNodes().size() == 0)) {
return;
}
int layoutStyle = 0;
if (checkStyle(ZestStyles.NODES_NO_LAYOUT_RESIZE)) {
layoutStyle = LayoutStyles.NO_LAYOUT_NODE_RESIZING;
}
if (layoutAlgorithm == null) {
layoutAlgorithm = new TreeLayoutAlgorithm(layoutStyle);
}
layoutAlgorithm.setStyle(layoutAlgorithm.getStyle() | layoutStyle);
// calculate the size for the layout algorithm
//Dimension d = this.scalledLayer.getSize();
Dimension d = new Dimension();
d.width = (int) scaledWidth;
d.height = (int) scaledHeight;
d.width = d.width - 10;
d.height = d.height - 10;
//if (d.height <= 0) {
//d.height = (CONTAINER_HEIGHT);
//}
//d.scale(1 / this.scalledLayer.getScale());
if (d.isEmpty()) {
return;
}
LayoutRelationship[] connectionsToLayout = getGraph().getConnectionsToLayout(getNodes());
LayoutEntity[] nodesToLayout = getGraph().getNodesToLayout(getNodes());
try {
Animation.markBegin();
layoutAlgorithm.applyLayout(nodesToLayout, connectionsToLayout, 25, 25, d.width - 50, d.height - 50, false, false);
Animation.run(ANIMATION_TIME);
getFigure().getUpdateManager().performUpdate();
} catch (InvalidLayoutConfiguration e) {
e.printStackTrace();
}
}
/**
* Get the scale for this container. This is the scale applied to the children contained within
* @return
*/
public double getScale() {
return this.scalledLayer.getScale();
}
/**
* Set the scale for this container. This is the scale applied to the children contained within.
* @param scale
*/
public void setScale(double scale) {
this.scalledLayer.setScale(scale);
}
/***************************************************************************
* NON API MEMBERS
**************************************************************************/
protected void initFigure() {
nodeFigure = createContainerFigure();
}
/**
* This is a small class to help represent the size of the container. It should only be
* used in the computeContainerSize method.
*/
class ContainerDimension {
int width;
int labelHeight;
int expandedHeight;
}
/**
* Computes size of the scroll pane that the child nodes will be placed in.
* @return
*/
private Dimension computeChildArea() {
ContainerDimension containerDimension = computeContainerSize();
Dimension dimension = new Dimension();
dimension.width = containerDimension.width;
dimension.height = containerDimension.expandedHeight - containerDimension.labelHeight + SUBLAYER_OFFSET;
return dimension;
}
/**
* Computes the desired size of the container. This method uses the
* minimum size, label size and setSize to compute the size.
* @return
*/
private ContainerDimension computeContainerSize() {
ContainerDimension dimension = new ContainerDimension();
int labelHeight = expandGraphLabel.getPreferredSize().height;
int labelWidth = expandGraphLabel.getPreferredSize().width;
if (labelWidth < MIN_WIDTH) {
labelWidth = MIN_WIDTH;
expandGraphLabel.setPreferredSize(labelWidth, labelHeight);
}
if (labelHeight < 30) {
labelHeight = 30;
}
dimension.labelHeight = labelHeight;
dimension.width = labelWidth;
dimension.width = Math.max(dimension.width, this.size.width);
dimension.expandedHeight = dimension.labelHeight + childAreaHeight - SUBLAYER_OFFSET;
dimension.expandedHeight = Math.max(dimension.expandedHeight, this.size.height);
return dimension;
}
/*
private double computeChildScale() {
Dimension childArea = computeChildArea();
double widthScale = childArea.width / scaledWidth;
double heightScale = childArea.height / scaledHeight;
return Math.min(widthScale, heightScale);
}
*/
private double computeHeightScale() {
Dimension childArea = computeChildArea();
double heightScale = childArea.height / scaledHeight;
return heightScale;
}
private double computeWidthScale() {
Dimension childArea = computeChildArea();
double widthScale = childArea.width / scaledWidth;
return widthScale;
}
private IFigure createContainerFigure() {
GraphContainer node = this;
IFigure containerFigure = new ContainerFigure();
containerFigure.setOpaque(true);
containerFigure.addLayoutListener(LayoutAnimator.getDefault());
containerFigure.setLayoutManager(new FreeformLayout());
expandGraphLabel = new ExpandGraphLabel(this, node.getText(), node.getImage(), false);
expandGraphLabel.setText(getText());
expandGraphLabel.setImage(getImage());
ContainerDimension containerDimension = computeContainerSize();
scrollPane = new ScrollPane();
scrollPane.addLayoutListener(LayoutAnimator.getDefault());
Viewport viewport = new FreeformViewport();
/*
* This is the code that helps remove the scroll bars moving when the nodes
* are dragged.
*
viewport.setHorizontalRangeModel(new DefaultRangeModel() {
public void setAll(int min, int ext, int max) {
System.out.println("Max: " + max + " : current Max: " + getMaximum());
if (max < getMaximum()) {
max = getMaximum();
}
super.setAll(min, ext, max);
}
public void setMaximum(int maximum) {
// TODO Auto-generated method stub
System.out.println("Max: " + maximum + " : current Max: " + getMaximum());
if (maximum < getMaximum()) {
return;
}
super.setMaximum(maximum);
}
});
*/
scrollPane.setViewport(viewport);
viewport.addLayoutListener(LayoutAnimator.getDefault());
scrollPane.setScrollBarVisibility(ScrollPane.AUTOMATIC);
//scalledLayer = new ScalableFreeformLayeredPane();
scalledLayer = new AspectRatioFreeformLayer("debug label");
scalledLayer.addLayoutListener(LayoutAnimator.getDefault());
//scalledLayer.setScale(computeChildScale());
scalledLayer.setScale(computeWidthScale(), computeHeightScale());
//container = new FreeformLayer();
//edgeLayer = new FreeformLayer();
zestLayer = new ZestRootLayer();
zestLayer.addLayoutListener(LayoutAnimator.getDefault());
//container.addLayoutListener(LayoutAnimator.getDefault());
//edgeLayer.addLayoutListener(LayoutAnimator.getDefault());
//scalledLayer.add(edgeLayer);
//scalledLayer.add(container);
scalledLayer.add(zestLayer);
//container.setLayoutManager(new FreeformLayout());
zestLayer.setLayoutManager(new FreeformLayout());
scrollPane.setSize(computeChildArea());
scrollPane.setLocation(new Point(0, containerDimension.labelHeight - SUBLAYER_OFFSET));
scrollPane.setForegroundColor(ColorConstants.gray());
expandGraphLabel.setBackgroundColor(getBackgroundColor());
expandGraphLabel.setForegroundColor(getForegroundColor());
expandGraphLabel.setLocation(new Point(0, 0));
containerFigure.add(scrollPane);
containerFigure.add(expandGraphLabel);
scrollPane.getViewport().setContents(scalledLayer);
scrollPane.setBorder(new LineBorder());
return containerFigure;
}
protected void updateFigureForModel(IFigure currentFigure) {
expandGraphLabel.setTextT(getText());
expandGraphLabel.setImage(getImage());
expandGraphLabel.setFont(getFont());
if (highlighted == HIGHLIGHT_ON) {
expandGraphLabel.setForegroundColor(getForegroundColor());
expandGraphLabel.setBackgroundColor(getHighlightColor());
}
// @tag ADJACENT : Removed highlight adjacent
/*
else if (highlighted == HIGHLIGHT_ADJACENT) {
expandGraphLabel.setForegroundColor(getForegroundColor());
expandGraphLabel.setBackgroundColor(getHighlightAdjacentColor());
}
*/
else {
expandGraphLabel.setForegroundColor(getForegroundColor());
expandGraphLabel.setBackgroundColor(getBackgroundColor());
}
ContainerDimension containerDimension = computeContainerSize();
expandGraphLabel.setSize(containerDimension.width, containerDimension.labelHeight);
if (isExpanded) {
//setSize(expandGraphLabel.getSize().width, expandGraphLabel.getSize().height + expandedHeight - SUBLAYER_OFFSET);
setSize(containerDimension.width, containerDimension.expandedHeight);
} else {
setSize(containerDimension.width, containerDimension.labelHeight);
}
scrollPane.setLocation(new Point(expandGraphLabel.getLocation().x, expandGraphLabel.getLocation().y + containerDimension.labelHeight - SUBLAYER_OFFSET));
//scrollPane.setLocation(new Point(0, labelHeight - SUBLAYER_OFFSET));
//Rectangle bounds = expandGraphLabel.getBounds().getCopy();
//Rectangle newBounds = new Rectangle(new Point(bounds.x, bounds.y + labelHeight - SUBLAYER_OFFSET), scrollPane.getSize());
//figure.setConstraint(scrollPane, newBounds);
/*
size.width = labelWidth;
if (scrollPane.getSize().height > 0) {
size.height = labelHeight + scrollPane.getSize().height - SUBLAYER_OFFSET;
} else {
size.height = labelHeight;
}
refreshLocation();
figure.getUpdateManager().performValidation();
*/
}
protected void refreshLocation() {
if (nodeFigure == null || nodeFigure.getParent() == null) {
return; // node figure has not been created yet
}
GraphNode node = this;
Point loc = node.getLocation();
ContainerDimension containerDimension = computeContainerSize();
Dimension size = new Dimension();
expandGraphLabel.setSize(containerDimension.width, containerDimension.labelHeight);
this.childAreaHeight = computeChildArea().height;
if (isExpanded) {
size.width = containerDimension.width;
size.height = containerDimension.expandedHeight;
} else {
size.width = containerDimension.width;
size.height = containerDimension.labelHeight;
}
Rectangle bounds = new Rectangle(loc, size);
nodeFigure.getParent().setConstraint(nodeFigure, bounds);
scrollPane.setLocation(new Point(expandGraphLabel.getLocation().x, expandGraphLabel.getLocation().y + containerDimension.labelHeight - SUBLAYER_OFFSET));
scrollPane.setSize(computeChildArea());
scalledLayer.setScale(computeWidthScale(), computeHeightScale());
}
void addConnectionFigure(PolylineConnection connection) {
nodeFigure.add(connection);
//zestLayer.addConnection(connection);
}
void addNode(GraphNode node) {
zestLayer.addNode(node.getNodeFigure());
this.childNodes.add(node);
//container.add(node.getNodeFigure());
//graph.registerItem(node);
}
void addNode(GraphContainer container) {
// Containers cannot be added to other containers (yet)
}
public List getNodes() {
return this.childNodes;
}
void paint() {
Iterator iterator = getNodes().iterator();
while (iterator.hasNext()) {
GraphNode node = (GraphNode) iterator.next();
node.paint();
}
}
}