Skip to content

Commit

Permalink
Merge pull request #60 from scdmitryvodich/FixVisibilityBindings
Browse files Browse the repository at this point in the history
Fix visibility bindings of undocked panels in specific cases
  • Loading branch information
Dirkster99 authored Aug 10, 2019
2 parents e6c9438 + bfed85e commit ba7e81a
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
namespace Xceed.Wpf.AvalonDock.Test
{
using System;
using System.Windows.Controls;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using Xceed.Wpf.AvalonDock.Layout;

[TestClass]
public sealed class DockingUtilitiesTest
{
[TestMethod]
public void CalculatedDockMinWidthHeightTest()
{
double defaultDockMinHeight = 25;
double defaultDockMinWidth = 25;

const double documentPaneDockMinHeight = 200;
const double documentPaneDockMinWidth = 400;
LayoutDocumentPane layoutDocumentPane = new LayoutDocumentPane { DockMinHeight = documentPaneDockMinHeight, DockMinWidth = documentPaneDockMinWidth };
layoutDocumentPane.InsertChildAt( 0, new LayoutDocument { ContentId = "Document" } );

LayoutDocumentPaneGroup layoutDocumentPaneGroup = new LayoutDocumentPaneGroup();
layoutDocumentPaneGroup.InsertChildAt( 0, layoutDocumentPane );

const double anchorablePaneDockMinHeight = 80;
const double anchorablePaneDockMinWidth = 160;
LayoutAnchorablePane layoutAnchorablePane = new LayoutAnchorablePane { DockMinHeight = anchorablePaneDockMinHeight, DockMinWidth = anchorablePaneDockMinWidth };
layoutAnchorablePane.InsertChildAt( 0, new LayoutAnchorable { ContentId = "Anchorable" } );

LayoutAnchorablePaneGroup layoutAnchorablePaneGroup = new LayoutAnchorablePaneGroup();
layoutAnchorablePaneGroup.InsertChildAt( 0, layoutAnchorablePane );

LayoutPanel layoutPanel = new LayoutPanel();
layoutPanel.InsertChildAt( 0, layoutDocumentPaneGroup );
layoutPanel.InsertChildAt( 1, layoutAnchorablePaneGroup );

Assert.AreEqual( defaultDockMinWidth, layoutPanel.DockMinWidth );
Assert.AreEqual( defaultDockMinHeight, layoutPanel.DockMinHeight );
Assert.AreEqual( documentPaneDockMinWidth + anchorablePaneDockMinWidth, layoutPanel.CalculatedDockMinWidth() );
Assert.AreEqual( Math.Max(documentPaneDockMinHeight, anchorablePaneDockMinHeight), layoutPanel.CalculatedDockMinHeight() );

Assert.AreEqual( documentPaneDockMinWidth, layoutDocumentPane.DockMinWidth );
Assert.AreEqual( documentPaneDockMinHeight, layoutDocumentPane.DockMinHeight );
Assert.AreEqual( layoutDocumentPane.DockMinWidth, layoutDocumentPane.CalculatedDockMinWidth() );
Assert.AreEqual( layoutDocumentPane.DockMinHeight, layoutDocumentPane.CalculatedDockMinHeight() );

Assert.AreEqual( defaultDockMinWidth, layoutDocumentPaneGroup.DockMinWidth );
Assert.AreEqual( defaultDockMinWidth, layoutDocumentPaneGroup.DockMinHeight );
Assert.AreEqual( documentPaneDockMinWidth, layoutDocumentPaneGroup.CalculatedDockMinWidth() );
Assert.AreEqual( documentPaneDockMinHeight, layoutDocumentPaneGroup.CalculatedDockMinHeight() );

Assert.AreEqual( anchorablePaneDockMinWidth, layoutAnchorablePane.DockMinWidth );
Assert.AreEqual( anchorablePaneDockMinHeight, layoutAnchorablePane.DockMinHeight );
Assert.AreEqual( layoutAnchorablePane.DockMinWidth, layoutAnchorablePane.CalculatedDockMinWidth() );
Assert.AreEqual( layoutAnchorablePane.DockMinHeight, layoutAnchorablePane.CalculatedDockMinHeight() );

Assert.AreEqual( defaultDockMinWidth, layoutAnchorablePaneGroup.DockMinWidth );
Assert.AreEqual( defaultDockMinWidth, layoutAnchorablePaneGroup.DockMinHeight );
Assert.AreEqual( anchorablePaneDockMinWidth, layoutAnchorablePaneGroup.CalculatedDockMinWidth() );
Assert.AreEqual( anchorablePaneDockMinHeight, layoutAnchorablePaneGroup.CalculatedDockMinHeight() );

layoutPanel.RemoveChild( layoutDocumentPaneGroup );
Assert.AreEqual( anchorablePaneDockMinWidth, layoutPanel.CalculatedDockMinWidth() );
Assert.AreEqual( anchorablePaneDockMinHeight, layoutPanel.CalculatedDockMinHeight() );
}

[TestMethod]
public void UpdateDocMinWidthHeightTest()
{
double documentPaneDockMinHeight = 100;
double documentPaneDockMinWidth = 101;
LayoutDocumentPane layoutDocumentPane = new LayoutDocumentPane { DockMinHeight = documentPaneDockMinHeight, DockMinWidth = documentPaneDockMinWidth };
layoutDocumentPane.InsertChildAt( 0, new LayoutDocument { ContentId = "Document" } );

LayoutDocumentPaneGroup layoutDocumentPaneGroup = new LayoutDocumentPaneGroup();
layoutDocumentPaneGroup.InsertChildAt( 0, layoutDocumentPane );

double anchorablePane1DockMinHeight = 150;
double anchorablePane1DockMinWidth = 151;
LayoutAnchorablePane layoutAnchorablePane1 = new LayoutAnchorablePane { DockMinHeight = anchorablePane1DockMinHeight, DockMinWidth = anchorablePane1DockMinWidth };
layoutAnchorablePane1.InsertChildAt( 0, new LayoutAnchorable { ContentId = "Anchorable1" } );

double anchorablePane2DockMinHeight = 200;
double anchorablePane2DockMinWidth = 201;
LayoutAnchorablePane layoutAnchorablePane2 = new LayoutAnchorablePane { DockMinHeight = anchorablePane2DockMinHeight, DockMinWidth = anchorablePane2DockMinWidth };
layoutAnchorablePane2.InsertChildAt( 0, new LayoutAnchorable { ContentId = "Anchorable2" } );

LayoutAnchorablePaneGroup layoutAnchorablePaneGroup = new LayoutAnchorablePaneGroup { Orientation = Orientation.Horizontal };
layoutAnchorablePaneGroup.InsertChildAt( 0, layoutAnchorablePane1 );
layoutAnchorablePaneGroup.InsertChildAt( 0, layoutAnchorablePane2 );

LayoutPanel layoutPanel = new LayoutPanel { Orientation = Orientation.Vertical };
layoutPanel.InsertChildAt( 0, layoutDocumentPaneGroup );
layoutPanel.InsertChildAt( 1, layoutAnchorablePaneGroup );

Assert.AreEqual( anchorablePane2DockMinWidth + anchorablePane1DockMinWidth, layoutAnchorablePaneGroup.CalculatedDockMinWidth() );
Assert.AreEqual( Math.Max( anchorablePane2DockMinHeight, anchorablePane1DockMinHeight ), layoutAnchorablePaneGroup.CalculatedDockMinHeight() );

Assert.AreEqual( documentPaneDockMinWidth, layoutDocumentPaneGroup.CalculatedDockMinWidth() );
Assert.AreEqual( documentPaneDockMinHeight, layoutDocumentPaneGroup.CalculatedDockMinHeight() );

Assert.AreEqual(
Math.Max( anchorablePane1DockMinWidth + anchorablePane2DockMinWidth, documentPaneDockMinWidth ),
layoutPanel.CalculatedDockMinWidth() );

Assert.AreEqual( documentPaneDockMinHeight + anchorablePane2DockMinHeight, layoutPanel.CalculatedDockMinHeight() );
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Data;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using Xceed.Wpf.AvalonDock.Controls;
using Xceed.Wpf.AvalonDock.Converters;
using Xceed.Wpf.AvalonDock.Layout;

namespace Xceed.Wpf.AvalonDock.Test
{
[TestClass]
public sealed class LayoutAnchorableTest
{
[TestMethod]
public void ClearBindingOfHiddenWindowTest()
{
LayoutAnchorable layoutAnchorable = new LayoutAnchorable
{
FloatingWidth = 50,
FloatingHeight = 100,
ContentId = "Test"
};

LayoutAnchorablePane layoutAnchorablePane = new LayoutAnchorablePane( layoutAnchorable );
LayoutAnchorablePaneGroup layoutAnchorablePaneGroup = new LayoutAnchorablePaneGroup( layoutAnchorablePane );
LayoutAnchorableFloatingWindow layoutFloatingWindow = new LayoutAnchorableFloatingWindow
{
RootPanel = layoutAnchorablePaneGroup
};

var ctor = typeof( LayoutAnchorableFloatingWindowControl )
.GetTypeInfo()
.GetConstructors( BindingFlags.NonPublic | BindingFlags.Instance )
.First( x => x.GetParameters().Length == 1 );

LayoutAnchorableFloatingWindowControl floatingWindowControl = ctor.Invoke( new object[] {layoutFloatingWindow} ) as LayoutAnchorableFloatingWindowControl;
floatingWindowControl.SetBinding(
UIElement.VisibilityProperty,
new Binding( "IsVisible" )
{
Source = floatingWindowControl.Model,
Converter = new BoolToVisibilityConverter(),
Mode = BindingMode.OneWay,
ConverterParameter = Visibility.Hidden
} );

BindingExpression visibilityBinding = floatingWindowControl.GetBindingExpression( UIElement.VisibilityProperty );
Assert.IsNotNull( visibilityBinding );

layoutAnchorable.Show();
layoutAnchorable.Hide();

visibilityBinding = floatingWindowControl.GetBindingExpression( UIElement.VisibilityProperty );
Assert.IsNotNull( visibilityBinding );

floatingWindowControl.Hide();

visibilityBinding = floatingWindowControl.GetBindingExpression( UIElement.VisibilityProperty );
Assert.IsNull( visibilityBinding );
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,13 @@
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xaml" />
<Reference Include="System.XML" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="AnchorablePaneTest.cs" />
<Compile Include="DockingUtilitiesTest.cs" />
<Compile Include="LayoutAnchorableTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestApp.xaml.cs">
<DependentUpon>TestApp.xaml</DependentUpon>
Expand Down Expand Up @@ -102,4 +105,4 @@
<Error Condition="!Exists('..\..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.targets'))" />
</Target>
<Import Project="..\..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\..\packages\MSTest.TestAdapter.1.4.0\build\net45\MSTest.TestAdapter.targets')" />
</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ internal LayoutAnchorableFloatingWindowControl( LayoutAnchorableFloatingWindow m
_model = model;
HideWindowCommand = new RelayCommand( ( p ) => OnExecuteHideWindowCommand( p ), ( p ) => CanExecuteHideWindowCommand( p ) );
CloseWindowCommand = new RelayCommand( ( p ) => OnExecuteCloseWindowCommand( p ), ( p ) => CanExecuteCloseWindowCommand( p ) );
Activated += LayoutAnchorableFloatingWindowControl_Activated;
UpdateThemeResources();
MinWidth = _model.RootPanel.CalculatedDockMinWidth();
MinHeight = _model.RootPanel.CalculatedDockMinHeight();
Expand All @@ -71,6 +72,17 @@ private void OnRootUpdated(object sender, EventArgs e)
}
}

private void LayoutAnchorableFloatingWindowControl_Activated( object sender, EventArgs e )
{
// Issue similar to: http://avalondock.codeplex.com/workitem/15036
var visibilityBinding = GetBindingExpression( VisibilityProperty );

if ( visibilityBinding == null && Visibility == Visibility.Visible )
{
SetVisibilityBinding();
}
}

internal LayoutAnchorableFloatingWindowControl( LayoutAnchorableFloatingWindow model)
: this( model, false )
{
Expand Down Expand Up @@ -147,9 +159,9 @@ protected override void OnInitialized( EventArgs e )
IsVisibleChanged += ( s, args ) =>
{
var visibilityBinding = GetBindingExpression( VisibilityProperty );
if( IsVisible && ( visibilityBinding == null ) )
if( visibilityBinding == null && IsVisible )
{
SetBinding( VisibilityProperty, new Binding( "IsVisible" ) { Source = _model, Converter = new BoolToVisibilityConverter(), Mode = BindingMode.OneWay, ConverterParameter = Visibility.Hidden } );
SetVisibilityBinding();
}
};

Expand Down Expand Up @@ -189,6 +201,8 @@ protected override void OnClosed( EventArgs e )
BindingOperations.ClearBinding(_model, VisibilityProperty);

_model.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler( _model_PropertyChanged );

Activated -= LayoutAnchorableFloatingWindowControl_Activated;
}

protected override void OnClosing( System.ComponentModel.CancelEventArgs e )
Expand All @@ -213,7 +227,12 @@ protected override IntPtr FilterMessage( IntPtr hwnd, int msg, IntPtr wParam, In
case Win32Helper.WM_NCLBUTTONDOWN: //Left button down on title -> start dragging over docking manager
if( wParam.ToInt32() == Win32Helper.HT_CAPTION )
{
_model.Descendents().OfType<LayoutAnchorablePane>().First( p => p.ChildrenCount > 0 && p.SelectedContent != null ).SelectedContent.IsActive = true;
var anchorablePane = _model.Descendents().OfType<LayoutAnchorablePane>()
.FirstOrDefault( p => p.ChildrenCount > 0 && p.SelectedContent != null );
if( anchorablePane != null )
{
anchorablePane.SelectedContent.IsActive = true;
}
handled = true;
}
break;
Expand Down Expand Up @@ -308,6 +327,59 @@ private bool IsContextMenuOpen()
return false;
}

private void SetVisibilityBinding()
{
SetBinding(
VisibilityProperty,
new Binding( "IsVisible" )
{
Source = _model,
Converter = new BoolToVisibilityConverter(),
Mode = BindingMode.OneWay,
ConverterParameter = Visibility.Hidden
}
);
}

#endregion

#region Public Methods

public override void EnableBindings()
{
_model.PropertyChanged += _model_PropertyChanged;
SetVisibilityBinding();
var root = Model.Root;
if( root != null )
{
LayoutRoot layoutRoot = root as LayoutRoot;
if ( layoutRoot != null )
{
layoutRoot.Updated += OnRootUpdated;
}
}

base.EnableBindings();
}

public override void DisableBindings()
{
var root = Model.Root;
if( root != null )
{
LayoutRoot layoutRoot = root as LayoutRoot;
if( layoutRoot != null )
{
layoutRoot.Updated -= OnRootUpdated;
}
}

BindingOperations.ClearBinding( _model, VisibilityProperty );
_model.PropertyChanged -= _model_PropertyChanged;

base.DisableBindings();
}

#endregion

#region Commands
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class LayoutAnchorableItem : LayoutItem
private ICommand _defaultAutoHideCommand;
private ICommand _defaultDockCommand;
private ReentrantFlag _visibilityReentrantFlag = new ReentrantFlag();
private ReentrantFlag _anchorableVisibilityReentrantFlag = new ReentrantFlag();

#endregion

Expand Down Expand Up @@ -377,9 +378,9 @@ private void _anchorable_IsVisibleChanged( object sender, EventArgs e )
{
if( _anchorable != null && _anchorable.Root != null )
{
if( _visibilityReentrantFlag.CanEnter )
if( _anchorableVisibilityReentrantFlag.CanEnter )
{
using( _visibilityReentrantFlag.Enter() )
using( _anchorableVisibilityReentrantFlag.Enter() )
{
if( _anchorable.IsVisible )
Visibility = Visibility.Visible;
Expand All @@ -390,12 +391,6 @@ private void _anchorable_IsVisibleChanged( object sender, EventArgs e )
}
}







#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,8 @@ internal virtual void UpdateThemeResources( Theme oldTheme = null )
}
}

var manager = _model.Root.Manager;
if( manager.Theme != null )
var manager = _model.Root?.Manager;
if( manager?.Theme != null )
{
if( manager.Theme is DictionaryTheme )
{
Expand Down Expand Up @@ -531,6 +531,14 @@ private void UpdateDragPosition()

#endregion

public virtual void EnableBindings()
{
}

public virtual void DisableBindings()
{
}

#region Internal Classes

protected internal class FloatingWindowContentHost : HwndHost
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -641,12 +641,17 @@ private bool IsChildVisible(int index)
{
if( Orientation == Orientation.Horizontal )
{
return ColumnDefinitions[index].Width.IsStar || ColumnDefinitions[index].Width.Value > 0;
if ( index < ColumnDefinitions.Count )
{
return ColumnDefinitions[ index ].Width.IsStar || ColumnDefinitions[ index ].Width.Value > 0;
}
}
else
else if( index < RowDefinitions.Count )
{
return RowDefinitions[ index ].Height.IsStar || RowDefinitions[ index ].Height.Value > 0;
}

return false;
}

private void ShowResizerOverlayWindow( LayoutGridResizerControl splitter )
Expand Down
Loading

0 comments on commit ba7e81a

Please sign in to comment.