chore: add avalonia button and brush demo.

This commit is contained in:
NaBian 2024-07-17 22:56:54 +08:00
parent 63bf5c6aa7
commit 40bb60164e
23 changed files with 1027 additions and 300 deletions

View File

@ -1,4 +1,5 @@
using Avalonia;
using System.Globalization;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Data.Core.Plugins;
using Avalonia.Markup.Xaml;
@ -6,7 +7,7 @@ using Avalonia.Markup.Xaml;
namespace HandyControlDemo;
public partial class App : Application
public class App : Application
{
public override void Initialize()
{
@ -15,6 +16,7 @@ public partial class App : Application
public override void OnFrameworkInitializationCompleted()
{
Properties.Langs.Lang.Culture = new CultureInfo("en");
BindingPlugins.DataValidators.RemoveAt(0);
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)

View File

@ -1,7 +1,7 @@
[
{
"title": "Styles",
"selectedIndex": 0,
"selectedIndex": -1,
"group": false,
"demoItemList": [
[ "Brush", "BrushDemoCtl", "Brush.Brush", "", "" ],

View File

@ -57,6 +57,10 @@
<Compile Update="Views\Styles\ButtonDemoCtrl.axaml.cs">
<DependentUpon>ButtonDemoCtrl.axaml</DependentUpon>
</Compile>
<Compile Update="UserControl\Styles\BrushDemoCtl.axaml.cs">
<DependentUpon>BoderDemoCtl.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>

View File

@ -6,46 +6,55 @@
Margin="16,16,0,16"
CornerRadius="10"
Effect="{StaticResource EffectShadow4}">
<TabControl BorderThickness="0 1 0 0"
SelectionChanged="TabControl_OnSelectionChanged"
ItemsSource="{Binding DemoInfoCollection}"
Background="Transparent"
SelectedIndex="0">
<TabControl.ItemTemplate>
<DataTemplate DataType="data:DemoInfoModel">
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="data:DemoInfoModel">
<Panel Margin="10">
<ListBox SelectionMode="Single"
Padding="0"
BorderThickness="0"
SelectedIndex="{Binding SelectedIndex}"
ItemsSource="{Binding DemoItemList}">
<ListBox.ItemTemplate>
<DataTemplate DataType="data:DemoItemModel">
<StackPanel Orientation="Horizontal">
<Rectangle Width="16"
Height="16"
Fill="{Binding ImageBrush}" />
<TextBlock Margin="6,0,0,0"
Text="{Binding Name}" />
<Path IsVisible="{Binding IsNew}"
VerticalAlignment="Center"
Data="{StaticResource NewGeometry}"
Stretch="Uniform"
Margin="10,0,0,0"
Width="30"
Height="14"
Fill="{DynamicResource AccentBrush}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Panel>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
<DockPanel>
<Button Content="Practical demos"
DockPanel.Dock="Top"
HorizontalAlignment="Stretch"
Margin="10,10,10,4"
BorderThickness="0"
Background="{DynamicResource SecondaryRegionBrush}" />
<TabControl BorderThickness="0 1 0 0"
Classes="inline"
SelectionChanged="TabControl_OnSelectionChanged"
ItemsSource="{Binding DemoInfoCollection}"
Background="Transparent"
SelectedIndex="0">
<TabControl.ItemTemplate>
<DataTemplate DataType="data:DemoInfoModel">
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="data:DemoInfoModel">
<Panel Margin="10">
<ListBox SelectionMode="Single"
Padding="0"
BorderThickness="0"
SelectedIndex="{Binding SelectedIndex}"
ItemsSource="{Binding DemoItemList}">
<ListBox.ItemTemplate>
<DataTemplate DataType="data:DemoItemModel">
<StackPanel Orientation="Horizontal">
<Rectangle Width="16"
Height="16"
Fill="{Binding ImageBrush}" />
<TextBlock Margin="6,0,0,0"
Text="{Binding Name}" />
<Path IsVisible="{Binding IsNew}"
VerticalAlignment="Center"
Data="{StaticResource NewGeometry}"
Stretch="Uniform"
Margin="10,0,0,0"
Width="30"
Height="14"
Fill="{DynamicResource AccentBrush}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Panel>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</DockPanel>
</UserControl>

View File

@ -0,0 +1,117 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:hc="https://handyorg.github.io/handycontrol"
x:Class="HandyControlDemo.UserControl.BrushDemoCtl"
Background="{DynamicResource RegionBrush}">
<ScrollViewer>
<hc:UniformSpacingPanel ChildWrapping="Wrap"
ItemWidth="200"
Margin="32"
Spacing="16"
VerticalAlignment="Center"
MaxWidth="632">
<Label Content="PrimaryBrush"
Theme="{StaticResource LabelPrimary}" />
<Label Content="DarkPrimaryBrush"
Background="{DynamicResource DarkPrimaryBrush}"
Foreground="White"
BorderThickness="0" />
<Label Content="DangerBrush"
Theme="{StaticResource LabelDanger}" />
<Label Content="DarkDangerBrush"
Background="{DynamicResource DarkDangerBrush}"
Foreground="White"
BorderThickness="0" />
<Label Content="WarningBrush"
Theme="{StaticResource LabelWarning}" />
<Label Content="DarkWarningBrush"
Background="{DynamicResource DarkWarningBrush}"
Foreground="White"
BorderThickness="0" />
<Label Content="InfoBrush"
Theme="{StaticResource LabelInfo}" />
<Label Content="DarkInfoBrush"
Background="{DynamicResource DarkInfoBrush}"
Foreground="White"
BorderThickness="0" />
<Label Content="SuccessBrush"
Theme="{StaticResource LabelSuccess}" />
<Label Content="DarkSuccessBrush"
Background="{DynamicResource DarkSuccessBrush}"
Foreground="White"
BorderThickness="0" />
<Label Content="AccentBrush"
Background="{DynamicResource AccentBrush}"
Foreground="White"
BorderThickness="0" />
<Label Content="DarkAccentBrush"
Background="{DynamicResource DarkAccentBrush}"
Foreground="White"
BorderThickness="0" />
<Label Content="PrimaryTextBrush"
Background="{DynamicResource PrimaryTextBrush}"
Foreground="{DynamicResource ThirdlyTextBrush}" />
<Label Content="SecondaryTextBrush"
BorderThickness="0"
Background="{DynamicResource SecondaryTextBrush}"
Foreground="White" />
<Label Content="ThirdlyTextBrush"
BorderThickness="0"
Background="{DynamicResource ThirdlyTextBrush}"
Foreground="White" />
<Label Content="ReverseTextBrush"
BorderThickness="0"
Background="{DynamicResource ReverseTextBrush}"
Foreground="White" />
<Label Content="TextIconBrush"
Background="{DynamicResource TextIconBrush}"
Foreground="{DynamicResource ReverseTextBrush}" />
<Label Content="BorderBrush"
BorderThickness="0"
Background="{DynamicResource BorderBrush}"
Foreground="{DynamicResource PrimaryTextBrush}" />
<Label Content="SecondaryBorderBrush"
BorderThickness="0"
Background="{DynamicResource SecondaryBorderBrush}"
Foreground="White" />
<Label Content="BackgroundBrush"
BorderThickness="0"
Background="{DynamicResource BackgroundBrush}"
Foreground="{DynamicResource ReverseTextBrush}" />
<Label Content="RegionBrush"
Background="{DynamicResource RegionBrush}"
Foreground="{DynamicResource PrimaryTextBrush}" />
<Label Content="SecondaryRegionBrush"
BorderThickness="0"
Background="{DynamicResource SecondaryRegionBrush}"
Foreground="{DynamicResource PrimaryTextBrush}" />
<Label Content="ThirdlyRegionBrush"
Background="{DynamicResource ThirdlyRegionBrush}"
Foreground="{DynamicResource PrimaryTextBrush}" />
<Label Content="TitleBrush"
BorderThickness="0"
Background="{DynamicResource TitleBrush}"
Foreground="White" />
<Label Content="DefaultBrush"
Background="{DynamicResource DefaultBrush}"
Foreground="{DynamicResource PrimaryTextBrush}" />
<Label Content="DarkDefaultBrush"
BorderThickness="0"
Background="{DynamicResource DarkDefaultBrush}"
Foreground="{DynamicResource PrimaryTextBrush}" />
<Label Content="DarkMaskBrush"
BorderThickness="0"
Background="{DynamicResource DarkMaskBrush}"
Foreground="{DynamicResource PrimaryTextBrush}" />
<Label Content="DarkOpacityBrush"
BorderThickness="0"
Background="{DynamicResource DarkOpacityBrush}"
Foreground="White" />
</hc:UniformSpacingPanel>
</ScrollViewer>
</UserControl>

View File

@ -0,0 +1,9 @@
namespace HandyControlDemo.UserControl;
public partial class BrushDemoCtl : Avalonia.Controls.UserControl
{
public BrushDemoCtl()
{
InitializeComponent();
}
}

View File

@ -1,28 +1,69 @@
<UserControl 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"
mc:Ignorable="d"
d:DesignWidth="800"
d:DesignHeight="450"
x:Class="HandyControlDemo.UserControl.ButtonDemoCtl"
xmlns:hc="https://handyorg.github.io/handycontrol"
Background="{DynamicResource RegionBrush}">
<ScrollViewer>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Top"
Spacing="4"
Margin="32">
<Button Content="default" />
<Button Content="primary"
Classes="primary" />
<Button Content="success"
Classes="success" />
<Button Content="info"
Classes="info" />
<Button Content="warning"
Classes="warning" />
<Button Content="danger"
Classes="danger" />
</StackPanel>
<hc:UniformSpacingPanel ChildWrapping="Wrap"
Spacing="32"
Margin="32">
<hc:UniformSpacingPanel Orientation="Vertical"
Spacing="32">
<WrapPanel>
<StackPanel>
<Button Content="default"
Margin="5" />
<Button IsEnabled="False"
Content="default"
Margin="5" />
</StackPanel>
<StackPanel>
<Button Content="primary"
Margin="5"
Theme="{StaticResource ButtonPrimary}" />
<Button IsEnabled="False"
Content="primary"
Margin="5"
Theme="{StaticResource ButtonPrimary}" />
</StackPanel>
<StackPanel>
<Button Content="success"
Margin="5"
Theme="{StaticResource ButtonSuccess}" />
<Button IsEnabled="False"
Content="success"
Margin="5"
Theme="{StaticResource ButtonSuccess}" />
</StackPanel>
<StackPanel>
<Button Content="info"
Margin="5"
Theme="{StaticResource ButtonInfo}" />
<Button IsEnabled="False"
Content="info"
Margin="5"
Theme="{StaticResource ButtonInfo}" />
</StackPanel>
<StackPanel>
<Button Content="warning"
Margin="5"
Theme="{StaticResource ButtonWarning}" />
<Button IsEnabled="False"
Content="warning"
Margin="5"
Theme="{StaticResource ButtonWarning}" />
</StackPanel>
<StackPanel>
<Button Content="danger"
Margin="5"
Theme="{StaticResource ButtonDanger}" />
<Button IsEnabled="False"
Content="danger"
Margin="5"
Theme="{StaticResource ButtonDanger}" />
</StackPanel>
</WrapPanel>
</hc:UniformSpacingPanel>
</hc:UniformSpacingPanel>
</ScrollViewer>
</UserControl>

View File

@ -69,7 +69,7 @@ public class MainViewModel : DemoViewModelBase<DemoDataModel>
return;
}
ContentTitle = Lang.ResourceManager.GetString(DemoItemCurrent.Name);
ContentTitle = Lang.ResourceManager.GetString(DemoItemCurrent.Name, Lang.Culture);
});
//load items
@ -91,7 +91,7 @@ public class MainViewModel : DemoViewModelBase<DemoDataModel>
}
DemoItemCurrent = item;
ContentTitle = Lang.ResourceManager.GetString(item.Name);
ContentTitle = Lang.ResourceManager.GetString(item.Name, Lang.Culture);
object? demoControl = AssemblyHelper.ResolveByKey(item.TargetCtlName) ?? AssemblyHelper.CreateInternalInstance($"UserControl.{item.TargetCtlName}");
SubContent = demoControl;
}

