This commit is contained in:
NaBian 2021-09-22 21:33:37 +08:00
commit da01b19c07
11 changed files with 280 additions and 150 deletions

View File

@ -1,13 +1,13 @@
<Project>
<PropertyGroup>
<UseWPF>true</UseWPF>
<Version>3.2.0.0</Version>
<FileVersion>3.2.0.0</FileVersion>
<AssemblyVersion>3.2.0.0</AssemblyVersion>
<Version>3.3.0.0</Version>
<FileVersion>3.3.0.0</FileVersion>
<AssemblyVersion>3.3.0.0</AssemblyVersion>
<LangVersion>latest</LangVersion>
<Copyright>Copyright © HandyOrg 2018-2021</Copyright>
<Authors>HandyOrg</Authors>
<RepositoryUrl>https://github.com/HandyOrg/HandyControl</RepositoryUrl>
<PackageProjectUrl>https://handyorg.github.io/</PackageProjectUrl>
</PropertyGroup>
</Project>
</Project>

View File

@ -25,6 +25,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HandyControlDemo_Code", "Sh
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Microsoft.Windows.Shell", "Shared\Microsoft.Windows.Shell\Microsoft.Windows.Shell.shproj", "{BBE51380-8B21-49FF-9CFC-B29447A40999}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7F52CFD3-EF6C-4D3C-A9D4-B25BF726382A}"
ProjectSection(SolutionItems) = preProject
Directory.Build.Props = Directory.Build.Props
EndProjectSection
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
Shared\HandyControl_Shared\HandyControl_Shared.projitems*{32204503-2ef0-4681-ae13-aa1feb6c658a}*SharedItemsImports = 5

View File

