/// <summary>
        /// If DisplayTimeDuration is True,
        /// then the system will calculate the Time Duration from the Parent Node to this Child Node
        /// </summary>
        private void ProcessDisplayTimeDuration(DocumentEntry item, TreeNode node)
        {
            if (item.Type != DocumentMapType.Event)
            {
                return;
            }

            var e = XmlDal.DataModel.GetEvent(item.Id);

            if (e == null)
            {
                return;
            }

            DocumentEntry parentItem = null;

            if (e.DisplayDurationFromParent)
            {
                var target = node.Parent ?? _View.Root;
                parentItem = target.Tag as DocumentEntry;
            }
            else
            if (e.DisplayDurationFromSibling)
            {
                var target = node.PrevNode ?? node.Parent ?? _View.Root;
                parentItem = target.Tag as DocumentEntry;
            }
            else
            {
                return;
            }

            if (parentItem == null)
            {
                return;
            }

            DateTime parentDateTime;

            DateTimeExt.TryParseWithTimeZoneRemoval(RegularExpression.GetTextBetweenTwoCharacters("<", ">", parentItem.Text),
                                                    out parentDateTime);

            DateTime childDateTime;

            DateTimeExt.TryParseWithTimeZoneRemoval(RegularExpression.GetTextBetweenTwoCharacters("<", ">", item.Text), out childDateTime);

            node.Text = string.Format("{0} [{1}]", node.Text,
                                      parentDateTime.Difference(childDateTime).ToReadableString());
            node.ForeColor = Color.Red;
            DocumentMapDurations.Add(new ValueBookMark {
                Name = node.Text, iLine = item.iLine, DocumentMapDuration = true
            });
        }
        public void BuildTreeView(IEnumerable <DocumentEntry> model, Action <TreeNodeCollection> callback)
        {
            lock (this)
            {
                DocumentMapDurations.Clear();
                var root = new TreeNode().Nodes;
                TreeNodeCollection lastLevel1 = null;
                TreeNodeCollection lastLevel2 = null;
                TreeNodeCollection lastLevel3 = null;

                #region Loop

                foreach (var item in model.OrderBy(n => n.iLine).ThenBy(n => n.Type))
                {
                    if ((!_View.ShowTimeGap && (item.Type == DocumentMapType.TimeGAPEnd || item.Type == DocumentMapType.TimeGAPStart)) ||
                        (!_View.ShowNetwork && item.Type == DocumentMapType.Network) ||
                        (!_View.ShowValues && item.Type == DocumentMapType.Value) ||
                        (!_View.ShowEvents && item.Type == DocumentMapType.Event))
                    {
                        continue;
                    }

                    if (_View.Filter && !item.Filtered)
                    {
                        continue;
                    }

                    TreeNode node;

                    switch (item.Type)
                    {
                    case DocumentMapType.TimeGAPStart:
                    case DocumentMapType.TimeGAPEnd:
                    case DocumentMapType.Event:
                    case DocumentMapType.Network:

                        node = new TreeNode(string.Format("{0}{1}", GetDocumentMapiLine(item), item.Name))
                        {
                            Tag = item
                        };
                        break;

                    case DocumentMapType.Value:
                        node = new TreeNode(string.Format("{0}{1} - {2}", GetDocumentMapiLine(item), item.Name, item.Value))
                        {
                            Tag = item
                        };
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    #region Level

                    switch (item.Level)
                    {
                    case DocumentMapLevel.Root:
                        lastLevel1 = null;
                        lastLevel2 = null;
                        lastLevel3 = null;
                        root.Add(node);
                        break;

                    case DocumentMapLevel.Level1:
                        if (root.Count == 0)
                        {
                            root.Add(new TreeNode("---"));
                        }

                        root.Add(node);

                        lastLevel1 = root[root.Count - 1].Nodes;
                        lastLevel2 = null;
                        lastLevel3 = null;
                        break;

                    case DocumentMapLevel.Level2:
                        if (root.Count == 0)
                        {
                            root.Add(new TreeNode("---"));
                        }
                        lastLevel1 = root[root.Count - 1].Nodes;

                        //if (lastLevel2 == null)
                        //{
                        //    if (lastLevel1.Count == 0)
                        //        lastLevel1.Add(new TreeNode("---"));
                        //}

                        lastLevel1.Add(node);

                        lastLevel2 = lastLevel1[lastLevel1.Count - 1].Nodes;
                        lastLevel3 = null;
                        break;

                    case DocumentMapLevel.Level3:
                        if (root.Count == 0)
                        {
                            root.Add(new TreeNode("---"));
                        }
                        lastLevel1 = root[root.Count - 1].Nodes;

                        if (lastLevel2 == null)
                        {
                            if (lastLevel1.Count == 0)
                            {
                                lastLevel1.Add(new TreeNode("---"));
                            }
                            lastLevel2 = lastLevel1[lastLevel1.Count - 1].Nodes;
                        }

                        //if (lastLevel3 == null)
                        //{
                        //    if (lastLevel2.Count == 0)
                        //        lastLevel2.Add(new TreeNode("---"));

                        //}

                        lastLevel2.Add(node);
                        lastLevel3 = lastLevel2[lastLevel2.Count - 1].Nodes;
                        break;

                    case DocumentMapLevel.Sibling:
                        if (lastLevel3 != null)
                        {
                            lastLevel3.Add(node);
                            break;
                        }
                        if (lastLevel2 != null)
                        {
                            lastLevel2.Add(node);
                            break;
                        }
                        if (lastLevel1 != null)
                        {
                            lastLevel1.Add(node);
                            break;
                        }
                        root.Add(node);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    #endregion Level

                    ProcessDisplayTimeDuration(item, node);
                    ProcessGaps(item, node);
                }
                #endregion Loop

                MainViewModel.Current.Model.File.DocumentMapDurations = DocumentMapDurations;

                callback(root);
            }
        }