From 4da0ae8dab4f844a9d7a4ddd6748c55aa6cee09e Mon Sep 17 00:00:00 2001 From: Arhell Date: Wed, 5 Oct 2022 01:10:26 +0300 Subject: [PATCH 1/6] update test folder links --- NOTICE.md | 4 ++-- .../Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs | 2 +- tests/Avalonia.UnitTests/MockStreamGeometryImpl.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/NOTICE.md b/NOTICE.md index 92fd725957..e97fc654c9 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -111,7 +111,7 @@ DEALINGS IN THE SOFTWARE. # Metsys.Bson -Copyright (c) 2010, Karl Seguin - http://www.openmymind.net/ +Copyright (c) 2010, Karl Seguin - https://www.openmymind.net/ All rights reserved. Redistribution and use in source and binary forms, with or without @@ -302,4 +302,4 @@ https://github.com/chromium/chromium // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs b/tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs index 1f0b82b465..26a1ab88c7 100644 --- a/tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs +++ b/tests/Avalonia.Base.UnitTests/VisualTree/MockRenderInterface.cs @@ -235,7 +235,7 @@ namespace Avalonia.Base.UnitTests.VisualTree public bool FillContains(Point point) { - // Use the algorithm from http://www.blackpawn.com/texts/pointinpoly/default.html + // Use the algorithm from https://www.blackpawn.com/texts/pointinpoly/default.html // to determine if the point is in the geometry (since it will always be convex in this situation) for (int i = 0; i < points.Count; i++) { diff --git a/tests/Avalonia.UnitTests/MockStreamGeometryImpl.cs b/tests/Avalonia.UnitTests/MockStreamGeometryImpl.cs index 864e2efbaf..9d039a386e 100644 --- a/tests/Avalonia.UnitTests/MockStreamGeometryImpl.cs +++ b/tests/Avalonia.UnitTests/MockStreamGeometryImpl.cs @@ -148,7 +148,7 @@ namespace Avalonia.UnitTests public bool FillContains(Point point) { - // Use the algorithm from http://www.blackpawn.com/texts/pointinpoly/default.html + // Use the algorithm from https://www.blackpawn.com/texts/pointinpoly/default.html // to determine if the point is in the geometry (since it will always be convex in this situation) for (int i = 0; i < points.Count; i++) { From 9f74febca316e5219ee8f2014efb3c18c1935158 Mon Sep 17 00:00:00 2001 From: robloo Date: Tue, 11 Oct 2022 21:11:11 -0400 Subject: [PATCH 2/6] Add initial TextBox.TextChanged event --- src/Avalonia.Controls/TextBox.cs | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 964a153c8b..76bb37efcf 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -18,6 +18,7 @@ using Avalonia.Media.TextFormatting; using Avalonia.Media.TextFormatting.Unicode; using Avalonia.Automation.Peers; using System.Diagnostics; +using Avalonia.Threading; namespace Avalonia.Controls { @@ -171,6 +172,10 @@ namespace Avalonia.Controls RoutedEvent.Register( nameof(PastingFromClipboard), RoutingStrategies.Bubble); + public static readonly RoutedEvent TextChangedEvent = + RoutedEvent.Register( + nameof(TextChanged), RoutingStrategies.Bubble); + readonly struct UndoRedoState : IEquatable { public string? Text { get; } @@ -359,8 +364,8 @@ namespace Avalonia.Controls /// public double LineHeight { - get { return GetValue(LineHeightProperty); } - set { SetValue(LineHeightProperty, value); } + get => GetValue(LineHeightProperty); + set => SetValue(LineHeightProperty, value); } [Content] @@ -564,6 +569,18 @@ namespace Avalonia.Controls remove => RemoveHandler(PastingFromClipboardEvent, value); } + /// + /// Occurs when text changes. + /// + /// + /// This event is asynchronous and occurs after the new text is rendered. + /// + public event EventHandler? TextChanged + { + add => AddHandler(TextChangedEvent, value); + remove => RemoveHandler(TextChangedEvent, value); + } + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { _presenter = e.NameScope.Get("PART_TextPresenter"); @@ -1543,7 +1560,16 @@ namespace Avalonia.Controls { if (raiseTextChanged) { - SetAndRaise(TextProperty, ref _text, value); + bool textChanged = SetAndRaise(TextProperty, ref _text, value); + + if (textChanged) + { + Dispatcher.UIThread.Post(() => + { + var eventArgs = new RoutedEventArgs(TextChangedEvent); + RaiseEvent(eventArgs); + }); + } } else { From d3dcf731131c4c8507d1b443e0545ab5b4f83d3c Mon Sep 17 00:00:00 2001 From: robloo Date: Tue, 11 Oct 2022 21:43:52 -0400 Subject: [PATCH 3/6] Add TextBox.TextChanging event --- src/Avalonia.Controls/TextBox.cs | 50 +++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 76bb37efcf..eb9f82516e 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -160,22 +160,41 @@ namespace Avalonia.Controls (o, v) => o.UndoLimit = v, unsetValue: -1); + /// + /// Defines the event. + /// public static readonly RoutedEvent CopyingToClipboardEvent = RoutedEvent.Register( nameof(CopyingToClipboard), RoutingStrategies.Bubble); + /// + /// Defines the event. + /// public static readonly RoutedEvent CuttingToClipboardEvent = RoutedEvent.Register( nameof(CuttingToClipboard), RoutingStrategies.Bubble); + /// + /// Defines the event. + /// public static readonly RoutedEvent PastingFromClipboardEvent = RoutedEvent.Register( nameof(PastingFromClipboard), RoutingStrategies.Bubble); + /// + /// Defines the event. + /// public static readonly RoutedEvent TextChangedEvent = RoutedEvent.Register( nameof(TextChanged), RoutingStrategies.Bubble); + /// + /// Defines the event. + /// + public static readonly RoutedEvent TextChangingEvent = + RoutedEvent.Register( + nameof(TextChanging), RoutingStrategies.Bubble); + readonly struct UndoRedoState : IEquatable { public string? Text { get; } @@ -570,17 +589,26 @@ namespace Avalonia.Controls } /// - /// Occurs when text changes. + /// Occurs asynchronously after text changes and the new text is rendered. /// - /// - /// This event is asynchronous and occurs after the new text is rendered. - /// public event EventHandler? TextChanged { add => AddHandler(TextChangedEvent, value); remove => RemoveHandler(TextChangedEvent, value); } + /// + /// Occurs synchronously when text starts to change but before it is rendered. + /// + /// + /// This event occurs just after the property value has been updated. + /// + public event EventHandler? TextChanging + { + add => AddHandler(TextChangingEvent, value); + remove => RemoveHandler(TextChangingEvent, value); + } + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { _presenter = e.NameScope.Get("PART_TextPresenter"); @@ -1564,11 +1592,19 @@ namespace Avalonia.Controls if (textChanged) { + // Note the following sequence of these events (following WinUI) + // 1. TextChanging occurs synchronously when text starts to change but before it is rendered. + // This occurs after the Text property is set. + // 2. TextChanged occurs asynchronously after text changes and the new text is rendered. + + var textChangingEventArgs = new RoutedEventArgs(TextChangingEvent); + RaiseEvent(textChangingEventArgs); + Dispatcher.UIThread.Post(() => { - var eventArgs = new RoutedEventArgs(TextChangedEvent); - RaiseEvent(eventArgs); - }); + var textChangedEventArgs = new RoutedEventArgs(TextChangedEvent); + RaiseEvent(textChangedEventArgs); + }, DispatcherPriority.Normal); } } else From 751474b329908dc9af20cc00c1ddbc847e6e3dda Mon Sep 17 00:00:00 2001 From: robloo Date: Wed, 12 Oct 2022 22:40:32 -0400 Subject: [PATCH 4/6] Add TextChangedEventArgs and TextChangingEventArgs --- src/Avalonia.Controls/TextBox.cs | 16 +++++++-------- src/Avalonia.Controls/TextChangedEventArgs.cs | 20 +++++++++++++++++++ .../TextChangingEventArgs.cs | 20 +++++++++++++++++++ 3 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 src/Avalonia.Controls/TextChangedEventArgs.cs create mode 100644 src/Avalonia.Controls/TextChangingEventArgs.cs diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index eb9f82516e..bace6c7811 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -184,15 +184,15 @@ namespace Avalonia.Controls /// /// Defines the event. /// - public static readonly RoutedEvent TextChangedEvent = - RoutedEvent.Register( + public static readonly RoutedEvent TextChangedEvent = + RoutedEvent.Register( nameof(TextChanged), RoutingStrategies.Bubble); /// /// Defines the event. /// - public static readonly RoutedEvent TextChangingEvent = - RoutedEvent.Register( + public static readonly RoutedEvent TextChangingEvent = + RoutedEvent.Register( nameof(TextChanging), RoutingStrategies.Bubble); readonly struct UndoRedoState : IEquatable @@ -591,7 +591,7 @@ namespace Avalonia.Controls /// /// Occurs asynchronously after text changes and the new text is rendered. /// - public event EventHandler? TextChanged + public event EventHandler? TextChanged { add => AddHandler(TextChangedEvent, value); remove => RemoveHandler(TextChangedEvent, value); @@ -603,7 +603,7 @@ namespace Avalonia.Controls /// /// This event occurs just after the property value has been updated. /// - public event EventHandler? TextChanging + public event EventHandler? TextChanging { add => AddHandler(TextChangingEvent, value); remove => RemoveHandler(TextChangingEvent, value); @@ -1597,12 +1597,12 @@ namespace Avalonia.Controls // This occurs after the Text property is set. // 2. TextChanged occurs asynchronously after text changes and the new text is rendered. - var textChangingEventArgs = new RoutedEventArgs(TextChangingEvent); + var textChangingEventArgs = new TextChangingEventArgs(TextChangingEvent); RaiseEvent(textChangingEventArgs); Dispatcher.UIThread.Post(() => { - var textChangedEventArgs = new RoutedEventArgs(TextChangedEvent); + var textChangedEventArgs = new TextChangedEventArgs(TextChangedEvent); RaiseEvent(textChangedEventArgs); }, DispatcherPriority.Normal); } diff --git a/src/Avalonia.Controls/TextChangedEventArgs.cs b/src/Avalonia.Controls/TextChangedEventArgs.cs new file mode 100644 index 0000000000..77c609f19b --- /dev/null +++ b/src/Avalonia.Controls/TextChangedEventArgs.cs @@ -0,0 +1,20 @@ +using Avalonia.Interactivity; + +namespace Avalonia.Controls +{ + /// + /// Provides data specific to a TextChanged event. + /// + public class TextChangedEventArgs : RoutedEventArgs + { + public TextChangedEventArgs(RoutedEvent? routedEvent) + : base (routedEvent) + { + } + + public TextChangedEventArgs(RoutedEvent? routedEvent, IInteractive? source) + : base(routedEvent, source) + { + } + } +} diff --git a/src/Avalonia.Controls/TextChangingEventArgs.cs b/src/Avalonia.Controls/TextChangingEventArgs.cs new file mode 100644 index 0000000000..4dedbc927b --- /dev/null +++ b/src/Avalonia.Controls/TextChangingEventArgs.cs @@ -0,0 +1,20 @@ +using Avalonia.Interactivity; + +namespace Avalonia.Controls +{ + /// + /// Provides data specific to a TextChanging event. + /// + public class TextChangingEventArgs : RoutedEventArgs + { + public TextChangingEventArgs(RoutedEvent? routedEvent) + : base (routedEvent) + { + } + + public TextChangingEventArgs(RoutedEvent? routedEvent, IInteractive? source) + : base(routedEvent, source) + { + } + } +} From 7f221b321f4b057dd928b3a4f79083fbdaa3c207 Mon Sep 17 00:00:00 2001 From: robloo Date: Wed, 12 Oct 2022 22:49:11 -0400 Subject: [PATCH 5/6] Raise text change events if set through the TextBox.Text property --- src/Avalonia.Controls/TextBox.cs | 49 +++++++++++++------ .../TextBoxTextInputMethodClient.cs | 2 +- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index bace6c7811..da4e90fb66 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -400,11 +400,19 @@ namespace Avalonia.Controls CaretIndex = CoerceCaretIndex(caretIndex, value); SelectionStart = CoerceCaretIndex(selectionStart, value); SelectionEnd = CoerceCaretIndex(selectionEnd, value); - if (SetAndRaise(TextProperty, ref _text, value) && IsUndoEnabled && !_isUndoingRedoing) + + var textChanged = SetAndRaise(TextProperty, ref _text, value); + + if (textChanged && IsUndoEnabled && !_isUndoingRedoing) { _undoRedoHelper.Clear(); SnapshotUndoRedo(); // so we always have an initial state } + + if (textChanged) + { + RaiseTextChangeEvents(); + } } } @@ -1297,7 +1305,7 @@ namespace Avalonia.Controls if (text != null && _wordSelectionStart >= 0) { - var distance = caretIndex - _wordSelectionStart; + var distance = caretIndex - _wordSelectionStart; if (distance <= 0) { @@ -1584,6 +1592,29 @@ namespace Avalonia.Controls return text.Substring(start, end - start); } + /// + /// Raises both the and events. + /// + /// + /// This must be called after the property is set. + /// + private void RaiseTextChangeEvents() + { + // Note the following sequence of these events (following WinUI) + // 1. TextChanging occurs synchronously when text starts to change but before it is rendered. + // This occurs after the Text property is set. + // 2. TextChanged occurs asynchronously after text changes and the new text is rendered. + + var textChangingEventArgs = new TextChangingEventArgs(TextChangingEvent); + RaiseEvent(textChangingEventArgs); + + Dispatcher.UIThread.Post(() => + { + var textChangedEventArgs = new TextChangedEventArgs(TextChangedEvent); + RaiseEvent(textChangedEventArgs); + }, DispatcherPriority.Normal); + } + private void SetTextInternal(string value, bool raiseTextChanged = true) { if (raiseTextChanged) @@ -1592,19 +1623,7 @@ namespace Avalonia.Controls if (textChanged) { - // Note the following sequence of these events (following WinUI) - // 1. TextChanging occurs synchronously when text starts to change but before it is rendered. - // This occurs after the Text property is set. - // 2. TextChanged occurs asynchronously after text changes and the new text is rendered. - - var textChangingEventArgs = new TextChangingEventArgs(TextChangingEvent); - RaiseEvent(textChangingEventArgs); - - Dispatcher.UIThread.Post(() => - { - var textChangedEventArgs = new TextChangedEventArgs(TextChangedEvent); - RaiseEvent(textChangedEventArgs); - }, DispatcherPriority.Normal); + RaiseTextChangeEvents(); } } else diff --git a/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs b/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs index d39d964277..5d5ffcc381 100644 --- a/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs +++ b/src/Avalonia.Controls/TextBoxTextInputMethodClient.cs @@ -64,7 +64,7 @@ namespace Avalonia.Controls return new TextInputMethodSurroundingText { - Text = lineText ?? "", + Text = lineText ?? "", AnchorOffset = anchorOffset, CursorOffset = cursorOffset }; From d5440ed76b7abcbfb05b2c5a706997aadc68ea49 Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Thu, 13 Oct 2022 16:48:21 +0000 Subject: [PATCH 6/6] fix android native embedded control regression --- src/Android/Avalonia.Android/AvaloniaView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Android/Avalonia.Android/AvaloniaView.cs b/src/Android/Avalonia.Android/AvaloniaView.cs index 34fa121cd7..94e863210b 100644 --- a/src/Android/Avalonia.Android/AvaloniaView.cs +++ b/src/Android/Avalonia.Android/AvaloniaView.cs @@ -74,7 +74,7 @@ namespace Avalonia.Android class ViewImpl : TopLevelImpl { - public ViewImpl(AvaloniaView avaloniaView) : base(avaloniaView, true) + public ViewImpl(AvaloniaView avaloniaView) : base(avaloniaView) { View.Focusable = true; View.FocusChange += ViewImpl_FocusChange;