Browse Source

Merge branch 'master' into fixes/list-selection-interactions

pull/11455/head
Max Katz 3 years ago
committed by GitHub
parent
commit
908e3d2888
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      .ncrunch/AppWithoutLifetime.v3.ncrunchproject
  2. 5
      .ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject
  3. 5
      .ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject
  4. 112
      src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs
  5. 2
      src/Avalonia.Base/Animation/AnimatorKeyFrame.cs
  6. 2
      src/Avalonia.Base/AvaloniaProperty.cs
  7. 2
      src/Avalonia.Base/AvaloniaProperty`1.cs
  8. 2
      src/Avalonia.Base/Collections/AvaloniaListConverter.cs
  9. 4
      src/Avalonia.Base/Data/BindingValue.cs
  10. 2
      src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs
  11. 2
      src/Avalonia.Base/Data/Core/BindingExpression.cs
  12. 0
      src/Avalonia.Base/Data/TemplateBinding.cs
  13. 8
      src/Avalonia.Base/Diagnostics/TrimmingMessages.cs
  14. 3
      src/Avalonia.Base/Input/IAccessKeyHandler.cs
  15. 5
      src/Avalonia.Base/Input/IInputRoot.cs
  16. 5
      src/Avalonia.Base/Input/IMainMenu.cs
  17. 46
      src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs
  18. 1
      src/Avalonia.Base/Properties/AssemblyInfo.cs
  19. 2
      src/Avalonia.Base/PropertyStore/DirectUntypedBindingObserver.cs
  20. 2
      src/Avalonia.Base/PropertyStore/LocalValueBindingObserver.cs
  21. 4
      src/Avalonia.Base/PropertyStore/UntypedValueUtils.cs
  22. 2
      src/Avalonia.Base/StyledProperty.cs
  23. 4
      src/Avalonia.Base/Styling/PropertyEqualsSelector.cs
  24. 2
      src/Avalonia.Base/Styling/Setter.cs
  25. 10
      src/Avalonia.Base/Utilities/TypeUtilities.cs
  26. 2
      src/Avalonia.Base/Visual.cs
  27. 6
      src/Avalonia.Controls.ColorPicker/ColorSlider/ColorSlider.cs
  28. 2
      src/Avalonia.Controls/Avalonia.Controls.csproj
  29. 4
      src/Avalonia.Controls/Button.cs
  30. 4
      src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs
  31. 7
      src/Avalonia.Controls/ComboBox.cs
  32. 11
      src/Avalonia.Controls/ContentControl.cs
  33. 3
      src/Avalonia.Controls/IContentControl.cs
  34. 2
      src/Avalonia.Controls/IHeadered.cs
  35. 3
      src/Avalonia.Controls/IMenu.cs
  36. 3
      src/Avalonia.Controls/IMenuElement.cs
  37. 3
      src/Avalonia.Controls/IMenuItem.cs
  38. 2
      src/Avalonia.Controls/INativeMenuExporterEventsImplBridge.cs
  39. 2
      src/Avalonia.Controls/Menu.cs
  40. 2
      src/Avalonia.Controls/MenuItemAccessKeyHandler.cs
  41. 2
      src/Avalonia.Controls/Panel.cs
  42. 459
      src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
  43. 58
      src/Avalonia.Controls/Platform/ExportAvaloniaModuleAttribute.cs
  44. 4
      src/Avalonia.Controls/Platform/IMenuInteractionHandler.cs
  45. 11
      src/Avalonia.Controls/Presenters/ContentPresenter.cs
  46. 5
      src/Avalonia.Controls/Presenters/IContentPresenterHost.cs
  47. 2
      src/Avalonia.Controls/Primitives/AccessText.cs
  48. 37
      src/Avalonia.Controls/Primitives/RangeBase.cs
  49. 18
      src/Avalonia.Controls/Slider.cs
  50. 6
      src/Avalonia.Controls/SplitButton/SplitButton.cs
  51. 18
      src/Avalonia.Controls/SplitView/SplitView.cs
  52. 6
      src/Avalonia.Controls/TextBlock.cs
  53. 2
      src/Avalonia.Controls/TextBox.cs
  54. 2
      src/Avalonia.Controls/ToggleSwitch.cs
  55. 25
      src/Avalonia.Controls/TopLevel.cs
  56. 4
      src/Avalonia.Controls/Window.cs
  57. 12
      src/Avalonia.Controls/WindowBase.cs
  58. 2
      src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleContext.cs
  59. 2
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  60. 2
      src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
  61. 2
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs
  62. 6
      src/Markup/Avalonia.Markup/Avalonia.Markup.csproj
  63. 4
      src/Markup/Avalonia.Markup/Data/BindingBase.cs
  64. 2
      src/Markup/Avalonia.Markup/Markup/Data/DelayedBinding.cs
  65. 5
      src/Markup/Avalonia.Markup/Markup/Parsers/ArgumentListParser.cs
  66. 5
      src/Markup/Avalonia.Markup/Markup/Parsers/PropertyPathGrammar.cs
  67. 2
      src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs
  68. 2
      tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs
  69. 2
      tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs
  70. 2
      tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
  71. 2
      tests/Avalonia.Controls.UnitTests/TopLevelTests.cs
  72. 2
      tests/Avalonia.Markup.Xaml.UnitTests/XamlTestBase.cs
  73. 2
      tests/Avalonia.UnitTests/TestRoot.cs

5
.ncrunch/AppWithoutLifetime.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/Avalonia.Headless.NUnit.netstandard2.0.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/Avalonia.Headless.XUnit.netstandard2.0.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

112
src/Android/Avalonia.Android/Platform/Input/AndroidKeyboardDevice.cs

@ -5,8 +5,9 @@ using Avalonia.Input;
namespace Avalonia.Android.Platform.Input namespace Avalonia.Android.Platform.Input
{ {
internal class AndroidKeyboardDevice : KeyboardDevice, IKeyboardDevice { internal class AndroidKeyboardDevice : KeyboardDevice, IKeyboardDevice
private static readonly Dictionary<Keycode, Key> KeyDic = new Dictionary<Keycode, Key> {
private static readonly Dictionary<Keycode, Key> KeyDic = new Dictionary<Keycode, Key>
{ {
// { Keycode.Cancel?, Key.Cancel }, // { Keycode.Cancel?, Key.Cancel },
{ Keycode.Del, Key.Back }, { Keycode.Del, Key.Back },
@ -15,7 +16,7 @@ namespace Avalonia.Android.Platform.Input
{ Keycode.Clear, Key.Clear }, { Keycode.Clear, Key.Clear },
{ Keycode.Enter, Key.Return }, { Keycode.Enter, Key.Return },
{ Keycode.MediaPause, Key.Pause }, { Keycode.MediaPause, Key.Pause },
//{ Keycode.?, Key.CapsLock } { Keycode.CapsLock, Key.CapsLock },
//{ Keycode.?, Key.HangulMode } //{ Keycode.?, Key.HangulMode }
//{ Keycode.?, Key.JunjaMode } //{ Keycode.?, Key.JunjaMode }
//{ Keycode.?, Key.FinalMode } //{ Keycode.?, Key.FinalMode }
@ -28,8 +29,8 @@ namespace Avalonia.Android.Platform.Input
{ Keycode.Space, Key.Space }, { Keycode.Space, Key.Space },
{ Keycode.PageUp, Key.Prior }, { Keycode.PageUp, Key.Prior },
{ Keycode.PageDown, Key.PageDown }, { Keycode.PageDown, Key.PageDown },
// { Keycode.end?, Key.End }, { Keycode.MoveEnd, Key.End },
{ Keycode.Home, Key.Home }, { Keycode.MoveHome, Key.Home },
{ Keycode.DpadLeft, Key.Left }, { Keycode.DpadLeft, Key.Left },
{ Keycode.DpadUp, Key.Up }, { Keycode.DpadUp, Key.Up },
{ Keycode.DpadRight, Key.Right }, { Keycode.DpadRight, Key.Right },
@ -37,20 +38,20 @@ namespace Avalonia.Android.Platform.Input
// { Keycode.ButtonSelect?, Key.Select }, // { Keycode.ButtonSelect?, Key.Select },
// { Keycode.print?, Key.Print }, // { Keycode.print?, Key.Print },
//{ Keycode.execute?, Key.Execute }, //{ Keycode.execute?, Key.Execute },
// { Keycode.snap, Key.Snapshot } //{ Keycode.snap?, Key.Snapshot }
{ Keycode.Insert, Key.Insert }, { Keycode.Insert, Key.Insert },
{ Keycode.ForwardDel, Key.Delete }, { Keycode.ForwardDel, Key.Delete },
//{ Keycode.help, Key.Help }, { Keycode.Help, Key.Help },
//{ Keycode.?, Key.D0 } { Keycode.Num0, Key.D0 },
//{ Keycode.?, Key.D1 } { Keycode.Num1, Key.D1 },
//{ Keycode.?, Key.D2 } { Keycode.Num2, Key.D2 },
//{ Keycode.?, Key.D3 } { Keycode.Num3, Key.D3 },
//{ Keycode.?, Key.D4 } { Keycode.Num4, Key.D4 },
//{ Keycode.?, Key.D5 } { Keycode.Num5, Key.D5 },
//{ Keycode.?, Key.D6 } { Keycode.Num6, Key.D6 },
//{ Keycode.?, Key.D7 } { Keycode.Num7, Key.D7 },
//{ Keycode.?, Key.D8 } { Keycode.Num8, Key.D8 },
//{ Keycode.?, Key.D9 } { Keycode.Num9, Key.D9 },
{ Keycode.A, Key.A }, { Keycode.A, Key.A },
{ Keycode.B, Key.B }, { Keycode.B, Key.B },
{ Keycode.C, Key.C }, { Keycode.C, Key.C },
@ -106,22 +107,22 @@ namespace Avalonia.Android.Platform.Input
//{ Keycode.?, Key.LWin } //{ Keycode.?, Key.LWin }
//{ Keycode.?, Key.RWin } //{ Keycode.?, Key.RWin }
//{ Keycode.?, Key.Apps } //{ Keycode.?, Key.Apps }
//{ Keycode.?, Key.Sleep } { Keycode.Sleep, Key.Sleep },
//{ Keycode.?, Key.NumPad0 } { Keycode.Numpad0, Key.NumPad0 },
//{ Keycode.?, Key.NumPad1 } { Keycode.Numpad1, Key.NumPad1 },
//{ Keycode.?, Key.NumPad2 } { Keycode.Numpad2, Key.NumPad2 },
//{ Keycode.?, Key.NumPad3 } { Keycode.Numpad3, Key.NumPad3 },
//{ Keycode.?, Key.NumPad4 } { Keycode.Numpad4, Key.NumPad4 },
//{ Keycode.?, Key.NumPad5 } { Keycode.Numpad5, Key.NumPad5 },
//{ Keycode.?, Key.NumPad6 } { Keycode.Numpad6, Key.NumPad6 },
//{ Keycode.?, Key.NumPad7 } { Keycode.Numpad7, Key.NumPad7 },
//{ Keycode.?, Key.NumPad8 } { Keycode.Numpad8, Key.NumPad8 },
//{ Keycode.?, Key.NumPad9 } { Keycode.Numpad9, Key.NumPad9 },
{ Keycode.NumpadMultiply, Key.Multiply }, { Keycode.NumpadMultiply, Key.Multiply },
{ Keycode.NumpadAdd, Key.Add }, { Keycode.NumpadAdd, Key.Add },
{ Keycode.NumpadComma, Key.Separator }, { Keycode.NumpadComma, Key.Separator },
{ Keycode.NumpadSubtract, Key.Subtract }, { Keycode.NumpadSubtract, Key.Subtract },
//{ Keycode.numpaddecimal?, Key.Decimal } { Keycode.NumpadDot, Key.Decimal },
{ Keycode.NumpadDivide, Key.Divide }, { Keycode.NumpadDivide, Key.Divide },
{ Keycode.F1, Key.F1 }, { Keycode.F1, Key.F1 },
{ Keycode.F2, Key.F2 }, { Keycode.F2, Key.F2 },
@ -147,14 +148,14 @@ namespace Avalonia.Android.Platform.Input
//{ Keycode.R2, Key.F22 }, //{ Keycode.R2, Key.F22 },
//{ Keycode.F23, Key.F23 }, //{ Keycode.F23, Key.F23 },
//{ Keycode.R4, Key.F24 }, //{ Keycode.R4, Key.F24 },
// { Keycode.numpad, Key.NumLock } { Keycode.NumLock, Key.NumLock },
{ Keycode.ScrollLock, Key.Scroll }, { Keycode.ScrollLock, Key.Scroll },
{ Keycode.ShiftLeft, Key.LeftShift }, { Keycode.ShiftLeft, Key.LeftShift },
//{ Keycode.?, Key.RightShift } { Keycode.ShiftRight, Key.RightShift },
//{ Keycode.?, Key.LeftCtrl } { Keycode.CtrlLeft, Key.LeftCtrl },
//{ Keycode.?, Key.RightCtrl } { Keycode.CtrlRight, Key.RightCtrl },
//{ Keycode.?, Key.LeftAlt } { Keycode.AltLeft, Key.LeftAlt },
//{ Keycode.?, Key.RightAlt } { Keycode.AltRight, Key.RightAlt },
//{ Keycode.?, Key.BrowserBack } //{ Keycode.?, Key.BrowserBack }
//{ Keycode.?, Key.BrowserForward } //{ Keycode.?, Key.BrowserForward }
//{ Keycode.?, Key.BrowserRefresh } //{ Keycode.?, Key.BrowserRefresh }
@ -163,28 +164,30 @@ namespace Avalonia.Android.Platform.Input
//{ Keycode.?, Key.BrowserFavorites } //{ Keycode.?, Key.BrowserFavorites }
//{ Keycode.?, Key.BrowserHome } //{ Keycode.?, Key.BrowserHome }
//{ Keycode.?, Key.VolumeMute } //{ Keycode.?, Key.VolumeMute }
//{ Keycode.?, Key.VolumeDown } { Keycode.VolumeDown, Key.VolumeDown },
//{ Keycode.?, Key.VolumeUp } { Keycode.VolumeUp, Key.VolumeUp },
//{ Keycode.?, Key.MediaNextTrack } { Keycode.MediaNext, Key.MediaNextTrack },
//{ Keycode.?, Key.MediaPreviousTrack } { Keycode.MediaPrevious, Key.MediaPreviousTrack },
//{ Keycode.?, Key.MediaStop } { Keycode.MediaStop, Key.MediaStop },
//{ Keycode.?, Key.MediaPlayPause } { Keycode.MediaPlayPause, Key.MediaPlayPause },
//{ Keycode.?, Key.LaunchMail } //{ Keycode.?, Key.LaunchMail }
//{ Keycode.?, Key.SelectMedia } //{ Keycode.?, Key.SelectMedia }
//{ Keycode.?, Key.LaunchApplication1 } //{ Keycode.?, Key.LaunchApplication1 }
//{ Keycode.?, Key.LaunchApplication2 } //{ Keycode.?, Key.LaunchApplication2 }
//{ Keycode.?, Key.OemSemicolon } { Keycode.Semicolon, Key.OemSemicolon },
//{ Keycode.?, Key.OemPlus } { Keycode.Plus, Key.OemPlus },
//{ Keycode.?, Key.OemComma } { Keycode.Comma, Key.OemComma },
//{ Keycode.?, Key.OemMinus } { Keycode.Minus, Key.OemMinus },
//{ Keycode.?, Key.OemPeriod } { Keycode.Period, Key.OemPeriod },
//{ Keycode.?, Key.Oem2 } //{ Keycode.?, Key.Oem2 }
//{ Keycode.?, Key.OemTilde } { Keycode.Grave, Key.OemTilde },
//{ Keycode.?, Key.AbntC1 } //{ Keycode.?, Key.AbntC1 }
//{ Keycode.?, Key.AbntC2 } //{ Keycode.?, Key.AbntC2 }
//{ Keycode.?, Key.Oem4 }
//{ Keycode.?, Key.OemPipe } //{ 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.Oem7 }
//{ Keycode.?, Key.Oem8 } //{ Keycode.?, Key.Oem8 }
//{ Keycode.?, Key.Oem102 } //{ Keycode.?, Key.Oem102 }
@ -200,17 +203,18 @@ namespace Avalonia.Android.Platform.Input
//{ Keycode.?, Key.DbeEnterWordRegisterMode } //{ Keycode.?, Key.DbeEnterWordRegisterMode }
//{ Keycode.?, Key.DbeEnterImeConfigureMode } //{ Keycode.?, Key.DbeEnterImeConfigureMode }
//{ Keycode.?, Key.EraseEof } //{ Keycode.?, Key.EraseEof }
//{ Keycode.?, Key.Play } { Keycode.MediaPlay, Key.Play },
//{ Keycode.?, Key.Zoom } //{ Keycode.?, Key.Zoom }
//{ Keycode.?, Key.NoName } //{ Keycode.?, Key.NoName }
//{ Keycode.?, Key.DbeEnterDialogConversionMode } //{ Keycode.?, Key.DbeEnterDialogConversionMode }
//{ Keycode.?, Key.OemClear } //{ Keycode.?, Key.OemClear }
//{ Keycode.?, Key.DeadCharProcessed } //{ Keycode.?, Key.DeadCharProcessed }
{ Keycode.Backslash, Key.OemBackslash }
}; };
internal static Key ConvertKey(Keycode key) { internal static Key ConvertKey(Keycode key)
Key result; {
return KeyDic.TryGetValue(key, out result) ? result : Key.None; return KeyDic.TryGetValue(key, out var result) ? result : Key.None;
}
} }
}
} }

2
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>() public T GetTypedValue<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T>()
{ {
var typeConv = TypeDescriptor.GetConverter(typeof(T)); var typeConv = TypeDescriptor.GetConverter(typeof(T));

2
src/Avalonia.Base/AvaloniaProperty.cs

@ -476,7 +476,7 @@ namespace Avalonia
/// </summary> /// </summary>
/// <param name="value">The value.</param> /// <param name="value">The value.</param>
/// <returns>True if the value is valid, otherwise false.</returns> /// <returns>True if the value is valid, otherwise false.</returns>
[RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)] [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConversionRequiresUnreferencedCodeMessage)]
public bool IsValidValue(object? value) public bool IsValidValue(object? value)
{ {
return TypeUtilities.TryConvertImplicit(PropertyType, value, out _); return TypeUtilities.TryConvertImplicit(PropertyType, value, out _);

2
src/Avalonia.Base/AvaloniaProperty`1.cs

