mirror of
https://gitee.com/chinware/atomui.git
synced 2024-11-29 18:38:16 +08:00
完成基础的 Collapse 功能
This commit is contained in:
parent
eb6ad5549b
commit
86f692cdab
@ -1,37 +1,31 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia" Version="$(AvaloniaVersionThatLibrariesUsed)"/>
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="$(AvaloniaVersionThatLibrariesUsed)"/>
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="$(AvaloniaVersionThatLibrariesUsed)"/>
|
||||
<PackageVersion Include="Avalonia.Controls.ColorPicker" Version="$(AvaloniaVersionThatLibrariesUsed)"/>
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="$(AvaloniaVersionThatLibrariesUsed)"/>
|
||||
<PackageVersion Include="Avalonia.Svg" Version="$(AvaloniaVersionThatLibrariesUsed)"/>
|
||||
<PackageVersion Include="Avalonia.Controls.TreeDataGrid" Version="11.0.10"/>
|
||||
<PackageVersion Include="Avalonia.Themes.Fluent" Version="$(AvaloniaVersionThatLibrariesUsed)"/>
|
||||
<PackageVersion Include="Avalonia.Win32" Version="$(AvaloniaVersionThatLibrariesUsed)"/>
|
||||
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.1" />
|
||||
|
||||
<!-- 测试相关依赖 -->
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.10.0-release-24177-07" />
|
||||
<PackageVersion Include="NSubstitute" Version="5.1.0" />
|
||||
<PackageVersion Include="Shouldly" Version="4.2.1" />
|
||||
<PackageVersion Include="xunit" Version="2.8.0" />
|
||||
<PackageVersion Include="xunit.extensibility.execution" Version="2.8.0" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.0" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.1.0" />
|
||||
|
||||
<!-- 开发支持 -->
|
||||
<PackageVersion Include="Nlnet.Avalonia.DevTools" Version="1.0.1-beta.23" />
|
||||
|
||||
<!-- 源码生成 -->
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0-3.final" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0-beta1.24219.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(MSBuildThisFileDirectory)\Build\Common.props" />
|
||||
<PropertyGroup>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia" Version="$(AvaloniaVersionThatLibrariesUsed)" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="$(AvaloniaVersionThatLibrariesUsed)" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="$(AvaloniaVersionThatLibrariesUsed)" />
|
||||
<PackageVersion Include="Avalonia.Controls.ColorPicker" Version="$(AvaloniaVersionThatLibrariesUsed)" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="$(AvaloniaVersionThatLibrariesUsed)" />
|
||||
<PackageVersion Include="Avalonia.Svg" Version="11.1.0" />
|
||||
<PackageVersion Include="Avalonia.Controls.TreeDataGrid" Version="11.0.10" />
|
||||
<PackageVersion Include="Avalonia.Themes.Fluent" Version="$(AvaloniaVersionThatLibrariesUsed)" />
|
||||
<PackageVersion Include="Avalonia.Win32" Version="$(AvaloniaVersionThatLibrariesUsed)" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.1" />
|
||||
<!-- 测试相关依赖 -->
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.10.0-release-24177-07" />
|
||||
<PackageVersion Include="NSubstitute" Version="5.1.0" />
|
||||
<PackageVersion Include="Shouldly" Version="4.2.1" />
|
||||
<PackageVersion Include="xunit" Version="2.8.0" />
|
||||
<PackageVersion Include="xunit.extensibility.execution" Version="2.8.0" />
|
||||
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.0" />
|
||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.1.0" />
|
||||
<!-- 开发支持 -->
|
||||
<PackageVersion Include="Nlnet.Avalonia.DevTools" Version="1.0.1-beta.23" />
|
||||
<!-- 源码生成 -->
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0-3.final" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0-beta1.24219.2" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,9 +1,8 @@
|
||||
<p align="center">
|
||||
<img src="./docs/images/ATOMUI.png" />
|
||||
</p>
|
||||
<p align="center">
|
||||
<h4>基于 Ant Design 5.0 和 Avalonia 技术的企业级跨平台控件库</h4>
|
||||
</p>
|
||||
|
||||
<div align="center" style = "font-weight: bold">基于 Ant Design 5.0 和 Avalonia 技术的企业级跨平台控件库</div>
|
||||
|
||||
#### 介绍
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
<NoWarn>$(NoWarn);CS7035</NoWarn>
|
||||
|
||||
<AvaloniaVersionThatLibrariesUsed>11.1.0</AvaloniaVersionThatLibrariesUsed>
|
||||
<AvaloniaVersionThatSampleUsed>11.1.0</AvaloniaVersionThatSampleUsed>
|
||||
<AvaloniaVersionThatLibrariesUsed>11.1.2</AvaloniaVersionThatLibrariesUsed>
|
||||
<AvaloniaVersionThatSampleUsed>11.1.2</AvaloniaVersionThatSampleUsed>
|
||||
<LibVersion>0.0.1</LibVersion>
|
||||
<NugetPackageVersion>$(LibVersion)-local.1</NugetPackageVersion>
|
||||
<NugetPackageVersion>$(LibVersion)-preview.1</NugetPackageVersion>
|
||||
|
@ -1,6 +1,5 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(MSBuildThisFileDirectory)..\..\Build\Common.props" />
|
||||
|
||||
<Import Project="$(MSBuildThisFileDirectory)..\..\Build\Output.App.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
|
33
samples/AtomUI.Demo.Desktop/ShowCase/CollapseShowCase.axaml
Normal file
33
samples/AtomUI.Demo.Desktop/ShowCase/CollapseShowCase.axaml
Normal file
@ -0,0 +1,33 @@
|
||||
<UserControl
|
||||
x:Class="AtomUI.Demo.Desktop.ShowCase.CollapseShowCase"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:atom="https://atomui.net"
|
||||
xmlns:showcase="clr-namespace:AtomUI.Demo.Desktop.ShowCase"
|
||||
mc:Ignorable="d">
|
||||
<showcase:ShowCasePanel>
|
||||
<showcase:ShowCaseItem
|
||||
Title="Collapse"
|
||||
Description="By default, any number of panels can be expanded at a time. The first panel is expanded in this example.">
|
||||
<atom:Collapse>
|
||||
<atom:CollapseItem Header="This is panel header 1">
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
A dog is a type of domesticated animal. Known for its loyalty and faithfulness, it can be found as a welcome guest in many households across the world.
|
||||
</TextBlock>
|
||||
</atom:CollapseItem>
|
||||
<atom:CollapseItem Header="This is panel header 2">
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
A dog is a type of domesticated animal. Known for its loyalty and faithfulness, it can be found as a welcome guest in many households across the world.
|
||||
</TextBlock>
|
||||
</atom:CollapseItem>
|
||||
<atom:CollapseItem Header="This is panel header 3">
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
A dog is a type of domesticated animal. Known for its loyalty and faithfulness, it can be found as a welcome guest in many households across the world.
|
||||
</TextBlock>
|
||||
</atom:CollapseItem>
|
||||
</atom:Collapse>
|
||||
</showcase:ShowCaseItem>
|
||||
</showcase:ShowCasePanel>
|
||||
</UserControl>
|
@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace AtomUI.Demo.Desktop.ShowCase;
|
||||
|
||||
public partial class CollapseShowCase : UserControl
|
||||
{
|
||||
public CollapseShowCase()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
@ -93,6 +93,9 @@
|
||||
<TabItem Header="Expander">
|
||||
<showcases:ExpanderShowCase />
|
||||
</TabItem>
|
||||
<TabItem Header="Collapse">
|
||||
<showcases:CollapseShowCase />
|
||||
</TabItem>
|
||||
<TabItem Header="ComboBox">
|
||||
<showcases:ComboBoxShowCase />
|
||||
</TabItem>
|
||||
|
@ -1,7 +1,5 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(MSBuildThisFileDirectory)..\..\Build\Common.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
@ -1,6 +1,8 @@
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.LogicalTree;
|
||||
@ -33,22 +35,26 @@ public class IconButton : AvaloniaButton, ICustomHitTest
|
||||
Cursor = new Cursor(StandardCursorType.Hand);
|
||||
}
|
||||
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
base.OnApplyTemplate(e);
|
||||
if (Icon is not null) {
|
||||
Icon.SetCurrentValue(PathIcon.HorizontalAlignmentProperty, HorizontalAlignment.Center);
|
||||
Icon.SetCurrentValue(PathIcon.VerticalAlignmentProperty, VerticalAlignment.Center);
|
||||
Content = Icon;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (VisualRoot is not null) {
|
||||
|
||||
if (e.Property == IconProperty) {
|
||||
var oldIcon = e.GetOldValue<PathIcon?>();
|
||||
if (oldIcon is not null) {
|
||||
((ISetLogicalParent)oldIcon).SetParent(null);
|
||||
}
|
||||
Content = e.GetNewValue<PathIcon?>();
|
||||
} else if (e.Property == IsPressedProperty ||
|
||||
e.Property == IsPointerOverProperty) {
|
||||
|
256
src/AtomUI.Controls/Collapse/Collapse.cs
Normal file
256
src/AtomUI.Controls/Collapse/Collapse.cs
Normal file
@ -0,0 +1,256 @@
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public enum CollapseTriggerType
|
||||
{
|
||||
Header,
|
||||
Icon,
|
||||
}
|
||||
|
||||
public enum CollapseExpandIconPosition
|
||||
{
|
||||
Start,
|
||||
End,
|
||||
}
|
||||
|
||||
[TemplatePart(CollapseTheme.ItemsPresenterPart, typeof(ItemsPresenter))]
|
||||
public class Collapse : SelectingItemsControl
|
||||
{
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly StyledProperty<SizeType> SizeTypeProperty =
|
||||
AvaloniaProperty.Register<Collapse, SizeType>(nameof(SizeType), SizeType.Middle);
|
||||
|
||||
public static readonly StyledProperty<bool> IsGhostStyleProperty =
|
||||
AvaloniaProperty.Register<Collapse, bool>(nameof(IsGhostStyle), false);
|
||||
|
||||
public static readonly StyledProperty<bool> IsBorderlessProperty =
|
||||
AvaloniaProperty.Register<Collapse, bool>(nameof(IsBorderless), false);
|
||||
|
||||
public static readonly StyledProperty<bool> IsAccordionProperty =
|
||||
AvaloniaProperty.Register<Collapse, bool>(nameof(IsAccordion), false);
|
||||
|
||||
public static readonly StyledProperty<CollapseTriggerType> TriggerTypeProperty =
|
||||
AvaloniaProperty.Register<Collapse, CollapseTriggerType>(nameof(TriggerType), CollapseTriggerType.Header);
|
||||
|
||||
public static readonly StyledProperty<CollapseExpandIconPosition> ExpandIconPositionProperty =
|
||||
AvaloniaProperty.Register<Collapse, CollapseExpandIconPosition>(nameof(ExpandIconPosition), CollapseExpandIconPosition.Start);
|
||||
|
||||
public SizeType SizeType
|
||||
{
|
||||
get => GetValue(SizeTypeProperty);
|
||||
set => SetValue(SizeTypeProperty, value);
|
||||
}
|
||||
|
||||
public bool IsGhostStyle
|
||||
{
|
||||
get => GetValue(IsGhostStyleProperty);
|
||||
set => SetValue(IsGhostStyleProperty, value);
|
||||
}
|
||||
|
||||
public bool IsBorderless
|
||||
{
|
||||
get => GetValue(IsBorderlessProperty);
|
||||
set => SetValue(IsBorderlessProperty, value);
|
||||
}
|
||||
|
||||
public bool IsAccordion
|
||||
{
|
||||
get => GetValue(IsAccordionProperty);
|
||||
set => SetValue(IsAccordionProperty, value);
|
||||
}
|
||||
|
||||
public CollapseTriggerType TriggerType
|
||||
{
|
||||
get => GetValue(TriggerTypeProperty);
|
||||
set => SetValue(TriggerTypeProperty, value);
|
||||
}
|
||||
|
||||
public CollapseExpandIconPosition ExpandIconPosition
|
||||
{
|
||||
get => GetValue(ExpandIconPositionProperty);
|
||||
set => SetValue(ExpandIconPositionProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region 内部属性定义
|
||||
|
||||
internal static readonly DirectProperty<Collapse, Thickness> EffectiveBorderThicknessProperty =
|
||||
AvaloniaProperty.RegisterDirect<Collapse, Thickness>(nameof(EffectiveBorderThickness),
|
||||
o => o.EffectiveBorderThickness,
|
||||
(o, v) => o.EffectiveBorderThickness = v);
|
||||
|
||||
private Thickness _effectiveBorderThickness;
|
||||
|
||||
internal Thickness EffectiveBorderThickness
|
||||
{
|
||||
get => _effectiveBorderThickness;
|
||||
set => SetAndRaise(EffectiveBorderThicknessProperty, ref _effectiveBorderThickness, value);
|
||||
}
|
||||
|
||||
internal ItemsPresenter? ItemsPresenterPart { get; private set; }
|
||||
|
||||
private static readonly FuncTemplate<Panel?> DefaultPanel =
|
||||
new(() => new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Vertical
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
static Collapse()
|
||||
{
|
||||
SelectionModeProperty.OverrideDefaultValue<Collapse>(SelectionMode.Multiple | SelectionMode.Toggle);
|
||||
ItemsPanelProperty.OverrideDefaultValue<Collapse>(DefaultPanel);
|
||||
}
|
||||
|
||||
public Collapse()
|
||||
{
|
||||
SelectionChanged += HandleSelectionChanged;
|
||||
}
|
||||
|
||||
private void HandleSelectionChanged(object? sender, SelectionChangedEventArgs args)
|
||||
{
|
||||
if (VisualRoot is not null) {
|
||||
for (var i = 0; i < ItemCount; ++i) {
|
||||
if (Items[i] is CollapseItem collapseItem) {
|
||||
SetupCollapseBorderThickness(collapseItem, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
TokenResourceBinder.CreateGlobalResourceBinding(this, BorderThicknessProperty, GlobalResourceKey.BorderThickness,
|
||||
BindingPriority.Template, new RenderScaleAwareThicknessConfigure(this));
|
||||
SetupEffectiveBorderThickness();
|
||||
SetupSelectionMode();
|
||||
}
|
||||
|
||||
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
||||
{
|
||||
return new CollapseItem();
|
||||
}
|
||||
|
||||
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
||||
{
|
||||
return NeedsContainer<CollapseItem>(item, out recycleKey);
|
||||
}
|
||||
|
||||
protected override void PrepareContainerForItemOverride(Control element, object? item, int index)
|
||||
{
|
||||
base.PrepareContainerForItemOverride(element, item, index);
|
||||
if (item is CollapseItem collapseItem) {
|
||||
BindUtils.RelayBind(this, SizeTypeProperty, collapseItem, CollapseItem.SizeTypeProperty);
|
||||
BindUtils.RelayBind(this, EffectiveBorderThicknessProperty, collapseItem, CollapseItem.BorderThicknessProperty);
|
||||
BindUtils.RelayBind(this, IsGhostStyleProperty, collapseItem, CollapseItem.IsGhostStyleProperty);
|
||||
BindUtils.RelayBind(this, TriggerTypeProperty, collapseItem, CollapseItem.TriggerTypeProperty);
|
||||
BindUtils.RelayBind(this, ExpandIconPositionProperty, collapseItem, CollapseItem.ExpandIconPositionProperty);
|
||||
SetupCollapseBorderThickness(collapseItem, index);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupCollapseBorderThickness(CollapseItem collapseItem, int index)
|
||||
{
|
||||
var headerBorderBottom = BorderThickness.Bottom;
|
||||
if (index == ItemCount - 1 && !collapseItem.IsSelected) {
|
||||
headerBorderBottom = 0d;
|
||||
}
|
||||
collapseItem.HeaderBorderThickness = new Thickness(0, 0, 0, headerBorderBottom);
|
||||
|
||||
var contentBorderBottom = BorderThickness.Bottom;
|
||||
if (index == ItemCount - 1 && collapseItem.IsSelected) {
|
||||
contentBorderBottom = 0d;
|
||||
}
|
||||
collapseItem.ContentBorderThickness = new Thickness(0, 0, 0, contentBorderBottom);
|
||||
}
|
||||
|
||||
protected override void ContainerIndexChangedOverride(Control container, int oldIndex, int newIndex)
|
||||
{
|
||||
base.ContainerIndexChangedOverride(container, oldIndex, newIndex);
|
||||
}
|
||||
|
||||
protected override void ClearContainerForItemOverride(Control element)
|
||||
{
|
||||
base.ClearContainerForItemOverride(element);
|
||||
}
|
||||
|
||||
protected override void OnGotFocus(GotFocusEventArgs e)
|
||||
{
|
||||
base.OnGotFocus(e);
|
||||
|
||||
if (e.NavigationMethod == NavigationMethod.Directional) {
|
||||
e.Handled = UpdateSelectionFromEventSource(e.Source);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
base.OnPointerPressed(e);
|
||||
|
||||
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && e.Pointer.Type == PointerType.Mouse) {
|
||||
e.Handled = UpdateSelectionFromEventSource(e.Source);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||
{
|
||||
if (e.InitialPressMouseButton == MouseButton.Left && e.Pointer.Type != PointerType.Mouse) {
|
||||
var container = GetContainerFromEventSource(e.Source);
|
||||
if (container != null
|
||||
&& container.GetVisualsAt(e.GetPosition(container))
|
||||
.Any(c => container == c || container.IsVisualAncestorOf(c))) {
|
||||
e.Handled = UpdateSelectionFromEventSource(e.Source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
if (VisualRoot is not null) {
|
||||
if (change.Property == IsBorderlessProperty) {
|
||||
SetupEffectiveBorderThickness();
|
||||
}
|
||||
}
|
||||
|
||||
if (change.Property == IsAccordionProperty) {
|
||||
SetupSelectionMode();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupEffectiveBorderThickness()
|
||||
{
|
||||
if (IsBorderless) {
|
||||
EffectiveBorderThickness = default;
|
||||
} else {
|
||||
EffectiveBorderThickness = BorderThickness;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupSelectionMode()
|
||||
{
|
||||
if (IsAccordion) {
|
||||
SelectionMode = SelectionMode.Single | SelectionMode.Toggle;
|
||||
} else {
|
||||
SelectionMode = SelectionMode.Multiple | SelectionMode.Toggle;
|
||||
}
|
||||
}
|
||||
}
|
195
src/AtomUI.Controls/Collapse/CollapseItem.cs
Normal file
195
src/AtomUI.Controls/Collapse/CollapseItem.cs
Normal file
@ -0,0 +1,195 @@
|
||||
using AtomUI.Controls.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Automation;
|
||||
using Avalonia.Automation.Peers;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Mixins;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
[PseudoClasses(StdPseudoClass.Pressed, StdPseudoClass.Selected)]
|
||||
public class CollapseItem : HeaderedContentControl, ISelectable
|
||||
{
|
||||
#region 公共属性定义
|
||||
public static readonly StyledProperty<bool> IsSelectedProperty =
|
||||
SelectingItemsControl.IsSelectedProperty.AddOwner<CollapseItem>();
|
||||
|
||||
public static readonly StyledProperty<bool> IsShowExpandIconProperty =
|
||||
AvaloniaProperty.Register<CollapseItem, bool>(nameof(IsShowExpandIcon));
|
||||
|
||||
public static readonly StyledProperty<PathIcon?> ExpandIconProperty =
|
||||
AvaloniaProperty.Register<CollapseItem, PathIcon?>(nameof(ExpandIcon));
|
||||
|
||||
public static readonly StyledProperty<object?> AddOnContentProperty =
|
||||
AvaloniaProperty.Register<CollapseItem, object?>(nameof(AddOnContent));
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get => GetValue(IsSelectedProperty);
|
||||
set => SetValue(IsSelectedProperty, value);
|
||||
}
|
||||
|
||||
public bool IsShowExpandIcon
|
||||
{
|
||||
get => GetValue(IsShowExpandIconProperty);
|
||||
set => SetValue(IsShowExpandIconProperty, value);
|
||||
}
|
||||
|
||||
public PathIcon? ExpandIcon
|
||||
{
|
||||
get => GetValue(ExpandIconProperty);
|
||||
set => SetValue(ExpandIconProperty, value);
|
||||
}
|
||||
|
||||
public object? AddOnContent
|
||||
{
|
||||
get => GetValue(AddOnContentProperty);
|
||||
set => SetValue(AddOnContentProperty, value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 内部属性定义
|
||||
internal static readonly DirectProperty<CollapseItem, SizeType> SizeTypeProperty =
|
||||
AvaloniaProperty.RegisterDirect<CollapseItem, SizeType>(nameof(SizeType),
|
||||
o => o.SizeType,
|
||||
(o, v) => o.SizeType = v);
|
||||
|
||||
internal static readonly DirectProperty<CollapseItem, bool> IsGhostStyleProperty =
|
||||
AvaloniaProperty.RegisterDirect<CollapseItem, bool>(nameof(IsGhostStyle),
|
||||
o => o.IsGhostStyle,
|
||||
(o, v) => o.IsGhostStyle = v);
|
||||
|
||||
internal static readonly DirectProperty<CollapseItem, CollapseTriggerType> TriggerTypeProperty =
|
||||
AvaloniaProperty.RegisterDirect<CollapseItem, CollapseTriggerType>(nameof(TriggerType),
|
||||
o => o.TriggerType,
|
||||
(o, v) => o.TriggerType = v);
|
||||
|
||||
internal static readonly DirectProperty<CollapseItem, CollapseExpandIconPosition> ExpandIconPositionProperty =
|
||||
AvaloniaProperty.RegisterDirect<CollapseItem, CollapseExpandIconPosition>(nameof(ExpandIconPosition),
|
||||
o => o.ExpandIconPosition,
|
||||
(o, v) => o.ExpandIconPosition = v);
|
||||
|
||||
internal static readonly DirectProperty<CollapseItem, Thickness> HeaderBorderThicknessProperty =
|
||||
AvaloniaProperty.RegisterDirect<CollapseItem, Thickness>(nameof(HeaderBorderThickness),
|
||||
o => o.HeaderBorderThickness,
|
||||
(o, v) => o.HeaderBorderThickness = v);
|
||||
|
||||
internal static readonly DirectProperty<CollapseItem, Thickness> ContentBorderThicknessProperty =
|
||||
AvaloniaProperty.RegisterDirect<CollapseItem, Thickness>(nameof(ContentBorderThickness),
|
||||
o => o. ContentBorderThickness,
|
||||
(o, v) => o. ContentBorderThickness = v);
|
||||
|
||||
private SizeType _sizeType;
|
||||
internal SizeType SizeType
|
||||
{
|
||||
get => _sizeType;
|
||||
set => SetAndRaise(SizeTypeProperty, ref _sizeType, value);
|
||||
}
|
||||
|
||||
private bool _isGhostStyle = false;
|
||||
internal bool IsGhostStyle
|
||||
{
|
||||
get => _isGhostStyle;
|
||||
set => SetAndRaise(IsGhostStyleProperty, ref _isGhostStyle, value);
|
||||
}
|
||||
|
||||
private CollapseTriggerType _triggerType = CollapseTriggerType.Header;
|
||||
internal CollapseTriggerType TriggerType
|
||||
{
|
||||
get => _triggerType;
|
||||
set => SetAndRaise(TriggerTypeProperty, ref _triggerType, value);
|
||||
}
|
||||
|
||||
private CollapseExpandIconPosition _expandIconPosition = CollapseExpandIconPosition.Start;
|
||||
internal CollapseExpandIconPosition ExpandIconPosition
|
||||
{
|
||||
get => _expandIconPosition;
|
||||
set => SetAndRaise(ExpandIconPositionProperty, ref _expandIconPosition, value);
|
||||
}
|
||||
|
||||
private Thickness _headerBorderThickness;
|
||||
internal Thickness HeaderBorderThickness
|
||||
{
|
||||
get => _headerBorderThickness;
|
||||
set => SetAndRaise(HeaderBorderThicknessProperty, ref _headerBorderThickness, value);
|
||||
}
|
||||
|
||||
private Thickness _contentBorderThickness;
|
||||
internal Thickness ContentBorderThickness
|
||||
{
|
||||
get => _contentBorderThickness;
|
||||
set => SetAndRaise(ContentBorderThicknessProperty, ref _contentBorderThickness, value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
static CollapseItem()
|
||||
{
|
||||
SelectableMixin.Attach<CollapseItem>(IsSelectedProperty);
|
||||
PressedMixin.Attach<CollapseItem>();
|
||||
FocusableProperty.OverrideDefaultValue(typeof(CollapseItem), true);
|
||||
DataContextProperty.Changed.AddClassHandler<CollapseItem>((x, e) => x.UpdateHeader(e));
|
||||
AutomationProperties.ControlTypeOverrideProperty.OverrideDefaultValue<TabItem>(AutomationControlType.TabItem);
|
||||
}
|
||||
|
||||
protected override AutomationPeer OnCreateAutomationPeer() => new ListItemAutomationPeer(this);
|
||||
|
||||
private void UpdateHeader(AvaloniaPropertyChangedEventArgs obj)
|
||||
{
|
||||
if (Header == null) {
|
||||
if (obj.NewValue is IHeadered headered) {
|
||||
if (Header != headered.Header) {
|
||||
SetCurrentValue(HeaderProperty, headered.Header);
|
||||
}
|
||||
} else {
|
||||
if (!(obj.NewValue is Control)) {
|
||||
SetCurrentValue(HeaderProperty, obj.NewValue);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Header == obj.OldValue) {
|
||||
SetCurrentValue(HeaderProperty, obj.NewValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
SetupIconButton();
|
||||
HandleSelectedChanged();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
if (change.Property == ExpandIconProperty) {
|
||||
SetupIconButton();
|
||||
}
|
||||
|
||||
if (VisualRoot is not null) {
|
||||
if (change.Property == IsSelectedProperty) {
|
||||
HandleSelectedChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleSelectedChanged()
|
||||
{
|
||||
if (Presenter is not null) {
|
||||
Presenter.IsVisible = IsSelected;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupIconButton()
|
||||
{
|
||||
if (ExpandIcon is null) {
|
||||
ExpandIcon = new PathIcon()
|
||||
{
|
||||
Kind = "RightOutlined"
|
||||
};
|
||||
}
|
||||
UIStructureUtils.SetTemplateParent(ExpandIcon, this);
|
||||
}
|
||||
}
|
210
src/AtomUI.Controls/Collapse/CollapseItemTheme.cs
Normal file
210
src/AtomUI.Controls/Collapse/CollapseItemTheme.cs
Normal file
@ -0,0 +1,210 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Documents;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
[ControlThemeProvider]
|
||||
internal class CollapseItemTheme : BaseControlTheme
|
||||
{
|
||||
public const string MainLayoutPart = "PART_MainLayout";
|
||||
public const string ExpandButtonPart = "PART_ExpandButton";
|
||||
public const string HeaderPresenterPart = "PART_HeaderPresenter";
|
||||
public const string HeaderDecoratorPart = "PART_HeaderDecorator";
|
||||
public const string ContentPresenterPart = "PART_ContentPresenter";
|
||||
|
||||
public CollapseItemTheme() : base(typeof(CollapseItem)) {}
|
||||
|
||||
protected override IControlTemplate BuildControlTemplate()
|
||||
{
|
||||
return new FuncControlTemplate<CollapseItem>((collapseItem, scope) =>
|
||||
{
|
||||
var mainLayout = new DockPanel()
|
||||
{
|
||||
Name = MainLayoutPart,
|
||||
LastChildFill = true,
|
||||
};
|
||||
|
||||
BuildHeader(mainLayout, scope);
|
||||
var contentPresenter = new ContentPresenter()
|
||||
{
|
||||
Name = ContentPresenterPart,
|
||||
};
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(contentPresenter, ContentPresenter.BorderBrushProperty, GlobalResourceKey.ColorBorder);
|
||||
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty, CollapseItem.ContentProperty);
|
||||
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentTemplateProperty, CollapseItem.ContentTemplateProperty);
|
||||
CreateTemplateParentBinding(contentPresenter, ContentPresenter.BorderThicknessProperty, CollapseItem.ContentBorderThicknessProperty);
|
||||
mainLayout.Children.Add(contentPresenter);
|
||||
contentPresenter.RegisterInNameScope(scope);
|
||||
return mainLayout;
|
||||
});
|
||||
}
|
||||
|
||||
private void BuildHeader(DockPanel layout, INameScope scope)
|
||||
{
|
||||
var headerDecorator = new Border()
|
||||
{
|
||||
Name = HeaderDecoratorPart
|
||||
};
|
||||
DockPanel.SetDock(headerDecorator, Dock.Top);
|
||||
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(headerDecorator, Border.BorderBrushProperty, GlobalResourceKey.ColorBorder);
|
||||
CreateTemplateParentBinding(headerDecorator, Border.BorderThicknessProperty, CollapseItem.HeaderBorderThicknessProperty);
|
||||
|
||||
var headerLayout = new Grid()
|
||||
{
|
||||
ColumnDefinitions = new ColumnDefinitions()
|
||||
{
|
||||
new ColumnDefinition(GridLength.Auto),
|
||||
new ColumnDefinition(GridLength.Star),
|
||||
new ColumnDefinition(GridLength.Auto),
|
||||
new ColumnDefinition(GridLength.Auto)
|
||||
}
|
||||
};
|
||||
|
||||
var expandButton = new IconButton()
|
||||
{
|
||||
Name = ExpandButtonPart,
|
||||
VerticalAlignment = VerticalAlignment.Center
|
||||
};
|
||||
CreateTemplateParentBinding(expandButton, IconButton.IconProperty, CollapseItem.ExpandIconProperty);
|
||||
headerLayout.Children.Add(expandButton);
|
||||
|
||||
var headerPresenter = new ContentPresenter()
|
||||
{
|
||||
Name = HeaderPresenterPart,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
HorizontalContentAlignment = HorizontalAlignment.Left,
|
||||
};
|
||||
CreateTemplateParentBinding(headerPresenter, ContentPresenter.ContentProperty, CollapseItem.HeaderProperty);
|
||||
CreateTemplateParentBinding(headerPresenter, ContentPresenter.ContentTemplateProperty, CollapseItem.HeaderTemplateProperty);
|
||||
Grid.SetColumn(headerPresenter, 1);
|
||||
headerPresenter.RegisterInNameScope(scope);
|
||||
headerLayout.Children.Add(headerPresenter);
|
||||
headerDecorator.Child = headerLayout;
|
||||
layout.Children.Add(headerDecorator);
|
||||
}
|
||||
|
||||
protected override void BuildStyles()
|
||||
{
|
||||
BuildCommonStyle();
|
||||
BuildTriggerStyle();
|
||||
BuildTriggerPositionStyle();
|
||||
BuildSizeTypeStyle();
|
||||
}
|
||||
|
||||
private void BuildCommonStyle()
|
||||
{
|
||||
var commonStyle = new Style(selector => selector.Nesting());
|
||||
var decoratorStyle = new Style(selector => selector.Nesting().Template().Name(HeaderDecoratorPart));
|
||||
decoratorStyle.Add(Border.BackgroundProperty, CollapseResourceKey.HeaderBg);
|
||||
commonStyle.Add(decoratorStyle);
|
||||
|
||||
var headerPresenter = new Style(selector => selector.Nesting().Template().Name(HeaderPresenterPart));
|
||||
headerPresenter.Add(ContentPresenter.ForegroundProperty, GlobalResourceKey.ColorTextHeading);
|
||||
commonStyle.Add(headerPresenter);
|
||||
|
||||
// ExpandIcon
|
||||
var expandIconStyle = new Style(selector => selector.Nesting().Template().Name(ExpandButtonPart).Descendant().OfType<PathIcon>());
|
||||
expandIconStyle.Add(PathIcon.WidthProperty, GlobalResourceKey.IconSizeSM);
|
||||
expandIconStyle.Add(PathIcon.HeightProperty, GlobalResourceKey.IconSizeSM);
|
||||
commonStyle.Add(expandIconStyle);
|
||||
|
||||
Add(commonStyle);
|
||||
}
|
||||
|
||||
private void BuildSizeTypeStyle()
|
||||
{
|
||||
var largeSizeStyle = new Style(selector => selector.Nesting().PropertyEquals(CollapseItem.SizeTypeProperty, SizeType.Large));
|
||||
{
|
||||
var decoratorStyle = new Style(selector => selector.Nesting().Template().Name(HeaderDecoratorPart));
|
||||
decoratorStyle.Add(Border.PaddingProperty, CollapseResourceKey.CollapseHeaderPaddingLG);
|
||||
decoratorStyle.Add(TextElement.FontSizeProperty, GlobalResourceKey.FontSizeLG);
|
||||
decoratorStyle.Add(TextBlock.LineHeightProperty, GlobalResourceKey.FontHeightLG);
|
||||
largeSizeStyle.Add(decoratorStyle);
|
||||
}
|
||||
|
||||
{
|
||||
var contentPresenterStyle = new Style(selector => selector.Nesting().Template().Name(ContentPresenterPart));
|
||||
contentPresenterStyle.Add(ContentPresenter.PaddingProperty, CollapseResourceKey.CollapseContentPaddingLG);
|
||||
largeSizeStyle.Add(contentPresenterStyle);
|
||||
}
|
||||
|
||||
Add(largeSizeStyle);
|
||||
|
||||
var middleSizeStyle = new Style(selector => selector.Nesting().PropertyEquals(CollapseItem.SizeTypeProperty, SizeType.Middle));
|
||||
{
|
||||
var decoratorStyle = new Style(selector => selector.Nesting().Template().Name(HeaderDecoratorPart));
|
||||
decoratorStyle.Add(Border.PaddingProperty, CollapseResourceKey.HeaderPadding);
|
||||
decoratorStyle.Add(TextElement.FontSizeProperty, GlobalResourceKey.FontSize);
|
||||
decoratorStyle.Add(TextBlock.LineHeightProperty, GlobalResourceKey.FontHeight);
|
||||
middleSizeStyle.Add(decoratorStyle);
|
||||
}
|
||||
|
||||
{
|
||||
var contentPresenterStyle = new Style(selector => selector.Nesting().Template().Name(ContentPresenterPart));
|
||||
contentPresenterStyle.Add(ContentPresenter.PaddingProperty, CollapseResourceKey.ContentPadding);
|
||||
middleSizeStyle.Add(contentPresenterStyle);
|
||||
}
|
||||
Add(middleSizeStyle);
|
||||
|
||||
var smallSizeStyle = new Style(selector => selector.Nesting().PropertyEquals(CollapseItem.SizeTypeProperty, SizeType.Small));
|
||||
{
|
||||
var decoratorStyle = new Style(selector => selector.Nesting().Template().Name(HeaderDecoratorPart));
|
||||
decoratorStyle.Add(Border.PaddingProperty, CollapseResourceKey.CollapseHeaderPaddingSM);
|
||||
decoratorStyle.Add(TextElement.FontSizeProperty, GlobalResourceKey.FontSize);
|
||||
decoratorStyle.Add(TextBlock.LineHeightProperty, GlobalResourceKey.FontHeight);
|
||||
smallSizeStyle.Add(decoratorStyle);
|
||||
}
|
||||
|
||||
{
|
||||
var contentPresenterStyle = new Style(selector => selector.Nesting().Template().Name(ContentPresenterPart));
|
||||
contentPresenterStyle.Add(ContentPresenter.PaddingProperty, CollapseResourceKey.CollapseContentPaddingSM);
|
||||
smallSizeStyle.Add(contentPresenterStyle);
|
||||
}
|
||||
|
||||
Add(smallSizeStyle);
|
||||
}
|
||||
|
||||
private void BuildTriggerStyle()
|
||||
{
|
||||
var headerTriggerHandleStyle = new Style(selector => selector.Nesting().PropertyEquals(CollapseItem.TriggerTypeProperty, CollapseTriggerType.Header));
|
||||
var headerDecoratorStyle = new Style(selector => selector.Nesting().Template().Name(HeaderDecoratorPart));
|
||||
headerDecoratorStyle.Add(Border.CursorProperty, new Cursor(StandardCursorType.Hand));
|
||||
headerTriggerHandleStyle.Add(headerDecoratorStyle);
|
||||
Add(headerTriggerHandleStyle);
|
||||
|
||||
var iconTriggerHandleStyle = new Style(selector => selector.Nesting().PropertyEquals(CollapseItem.TriggerTypeProperty, CollapseTriggerType.Icon));
|
||||
var expandIconStyle = new Style(selector => selector.Nesting().Template().Name(ExpandButtonPart));
|
||||
expandIconStyle.Add(IconButton.CursorProperty, new Cursor(StandardCursorType.Hand));
|
||||
iconTriggerHandleStyle.Add(expandIconStyle);
|
||||
Add(iconTriggerHandleStyle);
|
||||
}
|
||||
|
||||
private void BuildTriggerPositionStyle()
|
||||
{
|
||||
var startPositionStyle = new Style(selector => selector.Nesting().PropertyEquals(CollapseItem.ExpandIconPositionProperty, CollapseExpandIconPosition.Start));
|
||||
{
|
||||
var expandButtonStyle = new Style(selector => selector.Nesting().Template().Name(ExpandButtonPart));
|
||||
expandButtonStyle.Add(Grid.ColumnProperty, 0);
|
||||
expandButtonStyle.Add(IconButton.MarginProperty, CollapseResourceKey.LeftExpandButtonMargin);
|
||||
startPositionStyle.Add(expandButtonStyle);
|
||||
}
|
||||
Add(startPositionStyle);
|
||||
var endPositionStyle = new Style(selector => selector.Nesting().PropertyEquals(CollapseItem.ExpandIconPositionProperty, CollapseExpandIconPosition.End));
|
||||
{
|
||||
var expandButtonStyle = new Style(selector => selector.Nesting().Template().Name(ExpandButtonPart));
|
||||
expandButtonStyle.Add(Grid.ColumnProperty, 3);
|
||||
expandButtonStyle.Add(IconButton.MarginProperty, CollapseResourceKey.RightExpandButtonMargin);
|
||||
endPositionStyle.Add(expandButtonStyle);
|
||||
}
|
||||
Add(endPositionStyle);
|
||||
}
|
||||
}
|
51
src/AtomUI.Controls/Collapse/CollapseTheme.cs
Normal file
51
src/AtomUI.Controls/Collapse/CollapseTheme.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
[ControlThemeProvider]
|
||||
internal class CollapseTheme : BaseControlTheme
|
||||
{
|
||||
public const string FrameDecoratorPart = "PART_FrameDecorator";
|
||||
public const string ItemsPresenterPart = "PART_ItemsPresenter";
|
||||
|
||||
public CollapseTheme() : base(typeof(Collapse)) {}
|
||||
|
||||
|
||||
protected override IControlTemplate BuildControlTemplate()
|
||||
{
|
||||
return new FuncControlTemplate<Collapse>((collapse, scope) =>
|
||||
{
|
||||
var frameDecorator = new Border()
|
||||
{
|
||||
Name = FrameDecoratorPart,
|
||||
ClipToBounds = true
|
||||
};
|
||||
var itemsPresenter = new ItemsPresenter()
|
||||
{
|
||||
Name = ItemsPresenterPart
|
||||
};
|
||||
itemsPresenter.RegisterInNameScope(scope);
|
||||
frameDecorator.Child = itemsPresenter;
|
||||
|
||||
CreateTemplateParentBinding(itemsPresenter, ItemsPresenter.ItemsPanelProperty, Collapse.ItemsPanelProperty);
|
||||
CreateTemplateParentBinding(frameDecorator, Border.BorderThicknessProperty, Collapse.EffectiveBorderThicknessProperty);
|
||||
CreateTemplateParentBinding(frameDecorator, Border.BorderBrushProperty, Collapse.BorderBrushProperty);
|
||||
CreateTemplateParentBinding(frameDecorator, Border.CornerRadiusProperty, Collapse.CornerRadiusProperty);
|
||||
|
||||
return frameDecorator;
|
||||
});
|
||||
}
|
||||
|
||||
protected override void BuildStyles()
|
||||
{
|
||||
var commonStyle = new Style(selector => selector.Nesting());
|
||||
commonStyle.Add(Collapse.BorderBrushProperty, GlobalResourceKey.ColorBorder);
|
||||
commonStyle.Add(Collapse.CornerRadiusProperty, CollapseResourceKey.CollapsePanelBorderRadius);
|
||||
Add(commonStyle);
|
||||
}
|
||||
}
|
64
src/AtomUI.Controls/Collapse/CollapseToken.cs
Normal file
64
src/AtomUI.Controls/Collapse/CollapseToken.cs
Normal file
@ -0,0 +1,64 @@
|
||||
using AtomUI.Theme.TokenSystem;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
[ControlDesignToken]
|
||||
internal class CollapseToken : AbstractControlDesignToken
|
||||
{
|
||||
public const string ID = "Collapse";
|
||||
|
||||
public CollapseToken()
|
||||
: base(ID)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 折叠面板头部内边距
|
||||
/// </summary>
|
||||
public Thickness HeaderPadding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 折叠面板头部背景
|
||||
/// </summary>
|
||||
public Color HeaderBg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 折叠面板内容内边距
|
||||
/// </summary>
|
||||
public Thickness ContentPadding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 折叠面板内容背景
|
||||
/// </summary>
|
||||
public Color ContentBg { get; set; }
|
||||
|
||||
#region 内部 Token 定义
|
||||
|
||||
public Thickness CollapseHeaderPaddingSM { get; set; }
|
||||
public Thickness CollapseHeaderPaddingLG { get; set; }
|
||||
public Thickness CollapseContentPaddingSM { get; set; }
|
||||
public Thickness CollapseContentPaddingLG { get; set; }
|
||||
public CornerRadius CollapsePanelBorderRadius { get; set; }
|
||||
public Thickness LeftExpandButtonMargin { get; set; }
|
||||
public Thickness RightExpandButtonMargin { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
internal override void CalculateFromAlias()
|
||||
{
|
||||
base.CalculateFromAlias();
|
||||
HeaderPadding = new Thickness(_globalToken.Padding, _globalToken.PaddingSM);
|
||||
HeaderBg = _globalToken.ColorFillAlter;
|
||||
ContentPadding = new Thickness(16, _globalToken.Padding);
|
||||
CollapseContentPaddingSM = new Thickness(_globalToken.PaddingSM);
|
||||
CollapseContentPaddingLG = new Thickness(_globalToken.PaddingLG);
|
||||
ContentBg = _globalToken.ColorToken.ColorNeutralToken.ColorBgContainer;
|
||||
CollapseHeaderPaddingSM = new Thickness(_globalToken.PaddingSM, _globalToken.PaddingXS);
|
||||
CollapseHeaderPaddingLG = new Thickness(_globalToken.PaddingLG, _globalToken.Padding);
|
||||
CollapsePanelBorderRadius = _globalToken.StyleToken.BorderRadiusLG;
|
||||
LeftExpandButtonMargin = new Thickness(0, 0, _globalToken.MarginSM, 0);
|
||||
RightExpandButtonMargin = new Thickness(_globalToken.MarginSM, 0, 0, 0);
|
||||
}
|
||||
}
|
6
src/AtomUI.Controls/IHeadered.cs
Normal file
6
src/AtomUI.Controls/IHeadered.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public interface IHeadered
|
||||
{
|
||||
object? Header { get; set; }
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(MSBuildThisFileDirectory)..\..\Build\Common.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="$(CompilerGeneratedFilesOutputPath)/**/*.cs" />
|
||||
</ItemGroup>
|
||||
|
@ -1,7 +1,5 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(MSBuildThisFileDirectory)..\..\Build\Common.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia"/>
|
||||
</ItemGroup>
|
||||
|
@ -1,7 +1,5 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="$(MSBuildThisFileDirectory)..\..\Build\Common.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||
<CompilerGeneratedFilesOutputPath>GeneratedFiles</CompilerGeneratedFilesOutputPath>
|
||||
|
Loading…
Reference in New Issue
Block a user