View File

@ -0,0 +1,373 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Layout;
using HandyControl.Data;
using HandyControl.Tools;
namespace HandyControl.Controls;
public class UniformSpacingPanel : Panel
{
public static readonly StyledProperty<Orientation> OrientationProperty =
StackPanel.OrientationProperty.AddOwner<UniformSpacingPanel>();
public static readonly StyledProperty<VisualWrapping> ChildWrappingProperty =
AvaloniaProperty.Register<UniformSpacingPanel, VisualWrapping>(nameof(ChildWrapping));
public static readonly StyledProperty<double> SpacingProperty =
StackPanel.SpacingProperty.AddOwner<UniformSpacingPanel>(
new StyledPropertyMetadata<double>(defaultValue: double.NaN, coerce: CoerceLength));
public static readonly StyledProperty<double> HorizontalSpacingProperty =
AvaloniaProperty.Register<UniformSpacingPanel, double>(nameof(HorizontalSpacing), defaultValue: double.NaN,
coerce: CoerceLength);
public static readonly StyledProperty<double> VerticalSpacingProperty =
AvaloniaProperty.Register<UniformSpacingPanel, double>(nameof(VerticalSpacing), defaultValue: double.NaN,
coerce: CoerceLength);
public static readonly StyledProperty<double> ItemWidthProperty =
AvaloniaProperty.Register<UniformSpacingPanel, double>(nameof(ItemWidth), defaultValue: double.NaN,
coerce: CoerceLength);
public static readonly StyledProperty<double> ItemHeightProperty =
AvaloniaProperty.Register<UniformSpacingPanel, double>(nameof(ItemHeight), defaultValue: double.NaN,
coerce: CoerceLength);
public static readonly StyledProperty<HorizontalAlignment?> ItemHorizontalAlignmentProperty =
AvaloniaProperty.Register<UniformSpacingPanel, HorizontalAlignment?>(nameof(ItemHorizontalAlignment),
defaultValue: HorizontalAlignment.Stretch);
public static readonly StyledProperty<VerticalAlignment?> ItemVerticalAlignmentProperty =
AvaloniaProperty.Register<UniformSpacingPanel, VerticalAlignment?>(nameof(ItemVerticalAlignment),
defaultValue: VerticalAlignment.Stretch);
private Orientation _orientation = Orientation.Horizontal;
static UniformSpacingPanel()
{
AffectsMeasure<StackPanel>(OrientationProperty);
AffectsMeasure<StackPanel>(ChildWrappingProperty);
AffectsMeasure<StackPanel>(SpacingProperty);
AffectsMeasure<StackPanel>(HorizontalSpacingProperty);
AffectsMeasure<StackPanel>(VerticalSpacingProperty);
AffectsMeasure<StackPanel>(ItemWidthProperty);
AffectsMeasure<StackPanel>(ItemHeightProperty);
AffectsMeasure<StackPanel>(ItemHorizontalAlignmentProperty);
AffectsMeasure<StackPanel>(ItemVerticalAlignmentProperty);
OrientationProperty.Changed.AddClassHandler<UniformSpacingPanel>(OnOrientationChanged);
}
private static void OnOrientationChanged(UniformSpacingPanel self, AvaloniaPropertyChangedEventArgs args)
{
if (args.NewValue is Orientation orientation)
{
self._orientation = orientation;
}
}
private static double CoerceLength(AvaloniaObject _, double length) => length < 0 ? 0 : length;
public Orientation Orientation
{
get => GetValue(OrientationProperty);
set => SetValue(OrientationProperty, value);
}
public VisualWrapping ChildWrapping
{
get => GetValue(ChildWrappingProperty);
set => SetValue(ChildWrappingProperty, value);
}
public double Spacing
{
get => GetValue(SpacingProperty);
set => SetValue(SpacingProperty, value);
}
public double HorizontalSpacing
{
get => GetValue(HorizontalSpacingProperty);
set => SetValue(HorizontalSpacingProperty, value);
}
public double VerticalSpacing
{
get => GetValue(VerticalSpacingProperty);
set => SetValue(VerticalSpacingProperty, value);
}
public double ItemWidth
{
get => GetValue(ItemWidthProperty);
set => SetValue(ItemWidthProperty, value);
}
public double ItemHeight
{
get => GetValue(ItemHeightProperty);
set => SetValue(ItemHeightProperty, value);
}
public HorizontalAlignment? ItemHorizontalAlignment
{
get => GetValue(ItemHorizontalAlignmentProperty);
set => SetValue(ItemHorizontalAlignmentProperty, value);
}
public VerticalAlignment? ItemVerticalAlignment
{
get => GetValue(ItemVerticalAlignmentProperty);
set => SetValue(ItemVerticalAlignmentProperty, value);
}
protected override Size MeasureOverride(Size availableSize)
{
var curLineSize = new PanelUvSize(_orientation);
var panelSize = new PanelUvSize(_orientation);
var uvConstraint = new PanelUvSize(_orientation, availableSize);
double itemWidth = ItemWidth;
double itemHeight = ItemHeight;
bool itemWidthSet = !double.IsNaN(itemWidth);
bool itemHeightSet = !double.IsNaN(itemHeight);
var itemHorizontalAlignment = ItemHorizontalAlignment;
var itemVerticalAlignment = ItemVerticalAlignment;
bool itemHorizontalAlignmentSet = itemHorizontalAlignment != null;
bool itemVerticalAlignmentSet = itemVerticalAlignment != null;
var childWrapping = ChildWrapping;
var spacingSize = GetSpacingSize();
var childConstraint = new Size(
itemWidthSet ? itemWidth : availableSize.Width,
itemHeightSet ? itemHeight : availableSize.Height);
bool isFirst = true;
if (childWrapping == VisualWrapping.NoWrap)
{
var layoutSlotSize = new PanelUvSize(_orientation, availableSize);
if (_orientation == Orientation.Horizontal)
{
layoutSlotSize.U = double.PositiveInfinity;
}
else
{
layoutSlotSize.V = double.PositiveInfinity;
}
for (int i = 0, count = Children.Count; i < count; ++i)
{
var child = Children[i];
if (itemHorizontalAlignmentSet)
{
child.SetCurrentValue(HorizontalAlignmentProperty, itemHorizontalAlignment);
}
if (itemVerticalAlignmentSet)
{
child.SetCurrentValue(VerticalAlignmentProperty, itemVerticalAlignment);
}
child.Measure(new Size(layoutSlotSize.Width, layoutSlotSize.Height));
var sz = new PanelUvSize(
_orientation,
itemWidthSet ? itemWidth : child.DesiredSize.Width,
itemHeightSet ? itemHeight : child.DesiredSize.Height);
curLineSize.U += isFirst ? sz.U : sz.U + spacingSize.U;
curLineSize.V = Math.Max(sz.V, curLineSize.V);
isFirst = false;
}
}
else
{
for (int i = 0, count = Children.Count; i < count; i++)
{
var child = Children[i];
if (itemHorizontalAlignmentSet)
{
child.SetCurrentValue(HorizontalAlignmentProperty, itemHorizontalAlignment);
}
if (itemVerticalAlignmentSet)
{
child.SetCurrentValue(VerticalAlignmentProperty, itemVerticalAlignment);
}
child.Measure(childConstraint);
var sz = new PanelUvSize(
_orientation,
itemWidthSet ? itemWidth : child.DesiredSize.Width,
itemHeightSet ? itemHeight : child.DesiredSize.Height);
if (MathHelper.GreaterThan(curLineSize.U + sz.U + spacingSize.U, uvConstraint.U))
{
panelSize.U = Math.Max(curLineSize.U, panelSize.U);
panelSize.V += curLineSize.V + spacingSize.V;
curLineSize = sz;
if (MathHelper.GreaterThan(sz.U, uvConstraint.U))
{
panelSize.U = Math.Max(sz.U, panelSize.U);
panelSize.V += sz.V + spacingSize.V;
curLineSize = new PanelUvSize(_orientation);
}
}
else
{
curLineSize.U += isFirst ? sz.U : sz.U + spacingSize.U;
curLineSize.V = Math.Max(sz.V, curLineSize.V);
isFirst = false;
}
}
}
panelSize.U = Math.Max(curLineSize.U, panelSize.U);
panelSize.V += curLineSize.V;
return new Size(panelSize.Width, panelSize.Height);
}
protected override Size ArrangeOverride(Size finalSize)
{
int firstInLine = 0;
double itemWidth = ItemWidth;
double itemHeight = ItemHeight;
double accumulatedV = 0;
double itemU = _orientation == Orientation.Horizontal ? itemWidth : itemHeight;
var curLineSize = new PanelUvSize(_orientation);
var uvFinalSize = new PanelUvSize(_orientation, finalSize);
bool itemWidthSet = !double.IsNaN(itemWidth);
bool itemHeightSet = !double.IsNaN(itemHeight);
bool useItemU = _orientation == Orientation.Horizontal ? itemWidthSet : itemHeightSet;
var childWrapping = ChildWrapping;
var spacingSize = GetSpacingSize();
bool isFirst = true;
if (childWrapping == VisualWrapping.NoWrap)
{
ArrangeLine(uvFinalSize.V, useItemU, itemU, spacingSize.U);
}
else
{
for (int i = 0, count = Children.Count; i < count; i++)
{
var child = Children[i];
var sz = new PanelUvSize(
_orientation,
itemWidthSet ? itemWidth : child.DesiredSize.Width,
itemHeightSet ? itemHeight : child.DesiredSize.Height);
if (MathHelper.GreaterThan(curLineSize.U + (isFirst ? sz.U : sz.U + spacingSize.U), uvFinalSize.U))
{
ArrangeWrapLine(accumulatedV, curLineSize.V, firstInLine, i, useItemU, itemU, spacingSize.U);
accumulatedV += curLineSize.V + spacingSize.V;
curLineSize = sz;
firstInLine = i;
}
else
{
curLineSize.U += isFirst ? sz.U : sz.U + spacingSize.U;
curLineSize.V = Math.Max(sz.V, curLineSize.V);
}
isFirst = false;
}
if (firstInLine < Children.Count)
{
ArrangeWrapLine(accumulatedV, curLineSize.V, firstInLine, Children.Count, useItemU, itemU,
spacingSize.U);
}
}
return finalSize;
}
private PanelUvSize GetSpacingSize()
{
double spacing = Spacing;
if (!double.IsNaN(spacing))
{
return new PanelUvSize(_orientation, spacing, spacing);
}
double horizontalSpacing = HorizontalSpacing;
if (double.IsNaN(horizontalSpacing))
{
horizontalSpacing = 0;
}
double verticalSpacing = VerticalSpacing;
if (double.IsNaN(verticalSpacing))
{
verticalSpacing = 0;
}
return new PanelUvSize(_orientation, horizontalSpacing, verticalSpacing);
}
private void ArrangeLine(double lineV, bool useItemU, double itemU, double spacing)
{
double u = 0;
bool isHorizontal = _orientation == Orientation.Horizontal;
// ReSharper disable once ForCanBeConvertedToForeach
for (int i = 0; i < Children.Count; i++)
{
Control child = Children[i];
var childSize = new PanelUvSize(_orientation, child.DesiredSize);
double layoutSlotU = useItemU ? itemU : childSize.U;
child.Arrange(isHorizontal ? new Rect(u, 0, layoutSlotU, lineV) : new Rect(0, u, lineV, layoutSlotU));
if (layoutSlotU > 0)
{
u += layoutSlotU + spacing;
}
}
}
private void ArrangeWrapLine(
double v,
double lineV,
int start,
int end,
bool useItemU,
double itemU,
double spacing)
{
double u = 0;
bool isHorizontal = _orientation == Orientation.Horizontal;
for (int i = start; i < end; i++)
{
var child = Children[i];
var childSize = new PanelUvSize(_orientation, child.DesiredSize);
double layoutSlotU = useItemU ? itemU : childSize.U;
child.Arrange(isHorizontal ? new Rect(u, v, layoutSlotU, lineV) : new Rect(v, u, lineV, layoutSlotU));
if (layoutSlotU > 0)
{
u += layoutSlotU + spacing;
}
}
}
}

