Browse Source

remove event for querying text input options. replace with attached property that is inheritable.

pull/7781/head
Dan Walmsley 4 years ago
parent
commit
409be7f33f
  1. 3
      samples/ControlCatalog/Pages/TextBoxPage.xaml
  2. 6
      samples/ControlCatalog/Pages/TextBoxPage.xaml.cs
  3. 4
      src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs
  4. 8
      src/Avalonia.Input/ApiCompatBaseline.txt
  5. 17
      src/Avalonia.Input/InputElement.cs
  6. 1
      src/Avalonia.Input/Properties/AssemblyInfo.cs
  7. 2
      src/Avalonia.Input/TextInput/ITextInputMethodImpl.cs
  8. 31
      src/Avalonia.Input/TextInput/InputMethodManager.cs
  9. 37
      src/Avalonia.Input/TextInput/TextInputOptions.cs
  10. 71
      src/iOS/Avalonia.iOS/AvaloniaUIResponder.cs

3
samples/ControlCatalog/Pages/TextBoxPage.xaml

@ -18,7 +18,7 @@
</TextBox.ContextFlyout>
</TextBox>
<TextBox Width="200" Watermark="ReadOnly" IsReadOnly="True" Text="This is read only"/>
<TextBox Width="200" Watermark="Numeric with watermark" x:Name="numericWatermark"/>
<TextBox Width="200" Watermark="Numeric with watermark" TextInputOptions.ContentType="Number" />
<TextBox Width="200"
Watermark="Floating Watermark"
UseFloatingWatermark="True"
@ -34,6 +34,7 @@
<TextBox Width="200"
Watermark="Password Box"
Classes="revealPasswordButton"
TextInputOptions.ContentType="Password"
UseFloatingWatermark="True"
PasswordChar="*"
Text="Password" />

6
samples/ControlCatalog/Pages/TextBoxPage.xaml.cs

@ -13,12 +13,6 @@ namespace ControlCatalog.Pages
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
this.Get<TextBox>("numericWatermark")
.TextInputOptionsQuery += (s, a) =>
{
a.ContentType = Avalonia.Input.TextInput.TextInputContentType.Number;
};
}
}
}

4
src/Avalonia.FreeDesktop/DBusIme/DBusTextInputMethodBase.cs

@ -198,9 +198,9 @@ namespace Avalonia.FreeDesktop.DBusIme
UpdateActive();
}
void ITextInputMethodImpl.SetActive(bool active)
void ITextInputMethodImpl.SetActive(ITextInputMethodClient client)
{
_controlActive = active;
_controlActive = client is { };
UpdateActive();
}

8
src/Avalonia.Input/ApiCompatBaseline.txt

@ -4,11 +4,17 @@ MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.In
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.Gestures.RightTappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.Gestures.TappedEvent' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Input.IFocusManager.RemoveFocusScope(Avalonia.Input.IFocusScope)' is present in the implementation but not in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Input.TextInput.TextInputOptionsQueryEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Input.TextInput.TextInputOptionsQueryEventArgs> Avalonia.Input.InputElement.TextInputOptionsQueryEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.InputElement.DoubleTappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Interactivity.RoutedEvent<Avalonia.Interactivity.RoutedEventArgs> Avalonia.Input.InputElement.TappedEvent' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.add_DoubleTapped(System.EventHandler<Avalonia.Interactivity.RoutedEventArgs>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.add_Tapped(System.EventHandler<Avalonia.Interactivity.RoutedEventArgs>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.add_TextInputOptionsQuery(System.EventHandler<Avalonia.Input.TextInput.TextInputOptionsQueryEventArgs>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.remove_DoubleTapped(System.EventHandler<Avalonia.Interactivity.RoutedEventArgs>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.remove_Tapped(System.EventHandler<Avalonia.Interactivity.RoutedEventArgs>)' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Input.InputElement.remove_TextInputOptionsQuery(System.EventHandler<Avalonia.Input.TextInput.TextInputOptionsQueryEventArgs>)' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Input.TextInput.ITextInputMethodImpl.SetActive(Avalonia.Input.TextInput.ITextInputMethodClient)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Input.TextInput.ITextInputMethodImpl.SetActive(System.Boolean)' is present in the contract but not in the implementation.
MembersMustExist : Member 'public void Avalonia.Input.TextInput.ITextInputMethodImpl.SetActive(System.Boolean)' does not exist in the implementation but it does exist in the contract.
TypesMustExist : Type 'Avalonia.Platform.IStandardCursorFactory' does not exist in the implementation but it does exist in the contract.
Total Issues: 12
Total Issues: 18

