aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Scripting/Tango.Scripting.IDE/Project.cs
blob: 6392ddcb7df3912b74e73382856db423f2093791 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using Tango.SharedUI.Helpers;

namespace Tango.Scripting.IDE
{
    public abstract class Project : IProject
    {
        #region properties
        private static Dictionary<String, BitmapSource> _imageCache;
        public string FilePath { get; set; }

        public string WorkingFolder => Path.GetDirectoryName(FilePath);

        public string Name => Path.GetFileNameWithoutExtension(FilePath);

        public abstract BitmapSource Image { get; }

        public ObservableCollection<IProjectItem> Items { get; set; }
        public ObservableCollection<ISolutionItemCommand> Commands { get; set; }
        #endregion

        #region constructors
        static Project()
        {
            _imageCache = new Dictionary<string, BitmapSource>();
        }
        
        public Project()
        {
            Items = new ObservableCollection<IProjectItem>();
            Commands = new ObservableCollection<ISolutionItemCommand>
            {
                new SolutionItemCommand(BuildProject) { Name = "Build", Image= GetImage(@"Images/BuildSolution_16x.png") },
                new SolutionItemCommand(SetStartUpProject) { Name = "Set as StartUp Project" , Image= GetImage(@"Images/Settings_Inverse_16x.png")},
                new SolutionItemCommand(Remove) { Name = "Remove" , Image= GetImage(@"Images/deletered_16.png")},
                new SolutionItemCommand(Rename) { Name = "Rename", Image= GetImage(@"Images/Rename_16x.png") },
                new SolutionItemCommand(OpenFolderInFileExplorer) { Name = "Open Folder In File Explorer", Image= GetImage(@"Images/Open_16x.png") },
                new SolutionItemCommand()
                {
                    Name = "Add...",
                    Commands = new ObservableCollection<ISolutionItemCommand>
                    {
                        new SolutionItemCommand(AddNewScript) { Name = "Add New Script" },
                        new SolutionItemCommand(AddExistingScript) { Name = "Add Existing Script" },
                    }
                }
            };
        }
        #endregion

       

        #region Commands
        private void BuildProject()
        {

        }
        private void SetStartUpProject()
        {

        }
        private void Remove()
        {

        }
        private void Rename()
        {

        }
        private void OpenFolderInFileExplorer()
        {

        }
        /// <summary>
        /// Adds a new script file of type IProjectItem to the current project.
        /// </summary>
        private void AddNewScript()
        {

        }
        /// <summary>
        /// Adds the existing script file to the current project.
        /// </summary>
        private void AddExistingScript()
        {

        }
        #endregion

        #region Build_Run
        public abstract Task Build();
        public abstract Task Run();
        #endregion

        #region generic_functions 
        protected static BitmapSource GetImage(String name)
        {
            if (_imageCache.ContainsKey(name))
            {
                return _imageCache[name];
            }
            else
            {
                var image = ResourceHelper.GetImageFromResources(name);
                _imageCache.Add(name, image);
                return image;
            }
        }

