Base class for selections.
Esempio n. 1
0
		/// <summary>
		/// If there is a comment block immediately before selection, add it to selection.
		/// </summary>
		Selection ExtendSelectionToSeparateComments(IDocument document, Location selectionStart, Location selectionEnd, IEnumerable<Comment> commentsBlankLines)
		{
			var comments = commentsBlankLines.Where(c => c.CommentStartsLine).ToList();
			int commentIndex = comments.FindIndex(c => c.EndPosition <= selectionStart && IsWhitespaceBetween(document, c.EndPosition, selectionStart));
			if (commentIndex < 0) {
				return null;
			}
			var extendedSelection = new Selection { Start = selectionStart, End = selectionEnd };
			// start at the selection and keep adding comments upwards as long as they are separated only by whitespace
			while (commentIndex >= 0 && IsWhitespaceBetween(document, comments[commentIndex].EndPosition, extendedSelection.Start)) {
				var comment = comments[commentIndex];
				// Include the "//, /*, ///" since they are not included by the parser
				extendedSelection.Start = ExtendLeft(comment.StartPosition, document, "///", "/*", "//") ;
				commentIndex--;
			}
			return extendedSelection;
		}
Esempio n. 2
0
		void SelectText(Selection selection, ITextEditor editor)
		{
			if (selection == null)
				return;
			int startOffset, endOffset;
			try {
				startOffset = editor.Document.PositionToOffset(selection.Start);
				endOffset = editor.Document.PositionToOffset(selection.End);
			} catch (ArgumentOutOfRangeException) {
				return;
			}
			editor.Select(startOffset, endOffset - startOffset);
		}
Esempio n. 3
0
		Selection TryExtendSelectionToComments(IDocument document, Selection selection, IList<ISpecial> commentsBlankLines)
		{
			var extendedToComments = ExtendSelectionToComments(document, selection, commentsBlankLines);
			if (extendedToComments != null)
				return extendedToComments;
			return selection;
		}
Esempio n. 4
0
		Selection ExtendSelectionToComments(IDocument document, Selection selection, IList<ISpecial> commentsBlankLines)
		{
			if (selection == null)
				throw new ArgumentNullException("selection");
			return ExtendSelectionToComments(document, selection.Start, selection.End, commentsBlankLines);
		}
Esempio n. 5
0
		public void JumpTo(int line, int column)
		{
			locationJumpedTo = new TextLocation(column, line);
			selection = Selection.Create(textArea, -1, -1);
		}
