/************************************************************************************* Extended WPF Toolkit Copyright (C) 2007-2013 Xceed Software Inc. This program is provided to you under the terms of the Microsoft Public License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license For more features, controls, and fast professional support, pick up the Plus Edition at http://xceed.com/wpf_toolkit Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids ***********************************************************************************/ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using Xceed.Wpf.AvalonDock.Layout; using System.Windows.Input; using Xceed.Wpf.AvalonDock.Commands; using System.ComponentModel; using System.Windows.Data; using System.Windows.Media; using System.Windows.Controls; namespace Xceed.Wpf.AvalonDock.Controls { public abstract class LayoutItem : FrameworkElement { static LayoutItem() { ToolTipProperty.OverrideMetadata(typeof(LayoutItem), new FrameworkPropertyMetadata(null, (s, e) => OnToolTipChanged(s,e))); VisibilityProperty.OverrideMetadata(typeof(LayoutItem), new FrameworkPropertyMetadata(Visibility.Visible, (s,e) => OnVisibilityChanged(s, e))); } internal LayoutItem() { } internal virtual void Attach(LayoutContent model) { LayoutElement = model; Model = model.Content; InitDefaultCommands(); LayoutElement.IsSelectedChanged+=new EventHandler(LayoutElement_IsSelectedChanged); LayoutElement.IsActiveChanged+=new EventHandler(LayoutElement_IsActiveChanged); DataContext = this; System.Diagnostics.Trace.WriteLine( string.Format( "Attach({0})", LayoutElement.Title ) ); } void LayoutElement_IsActiveChanged(object sender, EventArgs e) { if (_isActiveReentrantFlag.CanEnter) { using (_isActiveReentrantFlag.Enter()) { var bnd = BindingOperations.GetBinding(this, IsActiveProperty); IsActive = LayoutElement.IsActive; var bnd2 = BindingOperations.GetBinding(this, IsActiveProperty); } } } void LayoutElement_IsSelectedChanged(object sender, EventArgs e) { if (_isSelectedReentrantFlag.CanEnter) { using (_isSelectedReentrantFlag.Enter()) { IsSelected = LayoutElement.IsSelected; } } } internal virtual void Detach() { System.Diagnostics.Trace.WriteLine( string.Format( "Detach({0})", LayoutElement.Title ) ); LayoutElement.IsSelectedChanged -= new EventHandler(LayoutElement_IsSelectedChanged); LayoutElement.IsActiveChanged -= new EventHandler(LayoutElement_IsActiveChanged); LayoutElement = null; Model = null; } public LayoutContent LayoutElement { get; private set; } public object Model { get; private set; } ICommand _defaultCloseCommand; ICommand _defaultFloatCommand; ICommand _defaultDockAsDocumentCommand; ICommand _defaultCloseAllButThisCommand; ICommand _defaultActivateCommand; ICommand _defaultNewVerticalTabGroupCommand; ICommand _defaultNewHorizontalTabGroupCommand; ICommand _defaultMoveToNextTabGroupCommand; ICommand _defaultMoveToPreviousTabGroupCommand; protected virtual void InitDefaultCommands() { _defaultCloseCommand = new RelayCommand((p) => ExecuteCloseCommand(p), (p) => CanExecuteCloseCommand(p)); _defaultFloatCommand = new RelayCommand((p) => ExecuteFloatCommand(p), (p) => CanExecuteFloatCommand(p)); _defaultDockAsDocumentCommand = new RelayCommand((p) => ExecuteDockAsDocumentCommand(p), (p) => CanExecuteDockAsDocumentCommand(p)); _defaultCloseAllButThisCommand = new RelayCommand((p) => ExecuteCloseAllButThisCommand(p), (p) => CanExecuteCloseAllButThisCommand(p)); _defaultActivateCommand = new RelayCommand((p) => ExecuteActivateCommand(p), (p) => CanExecuteActivateCommand(p)); _defaultNewVerticalTabGroupCommand = new RelayCommand((p) => ExecuteNewVerticalTabGroupCommand(p), (p) => CanExecuteNewVerticalTabGroupCommand(p)); _defaultNewHorizontalTabGroupCommand = new RelayCommand((p) => ExecuteNewHorizontalTabGroupCommand(p), (p) => CanExecuteNewHorizontalTabGroupCommand(p)); _defaultMoveToNextTabGroupCommand = new RelayCommand((p) => ExecuteMoveToNextTabGroupCommand(p), (p) => CanExecuteMoveToNextTabGroupCommand(p)); _defaultMoveToPreviousTabGroupCommand = new RelayCommand((p) => ExecuteMoveToPreviousTabGroupCommand(p), (p) => CanExecuteMoveToPreviousTabGroupCommand(p)); } protected virtual void ClearDefaultBindings() { if (CloseCommand == _defaultCloseCommand) BindingOperations.ClearBinding(this, CloseCommandProperty); if (FloatCommand == _defaultFloatCommand) BindingOperations.ClearBinding(this, FloatCommandProperty); if (DockAsDocumentCommand == _defaultDockAsDocumentCommand) BindingOperations.ClearBinding(this, DockAsDocumentCommandProperty); if (CloseAllButThisCommand == _defaultCloseAllButThisCommand) BindingOperations.ClearBinding(this, CloseAllButThisCommandProperty); if (ActivateCommand == _defaultActivateCommand) BindingOperations.ClearBinding(this, ActivateCommandProperty); if (NewVerticalTabGroupCommand == _defaultNewVerticalTabGroupCommand) BindingOperations.ClearBinding(this, NewVerticalTabGroupCommandProperty); if (NewHorizontalTabGroupCommand == _defaultNewHorizontalTabGroupCommand) BindingOperations.ClearBinding(this, NewHorizontalTabGroupCommandProperty); if (MoveToNextTabGroupCommand == _defaultMoveToNextTabGroupCommand) BindingOperations.ClearBinding(this, MoveToNextTabGroupCommandProperty); if (MoveToPreviousTabGroupCommand == _defaultMoveToPreviousTabGroupCommand) BindingOperations.ClearBinding(this, MoveToPreviousTabGroupCommandProperty); } protected virtual void SetDefaultBindings() { if (CloseCommand == null) CloseCommand = _defaultCloseCommand; if (FloatCommand == null) FloatCommand = _defaultFloatCommand; if (DockAsDocumentCommand == null) DockAsDocumentCommand = _defaultDockAsDocumentCommand; if (CloseAllButThisCommand == null) CloseAllButThisCommand = _defaultCloseAllButThisCommand; if (ActivateCommand == null) ActivateCommand = _defaultActivateCommand; if (NewVerticalTabGroupCommand == null) NewVerticalTabGroupCommand = _defaultNewVerticalTabGroupCommand; if (NewHorizontalTabGroupCommand == null) NewHorizontalTabGroupCommand = _defaultNewHorizontalTabGroupCommand; if (MoveToNextTabGroupCommand == null) MoveToNextTabGroupCommand = _defaultMoveToNextTabGroupCommand; if (MoveToPreviousTabGroupCommand == null) MoveToPreviousTabGroupCommand = _defaultMoveToPreviousTabGroupCommand; IsSelected = LayoutElement.IsSelected; IsActive = LayoutElement.IsActive; } internal void _ClearDefaultBindings() { ClearDefaultBindings(); } internal void _SetDefaultBindings() { SetDefaultBindings(); } ContentPresenter _view = null; public ContentPresenter View { get { if (_view == null) { _view = new ContentPresenter(); _view.SetBinding(ContentPresenter.ContentProperty, new Binding("Content") { Source = LayoutElement }); _view.SetBinding(ContentPresenter.ContentTemplateProperty, new Binding("LayoutItemTemplate") { Source = LayoutElement.Root.Manager}); _view.SetBinding(ContentPresenter.ContentTemplateSelectorProperty, new Binding("LayoutItemTemplateSelector") { Source = LayoutElement.Root.Manager }); LayoutElement.Root.Manager.InternalAddLogicalChild(_view); } return _view; } } #region Title /// /// Title Dependency Property /// public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(LayoutItem), new FrameworkPropertyMetadata((string)null, new PropertyChangedCallback(OnTitleChanged))); /// /// Gets or sets the Title property. This dependency property /// indicates the title of the element. /// public string Title { get { return (string)GetValue(TitleProperty); } set { SetValue(TitleProperty, value); } } /// /// Handles changes to the Title property. /// private static void OnTitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnTitleChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the Title property. /// protected virtual void OnTitleChanged(DependencyPropertyChangedEventArgs e) { if (LayoutElement != null) LayoutElement.Title = (string)e.NewValue; } #endregion #region ToolTip private static void OnToolTipChanged(DependencyObject s, DependencyPropertyChangedEventArgs e) { ((LayoutItem)s).OnToolTipChanged(); } private void OnToolTipChanged() { if (LayoutElement != null) LayoutElement.ToolTip = ToolTip; } #endregion #region IconSource /// /// IconSource Dependency Property /// public static readonly DependencyProperty IconSourceProperty = DependencyProperty.Register("IconSource", typeof(ImageSource), typeof(LayoutItem), new FrameworkPropertyMetadata((ImageSource)null, new PropertyChangedCallback(OnIconSourceChanged))); /// /// Gets or sets the IconSource property. This dependency property /// indicates icon associated with the item. /// public ImageSource IconSource { get { return (ImageSource)GetValue(IconSourceProperty); } set { SetValue(IconSourceProperty, value); } } /// /// Handles changes to the IconSource property. /// private static void OnIconSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnIconSourceChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the IconSource property. /// protected virtual void OnIconSourceChanged(DependencyPropertyChangedEventArgs e) { if (LayoutElement != null) LayoutElement.IconSource = IconSource; } #endregion #region Visibility private static void OnVisibilityChanged(DependencyObject s, DependencyPropertyChangedEventArgs e) { ((LayoutItem)s).OnVisibilityChanged(); } protected virtual void OnVisibilityChanged() { if (LayoutElement != null && Visibility == System.Windows.Visibility.Collapsed) LayoutElement.Close(); } #endregion #region ContentId /// /// ContentId Dependency Property /// public static readonly DependencyProperty ContentIdProperty = DependencyProperty.Register("ContentId", typeof(string), typeof(LayoutItem), new FrameworkPropertyMetadata((string)null, new PropertyChangedCallback(OnContentIdChanged))); /// /// Gets or sets the ContentId property. This dependency property /// indicates the content id used to retrive content when deserializing layouts. /// public string ContentId { get { return (string)GetValue(ContentIdProperty); } set { SetValue(ContentIdProperty, value); } } /// /// Handles changes to the ContentId property. /// private static void OnContentIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnContentIdChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the ContentId property. /// protected virtual void OnContentIdChanged(DependencyPropertyChangedEventArgs e) { if (LayoutElement != null) LayoutElement.ContentId = (string)e.NewValue; } #endregion #region IsSelected ReentrantFlag _isSelectedReentrantFlag = new ReentrantFlag(); /// /// IsSelected Dependency Property /// public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(LayoutItem), new FrameworkPropertyMetadata((bool)false, new PropertyChangedCallback(OnIsSelectedChanged))); /// /// Gets or sets the IsSelected property. This dependency property /// indicates if the item is selected inside its container. /// public bool IsSelected { get { return (bool)GetValue(IsSelectedProperty); } set { SetValue(IsSelectedProperty, value); } } /// /// Handles changes to the IsSelected property. /// private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnIsSelectedChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the IsSelected property. /// protected virtual void OnIsSelectedChanged(DependencyPropertyChangedEventArgs e) { if (_isSelectedReentrantFlag.CanEnter) { using (_isSelectedReentrantFlag.Enter()) { if (LayoutElement != null) LayoutElement.IsSelected = (bool)e.NewValue; } } } #endregion #region IsActive ReentrantFlag _isActiveReentrantFlag = new ReentrantFlag(); /// /// IsActive Dependency Property /// public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register("IsActive", typeof(bool), typeof(LayoutItem), new FrameworkPropertyMetadata((bool)false, new PropertyChangedCallback(OnIsActiveChanged))); /// /// Gets or sets the IsActive property. This dependency property /// indicates if the item is active in the UI. /// public bool IsActive { get { return (bool)GetValue(IsActiveProperty); } set { SetValue(IsActiveProperty, value); } } /// /// Handles changes to the IsActive property. /// private static void OnIsActiveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnIsActiveChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the IsActive property. /// protected virtual void OnIsActiveChanged(DependencyPropertyChangedEventArgs e) { if (_isActiveReentrantFlag.CanEnter) { using (_isActiveReentrantFlag.Enter()) { if (LayoutElement != null) LayoutElement.IsActive = (bool)e.NewValue; } } } #endregion #region CanClose /// /// CanClose Dependency Property /// public static readonly DependencyProperty CanCloseProperty = DependencyProperty.Register("CanClose", typeof(bool), typeof(LayoutItem), new FrameworkPropertyMetadata((bool)true, new PropertyChangedCallback(OnCanCloseChanged))); /// /// Gets or sets the CanClose property. This dependency property /// indicates if the item can be closed. /// public bool CanClose { get { return (bool)GetValue(CanCloseProperty); } set { SetValue(CanCloseProperty, value); } } /// /// Handles changes to the CanClose property. /// private static void OnCanCloseChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnCanCloseChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the CanClose property. /// protected virtual void OnCanCloseChanged(DependencyPropertyChangedEventArgs e) { if (LayoutElement != null) LayoutElement.CanClose = (bool)e.NewValue; } #endregion #region CanFloat /// /// CanFloat Dependency Property /// public static readonly DependencyProperty CanFloatProperty = DependencyProperty.Register("CanFloat", typeof(bool), typeof(LayoutItem), new FrameworkPropertyMetadata((bool)true, new PropertyChangedCallback(OnCanFloatChanged))); /// /// Gets or sets the CanFloat property. This dependency property /// indicates if user can move the layout element dragging it to another position. /// public bool CanFloat { get { return (bool)GetValue(CanFloatProperty); } set { SetValue(CanFloatProperty, value); } } /// /// Handles changes to the CanFloat property. /// private static void OnCanFloatChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnCanFloatChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the CanFloat property. /// protected virtual void OnCanFloatChanged(DependencyPropertyChangedEventArgs e) { if (LayoutElement != null) LayoutElement.CanFloat = (bool)e.NewValue; } #endregion #region CloseCommand /// /// CloseCommand Dependency Property /// public static readonly DependencyProperty CloseCommandProperty = DependencyProperty.Register("CloseCommand", typeof(ICommand), typeof(LayoutItem), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnCloseCommandChanged), new CoerceValueCallback(CoerceCloseCommandValue))); /// /// Gets or sets the CloseCommand property. This dependency property /// indicates the command to execute when user click the document close button. /// public ICommand CloseCommand { get { return (ICommand)GetValue(CloseCommandProperty); } set { SetValue(CloseCommandProperty, value); } } /// /// Handles changes to the CloseCommand property. /// private static void OnCloseCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnCloseCommandChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the CloseCommand property. /// protected virtual void OnCloseCommandChanged(DependencyPropertyChangedEventArgs e) { } /// /// Coerces the CloseCommand value. /// private static object CoerceCloseCommandValue(DependencyObject d, object value) { return value; } private bool CanExecuteCloseCommand(object parameter) { #if DEBUG if( LayoutElement != null ) System.Diagnostics.Trace.WriteLine( string.Format( "CanExecuteCloseCommand({0}) = {1}", LayoutElement.Title, LayoutElement.CanClose ) ); #endif return LayoutElement != null && LayoutElement.CanClose; } private void ExecuteCloseCommand(object parameter) { Close(); } protected abstract void Close(); #endregion #region FloatCommand /// /// FloatCommand Dependency Property /// public static readonly DependencyProperty FloatCommandProperty = DependencyProperty.Register("FloatCommand", typeof(ICommand), typeof(LayoutItem), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnFloatCommandChanged), new CoerceValueCallback(CoerceFloatCommandValue))); /// /// Gets or sets the FloatCommand property. This dependency property /// indicates the command to execute when user click the float button. /// /// By default this command move the anchorable inside new floating window. public ICommand FloatCommand { get { return (ICommand)GetValue(FloatCommandProperty); } set { SetValue(FloatCommandProperty, value); } } /// /// Handles changes to the FloatCommand property. /// private static void OnFloatCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnFloatCommandChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the FloatCommand property. /// protected virtual void OnFloatCommandChanged(DependencyPropertyChangedEventArgs e) { } /// /// Coerces the FloatCommand value. /// private static object CoerceFloatCommandValue(DependencyObject d, object value) { return value; } private bool CanExecuteFloatCommand(object anchorable) { return LayoutElement != null && LayoutElement.CanFloat && LayoutElement.FindParent() == null; } private void ExecuteFloatCommand(object parameter) { LayoutElement.Root.Manager._ExecuteFloatCommand(LayoutElement); } protected virtual void Float() { } #endregion #region DockAsDocumentCommand /// /// DockAsDocumentCommand Dependency Property /// public static readonly DependencyProperty DockAsDocumentCommandProperty = DependencyProperty.Register("DockAsDocumentCommand", typeof(ICommand), typeof(LayoutItem), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnDockAsDocumentCommandChanged), new CoerceValueCallback(CoerceDockAsDocumentCommandValue))); /// /// Gets or sets the DockAsDocumentCommand property. This dependency property /// indicates the command to execute when user click the DockAsDocument button. /// /// By default this command move the anchorable inside the last focused document pane. public ICommand DockAsDocumentCommand { get { return (ICommand)GetValue(DockAsDocumentCommandProperty); } set { SetValue(DockAsDocumentCommandProperty, value); } } /// /// Handles changes to the DockAsDocumentCommand property. /// private static void OnDockAsDocumentCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnDockAsDocumentCommandChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the DockAsDocumentCommand property. /// protected virtual void OnDockAsDocumentCommandChanged(DependencyPropertyChangedEventArgs e) { } /// /// Coerces the DockAsDocumentCommand value. /// private static object CoerceDockAsDocumentCommandValue(DependencyObject d, object value) { return value; } private bool CanExecuteDockAsDocumentCommand(object parameter) { return LayoutElement != null && LayoutElement.FindParent() == null; } private void ExecuteDockAsDocumentCommand(object parameter) { LayoutElement.Root.Manager._ExecuteDockAsDocumentCommand(LayoutElement); } #endregion #region CloseAllButThisCommand /// /// CloseAllButThisCommand Dependency Property /// public static readonly DependencyProperty CloseAllButThisCommandProperty = DependencyProperty.Register("CloseAllButThisCommand", typeof(ICommand), typeof(LayoutItem), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnCloseAllButThisCommandChanged), new CoerceValueCallback(CoerceCloseAllButThisCommandValue))); /// /// Gets or sets the CloseAllButThisCommand property. This dependency property /// indicates the 'Close All But This' command. /// public ICommand CloseAllButThisCommand { get { return (ICommand)GetValue(CloseAllButThisCommandProperty); } set { SetValue(CloseAllButThisCommandProperty, value); } } /// /// Handles changes to the CloseAllButThisCommand property. /// private static void OnCloseAllButThisCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnCloseAllButThisCommandChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the CloseAllButThisCommand property. /// protected virtual void OnCloseAllButThisCommandChanged(DependencyPropertyChangedEventArgs e) { } /// /// Coerces the CloseAllButThisCommand value. /// private static object CoerceCloseAllButThisCommandValue(DependencyObject d, object value) { return value; } private bool CanExecuteCloseAllButThisCommand(object parameter) { if (LayoutElement == null) return false; var root = LayoutElement.Root; if (root == null) return false; return LayoutElement.Root.Manager.Layout. Descendents().OfType().Where(d => d != LayoutElement && (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)).Any(); } private void ExecuteCloseAllButThisCommand(object parameter) { LayoutElement.Root.Manager._ExecuteCloseAllButThisCommand(LayoutElement); } #endregion #region ActivateCommand /// /// ActivateCommand Dependency Property /// public static readonly DependencyProperty ActivateCommandProperty = DependencyProperty.Register("ActivateCommand", typeof(ICommand), typeof(LayoutItem), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnActivateCommandChanged), new CoerceValueCallback(CoerceActivateCommandValue))); /// /// Gets or sets the ActivateCommand property. This dependency property /// indicates the command to execute when user wants to activate a content (either a Document or an Anchorable). /// public ICommand ActivateCommand { get { return (ICommand)GetValue(ActivateCommandProperty); } set { SetValue(ActivateCommandProperty, value); } } /// /// Handles changes to the ActivateCommand property. /// private static void OnActivateCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnActivateCommandChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the ActivateCommand property. /// protected virtual void OnActivateCommandChanged(DependencyPropertyChangedEventArgs e) { } /// /// Coerces the ActivateCommand value. /// private static object CoerceActivateCommandValue(DependencyObject d, object value) { return value; } private bool CanExecuteActivateCommand(object parameter) { return LayoutElement != null; } private void ExecuteActivateCommand(object parameter) { LayoutElement.Root.Manager._ExecuteContentActivateCommand(LayoutElement); } #endregion #region NewVerticalTabGroupCommand /// /// NewVerticalTabGroupCommand Dependency Property /// public static readonly DependencyProperty NewVerticalTabGroupCommandProperty = DependencyProperty.Register("NewVerticalTabGroupCommand", typeof(ICommand), typeof(LayoutItem), new FrameworkPropertyMetadata((ICommand)null, new PropertyChangedCallback(OnNewVerticalTabGroupCommandChanged))); /// /// Gets or sets the NewVerticalTabGroupCommand property. This dependency property /// indicates the new vertical tab group command. /// public ICommand NewVerticalTabGroupCommand { get { return (ICommand)GetValue(NewVerticalTabGroupCommandProperty); } set { SetValue(NewVerticalTabGroupCommandProperty, value); } } /// /// Handles changes to the NewVerticalTabGroupCommand property. /// private static void OnNewVerticalTabGroupCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnNewVerticalTabGroupCommandChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the NewVerticalTabGroupCommand property. /// protected virtual void OnNewVerticalTabGroupCommandChanged(DependencyPropertyChangedEventArgs e) { } private bool CanExecuteNewVerticalTabGroupCommand(object parameter) { if (LayoutElement == null) return false; var parentDocumentGroup = LayoutElement.FindParent(); var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane; return ((parentDocumentGroup == null || parentDocumentGroup.ChildrenCount == 1 || parentDocumentGroup.Root.Manager.AllowMixedOrientation || parentDocumentGroup.Orientation == System.Windows.Controls.Orientation.Horizontal) && parentDocumentPane != null && parentDocumentPane.ChildrenCount > 1); } private void ExecuteNewVerticalTabGroupCommand(object parameter) { var layoutElement = LayoutElement; var parentDocumentGroup = layoutElement.FindParent(); var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane; if (parentDocumentGroup == null) { var grandParent = parentDocumentPane.Parent as ILayoutContainer; parentDocumentGroup = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Horizontal }; grandParent.ReplaceChild(parentDocumentPane, parentDocumentGroup); parentDocumentGroup.Children.Add(parentDocumentPane); } parentDocumentGroup.Orientation = System.Windows.Controls.Orientation.Horizontal; int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane); parentDocumentGroup.InsertChildAt(indexOfParentPane + 1, new LayoutDocumentPane(layoutElement)); layoutElement.IsActive = true; layoutElement.Root.CollectGarbage(); } #endregion #region NewHorizontalTabGroupCommand /// /// NewHorizontalTabGroupCommand Dependency Property /// public static readonly DependencyProperty NewHorizontalTabGroupCommandProperty = DependencyProperty.Register("NewHorizontalTabGroupCommand", typeof(ICommand), typeof(LayoutItem), new FrameworkPropertyMetadata((ICommand)null, new PropertyChangedCallback(OnNewHorizontalTabGroupCommandChanged))); /// /// Gets or sets the NewHorizontalTabGroupCommand property. This dependency property /// indicates the new horizontal tab group command. /// public ICommand NewHorizontalTabGroupCommand { get { return (ICommand)GetValue(NewHorizontalTabGroupCommandProperty); } set { SetValue(NewHorizontalTabGroupCommandProperty, value); } } /// /// Handles changes to the NewHorizontalTabGroupCommand property. /// private static void OnNewHorizontalTabGroupCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnNewHorizontalTabGroupCommandChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the NewHorizontalTabGroupCommand property. /// protected virtual void OnNewHorizontalTabGroupCommandChanged(DependencyPropertyChangedEventArgs e) { } private bool CanExecuteNewHorizontalTabGroupCommand(object parameter) { if (LayoutElement == null) return false; var parentDocumentGroup = LayoutElement.FindParent(); var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane; return ((parentDocumentGroup == null || parentDocumentGroup.ChildrenCount == 1 || parentDocumentGroup.Root.Manager.AllowMixedOrientation || parentDocumentGroup.Orientation == System.Windows.Controls.Orientation.Vertical) && parentDocumentPane != null && parentDocumentPane.ChildrenCount > 1); } private void ExecuteNewHorizontalTabGroupCommand(object parameter) { var layoutElement = LayoutElement; var parentDocumentGroup = layoutElement.FindParent(); var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane; if (parentDocumentGroup == null) { var grandParent = parentDocumentPane.Parent as ILayoutContainer; parentDocumentGroup = new LayoutDocumentPaneGroup() { Orientation = System.Windows.Controls.Orientation.Vertical }; grandParent.ReplaceChild(parentDocumentPane, parentDocumentGroup); parentDocumentGroup.Children.Add(parentDocumentPane); } parentDocumentGroup.Orientation = System.Windows.Controls.Orientation.Vertical; int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane); parentDocumentGroup.InsertChildAt(indexOfParentPane + 1, new LayoutDocumentPane(layoutElement)); layoutElement.IsActive = true; layoutElement.Root.CollectGarbage(); } #endregion #region MoveToNextTabGroupCommand /// /// MoveToNextTabGroupCommand Dependency Property /// public static readonly DependencyProperty MoveToNextTabGroupCommandProperty = DependencyProperty.Register("MoveToNextTabGroupCommand", typeof(ICommand), typeof(LayoutItem), new FrameworkPropertyMetadata((ICommand)null, new PropertyChangedCallback(OnMoveToNextTabGroupCommandChanged))); /// /// Gets or sets the MoveToNextTabGroupCommand property. This dependency property /// indicates move to next tab group command. /// public ICommand MoveToNextTabGroupCommand { get { return (ICommand)GetValue(MoveToNextTabGroupCommandProperty); } set { SetValue(MoveToNextTabGroupCommandProperty, value); } } /// /// Handles changes to the MoveToNextTabGroupCommand property. /// private static void OnMoveToNextTabGroupCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnMoveToNextTabGroupCommandChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the MoveToNextTabGroupCommand property. /// protected virtual void OnMoveToNextTabGroupCommandChanged(DependencyPropertyChangedEventArgs e) { } private bool CanExecuteMoveToNextTabGroupCommand(object parameter) { if (LayoutElement == null) return false; var parentDocumentGroup = LayoutElement.FindParent(); var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane; return (parentDocumentGroup != null && parentDocumentPane != null && parentDocumentGroup.ChildrenCount > 1 && parentDocumentGroup.IndexOfChild(parentDocumentPane) < parentDocumentGroup.ChildrenCount - 1 && parentDocumentGroup.Children[parentDocumentGroup.IndexOfChild(parentDocumentPane) + 1] is LayoutDocumentPane); } private void ExecuteMoveToNextTabGroupCommand(object parameter) { var layoutElement = LayoutElement; var parentDocumentGroup = layoutElement.FindParent(); var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane; int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane); var nextDocumentPane = parentDocumentGroup.Children[indexOfParentPane + 1] as LayoutDocumentPane; nextDocumentPane.InsertChildAt(0, layoutElement); layoutElement.IsActive = true; layoutElement.Root.CollectGarbage(); } #endregion #region MoveToPreviousTabGroupCommand /// /// MoveToPreviousTabGroupCommand Dependency Property /// public static readonly DependencyProperty MoveToPreviousTabGroupCommandProperty = DependencyProperty.Register("MoveToPreviousTabGroupCommand", typeof(ICommand), typeof(LayoutItem), new FrameworkPropertyMetadata((ICommand)null, new PropertyChangedCallback(OnMoveToPreviousTabGroupCommandChanged))); /// /// Gets or sets the MoveToPreviousTabGroupCommand property. This dependency property /// indicates move to rpevious tab group command. /// public ICommand MoveToPreviousTabGroupCommand { get { return (ICommand)GetValue(MoveToPreviousTabGroupCommandProperty); } set { SetValue(MoveToPreviousTabGroupCommandProperty, value); } } /// /// Handles changes to the MoveToPreviousTabGroupCommand property. /// private static void OnMoveToPreviousTabGroupCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((LayoutItem)d).OnMoveToPreviousTabGroupCommandChanged(e); } /// /// Provides derived classes an opportunity to handle changes to the MoveToPreviousTabGroupCommand property. /// protected virtual void OnMoveToPreviousTabGroupCommandChanged(DependencyPropertyChangedEventArgs e) { } private bool CanExecuteMoveToPreviousTabGroupCommand(object parameter) { if (LayoutElement == null) return false; var parentDocumentGroup = LayoutElement.FindParent(); var parentDocumentPane = LayoutElement.Parent as LayoutDocumentPane; return (parentDocumentGroup != null && parentDocumentPane != null && parentDocumentGroup.ChildrenCount > 1 && parentDocumentGroup.IndexOfChild(parentDocumentPane) > 0 && parentDocumentGroup.Children[parentDocumentGroup.IndexOfChild(parentDocumentPane) - 1] is LayoutDocumentPane); } private void ExecuteMoveToPreviousTabGroupCommand(object parameter) { var layoutElement = LayoutElement; var parentDocumentGroup = layoutElement.FindParent(); var parentDocumentPane = layoutElement.Parent as LayoutDocumentPane; int indexOfParentPane = parentDocumentGroup.IndexOfChild(parentDocumentPane); var nextDocumentPane = parentDocumentGroup.Children[indexOfParentPane - 1] as LayoutDocumentPane; nextDocumentPane.InsertChildAt(0, layoutElement); layoutElement.IsActive = true; layoutElement.Root.CollectGarbage(); } #endregion } }