Browse Source

Rendering part of PreeditText

feature/ImePreeditText
Benedikt Stebner 4 years ago
parent
commit
75870f751e
  1. 5
      samples/Sandbox/MainWindow.axaml
  2. 1
      samples/Sandbox/MainWindow.axaml.cs
  3. 57
      src/Avalonia.Controls/Presenters/TextPresenter.cs
  4. 25
      src/Avalonia.Controls/TextBoxTextInputMethodClient.cs

5
samples/Sandbox/MainWindow.axaml

@ -1,4 +1,9 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
x:Class="Sandbox.MainWindow">
<StackPanel>
<TextBox x:Name="txtBox" />
<TextPresenter Text="Hello World" PreeditText="{Binding #txtBox.Text}" CaretIndex="11"/>
</StackPanel>
</Window>

1
samples/Sandbox/MainWindow.axaml.cs

@ -1,5 +1,6 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Markup.Xaml;
using Avalonia.Win32.WinRT.Composition;

57
src/Avalonia.Controls/Presenters/TextPresenter.cs

@ -54,6 +54,15 @@ namespace Avalonia.Controls.Presenters
o => o.Text,
(o, v) => o.Text = v);
/// <summary>
/// Defines the <see cref="PreeditText"/> property.
/// </summary>
public static readonly DirectProperty<TextPresenter, string?> PreeditTextProperty =
AvaloniaProperty.RegisterDirect<TextPresenter, string?>(
nameof(PreeditText),
o => o.PreeditText,
(o, v) => o.PreeditText = v);
/// <summary>
/// Defines the <see cref="TextAlignment"/> property.
/// </summary>
@ -90,6 +99,7 @@ namespace Avalonia.Controls.Presenters
private CharacterHit _lastCharacterHit;
private Rect _caretBounds;
private Point _navigationPosition;
private string? _preeditText;
static TextPresenter()
{
@ -124,6 +134,12 @@ namespace Avalonia.Controls.Presenters
set => SetAndRaise(TextProperty, ref _text, value);
}
public string? PreeditText
{
get => _preeditText;
set => SetAndRaise(PreeditTextProperty, ref _preeditText, value);
}
/// <summary>
/// Gets or sets the font family.
/// </summary>
@ -479,6 +495,18 @@ namespace Avalonia.Controls.Presenters
}
}
private string? GetText()
{
if (!string.IsNullOrEmpty(_preeditText))
{
var text = _text?.Substring(0, _caretIndex) + _preeditText + _text?.Substring(_caretIndex);
return text;
}
return _text;
}
/// <summary>
/// Creates the <see cref="TextLayout"/> used to render the text.
/// </summary>
@ -487,7 +515,7 @@ namespace Avalonia.Controls.Presenters
{
TextLayout result;
var text = Text;
var text = GetText();
var typeface = new Typeface(FontFamily, FontStyle, FontWeight);
@ -496,11 +524,11 @@ namespace Avalonia.Controls.Presenters
var start = Math.Min(selectionStart, selectionEnd);
var length = Math.Max(selectionStart, selectionEnd) - start;
IReadOnlyList<ValueSpan<TextRunProperties>>? textStyleOverrides = null;
List<ValueSpan<TextRunProperties>>? textStyleOverrides = null;
if (length > 0 && SelectionForegroundBrush != null)
{
textStyleOverrides = new[]
textStyleOverrides = new List<ValueSpan<TextRunProperties>>
{
new ValueSpan<TextRunProperties>(start, length,
new GenericTextRunProperties(typeface, FontSize,
@ -508,6 +536,28 @@ namespace Avalonia.Controls.Presenters
};
}
var foreground = Foreground;
if (!string.IsNullOrEmpty(_preeditText))
{
var preeditHighlight = new ValueSpan<TextRunProperties>(_caretIndex, _preeditText.Length,
new GenericTextRunProperties(typeface, FontSize,
foregroundBrush: foreground,
textDecorations: TextDecorations.Underline));
if (textStyleOverrides == null)
{
textStyleOverrides = new List<ValueSpan<TextRunProperties>>
{
preeditHighlight
};
}
else
{
textStyleOverrides.Add(preeditHighlight);
}
}
if (PasswordChar != default(char) && !RevealPassword)
{
result = CreateTextLayoutInternal(_constraint, new string(PasswordChar, text?.Length ?? 0), typeface,
@ -814,6 +864,7 @@ namespace Avalonia.Controls.Presenters
case nameof (FontStretch):
case nameof (Text):
case nameof (PreeditText):
case nameof (TextAlignment):
case nameof (TextWrapping):

25
src/Avalonia.Controls/TextBoxTextInputMethodClient.cs

@ -9,7 +9,7 @@ namespace Avalonia.Controls
{
internal class TextBoxTextInputMethodClient : ITextInputMethodClient
{
private InputElement? _parent;
private TextBox? _parent;
private TextPresenter? _presenter;
public Rect CursorRectangle
@ -36,19 +36,29 @@ namespace Avalonia.Controls
public event EventHandler? CursorRectangleChanged;
public IVisual TextViewVisual => _presenter!;
public event EventHandler? TextViewVisualChanged;
public bool SupportsPreedit => false;
public void SetPreeditText(string text) => throw new NotSupportedException();
public bool SupportsPreedit => true;
public void SetPreeditText(string? text)
{
if(_presenter == null)
{
return;
}
_presenter.PreeditText = text;
}
public bool SupportsSurroundingText => false;
public TextInputMethodSurroundingText SurroundingText => throw new NotSupportedException();
public event EventHandler? SurroundingTextChanged { add { } remove { } }
public TextInputMethodSurroundingText SurroundingText => throw new NotSupportedException();
public string? TextBeforeCursor => null;
public string? TextAfterCursor => null;
private void OnCaretBoundsChanged(object? sender, EventArgs e) => CursorRectangleChanged?.Invoke(this, EventArgs.Empty);
public void SetPresenter(TextPresenter? presenter, InputElement? parent)
public void SetPresenter(TextPresenter? presenter, TextBox? parent)
{
_parent = parent;
@ -63,6 +73,11 @@ namespace Avalonia.Controls
{
_presenter.CaretBoundsChanged += OnCaretBoundsChanged;
}
if(presenter == null)
{
SetPreeditText(null);
}
TextViewVisualChanged?.Invoke(this, EventArgs.Empty);
CursorRectangleChanged?.Invoke(this, EventArgs.Empty);

Loading…
Cancel
Save