//Copyright (c) 2007-2012, Adolfo Marinucci
//All rights reserved.
//Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
//following conditions are met:
//* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
//* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
//disclaimer in the documentation and/or other materials provided with the distribution.
//* Neither the name of Adolfo Marinucci nor the names of its contributors may be used to endorse or promote products
//derived from this software without specific prior written permission.
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
//INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
//STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
//EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Markup;
using System.ComponentModel;
using System.Windows.Interop;
using System.Diagnostics;
using AvalonDock.Layout;
using AvalonDock.Controls;
using System.Windows.Input;
using System.Collections;
using System.Collections.Specialized;
using System.Windows.Data;
using System.Windows.Threading;
using AvalonDock.Commands;
using AvalonDock.Themes;
namespace AvalonDock
{
[ContentProperty("Layout")]
[TemplatePart(Name="PART_AutoHideArea")]
public class DockingManager : Control, IOverlayWindowHost//, ILogicalChildrenContainer
{
static DockingManager()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DockingManager), new FrameworkPropertyMetadata(typeof(DockingManager)));
FocusableProperty.OverrideMetadata(typeof(DockingManager), new FrameworkPropertyMetadata(false));
HwndSource.DefaultAcquireHwndFocusInMenuMode = false;
}
public DockingManager()
{
Layout = new LayoutRoot() { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) };
this.Loaded += new RoutedEventHandler(DockingManager_Loaded);
this.Unloaded += new RoutedEventHandler(DockingManager_Unloaded);
}
#region Layout
/// <summary>
/// Layout Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutProperty =
DependencyProperty.Register("Layout", typeof(LayoutRoot), typeof(DockingManager),
new FrameworkPropertyMetadata(null,
new PropertyChangedCallback(OnLayoutChanged),
new CoerceValueCallback(CoerceLayoutValue)));
/// <summary>
/// Gets or sets the Layout property. This dependency property
/// indicates layout tree.
/// </summary>
public LayoutRoot Layout
{
get { return (LayoutRoot)GetValue(LayoutProperty); }
set { SetValue(LayoutProperty, value); }
}
/// <summary>
/// Handles changes to the Layout property.
/// </summary>
private static void OnLayoutChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnLayoutChanged(e.OldValue as LayoutRoot, e.NewValue as LayoutRoot);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the <see cref="DockingManager.Layout"/> property.
/// </summary>
protected virtual void OnLayoutChanged(LayoutRoot oldLayout, LayoutRoot newLayout)
{
if (oldLayout != null)
{
oldLayout.PropertyChanged -= new PropertyChangedEventHandler(OnLayoutRootPropertyChanged);
oldLayout.Updated -= new EventHandler(OnLayoutRootUpdated);
}
foreach (var fwc in _fwList.ToArray())
{
fwc.KeepContentVisibleOnClose = true;
fwc.InternalClose();
}
_fwList.Clear();
DetachDocumentsSource(oldLayout, DocumentsSource);
DetachAnchorablesSource(oldLayout, AnchorablesSource);
if (oldLayout != null &&
oldLayout.Manager == this)
oldLayout.Manager = null;
ClearLogicalChildrenList();
DetachLayoutItems();
Layout.Manager = this;
AttachLayoutItems();
AttachDocumentsSource(newLayout, DocumentsSource);
AttachAnchorablesSource(newLayout, AnchorablesSource);
if (IsLoaded)
{
LayoutRootPanel = CreateUIElementForModel(Layout.RootPanel) as LayoutPanelControl;
LeftSidePanel = CreateUIElementForModel(Layout.LeftSide) as LayoutAnchorSideControl;
TopSidePanel = CreateUIElementForModel(Layout.TopSide) as LayoutAnchorSideControl;
RightSidePanel = CreateUIElementForModel(Layout.RightSide) as LayoutAnchorSideControl;
BottomSidePanel = CreateUIElementForModel(Layout.BottomSide) as LayoutAnchorSideControl;
foreach (var fw in Layout.FloatingWindows.ToArray())
{
if (fw.IsValid)
_fwList.Add(CreateUIElementForModel(fw) as LayoutFloatingWindowControl);
}
foreach (var fw in _fwList)
{
//fw.Owner = Window.GetWindow(this);
//fw.SetParentToMainWindowOf(this);
}
}
if (newLayout != null)
{
newLayout.PropertyChanged += new PropertyChangedEventHandler(OnLayoutRootPropertyChanged);
newLayout.Updated += new EventHandler(OnLayoutRootUpdated);
}
if (LayoutChanged != null)
LayoutChanged(this, EventArgs.Empty);
//if (Layout != null)
// Layout.CollectGarbage();
CommandManager.InvalidateRequerySuggested();
}
DispatcherOperation _setFocusAsyncOperation = null;
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)
{
//Debug.WriteLine(new StackTrace().ToString());
//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.Background);
}
}
if (!_insideInternalSetActiveContent)
ActiveContent = Layout.ActiveContent != null ?
Layout.ActiveContent.Content : null;
}
}
void OnLayoutRootUpdated(object sender, EventArgs e)
{
CommandManager.InvalidateRequerySuggested();
}
/// <summary>
/// Event fired when <see cref="DockingManager.Layout"/> property changes
/// </summary>
public event EventHandler LayoutChanged;
/// <summary>
/// Coerces the <see cref="DockingManager.Layout"/> value.
/// </summary>
private static object CoerceLayoutValue(DependencyObject d, object value)
{
if (value == null)
return new LayoutRoot() { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) };
((DockingManager)d).OnLayoutChanging(value as LayoutRoot);
return value;
}
/// <summary>
/// Event fired when <see cref="DockingManager.Layout"/> property is about to be changed
/// </summary>
public event EventHandler LayoutChanging;
void OnLayoutChanging(LayoutRoot newLayout)
{
if (LayoutChanging != null)
LayoutChanging(this, EventArgs.Empty);
}
#region LayoutUpdateStrategy
/// <summary>
/// LayoutUpdateStrategy Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutUpdateStrategyProperty =
DependencyProperty.Register("LayoutUpdateStrategy", typeof(ILayoutUpdateStrategy), typeof(DockingManager),
new FrameworkPropertyMetadata((ILayoutUpdateStrategy)null));
/// <summary>
/// Gets or sets the LayoutUpdateStrategy property. This dependency property
/// indicates the strategy class to call when AvalonDock needs to positionate a LayoutAnchorable inside an existing layout.
/// </summary>
/// <remarks>Sometimes it's impossible to automatically insert an anchorable in the layout without specifing the target parent pane.
/// Set this property to an object that will be asked to insert the anchorable to the desidered position.</remarks>
public ILayoutUpdateStrategy LayoutUpdateStrategy
{
get { return (ILayoutUpdateStrategy)GetValue(LayoutUpdateStrategyProperty); }
set { SetValue(LayoutUpdateStrategyProperty, value); }
}
#endregion
#endregion
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
SetupAutoHideWindow();
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
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;
}
}
void DockingManager_Loaded(object sender, RoutedEventArgs e)
{
if (!DesignerProperties.GetIsInDesignMode(this))
{
//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);
}
}
void DockingManager_Unloaded(object sender, RoutedEventArgs e)
{
if (!DesignerProperties.GetIsInDesignMode(this))
{
_autoHideWindowManager.HideAutoWindow();
foreach (var fw in _fwList.ToArray())
{
//fw.Owner = null;
fw.SetParentWindowToNull();
fw.KeepContentVisibleOnClose = true;
fw.Close();
}
DestroyOverlayWindow();
FocusElementManager.FinalizeFocusManagement(this);
}
}
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("AnchorSideTemplate") { Source = this });
return templateModelView;
}
if (model is LayoutAnchorGroup)
{
var templateModelView = new LayoutAnchorGroupControl(model as LayoutAnchorGroup);
templateModelView.SetBinding(LayoutAnchorGroupControl.TemplateProperty, new Binding("AnchorGroupTemplate") { Source = this });
return templateModelView;
}
if (model is LayoutDocumentPane)
{
var templateModelView = new LayoutDocumentPaneControl(model as LayoutDocumentPane);
templateModelView.SetBinding(LayoutDocumentPaneControl.StyleProperty, new Binding("DocumentPaneControlStyle") { Source = this });
return templateModelView;
}
if (model is LayoutAnchorablePane)
{
var templateModelView = new LayoutAnchorablePaneControl(model as LayoutAnchorablePane);
templateModelView.SetBinding(LayoutAnchorablePaneControl.StyleProperty, new Binding("AnchorablePaneControlStyle") { 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 paneForExtentions = modelFW.RootPanel.Children.OfType<LayoutAnchorablePane>().FirstOrDefault();
if (paneForExtentions != null)
{
//ensure that floating window position is inside current (or nearest) monitor
paneForExtentions.KeepInsideNearestMonitor();
newFW.Left = paneForExtentions.FloatingLeft;
newFW.Top = paneForExtentions.FloatingTop;
newFW.Width = paneForExtentions.FloatingWidth;
newFW.Height = paneForExtentions.FloatingHeight;
}
newFW.ShowInTaskbar = false;
newFW.Show();
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 paneForExtentions = modelFW.RootDocument;
if (paneForExtentions != null)
{
//ensure that floating window position is inside current (or nearest) monitor
paneForExtentions.KeepInsideNearestMonitor();
newFW.Left = paneForExtentions.FloatingLeft;
newFW.Top = paneForExtentions.FloatingTop;
newFW.Width = paneForExtentions.FloatingWidth;
newFW.Height = paneForExtentions.FloatingHeight;
}
newFW.ShowInTaskbar = false;
newFW.Show();
return newFW;
}
if (model is LayoutDocument)
{
var templateModelView = new LayoutDocumentControl() { Model = model as LayoutDocument };
return templateModelView;
}
return null;
}
#region DocumentPaneTemplate
/// <summary>
/// DocumentPaneTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentPaneTemplateProperty =
DependencyProperty.Register("DocumentPaneTemplate", typeof(ControlTemplate), typeof(DockingManager),
new FrameworkPropertyMetadata((ControlTemplate)null,
new PropertyChangedCallback(OnDocumentPaneTemplateChanged)));
/// <summary>
/// Gets or sets the DocumentPaneDataTemplate property. This dependency property
/// indicates .
/// </summary>
public ControlTemplate DocumentPaneTemplate
{
get { return (ControlTemplate)GetValue(DocumentPaneTemplateProperty); }
set { SetValue(DocumentPaneTemplateProperty, value); }
}
/// <summary>
/// Handles changes to the DocumentPaneTemplate property.
/// </summary>
private static void OnDocumentPaneTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnDocumentPaneTemplateChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentPaneTemplate property.
/// </summary>
protected virtual void OnDocumentPaneTemplateChanged(DependencyPropertyChangedEventArgs e)
{
}
#endregion
#region AnchorablePaneTemplate
/// <summary>
/// AnchorablePaneTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorablePaneTemplateProperty =
DependencyProperty.Register("AnchorablePaneTemplate", typeof(ControlTemplate), typeof(DockingManager),
new FrameworkPropertyMetadata((ControlTemplate)null,
new PropertyChangedCallback(OnAnchorablePaneTemplateChanged)));
/// <summary>
/// Gets or sets the AnchorablePaneTemplate property. This dependency property
/// indicates ....
/// </summary>
public ControlTemplate AnchorablePaneTemplate
{
get { return (ControlTemplate)GetValue(AnchorablePaneTemplateProperty); }
set { SetValue(AnchorablePaneTemplateProperty, value); }
}
/// <summary>
/// Handles changes to the AnchorablePaneDataTemplate property.
/// </summary>
private static void OnAnchorablePaneTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnAnchorablePaneTemplateChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorablePaneDataTemplate property.
/// </summary>
protected virtual void OnAnchorablePaneTemplateChanged(DependencyPropertyChangedEventArgs e)
{
}
#endregion
#region AnchorSideTemplate
/// <summary>
/// AnchorSideTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorSideTemplateProperty =
DependencyProperty.Register("AnchorSideTemplate", typeof(ControlTemplate), typeof(DockingManager),
new FrameworkPropertyMetadata((ControlTemplate)null));
/// <summary>
/// Gets or sets the AnchorSideTemplate property. This dependency property
/// indicates ....
/// </summary>
public ControlTemplate AnchorSideTemplate
{
get { return (ControlTemplate)GetValue(AnchorSideTemplateProperty); }
set { SetValue(AnchorSideTemplateProperty, value); }
}
#endregion
#region AnchorGroupTemplate
/// <summary>
/// AnchorGroupTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorGroupTemplateProperty =
DependencyProperty.Register("AnchorGroupTemplate", typeof(ControlTemplate), typeof(DockingManager),
new FrameworkPropertyMetadata((ControlTemplate)null));
/// <summary>
/// Gets or sets the AnchorGroupTemplate property. This dependency property
/// indicates the template used to render the AnchorGroup control.
/// </summary>
public ControlTemplate AnchorGroupTemplate
{
get { return (ControlTemplate)GetValue(AnchorGroupTemplateProperty); }
set { SetValue(AnchorGroupTemplateProperty, value); }
}
#endregion
#region AnchorTemplate
/// <summary>
/// AnchorTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorTemplateProperty =
DependencyProperty.Register("AnchorTemplate", typeof(ControlTemplate), typeof(DockingManager),
new FrameworkPropertyMetadata((ControlTemplate)null));
/// <summary>
/// Gets or sets the AnchorTemplate property. This dependency property
/// indicates ....
/// </summary>
public ControlTemplate AnchorTemplate
{
get { return (ControlTemplate)GetValue(AnchorTemplateProperty); }
set { SetValue(AnchorTemplateProperty, value); }
}
#endregion
#region DocumentPaneControlStyle
/// <summary>
/// DocumentPaneControlStyle Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentPaneControlStyleProperty =
DependencyProperty.Register("DocumentPaneControlStyle", typeof(Style), typeof(DockingManager),
new FrameworkPropertyMetadata((Style)null,
new PropertyChangedCallback(OnDocumentPaneControlStyleChanged)));
/// <summary>
/// Gets or sets the DocumentPaneControlStyle property. This dependency property
/// indicates ....
/// </summary>
public Style DocumentPaneControlStyle
{
get { return (Style)GetValue(DocumentPaneControlStyleProperty); }
set { SetValue(DocumentPaneControlStyleProperty, value); }
}
/// <summary>
/// Handles changes to the DocumentPaneControlStyle property.
/// </summary>
private static void OnDocumentPaneControlStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnDocumentPaneControlStyleChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentPaneControlStyle property.
/// </summary>
protected virtual void OnDocumentPaneControlStyleChanged(DependencyPropertyChangedEventArgs e)
{
}
#endregion
#region AnchorablePaneControlStyle
/// <summary>
/// AnchorablePaneControlStyle Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorablePaneControlStyleProperty =
DependencyProperty.Register("AnchorablePaneControlStyle", typeof(Style), typeof(DockingManager),
new FrameworkPropertyMetadata((Style)null,
new PropertyChangedCallback(OnAnchorablePaneControlStyleChanged)));
/// <summary>
/// Gets or sets the AnchorablePaneControlStyle property. This dependency property
/// indicates the style to apply to AnchorablePaneControl.
/// </summary>
public Style AnchorablePaneControlStyle
{
get { return (Style)GetValue(AnchorablePaneControlStyleProperty); }
set { SetValue(AnchorablePaneControlStyleProperty, value); }
}
/// <summary>
/// Handles changes to the AnchorablePaneControlStyle property.
/// </summary>
private static void OnAnchorablePaneControlStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnAnchorablePaneControlStyleChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorablePaneControlStyle property.
/// </summary>
protected virtual void OnAnchorablePaneControlStyleChanged(DependencyPropertyChangedEventArgs e)
{
}
#endregion
#region DocumentHeaderTemplate
/// <summary>
/// DocumentHeaderTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentHeaderTemplateProperty =
DependencyProperty.Register("DocumentHeaderTemplate", typeof(DataTemplate), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplate)null,
new PropertyChangedCallback(OnDocumentHeaderTemplateChanged),
new CoerceValueCallback(CoerceDocumentHeaderTemplateValue)));
/// <summary>
/// Gets or sets the DocumentHeaderTemplate property. This dependency property
/// indicates data template to use for document header.
/// </summary>
public DataTemplate DocumentHeaderTemplate
{
get { return (DataTemplate)GetValue(DocumentHeaderTemplateProperty); }
set { SetValue(DocumentHeaderTemplateProperty, value); }
}
/// <summary>
/// Handles changes to the DocumentHeaderTemplate property.
/// </summary>
private static void OnDocumentHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnDocumentHeaderTemplateChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplate property.
/// </summary>
protected virtual void OnDocumentHeaderTemplateChanged(DependencyPropertyChangedEventArgs e)
{
}
/// <summary>
/// Coerces the DocumentHeaderTemplate value.
/// </summary>
private static object CoerceDocumentHeaderTemplateValue(DependencyObject d, object value)
{
if (value != null &&
d.GetValue(DocumentHeaderTemplateSelectorProperty) != null)
return null;
return value;
}
#endregion
#region DocumentHeaderTemplateSelector
/// <summary>
/// DocumentHeaderTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentHeaderTemplateSelectorProperty =
DependencyProperty.Register("DocumentHeaderTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplateSelector)null,
new PropertyChangedCallback(OnDocumentHeaderTemplateSelectorChanged),
new CoerceValueCallback(CoerceDocumentHeaderTemplateSelectorValue)));
/// <summary>
/// Gets or sets the DocumentHeaderTemplateSelector property. This dependency property
/// indicates the template selector that is used when selcting the data template for the header.
/// </summary>
public DataTemplateSelector DocumentHeaderTemplateSelector
{
get { return (DataTemplateSelector)GetValue(DocumentHeaderTemplateSelectorProperty); }
set { SetValue(DocumentHeaderTemplateSelectorProperty, value); }
}
/// <summary>
/// Handles changes to the DocumentHeaderTemplateSelector property.
/// </summary>
private static void OnDocumentHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnDocumentHeaderTemplateSelectorChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentHeaderTemplateSelector property.
/// </summary>
protected virtual void OnDocumentHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null &&
DocumentHeaderTemplate != null)
DocumentHeaderTemplate = null;
if (DocumentPaneMenuItemHeaderTemplateSelector == null)
DocumentPaneMenuItemHeaderTemplateSelector = DocumentHeaderTemplateSelector;
}
/// <summary>
/// Coerces the DocumentHeaderTemplateSelector value.
/// </summary>
private static object CoerceDocumentHeaderTemplateSelectorValue(DependencyObject d, object value)
{
return value;
}
#endregion
#region DocumentTitleTemplate
/// <summary>
/// DocumentTitleTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentTitleTemplateProperty =
DependencyProperty.Register("DocumentTitleTemplate", typeof(DataTemplate), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplate)null,
new PropertyChangedCallback(OnDocumentTitleTemplateChanged),
new CoerceValueCallback(CoerceDocumentTitleTemplateValue)));
/// <summary>
/// Gets or sets the DocumentTitleTemplate property. This dependency property
/// indicates the datatemplate to use when creating the title for a document.
/// </summary>
public DataTemplate DocumentTitleTemplate
{
get { return (DataTemplate)GetValue(DocumentTitleTemplateProperty); }
set { SetValue(DocumentTitleTemplateProperty, value); }
}
/// <summary>
/// Handles changes to the DocumentTitleTemplate property.
/// </summary>
private static void OnDocumentTitleTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnDocumentTitleTemplateChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentTitleTemplate property.
/// </summary>
protected virtual void OnDocumentTitleTemplateChanged(DependencyPropertyChangedEventArgs e)
{
}
/// <summary>
/// Coerces the DocumentTitleTemplate value.
/// </summary>
private static object CoerceDocumentTitleTemplateValue(DependencyObject d, object value)
{
if (value != null &&
d.GetValue(DocumentTitleTemplateSelectorProperty) != null)
return null;
return value;
}
#endregion
#region DocumentTitleTemplateSelector
/// <summary>
/// DocumentTitleTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentTitleTemplateSelectorProperty =
DependencyProperty.Register("DocumentTitleTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplateSelector)null,
new PropertyChangedCallback(OnDocumentTitleTemplateSelectorChanged),
new CoerceValueCallback(CoerceDocumentTitleTemplateSelectorValue)));
/// <summary>
/// Gets or sets the DocumentTitleTemplateSelector property. This dependency property
/// indicates the data template selector to use when creating the data template for the title.
/// </summary>
public DataTemplateSelector DocumentTitleTemplateSelector
{
get { return (DataTemplateSelector)GetValue(DocumentTitleTemplateSelectorProperty); }
set { SetValue(DocumentTitleTemplateSelectorProperty, value); }
}
/// <summary>
/// Handles changes to the DocumentTitleTemplateSelector property.
/// </summary>
private static void OnDocumentTitleTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnDocumentTitleTemplateSelectorChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentTitleTemplateSelector property.
/// </summary>
protected virtual void OnDocumentTitleTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null)
DocumentTitleTemplate = null;
}
/// <summary>
/// Coerces the DocumentTitleTemplateSelector value.
/// </summary>
private static object CoerceDocumentTitleTemplateSelectorValue(DependencyObject d, object value)
{
return value;
}
#endregion
#region AnchorableTitleTemplate
/// <summary>
/// AnchorableTitleTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorableTitleTemplateProperty =
DependencyProperty.Register("AnchorableTitleTemplate", typeof(DataTemplate), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplate)null,
new PropertyChangedCallback(OnAnchorableTitleTemplateChanged),
new CoerceValueCallback(CoerceAnchorableTitleTemplateValue)));
/// <summary>
/// Gets or sets the AnchorableTitleTemplate property. This dependency property
/// indicates the data template to use for anchorables title.
/// </summary>
public DataTemplate AnchorableTitleTemplate
{
get { return (DataTemplate)GetValue(AnchorableTitleTemplateProperty); }
set { SetValue(AnchorableTitleTemplateProperty, value); }
}
/// <summary>
/// Handles changes to the AnchorableTitleTemplate property.
/// </summary>
private static void OnAnchorableTitleTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnAnchorableTitleTemplateChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplate property.
/// </summary>
protected virtual void OnAnchorableTitleTemplateChanged(DependencyPropertyChangedEventArgs e)
{
}
/// <summary>
/// Coerces the AnchorableTitleTemplate value.
/// </summary>
private static object CoerceAnchorableTitleTemplateValue(DependencyObject d, object value)
{
if (value != null &&
d.GetValue(AnchorableTitleTemplateSelectorProperty) != null)
return null;
return value;
}
#endregion
#region AnchorableTitleTemplateSelector
/// <summary>
/// AnchorableTitleTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorableTitleTemplateSelectorProperty =
DependencyProperty.Register("AnchorableTitleTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplateSelector)null,
new PropertyChangedCallback(OnAnchorableTitleTemplateSelectorChanged)));
/// <summary>
/// Gets or sets the AnchorableTitleTemplateSelector property. This dependency property
/// indicates selctor to use when selecting data template for the title of anchorables.
/// </summary>
public DataTemplateSelector AnchorableTitleTemplateSelector
{
get { return (DataTemplateSelector)GetValue(AnchorableTitleTemplateSelectorProperty); }
set { SetValue(AnchorableTitleTemplateSelectorProperty, value); }
}
/// <summary>
/// Handles changes to the AnchorableTitleTemplateSelector property.
/// </summary>
private static void OnAnchorableTitleTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnAnchorableTitleTemplateSelectorChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorableTitleTemplateSelector property.
/// </summary>
protected virtual void OnAnchorableTitleTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null &&
AnchorableTitleTemplate != null)
AnchorableTitleTemplate = null;
}
#endregion
#region AnchorableHeaderTemplate
/// <summary>
/// AnchorableHeaderTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorableHeaderTemplateProperty =
DependencyProperty.Register("AnchorableHeaderTemplate", typeof(DataTemplate), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplate)null,
new PropertyChangedCallback(OnAnchorableHeaderTemplateChanged),
new CoerceValueCallback(CoerceAnchorableHeaderTemplateValue)));
/// <summary>
/// Gets or sets the AnchorableHeaderTemplate property. This dependency property
/// indicates the data template to use for anchorable templates.
/// </summary>
public DataTemplate AnchorableHeaderTemplate
{
get { return (DataTemplate)GetValue(AnchorableHeaderTemplateProperty); }
set { SetValue(AnchorableHeaderTemplateProperty, value); }
}
/// <summary>
/// Handles changes to the AnchorableHeaderTemplate property.
/// </summary>
private static void OnAnchorableHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnAnchorableHeaderTemplateChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplate property.
/// </summary>
protected virtual void OnAnchorableHeaderTemplateChanged(DependencyPropertyChangedEventArgs e)
{
}
/// <summary>
/// Coerces the AnchorableHeaderTemplate value.
/// </summary>
private static object CoerceAnchorableHeaderTemplateValue(DependencyObject d, object value)
{
if (value != null &&
d.GetValue(AnchorableHeaderTemplateSelectorProperty) != null)
return null;
return value;
}
#endregion
#region AnchorableHeaderTemplateSelector
/// <summary>
/// AnchorableHeaderTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorableHeaderTemplateSelectorProperty =
DependencyProperty.Register("AnchorableHeaderTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplateSelector)null,
new PropertyChangedCallback(OnAnchorableHeaderTemplateSelectorChanged)));
/// <summary>
/// Gets or sets the AnchorableHeaderTemplateSelector property. This dependency property
/// indicates the selector to use when selecting the data template for anchorable headers.
/// </summary>
public DataTemplateSelector AnchorableHeaderTemplateSelector
{
get { return (DataTemplateSelector)GetValue(AnchorableHeaderTemplateSelectorProperty); }
set { SetValue(AnchorableHeaderTemplateSelectorProperty, value); }
}
/// <summary>
/// Handles changes to the AnchorableHeaderTemplateSelector property.
/// </summary>
private static void OnAnchorableHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnAnchorableHeaderTemplateSelectorChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorableHeaderTemplateSelector property.
/// </summary>
protected virtual void OnAnchorableHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null)
AnchorableHeaderTemplate = null;
}
#endregion
protected override void OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
//if (e.NewFocus is Grid)
// Debug.WriteLine(string.Format("DockingManager.OnGotKeyboardFocus({0})", e.NewFocus));
base.OnGotKeyboardFocus(e);
}
protected override void OnPreviewGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e)
{
Debug.WriteLine(string.Format("DockingManager.OnPreviewGotKeyboardFocus({0})", e.NewFocus));
base.OnPreviewGotKeyboardFocus(e);
}
protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
Debug.WriteLine(string.Format("DockingManager.OnPreviewLostKeyboardFocus({0})", e.OldFocus));
base.OnPreviewLostKeyboardFocus(e);
}
protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
Debug.WriteLine(string.Format("DockingManager.OnMouseLeftButtonDown([{0}])", e.GetPosition(this)));
base.OnMouseLeftButtonDown(e);
}
protected override void OnMouseMove(System.Windows.Input.MouseEventArgs e)
{
//Debug.WriteLine(string.Format("DockingManager.OnMouseMove([{0}])", e.GetPosition(this)));
base.OnMouseMove(e);
}
#region LayoutRootPanel
/// <summary>
/// LayoutRootPanel Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutRootPanelProperty =
DependencyProperty.Register("LayoutRootPanel", typeof(LayoutPanelControl), typeof(DockingManager),
new FrameworkPropertyMetadata((LayoutPanelControl)null,
new PropertyChangedCallback(OnLayoutRootPanelChanged)));
/// <summary>
/// Gets or sets the LayoutRootPanel property. This dependency property
/// indicates the layout panel control which is attached to the Layout.Root property.
/// </summary>
public LayoutPanelControl LayoutRootPanel
{
get { return (LayoutPanelControl)GetValue(LayoutRootPanelProperty); }
set { SetValue(LayoutRootPanelProperty, value); }
}
/// <summary>
/// Handles changes to the LayoutRootPanel property.
/// </summary>
private static void OnLayoutRootPanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnLayoutRootPanelChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the LayoutRootPanel property.
/// </summary>
protected virtual void OnLayoutRootPanelChanged(DependencyPropertyChangedEventArgs e)
{
if (e.OldValue != null)
InternalRemoveLogicalChild(e.OldValue);
if (e.NewValue != null)
InternalAddLogicalChild(e.NewValue);
}
#endregion
#region RightSidePanel
/// <summary>
/// RightSidePanel Dependency Property
/// </summary>
public static readonly DependencyProperty RightSidePanelProperty =
DependencyProperty.Register("RightSidePanel", typeof(LayoutAnchorSideControl), typeof(DockingManager),
new FrameworkPropertyMetadata((LayoutAnchorSideControl)null,
new PropertyChangedCallback(OnRightSidePanelChanged)));
/// <summary>
/// Gets or sets the RightSidePanel property. This dependency property
/// indicates right side anchor panel.
/// </summary>
public LayoutAnchorSideControl RightSidePanel
{
get { return (LayoutAnchorSideControl)GetValue(RightSidePanelProperty); }
set { SetValue(RightSidePanelProperty, value); }
}
/// <summary>
/// Handles changes to the RightSidePanel property.
/// </summary>
private static void OnRightSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnRightSidePanelChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the RightSidePanel property.
/// </summary>
protected virtual void OnRightSidePanelChanged(DependencyPropertyChangedEventArgs e)
{
if (e.OldValue != null)
InternalRemoveLogicalChild(e.OldValue);
if (e.NewValue != null)
InternalAddLogicalChild(e.NewValue);
}
#endregion
#region LeftSidePanel
/// <summary>
/// LeftSidePanel Dependency Property
/// </summary>
public static readonly DependencyProperty LeftSidePanelProperty =
DependencyProperty.Register("LeftSidePanel", typeof(LayoutAnchorSideControl), typeof(DockingManager),
new FrameworkPropertyMetadata((LayoutAnchorSideControl)null,
new PropertyChangedCallback(OnLeftSidePanelChanged)));
/// <summary>
/// Gets or sets the LeftSidePanel property. This dependency property
/// indicates the left side panel control.
/// </summary>
public LayoutAnchorSideControl LeftSidePanel
{
get { return (LayoutAnchorSideControl)GetValue(LeftSidePanelProperty); }
set { SetValue(LeftSidePanelProperty, value); }
}
/// <summary>
/// Handles changes to the LeftSidePanel property.
/// </summary>
private static void OnLeftSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnLeftSidePanelChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the LeftSidePanel property.
/// </summary>
protected virtual void OnLeftSidePanelChanged(DependencyPropertyChangedEventArgs e)
{
if (e.OldValue != null)
InternalRemoveLogicalChild(e.OldValue);
if (e.NewValue != null)
InternalAddLogicalChild(e.NewValue);
}
#endregion
#region TopSidePanel
/// <summary>
/// TopSidePanel Dependency Property
/// </summary>
public static readonly DependencyProperty TopSidePanelProperty =
DependencyProperty.Register("TopSidePanel", typeof(LayoutAnchorSideControl), typeof(DockingManager),
new FrameworkPropertyMetadata((LayoutAnchorSideControl)null,
new PropertyChangedCallback(OnTopSidePanelChanged)));
/// <summary>
/// Gets or sets the TopSidePanel property. This dependency property
/// indicates top side control panel.
/// </summary>
public LayoutAnchorSideControl TopSidePanel
{
get { return (LayoutAnchorSideControl)GetValue(TopSidePanelProperty); }
set { SetValue(TopSidePanelProperty, value); }
}
/// <summary>
/// Handles changes to the TopSidePanel property.
/// </summary>
private static void OnTopSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnTopSidePanelChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the TopSidePanel property.
/// </summary>
protected virtual void OnTopSidePanelChanged(DependencyPropertyChangedEventArgs e)
{
if (e.OldValue != null)
InternalRemoveLogicalChild(e.OldValue);
if (e.NewValue != null)
InternalAddLogicalChild(e.NewValue);
}
#endregion
#region BottomSidePanel
/// <summary>
/// BottomSidePanel Dependency Property
/// </summary>
public static readonly DependencyProperty BottomSidePanelProperty =
DependencyProperty.Register("BottomSidePanel", typeof(LayoutAnchorSideControl), typeof(DockingManager),
new FrameworkPropertyMetadata((LayoutAnchorSideControl)null,
new PropertyChangedCallback(OnBottomSidePanelChanged)));
/// <summary>
/// Gets or sets the BottomSidePanel property. This dependency property
/// indicates bottom side panel control.
/// </summary>
public LayoutAnchorSideControl BottomSidePanel
{
get { return (LayoutAnchorSideControl)GetValue(BottomSidePanelProperty); }
set { SetValue(BottomSidePanelProperty, value); }
}
/// <summary>
/// Handles changes to the BottomSidePanel property.
/// </summary>
private static void OnBottomSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnBottomSidePanelChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the BottomSidePanel property.
/// </summary>
protected virtual void OnBottomSidePanelChanged(DependencyPropertyChangedEventArgs e)
{
if (e.OldValue != null)
InternalRemoveLogicalChild(e.OldValue);
if (e.NewValue != null)
InternalAddLogicalChild(e.NewValue);
}
#endregion
#region LogicalChildren
List<WeakReference> _logicalChildren = new List<WeakReference>();
protected override System.Collections.IEnumerator LogicalChildren
{
get
{
return _logicalChildren.Select(ch => ch.GetValueOrDefault<object>()).GetEnumerator();
}
}
internal void InternalAddLogicalChild(object element)
{
//System.Diagnostics.Debug.WriteLine("[{0}]InternalAddLogicalChild({1})", this, element);
#if DEBUG
if (_logicalChildren.Select(ch => ch.GetValueOrDefault<object>()).Contains(element))
new InvalidOperationException();
#endif
if (_logicalChildren.Select(ch => ch.GetValueOrDefault<object>()).Contains(element))
return;
_logicalChildren.Add(new WeakReference(element));
AddLogicalChild(element);
}
internal void InternalRemoveLogicalChild(object element)
{
//System.Diagnostics.Debug.WriteLine("[{0}]InternalRemoveLogicalChild({1})", this, element);
var wrToRemove = _logicalChildren.FirstOrDefault(ch => ch.GetValueOrDefault<object>() == element);
if (wrToRemove != null)
_logicalChildren.Remove(wrToRemove);
RemoveLogicalChild(element);
}
void ClearLogicalChildrenList()
{
foreach (var child in _logicalChildren.Select(ch => ch.GetValueOrDefault<object>()).ToArray())
RemoveLogicalChild(child);
_logicalChildren.Clear();
}
#endregion
#region AutoHide window
internal void ShowAutoHideWindow(LayoutAnchorControl anchor)
{
_autoHideWindowManager.ShowAutoHideWindow(anchor);
//if (_autohideArea == null)
// return;
//if (AutoHideWindow != null && AutoHideWindow.Model == anchor.Model)
// return;
//Debug.WriteLine("ShowAutoHideWindow()");
//_currentAutohiddenAnchor = new WeakReference(anchor);
//HideAutoHideWindow(anchor);
//SetAutoHideWindow(new LayoutAutoHideWindowControl(anchor));
//AutoHideWindow.Show();
}
internal void HideAutoHideWindow(LayoutAnchorControl anchor)
{
_autoHideWindowManager.HideAutoWindow(anchor);
}
void SetupAutoHideWindow()
{
_autohideArea = GetTemplateChild("PART_AutoHideArea") as FrameworkElement;
if (_autoHideWindowManager != null)
_autoHideWindowManager.HideAutoWindow();
else
_autoHideWindowManager = new AutoHideWindowManager(this);
if (AutoHideWindow != null)
AutoHideWindow.Dispose();
SetAutoHideWindow(new LayoutAutoHideWindowControl());
}
AutoHideWindowManager _autoHideWindowManager;
FrameworkElement _autohideArea;
internal FrameworkElement GetAutoHideAreaElement()
{
return _autohideArea;
}
#region AutoHideWindow
/// <summary>
/// AutoHideWindow Read-Only Dependency Property
/// </summary>
private static readonly DependencyPropertyKey AutoHideWindowPropertyKey
= DependencyProperty.RegisterReadOnly("AutoHideWindow", typeof(LayoutAutoHideWindowControl), typeof(DockingManager),
new FrameworkPropertyMetadata((LayoutAutoHideWindowControl)null,
new PropertyChangedCallback(OnAutoHideWindowChanged)));
public static readonly DependencyProperty AutoHideWindowProperty
= AutoHideWindowPropertyKey.DependencyProperty;
/// <summary>
/// Gets the AutoHideWindow property. This dependency property
/// indicates the currently shown autohide window.
/// </summary>
public LayoutAutoHideWindowControl AutoHideWindow
{
get { return (LayoutAutoHideWindowControl)GetValue(AutoHideWindowProperty); }
}
/// <summary>
/// Provides a secure method for setting the AutoHideWindow property.
/// This dependency property indicates the currently shown autohide window.
/// </summary>
/// <param name="value">The new value for the property.</param>
protected void SetAutoHideWindow(LayoutAutoHideWindowControl value)
{
SetValue(AutoHideWindowPropertyKey, value);
}
/// <summary>
/// Handles changes to the AutoHideWindow property.
/// </summary>
private static void OnAutoHideWindowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnAutoHideWindowChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AutoHideWindow property.
/// </summary>
protected virtual void OnAutoHideWindowChanged(DependencyPropertyChangedEventArgs e)
{
if (e.OldValue != null)
InternalRemoveLogicalChild(e.OldValue);
if (e.NewValue != null)
InternalAddLogicalChild(e.NewValue);
}
#endregion
#endregion
//#region AutoHide window
//WeakReference _currentAutohiddenAnchor = null;
//internal void ShowAutoHideWindow(LayoutAnchorControl anchor)
//{
// if (_autohideArea == null)
// return;
// if (AutoHideWindow != null && AutoHideWindow.Model == anchor.Model)
// return;
// Debug.WriteLine("ShowAutoHideWindow()");
// _currentAutohiddenAnchor = new WeakReference(anchor);
// HideAutoHideWindow(anchor);
// SetAutoHideWindow(new LayoutAutoHideWindowControl(anchor));
//}
//internal void HideAutoHideWindow(LayoutAnchorControl anchor)
//{
// if (AutoHideWindow != null)
// {
// if (anchor == _currentAutohiddenAnchor.GetValueOrDefault<LayoutAnchorControl>())
// {
// Debug.WriteLine("AutoHideWindow()");
// AutoHideWindow.Dispose();
// SetAutoHideWindow(null);
// }
// }
//}
//FrameworkElement _autohideArea;
//internal FrameworkElement GetAutoHideAreaElement()
//{
// return _autohideArea;
//}
//void SetupAutoHideArea()
//{
// _autohideArea = GetTemplateChild("PART_AutoHideArea") as FrameworkElement;
//}
//#region AutoHideWindow
///// <summary>
///// AutoHideWindow Read-Only Dependency Property
///// </summary>
//private static readonly DependencyPropertyKey AutoHideWindowPropertyKey
// = DependencyProperty.RegisterReadOnly("AutoHideWindow", typeof(LayoutAutoHideWindowControl), typeof(DockingManager),
// new FrameworkPropertyMetadata((LayoutAutoHideWindowControl)null,
// new PropertyChangedCallback(OnAutoHideWindowChanged)));
//public static readonly DependencyProperty AutoHideWindowProperty
// = AutoHideWindowPropertyKey.DependencyProperty;
///// <summary>
///// Gets the AutoHideWindow property. This dependency property
///// indicates the currently shown autohide window.
///// </summary>
//public LayoutAutoHideWindowControl AutoHideWindow
//{
// get { return (LayoutAutoHideWindowControl)GetValue(AutoHideWindowProperty); }
//}
///// <summary>
///// Provides a secure method for setting the AutoHideWindow property.
///// This dependency property indicates the currently shown autohide window.
///// </summary>
///// <param name="value">The new value for the property.</param>
//protected void SetAutoHideWindow(LayoutAutoHideWindowControl value)
//{
// SetValue(AutoHideWindowPropertyKey, value);
//}
///// <summary>
///// Handles changes to the AutoHideWindow property.
///// </summary>
//private static void OnAutoHideWindowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
//{
// ((DockingManager)d).OnAutoHideWindowChanged(e);
//}
///// <summary>
///// Provides derived classes an opportunity to handle changes to the AutoHideWindow property.
///// </summary>
//protected virtual void OnAutoHideWindowChanged(DependencyPropertyChangedEventArgs e)
//{
// if (e.OldValue != null)
// ((ILogicalChildrenContainer)this).InternalRemoveLogicalChild(e.OldValue);
// if (e.NewValue != null)
// ((ILogicalChildrenContainer)this).InternalAddLogicalChild(e.NewValue);
//}
//#endregion
//#endregion
#region Floating Windows
List<LayoutFloatingWindowControl> _fwList = new List<LayoutFloatingWindowControl>();
internal void StartDraggingFloatingWindowForContent(LayoutContent contentModel, bool startDrag = true)
{
if (!contentModel.CanFloat)
return;
var contentModelAsAnchorable = contentModel as LayoutAnchorable;
if (contentModelAsAnchorable != null &&
contentModelAsAnchorable.IsAutoHidden)
contentModelAsAnchorable.ToggleAutoHide();
var parentPane = contentModel.Parent as ILayoutPane;
var parentPaneAsPositionableElement = contentModel.Parent as ILayoutPositionableElement;
var parentPaneAsWithActualSize = contentModel.Parent as ILayoutPositionableElementWithActualSize;
var contentModelParentChildrenIndex = parentPane.Children.ToList().IndexOf(contentModel);
if (contentModel.FindParent<LayoutFloatingWindow>() == null)
{
((ILayoutPreviousContainer)contentModel).PreviousContainer = parentPane;
contentModel.PreviousContainerIndex = contentModelParentChildrenIndex;
}
parentPane.RemoveChildAt(contentModelParentChildrenIndex);
double fwWidth = contentModel.FloatingWidth;
double fwHeight = contentModel.FloatingHeight;
if (fwWidth == 0.0)
fwWidth = parentPaneAsPositionableElement.FloatingWidth;
if (fwHeight == 0.0)
fwHeight = parentPaneAsPositionableElement.FloatingHeight;
if (fwWidth == 0.0)
fwWidth = parentPaneAsWithActualSize.ActualWidth;
if (fwHeight == 0.0)
fwHeight = parentPaneAsWithActualSize.ActualHeight;
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)
{
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)
{
Width = fwWidth,
Height = fwHeight,
Left = contentModel.FloatingLeft,
Top = contentModel.FloatingTop
};
}
//fwc.Owner = Window.GetWindow(this);
//fwc.SetParentToMainWindowOf(this);
_fwList.Add(fwc);
Layout.CollectGarbage();
UpdateLayout();
Dispatcher.BeginInvoke(new Action(() =>
{
if (startDrag)
fwc.AttachDrag();
fwc.Show();
}), DispatcherPriority.Send);
}
internal void StartDraggingFloatingWindowForPane(LayoutAnchorablePane paneModel)
{
if (paneModel.Children.Any(c => !c.CanFloat))
return;
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;
if (fwHeight == 0.0)
fwHeight = paneAsWithActualSize.ActualHeight;
var destPane = new LayoutAnchorablePane()
{
DockWidth = paneAsPositionableElement.DockWidth,
DockHeight = paneAsPositionableElement.DockHeight,
DockMinHeight = paneAsPositionableElement.DockMinHeight,
DockMinWidth = paneAsPositionableElement.DockMinWidth,
FloatingLeft = paneAsPositionableElement.FloatingLeft,
FloatingTop = paneAsPositionableElement.FloatingTop,
FloatingWidth = paneAsPositionableElement.FloatingWidth,
FloatingHeight = paneAsPositionableElement.FloatingHeight,
};
bool savePreviousContainer = paneModel.FindParent<LayoutFloatingWindow>() == null;
int currentSelectedContentIndex = paneModel.SelectedContentIndex;
while (paneModel.Children.Count > 0)
{
var contentModel = paneModel.Children[paneModel.Children.Count - 1] as LayoutAnchorable;
if (savePreviousContainer)
{
var contentModelAsPreviousContainer = contentModel as ILayoutPreviousContainer;
contentModelAsPreviousContainer.PreviousContainer = paneModel;
contentModel.PreviousContainerIndex = paneModel.Children.Count - 1;
}
paneModel.RemoveChildAt(paneModel.Children.Count - 1);
destPane.Children.Insert(0, contentModel);
}
if (destPane.Children.Count > 0)
{
destPane.SelectedContentIndex = currentSelectedContentIndex;
}
LayoutFloatingWindow fw;
LayoutFloatingWindowControl fwc;
fw = new LayoutAnchorableFloatingWindow()
{
RootPanel = new LayoutAnchorablePaneGroup(
destPane)
{
DockHeight = destPane.DockHeight,
DockWidth = destPane.DockWidth,
DockMinHeight = destPane.DockMinHeight,
DockMinWidth = destPane.DockMinWidth,
}
};
Layout.FloatingWindows.Add(fw);
fwc = new LayoutAnchorableFloatingWindowControl(
fw as LayoutAnchorableFloatingWindow)
{
Width = fwWidth,
Height = fwHeight
};
//fwc.Owner = Window.GetWindow(this);
//fwc.SetParentToMainWindowOf(this);
_fwList.Add(fwc);
Layout.CollectGarbage();
InvalidateArrange();
fwc.AttachDrag();
fwc.Show();
}
internal IEnumerable<LayoutFloatingWindowControl> GetFloatingWindowsByZOrder()
{
var parentWindow = Window.GetWindow(this);
if (parentWindow == null)
yield break;
IntPtr windowParentHanlde = new WindowInteropHelper(parentWindow).Handle;
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);
}
public IEnumerable<LayoutFloatingWindowControl> FloatingWindows
{
get { return _fwList; }
}
#endregion
#region OverlayWindow
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; }
}
OverlayWindow _overlayWindow = null;
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;
}
void DestroyOverlayWindow()
{
if (_overlayWindow != null)
{
_overlayWindow.Close();
_overlayWindow = null;
}
}
IOverlayWindow IOverlayWindowHost.ShowOverlayWindow(LayoutFloatingWindowControl draggingWindow)
{
//Debug.WriteLine("ShowOverlayWindow");
CreateOverlayWindow();
_overlayWindow.Owner = draggingWindow;
_overlayWindow.EnableDropTargets();
_overlayWindow.Show();
return _overlayWindow;
}
void IOverlayWindowHost.HideOverlayWindow()
{
//Debug.WriteLine("HideOverlayWindow");
_areas = null;
_overlayWindow.Owner = null;
_overlayWindow.HideDropTargets();
}
List<IDropArea> _areas = null;
IEnumerable<IDropArea> IOverlayWindowHost.GetDropAreas(LayoutFloatingWindowControl draggingWindow)
{
if (_areas != null)
return _areas;
bool isDraggingDocuments = draggingWindow.Model is LayoutDocumentFloatingWindow;
_areas = new List<IDropArea>();
if (!isDraggingDocuments)
{
_areas.Add(new DropArea<DockingManager>(
this,
DropAreaType.DockingManager));
foreach (var areaHost in this.FindVisualChildren<LayoutAnchorablePaneControl>())
{
if (areaHost.Model.Descendents().Any())
{
_areas.Add(new DropArea<LayoutAnchorablePaneControl>(
areaHost,
DropAreaType.AnchorablePane));
}
}
}
foreach (var areaHost in this.FindVisualChildren<LayoutDocumentPaneControl>())
{
_areas.Add(new DropArea<LayoutDocumentPaneControl>(
areaHost,
DropAreaType.DocumentPane));
}
foreach (var areaHost in this.FindVisualChildren<LayoutDocumentPaneGroupControl>())
{
var documentGroupModel = areaHost.Model as LayoutDocumentPaneGroup;
if (documentGroupModel.Children.Where(c => c.IsVisible).Count() == 0)
{
_areas.Add(new DropArea<LayoutDocumentPaneGroupControl>(
areaHost,
DropAreaType.DocumentPaneGroup));
}
}
return _areas;
}
protected override Size ArrangeOverride(Size arrangeBounds)
{
_areas = null;
return base.ArrangeOverride(arrangeBounds);
}
#endregion
#region LayoutDocument & LayoutAnchorable Templates
#region LayoutItemTemplate
/// <summary>
/// LayoutItemTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutItemTemplateProperty =
DependencyProperty.Register("LayoutItemTemplate", typeof(DataTemplate), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplate)null,
new PropertyChangedCallback(OnLayoutItemTemplateChanged)));
/// <summary>
/// Gets or sets the AnchorableTemplate property. This dependency property
/// indicates the template to use to render anchorable and document contents.
/// </summary>
public DataTemplate LayoutItemTemplate
{
get { return (DataTemplate)GetValue(LayoutItemTemplateProperty); }
set { SetValue(LayoutItemTemplateProperty, value); }
}
/// <summary>
/// Handles changes to the AnchorableTemplate property.
/// </summary>
private static void OnLayoutItemTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnLayoutItemTemplateChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorableTemplate property.
/// </summary>
protected virtual void OnLayoutItemTemplateChanged(DependencyPropertyChangedEventArgs e)
{
}
#endregion
#region LayoutItemTemplateSelector
/// <summary>
/// LayoutItemTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutItemTemplateSelectorProperty =
DependencyProperty.Register("LayoutItemTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplateSelector)null,
new PropertyChangedCallback(OnLayoutItemTemplateSelectorChanged)));
/// <summary>
/// Gets or sets the LayoutItemTemplateSelector property. This dependency property
/// indicates selector object to use for anchorable templates.
/// </summary>
public DataTemplateSelector LayoutItemTemplateSelector
{
get { return (DataTemplateSelector)GetValue(LayoutItemTemplateSelectorProperty); }
set { SetValue(LayoutItemTemplateSelectorProperty, value); }
}
/// <summary>
/// Handles changes to the LayoutItemTemplateSelector property.
/// </summary>
private static void OnLayoutItemTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnLayoutItemTemplateSelectorChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the LayoutItemTemplateSelector property.
/// </summary>
protected virtual void OnLayoutItemTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
{
}
#endregion
#endregion
#region DocumentsSource
/// <summary>
/// DocumentsSource Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentsSourceProperty =
DependencyProperty.Register("DocumentsSource", typeof(IEnumerable), typeof(DockingManager),
new FrameworkPropertyMetadata((IEnumerable)null,
new PropertyChangedCallback(OnDocumentsSourceChanged)));
/// <summary>
/// Gets or sets the DocumentsSource property. This dependency property
/// indicates the source collection of documents.
/// </summary>
public IEnumerable DocumentsSource
{
get { return (IEnumerable)GetValue(DocumentsSourceProperty); }
set { SetValue(DocumentsSourceProperty, value); }
}
/// <summary>
/// Handles changes to the DocumentsSource property.
/// </summary>
private static void OnDocumentsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnDocumentsSourceChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentsSource property.
/// </summary>
protected virtual void OnDocumentsSourceChanged(DependencyPropertyChangedEventArgs e)
{
DetachDocumentsSource(Layout, e.OldValue as IEnumerable);
AttachDocumentsSource(Layout, e.NewValue as IEnumerable);
}
void AttachDocumentsSource(LayoutRoot layout, IEnumerable documentsSource)
{
if (documentsSource == null)
return;
if (layout == null)
return;
//if (layout.Descendents().OfType<LayoutDocument>().Any())
// throw new InvalidOperationException("Unable to set the DocumentsSource property if LayoutDocument objects are already present in the model");
var documentsImported = layout.Descendents().OfType<LayoutDocument>().Select(d => d.Content).ToArray();
var documents = documentsSource as IEnumerable;
var listOfDocumentsToImport = new List<object>(documents.OfType<object>());
foreach (var document in listOfDocumentsToImport.ToArray())
{
if (documentsImported.Contains(document))
listOfDocumentsToImport.Remove(document);
}
LayoutDocumentPane documentPane = null;
if (layout.LastFocusedDocument != null)
{
documentPane = layout.LastFocusedDocument.Parent as LayoutDocumentPane;
}
if (documentPane == null)
{
documentPane = layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
}
//if (documentPane == null)
// throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents");
_suspendLayoutItemCreation = true;
foreach (var documentContentToImport in listOfDocumentsToImport)
{
//documentPane.Children.Add(new LayoutDocument() { Content = documentToImport });
var documentToImport = new LayoutDocument()
{
Content = documentContentToImport
};
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 = true;
var documentsSourceAsNotifier = documentsSource as INotifyCollectionChanged;
if (documentsSourceAsNotifier != null)
documentsSourceAsNotifier.CollectionChanged += new NotifyCollectionChangedEventHandler(documentsSourceElementsChanged);
}
internal bool SuspendDocumentsSourceBinding = false;
void documentsSourceElementsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (Layout == null)
return;
//When deserializing documents are created automatically by the deserializer
if (SuspendDocumentsSourceBinding)
return;
//handle remove
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove ||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)
{
if (e.OldItems != null)
{
var documentsToRemove = Layout.Descendents().OfType<LayoutDocument>().Where(d => e.OldItems.Contains(d.Content)).ToArray();
foreach (var documentToRemove in documentsToRemove)
{
(documentToRemove.Parent as ILayoutContainer).RemoveChild(
documentToRemove);
}
}
}
//handle add
if (e.NewItems != null &&
(e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add ||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace))
{
if (e.NewItems != null)
{
LayoutDocumentPane documentPane = null;
if (Layout.LastFocusedDocument != null)
{
documentPane = Layout.LastFocusedDocument.Parent as LayoutDocumentPane;
}
if (documentPane == null)
{
documentPane = Layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault();
}
//if (documentPane == null)
// throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents");
_suspendLayoutItemCreation = true;
foreach (var documentContentToImport in e.NewItems)
{
var documentToImport = new LayoutDocument()
{
Content = documentContentToImport
};
bool added = false;
if (LayoutUpdateStrategy != null)
{
added = LayoutUpdateStrategy.BeforeInsertDocument(Layout, documentToImport, documentPane);
}
if (!added)
{
if (documentPane == null)
throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents");
documentPane.Children.Add(documentToImport);
added = true;
}
if (LayoutUpdateStrategy != null)
{
LayoutUpdateStrategy.AfterInsertDocument(Layout, documentToImport);
}
var root = documentToImport.Root;
if (root != null && root.Manager == this)
{
CreateDocumentLayoutItem(documentToImport);
}
}
_suspendLayoutItemCreation = false;
}
}
if (e.Action == NotifyCollectionChangedAction.Reset)
{
//NOTE: I'm going to clear every document present in layout but
//some documents may have been added directly to the layout, for now I clear them too
var documentsToRemove = Layout.Descendents().OfType<LayoutDocument>().ToArray();
foreach (var documentToRemove in documentsToRemove)
{
(documentToRemove.Parent as ILayoutContainer).RemoveChild(
documentToRemove);
}
}
if (Layout != null)
{
Layout.CollectGarbage();
}
}
void DetachDocumentsSource(LayoutRoot layout, IEnumerable documentsSource)
{
if (documentsSource == null)
return;
if (layout == null)
return;
var documentsToRemove = layout.Descendents().OfType<LayoutDocument>()
.Where(d => documentsSource.Contains(d.Content)).ToArray();
foreach (var documentToRemove in documentsToRemove)
{
(documentToRemove.Parent as ILayoutContainer).RemoveChild(
documentToRemove);
}
var documentsSourceAsNotifier = documentsSource as INotifyCollectionChanged;
if (documentsSourceAsNotifier != null)
documentsSourceAsNotifier.CollectionChanged -= new NotifyCollectionChangedEventHandler(documentsSourceElementsChanged);
}
#endregion
#region DocumentCloseCommand
internal void _ExecuteCloseCommand(LayoutDocument document)
{
if (DocumentClosing != null)
{
var evargs = new DocumentClosingEventArgs(document);
DocumentClosing(this, evargs);
if (evargs.Cancel)
return;
}
if (!document.TestCanClose())
return;
document.Close();
if (DocumentClosed != null)
{
var evargs = new DocumentClosedEventArgs(document);
DocumentClosed(this, evargs);
}
}
/// <summary>
/// Event fired when a document is about to be closed
/// </summary>
/// <remarks>Subscribers have the opportuniy to cancel the operation.</remarks>
public event EventHandler<DocumentClosingEventArgs> DocumentClosing;
/// <summary>
/// Event fired after a document is closed
/// </summary>
public event EventHandler<DocumentClosedEventArgs> DocumentClosed;
#endregion
internal void _ExecuteCloseAllButThisCommand(LayoutContent contentSelected)
{
foreach (var contentToClose in Layout.Descendents().OfType<LayoutContent>().Where(d => d != contentSelected && (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)).ToArray())
{
if (!contentToClose.CanClose)
continue;
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);
}
}
}
#region DocumentContextMenu
/// <summary>
/// DocumentContextMenu Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentContextMenuProperty =
DependencyProperty.Register("DocumentContextMenu", typeof(ContextMenu), typeof(DockingManager),
new FrameworkPropertyMetadata((ContextMenu)null));
/// <summary>
/// Gets or sets the DocumentContextMenu property. This dependency property
/// indicates context menu to show for documents.
/// </summary>
public ContextMenu DocumentContextMenu
{
get { return (ContextMenu)GetValue(DocumentContextMenuProperty); }
set { SetValue(DocumentContextMenuProperty, value); }
}
#endregion
#region AnchorablesSource
/// <summary>
/// AnchorablesSource Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorablesSourceProperty =
DependencyProperty.Register("AnchorablesSource", typeof(IEnumerable), typeof(DockingManager),
new FrameworkPropertyMetadata((IEnumerable)null,
new PropertyChangedCallback(OnAnchorablesSourceChanged)));
/// <summary>
/// Gets or sets the AnchorablesSource property. This dependency property
/// indicates source collection of anchorables.
/// </summary>
public IEnumerable AnchorablesSource
{
get { return (IEnumerable)GetValue(AnchorablesSourceProperty); }
set { SetValue(AnchorablesSourceProperty, value); }
}
/// <summary>
/// Handles changes to the AnchorablesSource property.
/// </summary>
private static void OnAnchorablesSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnAnchorablesSourceChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the AnchorablesSource property.
/// </summary>
protected virtual void OnAnchorablesSourceChanged(DependencyPropertyChangedEventArgs e)
{
DetachAnchorablesSource(Layout, e.OldValue as IEnumerable);
AttachAnchorablesSource(Layout, e.NewValue as IEnumerable);
}
void AttachAnchorablesSource(LayoutRoot layout, IEnumerable anchorablesSource)
{
if (anchorablesSource == null)
return;
if (layout == null)
return;
//if (layout.Descendents().OfType<LayoutAnchorable>().Any())
// throw new InvalidOperationException("Unable to set the AnchorablesSource property if LayoutAnchorable objects are already present in the model");
var anchorablesImported = layout.Descendents().OfType<LayoutAnchorable>().Select(d => d.Content).ToArray();
var anchorables = anchorablesSource as IEnumerable;
var listOfAnchorablesToImport = new List<object>(anchorables.OfType<object>());
foreach (var document in listOfAnchorablesToImport.ToArray())
{
if (anchorablesImported.Contains(document))
listOfAnchorablesToImport.Remove(document);
}
LayoutAnchorablePane anchorablePane = null;
if (layout.ActiveContent != null)
{
//look for active content parent pane
anchorablePane = layout.ActiveContent.Parent as LayoutAnchorablePane;
}
if (anchorablePane == null)
{
//look for a pane on the right side
anchorablePane = layout.Descendents().OfType<LayoutAnchorablePane>().Where(pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right).FirstOrDefault();
}
if (anchorablePane == null)
{
//look for an available pane
anchorablePane = layout.Descendents().OfType<LayoutAnchorablePane>().FirstOrDefault();
}
_suspendLayoutItemCreation = true;
foreach (var anchorableContentToImport in listOfAnchorablesToImport)
{
var anchorableToImport = new LayoutAnchorable()
{
Content = anchorableContentToImport
};
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)
anchorablesSourceAsNotifier.CollectionChanged += new NotifyCollectionChangedEventHandler(anchorablesSourceElementsChanged);
}
internal bool SuspendAnchorablesSourceBinding = false;
void anchorablesSourceElementsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (Layout == null)
return;
//When deserializing documents are created automatically by the deserializer
if (SuspendAnchorablesSourceBinding)
return;
//handle remove
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove ||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)
{
if (e.OldItems != null)
{
var anchorablesToRemove = Layout.Descendents().OfType<LayoutAnchorable>().Where(d => e.OldItems.Contains(d.Content)).ToArray();
foreach (var anchorableToRemove in anchorablesToRemove)
{
(anchorableToRemove.Parent as ILayoutContainer).RemoveChild(
anchorableToRemove);
}
}
}
//handle add
if (e.NewItems != null &&
(e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add ||
e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace))
{
if (e.NewItems != null)
{
LayoutAnchorablePane anchorablePane = null;
if (Layout.ActiveContent != null)
{
//look for active content parent pane
anchorablePane = Layout.ActiveContent.Parent as LayoutAnchorablePane;
}
if (anchorablePane == null)
{
//look for a pane on the right side
anchorablePane = Layout.Descendents().OfType<LayoutAnchorablePane>().Where(pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right).FirstOrDefault();
}
if (anchorablePane == null)
{
//look for an available pane
anchorablePane = Layout.Descendents().OfType<LayoutAnchorablePane>().FirstOrDefault();
}
_suspendLayoutItemCreation = true;
foreach (var anchorableContentToImport in e.NewItems)
{
var anchorableToImport = new LayoutAnchorable()
{
Content = anchorableContentToImport
};
bool added = false;
if (LayoutUpdateStrategy != null)
{
added = LayoutUpdateStrategy.BeforeInsertAnchorable(Layout, anchorableToImport, anchorablePane);
}
if (!added)
{
if (anchorablePane == null)
{
var mainLayoutPanel = new LayoutPanel() { Orientation = Orientation.Horizontal };
if (Layout.RootPanel != null)
{
mainLayoutPanel.Children.Add(Layout.RootPanel);
}
Layout.RootPanel = mainLayoutPanel;
anchorablePane = new LayoutAnchorablePane() { DockWidth = new GridLength(200.0, GridUnitType.Pixel) };
mainLayoutPanel.Children.Add(anchorablePane);
}
anchorablePane.Children.Add(anchorableToImport);
added = true;
}
if (LayoutUpdateStrategy != null)
{
LayoutUpdateStrategy.AfterInsertAnchorable(Layout, anchorableToImport);
}
var root = anchorableToImport.Root;
if (root != null && root.Manager == this)
{
CreateAnchorableLayoutItem(anchorableToImport);
}
}
_suspendLayoutItemCreation = false;
}
}
if (e.Action == NotifyCollectionChangedAction.Reset)
{
//NOTE: I'm going to clear every anchorable present in layout but
//some anchorable may have been added directly to the layout, for now I clear them too
var anchorablesToRemove = Layout.Descendents().OfType<LayoutAnchorable>().ToArray();
foreach (var anchorableToRemove in anchorablesToRemove)
{
(anchorableToRemove.Parent as ILayoutContainer).RemoveChild(
anchorableToRemove);
}
}
if (Layout != null)
Layout.CollectGarbage();
}
void DetachAnchorablesSource(LayoutRoot layout, IEnumerable anchorablesSource)
{
if (anchorablesSource == null)
return;
if (layout == null)
return;
var anchorablesToRemove = layout.Descendents().OfType<LayoutAnchorable>()
.Where(d => anchorablesSource.Contains(d.Content)).ToArray();
foreach (var anchorableToRemove in anchorablesToRemove)
{
(anchorableToRemove.Parent as ILayoutContainer).RemoveChild(
anchorableToRemove);
}
var anchorablesSourceAsNotifier = anchorablesSource as INotifyCollectionChanged;
if (anchorablesSourceAsNotifier != null)
anchorablesSourceAsNotifier.CollectionChanged -= new NotifyCollectionChangedEventHandler(anchorablesSourceElementsChanged);
}
#endregion
internal void _ExecuteCloseCommand(LayoutAnchorable anchorable)
{
var model = anchorable as LayoutAnchorable;
if (model != null && model.TestCanClose())
{
if (model.IsAutoHidden)
model.ToggleAutoHide();
model.Close();
return;
}
}
internal void _ExecuteHideCommand(LayoutAnchorable anchorable)
{
var model = anchorable as LayoutAnchorable;
if (model != null)
{
//by default hide the anchorable
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();
}
#region ActiveContent
/// <summary>
/// ActiveContent Dependency Property
/// </summary>
public static readonly DependencyProperty ActiveContentProperty =
DependencyProperty.Register("ActiveContent", typeof(object), typeof(DockingManager),
new FrameworkPropertyMetadata((object)null,
new PropertyChangedCallback(OnActiveContentChanged)));
/// <summary>
/// Gets or sets the ActiveContent property. This dependency property
/// indicates the content currently active.
/// </summary>
public object ActiveContent
{
get { return (object)GetValue(ActiveContentProperty); }
set { SetValue(ActiveContentProperty, value); }
}
/// <summary>
/// Handles changes to the ActiveContent property.
/// </summary>
private static void OnActiveContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).InternalSetActiveContent(e.NewValue);
((DockingManager)d).OnActiveContentChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the ActiveContent property.
/// </summary>
protected virtual void OnActiveContentChanged(DependencyPropertyChangedEventArgs e)
{
if (ActiveContentChanged != null)
ActiveContentChanged(this, EventArgs.Empty);
}
bool _insideInternalSetActiveContent = false;
void InternalSetActiveContent(object contentObject)
{
var layoutContent = Layout.Descendents().OfType<LayoutContent>().FirstOrDefault(lc => lc == contentObject || lc.Content == contentObject);
_insideInternalSetActiveContent = true;
Layout.ActiveContent = layoutContent;
_insideInternalSetActiveContent = false;
}
public event EventHandler ActiveContentChanged;
#endregion
#region AnchorableContextMenu
/// <summary>
/// AnchorableContextMenu Dependency Property
/// </summary>
public static readonly DependencyProperty AnchorableContextMenuProperty =
DependencyProperty.Register("AnchorableContextMenu", typeof(ContextMenu), typeof(DockingManager),
new FrameworkPropertyMetadata((ContextMenu)null));
/// <summary>
/// Gets or sets the AnchorableContextMenu property. This dependency property
/// indicates the context menu to show up for anchorables.
/// </summary>
public ContextMenu AnchorableContextMenu
{
get { return (ContextMenu)GetValue(AnchorableContextMenuProperty); }
set { SetValue(AnchorableContextMenuProperty, value); }
}
#endregion
#region Theme
/// <summary>
/// Theme Dependency Property
/// </summary>
public static readonly DependencyProperty ThemeProperty =
DependencyProperty.Register("Theme", typeof(Theme), typeof(DockingManager),
new FrameworkPropertyMetadata(null,
new PropertyChangedCallback(OnThemeChanged)));
/// <summary>
/// Gets or sets the Theme property. This dependency property
/// indicates the theme to use for AvalonDock controls.
/// </summary>
public Theme Theme
{
get { return (Theme)GetValue(ThemeProperty); }
set { SetValue(ThemeProperty, value); }
}
/// <summary>
/// Handles changes to the Theme property.
/// </summary>
private static void OnThemeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnThemeChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the Theme property.
/// </summary>
protected virtual void OnThemeChanged(DependencyPropertyChangedEventArgs e)
{
var oldTheme = e.OldValue as Theme;
var newTheme = e.NewValue as Theme;
var resources = Application.Current == null ? this.Resources : Application.Current.Resources;
if (oldTheme != null)
{
var resourceDictionaryToRemove =
resources.MergedDictionaries.FirstOrDefault(r => r.Source == oldTheme.GetResourceUri());
if (resourceDictionaryToRemove != null)
resources.MergedDictionaries.Remove(
resourceDictionaryToRemove);
}
if (newTheme != null)
{
resources.MergedDictionaries.Add(new ResourceDictionary() { Source = newTheme.GetResourceUri() });
}
if (Application.Current == null)
{
foreach (var fwc in _fwList)
fwc.UpdateThemeResources(oldTheme);
if (_navigatorWindow != null)
_navigatorWindow.UpdateThemeResources();
if (_overlayWindow != null)
_overlayWindow.UpdateThemeResources();
}
}
#endregion
#region GridSplitterWidth
/// <summary>
/// GridSplitterWidth Dependency Property
/// </summary>
public static readonly DependencyProperty GridSplitterWidthProperty =
DependencyProperty.Register("GridSplitterWidth", typeof(double), typeof(DockingManager),
new FrameworkPropertyMetadata((double)6.0));
/// <summary>
/// Gets or sets the GridSplitterWidth property. This dependency property
/// indicates width of grid splitters.
/// </summary>
public double GridSplitterWidth
{
get { return (double)GetValue(GridSplitterWidthProperty); }
set { SetValue(GridSplitterWidthProperty, value); }
}
#endregion
#region GridSplitterHeight
/// <summary>
/// GridSplitterHeight Dependency Property
/// </summary>
public static readonly DependencyProperty GridSplitterHeightProperty =
DependencyProperty.Register("GridSplitterHeight", typeof(double), typeof(DockingManager),
new FrameworkPropertyMetadata((double)6.0));
/// <summary>
/// Gets or sets the GridSplitterHeight property. This dependency property
/// indicates height of grid splitters.
/// </summary>
public double GridSplitterHeight
{
get { return (double)GetValue(GridSplitterHeightProperty); }
set { SetValue(GridSplitterHeightProperty, value); }
}
#endregion
internal void _ExecuteContentActivateCommand(LayoutContent content)
{
content.IsActive = true;
}
#region DocumentPaneMenuItemHeaderTemplate
/// <summary>
/// DocumentPaneMenuItemHeaderTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateProperty =
DependencyProperty.Register("DocumentPaneMenuItemHeaderTemplate", typeof(DataTemplate), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplate)null,
new PropertyChangedCallback(OnDocumentPaneMenuItemHeaderTemplateChanged),
new CoerceValueCallback(CoerceDocumentPaneMenuItemHeaderTemplateValue)));
/// <summary>
/// Gets or sets the DocumentPaneMenuItemHeaderTemplate property. This dependency property
/// indicates the header template to use while creating menu items for the document panes.
/// </summary>
public DataTemplate DocumentPaneMenuItemHeaderTemplate
{
get { return (DataTemplate)GetValue(DocumentPaneMenuItemHeaderTemplateProperty); }
set { SetValue(DocumentPaneMenuItemHeaderTemplateProperty, value); }
}
/// <summary>
/// Handles changes to the DocumentPaneMenuItemHeaderTemplate property.
/// </summary>
private static void OnDocumentPaneMenuItemHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnDocumentPaneMenuItemHeaderTemplateChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplate property.
/// </summary>
protected virtual void OnDocumentPaneMenuItemHeaderTemplateChanged(DependencyPropertyChangedEventArgs e)
{
}
/// <summary>
/// Coerces the DocumentPaneMenuItemHeaderTemplate value.
/// </summary>
private static object CoerceDocumentPaneMenuItemHeaderTemplateValue(DependencyObject d, object value)
{
if (value != null &&
d.GetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty) != null)
return null;
if (value == null)
return d.GetValue(DocumentHeaderTemplateProperty);
return value;
}
#endregion
#region DocumentPaneMenuItemHeaderTemplateSelector
/// <summary>
/// DocumentPaneMenuItemHeaderTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateSelectorProperty =
DependencyProperty.Register("DocumentPaneMenuItemHeaderTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplateSelector)null,
new PropertyChangedCallback(OnDocumentPaneMenuItemHeaderTemplateSelectorChanged),
new CoerceValueCallback(CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue)));
/// <summary>
/// Gets or sets the DocumentPaneMenuItemHeaderTemplateSelector property. This dependency property
/// indicates the data template selector to use for the menu items show when user select the DocumentPane document switch context menu.
/// </summary>
public DataTemplateSelector DocumentPaneMenuItemHeaderTemplateSelector
{
get { return (DataTemplateSelector)GetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty); }
set { SetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty, value); }
}
/// <summary>
/// Handles changes to the DocumentPaneMenuItemHeaderTemplateSelector property.
/// </summary>
private static void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the DocumentPaneMenuItemHeaderTemplateSelector property.
/// </summary>
protected virtual void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e)
{
if (e.NewValue != null &&
DocumentPaneMenuItemHeaderTemplate != null)
DocumentPaneMenuItemHeaderTemplate = null;
}
/// <summary>
/// Coerces the DocumentPaneMenuItemHeaderTemplateSelector value.
/// </summary>
private static object CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue(DependencyObject d, object value)
{
return value;
}
#endregion
#region IconContentTemplate
/// <summary>
/// IconContentTemplate Dependency Property
/// </summary>
public static readonly DependencyProperty IconContentTemplateProperty =
DependencyProperty.Register("IconContentTemplate", typeof(DataTemplate), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplate)null));
/// <summary>
/// Gets or sets the IconContentTemplate property. This dependency property
/// indicates the data template to use while extracting the icon from model.
/// </summary>
public DataTemplate IconContentTemplate
{
get { return (DataTemplate)GetValue(IconContentTemplateProperty); }
set { SetValue(IconContentTemplateProperty, value); }
}
#endregion
#region IconContentTemplateSelector
/// <summary>
/// IconContentTemplateSelector Dependency Property
/// </summary>
public static readonly DependencyProperty IconContentTemplateSelectorProperty =
DependencyProperty.Register("IconContentTemplateSelector", typeof(DataTemplateSelector), typeof(DockingManager),
new FrameworkPropertyMetadata((DataTemplateSelector)null));
/// <summary>
/// Gets or sets the IconContentTemplateSelector property. This dependency property
/// indicates data template selector to use while selecting the datatamplate for content icons.
/// </summary>
public DataTemplateSelector IconContentTemplateSelector
{
get { return (DataTemplateSelector)GetValue(IconContentTemplateSelectorProperty); }
set { SetValue(IconContentTemplateSelectorProperty, value); }
}
#endregion
#region LayoutItems
List<LayoutItem> _layoutItems = new List<LayoutItem>();
bool _suspendLayoutItemCreation = false;
void DetachLayoutItems()
{
if (Layout != null)
{
_layoutItems.ForEach<LayoutItem>(i => i.Detach());
_layoutItems.Clear();
Layout.ElementAdded -= new EventHandler<LayoutElementEventArgs>(Layout_ElementAdded);
Layout.ElementRemoved -= new EventHandler<LayoutElementEventArgs>(Layout_ElementRemoved);
}
}
void Layout_ElementRemoved(object sender, LayoutElementEventArgs e)
{
if (_suspendLayoutItemCreation)
return;
CollectLayoutItemsDeleted();
}
void Layout_ElementAdded(object sender, LayoutElementEventArgs e)
{
if (_suspendLayoutItemCreation)
return;
foreach (var content in Layout.Descendents().OfType<LayoutContent>())
{
if (content is LayoutDocument)
CreateDocumentLayoutItem(content as LayoutDocument);
else //if (content is LayoutAnchorable)
CreateAnchorableLayoutItem(content as LayoutAnchorable);
}
CollectLayoutItemsDeleted();
}
DispatcherOperation _collectLayoutItemsOperations = null;
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);
}
}));
}
void AttachLayoutItems()
{
if (Layout != null)
{
foreach (var document in Layout.Descendents().OfType<LayoutDocument>().ToArray())
{
CreateDocumentLayoutItem(document);
//var documentItem = new LayoutDocumentItem();
//documentItem.Attach(document);
//ApplyStyleToLayoutItem(documentItem);
//_layoutItems.Add(documentItem);
}
foreach (var anchorable in Layout.Descendents().OfType<LayoutAnchorable>().ToArray())
{
CreateAnchorableLayoutItem(anchorable);
//var anchorableItem = new LayoutAnchorableItem();
//anchorableItem.Attach(anchorable);
//ApplyStyleToLayoutItem(anchorableItem);
//_layoutItems.Add(anchorableItem);
}
Layout.ElementAdded += new EventHandler<LayoutElementEventArgs>(Layout_ElementAdded);
Layout.ElementRemoved += new EventHandler<LayoutElementEventArgs>(Layout_ElementRemoved);
}
}
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();
}
void CreateAnchorableLayoutItem(LayoutAnchorable contentToAttach)
{
if (_layoutItems.Any(item => item.LayoutElement == contentToAttach))
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);
}
}
void CreateDocumentLayoutItem(LayoutDocument contentToAttach)
{
if (_layoutItems.Any(item => item.LayoutElement == contentToAttach))
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);
}
}
#region LayoutItemContainerStyle
/// <summary>
/// LayoutItemContainerStyle Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutItemContainerStyleProperty =
DependencyProperty.Register("LayoutItemContainerStyle", typeof(Style), typeof(DockingManager),
new FrameworkPropertyMetadata((Style)null,
new PropertyChangedCallback(OnLayoutItemContainerStyleChanged)));
/// <summary>
/// Gets or sets the LayoutItemContainerStyle property. This dependency property
/// indicates the style to apply to LayoutDocumentItem objects. A LayoutDocumentItem object is created when a new LayoutDocument is created inside the current Layout.
/// </summary>
public Style LayoutItemContainerStyle
{
get { return (Style)GetValue(LayoutItemContainerStyleProperty); }
set { SetValue(LayoutItemContainerStyleProperty, value); }
}
/// <summary>
/// Handles changes to the LayoutItemContainerStyle property.
/// </summary>
private static void OnLayoutItemContainerStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnLayoutItemContainerStyleChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyle property.
/// </summary>
protected virtual void OnLayoutItemContainerStyleChanged(DependencyPropertyChangedEventArgs e)
{
AttachLayoutItems();
}
#endregion
#region LayoutItemContainerStyleSelector
/// <summary>
/// LayoutItemContainerStyleSelector Dependency Property
/// </summary>
public static readonly DependencyProperty LayoutItemContainerStyleSelectorProperty =
DependencyProperty.Register("LayoutItemContainerStyleSelector", typeof(StyleSelector), typeof(DockingManager),
new FrameworkPropertyMetadata((StyleSelector)null,
new PropertyChangedCallback(OnLayoutItemContainerStyleSelectorChanged)));
/// <summary>
/// Gets or sets the LayoutItemContainerStyleSelector property. This dependency property
/// indicates style selector of the LayoutDocumentItemStyle.
/// </summary>
public StyleSelector LayoutItemContainerStyleSelector
{
get { return (StyleSelector)GetValue(LayoutItemContainerStyleSelectorProperty); }
set { SetValue(LayoutItemContainerStyleSelectorProperty, value); }
}
/// <summary>
/// Handles changes to the LayoutItemContainerStyleSelector property.
/// </summary>
private static void OnLayoutItemContainerStyleSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DockingManager)d).OnLayoutItemContainerStyleSelectorChanged(e);
}
/// <summary>
/// Provides derived classes an opportunity to handle changes to the LayoutItemContainerStyleSelector property.
/// </summary>
protected virtual void OnLayoutItemContainerStyleSelectorChanged(DependencyPropertyChangedEventArgs e)
{
AttachLayoutItems();
}
#endregion
/// <summary>
/// Return the LayoutItem wrapper for the content passed as argument
/// </summary>
/// <param name="content">LayoutContent to search</param>
/// <returns>Either a LayoutAnchorableItem or LayoutDocumentItem which contains the LayoutContent passed as argument</returns>
public LayoutItem GetLayoutItemFromModel(LayoutContent content)
{
return _layoutItems.FirstOrDefault(item => item.LayoutElement == content);
}
#endregion
#region NavigatorWindow
NavigatorWindow _navigatorWindow = null;
void ShowNavigatorWindow()
{
if (_navigatorWindow == null)
{
_navigatorWindow = new NavigatorWindow(this)
{
Owner = Window.GetWindow(this),
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
}
_navigatorWindow.ShowDialog();
_navigatorWindow = null;
Debug.WriteLine("ShowNavigatorWindow()");
}
bool IsNavigatorWindowActive
{
get { return _navigatorWindow != null; }
}
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
Debug.WriteLine("OnPreviewKeyDown({0})", e.Key);
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);
}
#endregion
#region ShowSystemMenu
/// <summary>
/// ShowSystemMenu Dependency Property
/// </summary>
public static readonly DependencyProperty ShowSystemMenuProperty =
DependencyProperty.Register("ShowSystemMenu", typeof(bool), typeof(DockingManager),
new FrameworkPropertyMetadata((bool)true));
/// <summary>
/// Gets or sets the ShowSystemMenu property. This dependency property
/// indicates if floating windows should show the system menu when a custom context menu is not defined.
/// </summary>
public bool ShowSystemMenu
{
get { return (bool)GetValue(ShowSystemMenuProperty); }
set { SetValue(ShowSystemMenuProperty, value); }
}
#endregion
#region AllowMixedOrientation
/// <summary>
/// AllowMixedOrientation Dependency Property
/// </summary>
public static readonly DependencyProperty AllowMixedOrientationProperty =
DependencyProperty.Register("AllowMixedOrientation", typeof(bool), typeof(DockingManager),
new FrameworkPropertyMetadata((bool)false));
/// <summary>
/// Gets or sets the AllowMixedOrientation property. This dependency property
/// indicates if the manager should allow mixed orientation for document panes.
/// </summary>
public bool AllowMixedOrientation
{
get { return (bool)GetValue(AllowMixedOrientationProperty); }
set { SetValue(AllowMixedOrientationProperty, value); }
}
#endregion
}
}