@ -4,7 +4,6 @@ using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;
using HandyControl.Expression.Drawing;
using HandyControl.Tools;
namespace HandyControl.Controls
{
@ -45,8 +44,7 @@ namespace HandyControl.Controls
public static readonly DependencyProperty SpacingProperty = DependencyProperty.Register(
"Spacing", typeof(double), typeof(UniformSpacingPanel),
new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsMeasure),
ValidateHelper.IsInRangeOfPosDoubleIncludeZero);
new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure), IsSpacingValid);
public double Spacing
{
@ -54,6 +52,26 @@ namespace HandyControl.Controls
set => SetValue(SpacingProperty, value);
}
public static readonly DependencyProperty HorizontalSpacingProperty = DependencyProperty.Register(
"HorizontalSpacing", typeof(double), typeof(UniformSpacingPanel),
new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure), IsSpacingValid);
public double HorizontalSpacing
{
get => (double) GetValue(HorizontalSpacingProperty);
set => SetValue(HorizontalSpacingProperty, value);
}
public static readonly DependencyProperty VerticalSpacingProperty = DependencyProperty.Register(
"VerticalSpacing", typeof(double), typeof(UniformSpacingPanel),
new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure), IsSpacingValid);
public double VerticalSpacing
{
get => (double) GetValue(VerticalSpacingProperty);
set => SetValue(VerticalSpacingProperty, value);
}
public static readonly DependencyProperty ItemWidthProperty = DependencyProperty.Register(
"ItemWidth", typeof(double), typeof(UniformSpacingPanel),
new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure),
@ -78,12 +96,6 @@ namespace HandyControl.Controls
set => SetValue(ItemHeightProperty, value);
}
private static bool IsWidthHeightValid(object value)
{
var v = (double) value;
return double.IsNaN(v) || v >= 0.0d && !double.IsPositiveInfinity(v);
}
public static readonly DependencyProperty ItemHorizontalAlignmentProperty = DependencyProperty.Register(
"ItemHorizontalAlignment", typeof(HorizontalAlignment?), typeof(UniformSpacingPanel),
new FrameworkPropertyMetadata(HorizontalAlignment.Stretch, FrameworkPropertyMetadataOptions.AffectsMeasure));
@ -104,6 +116,22 @@ namespace HandyControl.Controls
set => SetValue(ItemVerticalAlignmentProperty, value);
}
private static bool IsWidthHeightValid(object value)
{
var v = (double) value;
return double.IsNaN(v) || v >= 0.0d && !double.IsPositiveInfinity(v);
}
private static bool IsSpacingValid(object value)
{
if (value is double spacing)
{
return double.IsNaN(spacing) || spacing > 0;
}
return false;
}
private void ArrangeWrapLine(double v, double lineV, int start, int end, bool useItemU, double itemU, double spacing)
{
double u = 0;
@ -115,7 +143,7 @@ namespace HandyControl.Controls
var child = children[i];
if (child == null) continue;
var childSize = new UVSize(_orientation, child.DesiredSize.Width, child.DesiredSize.Height);
var childSize = new PanelUvSize(_orientation, child.DesiredSize);
var layoutSlotU = useItemU ? itemU : childSize.U;
child.Arrange(isHorizontal ? new Rect(u, v, layoutSlotU, lineV) : new Rect(v, u, lineV, layoutSlotU));
@ -138,7 +166,7 @@ namespace HandyControl.Controls
var child = children[i];
if (child == null) continue;
var childSize = new UVSize(_orientation, child.DesiredSize.Width, child.DesiredSize.Height);
var childSize = new PanelUvSize(_orientation, child.DesiredSize);
var layoutSlotU = useItemU ? itemU : childSize.U;
child.Arrange(isHorizontal ? new Rect(u, 0, layoutSlotU, lineV) : new Rect(0, u, lineV, layoutSlotU));
@ -152,19 +180,19 @@ namespace HandyControl.Controls
protected override Size MeasureOverride(Size constraint)
{
var curLineSize = new UVSize(_orientation);
var panelSize = new UVSize(_orientation);
var uvConstraint = new UVSize(_orientation, constraint.Width, constraint.Height);
var curLineSize = new PanelUvSize(_orientation);
var panelSize = new PanelUvSize(_orientation);
var uvConstraint = new PanelUvSize(_orientation, constraint);
var itemWidth = ItemWidth;
var itemHeight = ItemHeight;
var itemWidthSet = !double.IsNaN(itemWidth);
var itemHeightSet = !double.IsNaN(itemHeight);
var spacing = Spacing;
var childWrapping = ChildWrapping;
var itemHorizontalAlignment = ItemHorizontalAlignment;
var itemVerticalAlignment = ItemVerticalAlignment;
var itemHorizontalAlignmentSet = itemHorizontalAlignment != null;
var itemVerticalAlignmentSet = ItemVerticalAlignment != null;
var spacingSize = GetSpacingSize();
var childConstraint = new Size(
itemWidthSet ? itemWidth : constraint.Width,
@ -192,29 +220,29 @@ namespace HandyControl.Controls
child.Measure(childConstraint);
var sz = new UVSize(
var sz = new PanelUvSize(
_orientation,
itemWidthSet ? itemWidth : child.DesiredSize.Width,
itemHeightSet ? itemHeight : child.DesiredSize.Height);
if (MathHelper.GreaterThan(curLineSize.U + sz.U + spacing, uvConstraint.U))
if (MathHelper.GreaterThan(curLineSize.U + sz.U + spacingSize.U, uvConstraint.U))
{
panelSize.U = Math.Max(curLineSize.U, panelSize.U);
panelSize.V += curLineSize.V + spacing;
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 + spacing;
curLineSize = new UVSize(_orientation);
panelSize.V += sz.V + spacingSize.V;
curLineSize = new PanelUvSize(_orientation);
}
isFirst = true;
}
else
{
curLineSize.U += isFirst ? sz.U : sz.U + spacing;
curLineSize.U += isFirst ? sz.U : sz.U + spacingSize.U;
curLineSize.V = Math.Max(sz.V, curLineSize.V);
isFirst = false;
@ -251,12 +279,12 @@ namespace HandyControl.Controls
child.Measure(layoutSlotSize);
var sz = new UVSize(
var sz = new PanelUvSize(
_orientation,
itemWidthSet ? itemWidth : child.DesiredSize.Width,
itemHeightSet ? itemHeight : child.DesiredSize.Height);
curLineSize.U += isFirst ? sz.U : sz.U + spacing;
curLineSize.U += isFirst ? sz.U : sz.U + spacingSize.U;
curLineSize.V = Math.Max(sz.V, curLineSize.V);
isFirst = false;
@ -269,6 +297,30 @@ namespace HandyControl.Controls
return new Size(panelSize.Width, panelSize.Height);
}
private PanelUvSize GetSpacingSize()
{
var spacing = Spacing;
if (!double.IsNaN(spacing))
{
return new PanelUvSize(_orientation, spacing, spacing);
}
var horizontalSpacing = HorizontalSpacing;
if (double.IsNaN(horizontalSpacing))
{
horizontalSpacing = 0;
}
var verticalSpacing = VerticalSpacing;
if (double.IsNaN(verticalSpacing))
{
verticalSpacing = 0;
}
return new PanelUvSize(_orientation, horizontalSpacing, verticalSpacing);
}
protected override Size ArrangeOverride(Size finalSize)
{
var firstInLine = 0;
@ -276,13 +328,13 @@ namespace HandyControl.Controls
var itemHeight = ItemHeight;
double accumulatedV = 0;
var itemU = _orientation == Orientation.Horizontal ? itemWidth : itemHeight;
var curLineSize = new UVSize(_orientation);
var uvFinalSize = new UVSize(_orientation, finalSize.Width, finalSize.Height);
var curLineSize = new PanelUvSize(_orientation);
var uvFinalSize = new PanelUvSize(_orientation, finalSize);
var itemWidthSet = !double.IsNaN(itemWidth);
var itemHeightSet = !double.IsNaN(itemHeight);
var useItemU = _orientation == Orientation.Horizontal ? itemWidthSet : itemHeightSet;
var spacing = Spacing;
var childWrapping = ChildWrapping;
var spacingSize = GetSpacingSize();
var children = InternalChildren;
var isFirst = true;
@ -294,104 +346,40 @@ namespace HandyControl.Controls
var child = children[i];
if (child == null) continue;
var sz = new UVSize(
var sz = new PanelUvSize(
_orientation,
itemWidthSet ? itemWidth : child.DesiredSize.Width,
itemHeightSet ? itemHeight : child.DesiredSize.Height);
if (MathHelper.GreaterThan(curLineSize.U + sz.U + spacing, uvFinalSize.U))
if (MathHelper.GreaterThan(curLineSize.U + (isFirst ? sz.U : sz.U + spacingSize.U), uvFinalSize.U))
{
ArrangeWrapLine(accumulatedV, curLineSize.V, firstInLine, i, useItemU, itemU, spacing);
ArrangeWrapLine(accumulatedV, curLineSize.V, firstInLine, i, useItemU, itemU, spacingSize.U);
accumulatedV += curLineSize.V + spacing;
accumulatedV += curLineSize.V + spacingSize.V;
curLineSize = sz;
if (MathHelper.GreaterThan(sz.U, uvFinalSize.U))
{
ArrangeWrapLine(accumulatedV, sz.V, i, ++i, useItemU, itemU, spacing);
accumulatedV += sz.V + spacing;
curLineSize = new UVSize(_orientation);
}
firstInLine = i;
isFirst = true;
}
else
{
curLineSize.U += isFirst ? sz.U : sz.U + spacing;
curLineSize.U += isFirst ? sz.U : sz.U + spacingSize.U;
curLineSize.V = Math.Max(sz.V, curLineSize.V);
isFirst = false;
}
isFirst = false;
}
if (firstInLine < children.Count)
{
ArrangeWrapLine(accumulatedV, curLineSize.V, firstInLine, children.Count, useItemU, itemU, spacing);
ArrangeWrapLine(accumulatedV, curLineSize.V, firstInLine, children.Count, useItemU, itemU, spacingSize.U);
}
}
else
{
ArrangeLine(uvFinalSize.V, useItemU, itemU, spacing);
ArrangeLine(uvFinalSize.V, useItemU, itemU, spacingSize.U);
}
return finalSize;
}
private struct UVSize
{
internal UVSize(Orientation orientation, double width, double height)
{
U = V = 0d;
_orientation = orientation;
Width = width;
Height = height;
}
internal UVSize(Orientation orientation)
{
U = V = 0d;
_orientation = orientation;
}
public double U { get; set; }
public double V { get; set; }
private readonly Orientation _orientation;
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;
}
}
}
}
}
}

