168 lines
4.9 KiB
C#
168 lines
4.9 KiB
C#
|
|
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
|
|||
|
|
//
|
|||
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
|||
|
|
// software and associated documentation files (the "Software"), to deal in the Software
|
|||
|
|
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
|||
|
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
|||
|
|
// to whom the Software is furnished to do so, subject to the following conditions:
|
|||
|
|
//
|
|||
|
|
// The above copyright notice and this permission notice shall be included in all copies or
|
|||
|
|
// substantial portions of the Software.
|
|||
|
|
//
|
|||
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|||
|
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|||
|
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
|||
|
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|||
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|||
|
|
// DEALINGS IN THE SOFTWARE.
|
|||
|
|
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.Diagnostics;
|
|||
|
|
using Unity.CodeEditor.Document;
|
|||
|
|
|
|||
|
|
namespace Unity.CodeEditor.Rendering
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// A node in the text view's height tree.
|
|||
|
|
/// </summary>
|
|||
|
|
internal sealed class HeightTreeNode
|
|||
|
|
{
|
|||
|
|
internal readonly DocumentLine DocumentLine;
|
|||
|
|
internal HeightTreeLineNode LineNode;
|
|||
|
|
|
|||
|
|
internal HeightTreeNode Left, Right, Parent;
|
|||
|
|
internal bool Color;
|
|||
|
|
|
|||
|
|
internal HeightTreeNode()
|
|||
|
|
{
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
internal HeightTreeNode(DocumentLine documentLine, float height)
|
|||
|
|
{
|
|||
|
|
this.DocumentLine = documentLine;
|
|||
|
|
this.TotalCount = 1;
|
|||
|
|
this.LineNode = new HeightTreeLineNode(height);
|
|||
|
|
this.TotalHeight = height;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
internal HeightTreeNode LeftMost {
|
|||
|
|
get {
|
|||
|
|
HeightTreeNode node = this;
|
|||
|
|
while (node.Left != null)
|
|||
|
|
node = node.Left;
|
|||
|
|
return node;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
internal HeightTreeNode RightMost {
|
|||
|
|
get {
|
|||
|
|
HeightTreeNode node = this;
|
|||
|
|
while (node.Right != null)
|
|||
|
|
node = node.Right;
|
|||
|
|
return node;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// Gets the inorder successor of the node.
|
|||
|
|
/// </summary>
|
|||
|
|
internal HeightTreeNode Successor {
|
|||
|
|
get {
|
|||
|
|
if (Right != null) {
|
|||
|
|
return Right.LeftMost;
|
|||
|
|
} else {
|
|||
|
|
HeightTreeNode node = this;
|
|||
|
|
HeightTreeNode oldNode;
|
|||
|
|
do {
|
|||
|
|
oldNode = node;
|
|||
|
|
node = node.Parent;
|
|||
|
|
// go up until we are coming out of a left subtree
|
|||
|
|
} while (node != null && node.Right == oldNode);
|
|||
|
|
return node;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// The number of lines in this node and its child nodes.
|
|||
|
|
/// Invariant:
|
|||
|
|
/// totalCount = 1 + left.totalCount + right.totalCount
|
|||
|
|
/// </summary>
|
|||
|
|
internal int TotalCount;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// The total height of this node and its child nodes, excluding directly collapsed nodes.
|
|||
|
|
/// Invariant:
|
|||
|
|
/// totalHeight = left.IsDirectlyCollapsed ? 0 : left.totalHeight
|
|||
|
|
/// + lineNode.IsDirectlyCollapsed ? 0 : lineNode.Height
|
|||
|
|
/// + right.IsDirectlyCollapsed ? 0 : right.totalHeight
|
|||
|
|
/// </summary>
|
|||
|
|
internal float TotalHeight;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// List of the sections that hold this node collapsed.
|
|||
|
|
/// Invariant 1:
|
|||
|
|
/// For each document line in the range described by a CollapsedSection, exactly one ancestor
|
|||
|
|
/// contains that CollapsedSection.
|
|||
|
|
/// Invariant 2:
|
|||
|
|
/// A CollapsedSection is contained either in left+middle or middle+right or just middle.
|
|||
|
|
/// Invariant 3:
|
|||
|
|
/// Start and end of a CollapsedSection always contain the collapsedSection in their
|
|||
|
|
/// documentLine (middle node).
|
|||
|
|
/// </summary>
|
|||
|
|
internal List<CollapsedLineSection> CollapsedSections;
|
|||
|
|
|
|||
|
|
internal bool IsDirectlyCollapsed {
|
|||
|
|
get {
|
|||
|
|
return CollapsedSections != null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
internal void AddDirectlyCollapsed(CollapsedLineSection section)
|
|||
|
|
{
|
|||
|
|
if (CollapsedSections == null) {
|
|||
|
|
CollapsedSections = new List<CollapsedLineSection>();
|
|||
|
|
TotalHeight = 0;
|
|||
|
|
}
|
|||
|
|
Debug.Assert(!CollapsedSections.Contains(section));
|
|||
|
|
CollapsedSections.Add(section);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
internal void RemoveDirectlyCollapsed(CollapsedLineSection section)
|
|||
|
|
{
|
|||
|
|
Debug.Assert(CollapsedSections.Contains(section));
|
|||
|
|
CollapsedSections.Remove(section);
|
|||
|
|
if (CollapsedSections.Count == 0) {
|
|||
|
|
CollapsedSections = null;
|
|||
|
|
TotalHeight = LineNode.TotalHeight;
|
|||
|
|
if (Left != null)
|
|||
|
|
TotalHeight += Left.TotalHeight;
|
|||
|
|
if (Right != null)
|
|||
|
|
TotalHeight += Right.TotalHeight;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#if DEBUG
|
|||
|
|
public override string ToString()
|
|||
|
|
{
|
|||
|
|
return "[HeightTreeNode "
|
|||
|
|
+ DocumentLine.LineNumber + " CS=" + GetCollapsedSections(CollapsedSections)
|
|||
|
|
+ " Line.CS=" + GetCollapsedSections(LineNode.CollapsedSections)
|
|||
|
|
+ " Line.Height=" + LineNode.Height
|
|||
|
|
+ " TotalHeight=" + TotalHeight
|
|||
|
|
+ "]";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static string GetCollapsedSections(List<CollapsedLineSection> list)
|
|||
|
|
{
|
|||
|
|
if (list == null)
|
|||
|
|
return "{}";
|
|||
|
|
return "{" +
|
|||
|
|
string.Join(",",
|
|||
|
|
list.ConvertAll(cs => cs.Id).ToArray())
|
|||
|
|
+ "}";
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
}
|