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.

3587 lines
123 KiB

/*************************************************************************************
Toolkit for WPF
Copyright (C) 2007-2020 Xceed Software Inc.
This program is provided to you under the terms of the XCEED SOFTWARE, INC.
COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
https://github.com/xceedsoftware/wpftoolkit/blob/master/license.md
For more features, controls, and fast professional support,
pick up the Plus Edition at https://xceed.com/xceed-toolkit-plus-for-wpf/
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Markup;
using System.ComponentModel;
using System.Windows.Interop;
using Xceed.Wpf.AvalonDock.Layout;
using Xceed.Wpf.AvalonDock.Controls;
using System.Windows.Input;
using System.Collections;
using System.Collections.Specialized;
using System.Windows.Data;
using System.Windows.Threading;
using Xceed.Wpf.AvalonDock.Themes;
using System.Diagnostics;
using System.Windows.Media;
using System.Windows.Controls.Primitives;
using System.Globalization;
namespace Xceed.Wpf.AvalonDock
{
[ContentProperty( "Layout" )]
[TemplatePart( Name = "PART_AutoHideArea" )]
public class DockingManager : Control, IOverlayWindowHost, IWeakEventListener//, ILogicalChildrenContainer
{
#region Members
private ResourceDictionary currentThemeResourceDictionary; // = null
private AutoHideWindowManager _autoHideWindowManager;
private FrameworkElement _autohideArea;
private List<LayoutFloatingWindowControl> _fwList = new List<LayoutFloatingWindowControl>();
private OverlayWindow _overlayWindow = null;
private List<IDropArea> _areas = null;
private bool _insideInternalSetActiveContent = false;
private List<LayoutItem> _layoutItems = new List<LayoutItem>();
private bool _suspendLayoutItemCreation = false;
private DispatcherOperation _collectLayoutItemsOperations = null;
private NavigatorWindow _navigatorWindow = null;
internal bool SuspendDocumentsSourceBinding = false;
internal bool SuspendAnchorablesSourceBinding = false;
#endregion
#region Constructors
static DockingManager()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( DockingManager ), new FrameworkPropertyMetadata( typeof( DockingManager ) ) );
FocusableProperty.OverrideMetadata( typeof( DockingManager ), new FrameworkPropertyMetadata( false ) );
HwndSource.DefaultAcquireHwndFocusInMenuMode = false;
}
public DockingManager()
{
#if !VS2008
Layout = new LayoutRoot() { RootPanel = new LayoutPanel( new LayoutDocumentPaneGroup( new LayoutDocumentPane() ) ) };
#else
this.SetCurrentValue( DockingManager.LayoutProperty, new LayoutRoot() { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) } );
#endif
this.Loaded += new RoutedEventHandler( DockingManager_Loaded );
this.Unloaded += new RoutedEventHandler( DockingManager_Unloaded );
}
#endregion
#region Properties
#region Layout
/// <summary>
/// Layout Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutProperty = DependencyProperty.Register( "Layout", typeof( LayoutRoot ), typeof( DockingManager ),
new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnLayoutChanged ), new CoerceValueCallback( CoerceLayoutValue ) ) );
/// <summary>
/// Gets or sets the Layout property. This dependency property
/// indicates layout tree.
/// </summary>
public LayoutRoot Layout
{
get
{
return ( LayoutRoot )GetValue( LayoutProperty );
}
set
{
SetValue( LayoutProperty, value );
}
}
/// <summary>
/// Coerces the <see cref="DockingManager.Layout"/> value.
/// </summary>
private static object CoerceLayoutValue( DependencyObject d, object value )
{
if( value == null )
return new LayoutRoot() { RootPanel = new LayoutPanel( new LayoutDocumentPaneGroup( new LayoutDocumentPane() ) ) };
( ( DockingManager )d ).OnLayoutChanging( value as LayoutRoot );
return value;
}
/// <summary>
/// Handles changes to the Layout property.
/// </summary>
private static void OnLayoutChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnLayoutChanged( e.OldValue as LayoutRoot, e.NewValue as LayoutRoot );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the <see cref="DockingManager.Layout"/> property.
/// </summary>
protected virtual void OnLayoutChanged( LayoutRoot oldLayout, LayoutRoot newLayout )
{
if( oldLayout != null )
{
oldLayout.PropertyChanged -= new PropertyChangedEventHandler( OnLayoutRootPropertyChanged );
oldLayout.Updated -= new EventHandler( OnLayoutRootUpdated );
}
foreach( var fwc in _fwList.ToArray() )
{
fwc.KeepContentVisibleOnClose = true;
fwc.InternalClose();
}
_fwList.Clear();
DetachDocumentsSource( oldLayout, DocumentsSource );
DetachAnchorablesSource( oldLayout, AnchorablesSource );
if( oldLayout != null &&
oldLayout.Manager == this )
oldLayout.Manager = null;
ClearLogicalChildrenList();
DetachLayoutItems();
Layout.Manager = this;
AttachLayoutItems();
AttachDocumentsSource( newLayout, DocumentsSource );
AttachAnchorablesSource( newLayout, AnchorablesSource );
if( IsLoaded )
{
LayoutRootPanel = CreateUIElementForModel( Layout.RootPanel ) as LayoutPanelControl;
LeftSidePanel = CreateUIElementForModel( Layout.LeftSide ) as LayoutAnchorSideControl;
TopSidePanel = CreateUIElementForModel( Layout.TopSide ) as LayoutAnchorSideControl;
RightSidePanel = CreateUIElementForModel( Layout.RightSide ) as LayoutAnchorSideControl;
BottomSidePanel = CreateUIElementForModel( Layout.BottomSide ) as LayoutAnchorSideControl;
foreach( var fw in Layout.FloatingWindows.ToArray() )
{
if( fw.IsValid )
_fwList.Add( CreateUIElementForModel( fw ) as LayoutFloatingWindowControl );
}
foreach( var fw in _fwList )
{
//fw.Owner = Window.GetWindow(this);
//fw.SetParentToMainWindowOf(this);
}
}
if( newLayout != null )
{
newLayout.PropertyChanged += new PropertyChangedEventHandler( OnLayoutRootPropertyChanged );
newLayout.Updated += new EventHandler( OnLayoutRootUpdated );
}
if( LayoutChanged != null )
LayoutChanged( this, EventArgs.Empty );
//if (Layout != null)
// Layout.CollectGarbage();
CommandManager.InvalidateRequerySuggested();
}
#endregion
#region LayoutUpdateStrategy
/// <summary>
/// LayoutUpdateStrategy Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutUpdateStrategyProperty = DependencyProperty.Register( "LayoutUpdateStrategy", typeof( ILayoutUpdateStrategy ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( ILayoutUpdateStrategy )null ) );
/// <summary>
/// Gets or sets the LayoutUpdateStrategy property. This dependency property
/// indicates the strategy class to call when AvalonDock needs to positionate a LayoutAnchorable inside an existing layout.
/// </summary>
/// <remarks>Sometimes it's impossible to automatically insert an anchorable in the layout without specifing the target parent pane.
/// Set this property to an object that will be asked to insert the anchorable to the desidered position.</remarks>
public ILayoutUpdateStrategy LayoutUpdateStrategy
{
get
{
return ( ILayoutUpdateStrategy )GetValue( LayoutUpdateStrategyProperty );
}
set
{
SetValue( LayoutUpdateStrategyProperty, value );
}
}
#endregion
#region DocumentPaneTemplate
/// <summary>
/// DocumentPaneTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentPaneTemplateProperty = DependencyProperty.Register( "DocumentPaneTemplate", typeof( ControlTemplate ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( ControlTemplate )null, new PropertyChangedCallback( OnDocumentPaneTemplateChanged ) ) );
/// <summary>
/// Gets or sets the DocumentPaneDataTemplate property. This dependency property
/// indicates .
/// </summary>
public ControlTemplate DocumentPaneTemplate
{
get
{
return ( ControlTemplate )GetValue( DocumentPaneTemplateProperty );
}
set
{
SetValue( DocumentPaneTemplateProperty, value );
}
}
/// <summary>
/// Handles changes to the DocumentPaneTemplate property.
/// </summary>
private static void OnDocumentPaneTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnDocumentPaneTemplateChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentPaneTemplate property.
/// </summary>
protected virtual void OnDocumentPaneTemplateChanged( DependencyPropertyChangedEventArgs e )
{
}
#endregion
#region AnchorablePaneTemplate
/// <summary>
/// AnchorablePaneTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorablePaneTemplateProperty = DependencyProperty.Register( "AnchorablePaneTemplate", typeof( ControlTemplate ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( ControlTemplate )null, new PropertyChangedCallback( OnAnchorablePaneTemplateChanged ) ) );
/// <summary>
/// Gets or sets the AnchorablePaneTemplate property. This dependency property
/// indicates ....
/// </summary>
public ControlTemplate AnchorablePaneTemplate
{
get
{
return ( ControlTemplate )GetValue( AnchorablePaneTemplateProperty );
}
set
{
SetValue( AnchorablePaneTemplateProperty, value );
}
}
/// <summary>
/// Handles changes to the AnchorablePaneDataTemplate property.
/// </summary>
private static void OnAnchorablePaneTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnAnchorablePaneTemplateChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorablePaneDataTemplate property.
/// </summary>
protected virtual void OnAnchorablePaneTemplateChanged( DependencyPropertyChangedEventArgs e )
{
}
#endregion
#region AnchorSideTemplate
/// <summary>
/// AnchorSideTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorSideTemplateProperty = DependencyProperty.Register( "AnchorSideTemplate", typeof( ControlTemplate ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( ControlTemplate )null ) );
/// <summary>
/// Gets or sets the AnchorSideTemplate property. This dependency property
/// indicates ....
/// </summary>
public ControlTemplate AnchorSideTemplate
{
get
{
return ( ControlTemplate )GetValue( AnchorSideTemplateProperty );
}
set
{
SetValue( AnchorSideTemplateProperty, value );
}
}
#endregion
#region AnchorGroupTemplate
/// <summary>
/// AnchorGroupTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorGroupTemplateProperty = DependencyProperty.Register( "AnchorGroupTemplate", typeof( ControlTemplate ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( ControlTemplate )null ) );
/// <summary>
/// Gets or sets the AnchorGroupTemplate property. This dependency property
/// indicates the template used to render the AnchorGroup control.
/// </summary>
public ControlTemplate AnchorGroupTemplate
{
get
{
return ( ControlTemplate )GetValue( AnchorGroupTemplateProperty );
}
set
{
SetValue( AnchorGroupTemplateProperty, value );
}
}
#endregion
#region AnchorTemplate
/// <summary>
/// AnchorTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorTemplateProperty = DependencyProperty.Register( "AnchorTemplate", typeof( ControlTemplate ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( ControlTemplate )null ) );
/// <summary>
/// Gets or sets the AnchorTemplate property. This dependency property
/// indicates ....
/// </summary>
public ControlTemplate AnchorTemplate
{
get
{
return ( ControlTemplate )GetValue( AnchorTemplateProperty );
}
set
{
SetValue( AnchorTemplateProperty, value );
}
}
#endregion
#region DocumentPaneControlStyle
/// <summary>
/// DocumentPaneControlStyle Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentPaneControlStyleProperty = DependencyProperty.Register( "DocumentPaneControlStyle", typeof( Style ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( Style )null, new PropertyChangedCallback( OnDocumentPaneControlStyleChanged ) ) );
/// <summary>
/// Gets or sets the DocumentPaneControlStyle property. This dependency property
/// indicates ....
/// </summary>
public Style DocumentPaneControlStyle
{
get
{
return ( Style )GetValue( DocumentPaneControlStyleProperty );
}
set
{
SetValue( DocumentPaneControlStyleProperty, value );
}
}
/// <summary>
/// Handles changes to the DocumentPaneControlStyle property.
/// </summary>
private static void OnDocumentPaneControlStyleChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnDocumentPaneControlStyleChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentPaneControlStyle property.
/// </summary>
protected virtual void OnDocumentPaneControlStyleChanged( DependencyPropertyChangedEventArgs e )
{
}
#endregion
#region AnchorablePaneControlStyle
/// <summary>
/// AnchorablePaneControlStyle Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorablePaneControlStyleProperty = DependencyProperty.Register( "AnchorablePaneControlStyle", typeof( Style ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( Style )null, new PropertyChangedCallback( OnAnchorablePaneControlStyleChanged ) ) );
/// <summary>
/// Gets or sets the AnchorablePaneControlStyle property. This dependency property
/// indicates the style to apply to AnchorablePaneControl.
/// </summary>
public Style AnchorablePaneControlStyle
{
get
{
return ( Style )GetValue( AnchorablePaneControlStyleProperty );
}
set
{
SetValue( AnchorablePaneControlStyleProperty, value );
}
}
/// <summary>
/// Handles changes to the AnchorablePaneControlStyle property.
/// </summary>
private static void OnAnchorablePaneControlStyleChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnAnchorablePaneControlStyleChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorablePaneControlStyle property.
/// </summary>
protected virtual void OnAnchorablePaneControlStyleChanged( DependencyPropertyChangedEventArgs e )
{
}
#endregion
#region DocumentHeaderTemplate
/// <summary>
/// DocumentHeaderTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentHeaderTemplateProperty = DependencyProperty.Register( "DocumentHeaderTemplate", typeof( DataTemplate ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnDocumentHeaderTemplateChanged ), new CoerceValueCallback( CoerceDocumentHeaderTemplateValue ) ) );
/// <summary>
/// Gets or sets the DocumentHeaderTemplate property. This dependency property
/// indicates data template to use for document header.
/// </summary>
public DataTemplate DocumentHeaderTemplate
{
get
{
return ( DataTemplate )GetValue( DocumentHeaderTemplateProperty );
}
set
{
SetValue( DocumentHeaderTemplateProperty, value );
}
}
/// <summary>
/// Handles changes to the DocumentHeaderTemplate property.
/// </summary>
private static void OnDocumentHeaderTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnDocumentHeaderTemplateChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplate property.
/// </summary>
protected virtual void OnDocumentHeaderTemplateChanged( DependencyPropertyChangedEventArgs e )
{
}
/// <summary>
/// Coerces the DocumentHeaderTemplate value.
/// </summary>
private static object CoerceDocumentHeaderTemplateValue( DependencyObject d, object value )
{
if( value != null &&
d.GetValue( DocumentHeaderTemplateSelectorProperty ) != null )
return null;
return value;
}
#endregion
#region DocumentHeaderTemplateSelector
/// <summary>
/// DocumentHeaderTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentHeaderTemplateSelectorProperty = DependencyProperty.Register( "DocumentHeaderTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnDocumentHeaderTemplateSelectorChanged ), new CoerceValueCallback( CoerceDocumentHeaderTemplateSelectorValue ) ) );
/// <summary>
/// Gets or sets the DocumentHeaderTemplateSelector property. This dependency property
/// indicates the template selector that is used when selcting the data template for the header.
/// </summary>
public DataTemplateSelector DocumentHeaderTemplateSelector
{
get
{
return ( DataTemplateSelector )GetValue( DocumentHeaderTemplateSelectorProperty );
}
set
{
SetValue( DocumentHeaderTemplateSelectorProperty, value );
}
}
/// <summary>
/// Handles changes to the DocumentHeaderTemplateSelector property.
/// </summary>
private static void OnDocumentHeaderTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnDocumentHeaderTemplateSelectorChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplateSelector property.
/// </summary>
protected virtual void OnDocumentHeaderTemplateSelectorChanged( DependencyPropertyChangedEventArgs e )
{
if( e.NewValue != null &&
DocumentHeaderTemplate != null )
DocumentHeaderTemplate = null;
if( DocumentPaneMenuItemHeaderTemplateSelector == null )
DocumentPaneMenuItemHeaderTemplateSelector = DocumentHeaderTemplateSelector;
}
/// <summary>
/// Coerces the DocumentHeaderTemplateSelector value.
/// </summary>
private static object CoerceDocumentHeaderTemplateSelectorValue( DependencyObject d, object value )
{
return value;
}
#endregion
#region DocumentTitleTemplate
/// <summary>
/// DocumentTitleTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentTitleTemplateProperty = DependencyProperty.Register( "DocumentTitleTemplate", typeof( DataTemplate ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnDocumentTitleTemplateChanged ), new CoerceValueCallback( CoerceDocumentTitleTemplateValue ) ) );
/// <summary>
/// Gets or sets the DocumentTitleTemplate property. This dependency property
/// indicates the datatemplate to use when creating the title for a document.
/// </summary>
public DataTemplate DocumentTitleTemplate
{
get
{
return ( DataTemplate )GetValue( DocumentTitleTemplateProperty );
}
set
{
SetValue( DocumentTitleTemplateProperty, value );
}
}
/// <summary>
/// Handles changes to the DocumentTitleTemplate property.
/// </summary>
private static void OnDocumentTitleTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnDocumentTitleTemplateChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentTitleTemplate property.
/// </summary>
protected virtual void OnDocumentTitleTemplateChanged( DependencyPropertyChangedEventArgs e )
{
}
/// <summary>
/// Coerces the DocumentTitleTemplate value.
/// </summary>
private static object CoerceDocumentTitleTemplateValue( DependencyObject d, object value )
{
if( value != null &&
d.GetValue( DocumentTitleTemplateSelectorProperty ) != null )
return null;
return value;
}
#endregion
#region DocumentTitleTemplateSelector
/// <summary>
/// DocumentTitleTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentTitleTemplateSelectorProperty = DependencyProperty.Register( "DocumentTitleTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnDocumentTitleTemplateSelectorChanged ), new CoerceValueCallback( CoerceDocumentTitleTemplateSelectorValue ) ) );
/// <summary>
/// Gets or sets the DocumentTitleTemplateSelector property. This dependency property
/// indicates the data template selector to use when creating the data template for the title.
/// </summary>
public DataTemplateSelector DocumentTitleTemplateSelector
{
get
{
return ( DataTemplateSelector )GetValue( DocumentTitleTemplateSelectorProperty );
}
set
{
SetValue( DocumentTitleTemplateSelectorProperty, value );
}
}
/// <summary>
/// Handles changes to the DocumentTitleTemplateSelector property.
/// </summary>
private static void OnDocumentTitleTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnDocumentTitleTemplateSelectorChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentTitleTemplateSelector property.
/// </summary>
protected virtual void OnDocumentTitleTemplateSelectorChanged( DependencyPropertyChangedEventArgs e )
{
if( e.NewValue != null )
DocumentTitleTemplate = null;
}
/// <summary>
/// Coerces the DocumentTitleTemplateSelector value.
/// </summary>
private static object CoerceDocumentTitleTemplateSelectorValue( DependencyObject d, object value )
{
return value;
}
#endregion
#region AnchorableTitleTemplate
/// <summary>
/// AnchorableTitleTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorableTitleTemplateProperty = DependencyProperty.Register( "AnchorableTitleTemplate", typeof( DataTemplate ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnAnchorableTitleTemplateChanged ), new CoerceValueCallback( CoerceAnchorableTitleTemplateValue ) ) );
/// <summary>
/// Gets or sets the AnchorableTitleTemplate property. This dependency property
/// indicates the data template to use for anchorables title.
/// </summary>
public DataTemplate AnchorableTitleTemplate
{
get
{
return ( DataTemplate )GetValue( AnchorableTitleTemplateProperty );
}
set
{
SetValue( AnchorableTitleTemplateProperty, value );
}
}
/// <summary>
/// Handles changes to the AnchorableTitleTemplate property.
/// </summary>
private static void OnAnchorableTitleTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnAnchorableTitleTemplateChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplate property.
/// </summary>
protected virtual void OnAnchorableTitleTemplateChanged( DependencyPropertyChangedEventArgs e )
{
}
/// <summary>
/// Coerces the AnchorableTitleTemplate value.
/// </summary>
private static object CoerceAnchorableTitleTemplateValue( DependencyObject d, object value )
{
if( value != null &&
d.GetValue( AnchorableTitleTemplateSelectorProperty ) != null )
return null;
return value;
}
#endregion
#region AnchorableTitleTemplateSelector
/// <summary>
/// AnchorableTitleTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorableTitleTemplateSelectorProperty = DependencyProperty.Register( "AnchorableTitleTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnAnchorableTitleTemplateSelectorChanged ) ) );
/// <summary>
/// Gets or sets the AnchorableTitleTemplateSelector property. This dependency property
/// indicates selctor to use when selecting data template for the title of anchorables.
/// </summary>
public DataTemplateSelector AnchorableTitleTemplateSelector
{
get
{
return ( DataTemplateSelector )GetValue( AnchorableTitleTemplateSelectorProperty );
}
set
{
SetValue( AnchorableTitleTemplateSelectorProperty, value );
}
}
/// <summary>
/// Handles changes to the AnchorableTitleTemplateSelector property.
/// </summary>
private static void OnAnchorableTitleTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnAnchorableTitleTemplateSelectorChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplateSelector property.
/// </summary>
protected virtual void OnAnchorableTitleTemplateSelectorChanged( DependencyPropertyChangedEventArgs e )
{
if( e.NewValue != null &&
AnchorableTitleTemplate != null )
AnchorableTitleTemplate = null;
}
#endregion
#region AnchorableHeaderTemplate
/// <summary>
/// AnchorableHeaderTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorableHeaderTemplateProperty = DependencyProperty.Register( "AnchorableHeaderTemplate", typeof( DataTemplate ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnAnchorableHeaderTemplateChanged ), new CoerceValueCallback( CoerceAnchorableHeaderTemplateValue ) ) );
/// <summary>
/// Gets or sets the AnchorableHeaderTemplate property. This dependency property
/// indicates the data template to use for anchorable templates.
/// </summary>
public DataTemplate AnchorableHeaderTemplate
{
get
{
return ( DataTemplate )GetValue( AnchorableHeaderTemplateProperty );
}
set
{
SetValue( AnchorableHeaderTemplateProperty, value );
}
}
/// <summary>
/// Handles changes to the AnchorableHeaderTemplate property.
/// </summary>
private static void OnAnchorableHeaderTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnAnchorableHeaderTemplateChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplate property.
/// </summary>
protected virtual void OnAnchorableHeaderTemplateChanged( DependencyPropertyChangedEventArgs e )
{
}
/// <summary>
/// Coerces the AnchorableHeaderTemplate value.
/// </summary>
private static object CoerceAnchorableHeaderTemplateValue( DependencyObject d, object value )
{
if( value != null &&
d.GetValue( AnchorableHeaderTemplateSelectorProperty ) != null )
return null;
return value;
}
#endregion
#region AnchorableHeaderTemplateSelector
/// <summary>
/// AnchorableHeaderTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorableHeaderTemplateSelectorProperty = DependencyProperty.Register( "AnchorableHeaderTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnAnchorableHeaderTemplateSelectorChanged ) ) );
/// <summary>
/// Gets or sets the AnchorableHeaderTemplateSelector property. This dependency property
/// indicates the selector to use when selecting the data template for anchorable headers.
/// </summary>
public DataTemplateSelector AnchorableHeaderTemplateSelector
{
get
{
return ( DataTemplateSelector )GetValue( AnchorableHeaderTemplateSelectorProperty );
}
set
{
SetValue( AnchorableHeaderTemplateSelectorProperty, value );
}
}
/// <summary>
/// Handles changes to the AnchorableHeaderTemplateSelector property.
/// </summary>
private static void OnAnchorableHeaderTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnAnchorableHeaderTemplateSelectorChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplateSelector property.
/// </summary>
protected virtual void OnAnchorableHeaderTemplateSelectorChanged( DependencyPropertyChangedEventArgs e )
{
if( e.NewValue != null )
AnchorableHeaderTemplate = null;
}
#endregion
#region LayoutRootPanel
/// <summary>
/// LayoutRootPanel Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutRootPanelProperty = DependencyProperty.Register( "LayoutRootPanel", typeof( LayoutPanelControl ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( LayoutPanelControl )null, new PropertyChangedCallback( OnLayoutRootPanelChanged ) ) );
/// <summary>
/// Gets or sets the LayoutRootPanel property. This dependency property
/// indicates the layout panel control which is attached to the Layout.Root property.
/// </summary>
public LayoutPanelControl LayoutRootPanel
{
get
{
return ( LayoutPanelControl )GetValue( LayoutRootPanelProperty );
}
set
{
SetValue( LayoutRootPanelProperty, value );
}
}
/// <summary>
/// Handles changes to the LayoutRootPanel property.
/// </summary>
private static void OnLayoutRootPanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnLayoutRootPanelChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the LayoutRootPanel property.
/// </summary>
protected virtual void OnLayoutRootPanelChanged( DependencyPropertyChangedEventArgs e )
{
if( e.OldValue != null )
InternalRemoveLogicalChild( e.OldValue );
if( e.NewValue != null )
InternalAddLogicalChild( e.NewValue );
}
#endregion
#region RightSidePanel
/// <summary>
/// RightSidePanel Dependency Property
/// </summary>
public static readonly DependencyProperty RightSidePanelProperty = DependencyProperty.Register( "RightSidePanel", typeof( LayoutAnchorSideControl ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( LayoutAnchorSideControl )null, new PropertyChangedCallback( OnRightSidePanelChanged ) ) );
/// <summary>
/// Gets or sets the RightSidePanel property. This dependency property
/// indicates right side anchor panel.
/// </summary>
public LayoutAnchorSideControl RightSidePanel
{
get
{
return ( LayoutAnchorSideControl )GetValue( RightSidePanelProperty );
}
set
{
SetValue( RightSidePanelProperty, value );
}
}
/// <summary>
/// Handles changes to the RightSidePanel property.
/// </summary>
private static void OnRightSidePanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnRightSidePanelChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the RightSidePanel property.
/// </summary>
protected virtual void OnRightSidePanelChanged( DependencyPropertyChangedEventArgs e )
{
if( e.OldValue != null )
InternalRemoveLogicalChild( e.OldValue );
if( e.NewValue != null )
InternalAddLogicalChild( e.NewValue );
}
#endregion
#region LeftSidePanel
/// <summary>
/// LeftSidePanel Dependency Property
/// </summary>
public static readonly DependencyProperty LeftSidePanelProperty = DependencyProperty.Register( "LeftSidePanel", typeof( LayoutAnchorSideControl ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( LayoutAnchorSideControl )null, new PropertyChangedCallback( OnLeftSidePanelChanged ) ) );
/// <summary>
/// Gets or sets the LeftSidePanel property. This dependency property
/// indicates the left side panel control.
/// </summary>
public LayoutAnchorSideControl LeftSidePanel
{
get
{
return ( LayoutAnchorSideControl )GetValue( LeftSidePanelProperty );
}
set
{
SetValue( LeftSidePanelProperty, value );
}
}
/// <summary>
/// Handles changes to the LeftSidePanel property.
/// </summary>
private static void OnLeftSidePanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnLeftSidePanelChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the LeftSidePanel property.
/// </summary>
protected virtual void OnLeftSidePanelChanged( DependencyPropertyChangedEventArgs e )
{
if( e.OldValue != null )
InternalRemoveLogicalChild( e.OldValue );
if( e.NewValue != null )
InternalAddLogicalChild( e.NewValue );
}
#endregion
#region TopSidePanel
/// <summary>
/// TopSidePanel Dependency Property
/// </summary>
public static readonly DependencyProperty TopSidePanelProperty = DependencyProperty.Register( "TopSidePanel", typeof( LayoutAnchorSideControl ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( LayoutAnchorSideControl )null, new PropertyChangedCallback( OnTopSidePanelChanged ) ) );
/// <summary>
/// Gets or sets the TopSidePanel property. This dependency property
/// indicates top side control panel.
/// </summary>
public LayoutAnchorSideControl TopSidePanel
{
get
{
return ( LayoutAnchorSideControl )GetValue( TopSidePanelProperty );
}
set
{
SetValue( TopSidePanelProperty, value );
}
}
/// <summary>
/// Handles changes to the TopSidePanel property.
/// </summary>
private static void OnTopSidePanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnTopSidePanelChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the TopSidePanel property.
/// </summary>
protected virtual void OnTopSidePanelChanged( DependencyPropertyChangedEventArgs e )
{
if( e.OldValue != null )
InternalRemoveLogicalChild( e.OldValue );
if( e.NewValue != null )
InternalAddLogicalChild( e.NewValue );
}
#endregion
#region BottomSidePanel
/// <summary>
/// BottomSidePanel Dependency Property
/// </summary>
public static readonly DependencyProperty BottomSidePanelProperty = DependencyProperty.Register( "BottomSidePanel", typeof( LayoutAnchorSideControl ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( LayoutAnchorSideControl )null, new PropertyChangedCallback( OnBottomSidePanelChanged ) ) );
/// <summary>
/// Gets or sets the BottomSidePanel property. This dependency property
/// indicates bottom side panel control.
/// </summary>
public LayoutAnchorSideControl BottomSidePanel
{
get
{
return ( LayoutAnchorSideControl )GetValue( BottomSidePanelProperty );
}
set
{
SetValue( BottomSidePanelProperty, value );
}
}
/// <summary>
/// Handles changes to the BottomSidePanel property.
/// </summary>
private static void OnBottomSidePanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnBottomSidePanelChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the BottomSidePanel property.
/// </summary>
protected virtual void OnBottomSidePanelChanged( DependencyPropertyChangedEventArgs e )
{
if( e.OldValue != null )
InternalRemoveLogicalChild( e.OldValue );
if( e.NewValue != null )
InternalAddLogicalChild( e.NewValue );
}
#endregion
#region LogicalChildren
List<WeakReference> _logicalChildren = new List<WeakReference>();
protected override System.Collections.IEnumerator LogicalChildren
{
get
{
return _logicalChildren.Select( ch => ch.GetValueOrDefault<object>() ).GetEnumerator();
}
}
public System.Collections.IEnumerator LogicalChildrenPublic
{
get
{
return this.LogicalChildren;
}
}
internal void InternalAddLogicalChild( object element )
{
#if DEBUG
if( _logicalChildren.Select( ch => ch.GetValueOrDefault<object>() ).Contains( element ) )
new InvalidOperationException();
#endif
if( _logicalChildren.Select( ch => ch.GetValueOrDefault<object>() ).Contains( element ) )
return;
_logicalChildren.Add( new WeakReference( element ) );
AddLogicalChild( element );
}
internal void InternalRemoveLogicalChild( object element )
{
var wrToRemove = _logicalChildren.FirstOrDefault( ch => ch.GetValueOrDefault<object>() == element );
if( wrToRemove != null )
_logicalChildren.Remove( wrToRemove );
RemoveLogicalChild( element );
}
private void ClearLogicalChildrenList()
{
foreach( var child in _logicalChildren.Select( ch => ch.GetValueOrDefault<object>() ).ToArray() )
RemoveLogicalChild( child );
_logicalChildren.Clear();
}
#endregion
#region AutoHideWindow
/// <summary>
/// AutoHideWindow Read-Only Dependency Property
/// </summary>
private static readonly DependencyPropertyKey AutoHideWindowPropertyKey = DependencyProperty.RegisterReadOnly( "AutoHideWindow", typeof( LayoutAutoHideWindowControl ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( LayoutAutoHideWindowControl )null, new PropertyChangedCallback( OnAutoHideWindowChanged ) ) );
public static readonly DependencyProperty AutoHideWindowProperty = AutoHideWindowPropertyKey.DependencyProperty;
/// <summary>
/// Gets the AutoHideWindow property. This dependency property
/// indicates the currently shown autohide window.
/// </summary>
public LayoutAutoHideWindowControl AutoHideWindow
{
get
{
return ( LayoutAutoHideWindowControl )GetValue( AutoHideWindowProperty );
}
}
/// <summary>
/// Provides a secure method for setting the AutoHideWindow property.
/// This dependency property indicates the currently shown autohide window.
/// </summary>
/// <param name="value">The new value for the property.</param>
protected void SetAutoHideWindow( LayoutAutoHideWindowControl value )
{
SetValue( AutoHideWindowPropertyKey, value );
}
/// <summary>
/// Handles changes to the AutoHideWindow property.
/// </summary>
private static void OnAutoHideWindowChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnAutoHideWindowChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AutoHideWindow property.
/// </summary>
protected virtual void OnAutoHideWindowChanged( DependencyPropertyChangedEventArgs e )
{
if( e.OldValue != null )
InternalRemoveLogicalChild( e.OldValue );
if( e.NewValue != null )
InternalAddLogicalChild( e.NewValue );
}
#endregion
#region Floating Windows
public IEnumerable<LayoutFloatingWindowControl> FloatingWindows
{
get
{
return _fwList;
}
}
#endregion
#region LayoutItemTemplate
/// <summary>
/// LayoutItemTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutItemTemplateProperty = DependencyProperty.Register( "LayoutItemTemplate", typeof( DataTemplate ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnLayoutItemTemplateChanged ) ) );
/// <summary>
/// Gets or sets the AnchorableTemplate property. This dependency property
/// indicates the template to use to render anchorable and document contents.
/// </summary>
public DataTemplate LayoutItemTemplate
{
get
{
return ( DataTemplate )GetValue( LayoutItemTemplateProperty );
}
set
{
SetValue( LayoutItemTemplateProperty, value );
}
}
/// <summary>
/// Handles changes to the AnchorableTemplate property.
/// </summary>
private static void OnLayoutItemTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnLayoutItemTemplateChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorableTemplate property.
/// </summary>
protected virtual void OnLayoutItemTemplateChanged( DependencyPropertyChangedEventArgs e )
{
}
#endregion
#region LayoutItemTemplateSelector
/// <summary>
/// LayoutItemTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutItemTemplateSelectorProperty = DependencyProperty.Register( "LayoutItemTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnLayoutItemTemplateSelectorChanged ) ) );
/// <summary>
/// Gets or sets the LayoutItemTemplateSelector property. This dependency property
/// indicates selector object to use for anchorable templates.
/// </summary>
public DataTemplateSelector LayoutItemTemplateSelector
{
get
{
return ( DataTemplateSelector )GetValue( LayoutItemTemplateSelectorProperty );
}
set
{
SetValue( LayoutItemTemplateSelectorProperty, value );
}
}
/// <summary>
/// Handles changes to the LayoutItemTemplateSelector property.
/// </summary>
private static void OnLayoutItemTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnLayoutItemTemplateSelectorChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the LayoutItemTemplateSelector property.
/// </summary>
protected virtual void OnLayoutItemTemplateSelectorChanged( DependencyPropertyChangedEventArgs e )
{
}
#endregion
#region DocumentsSource
/// <summary>
/// DocumentsSource Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentsSourceProperty = DependencyProperty.Register( "DocumentsSource", typeof( IEnumerable ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( IEnumerable )null, new PropertyChangedCallback( OnDocumentsSourceChanged ) ) );
/// <summary>
/// Gets or sets the DocumentsSource property. This dependency property
/// indicates the source collection of documents.
/// </summary>
public IEnumerable DocumentsSource
{
get
{
return ( IEnumerable )GetValue( DocumentsSourceProperty );
}
set
{
SetValue( DocumentsSourceProperty, value );
}
}
/// <summary>
/// Handles changes to the DocumentsSource property.
/// </summary>
private static void OnDocumentsSourceChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnDocumentsSourceChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentsSource property.
/// </summary>
protected virtual void OnDocumentsSourceChanged( DependencyPropertyChangedEventArgs e )
{
DetachDocumentsSource( Layout, e.OldValue as IEnumerable );
AttachDocumentsSource( Layout, e.NewValue as IEnumerable );
}
#endregion
#region DocumentContextMenu
/// <summary>
/// DocumentContextMenu Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentContextMenuProperty = DependencyProperty.Register( "DocumentContextMenu", typeof( ContextMenu ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( ContextMenu )null ) );
/// <summary>
/// Gets or sets the DocumentContextMenu property. This dependency property
/// indicates context menu to show for documents.
/// </summary>
public ContextMenu DocumentContextMenu
{
get
{
return ( ContextMenu )GetValue( DocumentContextMenuProperty );
}
set
{
SetValue( DocumentContextMenuProperty, value );
}
}
#endregion
#region AnchorablesSource
/// <summary>
/// AnchorablesSource Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorablesSourceProperty = DependencyProperty.Register( "AnchorablesSource", typeof( IEnumerable ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( IEnumerable )null, new PropertyChangedCallback( OnAnchorablesSourceChanged ) ) );
/// <summary>
/// Gets or sets the AnchorablesSource property. This dependency property
/// indicates source collection of anchorables.
/// </summary>
public IEnumerable AnchorablesSource
{
get
{
return ( IEnumerable )GetValue( AnchorablesSourceProperty );
}
set
{
SetValue( AnchorablesSourceProperty, value );
}
}
/// <summary>
/// Handles changes to the AnchorablesSource property.
/// </summary>
private static void OnAnchorablesSourceChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnAnchorablesSourceChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorablesSource property.
/// </summary>
protected virtual void OnAnchorablesSourceChanged( DependencyPropertyChangedEventArgs e )
{
DetachAnchorablesSource( Layout, e.OldValue as IEnumerable );
AttachAnchorablesSource( Layout, e.NewValue as IEnumerable );
}
#endregion
#region ActiveContent
/// <summary>
/// ActiveContent Dependency Property
/// </summary>
public static readonly DependencyProperty ActiveContentProperty = DependencyProperty.Register( "ActiveContent", typeof( object ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( object )null, new PropertyChangedCallback( OnActiveContentChanged ) ) );
/// <summary>
/// Gets or sets the ActiveContent property. This dependency property
/// indicates the content currently active.
/// </summary>
public object ActiveContent
{
get
{
return ( object )GetValue( ActiveContentProperty );
}
set
{
SetValue( ActiveContentProperty, value );
}
}
/// <summary>
/// Handles changes to the ActiveContent property.
/// </summary>
private static void OnActiveContentChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).InternalSetActiveContent( e.NewValue );
( ( DockingManager )d ).OnActiveContentChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the ActiveContent property.
/// </summary>
protected virtual void OnActiveContentChanged( DependencyPropertyChangedEventArgs e )
{
if( ActiveContentChanged != null )
ActiveContentChanged( this, EventArgs.Empty );
}
#endregion
#region AnchorableContextMenu
/// <summary>
/// AnchorableContextMenu Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorableContextMenuProperty = DependencyProperty.Register( "AnchorableContextMenu", typeof( ContextMenu ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( ContextMenu )null ) );
/// <summary>
/// Gets or sets the AnchorableContextMenu property. This dependency property
/// indicates the context menu to show up for anchorables.
/// </summary>
public ContextMenu AnchorableContextMenu
{
get
{
return ( ContextMenu )GetValue( AnchorableContextMenuProperty );
}
set
{
SetValue( AnchorableContextMenuProperty, value );
}
}
#endregion
#region Theme
/// <summary>
/// Theme Dependency Property
/// </summary>
public static readonly DependencyProperty ThemeProperty = DependencyProperty.Register( "Theme", typeof( Theme ), typeof( DockingManager ),
new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnThemeChanged ) ) );
/// <summary>
/// Gets or sets the Theme property. This dependency property
/// indicates the theme to use for AvalonDock controls.
/// </summary>
public Theme Theme
{
get
{
return ( Theme )GetValue( ThemeProperty );
}
set
{
SetValue( ThemeProperty, value );
}
}
/// <summary>
/// Handles changes to the Theme property.
/// </summary>
private static void OnThemeChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnThemeChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the Theme property.
/// </summary>
protected virtual void OnThemeChanged( DependencyPropertyChangedEventArgs e )
{
var oldTheme = e.OldValue as Theme;
var newTheme = e.NewValue as Theme;
var resources = this.Resources;
if( oldTheme != null )
{
if( oldTheme is DictionaryTheme )
{
if( currentThemeResourceDictionary != null )
{
resources.MergedDictionaries.Remove( currentThemeResourceDictionary );
currentThemeResourceDictionary = null;
}
}
else
{
var resourceDictionaryToRemove =
resources.MergedDictionaries.FirstOrDefault( r => r.Source == oldTheme.GetResourceUri() );
if( resourceDictionaryToRemove != null )
resources.MergedDictionaries.Remove(
resourceDictionaryToRemove );
}
}
if( newTheme != null )
{
if( newTheme is DictionaryTheme )
{
currentThemeResourceDictionary = ( ( DictionaryTheme )newTheme ).ThemeResourceDictionary;
resources.MergedDictionaries.Add( currentThemeResourceDictionary );
}
else
{
resources.MergedDictionaries.Add( new ResourceDictionary() { Source = newTheme.GetResourceUri() } );
}
}
foreach( var fwc in _fwList )
fwc.UpdateThemeResources( oldTheme );
if( _navigatorWindow != null )
_navigatorWindow.UpdateThemeResources();
if( _overlayWindow != null )
_overlayWindow.UpdateThemeResources();
}
#endregion
#region GridSplitterWidth
/// <summary>
/// GridSplitterWidth Dependency Property
/// </summary>
public static readonly DependencyProperty GridSplitterWidthProperty = DependencyProperty.Register( "GridSplitterWidth", typeof( double ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( double )6.0 ) );
/// <summary>
/// Gets or sets the GridSplitterWidth property. This dependency property
/// indicates width of grid splitters.
/// </summary>
public double GridSplitterWidth
{
get
{
return ( double )GetValue( GridSplitterWidthProperty );
}
set
{
SetValue( GridSplitterWidthProperty, value );
}
}
#endregion
#region GridSplitterHeight
/// <summary>
/// GridSplitterHeight Dependency Property
/// </summary>
public static readonly DependencyProperty GridSplitterHeightProperty = DependencyProperty.Register( "GridSplitterHeight", typeof( double ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( double )6.0 ) );
/// <summary>
/// Gets or sets the GridSplitterHeight property. This dependency property
/// indicates height of grid splitters.
/// </summary>
public double GridSplitterHeight
{
get
{
return ( double )GetValue( GridSplitterHeightProperty );
}
set
{
SetValue( GridSplitterHeightProperty, value );
}
}
#endregion
#region DocumentPaneMenuItemHeaderTemplate
/// <summary>
/// DocumentPaneMenuItemHeaderTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateProperty = DependencyProperty.Register( "DocumentPaneMenuItemHeaderTemplate", typeof( DataTemplate ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnDocumentPaneMenuItemHeaderTemplateChanged ), new CoerceValueCallback( CoerceDocumentPaneMenuItemHeaderTemplateValue ) ) );
/// <summary>
/// Gets or sets the DocumentPaneMenuItemHeaderTemplate property. This dependency property
/// indicates the header template to use while creating menu items for the document panes.
/// </summary>
public DataTemplate DocumentPaneMenuItemHeaderTemplate
{
get
{
return ( DataTemplate )GetValue( DocumentPaneMenuItemHeaderTemplateProperty );
}
set
{
SetValue( DocumentPaneMenuItemHeaderTemplateProperty, value );
}
}
/// <summary>
/// Handles changes to the DocumentPaneMenuItemHeaderTemplate property.
/// </summary>
private static void OnDocumentPaneMenuItemHeaderTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnDocumentPaneMenuItemHeaderTemplateChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplate property.
/// </summary>
protected virtual void OnDocumentPaneMenuItemHeaderTemplateChanged( DependencyPropertyChangedEventArgs e )
{
}
/// <summary>
/// Coerces the DocumentPaneMenuItemHeaderTemplate value.
/// </summary>
private static object CoerceDocumentPaneMenuItemHeaderTemplateValue( DependencyObject d, object value )
{
if( value != null &&
d.GetValue( DocumentPaneMenuItemHeaderTemplateSelectorProperty ) != null )
return null;
if( value == null )
return d.GetValue( DocumentHeaderTemplateProperty );
return value;
}
#endregion
#region DocumentPaneMenuItemHeaderTemplateSelector
/// <summary>
/// DocumentPaneMenuItemHeaderTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateSelectorProperty = DependencyProperty.Register( "DocumentPaneMenuItemHeaderTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnDocumentPaneMenuItemHeaderTemplateSelectorChanged ), new CoerceValueCallback( CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue ) ) );
/// <summary>
/// Gets or sets the DocumentPaneMenuItemHeaderTemplateSelector property. This dependency property
/// indicates the data template selector to use for the menu items show when user select the DocumentPane document switch context menu.
/// </summary>
public DataTemplateSelector DocumentPaneMenuItemHeaderTemplateSelector
{
get
{
return ( DataTemplateSelector )GetValue( DocumentPaneMenuItemHeaderTemplateSelectorProperty );
}
set
{
SetValue( DocumentPaneMenuItemHeaderTemplateSelectorProperty, value );
}
}
/// <summary>
/// Handles changes to the DocumentPaneMenuItemHeaderTemplateSelector property.
/// </summary>
private static void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnDocumentPaneMenuItemHeaderTemplateSelectorChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplateSelector property.
/// </summary>
protected virtual void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged( DependencyPropertyChangedEventArgs e )
{
if( e.NewValue != null &&
DocumentPaneMenuItemHeaderTemplate != null )
DocumentPaneMenuItemHeaderTemplate = null;
}
/// <summary>
/// Coerces the DocumentPaneMenuItemHeaderTemplateSelector value.
/// </summary>
private static object CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue( DependencyObject d, object value )
{
return value;
}
#endregion
#region IconContentTemplate
/// <summary>
/// IconContentTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty IconContentTemplateProperty = DependencyProperty.Register( "IconContentTemplate", typeof( DataTemplate ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplate )null ) );
/// <summary>
/// Gets or sets the IconContentTemplate property. This dependency property
/// indicates the data template to use while extracting the icon from model.
/// </summary>
public DataTemplate IconContentTemplate
{
get
{
return ( DataTemplate )GetValue( IconContentTemplateProperty );
}
set
{
SetValue( IconContentTemplateProperty, value );
}
}
#endregion
#region IconContentTemplateSelector
/// <summary>
/// IconContentTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty IconContentTemplateSelectorProperty = DependencyProperty.Register( "IconContentTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( DataTemplateSelector )null ) );
/// <summary>
/// Gets or sets the IconContentTemplateSelector property. This dependency property
/// indicates data template selector to use while selecting the datatamplate for content icons.
/// </summary>
public DataTemplateSelector IconContentTemplateSelector
{
get
{
return ( DataTemplateSelector )GetValue( IconContentTemplateSelectorProperty );
}
set
{
SetValue( IconContentTemplateSelectorProperty, value );
}
}
#endregion
#region LayoutItemContainerStyle
/// <summary>
/// LayoutItemContainerStyle Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutItemContainerStyleProperty = DependencyProperty.Register( "LayoutItemContainerStyle", typeof( Style ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( Style )null, new PropertyChangedCallback( OnLayoutItemContainerStyleChanged ) ) );
/// <summary>
/// Gets or sets the LayoutItemContainerStyle property. This dependency property
/// indicates the style to apply to LayoutDocumentItem objects. A LayoutDocumentItem object is created when a new LayoutDocument is created inside the current Layout.
/// </summary>
public Style LayoutItemContainerStyle
{
get
{
return ( Style )GetValue( LayoutItemContainerStyleProperty );
}
set
{
SetValue( LayoutItemContainerStyleProperty, value );
}
}
/// <summary>
/// Handles changes to the LayoutItemContainerStyle property.
/// </summary>
private static void OnLayoutItemContainerStyleChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnLayoutItemContainerStyleChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyle property.
/// </summary>
protected virtual void OnLayoutItemContainerStyleChanged( DependencyPropertyChangedEventArgs e )
{
AttachLayoutItems();
}
#endregion
#region LayoutItemContainerStyleSelector
/// <summary>
/// LayoutItemContainerStyleSelector Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutItemContainerStyleSelectorProperty = DependencyProperty.Register( "LayoutItemContainerStyleSelector", typeof( StyleSelector ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( StyleSelector )null, new PropertyChangedCallback( OnLayoutItemContainerStyleSelectorChanged ) ) );
/// <summary>
/// Gets or sets the LayoutItemContainerStyleSelector property. This dependency property
/// indicates style selector of the LayoutDocumentItemStyle.
/// </summary>
public StyleSelector LayoutItemContainerStyleSelector
{
get
{
return ( StyleSelector )GetValue( LayoutItemContainerStyleSelectorProperty );
}
set
{
SetValue( LayoutItemContainerStyleSelectorProperty, value );
}
}
/// <summary>
/// Handles changes to the LayoutItemContainerStyleSelector property.
/// </summary>
private static void OnLayoutItemContainerStyleSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
( ( DockingManager )d ).OnLayoutItemContainerStyleSelectorChanged( e );
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyleSelector property.
/// </summary>
protected virtual void OnLayoutItemContainerStyleSelectorChanged( DependencyPropertyChangedEventArgs e )
{
AttachLayoutItems();
}
#endregion
#region ShowSystemMenu
/// <summary>
/// ShowSystemMenu Dependency Property
/// </summary>
public static readonly DependencyProperty ShowSystemMenuProperty = DependencyProperty.Register( "ShowSystemMenu", typeof( bool ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( bool )true ) );
/// <summary>
/// Gets or sets the ShowSystemMenu property. This dependency property
/// indicates if floating windows should show the system menu when a custom context menu is not defined.
/// </summary>
public bool ShowSystemMenu
{
get
{
return ( bool )GetValue( ShowSystemMenuProperty );
}
set
{
SetValue( ShowSystemMenuProperty, value );
}
}
#endregion
#region AllowMixedOrientation
/// <summary>
/// AllowMixedOrientation Dependency Property
/// </summary>
public static readonly DependencyProperty AllowMixedOrientationProperty = DependencyProperty.Register( "AllowMixedOrientation", typeof( bool ), typeof( DockingManager ),
new FrameworkPropertyMetadata( ( bool )false ) );
/// <summary>
/// Gets or sets the AllowMixedOrientation property. This dependency property
/// indicates if the manager should allow mixed orientation for document panes.
/// </summary>
public bool AllowMixedOrientation
{
get
{
return ( bool )GetValue( AllowMixedOrientationProperty );
}
set
{
SetValue( AllowMixedOrientationProperty, value );
}
}
#endregion
#endregion
#region Internal Properties
internal bool IsNavigatorWindowActive
{
get
{
return _navigatorWindow != null;
}
}
#endregion
#region Overrides
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_autohideArea = GetTemplateChild( "PART_AutoHideArea" ) as FrameworkElement;
}
protected override void OnInitialized( EventArgs e )
{
base.OnInitialized( e );
}
protected override Size ArrangeOverride( Size arrangeBounds )
{
_areas = null;
return base.ArrangeOverride( arrangeBounds );
}
protected override void OnPreviewKeyDown( KeyEventArgs e )
{
if( Keyboard.IsKeyDown( Key.LeftCtrl ) || Keyboard.IsKeyDown( Key.RightCtrl ) )
{
if( e.IsDown && e.Key == Key.Tab )
{
if( !IsNavigatorWindowActive )
{
ShowNavigatorWindow();
e.Handled = true;
}
}
}
base.OnPreviewKeyDown( e );
}
protected override void OnKeyDown( KeyEventArgs e )
{
if( Keyboard.IsKeyDown( Key.LeftShift ) || Keyboard.IsKeyDown( Key.RightShift ) )
{
if( e.IsDown && Keyboard.IsKeyDown( Key.F10 ) )
{
var current = this.ActiveContent as DependencyObject;
while( current != null )
{
current = VisualTreeHelper.GetParent( current );
if( ( current is LayoutDocumentControl ) || ( current is LayoutAnchorableControl ) )
break;
}
if( current != null )
{
var ldc = current as LayoutDocumentControl;
if( ( ldc != null ) && ( this.DocumentContextMenu != null ) )
{
this.DocumentContextMenu.PlacementTarget = ldc;
this.DocumentContextMenu.Placement = PlacementMode.Relative;
this.DocumentContextMenu.DataContext = ldc.LayoutItem;
this.DocumentContextMenu.IsOpen = true;
}
else
{
var lac = current as LayoutAnchorableControl;
if( ( lac != null ) && ( this.AnchorableContextMenu != null) )
{
this.AnchorableContextMenu.PlacementTarget = lac;
this.AnchorableContextMenu.Placement = PlacementMode.Relative;
this.AnchorableContextMenu.DataContext = lac.LayoutItem;
this.AnchorableContextMenu.Opened += this.AnchorableContextMenu_Opened;
this.AnchorableContextMenu.IsOpen = true;
}
}
}
}
}
base.OnKeyDown( e );
}
#endregion
#region Public Methods
/// <summary>
/// Return the LayoutItem wrapper for the content passed as argument
/// </summary>
/// <param name="content">LayoutContent to search</param>
/// <returns>Either a LayoutAnchorableItem or LayoutDocumentItem which contains the LayoutContent passed as argument</returns>
public LayoutItem GetLayoutItemFromModel( LayoutContent content )
{
if( _layoutItems == null )
return null;
return _layoutItems.FirstOrDefault( item => item.LayoutElement == content );
}
public LayoutFloatingWindowControl CreateFloatingWindow( LayoutContent contentModel, bool isContentImmutable )
{
LayoutFloatingWindowControl lfwc = null;
if( contentModel is LayoutAnchorable )
{
var parent = contentModel.Parent as ILayoutPane;
if( parent == null )
{
var pane = new LayoutAnchorablePane( contentModel as LayoutAnchorable )
{
FloatingTop = contentModel.FloatingTop,
FloatingLeft = contentModel.FloatingLeft,
FloatingWidth = contentModel.FloatingWidth,
FloatingHeight = contentModel.FloatingHeight
};
lfwc = this.CreateFloatingWindowForLayoutAnchorableWithoutParent( pane, isContentImmutable );
}
}
if( lfwc == null )
{
lfwc = this.CreateFloatingWindowCore( contentModel, isContentImmutable );
}
return lfwc;
}
#endregion
#region Internal Methods
internal UIElement CreateUIElementForModel( ILayoutElement model )
{
if( model is LayoutPanel )
return new LayoutPanelControl( model as LayoutPanel );
if( model is LayoutAnchorablePaneGroup )
return new LayoutAnchorablePaneGroupControl( model as LayoutAnchorablePaneGroup );
if( model is LayoutDocumentPaneGroup )
return new LayoutDocumentPaneGroupControl( model as LayoutDocumentPaneGroup );
if( model is LayoutAnchorSide )
{
var templateModelView = new LayoutAnchorSideControl( model as LayoutAnchorSide );
templateModelView.SetBinding( LayoutAnchorSideControl.TemplateProperty, new Binding( DockingManager.AnchorSideTemplateProperty.Name ) { Source = this } );
return templateModelView;
}
if( model is LayoutAnchorGroup )
{
var templateModelView = new LayoutAnchorGroupControl( model as LayoutAnchorGroup );
templateModelView.SetBinding( LayoutAnchorGroupControl.TemplateProperty, new Binding( DockingManager.AnchorGroupTemplateProperty.Name ) { Source = this } );
return templateModelView;
}
if( model is LayoutDocumentPane )
{
var templateModelView = new LayoutDocumentPaneControl( model as LayoutDocumentPane );
templateModelView.SetBinding( LayoutDocumentPaneControl.StyleProperty, new Binding( DockingManager.DocumentPaneControlStyleProperty.Name ) { Source = this } );
return templateModelView;
}
if( model is LayoutAnchorablePane )
{
var templateModelView = new LayoutAnchorablePaneControl( model as LayoutAnchorablePane );
templateModelView.SetBinding( LayoutAnchorablePaneControl.StyleProperty, new Binding( DockingManager.AnchorablePaneControlStyleProperty.Name ) { Source = this } );
return templateModelView;
}
if( model is LayoutAnchorableFloatingWindow )
{
if( DesignerProperties.GetIsInDesignMode( this ) )
return null;
var modelFW = model as LayoutAnchorableFloatingWindow;
var newFW = new LayoutAnchorableFloatingWindowControl( modelFW )
{
//Owner = Window.GetWindow(this)
};
newFW.SetParentToMainWindowOf( this );
var paneForExtensions = modelFW.RootPanel.Descendents().OfType<LayoutAnchorablePane>().FirstOrDefault();
if( paneForExtensions != null )
{
//ensure that floating window position is inside current (or nearest) monitor
paneForExtensions.KeepInsideNearestMonitor();
newFW.Left = paneForExtensions.FloatingLeft;
newFW.Top = paneForExtensions.FloatingTop;
newFW.Width = paneForExtensions.FloatingWidth;
newFW.Height = paneForExtensions.FloatingHeight;
}
newFW.ShowInTaskbar = false;
Dispatcher.BeginInvoke( new Action( () =>
{
newFW.Show();
// Do not set the WindowState before showing or it will be lost
if( paneForExtensions != null && paneForExtensions.IsMaximized )
{
newFW.WindowState = WindowState.Maximized;
}
} ), DispatcherPriority.DataBind );
return newFW;
}
if( model is LayoutDocumentFloatingWindow )
{
if( DesignerProperties.GetIsInDesignMode( this ) )
return null;
var modelFW = model as LayoutDocumentFloatingWindow;
var newFW = new LayoutDocumentFloatingWindowControl( modelFW )
{
//Owner = Window.GetWindow(this)
};
newFW.SetParentToMainWindowOf( this );
var paneForExtensions = modelFW.RootDocument;
if( paneForExtensions != null )
{
//ensure that floating window position is inside current (or nearest) monitor
paneForExtensions.KeepInsideNearestMonitor();
newFW.Left = paneForExtensions.FloatingLeft;
newFW.Top = paneForExtensions.FloatingTop;
newFW.Width = paneForExtensions.FloatingWidth;
newFW.Height = paneForExtensions.FloatingHeight;
}
newFW.ShowInTaskbar = false;
newFW.Show();
// Do not set the WindowState before showing or it will be lost
if( paneForExtensions != null && paneForExtensions.IsMaximized )
{
newFW.WindowState = WindowState.Maximized;
}
return newFW;
}
if( model is LayoutDocument )
{
var templateModelView = new LayoutDocumentControl() { Model = model as LayoutDocument };
templateModelView.SetResourcesFromObject( this );
return templateModelView;
}
return null;
}
internal void ShowAutoHideWindow( LayoutAnchorControl anchor )
{
_autoHideWindowManager.ShowAutoHideWindow( anchor );
//if (_autohideArea == null)
// return;
//if (AutoHideWindow != null && AutoHideWindow.Model == anchor.Model)
// return;
//Trace.WriteLine("ShowAutoHideWindow()");
//_currentAutohiddenAnchor = new WeakReference(anchor);
//HideAutoHideWindow(anchor);
//SetAutoHideWindow(new LayoutAutoHideWindowControl(anchor));
//AutoHideWindow.Show();
}
internal void HideAutoHideWindow( LayoutAnchorControl anchor )
{
_autoHideWindowManager.HideAutoWindow( anchor );
}
internal FrameworkElement GetAutoHideAreaElement()
{
return _autohideArea;
}
internal void StartDraggingFloatingWindowForContent( LayoutContent contentModel, bool startDrag = true )
{
if( ( contentModel == null) || !contentModel.CanFloat )
return;
var fwc = this.CreateFloatingWindow( contentModel, false );
if( fwc != null )
{
Dispatcher.BeginInvoke( new Action( () =>
{
if( startDrag )
fwc.AttachDrag();
fwc.Show();
} ), DispatcherPriority.Send );
}
}
internal void StartDraggingFloatingWindowForPane( LayoutAnchorablePane paneModel )
{
var fwc = this.CreateFloatingWindowForLayoutAnchorableWithoutParent( paneModel, false );
if( fwc != null )
{
fwc.AttachDrag();
fwc.Show();
}
}
internal IEnumerable<LayoutFloatingWindowControl> GetFloatingWindowsByZOrder()
{
IntPtr windowParentHanlde;
var parentWindow = Window.GetWindow( this );
if( parentWindow != null )
{
windowParentHanlde = new WindowInteropHelper( parentWindow ).Handle;
}
else
{
var mainProcess = Process.GetCurrentProcess();
if( mainProcess == null )
yield break;
windowParentHanlde = mainProcess.MainWindowHandle;
}
IntPtr currentHandle = Win32Helper.GetWindow( windowParentHanlde, ( uint )Win32Helper.GetWindow_Cmd.GW_HWNDFIRST );
while( currentHandle != IntPtr.Zero )
{
LayoutFloatingWindowControl ctrl = _fwList.FirstOrDefault( fw => new WindowInteropHelper( fw ).Handle == currentHandle );
if( ctrl != null && ctrl.Model.Root.Manager == this )
yield return ctrl;
currentHandle = Win32Helper.GetWindow( currentHandle, ( uint )Win32Helper.GetWindow_Cmd.GW_HWNDNEXT );
}
}
internal void RemoveFloatingWindow( LayoutFloatingWindowControl floatingWindow )
{
_fwList.Remove( floatingWindow );
}
internal void _ExecuteCloseCommand( LayoutDocument document )
{
if( DocumentClosing != null )
{
var evargs = new DocumentClosingEventArgs( document );
DocumentClosing( this, evargs );
if( evargs.Cancel )
return;
}
if( document.CloseDocument() )
{
this.RemoveViewFromLogicalChild( document );
if( DocumentClosed != null )
{
var evargs = new DocumentClosedEventArgs( document );
DocumentClosed( this, evargs );
}
}
}
internal void _ExecuteCloseAllButThisCommand( LayoutContent contentSelected )
{
foreach( var contentToClose in Layout.Descendents().OfType<LayoutContent>().Where( d => d != contentSelected && ( d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow ) ).ToArray() )
{
this.Close( contentToClose );
}
}
internal void _ExecuteCloseAllCommand( LayoutContent contentSelected )
{
foreach( var contentToClose in Layout.Descendents().OfType<LayoutContent>().Where( d => ( d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow ) ).ToArray() )
{
this.Close( contentToClose );
}
}
internal void _ExecuteCloseCommand( LayoutAnchorable anchorable )
{
var model = anchorable as LayoutAnchorable;
if( model != null )
{
model.CloseAnchorable();
this.RemoveViewFromLogicalChild( anchorable );
}
}
internal void _ExecuteHideCommand( LayoutAnchorable anchorable )
{
var model = anchorable as LayoutAnchorable;
if( model != null )
{
model.Hide();
}
}
internal void _ExecuteAutoHideCommand( LayoutAnchorable _anchorable )
{
_anchorable.ToggleAutoHide();
}
internal void _ExecuteFloatCommand( LayoutContent contentToFloat )
{
contentToFloat.Float();
}
internal void _ExecuteDockCommand( LayoutAnchorable anchorable )
{
anchorable.Dock();
}
internal void _ExecuteDockAsDocumentCommand( LayoutContent content )
{
content.DockAsDocument();
}
internal void _ExecuteContentActivateCommand( LayoutContent content )
{
content.IsActive = true;
}
protected internal virtual void ShowNavigatorWindow()
{
if( _navigatorWindow == null )
{
_navigatorWindow = new NavigatorWindow( this )
{
Owner = Window.GetWindow( this ),
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
}
_navigatorWindow.ShowDialog();
_navigatorWindow = null;
}
#endregion
#region Private Methods
private void OnLayoutRootPropertyChanged( object sender, PropertyChangedEventArgs e )
{
if( e.PropertyName == "RootPanel" )
{
if( IsInitialized )
{
var layoutRootPanel = CreateUIElementForModel( Layout.RootPanel ) as LayoutPanelControl;
LayoutRootPanel = layoutRootPanel;
}
}
else if( e.PropertyName == "ActiveContent" )
{
if( Layout.ActiveContent != null )
{
//set focus on active element only after a layout pass is completed
//it's possible that it is not yet visible in the visual tree
//if (_setFocusAsyncOperation == null)
//{
// _setFocusAsyncOperation = Dispatcher.BeginInvoke(new Action(() =>
// {
if( Layout.ActiveContent != null )
FocusElementManager.SetFocusOnLastElement( Layout.ActiveContent );
//_setFocusAsyncOperation = null;
// } ), DispatcherPriority.Input );
//}
}
if( !_insideInternalSetActiveContent )
{
#if VS2008
this.ActiveContent = ( Layout.ActiveContent != null ) ? Layout.ActiveContent.Content : null;
#else
this.SetCurrentValue( DockingManager.ActiveContentProperty, ( Layout.ActiveContent != null ) ? Layout.ActiveContent.Content : null );
#endif
}
}
}
private void OnLayoutRootUpdated( object sender, EventArgs e )
{
CommandManager.InvalidateRequerySuggested();
}
private void OnLayoutChanging( LayoutRoot newLayout )
{
if( LayoutChanging != null )
LayoutChanging( this, EventArgs.Empty );
}
private void DockingManager_Loaded( object sender, RoutedEventArgs e )
{
if( !DesignerProperties.GetIsInDesignMode( this ) )
{
if( Layout.Manager == this )
{
LayoutRootPanel = CreateUIElementForModel( Layout.RootPanel ) as LayoutPanelControl;
LeftSidePanel = CreateUIElementForModel( Layout.LeftSide ) as LayoutAnchorSideControl;
TopSidePanel = CreateUIElementForModel( Layout.TopSide ) as LayoutAnchorSideControl;
RightSidePanel = CreateUIElementForModel( Layout.RightSide ) as LayoutAnchorSideControl;
BottomSidePanel = CreateUIElementForModel( Layout.BottomSide ) as LayoutAnchorSideControl;
}
SetupAutoHideWindow();
//load windows not already loaded!
foreach( var fw in Layout.FloatingWindows.Where( fw => !_fwList.Any( fwc => fwc.Model == fw ) ) )
_fwList.Add( CreateUIElementForModel( fw ) as LayoutFloatingWindowControl );
//create the overlaywindow if it's possible
if( IsVisible )
CreateOverlayWindow();
FocusElementManager.SetupFocusManagement( this );
}
}
private void DockingManager_Unloaded( object sender, RoutedEventArgs e )
{
if( !DesignerProperties.GetIsInDesignMode( this ) )
{
if( _autoHideWindowManager != null )
{
_autoHideWindowManager.HideAutoWindow();
}
if( AutoHideWindow != null )
{
AutoHideWindow.Dispose();
}
foreach( var fw in _fwList.ToArray() )
{
//fw.Owner = null;
fw.SetParentWindowToNull();
fw.KeepContentVisibleOnClose = true;
fw.Close();
}
_fwList.Clear();
DestroyOverlayWindow();
FocusElementManager.FinalizeFocusManagement( this );
}
}
private void SetupAutoHideWindow()
{
if( _autoHideWindowManager != null )
_autoHideWindowManager.HideAutoWindow();
else
_autoHideWindowManager = new AutoHideWindowManager( this );
if( AutoHideWindow != null )
{
AutoHideWindow.Dispose();
}
SetAutoHideWindow( new LayoutAutoHideWindowControl() );
}
private void CreateOverlayWindow()
{
if( _overlayWindow == null )
{
_overlayWindow = new OverlayWindow( this );
}
Rect rectWindow = new Rect( this.PointToScreenDPIWithoutFlowDirection( new Point() ), this.TransformActualSizeToAncestor() );
_overlayWindow.Left = rectWindow.Left;
_overlayWindow.Top = rectWindow.Top;
_overlayWindow.Width = rectWindow.Width;
_overlayWindow.Height = rectWindow.Height;
}
private void DestroyOverlayWindow()
{
if( _overlayWindow != null )
{
_overlayWindow.Close();
_overlayWindow = null;
}
}
private void AttachDocumentsSource( LayoutRoot layout, IEnumerable documentsSource )
{
if( documentsSource == null )
return;
if( layout == null )
return;
//if (layout.Descendents().OfType<LayoutDocument>().Any())
// throw new InvalidOperationException("Unable to set the DocumentsSource property if LayoutDocument objects are already present in the model");
var documentsImported = layout.Descendents().OfType<LayoutDocument>().Select( d => d.Content ).ToArray();
var documents = documentsSource as IEnumerable;
var listOfDocumentsToImport = new List<object>( documents.OfType<object>() );
foreach( var document in listOfDocumentsToImport.ToArray() )
{
if( documentsImported.Contains( document ) )
listOfDocumentsToImport.Remove( document );
}
LayoutDocumentPane documentPane = null;
if( layout.LastFocusedDocument != null )
{
documentPane = layout.LastFocusedDocument.Parent as LayoutDocumentPane;
}
if( documentPane == null )
{
documentPane = layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
}
//if (documentPane == null)
// throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents");
_suspendLayoutItemCreation = true;
foreach( var documentContentToImport in listOfDocumentsToImport )
{
//documentPane.Children.Add(new LayoutDocument() { Content = documentToImport });
var documentToImport = new LayoutDocument()
{
Content = documentContentToImport,
ContentId = Guid.NewGuid().ToString()
};
bool added = false;
if( LayoutUpdateStrategy != null )
{
added = LayoutUpdateStrategy.BeforeInsertDocument( layout, documentToImport, documentPane );
}
if( !added )
{
if( documentPane == null )
throw new InvalidOperationException( "Layout must contains at least one LayoutDocumentPane in order to host documents" );
documentPane.Children.Add( documentToImport );
added = true;
}
if( LayoutUpdateStrategy != null )
LayoutUpdateStrategy.AfterInsertDocument( layout, documentToImport );
CreateDocumentLayoutItem( documentToImport );
}
_suspendLayoutItemCreation = false;
var documentsSourceAsNotifier = documentsSource as INotifyCollectionChanged;
if( documentsSourceAsNotifier != null )
{
CollectionChangedEventManager.AddListener( documentsSourceAsNotifier, this );
}
}
private void documentsSourceElementsChanged( object sender, NotifyCollectionChangedEventArgs e )
{
if( Layout == null )
return;
//When deserializing documents are created automatically by the deserializer
if( SuspendDocumentsSourceBinding )
return;
//handle remove
if( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove ||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace )
{
if( e.OldItems != null )
{
var documentsToRemove = Layout.Descendents().OfType<LayoutDocument>().Where( d => e.OldItems.Contains( d.Content ) ).ToArray();
foreach( var documentToRemove in documentsToRemove )
{
//documentToRemove.Content = null;
( documentToRemove.Parent as ILayoutContainer ).RemoveChild(
documentToRemove );
this.RemoveViewFromLogicalChild( documentToRemove );
}
}
}
//handle add
if( e.NewItems != null &&
( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add ||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) )
{
if( e.NewItems != null )
{
LayoutDocumentPane documentPane = null;
if( Layout.LastFocusedDocument != null )
{
documentPane = Layout.LastFocusedDocument.Parent as LayoutDocumentPane;
}
if( documentPane == null )
{
documentPane = Layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
}
//if (documentPane == null)
// throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents");
_suspendLayoutItemCreation = true;
foreach( var documentContentToImport in e.NewItems )
{
var documentToImport = new LayoutDocument()
{
Content = documentContentToImport
};
bool added = false;
if( LayoutUpdateStrategy != null )
{
added = LayoutUpdateStrategy.BeforeInsertDocument( Layout, documentToImport, documentPane );
}
if( !added )
{
if( documentPane == null )
throw new InvalidOperationException( "Layout must contains at least one LayoutDocumentPane in order to host documents" );
documentPane.Children.Add( documentToImport );
added = true;
}
if( LayoutUpdateStrategy != null )
{
LayoutUpdateStrategy.AfterInsertDocument( Layout, documentToImport );
}
var root = documentToImport.Root;
if( root != null && root.Manager == this )
{
CreateDocumentLayoutItem( documentToImport );
}
}
_suspendLayoutItemCreation = false;
}
}
if( e.Action == NotifyCollectionChangedAction.Reset )
{
//NOTE: I'm going to clear every document present in layout but
//some documents may have been added directly to the layout, for now I clear them too
var documentsToRemove = Layout.Descendents().OfType<LayoutDocument>().ToArray();
foreach( var documentToRemove in documentsToRemove )
{
( documentToRemove.Parent as ILayoutContainer ).RemoveChild(
documentToRemove );
this.RemoveViewFromLogicalChild( documentToRemove );
}
}
if( Layout != null )
{
Layout.CollectGarbage();
}
}
private void DetachDocumentsSource( LayoutRoot layout, IEnumerable documentsSource )
{
if( documentsSource == null )
return;
if( layout == null )
return;
var documentsToRemove = layout.Descendents().OfType<LayoutDocument>()
.Where( d => documentsSource.Contains( d.Content ) ).ToArray();
foreach( var documentToRemove in documentsToRemove )
{
( documentToRemove.Parent as ILayoutContainer ).RemoveChild(
documentToRemove );
this.RemoveViewFromLogicalChild( documentToRemove );
}
var documentsSourceAsNotifier = documentsSource as INotifyCollectionChanged;
if( documentsSourceAsNotifier != null )
{
CollectionChangedEventManager.RemoveListener( documentsSourceAsNotifier, this );
}
}
private void Close( LayoutContent contentToClose )
{
if( !contentToClose.CanClose )
return;
var layoutItem = GetLayoutItemFromModel( contentToClose );
if( layoutItem.CloseCommand != null )
{
if( layoutItem.CloseCommand.CanExecute( null ) )
layoutItem.CloseCommand.Execute( null );
}
else
{
if( contentToClose is LayoutDocument )
_ExecuteCloseCommand( contentToClose as LayoutDocument );
else if( contentToClose is LayoutAnchorable )
_ExecuteCloseCommand( contentToClose as LayoutAnchorable );
}
}
private void AttachAnchorablesSource( LayoutRoot layout, IEnumerable anchorablesSource )
{
if( anchorablesSource == null )
return;
if( layout == null )
return;
//if (layout.Descendents().OfType<LayoutAnchorable>().Any())
// throw new InvalidOperationException("Unable to set the AnchorablesSource property if LayoutAnchorable objects are already present in the model");
var anchorablesImported = layout.Descendents().OfType<LayoutAnchorable>().Select( d => d.Content ).ToArray();
var anchorables = anchorablesSource as IEnumerable;
var listOfAnchorablesToImport = new List<object>( anchorables.OfType<object>() );
foreach( var document in listOfAnchorablesToImport.ToArray() )
{
if( anchorablesImported.Contains( document ) )
listOfAnchorablesToImport.Remove( document );
}
LayoutAnchorablePane anchorablePane = null;
if( layout.ActiveContent != null )
{
//look for active content parent pane
anchorablePane = layout.ActiveContent.Parent as LayoutAnchorablePane;
}
if( anchorablePane == null )
{
//look for a pane on the right side
anchorablePane = layout.Descendents().OfType<LayoutAnchorablePane>().Where( pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right ).FirstOrDefault();
}
if( anchorablePane == null )
{
//look for an available pane
anchorablePane = layout.Descendents().OfType<LayoutAnchorablePane>().FirstOrDefault();
}
_suspendLayoutItemCreation = true;
foreach( var anchorableContentToImport in listOfAnchorablesToImport )
{
var anchorableToImport = new LayoutAnchorable()
{
Content = anchorableContentToImport,
ContentId = Guid.NewGuid().ToString()
};
bool added = false;
if( LayoutUpdateStrategy != null )
{
added = LayoutUpdateStrategy.BeforeInsertAnchorable( layout, anchorableToImport, anchorablePane );
}
if( !added )
{
if( anchorablePane == null )
{
var mainLayoutPanel = new LayoutPanel() { Orientation = Orientation.Horizontal };
if( layout.RootPanel != null )
{
mainLayoutPanel.Children.Add( layout.RootPanel );
}
layout.RootPanel = mainLayoutPanel;
anchorablePane = new LayoutAnchorablePane() { DockWidth = new GridLength( 200.0, GridUnitType.Pixel ) };
mainLayoutPanel.Children.Add( anchorablePane );
}
anchorablePane.Children.Add( anchorableToImport );
added = true;
}
if( LayoutUpdateStrategy != null )
LayoutUpdateStrategy.AfterInsertAnchorable( layout, anchorableToImport );
CreateAnchorableLayoutItem( anchorableToImport );
}
_suspendLayoutItemCreation = false;
var anchorablesSourceAsNotifier = anchorablesSource as INotifyCollectionChanged;
if( anchorablesSourceAsNotifier != null )
{
CollectionChangedEventManager.AddListener( anchorablesSourceAsNotifier, this );
}
}
private void anchorablesSourceElementsChanged( object sender, NotifyCollectionChangedEventArgs e )
{
if( Layout == null )
return;
//When deserializing documents are created automatically by the deserializer
if( SuspendAnchorablesSourceBinding )
return;
//handle remove
if( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove ||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace )
{
if( e.OldItems != null )
{
var anchorablesToRemove = Layout.Descendents().OfType<LayoutAnchorable>().Where( d => e.OldItems.Contains( d.Content ) ).ToArray();
foreach( var anchorableToRemove in anchorablesToRemove )
{
anchorableToRemove.Content = null;
( anchorableToRemove.Parent as ILayoutContainer ).RemoveChild(
anchorableToRemove );
this.RemoveViewFromLogicalChild( anchorableToRemove );
}
}
}
//handle add
if( e.NewItems != null &&
( e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add ||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace ) )
{
if( e.NewItems != null )
{
LayoutAnchorablePane anchorablePane = null;
if( Layout.ActiveContent != null )
{
//look for active content parent pane
anchorablePane = Layout.ActiveContent.Parent as LayoutAnchorablePane;
}
if( anchorablePane == null )
{
//look for a pane on the right side
anchorablePane = Layout.Descendents().OfType<LayoutAnchorablePane>().Where( pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right ).FirstOrDefault();
}
if( anchorablePane == null )
{
//look for an available pane
anchorablePane = Layout.Descendents().OfType<LayoutAnchorablePane>().FirstOrDefault();
}
_suspendLayoutItemCreation = true;
foreach( var anchorableContentToImport in e.NewItems )
{
var anchorableToImport = new LayoutAnchorable()
{
Content = anchorableContentToImport
};
bool added = false;
if( LayoutUpdateStrategy != null )
{
added = LayoutUpdateStrategy.BeforeInsertAnchorable( Layout, anchorableToImport, anchorablePane );
}
if( !added )
{
if( anchorablePane == null )
{
var mainLayoutPanel = new LayoutPanel() { Orientation = Orientation.Horizontal };
if( Layout.RootPanel != null )
{
mainLayoutPanel.Children.Add( Layout.RootPanel );
}
Layout.RootPanel = mainLayoutPanel;
anchorablePane = new LayoutAnchorablePane() { DockWidth = new GridLength( 200.0, GridUnitType.Pixel ) };
mainLayoutPanel.Children.Add( anchorablePane );
}
anchorablePane.Children.Add( anchorableToImport );
added = true;
}
if( LayoutUpdateStrategy != null )
{
LayoutUpdateStrategy.AfterInsertAnchorable( Layout, anchorableToImport );
}
var root = anchorableToImport.Root;
if( root != null && root.Manager == this )
{
CreateAnchorableLayoutItem( anchorableToImport );
}
}
_suspendLayoutItemCreation = false;
}
}
if( e.Action == NotifyCollectionChangedAction.Reset )
{
//NOTE: I'm going to clear every anchorable present in layout but
//some anchorable may have been added directly to the layout, for now I clear them too
var anchorablesToRemove = Layout.Descendents().OfType<LayoutAnchorable>().ToArray();
foreach( var anchorableToRemove in anchorablesToRemove )
{
( anchorableToRemove.Parent as ILayoutContainer ).RemoveChild(
anchorableToRemove );
this.RemoveViewFromLogicalChild( anchorableToRemove );
}
}
if( Layout != null )
Layout.CollectGarbage();
}
private void DetachAnchorablesSource( LayoutRoot layout, IEnumerable anchorablesSource )
{
if( anchorablesSource == null )
return;
if( layout == null )
return;
var anchorablesToRemove = layout.Descendents().OfType<LayoutAnchorable>()
.Where( d => anchorablesSource.Contains( d.Content ) ).ToArray();
foreach( var anchorableToRemove in anchorablesToRemove )
{
( anchorableToRemove.Parent as ILayoutContainer ).RemoveChild(
anchorableToRemove );
this.RemoveViewFromLogicalChild( anchorableToRemove );
}
var anchorablesSourceAsNotifier = anchorablesSource as INotifyCollectionChanged;
if( anchorablesSourceAsNotifier != null )
{
CollectionChangedEventManager.RemoveListener( anchorablesSourceAsNotifier, this );
}
}
private void RemoveViewFromLogicalChild( LayoutContent layoutContent )
{
if( layoutContent == null )
return;
var layoutItem = this.GetLayoutItemFromModel( layoutContent );
if( layoutItem != null )
{
if( layoutItem.IsViewExists() )
{
this.InternalRemoveLogicalChild( layoutItem.View );
}
}
}
private void InternalSetActiveContent( object contentObject )
{
var layoutContent = Layout.Descendents().OfType<LayoutContent>().FirstOrDefault( lc => lc == contentObject || lc.Content == contentObject );
_insideInternalSetActiveContent = true;
Layout.ActiveContent = layoutContent;
_insideInternalSetActiveContent = false;
}
private void DetachLayoutItems()
{
if( Layout != null )
{
_layoutItems.ForEach<LayoutItem>( i => i.Detach() );
_layoutItems.Clear();
Layout.ElementAdded -= new EventHandler<LayoutElementEventArgs>( Layout_ElementAdded );
Layout.ElementRemoved -= new EventHandler<LayoutElementEventArgs>( Layout_ElementRemoved );
}
}
private void Layout_ElementRemoved( object sender, LayoutElementEventArgs e )
{
if( _suspendLayoutItemCreation )
return;
CollectLayoutItemsDeleted();
}
private void Layout_ElementAdded( object sender, LayoutElementEventArgs e )
{
if( _suspendLayoutItemCreation )
return;
foreach( var content in Layout.Descendents().OfType<LayoutContent>() )
{
if( content is LayoutDocument )
CreateDocumentLayoutItem( content as LayoutDocument );
else //if (content is LayoutAnchorable)
CreateAnchorableLayoutItem( content as LayoutAnchorable );
}
CollectLayoutItemsDeleted();
}
private void CollectLayoutItemsDeleted()
{
if( _collectLayoutItemsOperations != null )
return;
_collectLayoutItemsOperations = Dispatcher.BeginInvoke( new Action( () =>
{
_collectLayoutItemsOperations = null;
foreach( var itemToRemove in _layoutItems.Where( item => item.LayoutElement.Root != Layout ).ToArray() )
{
if( itemToRemove != null &&
itemToRemove.Model != null &&
itemToRemove.Model is UIElement )
{
//((ILogicalChildrenContainer)this).InternalRemoveLogicalChild(itemToRemove.Model as UIElement);
}
itemToRemove.Detach();
_layoutItems.Remove( itemToRemove );
}
} ) );
}
private void AttachLayoutItems()
{
if( Layout != null )
{
foreach( var document in Layout.Descendents().OfType<LayoutDocument>().ToArray() )
{
CreateDocumentLayoutItem( document );
//var documentItem = new LayoutDocumentItem();
//documentItem.Attach(document);
//ApplyStyleToLayoutItem(documentItem);
//_layoutItems.Add(documentItem);
}
foreach( var anchorable in Layout.Descendents().OfType<LayoutAnchorable>().ToArray() )
{
CreateAnchorableLayoutItem( anchorable );
//var anchorableItem = new LayoutAnchorableItem();
//anchorableItem.Attach(anchorable);
//ApplyStyleToLayoutItem(anchorableItem);
//_layoutItems.Add(anchorableItem);
}
Layout.ElementAdded += new EventHandler<LayoutElementEventArgs>( Layout_ElementAdded );
Layout.ElementRemoved += new EventHandler<LayoutElementEventArgs>( Layout_ElementRemoved );
}
}
private void ApplyStyleToLayoutItem( LayoutItem layoutItem )
{
layoutItem._ClearDefaultBindings();
if( LayoutItemContainerStyle != null )
layoutItem.Style = LayoutItemContainerStyle;
else if( LayoutItemContainerStyleSelector != null )
layoutItem.Style = LayoutItemContainerStyleSelector.SelectStyle( layoutItem.Model, layoutItem );
layoutItem._SetDefaultBindings();
}
private void CreateAnchorableLayoutItem( LayoutAnchorable contentToAttach )
{
if( _layoutItems.Any( item => item.LayoutElement == contentToAttach ) )
{
foreach( var item in _layoutItems )
{
ApplyStyleToLayoutItem( item );
}
return;
}
var layoutItem = new LayoutAnchorableItem();
layoutItem.Attach( contentToAttach );
ApplyStyleToLayoutItem( layoutItem );
_layoutItems.Add( layoutItem );
if( contentToAttach != null &&
contentToAttach.Content != null &&
contentToAttach.Content is UIElement )
{
InternalAddLogicalChild( contentToAttach.Content );
}
}
private void CreateDocumentLayoutItem( LayoutDocument contentToAttach )
{
if( _layoutItems.Any( item => item.LayoutElement == contentToAttach ) )
{
foreach( var item in _layoutItems )
{
ApplyStyleToLayoutItem( item );
}
return;
}
var layoutItem = new LayoutDocumentItem();
layoutItem.Attach( contentToAttach );
ApplyStyleToLayoutItem( layoutItem );
_layoutItems.Add( layoutItem );
if( contentToAttach != null &&
contentToAttach.Content != null &&
contentToAttach.Content is UIElement )
{
InternalAddLogicalChild( contentToAttach.Content );
}
}
private LayoutFloatingWindowControl CreateFloatingWindowForLayoutAnchorableWithoutParent( LayoutAnchorablePane paneModel, bool isContentImmutable )
{
if( paneModel.Children.Any( c => !c.CanFloat ) )
return null;
var paneAsPositionableElement = paneModel as ILayoutPositionableElement;
var paneAsWithActualSize = paneModel as ILayoutPositionableElementWithActualSize;
double fwWidth = paneAsPositionableElement.FloatingWidth;
double fwHeight = paneAsPositionableElement.FloatingHeight;
double fwLeft = paneAsPositionableElement.FloatingLeft;
double fwTop = paneAsPositionableElement.FloatingTop;
if( fwWidth == 0.0 )
fwWidth = paneAsWithActualSize.ActualWidth + 10; //10 includes BorderThickness and Margins inside LayoutAnchorableFloatingWindowControl.
if( fwHeight == 0.0 )
fwHeight = paneAsWithActualSize.ActualHeight + 10; //10 includes BorderThickness and Margins inside LayoutAnchorableFloatingWindowControl.
var destPane = new LayoutAnchorablePane()
{
DockWidth = paneAsPositionableElement.DockWidth,
DockHeight = paneAsPositionableElement.DockHeight,
DockMinHeight = paneAsPositionableElement.DockMinHeight,
DockMinWidth = paneAsPositionableElement.DockMinWidth,
FloatingLeft = paneAsPositionableElement.FloatingLeft,
FloatingTop = paneAsPositionableElement.FloatingTop,
FloatingWidth = paneAsPositionableElement.FloatingWidth,
FloatingHeight = paneAsPositionableElement.FloatingHeight,
};
bool savePreviousContainer = paneModel.FindParent<LayoutFloatingWindow>() == null;
int currentSelectedContentIndex = paneModel.SelectedContentIndex;
while( paneModel.Children.Count > 0 )
{
var contentModel = paneModel.Children[ paneModel.Children.Count - 1 ] as LayoutAnchorable;
if( savePreviousContainer )
{
var contentModelAsPreviousContainer = contentModel as ILayoutPreviousContainer;
contentModelAsPreviousContainer.PreviousContainer = paneModel;
contentModel.PreviousContainerIndex = paneModel.Children.Count - 1;
}
paneModel.RemoveChildAt( paneModel.Children.Count - 1 );
destPane.Children.Insert( 0, contentModel );
}
if( destPane.Children.Count > 0 )
{
destPane.SelectedContentIndex = currentSelectedContentIndex;
}
LayoutFloatingWindow fw;
LayoutFloatingWindowControl fwc;
fw = new LayoutAnchorableFloatingWindow()
{
RootPanel = new LayoutAnchorablePaneGroup(
destPane )
{
DockHeight = destPane.DockHeight,
DockWidth = destPane.DockWidth,
DockMinHeight = destPane.DockMinHeight,
DockMinWidth = destPane.DockMinWidth,
}
};
Layout.FloatingWindows.Add( fw );
fwc = new LayoutAnchorableFloatingWindowControl(
fw as LayoutAnchorableFloatingWindow, isContentImmutable )
{
Width = fwWidth,
Height = fwHeight,
Top = fwTop,
Left = fwLeft
};
//fwc.Owner = Window.GetWindow(this);
//fwc.SetParentToMainWindowOf(this);
_fwList.Add( fwc );
Layout.CollectGarbage();
InvalidateArrange();
return fwc;
}
private LayoutFloatingWindowControl CreateFloatingWindowCore( LayoutContent contentModel, bool isContentImmutable )
{
if( !contentModel.CanFloat )
return null;
var contentModelAsAnchorable = contentModel as LayoutAnchorable;
if( contentModelAsAnchorable != null &&
contentModelAsAnchorable.IsAutoHidden )
contentModelAsAnchorable.ToggleAutoHide();
this.UpdateStarSize( contentModel );
var parentPane = contentModel.Parent as ILayoutPane;
var parentPaneAsPositionableElement = contentModel.Parent as ILayoutPositionableElement;
var parentPaneAsWithActualSize = contentModel.Parent as ILayoutPositionableElementWithActualSize;
var contentModelParentChildrenIndex = parentPane.Children.ToList().IndexOf( contentModel );
if( contentModel.FindParent<LayoutFloatingWindow>() == null )
{
( (ILayoutPreviousContainer)contentModel ).PreviousContainer = parentPane;
contentModel.PreviousContainerIndex = contentModelParentChildrenIndex;
}
parentPane.RemoveChildAt( contentModelParentChildrenIndex );
double fwWidth = contentModel.FloatingWidth;
double fwHeight = contentModel.FloatingHeight;
if( fwWidth == 0.0 )
fwWidth = parentPaneAsPositionableElement.FloatingWidth;
if( fwHeight == 0.0 )
fwHeight = parentPaneAsPositionableElement.FloatingHeight;
if( fwWidth == 0.0 )
fwWidth = parentPaneAsWithActualSize.ActualWidth + 10; //10 includes BorderThickness and Margins inside LayoutDocumentFloatingWindowControl.
if( fwHeight == 0.0 )
fwHeight = parentPaneAsWithActualSize.ActualHeight + 10; //10 includes BorderThickness and Margins inside LayoutDocumentFloatingWindowControl.
LayoutFloatingWindow fw;
LayoutFloatingWindowControl fwc;
if( contentModel is LayoutAnchorable )
{
var anchorableContent = contentModel as LayoutAnchorable;
fw = new LayoutAnchorableFloatingWindow()
{
RootPanel = new LayoutAnchorablePaneGroup(
new LayoutAnchorablePane( anchorableContent )
{
DockWidth = parentPaneAsPositionableElement.DockWidth,
DockHeight = parentPaneAsPositionableElement.DockHeight,
DockMinHeight = parentPaneAsPositionableElement.DockMinHeight,
DockMinWidth = parentPaneAsPositionableElement.DockMinWidth,
FloatingLeft = parentPaneAsPositionableElement.FloatingLeft,
FloatingTop = parentPaneAsPositionableElement.FloatingTop,
FloatingWidth = parentPaneAsPositionableElement.FloatingWidth,
FloatingHeight = parentPaneAsPositionableElement.FloatingHeight,
} )
};
Layout.FloatingWindows.Add( fw );
fwc = new LayoutAnchorableFloatingWindowControl(
fw as LayoutAnchorableFloatingWindow, isContentImmutable )
{
Width = fwWidth,
Height = fwHeight,
Left = contentModel.FloatingLeft,
Top = contentModel.FloatingTop
};
}
else
{
var anchorableDocument = contentModel as LayoutDocument;
fw = new LayoutDocumentFloatingWindow()
{
RootDocument = anchorableDocument
};
Layout.FloatingWindows.Add( fw );
fwc = new LayoutDocumentFloatingWindowControl(
fw as LayoutDocumentFloatingWindow, isContentImmutable )
{
Width = fwWidth,
Height = fwHeight,
Left = contentModel.FloatingLeft,
Top = contentModel.FloatingTop
};
}
//fwc.Owner = Window.GetWindow(this);
//fwc.SetParentToMainWindowOf(this);
_fwList.Add( fwc );
Layout.CollectGarbage();
UpdateLayout();
return fwc;
}
private void UpdateStarSize( LayoutContent contentModel )
{
if( contentModel == null )
return;
var parentPane = contentModel.Parent as ILayoutPositionableElement;
if( parentPane != null)
{
// Reset Dock Size of floating LayoutContent
if( parentPane.DockWidth.IsStar )
{
parentPane.DockWidth = new GridLength( 1d, GridUnitType.Star );
}
if( parentPane.DockHeight.IsStar )
{
parentPane.DockHeight = new GridLength( 1d, GridUnitType.Star );
}
var grandParentPaneOrientation = parentPane.Parent as ILayoutOrientableGroup;
var grandParentPane = parentPane.Parent as ILayoutPositionableElement;
if( (grandParentPaneOrientation != null) && (grandParentPane != null) )
{
if( grandParentPaneOrientation.Orientation == Orientation.Horizontal )
{
// Reset Dock Width of remaining LayoutContent
if( grandParentPane.DockWidth.IsStar )
{
var grandParentPaneContainer = parentPane.Parent as ILayoutContainer;
if( grandParentPaneContainer != null )
{
var children = grandParentPaneContainer.Children.Where( child => !child.Equals( parentPane ) ).Cast<ILayoutPositionableElement>().Where( child => child.DockWidth.IsStar );
var childrenTotalWidth = children.Sum( child => child.DockWidth.Value );
foreach( var child in children )
{
child.DockWidth = new GridLength( child.DockWidth.Value / childrenTotalWidth, GridUnitType.Star );
}
}
}
}
else
{
// Reset Dock Height of remaining LayoutContent
if( grandParentPane.DockHeight.IsStar )
{
var grandParentPaneContainer = parentPane.Parent as ILayoutContainer;
if( grandParentPaneContainer != null )
{
var children = grandParentPaneContainer.Children.Where( child => !child.Equals( parentPane ) ).Cast<ILayoutPositionableElement>().Where( child => child.DockHeight.IsStar );
var childrenTotalHeight = children.Sum( child => child.DockHeight.Value );
foreach( var child in children )
{
child.DockHeight = new GridLength( child.DockHeight.Value / childrenTotalHeight, GridUnitType.Star );
}
}
}
}
}
}
}
private void AnchorableContextMenu_Opened( object sender, RoutedEventArgs e )
{
var anchorableContextMenu = sender as ContextMenu;
if( anchorableContextMenu != null )
{
if( anchorableContextMenu.PlacementTarget is Control )
{
anchorableContextMenu.VerticalOffset = ( (Control)anchorableContextMenu.PlacementTarget ).ActualHeight - anchorableContextMenu.ActualHeight;
}
this.AnchorableContextMenu.Opened -= this.AnchorableContextMenu_Opened;
}
}
#endregion
#region Events
/// <summary>
/// Event fired when <see cref="DockingManager.Layout"/> property changes
/// </summary>
public event EventHandler LayoutChanged;
/// <summary>
/// Event fired when <see cref="DockingManager.Layout"/> property is about to be changed
/// </summary>
public event EventHandler LayoutChanging;
/// <summary>
/// Event fired when a document is about to be closed
/// </summary>
/// <remarks>Subscribers have the opportuniy to cancel the operation.</remarks>
public event EventHandler<DocumentClosingEventArgs> DocumentClosing;
/// <summary>
/// Event fired after a document is closed
/// </summary>
public event EventHandler<DocumentClosedEventArgs> DocumentClosed;
public event EventHandler ActiveContentChanged;
#endregion
#region IOverlayWindowHost Interface
bool IOverlayWindowHost.HitTest( Point dragPoint )
{
Rect detectionRect = new Rect( this.PointToScreenDPIWithoutFlowDirection( new Point() ), this.TransformActualSizeToAncestor() );
return detectionRect.Contains( dragPoint );
}
DockingManager IOverlayWindowHost.Manager
{
get
{
return this;
}
}
IOverlayWindow IOverlayWindowHost.ShowOverlayWindow( LayoutFloatingWindowControl draggingWindow )
{
CreateOverlayWindow();
_overlayWindow.Owner = draggingWindow;
_overlayWindow.EnableDropTargets();
_overlayWindow.Show();
return _overlayWindow;
}
void IOverlayWindowHost.HideOverlayWindow()
{
_areas = null;
_overlayWindow.Owner = null;
_overlayWindow.HideDropTargets();
}
IEnumerable<IDropArea> IOverlayWindowHost.GetDropAreas( LayoutFloatingWindowControl draggingWindow )
{
if( _areas != null )
return _areas;
var draggingWindowManager = draggingWindow.Model.Root.Manager;
bool isDraggingDocuments = draggingWindow.Model is LayoutDocumentFloatingWindow;
_areas = new List<IDropArea>();
if( !isDraggingDocuments )
{
if( draggingWindowManager == this )
{
_areas.Add( new DropArea<DockingManager>(
this,
DropAreaType.DockingManager ) );
}
foreach( var areaHost in this.FindVisualChildren<LayoutAnchorablePaneControl>() )
{
if( areaHost.Model.Descendents().Any() )
{
if( draggingWindowManager == areaHost.Model.Root.Manager )
{
_areas.Add( new DropArea<LayoutAnchorablePaneControl>(
areaHost,
DropAreaType.AnchorablePane ) );
}
}
}
}
foreach( var areaHost in this.FindVisualChildren<LayoutDocumentPaneControl>() )
{
if( isDraggingDocuments
|| ( !isDraggingDocuments && draggingWindow.Model.Descendents().OfType<LayoutAnchorable>().All( x => x.CanDockAsTabbedDocument ) ) )
{
if( draggingWindowManager == areaHost.Model.Root.Manager )
{
_areas.Add( new DropArea<LayoutDocumentPaneControl>(
areaHost,
DropAreaType.DocumentPane ) );
}
}
}
foreach( var areaHost in this.FindVisualChildren<LayoutDocumentPaneGroupControl>() )
{
var documentGroupModel = areaHost.Model as LayoutDocumentPaneGroup;
if( documentGroupModel.Children.Where( c => c.IsVisible ).Count() == 0 )
{
if( draggingWindowManager == areaHost.Model.Root.Manager )
{
_areas.Add( new DropArea<LayoutDocumentPaneGroupControl>(
areaHost,
DropAreaType.DocumentPaneGroup ) );
}
}
}
return _areas;
}
#endregion
#region IWeakEventListener
bool IWeakEventListener.ReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
return this.OnReceiveWeakEvent( managerType, sender, e );
}
protected virtual bool OnReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
if( typeof( CollectionChangedEventManager ) == managerType )
{
var args = (NotifyCollectionChangedEventArgs)e;
if( sender == this.DocumentsSource )
{
this.documentsSourceElementsChanged( sender, args );
}
else if( sender == this.AnchorablesSource )
{
this.anchorablesSourceElementsChanged( sender, args );
}
}
else
{
return false;
}
return true;
}
#endregion
}
}