|
|
|
@ -1,9 +1,7 @@ |
|
|
|
using System; |
|
|
|
using Avalonia.Controls.Presenters; |
|
|
|
using Avalonia.Input.TextInput; |
|
|
|
using Avalonia.Media.TextFormatting; |
|
|
|
using Avalonia.Reactive; |
|
|
|
using Avalonia.Utilities; |
|
|
|
|
|
|
|
namespace Avalonia.Controls |
|
|
|
{ |
|
|
|
@ -13,6 +11,7 @@ namespace Avalonia.Controls |
|
|
|
private TextPresenter? _presenter; |
|
|
|
private bool _selectionChanged; |
|
|
|
private bool _isInChange; |
|
|
|
private EventHandler? _caretBoundsChangedHandler; |
|
|
|
|
|
|
|
public override Visual TextViewVisual => _presenter!; |
|
|
|
|
|
|
|
@ -20,28 +19,22 @@ namespace Avalonia.Controls |
|
|
|
{ |
|
|
|
get |
|
|
|
{ |
|
|
|
if (_presenter is null || _parent is null) |
|
|
|
if (_parent is null) |
|
|
|
{ |
|
|
|
return ""; |
|
|
|
} |
|
|
|
|
|
|
|
if (_parent.CaretIndex != _presenter.CaretIndex) |
|
|
|
if (_presenter is not null && _parent.CaretIndex != _presenter.CaretIndex) |
|
|
|
{ |
|
|
|
_presenter.SetCurrentValue(TextPresenter.CaretIndexProperty, _parent.CaretIndex); |
|
|
|
} |
|
|
|
|
|
|
|
if (_parent.Text != _presenter.Text) |
|
|
|
if (_presenter is not null && _parent.Text != _presenter.Text) |
|
|
|
{ |
|
|
|
_presenter.SetCurrentValue(TextPresenter.TextProperty, _parent.Text); |
|
|
|
} |
|
|
|
|
|
|
|
var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(_presenter.CaretIndex, false); |
|
|
|
|
|
|
|
var textLine = _presenter.TextLayout.TextLines[lineIndex]; |
|
|
|
|
|
|
|
var lineText = GetTextLineText(textLine); |
|
|
|
|
|
|
|
return lineText; |
|
|
|
return _parent.Text ?? string.Empty; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -69,41 +62,22 @@ namespace Avalonia.Controls |
|
|
|
{ |
|
|
|
get |
|
|
|
{ |
|
|
|
if (_presenter is null || _parent is null) |
|
|
|
if (_parent is null) |
|
|
|
{ |
|
|
|
return default; |
|
|
|
} |
|
|
|
|
|
|
|
var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(_parent.CaretIndex, false); |
|
|
|
|
|
|
|
var textLine = _presenter.TextLayout.TextLines[lineIndex]; |
|
|
|
|
|
|
|
var lineStart = textLine.FirstTextSourceIndex; |
|
|
|
|
|
|
|
var selectionStart = Math.Max(0, _parent.SelectionStart - lineStart); |
|
|
|
|
|
|
|
var selectionEnd = Math.Max(0, _parent.SelectionEnd - lineStart); |
|
|
|
|
|
|
|
return new TextSelection(selectionStart, selectionEnd); |
|
|
|
return new TextSelection(_parent.SelectionStart, _parent.SelectionEnd); |
|
|
|
} |
|
|
|
set |
|
|
|
{ |
|
|
|
if (_parent is null || _presenter is null) |
|
|
|
if (_parent is null) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
var lineIndex = _presenter.TextLayout.GetLineIndexFromCharacterIndex(_parent.CaretIndex, false); |
|
|
|
|
|
|
|
var textLine = _presenter.TextLayout.TextLines[lineIndex]; |
|
|
|
|
|
|
|
var lineStart = textLine.FirstTextSourceIndex; |
|
|
|
|
|
|
|
var selectionStart = lineStart + value.Start; |
|
|
|
var selectionEnd = lineStart + value.End; |
|
|
|
|
|
|
|
_parent.SelectionStart = selectionStart; |
|
|
|
_parent.SelectionEnd = selectionEnd; |
|
|
|
_parent.SelectionStart = value.Start; |
|
|
|
_parent.SelectionEnd = value.End; |
|
|
|
|
|
|
|
RaiseSelectionChanged(); |
|
|
|
} |
|
|
|
@ -136,7 +110,10 @@ namespace Avalonia.Controls |
|
|
|
oldPresenter.CurrentImClient = null; |
|
|
|
oldPresenter.ClearValue(TextPresenter.PreeditTextProperty); |
|
|
|
|
|
|
|
oldPresenter.CaretBoundsChanged -= (s, e) => RaiseCursorRectangleChanged(); |
|
|
|
if (_caretBoundsChangedHandler is not null) |
|
|
|
{ |
|
|
|
oldPresenter.CaretBoundsChanged -= _caretBoundsChangedHandler; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
_presenter = presenter; |
|
|
|
@ -145,7 +122,8 @@ namespace Avalonia.Controls |
|
|
|
{ |
|
|
|
|
|
|
|
_presenter.CurrentImClient = this; |
|
|
|
_presenter.CaretBoundsChanged += (s, e) => RaiseCursorRectangleChanged(); |
|
|
|
_caretBoundsChangedHandler ??= OnPresenterCaretBoundsChanged; |
|
|
|
_presenter.CaretBoundsChanged += _caretBoundsChangedHandler; |
|
|
|
} |
|
|
|
|
|
|
|
RaiseTextViewVisualChanged(); |
|
|
|
@ -153,6 +131,11 @@ namespace Avalonia.Controls |
|
|
|
RaiseCursorRectangleChanged(); |
|
|
|
} |
|
|
|
|
|
|
|
private void OnPresenterCaretBoundsChanged(object? sender, EventArgs e) |
|
|
|
{ |
|
|
|
RaiseCursorRectangleChanged(); |
|
|
|
} |
|
|
|
|
|
|
|
private void OnParentTapped(object? sender, Input.TappedEventArgs e) |
|
|
|
{ |
|
|
|
RaiseInputPaneActivationRequested(); |
|
|
|
@ -171,30 +154,6 @@ namespace Avalonia.Controls |
|
|
|
_presenter.SetCurrentValue(TextPresenter.PreeditTextCursorPositionProperty, cursorPos); |
|
|
|
} |
|
|
|
|
|
|
|
private static string GetTextLineText(TextLine textLine) |
|
|
|
{ |
|
|
|
if (textLine.Length == 0) |
|
|
|
{ |
|
|
|
return string.Empty; |
|
|
|
} |
|
|
|
|
|
|
|
var builder = StringBuilderCache.Acquire(textLine.Length); |
|
|
|
|
|
|
|
foreach (var run in textLine.TextRuns) |
|
|
|
{ |
|
|
|
if (run.Length > 0) |
|
|
|
{ |
|
|
|
builder.Append(run.Text.Span); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var lineText = builder.ToString(); |
|
|
|
|
|
|
|
StringBuilderCache.Release(builder); |
|
|
|
|
|
|
|
return lineText; |
|
|
|
} |
|
|
|
|
|
|
|
public override void ExecuteContextMenuAction(ContextMenuAction action) |
|
|
|
{ |
|
|
|
base.ExecuteContextMenuAction(action); |
|
|
|
|