diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs index 458e972db3..1c60c0d906 100644 --- a/src/Avalonia.Controls/Presenters/TextPresenter.cs +++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs @@ -78,14 +78,14 @@ namespace Avalonia.Controls.Presenters private int _selectionEnd; private bool _caretBlink; private string _text; - private TextLayout _textLayout; + private TextLayout? _textLayout; private Size _constraint = Size.Infinity; private CharacterHit _lastCharacterHit; private Rect _caretBounds; private Point _navigationPosition; - private ScrollViewer _scrollViewer; + private ScrollViewer? _scrollViewer; static TextPresenter() { @@ -99,7 +99,7 @@ namespace Avalonia.Controls.Presenters _caretTimer.Tick += CaretTimerTick; } - public event EventHandler CaretBoundsChanged; + public event EventHandler? CaretBoundsChanged; /// /// Gets or sets a brush used to paint the control's background. @@ -186,7 +186,7 @@ namespace Avalonia.Controls.Presenters /// /// Gets the used to render the text. /// - public TextLayout TextLayout + public TextLayout? TextLayout { get { @@ -284,13 +284,20 @@ namespace Avalonia.Controls.Presenters /// /// /// A object. - private TextLayout CreateTextLayoutInternal(Size constraint, string text, Typeface typeface, - IReadOnlyList> textStyleOverrides) + private TextLayout? CreateTextLayoutInternal(Size constraint, string text, Typeface typeface, + IReadOnlyList>? textStyleOverrides) { + var foreground = Foreground; + + if (foreground == null) + { + return null; + } + var maxWidth = MathUtilities.IsZero(constraint.Width) ? double.PositiveInfinity : constraint.Width; var maxHeight = MathUtilities.IsZero(constraint.Height) ? double.PositiveInfinity : constraint.Height; - var textLayout = new TextLayout(text ?? string.Empty, typeface, FontSize, Foreground, TextAlignment, + var textLayout = new TextLayout(text ?? string.Empty, typeface, FontSize, foreground, TextAlignment, TextWrapping, maxWidth: maxWidth, maxHeight: maxHeight, textStyleOverrides: textStyleOverrides, flowDirection: FlowDirection); @@ -310,6 +317,11 @@ namespace Avalonia.Controls.Presenters context.FillRectangle(background, new Rect(Bounds.Size)); } + if (TextLayout == null) + { + return; + } + var top = 0d; var left = 0.0; @@ -344,7 +356,7 @@ namespace Avalonia.Controls.Presenters var selectionStart = SelectionStart; var selectionEnd = SelectionEnd; - if (selectionStart != selectionEnd) + if (selectionStart != selectionEnd && TextLayout != null) { var start = Math.Min(selectionStart, selectionEnd); var length = Math.Max(selectionStart, selectionEnd) - start; @@ -458,9 +470,9 @@ namespace Avalonia.Controls.Presenters /// Creates the used to render the text. /// /// A object. - protected virtual TextLayout CreateTextLayout() + protected virtual TextLayout? CreateTextLayout() { - TextLayout result; + TextLayout? result; var text = Text; @@ -471,7 +483,7 @@ namespace Avalonia.Controls.Presenters var start = Math.Min(selectionStart, selectionEnd); var length = Math.Max(selectionStart, selectionEnd) - start; - IReadOnlyList> textStyleOverrides = null; + IReadOnlyList>? textStyleOverrides = null; if (length > 0) { @@ -512,7 +524,7 @@ namespace Avalonia.Controls.Presenters InvalidateTextLayout(); } - return TextLayout.Size; + return TextLayout?.Size ?? default; } private int CoerceCaretIndex(int value) @@ -522,7 +534,7 @@ namespace Avalonia.Controls.Presenters return Math.Max(0, Math.Min(length, value)); } - private void CaretTimerTick(object sender, EventArgs e) + private void CaretTimerTick(object? sender, EventArgs e) { _caretBlink = !_caretBlink; InvalidateVisual(); @@ -530,6 +542,11 @@ namespace Avalonia.Controls.Presenters public void MoveCaretToTextPosition(int textPosition, bool trailingEdge = false) { + if (TextLayout == null) + { + return; + } + var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(textPosition, trailingEdge); var textLine = TextLayout.TextLines[lineIndex]; @@ -556,6 +573,11 @@ namespace Avalonia.Controls.Presenters public void MoveCaretToPoint(Point point) { + if (TextLayout == null) + { + return; + } + var hit = TextLayout.HitTestPoint(point); UpdateCaret(hit.CharacterHit); @@ -565,6 +587,11 @@ namespace Avalonia.Controls.Presenters public void MoveCaretVertical(LogicalDirection direction = LogicalDirection.Forward) { + if (TextLayout == null) + { + return; + } + var lineIndex = TextLayout.GetLineIndexFromCharacterIndex(CaretIndex, _lastCharacterHit.TrailingLength > 0); if (lineIndex < 0) @@ -606,6 +633,11 @@ namespace Avalonia.Controls.Presenters public void MoveCaretHorizontal(LogicalDirection direction = LogicalDirection.Forward) { + if (TextLayout == null) + { + return; + } + var characterHit = _lastCharacterHit; var caretIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength; @@ -681,6 +713,11 @@ namespace Avalonia.Controls.Presenters private void UpdateCaret(CharacterHit characterHit) { + if (TextLayout == null) + { + return; + } + _lastCharacterHit = characterHit; var caretIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength; diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 274074030a..dc6b8ffa4c 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -937,7 +937,7 @@ namespace Avalonia.Controls { selection = DetectSelection(); - _presenter?.MoveCaretVertical(); + _presenter.MoveCaretVertical(); if (caretIndex != _presenter.CaretIndex) { @@ -1273,7 +1273,7 @@ namespace Avalonia.Controls { caretIndex = 0; } - else + else if (_presenter.TextLayout is not null) { var lines = _presenter.TextLayout.TextLines; var pos = 0; @@ -1308,7 +1308,7 @@ namespace Avalonia.Controls { caretIndex = text.Length; } - else + else if (_presenter.TextLayout is not null) { var lines = _presenter.TextLayout.TextLines; var pos = 0;