diff --git a/samples/Sandbox/MainWindow.axaml b/samples/Sandbox/MainWindow.axaml
index 6929f192c7..20d7a53a11 100644
--- a/samples/Sandbox/MainWindow.axaml
+++ b/samples/Sandbox/MainWindow.axaml
@@ -1,4 +1,9 @@
+
+
+
+
+
diff --git a/samples/Sandbox/MainWindow.axaml.cs b/samples/Sandbox/MainWindow.axaml.cs
index 3d54036d29..23d45edf6a 100644
--- a/samples/Sandbox/MainWindow.axaml.cs
+++ b/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;
diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs
index e540f58195..3f4d881735 100644
--- a/src/Avalonia.Controls/Presenters/TextPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs
@@ -54,6 +54,15 @@ namespace Avalonia.Controls.Presenters
o => o.Text,
(o, v) => o.Text = v);
+ ///
+ /// Defines the property.
+ ///
+ public static readonly DirectProperty PreeditTextProperty =
+ AvaloniaProperty.RegisterDirect(
+ nameof(PreeditText),
+ o => o.PreeditText,
+ (o, v) => o.PreeditText = v);
+
///
/// Defines the property.
///
@@ -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);
+ }
+
///
/// Gets or sets the font family.
///
@@ -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;
+ }
+
///
/// Creates the used to render the text.
///
@@ -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>? textStyleOverrides = null;
+ List>? textStyleOverrides = null;
if (length > 0 && SelectionForegroundBrush != null)
{
- textStyleOverrides = new[]
+ textStyleOverrides = new List>
{
new ValueSpan(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(_caretIndex, _preeditText.Length,
+ new GenericTextRunProperties(typeface, FontSize,
+ foregroundBrush: foreground,
+ textDecorations: TextDecorations.Underline));
+
+ if (textStyleOverrides == null)
+ {
+ textStyleOverrides = new List>
+ {
+ 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):
diff --git a/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs b/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
index 4d2ed03440..f9eb90611d 100644
--- a/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
+++ b/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);