Free cookie consent management tool by TermsFeed Policy Generator

source: branches/CodeEditor/HeuristicLab.ExtLibs/HeuristicLab.AvalonEdit/5.0.1/AvalonEdit-5.0.1/Rendering/VisualLineTextSource.cs @ 11700

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

#2077: created branch and added first version

File size: 5.5 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.Windows.Media.TextFormatting;
22
23using ICSharpCode.AvalonEdit.Document;
24using ICSharpCode.AvalonEdit.Utils;
25
26namespace ICSharpCode.AvalonEdit.Rendering
27{
28  /// <summary>
29  /// WPF TextSource implementation that creates TextRuns for a VisualLine.
30  /// </summary>
31  sealed class VisualLineTextSource : TextSource, ITextRunConstructionContext
32  {
33    public VisualLineTextSource(VisualLine visualLine)
34    {
35      this.VisualLine = visualLine;
36    }
37   
38    public VisualLine VisualLine { get; private set; }
39    public TextView TextView { get; set; }
40    public TextDocument Document { get; set; }
41    public TextRunProperties GlobalTextRunProperties { get; set; }
42   
43    public override TextRun GetTextRun(int textSourceCharacterIndex)
44    {
45      try {
46        foreach (VisualLineElement element in VisualLine.Elements) {
47          if (textSourceCharacterIndex >= element.VisualColumn
48              && textSourceCharacterIndex < element.VisualColumn + element.VisualLength)
49          {
50            int relativeOffset = textSourceCharacterIndex - element.VisualColumn;
51            TextRun run = element.CreateTextRun(textSourceCharacterIndex, this);
52            if (run == null)
53              throw new ArgumentNullException(element.GetType().Name + ".CreateTextRun");
54            if (run.Length == 0)
55              throw new ArgumentException("The returned TextRun must not have length 0.", element.GetType().Name + ".Length");
56            if (relativeOffset + run.Length > element.VisualLength)
57              throw new ArgumentException("The returned TextRun is too long.", element.GetType().Name + ".CreateTextRun");
58            InlineObjectRun inlineRun = run as InlineObjectRun;
59            if (inlineRun != null) {
60              inlineRun.VisualLine = VisualLine;
61              VisualLine.hasInlineObjects = true;
62              TextView.AddInlineObject(inlineRun);
63            }
64            return run;
65          }
66        }
67        if (TextView.Options.ShowEndOfLine && textSourceCharacterIndex == VisualLine.VisualLength) {
68          return CreateTextRunForNewLine();
69        }
70        return new TextEndOfParagraph(1);
71      } catch (Exception ex) {
72        Debug.WriteLine(ex.ToString());
73        throw;
74      }
75    }
76
77    TextRun CreateTextRunForNewLine()
78    {
79      string newlineText = "";
80      DocumentLine lastDocumentLine = VisualLine.LastDocumentLine;
81      if (lastDocumentLine.DelimiterLength == 2) {
82        newlineText = "¶";
83      } else if (lastDocumentLine.DelimiterLength == 1) {
84        char newlineChar = Document.GetCharAt(lastDocumentLine.Offset + lastDocumentLine.Length);
85        if (newlineChar == '\r')
86          newlineText = "\\r";
87        else if (newlineChar == '\n')
88          newlineText = "\\n";
89        else
90          newlineText = "?";
91      }
92      return new FormattedTextRun(new FormattedTextElement(TextView.cachedElements.GetTextForNonPrintableCharacter(newlineText, this), 0), GlobalTextRunProperties);
93    }
94   
95    public override TextSpan<CultureSpecificCharacterBufferRange> GetPrecedingText(int textSourceCharacterIndexLimit)
96    {
97      try {
98        foreach (VisualLineElement element in VisualLine.Elements) {
99          if (textSourceCharacterIndexLimit > element.VisualColumn
100              && textSourceCharacterIndexLimit <= element.VisualColumn + element.VisualLength)
101          {
102            TextSpan<CultureSpecificCharacterBufferRange> span = element.GetPrecedingText(textSourceCharacterIndexLimit, this);
103            if (span == null)
104              break;
105            int relativeOffset = textSourceCharacterIndexLimit - element.VisualColumn;
106            if (span.Length > relativeOffset)
107              throw new ArgumentException("The returned TextSpan is too long.", element.GetType().Name + ".GetPrecedingText");
108            return span;
109          }
110        }
111        CharacterBufferRange empty = CharacterBufferRange.Empty;
112        return new TextSpan<CultureSpecificCharacterBufferRange>(empty.Length, new CultureSpecificCharacterBufferRange(null, empty));
113      } catch (Exception ex) {
114        Debug.WriteLine(ex.ToString());
115        throw;
116      }
117    }
118   
119    public override int GetTextEffectCharacterIndexFromTextSourceCharacterIndex(int textSourceCharacterIndex)
120    {
121      throw new NotSupportedException();
122    }
123   
124    string cachedString;
125    int cachedStringOffset;
126   
127    public StringSegment GetText(int offset, int length)
128    {
129      if (cachedString != null) {
130        if (offset >= cachedStringOffset && offset + length <= cachedStringOffset + cachedString.Length) {
131          return new StringSegment(cachedString, offset - cachedStringOffset, length);
132        }
133      }
134      cachedStringOffset = offset;
135      return new StringSegment(cachedString = this.Document.GetText(offset, length));
136    }
137  }
138}
Note: See TracBrowser for help on using the repository browser.