Esempio n. 6
0
		public MockTextEditor()
		{
			textArea = new TextArea();
			textArea.Document = textDocument;
			selection = Selection.Create(textArea, -1, -1);
		}
		// move selection - find outermost node in selection, swap selection with closest child of its parent to the selection
		void MoveStatement(ITextEditor editor, MoveStatementDirection direction)
		{
			IList<AstNode> commentsBlankLines;
			var parsedCU = ParseDocument(editor, out commentsBlankLines);
			if (parsedCU == null)	return;
			
			// Find the Statement or Definition containing caret -> Extend selection to Statement or Definition
			
			AstNode currentStatement;
			Selection statementSelection = ExtendSelection(editor, parsedCU, commentsBlankLines, out currentStatement, new Type[] {
			                                               	typeof(Statement),
			                                               	typeof(EntityDeclaration) });
			if (currentStatement == null)
				return;
			statementSelection = TryExtendSelectionToComments(editor.Document, statementSelection, commentsBlankLines);
			// Take its sibling
			if (currentStatement.Parent == null)
				return;
			var siblings = currentStatement.Parent.Children.Where(c => (c.Role.GetType() == currentStatement.Role.GetType())).ToList();
			int currentStatementStartPos = siblings.IndexOf(currentStatement);
			int currentStatementEndPos = currentStatementStartPos;
			
			AstNode swapStartSibling = null;
			AstNode swapEndSibling = null;
			
			// Expand selection to full line, if there is more than one statement in it
			AstNode currentSelectionStartNode = currentStatement;
			while ((currentSelectionStartNode.PrevSibling != null)
			       && !(currentSelectionStartNode.PrevSibling is NewLineNode)
			       && (currentSelectionStartNode.Parent == currentSelectionStartNode.PrevSibling.Parent)) {
				currentSelectionStartNode = currentSelectionStartNode.PrevSibling;
				if (currentSelectionStartNode.EndLocation.Line >= statementSelection.Start.Line) {
					statementSelection.Start = currentSelectionStartNode.StartLocation;
					if (!(currentSelectionStartNode is Comment))
						currentStatementStartPos--;
				} else {
					// This node won't belong to current selection, so go back to next element
					currentSelectionStartNode = currentSelectionStartNode.NextSibling;
					break;
				}
			}
			AstNode currentSelectionEndNode = currentStatement;
			while ((currentSelectionEndNode.NextSibling != null)
			       && !(currentSelectionEndNode.NextSibling is NewLineNode)
			       && (currentSelectionEndNode.Parent == currentSelectionEndNode.NextSibling.Parent)) {
				currentSelectionEndNode = currentSelectionEndNode.NextSibling;
				if (currentSelectionEndNode.StartLocation.Line <= statementSelection.End.Line) {
					statementSelection.End = currentSelectionEndNode.EndLocation;
					if (!(currentSelectionEndNode is Comment))
						currentStatementEndPos++;
				} else {
					// This node won't belong to current selection, so go back to next element
					currentSelectionEndNode = currentSelectionEndNode.NextSibling;
					break;
				}
			}
			
			int swapIndex = 0;
			if (direction == MoveStatementDirection.Down) {
				swapIndex = currentStatementEndPos + 1;
			} else {
				swapIndex = currentStatementStartPos - 1;
			}
			Func<AstNode, bool> isAllowedGrandParentNode =
				(n => (n is IfElseStatement) || (n is ForStatement) || (n is ForeachStatement) || (n is WhileStatement) || (n is DoWhileStatement));
			if (swapIndex < 0) {
				// This is the 1st statement in block, so swap it with beginning of the block to get it outside of it
				var parentNode = currentStatement.Parent as BlockStatement;
				if (parentNode != null) {
					var grandParentNode = parentNode.Parent;
					if ((grandParentNode != null) && isAllowedGrandParentNode(grandParentNode)) {
						// Swap with head of grandparent statement
						swapStartSibling = grandParentNode;
						swapEndSibling = ((BlockStatement) parentNode).LBraceToken;
					}
				}
			} else if (swapIndex >= siblings.Count) {
				// This is the last statement in block, so swap it with block end to get the statement outside of it
				var parentNode = currentStatement.Parent as BlockStatement;
				if (parentNode != null) {
					var grandParentNode = parentNode.Parent;
					if ((grandParentNode != null) && isAllowedGrandParentNode(grandParentNode)) {
						// Swap with rest of grandparent control statement
						swapStartSibling = ((BlockStatement) parentNode).RBraceToken;
						swapEndSibling = grandParentNode;
					}
				}
			} else {
				// In the middle of current block
				swapStartSibling = siblings[swapIndex];
				swapEndSibling = swapStartSibling;
				
				// Special handling for swap nodes containing blocks: Move current statement into it
				if (swapStartSibling is IfElseStatement) {
					var ifElseStatement = swapStartSibling as IfElseStatement;
					if (direction == MoveStatementDirection.Up) {
						BlockStatement swappedIfElseBlock = ifElseStatement.FalseStatement as BlockStatement;
						if (swappedIfElseBlock == null)
							swappedIfElseBlock = ifElseStatement.TrueStatement as BlockStatement;
						if (swappedIfElseBlock != null) {
							swapStartSibling = swappedIfElseBlock.RBraceToken;
						}
					} else {
						BlockStatement swappedIfElseBlock = ifElseStatement.TrueStatement as BlockStatement;
						if (swappedIfElseBlock == null)
							swappedIfElseBlock = ifElseStatement.TrueStatement as BlockStatement;
						if (swappedIfElseBlock != null) {
							swapEndSibling = swappedIfElseBlock.LBraceToken;
						}
					}
				} else {
					BlockStatement innerBlockStatement = GetInnerBlockOfControlNode(swapStartSibling);
					if (innerBlockStatement != null) {
						if (direction == MoveStatementDirection.Up) {
							swapStartSibling = innerBlockStatement.RBraceToken;
						} else {
							swapEndSibling = innerBlockStatement.LBraceToken;
						}
					}
				}
			}

			if ((swapStartSibling == null) || (swapEndSibling == null))
				return;
			
			Selection swapSiblingSelection = ExtendSelectionToComments(editor.Document, swapStartSibling.StartLocation, swapEndSibling.EndLocation, commentsBlankLines);
			if (swapSiblingSelection == null)
				swapSiblingSelection = new Selection() { Start = swapStartSibling.StartLocation, End = swapEndSibling.EndLocation };
			
			// Expand swapSiblingSelection, too, if there are > 1 statements in line
			if (direction == MoveStatementDirection.Up) {
				AstNode tempNode = swapStartSibling;
				while ((tempNode.PrevSibling != null) && !(tempNode.PrevSibling is NewLineNode)) {
					tempNode = tempNode.PrevSibling;
					if (tempNode.EndLocation.Line >= swapSiblingSelection.Start.Line) {
						swapSiblingSelection.Start = tempNode.StartLocation;
					} else {
						break;
					}
				}
			} else {
				AstNode tempNode = swapEndSibling;
				while ((tempNode.NextSibling != null) && !(tempNode.NextSibling is NewLineNode)) {
					tempNode = tempNode.NextSibling;
					if (tempNode.StartLocation.Line <= swapSiblingSelection.End.Line) {
						swapSiblingSelection.End = tempNode.EndLocation;
					} else {
						break;
					}
				}
			}
			
			// Preserve the indentation of moved statement
			if (statementSelection.Start.Column > swapSiblingSelection.Start.Column) {
				statementSelection = new Selection {
					Start = new TextLocation(statementSelection.Start.Line, swapSiblingSelection.Start.Column),
					End = statementSelection.End
				};
			} else if (statementSelection.Start.Column < swapSiblingSelection.Start.Column) {
				swapSiblingSelection = new Selection {
					Start = new TextLocation(swapSiblingSelection.Start.Line, statementSelection.Start.Column),
					End = swapSiblingSelection.End
				};
			}
			
			// Swap them
			string currentNodeText = editor.Document.GetText(statementSelection.Start, statementSelection.End);
			SwapText(editor.Document, statementSelection.Start, statementSelection.End, swapSiblingSelection.Start, swapSiblingSelection.End);
			// Move caret to the start of moved statement
			TextLocation upperLocation = new TextLocation[] {statementSelection.Start, swapSiblingSelection.Start}.Min();
			if (direction == MoveStatementDirection.Up)
				editor.Caret.Location = upperLocation;
			else {
				// look where current statement ended up because it is hard to calculate it correctly
				int currentMovedOffset = editor.Document.Text.IndexOf(currentNodeText, editor.Document.GetOffset(upperLocation));
				editor.Caret.Offset = currentMovedOffset;
			}
		}
