Skip to content

Commit

Permalink
Dirkster99#37 Resize behavior of anchorable panels, the case when pan…
Browse files Browse the repository at this point in the history
…els are not visible
  • Loading branch information
scdmitryvodich committed Jun 12, 2019
1 parent 5d0c8eb commit 59171a5
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,15 @@ public LayoutAnchorablePaneControl( LayoutAnchorablePane model )
SetBinding( ItemsSourceProperty, new Binding( "Model.Children" ) { Source = this } );
SetBinding( FlowDirectionProperty, new Binding( "Model.Root.Manager.FlowDirection" ) { Source = this } );

this.LayoutUpdated += new EventHandler( OnLayoutUpdated );
}

// Handle SizeChanged event instead of LayoutUpdated. It will exlude fluctuations of Actual size values.
// this.LayoutUpdated += new EventHandler( OnLayoutUpdated );
this.SizeChanged += OnSizeChanged;
}

#endregion


#region Properties


public ILayoutElement Model
{
get
Expand Down Expand Up @@ -95,11 +97,11 @@ protected override void OnMouseRightButtonDown( System.Windows.Input.MouseButton

#region Private Methods

private void OnLayoutUpdated( object sender, EventArgs e )
private void OnSizeChanged( object sender, SizeChangedEventArgs e)
{
var modelWithAtcualSize = _model as ILayoutPositionableElementWithActualSize;
modelWithAtcualSize.ActualWidth = ActualWidth;
modelWithAtcualSize.ActualHeight = ActualHeight;
var modelWithActualSize = _model as ILayoutPositionableElementWithActualSize;
modelWithActualSize.ActualWidth = ActualWidth;
modelWithActualSize.ActualHeight = ActualHeight;
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ internal LayoutDocumentPaneControl( LayoutDocumentPane model )
SetBinding( ItemsSourceProperty, new Binding( "Model.Children" ) { Source = this } );
SetBinding( FlowDirectionProperty, new Binding( "Model.Root.Manager.FlowDirection" ) { Source = this } );

this.LayoutUpdated += new EventHandler( OnLayoutUpdated );
}
// Handle SizeChanged event instead of LayoutUpdated. It will exlude fluctuations of Actual size values.
// this.LayoutUpdated += new EventHandler( OnLayoutUpdated );
this.SizeChanged += OnSizeChanged;
}

#endregion

Expand Down Expand Up @@ -105,7 +107,7 @@ protected override void OnMouseRightButtonDown( System.Windows.Input.MouseButton

#region Private Methods

private void OnLayoutUpdated( object sender, EventArgs e )
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
var modelWithAtcualSize = _model as ILayoutPositionableElementWithActualSize;
modelWithAtcualSize.ActualWidth = ActualWidth;
Expand Down
169 changes: 157 additions & 12 deletions source/Components/Xceed.Wpf.AvalonDock/Controls/LayoutGridControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This program is provided to you under the terms of the Microsoft Public
***********************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using System.Windows;
Expand All @@ -25,7 +26,7 @@ This program is provided to you under the terms of the Microsoft Public

namespace Xceed.Wpf.AvalonDock.Controls
{
public abstract class LayoutGridControl<T> : Grid, ILayoutControl where T : class, ILayoutPanelElement
public abstract class LayoutGridControl<T> : Grid, ILayoutControl, IAdjustableSizeLayout where T : class, ILayoutPanelElement
{
#region Members

Expand Down Expand Up @@ -55,6 +56,7 @@ internal LayoutGridControl( LayoutPositionableGroup<T> model, Orientation orient
_orientation = orientation;

FlowDirection = System.Windows.FlowDirection.LeftToRight;
Unloaded += OnUnloaded;
}

#endregion
Expand Down Expand Up @@ -106,7 +108,7 @@ protected override void OnInitialized( EventArgs e )
} ), DispatcherPriority.Normal, null );
};

this.LayoutUpdated += new EventHandler( OnLayoutUpdated );
this.SizeChanged += OnSizeChanged;
}

#endregion
Expand All @@ -125,7 +127,7 @@ protected void FixChildrenDockLengths()

#region Private Methods

private void OnLayoutUpdated( object sender, EventArgs e )
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
var modelWithAtcualSize = _model as ILayoutPositionableElementWithActualSize;
modelWithAtcualSize.ActualWidth = ActualWidth;
Expand All @@ -136,6 +138,14 @@ private void OnLayoutUpdated( object sender, EventArgs e )
_initialized = true;
UpdateChildren();
}

AdjustFixedChildrenPanelSizes();
}

private void OnUnloaded(object sender, RoutedEventArgs e)
{
SizeChanged -= OnSizeChanged;
Unloaded -= OnUnloaded;
}

private void UpdateChildren()
Expand Down Expand Up @@ -459,26 +469,161 @@ private void OnSplitterDragCompleted( object sender, System.Windows.Controls.Pri
HideResizerOverlayWindow();
}

