diff --git a/src/Avalonia/HandyControlDemo_Avalonia/UserControl/Main/LeftMainContent.axaml b/src/Avalonia/HandyControlDemo_Avalonia/UserControl/Main/LeftMainContent.axaml index 7bbdd25a..58cb4fb2 100644 --- a/src/Avalonia/HandyControlDemo_Avalonia/UserControl/Main/LeftMainContent.axaml +++ b/src/Avalonia/HandyControlDemo_Avalonia/UserControl/Main/LeftMainContent.axaml @@ -14,7 +14,7 @@ BorderThickness="0" Background="{DynamicResource SecondaryRegionBrush}" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Avalonia/HandyControlDemo_Avalonia/UserControl/Styles/NativeTabControlDemo.axaml.cs b/src/Avalonia/HandyControlDemo_Avalonia/UserControl/Styles/NativeTabControlDemo.axaml.cs new file mode 100644 index 00000000..e56f2c5d --- /dev/null +++ b/src/Avalonia/HandyControlDemo_Avalonia/UserControl/Styles/NativeTabControlDemo.axaml.cs @@ -0,0 +1,10 @@ +namespace HandyControlDemo.UserControl; + +public partial class NativeTabControlDemo : Avalonia.Controls.UserControl +{ + public NativeTabControlDemo() + { + InitializeComponent(); + } +} + diff --git a/src/Avalonia/HandyControl_Avalonia/Controls/Attach/ItemsControlAttach.cs b/src/Avalonia/HandyControl_Avalonia/Controls/Attach/ItemsControlAttach.cs new file mode 100644 index 00000000..8ff0229c --- /dev/null +++ b/src/Avalonia/HandyControl_Avalonia/Controls/Attach/ItemsControlAttach.cs @@ -0,0 +1,71 @@ +using Avalonia; +using Avalonia.Controls; +using HandyControl.Tools; + +namespace HandyControl.Controls; + +public class ItemsControlAttach +{ + public static readonly AttachedProperty ItemsContainerThemeSelectorProperty = + AvaloniaProperty.RegisterAttached( + "ItemsContainerThemeSelector"); + + public static void SetItemsContainerThemeSelector(AvaloniaObject element, ThemeSelector? value) => + element.SetValue(ItemsContainerThemeSelectorProperty, value); + + public static ThemeSelector? GetItemsContainerThemeSelector(AvaloniaObject element) => + element.GetValue(ItemsContainerThemeSelectorProperty); + + static ItemsControlAttach() + { + ItemsContainerThemeSelectorProperty.Changed.AddClassHandler( + OnItemsContainerThemeSelectorChanged); + } + + private static void OnItemsContainerThemeSelectorChanged(AvaloniaObject element, AvaloniaPropertyChangedEventArgs e) + { + if (element is not ItemsControl itemsControl) + { + return; + } + + itemsControl.ContainerPrepared -= OnContainerPrepared; + var themeSelector = e.GetNewValue(); + + if (themeSelector is null) + { + return; + } + + itemsControl.ContainerPrepared += OnContainerPrepared; + ApplyTheme(itemsControl, themeSelector); + } + + private static void OnContainerPrepared(object? sender, ContainerPreparedEventArgs e) + { + if (sender is not ItemsControl itemsControl) + { + return; + } + + var themeSelector = GetItemsContainerThemeSelector(itemsControl); + if (themeSelector is null) + { + return; + } + + ApplyTheme(itemsControl, themeSelector); + } + + private static void ApplyTheme(ItemsControl itemsControl, ThemeSelector themeSelector) + { + for (int i = 0; i < itemsControl.ItemCount; i++) + { + var container = itemsControl.ContainerFromIndex(i); + if (container != null) + { + container.Theme = themeSelector.SelectTheme(itemsControl.Items[i], container); + } + } + } +} diff --git a/src/Avalonia/HandyControl_Avalonia/Controls/Attach/TitleElement.cs b/src/Avalonia/HandyControl_Avalonia/Controls/Attach/TitleElement.cs index 50c9ed51..fcf44593 100644 --- a/src/Avalonia/HandyControl_Avalonia/Controls/Attach/TitleElement.cs +++ b/src/Avalonia/HandyControl_Avalonia/Controls/Attach/TitleElement.cs @@ -5,6 +5,14 @@ namespace HandyControl.Controls; public class TitleElement { + public static readonly AttachedProperty BorderBrushProperty = + AvaloniaProperty.RegisterAttached("BorderBrush", inherits: true); + + public static void SetBorderBrush(AvaloniaObject element, IBrush? value) => + element.SetValue(BorderBrushProperty, value); + + public static IBrush? GetBorderBrush(AvaloniaObject element) => element.GetValue(BorderBrushProperty); + public static readonly AttachedProperty BackgroundProperty = AvaloniaProperty.RegisterAttached("Background", inherits: true); diff --git a/src/Avalonia/HandyControl_Avalonia/Themes/Styles/TabControl.axaml b/src/Avalonia/HandyControl_Avalonia/Themes/Styles/TabControl.axaml index 253bfc22..cf180748 100644 --- a/src/Avalonia/HandyControl_Avalonia/Themes/Styles/TabControl.axaml +++ b/src/Avalonia/HandyControl_Avalonia/Themes/Styles/TabControl.axaml @@ -1,6 +1,74 @@  - + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -8,6 +76,8 @@ Value="{DynamicResource RegionBrush}" /> + @@ -46,29 +116,290 @@ Value="Left" /> - - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Avalonia/HandyControl_Avalonia/Themes/Styles/TabItem.axaml b/src/Avalonia/HandyControl_Avalonia/Themes/Styles/TabItem.axaml deleted file mode 100644 index 71ed5a28..00000000 --- a/src/Avalonia/HandyControl_Avalonia/Themes/Styles/TabItem.axaml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Avalonia/HandyControl_Avalonia/Themes/Theme.axaml b/src/Avalonia/HandyControl_Avalonia/Themes/Theme.axaml index 3fc5f496..6d930aa3 100644 --- a/src/Avalonia/HandyControl_Avalonia/Themes/Theme.axaml +++ b/src/Avalonia/HandyControl_Avalonia/Themes/Theme.axaml @@ -26,7 +26,6 @@ - diff --git a/src/Avalonia/HandyControl_Avalonia/Tools/StyleSelector/TabItemCapsuleStyleSelector.cs b/src/Avalonia/HandyControl_Avalonia/Tools/StyleSelector/TabItemCapsuleStyleSelector.cs new file mode 100644 index 00000000..7faa5930 --- /dev/null +++ b/src/Avalonia/HandyControl_Avalonia/Tools/StyleSelector/TabItemCapsuleStyleSelector.cs @@ -0,0 +1,35 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Styling; +using HandyControl.Data; + +namespace HandyControl.Tools; + +public class TabItemCapsuleThemeSelector : ThemeSelector +{ + public override ControlTheme? SelectTheme(object? item, AvaloniaObject? container) + { + if (container is not TabItem { Parent: TabControl tabControl } tabItem) + { + return null; + } + + int count = tabControl.Items.Count; + if (count == 1) + { + return ResourceHelper.GetResource(ResourceToken.TabItemCapsuleSingle); + } + + int index = tabControl.IndexFromContainer(tabItem); + return index == 0 + ? ResourceHelper.GetResource( + tabControl.TabStripPlacement is Dock.Top or Dock.Bottom + ? ResourceToken.TabItemCapsuleHorizontalFirst + : ResourceToken.TabItemCapsuleVerticalFirst) + : ResourceHelper.GetResource(index == count - 1 + ? tabControl.TabStripPlacement is Dock.Top or Dock.Bottom + ? ResourceToken.TabItemCapsuleHorizontalLast + : ResourceToken.TabItemCapsuleVerticalLast + : ResourceToken.TabItemCapsuleDefault); + } +} diff --git a/src/Avalonia/HandyControl_Avalonia/Tools/StyleSelector/ThemeSelector.cs b/src/Avalonia/HandyControl_Avalonia/Tools/StyleSelector/ThemeSelector.cs new file mode 100644 index 00000000..80716646 --- /dev/null +++ b/src/Avalonia/HandyControl_Avalonia/Tools/StyleSelector/ThemeSelector.cs @@ -0,0 +1,9 @@ +using Avalonia; +using Avalonia.Styling; + +namespace HandyControl.Tools; + +public class ThemeSelector +{ + public virtual ControlTheme? SelectTheme(object? item, AvaloniaObject? container) => null; +} diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/TabControl.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/TabControl.xaml index 9a2abccc..a95fe57f 100644 --- a/src/Shared/HandyControl_Shared/Themes/Styles/TabControl.xaml +++ b/src/Shared/HandyControl_Shared/Themes/Styles/TabControl.xaml @@ -189,6 +189,7 @@