public void AddChild( SyntacticTreeViewNode child ) { if( child == null ) throw new ArgumentNullException("child"); if( child.Parent != null ) child.Parent.RemoveChild(child); this.children.Add(child); child.parent = this; }
public void RemoveChild( SyntacticTreeViewNode child ) { if( this.children.Remove(child) ) child.parent = null; }
public void ClearChildren() { for( int i = 0; i < this.children.Count; ++i ) this.children[i].parent = null; this.children.Clear(); }
private void UpdateNodeStyleRecursively( SyntacticTreeViewNode node ) { NodeStyle base_style; if( node.Parent == null ) base_style = this.top_level_node_style; else if( node.Children.Count == 0 ) base_style = this.leaf_node_style; else base_style = this.internal_node_style; NodeStyle custom_style = null; this.style_map.TryGetValue(node, out custom_style); var layout_node = this.node_map[node]; layout_node.BackBrush = custom_style != null ? (custom_style.BackBrush ?? base_style.BackBrush) : base_style.BackBrush; layout_node.LabelBrush = custom_style != null ? (custom_style.LabelBrush ?? base_style.LabelBrush) : base_style.LabelBrush; layout_node.BorderPen = custom_style != null ? (custom_style.BorderPen ?? base_style.BorderPen) : base_style.BorderPen; for( int i = 0; i < node.Children.Count; ++i ) this.UpdateNodeStyleRecursively(node.Children[i]); }
private void UpdateBoundingBoxRecursively( SyntacticTreeViewNode node ) { var label_size = this.Graph.MeasureString(this.Font, node.Name); var node_box = new RectangleF( -this.label_margin - label_size.Width / 2, -this.label_margin - label_size.Height / 2, 2 * this.label_margin + label_size.Width, 2 * this.label_margin + label_size.Height); node.NodeBox = node_box; node.NodeBBox = new RectangleF( node_box.X - this.horizontal_space, node_box.Y - this.vertical_space, node_box.Width + 2 * this.horizontal_space, node_box.Height + 2 * this.vertical_space); if( node.Children.Count > 0 ) { for( int i = 0; i < node.Children.Count; ++i ) this.UpdateBoundingBoxRecursively(node.Children[i]); if( node.Children.Count == 1 ) { var child_bbox = node.Children[0].SubtreeBBox; float left = Math.Min(node.NodeBBox.Left, child_bbox.Left); float right = Math.Max(node.NodeBBox.Right, child_bbox.Right); node.SubtreeBBox = new RectangleF( left, node.NodeBBox.Top, right - left, node.NodeBBox.Height + child_bbox.Height); node.Children[0].OffsetFromParent = new PointF(0, node.NodeBBox.Bottom - child_bbox.Top); } else { float children_width = 0; for( int i = 0; i < node.Children.Count; ++i ) children_width += node.Children[i].SubtreeBBox.Width; float horizontal_center = children_width + node.Children[0].SubtreeBBox.Left - node.Children[node.Children.Count - 1].SubtreeBBox.Right; horizontal_center /= 2; float child_offs = -horizontal_center + node.Children[0].SubtreeBBox.Left; float top = 0; float bottom = 0; for( int i = 0; i < node.Children.Count; ++i ) { // Set child's offset var child_bbox = node.Children[i].SubtreeBBox; node.Children[i].OffsetFromParent = new PointF(child_offs - child_bbox.Left, node.NodeBBox.Bottom - child_bbox.Top); child_offs += child_bbox.Width; // Find the most top and most bottom bbox values. if( top > child_bbox.Top ) top = child_bbox.Top; if( bottom < child_bbox.Bottom ) bottom = child_bbox.Bottom; } float left = Math.Min(node.NodeBBox.Left, node.Children[0].OffsetFromParent.X + node.Children[0].SubtreeBBox.Left); float right = Math.Max(node.NodeBBox.Right, node.Children[node.Children.Count - 1].OffsetFromParent.X + node.Children[node.Children.Count - 1].SubtreeBBox.Right); node.SubtreeBBox = new RectangleF( left, node.NodeBBox.Top, right - left, node.NodeBBox.Height + bottom - top); } } else { node.SubtreeBBox = node.NodeBBox; } }
private void LayoutChildrenRecursively( SyntacticTreeViewNode parent ) { var parent_layout = this.node_map[parent]; for( int i = 0; i < parent.Children.Count; ++i ) { var node = parent.Children[i]; var layout_node = this.node_map[node]; // Layout the child layout_node.Position = new PointF( parent_layout.Position.X + node.OffsetFromParent.X, parent_layout.Position.Y + node.OffsetFromParent.Y); layout_node.Box = node.NodeBox; layout_node.LabelOffset = new PointF( node.NodeBox.Left + this.label_margin, node.NodeBox.Top + this.label_margin); // Layout the child's children this.LayoutChildrenRecursively(node); } // Layout edges foreach( var edge in this.Graph.OutEdgesOf(parent_layout) ) { edge.StartPosition = edge.StartNode.Position; edge.EndPosition = edge.EndNode.Position; } }
public void MarkNode( SyntacticTreeViewNode node, Color back_color ) { if( node == null ) throw new ArgumentNullException("node"); var layout_node = this.node_map[node]; NodeStyle custom_style; if( this.style_map.TryGetValue(node, out custom_style) ) { if( custom_style.BorderPen != null ) { custom_style.BorderPen.Dispose(); custom_style.BorderPen = null; } if( custom_style.LabelBrush != null ) { custom_style.LabelBrush.Dispose(); custom_style.LabelBrush = null; } } else { custom_style = new NodeStyle(); this.style_map.Add(node, custom_style); } if( custom_style.BackBrush == null ) custom_style.BackBrush = new SolidBrush(back_color); else custom_style.BackBrush.Color = back_color; this.FlagUpdate(false); }
public void AddTopLevelNode( string symbol_name, int child_count ) { int tln_count = this.top_level_nodes.Count; if( child_count > tln_count ) throw new ArgumentOutOfRangeException(string.Format( "Insufficient top level nodes ({0}) to match child count ({1}).", tln_count, child_count)); var new_node = new SyntacticTreeViewNode(symbol_name); for( int i = 0; i < child_count; ++i ) new_node.AddChild(this.top_level_nodes[tln_count - child_count + i]); for( int i = 0; i < child_count; ++i ) this.top_level_nodes.RemoveAt(this.top_level_nodes.Count - 1); this.top_level_nodes.Add(new_node); // Update graph var new_layout_node = new Node() { Shape = NodeShape.Rectangle, BorderType = NodeBorderType.Single, LabelText = new_node.Name, LabelFont = this.Font, }; this.node_map.Add(new_node, new_layout_node); this.Graph.Nodes.Add(new_layout_node); for( int i = 0; i < child_count; ++i ) this.Graph.Edges.Add(new Edge() { StartNode = new_layout_node, EndNode = this.node_map[new_node.Children[i]], LinePen = this.edge_pen, }); this.FlagUpdate(true); }