/************************************************************************************* 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 _fwList = new List(); private OverlayWindow _overlayWindow = null; private List _areas = null; private bool _insideInternalSetActiveContent = false; private List _layoutItems = new List(); 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 /// /// Layout Dependency Property /// public static readonly DependencyProperty LayoutProperty = DependencyProperty.Register( "Layout", typeof( LayoutRoot ), typeof( DockingManager ), new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnLayoutChanged ), new CoerceValueCallback( CoerceLayoutValue ) ) ); /// /// Gets or sets the Layout property. This dependency property /// indicates layout tree. /// public LayoutRoot Layout { get { return ( LayoutRoot )GetValue( LayoutProperty ); } set { SetValue( LayoutProperty, value ); } } /// /// Coerces the value. /// 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; } /// /// Handles changes to the Layout property. /// private static void OnLayoutChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnLayoutChanged( e.OldValue as LayoutRoot, e.NewValue as LayoutRoot ); } /// /// Provides derived classes an opportunity to handle changes to the property. /// 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 /// /// LayoutUpdateStrategy Dependency Property /// public static readonly DependencyProperty LayoutUpdateStrategyProperty = DependencyProperty.Register( "LayoutUpdateStrategy", typeof( ILayoutUpdateStrategy ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( ILayoutUpdateStrategy )null ) ); /// /// 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. /// /// 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. public ILayoutUpdateStrategy LayoutUpdateStrategy { get { return ( ILayoutUpdateStrategy )GetValue( LayoutUpdateStrategyProperty ); } set { SetValue( LayoutUpdateStrategyProperty, value ); } } #endregion #region DocumentPaneTemplate /// /// DocumentPaneTemplate Dependency Property /// public static readonly DependencyProperty DocumentPaneTemplateProperty = DependencyProperty.Register( "DocumentPaneTemplate", typeof( ControlTemplate ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( ControlTemplate )null, new PropertyChangedCallback( OnDocumentPaneTemplateChanged ) ) ); /// /// Gets or sets the DocumentPaneDataTemplate property. This dependency property /// indicates . /// public ControlTemplate DocumentPaneTemplate { get { return ( ControlTemplate )GetValue( DocumentPaneTemplateProperty ); } set { SetValue( DocumentPaneTemplateProperty, value ); } } /// /// Handles changes to the DocumentPaneTemplate property. /// private static void OnDocumentPaneTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnDocumentPaneTemplateChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the DocumentPaneTemplate property. /// protected virtual void OnDocumentPaneTemplateChanged( DependencyPropertyChangedEventArgs e ) { } #endregion #region AnchorablePaneTemplate /// /// AnchorablePaneTemplate Dependency Property /// public static readonly DependencyProperty AnchorablePaneTemplateProperty = DependencyProperty.Register( "AnchorablePaneTemplate", typeof( ControlTemplate ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( ControlTemplate )null, new PropertyChangedCallback( OnAnchorablePaneTemplateChanged ) ) ); /// /// Gets or sets the AnchorablePaneTemplate property. This dependency property /// indicates .... /// public ControlTemplate AnchorablePaneTemplate { get { return ( ControlTemplate )GetValue( AnchorablePaneTemplateProperty ); } set { SetValue( AnchorablePaneTemplateProperty, value ); } } /// /// Handles changes to the AnchorablePaneDataTemplate property. /// private static void OnAnchorablePaneTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnAnchorablePaneTemplateChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the AnchorablePaneDataTemplate property. /// protected virtual void OnAnchorablePaneTemplateChanged( DependencyPropertyChangedEventArgs e ) { } #endregion #region AnchorSideTemplate /// /// AnchorSideTemplate Dependency Property /// public static readonly DependencyProperty AnchorSideTemplateProperty = DependencyProperty.Register( "AnchorSideTemplate", typeof( ControlTemplate ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( ControlTemplate )null ) ); /// /// Gets or sets the AnchorSideTemplate property. This dependency property /// indicates .... /// public ControlTemplate AnchorSideTemplate { get { return ( ControlTemplate )GetValue( AnchorSideTemplateProperty ); } set { SetValue( AnchorSideTemplateProperty, value ); } } #endregion #region AnchorGroupTemplate /// /// AnchorGroupTemplate Dependency Property /// public static readonly DependencyProperty AnchorGroupTemplateProperty = DependencyProperty.Register( "AnchorGroupTemplate", typeof( ControlTemplate ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( ControlTemplate )null ) ); /// /// Gets or sets the AnchorGroupTemplate property. This dependency property /// indicates the template used to render the AnchorGroup control. /// public ControlTemplate AnchorGroupTemplate { get { return ( ControlTemplate )GetValue( AnchorGroupTemplateProperty ); } set { SetValue( AnchorGroupTemplateProperty, value ); } } #endregion #region AnchorTemplate /// /// AnchorTemplate Dependency Property /// public static readonly DependencyProperty AnchorTemplateProperty = DependencyProperty.Register( "AnchorTemplate", typeof( ControlTemplate ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( ControlTemplate )null ) ); /// /// Gets or sets the AnchorTemplate property. This dependency property /// indicates .... /// public ControlTemplate AnchorTemplate { get { return ( ControlTemplate )GetValue( AnchorTemplateProperty ); } set { SetValue( AnchorTemplateProperty, value ); } } #endregion #region DocumentPaneControlStyle /// /// DocumentPaneControlStyle Dependency Property /// public static readonly DependencyProperty DocumentPaneControlStyleProperty = DependencyProperty.Register( "DocumentPaneControlStyle", typeof( Style ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( Style )null, new PropertyChangedCallback( OnDocumentPaneControlStyleChanged ) ) ); /// /// Gets or sets the DocumentPaneControlStyle property. This dependency property /// indicates .... /// public Style DocumentPaneControlStyle { get { return ( Style )GetValue( DocumentPaneControlStyleProperty ); } set { SetValue( DocumentPaneControlStyleProperty, value ); } } /// /// Handles changes to the DocumentPaneControlStyle property. /// private static void OnDocumentPaneControlStyleChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnDocumentPaneControlStyleChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the DocumentPaneControlStyle property. /// protected virtual void OnDocumentPaneControlStyleChanged( DependencyPropertyChangedEventArgs e ) { } #endregion #region AnchorablePaneControlStyle /// /// AnchorablePaneControlStyle Dependency Property /// public static readonly DependencyProperty AnchorablePaneControlStyleProperty = DependencyProperty.Register( "AnchorablePaneControlStyle", typeof( Style ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( Style )null, new PropertyChangedCallback( OnAnchorablePaneControlStyleChanged ) ) ); /// /// Gets or sets the AnchorablePaneControlStyle property. This dependency property /// indicates the style to apply to AnchorablePaneControl. /// public Style AnchorablePaneControlStyle { get { return ( Style )GetValue( AnchorablePaneControlStyleProperty ); } set { SetValue( AnchorablePaneControlStyleProperty, value ); } } /// /// Handles changes to the AnchorablePaneControlStyle property. /// private static void OnAnchorablePaneControlStyleChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnAnchorablePaneControlStyleChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the AnchorablePaneControlStyle property. /// protected virtual void OnAnchorablePaneControlStyleChanged( DependencyPropertyChangedEventArgs e ) { } #endregion #region DocumentHeaderTemplate /// /// DocumentHeaderTemplate Dependency Property /// public static readonly DependencyProperty DocumentHeaderTemplateProperty = DependencyProperty.Register( "DocumentHeaderTemplate", typeof( DataTemplate ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnDocumentHeaderTemplateChanged ), new CoerceValueCallback( CoerceDocumentHeaderTemplateValue ) ) ); /// /// Gets or sets the DocumentHeaderTemplate property. This dependency property /// indicates data template to use for document header. /// public DataTemplate DocumentHeaderTemplate { get { return ( DataTemplate )GetValue( DocumentHeaderTemplateProperty ); } set { SetValue( DocumentHeaderTemplateProperty, value ); } } /// /// Handles changes to the DocumentHeaderTemplate property. /// private static void OnDocumentHeaderTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnDocumentHeaderTemplateChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplate property. /// protected virtual void OnDocumentHeaderTemplateChanged( DependencyPropertyChangedEventArgs e ) { } /// /// Coerces the DocumentHeaderTemplate value. /// private static object CoerceDocumentHeaderTemplateValue( DependencyObject d, object value ) { if( value != null && d.GetValue( DocumentHeaderTemplateSelectorProperty ) != null ) return null; return value; } #endregion #region DocumentHeaderTemplateSelector /// /// DocumentHeaderTemplateSelector Dependency Property /// public static readonly DependencyProperty DocumentHeaderTemplateSelectorProperty = DependencyProperty.Register( "DocumentHeaderTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnDocumentHeaderTemplateSelectorChanged ), new CoerceValueCallback( CoerceDocumentHeaderTemplateSelectorValue ) ) ); /// /// Gets or sets the DocumentHeaderTemplateSelector property. This dependency property /// indicates the template selector that is used when selcting the data template for the header. /// public DataTemplateSelector DocumentHeaderTemplateSelector { get { return ( DataTemplateSelector )GetValue( DocumentHeaderTemplateSelectorProperty ); } set { SetValue( DocumentHeaderTemplateSelectorProperty, value ); } } /// /// Handles changes to the DocumentHeaderTemplateSelector property. /// private static void OnDocumentHeaderTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnDocumentHeaderTemplateSelectorChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplateSelector property. /// protected virtual void OnDocumentHeaderTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) { if( e.NewValue != null && DocumentHeaderTemplate != null ) DocumentHeaderTemplate = null; if( DocumentPaneMenuItemHeaderTemplateSelector == null ) DocumentPaneMenuItemHeaderTemplateSelector = DocumentHeaderTemplateSelector; } /// /// Coerces the DocumentHeaderTemplateSelector value. /// private static object CoerceDocumentHeaderTemplateSelectorValue( DependencyObject d, object value ) { return value; } #endregion #region DocumentTitleTemplate /// /// DocumentTitleTemplate Dependency Property /// public static readonly DependencyProperty DocumentTitleTemplateProperty = DependencyProperty.Register( "DocumentTitleTemplate", typeof( DataTemplate ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnDocumentTitleTemplateChanged ), new CoerceValueCallback( CoerceDocumentTitleTemplateValue ) ) ); /// /// Gets or sets the DocumentTitleTemplate property. This dependency property /// indicates the datatemplate to use when creating the title for a document. /// public DataTemplate DocumentTitleTemplate { get { return ( DataTemplate )GetValue( DocumentTitleTemplateProperty ); } set { SetValue( DocumentTitleTemplateProperty, value ); } } /// /// Handles changes to the DocumentTitleTemplate property. /// private static void OnDocumentTitleTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnDocumentTitleTemplateChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the DocumentTitleTemplate property. /// protected virtual void OnDocumentTitleTemplateChanged( DependencyPropertyChangedEventArgs e ) { } /// /// Coerces the DocumentTitleTemplate value. /// private static object CoerceDocumentTitleTemplateValue( DependencyObject d, object value ) { if( value != null && d.GetValue( DocumentTitleTemplateSelectorProperty ) != null ) return null; return value; } #endregion #region DocumentTitleTemplateSelector /// /// DocumentTitleTemplateSelector Dependency Property /// public static readonly DependencyProperty DocumentTitleTemplateSelectorProperty = DependencyProperty.Register( "DocumentTitleTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnDocumentTitleTemplateSelectorChanged ), new CoerceValueCallback( CoerceDocumentTitleTemplateSelectorValue ) ) ); /// /// Gets or sets the DocumentTitleTemplateSelector property. This dependency property /// indicates the data template selector to use when creating the data template for the title. /// public DataTemplateSelector DocumentTitleTemplateSelector { get { return ( DataTemplateSelector )GetValue( DocumentTitleTemplateSelectorProperty ); } set { SetValue( DocumentTitleTemplateSelectorProperty, value ); } } /// /// Handles changes to the DocumentTitleTemplateSelector property. /// private static void OnDocumentTitleTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnDocumentTitleTemplateSelectorChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the DocumentTitleTemplateSelector property. /// protected virtual void OnDocumentTitleTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) { if( e.NewValue != null ) DocumentTitleTemplate = null; } /// /// Coerces the DocumentTitleTemplateSelector value. /// private static object CoerceDocumentTitleTemplateSelectorValue( DependencyObject d, object value ) { return value; } #endregion #region AnchorableTitleTemplate /// /// AnchorableTitleTemplate Dependency Property /// public static readonly DependencyProperty AnchorableTitleTemplateProperty = DependencyProperty.Register( "AnchorableTitleTemplate", typeof( DataTemplate ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnAnchorableTitleTemplateChanged ), new CoerceValueCallback( CoerceAnchorableTitleTemplateValue ) ) ); /// /// Gets or sets the AnchorableTitleTemplate property. This dependency property /// indicates the data template to use for anchorables title. /// public DataTemplate AnchorableTitleTemplate { get { return ( DataTemplate )GetValue( AnchorableTitleTemplateProperty ); } set { SetValue( AnchorableTitleTemplateProperty, value ); } } /// /// Handles changes to the AnchorableTitleTemplate property. /// private static void OnAnchorableTitleTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnAnchorableTitleTemplateChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplate property. /// protected virtual void OnAnchorableTitleTemplateChanged( DependencyPropertyChangedEventArgs e ) { } /// /// Coerces the AnchorableTitleTemplate value. /// private static object CoerceAnchorableTitleTemplateValue( DependencyObject d, object value ) { if( value != null && d.GetValue( AnchorableTitleTemplateSelectorProperty ) != null ) return null; return value; } #endregion #region AnchorableTitleTemplateSelector /// /// AnchorableTitleTemplateSelector Dependency Property /// public static readonly DependencyProperty AnchorableTitleTemplateSelectorProperty = DependencyProperty.Register( "AnchorableTitleTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnAnchorableTitleTemplateSelectorChanged ) ) ); /// /// Gets or sets the AnchorableTitleTemplateSelector property. This dependency property /// indicates selctor to use when selecting data template for the title of anchorables. /// public DataTemplateSelector AnchorableTitleTemplateSelector { get { return ( DataTemplateSelector )GetValue( AnchorableTitleTemplateSelectorProperty ); } set { SetValue( AnchorableTitleTemplateSelectorProperty, value ); } } /// /// Handles changes to the AnchorableTitleTemplateSelector property. /// private static void OnAnchorableTitleTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnAnchorableTitleTemplateSelectorChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplateSelector property. /// protected virtual void OnAnchorableTitleTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) { if( e.NewValue != null && AnchorableTitleTemplate != null ) AnchorableTitleTemplate = null; } #endregion #region AnchorableHeaderTemplate /// /// AnchorableHeaderTemplate Dependency Property /// public static readonly DependencyProperty AnchorableHeaderTemplateProperty = DependencyProperty.Register( "AnchorableHeaderTemplate", typeof( DataTemplate ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnAnchorableHeaderTemplateChanged ), new CoerceValueCallback( CoerceAnchorableHeaderTemplateValue ) ) ); /// /// Gets or sets the AnchorableHeaderTemplate property. This dependency property /// indicates the data template to use for anchorable templates. /// public DataTemplate AnchorableHeaderTemplate { get { return ( DataTemplate )GetValue( AnchorableHeaderTemplateProperty ); } set { SetValue( AnchorableHeaderTemplateProperty, value ); } } /// /// Handles changes to the AnchorableHeaderTemplate property. /// private static void OnAnchorableHeaderTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnAnchorableHeaderTemplateChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplate property. /// protected virtual void OnAnchorableHeaderTemplateChanged( DependencyPropertyChangedEventArgs e ) { } /// /// Coerces the AnchorableHeaderTemplate value. /// private static object CoerceAnchorableHeaderTemplateValue( DependencyObject d, object value ) { if( value != null && d.GetValue( AnchorableHeaderTemplateSelectorProperty ) != null ) return null; return value; } #endregion #region AnchorableHeaderTemplateSelector /// /// AnchorableHeaderTemplateSelector Dependency Property /// public static readonly DependencyProperty AnchorableHeaderTemplateSelectorProperty = DependencyProperty.Register( "AnchorableHeaderTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnAnchorableHeaderTemplateSelectorChanged ) ) ); /// /// Gets or sets the AnchorableHeaderTemplateSelector property. This dependency property /// indicates the selector to use when selecting the data template for anchorable headers. /// public DataTemplateSelector AnchorableHeaderTemplateSelector { get { return ( DataTemplateSelector )GetValue( AnchorableHeaderTemplateSelectorProperty ); } set { SetValue( AnchorableHeaderTemplateSelectorProperty, value ); } } /// /// Handles changes to the AnchorableHeaderTemplateSelector property. /// private static void OnAnchorableHeaderTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnAnchorableHeaderTemplateSelectorChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplateSelector property. /// protected virtual void OnAnchorableHeaderTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) { if( e.NewValue != null ) AnchorableHeaderTemplate = null; } #endregion #region LayoutRootPanel /// /// LayoutRootPanel Dependency Property /// public static readonly DependencyProperty LayoutRootPanelProperty = DependencyProperty.Register( "LayoutRootPanel", typeof( LayoutPanelControl ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( LayoutPanelControl )null, new PropertyChangedCallback( OnLayoutRootPanelChanged ) ) ); /// /// Gets or sets the LayoutRootPanel property. This dependency property /// indicates the layout panel control which is attached to the Layout.Root property. /// public LayoutPanelControl LayoutRootPanel { get { return ( LayoutPanelControl )GetValue( LayoutRootPanelProperty ); } set { SetValue( LayoutRootPanelProperty, value ); } } /// /// Handles changes to the LayoutRootPanel property. /// private static void OnLayoutRootPanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnLayoutRootPanelChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the LayoutRootPanel property. /// protected virtual void OnLayoutRootPanelChanged( DependencyPropertyChangedEventArgs e ) { if( e.OldValue != null ) InternalRemoveLogicalChild( e.OldValue ); if( e.NewValue != null ) InternalAddLogicalChild( e.NewValue ); } #endregion #region RightSidePanel /// /// RightSidePanel Dependency Property /// public static readonly DependencyProperty RightSidePanelProperty = DependencyProperty.Register( "RightSidePanel", typeof( LayoutAnchorSideControl ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( LayoutAnchorSideControl )null, new PropertyChangedCallback( OnRightSidePanelChanged ) ) ); /// /// Gets or sets the RightSidePanel property. This dependency property /// indicates right side anchor panel. /// public LayoutAnchorSideControl RightSidePanel { get { return ( LayoutAnchorSideControl )GetValue( RightSidePanelProperty ); } set { SetValue( RightSidePanelProperty, value ); } } /// /// Handles changes to the RightSidePanel property. /// private static void OnRightSidePanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnRightSidePanelChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the RightSidePanel property. /// protected virtual void OnRightSidePanelChanged( DependencyPropertyChangedEventArgs e ) { if( e.OldValue != null ) InternalRemoveLogicalChild( e.OldValue ); if( e.NewValue != null ) InternalAddLogicalChild( e.NewValue ); } #endregion #region LeftSidePanel /// /// LeftSidePanel Dependency Property /// public static readonly DependencyProperty LeftSidePanelProperty = DependencyProperty.Register( "LeftSidePanel", typeof( LayoutAnchorSideControl ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( LayoutAnchorSideControl )null, new PropertyChangedCallback( OnLeftSidePanelChanged ) ) ); /// /// Gets or sets the LeftSidePanel property. This dependency property /// indicates the left side panel control. /// public LayoutAnchorSideControl LeftSidePanel { get { return ( LayoutAnchorSideControl )GetValue( LeftSidePanelProperty ); } set { SetValue( LeftSidePanelProperty, value ); } } /// /// Handles changes to the LeftSidePanel property. /// private static void OnLeftSidePanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnLeftSidePanelChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the LeftSidePanel property. /// protected virtual void OnLeftSidePanelChanged( DependencyPropertyChangedEventArgs e ) { if( e.OldValue != null ) InternalRemoveLogicalChild( e.OldValue ); if( e.NewValue != null ) InternalAddLogicalChild( e.NewValue ); } #endregion #region TopSidePanel /// /// TopSidePanel Dependency Property /// public static readonly DependencyProperty TopSidePanelProperty = DependencyProperty.Register( "TopSidePanel", typeof( LayoutAnchorSideControl ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( LayoutAnchorSideControl )null, new PropertyChangedCallback( OnTopSidePanelChanged ) ) ); /// /// Gets or sets the TopSidePanel property. This dependency property /// indicates top side control panel. /// public LayoutAnchorSideControl TopSidePanel { get { return ( LayoutAnchorSideControl )GetValue( TopSidePanelProperty ); } set { SetValue( TopSidePanelProperty, value ); } } /// /// Handles changes to the TopSidePanel property. /// private static void OnTopSidePanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnTopSidePanelChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the TopSidePanel property. /// protected virtual void OnTopSidePanelChanged( DependencyPropertyChangedEventArgs e ) { if( e.OldValue != null ) InternalRemoveLogicalChild( e.OldValue ); if( e.NewValue != null ) InternalAddLogicalChild( e.NewValue ); } #endregion #region BottomSidePanel /// /// BottomSidePanel Dependency Property /// public static readonly DependencyProperty BottomSidePanelProperty = DependencyProperty.Register( "BottomSidePanel", typeof( LayoutAnchorSideControl ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( LayoutAnchorSideControl )null, new PropertyChangedCallback( OnBottomSidePanelChanged ) ) ); /// /// Gets or sets the BottomSidePanel property. This dependency property /// indicates bottom side panel control. /// public LayoutAnchorSideControl BottomSidePanel { get { return ( LayoutAnchorSideControl )GetValue( BottomSidePanelProperty ); } set { SetValue( BottomSidePanelProperty, value ); } } /// /// Handles changes to the BottomSidePanel property. /// private static void OnBottomSidePanelChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnBottomSidePanelChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the BottomSidePanel property. /// protected virtual void OnBottomSidePanelChanged( DependencyPropertyChangedEventArgs e ) { if( e.OldValue != null ) InternalRemoveLogicalChild( e.OldValue ); if( e.NewValue != null ) InternalAddLogicalChild( e.NewValue ); } #endregion #region LogicalChildren List _logicalChildren = new List(); protected override System.Collections.IEnumerator LogicalChildren { get { return _logicalChildren.Select( ch => ch.GetValueOrDefault() ).GetEnumerator(); } } public System.Collections.IEnumerator LogicalChildrenPublic { get { return this.LogicalChildren; } } internal void InternalAddLogicalChild( object element ) { #if DEBUG if( _logicalChildren.Select( ch => ch.GetValueOrDefault() ).Contains( element ) ) new InvalidOperationException(); #endif if( _logicalChildren.Select( ch => ch.GetValueOrDefault() ).Contains( element ) ) return; _logicalChildren.Add( new WeakReference( element ) ); AddLogicalChild( element ); } internal void InternalRemoveLogicalChild( object element ) { var wrToRemove = _logicalChildren.FirstOrDefault( ch => ch.GetValueOrDefault() == element ); if( wrToRemove != null ) _logicalChildren.Remove( wrToRemove ); RemoveLogicalChild( element ); } private void ClearLogicalChildrenList() { foreach( var child in _logicalChildren.Select( ch => ch.GetValueOrDefault() ).ToArray() ) RemoveLogicalChild( child ); _logicalChildren.Clear(); } #endregion #region AutoHideWindow /// /// AutoHideWindow Read-Only Dependency Property /// 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; /// /// Gets the AutoHideWindow property. This dependency property /// indicates the currently shown autohide window. /// public LayoutAutoHideWindowControl AutoHideWindow { get { return ( LayoutAutoHideWindowControl )GetValue( AutoHideWindowProperty ); } } /// /// Provides a secure method for setting the AutoHideWindow property. /// This dependency property indicates the currently shown autohide window. /// /// The new value for the property. protected void SetAutoHideWindow( LayoutAutoHideWindowControl value ) { SetValue( AutoHideWindowPropertyKey, value ); } /// /// Handles changes to the AutoHideWindow property. /// private static void OnAutoHideWindowChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnAutoHideWindowChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the AutoHideWindow property. /// 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 FloatingWindows { get { return _fwList; } } #endregion #region LayoutItemTemplate /// /// LayoutItemTemplate Dependency Property /// public static readonly DependencyProperty LayoutItemTemplateProperty = DependencyProperty.Register( "LayoutItemTemplate", typeof( DataTemplate ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnLayoutItemTemplateChanged ) ) ); /// /// Gets or sets the AnchorableTemplate property. This dependency property /// indicates the template to use to render anchorable and document contents. /// public DataTemplate LayoutItemTemplate { get { return ( DataTemplate )GetValue( LayoutItemTemplateProperty ); } set { SetValue( LayoutItemTemplateProperty, value ); } } /// /// Handles changes to the AnchorableTemplate property. /// private static void OnLayoutItemTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnLayoutItemTemplateChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the AnchorableTemplate property. /// protected virtual void OnLayoutItemTemplateChanged( DependencyPropertyChangedEventArgs e ) { } #endregion #region LayoutItemTemplateSelector /// /// LayoutItemTemplateSelector Dependency Property /// public static readonly DependencyProperty LayoutItemTemplateSelectorProperty = DependencyProperty.Register( "LayoutItemTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnLayoutItemTemplateSelectorChanged ) ) ); /// /// Gets or sets the LayoutItemTemplateSelector property. This dependency property /// indicates selector object to use for anchorable templates. /// public DataTemplateSelector LayoutItemTemplateSelector { get { return ( DataTemplateSelector )GetValue( LayoutItemTemplateSelectorProperty ); } set { SetValue( LayoutItemTemplateSelectorProperty, value ); } } /// /// Handles changes to the LayoutItemTemplateSelector property. /// private static void OnLayoutItemTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnLayoutItemTemplateSelectorChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the LayoutItemTemplateSelector property. /// protected virtual void OnLayoutItemTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) { } #endregion #region DocumentsSource /// /// DocumentsSource Dependency Property /// public static readonly DependencyProperty DocumentsSourceProperty = DependencyProperty.Register( "DocumentsSource", typeof( IEnumerable ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( IEnumerable )null, new PropertyChangedCallback( OnDocumentsSourceChanged ) ) ); /// /// Gets or sets the DocumentsSource property. This dependency property /// indicates the source collection of documents. /// public IEnumerable DocumentsSource { get { return ( IEnumerable )GetValue( DocumentsSourceProperty ); } set { SetValue( DocumentsSourceProperty, value ); } } /// /// Handles changes to the DocumentsSource property. /// private static void OnDocumentsSourceChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnDocumentsSourceChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the DocumentsSource property. /// protected virtual void OnDocumentsSourceChanged( DependencyPropertyChangedEventArgs e ) { DetachDocumentsSource( Layout, e.OldValue as IEnumerable ); AttachDocumentsSource( Layout, e.NewValue as IEnumerable ); } #endregion #region DocumentContextMenu /// /// DocumentContextMenu Dependency Property /// public static readonly DependencyProperty DocumentContextMenuProperty = DependencyProperty.Register( "DocumentContextMenu", typeof( ContextMenu ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( ContextMenu )null ) ); /// /// Gets or sets the DocumentContextMenu property. This dependency property /// indicates context menu to show for documents. /// public ContextMenu DocumentContextMenu { get { return ( ContextMenu )GetValue( DocumentContextMenuProperty ); } set { SetValue( DocumentContextMenuProperty, value ); } } #endregion #region AnchorablesSource /// /// AnchorablesSource Dependency Property /// public static readonly DependencyProperty AnchorablesSourceProperty = DependencyProperty.Register( "AnchorablesSource", typeof( IEnumerable ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( IEnumerable )null, new PropertyChangedCallback( OnAnchorablesSourceChanged ) ) ); /// /// Gets or sets the AnchorablesSource property. This dependency property /// indicates source collection of anchorables. /// public IEnumerable AnchorablesSource { get { return ( IEnumerable )GetValue( AnchorablesSourceProperty ); } set { SetValue( AnchorablesSourceProperty, value ); } } /// /// Handles changes to the AnchorablesSource property. /// private static void OnAnchorablesSourceChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnAnchorablesSourceChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the AnchorablesSource property. /// protected virtual void OnAnchorablesSourceChanged( DependencyPropertyChangedEventArgs e ) { DetachAnchorablesSource( Layout, e.OldValue as IEnumerable ); AttachAnchorablesSource( Layout, e.NewValue as IEnumerable ); } #endregion #region ActiveContent /// /// ActiveContent Dependency Property /// public static readonly DependencyProperty ActiveContentProperty = DependencyProperty.Register( "ActiveContent", typeof( object ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( object )null, new PropertyChangedCallback( OnActiveContentChanged ) ) ); /// /// Gets or sets the ActiveContent property. This dependency property /// indicates the content currently active. /// public object ActiveContent { get { return ( object )GetValue( ActiveContentProperty ); } set { SetValue( ActiveContentProperty, value ); } } /// /// Handles changes to the ActiveContent property. /// private static void OnActiveContentChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).InternalSetActiveContent( e.NewValue ); ( ( DockingManager )d ).OnActiveContentChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the ActiveContent property. /// protected virtual void OnActiveContentChanged( DependencyPropertyChangedEventArgs e ) { if( ActiveContentChanged != null ) ActiveContentChanged( this, EventArgs.Empty ); } #endregion #region AnchorableContextMenu /// /// AnchorableContextMenu Dependency Property /// public static readonly DependencyProperty AnchorableContextMenuProperty = DependencyProperty.Register( "AnchorableContextMenu", typeof( ContextMenu ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( ContextMenu )null ) ); /// /// Gets or sets the AnchorableContextMenu property. This dependency property /// indicates the context menu to show up for anchorables. /// public ContextMenu AnchorableContextMenu { get { return ( ContextMenu )GetValue( AnchorableContextMenuProperty ); } set { SetValue( AnchorableContextMenuProperty, value ); } } #endregion #region Theme /// /// Theme Dependency Property /// public static readonly DependencyProperty ThemeProperty = DependencyProperty.Register( "Theme", typeof( Theme ), typeof( DockingManager ), new FrameworkPropertyMetadata( null, new PropertyChangedCallback( OnThemeChanged ) ) ); /// /// Gets or sets the Theme property. This dependency property /// indicates the theme to use for AvalonDock controls. /// public Theme Theme { get { return ( Theme )GetValue( ThemeProperty ); } set { SetValue( ThemeProperty, value ); } } /// /// Handles changes to the Theme property. /// private static void OnThemeChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnThemeChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the Theme property. /// 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 /// /// GridSplitterWidth Dependency Property /// public static readonly DependencyProperty GridSplitterWidthProperty = DependencyProperty.Register( "GridSplitterWidth", typeof( double ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( double )6.0 ) ); /// /// Gets or sets the GridSplitterWidth property. This dependency property /// indicates width of grid splitters. /// public double GridSplitterWidth { get { return ( double )GetValue( GridSplitterWidthProperty ); } set { SetValue( GridSplitterWidthProperty, value ); } } #endregion #region GridSplitterHeight /// /// GridSplitterHeight Dependency Property /// public static readonly DependencyProperty GridSplitterHeightProperty = DependencyProperty.Register( "GridSplitterHeight", typeof( double ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( double )6.0 ) ); /// /// Gets or sets the GridSplitterHeight property. This dependency property /// indicates height of grid splitters. /// public double GridSplitterHeight { get { return ( double )GetValue( GridSplitterHeightProperty ); } set { SetValue( GridSplitterHeightProperty, value ); } } #endregion #region DocumentPaneMenuItemHeaderTemplate /// /// DocumentPaneMenuItemHeaderTemplate Dependency Property /// public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateProperty = DependencyProperty.Register( "DocumentPaneMenuItemHeaderTemplate", typeof( DataTemplate ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplate )null, new PropertyChangedCallback( OnDocumentPaneMenuItemHeaderTemplateChanged ), new CoerceValueCallback( CoerceDocumentPaneMenuItemHeaderTemplateValue ) ) ); /// /// Gets or sets the DocumentPaneMenuItemHeaderTemplate property. This dependency property /// indicates the header template to use while creating menu items for the document panes. /// public DataTemplate DocumentPaneMenuItemHeaderTemplate { get { return ( DataTemplate )GetValue( DocumentPaneMenuItemHeaderTemplateProperty ); } set { SetValue( DocumentPaneMenuItemHeaderTemplateProperty, value ); } } /// /// Handles changes to the DocumentPaneMenuItemHeaderTemplate property. /// private static void OnDocumentPaneMenuItemHeaderTemplateChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnDocumentPaneMenuItemHeaderTemplateChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplate property. /// protected virtual void OnDocumentPaneMenuItemHeaderTemplateChanged( DependencyPropertyChangedEventArgs e ) { } /// /// Coerces the DocumentPaneMenuItemHeaderTemplate value. /// 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 /// /// DocumentPaneMenuItemHeaderTemplateSelector Dependency Property /// public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateSelectorProperty = DependencyProperty.Register( "DocumentPaneMenuItemHeaderTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplateSelector )null, new PropertyChangedCallback( OnDocumentPaneMenuItemHeaderTemplateSelectorChanged ), new CoerceValueCallback( CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue ) ) ); /// /// 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. /// public DataTemplateSelector DocumentPaneMenuItemHeaderTemplateSelector { get { return ( DataTemplateSelector )GetValue( DocumentPaneMenuItemHeaderTemplateSelectorProperty ); } set { SetValue( DocumentPaneMenuItemHeaderTemplateSelectorProperty, value ); } } /// /// Handles changes to the DocumentPaneMenuItemHeaderTemplateSelector property. /// private static void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnDocumentPaneMenuItemHeaderTemplateSelectorChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplateSelector property. /// protected virtual void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged( DependencyPropertyChangedEventArgs e ) { if( e.NewValue != null && DocumentPaneMenuItemHeaderTemplate != null ) DocumentPaneMenuItemHeaderTemplate = null; } /// /// Coerces the DocumentPaneMenuItemHeaderTemplateSelector value. /// private static object CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue( DependencyObject d, object value ) { return value; } #endregion #region IconContentTemplate /// /// IconContentTemplate Dependency Property /// public static readonly DependencyProperty IconContentTemplateProperty = DependencyProperty.Register( "IconContentTemplate", typeof( DataTemplate ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplate )null ) ); /// /// Gets or sets the IconContentTemplate property. This dependency property /// indicates the data template to use while extracting the icon from model. /// public DataTemplate IconContentTemplate { get { return ( DataTemplate )GetValue( IconContentTemplateProperty ); } set { SetValue( IconContentTemplateProperty, value ); } } #endregion #region IconContentTemplateSelector /// /// IconContentTemplateSelector Dependency Property /// public static readonly DependencyProperty IconContentTemplateSelectorProperty = DependencyProperty.Register( "IconContentTemplateSelector", typeof( DataTemplateSelector ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( DataTemplateSelector )null ) ); /// /// Gets or sets the IconContentTemplateSelector property. This dependency property /// indicates data template selector to use while selecting the datatamplate for content icons. /// public DataTemplateSelector IconContentTemplateSelector { get { return ( DataTemplateSelector )GetValue( IconContentTemplateSelectorProperty ); } set { SetValue( IconContentTemplateSelectorProperty, value ); } } #endregion #region LayoutItemContainerStyle /// /// LayoutItemContainerStyle Dependency Property /// public static readonly DependencyProperty LayoutItemContainerStyleProperty = DependencyProperty.Register( "LayoutItemContainerStyle", typeof( Style ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( Style )null, new PropertyChangedCallback( OnLayoutItemContainerStyleChanged ) ) ); /// /// 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. /// public Style LayoutItemContainerStyle { get { return ( Style )GetValue( LayoutItemContainerStyleProperty ); } set { SetValue( LayoutItemContainerStyleProperty, value ); } } /// /// Handles changes to the LayoutItemContainerStyle property. /// private static void OnLayoutItemContainerStyleChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnLayoutItemContainerStyleChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyle property. /// protected virtual void OnLayoutItemContainerStyleChanged( DependencyPropertyChangedEventArgs e ) { AttachLayoutItems(); } #endregion #region LayoutItemContainerStyleSelector /// /// LayoutItemContainerStyleSelector Dependency Property /// public static readonly DependencyProperty LayoutItemContainerStyleSelectorProperty = DependencyProperty.Register( "LayoutItemContainerStyleSelector", typeof( StyleSelector ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( StyleSelector )null, new PropertyChangedCallback( OnLayoutItemContainerStyleSelectorChanged ) ) ); /// /// Gets or sets the LayoutItemContainerStyleSelector property. This dependency property /// indicates style selector of the LayoutDocumentItemStyle. /// public StyleSelector LayoutItemContainerStyleSelector { get { return ( StyleSelector )GetValue( LayoutItemContainerStyleSelectorProperty ); } set { SetValue( LayoutItemContainerStyleSelectorProperty, value ); } } /// /// Handles changes to the LayoutItemContainerStyleSelector property. /// private static void OnLayoutItemContainerStyleSelectorChanged( DependencyObject d, DependencyPropertyChangedEventArgs e ) { ( ( DockingManager )d ).OnLayoutItemContainerStyleSelectorChanged( e ); } /// /// Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyleSelector property. /// protected virtual void OnLayoutItemContainerStyleSelectorChanged( DependencyPropertyChangedEventArgs e ) { AttachLayoutItems(); } #endregion #region ShowSystemMenu /// /// ShowSystemMenu Dependency Property /// public static readonly DependencyProperty ShowSystemMenuProperty = DependencyProperty.Register( "ShowSystemMenu", typeof( bool ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( bool )true ) ); /// /// 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. /// public bool ShowSystemMenu { get { return ( bool )GetValue( ShowSystemMenuProperty ); } set { SetValue( ShowSystemMenuProperty, value ); } } #endregion #region AllowMixedOrientation /// /// AllowMixedOrientation Dependency Property /// public static readonly DependencyProperty AllowMixedOrientationProperty = DependencyProperty.Register( "AllowMixedOrientation", typeof( bool ), typeof( DockingManager ), new FrameworkPropertyMetadata( ( bool )false ) ); /// /// Gets or sets the AllowMixedOrientation property. This dependency property /// indicates if the manager should allow mixed orientation for document panes. /// 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 /// /// Return the LayoutItem wrapper for the content passed as argument /// /// LayoutContent to search /// Either a LayoutAnchorableItem or LayoutDocumentItem which contains the LayoutContent passed as argument 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().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 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().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().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().Any()) // throw new InvalidOperationException("Unable to set the DocumentsSource property if LayoutDocument objects are already present in the model"); var documentsImported = layout.Descendents().OfType().Select( d => d.Content ).ToArray(); var documents = documentsSource as IEnumerable; var listOfDocumentsToImport = new List( documents.OfType() ); 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().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().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().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().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() .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().Any()) // throw new InvalidOperationException("Unable to set the AnchorablesSource property if LayoutAnchorable objects are already present in the model"); var anchorablesImported = layout.Descendents().OfType().Select( d => d.Content ).ToArray(); var anchorables = anchorablesSource as IEnumerable; var listOfAnchorablesToImport = new List( anchorables.OfType() ); 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().Where( pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right ).FirstOrDefault(); } if( anchorablePane == null ) { //look for an available pane anchorablePane = layout.Descendents().OfType().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().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().Where( pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right ).FirstOrDefault(); } if( anchorablePane == null ) { //look for an available pane anchorablePane = Layout.Descendents().OfType().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().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() .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().FirstOrDefault( lc => lc == contentObject || lc.Content == contentObject ); _insideInternalSetActiveContent = true; Layout.ActiveContent = layoutContent; _insideInternalSetActiveContent = false; } private void DetachLayoutItems() { if( Layout != null ) { _layoutItems.ForEach( i => i.Detach() ); _layoutItems.Clear(); Layout.ElementAdded -= new EventHandler( Layout_ElementAdded ); Layout.ElementRemoved -= new EventHandler( 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() ) { 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().ToArray() ) { CreateDocumentLayoutItem( document ); //var documentItem = new LayoutDocumentItem(); //documentItem.Attach(document); //ApplyStyleToLayoutItem(documentItem); //_layoutItems.Add(documentItem); } foreach( var anchorable in Layout.Descendents().OfType().ToArray() ) { CreateAnchorableLayoutItem( anchorable ); //var anchorableItem = new LayoutAnchorableItem(); //anchorableItem.Attach(anchorable); //ApplyStyleToLayoutItem(anchorableItem); //_layoutItems.Add(anchorableItem); } Layout.ElementAdded += new EventHandler( Layout_ElementAdded ); Layout.ElementRemoved += new EventHandler( 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() == 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() == 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().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().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 /// /// Event fired when property changes /// public event EventHandler LayoutChanged; /// /// Event fired when property is about to be changed /// public event EventHandler LayoutChanging; /// /// Event fired when a document is about to be closed /// /// Subscribers have the opportuniy to cancel the operation. public event EventHandler DocumentClosing; /// /// Event fired after a document is closed /// public event EventHandler 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 IOverlayWindowHost.GetDropAreas( LayoutFloatingWindowControl draggingWindow ) { if( _areas != null ) return _areas; var draggingWindowManager = draggingWindow.Model.Root.Manager; bool isDraggingDocuments = draggingWindow.Model is LayoutDocumentFloatingWindow; _areas = new List(); if( !isDraggingDocuments ) { if( draggingWindowManager == this ) { _areas.Add( new DropArea( this, DropAreaType.DockingManager ) ); } foreach( var areaHost in this.FindVisualChildren() ) { if( areaHost.Model.Descendents().Any() ) { if( draggingWindowManager == areaHost.Model.Root.Manager ) { _areas.Add( new DropArea( areaHost, DropAreaType.AnchorablePane ) ); } } } } foreach( var areaHost in this.FindVisualChildren() ) { if( isDraggingDocuments || ( !isDraggingDocuments && draggingWindow.Model.Descendents().OfType().All( x => x.CanDockAsTabbedDocument ) ) ) { if( draggingWindowManager == areaHost.Model.Root.Manager ) { _areas.Add( new DropArea( areaHost, DropAreaType.DocumentPane ) ); } } } foreach( var areaHost in this.FindVisualChildren() ) { 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( 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 } }