View File

@ -0,0 +1,7 @@
namespace HandyControl.Data;
public enum VisualWrapping
{
NoWrap,
Wrap
}

View File

@ -0,0 +1,69 @@
using Avalonia;
using Avalonia.Layout;
namespace HandyControl.Data;
internal struct PanelUvSize
{
private readonly Orientation _orientation;
public Size ScreenSize => new(U, V);
public double U { get; set; }
public double V { get; set; }
public double Width
{
get => _orientation == Orientation.Horizontal ? U : V;
private set
{
if (_orientation == Orientation.Horizontal)
{
U = value;
}
else
{
V = value;
}
}
}
public double Height
{
get => _orientation == Orientation.Horizontal ? V : U;
private set
{
if (_orientation == Orientation.Horizontal)
{
V = value;
}
else
{
U = value;
}
}
}
public PanelUvSize(Orientation orientation, double width, double height)
{
U = V = 0d;
_orientation = orientation;
Width = width;
Height = height;
}
public PanelUvSize(Orientation orientation, Size size)
{
U = V = 0d;
_orientation = orientation;
Width = size.Width;
Height = size.Height;
}
public PanelUvSize(Orientation orientation)
{
U = V = 0d;
_orientation = orientation;
}
}

View File

@ -8,7 +8,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)" />
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)"/>
</ItemGroup>
<ItemGroup>
@ -26,7 +26,4 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
</Project>