View File

@ -2,6 +2,8 @@
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;
using HandyControl.Expression.Drawing;
using HandyControl.Tools;
namespace HandyControl.Controls
{
@ -19,9 +21,30 @@ namespace HandyControl.Controls
private static bool IsGroupsValid(object value) => (int) value >= 1;
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
"Orientation", typeof(Orientation), typeof(WaterfallPanel), new FrameworkPropertyMetadata(
Orientation.Horizontal, FrameworkPropertyMetadataOptions.AffectsMeasure));
public static readonly DependencyProperty AutoGroupProperty = DependencyProperty.Register(
"AutoGroup", typeof(bool), typeof(WaterfallPanel), new FrameworkPropertyMetadata(
ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsMeasure));
public bool AutoGroup
{
get => (bool) GetValue(AutoGroupProperty);
set => SetValue(AutoGroupProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty DesiredLengthProperty = DependencyProperty.Register(
"DesiredLength", typeof(double), typeof(WaterfallPanel), new FrameworkPropertyMetadata(ValueBoxes.Double0Box,
FrameworkPropertyMetadataOptions.AffectsMeasure), ValidateHelper.IsInRangeOfPosDoubleIncludeZero);
public double DesiredLength
{
get => (double) GetValue(DesiredLengthProperty);
set => SetValue(DesiredLengthProperty, value);
}
public static readonly DependencyProperty OrientationProperty =
StackPanel.OrientationProperty.AddOwner(typeof(WaterfallPanel),
new FrameworkPropertyMetadata(Orientation.Horizontal,
FrameworkPropertyMetadataOptions.AffectsMeasure));
public Orientation Orientation
{
@ -29,56 +52,98 @@ namespace HandyControl.Controls
set => SetValue(OrientationProperty, value);
}
private int CaculateGroupCount(Orientation orientation, PanelUvSize size)
{
if (!AutoGroup)
{
return Groups;
}
var itemLength = DesiredLength;
if (MathHelper.IsVerySmall(itemLength))
{
return Groups;
}
return (int) (size.U / itemLength);
}
protected override Size ArrangeOverride(Size finalSize)
{
var orientation = Orientation;
var uvConstraint = new PanelUvSize(orientation, finalSize);
var groups = CaculateGroupCount(orientation, uvConstraint);
if (groups < 1)
{
return finalSize;
}
var vArr = new double[groups].ToList();
var itemU = uvConstraint.U / groups;
var children = InternalChildren;
for (int i = 0, count = children.Count; i < count; i++)
{
var child = children[i];
if (child == null)
{
continue;
}
var minIndex = vArr.IndexOf(vArr.Min());
var minV = vArr[minIndex];
var childUvSize = new PanelUvSize(orientation, child.DesiredSize);
var childSize = new PanelUvSize(orientation, itemU, childUvSize.V);
var childRectSize = new PanelUvSize(orientation, minIndex * itemU, minV);
child.Arrange(new Rect(new Point(childRectSize.U, childRectSize.V), childSize.ScreenSize));
vArr[minIndex] = minV + childUvSize.V;
}
return finalSize;
}
protected override Size MeasureOverride(Size constraint)
{
var groups = Groups;
var orientation = Orientation;
var uvConstraint = new PanelUvSize(orientation, constraint);
var groups = CaculateGroupCount(orientation, uvConstraint);
if (groups < 1)
{
return constraint;
}
var vArr = new double[groups].ToList();
var itemU = uvConstraint.U / groups;
if (double.IsNaN(itemU) || double.IsInfinity(itemU))
{
return constraint;
}
if (groups < 1) return constraint;
var children = InternalChildren;
Size panelSize;
if (Orientation == Orientation.Horizontal)
for (int i = 0, count = children.Count; i < count; i++)
{
var heightArr = new double[groups].ToList();
var itemWidth = constraint.Width / groups;
if (double.IsNaN(itemWidth) || double.IsInfinity(itemWidth)) return constraint;
for (int i = 0, count = children.Count; i < count; i++)
var child = children[i];
if (child == null)
{
var child = children[i];
if (child == null) continue;
child.Measure(constraint);
var minIndex = heightArr.IndexOf(heightArr.Min());
var minY = heightArr[minIndex];
child.Arrange(new Rect(new Point(minIndex * itemWidth, minY), new Size(itemWidth, child.DesiredSize.Height)));
heightArr[minIndex] = minY + child.DesiredSize.Height;
continue;
}
panelSize = new Size(constraint.Width, heightArr.Max());
}
else
{
var widthArr = new double[groups].ToList();
var itemHeight = constraint.Height / groups;
if (double.IsNaN(itemHeight) || double.IsInfinity(itemHeight)) return constraint;
for (int i = 0, count = children.Count; i < count; i++)
{
var child = children[i];
if (child == null) continue;
child.Measure(constraint);
child.Measure(constraint);
var minIndex = widthArr.IndexOf(widthArr.Min());
var minX = widthArr[minIndex];
child.Arrange(new Rect(new Point(minX, minIndex * itemHeight), new Size(child.DesiredSize.Width, itemHeight)));
var sz = new PanelUvSize(orientation, child.DesiredSize);
var minIndex = vArr.IndexOf(vArr.Min());
var minV = vArr[minIndex];
widthArr[minIndex] = minX + child.DesiredSize.Width;
}
panelSize = new Size(widthArr.Max(), constraint.Height);
vArr[minIndex] = minV + sz.V;
}
return panelSize;
uvConstraint = new PanelUvSize(orientation, new Size(uvConstraint.ScreenSize.Width, vArr.Max()));
return uvConstraint.ScreenSize;
}
}
}

