From 5c74e2c32bc401cc26b8d80f61e7e57ea4804c34 Mon Sep 17 00:00:00 2001 From: robloo Date: Sat, 13 May 2023 14:26:35 -0400 Subject: [PATCH 01/36] Add RangeBase.ValueChanged event --- .../RoutedPropertyChangedEventArgs.cs | 46 +++++++++++++++++++ src/Avalonia.Controls/Primitives/RangeBase.cs | 37 ++++++++++++++- 2 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs diff --git a/src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs b/src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs new file mode 100644 index 0000000000..22134b518d --- /dev/null +++ b/src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs @@ -0,0 +1,46 @@ +namespace Avalonia.Interactivity +{ + /// + /// Provides both old and new property values with a routed event. + /// + /// The type of values. + public class RoutedPropertyChangedEventArgs : RoutedEventArgs + { + /// + /// Initializes a new instance of the class. + /// + /// The old property value. + /// The new property value. + /// The routed event associated with these event args. + public RoutedPropertyChangedEventArgs(T oldValue, T newValue, RoutedEvent? routedEvent) + : base(routedEvent) + { + OldValue = oldValue; + NewValue = newValue; + } + + /// + /// Initializes a new instance of the class. + /// + /// The old property value. + /// The new property value. + /// The routed event associated with these event args. + /// The source object that raised the routed event. + public RoutedPropertyChangedEventArgs(T oldValue, T newValue, RoutedEvent? routedEvent, object? source) + : base(routedEvent, source) + { + OldValue = oldValue; + NewValue = newValue; + } + + /// + /// Gets the old value of the property. + /// + public T OldValue { get; init; } + + /// + /// Gets the new value of the property. + /// + public T NewValue { get; init; } + } +} diff --git a/src/Avalonia.Controls/Primitives/RangeBase.cs b/src/Avalonia.Controls/Primitives/RangeBase.cs index fd9de47236..ebf7879412 100644 --- a/src/Avalonia.Controls/Primitives/RangeBase.cs +++ b/src/Avalonia.Controls/Primitives/RangeBase.cs @@ -1,5 +1,6 @@ using System; using Avalonia.Data; +using Avalonia.Interactivity; using Avalonia.Utilities; namespace Avalonia.Controls.Primitives @@ -42,7 +43,23 @@ namespace Avalonia.Controls.Primitives AvaloniaProperty.Register(nameof(LargeChange), 10); /// - /// Gets or sets the minimum value. + /// Defines the event. + /// + public static readonly RoutedEvent> ValueChangedEvent = + RoutedEvent.Register>( + nameof(ValueChanged), RoutingStrategies.Bubble); + + /// + /// Occurs when the property changes. + /// + public event EventHandler>? ValueChanged + { + add => AddHandler(ValueChangedEvent, value); + remove => RemoveHandler(ValueChangedEvent, value); + } + + /// + /// Gets or sets the minimum possible value. /// public double Minimum { @@ -65,7 +82,7 @@ namespace Avalonia.Controls.Primitives } /// - /// Gets or sets the maximum value. + /// Gets or sets the maximum possible value. /// public double Maximum { @@ -104,18 +121,25 @@ namespace Avalonia.Controls.Primitives : sender.GetValue(ValueProperty); } + /// + /// Gets or sets the small increment value added or subtracted from the . + /// public double SmallChange { get => GetValue(SmallChangeProperty); set => SetValue(SmallChangeProperty, value); } + /// + /// Gets or sets the large increment value added or subtracted from the . + /// public double LargeChange { get => GetValue(LargeChangeProperty); set => SetValue(LargeChangeProperty, value); } + /// protected override void OnInitialized() { base.OnInitialized(); @@ -124,6 +148,7 @@ namespace Avalonia.Controls.Primitives CoerceValue(ValueProperty); } + /// protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); @@ -136,6 +161,14 @@ namespace Avalonia.Controls.Primitives { OnMaximumChanged(); } + else if (change.Property == ValueProperty) + { + var valueChangedEventArgs = new RoutedPropertyChangedEventArgs( + change.GetOldValue(), + change.GetNewValue(), + ValueChangedEvent); + RaiseEvent(valueChangedEventArgs); + } } /// From 4d67f3230cc58d182ff687a4eec855da57fe078c Mon Sep 17 00:00:00 2001 From: FitDev Date: Mon, 22 May 2023 11:21:28 +0300 Subject: [PATCH 02/36] Move TryGetPlatformHandle to TopLevel --- src/Avalonia.Controls/TopLevel.cs | 18 ++++++++++++++++++ src/Avalonia.Controls/WindowBase.cs | 8 -------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 67847f621b..d3733e3da5 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -376,6 +376,24 @@ namespace Avalonia.Controls /// public ITopLevelImpl? PlatformImpl { get; private set; } + /// + /// Trys to get the platform handle for the TopLevel-derived control. + /// + /// + /// An describing the window handle, or null if the handle + /// could not be retrieved. + /// + public IPlatformHandle? TryGetPlatformHandle() => PlatformImpl?.Handle; + + /// + /// Trys to get the platform handle for the TopLevel-derived control. + /// + /// + /// An describing the window handle, or null if the handle + /// could not be retrieved. + /// + public IPlatformHandle? TryGetPlatformHandle() => PlatformImpl?.Handle; + /// /// Gets the renderer for the window. /// diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index b19ad49820..0fad02d72b 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -178,14 +178,6 @@ namespace Avalonia.Controls } } - /// - /// Trys to get the platform handle for the window. - /// - /// - /// An describing the window handle, or null if the handle - /// could not be retrieved. - /// - public IPlatformHandle? TryGetPlatformHandle() => PlatformImpl?.Handle; /// /// Ensures that the window is initialized. From ee1ef13ff259f4f976358d99673406c1df82df10 Mon Sep 17 00:00:00 2001 From: FitDev Date: Mon, 22 May 2023 11:43:55 +0300 Subject: [PATCH 03/36] Move TryGetPlatformHandle to TopLevel Fix --- src/Avalonia.Controls/TopLevel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index d3733e3da5..dc15ba2a6f 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -383,7 +383,7 @@ namespace Avalonia.Controls /// An describing the window handle, or null if the handle /// could not be retrieved. /// - public IPlatformHandle? TryGetPlatformHandle() => PlatformImpl?.Handle; + public IPlatformHandle? TryGetPlatformHandle() => ((IWindowBaseImpl?) PlatformImpl)?.Handle; /// /// Trys to get the platform handle for the TopLevel-derived control. From c2ab39e6dbda5ef887b3f37aad9c692eafebe0e7 Mon Sep 17 00:00:00 2001 From: FitDev Date: Mon, 22 May 2023 12:14:19 +0300 Subject: [PATCH 04/36] Move TryGetPlatformHandle to TopLevel Fix 2 --- src/Avalonia.Controls/TopLevel.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index dc15ba2a6f..54ee31e897 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -385,15 +385,6 @@ namespace Avalonia.Controls /// public IPlatformHandle? TryGetPlatformHandle() => ((IWindowBaseImpl?) PlatformImpl)?.Handle; - /// - /// Trys to get the platform handle for the TopLevel-derived control. - /// - /// - /// An describing the window handle, or null if the handle - /// could not be retrieved. - /// - public IPlatformHandle? TryGetPlatformHandle() => PlatformImpl?.Handle; - /// /// Gets the renderer for the window. /// From de61af19a681429f192587381907386d0e3a4416 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 11:21:59 +0200 Subject: [PATCH 05/36] Update ncrunch config. --- .ncrunch/AppWithoutLifetime.v3.ncrunchproject | 5 +++++ .../Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject | 5 +++++ .../Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject | 5 +++++ 3 files changed, 15 insertions(+) create mode 100644 .ncrunch/AppWithoutLifetime.v3.ncrunchproject create mode 100644 .ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject create mode 100644 .ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject diff --git a/.ncrunch/AppWithoutLifetime.v3.ncrunchproject b/.ncrunch/AppWithoutLifetime.v3.ncrunchproject new file mode 100644 index 0000000000..319cd523ce --- /dev/null +++ b/.ncrunch/AppWithoutLifetime.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/.ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject b/.ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject new file mode 100644 index 0000000000..319cd523ce --- /dev/null +++ b/.ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/.ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject b/.ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject new file mode 100644 index 0000000000..319cd523ce --- /dev/null +++ b/.ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file From 1e5ef03eca58b391185b562b4cd1f13617c8aa04 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 10:11:12 +0200 Subject: [PATCH 06/36] Make InvalidateMirrorTransform protected. --- src/Avalonia.Base/Visual.cs | 2 +- src/Avalonia.Controls/ComboBox.cs | 2 +- src/Avalonia.Controls/TopLevel.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Base/Visual.cs b/src/Avalonia.Base/Visual.cs index 50b23f158d..1b7975c154 100644 --- a/src/Avalonia.Base/Visual.cs +++ b/src/Avalonia.Base/Visual.cs @@ -774,7 +774,7 @@ namespace Avalonia /// Computes the value according to the /// and /// - public virtual void InvalidateMirrorTransform() + protected internal virtual void InvalidateMirrorTransform() { var flowDirection = this.FlowDirection; var parentFlowDirection = FlowDirection.LeftToRight; diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index efa319ad54..8872afab9f 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -164,7 +164,7 @@ namespace Avalonia.Controls UpdateSelectionBoxItem(SelectedItem); } - public override void InvalidateMirrorTransform() + protected internal override void InvalidateMirrorTransform() { base.InvalidateMirrorTransform(); UpdateFlowDirection(); diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 67847f621b..f655016769 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -740,7 +740,7 @@ namespace Avalonia.Controls protected override bool BypassFlowDirectionPolicies => true; - public override void InvalidateMirrorTransform() + protected internal override void InvalidateMirrorTransform() { // Do nothing becuase TopLevel should't apply MirrorTransform on himself. } From 808ada86cdaff999a2f5a62334c4947904e400d9 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 10:15:53 +0200 Subject: [PATCH 07/36] Make ContentControl.ContentChanged private again. Was added in #9803 for `TransitioningContentControl` but is no longer needed (and anyway it should be called `OnContentChanged` if we want to keep it). --- src/Avalonia.Controls/ContentControl.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Controls/ContentControl.cs b/src/Avalonia.Controls/ContentControl.cs index f30920ed2e..0362f7ade4 100644 --- a/src/Avalonia.Controls/ContentControl.cs +++ b/src/Avalonia.Controls/ContentControl.cs @@ -116,19 +116,14 @@ namespace Avalonia.Controls return false; } - protected virtual void ContentChanged(AvaloniaPropertyChangedEventArgs e) + private void ContentChanged(AvaloniaPropertyChangedEventArgs e) { - UpdateLogicalTree(e.OldValue, e.NewValue); - } - - protected void UpdateLogicalTree(object? toRemove, object? toAdd) - { - if (toRemove is ILogical oldChild) + if (e.OldValue is ILogical oldChild) { LogicalChildren.Remove(oldChild); } - if (toAdd is ILogical newChild) + if (e.NewValue is ILogical newChild) { LogicalChildren.Add(newChild); } From d390b4796f4aa229a32287702dd616be8f0a1a41 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 11:05:09 +0200 Subject: [PATCH 08/36] Make IContentControl internal. Can probably be removed. --- src/Avalonia.Controls/IContentControl.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/IContentControl.cs b/src/Avalonia.Controls/IContentControl.cs index b2828c26e8..1f975d5fa6 100644 --- a/src/Avalonia.Controls/IContentControl.cs +++ b/src/Avalonia.Controls/IContentControl.cs @@ -8,8 +8,7 @@ namespace Avalonia.Controls /// Defines a control that displays according to a /// . /// - [NotClientImplementable] - public interface IContentControl + internal interface IContentControl { /// /// Gets or sets the content to display. From 6bbd56f7d979122c519a1425307db52e2aaed881 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 11:14:37 +0200 Subject: [PATCH 09/36] Make IHeadered internal. Can probably be removed. --- src/Avalonia.Controls/Avalonia.Controls.csproj | 2 ++ src/Avalonia.Controls/IHeadered.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj index 48761ca8b8..3f1753a4d3 100644 --- a/src/Avalonia.Controls/Avalonia.Controls.csproj +++ b/src/Avalonia.Controls/Avalonia.Controls.csproj @@ -14,6 +14,7 @@ + @@ -22,5 +23,6 @@ + diff --git a/src/Avalonia.Controls/IHeadered.cs b/src/Avalonia.Controls/IHeadered.cs index 8c1b5cfb1b..c59ddafe73 100644 --- a/src/Avalonia.Controls/IHeadered.cs +++ b/src/Avalonia.Controls/IHeadered.cs @@ -3,7 +3,7 @@ namespace Avalonia.Controls /// /// Defines a headered object. /// - public interface IHeadered + internal interface IHeadered { /// /// Gets or set the header. From 8f94a6505ba5667889719b698eaf5d8d32aaf803 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 11:36:36 +0200 Subject: [PATCH 10/36] Make IMenu, IMenuElement, IMenuItem internal. Should only be needed for unit tests. --- src/Avalonia.Controls/IMenu.cs | 3 +- src/Avalonia.Controls/IMenuElement.cs | 3 +- src/Avalonia.Controls/IMenuItem.cs | 3 +- .../Platform/DefaultMenuInteractionHandler.cs | 459 +++++++++--------- .../Platform/IMenuInteractionHandler.cs | 4 +- .../DefaultMenuInteractionHandlerTests.cs | 2 +- 6 files changed, 238 insertions(+), 236 deletions(-) diff --git a/src/Avalonia.Controls/IMenu.cs b/src/Avalonia.Controls/IMenu.cs index ddf2997014..b3ec77b108 100644 --- a/src/Avalonia.Controls/IMenu.cs +++ b/src/Avalonia.Controls/IMenu.cs @@ -8,8 +8,7 @@ namespace Avalonia.Controls /// /// Represents a or . /// - [NotClientImplementable] - public interface IMenu : IMenuElement, IInputElement + internal interface IMenu : IMenuElement, IInputElement { /// /// Gets the menu interaction handler. diff --git a/src/Avalonia.Controls/IMenuElement.cs b/src/Avalonia.Controls/IMenuElement.cs index 2a81d20bd9..a474f335f2 100644 --- a/src/Avalonia.Controls/IMenuElement.cs +++ b/src/Avalonia.Controls/IMenuElement.cs @@ -8,8 +8,7 @@ namespace Avalonia.Controls /// /// Represents an or . /// - [NotClientImplementable] - public interface IMenuElement : IInputElement, ILogical + internal interface IMenuElement : IInputElement, ILogical { /// /// Gets or sets the currently selected submenu item. diff --git a/src/Avalonia.Controls/IMenuItem.cs b/src/Avalonia.Controls/IMenuItem.cs index 1257d33684..3a9c5373a6 100644 --- a/src/Avalonia.Controls/IMenuItem.cs +++ b/src/Avalonia.Controls/IMenuItem.cs @@ -5,8 +5,7 @@ namespace Avalonia.Controls /// /// Represents a . /// - [NotClientImplementable] - public interface IMenuItem : IMenuElement + internal interface IMenuItem : IMenuElement { /// /// Gets or sets a value that indicates whether the item has a submenu. diff --git a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs index d2b23a7ac3..79a3038edf 100644 --- a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs +++ b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs @@ -39,91 +39,20 @@ namespace Avalonia.Controls.Platform DelayRun = delayRun; } - public virtual void Attach(IMenu menu) - { - if (Menu != null) - { - throw new NotSupportedException("DefaultMenuInteractionHandler is already attached."); - } - - Menu = menu; - Menu.GotFocus += GotFocus; - Menu.LostFocus += LostFocus; - Menu.KeyDown += KeyDown; - Menu.PointerPressed += PointerPressed; - Menu.PointerReleased += PointerReleased; - Menu.AddHandler(AccessKeyHandler.AccessKeyPressedEvent, AccessKeyPressed); - Menu.AddHandler(MenuBase.MenuOpenedEvent, MenuOpened); - Menu.AddHandler(MenuItem.PointerEnteredItemEvent, PointerEntered); - Menu.AddHandler(MenuItem.PointerExitedItemEvent, PointerExited); - Menu.AddHandler(InputElement.PointerMovedEvent, PointerMoved); - - _root = Menu.VisualRoot; - - if (_root is InputElement inputRoot) - { - inputRoot.AddHandler(InputElement.PointerPressedEvent, RootPointerPressed, RoutingStrategies.Tunnel); - } - - if (_root is WindowBase window) - { - window.Deactivated += WindowDeactivated; - } - - if (_root is TopLevel tl && tl.PlatformImpl is ITopLevelImpl pimpl) - pimpl.LostFocus += TopLevelLostPlatformFocus; - - _inputManagerSubscription = InputManager?.Process.Subscribe(RawInput); - } - - public virtual void Detach(IMenu menu) - { - if (Menu != menu) - { - throw new NotSupportedException("DefaultMenuInteractionHandler is not attached to the menu."); - } - - Menu.GotFocus -= GotFocus; - Menu.LostFocus -= LostFocus; - Menu.KeyDown -= KeyDown; - Menu.PointerPressed -= PointerPressed; - Menu.PointerReleased -= PointerReleased; - Menu.RemoveHandler(AccessKeyHandler.AccessKeyPressedEvent, AccessKeyPressed); - Menu.RemoveHandler(MenuBase.MenuOpenedEvent, MenuOpened); - Menu.RemoveHandler(MenuItem.PointerEnteredItemEvent, PointerEntered); - Menu.RemoveHandler(MenuItem.PointerExitedItemEvent, PointerExited); - Menu.RemoveHandler(InputElement.PointerMovedEvent, PointerMoved); - - if (_root is InputElement inputRoot) - { - inputRoot.RemoveHandler(InputElement.PointerPressedEvent, RootPointerPressed); - } - - if (_root is WindowBase root) - { - root.Deactivated -= WindowDeactivated; - } - - if (_root is TopLevel tl && tl.PlatformImpl != null) - tl.PlatformImpl.LostFocus -= TopLevelLostPlatformFocus; - - _inputManagerSubscription?.Dispose(); - - Menu = null; - _root = null; - } + public void Attach(MenuBase menu) => AttachCore(menu); + public void Detach(MenuBase menu) => DetachCore(menu); protected Action DelayRun { get; } protected IInputManager? InputManager { get; } - protected IMenu? Menu { get; private set; } + internal IMenu? Menu { get; private set; } protected static TimeSpan MenuShowDelay { get; } = TimeSpan.FromMilliseconds(400); protected internal virtual void GotFocus(object? sender, GotFocusEventArgs e) { - var item = GetMenuItem(e.Source as Control); + var item = GetMenuItemCore(e.Source as Control); if (item?.Parent != null) { @@ -133,7 +62,7 @@ namespace Avalonia.Controls.Platform protected internal virtual void LostFocus(object? sender, RoutedEventArgs e) { - var item = GetMenuItem(e.Source as Control); + var item = GetMenuItemCore(e.Source as Control); if (item != null) { @@ -143,146 +72,12 @@ namespace Avalonia.Controls.Platform protected internal virtual void KeyDown(object? sender, KeyEventArgs e) { - KeyDown(GetMenuItem(e.Source as Control), e); - } - - protected internal virtual void KeyDown(IMenuItem? item, KeyEventArgs e) - { - switch (e.Key) - { - case Key.Up: - case Key.Down: - { - if (item?.IsTopLevel == true && item.HasSubMenu) - { - if (!item.IsSubMenuOpen) - { - Open(item, true); - } - else - { - item.MoveSelection(NavigationDirection.First, true); - } - - e.Handled = true; - } - else - { - goto default; - } - break; - } - - case Key.Left: - { - if (item is { IsSubMenuOpen: true, SelectedItem: null }) - { - item.Close(); - } - else if (item?.Parent is IMenuItem { IsTopLevel: false, IsSubMenuOpen: true } parent) - { - parent.Close(); - parent.Focus(); - e.Handled = true; - } - else - { - goto default; - } - break; - } - - case Key.Right: - { - if (item != null && !item.IsTopLevel && item.HasSubMenu) - { - Open(item, true); - e.Handled = true; - } - else - { - goto default; - } - break; - } - - case Key.Enter: - { - if (item != null) - { - if (!item.HasSubMenu) - { - Click(item); - } - else - { - Open(item, true); - } - - e.Handled = true; - } - break; - } - - case Key.Escape: - { - if (item?.Parent is IMenuElement parent) - { - parent.Close(); - parent.Focus(); - } - else - { - Menu!.Close(); - } - - e.Handled = true; - break; - } - - default: - { - var direction = e.Key.ToNavigationDirection(); - - if (direction?.IsDirectional() == true) - { - if (item == null && _isContextMenu) - { - if (Menu!.MoveSelection(direction.Value, true) == true) - { - e.Handled = true; - } - } - else if (item?.Parent?.MoveSelection(direction.Value, true) == true) - { - // If the the parent is an IMenu which successfully moved its selection, - // and the current menu is open then close the current menu and open the - // new menu. - if (item.IsSubMenuOpen && - item.Parent is IMenu && - item.Parent.SelectedItem is object && - item.Parent.SelectedItem != item) - { - item.Close(); - Open(item.Parent.SelectedItem, true); - } - e.Handled = true; - } - } - - break; - } - } - - if (!e.Handled && item?.Parent is IMenuItem parentItem) - { - KeyDown(parentItem, e); - } + KeyDown(GetMenuItemCore(e.Source as Control), e); } protected internal virtual void AccessKeyPressed(object? sender, RoutedEventArgs e) { - var item = GetMenuItem(e.Source as Control); + var item = GetMenuItemCore(e.Source as Control); if (item == null) { @@ -303,7 +98,7 @@ namespace Avalonia.Controls.Platform protected internal virtual void PointerEntered(object? sender, RoutedEventArgs e) { - var item = GetMenuItem(e.Source as Control); + var item = GetMenuItemCore(e.Source as Control); if (item?.Parent == null) { @@ -349,7 +144,7 @@ namespace Avalonia.Controls.Platform protected internal virtual void PointerMoved(object? sender, PointerEventArgs e) { // HACK: #8179 needs to be addressed to correctly implement it in the PointerPressed method. - var item = GetMenuItem(e.Source as Control) as MenuItem; + var item = GetMenuItemCore(e.Source as Control) as MenuItem; if (item == null) return; @@ -370,7 +165,7 @@ namespace Avalonia.Controls.Platform protected internal virtual void PointerExited(object? sender, RoutedEventArgs e) { - var item = GetMenuItem(e.Source as Control); + var item = GetMenuItemCore(e.Source as Control); if (item?.Parent == null) { @@ -405,7 +200,7 @@ namespace Avalonia.Controls.Platform protected internal virtual void PointerPressed(object? sender, PointerPressedEventArgs e) { - var item = GetMenuItem(e.Source as Control); + var item = GetMenuItemCore(e.Source as Control); if (sender is Visual visual && e.GetCurrentPoint(visual).Properties.IsLeftButtonPressed && item?.HasSubMenu == true) @@ -436,7 +231,7 @@ namespace Avalonia.Controls.Platform protected internal virtual void PointerReleased(object? sender, PointerReleasedEventArgs e) { - var item = GetMenuItem(e.Source as Control); + var item = GetMenuItemCore(e.Source as Control); if (e.InitialPressMouseButton == MouseButton.Left && item?.HasSubMenu == false) { @@ -478,13 +273,84 @@ namespace Avalonia.Controls.Platform { Menu?.Close(); } - - private void TopLevelLostPlatformFocus() + + internal static MenuItem? GetMenuItem(StyledElement? item) => (MenuItem?)GetMenuItemCore(item); + + internal void AttachCore(IMenu menu) { - Menu?.Close(); + if (Menu != null) + { + throw new NotSupportedException("DefaultMenuInteractionHandler is already attached."); + } + + Menu = menu; + Menu.GotFocus += GotFocus; + Menu.LostFocus += LostFocus; + Menu.KeyDown += KeyDown; + Menu.PointerPressed += PointerPressed; + Menu.PointerReleased += PointerReleased; + Menu.AddHandler(AccessKeyHandler.AccessKeyPressedEvent, AccessKeyPressed); + Menu.AddHandler(MenuBase.MenuOpenedEvent, MenuOpened); + Menu.AddHandler(MenuItem.PointerEnteredItemEvent, PointerEntered); + Menu.AddHandler(MenuItem.PointerExitedItemEvent, PointerExited); + Menu.AddHandler(InputElement.PointerMovedEvent, PointerMoved); + + _root = Menu.VisualRoot; + + if (_root is InputElement inputRoot) + { + inputRoot.AddHandler(InputElement.PointerPressedEvent, RootPointerPressed, RoutingStrategies.Tunnel); + } + + if (_root is WindowBase window) + { + window.Deactivated += WindowDeactivated; + } + + if (_root is TopLevel tl && tl.PlatformImpl is ITopLevelImpl pimpl) + pimpl.LostFocus += TopLevelLostPlatformFocus; + + _inputManagerSubscription = InputManager?.Process.Subscribe(RawInput); } - protected void Click(IMenuItem item) + internal void DetachCore(IMenu menu) + { + if (Menu != menu) + { + throw new NotSupportedException("DefaultMenuInteractionHandler is not attached to the menu."); + } + + Menu.GotFocus -= GotFocus; + Menu.LostFocus -= LostFocus; + Menu.KeyDown -= KeyDown; + Menu.PointerPressed -= PointerPressed; + Menu.PointerReleased -= PointerReleased; + Menu.RemoveHandler(AccessKeyHandler.AccessKeyPressedEvent, AccessKeyPressed); + Menu.RemoveHandler(MenuBase.MenuOpenedEvent, MenuOpened); + Menu.RemoveHandler(MenuItem.PointerEnteredItemEvent, PointerEntered); + Menu.RemoveHandler(MenuItem.PointerExitedItemEvent, PointerExited); + Menu.RemoveHandler(InputElement.PointerMovedEvent, PointerMoved); + + if (_root is InputElement inputRoot) + { + inputRoot.RemoveHandler(InputElement.PointerPressedEvent, RootPointerPressed); + } + + if (_root is WindowBase root) + { + root.Deactivated -= WindowDeactivated; + } + + if (_root is TopLevel tl && tl.PlatformImpl != null) + tl.PlatformImpl.LostFocus -= TopLevelLostPlatformFocus; + + _inputManagerSubscription?.Dispose(); + + Menu = null; + _root = null; + } + + internal void Click(IMenuItem item) { item.RaiseClick(); @@ -494,7 +360,7 @@ namespace Avalonia.Controls.Platform } } - protected void CloseMenu(IMenuItem item) + internal void CloseMenu(IMenuItem item) { var current = (IMenuElement?)item; @@ -506,7 +372,7 @@ namespace Avalonia.Controls.Platform current?.Close(); } - protected void CloseWithDelay(IMenuItem item) + internal void CloseWithDelay(IMenuItem item) { void Execute() { @@ -519,7 +385,141 @@ namespace Avalonia.Controls.Platform DelayRun(Execute, MenuShowDelay); } - protected void Open(IMenuItem item, bool selectFirst) + internal void KeyDown(IMenuItem? item, KeyEventArgs e) + { + switch (e.Key) + { + case Key.Up: + case Key.Down: + { + if (item?.IsTopLevel == true && item.HasSubMenu) + { + if (!item.IsSubMenuOpen) + { + Open(item, true); + } + else + { + item.MoveSelection(NavigationDirection.First, true); + } + + e.Handled = true; + } + else + { + goto default; + } + break; + } + + case Key.Left: + { + if (item is { IsSubMenuOpen: true, SelectedItem: null }) + { + item.Close(); + } + else if (item?.Parent is IMenuItem { IsTopLevel: false, IsSubMenuOpen: true } parent) + { + parent.Close(); + parent.Focus(); + e.Handled = true; + } + else + { + goto default; + } + break; + } + + case Key.Right: + { + if (item != null && !item.IsTopLevel && item.HasSubMenu) + { + Open(item, true); + e.Handled = true; + } + else + { + goto default; + } + break; + } + + case Key.Enter: + { + if (item != null) + { + if (!item.HasSubMenu) + { + Click(item); + } + else + { + Open(item, true); + } + + e.Handled = true; + } + break; + } + + case Key.Escape: + { + if (item?.Parent is IMenuElement parent) + { + parent.Close(); + parent.Focus(); + } + else + { + Menu!.Close(); + } + + e.Handled = true; + break; + } + + default: + { + var direction = e.Key.ToNavigationDirection(); + + if (direction?.IsDirectional() == true) + { + if (item == null && _isContextMenu) + { + if (Menu!.MoveSelection(direction.Value, true) == true) + { + e.Handled = true; + } + } + else if (item?.Parent?.MoveSelection(direction.Value, true) == true) + { + // If the the parent is an IMenu which successfully moved its selection, + // and the current menu is open then close the current menu and open the + // new menu. + if (item.IsSubMenuOpen && + item.Parent is IMenu && + item.Parent.SelectedItem is object && + item.Parent.SelectedItem != item) + { + item.Close(); + Open(item.Parent.SelectedItem, true); + } + e.Handled = true; + } + } + + break; + } + } + + if (!e.Handled && item?.Parent is IMenuItem parentItem) + { + KeyDown(parentItem, e); + } + } + + internal void Open(IMenuItem item, bool selectFirst) { item.Open(); @@ -529,7 +529,7 @@ namespace Avalonia.Controls.Platform } } - protected void OpenWithDelay(IMenuItem item) + internal void OpenWithDelay(IMenuItem item) { void Execute() { @@ -542,7 +542,7 @@ namespace Avalonia.Controls.Platform DelayRun(Execute, MenuShowDelay); } - protected void SelectItemAndAncestors(IMenuItem item) + internal void SelectItemAndAncestors(IMenuItem item) { var current = (IMenuItem?)item; @@ -553,7 +553,7 @@ namespace Avalonia.Controls.Platform } } - protected static IMenuItem? GetMenuItem(StyledElement? item) + internal static IMenuItem? GetMenuItemCore(StyledElement? item) { while (true) { @@ -565,6 +565,11 @@ namespace Avalonia.Controls.Platform } } + private void TopLevelLostPlatformFocus() + { + Menu?.Close(); + } + private static void DefaultDelayRun(Action action, TimeSpan timeSpan) { DispatcherTimer.RunOnce(action, timeSpan); diff --git a/src/Avalonia.Controls/Platform/IMenuInteractionHandler.cs b/src/Avalonia.Controls/Platform/IMenuInteractionHandler.cs index 47b5a048b0..d1d2267f05 100644 --- a/src/Avalonia.Controls/Platform/IMenuInteractionHandler.cs +++ b/src/Avalonia.Controls/Platform/IMenuInteractionHandler.cs @@ -12,11 +12,11 @@ namespace Avalonia.Controls.Platform /// Attaches the interaction handler to a menu. /// /// The menu. - void Attach(IMenu menu); + void Attach(MenuBase menu); /// /// Detaches the interaction handler from the attached menu. /// - void Detach(IMenu menu); + void Detach(MenuBase menu); } } diff --git a/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs b/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs index eaf95b0c8c..506a62525c 100644 --- a/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs @@ -554,7 +554,7 @@ namespace Avalonia.Controls.UnitTests.Platform var contextMenu = Mock.Of(x => x.MoveSelection(NavigationDirection.Down, true) == true); var e = new KeyEventArgs { Key = Key.Down, Source = contextMenu }; - target.Attach(contextMenu); + target.AttachCore(contextMenu); target.KeyDown(contextMenu, e); Mock.Get(contextMenu).Verify(x => x.MoveSelection(NavigationDirection.Down, true)); From 8428ea9d6b0e44b1dc3f27aa4cd95f97a5b486dc Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 11:51:22 +0200 Subject: [PATCH 11/36] Make IMainMenu and IAccessKeyHandler internal. --- src/Avalonia.Base/Input/IAccessKeyHandler.cs | 3 +-- src/Avalonia.Base/Input/IInputRoot.cs | 5 ----- src/Avalonia.Base/Input/IMainMenu.cs | 5 +---- src/Avalonia.Controls/Menu.cs | 2 +- src/Avalonia.Controls/MenuItemAccessKeyHandler.cs | 2 +- src/Avalonia.Controls/Primitives/AccessText.cs | 2 +- src/Avalonia.Controls/TopLevel.cs | 2 +- tests/Avalonia.UnitTests/TestRoot.cs | 2 -- 8 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/Avalonia.Base/Input/IAccessKeyHandler.cs b/src/Avalonia.Base/Input/IAccessKeyHandler.cs index 93a50968e2..aaad93eb23 100644 --- a/src/Avalonia.Base/Input/IAccessKeyHandler.cs +++ b/src/Avalonia.Base/Input/IAccessKeyHandler.cs @@ -5,8 +5,7 @@ namespace Avalonia.Input /// /// Defines the interface for classes that handle access keys for a window. /// - [Unstable] - public interface IAccessKeyHandler + internal interface IAccessKeyHandler { /// /// Gets or sets the window's main menu. diff --git a/src/Avalonia.Base/Input/IInputRoot.cs b/src/Avalonia.Base/Input/IInputRoot.cs index 0100b22ba7..d0921eea2d 100644 --- a/src/Avalonia.Base/Input/IInputRoot.cs +++ b/src/Avalonia.Base/Input/IInputRoot.cs @@ -8,11 +8,6 @@ namespace Avalonia.Input [NotClientImplementable] public interface IInputRoot : IInputElement { - /// - /// Gets or sets the access key handler. - /// - IAccessKeyHandler AccessKeyHandler { get; } - /// /// Gets or sets the keyboard navigation handler. /// diff --git a/src/Avalonia.Base/Input/IMainMenu.cs b/src/Avalonia.Base/Input/IMainMenu.cs index 0010397c1a..cc1b88d4c3 100644 --- a/src/Avalonia.Base/Input/IMainMenu.cs +++ b/src/Avalonia.Base/Input/IMainMenu.cs @@ -1,15 +1,12 @@ using System; using Avalonia.Interactivity; -using Avalonia.Metadata; -using Avalonia.VisualTree; namespace Avalonia.Input { /// /// Defines the interface for a window's main menu. /// - [NotClientImplementable] - public interface IMainMenu + internal interface IMainMenu { /// /// Gets a value indicating whether the menu is open. diff --git a/src/Avalonia.Controls/Menu.cs b/src/Avalonia.Controls/Menu.cs index 4df423dee8..fe4d42c603 100644 --- a/src/Avalonia.Controls/Menu.cs +++ b/src/Avalonia.Controls/Menu.cs @@ -87,7 +87,7 @@ namespace Avalonia.Controls { base.OnAttachedToVisualTree(e); - var inputRoot = e.Root as IInputRoot; + var inputRoot = e.Root as TopLevel; if (inputRoot?.AccessKeyHandler != null) { diff --git a/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs b/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs index 381f1799d4..e1e7779f17 100644 --- a/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs +++ b/src/Avalonia.Controls/MenuItemAccessKeyHandler.cs @@ -9,7 +9,7 @@ namespace Avalonia.Controls /// /// Handles access keys within a /// - public class MenuItemAccessKeyHandler : IAccessKeyHandler + internal class MenuItemAccessKeyHandler : IAccessKeyHandler { /// /// The registered access keys. diff --git a/src/Avalonia.Controls/Primitives/AccessText.cs b/src/Avalonia.Controls/Primitives/AccessText.cs index c5dbc3000f..2e570e25c7 100644 --- a/src/Avalonia.Controls/Primitives/AccessText.cs +++ b/src/Avalonia.Controls/Primitives/AccessText.cs @@ -86,7 +86,7 @@ namespace Avalonia.Controls.Primitives protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) { base.OnAttachedToVisualTree(e); - _accessKeys = (e.Root as IInputRoot)?.AccessKeyHandler; + _accessKeys = (e.Root as TopLevel)?.AccessKeyHandler; if (_accessKeys != null && AccessKey != 0) { diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index f655016769..474735d25b 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -386,7 +386,7 @@ namespace Avalonia.Controls /// /// Gets the access key handler for the window. /// - IAccessKeyHandler IInputRoot.AccessKeyHandler => _accessKeyHandler!; + internal IAccessKeyHandler AccessKeyHandler => _accessKeyHandler!; /// /// Gets or sets the keyboard navigation handler for the window. diff --git a/tests/Avalonia.UnitTests/TestRoot.cs b/tests/Avalonia.UnitTests/TestRoot.cs index 8dabfe2197..80f0cf5406 100644 --- a/tests/Avalonia.UnitTests/TestRoot.cs +++ b/tests/Avalonia.UnitTests/TestRoot.cs @@ -51,8 +51,6 @@ namespace Avalonia.UnitTests public IRenderer Renderer { get; set; } - public IAccessKeyHandler AccessKeyHandler => null; - public IKeyboardNavigationHandler KeyboardNavigationHandler => null; public IFocusManager FocusManager => AvaloniaLocator.Current.GetService(); From da2af10efe1b47e5ce743b720d78c66373535c9e Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 11:53:23 +0200 Subject: [PATCH 12/36] Make INativeMenuExporterEventsImplBridge a private API. --- src/Avalonia.Controls/INativeMenuExporterEventsImplBridge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/INativeMenuExporterEventsImplBridge.cs b/src/Avalonia.Controls/INativeMenuExporterEventsImplBridge.cs index 29963e4821..6a22676a69 100644 --- a/src/Avalonia.Controls/INativeMenuExporterEventsImplBridge.cs +++ b/src/Avalonia.Controls/INativeMenuExporterEventsImplBridge.cs @@ -2,7 +2,7 @@ using Avalonia.Metadata; namespace Avalonia.Controls { - [Unstable] + [PrivateApi] public interface INativeMenuExporterEventsImplBridge { void RaiseNeedsUpdate (); From d992fc2b4f011429fcb9947a700089bc246a4e75 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 12:49:06 +0200 Subject: [PATCH 13/36] Hide IChildIndexProvider interface method. --- src/Avalonia.Controls/Panel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Panel.cs b/src/Avalonia.Controls/Panel.cs index eff6603727..4705b0e9a5 100644 --- a/src/Avalonia.Controls/Panel.cs +++ b/src/Avalonia.Controls/Panel.cs @@ -213,7 +213,7 @@ namespace Avalonia.Controls } /// - public bool TryGetTotalCount(out int count) + bool IChildIndexProvider.TryGetTotalCount(out int count) { count = Children.Count; return true; From 61be135c8cbb5fe11ebf6484ed6e2e77ef27b421 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 12:52:30 +0200 Subject: [PATCH 14/36] Don't expose protected fields. --- .../ColorSlider/ColorSlider.cs | 6 ++-- src/Avalonia.Controls/Slider.cs | 28 ++++++++++++++++--- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls.ColorPicker/ColorSlider/ColorSlider.cs b/src/Avalonia.Controls.ColorPicker/ColorSlider/ColorSlider.cs index a6d9ca459f..31ac18100e 100644 --- a/src/Avalonia.Controls.ColorPicker/ColorSlider/ColorSlider.cs +++ b/src/Avalonia.Controls.ColorPicker/ColorSlider/ColorSlider.cs @@ -98,10 +98,10 @@ namespace Avalonia.Controls.Primitives int pixelWidth; int pixelHeight; - if (base._track != null) + if (base.Track != null) { - pixelWidth = Convert.ToInt32(base._track.Bounds.Width * scale); - pixelHeight = Convert.ToInt32(base._track.Bounds.Height * scale); + pixelWidth = Convert.ToInt32(base.Track.Bounds.Width * scale); + pixelHeight = Convert.ToInt32(base.Track.Bounds.Height * scale); } else { diff --git a/src/Avalonia.Controls/Slider.cs b/src/Avalonia.Controls/Slider.cs index b0dff5be79..de3c4023bd 100644 --- a/src/Avalonia.Controls/Slider.cs +++ b/src/Avalonia.Controls/Slider.cs @@ -86,10 +86,10 @@ namespace Avalonia.Controls TickBar.TicksProperty.AddOwner(); // Slider required parts - protected bool _isDragging; - protected Track? _track; - protected Button? _decreaseButton; - protected Button? _increaseButton; + private bool _isDragging; + private Track? _track; + private Button? _decreaseButton; + private Button? _increaseButton; private IDisposable? _decreaseButtonPressDispose; private IDisposable? _decreaseButtonReleaseDispose; private IDisposable? _increaseButtonSubscription; @@ -181,6 +181,26 @@ namespace Avalonia.Controls set { SetValue(TickPlacementProperty, value); } } + /// + /// Gets a value indicating whether the is currently being dragged. + /// + protected bool IsDragging => _isDragging; + + /// + /// Gets the part of the . + /// + protected Track? Track => _track; + + /// + /// Gets the that decreases the value. + /// + protected Button? DecreaseButton => _decreaseButton; + + /// + /// Gets the that increases the value. + /// + protected Button? IncreaseButton => _increaseButton; + /// protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { From 16615a43d3fff2b27977cdb598c111443e3c563d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 12:59:37 +0200 Subject: [PATCH 15/36] Don't expose pseudoclass constants. 1. They don't follow naming conventions 2. If we're going to expose them, why just `protected`? 3. If we do it, we should do it on all controls --- src/Avalonia.Controls/Button.cs | 4 ++-- .../CalendarDatePicker/CalendarDatePicker.cs | 4 ++-- src/Avalonia.Controls/ComboBox.cs | 5 +++-- .../SplitButton/SplitButton.cs | 6 +++--- src/Avalonia.Controls/SplitView/SplitView.cs | 18 +++++++++--------- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/Avalonia.Controls/Button.cs b/src/Avalonia.Controls/Button.cs index f48d7a7cc1..d8c31fc477 100644 --- a/src/Avalonia.Controls/Button.cs +++ b/src/Avalonia.Controls/Button.cs @@ -34,8 +34,8 @@ namespace Avalonia.Controls [PseudoClasses(pcFlyoutOpen, pcPressed)] public class Button : ContentControl, ICommandSource, IClickableControl { - protected const string pcPressed = ":pressed"; - protected const string pcFlyoutOpen = ":flyout-open"; + private const string pcPressed = ":pressed"; + private const string pcFlyoutOpen = ":flyout-open"; /// /// Defines the property. diff --git a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs index 90153d3293..679ac4a853 100644 --- a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs +++ b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs @@ -26,8 +26,8 @@ namespace Avalonia.Controls [PseudoClasses(pcFlyoutOpen, pcPressed)] public partial class CalendarDatePicker : TemplatedControl { - protected const string pcPressed = ":pressed"; - protected const string pcFlyoutOpen = ":flyout-open"; + private const string pcPressed = ":pressed"; + private const string pcFlyoutOpen = ":flyout-open"; private const string ElementTextBox = "PART_TextBox"; private const string ElementButton = "PART_Button"; diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index 8872afab9f..926cd5d58e 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -21,8 +21,9 @@ namespace Avalonia.Controls [PseudoClasses(pcDropdownOpen, pcPressed)] public class ComboBox : SelectingItemsControl { - public const string pcDropdownOpen = ":dropdownopen"; - public const string pcPressed = ":pressed"; + internal const string pcDropdownOpen = ":dropdownopen"; + internal const string pcPressed = ":pressed"; + /// /// The default value for the property. /// diff --git a/src/Avalonia.Controls/SplitButton/SplitButton.cs b/src/Avalonia.Controls/SplitButton/SplitButton.cs index 7f10c632c5..bc46e549eb 100644 --- a/src/Avalonia.Controls/SplitButton/SplitButton.cs +++ b/src/Avalonia.Controls/SplitButton/SplitButton.cs @@ -18,9 +18,9 @@ namespace Avalonia.Controls [PseudoClasses(pcFlyoutOpen, pcPressed)] public class SplitButton : ContentControl, ICommandSource { - protected const string pcChecked = ":checked"; - protected const string pcPressed = ":pressed"; - protected const string pcFlyoutOpen = ":flyout-open"; + internal const string pcChecked = ":checked"; + internal const string pcPressed = ":pressed"; + internal const string pcFlyoutOpen = ":flyout-open"; /// /// Raised when the user presses the primary part of the . diff --git a/src/Avalonia.Controls/SplitView/SplitView.cs b/src/Avalonia.Controls/SplitView/SplitView.cs index 3ad656ee3c..b943a01a4b 100644 --- a/src/Avalonia.Controls/SplitView/SplitView.cs +++ b/src/Avalonia.Controls/SplitView/SplitView.cs @@ -22,15 +22,15 @@ namespace Avalonia.Controls [PseudoClasses(pcLightDismiss)] public class SplitView : ContentControl { - protected const string pcOpen = ":open"; - protected const string pcClosed = ":closed"; - protected const string pcCompactOverlay = ":compactoverlay"; - protected const string pcCompactInline = ":compactinline"; - protected const string pcOverlay = ":overlay"; - protected const string pcInline = ":inline"; - protected const string pcLeft = ":left"; - protected const string pcRight = ":right"; - protected const string pcLightDismiss = ":lightDismiss"; + private const string pcOpen = ":open"; + private const string pcClosed = ":closed"; + private const string pcCompactOverlay = ":compactoverlay"; + private const string pcCompactInline = ":compactinline"; + private const string pcOverlay = ":overlay"; + private const string pcInline = ":inline"; + private const string pcLeft = ":left"; + private const string pcRight = ":right"; + private const string pcLightDismiss = ":lightDismiss"; /// /// Defines the property From de0ebdda22ee2e520100ca2a33bb36a911f666ce Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 13:02:13 +0200 Subject: [PATCH 16/36] Don't expose fields. --- src/Avalonia.Controls/TextBlock.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs index c1edf23c89..11a180c4d7 100644 --- a/src/Avalonia.Controls/TextBlock.cs +++ b/src/Avalonia.Controls/TextBlock.cs @@ -144,8 +144,8 @@ namespace Avalonia.Controls AvaloniaProperty.RegisterDirect( nameof(Inlines), t => t.Inlines, (t, v) => t.Inlines = v); - protected TextLayout? _textLayout; - protected Size _constraint; + private TextLayout? _textLayout; + private Size _constraint; private IReadOnlyList? _textRuns; private InlineCollection? _inlines; From b0bcfcfbf7591c87de03b0494dc5166653e19e36 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 13:04:00 +0200 Subject: [PATCH 17/36] Make TextBlock.SimpleTextSource private. --- src/Avalonia.Controls/TextBlock.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs index 11a180c4d7..6144136882 100644 --- a/src/Avalonia.Controls/TextBlock.cs +++ b/src/Avalonia.Controls/TextBlock.cs @@ -829,7 +829,7 @@ namespace Avalonia.Controls InvalidateTextLayout(); } - protected readonly record struct SimpleTextSource : ITextSource + private readonly record struct SimpleTextSource : ITextSource { private readonly string _text; private readonly TextRunProperties _defaultProperties; From 224187331649f72e035079872c5731fcd1889077 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 13:05:30 +0200 Subject: [PATCH 18/36] Make TextBox.RemoveInvalidCharacters private. --- src/Avalonia.Controls/TextBox.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 2a8fdd30c7..51a7fe9b7f 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -1017,7 +1017,7 @@ namespace Avalonia.Controls } } - public string? RemoveInvalidCharacters(string? text) + private string? RemoveInvalidCharacters(string? text) { if (text is null) return null; From 4ea25f7990aefe26faea37a2fcbd15808071e8f1 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 13:10:19 +0200 Subject: [PATCH 19/36] Make ToggleSwitch.UpdateKnobPos private. --- src/Avalonia.Controls/ToggleSwitch.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/ToggleSwitch.cs b/src/Avalonia.Controls/ToggleSwitch.cs index 108deba257..29e1b90ca0 100644 --- a/src/Avalonia.Controls/ToggleSwitch.cs +++ b/src/Avalonia.Controls/ToggleSwitch.cs @@ -241,7 +241,7 @@ namespace Avalonia.Controls } } - protected void UpdateKnobPos(bool value) + private void UpdateKnobPos(bool value) { if ((_switchKnob != null) && (_knobsPanel != null)) { From 673b3e4b710aea58dc7957ec9735effe0d956069 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 13:15:33 +0200 Subject: [PATCH 20/36] Make top level Handle* methods internal. --- src/Avalonia.Controls/TopLevel.cs | 8 ++++---- src/Avalonia.Controls/Window.cs | 4 ++-- src/Avalonia.Controls/WindowBase.cs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 474735d25b..4736398509 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -529,7 +529,7 @@ namespace Avalonia.Controls /// Handles a paint notification from . /// /// The dirty area. - protected virtual void HandlePaint(Rect rect) + private void HandlePaint(Rect rect) { Renderer.Paint(rect); } @@ -537,7 +537,7 @@ namespace Avalonia.Controls /// /// Handles a closed notification from . /// - protected virtual void HandleClosed() + private protected virtual void HandleClosed() { Renderer.SceneInvalidated -= SceneInvalidated; // We need to wait for the renderer to complete any in-flight operations @@ -595,7 +595,7 @@ namespace Avalonia.Controls /// . /// /// The window scaling. - protected virtual void HandleScalingChanged(double scaling) + private void HandleScalingChanged(double scaling) { LayoutHelper.InvalidateSelfAndChildrenMeasure(this); ScalingChanged?.Invoke(this, EventArgs.Empty); @@ -615,7 +615,7 @@ namespace Avalonia.Controls return false; } - protected virtual void HandleTransparencyLevelChanged(WindowTransparencyLevel transparencyLevel) + private void HandleTransparencyLevelChanged(WindowTransparencyLevel transparencyLevel) { if(_transparencyFallbackBorder != null) { diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 3f04350995..e64341b735 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -535,7 +535,7 @@ namespace Avalonia.Controls return true; } - protected virtual void HandleWindowStateChanged(WindowState state) + private void HandleWindowStateChanged(WindowState state) { WindowState = state; @@ -979,7 +979,7 @@ namespace Avalonia.Controls return ClientSize; } - protected sealed override void HandleClosed() + private protected sealed override void HandleClosed() { RaiseEvent(new RoutedEventArgs(WindowClosedEvent)); diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index b19ad49820..491c32887c 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -226,7 +226,7 @@ namespace Avalonia.Controls /// An that contains the event data. protected virtual void OnResized(WindowResizedEventArgs e) => Resized?.Invoke(this, e); - protected override void HandleClosed() + private protected override void HandleClosed() { using (FreezeVisibilityChangeHandling()) { From e4634a917eb126f483c525a7c7fe5bbd679ceb82 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 13:24:13 +0200 Subject: [PATCH 21/36] Make TopLevel.CreateLayoutManager internal. Should only be needed for unit tests. --- src/Avalonia.Controls/TopLevel.cs | 2 +- tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs | 2 +- tests/Avalonia.Controls.UnitTests/TextBoxTests.cs | 2 +- tests/Avalonia.Controls.UnitTests/TopLevelTests.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 4736398509..3a206c0e15 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -523,7 +523,7 @@ namespace Avalonia.Controls /// /// Creates the layout manager for this . /// - protected virtual ILayoutManager CreateLayoutManager() => new LayoutManager(this); + private protected virtual ILayoutManager CreateLayoutManager() => new LayoutManager(this); /// /// Handles a paint notification from . diff --git a/tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs index 04acd1c36d..dead810dbb 100644 --- a/tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs @@ -1004,7 +1004,7 @@ namespace Avalonia.Controls.UnitTests _layoutManager = layoutManager ?? new LayoutManager(this); } - protected override ILayoutManager CreateLayoutManager() => _layoutManager; + private protected override ILayoutManager CreateLayoutManager() => _layoutManager; } private static Mock CreateMockTopLevelImpl() diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs index ca1986d293..0d559557fe 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs @@ -1208,7 +1208,7 @@ namespace Avalonia.Controls.UnitTests _layoutManager = layoutManager ?? new LayoutManager(this); } - protected override ILayoutManager CreateLayoutManager() => _layoutManager; + private protected override ILayoutManager CreateLayoutManager() => _layoutManager; } private static Mock CreateMockTopLevelImpl() diff --git a/tests/Avalonia.Controls.UnitTests/TopLevelTests.cs b/tests/Avalonia.Controls.UnitTests/TopLevelTests.cs index 0884dd306a..1c7935e167 100644 --- a/tests/Avalonia.Controls.UnitTests/TopLevelTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TopLevelTests.cs @@ -339,7 +339,7 @@ namespace Avalonia.Controls.UnitTests _layoutManager = layoutManager ?? new LayoutManager(this); } - protected override ILayoutManager CreateLayoutManager() => _layoutManager; + private protected override ILayoutManager CreateLayoutManager() => _layoutManager; } } } From f6699faf4a20307eea8ff2d5ee557f2c4b02e0bf Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 13:24:25 +0200 Subject: [PATCH 22/36] Make FreezeVisibilityChangeHandling internal. --- src/Avalonia.Controls/WindowBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index 491c32887c..6e0c6313f1 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -60,7 +60,7 @@ namespace Avalonia.Controls impl.PositionChanged = HandlePositionChanged; } - protected IDisposable FreezeVisibilityChangeHandling() + private protected IDisposable FreezeVisibilityChangeHandling() { return new IgnoreVisibilityChangesDisposable(this); } From 4c194b47c22070e913f7382a66c227010ebb8b50 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 13:37:22 +0200 Subject: [PATCH 23/36] Removed ContentPresenter.CreateChild. Unused API and I'm not sure we want to expose an extension point here. --- src/Avalonia.Controls/Presenters/ContentPresenter.cs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/Avalonia.Controls/Presenters/ContentPresenter.cs b/src/Avalonia.Controls/Presenters/ContentPresenter.cs index 736c338c10..972fd2d4ff 100644 --- a/src/Avalonia.Controls/Presenters/ContentPresenter.cs +++ b/src/Avalonia.Controls/Presenters/ContentPresenter.cs @@ -540,17 +540,6 @@ namespace Avalonia.Controls.Presenters BoxShadow); } - /// - /// Creates the child control. - /// - /// The child control or null. - protected virtual Control? CreateChild() - { - var content = Content; - var oldChild = Child; - return CreateChild(content, oldChild, ContentTemplate); - } - private Control? CreateChild(object? content, Control? oldChild, IDataTemplate? template) { var newChild = content as Control; From 38a77e2f6966a575b80d2b5ca345e665a3fd083d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 13:39:59 +0200 Subject: [PATCH 24/36] Make IContentPresenterHost internal. Can probably be removed? --- src/Avalonia.Controls/Presenters/IContentPresenterHost.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/Presenters/IContentPresenterHost.cs b/src/Avalonia.Controls/Presenters/IContentPresenterHost.cs index 4c1e16ef72..dd1aafba65 100644 --- a/src/Avalonia.Controls/Presenters/IContentPresenterHost.cs +++ b/src/Avalonia.Controls/Presenters/IContentPresenterHost.cs @@ -1,7 +1,5 @@ using Avalonia.Collections; using Avalonia.LogicalTree; -using Avalonia.Metadata; -using Avalonia.Styling; namespace Avalonia.Controls.Presenters { @@ -16,8 +14,7 @@ namespace Avalonia.Controls.Presenters /// parent control's template is instantiated so they register themselves using this /// interface. /// - [NotClientImplementable] - public interface IContentPresenterHost + internal interface IContentPresenterHost { /// /// Gets a collection describing the logical children of the host control. From 79b043cbfabb153a30d4d42dbb5b8a8915b7add4 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 13:55:30 +0200 Subject: [PATCH 25/36] Remove ExportAvaloniaModuleAttribute . This feature is no longer supported. --- .../Platform/ExportAvaloniaModuleAttribute.cs | 58 ------------------- 1 file changed, 58 deletions(-) delete mode 100644 src/Avalonia.Controls/Platform/ExportAvaloniaModuleAttribute.cs diff --git a/src/Avalonia.Controls/Platform/ExportAvaloniaModuleAttribute.cs b/src/Avalonia.Controls/Platform/ExportAvaloniaModuleAttribute.cs deleted file mode 100644 index f271abb59a..0000000000 --- a/src/Avalonia.Controls/Platform/ExportAvaloniaModuleAttribute.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; - -namespace Avalonia.Platform -{ - /// - /// Defines an "Avalonia Module", a 3rd party extension to Avalonia that can be automatically initialized by an AppBuilder instance. - /// - /// - /// Avalonia Modules can either be platform independent (ex default control styles provider) or dependent on a - /// specific windowing or rendering subsystem being used (ex native rendering speedup, subsystem-specific interop backends). - /// In the case of a subsystem-specific module, you can specify multiple module implementations, and also a fallback - /// platform-independent module if you so choose. Additionally, these different implementations can be in different assemblies. - /// They just need to all share the same module name. - /// - /// For example, if I had a module Foo that has a special back-end for Skia and a less performant/less user friendly back-end for - /// any other rendering subsystem, I would do the following: - /// - /// // In assembly FooModuleSkia.dll - /// [assembly:ExportAvaloniaModule("Foo", typeof(FooModuleSkia), ForRenderingSubsystem="Skia")] - /// - /// class FooModuleSkia - /// { - /// public FooModuleSkia() - /// { - /// InitializeModule(); - /// } - /// } - /// - /// // In assembly FooModuleFallback.dll - /// [assembly:ExportAvaloniaModule("Foo", typeof(FooModuleFallback))] - /// - /// class FooModuleFallback - /// { - /// public FooModuleFallback() - /// { - /// InitializeModule(); - /// } - /// } - /// - /// - /// The fallback module will only be initialized if the Skia-specific module is not applicable. - /// - [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] - public sealed class ExportAvaloniaModuleAttribute : Attribute - { - public ExportAvaloniaModuleAttribute(string name, Type moduleType) - { - Name = name; - ModuleType = moduleType; - } - - public string Name { get; private set; } - public Type ModuleType { get; private set; } - - public string ForWindowingSubsystem { get; set; } = ""; - public string ForRenderingSubsystem { get; set; } = ""; - } -} From f1cde62c9836d888d1edf09b10c8fed1758bd701 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 16:02:15 +0200 Subject: [PATCH 26/36] Make ConsoleContext internal. --- src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleContext.cs b/src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleContext.cs index 4f4579c7d9..4fd3de25dd 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleContext.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleContext.cs @@ -4,7 +4,7 @@ using Avalonia.Diagnostics.ViewModels; namespace Avalonia.Diagnostics.Models { - public class ConsoleContext + internal class ConsoleContext { private readonly ConsoleViewModel _owner; From 29ba660e4b74565844c703b2edb823deaabb13a3 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 16:06:10 +0200 Subject: [PATCH 27/36] Make BindingBase.GetParentDataContext private. --- src/Markup/Avalonia.Markup/Data/BindingBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Markup/Avalonia.Markup/Data/BindingBase.cs b/src/Markup/Avalonia.Markup/Data/BindingBase.cs index 17f44a4b54..799401cd4e 100644 --- a/src/Markup/Avalonia.Markup/Data/BindingBase.cs +++ b/src/Markup/Avalonia.Markup/Data/BindingBase.cs @@ -234,7 +234,7 @@ namespace Avalonia.Data return result; } - protected IObservable GetParentDataContext(AvaloniaObject target) + private IObservable GetParentDataContext(AvaloniaObject target) { // The DataContext is based on the visual parent and not the logical parent: this may // seem counter intuitive considering the fact that property inheritance works on the logical From c83e64d4d93870c7630947fa8e4585cffd44d70a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 16:09:50 +0200 Subject: [PATCH 28/36] Fix spelling mistake. --- src/Avalonia.Base/Animation/AnimatorKeyFrame.cs | 2 +- src/Avalonia.Base/AvaloniaProperty.cs | 2 +- src/Avalonia.Base/AvaloniaProperty`1.cs | 2 +- src/Avalonia.Base/Collections/AvaloniaListConverter.cs | 2 +- src/Avalonia.Base/Data/BindingValue.cs | 4 ++-- .../Data/Converters/DefaultValueConverter.cs | 2 +- src/Avalonia.Base/Data/Core/BindingExpression.cs | 2 +- src/Avalonia.Base/Diagnostics/TrimmingMessages.cs | 8 ++++---- .../PropertyStore/DirectUntypedBindingObserver.cs | 2 +- .../PropertyStore/LocalValueBindingObserver.cs | 2 +- src/Avalonia.Base/PropertyStore/UntypedValueUtils.cs | 4 ++-- src/Avalonia.Base/StyledProperty.cs | 2 +- src/Avalonia.Base/Styling/PropertyEqualsSelector.cs | 4 ++-- src/Avalonia.Base/Styling/Setter.cs | 2 +- src/Avalonia.Base/Utilities/TypeUtilities.cs | 10 +++++----- src/Markup/Avalonia.Markup/Data/BindingBase.cs | 2 +- 16 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs b/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs index dcce75b31c..892be5cb26 100644 --- a/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs +++ b/src/Avalonia.Base/Animation/AnimatorKeyFrame.cs @@ -67,7 +67,7 @@ namespace Avalonia.Animation } } - [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)] + [RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)] public T GetTypedValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>() { var typeConv = TypeDescriptor.GetConverter(typeof(T)); diff --git a/src/Avalonia.Base/AvaloniaProperty.cs b/src/Avalonia.Base/AvaloniaProperty.cs index 95f8eea852..5ab52cfde9 100644 --- a/src/Avalonia.Base/AvaloniaProperty.cs +++ b/src/Avalonia.Base/AvaloniaProperty.cs @@ -476,7 +476,7 @@ namespace Avalonia /// /// The value. /// True if the value is valid, otherwise false. - [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)] + [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConversionRequiresUnreferencedCodeMessage)] public bool IsValidValue(object? value) { return TypeUtilities.TryConvertImplicit(PropertyType, value, out _); diff --git a/src/Avalonia.Base/AvaloniaProperty`1.cs b/src/Avalonia.Base/AvaloniaProperty`1.cs index ea2f3577e5..c7e0f381b3 100644 --- a/src/Avalonia.Base/AvaloniaProperty`1.cs +++ b/src/Avalonia.Base/AvaloniaProperty`1.cs @@ -70,7 +70,7 @@ namespace Avalonia private protected override IObservable GetChanged() => Changed; - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)] private protected BindingValue TryConvert(object? value) { if (value == UnsetValue) diff --git a/src/Avalonia.Base/Collections/AvaloniaListConverter.cs b/src/Avalonia.Base/Collections/AvaloniaListConverter.cs index 34ccb5e65f..bcd681f898 100644 --- a/src/Avalonia.Base/Collections/AvaloniaListConverter.cs +++ b/src/Avalonia.Base/Collections/AvaloniaListConverter.cs @@ -9,7 +9,7 @@ namespace Avalonia.Collections /// /// Creates an from a string representation. /// - [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)] + [RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)] public class AvaloniaListConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T> : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) diff --git a/src/Avalonia.Base/Data/BindingValue.cs b/src/Avalonia.Base/Data/BindingValue.cs index 3bc172f596..ac79d1eff7 100644 --- a/src/Avalonia.Base/Data/BindingValue.cs +++ b/src/Avalonia.Base/Data/BindingValue.cs @@ -237,7 +237,7 @@ namespace Avalonia.Data /// /// The untyped value. /// The typed binding value. - [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)] + [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConversionRequiresUnreferencedCodeMessage)] public static BindingValue FromUntyped(object? value) { return FromUntyped(value, typeof(T)); @@ -251,7 +251,7 @@ namespace Avalonia.Data /// The untyped value. /// The runtime target type. /// The typed binding value. - [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)] + [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConversionRequiresUnreferencedCodeMessage)] public static BindingValue FromUntyped(object? value, Type targetType) { if (value == AvaloniaProperty.UnsetValue) diff --git a/src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs b/src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs index aeb71d16ae..a31ac6eee1 100644 --- a/src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs +++ b/src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs @@ -10,7 +10,7 @@ namespace Avalonia.Data.Converters /// Provides a default set of value conversions for bindings that do not specify a value /// converter. /// - [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)] + [RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)] public class DefaultValueConverter : IValueConverter { /// diff --git a/src/Avalonia.Base/Data/Core/BindingExpression.cs b/src/Avalonia.Base/Data/Core/BindingExpression.cs index 79942cb9ce..7065e5bc32 100644 --- a/src/Avalonia.Base/Data/Core/BindingExpression.cs +++ b/src/Avalonia.Base/Data/Core/BindingExpression.cs @@ -12,7 +12,7 @@ namespace Avalonia.Data.Core /// Binds to an expression on an object using a type value converter to convert the values /// that are sent and received. /// - [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)] + [RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)] internal class BindingExpression : LightweightObservableBase, IAvaloniaSubject, IDescription { private readonly ExpressionObserver _inner; diff --git a/src/Avalonia.Base/Diagnostics/TrimmingMessages.cs b/src/Avalonia.Base/Diagnostics/TrimmingMessages.cs index a893256d17..37c2831a50 100644 --- a/src/Avalonia.Base/Diagnostics/TrimmingMessages.cs +++ b/src/Avalonia.Base/Diagnostics/TrimmingMessages.cs @@ -2,11 +2,11 @@ internal static class TrimmingMessages { - public const string ImplicitTypeConvertionSupressWarningMessage = "Implicit convertion methods might be removed by the linker. We don't have a reliable way to prevent it, except converting everything in compile time when possible."; - public const string ImplicitTypeConvertionRequiresUnreferencedCodeMessage = "Implicit convertion methods are required for type conversion."; + public const string ImplicitTypeConversionSupressWarningMessage = "Implicit conversion methods might be removed by the linker. We don't have a reliable way to prevent it, except converting everything in compile time when possible."; + public const string ImplicitTypeConversionRequiresUnreferencedCodeMessage = "Implicit conversion methods are required for type conversion."; - public const string TypeConvertionSupressWarningMessage = "Convertion methods might be removed by the linker. We don't have a reliable way to prevent it, except converting everything in compile time when possible."; - public const string TypeConvertionRequiresUnreferencedCodeMessage = "Convertion methods are required for type conversion, including op_Implicit, op_Explicit, Parse and TypeConverter."; + public const string TypeConversionSupressWarningMessage = "Conversion methods might be removed by the linker. We don't have a reliable way to prevent it, except converting everything in compile time when possible."; + public const string TypeConversionRequiresUnreferencedCodeMessage = "Conversion methods are required for type conversion, including op_Implicit, op_Explicit, Parse and TypeConverter."; public const string ReflectionBindingRequiresUnreferencedCodeMessage = "BindingExpression and ReflectionBinding heavily use reflection. Consider using CompiledBindings instead."; public const string ReflectionBindingSupressWarningMessage = "BindingExpression and ReflectionBinding internal heavily use reflection."; diff --git a/src/Avalonia.Base/PropertyStore/DirectUntypedBindingObserver.cs b/src/Avalonia.Base/PropertyStore/DirectUntypedBindingObserver.cs index 1cf108df9b..54dffa3a95 100644 --- a/src/Avalonia.Base/PropertyStore/DirectUntypedBindingObserver.cs +++ b/src/Avalonia.Base/PropertyStore/DirectUntypedBindingObserver.cs @@ -5,7 +5,7 @@ using Avalonia.Threading; namespace Avalonia.PropertyStore { - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)] internal class DirectUntypedBindingObserver : IObserver, IDisposable { diff --git a/src/Avalonia.Base/PropertyStore/LocalValueBindingObserver.cs b/src/Avalonia.Base/PropertyStore/LocalValueBindingObserver.cs index 9e9b4a3190..7bcf6165fe 100644 --- a/src/Avalonia.Base/PropertyStore/LocalValueBindingObserver.cs +++ b/src/Avalonia.Base/PropertyStore/LocalValueBindingObserver.cs @@ -14,7 +14,7 @@ namespace Avalonia.PropertyStore public void Start(IObservable source) => _subscription = source.Subscribe(this); - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)] public void OnNext(object? value) { if (value == BindingOperations.DoNothing) diff --git a/src/Avalonia.Base/PropertyStore/UntypedValueUtils.cs b/src/Avalonia.Base/PropertyStore/UntypedValueUtils.cs index 372a808fb2..4912ec1d81 100644 --- a/src/Avalonia.Base/PropertyStore/UntypedValueUtils.cs +++ b/src/Avalonia.Base/PropertyStore/UntypedValueUtils.cs @@ -7,7 +7,7 @@ namespace Avalonia.PropertyStore { internal static class UntypedValueUtils { - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)] public static BindingValue ConvertAndValidate( object? value, Type targetType, @@ -24,7 +24,7 @@ namespace Avalonia.PropertyStore return v; } - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)] public static bool TryConvertAndValidate( StyledProperty property, object? value, diff --git a/src/Avalonia.Base/StyledProperty.cs b/src/Avalonia.Base/StyledProperty.cs index ee8748956e..b6bd737234 100644 --- a/src/Avalonia.Base/StyledProperty.cs +++ b/src/Avalonia.Base/StyledProperty.cs @@ -221,7 +221,7 @@ namespace Avalonia return target.Bind(this, source, priority); } - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)] private bool ShouldSetValue(AvaloniaObject target, object? value, [NotNullWhen(true)] out TValue? converted) { if (value == BindingOperations.DoNothing) diff --git a/src/Avalonia.Base/Styling/PropertyEqualsSelector.cs b/src/Avalonia.Base/Styling/PropertyEqualsSelector.cs index 3a50923094..1d684eeca3 100644 --- a/src/Avalonia.Base/Styling/PropertyEqualsSelector.cs +++ b/src/Avalonia.Base/Styling/PropertyEqualsSelector.cs @@ -91,8 +91,8 @@ namespace Avalonia.Styling private protected override Selector? MovePrevious() => _previous; private protected override Selector? MovePreviousOrParent() => _previous; - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.TypeConvertionSupressWarningMessage)] - [UnconditionalSuppressMessage("Trimming", "IL2067", Justification = TrimmingMessages.TypeConvertionSupressWarningMessage)] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.TypeConversionSupressWarningMessage)] + [UnconditionalSuppressMessage("Trimming", "IL2067", Justification = TrimmingMessages.TypeConversionSupressWarningMessage)] internal static bool Compare(Type propertyType, object? propertyValue, object? value) { if (propertyType == typeof(object) && diff --git a/src/Avalonia.Base/Styling/Setter.cs b/src/Avalonia.Base/Styling/Setter.cs index e5b2bed738..1ac26c79ec 100644 --- a/src/Avalonia.Base/Styling/Setter.cs +++ b/src/Avalonia.Base/Styling/Setter.cs @@ -65,7 +65,7 @@ namespace Avalonia.Styling void IValueEntry.Unsubscribe() { } - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)] internal override ISetterInstance Instance(IStyleInstance instance, StyledElement target) { if (target is not AvaloniaObject ao) diff --git a/src/Avalonia.Base/Utilities/TypeUtilities.cs b/src/Avalonia.Base/Utilities/TypeUtilities.cs index fafafabd82..3a82bf02e0 100644 --- a/src/Avalonia.Base/Utilities/TypeUtilities.cs +++ b/src/Avalonia.Base/Utilities/TypeUtilities.cs @@ -126,7 +126,7 @@ namespace Avalonia.Utilities /// The culture to use. /// If successful, contains the convert value. /// True if the cast was successful, otherwise false. - [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)] + [RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)] public static bool TryConvert(Type to, object? value, CultureInfo? culture, out object? result) { if (value == null) @@ -246,7 +246,7 @@ namespace Avalonia.Utilities /// The value to convert. /// If successful, contains the converted value. /// True if the convert was successful, otherwise false. - [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)] + [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConversionRequiresUnreferencedCodeMessage)] public static bool TryConvertImplicit(Type to, object? value, out object? result) { if (value == null) @@ -309,7 +309,7 @@ namespace Avalonia.Utilities /// The type to convert to.. /// The culture to use. /// A value of . - [RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)] + [RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)] public static object? ConvertOrDefault(object? value, Type type, CultureInfo culture) { return TryConvert(type, value, culture, out var result) ? result : Default(type); @@ -322,13 +322,13 @@ namespace Avalonia.Utilities /// The value to convert. /// The type to convert to. /// A value of . - [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)] + [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConversionRequiresUnreferencedCodeMessage)] public static object? ConvertImplicitOrDefault(object? value, Type type) { return TryConvertImplicit(type, value, out var result) ? result : Default(type); } - [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)] + [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConversionRequiresUnreferencedCodeMessage)] public static T ConvertImplicit(object? value) { if (TryConvertImplicit(typeof(T), value, out var result)) diff --git a/src/Markup/Avalonia.Markup/Data/BindingBase.cs b/src/Markup/Avalonia.Markup/Data/BindingBase.cs index 799401cd4e..1d82725e57 100644 --- a/src/Markup/Avalonia.Markup/Data/BindingBase.cs +++ b/src/Markup/Avalonia.Markup/Data/BindingBase.cs @@ -76,7 +76,7 @@ namespace Avalonia.Data bool enableDataValidation); /// - [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.TypeConvertionSupressWarningMessage)] + [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.TypeConversionSupressWarningMessage)] public InstancedBinding? Initiate( AvaloniaObject target, AvaloniaProperty? targetProperty, From 46488628dd5176a26f5042095acc1f43eccc8913 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 16:15:43 +0200 Subject: [PATCH 29/36] Move TemplateBinding to Avalonia.Base. It would be useful to be able to access it from here to provide bindings in default template values, and it has no dependency on XAML. --- .../Avalonia.Markup => Avalonia.Base}/Data/TemplateBinding.cs | 0 src/Avalonia.Base/Properties/AssemblyInfo.cs | 1 + tests/Avalonia.Markup.Xaml.UnitTests/XamlTestBase.cs | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) rename src/{Markup/Avalonia.Markup => Avalonia.Base}/Data/TemplateBinding.cs (100%) diff --git a/src/Markup/Avalonia.Markup/Data/TemplateBinding.cs b/src/Avalonia.Base/Data/TemplateBinding.cs similarity index 100% rename from src/Markup/Avalonia.Markup/Data/TemplateBinding.cs rename to src/Avalonia.Base/Data/TemplateBinding.cs diff --git a/src/Avalonia.Base/Properties/AssemblyInfo.cs b/src/Avalonia.Base/Properties/AssemblyInfo.cs index 260771ea9d..d37ec86f2a 100644 --- a/src/Avalonia.Base/Properties/AssemblyInfo.cs +++ b/src/Avalonia.Base/Properties/AssemblyInfo.cs @@ -6,6 +6,7 @@ using Avalonia.Metadata; [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation.Easings")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")] +[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Data")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Data.Converters")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Input")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Input.GestureRecognizers")] diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/XamlTestBase.cs b/tests/Avalonia.Markup.Xaml.UnitTests/XamlTestBase.cs index 6d26de2b29..26fba7ec57 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/XamlTestBase.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/XamlTestBase.cs @@ -13,7 +13,7 @@ namespace Avalonia.Markup.Xaml.UnitTests public XamlTestBase() { // Ensure necessary assemblies are loaded. - var _ = typeof(TemplateBinding); + var _ = typeof(Binding); GC.KeepAlive(typeof(ItemsRepeater)); if (AvaloniaLocator.Current.GetService() == null) AvaloniaLocator.CurrentMutable.Bind() From 89be3ee5334e9ba3541254beabe97a2867a29c6d Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Mon, 22 May 2023 14:21:35 +0000 Subject: [PATCH 30/36] Add more android keycode support --- .../Platform/Input/AndroidKeyboardDevice.cs | 112 +++++++++--------- 1 file changed, 58 insertions(+), 54 deletions(-) diff --git a/src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs b/src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs index ab84801e57..a416e05b52 100644 --- a/src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs +++ b/src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs @@ -5,8 +5,9 @@ using Avalonia.Input; namespace Avalonia.Android.Platform.Input { - internal class AndroidKeyboardDevice : KeyboardDevice, IKeyboardDevice { - private static readonly Dictionary KeyDic = new Dictionary + internal class AndroidKeyboardDevice : KeyboardDevice, IKeyboardDevice + { + private static readonly Dictionary KeyDic = new Dictionary { // { Keycode.Cancel?, Key.Cancel }, { Keycode.Del, Key.Back }, @@ -15,7 +16,7 @@ namespace Avalonia.Android.Platform.Input { Keycode.Clear, Key.Clear }, { Keycode.Enter, Key.Return }, { Keycode.MediaPause, Key.Pause }, - //{ Keycode.?, Key.CapsLock } + { Keycode.CapsLock, Key.CapsLock }, //{ Keycode.?, Key.HangulMode } //{ Keycode.?, Key.JunjaMode } //{ Keycode.?, Key.FinalMode } @@ -28,8 +29,8 @@ namespace Avalonia.Android.Platform.Input { Keycode.Space, Key.Space }, { Keycode.PageUp, Key.Prior }, { Keycode.PageDown, Key.PageDown }, - // { Keycode.end?, Key.End }, - { Keycode.Home, Key.Home }, + { Keycode.MoveEnd, Key.End }, + { Keycode.MoveHome, Key.Home }, { Keycode.DpadLeft, Key.Left }, { Keycode.DpadUp, Key.Up }, { Keycode.DpadRight, Key.Right }, @@ -37,20 +38,20 @@ namespace Avalonia.Android.Platform.Input // { Keycode.ButtonSelect?, Key.Select }, // { Keycode.print?, Key.Print }, //{ Keycode.execute?, Key.Execute }, - // { Keycode.snap, Key.Snapshot } + //{ Keycode.snap?, Key.Snapshot } { Keycode.Insert, Key.Insert }, { Keycode.ForwardDel, Key.Delete }, - //{ Keycode.help, Key.Help }, - //{ Keycode.?, Key.D0 } - //{ Keycode.?, Key.D1 } - //{ Keycode.?, Key.D2 } - //{ Keycode.?, Key.D3 } - //{ Keycode.?, Key.D4 } - //{ Keycode.?, Key.D5 } - //{ Keycode.?, Key.D6 } - //{ Keycode.?, Key.D7 } - //{ Keycode.?, Key.D8 } - //{ Keycode.?, Key.D9 } + { Keycode.Help, Key.Help }, + { Keycode.Num0, Key.D0 }, + { Keycode.Num1, Key.D1 }, + { Keycode.Num2, Key.D2 }, + { Keycode.Num3, Key.D3 }, + { Keycode.Num4, Key.D4 }, + { Keycode.Num5, Key.D5 }, + { Keycode.Num6, Key.D6 }, + { Keycode.Num7, Key.D7 }, + { Keycode.Num8, Key.D8 }, + { Keycode.Num9, Key.D9 }, { Keycode.A, Key.A }, { Keycode.B, Key.B }, { Keycode.C, Key.C }, @@ -106,22 +107,22 @@ namespace Avalonia.Android.Platform.Input //{ Keycode.?, Key.LWin } //{ Keycode.?, Key.RWin } //{ Keycode.?, Key.Apps } - //{ Keycode.?, Key.Sleep } - //{ Keycode.?, Key.NumPad0 } - //{ Keycode.?, Key.NumPad1 } - //{ Keycode.?, Key.NumPad2 } - //{ Keycode.?, Key.NumPad3 } - //{ Keycode.?, Key.NumPad4 } - //{ Keycode.?, Key.NumPad5 } - //{ Keycode.?, Key.NumPad6 } - //{ Keycode.?, Key.NumPad7 } - //{ Keycode.?, Key.NumPad8 } - //{ Keycode.?, Key.NumPad9 } + { Keycode.Sleep, Key.Sleep }, + { Keycode.Numpad0, Key.NumPad0 }, + { Keycode.Numpad1, Key.NumPad1 }, + { Keycode.Numpad2, Key.NumPad2 }, + { Keycode.Numpad3, Key.NumPad3 }, + { Keycode.Numpad4, Key.NumPad4 }, + { Keycode.Numpad5, Key.NumPad5 }, + { Keycode.Numpad6, Key.NumPad6 }, + { Keycode.Numpad7, Key.NumPad7 }, + { Keycode.Numpad8, Key.NumPad8 }, + { Keycode.Numpad9, Key.NumPad9 }, { Keycode.NumpadMultiply, Key.Multiply }, { Keycode.NumpadAdd, Key.Add }, { Keycode.NumpadComma, Key.Separator }, { Keycode.NumpadSubtract, Key.Subtract }, - //{ Keycode.numpaddecimal?, Key.Decimal } + { Keycode.NumpadDot, Key.Decimal }, { Keycode.NumpadDivide, Key.Divide }, { Keycode.F1, Key.F1 }, { Keycode.F2, Key.F2 }, @@ -147,14 +148,14 @@ namespace Avalonia.Android.Platform.Input //{ Keycode.R2, Key.F22 }, //{ Keycode.F23, Key.F23 }, //{ Keycode.R4, Key.F24 }, - // { Keycode.numpad, Key.NumLock } + { Keycode.NumLock, Key.NumLock }, { Keycode.ScrollLock, Key.Scroll }, { Keycode.ShiftLeft, Key.LeftShift }, - //{ Keycode.?, Key.RightShift } - //{ Keycode.?, Key.LeftCtrl } - //{ Keycode.?, Key.RightCtrl } - //{ Keycode.?, Key.LeftAlt } - //{ Keycode.?, Key.RightAlt } + { Keycode.ShiftRight, Key.RightShift }, + { Keycode.CtrlLeft, Key.LeftCtrl }, + { Keycode.CtrlRight, Key.RightCtrl }, + { Keycode.AltLeft, Key.LeftAlt }, + { Keycode.AltRight, Key.RightAlt }, //{ Keycode.?, Key.BrowserBack } //{ Keycode.?, Key.BrowserForward } //{ Keycode.?, Key.BrowserRefresh } @@ -163,28 +164,30 @@ namespace Avalonia.Android.Platform.Input //{ Keycode.?, Key.BrowserFavorites } //{ Keycode.?, Key.BrowserHome } //{ Keycode.?, Key.VolumeMute } - //{ Keycode.?, Key.VolumeDown } - //{ Keycode.?, Key.VolumeUp } - //{ Keycode.?, Key.MediaNextTrack } - //{ Keycode.?, Key.MediaPreviousTrack } - //{ Keycode.?, Key.MediaStop } - //{ Keycode.?, Key.MediaPlayPause } + { Keycode.VolumeDown, Key.VolumeDown }, + { Keycode.VolumeUp, Key.VolumeUp }, + { Keycode.MediaNext, Key.MediaNextTrack }, + { Keycode.MediaPrevious, Key.MediaPreviousTrack }, + { Keycode.MediaStop, Key.MediaStop }, + { Keycode.MediaPlayPause, Key.MediaPlayPause }, //{ Keycode.?, Key.LaunchMail } //{ Keycode.?, Key.SelectMedia } //{ Keycode.?, Key.LaunchApplication1 } //{ Keycode.?, Key.LaunchApplication2 } - //{ Keycode.?, Key.OemSemicolon } - //{ Keycode.?, Key.OemPlus } - //{ Keycode.?, Key.OemComma } - //{ Keycode.?, Key.OemMinus } - //{ Keycode.?, Key.OemPeriod } + { Keycode.Semicolon, Key.OemSemicolon }, + { Keycode.Plus, Key.OemPlus }, + { Keycode.Comma, Key.OemComma }, + { Keycode.Minus, Key.OemMinus }, + { Keycode.Period, Key.OemPeriod }, //{ Keycode.?, Key.Oem2 } - //{ Keycode.?, Key.OemTilde } + { Keycode.Grave, Key.OemTilde }, //{ Keycode.?, Key.AbntC1 } //{ Keycode.?, Key.AbntC2 } - //{ Keycode.?, Key.Oem4 } //{ Keycode.?, Key.OemPipe } - //{ Keycode.?, Key.OemCloseBrackets } + { Keycode.Apostrophe, Key.OemQuotes }, + { Keycode.Slash, Key.OemQuestion }, + { Keycode.LeftBracket, Key.OemOpenBrackets }, + { Keycode.RightBracket, Key.OemCloseBrackets }, //{ Keycode.?, Key.Oem7 } //{ Keycode.?, Key.Oem8 } //{ Keycode.?, Key.Oem102 } @@ -200,17 +203,18 @@ namespace Avalonia.Android.Platform.Input //{ Keycode.?, Key.DbeEnterWordRegisterMode } //{ Keycode.?, Key.DbeEnterImeConfigureMode } //{ Keycode.?, Key.EraseEof } - //{ Keycode.?, Key.Play } + { Keycode.MediaPlay, Key.Play }, //{ Keycode.?, Key.Zoom } //{ Keycode.?, Key.NoName } //{ Keycode.?, Key.DbeEnterDialogConversionMode } //{ Keycode.?, Key.OemClear } //{ Keycode.?, Key.DeadCharProcessed } + { Keycode.Backslash, Key.OemBackslash } }; - internal static Key ConvertKey(Keycode key) { - Key result; - return KeyDic.TryGetValue(key, out result) ? result : Key.None; + internal static Key ConvertKey(Keycode key) + { + return KeyDic.TryGetValue(key, out var result) ? result : Key.None; + } } - } } From 3b203225cda7dd8be608cba973c78ae99d1d5cfb Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 16:25:15 +0200 Subject: [PATCH 31/36] Make DelayedBinding internal. Is only used by `StaticResource` and a few unit tests. Can probably be removed. --- src/Markup/Avalonia.Markup/Avalonia.Markup.csproj | 2 ++ src/Markup/Avalonia.Markup/Markup/Data/DelayedBinding.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj index ec44eeb38f..77a1082ed5 100644 --- a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj +++ b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj @@ -19,7 +19,9 @@ + + diff --git a/src/Markup/Avalonia.Markup/Markup/Data/DelayedBinding.cs b/src/Markup/Avalonia.Markup/Markup/Data/DelayedBinding.cs index 551e017a61..6c70a81298 100644 --- a/src/Markup/Avalonia.Markup/Markup/Data/DelayedBinding.cs +++ b/src/Markup/Avalonia.Markup/Markup/Data/DelayedBinding.cs @@ -18,7 +18,7 @@ namespace Avalonia.Markup.Data /// is applied to the property before the properties on the `Binding` object are set. Looking /// at WPF it uses a similar mechanism for bindings that come from XAML. /// - public static class DelayedBinding + internal static class DelayedBinding { private static readonly ConditionalWeakTable> _entries = new(); From 5836b202cc21316f47b9cd3385a84aed746f74ac Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 16:33:59 +0200 Subject: [PATCH 32/36] Make parsers internal. --- src/Markup/Avalonia.Markup/Avalonia.Markup.csproj | 4 ++++ .../Avalonia.Markup/Markup/Parsers/ArgumentListParser.cs | 5 +---- .../Avalonia.Markup/Markup/Parsers/PropertyPathGrammar.cs | 5 +---- src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj index 77a1082ed5..d041e7d2e6 100644 --- a/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj +++ b/src/Markup/Avalonia.Markup/Avalonia.Markup.csproj @@ -19,8 +19,12 @@ + + + + diff --git a/src/Markup/Avalonia.Markup/Markup/Parsers/ArgumentListParser.cs b/src/Markup/Avalonia.Markup/Markup/Parsers/ArgumentListParser.cs index e858bacb74..c3651594e9 100644 --- a/src/Markup/Avalonia.Markup/Markup/Parsers/ArgumentListParser.cs +++ b/src/Markup/Avalonia.Markup/Markup/Parsers/ArgumentListParser.cs @@ -4,10 +4,7 @@ using Avalonia.Utilities; namespace Avalonia.Markup.Parsers { -#if !BUILDTASK - public -#endif - static class ArgumentListParser + internal static class ArgumentListParser { public static IList ParseArguments(this ref CharacterReader r, char open, char close, char delimiter = ',') { diff --git a/src/Markup/Avalonia.Markup/Markup/Parsers/PropertyPathGrammar.cs b/src/Markup/Avalonia.Markup/Markup/Parsers/PropertyPathGrammar.cs index bf11a02fee..74d2ee3153 100644 --- a/src/Markup/Avalonia.Markup/Markup/Parsers/PropertyPathGrammar.cs +++ b/src/Markup/Avalonia.Markup/Markup/Parsers/PropertyPathGrammar.cs @@ -7,10 +7,7 @@ using Avalonia.Utilities; namespace Avalonia.Markup.Parsers { -#if !BUILDTASK - public -#endif - class PropertyPathGrammar + internal class PropertyPathGrammar { private enum State { diff --git a/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs b/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs index 557045d469..350b07742f 100644 --- a/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs +++ b/src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs @@ -11,7 +11,7 @@ namespace Avalonia.Markup.Parsers /// /// Parses a from text. /// - public class SelectorParser + internal class SelectorParser { private readonly Func _typeResolver; From 11b44129d1191fc979b56f0fde2c557767f69095 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 16:36:58 +0200 Subject: [PATCH 33/36] Make IRuntimeXamlLoader internal. --- src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj | 2 ++ src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj index 05e937fc05..618379757b 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj +++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj @@ -71,6 +71,8 @@ + + diff --git a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs index 834fa84b53..3d952a7ee9 100644 --- a/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs +++ b/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs @@ -9,7 +9,7 @@ namespace Avalonia.Markup.Xaml /// public static class AvaloniaXamlLoader { - public interface IRuntimeXamlLoader + internal interface IRuntimeXamlLoader { object Load(RuntimeXamlLoaderDocument document, RuntimeXamlLoaderConfiguration configuration); } From afb5d65f683dd64916769813d0c6cb7df1f787ec Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 16:39:46 +0200 Subject: [PATCH 34/36] Make ICompiledBindingPathElement internal. --- .../MarkupExtensions/CompiledBindings/CompiledBindingPath.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs index 49349b047c..73da7a7fe6 100644 --- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs +++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs @@ -173,7 +173,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings public CompiledBindingPath Build() => new CompiledBindingPath(_elements.ToArray(), _rawSource); } - public interface ICompiledBindingPathElement + internal interface ICompiledBindingPathElement { } From a99839be1d1a481175731ba384398d533e64ca16 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 22 May 2023 22:44:00 +0200 Subject: [PATCH 35/36] Remove unneeded protected properties. --- src/Avalonia.Controls/Slider.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Avalonia.Controls/Slider.cs b/src/Avalonia.Controls/Slider.cs index de3c4023bd..25fff93f85 100644 --- a/src/Avalonia.Controls/Slider.cs +++ b/src/Avalonia.Controls/Slider.cs @@ -191,16 +191,6 @@ namespace Avalonia.Controls /// protected Track? Track => _track; - /// - /// Gets the that decreases the value. - /// - protected Button? DecreaseButton => _decreaseButton; - - /// - /// Gets the that increases the value. - /// - protected Button? IncreaseButton => _increaseButton; - /// protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { From b1769a0356cced1a9c6f1b7938f1234fe87f9221 Mon Sep 17 00:00:00 2001 From: FitDev Date: Tue, 23 May 2023 00:18:03 +0300 Subject: [PATCH 36/36] Move TryGetPlatformHandle to TopLevel Fix 3 --- src/Avalonia.Controls/TopLevel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 54ee31e897..5b0d94a6ee 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -375,7 +375,7 @@ namespace Avalonia.Controls /// Gets the platform-specific window implementation. /// public ITopLevelImpl? PlatformImpl { get; private set; } - + /// /// Trys to get the platform handle for the TopLevel-derived control. /// @@ -383,7 +383,7 @@ namespace Avalonia.Controls /// An describing the window handle, or null if the handle /// could not be retrieved. /// - public IPlatformHandle? TryGetPlatformHandle() => ((IWindowBaseImpl?) PlatformImpl)?.Handle; + public IPlatformHandle? TryGetPlatformHandle() => ((IWindowBaseImpl?) PlatformImpl)?.Handle; /// /// Gets the renderer for the window.