View File

@ -1,19 +1,11 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTheme x:Key="{x:Type Button}"
<ControlTheme x:Key="ButtonBaseStyle"
TargetType="Button">
<Setter Property="Background"
Value="{DynamicResource RegionBrush}" />
<Setter Property="Foreground"
Value="{DynamicResource PrimaryTextBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource BorderBrush}" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="CornerRadius"
Value="{DynamicResource DefaultCornerRadius}" />
<Setter Property="Height"
Value="{StaticResource DefaultControlHeight}" />
<Setter Property="Padding"
Value="{DynamicResource DefaultControlPadding}" />
Value="{StaticResource DefaultControlPadding}" />
<Setter Property="HorizontalAlignment"
Value="Center" />
<Setter Property="VerticalAlignment"
@ -22,8 +14,18 @@
Value="Center" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="Background"
Value="{DynamicResource RegionBrush}" />
<Setter Property="Foreground"
Value="{DynamicResource TextIconBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource BorderBrush}" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="CornerRadius"
Value="{StaticResource DefaultCornerRadius}" />
<Setter Property="Template">
<ControlTemplate TargetType="Button">
<ControlTemplate>
<ContentPresenter x:Name="PART_ContentPresenter"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
@ -38,104 +40,85 @@
</ControlTemplate>
</Setter>
<Style Selector="^:pointerover">
<Style Selector="^:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Opacity"
Value="0.9" />
</Style>
<Style Selector="^:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Opacity"
Value="0.6" />
</Style>
<Style Selector="^:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Opacity"
Value="0.4" />
</Style>
</ControlTheme>
<ControlTheme x:Key="ButtonDefault"
BasedOn="{StaticResource ButtonBaseStyle}"
TargetType="Button">
<Setter Property="Foreground"
Value="{DynamicResource PrimaryTextBrush}" />
<Style Selector="^:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background"
Value="{DynamicResource SecondaryRegionBrush}" />
</Style>
<Style Selector="^:pressed">
<Style Selector="^:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background"
Value="{DynamicResource BorderBrush}" />
</Style>
</ControlTheme>
<Style Selector="^:disabled">
<Setter Property="Opacity"
Value=".4" />
</Style>
<ControlTheme x:Key="{x:Type Button}"
BasedOn="{StaticResource ButtonDefault}"
TargetType="Button" />
<Style Selector="^.primary">
<Setter Property="Foreground"
Value="{DynamicResource TextIconBrush}" />
<Setter Property="Background"
Value="{DynamicResource PrimaryBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource PrimaryBrush}" />
<Style Selector="^:pointerover">
<Setter Property="Opacity"
Value=".9" />
</Style>
<Style Selector="^:pressed">
<Setter Property="Opacity"
Value=".6" />
</Style>
</Style>
<ControlTheme x:Key="ButtonPrimary"
BasedOn="{StaticResource ButtonBaseStyle}"
TargetType="Button">
<Setter Property="Background"
Value="{DynamicResource PrimaryBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource PrimaryBrush}" />
</ControlTheme>
<Style Selector="^.success">
<Setter Property="Foreground"
Value="{DynamicResource TextIconBrush}" />
<Setter Property="Background"
Value="{DynamicResource SuccessBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource SuccessBrush}" />
<Style Selector="^:pointerover">
<Setter Property="Opacity"
Value=".9" />
</Style>
<Style Selector="^:pressed">
<Setter Property="Opacity"
Value=".6" />
</Style>
</Style>
<ControlTheme x:Key="ButtonSuccess"
BasedOn="{StaticResource ButtonBaseStyle}"
TargetType="Button">
<Setter Property="Background"
Value="{DynamicResource SuccessBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource SuccessBrush}" />
</ControlTheme>
<Style Selector="^.info">
<Setter Property="Foreground"
Value="{DynamicResource TextIconBrush}" />
<Setter Property="Background"
Value="{DynamicResource InfoBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource InfoBrush}" />
<Style Selector="^:pointerover">
<Setter Property="Opacity"
Value=".9" />
</Style>
<Style Selector="^:pressed">
<Setter Property="Opacity"
Value=".6" />
</Style>
</Style>
<ControlTheme x:Key="ButtonInfo"
BasedOn="{StaticResource ButtonBaseStyle}"
TargetType="Button">
<Setter Property="Background"
Value="{DynamicResource InfoBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource InfoBrush}" />
</ControlTheme>
<Style Selector="^.warning">
<Setter Property="Foreground"
Value="{DynamicResource TextIconBrush}" />
<Setter Property="Background"
Value="{DynamicResource WarningBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource WarningBrush}" />
<Style Selector="^:pointerover">
<Setter Property="Opacity"
Value=".9" />
</Style>
<Style Selector="^:pressed">
<Setter Property="Opacity"
Value=".6" />
</Style>
</Style>
<ControlTheme x:Key="ButtonWarning"
BasedOn="{StaticResource ButtonBaseStyle}"
TargetType="Button">
<Setter Property="Background"
Value="{DynamicResource WarningBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource WarningBrush}" />
</ControlTheme>
<Style Selector="^.danger">
<Setter Property="Foreground"
Value="{DynamicResource TextIconBrush}" />
<Setter Property="Background"
Value="{DynamicResource DangerBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource DangerBrush}" />
<Style Selector="^:pointerover">
<Setter Property="Opacity"
Value=".9" />
</Style>
<Style Selector="^:pressed">
<Setter Property="Opacity"
Value=".6" />
</Style>
</Style>
<ControlTheme x:Key="ButtonDanger"
BasedOn="{StaticResource ButtonBaseStyle}"
TargetType="Button">
<Setter Property="Background"
Value="{DynamicResource DangerBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource DangerBrush}" />
</ControlTheme>
</ResourceDictionary>

