예제 #1
0
        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;
        }
예제 #2
0
 public void RemoveChild( SyntacticTreeViewNode child )
 {
     if( this.children.Remove(child) )
         child.parent = null;
 }
예제 #3
0
 public void ClearChildren()
 {
     for( int i = 0; i < this.children.Count; ++i )
         this.children[i].parent = null;
     this.children.Clear();
 }
예제 #4
0
        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]);
        }
예제 #5
0
        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;
            }
        }
예제 #6
0
        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;
            }
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
        }