Example #1
0
        Rectangle LayoutSubTopics(Topic parent, Topic[] subTopics, Vector4 vector, XList <int> rows, XList <int> columns, int parentRow, int parentCol, MindMapLayoutArgs e)
        {
            if (parent == null)
            {
                throw new ArgumentNullException();
            }

            if (rows.IsEmpty || columns.IsEmpty)
            {
                return(Rectangle.Empty);
            }

            if (parent.Folded || parent.Children.IsEmpty)
            {
                return(Rectangle.Empty);
            }

            int   vSpace = e.ItemsSpace;
            Topic root   = parent.GetRoot();

            Rectangle rectFull = Rectangle.Empty;
            Point     pp       = PaintHelper.CenterPoint(root.ContentBounds);

            int   fullHeight = GetYPos(rows.Count - 1, vSpace, rows);
            int   x          = vector == Vector4.Left ? root.Left - e.LayerSpace : root.Right + e.LayerSpace;
            int   y          = pp.Y - (fullHeight / 2) - 30;
            int   hSpace     = 10;
            Topic previous   = parent == root ? root : parent.ParentTopic;
            int   prevRow    = 0;

            for (int i = 0, n = subTopics.Length; i < n; ++i)
            {
                Topic subTopic = subTopics[i];
                subTopic.Vector = vector;
                int row = 0, column = 0;
                switch (vector)
                {
                case Vector4.Top:
                    subTopic.Location = new Point(root.Bounds.Left - (subTopic.Width - root.Width) / 2, parent.Location.Y - e.LayerSpace - subTopic.Size.Height);
                    break;

                case Vector4.Left:
                case Vector4.Right:
                default:
                    if (subTopic.Type == TopicType.Barrier)
                    {
                        column = parentCol - subTopics.Length + i;
                        row    = parentRow;
                    }
                    else
                    {
                        column = parentCol + (subTopic.Folded ? 0 : subTopic.Children.Count) + 1;
                        row    = parentRow + 1;
                        if (subTopic.Type == TopicType.Escalation)
                        {
                            int maxUncleRow = 0;
                            if (parent.ParentTopic != null)
                            {
                                XList <Topic> children  = parent.ParentTopic.Children;
                                int           nextIndex = children.IndexOf(parent) + 1;
                                if (nextIndex < children.Count)
                                {
                                    maxUncleRow = CalculateMaxRow(children[nextIndex], children.ToArray());
                                }
                            }

                            int maxSiblingRow = 0;
                            int prevIndex     = i - 1;
                            if (prevIndex >= 0)
                            {
                                maxSiblingRow = CalculateMaxRow(parent.Children[prevIndex], parent.Children.ToArray());
                            }
                            row += maxSiblingRow + maxUncleRow;
                        }
                        else if (parent.IsRoot)
                        {
                            int prevIndex = i - 1;
                            if (prevIndex >= 0)
                            {
                                row += CalculateMaxRow(subTopics[prevIndex], subTopics);
                            }
                        }
                    }
                    Point pt = new Point(GetXPos(column, hSpace, columns, vector), GetYPos(row, vSpace, rows));
                    if (subTopic.Type == TopicType.Barrier)
                    {
                        if (vector == Vector4.Left)
                        {
                            pt.X -= (subTopic.ContentBounds.Width - subTopic.Width) / 2;
                        }
                        else
                        {
                            pt.X += (subTopic.ContentBounds.Width - subTopic.Width) / 2;
                        }
                    }
                    subTopic.Location = new Point(vector == Vector4.Left ? x - pt.X: x + pt.X, pt.Y + y);
                    prevRow           = row;
                    break;
                }

                // line
                if (!parent.Folded && subTopic.Type == TopicType.Barrier)
                {
                    var lines = CreateTopicLines(e, previous, subTopic, vector, GetReverseVector(vector));
                    if (lines != null)
                    {
                        parent.Lines.AddRange(lines);
                    }
                }
                subTopic.Lines.Clear();

                Rectangle rectFullSub = LayoutSubTopics(subTopic, subTopic.Children.ToArray(), vector, rows, columns, row, column, e);
                // Threat topic will be drawn as the last element
                if (subTopic.Type == TopicType.Threat || subTopic.Type == TopicType.Consequence || subTopic.Type == TopicType.Escalation)
                {
                    Topic beginNode, endNode;
                    if (subTopic.HasChildren && !subTopic.Folded)
                    {
                        beginNode = subTopic.Children[subTopic.Children.Count - 1];
                        endNode   = subTopic;
                    }
                    else
                    {
                        beginNode = parent;
                        endNode   = subTopic;
                    }
                    var lines = CreateTopicLines(e, beginNode, endNode, vector, GetReverseVector(vector));
                    if (lines != null)
                    {
                        beginNode.Lines.AddRange(lines);
                    }

                    if (subTopic.HasChildren)
                    {
                        int foldBtnSize = FoldingButtonSize;
                        if (vector == Vector4.Left)
                        {
                            subTopic.FoldingButton = new Rectangle(subTopic.Right - foldBtnSize + 4,
                                                                   subTopic.Top + (int)Math.Round((60 - foldBtnSize) / 2.0f, MidpointRounding.AwayFromZero),
                                                                   foldBtnSize,
                                                                   foldBtnSize);
                        }
                        else if (vector == Vector4.Right)
                        {
                            subTopic.FoldingButton = new Rectangle(subTopic.Left - foldBtnSize + 4,
                                                                   subTopic.Top + (int)Math.Round((60 - foldBtnSize) / 2.0f, MidpointRounding.AwayFromZero),
                                                                   foldBtnSize,
                                                                   foldBtnSize);
                        }
                    }
                }
                else if (subTopic.Type == TopicType.Hazard)
                {
                    var lines = CreateTopicLines(e, root, subTopic, vector, GetReverseVector(vector));
                    if (lines != null)
                    {
                        root.Lines.AddRange(lines);
                    }
                }

                rectFull = Rectangle.Union(rectFull, subTopic.ContentBounds);
                if (!rectFullSub.IsEmpty)
                {
                    rectFull = Rectangle.Union(rectFull, rectFullSub);
                }
                previous = subTopic;
            }

            return(rectFull);
        }