public virtual void AdjustFixedChildrenPanelSizes(Size? parentSize = null)
{
List<FrameworkElement> visibleChildren = GetVisibleChildren();
if (visibleChildren.Count == 0)
{
return;
}

List<ILayoutPositionableElementWithActualSize> layoutChildrenModels = visibleChildren.OfType<ILayoutControl>()
.Select(child => child.Model)
.OfType<ILayoutPositionableElementWithActualSize>()
.ToList();

List<LayoutGridResizerControl> splitterChildren = visibleChildren.OfType<LayoutGridResizerControl>().ToList();
List<ILayoutPositionableElementWithActualSize> fixedPanels;
List<ILayoutPositionableElementWithActualSize> relativePanels;

// Get current available size of panel.
Size availableSize = parentSize ?? new Size(ActualWidth, ActualHeight);

// Calculate minimum required size and current size of children.
Size minimumSize = new Size(0, 0);
Size currentSize = new Size(0, 0);
Size preferredMinimumSize = new Size(0, 0);
if (Orientation == Orientation.Vertical)
{
fixedPanels = layoutChildrenModels.Where(child => child.DockHeight.IsAbsolute).ToList();
relativePanels = layoutChildrenModels.Where(child => !child.DockHeight.IsAbsolute).ToList();
minimumSize.Width += layoutChildrenModels.Max(child => child.DockMinWidth);
minimumSize.Height += layoutChildrenModels.Sum(child => child.DockMinHeight);
minimumSize.Height += splitterChildren.Sum(child => child.ActualHeight);
currentSize.Width += layoutChildrenModels.Max(child => child.ActualWidth);
currentSize.Height += layoutChildrenModels.Sum(child => child.ActualHeight);
currentSize.Height += splitterChildren.Sum(child => child.ActualHeight);
preferredMinimumSize.Width += layoutChildrenModels.Max(child => child.DockMinWidth);
preferredMinimumSize.Height += minimumSize.Height + fixedPanels.Sum(child => child.FixedDockHeight) - fixedPanels.Sum(child => child.DockMinHeight);
}
else
{
fixedPanels = layoutChildrenModels.Where(child => child.DockWidth.IsAbsolute).ToList();
relativePanels = layoutChildrenModels.Where(child => !child.DockWidth.IsAbsolute).ToList();
minimumSize.Width += layoutChildrenModels.Sum(child => child.DockMinWidth);
minimumSize.Height += layoutChildrenModels.Max(child => child.DockMinHeight);
minimumSize.Width += splitterChildren.Sum(child => child.ActualWidth);
currentSize.Width += layoutChildrenModels.Sum(child => child.ActualWidth);
currentSize.Height += layoutChildrenModels.Max(child => child.ActualHeight);
currentSize.Width += splitterChildren.Sum(child => child.ActualWidth);
preferredMinimumSize.Height += layoutChildrenModels.Max(child => child.DockMinHeight);
preferredMinimumSize.Width += minimumSize.Width + fixedPanels.Sum(child => child.FixedDockWidth) - fixedPanels.Sum(child => child.DockMinWidth);
}

// Apply corrected sizes for fixed panels.
if (Orientation == Orientation.Vertical)
{
double delta = availableSize.Height - currentSize.Height;
double relativeDelta = relativePanels.Sum(child => child.ActualHeight - child.DockMinHeight);
delta += relativeDelta;
foreach (var fixedChild in fixedPanels)
{
if (minimumSize.Height >= availableSize.Height)
{
fixedChild.ResizableAbsoluteDockHeight = fixedChild.DockMinHeight;
}
else if (preferredMinimumSize.Height <= availableSize.Height)
{
fixedChild.ResizableAbsoluteDockHeight = fixedChild.FixedDockHeight;
}
else if (relativePanels.All(child => Math.Abs(child.ActualHeight - child.DockMinHeight) <= 1))
{
int indexOfChild = fixedPanels.IndexOf(fixedChild);
double fixedHeightLeft = fixedPanels.Where(child => fixedPanels.IndexOf(child) >= indexOfChild)
.Sum(child => child.FixedDockHeight);
double panelFraction = fixedChild.FixedDockHeight / (fixedHeightLeft > 0 ? fixedHeightLeft : 1);
double childActualHeight = fixedChild.ActualHeight;
double heightToSet = Math.Max(Math.Round(delta * panelFraction + fixedChild.ActualHeight), fixedChild.DockMinHeight);
fixedChild.ResizableAbsoluteDockHeight = heightToSet;
delta -= heightToSet - childActualHeight;
}
}
}
else
{
double delta = availableSize.Width - currentSize.Width;
double relativeDelta = relativePanels.Sum(child => child.ActualWidth - child.DockMinWidth);
delta += relativeDelta;
foreach (var fixedChild in fixedPanels)
{
if (minimumSize.Width >= availableSize.Width)
{
fixedChild.ResizableAbsoluteDockWidth = fixedChild.DockMinWidth;
}
else if (preferredMinimumSize.Width <= availableSize.Width)
{
fixedChild.ResizableAbsoluteDockWidth = fixedChild.FixedDockWidth;
}
else
{
int indexOfChild = fixedPanels.IndexOf(fixedChild);
double fixedWidthLeft = fixedPanels.Where(child => fixedPanels.IndexOf(child) >= indexOfChild)
.Sum(child => child.FixedDockWidth);
double panelFraction = fixedChild.FixedDockWidth / (fixedWidthLeft > 0 ? fixedWidthLeft : 1);
double childActualWidth = fixedChild.ActualWidth;
double widthToSet = Math.Max(Math.Round(delta * panelFraction + fixedChild.ActualWidth), fixedChild.DockMinWidth);
fixedChild.ResizableAbsoluteDockWidth = widthToSet;
delta -= widthToSet - childActualWidth;
}
}
}

foreach (IAdjustableSizeLayout child in InternalChildren.OfType<IAdjustableSizeLayout>())
{
child.AdjustFixedChildrenPanelSizes(availableSize);
}
}

