A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

142 lines
4.8 KiB

// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using Avalonia.Media;
using Avalonia.Metadata;
namespace Avalonia.Controls
{
/// <summary>
/// Base class for controls that can contain multiple children.
/// </summary>
/// <remarks>
/// Controls can be added to a <see cref="Panel"/> by adding them to its <see cref="Children"/>
/// collection. All children are layed out to fill the panel.
/// </remarks>
public class Panel : Control, IPanel
{
/// <summary>
/// Defines the <see cref="Background"/> property.
/// </summary>
public static readonly StyledProperty<IBrush> BackgroundProperty =
Border.BackgroundProperty.AddOwner<Panel>();
private readonly Controls _children = new Controls();
/// <summary>
/// Initializes static members of the <see cref="Panel"/> class.
/// </summary>
static Panel()
{
ClipToBoundsProperty.OverrideDefaultValue<Panel>(true);
}
/// <summary>
/// Initializes a new instance of the <see cref="Panel"/> class.
/// </summary>
public Panel()
{
_children.CollectionChanged += ChildrenChanged;
}
/// <summary>
/// Gets or sets the children of the <see cref="Panel"/>.
/// </summary>
/// <remarks>
/// Even though this property can be set, the setter is only intended for use in object
/// initializers. Assigning to this property does not change the underlying collection,
/// it simply clears the existing collection and adds the contents of the assigned
/// collection.
/// </remarks>
[Content]
public Controls Children
{
get
{
return _children;
}
set
{
Contract.Requires<ArgumentNullException>(value != null);
VisualChildren.Clear();
_children.Clear();
_children.AddRange(value);
}
}
/// <summary>
/// Gets or Sets Panel background brush.
/// </summary>
public IBrush Background
{
get { return GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
}
/// <summary>
/// Renders the visual to a <see cref="DrawingContext"/>.
/// </summary>
/// <param name="context">The drawing context.</param>
public override void Render(DrawingContext context)
{
var background = Background;
if (background != null)
{
var renderSize = Bounds.Size;
context.FillRectangle(background, new Rect(renderSize));
}
base.Render(context);
}
/// <summary>
/// Called when the <see cref="Children"/> collection changes.
/// </summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event args.</param>
protected virtual void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
{
List<Control> controls;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
controls = e.NewItems.OfType<Control>().ToList();
LogicalChildren.InsertRange(e.NewStartingIndex, controls);
VisualChildren.AddRange(e.NewItems.OfType<Visual>());
break;
case NotifyCollectionChangedAction.Remove:
controls = e.OldItems.OfType<Control>().ToList();
LogicalChildren.RemoveAll(controls);
VisualChildren.RemoveAll(e.OldItems.OfType<Visual>());
break;
case NotifyCollectionChangedAction.Replace:
for (var i = 0; i < e.OldItems.Count; ++i)
{
var index = i + e.OldStartingIndex;
var child = (IControl)e.NewItems[i];
LogicalChildren[index] = child;
VisualChildren[index] = child;
}
break;
case NotifyCollectionChangedAction.Reset:
controls = e.OldItems.OfType<Control>().ToList();
LogicalChildren.Clear();
VisualChildren.Clear();
VisualChildren.AddRange(_children);
break;
}
InvalidateMeasure();
}
}
}