Rect CalcCaretRectangle(VisualLine visualLine) { if (!visualColumnValid) { RevalidateVisualColumn(visualLine); } TextLine textLine = visualLine.GetTextLine(position.VisualColumn); double xPos = visualLine.GetTextLineVisualXPosition(textLine, position.VisualColumn); double lineTop = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextTop); double lineBottom = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextBottom); return(new Rect(xPos, lineTop, SystemParameters.CaretWidth, lineBottom - lineTop)); }
static Rect GetCharacterBounds(this TextView textView, TextViewPosition pos, HwndSource source) { VisualLine vl = textView.GetVisualLine(pos.Line); if (vl == null) { return(EMPTY_RECT); } // this may happen during layout changes in AvalonDock, so we just return an empty rectangle // in those cases. It should be refreshed immediately. if (source.RootVisual == null || !source.RootVisual.IsAncestorOf(textView)) { return(EMPTY_RECT); } TextLine line = vl.GetTextLine(pos.VisualColumn); Rect displayRect; // calculate the display rect for the current character if (pos.VisualColumn < vl.VisualLengthWithEndOfLineMarker) { displayRect = line.GetTextBounds(pos.VisualColumn, 1).First().Rectangle; displayRect.Offset(0, vl.GetTextLineVisualYPosition(line, VisualYPosition.LineTop)); } else { // if we are in virtual space, we just use one wide-space as character width displayRect = new Rect(vl.GetVisualPosition(pos.VisualColumn, VisualYPosition.TextTop), new Size(textView.WideSpaceWidth, textView.DefaultLineHeight)); } // adjust to current scrolling displayRect.Offset(-textView.ScrollOffset); return(textView .TransformToAncestor(source.RootVisual).TransformBounds(displayRect) // rect on root visual .TransformToDevice(source.RootVisual)); // rect on HWND }
protected override void OnRender(DrawingContext drawingContext) { if (TextView != null && TextView.VisualLinesValid && m_Settings.AssemblyEditorSettings.ShowClockCycles) { if (m_Analyzer.InterPretedAssemblyRows != null) { var interpretedz80Instructions = m_Analyzer.InterPretedAssemblyRows .Where(ar => ar.Instruction.Type == Z80.Kernel.Z80Assembler.InstructionType.ProcessorInstruction) .Select(ar => ar); m_TextColor = new SolidColorBrush(m_Settings.AssemblyEditorSettings.ClockCycleColor.Color); foreach (AssemblyRow assemblyRow in interpretedz80Instructions) { VisualLine line = TextView.VisualLines.FirstOrDefault(vl => vl.FirstDocumentLine.LineNumber == assemblyRow.RowNumber); if (line != null) { FormattedText text = new FormattedText($"[{assemblyRow.ClockCycles}]", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("") , m_EmSize, m_TextColor); double y = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.LineTop); double x = line.GetTextLineVisualXPosition(line.TextLines[0], line.GetTextLineVisualStartColumn(line.TextLines[0])); drawingContext.DrawText(text, new Point(x, y - TextView.VerticalOffset)); } } } } }
static Rect GetCharacterBounds(this TextView textView, TextViewPosition pos, HwndSource source) { VisualLine vl = textView.GetVisualLine(pos.Line); if (vl == null) { return(EMPTY_RECT); } TextLine line = vl.GetTextLine(pos.VisualColumn); double offset = vl.GetTextLineVisualYPosition(line, VisualYPosition.LineTop) - textView.ScrollOffset.Y; Rect r = line.GetTextBounds(pos.VisualColumn, 1).First().Rectangle; r.Offset(-textView.ScrollOffset.X, offset); // this may happen during layout changes in AvalonDock, so we just return an empty rectangle // in those cases. It should be refreshed immediately. if (!source.RootVisual.IsAncestorOf(textView)) { return(EMPTY_RECT); } Point pointOnRootVisual = textView.TransformToAncestor(source.RootVisual).Transform(r.Location); Point pointOnHwnd = pointOnRootVisual.TransformToDevice(source.RootVisual); r.Location = pointOnHwnd; return(r); }
public void Render(DrawingContext drawingContext, VisualLine line, Size pixelSize) { var lineMiddle = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.TextMiddle) - _textView.VerticalOffset; // Draw the error line drawingContext.DrawLine(new Pen(Brushes.Red, 4), new Point(0, lineMiddle), new Point(20, lineMiddle)); }
public void Render(DrawingContext drawingContext, VisualLine line, Size pixelSize) { var lineMiddle = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.TextMiddle) - _textView.VerticalOffset; var rect = new Rect(3, PixelSnapHelpers.Round(lineMiddle - 8, pixelSize.Height) + 1, 14, 14); drawingContext.DrawRoundedRectangle(Brushes.DarkRed, null, rect, 8, 8); }
private void DrawText(DrawingContext drawingContext, Brush foreground) { for (int i = 0; i < TextView.VisualLines.Count; i++) { VisualLine line = TextView.VisualLines[i]; FormattedText text = GetTextByState(LeftMarginStatesList[line.FirstDocumentLine.LineNumber - 1], foreground); double y = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.TextTop); drawingContext.DrawText(text, new Point(INSERTION_X_COORDINATE, y - TextView.VerticalOffset)); } }
Rect CalcCaretOverstrikeRectangle(VisualLine visualLine) { if (!visualColumnValid) { RevalidateVisualColumn(visualLine); } int currentPos = position.VisualColumn; // The text being overwritten in overstrike mode is everything up to the next normal caret stop int nextPos = visualLine.GetNextCaretPosition(currentPos, LogicalDirection.Forward, CaretPositioningMode.Normal, true); TextLine textLine = visualLine.GetTextLine(currentPos); Rect r; if (currentPos < visualLine.VisualLength) { // If the caret is within the text, use GetTextBounds() for the text being overwritten. // This is necessary to ensure the rectangle is calculated correctly in bidirectional text. var textBounds = textLine.GetTextBounds(currentPos, nextPos - currentPos)[0]; r = textBounds.Rectangle; r.Y += visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineTop); } else { // If the caret is at the end of the line (or in virtual space), // use the visual X position of currentPos and nextPos (one or more of which will be in virtual space) double xPos = visualLine.GetTextLineVisualXPosition(textLine, currentPos); double xPos2 = visualLine.GetTextLineVisualXPosition(textLine, nextPos); double lineTop = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextTop); double lineBottom = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.TextBottom); r = new Rect(xPos, lineTop, xPos2 - xPos, lineBottom - lineTop); } // If the caret is too small (e.g. in front of zero-width character), ensure it's still visible if (r.Width < SystemParameters.CaretWidth) { r.Width = SystemParameters.CaretWidth; } return(r); }
double GetVisualPos(VisualLine vl, TextLine tl, double pixelHeight) { double pos = vl.GetTextLineVisualYPosition(tl, VisualYPosition.LineTop) + tl.Height / 2 - TextView.VerticalOffset; return(PixelSnapHelpers.PixelAlign(pos, pixelHeight)); }
static void MoveCaretUpDown(TextArea textArea, CaretMovementType direction, VisualLine visualLine, TextLine textLine, int caretVisualColumn) { // moving up/down happens using the desired visual X position double xPos = textArea.Caret.DesiredXPos; if (double.IsNaN(xPos)) { xPos = textLine.GetDistanceFromCharacterHit(new CharacterHit(caretVisualColumn, 0)); } // now find the TextLine+VisualLine where the caret will end up in VisualLine targetVisualLine = visualLine; TextLine targetLine; int textLineIndex = visualLine.TextLines.IndexOf(textLine); switch (direction) { case CaretMovementType.LineUp: { // Move up: move to the previous TextLine in the same visual line // or move to the last TextLine of the previous visual line int prevLineNumber = visualLine.FirstDocumentLine.LineNumber - 1; if (textLineIndex > 0) { targetLine = visualLine.TextLines[textLineIndex - 1]; } else if (prevLineNumber >= 1) { DocumentLine prevLine = textArea.Document.GetLineByNumber(prevLineNumber); targetVisualLine = textArea.TextView.GetOrConstructVisualLine(prevLine); targetLine = targetVisualLine.TextLines[targetVisualLine.TextLines.Count - 1]; } else { targetLine = null; } break; } case CaretMovementType.LineDown: { // Move down: move to the next TextLine in the same visual line // or move to the first TextLine of the next visual line int nextLineNumber = visualLine.LastDocumentLine.LineNumber + 1; if (textLineIndex < visualLine.TextLines.Count - 1) { targetLine = visualLine.TextLines[textLineIndex + 1]; } else if (nextLineNumber <= textArea.Document.LineCount) { DocumentLine nextLine = textArea.Document.GetLineByNumber(nextLineNumber); targetVisualLine = textArea.TextView.GetOrConstructVisualLine(nextLine); targetLine = targetVisualLine.TextLines[0]; } else { targetLine = null; } break; } case CaretMovementType.PageUp: case CaretMovementType.PageDown: { // Page up/down: find the target line using its visual position double yPos = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineMiddle); if (direction == CaretMovementType.PageUp) { yPos -= textArea.TextView.RenderSize.Height; } else { yPos += textArea.TextView.RenderSize.Height; } DocumentLine newLine = textArea.TextView.GetDocumentLineByVisualTop(yPos); targetVisualLine = textArea.TextView.GetOrConstructVisualLine(newLine); targetLine = targetVisualLine.GetTextLineByVisualYPosition(yPos); break; } default: throw new NotSupportedException(direction.ToString()); } if (targetLine != null) { CharacterHit ch = targetLine.GetCharacterHitFromDistance(xPos); SetCaretPosition(textArea, targetVisualLine, targetLine, ch, false); textArea.Caret.DesiredXPos = xPos; } }
static TextViewPosition GetUpDownCaretPosition(TextView textView, TextViewPosition caretPosition, CaretMovementType direction, VisualLine visualLine, TextLine textLine, bool enableVirtualSpace, ref double xPos) { // moving up/down happens using the desired visual X position if (double.IsNaN(xPos)) { xPos = visualLine.GetTextLineVisualXPosition(textLine, caretPosition.VisualColumn); } // now find the TextLine+VisualLine where the caret will end up in VisualLine targetVisualLine = visualLine; TextLine targetLine; int textLineIndex = visualLine.TextLines.IndexOf(textLine); switch (direction) { case CaretMovementType.LineUp: { // Move up: move to the previous TextLine in the same visual line // or move to the last TextLine of the previous visual line int prevLineNumber = visualLine.FirstDocumentLine.LineNumber - 1; if (textLineIndex > 0) { targetLine = visualLine.TextLines[textLineIndex - 1]; } else if (prevLineNumber >= 1) { DocumentLine prevLine = textView.Document.GetLineByNumber(prevLineNumber); targetVisualLine = textView.GetOrConstructVisualLine(prevLine); targetLine = targetVisualLine.TextLines[targetVisualLine.TextLines.Count - 1]; } else { targetLine = null; } break; } case CaretMovementType.LineDown: { // Move down: move to the next TextLine in the same visual line // or move to the first TextLine of the next visual line int nextLineNumber = visualLine.LastDocumentLine.LineNumber + 1; if (textLineIndex < visualLine.TextLines.Count - 1) { targetLine = visualLine.TextLines[textLineIndex + 1]; } else if (nextLineNumber <= textView.Document.LineCount) { DocumentLine nextLine = textView.Document.GetLineByNumber(nextLineNumber); targetVisualLine = textView.GetOrConstructVisualLine(nextLine); targetLine = targetVisualLine.TextLines[0]; } else { targetLine = null; } break; } case CaretMovementType.PageUp: case CaretMovementType.PageDown: { // Page up/down: find the target line using its visual position double yPos = visualLine.GetTextLineVisualYPosition(textLine, VisualYPosition.LineMiddle); if (direction == CaretMovementType.PageUp) { yPos -= textView.RenderSize.Height; } else { yPos += textView.RenderSize.Height; } DocumentLine newLine = textView.GetDocumentLineByVisualTop(yPos); targetVisualLine = textView.GetOrConstructVisualLine(newLine); targetLine = targetVisualLine.GetTextLineByVisualYPosition(yPos); break; } default: throw new NotSupportedException(direction.ToString()); } if (targetLine != null) { double yPos = targetVisualLine.GetTextLineVisualYPosition(targetLine, VisualYPosition.LineMiddle); int newVisualColumn = targetVisualLine.GetVisualColumn(new Point(xPos, yPos), enableVirtualSpace); // prevent wrapping to the next line; TODO: could 'IsAtEnd' help here? int targetLineStartCol = targetVisualLine.GetTextLineVisualStartColumn(targetLine); if (newVisualColumn >= targetLineStartCol + targetLine.Length) { if (newVisualColumn <= targetVisualLine.VisualLength) { newVisualColumn = targetLineStartCol + targetLine.Length - 1; } } return(targetVisualLine.GetTextViewPosition(newVisualColumn)); } else { return(caretPosition); } }
double GetVisualPos(VisualLine vl, TextLine tl) { double pos = vl.GetTextLineVisualYPosition(tl, VisualYPosition.LineTop) + tl.Height / 2 - TextView.VerticalOffset; return(Math.Round(pos) + 0.5); }