@ -70,7 +70,7 @@ namespace Avalonia
private protected override IObservable<AvaloniaPropertyChangedEventArgs> GetChanged() => Changed; private protected override IObservable<AvaloniaPropertyChangedEventArgs> GetChanged() => Changed;
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)]
private protected BindingValue<object?> TryConvert(object? value) private protected BindingValue<object?> TryConvert(object? value)
{ {
if (value == UnsetValue) if (value == UnsetValue)

2
src/Avalonia.Base/Collections/AvaloniaListConverter.cs

@ -9,7 +9,7 @@ namespace Avalonia.Collections
/// <summary> /// <summary>
/// Creates an <see cref="AvaloniaList{T}"/> from a string representation. /// Creates an <see cref="AvaloniaList{T}"/> from a string representation.
/// </summary> /// </summary>
[RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)] [RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)]
public class AvaloniaListConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T> : TypeConverter public class AvaloniaListConverter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] T> : TypeConverter
{ {
public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType) public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)

4
src/Avalonia.Base/Data/BindingValue.cs

@ -237,7 +237,7 @@ namespace Avalonia.Data
/// </summary> /// </summary>
/// <param name="value">The untyped value.</param> /// <param name="value">The untyped value.</param>
/// <returns>The typed binding value.</returns> /// <returns>The typed binding value.</returns>
[RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)] [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConversionRequiresUnreferencedCodeMessage)]
public static BindingValue<T> FromUntyped(object? value) public static BindingValue<T> FromUntyped(object? value)
{ {
return FromUntyped(value, typeof(T)); return FromUntyped(value, typeof(T));
@ -251,7 +251,7 @@ namespace Avalonia.Data
/// <param name="value">The untyped value.</param> /// <param name="value">The untyped value.</param>
/// <param name="targetType">The runtime target type.</param> /// <param name="targetType">The runtime target type.</param>
/// <returns>The typed binding value.</returns> /// <returns>The typed binding value.</returns>
[RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)] [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConversionRequiresUnreferencedCodeMessage)]
public static BindingValue<T> FromUntyped(object? value, Type targetType) public static BindingValue<T> FromUntyped(object? value, Type targetType)
{ {
if (value == AvaloniaProperty.UnsetValue) if (value == AvaloniaProperty.UnsetValue)

2
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 /// Provides a default set of value conversions for bindings that do not specify a value
/// converter. /// converter.
/// </summary> /// </summary>
[RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)] [RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)]
public class DefaultValueConverter : IValueConverter public class DefaultValueConverter : IValueConverter
{ {
/// <summary> /// <summary>

2
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 /// Binds to an expression on an object using a type value converter to convert the values
/// that are sent and received. /// that are sent and received.
/// </summary> /// </summary>
[RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)] [RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)]
internal class BindingExpression : LightweightObservableBase<object?>, IAvaloniaSubject<object?>, IDescription internal class BindingExpression : LightweightObservableBase<object?>, IAvaloniaSubject<object?>, IDescription
{ {
private readonly ExpressionObserver _inner; private readonly ExpressionObserver _inner;

0
src/Markup/Avalonia.Markup/Data/TemplateBinding.cs → src/Avalonia.Base/Data/TemplateBinding.cs

8
src/Avalonia.Base/Diagnostics/TrimmingMessages.cs

@ -2,11 +2,11 @@
internal static class TrimmingMessages 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 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 ImplicitTypeConvertionRequiresUnreferencedCodeMessage = "Implicit convertion methods are required for type conversion."; 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 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 TypeConvertionRequiresUnreferencedCodeMessage = "Convertion methods are required for type conversion, including op_Implicit, op_Explicit, Parse and TypeConverter."; 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 ReflectionBindingRequiresUnreferencedCodeMessage = "BindingExpression and ReflectionBinding heavily use reflection. Consider using CompiledBindings instead.";
public const string ReflectionBindingSupressWarningMessage = "BindingExpression and ReflectionBinding internal heavily use reflection."; public const string ReflectionBindingSupressWarningMessage = "BindingExpression and ReflectionBinding internal heavily use reflection.";

3
src/Avalonia.Base/Input/IAccessKeyHandler.cs

@ -5,8 +5,7 @@ namespace Avalonia.Input
/// <summary> /// <summary>
/// Defines the interface for classes that handle access keys for a window. /// Defines the interface for classes that handle access keys for a window.
/// </summary> /// </summary>
[Unstable] internal interface IAccessKeyHandler
public interface IAccessKeyHandler
{ {
/// <summary> /// <summary>
/// Gets or sets the window's main menu. /// Gets or sets the window's main menu.

5
src/Avalonia.Base/Input/IInputRoot.cs

@ -8,11 +8,6 @@ namespace Avalonia.Input
[NotClientImplementable] [NotClientImplementable]
public interface IInputRoot : IInputElement public interface IInputRoot : IInputElement
{ {
/// <summary>
/// Gets or sets the access key handler.
/// </summary>
IAccessKeyHandler AccessKeyHandler { get; }
/// <summary> /// <summary>
/// Gets or sets the keyboard navigation handler. /// Gets or sets the keyboard navigation handler.
/// </summary> /// </summary>

5
src/Avalonia.Base/Input/IMainMenu.cs

@ -1,15 +1,12 @@
using System; using System;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Metadata;
using Avalonia.VisualTree;
namespace Avalonia.Input namespace Avalonia.Input
{ {
/// <summary> /// <summary>
/// Defines the interface for a window's main menu. /// Defines the interface for a window's main menu.
/// </summary> /// </summary>
[NotClientImplementable] internal interface IMainMenu
public interface IMainMenu
{ {
/// <summary> /// <summary>
/// Gets a value indicating whether the menu is open. /// Gets a value indicating whether the menu is open.

46
src/Avalonia.Base/Interactivity/RoutedPropertyChangedEventArgs.cs

@ -0,0 +1,46 @@
namespace Avalonia.Interactivity
{
/// <summary>
/// Provides both old and new property values with a routed event.
/// </summary>
/// <typeparam name="T">The type of values.</typeparam>
public class RoutedPropertyChangedEventArgs<T> : RoutedEventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="RoutedPropertyChangedEventArgs{T}"/> class.
/// </summary>
/// <param name="oldValue">The old property value.</param>
/// <param name="newValue">The new property value.</param>
/// <param name="routedEvent">The routed event associated with these event args.</param>
public RoutedPropertyChangedEventArgs(T oldValue, T newValue, RoutedEvent? routedEvent)
: base(routedEvent)
{
OldValue = oldValue;
NewValue = newValue;
}
/// <summary>
/// Initializes a new instance of the <see cref="RoutedPropertyChangedEventArgs{T}"/> class.
/// </summary>
/// <param name="oldValue">The old property value.</param>
/// <param name="newValue">The new property value.</param>
/// <param name="routedEvent">The routed event associated with these event args.</param>
/// <param name="source">The source object that raised the routed event.</param>
public RoutedPropertyChangedEventArgs(T oldValue, T newValue, RoutedEvent? routedEvent, object? source)
: base(routedEvent, source)
{
OldValue = oldValue;
NewValue = newValue;
}
/// <summary>
/// Gets the old value of the property.
/// </summary>
public T OldValue { get; init; }
/// <summary>
/// Gets the new value of the property.
/// </summary>
public T NewValue { get; init; }
}
}

1
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")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation.Easings")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Animation.Easings")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Controls")] [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.Data.Converters")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Input")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Input")]
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Input.GestureRecognizers")] [assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Input.GestureRecognizers")]

2
src/Avalonia.Base/PropertyStore/DirectUntypedBindingObserver.cs

@ -5,7 +5,7 @@ using Avalonia.Threading;
namespace Avalonia.PropertyStore namespace Avalonia.PropertyStore
{ {
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)]
internal class DirectUntypedBindingObserver<T> : IObserver<object?>, internal class DirectUntypedBindingObserver<T> : IObserver<object?>,
IDisposable IDisposable
{ {

2
src/Avalonia.Base/PropertyStore/LocalValueBindingObserver.cs

@ -14,7 +14,7 @@ namespace Avalonia.PropertyStore
public void Start(IObservable<object?> source) => _subscription = source.Subscribe(this); public void Start(IObservable<object?> source) => _subscription = source.Subscribe(this);
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)]
public void OnNext(object? value) public void OnNext(object? value)
{ {
if (value == BindingOperations.DoNothing) if (value == BindingOperations.DoNothing)

4
src/Avalonia.Base/PropertyStore/UntypedValueUtils.cs

@ -7,7 +7,7 @@ namespace Avalonia.PropertyStore
{ {
internal static class UntypedValueUtils internal static class UntypedValueUtils
{ {
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)]
public static BindingValue<T> ConvertAndValidate<T>( public static BindingValue<T> ConvertAndValidate<T>(
object? value, object? value,
Type targetType, Type targetType,
@ -24,7 +24,7 @@ namespace Avalonia.PropertyStore
return v; return v;
} }
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)]
public static bool TryConvertAndValidate<T>( public static bool TryConvertAndValidate<T>(
StyledProperty<T> property, StyledProperty<T> property,
object? value, object? value,

2
src/Avalonia.Base/StyledProperty.cs

@ -221,7 +221,7 @@ namespace Avalonia
return target.Bind<TValue>(this, source, priority); return target.Bind<TValue>(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) private bool ShouldSetValue(AvaloniaObject target, object? value, [NotNullWhen(true)] out TValue? converted)
{ {
if (value == BindingOperations.DoNothing) if (value == BindingOperations.DoNothing)

4
src/Avalonia.Base/Styling/PropertyEqualsSelector.cs

@ -91,8 +91,8 @@ namespace Avalonia.Styling
private protected override Selector? MovePrevious() => _previous; private protected override Selector? MovePrevious() => _previous;
private protected override Selector? MovePreviousOrParent() => _previous; private protected override Selector? MovePreviousOrParent() => _previous;
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.TypeConvertionSupressWarningMessage)] [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.TypeConversionSupressWarningMessage)]
[UnconditionalSuppressMessage("Trimming", "IL2067", Justification = TrimmingMessages.TypeConvertionSupressWarningMessage)] [UnconditionalSuppressMessage("Trimming", "IL2067", Justification = TrimmingMessages.TypeConversionSupressWarningMessage)]
internal static bool Compare(Type propertyType, object? propertyValue, object? value) internal static bool Compare(Type propertyType, object? propertyValue, object? value)
{ {
if (propertyType == typeof(object) && if (propertyType == typeof(object) &&

2
src/Avalonia.Base/Styling/Setter.cs

@ -65,7 +65,7 @@ namespace Avalonia.Styling
void IValueEntry.Unsubscribe() { } void IValueEntry.Unsubscribe() { }
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConvertionSupressWarningMessage)] [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.ImplicitTypeConversionSupressWarningMessage)]
internal override ISetterInstance Instance(IStyleInstance instance, StyledElement target) internal override ISetterInstance Instance(IStyleInstance instance, StyledElement target)
{ {
if (target is not AvaloniaObject ao) if (target is not AvaloniaObject ao)

10
src/Avalonia.Base/Utilities/TypeUtilities.cs

@ -126,7 +126,7 @@ namespace Avalonia.Utilities
/// <param name="culture">The culture to use.</param> /// <param name="culture">The culture to use.</param>
/// <param name="result">If successful, contains the convert value.</param> /// <param name="result">If successful, contains the convert value.</param>
/// <returns>True if the cast was successful, otherwise false.</returns> /// <returns>True if the cast was successful, otherwise false.</returns>
[RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)] [RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)]
public static bool TryConvert(Type to, object? value, CultureInfo? culture, out object? result) public static bool TryConvert(Type to, object? value, CultureInfo? culture, out object? result)
{ {
if (value == null) if (value == null)
@ -246,7 +246,7 @@ namespace Avalonia.Utilities
/// <param name="value">The value to convert.</param> /// <param name="value">The value to convert.</param>
/// <param name="result">If successful, contains the converted value.</param> /// <param name="result">If successful, contains the converted value.</param>
/// <returns>True if the convert was successful, otherwise false.</returns> /// <returns>True if the convert was successful, otherwise false.</returns>
[RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)] [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConversionRequiresUnreferencedCodeMessage)]
public static bool TryConvertImplicit(Type to, object? value, out object? result) public static bool TryConvertImplicit(Type to, object? value, out object? result)
{ {
if (value == null) if (value == null)
@ -309,7 +309,7 @@ namespace Avalonia.Utilities
/// <param name="type">The type to convert to..</param> /// <param name="type">The type to convert to..</param>
/// <param name="culture">The culture to use.</param> /// <param name="culture">The culture to use.</param>
/// <returns>A value of <paramref name="type"/>.</returns> /// <returns>A value of <paramref name="type"/>.</returns>
[RequiresUnreferencedCode(TrimmingMessages.TypeConvertionRequiresUnreferencedCodeMessage)] [RequiresUnreferencedCode(TrimmingMessages.TypeConversionRequiresUnreferencedCodeMessage)]
public static object? ConvertOrDefault(object? value, Type type, CultureInfo culture) public static object? ConvertOrDefault(object? value, Type type, CultureInfo culture)
{ {
return TryConvert(type, value, culture, out var result) ? result : Default(type); return TryConvert(type, value, culture, out var result) ? result : Default(type);
@ -322,13 +322,13 @@ namespace Avalonia.Utilities
/// <param name="value">The value to convert.</param> /// <param name="value">The value to convert.</param>
/// <param name="type">The type to convert to.</param> /// <param name="type">The type to convert to.</param>
/// <returns>A value of <paramref name="type"/>.</returns> /// <returns>A value of <paramref name="type"/>.</returns>
[RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)] [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConversionRequiresUnreferencedCodeMessage)]
public static object? ConvertImplicitOrDefault(object? value, Type type) public static object? ConvertImplicitOrDefault(object? value, Type type)
{ {
return TryConvertImplicit(type, value, out var result) ? result : Default(type); return TryConvertImplicit(type, value, out var result) ? result : Default(type);
} }
[RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConvertionRequiresUnreferencedCodeMessage)] [RequiresUnreferencedCode(TrimmingMessages.ImplicitTypeConversionRequiresUnreferencedCodeMessage)]
public static T ConvertImplicit<T>(object? value) public static T ConvertImplicit<T>(object? value)
{ {
if (TryConvertImplicit(typeof(T), value, out var result)) if (TryConvertImplicit(typeof(T), value, out var result))

2
src/Avalonia.Base/Visual.cs

@ -774,7 +774,7 @@ namespace Avalonia
/// Computes the <see cref="HasMirrorTransform"/> value according to the /// Computes the <see cref="HasMirrorTransform"/> value according to the
/// <see cref="FlowDirection"/> and <see cref="BypassFlowDirectionPolicies"/> /// <see cref="FlowDirection"/> and <see cref="BypassFlowDirectionPolicies"/>
/// </summary> /// </summary>
public virtual void InvalidateMirrorTransform() protected internal virtual void InvalidateMirrorTransform()
{ {
var flowDirection = this.FlowDirection; var flowDirection = this.FlowDirection;
var parentFlowDirection = FlowDirection.LeftToRight; var parentFlowDirection = FlowDirection.LeftToRight;

6
src/Avalonia.Controls.ColorPicker/ColorSlider/ColorSlider.cs

@ -98,10 +98,10 @@ namespace Avalonia.Controls.Primitives
int pixelWidth; int pixelWidth;
int pixelHeight; int pixelHeight;
if (base._track != null) if (base.Track != null)
{ {
pixelWidth = Convert.ToInt32(base._track.Bounds.Width * scale); pixelWidth = Convert.ToInt32(base.Track.Bounds.Width * scale);
pixelHeight = Convert.ToInt32(base._track.Bounds.Height * scale); pixelHeight = Convert.ToInt32(base.Track.Bounds.Height * scale);
} }
else else
{ {

2
src/Avalonia.Controls/Avalonia.Controls.csproj

@ -14,6 +14,7 @@
<ItemGroup Label="InternalsVisibleTo"> <ItemGroup Label="InternalsVisibleTo">
<InternalsVisibleTo Include="Avalonia.Controls.ItemsRepeater, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.Controls.ItemsRepeater, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Controls.UnitTests, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.Controls.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Markup.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.DesignerSupport, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.DesignerSupport, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Diagnostics, PublicKey=$(AvaloniaPublicKey)"/> <InternalsVisibleTo Include="Avalonia.Diagnostics, PublicKey=$(AvaloniaPublicKey)"/>
<InternalsVisibleTo Include="Avalonia.LeakTests, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.LeakTests, PublicKey=$(AvaloniaPublicKey)" />
@ -22,5 +23,6 @@
<InternalsVisibleTo Include="Avalonia.X11, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.X11, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.DesignerSupport.Remote, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.DesignerSupport.Remote, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Browser, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.Browser, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7" />
</ItemGroup> </ItemGroup>
</Project> </Project>

4
src/Avalonia.Controls/Button.cs

@ -34,8 +34,8 @@ namespace Avalonia.Controls
[PseudoClasses(pcFlyoutOpen, pcPressed)] [PseudoClasses(pcFlyoutOpen, pcPressed)]
public class Button : ContentControl, ICommandSource, IClickableControl public class Button : ContentControl, ICommandSource, IClickableControl
{ {
protected const string pcPressed = ":pressed"; private const string pcPressed = ":pressed";
protected const string pcFlyoutOpen = ":flyout-open"; private const string pcFlyoutOpen = ":flyout-open";
/// <summary> /// <summary>
/// Defines the <see cref="ClickMode"/> property. /// Defines the <see cref="ClickMode"/> property.

4
src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs

@ -26,8 +26,8 @@ namespace Avalonia.Controls
[PseudoClasses(pcFlyoutOpen, pcPressed)] [PseudoClasses(pcFlyoutOpen, pcPressed)]
public partial class CalendarDatePicker : TemplatedControl public partial class CalendarDatePicker : TemplatedControl
{ {
protected const string pcPressed = ":pressed"; private const string pcPressed = ":pressed";
protected const string pcFlyoutOpen = ":flyout-open"; private const string pcFlyoutOpen = ":flyout-open";
private const string ElementTextBox = "PART_TextBox"; private const string ElementTextBox = "PART_TextBox";
private const string ElementButton = "PART_Button"; private const string ElementButton = "PART_Button";

7
src/Avalonia.Controls/ComboBox.cs

@ -21,8 +21,9 @@ namespace Avalonia.Controls
[PseudoClasses(pcDropdownOpen, pcPressed)] [PseudoClasses(pcDropdownOpen, pcPressed)]
public class ComboBox : SelectingItemsControl public class ComboBox : SelectingItemsControl
{ {
public const string pcDropdownOpen = ":dropdownopen"; internal const string pcDropdownOpen = ":dropdownopen";
public const string pcPressed = ":pressed"; internal const string pcPressed = ":pressed";
/// <summary> /// <summary>
/// The default value for the <see cref="ItemsControl.ItemsPanel"/> property. /// The default value for the <see cref="ItemsControl.ItemsPanel"/> property.
/// </summary> /// </summary>
@ -164,7 +165,7 @@ namespace Avalonia.Controls
UpdateSelectionBoxItem(SelectedItem); UpdateSelectionBoxItem(SelectedItem);
} }
public override void InvalidateMirrorTransform() protected internal override void InvalidateMirrorTransform()
{ {
base.InvalidateMirrorTransform(); base.InvalidateMirrorTransform();
UpdateFlowDirection(); UpdateFlowDirection();

11
src/Avalonia.Controls/ContentControl.cs

@ -116,19 +116,14 @@ namespace Avalonia.Controls
return false; return false;
} }
protected virtual void ContentChanged(AvaloniaPropertyChangedEventArgs e) private void ContentChanged(AvaloniaPropertyChangedEventArgs e)
{ {
UpdateLogicalTree(e.OldValue, e.NewValue); if (e.OldValue is ILogical oldChild)
}
protected void UpdateLogicalTree(object? toRemove, object? toAdd)
{
if (toRemove is ILogical oldChild)
{ {
LogicalChildren.Remove(oldChild); LogicalChildren.Remove(oldChild);
} }
if (toAdd is ILogical newChild) if (e.NewValue is ILogical newChild)
{ {
LogicalChildren.Add(newChild); LogicalChildren.Add(newChild);
} }

3
src/Avalonia.Controls/IContentControl.cs

@ -8,8 +8,7 @@ namespace Avalonia.Controls
/// Defines a control that displays <see cref="Content"/> according to a /// Defines a control that displays <see cref="Content"/> according to a
/// <see cref="Avalonia.Controls.Templates.FuncDataTemplate"/>. /// <see cref="Avalonia.Controls.Templates.FuncDataTemplate"/>.
/// </summary> /// </summary>
[NotClientImplementable] internal interface IContentControl
public interface IContentControl
{ {
/// <summary> /// <summary>
/// Gets or sets the content to display. /// Gets or sets the content to display.

2
src/Avalonia.Controls/IHeadered.cs

@ -3,7 +3,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Defines a headered object. /// Defines a headered object.
/// </summary> /// </summary>
public interface IHeadered internal interface IHeadered
{ {
/// <summary> /// <summary>
/// Gets or set the header. /// Gets or set the header.

3
src/Avalonia.Controls/IMenu.cs

@ -8,8 +8,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Represents a <see cref="Menu"/> or <see cref="ContextMenu"/>. /// Represents a <see cref="Menu"/> or <see cref="ContextMenu"/>.
/// </summary> /// </summary>
[NotClientImplementable] internal interface IMenu : IMenuElement, IInputElement
public interface IMenu : IMenuElement, IInputElement
{ {
/// <summary> /// <summary>
/// Gets the menu interaction handler. /// Gets the menu interaction handler.

3
src/Avalonia.Controls/IMenuElement.cs

@ -8,8 +8,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Represents an <see cref="IMenu"/> or <see cref="IMenuItem"/>. /// Represents an <see cref="IMenu"/> or <see cref="IMenuItem"/>.
/// </summary> /// </summary>
[NotClientImplementable] internal interface IMenuElement : IInputElement, ILogical
public interface IMenuElement : IInputElement, ILogical
{ {
/// <summary> /// <summary>
/// Gets or sets the currently selected submenu item. /// Gets or sets the currently selected submenu item.

3
src/Avalonia.Controls/IMenuItem.cs

@ -5,8 +5,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Represents a <see cref="MenuItem"/>. /// Represents a <see cref="MenuItem"/>.
/// </summary> /// </summary>
[NotClientImplementable] internal interface IMenuItem : IMenuElement
public interface IMenuItem : IMenuElement
{ {
/// <summary> /// <summary>
/// Gets or sets a value that indicates whether the item has a submenu. /// Gets or sets a value that indicates whether the item has a submenu.

2
src/Avalonia.Controls/INativeMenuExporterEventsImplBridge.cs

@ -2,7 +2,7 @@ using Avalonia.Metadata;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
[Unstable] [PrivateApi]
public interface INativeMenuExporterEventsImplBridge public interface INativeMenuExporterEventsImplBridge
{ {
void RaiseNeedsUpdate (); void RaiseNeedsUpdate ();

2
src/Avalonia.Controls/Menu.cs

@ -87,7 +87,7 @@ namespace Avalonia.Controls
{ {
base.OnAttachedToVisualTree(e); base.OnAttachedToVisualTree(e);
var inputRoot = e.Root as IInputRoot; var inputRoot = e.Root as TopLevel;
if (inputRoot?.AccessKeyHandler != null) if (inputRoot?.AccessKeyHandler != null)
{ {

2
src/Avalonia.Controls/MenuItemAccessKeyHandler.cs

@ -9,7 +9,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Handles access keys within a <see cref="MenuItem"/> /// Handles access keys within a <see cref="MenuItem"/>
/// </summary> /// </summary>
public class MenuItemAccessKeyHandler : IAccessKeyHandler internal class MenuItemAccessKeyHandler : IAccessKeyHandler
{ {
/// <summary> /// <summary>
/// The registered access keys. /// The registered access keys.

2
src/Avalonia.Controls/Panel.cs

@ -213,7 +213,7 @@ namespace Avalonia.Controls
} }
/// <inheritdoc /> /// <inheritdoc />
public bool TryGetTotalCount(out int count) bool IChildIndexProvider.TryGetTotalCount(out int count)
{ {
count = Children.Count; count = Children.Count;
return true; return true;

459
src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs

@ -39,91 +39,20 @@ namespace Avalonia.Controls.Platform
DelayRun = delayRun; DelayRun = delayRun;
} }
public virtual void Attach(IMenu menu) public void Attach(MenuBase menu) => AttachCore(menu);
{ public void Detach(MenuBase menu) => DetachCore(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;
}
protected Action<Action, TimeSpan> DelayRun { get; } protected Action<Action, TimeSpan> DelayRun { get; }
protected IInputManager? InputManager { 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 static TimeSpan MenuShowDelay { get; } = TimeSpan.FromMilliseconds(400);
protected internal virtual void GotFocus(object? sender, GotFocusEventArgs e) 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) if (item?.Parent != null)
{ {
@ -133,7 +62,7 @@ namespace Avalonia.Controls.Platform
protected internal virtual void LostFocus(object? sender, RoutedEventArgs e) 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) if (item != null)
{ {
@ -143,146 +72,12 @@ namespace Avalonia.Controls.Platform
protected internal virtual void KeyDown(object? sender, KeyEventArgs e) protected internal virtual void KeyDown(object? sender, KeyEventArgs e)
{ {
KeyDown(GetMenuItem(e.Source as Control), e); KeyDown(GetMenuItemCore(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);
}
} }
protected internal virtual void AccessKeyPressed(object? sender, RoutedEventArgs 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) if (item == null)
{ {
@ -303,7 +98,7 @@ namespace Avalonia.Controls.Platform
protected internal virtual void PointerEntered(object? sender, RoutedEventArgs e) 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) if (item?.Parent == null)
{ {
@ -349,7 +144,7 @@ namespace Avalonia.Controls.Platform
protected internal virtual void PointerMoved(object? sender, PointerEventArgs e) protected internal virtual void PointerMoved(object? sender, PointerEventArgs e)
{ {
// HACK: #8179 needs to be addressed to correctly implement it in the PointerPressed method. // 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) if (item == null)
return; return;
@ -370,7 +165,7 @@ namespace Avalonia.Controls.Platform
protected internal virtual void PointerExited(object? sender, RoutedEventArgs e) 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) if (item?.Parent == null)
{ {
@ -405,7 +200,7 @@ namespace Avalonia.Controls.Platform
protected internal virtual void PointerPressed(object? sender, PointerPressedEventArgs e) 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 && if (sender is Visual visual &&
e.GetCurrentPoint(visual).Properties.IsLeftButtonPressed && item?.HasSubMenu == true) 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) 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) if (e.InitialPressMouseButton == MouseButton.Left && item?.HasSubMenu == false)
{ {
@ -478,13 +273,84 @@ namespace Avalonia.Controls.Platform
{ {
Menu?.Close(); 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(); item.RaiseClick();
@ -494,7 +360,7 @@ namespace Avalonia.Controls.Platform
} }
} }
protected void CloseMenu(IMenuItem item) internal void CloseMenu(IMenuItem item)
{ {
var current = (IMenuElement?)item; var current = (IMenuElement?)item;
@ -506,7 +372,7 @@ namespace Avalonia.Controls.Platform
current?.Close(); current?.Close();
} }
protected void CloseWithDelay(IMenuItem item) internal void CloseWithDelay(IMenuItem item)
{ {
void Execute() void Execute()
{ {
@ -519,7 +385,141 @@ namespace Avalonia.Controls.Platform
DelayRun(Execute, MenuShowDelay); 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(); item.Open();
@ -529,7 +529,7 @@ namespace Avalonia.Controls.Platform
} }
} }
protected void OpenWithDelay(IMenuItem item) internal void OpenWithDelay(IMenuItem item)
{ {
void Execute() void Execute()
{ {
@ -542,7 +542,7 @@ namespace Avalonia.Controls.Platform
DelayRun(Execute, MenuShowDelay); DelayRun(Execute, MenuShowDelay);
} }
protected void SelectItemAndAncestors(IMenuItem item) internal void SelectItemAndAncestors(IMenuItem item)
{ {
var current = (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) while (true)
{ {
@ -565,6 +565,11 @@ namespace Avalonia.Controls.Platform
} }
} }
private void TopLevelLostPlatformFocus()
{
Menu?.Close();
}
private static void DefaultDelayRun(Action action, TimeSpan timeSpan) private static void DefaultDelayRun(Action action, TimeSpan timeSpan)
{ {
DispatcherTimer.RunOnce(action, timeSpan); DispatcherTimer.RunOnce(action, timeSpan);

58
src/Avalonia.Controls/Platform/ExportAvaloniaModuleAttribute.cs

@ -1,58 +0,0 @@
using System;
namespace Avalonia.Platform
{
/// <summary>
/// Defines an "Avalonia Module", a 3rd party extension to Avalonia that can be automatically initialized by an AppBuilder instance.
/// </summary>
/// <remarks>
/// 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:
/// <code>
/// // 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();
/// }
/// }
///
/// </code>
/// The fallback module will only be initialized if the Skia-specific module is not applicable.
/// </remarks>
[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; } = "";
}
}

4
src/Avalonia.Controls/Platform/IMenuInteractionHandler.cs

@ -12,11 +12,11 @@ namespace Avalonia.Controls.Platform
/// Attaches the interaction handler to a menu. /// Attaches the interaction handler to a menu.
/// </summary> /// </summary>
/// <param name="menu">The menu.</param> /// <param name="menu">The menu.</param>
void Attach(IMenu menu); void Attach(MenuBase menu);
/// <summary> /// <summary>
/// Detaches the interaction handler from the attached menu. /// Detaches the interaction handler from the attached menu.
/// </summary> /// </summary>
void Detach(IMenu menu); void Detach(MenuBase menu);
} }
} }

11
src/Avalonia.Controls/Presenters/ContentPresenter.cs

@ -540,17 +540,6 @@ namespace Avalonia.Controls.Presenters
BoxShadow); BoxShadow);
} }
/// <summary>
/// Creates the child control.
/// </summary>
/// <returns>The child control or null.</returns>
protected virtual Control? CreateChild()
{
var content = Content;
var oldChild = Child;
return CreateChild(content, oldChild, ContentTemplate);
}
private Control? CreateChild(object? content, Control? oldChild, IDataTemplate? template) private Control? CreateChild(object? content, Control? oldChild, IDataTemplate? template)
{ {
var newChild = content as Control; var newChild = content as Control;

5
src/Avalonia.Controls/Presenters/IContentPresenterHost.cs

@ -1,7 +1,5 @@
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.LogicalTree; using Avalonia.LogicalTree;
using Avalonia.Metadata;
using Avalonia.Styling;
namespace Avalonia.Controls.Presenters namespace Avalonia.Controls.Presenters
{ {
@ -16,8 +14,7 @@ namespace Avalonia.Controls.Presenters
/// parent control's template is instantiated so they register themselves using this /// parent control's template is instantiated so they register themselves using this
/// interface. /// interface.
/// </remarks> /// </remarks>
[NotClientImplementable] internal interface IContentPresenterHost
public interface IContentPresenterHost
{ {
/// <summary> /// <summary>
/// Gets a collection describing the logical children of the host control. /// Gets a collection describing the logical children of the host control.

2
src/Avalonia.Controls/Primitives/AccessText.cs

@ -86,7 +86,7 @@ namespace Avalonia.Controls.Primitives
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{ {
base.OnAttachedToVisualTree(e); base.OnAttachedToVisualTree(e);
_accessKeys = (e.Root as IInputRoot)?.AccessKeyHandler; _accessKeys = (e.Root as TopLevel)?.AccessKeyHandler;
if (_accessKeys != null && AccessKey != 0) if (_accessKeys != null && AccessKey != 0)
{ {

37
src/Avalonia.Controls/Primitives/RangeBase.cs

@ -1,5 +1,6 @@
using System; using System;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Interactivity;
using Avalonia.Utilities; using Avalonia.Utilities;
namespace Avalonia.Controls.Primitives namespace Avalonia.Controls.Primitives
@ -42,7 +43,23 @@ namespace Avalonia.Controls.Primitives
AvaloniaProperty.Register<RangeBase, double>(nameof(LargeChange), 10); AvaloniaProperty.Register<RangeBase, double>(nameof(LargeChange), 10);
/// <summary> /// <summary>
/// Gets or sets the minimum value. /// Defines the <see cref="ValueChanged"/> event.
/// </summary>
public static readonly RoutedEvent<RoutedPropertyChangedEventArgs<double>> ValueChangedEvent =
RoutedEvent.Register<RangeBase, RoutedPropertyChangedEventArgs<double>>(
nameof(ValueChanged), RoutingStrategies.Bubble);
/// <summary>
/// Occurs when the <see cref="Value"/> property changes.
/// </summary>
public event EventHandler<RoutedPropertyChangedEventArgs<double>>? ValueChanged
{
add => AddHandler(ValueChangedEvent, value);
remove => RemoveHandler(ValueChangedEvent, value);
}
/// <summary>
/// Gets or sets the minimum possible value.
/// </summary> /// </summary>
public double Minimum public double Minimum
{ {
@ -65,7 +82,7 @@ namespace Avalonia.Controls.Primitives
} }
/// <summary> /// <summary>
/// Gets or sets the maximum value. /// Gets or sets the maximum possible value.
/// </summary> /// </summary>
public double Maximum public double Maximum
{ {
@ -104,18 +121,25 @@ namespace Avalonia.Controls.Primitives
: sender.GetValue(ValueProperty); : sender.GetValue(ValueProperty);
} }
/// <summary>
/// Gets or sets the small increment value added or subtracted from the <see cref="Value"/>.
/// </summary>
public double SmallChange public double SmallChange
{ {
get => GetValue(SmallChangeProperty); get => GetValue(SmallChangeProperty);
set => SetValue(SmallChangeProperty, value); set => SetValue(SmallChangeProperty, value);
} }
/// <summary>
/// Gets or sets the large increment value added or subtracted from the <see cref="Value"/>.
/// </summary>
public double LargeChange public double LargeChange
{ {
get => GetValue(LargeChangeProperty); get => GetValue(LargeChangeProperty);
set => SetValue(LargeChangeProperty, value); set => SetValue(LargeChangeProperty, value);
} }
/// <inheritdoc/>
protected override void OnInitialized() protected override void OnInitialized()
{ {
base.OnInitialized(); base.OnInitialized();
@ -124,6 +148,7 @@ namespace Avalonia.Controls.Primitives
CoerceValue(ValueProperty); CoerceValue(ValueProperty);
} }
/// <inheritdoc/>
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{ {
base.OnPropertyChanged(change); base.OnPropertyChanged(change);
@ -136,6 +161,14 @@ namespace Avalonia.Controls.Primitives
{ {
OnMaximumChanged(); OnMaximumChanged();
} }
else if (change.Property == ValueProperty)
{
var valueChangedEventArgs = new RoutedPropertyChangedEventArgs<double>(
change.GetOldValue<double>(),
change.GetNewValue<double>(),
ValueChangedEvent);
RaiseEvent(valueChangedEventArgs);
}
} }
/// <summary> /// <summary>

18
src/Avalonia.Controls/Slider.cs

@ -86,10 +86,10 @@ namespace Avalonia.Controls
TickBar.TicksProperty.AddOwner<Slider>(); TickBar.TicksProperty.AddOwner<Slider>();
// Slider required parts // Slider required parts
protected bool _isDragging; private bool _isDragging;
protected Track? _track; private Track? _track;
protected Button? _decreaseButton; private Button? _decreaseButton;
protected Button? _increaseButton; private Button? _increaseButton;
private IDisposable? _decreaseButtonPressDispose; private IDisposable? _decreaseButtonPressDispose;
private IDisposable? _decreaseButtonReleaseDispose; private IDisposable? _decreaseButtonReleaseDispose;
private IDisposable? _increaseButtonSubscription; private IDisposable? _increaseButtonSubscription;
@ -181,6 +181,16 @@ namespace Avalonia.Controls
set { SetValue(TickPlacementProperty, value); } set { SetValue(TickPlacementProperty, value); }
} }
/// <summary>
/// Gets a value indicating whether the <see cref="Slider"/> is currently being dragged.
/// </summary>
protected bool IsDragging => _isDragging;
/// <summary>
/// Gets the <see cref="Track"/> part of the <see cref="Slider"/>.
/// </summary>
protected Track? Track => _track;
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {

6
src/Avalonia.Controls/SplitButton/SplitButton.cs

@ -18,9 +18,9 @@ namespace Avalonia.Controls
[PseudoClasses(pcFlyoutOpen, pcPressed)] [PseudoClasses(pcFlyoutOpen, pcPressed)]
public class SplitButton : ContentControl, ICommandSource public class SplitButton : ContentControl, ICommandSource
{ {
protected const string pcChecked = ":checked"; internal const string pcChecked = ":checked";
protected const string pcPressed = ":pressed"; internal const string pcPressed = ":pressed";
protected const string pcFlyoutOpen = ":flyout-open"; internal const string pcFlyoutOpen = ":flyout-open";
/// <summary> /// <summary>
/// Raised when the user presses the primary part of the <see cref="SplitButton"/>. /// Raised when the user presses the primary part of the <see cref="SplitButton"/>.

18
src/Avalonia.Controls/SplitView/SplitView.cs

@ -22,15 +22,15 @@ namespace Avalonia.Controls
[PseudoClasses(pcLightDismiss)] [PseudoClasses(pcLightDismiss)]
public class SplitView : ContentControl public class SplitView : ContentControl
{ {
protected const string pcOpen = ":open"; private const string pcOpen = ":open";
protected const string pcClosed = ":closed"; private const string pcClosed = ":closed";
protected const string pcCompactOverlay = ":compactoverlay"; private const string pcCompactOverlay = ":compactoverlay";
protected const string pcCompactInline = ":compactinline"; private const string pcCompactInline = ":compactinline";
protected const string pcOverlay = ":overlay"; private const string pcOverlay = ":overlay";
protected const string pcInline = ":inline"; private const string pcInline = ":inline";
protected const string pcLeft = ":left"; private const string pcLeft = ":left";
protected const string pcRight = ":right"; private const string pcRight = ":right";
protected const string pcLightDismiss = ":lightDismiss"; private const string pcLightDismiss = ":lightDismiss";
/// <summary> /// <summary>
/// Defines the <see cref="CompactPaneLength"/> property /// Defines the <see cref="CompactPaneLength"/> property

6
src/Avalonia.Controls/TextBlock.cs

@ -144,8 +144,8 @@ namespace Avalonia.Controls
AvaloniaProperty.RegisterDirect<TextBlock, InlineCollection?>( AvaloniaProperty.RegisterDirect<TextBlock, InlineCollection?>(
nameof(Inlines), t => t.Inlines, (t, v) => t.Inlines = v); nameof(Inlines), t => t.Inlines, (t, v) => t.Inlines = v);
protected TextLayout? _textLayout; private TextLayout? _textLayout;
protected Size _constraint; private Size _constraint;
private IReadOnlyList<TextRun>? _textRuns; private IReadOnlyList<TextRun>? _textRuns;
private InlineCollection? _inlines; private InlineCollection? _inlines;
@ -829,7 +829,7 @@ namespace Avalonia.Controls
InvalidateTextLayout(); InvalidateTextLayout();
} }
protected readonly record struct SimpleTextSource : ITextSource private readonly record struct SimpleTextSource : ITextSource
{ {
private readonly string _text; private readonly string _text;
private readonly TextRunProperties _defaultProperties; private readonly TextRunProperties _defaultProperties;

2
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) if (text is null)
return null; return null;

2
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)) if ((_switchKnob != null) && (_knobsPanel != null))
{ {

25
src/Avalonia.Controls/TopLevel.cs

@ -375,7 +375,16 @@ namespace Avalonia.Controls
/// Gets the platform-specific window implementation. /// Gets the platform-specific window implementation.
/// </summary> /// </summary>
public ITopLevelImpl? PlatformImpl { get; private set; } public ITopLevelImpl? PlatformImpl { get; private set; }
/// <summary>
/// Trys to get the platform handle for the TopLevel-derived control.
/// </summary>
/// <returns>
/// An <see cref="IPlatformHandle"/> describing the window handle, or null if the handle
/// could not be retrieved.
/// </returns>
public IPlatformHandle? TryGetPlatformHandle() => ((IWindowBaseImpl?) PlatformImpl)?.Handle;
/// <summary> /// <summary>
/// Gets the renderer for the window. /// Gets the renderer for the window.
/// </summary> /// </summary>
@ -386,7 +395,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Gets the access key handler for the window. /// Gets the access key handler for the window.
/// </summary> /// </summary>
IAccessKeyHandler IInputRoot.AccessKeyHandler => _accessKeyHandler!; internal IAccessKeyHandler AccessKeyHandler => _accessKeyHandler!;
/// <summary> /// <summary>
/// Gets or sets the keyboard navigation handler for the window. /// Gets or sets the keyboard navigation handler for the window.
@ -523,13 +532,13 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Creates the layout manager for this <see cref="TopLevel" />. /// Creates the layout manager for this <see cref="TopLevel" />.
/// </summary> /// </summary>
protected virtual ILayoutManager CreateLayoutManager() => new LayoutManager(this); private protected virtual ILayoutManager CreateLayoutManager() => new LayoutManager(this);
/// <summary> /// <summary>
/// Handles a paint notification from <see cref="ITopLevelImpl.Resized"/>. /// Handles a paint notification from <see cref="ITopLevelImpl.Resized"/>.
/// </summary> /// </summary>
/// <param name="rect">The dirty area.</param> /// <param name="rect">The dirty area.</param>
protected virtual void HandlePaint(Rect rect) private void HandlePaint(Rect rect)
{ {
Renderer.Paint(rect); Renderer.Paint(rect);
} }
@ -537,7 +546,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Handles a closed notification from <see cref="ITopLevelImpl.Closed"/>. /// Handles a closed notification from <see cref="ITopLevelImpl.Closed"/>.
/// </summary> /// </summary>
protected virtual void HandleClosed() private protected virtual void HandleClosed()
{ {
Renderer.SceneInvalidated -= SceneInvalidated; Renderer.SceneInvalidated -= SceneInvalidated;
// We need to wait for the renderer to complete any in-flight operations // We need to wait for the renderer to complete any in-flight operations
@ -595,7 +604,7 @@ namespace Avalonia.Controls
/// <see cref="ITopLevelImpl.ScalingChanged"/>. /// <see cref="ITopLevelImpl.ScalingChanged"/>.
/// </summary> /// </summary>
/// <param name="scaling">The window scaling.</param> /// <param name="scaling">The window scaling.</param>
protected virtual void HandleScalingChanged(double scaling) private void HandleScalingChanged(double scaling)
{ {
LayoutHelper.InvalidateSelfAndChildrenMeasure(this); LayoutHelper.InvalidateSelfAndChildrenMeasure(this);
ScalingChanged?.Invoke(this, EventArgs.Empty); ScalingChanged?.Invoke(this, EventArgs.Empty);
@ -615,7 +624,7 @@ namespace Avalonia.Controls
return false; return false;
} }
protected virtual void HandleTransparencyLevelChanged(WindowTransparencyLevel transparencyLevel) private void HandleTransparencyLevelChanged(WindowTransparencyLevel transparencyLevel)
{ {
if(_transparencyFallbackBorder != null) if(_transparencyFallbackBorder != null)
{ {
@ -740,7 +749,7 @@ namespace Avalonia.Controls
protected override bool BypassFlowDirectionPolicies => true; protected override bool BypassFlowDirectionPolicies => true;
public override void InvalidateMirrorTransform() protected internal override void InvalidateMirrorTransform()
{ {
// Do nothing becuase TopLevel should't apply MirrorTransform on himself. // Do nothing becuase TopLevel should't apply MirrorTransform on himself.
} }

4
src/Avalonia.Controls/Window.cs

@ -535,7 +535,7 @@ namespace Avalonia.Controls
return true; return true;
} }
protected virtual void HandleWindowStateChanged(WindowState state) private void HandleWindowStateChanged(WindowState state)
{ {
WindowState = state; WindowState = state;
@ -979,7 +979,7 @@ namespace Avalonia.Controls
return ClientSize; return ClientSize;
} }
protected sealed override void HandleClosed() private protected sealed override void HandleClosed()
{ {
RaiseEvent(new RoutedEventArgs(WindowClosedEvent)); RaiseEvent(new RoutedEventArgs(WindowClosedEvent));

12
src/Avalonia.Controls/WindowBase.cs

@ -60,7 +60,7 @@ namespace Avalonia.Controls
impl.PositionChanged = HandlePositionChanged; impl.PositionChanged = HandlePositionChanged;
} }
protected IDisposable FreezeVisibilityChangeHandling() private protected IDisposable FreezeVisibilityChangeHandling()
{ {
return new IgnoreVisibilityChangesDisposable(this); return new IgnoreVisibilityChangesDisposable(this);
} }
@ -178,14 +178,6 @@ namespace Avalonia.Controls
} }
} }
/// <summary>
/// Trys to get the platform handle for the window.
/// </summary>
/// <returns>
/// An <see cref="IPlatformHandle"/> describing the window handle, or null if the handle
/// could not be retrieved.
/// </returns>
public IPlatformHandle? TryGetPlatformHandle() => PlatformImpl?.Handle;
/// <summary> /// <summary>
/// Ensures that the window is initialized. /// Ensures that the window is initialized.
@ -226,7 +218,7 @@ namespace Avalonia.Controls
/// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param> /// <param name="e">An <see cref="EventArgs"/> that contains the event data.</param>
protected virtual void OnResized(WindowResizedEventArgs e) => Resized?.Invoke(this, e); protected virtual void OnResized(WindowResizedEventArgs e) => Resized?.Invoke(this, e);
protected override void HandleClosed() private protected override void HandleClosed()
{ {
using (FreezeVisibilityChangeHandling()) using (FreezeVisibilityChangeHandling())
{ {

2
src/Avalonia.Diagnostics/Diagnostics/Models/ConsoleContext.cs

@ -4,7 +4,7 @@ using Avalonia.Diagnostics.ViewModels;
namespace Avalonia.Diagnostics.Models namespace Avalonia.Diagnostics.Models
{ {
public class ConsoleContext internal class ConsoleContext
{ {
private readonly ConsoleViewModel _owner; private readonly ConsoleViewModel _owner;

2
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -71,6 +71,8 @@
<Import Project="..\..\..\build\NullableEnable.props" /> <Import Project="..\..\..\build\NullableEnable.props" />
<ItemGroup Label="InternalsVisibleTo"> <ItemGroup Label="InternalsVisibleTo">
<InternalsVisibleTo Include="Avalonia.Designer.HostApp, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.DesignerSupport, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Markup.Xaml.UnitTests, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.Markup.Xaml.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
</ItemGroup> </ItemGroup>
</Project> </Project>

2
src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs

@ -9,7 +9,7 @@ namespace Avalonia.Markup.Xaml
/// </summary> /// </summary>
public static class AvaloniaXamlLoader public static class AvaloniaXamlLoader
{ {
public interface IRuntimeXamlLoader internal interface IRuntimeXamlLoader
{ {
object Load(RuntimeXamlLoaderDocument document, RuntimeXamlLoaderConfiguration configuration); object Load(RuntimeXamlLoaderDocument document, RuntimeXamlLoaderConfiguration configuration);
} }

2
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 CompiledBindingPath Build() => new CompiledBindingPath(_elements.ToArray(), _rawSource);
} }
public interface ICompiledBindingPathElement internal interface ICompiledBindingPathElement
{ {
} }

6
src/Markup/Avalonia.Markup/Avalonia.Markup.csproj

@ -19,7 +19,13 @@
<Import Project="..\..\..\build\TrimmingEnable.props" /> <Import Project="..\..\..\build\TrimmingEnable.props" />
<ItemGroup Label="InternalsVisibleTo"> <ItemGroup Label="InternalsVisibleTo">
<InternalsVisibleTo Include="Avalonia.Base.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Benchmarks, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Controls.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Designer.HostApp, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Markup.Xaml, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.Markup.Xaml, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Markup.Xaml.Loader, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Markup.UnitTests, PublicKey=$(AvaloniaPublicKey)" /> <InternalsVisibleTo Include="Avalonia.Markup.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
<InternalsVisibleTo Include="Avalonia.Markup.Xaml.UnitTests, PublicKey=$(AvaloniaPublicKey)" />
</ItemGroup> </ItemGroup>
</Project> </Project>

4
src/Markup/Avalonia.Markup/Data/BindingBase.cs

@ -76,7 +76,7 @@ namespace Avalonia.Data
bool enableDataValidation); bool enableDataValidation);
/// <inheritdoc/> /// <inheritdoc/>
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.TypeConvertionSupressWarningMessage)] [UnconditionalSuppressMessage("Trimming", "IL2026", Justification = TrimmingMessages.TypeConversionSupressWarningMessage)]
public InstancedBinding? Initiate( public InstancedBinding? Initiate(
AvaloniaObject target, AvaloniaObject target,
AvaloniaProperty? targetProperty, AvaloniaProperty? targetProperty,
@ -234,7 +234,7 @@ namespace Avalonia.Data
return result; return result;
} }
protected IObservable<object?> GetParentDataContext(AvaloniaObject target) private IObservable<object?> GetParentDataContext(AvaloniaObject target)
{ {
// The DataContext is based on the visual parent and not the logical parent: this may // 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 // seem counter intuitive considering the fact that property inheritance works on the logical

2
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 /// 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. /// at WPF it uses a similar mechanism for bindings that come from XAML.
/// </remarks> /// </remarks>
public static class DelayedBinding internal static class DelayedBinding
{ {
private static readonly ConditionalWeakTable<StyledElement, List<Entry>> _entries = new(); private static readonly ConditionalWeakTable<StyledElement, List<Entry>> _entries = new();

5
src/Markup/Avalonia.Markup/Markup/Parsers/ArgumentListParser.cs

@ -4,10 +4,7 @@ using Avalonia.Utilities;
namespace Avalonia.Markup.Parsers namespace Avalonia.Markup.Parsers
{ {
#if !BUILDTASK internal static class ArgumentListParser
public
#endif
static class ArgumentListParser
{ {
public static IList<string> ParseArguments(this ref CharacterReader r, char open, char close, char delimiter = ',') public static IList<string> ParseArguments(this ref CharacterReader r, char open, char close, char delimiter = ',')
{ {

5
src/Markup/Avalonia.Markup/Markup/Parsers/PropertyPathGrammar.cs

@ -7,10 +7,7 @@ using Avalonia.Utilities;
namespace Avalonia.Markup.Parsers namespace Avalonia.Markup.Parsers
{ {
#if !BUILDTASK internal class PropertyPathGrammar
public
#endif
class PropertyPathGrammar
{ {
private enum State private enum State
{ {

2
src/Markup/Avalonia.Markup/Markup/Parsers/SelectorParser.cs

@ -11,7 +11,7 @@ namespace Avalonia.Markup.Parsers
/// <summary> /// <summary>
/// Parses a <see cref="Selector"/> from text. /// Parses a <see cref="Selector"/> from text.
/// </summary> /// </summary>
public class SelectorParser internal class SelectorParser
{ {
private readonly Func<string, string, Type> _typeResolver; private readonly Func<string, string, Type> _typeResolver;

2
tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs

@ -1004,7 +1004,7 @@ namespace Avalonia.Controls.UnitTests
_layoutManager = layoutManager ?? new LayoutManager(this); _layoutManager = layoutManager ?? new LayoutManager(this);
} }
protected override ILayoutManager CreateLayoutManager() => _layoutManager; private protected override ILayoutManager CreateLayoutManager() => _layoutManager;
} }
private static Mock<ITopLevelImpl> CreateMockTopLevelImpl() private static Mock<ITopLevelImpl> CreateMockTopLevelImpl()

2
tests/Avalonia.Controls.UnitTests/Platform/DefaultMenuInteractionHandlerTests.cs

@ -554,7 +554,7 @@ namespace Avalonia.Controls.UnitTests.Platform
var contextMenu = Mock.Of<IMenu>(x => x.MoveSelection(NavigationDirection.Down, true) == true); var contextMenu = Mock.Of<IMenu>(x => x.MoveSelection(NavigationDirection.Down, true) == true);
var e = new KeyEventArgs { Key = Key.Down, Source = contextMenu }; var e = new KeyEventArgs { Key = Key.Down, Source = contextMenu };
target.Attach(contextMenu); target.AttachCore(contextMenu);
target.KeyDown(contextMenu, e); target.KeyDown(contextMenu, e);
Mock.Get(contextMenu).Verify(x => x.MoveSelection(NavigationDirection.Down, true)); Mock.Get(contextMenu).Verify(x => x.MoveSelection(NavigationDirection.Down, true));

2
tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

@ -1208,7 +1208,7 @@ namespace Avalonia.Controls.UnitTests
_layoutManager = layoutManager ?? new LayoutManager(this); _layoutManager = layoutManager ?? new LayoutManager(this);
} }
protected override ILayoutManager CreateLayoutManager() => _layoutManager; private protected override ILayoutManager CreateLayoutManager() => _layoutManager;
} }
private static Mock<ITopLevelImpl> CreateMockTopLevelImpl() private static Mock<ITopLevelImpl> CreateMockTopLevelImpl()

2
tests/Avalonia.Controls.UnitTests/TopLevelTests.cs

@ -339,7 +339,7 @@ namespace Avalonia.Controls.UnitTests
_layoutManager = layoutManager ?? new LayoutManager(this); _layoutManager = layoutManager ?? new LayoutManager(this);
} }
protected override ILayoutManager CreateLayoutManager() => _layoutManager; private protected override ILayoutManager CreateLayoutManager() => _layoutManager;
} }
} }
} }

2
tests/Avalonia.Markup.Xaml.UnitTests/XamlTestBase.cs

@ -13,7 +13,7 @@ namespace Avalonia.Markup.Xaml.UnitTests
public XamlTestBase() public XamlTestBase()
{ {
// Ensure necessary assemblies are loaded. // Ensure necessary assemblies are loaded.
var _ = typeof(TemplateBinding); var _ = typeof(Binding);
GC.KeepAlive(typeof(ItemsRepeater)); GC.KeepAlive(typeof(ItemsRepeater));
if (AvaloniaLocator.Current.GetService<AvaloniaXamlLoader.IRuntimeXamlLoader>() == null) if (AvaloniaLocator.Current.GetService<AvaloniaXamlLoader.IRuntimeXamlLoader>() == null)
AvaloniaLocator.CurrentMutable.Bind<AvaloniaXamlLoader.IRuntimeXamlLoader>() AvaloniaLocator.CurrentMutable.Bind<AvaloniaXamlLoader.IRuntimeXamlLoader>()

2
tests/Avalonia.UnitTests/TestRoot.cs

@ -51,8 +51,6 @@ namespace Avalonia.UnitTests
public IRenderer Renderer { get; set; } public IRenderer Renderer { get; set; }
public IAccessKeyHandler AccessKeyHandler => null;
public IKeyboardNavigationHandler KeyboardNavigationHandler => null; public IKeyboardNavigationHandler KeyboardNavigationHandler => null;
public IFocusManager FocusManager => AvaloniaLocator.Current.GetService<IFocusManager>(); public IFocusManager FocusManager => AvaloniaLocator.Current.GetService<IFocusManager>();

Loading…
Cancel
Save