aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Rendering/VisualLineTextSource.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Rendering/VisualLineTextSource.cs')
-rw-r--r--Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Rendering/VisualLineTextSource.cs123
1 files changed, 123 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Rendering/VisualLineTextSource.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Rendering/VisualLineTextSource.cs
new file mode 100644
index 000000000..3a5167010
--- /dev/null
+++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Rendering/VisualLineTextSource.cs
@@ -0,0 +1,123 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Diagnostics;
+using System.Windows.Media.TextFormatting;
+
+using Tango.Scripting.Editors.Document;
+using Tango.Scripting.Editors.Utils;
+
+namespace Tango.Scripting.Editors.Rendering
+{
+ /// <summary>
+ /// WPF TextSource implementation that creates TextRuns for a VisualLine.
+ /// </summary>
+ sealed class VisualLineTextSource : TextSource, ITextRunConstructionContext
+ {
+ public VisualLineTextSource(VisualLine visualLine)
+ {
+ this.VisualLine = visualLine;
+ }
+
+ public VisualLine VisualLine { get; private set; }
+ public TextView TextView { get; set; }
+ public TextDocument Document { get; set; }
+ public TextRunProperties GlobalTextRunProperties { get; set; }
+
+ public override TextRun GetTextRun(int textSourceCharacterIndex)
+ {
+ try {
+ foreach (VisualLineElement element in VisualLine.Elements) {
+ if (textSourceCharacterIndex >= element.VisualColumn
+ && textSourceCharacterIndex < element.VisualColumn + element.VisualLength)
+ {
+ int relativeOffset = textSourceCharacterIndex - element.VisualColumn;
+ TextRun run = element.CreateTextRun(textSourceCharacterIndex, this);
+ if (run == null)
+ throw new ArgumentNullException(element.GetType().Name + ".CreateTextRun");
+ if (run.Length == 0)
+ throw new ArgumentException("The returned TextRun must not have length 0.", element.GetType().Name + ".Length");
+ if (relativeOffset + run.Length > element.VisualLength)
+ throw new ArgumentException("The returned TextRun is too long.", element.GetType().Name + ".CreateTextRun");
+ InlineObjectRun inlineRun = run as InlineObjectRun;
+ if (inlineRun != null) {
+ inlineRun.VisualLine = VisualLine;
+ VisualLine.hasInlineObjects = true;
+ TextView.AddInlineObject(inlineRun);
+ }
+ return run;
+ }
+ }
+ if (TextView.Options.ShowEndOfLine && textSourceCharacterIndex == VisualLine.VisualLength) {
+ return CreateTextRunForNewLine();
+ }
+ return new TextEndOfParagraph(1);
+ } catch (Exception ex) {
+ Debug.WriteLine(ex.ToString());
+ throw;
+ }
+ }
+
+ TextRun CreateTextRunForNewLine()
+ {
+ string newlineText = "";
+ DocumentLine lastDocumentLine = VisualLine.LastDocumentLine;
+ if (lastDocumentLine.DelimiterLength == 2) {
+ newlineText = "¶";
+ } else if (lastDocumentLine.DelimiterLength == 1) {
+ char newlineChar = Document.GetCharAt(lastDocumentLine.Offset + lastDocumentLine.Length);
+ if (newlineChar == '\r')
+ newlineText = "\\r";
+ else if (newlineChar == '\n')
+ newlineText = "\\n";
+ else
+ newlineText = "?";
+ }
+ return new FormattedTextRun(new FormattedTextElement(TextView.cachedElements.GetTextForNonPrintableCharacter(newlineText, this), 0), GlobalTextRunProperties);
+ }
+
+ public override TextSpan<CultureSpecificCharacterBufferRange> GetPrecedingText(int textSourceCharacterIndexLimit)
+ {
+ try {
+ foreach (VisualLineElement element in VisualLine.Elements) {
+ if (textSourceCharacterIndexLimit > element.VisualColumn
+ && textSourceCharacterIndexLimit <= element.VisualColumn + element.VisualLength)
+ {
+ TextSpan<CultureSpecificCharacterBufferRange> span = element.GetPrecedingText(textSourceCharacterIndexLimit, this);
+ if (span == null)
+ break;
+ int relativeOffset = textSourceCharacterIndexLimit - element.VisualColumn;
+ if (span.Length > relativeOffset)
+ throw new ArgumentException("The returned TextSpan is too long.", element.GetType().Name + ".GetPrecedingText");
+ return span;
+ }
+ }
+ CharacterBufferRange empty = CharacterBufferRange.Empty;
+ return new TextSpan<CultureSpecificCharacterBufferRange>(empty.Length, new CultureSpecificCharacterBufferRange(null, empty));
+ } catch (Exception ex) {
+ Debug.WriteLine(ex.ToString());
+ throw;
+ }
+ }
+
+ public override int GetTextEffectCharacterIndexFromTextSourceCharacterIndex(int textSourceCharacterIndex)
+ {
+ throw new NotSupportedException();
+ }
+
+ string cachedString;
+ int cachedStringOffset;
+
+ public StringSegment GetText(int offset, int length)
+ {
+ if (cachedString != null) {
+ if (offset >= cachedStringOffset && offset + length <= cachedStringOffset + cachedString.Length) {
+ return new StringSegment(cachedString, offset - cachedStringOffset, length);
+ }
+ }
+ cachedStringOffset = offset;
+ return new StringSegment(cachedString = this.Document.GetText(offset, length));
+ }
+ }
+}