Skip to content

Commit

Permalink
Merge branch 'main' into niels9001/switchpresenter-loader-example
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-hawker authored Mar 4, 2024
2 parents 3277b87 + b8088df commit 3b86efd
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 42 deletions.
6 changes: 4 additions & 2 deletions components/Primitives/samples/DockPanelSample.xaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
<Page x:Class="PrimitivesExperiment.Samples.DockPanelSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Expand Down Expand Up @@ -36,7 +36,9 @@
<controls:DockPanel x:Name="SampleDockPanel"
Grid.Column="1"
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
LastChildFill="False">
HorizontalSpacing="5"
LastChildFill="False"
VerticalSpacing="5">
<StackPanel Height="100"
controls:DockPanel.Dock="Top"
Background="Black" />
Expand Down
54 changes: 47 additions & 7 deletions components/Primitives/src/DockPanel/DockPanel.Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public partial class DockPanel
/// Gets or sets a value that indicates the position of a child element within a parent <see cref="DockPanel"/>.
/// </summary>
public static readonly DependencyProperty DockProperty = DependencyProperty.RegisterAttached(
"Dock",
nameof(Dock),
typeof(Dock),
typeof(FrameworkElement),
new PropertyMetadata(Dock.Left, DockChanged));
Expand Down Expand Up @@ -46,15 +46,15 @@ public static readonly DependencyProperty LastChildFillProperty
nameof(LastChildFill),
typeof(bool),
typeof(DockPanel),
new PropertyMetadata(true, LastChildFillChanged));
new PropertyMetadata(true, OnPropertyChanged));

/// <summary>
/// Gets or sets a value indicating whether the last child element within a DockPanel stretches to fill the remaining available space.
/// </summary>
public bool LastChildFill
{
get { return (bool)GetValue(LastChildFillProperty); }
set { SetValue(LastChildFillProperty, value); }
get => (bool)GetValue(LastChildFillProperty);
set => SetValue(LastChildFillProperty, value);
}

/// <summary>
Expand All @@ -66,7 +66,7 @@ public bool LastChildFill
nameof(Padding),
typeof(Thickness),
typeof(DockPanel),
new PropertyMetadata(default(Thickness), OnPaddingChanged));
new PropertyMetadata(default(Thickness), OnPropertyChanged));

/// <summary>
/// Gets or sets the distance between the border and its child object.
Expand All @@ -77,7 +77,47 @@ public bool LastChildFill
/// </returns>
public Thickness Padding
{
get { return (Thickness)GetValue(PaddingProperty); }
set { SetValue(PaddingProperty, value); }
get => (Thickness)GetValue(PaddingProperty);
set => SetValue(PaddingProperty, value);
}

/// <summary>
/// Identifies the HorizontalSpacing dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="HorizontalSpacing"/> dependency property.</returns>
public static readonly DependencyProperty HorizontalSpacingProperty
= DependencyProperty.Register(
nameof(HorizontalSpacing),
typeof(double),
typeof(DockPanel),
new PropertyMetadata(0d, OnPropertyChanged));

/// <summary>
/// Gets or sets the horizontal distance between the child objects.
/// </summary>
public double HorizontalSpacing
{
get => (double)GetValue(HorizontalSpacingProperty);
set => SetValue(HorizontalSpacingProperty, value);
}

/// <summary>
/// Identifies the VerticalSpacing dependency property.
/// </summary>
/// <returns>The identifier for the <see cref="VerticalSpacing"/> dependency property.</returns>
public static readonly DependencyProperty VerticalSpacingProperty
= DependencyProperty.Register(
nameof(VerticalSpacing),
typeof(double),
typeof(DockPanel),
new PropertyMetadata(default(double), OnPropertyChanged));

/// <summary>
/// Gets or sets the vertical distance between the child objects.
/// </summary>
public double VerticalSpacing
{
get => (double)GetValue(VerticalSpacingProperty);
set => SetValue(VerticalSpacingProperty, value);
}
}
90 changes: 58 additions & 32 deletions components/Primitives/src/DockPanel/DockPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ private static void DockChanged(DependencyObject sender, DependencyPropertyChang
dockPanel?.InvalidateArrange();
}

private static void LastChildFillChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var dockPanel = (DockPanel)sender;
dockPanel.InvalidateArrange();
}

