private void Offset(TreeNode node, MethodCallVisitor visitor) { float xOff = (float)visitor.GetData(_XOffsetData); float yOff = (float)visitor.GetData(_YOffsetData); RectangleF rc = node.Bounds; rc.Offset(xOff, yOff); node.Bounds = rc; }
/// <summary> /// Offset a branch of the tree with the specified values. /// </summary> /// <param name="tiFrom">The root node of the branch to offset.</param> /// <param name="xoff">The x-axis offset.</param> /// <param name="yoff">The y-axis offset.</param> private void OffsetBranch(TreeNode nodeFrom, float xoff, float yoff) { MethodCallVisitor visitor = new MethodCallVisitor(new VisitOperation(this.Offset)); visitor.SetData(_XOffsetData, xoff); visitor.SetData(_YOffsetData, yoff); _tree.WalkTree(nodeFrom, visitor); }
private void Stretch(TreeNode node, MethodCallVisitor visitor) { float factor = (float)visitor.GetData(_StretchFactor); PointF center = (PointF)visitor.GetData(_StretchCenter); PointF pos = node.Center; // Stretch in X direction float xOff = (pos.X - center.X) * factor; node.Center = new PointF(center.X + xOff, pos.Y); }
private void CalcBounds(TreeNode node, MethodCallVisitor visitor) { object data = visitor.GetData(_CalcBoundsData); RectangleF rc; if (data == null) { rc = node.Bounds; } else { rc = Utilities.UnionRects((RectangleF)data, node.Bounds); } visitor.SetData(_CalcBoundsData, rc); }
/// <summary> /// Build the levels of the tree. Each level contain all the nodes from that level. /// </summary> protected void BuildLevels() { int levels; MethodCallVisitor visitor; // Find the number of levels in the tree, i.e. tree depth. visitor = new MethodCallVisitor(new VisitOperation(this.FindMaxLevel)); visitor.SetData(_MaxLevelData, 0); WalkTree(_root, visitor); levels = (int)visitor.GetData(_MaxLevelData) + 1; _treeLevels = new ArrayList(); for (int i = 0; i < levels; i++) { _treeLevels.Add(new ArrayList()); } // Assign each node to its appropriate level. visitor = new MethodCallVisitor(new VisitOperation(this.AssignLevel)); visitor.SetData(_LevelAssignData, _treeLevels); WalkTree(_root, visitor); }
private void AssignLevel(TreeNode node, MethodCallVisitor visitor) { ArrayList levels = (ArrayList)visitor.GetData(_LevelAssignData); ((ArrayList)levels[node.Level]).Add(node); }
private void FindMaxLevel(TreeNode node, MethodCallVisitor visitor) { visitor.SetData(_MaxLevelData, Math.Max(node.Level, (int)visitor.GetData(_MaxLevelData))); }
/// <summary> /// Build the levels of the tree. Each level contain all the nodes from that level. /// </summary> protected void BuildLevels() { int levels; MethodCallVisitor visitor; // Find the number of levels in the tree, i.e. tree depth. visitor = new MethodCallVisitor(new VisitOperation(this.FindMaxLevel)); visitor.SetData(_MaxLevelData, 0); WalkTree(_root, visitor); levels = (int)visitor.GetData(_MaxLevelData) + 1; _treeLevels = new ArrayList(); for(int i = 0; i < levels; i++) _treeLevels.Add(new ArrayList()); // Assign each node to its appropriate level. visitor = new MethodCallVisitor(new VisitOperation(this.AssignLevel)); visitor.SetData(_LevelAssignData, _treeLevels); WalkTree(_root, visitor); }
private void AssignLevel(TreeNode node, MethodCallVisitor visitor) { ArrayList levels = (ArrayList)visitor.GetData(_LevelAssignData); ((ArrayList)levels[node.Level]).Add(node); }
private void FindMaxLevel(TreeNode node, MethodCallVisitor visitor) { visitor.SetData(_MaxLevelData, Math.Max(node.Level, (int)visitor.GetData(_MaxLevelData))); }
public bool Arrange(INode rootNode, TreeLayoutInfo info, LayoutProgress progress) { // Preserve the root position. RectangleF rcRoot = rootNode.Bounds; _tree = new Tree(); if (!_tree.Build(rootNode)) { return(false); } // Place the root at (0, 0) TreeNode root = _tree.Root; root.Center = new PointF(0, 0); // Set root's bisectors double deg = 0; switch (info.Direction) { case TreeLayoutDirection.TopToBottom: deg = 270; break; case TreeLayoutDirection.BottomToTop: deg = 90; break; case TreeLayoutDirection.LeftToRight: deg = 180; break; case TreeLayoutDirection.RightToLeft: deg = 0; break; } root.SetData(_LeftBisectorData, deg); root.SetData(_RightBisectorData, deg + 360); // Update progress int total = _tree.TreeLevels.Count; int current = 0; if (progress != null) { progress(current++, total); } // Iterate through all levels and arrange them for (int l = 0; l < _tree.TreeLevels.Count - 1; l++) { // Update progress if (progress != null) { progress(current++, total); } ArrangeLevel(l, info); } // Offset the whole tree structure float xOff = 0; float yOff = 0; MethodCallVisitor visitor; if (info.KeepRootPosition) { xOff = rcRoot.Left - root.Bounds.Left; yOff = rcRoot.Top - root.Bounds.Top; } else { // Calculate the bounding rect of the entire tree's visitor = new MethodCallVisitor(new VisitOperation(this.CalcBounds)); _tree.WalkTree(root, visitor); RectangleF rc = (RectangleF)visitor.GetData(_CalcBoundsData); xOff = -rc.Left + info.XGap; yOff = -rc.Top + info.YGap; } visitor = new MethodCallVisitor(new VisitOperation(this.Offset)); visitor.SetData(_XOffsetData, xOff); visitor.SetData(_YOffsetData, yOff); _tree.WalkTree(root, visitor); // Apply the stretch factor visitor = new MethodCallVisitor(new VisitOperation(this.Stretch)); visitor.SetData(_StretchFactor, info.StretchFactor); if (info.KeepRootPosition) { visitor.SetData(_StretchCenter, _tree.Root.Center); } else { visitor.SetData(_StretchCenter, new PointF(info.XGap, info.YGap)); } _tree.WalkTree(root, visitor); // Apply the arrangement visitor = new MethodCallVisitor(new VisitOperation(this.Apply)); _tree.WalkTree(_tree.Root, visitor); // Update progress if (progress != null) { progress(total, total); } return(true); }
private void Apply(TreeNode node, MethodCallVisitor visitor) { node.Node.Bounds = node.Bounds; }
public bool Arrange(INode rootNode, TreeLayoutInfo info, LayoutProgress progress) { // Preserve the root position. RectangleF rcRoot = rootNode.Bounds; _tree = new Tree(); if (!_tree.Build(rootNode)) { return(false); } int i, j; float sz, s = 0; // Calculate the size of each level. ArrayList levelSizes = new ArrayList(); for (i = 0; i < _tree.TreeLevels.Count; i++) { ArrayList treeLevel = (ArrayList)_tree.TreeLevels[i]; sz = 0; for (j = 0; j < treeLevel.Count; j++) { if (info.Direction == TreeLayoutDirection.LeftToRight || info.Direction == TreeLayoutDirection.RightToLeft) { sz = Math.Max(sz, ((TreeNode)treeLevel[j]).Bounds.Width); } else { sz = Math.Max(sz, ((TreeNode)treeLevel[j]).Bounds.Height); } } levelSizes.Add(sz); } // Arrange the bottommost level nodes at equal distance. ArrayList lastLevel = (ArrayList)_tree.TreeLevels[_tree.TreeLevels.Count - 1]; for (i = 0; i < lastLevel.Count; i++) { TreeNode node = (TreeNode)lastLevel[i]; RectangleF rc = node.Bounds; if (info.Direction == TreeLayoutDirection.LeftToRight || info.Direction == TreeLayoutDirection.RightToLeft) { rc.Offset(0, s); s += rc.Height + info.NodeDistance; } else { rc.Offset(s, 0); s += rc.Width + info.NodeDistance; } node.Bounds = rc; } // Update progress int total = _tree.TreeLevels.Count; int current = 0; if (progress != null) { progress(current++, total); } // Skip the bottommost level of nodes during arrangement cycle. for (i = _tree.TreeLevels.Count - 2; i >= 0; i--) { // Update progress if (progress != null) { progress(current++, total); } ArrayList treeLevel = (ArrayList)_tree.TreeLevels[i]; for (j = 0; j < treeLevel.Count; j++) { TreeNode node = (TreeNode)treeLevel[j]; // Make this node in the center of its children. if (node.Children.Count > 0) { ArrayList children = node.Children; RectangleF rcTotal = ((TreeNode)children[0]).Bounds; // First node's rectangle. for (int c = 1; c < children.Count; c++) { rcTotal = Utilities.UnionRects(rcTotal, ((TreeNode)children[c]).Bounds); } RectangleF rc = node.Bounds; if (info.Direction == TreeLayoutDirection.LeftToRight || info.Direction == TreeLayoutDirection.RightToLeft) { rc.Offset(0, (rcTotal.Top + rcTotal.Bottom) / 2 - rc.Height / 2); } else { rc.Offset( (rcTotal.Left + rcTotal.Right) / 2 - rc.Width / 2, 0); } node.Bounds = rc; } } // Check if there is a need to offset branches. for (j = 0; j < treeLevel.Count - 1; j++) { for (int k = j; k >= 0; k--) { float dist = BranchDistance(info, (TreeNode)treeLevel[k], (TreeNode)treeLevel[j + 1]); if (dist < info.NodeDistance) { if (info.Direction == TreeLayoutDirection.LeftToRight || info.Direction == TreeLayoutDirection.RightToLeft) { OffsetBranch((TreeNode)treeLevel[j + 1], 0, info.NodeDistance - dist); } else { OffsetBranch((TreeNode)treeLevel[j + 1], info.NodeDistance - dist, 0); } } } } } // Arrange the levels. float mh = 0; s = 0; int iStart; int iEnd; int iGrow; if (info.Direction == TreeLayoutDirection.LeftToRight || info.Direction == TreeLayoutDirection.TopToBottom) { iStart = 0; iEnd = _tree.TreeLevels.Count; iGrow = +1; } else { iStart = _tree.TreeLevels.Count - 1; iEnd = -1; iGrow = -1; } for (i = iStart; (info.Direction == TreeLayoutDirection.LeftToRight || info.Direction == TreeLayoutDirection.TopToBottom) ? i <iEnd : i> iEnd; i += iGrow) { mh = 0; ArrayList treeLevel = (ArrayList)_tree.TreeLevels[i]; for (j = 0; j < treeLevel.Count; j++) { TreeNode node = (TreeNode)treeLevel[j]; float o = 0; if (info.Direction == TreeLayoutDirection.LeftToRight || info.Direction == TreeLayoutDirection.RightToLeft) { o = node.Bounds.Width; float xoff = 0; if (info.Direction == TreeLayoutDirection.RightToLeft) { xoff = (float)levelSizes[i] - o; } node.Bounds = new RectangleF( s + xoff + info.XGap, node.Bounds.Top + info.YGap, node.Bounds.Width, node.Bounds.Height); } else { o = node.Bounds.Height; float yoff = 0; if (info.Direction == TreeLayoutDirection.BottomToTop) { yoff = (float)levelSizes[i] - o; } node.Bounds = new RectangleF( node.Bounds.Left + info.XGap, s + yoff + info.YGap, node.Bounds.Width, node.Bounds.Height); } mh = Math.Max(mh, o); } s += mh + info.LevelDistance; } // Offset the tree as though the root has persisted its position. if (info.KeepRootPosition) { RectangleF rcNewRoot = _tree.Root.Bounds; float xoff = rcRoot.Left - rcNewRoot.Left; float yoff = rcRoot.Top - rcNewRoot.Top; OffsetBranch(_tree.Root, xoff, yoff); } // Apply the arrangement MethodCallVisitor visitor = new MethodCallVisitor(new VisitOperation(this.Apply)); _tree.WalkTree(_tree.Root, visitor); // Update progress if (progress != null) { progress(total, total); } return(true); }
private void Counter(TreeNode node, MethodCallVisitor visitor) { _total++; }
public bool Arrange(INode rootNode, TreeLayoutInfo info, LayoutProgress progress) { // Preserve the root position. RectangleF rcRoot = rootNode.Bounds; _tree = new Tree(); if (!_tree.Build(rootNode)) { return(false); } if (info.KeepRootPosition) { _x = rcRoot.Left; _y = rcRoot.Top; } else { _x = info.XGap; _y = info.YGap; } _total = 0; _current = 0; _progress = progress; // Update progress MethodCallVisitor counter = new MethodCallVisitor( new VisitOperation(this.Counter)); _tree.WalkTree(_tree.Root, counter); // Make sure total is within reasonable bounds float factor = _total / 100; if (factor > 1) { _factor = (int)Math.Floor((double)factor); _total = _total / _factor + 1; } if (progress != null) { progress(_current++, _total); } // Arrange the tree. RArrange(_tree.Root, info); // Offset levels... // Calculate the size of each level. int i, j; float sz; ArrayList levelSizes = new ArrayList(); for (i = 0; i < _tree.TreeLevels.Count; i++) { ArrayList treeLevel = (ArrayList)_tree.TreeLevels[i]; sz = 0; for (j = 0; j < treeLevel.Count; j++) { if (info.Direction == TreeLayoutDirection.LeftToRight || info.Direction == TreeLayoutDirection.RightToLeft) { sz = Math.Max(sz, ((TreeNode)treeLevel[j]).Bounds.Width); } else { sz = Math.Max(sz, ((TreeNode)treeLevel[j]).Bounds.Height); } } levelSizes.Add(sz); } // Perform the offseting. float off = 0; if (info.KeepRootPosition) { if (info.Direction == TreeLayoutDirection.BottomToTop) { off = rcRoot.Top; } if (info.Direction == TreeLayoutDirection.RightToLeft) { off = rcRoot.Left; } } else { // Calculate the space needed. float size = 0; for (int l = 1; l < levelSizes.Count; l++) { size += (float)levelSizes[l]; size += info.LevelDistance; } if (info.Direction == TreeLayoutDirection.LeftToRight || info.Direction == TreeLayoutDirection.RightToLeft) { size += info.XGap; } else { size += info.YGap; } if (info.Direction == TreeLayoutDirection.RightToLeft || info.Direction == TreeLayoutDirection.BottomToTop) { off = size; } } for (i = 0; i < _tree.TreeLevels.Count; i++) { ArrayList treeLevel = (ArrayList)_tree.TreeLevels[i]; for (j = 0; j < treeLevel.Count; j++) { RectangleF rc = ((TreeNode)treeLevel[j]).Bounds; if (info.Direction == TreeLayoutDirection.TopToBottom || info.Direction == TreeLayoutDirection.BottomToTop) { rc.Offset(0, off); } else { rc.Offset(off, 0); } ((TreeNode)treeLevel[j]).Bounds = rc; } switch (info.Direction) { case TreeLayoutDirection.LeftToRight: case TreeLayoutDirection.TopToBottom: off += info.LevelDistance + (float)levelSizes[i]; break; case TreeLayoutDirection.BottomToTop: case TreeLayoutDirection.RightToLeft: off += -(info.LevelDistance + (float)levelSizes[i]); break; } } // Apply the arrangement MethodCallVisitor visitor = new MethodCallVisitor(new VisitOperation(this.Apply)); _tree.WalkTree(_tree.Root, visitor); // Update progress if (progress != null) { progress(_total, _total); } return(true); }