View File

@ -0,0 +1,94 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTheme x:Key="LabelBaseStyle"
TargetType="Label">
<Setter Property="Foreground"
Value="{DynamicResource TextIconBrush}" />
<Setter Property="Background"
Value="{DynamicResource RegionBrush}" />
<Setter Property="BorderBrush"
Value="{DynamicResource BorderBrush}" />
<Setter Property="CornerRadius"
Value="{StaticResource DefaultCornerRadius}" />
<Setter Property="Padding"
Value="{StaticResource DefaultControlPadding}" />
<Setter Property="HorizontalContentAlignment"
Value="Center" />
<Setter Property="VerticalContentAlignment"
Value="Center" />
<Setter Property="HorizontalAlignment"
Value="Center" />
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="Height"
Value="{StaticResource DefaultControlHeight}" />
<Setter Property="Template">
<ControlTemplate>
<ContentPresenter Name="PART_ContentPresenter"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
CornerRadius="{TemplateBinding CornerRadius}"
RecognizesAccessKey="True" />
</ControlTemplate>
</Setter>
<Style Selector="^:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Opacity"
Value="0.4" />
</Style>
</ControlTheme>
<ControlTheme x:Key="LabelDefault"
BasedOn="{StaticResource LabelBaseStyle}"
TargetType="Label">
<Setter Property="Foreground"
Value="{DynamicResource PrimaryTextBrush}" />
<Setter Property="BorderThickness"
Value="1" />
</ControlTheme>
<ControlTheme x:Key="{x:Type Label}"
BasedOn="{StaticResource LabelDefault}"
TargetType="Label" />
<ControlTheme x:Key="LabelPrimary"
BasedOn="{StaticResource LabelBaseStyle}"
TargetType="Label">
<Setter Property="Background"
Value="{DynamicResource PrimaryBrush}" />
</ControlTheme>
<ControlTheme x:Key="LabelSuccess"
BasedOn="{StaticResource LabelBaseStyle}"
TargetType="Label">
<Setter Property="Background"
Value="{DynamicResource SuccessBrush}" />
</ControlTheme>
<ControlTheme x:Key="LabelInfo"
BasedOn="{StaticResource LabelBaseStyle}"
TargetType="Label">
<Setter Property="Background"
Value="{DynamicResource InfoBrush}" />
</ControlTheme>
<ControlTheme x:Key="LabelWarning"
BasedOn="{StaticResource LabelBaseStyle}"
TargetType="Label">
<Setter Property="Background"
Value="{DynamicResource WarningBrush}" />
</ControlTheme>
<ControlTheme x:Key="LabelDanger"
BasedOn="{StaticResource LabelBaseStyle}"
TargetType="Label">
<Setter Property="Background"
Value="{DynamicResource DangerBrush}" />
</ControlTheme>
</ResourceDictionary>

