All the controls missing in WPF. Over 1 million downloads.
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.

284 lines
9.8 KiB

/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Xceed.Wpf.Toolkit.Core.Utilities;
namespace Xceed.Wpf.Toolkit.Panels
{
public class WrapPanel : AnimationPanel
{
#region Orientation Property
public static readonly DependencyProperty OrientationProperty =
StackPanel.OrientationProperty.AddOwner( typeof( WrapPanel ),
new FrameworkPropertyMetadata( Orientation.Horizontal,
new PropertyChangedCallback( WrapPanel.OnOrientationChanged ) ) );
public Orientation Orientation
{
get
{
return _orientation;
}
set
{
base.SetValue( WrapPanel.OrientationProperty, value );
}
}
private static void OnOrientationChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
WrapPanel panel = ( WrapPanel )d;
panel._orientation = ( Orientation )e.NewValue;
panel.InvalidateMeasure();
}
private Orientation _orientation;
#endregion
#region ItemWidth Property
public static readonly DependencyProperty ItemWidthProperty =
DependencyProperty.Register( "ItemWidth", typeof( double ), typeof( WrapPanel ),
new FrameworkPropertyMetadata( double.NaN,
new PropertyChangedCallback( WrapPanel.OnInvalidateMeasure ) ), new ValidateValueCallback( WrapPanel.IsWidthHeightValid ) );
[TypeConverter( typeof( LengthConverter ) )]
public double ItemWidth
{
get
{
return ( double )base.GetValue( WrapPanel.ItemWidthProperty );
}
set
{
base.SetValue( WrapPanel.ItemWidthProperty, value );
}
}
#endregion
#region ItemHeight Property
public static readonly DependencyProperty ItemHeightProperty =
DependencyProperty.Register( "ItemHeight", typeof( double ), typeof( WrapPanel ),
new FrameworkPropertyMetadata( double.NaN,
new PropertyChangedCallback( WrapPanel.OnInvalidateMeasure ) ), new ValidateValueCallback( WrapPanel.IsWidthHeightValid ) );
[TypeConverter( typeof( LengthConverter ) )]
public double ItemHeight
{
get
{
return ( double )base.GetValue( WrapPanel.ItemHeightProperty );
}
set
{
base.SetValue( WrapPanel.ItemHeightProperty, value );
}
}
#endregion
#region IsChildOrderReversed Property
public static readonly DependencyProperty IsStackReversedProperty =
DependencyProperty.Register( "IsChildOrderReversed", typeof( bool ), typeof( WrapPanel ),
new FrameworkPropertyMetadata( false,
new PropertyChangedCallback( WrapPanel.OnInvalidateMeasure ) ) );
public bool IsChildOrderReversed
{
get
{
return ( bool )this.GetValue( WrapPanel.IsStackReversedProperty );
}
set
{
this.SetValue( WrapPanel.IsStackReversedProperty, value );
}
}
#endregion
protected override Size MeasureChildrenOverride( UIElementCollection children, Size constraint )
{
double desiredExtent = 0;
double desiredStack = 0;
bool isHorizontal = ( this.Orientation == Orientation.Horizontal );
double constraintExtent = ( isHorizontal ? constraint.Width : constraint.Height );
double itemWidth = ItemWidth;
double itemHeight = ItemHeight;
double itemExtent = ( isHorizontal ? itemWidth : itemHeight );
bool hasExplicitItemWidth = !double.IsNaN( itemWidth );
bool hasExplicitItemHeight = !double.IsNaN( itemHeight );
bool useItemExtent = ( isHorizontal ? hasExplicitItemWidth : hasExplicitItemHeight );
double lineExtent = 0;
double lineStack = 0;
Size childConstraint = new Size( ( hasExplicitItemWidth ? itemWidth : constraint.Width ),
( hasExplicitItemHeight ? itemHeight : constraint.Height ) );
bool isReversed = this.IsChildOrderReversed;
int from = isReversed ? children.Count - 1 : 0;
int to = isReversed ? 0 : children.Count - 1;
int step = isReversed ? -1 : 1;
for( int i = from, pass = 0; pass < children.Count; i += step, pass++ )
{
UIElement child = children[ i ] as UIElement;
child.Measure( childConstraint );
double childExtent = isHorizontal
? ( hasExplicitItemWidth ? itemWidth : child.DesiredSize.Width )
: ( hasExplicitItemHeight ? itemHeight : child.DesiredSize.Height );
double childStack = isHorizontal
? ( hasExplicitItemHeight ? itemHeight : child.DesiredSize.Height )
: ( hasExplicitItemWidth ? itemWidth : child.DesiredSize.Width );
if( lineExtent + childExtent > constraintExtent )
{
desiredExtent = Math.Max( lineExtent, desiredExtent );
desiredStack += lineStack;
lineExtent = childExtent;
lineStack = childStack;
if( childExtent > constraintExtent )
{
desiredExtent = Math.Max( childExtent, desiredExtent );
desiredStack += childStack;
lineExtent = 0;
lineStack = 0;
}
}
else
{
lineExtent += childExtent;
lineStack = Math.Max( childStack, lineStack );
}
}
desiredExtent = Math.Max( lineExtent, desiredExtent );
desiredStack += lineStack;
return isHorizontal
? new Size( desiredExtent, desiredStack )
: new Size( desiredStack, desiredExtent );
}
protected override Size ArrangeChildrenOverride( UIElementCollection children, Size finalSize )
{
bool isHorizontal = ( this.Orientation == Orientation.Horizontal );
double finalExtent = ( isHorizontal ? finalSize.Width : finalSize.Height );
double itemWidth = this.ItemWidth;
double itemHeight = this.ItemHeight;
double itemExtent = ( isHorizontal ? itemWidth : itemHeight );
bool hasExplicitItemWidth = !double.IsNaN( itemWidth );
bool hasExplicitItemHeight = !double.IsNaN( itemHeight );
bool useItemExtent = ( isHorizontal ? hasExplicitItemWidth : hasExplicitItemHeight );
double lineExtent = 0;
double lineStack = 0;
double lineStackSum = 0;
int from = this.IsChildOrderReversed ? children.Count - 1 : 0;
int to = this.IsChildOrderReversed ? 0 : children.Count - 1;
int step = this.IsChildOrderReversed ? -1 : 1;
Collection<UIElement> childrenInLine = new Collection<UIElement>();
for( int i = from, pass = 0; pass < children.Count; i += step, pass++ )
{
UIElement child = children[ i ] as UIElement;
double childExtent = isHorizontal
? ( hasExplicitItemWidth ? itemWidth : child.DesiredSize.Width )
: ( hasExplicitItemHeight ? itemHeight : child.DesiredSize.Height );
double childStack = isHorizontal
? ( hasExplicitItemHeight ? itemHeight : child.DesiredSize.Height )
: ( hasExplicitItemWidth ? itemWidth : child.DesiredSize.Width );
if( lineExtent + childExtent > finalExtent )
{
this.ArrangeLineOfChildren( childrenInLine, isHorizontal, lineStack, lineStackSum, itemExtent, useItemExtent );
lineStackSum += lineStack;
lineExtent = childExtent;
if( childExtent > finalExtent )
{
childrenInLine.Add( child );
this.ArrangeLineOfChildren( childrenInLine, isHorizontal, childStack, lineStackSum, itemExtent, useItemExtent );
lineStackSum += childStack;
lineExtent = 0;
}
childrenInLine.Add( child );
}
else
{
childrenInLine.Add( child );
lineExtent += childExtent;
lineStack = Math.Max( childStack, lineStack );
}
}
if( childrenInLine.Count > 0 )
{
this.ArrangeLineOfChildren( childrenInLine, isHorizontal, lineStack, lineStackSum, itemExtent, useItemExtent );
}
return finalSize;
}
private void ArrangeLineOfChildren( Collection<UIElement> children, bool isHorizontal, double lineStack, double lineStackSum, double itemExtent, bool useItemExtent )
{
double extent = 0;
foreach( UIElement child in children )
{
double childExtent = ( isHorizontal ? child.DesiredSize.Width : child.DesiredSize.Height );
double elementExtent = ( useItemExtent ? itemExtent : childExtent );
this.ArrangeChild( child, isHorizontal ? new Rect( extent, lineStackSum, elementExtent, lineStack )
: new Rect( lineStackSum, extent, lineStack, elementExtent ) );
extent += elementExtent;
}
children.Clear();
}
private static void OnInvalidateMeasure( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( AnimationPanel )d ).InvalidateMeasure();
}
private static bool IsWidthHeightValid( object value )
{
double num = ( double )value;
return ( DoubleHelper.IsNaN( num ) || ( ( num >= 0d ) && !double.IsPositiveInfinity( num ) ) );
}
}
}