| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689 |
- /*************************************************************************************
- 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 System.Collections.ObjectModel;
- using System.Windows.Markup;
- using System.Xml.Serialization;
- using Standard;
- namespace Xceed.Wpf.AvalonDock.Layout
- {
- [ContentProperty("RootPanel")]
- [Serializable]
- public class LayoutRoot : LayoutElement, ILayoutContainer, ILayoutRoot
- {
- public LayoutRoot()
- {
- RightSide = new LayoutAnchorSide();
- LeftSide = new LayoutAnchorSide();
- TopSide = new LayoutAnchorSide();
- BottomSide = new LayoutAnchorSide();
- RootPanel = new LayoutPanel(new LayoutDocumentPane());
- }
- #region RootPanel
- private LayoutPanel _rootPanel;
- public LayoutPanel RootPanel
- {
- get { return _rootPanel; }
- set
- {
- if (_rootPanel != value)
- {
- RaisePropertyChanging("RootPanel");
- if (_rootPanel != null &&
- _rootPanel.Parent == this)
- _rootPanel.Parent = null;
- _rootPanel = value;
- if (_rootPanel == null)
- _rootPanel = new LayoutPanel(new LayoutDocumentPane());
- if (_rootPanel != null)
- _rootPanel.Parent = this;
- RaisePropertyChanged("RootPanel");
- }
- }
- }
- #endregion
- #region TopSide
- private LayoutAnchorSide _topSide = null;
- public LayoutAnchorSide TopSide
- {
- get { return _topSide; }
- set
- {
- if (_topSide != value)
- {
- RaisePropertyChanging("TopSide");
- _topSide = value;
- if (_topSide != null)
- _topSide.Parent = this;
- RaisePropertyChanged("TopSide");
- }
- }
- }
- #endregion
- #region RightSide
- private LayoutAnchorSide _rightSide;
- public LayoutAnchorSide RightSide
- {
- get { return _rightSide; }
- set
- {
- if (_rightSide != value)
- {
- RaisePropertyChanging("RightSide");
- _rightSide = value;
- if (_rightSide != null)
- _rightSide.Parent = this;
- RaisePropertyChanged("RightSide");
- }
- }
- }
- #endregion
- #region LeftSide
- private LayoutAnchorSide _leftSide = null;
- public LayoutAnchorSide LeftSide
- {
- get { return _leftSide; }
- set
- {
- if (_leftSide != value)
- {
- RaisePropertyChanging("LeftSide");
- _leftSide = value;
- if (_leftSide != null)
- _leftSide.Parent = this;
- RaisePropertyChanged("LeftSide");
- }
- }
- }
- #endregion
- #region BottomSide
- private LayoutAnchorSide _bottomSide = null;
- public LayoutAnchorSide BottomSide
- {
- get { return _bottomSide; }
- set
- {
- if (_bottomSide != value)
- {
- RaisePropertyChanging("BottomSide");
- _bottomSide = value;
- if (_bottomSide != null)
- _bottomSide.Parent = this;
- RaisePropertyChanged("BottomSide");
- }
- }
- }
- #endregion
- #region FloatingWindows
- ObservableCollection<LayoutFloatingWindow> _floatingWindows = null;
- public ObservableCollection<LayoutFloatingWindow> FloatingWindows
- {
- get
- {
- if (_floatingWindows == null)
- {
- _floatingWindows = new ObservableCollection<LayoutFloatingWindow>();
- _floatingWindows.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_floatingWindows_CollectionChanged);
- }
- return _floatingWindows;
- }
- }
- void _floatingWindows_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
- {
- if (e.OldItems != null && (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove ||
- e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace))
- {
- foreach (LayoutFloatingWindow element in e.OldItems)
- {
- if (element.Parent == this)
- element.Parent = null;
- }
- }
- if (e.NewItems != null && (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add ||
- e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace))
- {
- foreach (LayoutFloatingWindow element in e.NewItems)
- element.Parent = this;
- }
- }
- #endregion
- #region HiddenAnchorables
- ObservableCollection<LayoutAnchorable> _hiddenAnchorables = null;
- public ObservableCollection<LayoutAnchorable> Hidden
- {
- get
- {
- if (_hiddenAnchorables == null)
- {
- _hiddenAnchorables = new ObservableCollection<LayoutAnchorable>();
- _hiddenAnchorables.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(_hiddenAnchorables_CollectionChanged);
- }
- return _hiddenAnchorables;
- }
- }
- void _hiddenAnchorables_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
- {
- if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove ||
- e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)
- {
- if (e.OldItems != null)
- {
- foreach (LayoutAnchorable element in e.OldItems)
- {
- if (element.Parent == this)
- element.Parent = null;
- }
- }
- }
- if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add ||
- e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Replace)
- {
- if (e.NewItems != null)
- {
- foreach (LayoutAnchorable element in e.NewItems)
- {
- if (element.Parent != this)
- {
- if (element.Parent != null)
- element.Parent.RemoveChild(element);
- element.Parent = this;
- }
- }
- }
- }
- }
- #endregion
- #region Children
- public IEnumerable<ILayoutElement> Children
- {
- get
- {
- if (RootPanel != null)
- yield return RootPanel;
- if (_floatingWindows != null)
- {
- foreach (var floatingWindow in _floatingWindows)
- yield return floatingWindow;
- }
- if (TopSide != null)
- yield return TopSide;
- if (RightSide != null)
- yield return RightSide;
- if (BottomSide != null)
- yield return BottomSide;
- if (LeftSide != null)
- yield return LeftSide;
- if (_hiddenAnchorables != null)
- {
- foreach (var hiddenAnchorable in _hiddenAnchorables)
- yield return hiddenAnchorable;
- }
- }
- }
- public void RemoveChild(ILayoutElement element)
- {
- if (element == RootPanel)
- RootPanel = null;
- else if (_floatingWindows != null && _floatingWindows.Contains(element))
- _floatingWindows.Remove(element as LayoutFloatingWindow);
- else if (_hiddenAnchorables != null && _hiddenAnchorables.Contains(element))
- _hiddenAnchorables.Remove(element as LayoutAnchorable);
- else if (element == TopSide)
- TopSide = null;
- else if (element == RightSide)
- RightSide = null;
- else if (element == BottomSide)
- BottomSide = null;
- else if (element == LeftSide)
- LeftSide = null;
- }
- public void ReplaceChild(ILayoutElement oldElement, ILayoutElement newElement)
- {
- if (oldElement == RootPanel)
- RootPanel = (LayoutPanel)newElement;
- else if (_floatingWindows != null && _floatingWindows.Contains(oldElement))
- {
- int index = _floatingWindows.IndexOf(oldElement as LayoutFloatingWindow);
- _floatingWindows.Remove(oldElement as LayoutFloatingWindow);
- _floatingWindows.Insert(index, newElement as LayoutFloatingWindow);
- }
- else if (_hiddenAnchorables != null && _hiddenAnchorables.Contains(oldElement))
- {
- int index = _hiddenAnchorables.IndexOf(oldElement as LayoutAnchorable);
- _hiddenAnchorables.Remove(oldElement as LayoutAnchorable);
- _hiddenAnchorables.Insert(index, newElement as LayoutAnchorable);
- }
- else if (oldElement == TopSide)
- TopSide = (LayoutAnchorSide)newElement;
- else if (oldElement == RightSide)
- RightSide = (LayoutAnchorSide)newElement;
- else if (oldElement == BottomSide)
- BottomSide = (LayoutAnchorSide)newElement;
- else if (oldElement == LeftSide)
- LeftSide = (LayoutAnchorSide)newElement;
- }
- public int ChildrenCount
- {
- get
- {
- return 5 +
- (_floatingWindows != null ? _floatingWindows.Count : 0) +
- (_hiddenAnchorables != null ? _hiddenAnchorables.Count : 0);
- }
- }
- #endregion
- #region ActiveContent
- [field:NonSerialized]
- private WeakReference _activeContent = null;
- private bool _activeContentSet = false;
- [XmlIgnore]
- public LayoutContent ActiveContent
- {
- get { return _activeContent.GetValueOrDefault<LayoutContent>(); }
- set
- {
- var currentValue = ActiveContent;
- if (currentValue != value)
- {
- InternalSetActiveContent(currentValue, value);
- }
- }
- }
- void InternalSetActiveContent(LayoutContent currentValue, LayoutContent newActiveContent)
- {
- RaisePropertyChanging("ActiveContent");
- if (currentValue != null)
- currentValue.IsActive = false;
- _activeContent = new WeakReference(newActiveContent);
- currentValue = ActiveContent;
- if (currentValue != null)
- currentValue.IsActive = true;
- RaisePropertyChanged("ActiveContent");
- _activeContentSet = currentValue != null;
- if (currentValue != null)
- {
- if (currentValue.Parent is LayoutDocumentPane || currentValue is LayoutDocument)
- LastFocusedDocument = currentValue;
- }
- else
- LastFocusedDocument = null;
- }
- void UpdateActiveContentProperty()
- {
- var activeContent = ActiveContent;
- if (_activeContentSet && (activeContent == null || activeContent.Root != this))
- {
- _activeContentSet = false;
- InternalSetActiveContent(activeContent, null);
- }
- }
- #endregion
- #region LastFocusedDocument
- [field: NonSerialized]
- private WeakReference _lastFocusedDocument = null;
- [field: NonSerialized]
- private bool _lastFocusedDocumentSet = false;
- [XmlIgnore]
- public LayoutContent LastFocusedDocument
- {
- get { return _lastFocusedDocument.GetValueOrDefault<LayoutContent>(); }
- private set
- {
- var currentValue = LastFocusedDocument;
- if (currentValue != value)
- {
- RaisePropertyChanging("LastFocusedDocument");
- if (currentValue != null)
- currentValue.IsLastFocusedDocument = false;
- _lastFocusedDocument = new WeakReference(value);
- currentValue = LastFocusedDocument;
- if (currentValue != null)
- currentValue.IsLastFocusedDocument = true;
- _lastFocusedDocumentSet = currentValue != null;
- RaisePropertyChanged("LastFocusedDocument");
- }
- }
- }
- #endregion
- #region Manager
- [NonSerialized]
- private DockingManager _manager = null;
- [XmlIgnore]
- public DockingManager Manager
- {
- get { return _manager; }
- internal set
- {
- if (_manager != value)
- {
- RaisePropertyChanging("Manager");
- _manager = value;
- RaisePropertyChanged("Manager");
- }
- }
- }
- #endregion
- #region CollectGarbage
- /// <summary>
- /// Removes any empty container not directly referenced by other layout items
- /// </summary>
- public void CollectGarbage()
- {
- bool exitFlag = true;
- #region collect empty panes
- do
- {
- exitFlag = true;
- //for each content that references via PreviousContainer a disconnected Pane set the property to null
- foreach (var content in this.Descendents().OfType<ILayoutPreviousContainer>().Where(c => c.PreviousContainer != null &&
- (c.PreviousContainer.Parent == null || c.PreviousContainer.Parent.Root != this)))
- {
- content.PreviousContainer = null;
- }
- //for each pane that is empty
- foreach (var emptyPane in this.Descendents().OfType<ILayoutPane>().Where(p => p.ChildrenCount == 0))
- {
- //...set null any reference coming from contents not yet hosted in a floating window
- foreach (var contentReferencingEmptyPane in this.Descendents().OfType<LayoutContent>()
- .Where(c => ((ILayoutPreviousContainer)c).PreviousContainer == emptyPane && !c.IsFloating))
- {
- if (contentReferencingEmptyPane is LayoutAnchorable &&
- !((LayoutAnchorable)contentReferencingEmptyPane).IsVisible)
- continue;
- ((ILayoutPreviousContainer)contentReferencingEmptyPane).PreviousContainer = null;
- contentReferencingEmptyPane.PreviousContainerIndex = -1;
- }
- //...if this pane is the only documentpane present in the layout than skip it
- if (emptyPane is LayoutDocumentPane &&
- this.Descendents().OfType<LayoutDocumentPane>().Count(c => c != emptyPane) == 0)
- continue;
- //...if this empty panes is not referenced by anyone, than removes it from its parent container
- if (!this.Descendents().OfType<ILayoutPreviousContainer>().Any(c => c.PreviousContainer == emptyPane))
- {
- var parentGroup = emptyPane.Parent as ILayoutContainer;
- parentGroup.RemoveChild(emptyPane);
- exitFlag = false;
- break;
- }
- }
- if (!exitFlag)
- {
- //removes any empty anchorable pane group
- foreach (var emptyPaneGroup in this.Descendents().OfType<LayoutAnchorablePaneGroup>().Where(p => p.ChildrenCount == 0))
- {
- var parentGroup = emptyPaneGroup.Parent as ILayoutContainer;
- parentGroup.RemoveChild(emptyPaneGroup);
- exitFlag = false;
- break;
- }
- }
- if (!exitFlag)
- {
- //removes any empty layout panel
- foreach (var emptyPaneGroup in this.Descendents().OfType<LayoutPanel>().Where(p => p.ChildrenCount == 0))
- {
- var parentGroup = emptyPaneGroup.Parent as ILayoutContainer;
- parentGroup.RemoveChild(emptyPaneGroup);
- exitFlag = false;
- break;
- }
- }
- if (!exitFlag)
- {
- //removes any empty floating window
- foreach (var emptyPaneGroup in this.Descendents().OfType<LayoutFloatingWindow>().Where(p => p.ChildrenCount == 0))
- {
- var parentGroup = emptyPaneGroup.Parent as ILayoutContainer;
- parentGroup.RemoveChild(emptyPaneGroup);
- exitFlag = false;
- break;
- }
- }
- if (!exitFlag)
- {
- //removes any empty anchor group
- foreach (var emptyPaneGroup in this.Descendents().OfType<LayoutAnchorGroup>().Where(p => p.ChildrenCount == 0))
- {
- var parentGroup = emptyPaneGroup.Parent as ILayoutContainer;
- parentGroup.RemoveChild(emptyPaneGroup);
- exitFlag = false;
- break;
- }
- }
- }
- while (!exitFlag);
- #endregion
- #region collapse single child anchorable pane groups
- do
- {
- exitFlag = true;
- //for each pane that is empty
- foreach (var paneGroupToCollapse in this.Descendents().OfType<LayoutAnchorablePaneGroup>().Where(p => p.ChildrenCount == 1 && p.Children[0] is LayoutAnchorablePaneGroup).ToArray())
- {
- var singleChild = paneGroupToCollapse.Children[0] as LayoutAnchorablePaneGroup;
- paneGroupToCollapse.Orientation = singleChild.Orientation;
- paneGroupToCollapse.RemoveChild(singleChild);
- while (singleChild.ChildrenCount > 0)
- {
- paneGroupToCollapse.InsertChildAt(
- paneGroupToCollapse.ChildrenCount, singleChild.Children[0]);
- }
- exitFlag = false;
- break;
- }
- }
- while (!exitFlag);
- #endregion
- #region collapse single child document pane groups
- do
- {
- exitFlag = true;
- //for each pane that is empty
- foreach (var paneGroupToCollapse in this.Descendents().OfType<LayoutDocumentPaneGroup>().Where(p => p.ChildrenCount == 1 && p.Children[0] is LayoutDocumentPaneGroup).ToArray())
- {
- var singleChild = paneGroupToCollapse.Children[0] as LayoutDocumentPaneGroup;
- paneGroupToCollapse.Orientation = singleChild.Orientation;
- paneGroupToCollapse.RemoveChild(singleChild);
- while (singleChild.ChildrenCount > 0)
- {
- paneGroupToCollapse.InsertChildAt(
- paneGroupToCollapse.ChildrenCount, singleChild.Children[0]);
- }
- exitFlag = false;
- break;
- }
- }
- while (!exitFlag);
- #endregion
- #region collapse single child layout panels
- do
- {
- exitFlag = true;
- //for each panel that has only one child
- foreach (var panelToCollapse in this.Descendents().OfType<LayoutPanel>().Where(p => p.ChildrenCount == 1 && p.Children[0] is LayoutPanel).ToArray())
- {
- var singleChild = panelToCollapse.Children[0] as LayoutPanel;
- panelToCollapse.Orientation = singleChild.Orientation;
- panelToCollapse.RemoveChild(singleChild);
- while (singleChild.ChildrenCount > 0)
- {
- panelToCollapse.InsertChildAt(
- panelToCollapse.ChildrenCount, singleChild.Children[0]);
- }
- exitFlag = false;
- break;
- }
- }
- while (!exitFlag);
- #endregion
- #region Update ActiveContent and LastFocusedDocument properties
- UpdateActiveContentProperty();
- #endregion
- #if DEBUG
- System.Diagnostics.Debug.Assert(
- !this.Descendents().OfType<LayoutAnchorablePane>().Any(a => a.ChildrenCount == 0 && a.IsVisible));
- #if TRACE
- RootPanel.ConsoleDump(4);
- #endif
- #endif
- }
- #endregion
- public event EventHandler Updated;
- internal void FireLayoutUpdated()
- {
- if (Updated != null)
- Updated(this, EventArgs.Empty);
- }
- #region LayoutElement Added/Removed events
- internal void OnLayoutElementAdded(LayoutElement element)
- {
- if (ElementAdded != null)
- ElementAdded(this, new LayoutElementEventArgs(element));
- }
- public event EventHandler<LayoutElementEventArgs> ElementAdded;
- internal void OnLayoutElementRemoved(LayoutElement element)
- {
- if (element.Descendents().OfType<LayoutContent>().Any(c => c == LastFocusedDocument))
- LastFocusedDocument = null;
- if (element.Descendents().OfType<LayoutContent>().Any(c => c == ActiveContent))
- ActiveContent = null;
- if (ElementRemoved != null)
- ElementRemoved(this, new LayoutElementEventArgs(element));
- }
- public event EventHandler<LayoutElementEventArgs> ElementRemoved;
- #endregion
- #if TRACE
- public override void ConsoleDump(int tab)
- {
- System.Diagnostics.Trace.Write( new string( ' ', tab * 4 ) );
- System.Diagnostics.Trace.WriteLine( "RootPanel()" );
- RootPanel.ConsoleDump(tab + 1);
- System.Diagnostics.Trace.Write( new string( ' ', tab * 4 ) );
- System.Diagnostics.Trace.WriteLine( "FloatingWindows()" );
- foreach (LayoutFloatingWindow fw in FloatingWindows)
- fw.ConsoleDump(tab + 1);
- System.Diagnostics.Trace.Write( new string( ' ', tab * 4 ) );
- System.Diagnostics.Trace.WriteLine( "Hidden()" );
- foreach (LayoutAnchorable hidden in Hidden)
- hidden.ConsoleDump(tab + 1);
- }
- #endif
- }
- }
|