mirror of
https://gitee.com/chinware/atomui.git
synced 2024-11-29 18:38:16 +08:00
feat: 添加BoxPanel组件
This commit is contained in:
parent
62be8f3443
commit
d0d20b4106
209
src/AtomUI.Controls/BoxPanel/BoxPanel.cs
Normal file
209
src/AtomUI.Controls/BoxPanel/BoxPanel.cs
Normal file
@ -0,0 +1,209 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Layout;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class BoxPanel : Panel
|
||||
{
|
||||
|
||||
#region 公共属性定义
|
||||
public static readonly StyledProperty<Orientation> OrientationProperty =
|
||||
AvaloniaProperty.Register<BoxPanel, Orientation>(nameof(Orientation), Orientation.Vertical);
|
||||
|
||||
public static readonly StyledProperty<double> SpacingProperty =
|
||||
AvaloniaProperty.Register<BoxPanel, double>(nameof(Spacing), 0.0);
|
||||
|
||||
public static readonly AttachedProperty<int> FlexProperty =
|
||||
AvaloniaProperty.RegisterAttached<BoxPanel, Control, int>("Flex", 0);
|
||||
|
||||
#endregion
|
||||
|
||||
public Orientation Orientation
|
||||
{
|
||||
get => GetValue(OrientationProperty);
|
||||
set => SetValue(OrientationProperty, value);
|
||||
}
|
||||
|
||||
public double Spacing
|
||||
{
|
||||
get => GetValue(SpacingProperty);
|
||||
set => SetValue(SpacingProperty, value);
|
||||
}
|
||||
|
||||
public static void SetFlex(Control element, int value)
|
||||
{
|
||||
element.SetValue(FlexProperty, value);
|
||||
}
|
||||
|
||||
public static int GetFlex(Control element)
|
||||
{
|
||||
return element.GetValue(FlexProperty);
|
||||
}
|
||||
|
||||
static BoxPanel()
|
||||
{
|
||||
AffectsMeasure<BoxPanel>(OrientationProperty, SpacingProperty, FlexProperty);
|
||||
AffectsArrange<BoxPanel>(OrientationProperty, SpacingProperty, FlexProperty);
|
||||
|
||||
((IObservable<AvaloniaPropertyChangedEventArgs>)FlexProperty.Changed)
|
||||
.AddClassHandler<Control>(
|
||||
new Action<Control, AvaloniaPropertyChangedEventArgs>(OnFlexPropertyChanged));
|
||||
}
|
||||
|
||||
private static void OnFlexPropertyChanged(Control control, AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
var parentBoxPanel = control.Parent as BoxPanel;
|
||||
if (parentBoxPanel != null)
|
||||
{
|
||||
parentBoxPanel.InvalidateMeasure();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddSpacing(double size)
|
||||
{
|
||||
var spacer = new Border
|
||||
{
|
||||
Width = Orientation == Orientation.Horizontal ? size : 0,
|
||||
Height = Orientation == Orientation.Vertical ? size : 0
|
||||
};
|
||||
Children.Add(spacer);
|
||||
}
|
||||
|
||||
public void AddFlex(int flex)
|
||||
{
|
||||
var spacer = new Border();
|
||||
SetFlex(spacer, flex);
|
||||
Children.Add(spacer);
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
double totalWidth = 0;
|
||||
double totalHeight = 0;
|
||||
double maxWidth = 0;
|
||||
double maxHeight = 0;
|
||||
double spacing = Spacing;
|
||||
int visibleChildren = 0;
|
||||
|
||||
foreach (var child in Children)
|
||||
{
|
||||
if (!child.IsVisible)
|
||||
continue;
|
||||
|
||||
child.Measure(availableSize);
|
||||
var desired = child.DesiredSize;
|
||||
|
||||
if (Orientation == Orientation.Vertical)
|
||||
{
|
||||
totalHeight += desired.Height;
|
||||
maxWidth = Math.Max(maxWidth, desired.Width);
|
||||
}
|
||||
else
|
||||
{
|
||||
totalWidth += desired.Width;
|
||||
maxHeight = Math.Max(maxHeight, desired.Height);
|
||||
}
|
||||
|
||||
visibleChildren++;
|
||||
}
|
||||
|
||||
// Add spacing
|
||||
if (visibleChildren > 1)
|
||||
{
|
||||
if (Orientation == Orientation.Vertical)
|
||||
{
|
||||
totalHeight += spacing * (visibleChildren - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
totalWidth += spacing * (visibleChildren - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (Orientation == Orientation.Vertical)
|
||||
{
|
||||
double desiredWidth = double.IsInfinity(availableSize.Width) ? maxWidth : availableSize.Width;
|
||||
return new Size(desiredWidth, totalHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
double desiredHeight = double.IsInfinity(availableSize.Height) ? maxHeight : availableSize.Height;
|
||||
return new Size(totalWidth, desiredHeight);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
double offset = 0;
|
||||
double spacing = Spacing;
|
||||
double totalFlex = 0;
|
||||
double originTotalWidth = 0;
|
||||
double originTotalHeight = 0;
|
||||
int visibleChildren = 0;
|
||||
|
||||
|
||||
foreach (var child in Children)
|
||||
{
|
||||
if (!child.IsVisible)
|
||||
continue;
|
||||
|
||||
visibleChildren++;
|
||||
int childFlex = GetFlex(child);
|
||||
totalFlex += childFlex;
|
||||
if (childFlex == 0)
|
||||
{
|
||||
if (Orientation == Orientation.Horizontal)
|
||||
{
|
||||
originTotalWidth += child.DesiredSize.Width;
|
||||
} else
|
||||
{
|
||||
originTotalHeight += child.DesiredSize.Height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Orientation == Orientation.Horizontal)
|
||||
{
|
||||
originTotalWidth += spacing * (visibleChildren - 1);
|
||||
} else
|
||||
{
|
||||
originTotalHeight += spacing * (visibleChildren - 1);
|
||||
}
|
||||
|
||||
|
||||
foreach (var child in Children)
|
||||
{
|
||||
if (!child.IsVisible)
|
||||
continue;
|
||||
|
||||
int flex = GetFlex(child);
|
||||
double allocatedSize = (totalFlex > 0)
|
||||
? (Orientation == Orientation.Vertical ? finalSize.Height - originTotalHeight : finalSize.Width - originTotalWidth) *
|
||||
(flex / (double)totalFlex)
|
||||
: 0;
|
||||
|
||||
if (Orientation == Orientation.Vertical)
|
||||
{
|
||||
double height = allocatedSize > 0 ? allocatedSize : child.DesiredSize.Height;
|
||||
double width = finalSize.Width;
|
||||
|
||||
var rect = new Rect(0, offset, width, height);
|
||||
|
||||
child.Arrange(rect);
|
||||
offset += height + spacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
double width = allocatedSize > 0 ? allocatedSize : child.DesiredSize.Width;
|
||||
double height = finalSize.Height;
|
||||
|
||||
var rect = new Rect(offset, 0, width, height);
|
||||
child.Arrange(rect);
|
||||
offset += width + spacing;
|
||||
}
|
||||
}
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
}
|
9
src/AtomUI.Controls/BoxPanel/HBoxPanel.cs
Normal file
9
src/AtomUI.Controls/BoxPanel/HBoxPanel.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class HBoxPanel: BoxPanel
|
||||
{
|
||||
public HBoxPanel()
|
||||
{
|
||||
Orientation = Avalonia.Layout.Orientation.Horizontal;
|
||||
}
|
||||
}
|
9
src/AtomUI.Controls/BoxPanel/VBoxPanel.cs
Normal file
9
src/AtomUI.Controls/BoxPanel/VBoxPanel.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class VBoxPanel: BoxPanel
|
||||
{
|
||||
public VBoxPanel()
|
||||
{
|
||||
Orientation = Avalonia.Layout.Orientation.Vertical;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user