View File

@ -8,6 +8,8 @@
Value="{DynamicResource BorderBrush}" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="CornerRadius"
Value="{StaticResource DefaultCornerRadius}" />
<Setter Property="Padding"
Value="4" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility"

View File

@ -1,5 +1,6 @@
<ResourceDictionary xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:hc="clr-namespace:HandyControl.Controls">
<ControlTheme x:Key="{x:Type ListBoxItem}"
TargetType="ListBoxItem">
<Setter Property="Padding"
@ -12,6 +13,8 @@
Value="{DynamicResource RegionBrush}" />
<Setter Property="BorderBrush"
Value="Transparent" />
<Setter Property="CornerRadius"
Value="{StaticResource DefaultCornerRadius}" />
<Setter Property="BorderThickness"
Value="0" />
<Setter Property="Margin"
@ -33,27 +36,14 @@
<Style Selector="^:pointerover /template/ ContentPresenter">
<Setter Property="Background"
Value="{DynamicResource ThemeControlHighlightMidBrush}" />
Value="{DynamicResource SecondaryRegionBrush}" />
</Style>
<Style Selector="^:selected /template/ ContentPresenter">
<Setter Property="Background"
Value="{DynamicResource ThemeAccentBrush4}" />
</Style>
<Style Selector="^:selected:focus /template/ ContentPresenter">
<Setter Property="Background"
Value="{DynamicResource ThemeAccentBrush3}" />
</Style>
<Style Selector="^:selected:pointerover /template/ ContentPresenter">
<Setter Property="Background"
Value="{DynamicResource ThemeAccentBrush3}" />
</Style>
<Style Selector="^:selected:focus:pointerover /template/ ContentPresenter">
<Setter Property="Background"
Value="{DynamicResource ThemeAccentBrush2}" />
Value="{DynamicResource PrimaryBrush}" />
<Setter Property="Foreground"
Value="{DynamicResource TextIconBrush}" />
</Style>
</ControlTheme>
</ResourceDictionary>

