diff --git a/Terminal.Gui/Views/TreeView.cs b/Terminal.Gui/Views/TreeView.cs index d1526f456..144b9c502 100644 --- a/Terminal.Gui/Views/TreeView.cs +++ b/Terminal.Gui/Views/TreeView.cs @@ -319,8 +319,13 @@ namespace Terminal.Gui { /// /// Secondary selected regions of tree when is true /// - private Stack> _multiSelectedRegions = new Stack>(); + private Stack> multiSelectedRegions = new Stack>(); + /// + /// Cached result of + /// + private Branch[] cachedLineMap; + /// /// Error message to display when the control is not properly initialized at draw time (nodes added but no tree builder set) @@ -400,18 +405,21 @@ namespace Terminal.Gui { { if(!roots.ContainsKey(o)) { roots.Add(o,new Branch(this,null,o)); + InvalidateLineMap(); SetNeedsDisplay(); } } + /// /// Removes all objects from the tree and clears /// public void ClearObjects() { SelectedObject = default(T); - _multiSelectedRegions.Clear(); + multiSelectedRegions.Clear(); roots = new Dictionary>(); + InvalidateLineMap(); SetNeedsDisplay(); } @@ -424,6 +432,7 @@ namespace Terminal.Gui { { if(roots.ContainsKey(o)) { roots.Remove(o); + InvalidateLineMap(); SetNeedsDisplay(); if(Equals(SelectedObject,o)) @@ -445,9 +454,11 @@ namespace Terminal.Gui { objectsAdded = true; } } - - if(objectsAdded) + + if (objectsAdded) { + InvalidateLineMap(); SetNeedsDisplay(); + } } /// @@ -461,6 +472,7 @@ namespace Terminal.Gui { var branch = ObjectToBranch(o); if(branch != null) { branch.Refresh(startAtTop); + InvalidateLineMap(); SetNeedsDisplay(); } @@ -474,6 +486,7 @@ namespace Terminal.Gui { foreach(var branch in roots.Values) branch.Rebuild(); + InvalidateLineMap(); SetNeedsDisplay(); } @@ -590,13 +603,16 @@ namespace Terminal.Gui { /// private Branch[] BuildLineMap() { + if(cachedLineMap != null) + return cachedLineMap; + List> toReturn = new List>(); foreach(var root in roots.Values) { toReturn.AddRange(AddToLineMap(root)); } - return toReturn.ToArray(); + return cachedLineMap = toReturn.ToArray(); } private IEnumerable> AddToLineMap (Branch currentBranch) @@ -733,14 +749,14 @@ namespace Terminal.Gui { clickedBranch.Expand(); else { SelectedObject = clickedBranch.Model; // It is a leaf node - _multiSelectedRegions.Clear(); + multiSelectedRegions.Clear(); } } else { // It is a first click somewhere in the current line that doesn't look like an expansion/collapse attempt SelectedObject = clickedBranch.Model; - _multiSelectedRegions.Clear(); + multiSelectedRegions.Clear(); } SetNeedsDisplay(); @@ -829,7 +845,7 @@ namespace Terminal.Gui { { // if it is not a shift click or we don't allow multi select if(!expandSelection || !MultiSelect) - _multiSelectedRegions.Clear(); + multiSelectedRegions.Clear(); if(SelectedObject == null){ SelectedObject = roots.Keys.FirstOrDefault(); @@ -852,16 +868,16 @@ namespace Terminal.Gui { // If it is a multi selection if(expandSelection && MultiSelect) { - if(_multiSelectedRegions.Any()) + if(multiSelectedRegions.Any()) { // expand the existing head selection - var head = _multiSelectedRegions.Pop(); - _multiSelectedRegions.Push(new TreeSelection(head.Origin,newIdx,map)); + var head = multiSelectedRegions.Pop(); + multiSelectedRegions.Push(new TreeSelection(head.Origin,newIdx,map)); } else { // or start a new multi selection region - _multiSelectedRegions.Push(new TreeSelection(map[idx],newIdx,map)); + multiSelectedRegions.Push(new TreeSelection(map[idx],newIdx,map)); } } @@ -882,7 +898,8 @@ namespace Terminal.Gui { } } - + + InvalidateLineMap(); SetNeedsDisplay(); } @@ -896,6 +913,7 @@ namespace Terminal.Gui { return; ObjectToBranch(toExpand)?.Expand(); + InvalidateLineMap(); SetNeedsDisplay(); } @@ -909,6 +927,7 @@ namespace Terminal.Gui { return; ObjectToBranch(toExpand)?.ExpandAll(); + InvalidateLineMap(); SetNeedsDisplay(); } /// @@ -919,7 +938,8 @@ namespace Terminal.Gui { foreach (var item in roots) { item.Value.ExpandAll(); } - + + InvalidateLineMap(); SetNeedsDisplay(); } /// @@ -968,7 +988,8 @@ namespace Terminal.Gui { foreach (var item in roots) { item.Value.Collapse(); } - + + InvalidateLineMap(); SetNeedsDisplay(); } @@ -1001,8 +1022,17 @@ namespace Terminal.Gui { SelectedObject = null; } + InvalidateLineMap(); SetNeedsDisplay(); } + + /// + /// Clears any cached results of + /// + protected void InvalidateLineMap() + { + cachedLineMap = null; + } /// /// Returns the corresponding in the tree for . This will not work for objects hidden by their parent being collapsed @@ -1022,7 +1052,7 @@ namespace Terminal.Gui { public bool IsSelected (T model) { return Equals(SelectedObject , model) || - (MultiSelect && _multiSelectedRegions.Any(s=>s.Contains(model))); + (MultiSelect && multiSelectedRegions.Any(s=>s.Contains(model))); } /// @@ -1054,14 +1084,14 @@ namespace Terminal.Gui { if(!MultiSelect) return; - _multiSelectedRegions.Clear(); + multiSelectedRegions.Clear(); var map = BuildLineMap(); if(map.Length == 0) return; - _multiSelectedRegions.Push(new TreeSelection(map[0],map.Length,map)); + multiSelectedRegions.Push(new TreeSelection(map[0],map.Length,map)); SetNeedsDisplay(); OnSelectionChanged(new SelectionChangedEventArgs(this,SelectedObject,SelectedObject));