diff --git a/.editorconfig b/.editorconfig index 30edee1633..128b6f1712 100644 --- a/.editorconfig +++ b/.editorconfig @@ -137,6 +137,9 @@ space_within_single_line_array_initializer_braces = true # Wrapping preferences csharp_wrap_before_ternary_opsigns = false +# Avalonia DevAnalyzer preferences +dotnet_diagnostic.AVADEV2001.severity = error + # Xaml files [*.{xaml,axaml}] indent_size = 2 diff --git a/.gitignore b/.gitignore index 44fe5e4ba4..84faae1806 100644 --- a/.gitignore +++ b/.gitignore @@ -212,3 +212,6 @@ coc-settings.json *.map src/Web/Avalonia.Web.Blazor/wwwroot/*.js src/Web/Avalonia.Web.Blazor/Interop/Typescript/*.js +node_modules +src/Web/Avalonia.Web.Blazor/webapp/package-lock.json +src/Web/Avalonia.Web.Blazor/wwwroot diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index af8c53cb33..ddc50c26b6 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -91,8 +91,6 @@ HRESULT WindowImpl::SetParent(IAvnWindow *parent) { if(_parent != nullptr) { _parent->_children.remove(this); - - _parent->BringToFront(); } auto cparent = dynamic_cast(parent); diff --git a/samples/ControlCatalog/Converter/HexConverter.cs b/samples/ControlCatalog/Converter/HexConverter.cs index 83a52212f6..31cce5ba67 100644 --- a/samples/ControlCatalog/Converter/HexConverter.cs +++ b/samples/ControlCatalog/Converter/HexConverter.cs @@ -7,7 +7,7 @@ namespace ControlCatalog.Converter; public class HexConverter : IValueConverter { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { var str = value?.ToString(); if (str == null) @@ -18,7 +18,7 @@ public class HexConverter : IValueConverter } - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { try { diff --git a/samples/IntegrationTestApp/MacOSIntegration.cs b/samples/IntegrationTestApp/MacOSIntegration.cs new file mode 100644 index 0000000000..f700a5b4e2 --- /dev/null +++ b/samples/IntegrationTestApp/MacOSIntegration.cs @@ -0,0 +1,27 @@ +using System; +using System.Runtime.InteropServices; +using Avalonia.Controls; + +namespace IntegrationTestApp +{ + public static class MacOSIntegration + { + [DllImport("/usr/lib/libobjc.dylib", EntryPoint = "sel_registerName")] + private static extern IntPtr GetHandle(string name); + + [DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] + private static extern long Int64_objc_msgSend(IntPtr receiver, IntPtr selector); + + private static readonly IntPtr s_orderedIndexSelector; + + static MacOSIntegration() + { + s_orderedIndexSelector = GetHandle("orderedIndex");; + } + + public static long GetOrderedIndex(Window window) + { + return Int64_objc_msgSend(window.PlatformImpl!.Handle.Handle, s_orderedIndexSelector); + } + } +} diff --git a/samples/IntegrationTestApp/MainWindow.axaml.cs b/samples/IntegrationTestApp/MainWindow.axaml.cs index 2085b5da2b..f72f83fcb8 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml.cs +++ b/samples/IntegrationTestApp/MainWindow.axaml.cs @@ -1,11 +1,13 @@ using System.Collections.Generic; using System.Linq; using Avalonia; +using Avalonia.Automation; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; using Avalonia.VisualTree; +using Microsoft.CodeAnalysis; namespace IntegrationTestApp { @@ -63,6 +65,17 @@ namespace IntegrationTestApp WindowStartupLocation = (WindowStartupLocation)locationComboBox.SelectedIndex, }; + if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime lifetime) + { + // Make sure the windows have unique names and AutomationIds. + var existing = lifetime.Windows.OfType().Count(); + if (existing > 0) + { + AutomationProperties.SetAutomationId(window, window.Name + (existing + 1)); + window.Title += $" {existing + 1}"; + } + } + if (size.HasValue) { window.Width = size.Value.Width; diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml b/samples/IntegrationTestApp/ShowWindowTest.axaml index 4001bac7e2..17c359df51 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml @@ -3,7 +3,7 @@ x:Class="IntegrationTestApp.ShowWindowTest" Name="SecondaryWindow" Title="Show Window Test"> - + @@ -31,6 +31,10 @@ Maximized Fullscreen - + + + + + diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs index 001f186761..43875dd990 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs @@ -1,21 +1,32 @@ using System; +using System.Runtime.InteropServices; using Avalonia; using Avalonia.Controls; -using Avalonia.Interactivity; using Avalonia.Markup.Xaml; -using Avalonia.Rendering; +using Avalonia.Threading; namespace IntegrationTestApp { public class ShowWindowTest : Window { + private readonly DispatcherTimer? _timer; + private readonly TextBox? _orderTextBox; + public ShowWindowTest() { InitializeComponent(); DataContext = this; PositionChanged += (s, e) => this.GetControl("Position").Text = $"{Position}"; - } + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + _orderTextBox = this.GetControl("Order"); + _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(250) }; + _timer.Tick += TimerOnTick; + _timer.Start(); + } + } + private void InitializeComponent() { AvaloniaXamlLoader.Load(this); @@ -36,5 +47,16 @@ namespace IntegrationTestApp ownerRect.Text = $"{owner.Position}, {PixelSize.FromSize(owner.FrameSize!.Value, scaling)}"; } } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + _timer?.Stop(); + } + + private void TimerOnTick(object? sender, EventArgs e) + { + _orderTextBox!.Text = MacOSIntegration.GetOrderedIndex(this).ToString(); + } } } diff --git a/src/Avalonia.Base/Data/Core/Plugins/MethodAccessorPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/MethodAccessorPlugin.cs index 1ca70140ec..0d51a6ed36 100644 --- a/src/Avalonia.Base/Data/Core/Plugins/MethodAccessorPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/MethodAccessorPlugin.cs @@ -55,13 +55,20 @@ namespace Avalonia.Data.Core.Plugins var methods = type.GetMethods(bindingFlags); - foreach (MethodInfo methodInfo in methods) + foreach (var methodInfo in methods) { if (methodInfo.Name == methodName) { - found = methodInfo; - - break; + var parameters = methodInfo.GetParameters(); + if (parameters.Length == 1 && parameters[0].ParameterType == typeof(object)) + { + found = methodInfo; + break; + } + else if (parameters.Length == 0) + { + found = methodInfo; + } } } diff --git a/src/Avalonia.Base/Data/Core/Plugins/ObservableStreamPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/ObservableStreamPlugin.cs index 0288dbce91..6232fa39a1 100644 --- a/src/Avalonia.Base/Data/Core/Plugins/ObservableStreamPlugin.cs +++ b/src/Avalonia.Base/Data/Core/Plugins/ObservableStreamPlugin.cs @@ -42,7 +42,7 @@ namespace Avalonia.Data.Core.Plugins if (target is IObservable result) { return result; - }; + } // If the observable returns a value type then we need to call Observable.Select on it. // First get the type of T in `IObservable`. diff --git a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs index 889b7e3b82..4f5585ab6c 100644 --- a/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs +++ b/src/Avalonia.Base/Input/GestureRecognizers/ScrollGestureRecognizer.cs @@ -71,7 +71,7 @@ namespace Avalonia.Input.GestureRecognizers { EndGesture(); _tracking = e.Pointer; - _gestureId = ScrollGestureEventArgs.GetNextFreeId();; + _gestureId = ScrollGestureEventArgs.GetNextFreeId(); _trackedRootPoint = e.GetPosition(_target); } } diff --git a/src/Avalonia.Base/Input/PointerEventArgs.cs b/src/Avalonia.Base/Input/PointerEventArgs.cs index 1f3c726e7b..a0e8d4a074 100644 --- a/src/Avalonia.Base/Input/PointerEventArgs.cs +++ b/src/Avalonia.Base/Input/PointerEventArgs.cs @@ -65,6 +65,7 @@ namespace Avalonia.Input return default; if (relativeTo == null) return pt; + return pt * _rootVisual.TransformToVisual(relativeTo) ?? default; } diff --git a/src/Avalonia.Base/Input/PointerOverPreProcessor.cs b/src/Avalonia.Base/Input/PointerOverPreProcessor.cs index 2ebf01bcf6..e367f9f74f 100644 --- a/src/Avalonia.Base/Input/PointerOverPreProcessor.cs +++ b/src/Avalonia.Base/Input/PointerOverPreProcessor.cs @@ -68,27 +68,29 @@ namespace Avalonia.Input if (dirtyRect.Contains(clientPoint)) { - SetPointerOver(pointer, _inputRoot, _inputRoot.InputHitTest(clientPoint), 0, clientPoint, PointerPointProperties.None, KeyModifiers.None); + var element = pointer.Captured ?? _inputRoot.InputHitTest(clientPoint); + SetPointerOver(pointer, _inputRoot, element, 0, clientPoint, PointerPointProperties.None, KeyModifiers.None); } else if (!_inputRoot.Bounds.Contains(clientPoint)) { - ClearPointerOver(pointer, _inputRoot, 0, new Point(-1, -1), PointerPointProperties.None, KeyModifiers.None); + ClearPointerOver(pointer, _inputRoot, 0, clientPoint, PointerPointProperties.None, KeyModifiers.None); } } } private void ClearPointerOver() { - if (_lastPointer is (var pointer, var _)) + if (_lastPointer is (var pointer, var position)) { - ClearPointerOver(pointer, _inputRoot, 0, new Point(-1, -1), PointerPointProperties.None, KeyModifiers.None); + var clientPoint = _inputRoot.PointToClient(position); + ClearPointerOver(pointer, _inputRoot, 0, clientPoint, PointerPointProperties.None, KeyModifiers.None); } _lastPointer = null; _lastActivePointerDevice = null; } private void ClearPointerOver(IPointer pointer, IInputRoot root, - ulong timestamp, Point position, PointerPointProperties properties, KeyModifiers inputModifiers) + ulong timestamp, Point? position, PointerPointProperties properties, KeyModifiers inputModifiers) { var element = root.PointerOverElement; if (element is null) @@ -96,11 +98,10 @@ namespace Avalonia.Input return; } - // Do not pass rootVisual, when we have unknown (negative) position, + // Do not pass rootVisual, when we have unknown position, // so GetPosition won't return invalid values. - var hasPosition = position.X >= 0 && position.Y >= 0; var e = new PointerEventArgs(InputElement.PointerExitedEvent, element, pointer, - hasPosition ? root : null, hasPosition ? position : default, + position.HasValue ? root : null, position.HasValue ? position.Value : default, timestamp, properties, inputModifiers); if (element != null && !element.IsAttachedToVisualTree) diff --git a/src/Avalonia.Base/Layout/FlowLayoutAlgorithm.cs b/src/Avalonia.Base/Layout/FlowLayoutAlgorithm.cs index 3e516b4f97..e6a95d1ffb 100644 --- a/src/Avalonia.Base/Layout/FlowLayoutAlgorithm.cs +++ b/src/Avalonia.Base/Layout/FlowLayoutAlgorithm.cs @@ -523,7 +523,7 @@ namespace Avalonia.Layout { firstRealizedElement = _elementManager.GetAt(0); firstBounds = _elementManager.GetLayoutBoundsForRealizedIndex(0); - firstDataIndex = _elementManager.GetDataIndexFromRealizedRangeIndex(0);; + firstDataIndex = _elementManager.GetDataIndexFromRealizedRangeIndex(0); int last = _elementManager.GetRealizedElementCount() - 1; lastRealizedElement = _elementManager.GetAt(last); diff --git a/src/Avalonia.Base/Layout/LayoutHelper.cs b/src/Avalonia.Base/Layout/LayoutHelper.cs index 404d19906a..0851dbaea9 100644 --- a/src/Avalonia.Base/Layout/LayoutHelper.cs +++ b/src/Avalonia.Base/Layout/LayoutHelper.cs @@ -251,6 +251,17 @@ namespace Avalonia.Layout { double newValue; + // Round the value to avoid FP errors. This is needed because if `value` has a floating + // point precision error (e.g. 79.333333333333343) then when it's multiplied by + // `dpiScale` and rounded up, it will be rounded up to a value one greater than it + // should be. +#if NET6_0_OR_GREATER + value = Math.Round(value, 8, MidpointRounding.ToZero); +#else + // MidpointRounding.ToZero isn't available in netstandard2.0. + value = Math.Truncate(value * 1e8) / 1e8; +#endif + // If DPI == 1, don't use DPI-aware rounding. if (!MathUtilities.IsOne(dpiScale)) { diff --git a/src/Avalonia.Base/Layout/StackLayout.cs b/src/Avalonia.Base/Layout/StackLayout.cs index 00ac4a37f0..e3c2ab3817 100644 --- a/src/Avalonia.Base/Layout/StackLayout.cs +++ b/src/Avalonia.Base/Layout/StackLayout.cs @@ -322,6 +322,7 @@ namespace Avalonia.Layout protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { + base.OnPropertyChanged(change); if (change.Property == OrientationProperty) { var orientation = change.GetNewValue(); diff --git a/src/Avalonia.Base/Layout/UniformGridLayout.cs b/src/Avalonia.Base/Layout/UniformGridLayout.cs index 47c994a350..a7880a1545 100644 --- a/src/Avalonia.Base/Layout/UniformGridLayout.cs +++ b/src/Avalonia.Base/Layout/UniformGridLayout.cs @@ -473,6 +473,7 @@ namespace Avalonia.Layout protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { + base.OnPropertyChanged(change); if (change.Property == OrientationProperty) { var orientation = change.GetNewValue(); diff --git a/src/Avalonia.Base/Media/DashStyle.cs b/src/Avalonia.Base/Media/DashStyle.cs index abee580020..3a30b2d32f 100644 --- a/src/Avalonia.Base/Media/DashStyle.cs +++ b/src/Avalonia.Base/Media/DashStyle.cs @@ -35,7 +35,6 @@ namespace Avalonia.Media /// Initializes a new instance of the class. /// public DashStyle() - : this(null, 0) { } diff --git a/src/Avalonia.Base/Media/TextTrimming.cs b/src/Avalonia.Base/Media/TextTrimming.cs index b6f5be496f..e2737210be 100644 --- a/src/Avalonia.Base/Media/TextTrimming.cs +++ b/src/Avalonia.Base/Media/TextTrimming.cs @@ -8,7 +8,7 @@ namespace Avalonia.Media /// public abstract class TextTrimming { - public static char s_defaultEllipsisChar = '\u2026'; + internal const char DefaultEllipsisChar = '\u2026'; /// /// Text is not trimmed. @@ -18,22 +18,22 @@ namespace Avalonia.Media /// /// Text is trimmed at a character boundary. An ellipsis (...) is drawn in place of remaining text. /// - public static TextTrimming CharacterEllipsis { get; } = new TextTrailingTrimming(s_defaultEllipsisChar, false); + public static TextTrimming CharacterEllipsis { get; } = new TextTrailingTrimming(DefaultEllipsisChar, false); /// /// Text is trimmed at a word boundary. An ellipsis (...) is drawn in place of remaining text. /// - public static TextTrimming WordEllipsis { get; } = new TextTrailingTrimming(s_defaultEllipsisChar, true); + public static TextTrimming WordEllipsis { get; } = new TextTrailingTrimming(DefaultEllipsisChar, true); /// /// Text is trimmed after a given prefix length. An ellipsis (...) is drawn in between prefix and suffix and represents remaining text. /// - public static TextTrimming PrefixCharacterEllipsis { get; } = new TextLeadingPrefixTrimming(s_defaultEllipsisChar, 8); + public static TextTrimming PrefixCharacterEllipsis { get; } = new TextLeadingPrefixTrimming(DefaultEllipsisChar, 8); /// /// Text is trimmed at a character boundary starting from the beginning. An ellipsis (...) is drawn in place of remaining text. /// - public static TextTrimming LeadingCharacterEllipsis { get; } = new TextLeadingPrefixTrimming(s_defaultEllipsisChar, 0); + public static TextTrimming LeadingCharacterEllipsis { get; } = new TextLeadingPrefixTrimming(DefaultEllipsisChar, 0); /// /// Creates properties that will be used for collapsing lines of text. diff --git a/src/Avalonia.Base/Media/UnicodeRange.cs b/src/Avalonia.Base/Media/UnicodeRange.cs index 0077dd64ac..e2338b9b26 100644 --- a/src/Avalonia.Base/Media/UnicodeRange.cs +++ b/src/Avalonia.Base/Media/UnicodeRange.cs @@ -9,7 +9,7 @@ namespace Avalonia.Media /// public readonly struct UnicodeRange { - public static UnicodeRange Default = Parse("0-10FFFD"); + public readonly static UnicodeRange Default = Parse("0-10FFFD"); private readonly UnicodeRangeSegment _single; private readonly IReadOnlyList? _segments = null; diff --git a/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs b/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs index 9742a6b3ba..e47c8e7e31 100644 --- a/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs +++ b/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs @@ -87,7 +87,16 @@ public class CompositingRenderer : IRendererWithCompositor /// public IEnumerable HitTest(Point p, IVisual root, Func? filter) { - var res = CompositionTarget.TryHitTest(p, filter); + Func? f = null; + if (filter != null) + f = v => + { + if (v is CompositionDrawListVisual dlv) + return filter(dlv.Visual); + return true; + }; + + var res = CompositionTarget.TryHitTest(p, f); if(res == null) yield break; foreach(var v in res) diff --git a/src/Avalonia.Base/Rendering/Composition/CompositionDrawListVisual.cs b/src/Avalonia.Base/Rendering/Composition/CompositionDrawListVisual.cs index 77b392eee5..b019d1792b 100644 --- a/src/Avalonia.Base/Rendering/Composition/CompositionDrawListVisual.cs +++ b/src/Avalonia.Base/Rendering/Composition/CompositionDrawListVisual.cs @@ -54,13 +54,11 @@ internal class CompositionDrawListVisual : CompositionContainerVisual Visual = visual; } - internal override bool HitTest(Point pt, Func? filter) + internal override bool HitTest(Point pt) { var custom = Visual as ICustomHitTest; if (DrawList == null && custom == null) return false; - if (filter != null && !filter(Visual)) - return false; if (custom != null) { // Simulate the old behavior diff --git a/src/Avalonia.Base/Rendering/Composition/CompositionTarget.cs b/src/Avalonia.Base/Rendering/Composition/CompositionTarget.cs index 4e53e163ec..eb499604e0 100644 --- a/src/Avalonia.Base/Rendering/Composition/CompositionTarget.cs +++ b/src/Avalonia.Base/Rendering/Composition/CompositionTarget.cs @@ -31,7 +31,7 @@ namespace Avalonia.Rendering.Composition /// /// /// - public PooledList? TryHitTest(Point point, Func? filter) + public PooledList? TryHitTest(Point point, Func? filter) { Server.Readback.NextRead(); if (Root == null) @@ -88,10 +88,14 @@ namespace Avalonia.Rendering.Composition } void HitTestCore(CompositionVisual visual, Point globalPoint, PooledList result, - Func? filter) + Func? filter) { if (visual.Visible == false) return; + + if (filter != null && !filter(visual)) + return; + if (!TryTransformTo(visual, globalPoint, out var point)) return; @@ -111,7 +115,7 @@ namespace Avalonia.Rendering.Composition } // Hit-test the current node - if (visual.HitTest(point, filter)) + if (visual.HitTest(point)) result.Add(visual); } diff --git a/src/Avalonia.Base/Rendering/Composition/Visual.cs b/src/Avalonia.Base/Rendering/Composition/Visual.cs index 7356b7b9e8..6d6818256a 100644 --- a/src/Avalonia.Base/Rendering/Composition/Visual.cs +++ b/src/Avalonia.Base/Rendering/Composition/Visual.cs @@ -53,6 +53,6 @@ namespace Avalonia.Rendering.Composition internal object? Tag { get; set; } - internal virtual bool HitTest(Point point, Func? filter) => true; + internal virtual bool HitTest(Point point) => true; } } diff --git a/src/Avalonia.Base/Rotate3DTransform.cs b/src/Avalonia.Base/Rotate3DTransform.cs index 2c4e515861..2de33889c8 100644 --- a/src/Avalonia.Base/Rotate3DTransform.cs +++ b/src/Avalonia.Base/Rotate3DTransform.cs @@ -205,6 +205,7 @@ public class Rotate3DTransform : Transform protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { + base.OnPropertyChanged(change); if (!_isInitializing) RaiseChanged(); } } diff --git a/src/Avalonia.Base/Utilities/IWeakSubscriber.cs b/src/Avalonia.Base/Utilities/IWeakSubscriber.cs index 613c931165..2a5b8d39c5 100644 --- a/src/Avalonia.Base/Utilities/IWeakSubscriber.cs +++ b/src/Avalonia.Base/Utilities/IWeakSubscriber.cs @@ -3,7 +3,7 @@ using System; namespace Avalonia.Utilities { /// - /// Defines a listener to a event subscribed vis the . + /// Defines a listener to a event subscribed vis the . /// /// The type of the event arguments. public interface IWeakSubscriber where T : EventArgs diff --git a/src/Avalonia.Controls.ColorPicker/Converters/DoNothingForNullConverter.cs b/src/Avalonia.Controls.ColorPicker/Converters/DoNothingForNullConverter.cs new file mode 100644 index 0000000000..421a5acb28 --- /dev/null +++ b/src/Avalonia.Controls.ColorPicker/Converters/DoNothingForNullConverter.cs @@ -0,0 +1,35 @@ +using System; +using System.Globalization; +using Avalonia.Data; +using Avalonia.Data.Converters; + +namespace Avalonia.Controls.Converters +{ + /// + /// Converter that will do nothing (not update bound values) when a null value is encountered. + /// This converter enables binding nullable with non-nullable properties in some scenarios. + /// + public class DoNothingForNullConverter : IValueConverter + { + /// + public object? Convert( + object? value, + Type targetType, + object? parameter, + CultureInfo culture) + { + return value ?? BindingOperations.DoNothing; + } + + /// + public object? ConvertBack( + object? value, + Type targetType, + object? parameter, + CultureInfo culture) + { + return value ?? BindingOperations.DoNothing; + } + } +} + diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml index 59cc48975f..dab4142001 100644 --- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml +++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml @@ -11,6 +11,7 @@ + 48 30 @@ -205,7 +206,7 @@ diff --git a/src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs b/src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs index d63c738133..69e6766bfd 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs @@ -23,10 +23,10 @@ namespace Avalonia.Controls [PseudoClasses(":pressed", ":current", ":expanded")] public class DataGridRowGroupHeader : TemplatedControl { - private const string DATAGRIDROWGROUPHEADER_expanderButton = "ExpanderButton"; - private const string DATAGRIDROWGROUPHEADER_indentSpacer = "IndentSpacer"; - private const string DATAGRIDROWGROUPHEADER_itemCountElement = "ItemCountElement"; - private const string DATAGRIDROWGROUPHEADER_propertyNameElement = "PropertyNameElement"; + private const string DATAGRIDROWGROUPHEADER_expanderButton = "PART_ExpanderButton"; + private const string DATAGRIDROWGROUPHEADER_indentSpacer = "PART_IndentSpacer"; + private const string DATAGRIDROWGROUPHEADER_itemCountElement = "PART_ItemCountElement"; + private const string DATAGRIDROWGROUPHEADER_propertyNameElement = "PART_PropertyNameElement"; private bool _areIsCheckedHandlersSuspended; private ToggleButton _expanderButton; diff --git a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml index 364a2a52e3..b4bae02b9b 100644 --- a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml +++ b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml @@ -409,9 +409,9 @@ ColumnDefinitions="Auto,Auto,Auto,Auto,*" RowDefinitions="*,Auto"> - - - - diff --git a/src/Avalonia.Controls.DataGrid/Themes/Simple.xaml b/src/Avalonia.Controls.DataGrid/Themes/Simple.xaml index 6a748f399e..b43addff86 100644 --- a/src/Avalonia.Controls.DataGrid/Themes/Simple.xaml +++ b/src/Avalonia.Controls.DataGrid/Themes/Simple.xaml @@ -258,10 +258,10 @@ ColumnDefinitions="Auto,Auto,Auto,Auto" RowDefinitions="Auto,*,Auto"> - - - - diff --git a/src/Avalonia.Controls/Calendar/Calendar.cs b/src/Avalonia.Controls/Calendar/Calendar.cs index bb838a4f3f..0de068a416 100644 --- a/src/Avalonia.Controls/Calendar/Calendar.cs +++ b/src/Avalonia.Controls/Calendar/Calendar.cs @@ -2109,8 +2109,8 @@ namespace Avalonia.Controls RemovedItems = new Collection(); } - private const string PART_ElementRoot = "Root"; - private const string PART_ElementMonth = "CalendarItem"; + private const string PART_ElementRoot = "PART_Root"; + private const string PART_ElementMonth = "PART_CalendarItem"; /// /// Builds the visual tree for the diff --git a/src/Avalonia.Controls/Calendar/CalendarItem.cs b/src/Avalonia.Controls/Calendar/CalendarItem.cs index 75e9f52621..e2eabb5f28 100644 --- a/src/Avalonia.Controls/Calendar/CalendarItem.cs +++ b/src/Avalonia.Controls/Calendar/CalendarItem.cs @@ -32,11 +32,11 @@ namespace Avalonia.Controls.Primitives /// private const int NumberOfDaysPerWeek = 7; - private const string PART_ElementHeaderButton = "HeaderButton"; - private const string PART_ElementPreviousButton = "PreviousButton"; - private const string PART_ElementNextButton = "NextButton"; - private const string PART_ElementMonthView = "MonthView"; - private const string PART_ElementYearView = "YearView"; + private const string PART_ElementHeaderButton = "PART_HeaderButton"; + private const string PART_ElementPreviousButton = "PART_PreviousButton"; + private const string PART_ElementNextButton = "PART_NextButton"; + private const string PART_ElementMonthView = "PART_MonthView"; + private const string PART_ElementYearView = "PART_YearView"; private Button? _headerButton; private Button? _nextButton; diff --git a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs index f2b808fe0d..fb27feb521 100644 --- a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs +++ b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs @@ -14,15 +14,15 @@ namespace Avalonia.Controls /// /// A control to allow the user to select a date /// - [TemplatePart("ButtonContentGrid", typeof(Grid))] - [TemplatePart("DayText", typeof(TextBlock))] - [TemplatePart("FirstSpacer", typeof(Rectangle))] - [TemplatePart("FlyoutButton", typeof(Button))] - [TemplatePart("MonthText", typeof(TextBlock))] - [TemplatePart("PickerPresenter", typeof(DatePickerPresenter))] - [TemplatePart("Popup", typeof(Popup))] - [TemplatePart("SecondSpacer", typeof(Rectangle))] - [TemplatePart("YearText", typeof(TextBlock))] + [TemplatePart("PART_ButtonContentGrid", typeof(Grid))] + [TemplatePart("PART_DayTextBlock", typeof(TextBlock))] + [TemplatePart("PART_FirstSpacer", typeof(Rectangle))] + [TemplatePart("PART_FlyoutButton", typeof(Button))] + [TemplatePart("PART_MonthTextBlock", typeof(TextBlock))] + [TemplatePart("PART_PickerPresenter", typeof(DatePickerPresenter))] + [TemplatePart("PART_Popup", typeof(Popup))] + [TemplatePart("PART_SecondSpacer", typeof(Rectangle))] + [TemplatePart("PART_YearTextBlock", typeof(TextBlock))] [PseudoClasses(":hasnodate")] public class DatePicker : TemplatedControl { @@ -280,15 +280,15 @@ namespace Avalonia.Controls } base.OnApplyTemplate(e); - _flyoutButton = e.NameScope.Find - [TemplatePart("AcceptButton", typeof(Button))] - [TemplatePart("DayDownButton", typeof(RepeatButton))] - [TemplatePart("DayHost", typeof(Panel))] - [TemplatePart("DaySelector", typeof(DateTimePickerPanel))] - [TemplatePart("DayUpButton", typeof(RepeatButton))] - [TemplatePart("DismissButton", typeof(Button))] - [TemplatePart("FirstSpacer", typeof(Rectangle))] - [TemplatePart("MonthDownButton", typeof(RepeatButton))] - [TemplatePart("MonthHost", typeof(Panel))] - [TemplatePart("MonthSelector", typeof(DateTimePickerPanel))] - [TemplatePart("MonthUpButton", typeof(RepeatButton))] - [TemplatePart("PickerContainer", typeof(Grid))] - [TemplatePart("SecondSpacer", typeof(Rectangle))] - [TemplatePart("YearDownButton", typeof(RepeatButton))] - [TemplatePart("YearHost", typeof(Panel))] - [TemplatePart("YearSelector", typeof(DateTimePickerPanel))] - [TemplatePart("YearUpButton", typeof(RepeatButton))] + [TemplatePart("PART_AcceptButton", typeof(Button))] + [TemplatePart("PART_DayDownButton", typeof(RepeatButton))] + [TemplatePart("PART_DayHost", typeof(Panel))] + [TemplatePart("PART_DaySelector", typeof(DateTimePickerPanel))] + [TemplatePart("PART_DayUpButton", typeof(RepeatButton))] + [TemplatePart("PART_DismissButton", typeof(Button))] + [TemplatePart("PART_FirstSpacer", typeof(Rectangle))] + [TemplatePart("PART_MonthDownButton", typeof(RepeatButton))] + [TemplatePart("PART_MonthHost", typeof(Panel))] + [TemplatePart("PART_MonthSelector", typeof(DateTimePickerPanel))] + [TemplatePart("PART_MonthUpButton", typeof(RepeatButton))] + [TemplatePart("PART_PickerContainer", typeof(Grid))] + [TemplatePart("PART_SecondSpacer", typeof(Rectangle))] + [TemplatePart("PART_YearDownButton", typeof(RepeatButton))] + [TemplatePart("PART_YearHost", typeof(Panel))] + [TemplatePart("PART_YearSelector", typeof(DateTimePickerPanel))] + [TemplatePart("PART_YearUpButton", typeof(RepeatButton))] public class DatePickerPresenter : PickerPresenterBase { /// @@ -253,58 +253,58 @@ namespace Avalonia.Controls { base.OnApplyTemplate(e); // These are requirements, so throw if not found - _pickerContainer = e.NameScope.Get("PickerContainer"); - _monthHost = e.NameScope.Get("MonthHost"); - _dayHost = e.NameScope.Get("DayHost"); - _yearHost = e.NameScope.Get("YearHost"); + _pickerContainer = e.NameScope.Get("PART_PickerContainer"); + _monthHost = e.NameScope.Get("PART_MonthHost"); + _dayHost = e.NameScope.Get("PART_DayHost"); + _yearHost = e.NameScope.Get("PART_YearHost"); - _monthSelector = e.NameScope.Get("MonthSelector"); + _monthSelector = e.NameScope.Get("PART_MonthSelector"); _monthSelector.SelectionChanged += OnMonthChanged; - _daySelector = e.NameScope.Get("DaySelector"); + _daySelector = e.NameScope.Get("PART_DaySelector"); _daySelector.SelectionChanged += OnDayChanged; - _yearSelector = e.NameScope.Get("YearSelector"); + _yearSelector = e.NameScope.Get("PART_YearSelector"); _yearSelector.SelectionChanged += OnYearChanged; - _acceptButton = e.NameScope.Get - [TemplatePart("AcceptButton", typeof(Button))] - [TemplatePart("DismissButton", typeof(Button))] - [TemplatePart("HourDownButton", typeof(RepeatButton))] - [TemplatePart("HourSelector", typeof(DateTimePickerPanel))] - [TemplatePart("HourUpButton", typeof(RepeatButton))] - [TemplatePart("MinuteDownButton", typeof(RepeatButton))] - [TemplatePart("MinuteSelector", typeof(DateTimePickerPanel))] - [TemplatePart("MinuteUpButton", typeof(RepeatButton))] - [TemplatePart("PeriodDownButton", typeof(RepeatButton))] - [TemplatePart("PeriodHost", typeof(Panel))] - [TemplatePart("PeriodSelector", typeof(DateTimePickerPanel))] - [TemplatePart("PeriodUpButton", typeof(RepeatButton))] - [TemplatePart("PickerContainer", typeof(Grid))] - [TemplatePart("SecondSpacer", typeof(Rectangle))] + [TemplatePart("PART_AcceptButton", typeof(Button))] + [TemplatePart("PART_DismissButton", typeof(Button))] + [TemplatePart("PART_HourDownButton", typeof(RepeatButton))] + [TemplatePart("PART_HourSelector", typeof(DateTimePickerPanel))] + [TemplatePart("PART_HourUpButton", typeof(RepeatButton))] + [TemplatePart("PART_MinuteDownButton", typeof(RepeatButton))] + [TemplatePart("PART_MinuteSelector", typeof(DateTimePickerPanel))] + [TemplatePart("PART_MinuteUpButton", typeof(RepeatButton))] + [TemplatePart("PART_PeriodDownButton", typeof(RepeatButton))] + [TemplatePart("PART_PeriodHost", typeof(Panel))] + [TemplatePart("PART_PeriodSelector", typeof(DateTimePickerPanel))] + [TemplatePart("PART_PeriodUpButton", typeof(RepeatButton))] + [TemplatePart("PART_PickerContainer", typeof(Grid))] + [TemplatePart("PART_SecondSpacer", typeof(Rectangle))] public class TimePickerPresenter : PickerPresenterBase { /// @@ -122,40 +122,40 @@ namespace Avalonia.Controls { base.OnApplyTemplate(e); - _pickerContainer = e.NameScope.Get("PickerContainer"); - _periodHost = e.NameScope.Get("PeriodHost"); + _pickerContainer = e.NameScope.Get("PART_PickerContainer"); + _periodHost = e.NameScope.Get("PART_PeriodHost"); - _hourSelector = e.NameScope.Get("HourSelector"); - _minuteSelector = e.NameScope.Get("MinuteSelector"); - _periodSelector = e.NameScope.Get("PeriodSelector"); + _hourSelector = e.NameScope.Get("PART_HourSelector"); + _minuteSelector = e.NameScope.Get("PART_MinuteSelector"); + _periodSelector = e.NameScope.Get("PART_PeriodSelector"); - _spacer2 = e.NameScope.Get("SecondSpacer"); + _spacer2 = e.NameScope.Get("PART_SecondSpacer"); - _acceptButton = e.NameScope.Get