View File

@ -17,6 +17,7 @@
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/ListBox.axaml" />
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/ScrollBar.axaml" />
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/ScrollViewer.axaml" />
<MergeResourceInclude Source="avares://HandyControl/Themes/Styles/Label.axaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Styles.Resources>

View File

@ -2,69 +2,73 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ControlTheme x:Key="{x:Type TabControl}"
TargetType="TabControl">
<Setter Property="Padding"
Value="8" />
<Setter Property="BorderBrush"
Value="{DynamicResource BorderBrush}" />
<Setter Property="Background"
Value="{DynamicResource RegionBrush}" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="Template">
<ControlTemplate>
<Border Padding="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<DockPanel>
<ItemsPresenter Name="PART_ItemsPresenter"
ItemsPanel="{TemplateBinding ItemsPanel}" />
<DockPanel>
<ItemsPresenter Name="PART_ItemsPresenter"
ItemsPanel="{TemplateBinding ItemsPanel}" />
<Border Padding="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<ContentPresenter Name="PART_SelectedContentHost"
Margin="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding SelectedContent}"
ContentTemplate="{TemplateBinding SelectedContentTemplate}" />
</DockPanel>
</Border>
</Border>
</DockPanel>
</ControlTemplate>
</Setter>
<Style Selector="^[TabStripPlacement=Top]">
<Setter Property="Padding"
Value="0 4 0 0" />
</Style>
<Style Selector="^[TabStripPlacement=Top] /template/ ItemsPresenter#PART_ItemsPresenter">
<Setter Property="DockPanel.Dock"
Value="Top" />
</Style>
<Style Selector="^[TabStripPlacement=Bottom] /template/ ItemsPresenter#PART_ItemsPresenter">
<Setter Property="DockPanel.Dock"
Value="Bottom" />
</Style>
<Style Selector="^[TabStripPlacement=Bottom]">
<Setter Property="Padding"
Value="0 0 0 4" />
</Style>
<Style Selector="^[TabStripPlacement=Left] /template/ ItemsPresenter#PART_ItemsPresenter">
<Setter Property="DockPanel.Dock"
Value="Left" />
</Style>
<Style Selector="^[TabStripPlacement=Left] /template/ ItemsPresenter#PART_ItemsPresenter > WrapPanel">
<Setter Property="Orientation"
Value="Vertical" />
</Style>
<Style Selector="^[TabStripPlacement=Left]">
<Setter Property="Padding"
Value="4 0 0 0" />
</Style>
<Style Selector="^[TabStripPlacement=Right] /template/ ItemsPresenter#PART_ItemsPresenter">
<Setter Property="DockPanel.Dock"
Value="Right" />
</Style>
<Style Selector="^[TabStripPlacement=Right] /template/ ItemsPresenter#PART_ItemsPresenter > WrapPanel">
<Setter Property="Orientation"
Value="Vertical" />
</Style>
<Style Selector="^[TabStripPlacement=Right]">
<Setter Property="Padding"
Value="0 0 4 0" />
<Style Selector="^.inline">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<UniformGrid Rows="1"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</ControlTheme>
</ResourceDictionary>

View File

@ -15,31 +15,42 @@
<Setter Property="MinHeight"
Value="{StaticResource DefaultControlHeight}" />
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
Value="Center" />
<Setter Property="VerticalContentAlignment"
Value="Stretch" />
Value="Center" />
<Setter Property="Template">
<ControlTemplate TargetType="TabItem">
<Border Name="PART_LayoutRoot"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"
Padding="{TemplateBinding Padding}">
<Panel>
<ContentPresenter Name="PART_ContentPresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
RecognizesAccessKey="True" />
<Border Name="PART_SelectedPipe"
Background="{DynamicResource TabItemHeaderSelectedPipeFill}"
CornerRadius="{DynamicResource ControlCornerRadius}"
IsVisible="False" />
</Panel>
</Border>
<ControlTemplate>
<Panel>
<Border Name="mainBorder"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="0"
Background="{TemplateBinding Background}"
Margin="0" />
<ContentPresenter Name="PART_ContentPresenter"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
CornerRadius="{TemplateBinding CornerRadius}"
RecognizesAccessKey="True" />
</Panel>
</ControlTemplate>
</Setter>
<Style Selector="^:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Opacity"
Value="0.4" />
</Style>
<Style Selector="^:selected /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground"
Value="{DynamicResource PrimaryBrush}" />
</Style>
<Style Selector="^:selected /template/ Border#mainBorder">
<Setter Property="BorderThickness"
Value="0,0,0,2" />
</Style>
</ControlTheme>
</ResourceDictionary>

View File

@ -12,7 +12,7 @@
<Setter Property="Foreground"
Value="{DynamicResource PrimaryTextBrush}" />
<Setter Property="FontSize"
Value="13" />
Value="12" />
<Setter Property="Template">
<ControlTemplate TargetType="Window">
<Panel>

View File

@ -0,0 +1,16 @@
using System;
namespace HandyControl.Tools;
internal static class MathHelper
{
public const double Epsilon = 2.2204460492503131e-016;
public static bool AreClose(double value1, double value2) =>
// ReSharper disable once CompareOfFloatsByEqualityOperator
value1 == value2 || IsVerySmall(value1 - value2);
public static bool IsVerySmall(double value) => Math.Abs(value) < 1E-06;
public static bool GreaterThan(double value1, double value2) => value1 > value2 && !AreClose(value1, value2);
}

View File