private FrameworkElement GetNextVisibleChild( int index )
{
for( int i = index + 1; i < InternalChildren.Count; i++ )
for (int i = index + 1; i < InternalChildren.Count; i++)
{
if( InternalChildren[ i ] is LayoutGridResizerControl )
if (InternalChildren[i] is LayoutGridResizerControl)
continue;

if( Orientation == System.Windows.Controls.Orientation.Horizontal )
if (IsChildVisible(i))
{
if( ColumnDefinitions[ i ].Width.IsStar || ColumnDefinitions[ i ].Width.Value > 0 )
return InternalChildren[ i ] as FrameworkElement;
return InternalChildren[i] as FrameworkElement;
}
else
}

return null;
}

private List<FrameworkElement> GetVisibleChildren()
{
List<FrameworkElement> visibleChildren = new List<FrameworkElement>();
for (int i = 0; i < InternalChildren.Count; i++)
{
if (IsChildVisible(i) && InternalChildren[i] is FrameworkElement frameworkElement)
{
if( RowDefinitions[ i ].Height.IsStar || RowDefinitions[ i ].Height.Value > 0 )
return InternalChildren[ i ] as FrameworkElement;
visibleChildren.Add(frameworkElement);
}
}

return null;
return visibleChildren;
}

private bool IsChildVisible(int index)
{
if( Orientation == Orientation.Horizontal )
{
return ColumnDefinitions[index].Width.IsStar || ColumnDefinitions[index].Width.Value > 0;
}
else
{
return RowDefinitions[ index ].Height.IsStar || RowDefinitions[ index ].Height.Value > 0;
}
}

private void ShowResizerOverlayWindow( LayoutGridResizerControl splitter )
Expand Down
11 changes: 11 additions & 0 deletions source/Components/Xceed.Wpf.AvalonDock/DockingManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ protected virtual void OnLayoutChanged( LayoutRoot oldLayout, LayoutRoot newLayo
//fw.Owner = Window.GetWindow(this);
//fw.SetParentToMainWindowOf(this);
}

SizeChanged += OnSizeChanged;
}

if( newLayout != null )
Expand Down Expand Up @@ -2381,8 +2383,17 @@ private void DockingManager_Loaded( object sender, RoutedEventArgs e )
}
}

private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
double childrenWidth = LayoutRootPanel.ActualWidth + RightSidePanel.ActualWidth + LeftSidePanel.ActualWidth;
double childrenHeight = LayoutRootPanel.ActualHeight + TopSidePanel.ActualHeight + BottomSidePanel.ActualHeight;
LayoutRootPanel.AdjustFixedChildrenPanelSizes(new Size(ActualWidth, ActualHeight));
}

private void DockingManager_Unloaded( object sender, RoutedEventArgs e )
{
SizeChanged -= OnSizeChanged;

if( !DesignerProperties.GetIsInDesignMode( this ) )
{
if( _autoHideWindowManager != null )
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*************************************************************************************
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.Windows;

namespace Xceed.Wpf.AvalonDock.Layout
{
public interface IAdjustableSizeLayout
{
void AdjustFixedChildrenPanelSizes(Size? parentSize = null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,28 @@ GridLength DockWidth
set;
}

double FixedDockWidth { get; }

double ResizableAbsoluteDockWidth
{
get;
set;
}

GridLength DockHeight
{
get;
set;
}

double FixedDockHeight { get; }

double ResizableAbsoluteDockHeight
{
get;
set;
}

double DockMinWidth
{
get; set;
Expand All @@ -53,7 +69,7 @@ bool IsVisible
}


internal interface ILayoutPositionableElementWithActualSize
internal interface ILayoutPositionableElementWithActualSize : ILayoutPositionableElement
{
double ActualWidth
{
Expand Down
Loading

0 comments on commit 59171a5

Please sign in to comment.