private static void OnPaddingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
private static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var dockPanel = (DockPanel)sender;
dockPanel.InvalidateMeasure();
Expand All @@ -32,15 +26,17 @@ private static void OnPaddingChanged(DependencyObject sender, DependencyProperty
/// <inheritdoc />
protected override Size ArrangeOverride(Size finalSize)
{
if (Children.Count == 0)
{
if (Children.Count is 0)
return finalSize;
}

var currentBounds = new Rect(Padding.Left, Padding.Top, finalSize.Width - Padding.Right, finalSize.Height - Padding.Bottom);
var currentBounds = new Rect(
Padding.Left,
Padding.Top,
GetPositiveOrZero(finalSize.Width - Padding.Left - Padding.Right),
GetPositiveOrZero(finalSize.Height - Padding.Top - Padding.Bottom));
var childrenCount = LastChildFill ? Children.Count - 1 : Children.Count;

for (var index = 0; index < childrenCount; index++)
for (var index = 0; index < childrenCount; ++index)
{
var child = Children[index];
var dock = (Dock)child.GetValue(DockProperty);
Expand All @@ -49,42 +45,45 @@ protected override Size ArrangeOverride(Size finalSize)
{
case Dock.Left:

width = Math.Min(child.DesiredSize.Width, GetPositiveOrZero(currentBounds.Width - currentBounds.X));
child.Arrange(new Rect(currentBounds.X, currentBounds.Y, width, GetPositiveOrZero(currentBounds.Height - currentBounds.Y)));
width = Math.Min(child.DesiredSize.Width, currentBounds.Width);
child.Arrange(new Rect(currentBounds.X, currentBounds.Y, width, currentBounds.Height));
width += HorizontalSpacing;
currentBounds.X += width;
currentBounds.Width = GetPositiveOrZero(currentBounds.Width - width);

break;
case Dock.Top:

height = Math.Min(child.DesiredSize.Height, GetPositiveOrZero(currentBounds.Height - currentBounds.Y));
child.Arrange(new Rect(currentBounds.X, currentBounds.Y, GetPositiveOrZero(currentBounds.Width - currentBounds.X), height));
height = Math.Min(child.DesiredSize.Height, currentBounds.Height);
child.Arrange(new Rect(currentBounds.X, currentBounds.Y, currentBounds.Width, height));
height += VerticalSpacing;
currentBounds.Y += height;
currentBounds.Height = GetPositiveOrZero(currentBounds.Height - height);

break;
case Dock.Right:

width = Math.Min(child.DesiredSize.Width, GetPositiveOrZero(currentBounds.Width - currentBounds.X));
child.Arrange(new Rect(GetPositiveOrZero(currentBounds.Width - width), currentBounds.Y, width, GetPositiveOrZero(currentBounds.Height - currentBounds.Y)));
currentBounds.Width -= (currentBounds.Width - width) > 0 ? width : 0;
width = Math.Min(child.DesiredSize.Width, currentBounds.Width);
child.Arrange(new Rect(currentBounds.X + currentBounds.Width - width, currentBounds.Y, width, currentBounds.Height));
width += HorizontalSpacing;
currentBounds.Width = GetPositiveOrZero(currentBounds.Width - width);

break;
case Dock.Bottom:

height = Math.Min(child.DesiredSize.Height, GetPositiveOrZero(currentBounds.Height - currentBounds.Y));
child.Arrange(new Rect(currentBounds.X, GetPositiveOrZero(currentBounds.Height - height), GetPositiveOrZero(currentBounds.Width - currentBounds.X), height));
currentBounds.Height -= (currentBounds.Height - height) > 0 ? height : 0;
height = Math.Min(child.DesiredSize.Height, currentBounds.Height);
child.Arrange(new Rect(currentBounds.X, currentBounds.Y + currentBounds.Height - height, currentBounds.Width, height));
height += VerticalSpacing;
currentBounds.Height = GetPositiveOrZero(currentBounds.Height - height);

break;
}
}

if (LastChildFill)
{
var width = GetPositiveOrZero(currentBounds.Width - currentBounds.X);
var height = GetPositiveOrZero(currentBounds.Height - currentBounds.Y);
var child = Children[Children.Count - 1];
child.Arrange(
new Rect(currentBounds.X, currentBounds.Y, width, height));
child.Arrange(new Rect(currentBounds.X, currentBounds.Y, currentBounds.Width, currentBounds.Height));
}

return finalSize;
Expand All @@ -98,6 +97,11 @@ protected override Size MeasureOverride(Size availableSize)
var accumulatedWidth = Padding.Left + Padding.Right;
var accumulatedHeight = Padding.Top + Padding.Bottom;

var leftSpacing = false;
var topSpacing = false;
var rightSpacing = false;
var bottomSpacing = false;

foreach (var child in Children)
{
var childConstraint = new Size(
Expand All @@ -110,26 +114,48 @@ protected override Size MeasureOverride(Size availableSize)
switch ((Dock)child.GetValue(DockProperty))
{
case Dock.Left:
if (childConstraint.Width is not 0)
accumulatedWidth += HorizontalSpacing;
leftSpacing = true;
parentHeight = Math.Max(parentHeight, accumulatedHeight + childDesiredSize.Height - VerticalSpacing);
accumulatedWidth += childDesiredSize.Width;
break;

case Dock.Right:
parentHeight = Math.Max(parentHeight, accumulatedHeight + childDesiredSize.Height);
if (childConstraint.Width is not 0)
accumulatedWidth += HorizontalSpacing;
rightSpacing = true;
parentHeight = Math.Max(parentHeight, accumulatedHeight + childDesiredSize.Height - VerticalSpacing);
accumulatedWidth += childDesiredSize.Width;
break;

case Dock.Top:
if (childConstraint.Height is not 0)
accumulatedHeight += VerticalSpacing;
topSpacing = true;
parentWidth = Math.Max(parentWidth, accumulatedWidth + childDesiredSize.Width - HorizontalSpacing);
accumulatedHeight += childDesiredSize.Height;
break;

case Dock.Bottom:
parentWidth = Math.Max(parentWidth, accumulatedWidth + childDesiredSize.Width);
if (childConstraint.Height is not 0)
accumulatedHeight += VerticalSpacing;
bottomSpacing = true;
parentWidth = Math.Max(parentWidth, accumulatedWidth + childDesiredSize.Width - HorizontalSpacing);
accumulatedHeight += childDesiredSize.Height;
break;
}
}

if (leftSpacing || rightSpacing)
accumulatedWidth -= HorizontalSpacing;
if (bottomSpacing || topSpacing)
accumulatedHeight -= VerticalSpacing;

parentWidth = Math.Max(parentWidth, accumulatedWidth);
parentHeight = Math.Max(parentHeight, accumulatedHeight);
return new Size(parentWidth, parentHeight);
}

private static double GetPositiveOrZero(double value)
{
return Math.Max(value, 0);
}
private static double GetPositiveOrZero(double value) => Math.Max(value, 0);
}
2 changes: 1 addition & 1 deletion tooling

0 comments on commit 3b86efd

Please sign in to comment.