@ -10720,8 +10720,8 @@
<RowDefinition x:Name="RowDefinition0" Height="Auto" />
<RowDefinition x:Name="RowDefinition1" Height="*" />
</Grid.RowDefinitions>
<TabPanel x:Name="headerPanel" Background="Transparent" Grid.Column="0" IsItemsHost="true" Margin="0" Grid.Row="0" />
<Border x:Name="contentPanel" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{DynamicResource BorderBrush}" Background="{TemplateBinding Background}" Grid.Column="0" Grid.Row="1">
<TabPanel x:Name="headerPanel" Background="Transparent" IsItemsHost="true" Margin="0" Grid.Row="0" />
<Border x:Name="contentPanel" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{DynamicResource BorderBrush}" Background="{TemplateBinding Background}" Grid.Row="1">
<ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</Grid>

View File

@ -9,16 +9,12 @@ namespace HandyControl.Controls;
public class UniformSpacingPanel : Panel
{
private Orientation _orientation;
public UniformSpacingPanel()
{
_orientation = Orientation.Horizontal;
}
private Orientation _orientation = Orientation.Horizontal;
public static readonly DependencyProperty OrientationProperty =
StackPanel.OrientationProperty.AddOwner(typeof(UniformSpacingPanel),
new FrameworkPropertyMetadata(Orientation.Horizontal, FrameworkPropertyMetadataOptions.AffectsMeasure, OnOrientationChanged));
new FrameworkPropertyMetadata(Orientation.Horizontal, FrameworkPropertyMetadataOptions.AffectsMeasure,
OnOrientationChanged));
private static void OnOrientationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
@ -132,7 +128,8 @@ public class UniformSpacingPanel : Panel
return false;
}
private void ArrangeWrapLine(double v, double lineV, int start, int end, bool useItemU, double itemU, double spacing)
private void ArrangeWrapLine(double v, double lineV, int start, int end, bool useItemU, double itemU,
double spacing)
{
double u = 0;
var isHorizontal = _orientation == Orientation.Horizontal;
@ -191,7 +188,7 @@ public class UniformSpacingPanel : Panel
var itemHorizontalAlignment = ItemHorizontalAlignment;
var itemVerticalAlignment = ItemVerticalAlignment;
var itemHorizontalAlignmentSet = itemHorizontalAlignment != null;
var itemVerticalAlignmentSet = ItemVerticalAlignment != null;
var itemVerticalAlignmentSet = itemVerticalAlignment != null;
var spacingSize = GetSpacingSize();
var childConstraint = new Size(
@ -201,7 +198,48 @@ public class UniformSpacingPanel : Panel
var children = InternalChildren;
var isFirst = true;
if (childWrapping == VisualWrapping.Wrap)
if (childWrapping == VisualWrapping.NoWrap)
{
var layoutSlotSize = constraint;
if (_orientation == Orientation.Horizontal)
{
layoutSlotSize.Width = double.PositiveInfinity;
}
else
{
layoutSlotSize.Height = double.PositiveInfinity;
}
for (int i = 0, count = children.Count; i < count; ++i)
{
var child = children[i];
if (child == null) continue;
if (itemHorizontalAlignmentSet)
{
child.SetCurrentValue(HorizontalAlignmentProperty, itemHorizontalAlignment);
}
if (itemVerticalAlignmentSet)
{
child.SetCurrentValue(VerticalAlignmentProperty, itemVerticalAlignment);
}
child.Measure(layoutSlotSize);
var sz = new PanelUvSize(
_orientation,
itemWidthSet ? itemWidth : child.DesiredSize.Width,
itemHeightSet ? itemHeight : child.DesiredSize.Height);
curLineSize.U += isFirst ? sz.U : sz.U + spacingSize.U;
curLineSize.V = Math.Max(sz.V, curLineSize.V);
isFirst = false;
}
}
else
{
for (int i = 0, count = children.Count; i < count; i++)
{
@ -247,47 +285,6 @@ public class UniformSpacingPanel : Panel
}
}
}
else
{
var layoutSlotSize = constraint;
if (_orientation == Orientation.Horizontal)
{
layoutSlotSize.Width = double.PositiveInfinity;
}
else
{
layoutSlotSize.Height = double.PositiveInfinity;
}
for (int i = 0, count = children.Count; i < count; ++i)
{
var child = children[i];
if (child == null) continue;
if (itemHorizontalAlignmentSet)
{
child.SetCurrentValue(HorizontalAlignmentProperty, itemHorizontalAlignment);
}
if (itemVerticalAlignmentSet)
{
child.SetCurrentValue(VerticalAlignmentProperty, itemVerticalAlignment);
}
child.Measure(layoutSlotSize);
var sz = new PanelUvSize(
_orientation,
itemWidthSet ? itemWidth : child.DesiredSize.Width,
itemHeightSet ? itemHeight : child.DesiredSize.Height);
curLineSize.U += isFirst ? sz.U : sz.U + spacingSize.U;
curLineSize.V = Math.Max(sz.V, curLineSize.V);
isFirst = false;
}
}
panelSize.U = Math.Max(curLineSize.U, panelSize.U);
panelSize.V += curLineSize.V;
@ -337,7 +334,11 @@ public class UniformSpacingPanel : Panel
var children = InternalChildren;
var isFirst = true;
if (childWrapping == VisualWrapping.Wrap)
if (childWrapping == VisualWrapping.NoWrap)
{
ArrangeLine(uvFinalSize.V, useItemU, itemU, spacingSize.U);
}
else
{
for (int i = 0, count = children.Count; i < count; i++)
{
@ -369,13 +370,10 @@ public class UniformSpacingPanel : Panel
if (firstInLine < children.Count)
{
ArrangeWrapLine(accumulatedV, curLineSize.V, firstInLine, children.Count, useItemU, itemU, spacingSize.U);
ArrangeWrapLine(accumulatedV, curLineSize.V, firstInLine, children.Count, useItemU, itemU,
spacingSize.U);
}
}
else
{
ArrangeLine(uvFinalSize.V, useItemU, itemU, spacingSize.U);
}
return finalSize;
}