17
src/Avalonia.Input/InputElement.cs

@ -126,14 +126,6 @@ namespace Avalonia.Input
RoutedEvent.Register<InputElement, TextInputMethodClientRequestedEventArgs>(
"TextInputMethodClientRequested",
RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
/// <summary>
/// Defines the <see cref="TextInputOptionsQuery"/> event.
/// </summary>
public static readonly RoutedEvent<TextInputOptionsQueryEventArgs> TextInputOptionsQueryEvent =
RoutedEvent.Register<InputElement, TextInputOptionsQueryEventArgs>(
"TextInputOptionsQuery",
RoutingStrategies.Tunnel | RoutingStrategies.Bubble);
/// <summary>
/// Defines the <see cref="PointerEnter"/> event.
@ -283,15 +275,6 @@ namespace Avalonia.Input
add { AddHandler(TextInputMethodClientRequestedEvent, value); }
remove { RemoveHandler(TextInputMethodClientRequestedEvent, value); }
}
/// <summary>
/// Occurs when an input element gains input focus and input method is asking for required content options
/// </summary>
public event EventHandler<TextInputOptionsQueryEventArgs>? TextInputOptionsQuery
{
add { AddHandler(TextInputOptionsQueryEvent, value); }
remove { RemoveHandler(TextInputOptionsQueryEvent, value); }
}
/// <summary>
/// Occurs when the pointer enters the control.

1
src/Avalonia.Input/Properties/AssemblyInfo.cs

@ -2,4 +2,5 @@ using System.Reflection;
using Avalonia.Metadata;
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Input")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Input.TextInput")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Input.GestureRecognizers")]

2
src/Avalonia.Input/TextInput/ITextInputMethodImpl.cs

@ -2,7 +2,7 @@ namespace Avalonia.Input.TextInput
{
public interface ITextInputMethodImpl
{
void SetActive(bool active);
void SetActive(ITextInputMethodClient? client);
void SetCursorRect(Rect rect);
void SetOptions(TextInputOptionsQueryEventArgs options);
void Reset();

31
src/Avalonia.Input/TextInput/InputMethodManager.cs

@ -35,21 +35,25 @@ namespace Avalonia.Input.TextInput
{
_client.CursorRectangleChanged += OnCursorRectangleChanged;
_client.TextViewVisualChanged += OnTextViewVisualChanged;
var optionsQuery = new TextInputOptionsQueryEventArgs
{
RoutedEvent = InputElement.TextInputOptionsQueryEvent
};
_focusedElement?.RaiseEvent(optionsQuery);
_im?.Reset();
_im?.SetOptions(optionsQuery);
_transformTracker?.SetVisual(_client?.TextViewVisual);
if (_focusedElement is AvaloniaObject target)
{
var options =
new TextInputOptionsQueryEventArgs { ContentType = TextInputOptions.GetContentType(target) };
_im?.SetOptions(options);
}
_transformTracker.SetVisual(_client?.TextViewVisual);
UpdateCursorRect();
_im?.SetActive(true);
_im?.SetActive(_client);
}
else
{
_im?.SetActive(false);
_im?.SetActive(null);
_transformTracker.SetVisual(null);
}
}
@ -91,12 +95,15 @@ namespace Avalonia.Input.TextInput
_focusedElement = element;
var inputMethod = (element?.VisualRoot as ITextInputMethodRoot)?.InputMethod;
if (_im != inputMethod)
_im?.SetActive(false);
_im = inputMethod;
TryFindAndApplyClient();
if (_im != inputMethod)
{
_im?.SetActive(Client);
}
}
private void TryFindAndApplyClient()

37
src/Avalonia.Input/TextInput/TextInputOptions.cs