Esempio n. 8
0
		public void Select(int selectionStart, int selectionLength)
		{
			selection = Selection.Create(textArea, selectionStart, selectionLength + selectionStart);
		}
Esempio n. 9
0
 /// <summary>
 /// Clears the current selection.
 /// </summary>
 public void ClearSelection()
 {
     Selection = emptySelection;
 }
        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;
                    bool isAtEndOfLine;
                    int  offset = GetOffsetFromMousePosition(e, out visualColumn, out isAtEndOfLine);
                    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;
        }
        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);

                            string pasteFormat;
                            // fill the suggested DataFormat used for the paste action:
                            if (rectangular)
                            {
                                pasteFormat = RectangleSelection.RectangularSelectionDataType;
                            }
                            else
                            {
                                pasteFormat = DataFormats.UnicodeText;
                            }

                            var pastingEventArgs = new DataObjectPastingEventArgs(e.Data, true, pasteFormat);
                            textArea.RaiseEvent(pastingEventArgs);
                            if (pastingEventArgs.CommandCancelled)
                            {
                                return;
                            }

                            // DataObject.PastingEvent handlers might have changed the format to apply.
                            rectangular = pastingEventArgs.FormatToApply == RectangleSelection.RectangularSelectionDataType;

                            // 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 AssertSelectionsAreEqual(Selection expectedSelection, IScriptingConsoleTextEditor consoleTextEditor)
		{
			int selectionEnd = consoleTextEditor.SelectionStart + consoleTextEditor.SelectionLength;
			Selection actualSelection = Selection.Create(avalonEditTextEditor.TextArea, consoleTextEditor.SelectionStart, selectionEnd);
			Assert.AreEqual(expectedSelection, actualSelection);
		}
Esempio n. 13
0
 /// <summary>
 /// Clears the current selection.
 /// </summary>
 public void ClearSelection()
 {
     this.Selection = emptySelection;
 }