View File

@ -55,7 +55,7 @@ namespace HandyControl.Controls
public bool IsIndeterminate
{
get => (bool) GetValue(IsIndeterminateProperty);
set => SetValue(IsIndeterminateProperty, value);
set => SetValue(IsIndeterminateProperty, ValueBoxes.BooleanBox(value));
}
private void SetProgressBarIndicatorAngle()

View File

@ -99,7 +99,7 @@ namespace HandyControl.Controls
public bool ShowSortButton
{
get => (bool) GetValue(ShowSortButtonProperty);
set => SetValue(ShowSortButtonProperty, value);
set => SetValue(ShowSortButtonProperty, ValueBoxes.BooleanBox(value));
}
public override void OnApplyTemplate()

View File

@ -95,7 +95,7 @@ namespace HandyControl.Controls
public bool ShowCloseButton
{
get => (bool) GetValue(ShowCloseButtonProperty);
set => SetValue(ShowCloseButtonProperty, value);
set => SetValue(ShowCloseButtonProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@ -116,7 +116,7 @@ namespace HandyControl.Controls
public bool ShowContextMenu
{
get => (bool) GetValue(ShowContextMenuProperty);
set => SetValue(ShowContextMenuProperty, value);
set => SetValue(ShowContextMenuProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>

View File

@ -141,7 +141,7 @@ namespace HandyControl.Controls
public bool ShowCloseButton
{
get => (bool) GetValue(ShowCloseButtonProperty);
set => SetValue(ShowCloseButtonProperty, value);
set => SetValue(ShowCloseButtonProperty, ValueBoxes.BooleanBox(value));
}
public static void SetShowCloseButton(DependencyObject element, bool value)

View File

@ -0,0 +1,70 @@
using System.Windows;
using System.Windows.Controls;
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

@ -87,6 +87,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Controls\Text\SimpleText.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Controls\Window\GlowWindow.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\EnumItem.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\PanelUvSize.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\Converter\BooleanArr2BooleanConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tools\Generator\DateTimeRangeComparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\VisualWrapping.cs" />

View File

@ -3,6 +3,7 @@ using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
using HandyControl.Data;
using HandyControl.Tools;
// ReSharper disable PossibleInvalidOperationException
@ -173,7 +174,7 @@ namespace HandyControl.Media.Animation
public bool IsCumulative
{
get => (bool) GetValue(IsCumulativeProperty);
set => SetValue(IsCumulativeProperty, value);
set => SetValue(IsCumulativeProperty, ValueBoxes.BooleanBox(value));
}
}
}