Refactor Segmented themes

This commit is contained in:
CHINBOY
2025-06-18 16:25:05 +08:00
parent 13d37100a5
commit b2d226a966
17 changed files with 276 additions and 402 deletions
@@ -31,6 +31,7 @@
<ResourceInclude Source="ProgressBar/Themes/ProgressBarThemes.axaml" />
<ResourceInclude Source="RadioButton/Themes/RadioButtonTheme.axaml" />
<ResourceInclude Source="ScrollBar/Themes/ScrollBarThemes.axaml" />
<ResourceInclude Source="Segmented/Themes/SegmentedThemes.axaml" />
<ResourceInclude Source="PopupConfirm/Themes/PopupConfirmContainerTheme.axaml" />
<ResourceInclude Source="Tag/Themes/TagTheme.axaml" />
<ResourceInclude Source="NumericUpDown/Themes/NumericUpDownTheme.axaml" />
@@ -192,7 +192,7 @@
</Style>
</Style>
<Style Selector="^:not(^:icononly)">
<Style Selector="^:not(:icononly)">
<Style Selector="^ /template/ atom|IconPresenter#PART_ButtonIcon, ^ /template/ atom|Icon#PART_LoadingIcon">
<Setter Property="Margin" Value="{DynamicResource {x:Static atom:ButtonTokenKey.IconMargin}}" />
</Style>
@@ -56,7 +56,7 @@
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorPrimary}}" />
</Style>
<Style Selector="^:selected:not(^:inactive)">
<Style Selector="^:selected:not(:inactive)">
<Setter Property="Background" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorPrimary}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorWhite}}" />
<Setter Property="BorderThickness" Value="0" />
@@ -74,7 +74,7 @@
<Setter Property="SpinnerHandleWidthToken" Value="{DynamicResource {x:Static atom:ButtonSpinnerTokenKey.HandleWidth}}"/>
<Style Selector="^[IsEnabled=True]">
<Style Selector="^:not(^:filled)">
<Style Selector="^:not(:filled)">
<Style Selector="^ /template/ Border#PART_InnerBoxDecorator">
<Setter Property="Background" Value="Transparent"/>
</Style>
@@ -56,7 +56,7 @@
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorPrimary}}" />
</Style>
<Style Selector="^:selected:not(^:inactive)">
<Style Selector="^:selected:not(:inactive)">
<Setter Property="Background" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorPrimary}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorWhite}}" />
<Setter Property="BorderThickness" Value="0" />
@@ -57,7 +57,7 @@
<Setter Property="BorderBrush" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorPrimary}}" />
</Style>
<Style Selector="^:selected:not(^:inactive)">
<Style Selector="^:selected:not(:inactive)">
<Setter Property="Background" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorPrimary}}" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorWhite}}" />
<Setter Property="BorderThickness" Value="0" />
@@ -15,8 +15,6 @@ namespace AtomUI.Theme
themes.Add(new AtomUI.Controls.CardTabStripItemTheme());
themes.Add(new AtomUI.Controls.CardTabStripTheme());
themes.Add(new AtomUI.Controls.HyperLinkTextBlockTheme());
themes.Add(new AtomUI.Controls.SegmentedItemTheme());
themes.Add(new AtomUI.Controls.SegmentedTheme());
themes.Add(new AtomUI.Controls.SeparatorTheme());
themes.Add(new AtomUI.Controls.SliderTheme());
themes.Add(new AtomUI.Controls.SliderThumbTheme());
+18 -21
View File
@@ -1,8 +1,7 @@
using System.Reactive.Disposables;
using AtomUI.Controls.Themes;
using AtomUI.Controls.Utils;
using AtomUI.Data;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using Avalonia;
using Avalonia.Animation;
@@ -11,13 +10,12 @@ using Avalonia.Controls.Metadata;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.VisualTree;
namespace AtomUI.Controls;
[TemplatePart(SegmentedTheme.ItemsPresenterPart, typeof(ItemsPresenter))]
[TemplatePart(SegmentedThemeConstants.ItemsPresenterPart, typeof(ItemsPresenter))]
public class Segmented : SelectingItemsControl,
IMotionAwareControl,
IControlSharedTokenResourcesHost
@@ -112,9 +110,12 @@ public class Segmented : SelectingItemsControl,
static Segmented()
{
AffectsMeasure<Segmented>(IsExpandingProperty, SizeTypeProperty);
AffectsRender<Segmented>(SelectedThumbCornerRadiusProperty, SelectedThumbBgProperty,
AffectsRender<Segmented>(
SelectedThumbCornerRadiusProperty,
SelectedThumbBgProperty,
SelectedThumbBoxShadowsProperty,
SelectedThumbSizeProperty, SelectedThumbPosProperty);
SelectedThumbSizeProperty,
SelectedThumbPosProperty);
}
public Segmented()
@@ -151,9 +152,18 @@ public class Segmented : SelectingItemsControl,
SetupSelectedThumbRect();
}
private void HandleSelectionChanged(object? sender, SelectionChangedEventArgs args)
{
if (this.IsAttachedToVisualTree())
{
SetupSelectedThumbRect();
}
}
protected override void OnSizeChanged(SizeChangedEventArgs e)
{
base.OnSizeChanged(e);
SetupSelectedThumbRect();
}
@@ -194,18 +204,6 @@ public class Segmented : SelectingItemsControl,
}
}
protected override Size ArrangeOverride(Size finalSize)
{
base.ArrangeOverride(finalSize);
if (Transitions is null)
{
SetupSelectedThumbRect();
ConfigureTransitions();
}
return finalSize;
}
private void ConfigureTransitions()
{
if (IsMotionEnabled)
@@ -213,8 +211,7 @@ public class Segmented : SelectingItemsControl,
Transitions = new Transitions
{
TransitionUtils.CreateTransition<PointTransition>(SelectedThumbPosProperty),
TransitionUtils.CreateTransition<SizeTransition>(SelectedThumbSizeProperty,
SharedTokenKey.MotionDurationFast)
TransitionUtils.CreateTransition<SizeTransition>(SelectedThumbSizeProperty)
};
}
else
+13 -31
View File
@@ -1,10 +1,7 @@
using System.Diagnostics;
using System.Reactive.Disposables;
using AtomUI.Animations;
using AtomUI.Controls.Utils;
using AtomUI.IconPkg;
using AtomUI.Reflection;
using AtomUI.Theme;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
@@ -17,10 +14,8 @@ using Avalonia.VisualTree;
namespace AtomUI.Controls;
[PseudoClasses(StdPseudoClass.Pressed, StdPseudoClass.Selected)]
public class SegmentedItem : ContentControl,
ISelectable,
IResourceBindingManager
[PseudoClasses(StdPseudoClass.Pressed, StdPseudoClass.Selected, SegmentedPseudoClass.HasIcon)]
public class SegmentedItem : ContentControl, ISelectable
{
#region 公共属性定义
@@ -64,11 +59,7 @@ public class SegmentedItem : ContentControl,
set => SetValue(IsMotionEnabledProperty, value);
}
CompositeDisposable? IResourceBindingManager.ResourceBindingsDisposable => _resourceBindingsDisposable;
#endregion
private CompositeDisposable? _resourceBindingsDisposable;
static SegmentedItem()
{
@@ -81,16 +72,9 @@ public class SegmentedItem : ContentControl,
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
_resourceBindingsDisposable = new CompositeDisposable();
Debug.Assert(Parent is Segmented, "SegmentedItem's Parent must be Segmented Control.");
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnDetachedFromLogicalTree(e);
this.DisposeTokenBindings();
}
protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
base.OnPointerReleased(e);
@@ -114,12 +98,18 @@ public class SegmentedItem : ContentControl,
{
base.OnApplyTemplate(e);
ConfigureTransitions();
UpdatePseudoClasses();
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == IconProperty)
{
UpdatePseudoClasses();
}
if (this.IsAttachedToVisualTree())
{
if (change.Property == IsMotionEnabledProperty)
@@ -127,19 +117,6 @@ public class SegmentedItem : ContentControl,
ConfigureTransitions();
}
}
if (change.Property == IconProperty)
{
if (change.OldValue is Icon oldIcon)
{
oldIcon.SetTemplatedParent(null);
}
if (change.NewValue is Icon newIcon)
{
newIcon.SetTemplatedParent(this);
}
}
}
private void ConfigureTransitions()
@@ -156,4 +133,9 @@ public class SegmentedItem : ContentControl,
Transitions = null;
}
}
private void UpdatePseudoClasses()
{
PseudoClasses.Set(SegmentedPseudoClass.HasIcon, Icon is not null);
}
}
@@ -1,246 +0,0 @@
using AtomUI.IconPkg;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Styling;
namespace AtomUI.Controls;
[ControlThemeProvider]
internal class SegmentedItemTheme : BaseControlTheme
{
public const string MainFramePart = "PART_MainFrame";
public const string IconContentPart = "PART_IconContent";
public const string ContentPart = "PART_Content";
public SegmentedItemTheme() : base(typeof(SegmentedItem))
{
}
protected override IControlTemplate BuildControlTemplate()
{
return new FuncControlTemplate<SegmentedItem>((segmentedItem, scope) =>
{
var mainFrame = new Border
{
Name = MainFramePart
};
CreateTemplateParentBinding(mainFrame, Border.BackgroundProperty, TemplatedControl.BackgroundProperty);
CreateTemplateParentBinding(mainFrame, Border.CornerRadiusProperty, TemplatedControl.CornerRadiusProperty);
CreateTemplateParentBinding(mainFrame, Decorator.PaddingProperty, TemplatedControl.PaddingProperty);
var contentLayout = new DockPanel
{
LastChildFill = true
};
var iconContent = new ContentPresenter
{
Name = IconContentPart
};
iconContent.RegisterInNameScope(scope);
CreateTemplateParentBinding(iconContent, ContentPresenter.ContentProperty, SegmentedItem.IconProperty);
CreateTemplateParentBinding(iconContent, Visual.IsVisibleProperty, SegmentedItem.IconProperty,
BindingMode.Default,
ObjectConverters.IsNotNull);
contentLayout.Children.Add(iconContent);
var contentPresenter = new ContentPresenter
{
Name = ContentPart,
HorizontalContentAlignment = HorizontalAlignment.Center,
VerticalContentAlignment = VerticalAlignment.Center
};
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty,
ContentControl.ContentProperty,
BindingMode.Default,
new FuncValueConverter<object?, object?>(content =>
{
if (content is string text)
{
return new TextBlock()
{
Text = text,
VerticalAlignment = VerticalAlignment.Center,
};
}
return content;
}));
CreateTemplateParentBinding(contentPresenter, Visual.IsVisibleProperty, ContentControl.ContentProperty,
BindingMode.Default,
ObjectConverters.IsNotNull);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentTemplateProperty,
ContentControl.ContentTemplateProperty);
contentLayout.Children.Add(contentPresenter);
mainFrame.Child = contentLayout;
return mainFrame;
});
}
protected override void BuildStyles()
{
var commonStyle = new Style(selector => selector.Nesting());
// 没有被选择的正常状态
var enabledStyle =
new Style(selector => selector.Nesting().PropertyEquals(InputElement.IsEnabledProperty, true));
enabledStyle.Add(InputElement.CursorProperty, new SetterValueFactory<Cursor>(() => new Cursor(StandardCursorType.Hand)));
{
var iconStyle = new Style(selector => selector.Nesting().Template().Name(IconContentPart).Child().OfType<Icon>());
iconStyle.Add(Icon.IconModeProperty, IconMode.Normal);
Add(iconStyle);
}
// 选中状态
var selectedStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Selected));
selectedStyle.Add(TemplatedControl.ForegroundProperty, SegmentedTokenKey.ItemSelectedColor);
selectedStyle.Add(TemplatedControl.BackgroundProperty, SegmentedTokenKey.ItemSelectedBg);
{
var iconStyle = new Style(selector => selector.Nesting().Template().Name(IconContentPart).Child().OfType<Icon>());
iconStyle.Add(Icon.IconModeProperty, IconMode.Selected);
selectedStyle.Add(iconStyle);
}
enabledStyle.Add(selectedStyle);
// 没有被选中的状态
var notSelectedStyle =
new Style(selector => selector.Nesting().Not(x => x.Nesting().Class(StdPseudoClass.Selected)));
notSelectedStyle.Add(TemplatedControl.BackgroundProperty, SharedTokenKey.ColorTransparent);
notSelectedStyle.Add(TemplatedControl.ForegroundProperty, SegmentedTokenKey.ItemColor);
// Hover 状态
var hoverStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.PointerOver));
hoverStyle.Add(TemplatedControl.BackgroundProperty, SegmentedTokenKey.ItemHoverBg);
hoverStyle.Add(TemplatedControl.ForegroundProperty, SegmentedTokenKey.ItemHoverColor);
{
var iconStyle = new Style(selector => selector.Nesting().Template().Name(IconContentPart).Child().OfType<Icon>());
iconStyle.Add(Icon.IconModeProperty, IconMode.Active);
hoverStyle.Add(iconStyle);
}
notSelectedStyle.Add(hoverStyle);
// Pressed 状态
var pressedStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Pressed));
pressedStyle.Add(TemplatedControl.BackgroundProperty, SegmentedTokenKey.ItemActiveBg);
notSelectedStyle.Add(pressedStyle);
{
var iconStyle = new Style(selector => selector.Nesting().Template().Name(IconContentPart).Child().OfType<Icon>());
iconStyle.Add(Icon.IconModeProperty, IconMode.Selected);
pressedStyle.Add(iconStyle);
}
enabledStyle.Add(notSelectedStyle);
commonStyle.Add(enabledStyle);
Add(commonStyle);
BuildSizeTypeStyle();
BuildIconStyle();
BuildDisabledStyle();
}
private void BuildSizeTypeStyle()
{
var largeSizeStyle =
new Style(selector => selector.Nesting().PropertyEquals(SegmentedItem.SizeTypeProperty, SizeType.Large));
largeSizeStyle.Add(TemplatedControl.CornerRadiusProperty, SharedTokenKey.BorderRadius);
largeSizeStyle.Add(TemplatedControl.FontSizeProperty, SharedTokenKey.FontSizeLG);
largeSizeStyle.Add(Layoutable.MinHeightProperty, SegmentedTokenKey.ItemMinHeightLG);
largeSizeStyle.Add(TemplatedControl.PaddingProperty, SegmentedTokenKey.SegmentedItemPadding);
Add(largeSizeStyle);
var middleSizeStyle =
new Style(selector => selector.Nesting().PropertyEquals(SegmentedItem.SizeTypeProperty, SizeType.Middle));
middleSizeStyle.Add(TemplatedControl.CornerRadiusProperty, SharedTokenKey.BorderRadiusSM);
middleSizeStyle.Add(TemplatedControl.FontSizeProperty, SharedTokenKey.FontSize);
middleSizeStyle.Add(Layoutable.MinHeightProperty, SegmentedTokenKey.ItemMinHeight);
middleSizeStyle.Add(TemplatedControl.PaddingProperty, SegmentedTokenKey.SegmentedItemPadding);
Add(middleSizeStyle);
var smallSizeStyle =
new Style(selector => selector.Nesting().PropertyEquals(SegmentedItem.SizeTypeProperty, SizeType.Small));
smallSizeStyle.Add(TemplatedControl.CornerRadiusProperty, SharedTokenKey.BorderRadiusXS);
smallSizeStyle.Add(TemplatedControl.FontSizeProperty, SharedTokenKey.FontSize);
smallSizeStyle.Add(Layoutable.MinHeightProperty, SegmentedTokenKey.ItemMinHeightSM);
smallSizeStyle.Add(TemplatedControl.PaddingProperty, SegmentedTokenKey.SegmentedItemPaddingSM);
Add(smallSizeStyle);
}
private void BuildIconStyle()
{
var hasIconStyle =
new Style(selector => selector.Nesting()
.Not(x => x.Nesting().PropertyEquals(SegmentedItem.IconProperty, null)));
{
var labelStyle = new Style(selector => selector.Nesting().Template().Name(ContentPart));
labelStyle.Add(Layoutable.MarginProperty, SegmentedTokenKey.SegmentedItemContentMargin);
hasIconStyle.Add(labelStyle);
}
Add(hasIconStyle);
{
var iconStyle = new Style(selector => selector.Nesting().Template().Name(IconContentPart).Child().OfType<Icon>());
iconStyle.Add(Icon.NormalFilledBrushProperty, SegmentedTokenKey.ItemColor);
iconStyle.Add(Icon.ActiveFilledBrushProperty, SegmentedTokenKey.ItemHoverColor);
iconStyle.Add(Icon.SelectedFilledBrushProperty, SegmentedTokenKey.ItemSelectedColor);
iconStyle.Add(Icon.DisabledFilledBrushProperty, SharedTokenKey.ColorTextDisabled);
Add(iconStyle);
}
var largeSizeStyle =
new Style(selector => selector.Nesting().PropertyEquals(SegmentedItem.SizeTypeProperty, SizeType.Large));
{
var iconStyle = new Style(selector => selector.Nesting().Template().Name(IconContentPart).Child().OfType<Icon>());
iconStyle.Add(Layoutable.WidthProperty, SharedTokenKey.IconSizeLG);
iconStyle.Add(Layoutable.HeightProperty, SharedTokenKey.IconSizeLG);
largeSizeStyle.Add(iconStyle);
}
Add(largeSizeStyle);
var middleSizeStyle =
new Style(selector => selector.Nesting().PropertyEquals(SegmentedItem.SizeTypeProperty, SizeType.Middle));
{
var iconStyle = new Style(selector => selector.Nesting().Template().Name(IconContentPart).Child().OfType<Icon>());
iconStyle.Add(Layoutable.WidthProperty, SharedTokenKey.IconSize);
iconStyle.Add(Layoutable.HeightProperty, SharedTokenKey.IconSize);
middleSizeStyle.Add(iconStyle);
}
Add(middleSizeStyle);
var smallSizeStyle =
new Style(selector => selector.Nesting().PropertyEquals(SegmentedItem.SizeTypeProperty, SizeType.Small));
{
var iconStyle = new Style(selector => selector.Nesting().Template().Name(IconContentPart).Child().OfType<Icon>());
iconStyle.Add(Layoutable.WidthProperty, SharedTokenKey.IconSizeSM);
iconStyle.Add(Layoutable.HeightProperty, SharedTokenKey.IconSizeSM);
smallSizeStyle.Add(iconStyle);
}
Add(smallSizeStyle);
}
private void BuildDisabledStyle()
{
var disabledStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Disabled));
disabledStyle.Add(TemplatedControl.ForegroundProperty, SharedTokenKey.ColorTextDisabled);
{
var iconStyle = new Style(selector => selector.Nesting().Template().Name(IconContentPart).Child().OfType<Icon>());
iconStyle.Add(Icon.IconModeProperty, IconMode.Disabled);
disabledStyle.Add(iconStyle);
}
Add(disabledStyle);
}
}
@@ -0,0 +1,6 @@
namespace AtomUI.Controls;
public static class SegmentedPseudoClass
{
public const string HasIcon = ":has-icon";
}
@@ -1,90 +0,0 @@
using AtomUI.Data;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Layout;
using Avalonia.Styling;
namespace AtomUI.Controls;
[ControlThemeProvider]
internal class SegmentedTheme : BaseControlTheme
{
public const string FramePart = "PART_Frame";
public const string ItemsPresenterPart = "PART_ItemsPresenter";
public SegmentedTheme() : base(typeof(Segmented))
{
}
protected override IControlTemplate BuildControlTemplate()
{
return new FuncControlTemplate<Segmented>((segmented, scope) =>
{
var frame = new Border
{
Name = FramePart,
ClipToBounds = true
};
var itemsPresenter = new ItemsPresenter
{
Name = ItemsPresenterPart,
ItemsPanel = new FuncTemplate<Panel?>(() =>
{
var panel = new SegmentedStackPanel();
BindUtils.RelayBind(segmented, Segmented.IsExpandingProperty, panel,
SegmentedStackPanel.IsExpandingProperty);
return panel;
})
};
itemsPresenter.RegisterInNameScope(scope);
frame.Child = itemsPresenter;
CreateTemplateParentBinding(frame, Border.CornerRadiusProperty,
TemplatedControl.CornerRadiusProperty);
CreateTemplateParentBinding(frame, Decorator.PaddingProperty, TemplatedControl.PaddingProperty);
return frame;
});
}
protected override void BuildStyles()
{
var commonStyle = new Style(selector => selector.Nesting());
commonStyle.Add(TemplatedControl.PaddingProperty, SegmentedTokenKey.TrackPadding);
commonStyle.Add(TemplatedControl.BackgroundProperty, SegmentedTokenKey.TrackBg);
commonStyle.Add(Layoutable.HorizontalAlignmentProperty, HorizontalAlignment.Left);
commonStyle.Add(Segmented.SelectedThumbBgProperty, SegmentedTokenKey.ItemSelectedBg);
commonStyle.Add(Segmented.SelectedThumbBoxShadowsProperty, SharedTokenKey.BoxShadowsTertiary);
var expandingStyle =
new Style(selector => selector.Nesting().PropertyEquals(Segmented.IsExpandingProperty, true));
expandingStyle.Add(Layoutable.HorizontalAlignmentProperty, HorizontalAlignment.Stretch);
commonStyle.Add(expandingStyle);
Add(commonStyle);
BuildSizeTypeStyle();
}
private void BuildSizeTypeStyle()
{
var largeSizeTypeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(Segmented.SizeTypeProperty, SizeType.Large));
largeSizeTypeStyle.Add(TemplatedControl.CornerRadiusProperty, SharedTokenKey.BorderRadiusLG);
largeSizeTypeStyle.Add(Segmented.SelectedThumbCornerRadiusProperty, SharedTokenKey.BorderRadius);
Add(largeSizeTypeStyle);
var middleSizeTypeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(Segmented.SizeTypeProperty, SizeType.Middle));
middleSizeTypeStyle.Add(TemplatedControl.CornerRadiusProperty, SharedTokenKey.BorderRadius);
middleSizeTypeStyle.Add(Segmented.SelectedThumbCornerRadiusProperty, SharedTokenKey.BorderRadiusSM);
Add(middleSizeTypeStyle);
var smallSizeTypeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(Segmented.SizeTypeProperty, SizeType.Small));
smallSizeTypeStyle.Add(TemplatedControl.CornerRadiusProperty, SharedTokenKey.BorderRadiusSM);
smallSizeTypeStyle.Add(Segmented.SelectedThumbCornerRadiusProperty, SharedTokenKey.BorderRadiusXS);
Add(smallSizeTypeStyle);
}
}
@@ -0,0 +1,158 @@
<ResourceDictionary
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atom="https://atomui.net">
<atom:StringToTextBlockConverter x:Key="StringToTextBlockConverter" VerticalAlignment="Center" />
<ControlTheme x:Key="{x:Type atom:SegmentedItem}" TargetType="atom:SegmentedItem">
<Setter Property="Template">
<ControlTemplate>
<Border Name="{x:Static atom:SegmentedItemThemeConstants.MainFramePart}"
Background="{TemplateBinding Background}"
CornerRadius="{TemplateBinding CornerRadius}"
Padding="{TemplateBinding Padding}">
<DockPanel LastChildFill="True">
<atom:IconPresenter Name="{x:Static atom:SegmentedItemThemeConstants.IconPresenterPart}"
Icon="{TemplateBinding Icon}"
IsVisible="{TemplateBinding Icon, Converter={x:Static ObjectConverters.IsNotNull}}" />
<ContentPresenter Name="{x:Static atom:SegmentedItemThemeConstants.ContentPart}"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Content="{TemplateBinding Content, Converter={StaticResource StringToTextBlockConverter}}"
IsVisible="{TemplateBinding Content, Converter={x:Static ObjectConverters.IsNotNull}}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
</DockPanel>
</Border>
</ControlTemplate>
</Setter>
<Style Selector="^[IsEnabled=True]">
<Setter Property="Cursor" Value="Hand" />
<Style Selector="^ /template/ atom|IconPresenter#PART_IconPresenter">
<Setter Property="IconMode" Value="Normal" />
</Style>
<Style Selector="^:selected">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemSelectedColor}}" />
<Setter Property="Background"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemSelectedBg}}" />
<Style Selector="^ /template/ atom|IconPresenter#PART_IconPresenter">
<Setter Property="IconMode" Value="Selected" />
</Style>
</Style>
<Style Selector="^:not(^:selected)">
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemColor}}" />
<Setter Property="Background" Value="Transparent" />
<Style Selector="^:pointerover">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemHoverColor}}" />
<Setter Property="Background"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemHoverBg}}" />
<Style Selector="^ /template/ atom|IconPresenter#PART_IconPresenter">
<Setter Property="IconMode" Value="Active" />
</Style>
</Style>
<Style Selector="^:pressed">
<Setter Property="Background"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemActiveBg}}" />
<Style Selector="^ /template/ atom|IconPresenter#PART_IconPresenter">
<Setter Property="IconMode" Value="Selected" />
</Style>
</Style>
</Style>
</Style>
<Style Selector="^[SizeType=Large]">
<Setter Property="CornerRadius"
Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadius}}" />
<Setter Property="FontSize"
Value="{DynamicResource {x:Static atom:SharedTokenKey.FontSizeLG}}" />
<Setter Property="MinHeight"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemMinHeightLG}}" />
<Setter Property="Padding"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.SegmentedItemPadding}}" />
</Style>
<Style Selector="^[SizeType=Middle]">
<Setter Property="CornerRadius"
Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadiusSM}}" />
<Setter Property="FontSize"
Value="{DynamicResource {x:Static atom:SharedTokenKey.FontSize}}" />
<Setter Property="MinHeight"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemMinHeight}}" />
<Setter Property="Padding"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.SegmentedItemPadding}}" />
</Style>
<Style Selector="^[SizeType=Small]">
<Setter Property="CornerRadius"
Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadiusXS}}" />
<Setter Property="FontSize"
Value="{DynamicResource {x:Static atom:SharedTokenKey.FontSize}}" />
<Setter Property="MinHeight"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemMinHeightSM}}" />
<Setter Property="Padding"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.SegmentedItemPaddingSM}}" />
</Style>
<!-- BuildIconStyle begin -->
<Style Selector="^:has-icon">
<Style Selector="^ /template/ ContentPresenter#PART_Content">
<Setter Property="Margin"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.SegmentedItemContentMargin}}" />
</Style>
</Style>
<Style Selector="^ /template/ atom|IconPresenter#PART_IconPresenter">
<Setter Property="NormalFilledBrush"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemColor}}" />
<Setter Property="ActiveFilledBrush"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemHoverColor}}" />
<Setter Property="SelectedFilledBrush"
Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemSelectedColor}}" />
<Setter Property="DisabledFilledBrush"
Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextDisabled}}" />
</Style>
<Style Selector="^[SizeType=Large]">
<Style Selector="^ /template/ atom|IconPresenter#PART_IconPresenter">
<Setter Property="IconWidth"
Value="{DynamicResource {x:Static atom:SharedTokenKey.IconSizeLG}}" />
<Setter Property="IconHeight"
Value="{DynamicResource {x:Static atom:SharedTokenKey.IconSizeLG}}" />
</Style>
</Style>
<Style Selector="^[SizeType=Middle]">
<Style Selector="^ /template/ atom|IconPresenter#PART_IconPresenter">
<Setter Property="IconWidth"
Value="{DynamicResource {x:Static atom:SharedTokenKey.IconSize}}" />
<Setter Property="IconHeight"
Value="{DynamicResource {x:Static atom:SharedTokenKey.IconSize}}" />
</Style>
</Style>
<Style Selector="^[SizeType=Small]">
<Style Selector="^ /template/ atom|IconPresenter#PART_IconPresenter">
<Setter Property="IconWidth"
Value="{DynamicResource {x:Static atom:SharedTokenKey.IconSizeSM}}" />
<Setter Property="IconHeight"
Value="{DynamicResource {x:Static atom:SharedTokenKey.IconSizeSM}}" />
</Style>
</Style>
<!-- BuildIconStyle end -->
<Style Selector="^:disabled">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextDisabled}}" />
<Style Selector="^ /template/ atom|IconPresenter#PART_IconPresenter">
<Setter Property="IconMode" Value="Disabled"/>
</Style>
</Style>
</ControlTheme>
</ResourceDictionary>
@@ -0,0 +1,48 @@
<ResourceDictionary
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atom="https://atomui.net">
<ControlTheme x:Key="{x:Type atom:Segmented}" TargetType="atom:Segmented">
<Setter Property="Template">
<ControlTemplate>
<Border Name="{x:Static atom:SegmentedThemeConstants.FramePart}"
CornerRadius="{TemplateBinding CornerRadius}"
Padding="{TemplateBinding Padding}"
ClipToBounds="True">
<ItemsPresenter Name="{x:Static atom:SegmentedThemeConstants.ItemsPresenterPart}">
<ItemsPresenter.ItemsPanel>
<ItemsPanelTemplate>
<atom:SegmentedStackPanel IsExpanding="{Binding IsExpanding, RelativeSource={RelativeSource AncestorType=atom:Segmented}}"/>
</ItemsPanelTemplate>
</ItemsPresenter.ItemsPanel>
</ItemsPresenter>
</Border>
</ControlTemplate>
</Setter>
<Setter Property="Padding" Value="{DynamicResource {x:Static atom:SegmentedTokenKey.TrackPadding}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static atom:SegmentedTokenKey.TrackBg}}" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="SelectedThumbBg" Value="{DynamicResource {x:Static atom:SegmentedTokenKey.ItemSelectedBg}}" />
<Setter Property="SelectedThumbBoxShadows" Value="{DynamicResource {x:Static atom:SharedTokenKey.BoxShadowsTertiary}}" />
<Style Selector="^[IsExpanding=True]">
<Setter Property="HorizontalAlignment" Value="Stretch" />
</Style>
<Style Selector="^[SizeType=Large]">
<Setter Property="CornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadiusLG}}" />
<Setter Property="SelectedThumbCornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadius}}" />
</Style>
<Style Selector="^[SizeType=Middle]">
<Setter Property="CornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadius}}" />
<Setter Property="SelectedThumbCornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadiusSM}}" />
</Style>
<Style Selector="^[SizeType=Small]">
<Setter Property="CornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadiusSM}}" />
<Setter Property="SelectedThumbCornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadiusXS}}" />
</Style>
</ControlTheme>
</ResourceDictionary>
@@ -0,0 +1,14 @@
namespace AtomUI.Controls.Themes;
internal static class SegmentedItemThemeConstants
{
public const string MainFramePart = "PART_MainFrame";
public const string IconPresenterPart = "PART_IconPresenter";
public const string ContentPart = "PART_Content";
}
internal static class SegmentedThemeConstants
{
public const string FramePart = "PART_Frame";
public const string ItemsPresenterPart = "PART_ItemsPresenter";
}
@@ -0,0 +1,7 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceInclude Source="SegmentedTheme.axaml"/>
<ResourceInclude Source="SegmentedItemTheme.axaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
+6 -7
View File
@@ -2,7 +2,6 @@ using AtomUI.Data;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Data;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Metadata;
@@ -185,25 +184,25 @@ public class IconPresenter : Control
private void ConfigureIcon(Icon icon)
{
SetValue(LoadingAnimationProperty, icon.LoadingAnimation, BindingPriority.Template);
SetValue(LoadingAnimationDurationProperty, icon.LoadingAnimationDuration, BindingPriority.Template);
SetCurrentValue(LoadingAnimationProperty, icon.LoadingAnimation);
SetCurrentValue(LoadingAnimationDurationProperty, icon.LoadingAnimationDuration);
if (icon.ThemeType != IconThemeType.TwoTone)
{
if (icon.NormalFilledBrush != null)
{
SetValue(NormalFilledBrushProperty, icon.NormalFilledBrush, BindingPriority.Template);
SetCurrentValue(NormalFilledBrushProperty, icon.NormalFilledBrush);
}
if (icon.ActiveFilledBrush != null)
{
SetValue(ActiveFilledBrushProperty, icon.ActiveFilledBrush, BindingPriority.Template);
SetCurrentValue(ActiveFilledBrushProperty, icon.ActiveFilledBrush);
}
if (icon.SecondaryFilledBrush != null)
{
SetValue(SelectedFilledBrushProperty, icon.SecondaryFilledBrush, BindingPriority.Template);
SetCurrentValue(SelectedFilledBrushProperty, icon.SecondaryFilledBrush);
}
if (icon.SecondaryFilledBrush != null)
{
SetValue(DisabledFilledBrushProperty, icon.DisabledFilledBrush, BindingPriority.Template);
SetCurrentValue(DisabledFilledBrushProperty, icon.DisabledFilledBrush);
}
}