Free cookie consent management tool by TermsFeed Policy Generator

source: branches/RemoveBackwardsCompatibility/HeuristicLab.ExtLibs/HeuristicLab.AvalonEdit/5.0.1/AvalonEdit-5.0.1/Folding/FoldingSection.cs @ 18242

Last change on this file since 18242 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 6.9 KB
Line 
1// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20using System.Diagnostics;
21using System.Text;
22#if NREFACTORY
23using ICSharpCode.NRefactory.Editor;
24#endif
25using ICSharpCode.AvalonEdit.Document;
26using ICSharpCode.AvalonEdit.Rendering;
27using ICSharpCode.AvalonEdit.Utils;
28
29namespace ICSharpCode.AvalonEdit.Folding
30{
31  /// <summary>
32  /// A section that can be folded.
33  /// </summary>
34  public sealed class FoldingSection : TextSegment
35  {
36    readonly FoldingManager manager;
37    bool isFolded;
38    internal CollapsedLineSection[] collapsedSections;
39    string title;
40   
41    /// <summary>
42    /// Gets/sets if the section is folded.
43    /// </summary>
44    public bool IsFolded {
45      get { return isFolded; }
46      set {
47        if (isFolded != value) {
48          isFolded = value;
49          ValidateCollapsedLineSections(); // create/destroy CollapsedLineSection
50            manager.Redraw(this);
51        }
52      }
53    }
54   
55    internal void ValidateCollapsedLineSections()
56    {
57      if (!isFolded) {
58        RemoveCollapsedLineSection();
59        return;
60      }
61      // It is possible that StartOffset/EndOffset get set to invalid values via the property setters in TextSegment,
62      // so we coerce those values into the valid range.
63      DocumentLine startLine = manager.document.GetLineByOffset(StartOffset.CoerceValue(0, manager.document.TextLength));
64      DocumentLine endLine = manager.document.GetLineByOffset(EndOffset.CoerceValue(0, manager.document.TextLength));
65      if (startLine == endLine) {
66        RemoveCollapsedLineSection();
67      } else {
68        if (collapsedSections == null)
69          collapsedSections = new CollapsedLineSection[manager.textViews.Count];
70        // Validate collapsed line sections
71        DocumentLine startLinePlusOne = startLine.NextLine;
72        for (int i = 0; i < collapsedSections.Length; i++) {
73          var collapsedSection = collapsedSections[i];
74          if (collapsedSection == null || collapsedSection.Start != startLinePlusOne || collapsedSection.End != endLine) {
75            // recreate this collapsed section
76            if (collapsedSection != null) {
77              Debug.WriteLine("CollapsedLineSection validation - recreate collapsed section from " + startLinePlusOne + " to " + endLine);
78              collapsedSection.Uncollapse();
79            }
80            collapsedSections[i] = manager.textViews[i].CollapseLines(startLinePlusOne, endLine);
81          }
82        }
83      }
84    }
85   
86    /// <inheritdoc/>
87    protected override void OnSegmentChanged()
88    {
89      ValidateCollapsedLineSections();
90      base.OnSegmentChanged();
91      // don't redraw if the FoldingSection wasn't added to the FoldingManager's collection yet
92      if (IsConnectedToCollection)
93        manager.Redraw(this);
94    }
95   
96    /// <summary>
97    /// Gets/Sets the text used to display the collapsed version of the folding section.
98    /// </summary>
99    public string Title {
100      get {
101        return title;
102      }
103      set {
104        if (title != value) {
105          title = value;
106          if (this.IsFolded)
107            manager.Redraw(this);
108        }
109      }
110    }
111   
112    /// <summary>
113    /// Gets the content of the collapsed lines as text.
114    /// </summary>
115    public string TextContent {
116      get {
117        return manager.document.GetText(StartOffset, EndOffset - StartOffset);
118      }
119    }
120   
121    /// <summary>
122    /// Gets the content of the collapsed lines as tooltip text.
123    /// </summary>
124    [Obsolete]
125    public string TooltipText {
126      get {
127        // This fixes SD-1394:
128        // Each line is checked for leading indentation whitespaces. If
129        // a line has the same or more indentation than the first line,
130        // it is reduced. If a line is less indented than the first line
131        // the indentation is removed completely.
132        //
133        // See the following example:
134        //  line 1
135        //    line 2
136        //      line 3
137        //  line 4
138        //
139        // is reduced to:
140        // line 1
141        //  line 2
142        //    line 3
143        // line 4
144       
145        var startLine = manager.document.GetLineByOffset(StartOffset);
146        var endLine = manager.document.GetLineByOffset(EndOffset);
147        var builder = new StringBuilder();
148       
149        var current = startLine;
150        ISegment startIndent = TextUtilities.GetLeadingWhitespace(manager.document, startLine);
151       
152        while (current != endLine.NextLine) {
153          ISegment currentIndent = TextUtilities.GetLeadingWhitespace(manager.document, current);
154         
155          if (current == startLine && current == endLine)
156            builder.Append(manager.document.GetText(StartOffset, EndOffset - StartOffset));
157          else if (current == startLine) {
158            if (current.EndOffset - StartOffset > 0)
159              builder.AppendLine(manager.document.GetText(StartOffset, current.EndOffset - StartOffset).TrimStart());
160          } else if (current == endLine) {
161            if (startIndent.Length <= currentIndent.Length)
162              builder.Append(manager.document.GetText(current.Offset + startIndent.Length, EndOffset - current.Offset - startIndent.Length));
163            else
164              builder.Append(manager.document.GetText(current.Offset + currentIndent.Length, EndOffset - current.Offset - currentIndent.Length));
165          } else {
166            if (startIndent.Length <= currentIndent.Length)
167              builder.AppendLine(manager.document.GetText(current.Offset + startIndent.Length, current.Length - startIndent.Length));
168            else
169              builder.AppendLine(manager.document.GetText(current.Offset + currentIndent.Length, current.Length - currentIndent.Length));
170          }
171         
172          current = current.NextLine;
173        }
174       
175        return builder.ToString();
176      }
177    }
178   
179    /// <summary>
180    /// Gets/Sets an additional object associated with this folding section.
181    /// </summary>
182    public object Tag { get; set; }
183   
184    internal FoldingSection(FoldingManager manager, int startOffset, int endOffset)
185    {
186      Debug.Assert(manager != null);
187      this.manager = manager;
188      this.StartOffset = startOffset;
189      this.Length = endOffset - startOffset;
190    }
191   
192    void RemoveCollapsedLineSection()
193    {
194      if (collapsedSections != null) {
195        foreach (var collapsedSection in collapsedSections) {
196          if (collapsedSection != null && collapsedSection.Start != null)
197            collapsedSection.Uncollapse();
198        }
199        collapsedSections = null;
200      }
201    }
202  }
203}
Note: See TracBrowser for help on using the repository browser.