From 080f1697e97e13461ec6df4d31c8924d01257a1b Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Tue, 9 Apr 2019 01:47:48 +0300 Subject: MERGE --- .../Tango.Scripting.Editors/Editing/Selection.cs | 268 +++++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Editing/Selection.cs (limited to 'Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Editing/Selection.cs') diff --git a/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Editing/Selection.cs b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Editing/Selection.cs new file mode 100644 index 000000000..014fa8680 --- /dev/null +++ b/Software/Visual_Studio/Scripting/Tango.Scripting.Editors/Editing/Selection.cs @@ -0,0 +1,268 @@ +// 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.Collections.Generic; +using System.Text; +using System.Windows; +using Tango.Scripting.Editors.Document; +using Tango.Scripting.Editors.Highlighting; +using Tango.Scripting.Editors.Utils; + +namespace Tango.Scripting.Editors.Editing +{ + /// + /// Base class for selections. + /// + public abstract class Selection + { + /// + /// Creates a new simple selection that selects the text from startOffset to endOffset. + /// + public static Selection Create(TextArea textArea, int startOffset, int endOffset) + { + if (textArea == null) + throw new ArgumentNullException("textArea"); + if (startOffset == endOffset) + return textArea.emptySelection; + else + return new SimpleSelection(textArea, + new TextViewPosition(textArea.Document.GetLocation(startOffset)), + new TextViewPosition(textArea.Document.GetLocation(endOffset))); + } + + internal static Selection Create(TextArea textArea, TextViewPosition start, TextViewPosition end) + { + if (textArea == null) + throw new ArgumentNullException("textArea"); + if (textArea.Document.GetOffset(start.Location) == textArea.Document.GetOffset(end.Location) && start.VisualColumn == end.VisualColumn) + return textArea.emptySelection; + else + return new SimpleSelection(textArea, start, end); + } + + /// + /// Creates a new simple selection that selects the text in the specified segment. + /// + public static Selection Create(TextArea textArea, ISegment segment) + { + if (segment == null) + throw new ArgumentNullException("segment"); + return Create(textArea, segment.Offset, segment.EndOffset); + } + + internal readonly TextArea textArea; + + /// + /// Constructor for Selection. + /// + protected Selection(TextArea textArea) + { + if (textArea == null) + throw new ArgumentNullException("textArea"); + this.textArea = textArea; + } + + /// + /// Gets the start position of the selection. + /// + public abstract TextViewPosition StartPosition { get; } + + /// + /// Gets the end position of the selection. + /// + public abstract TextViewPosition EndPosition { get; } + + /// + /// Gets the selected text segments. + /// + public abstract IEnumerable Segments { get; } + + /// + /// Gets the smallest segment that contains all segments in this selection. + /// May return null if the selection is empty. + /// + public abstract ISegment SurroundingSegment { get; } + + /// + /// Replaces the selection with the specified text. + /// + public abstract void ReplaceSelectionWithText(string newText); + + internal string AddSpacesIfRequired(string newText, TextViewPosition start, TextViewPosition end) + { + if (EnableVirtualSpace && InsertVirtualSpaces(newText, start, end)) { + var line = textArea.Document.GetLineByNumber(start.Line); + string lineText = textArea.Document.GetText(line); + var vLine = textArea.TextView.GetOrConstructVisualLine(line); + int colDiff = start.VisualColumn - vLine.VisualLengthWithEndOfLineMarker; + if (colDiff > 0) { + string additionalSpaces = ""; + if (!textArea.Options.ConvertTabsToSpaces && lineText.Trim('\t').Length == 0) { + int tabCount = (int)(colDiff / textArea.Options.IndentationSize); + additionalSpaces = new string('\t', tabCount); + colDiff -= tabCount * textArea.Options.IndentationSize; + } + additionalSpaces += new string(' ', colDiff); + return additionalSpaces + newText; + } + } + return newText; + } + + bool InsertVirtualSpaces(string newText, TextViewPosition start, TextViewPosition end) + { + return (!string.IsNullOrEmpty(newText) || !(IsInVirtualSpace(start) && IsInVirtualSpace(end))) + && newText != "\r\n" + && newText != "\n" + && newText != "\r"; + } + + bool IsInVirtualSpace(TextViewPosition pos) + { + return pos.VisualColumn > textArea.TextView.GetOrConstructVisualLine(textArea.Document.GetLineByNumber(pos.Line)).VisualLength; + } + + /// + /// Updates the selection when the document changes. + /// + public abstract Selection UpdateOnDocumentChange(DocumentChangeEventArgs e); + + /// + /// Gets whether the selection is empty. + /// + public virtual bool IsEmpty { + get { return Length == 0; } + } + + /// + /// Gets whether virtual space is enabled for this selection. + /// + public virtual bool EnableVirtualSpace { + get { return textArea.Options.EnableVirtualSpace; } + } + + /// + /// Gets the selection length. + /// + public abstract int Length { get; } + + /// + /// Returns a new selection with the changed end point. + /// + /// Cannot set endpoint for empty selection + public abstract Selection SetEndpoint(TextViewPosition endPosition); + + /// + /// If this selection is empty, starts a new selection from to + /// , otherwise, changes the endpoint of this selection. + /// + public abstract Selection StartSelectionOrSetEndpoint(TextViewPosition startPosition, TextViewPosition endPosition); + + /// + /// Gets whether the selection is multi-line. + /// + public virtual bool IsMultiline { + get { + ISegment surroundingSegment = this.SurroundingSegment; + if (surroundingSegment == null) + return false; + int start = surroundingSegment.Offset; + int end = start + surroundingSegment.Length; + var document = textArea.Document; + if (document == null) + throw ThrowUtil.NoDocumentAssigned(); + return document.GetLineByOffset(start) != document.GetLineByOffset(end); + } + } + + /// + /// Gets the selected text. + /// + public virtual string GetText() + { + var document = textArea.Document; + if (document == null) + throw ThrowUtil.NoDocumentAssigned(); + StringBuilder b = null; + string text = null; + foreach (ISegment s in Segments) { + if (text != null) { + if (b == null) + b = new StringBuilder(text); + else + b.Append(text); + } + text = document.GetText(s); + } + if (b != null) { + if (text != null) b.Append(text); + return b.ToString(); + } else { + return text ?? string.Empty; + } + } + + /// + /// Creates a HTML fragment for the selected text. + /// + public string CreateHtmlFragment(HtmlOptions options) + { + if (options == null) + throw new ArgumentNullException("options"); + IHighlighter highlighter = textArea.GetService(typeof(IHighlighter)) as IHighlighter; + StringBuilder html = new StringBuilder(); + bool first = true; + foreach (ISegment selectedSegment in this.Segments) { + if (first) + first = false; + else + html.AppendLine("
"); + html.Append(HtmlClipboard.CreateHtmlFragment(textArea.Document, highlighter, selectedSegment, options)); + } + return html.ToString(); + } + + /// + public abstract override bool Equals(object obj); + + /// + public abstract override int GetHashCode(); + + /// + /// Gets whether the specified offset is included in the selection. + /// + /// True, if the selection contains the offset (selection borders inclusive); + /// otherwise, false. + public virtual bool Contains(int offset) + { + if (this.IsEmpty) + return false; + if (this.SurroundingSegment.Contains(offset)) { + foreach (ISegment s in this.Segments) { + if (s.Contains(offset)) { + return true; + } + } + } + return false; + } + + /// + /// Creates a data object containing the selection's text. + /// + public virtual DataObject CreateDataObject(TextArea textArea) + { + string text = GetText(); + // Ensure we use the appropriate newline sequence for the OS + DataObject data = new DataObject(TextUtilities.NormalizeNewLines(text, Environment.NewLine)); + // we cannot use DataObject.SetText - then we cannot drag to SciTe + // (but dragging to Word works in both cases) + + // Also copy text in HTML format to clipboard - good for pasting text into Word + // or to the SharpDevelop forums. + HtmlClipboard.SetHtml(data, CreateHtmlFragment(new HtmlOptions(textArea.Options))); + return data; + } + } +} -- cgit v1.3.1