namespace Avalonia.Controls
{
using System;
///
/// Defines the available docking modes for a control in a .
///
public enum Dock
{
Left = 0,
Bottom,
Right,
Top
}
///
/// A panel which arranges its children at the top, bottom, left, right or center.
///
public class DockPanel : Panel
{
///
/// Defines the Dock attached property.
///
public static readonly AttachedProperty DockProperty =
AvaloniaProperty.RegisterAttached("Dock");
///
/// Defines the property.
///
public static readonly StyledProperty LastChildFillProperty =
AvaloniaProperty.Register(
nameof(LastChildFillProperty),
defaultValue: true);
///
/// Initializes static members of the class.
///
static DockPanel()
{
AffectsArrange(DockProperty);
}
///
/// Gets the value of the Dock attached property on the specified control.
///
/// The control.
/// The Dock attached property.
public static Dock GetDock(Control control)
{
return control.GetValue(DockProperty);
}
///
/// Sets the value of the Dock attached property on the specified control.
///
/// The control.
/// The value of the Dock property.
public static void SetDock(Control control, Dock value)
{
control.SetValue(DockProperty, value);
}
///
/// Gets or sets a value which indicates whether the last child of the
/// fills the remaining space in the panel.
///
public bool LastChildFill
{
get { return GetValue(LastChildFillProperty); }
set { SetValue(LastChildFillProperty, value); }
}
///
protected override Size MeasureOverride(Size constraint)
{
double usedWidth = 0.0;
double usedHeight = 0.0;
double maximumWidth = 0.0;
double maximumHeight = 0.0;
// Measure each of the Children
foreach (Control element in Children)
{
// Get the child's desired size
Size remainingSize = new Size(
Math.Max(0.0, constraint.Width - usedWidth),
Math.Max(0.0, constraint.Height - usedHeight));
element.Measure(remainingSize);
Size desiredSize = element.DesiredSize;
// Decrease the remaining space for the rest of the children
switch (GetDock(element))
{
case Dock.Left:
case Dock.Right:
maximumHeight = Math.Max(maximumHeight, usedHeight + desiredSize.Height);
usedWidth += desiredSize.Width;
break;
case Dock.Top:
case Dock.Bottom:
maximumWidth = Math.Max(maximumWidth, usedWidth + desiredSize.Width);
usedHeight += desiredSize.Height;
break;
}
}
maximumWidth = Math.Max(maximumWidth, usedWidth);
maximumHeight = Math.Max(maximumHeight, usedHeight);
return new Size(maximumWidth, maximumHeight);
}
///
protected override Size ArrangeOverride(Size arrangeSize)
{
double left = 0.0;
double top = 0.0;
double right = 0.0;
double bottom = 0.0;
// Arrange each of the Children
var children = Children;
int dockedCount = children.Count - (LastChildFill ? 1 : 0);
int index = 0;
foreach (Control element in children)
{
// Determine the remaining space left to arrange the element
Rect remainingRect = new Rect(
left,
top,
Math.Max(0.0, arrangeSize.Width - left - right),
Math.Max(0.0, arrangeSize.Height - top - bottom));
// Trim the remaining Rect to the docked size of the element
// (unless the element should fill the remaining space because
// of LastChildFill)
if (index < dockedCount)
{
Size desiredSize = element.DesiredSize;
switch (GetDock(element))
{
case Dock.Left:
left += desiredSize.Width;
remainingRect = remainingRect.WithWidth(desiredSize.Width);
break;
case Dock.Top:
top += desiredSize.Height;
remainingRect = remainingRect.WithHeight(desiredSize.Height);
break;
case Dock.Right:
right += desiredSize.Width;
remainingRect = new Rect(
Math.Max(0.0, arrangeSize.Width - right),
remainingRect.Y,
desiredSize.Width,
remainingRect.Height);
break;
case Dock.Bottom:
bottom += desiredSize.Height;
remainingRect = new Rect(
remainingRect.X,
Math.Max(0.0, arrangeSize.Height - bottom),
remainingRect.Width,
desiredSize.Height);
break;
}
}
element.Arrange(remainingRect);
index++;
}
return arrangeSize;
}
}
}