@ -0,0 +1,37 @@
namespace Avalonia.Input.TextInput;
public class TextInputOptions
{
/// <summary>
/// Defines the <see cref="ContentType"/> property.
/// </summary>
public static readonly AttachedProperty<TextInputContentType> ContentTypeProperty =
AvaloniaProperty.RegisterAttached<TextInputOptions, AvaloniaObject, TextInputContentType>(
"ContentType",
defaultValue: TextInputContentType.Normal,
inherits: true);
/// <summary>
/// Sets the value of the attached <see cref="ContentTypeProperty"/> on a control.
/// </summary>
/// <param name="avaloniaObject">The control.</param>
/// <param name="value">The property value to set.</param>
public static void SetContentType(AvaloniaObject avaloniaObject, TextInputContentType value)
{
avaloniaObject.SetValue(ContentTypeProperty, value);
}
/// <summary>
/// Gets the value of the attached <see cref="ContentTypeProperty"/> on a control.
/// </summary>
/// <param name="avaloniaObject">The control.</param>
/// <returns>The font family.</returns>
public static TextInputContentType GetContentType(AvaloniaObject avaloniaObject)
{
return avaloniaObject.GetValue(ContentTypeProperty);
}
}

71
src/iOS/Avalonia.iOS/AvaloniaUIResponder.cs

@ -1,20 +1,41 @@
using Foundation;
using ObjCRuntime;
using UIKit;
using Avalonia.Input.TextInput;
using Avalonia.Input;
using Avalonia.Input.Raw;
using UIKit;
namespace Avalonia.iOS;
#nullable enable
[Adopts("UITextInputTraits")]
[Adopts("UIKeyInput")]
public partial class AvaloniaView : ITextInputMethodImpl
{
private ITextInputMethodClient? _currentClient;
public override bool CanResignFirstResponder => true;
public override bool CanBecomeFirstResponder => true;
public override bool CanBecomeFocused => true;
[Export("hasText")] public bool HasText => false;
[Export("hasText")]
public bool HasText
{
get
{
if (_currentClient is { } && _currentClient.SupportsSurroundingText &&
_currentClient.SurroundingText.Text.Length > 0)
{
return true;
}
return false;
}
}
[Export("keyboardType")] public UIKeyboardType KeyboardType { get; private set; } = UIKeyboardType.Default;
[Export("isSecureTextEntry")] public bool IsSecureEntry { get; private set; }
[Export("insertText:")]
public void InsertText(string text)
@ -24,7 +45,6 @@ public partial class AvaloniaView : ITextInputMethodImpl
_topLevelImpl.Input?.Invoke(new RawTextInputEventArgs(KeyboardDevice.Instance,
0, InputRoot, text));
}
}
[Export("deleteBackward")]
@ -41,13 +61,13 @@ public partial class AvaloniaView : ITextInputMethodImpl
}
}
void ITextInputMethodImpl.SetActive(bool active)
void ITextInputMethodImpl.SetActive(ITextInputMethodClient? client)
{
if (active)
_currentClient = client;
if (client is { })
{
var isFr = IsFirstResponder;
var next = NextResponder;
var result = BecomeFirstResponder();
BecomeFirstResponder();
}
else
{
@ -57,16 +77,43 @@ public partial class AvaloniaView : ITextInputMethodImpl
void ITextInputMethodImpl.SetCursorRect(Rect rect)
{
}
void ITextInputMethodImpl.SetOptions(TextInputOptionsQueryEventArgs options)
{
switch (options.ContentType)
{
case TextInputContentType.Email:
KeyboardType = UIKeyboardType.EmailAddress;
break;
case TextInputContentType.Number:
KeyboardType = UIKeyboardType.NumberPad;
break;
case TextInputContentType.Password:
IsSecureEntry = true;
break;
case TextInputContentType.Phone:
KeyboardType = UIKeyboardType.PhonePad;
break;
case TextInputContentType.Url:
KeyboardType = UIKeyboardType.Url;
break;
case TextInputContentType.Normal:
KeyboardType = UIKeyboardType.Default;
break;
}
}
void ITextInputMethodImpl.Reset()
{
IsSecureEntry = false;
KeyboardType = UIKeyboardType.Default;
ResignFirstResponder();
}
}

Loading…
Cancel
Save