        public bool CanOpen => false;
        #endregion
    }
}
s="p">; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media.TextFormatting; using System.Windows.Threading; using Tango.Scripting.Editors.Document; using Tango.Scripting.Editors.Rendering; using Tango.Scripting.Editors.Utils; namespace Tango.Scripting.Editors.Editing { /// <summary> /// Handles selection of text using the mouse. /// </summary> sealed class SelectionMouseHandler : ITextAreaInputHandler { #region enum SelectionMode enum SelectionMode { /// <summary> /// no selection (no mouse button down) /// </summary> None, /// <summary> /// left mouse button down on selection, might be normal click /// or might be drag'n'drop /// </summary> PossibleDragStart, /// <summary> /// dragging text /// </summary> Drag, /// <summary> /// normal selection (click+drag) /// </summary> Normal, /// <summary> /// whole-word selection (double click+drag or ctrl+click+drag) /// </summary> WholeWord, /// <summary> /// whole-line selection (triple click+drag) /// </summary> WholeLine, /// <summary> /// rectangular selection (alt+click+drag) /// </summary> Rectangular } #endregion readonly TextArea textArea; SelectionMode mode; AnchorSegment startWord; Point possibleDragStartMousePos; #region Constructor + Attach + Detach public SelectionMouseHandler(TextArea textArea) { if (textArea == null) throw new ArgumentNullException("textArea"); this.textArea = textArea; } public TextArea TextArea { get { return textArea; } } public void Attach() { textArea.MouseLeftButtonDown += textArea_MouseLeftButtonDown; textArea.MouseMove += textArea_MouseMove; textArea.MouseLeftButtonUp += textArea_MouseLeftButtonUp; textArea.QueryCursor += textArea_QueryCursor; textArea.OptionChanged += textArea_OptionChanged; enableTextDragDrop = textArea.Options.EnableTextDragDrop; if (enableTextDragDrop) { AttachDragDrop(); } } public void Detach() { mode = SelectionMode.None; textArea.MouseLeftButtonDown -= textArea_MouseLeftButtonDown; textArea.MouseMove -= textArea_MouseMove; textArea.MouseLeftButtonUp -= textArea_MouseLeftButtonUp; textArea.QueryCursor -= textArea_QueryCursor; textArea.OptionChanged -= textArea_OptionChanged; if (enableTextDragDrop) { DetachDragDrop(); } } void AttachDragDrop() { textArea.AllowDrop = true; textArea.GiveFeedback += textArea_GiveFeedback; textArea.QueryContinueDrag += textArea_QueryContinueDrag; textArea.DragEnter += textArea_DragEnter; textArea.DragOver += textArea_DragOver; textArea.DragLeave += textArea_DragLeave; textArea.Drop += textArea_Drop; } void DetachDragDrop() { textArea.AllowDrop = false; textArea.GiveFeedback -= textArea_GiveFeedback; textArea.QueryContinueDrag -= textArea_QueryContinueDrag; textArea.DragEnter -= textArea_DragEnter; textArea.DragOver -= textArea_DragOver; textArea.DragLeave -= textArea_DragLeave; textArea.Drop -= textArea_Drop; } bool enableTextDragDrop; void textArea_OptionChanged(object sender, PropertyChangedEventArgs e) { bool newEnableTextDragDrop = textArea.Options.EnableTextDragDrop; if (newEnableTextDragDrop != enableTextDragDrop) { enableTextDragDrop = newEnableTextDragDrop; if (newEnableTextDragDrop) AttachDragDrop(); else DetachDragDrop(); } } #endregion #region Dropping text [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] void textArea_DragEnter(object sender, DragEventArgs e) { try { e.Effects = GetEffect(e); textArea.Caret.Show(); } catch (Exception ex) { OnDragException(ex); } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] void textArea_DragOver(object sender, DragEventArgs e) { try { e.Effects = GetEffect(e); } catch (Exception ex) { OnDragException(ex); } } DragDropEffects GetEffect(DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.UnicodeText, true)) { e.Handled = true; int visualColumn; int offset = GetOffsetFromMousePosition(e.GetPosition(textArea.TextView), out visualColumn); if (offset >= 0) { textArea.Caret.Position = new TextViewPosition(textArea.Document.GetLocation(offset), visualColumn); textArea.Caret.DesiredXPos = double.NaN; if (textArea.ReadOnlySectionProvider.CanInsert(offset)) { if ((e.AllowedEffects & DragDropEffects.Move) == DragDropEffects.Move && (e.KeyStates & DragDropKeyStates.ControlKey) != DragDropKeyStates.ControlKey) { return DragDropEffects.Move; } else { return e.AllowedEffects & DragDropEffects.Copy; } } } } return DragDropEffects.None; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] void textArea_DragLeave(object sender, DragEventArgs e) { try { e.Handled = true; if (!textArea.IsKeyboardFocusWithin) textArea.Caret.Hide(); } catch (Exception ex) { OnDragException(ex); } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] void textArea_Drop(object sender, DragEventArgs e) { try { DragDropEffects effect = GetEffect(e); e.Effects = effect; if (effect != DragDropEffects.None) { string text = e.Data.GetData(DataFormats.UnicodeText, true) as string; if (text != null) { int start = textArea.Caret.Offset; if (mode == SelectionMode.Drag && textArea.Selection.Contains(start)) { Debug.WriteLine("Drop: did not drop: drop target is inside selection"); e.Effects = DragDropEffects.None; } else { Debug.WriteLine("Drop: insert at " + start); bool rectangular = e.Data.GetDataPresent(RectangleSelection.RectangularSelectionDataType); string newLine = TextUtilities.GetNewLineFromDocument(textArea.Document, textArea.Caret.Line); text = TextUtilities.NormalizeNewLines(text, newLine); // Mark the undo group with the currentDragDescriptor, if the drag // is originating from the same control. This allows combining // the undo groups when text is moved. textArea.Document.UndoStack.StartUndoGroup(this.currentDragDescriptor); try { if (rectangular && RectangleSelection.PerformRectangularPaste(textArea, textArea.Caret.Position, text, true)) { } else { textArea.Document.Insert(start, text); textArea.Selection = Selection.Create(textArea, start, start + text.Length); } } finally { textArea.Document.UndoStack.EndUndoGroup(); } } e.Handled = true; } } } catch (Exception ex) { OnDragException(ex); } } void OnDragException(Exception ex) { // WPF swallows exceptions during drag'n'drop or reports them incorrectly, so // we re-throw them later to allow the application's unhandled exception handler // to catch them textArea.Dispatcher.BeginInvoke( DispatcherPriority.Normal, new Action(delegate { throw new DragDropException("Exception during drag'n'drop", ex); })); } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] void textArea_GiveFeedback(object sender, GiveFeedbackEventArgs e) { try { e.UseDefaultCursors = true; e.Handled = true; } catch (Exception ex) { OnDragException(ex); } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] void textArea_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) { try { if (e.EscapePressed) { e.Action = DragAction.Cancel; } else if ((e.KeyStates & DragDropKeyStates.LeftMouseButton) != DragDropKeyStates.LeftMouseButton) { e.Action = DragAction.Drop; } else { e.Action = DragAction.Continue; } e.Handled = true; } catch (Exception ex) { OnDragException(ex); } } #endregion #region Start Drag object currentDragDescriptor; void StartDrag() { // prevent nested StartDrag calls mode = SelectionMode.Drag; // mouse capture and Drag'n'Drop doesn't mix textArea.ReleaseMouseCapture(); DataObject dataObject = textArea.Selection.CreateDataObject(textArea); DragDropEffects allowedEffects = DragDropEffects.All; var deleteOnMove = textArea.Selection.Segments.Select(s => new AnchorSegment(textArea.Document, s)).ToList(); foreach (ISegment s in deleteOnMove) { ISegment[] result = textArea.GetDeletableSegments(s); if (result.Length != 1 || result[0].Offset != s.Offset || result[0].EndOffset != s.EndOffset) { allowedEffects &= ~DragDropEffects.Move; } } object dragDescriptor = new object(); this.currentDragDescriptor = dragDescriptor; DragDropEffects resultEffect; using (textArea.AllowCaretOutsideSelection()) { var oldCaretPosition = textArea.Caret.Position; try { Debug.WriteLine("DoDragDrop with allowedEffects=" + allowedEffects); resultEffect = DragDrop.DoDragDrop(textArea, dataObject, allowedEffects); Debug.WriteLine("DoDragDrop done, resultEffect=" + resultEffect); } catch (COMException ex) { // ignore COM errors - don't crash on badly implemented drop targets Debug.WriteLine("DoDragDrop failed: " + ex.ToString()); return; } if (resultEffect == DragDropEffects.None) { // reset caret if drag was aborted textArea.Caret.Position = oldCaretPosition; } } this.currentDragDescriptor = null; if (deleteOnMove != null && resultEffect == DragDropEffects.Move && (allowedEffects & DragDropEffects.Move) == DragDropEffects.Move) { bool draggedInsideSingleDocument = (dragDescriptor == textArea.Document.UndoStack.LastGroupDescriptor); if (draggedInsideSingleDocument) textArea.Document.UndoStack.StartContinuedUndoGroup(null); textArea.Document.BeginUpdate(); try { foreach (ISegment s in deleteOnMove) { textArea.Document.Remove(s.Offset, s.Length); } } finally { textArea.Document.EndUpdate(); if (draggedInsideSingleDocument) textArea.Document.UndoStack.EndUndoGroup(); } } } #endregion #region QueryCursor // provide the IBeam Cursor for the text area void textArea_QueryCursor(object sender, QueryCursorEventArgs e) { if (!e.Handled) { if (mode != SelectionMode.None || !enableTextDragDrop) { e.Cursor = Cursors.IBeam; e.Handled = true; } else if (textArea.TextView.VisualLinesValid) { // Only query the cursor if the visual lines are valid. // If they are invalid, the cursor will get re-queried when the visual lines // get refreshed. Point p = e.GetPosition(textArea.TextView); if (p.X >= 0 && p.Y >= 0 && p.X <= textArea.TextView.ActualWidth && p.Y <= textArea.TextView.ActualHeight) { int visualColumn; int offset = GetOffsetFromMousePosition(e, out visualColumn); if (textArea.Selection.Contains(offset)) e.Cursor = Cursors.Arrow; else e.Cursor = Cursors.IBeam; e.Handled = true; } } } } #endregion #region LeftButtonDown void textArea_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { mode = SelectionMode.None; if (!e.Handled && e.ChangedButton == MouseButton.Left) { ModifierKeys modifiers = Keyboard.Modifiers; bool shift = (modifiers & ModifierKeys.Shift) == ModifierKeys.Shift; if (enableTextDragDrop && e.ClickCount == 1 && !shift) { int visualColumn; int offset = GetOffsetFromMousePosition(e, out visualColumn); if (textArea.Selection.Contains(offset)) { if (textArea.CaptureMouse()) { mode = SelectionMode.PossibleDragStart; possibleDragStartMousePos = e.GetPosition(textArea); } e.Handled = true; return; } } var oldPosition = textArea.Caret.Position; SetCaretOffsetToMousePosition(e); if (!shift) { textArea.ClearSelection(); } if (textArea.CaptureMouse()) { if ((modifiers & ModifierKeys.Alt) == ModifierKeys.Alt && textArea.Options.EnableRectangularSelection) { mode = SelectionMode.Rectangular; if (shift && textArea.Selection is RectangleSelection) { textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position); } } else if (e.ClickCount == 1 && ((modifiers & ModifierKeys.Control) == 0)) { mode = SelectionMode.Normal; if (shift && !(textArea.Selection is RectangleSelection)) { textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position); } } else { SimpleSegment startWord; if (e.ClickCount == 3) { mode = SelectionMode.WholeLine; startWord = GetLineAtMousePosition(e); } else { mode = SelectionMode.WholeWord; startWord = GetWordAtMousePosition(e); } if (startWord == SimpleSegment.Invalid) { mode = SelectionMode.None; textArea.ReleaseMouseCapture(); return; } if (shift && !textArea.Selection.IsEmpty) { if (startWord.Offset < textArea.Selection.SurroundingSegment.Offset) { textArea.Selection = textArea.Selection.SetEndpoint(new TextViewPosition(textArea.Document.GetLocation(startWord.Offset))); } else if (startWord.EndOffset > textArea.Selection.SurroundingSegment.EndOffset) { textArea.Selection = textArea.Selection.SetEndpoint(new TextViewPosition(textArea.Document.GetLocation(startWord.EndOffset))); } this.startWord = new AnchorSegment(textArea.Document, textArea.Selection.SurroundingSegment); } else { textArea.Selection = Selection.Create(textArea, startWord.Offset, startWord.EndOffset); this.startWord = new AnchorSegment(textArea.Document, startWord.Offset, startWord.Length); } } } } e.Handled = true; } #endregion #region Mouse Position <-> Text coordinates SimpleSegment GetWordAtMousePosition(MouseEventArgs e) { TextView textView = textArea.TextView; if (textView == null) return SimpleSegment.Invalid; Point pos = e.GetPosition(textView); if (pos.Y < 0) pos.Y = 0; if (pos.Y > textView.ActualHeight) pos.Y = textView.ActualHeight; pos += textView.ScrollOffset; VisualLine line = textView.GetVisualLineFromVisualTop(pos.Y); if (line != null) { int visualColumn = line.GetVisualColumn(pos, textArea.Selection.EnableVirtualSpace); int wordStartVC = line.GetNextCaretPosition(visualColumn + 1, LogicalDirection.Backward, CaretPositioningMode.WordStartOrSymbol, textArea.Selection.EnableVirtualSpace); if (wordStartVC == -1) wordStartVC = 0; int wordEndVC = line.GetNextCaretPosition(wordStartVC, LogicalDirection.Forward, CaretPositioningMode.WordBorderOrSymbol, textArea.Selection.EnableVirtualSpace); if (wordEndVC == -1) wordEndVC = line.VisualLength; int relOffset = line.FirstDocumentLine.Offset; int wordStartOffset = line.GetRelativeOffset(wordStartVC) + relOffset; int wordEndOffset = line.GetRelativeOffset(wordEndVC) + relOffset; return new SimpleSegment(wordStartOffset, wordEndOffset - wordStartOffset); } else { return SimpleSegment.Invalid; } } SimpleSegment GetLineAtMousePosition(MouseEventArgs e) { TextView textView = textArea.TextView; if (textView == null) return SimpleSegment.Invalid; Point pos = e.GetPosition(textView); if (pos.Y < 0) pos.Y = 0; if (pos.Y > textView.ActualHeight) pos.Y = textView.ActualHeight; pos += textView.ScrollOffset; VisualLine line = textView.GetVisualLineFromVisualTop(pos.Y); if (line != null) { return new SimpleSegment(line.StartOffset, line.LastDocumentLine.EndOffset - line.StartOffset); } else { return SimpleSegment.Invalid; } } int GetOffsetFromMousePosition(MouseEventArgs e, out int visualColumn) { return GetOffsetFromMousePosition(e.GetPosition(textArea.TextView), out visualColumn); } int GetOffsetFromMousePosition(Point positionRelativeToTextView, out int visualColumn) { visualColumn = 0; TextView textView = textArea.TextView; Point pos = positionRelativeToTextView; if (pos.Y < 0) pos.Y = 0; if (pos.Y > textView.ActualHeight) pos.Y = textView.ActualHeight; pos += textView.ScrollOffset; if (pos.Y > textView.DocumentHeight) pos.Y = textView.DocumentHeight - ExtensionMethods.Epsilon; VisualLine line = textView.GetVisualLineFromVisualTop(pos.Y); if (line != null) { visualColumn = line.GetVisualColumn(pos, textArea.Selection.EnableVirtualSpace); return line.GetRelativeOffset(visualColumn) + line.FirstDocumentLine.Offset; } return -1; } int GetOffsetFromMousePositionFirstTextLineOnly(Point positionRelativeToTextView, out int visualColumn) { visualColumn = 0; TextView textView = textArea.TextView; Point pos = positionRelativeToTextView; if (pos.Y < 0) pos.Y = 0; if (pos.Y > textView.ActualHeight) pos.Y = textView.ActualHeight; pos += textView.ScrollOffset; if (pos.Y > textView.DocumentHeight) pos.Y = textView.DocumentHeight - ExtensionMethods.Epsilon; VisualLine line = textView.GetVisualLineFromVisualTop(pos.Y); if (line != null) { visualColumn = line.GetVisualColumn(line.TextLines.First(), pos.X, textArea.Selection.EnableVirtualSpace); return line.GetRelativeOffset(visualColumn) + line.FirstDocumentLine.Offset; } return -1; } #endregion #region MouseMove void textArea_MouseMove(object sender, MouseEventArgs e) { if (e.Handled) return; if (mode == SelectionMode.Normal || mode == SelectionMode.WholeWord || mode == SelectionMode.WholeLine || mode == SelectionMode.Rectangular) { e.Handled = true; if (textArea.TextView.VisualLinesValid) { // If the visual lines are not valid, don't extend the selection. // Extending the selection forces a VisualLine refresh, and it is sufficient // to do that on MouseUp, we don't have to do it every MouseMove. ExtendSelectionToMouse(e); } } else if (mode == SelectionMode.PossibleDragStart) { e.Handled = true; Vector mouseMovement = e.GetPosition(textArea) - possibleDragStartMousePos; if (Math.Abs(mouseMovement.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(mouseMovement.Y) > SystemParameters.MinimumVerticalDragDistance) { StartDrag(); } } } #endregion #region ExtendSelection void SetCaretOffsetToMousePosition(MouseEventArgs e) { SetCaretOffsetToMousePosition(e, null); } void SetCaretOffsetToMousePosition(MouseEventArgs e, ISegment allowedSegment) { int visualColumn; int offset; if (mode == SelectionMode.Rectangular) offset = GetOffsetFromMousePositionFirstTextLineOnly(e.GetPosition(textArea.TextView), out visualColumn); else offset = GetOffsetFromMousePosition(e, out visualColumn); if (allowedSegment != null) { offset = offset.CoerceValue(allowedSegment.Offset, allowedSegment.EndOffset); } if (offset >= 0) { textArea.Caret.Position = new TextViewPosition(textArea.Document.GetLocation(offset), visualColumn); textArea.Caret.DesiredXPos = double.NaN; } } void ExtendSelectionToMouse(MouseEventArgs e) { TextViewPosition oldPosition = textArea.Caret.Position; if (mode == SelectionMode.Normal || mode == SelectionMode.Rectangular) { SetCaretOffsetToMousePosition(e); if (mode == SelectionMode.Normal && textArea.Selection is RectangleSelection) textArea.Selection = new SimpleSelection(textArea, oldPosition, textArea.Caret.Position); else if (mode == SelectionMode.Rectangular && !(textArea.Selection is RectangleSelection)) textArea.Selection = new RectangleSelection(textArea, oldPosition, textArea.Caret.Position); else textArea.Selection = textArea.Selection.StartSelectionOrSetEndpoint(oldPosition, textArea.Caret.Position); } else if (mode == SelectionMode.WholeWord || mode == SelectionMode.WholeLine) { var newWord = (mode == SelectionMode.WholeLine) ? GetLineAtMousePosition(e) : GetWordAtMousePosition(e); if (newWord != SimpleSegment.Invalid) { textArea.Selection = Selection.Create(textArea, Math.Min(newWord.Offset, startWord.Offset), Math.Max(newWord.EndOffset, startWord.EndOffset)); // Set caret offset, but limit the caret to stay inside the selection. // in whole-word selection, it's otherwise possible that we get the caret outside the // selection - but the TextArea doesn't like that and will reset the selection, causing // flickering. SetCaretOffsetToMousePosition(e, textArea.Selection.SurroundingSegment); } } textArea.Caret.BringCaretToView(5.0); } #endregion #region MouseLeftButtonUp void textArea_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (mode == SelectionMode.None || e.Handled) return; e.Handled = true; if (mode == SelectionMode.PossibleDragStart) { // -> this was not a drag start (mouse didn't move after mousedown) SetCaretOffsetToMousePosition(e); textArea.ClearSelection(); } else if (mode == SelectionMode.Normal || mode == SelectionMode.WholeWord || mode == SelectionMode.WholeLine || mode == SelectionMode.Rectangular) { ExtendSelectionToMouse(e); } mode = SelectionMode.None; textArea.ReleaseMouseCapture(); } #endregion } }