diff --git a/AvalonDockIcon.design b/AvalonDockIcon.design new file mode 100644 index 00000000..058d74aa Binary files /dev/null and b/AvalonDockIcon.design differ diff --git a/source/.editorconfig b/source/.editorconfig new file mode 100644 index 00000000..16da0401 --- /dev/null +++ b/source/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# IDE0055: 修正格式 +dotnet_diagnostic.IDE0055.severity = none diff --git a/source/Components/AvalonDock.Themes.Aero/Properties/AssemblyInfo.cs b/source/Components/AvalonDock.Themes.Aero/Properties/AssemblyInfo.cs index 979eadc9..cd5334c6 100644 --- a/source/Components/AvalonDock.Themes.Aero/Properties/AssemblyInfo.cs +++ b/source/Components/AvalonDock.Themes.Aero/Properties/AssemblyInfo.cs @@ -38,4 +38,6 @@ This program is provided to you under the terms of the Microsoft Public )] -[assembly: XmlnsDefinition("https://github.com/Dirkster99/AvalonDock", "AvalonDock.Themes")] \ No newline at end of file +[assembly: XmlnsDefinition("https://github.com/Dirkster99/AvalonDock", "AvalonDock.Themes")] +[assembly: XmlnsPrefix("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "AvalonDock.Themes")] +[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "AvalonDock.Themes")] \ No newline at end of file diff --git a/source/Components/AvalonDock.Themes.Aero/Theme.xaml b/source/Components/AvalonDock.Themes.Aero/Theme.xaml index d9bf9ada..da765898 100644 --- a/source/Components/AvalonDock.Themes.Aero/Theme.xaml +++ b/source/Components/AvalonDock.Themes.Aero/Theme.xaml @@ -1,1548 +1,1538 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/Components/AvalonDock.Themes.Expression/Properties/AssemblyInfo.cs b/source/Components/AvalonDock.Themes.Expression/Properties/AssemblyInfo.cs index 3c724777..ec11e47e 100644 --- a/source/Components/AvalonDock.Themes.Expression/Properties/AssemblyInfo.cs +++ b/source/Components/AvalonDock.Themes.Expression/Properties/AssemblyInfo.cs @@ -39,3 +39,5 @@ This program is provided to you under the terms of the Microsoft Public [assembly: XmlnsDefinition("https://github.com/Dirkster99/AvalonDock", "AvalonDock.Themes")] +[assembly: XmlnsPrefix("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "AvalonDock.Themes")] +[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "AvalonDock.Themes")] diff --git a/source/Components/AvalonDock.Themes.Expression/Theme.xaml b/source/Components/AvalonDock.Themes.Expression/Theme.xaml index 42199afb..35d9ea8d 100644 --- a/source/Components/AvalonDock.Themes.Expression/Theme.xaml +++ b/source/Components/AvalonDock.Themes.Expression/Theme.xaml @@ -1,1613 +1,1603 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/Components/AvalonDock.Themes.VS2013/DarkBrushs.xaml b/source/Components/AvalonDock.Themes.VS2013/DarkBrushs.xaml index 2711d9fc..383f246a 100644 --- a/source/Components/AvalonDock.Themes.VS2013/DarkBrushs.xaml +++ b/source/Components/AvalonDock.Themes.VS2013/DarkBrushs.xaml @@ -1,429 +1,429 @@  - - - + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:options="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" + xmlns:reskeys="clr-namespace:AvalonDock.Themes.VS2013.Themes"> + + + - - #1ba1e2 + + #FF007ACC - + - - - - + + + + - - - - + + + + - - - - + + + + - - + + - - - - - - - - - - + + + + + + + + + + - - - + + + - - - - - - - - + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - + + - - - - + + + + - - - + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - + + + + - - + + - - - + + + \ No newline at end of file diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockAnchorableBottom.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockAnchorableBottom.png deleted file mode 100644 index a786a61f..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockAnchorableBottom.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockAnchorableLeft.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockAnchorableLeft.png deleted file mode 100644 index 1499c434..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockAnchorableLeft.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockAnchorableRight.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockAnchorableRight.png deleted file mode 100644 index e6802ba3..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockAnchorableRight.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockAnchorableTop.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockAnchorableTop.png deleted file mode 100644 index cd79f578..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockAnchorableTop.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentAsAnchorableBottom.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentAsAnchorableBottom.png deleted file mode 100644 index 00436bba..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentAsAnchorableBottom.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentAsAnchorableLeft.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentAsAnchorableLeft.png deleted file mode 100644 index 6500b08c..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentAsAnchorableLeft.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentAsAnchorableRight.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentAsAnchorableRight.png deleted file mode 100644 index a71a8c50..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentAsAnchorableRight.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentAsAnchorableTop.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentAsAnchorableTop.png deleted file mode 100644 index 2ac77654..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentAsAnchorableTop.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentBottom.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentBottom.png deleted file mode 100644 index c5bed349..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentBottom.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentInside.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentInside.png deleted file mode 100644 index 038ac8b3..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentInside.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentLeft.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentLeft.png deleted file mode 100644 index d77a43f2..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentLeft.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentRight.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentRight.png deleted file mode 100644 index 83322201..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentRight.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentTop.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentTop.png deleted file mode 100644 index f8e075d9..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockDocumentTop.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockPaneEmpty.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockPaneEmpty.png deleted file mode 100644 index 8ad11767..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockPaneEmpty.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/DockPaneLargeEmpty.png b/source/Components/AvalonDock.Themes.VS2013/Images/DockPaneLargeEmpty.png deleted file mode 100644 index 8205a034..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/DockPaneLargeEmpty.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/HTabGroup.png b/source/Components/AvalonDock.Themes.VS2013/Images/HTabGroup.png deleted file mode 100644 index 4c50d26d..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/HTabGroup.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/Locked.png b/source/Components/AvalonDock.Themes.VS2013/Images/Locked.png deleted file mode 100644 index b8f6ced2..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/Locked.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinAutoHide.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinAutoHide.png deleted file mode 100644 index abefd96b..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinAutoHide.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinAutoHide_Black.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinAutoHide_Black.png deleted file mode 100644 index 87b66ced..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinAutoHide_Black.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinAutoHide_Dark.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinAutoHide_Dark.png deleted file mode 100644 index 470548dc..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinAutoHide_Dark.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinAutoHide_White.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinAutoHide_White.png deleted file mode 100644 index 3ef7f338..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinAutoHide_White.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinClose.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinClose.png deleted file mode 100644 index 132bdfaf..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinClose.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinClose_Black.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinClose_Black.png deleted file mode 100644 index abf709cb..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinClose_Black.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinClose_Dark.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinClose_Dark.png deleted file mode 100644 index 575e4fdb..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinClose_Dark.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinClose_White.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinClose_White.png deleted file mode 100644 index 662933b9..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinClose_White.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinDocMenu.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinDocMenu.png deleted file mode 100644 index 86db3070..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinDocMenu.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinDocMenu_Black.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinDocMenu_Black.png deleted file mode 100644 index be081925..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinDocMenu_Black.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinMaximize.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinMaximize.png deleted file mode 100644 index 79d8c2d0..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinMaximize.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinMaximize_Black.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinMaximize_Black.png deleted file mode 100644 index 42ae679a..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinMaximize_Black.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinMaximize_Dark.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinMaximize_Dark.png deleted file mode 100644 index e28e0607..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinMaximize_Dark.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinMenu.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinMenu.png deleted file mode 100644 index 653373ce..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinMenu.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinMenu_Black.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinMenu_Black.png deleted file mode 100644 index 31e2f102..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinMenu_Black.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinMenu_Dark.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinMenu_Dark.png deleted file mode 100644 index 25a47678..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinMenu_Dark.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinMenu_White.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinMenu_White.png deleted file mode 100644 index ffe5e0e8..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinMenu_White.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinRestore.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinRestore.png deleted file mode 100644 index 1bccead4..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinRestore.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinRestore_Black.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinRestore_Black.png deleted file mode 100644 index 7c7e0032..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinRestore_Black.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/PinRestore_Dark.png b/source/Components/AvalonDock.Themes.VS2013/Images/PinRestore_Dark.png deleted file mode 100644 index f3ebfe4c..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/PinRestore_Dark.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/Images/VTabGroup.png b/source/Components/AvalonDock.Themes.VS2013/Images/VTabGroup.png deleted file mode 100644 index c3f279f7..00000000 Binary files a/source/Components/AvalonDock.Themes.VS2013/Images/VTabGroup.png and /dev/null differ diff --git a/source/Components/AvalonDock.Themes.VS2013/OverlayButtons.xaml b/source/Components/AvalonDock.Themes.VS2013/OverlayButtons.xaml index 7c55a32f..523d5662 100644 --- a/source/Components/AvalonDock.Themes.VS2013/OverlayButtons.xaml +++ b/source/Components/AvalonDock.Themes.VS2013/OverlayButtons.xaml @@ -1,649 +1,582 @@  - - - - - 48 - 48 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:reskeys="clr-namespace:AvalonDock.Themes.VS2013.Themes" + xmlns:sys="clr-namespace:System;assembly=mscorlib"> + + + + + 40 + 40 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/Components/AvalonDock.Themes.VS2013/Properties/AssemblyInfo.cs b/source/Components/AvalonDock.Themes.VS2013/Properties/AssemblyInfo.cs index 3c724777..cd5334c6 100644 --- a/source/Components/AvalonDock.Themes.VS2013/Properties/AssemblyInfo.cs +++ b/source/Components/AvalonDock.Themes.VS2013/Properties/AssemblyInfo.cs @@ -39,3 +39,5 @@ This program is provided to you under the terms of the Microsoft Public [assembly: XmlnsDefinition("https://github.com/Dirkster99/AvalonDock", "AvalonDock.Themes")] +[assembly: XmlnsPrefix("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "AvalonDock.Themes")] +[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "AvalonDock.Themes")] \ No newline at end of file diff --git a/source/Components/AvalonDock.Themes.VS2013/Themes/Generic.xaml b/source/Components/AvalonDock.Themes.VS2013/Themes/Generic.xaml index 58db40d6..8fb1ed23 100644 --- a/source/Components/AvalonDock.Themes.VS2013/Themes/Generic.xaml +++ b/source/Components/AvalonDock.Themes.VS2013/Themes/Generic.xaml @@ -1,2368 +1,2287 @@  - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/Components/AvalonDock.Themes.VS2013/Themes/Icons/IconGeometry.xaml b/source/Components/AvalonDock.Themes.VS2013/Themes/Icons/IconGeometry.xaml new file mode 100644 index 00000000..ee5acde2 --- /dev/null +++ b/source/Components/AvalonDock.Themes.VS2013/Themes/Icons/IconGeometry.xaml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/Components/AvalonDock.Themes.VS2013/Themes/Menu/MenuItem.xaml b/source/Components/AvalonDock.Themes.VS2013/Themes/Menu/MenuItem.xaml index 5eea8be2..b9980c3d 100644 --- a/source/Components/AvalonDock.Themes.VS2013/Themes/Menu/MenuItem.xaml +++ b/source/Components/AvalonDock.Themes.VS2013/Themes/Menu/MenuItem.xaml @@ -1,108 +1,135 @@ - + - - + + M 0,5.1 L 1.7,5.2 L 3.4,7.1 L 8,0.4 L 9.2,0 L 3.3,10.8 Z - - + + - - - + + + - + - + - + - + - + - - + + VerticalAlignment="Center" + Data="M0,0 L0,8 L4,4 z" + Fill="{TemplateBinding Foreground}" /> - + - - - - + + + + - - + + - + - - + + - - - - + + + + - - - - - + + + + + - - + + + - - + + - - - + + + - + - + - + - - - + + + - + \ No newline at end of file diff --git a/source/Components/AvalonDock/Controls/DropDownControlArea.cs b/source/Components/AvalonDock/Controls/DropDownControlArea.cs index 5c1fc16d..ea310385 100644 --- a/source/Components/AvalonDock/Controls/DropDownControlArea.cs +++ b/source/Components/AvalonDock/Controls/DropDownControlArea.cs @@ -21,8 +21,8 @@ namespace AvalonDock.Controls /// /// The content is usually displayed via ContentPresenter binding in the theme definition. /// - /// - public class DropDownControlArea : UserControl + /// + public class DropDownControlArea : ContentControl { #region Properties diff --git a/source/Components/AvalonDock/Controls/LayoutAnchorableItem.cs b/source/Components/AvalonDock/Controls/LayoutAnchorableItem.cs index 70a0d2d4..e281aba9 100644 --- a/source/Components/AvalonDock/Controls/LayoutAnchorableItem.cs +++ b/source/Components/AvalonDock/Controls/LayoutAnchorableItem.cs @@ -16,287 +16,287 @@ This program is provided to you under the terms of the Microsoft Public namespace AvalonDock.Controls { - /// - /// - /// This is a wrapper for around the custom anchorable content view of . - /// Implements the - /// - /// All DPs implemented here can be bound in a corresponding style to control parameters - /// in dependency properties via binding in MVVM. - /// - /// - public class LayoutAnchorableItem : LayoutItem - { - #region fields - private LayoutAnchorable _anchorable; // The content of this item - private ICommand _defaultHideCommand; - private ICommand _defaultAutoHideCommand; - private ICommand _defaultDockCommand; - private ReentrantFlag _visibilityReentrantFlag = new ReentrantFlag(); - private ReentrantFlag _anchorableVisibilityReentrantFlag = new ReentrantFlag(); - #endregion fields - - #region Constructors - /// Class constructor - internal LayoutAnchorableItem() - { - } - #endregion Constructors - - #region Properties - - #region HideCommand - - /// dependency property. - public static readonly DependencyProperty HideCommandProperty = DependencyProperty.Register(nameof(HideCommand), typeof(ICommand), typeof(LayoutAnchorableItem), - new FrameworkPropertyMetadata(null, OnHideCommandChanged, CoerceHideCommandValue)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the command to execute when an anchorable is hidden. - /// - public ICommand HideCommand - { - get => (ICommand)GetValue(HideCommandProperty); - set => SetValue(HideCommandProperty, value); - } - - /// Handles changes to the property. - private static void OnHideCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((LayoutAnchorableItem)d).OnHideCommandChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnHideCommandChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// Coerces the value. - private static object CoerceHideCommandValue(DependencyObject d, object value) => value; - - private bool CanExecuteHideCommand(object parameter) => LayoutElement != null && _anchorable.CanHide; - - private void ExecuteHideCommand(object parameter) => _anchorable?.Root?.Manager?._ExecuteHideCommand(_anchorable); - - #endregion HideCommand - - #region AutoHideCommand - - /// dependency property. - public static readonly DependencyProperty AutoHideCommandProperty = DependencyProperty.Register(nameof(AutoHideCommand), typeof(ICommand), typeof(LayoutAnchorableItem), - new FrameworkPropertyMetadata(null, OnAutoHideCommandChanged, CoerceAutoHideCommandValue)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the command to execute when user click the auto hide button. - /// - /// By default this command toggles auto hide state for an anchorable. - public ICommand AutoHideCommand - { - get => (ICommand)GetValue(AutoHideCommandProperty); - set => SetValue(AutoHideCommandProperty, value); - } - - /// Handles changes to the property. - private static void OnAutoHideCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((LayoutAnchorableItem)d).OnAutoHideCommandChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnAutoHideCommandChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// Coerces the value. - private static object CoerceAutoHideCommandValue(DependencyObject d, object value) => value; - - private bool CanExecuteAutoHideCommand(object parameter) - { - if (LayoutElement == null) return false; - if (LayoutElement.FindParent() != null) return false;//is floating - return _anchorable.CanAutoHide; - } - - private void ExecuteAutoHideCommand(object parameter) => _anchorable?.Root?.Manager?._ExecuteAutoHideCommand(_anchorable); - - #endregion AutoHideCommand - - #region DockCommand - - /// dependency property. - public static readonly DependencyProperty DockCommandProperty = DependencyProperty.Register(nameof(DockCommand), typeof(ICommand), typeof(LayoutAnchorableItem), - new FrameworkPropertyMetadata(null, OnDockCommandChanged, CoerceDockCommandValue)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the command to execute when user click the Dock button. - /// - /// By default this command moves the anchorable inside the container pane which previously hosted the object. - public ICommand DockCommand - { - get => (ICommand)GetValue(DockCommandProperty); - set => SetValue(DockCommandProperty, value); - } - - /// Handles changes to the property. - private static void OnDockCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((LayoutAnchorableItem)d).OnDockCommandChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnDockCommandChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// Coerces the value. - private static object CoerceDockCommandValue(DependencyObject d, object value) => value; - - private bool CanExecuteDockCommand(object parameter) => LayoutElement?.FindParent() != null; - - private void ExecuteDockCommand(object parameter) => LayoutElement.Root.Manager._ExecuteDockCommand(_anchorable); - - #endregion DockCommand - - #region CanHide - - /// dependency property. - public static readonly DependencyProperty CanHideProperty = DependencyProperty.Register(nameof(CanHide), typeof(bool), typeof(LayoutAnchorableItem), new FrameworkPropertyMetadata((bool)true, - OnCanHideChanged)); - - /// - /// Gets or sets the property. This dependency property - /// indicates if user can hide the anchorable item. - /// - public bool CanHide - { - get => (bool)GetValue(CanHideProperty); - set => SetValue(CanHideProperty, value); - } - - /// Handles changes to the property. - private static void OnCanHideChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((LayoutAnchorableItem)d).OnCanHideChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnCanHideChanged(DependencyPropertyChangedEventArgs e) - { - if (_anchorable != null) _anchorable.CanHide = (bool)e.NewValue; - } - - #endregion CanHide - - #region CanMove - - /// dependency property. - public static readonly DependencyProperty CanMoveProperty = DependencyProperty.Register(nameof(CanMove), typeof(bool), typeof(LayoutAnchorableItem), new FrameworkPropertyMetadata((bool)true, - OnCanMoveChanged)); - - /// - /// Gets or sets the property. This dependency property - /// indicates if user can hide the anchorable item. - /// - public bool CanMove - { - get => (bool)GetValue(CanMoveProperty); - set => SetValue(CanMoveProperty, value); - } - - /// Handles changes to the property. - private static void OnCanMoveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((LayoutAnchorableItem)d).OnCanHideChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnCanMoveChanged(DependencyPropertyChangedEventArgs e) - { - if (_anchorable != null) _anchorable.CanMove = (bool)e.NewValue; - } - - #endregion CanMove - - #endregion Properties - - #region Overrides - - internal override void Attach(LayoutContent model) - { - _anchorable = model as LayoutAnchorable; - _anchorable.IsVisibleChanged += _anchorable_IsVisibleChanged; - base.Attach(model); - } - - internal override void Detach() - { - _anchorable.IsVisibleChanged -= _anchorable_IsVisibleChanged; - _anchorable = null; - base.Detach(); - } - - /// - protected override bool CanExecuteDockAsDocumentCommand() - { - var canExecute = base.CanExecuteDockAsDocumentCommand(); - if (canExecute && _anchorable != null) return _anchorable.CanDockAsTabbedDocument; - return canExecute; - } - - /// - protected override void Close() - { - if (_anchorable.Root?.Manager == null) return; - var dockingManager = _anchorable.Root.Manager; - dockingManager._ExecuteCloseCommand(_anchorable); - } - - /// - protected override void InitDefaultCommands() - { - _defaultHideCommand = new RelayCommand(ExecuteHideCommand, CanExecuteHideCommand); - _defaultAutoHideCommand = new RelayCommand(ExecuteAutoHideCommand, CanExecuteAutoHideCommand); - _defaultDockCommand = new RelayCommand(ExecuteDockCommand, CanExecuteDockCommand); - base.InitDefaultCommands(); - } - - /// - protected override void ClearDefaultBindings() - { - if (HideCommand == _defaultHideCommand) BindingOperations.ClearBinding(this, HideCommandProperty); - if (AutoHideCommand == _defaultAutoHideCommand) BindingOperations.ClearBinding(this, AutoHideCommandProperty); - if (DockCommand == _defaultDockCommand) BindingOperations.ClearBinding(this, DockCommandProperty); - base.ClearDefaultBindings(); - } - - /// - protected override void SetDefaultBindings() - { - if (HideCommand == null) HideCommand = _defaultHideCommand; - if (AutoHideCommand == null) AutoHideCommand = _defaultAutoHideCommand; - if (DockCommand == null) DockCommand = _defaultDockCommand; - Visibility = _anchorable.IsVisible ? Visibility.Visible : Visibility.Hidden; - base.SetDefaultBindings(); - } - - /// - protected override void OnVisibilityChanged() - { - if (_anchorable?.Root != null && _visibilityReentrantFlag.CanEnter) - { - using (_visibilityReentrantFlag.Enter()) - { - switch (Visibility) - { - case Visibility.Hidden: _anchorable.Hide(false); break; - case Visibility.Visible: _anchorable.Show(); break; - } - } - } - base.OnVisibilityChanged(); - } - - #endregion Overrides - - #region Private Methods - - private void _anchorable_IsVisibleChanged(object sender, EventArgs e) - { - if (_anchorable?.Root == null || !_anchorableVisibilityReentrantFlag.CanEnter) return; - using (_anchorableVisibilityReentrantFlag.Enter()) - { - Visibility = _anchorable.IsVisible ? Visibility.Visible : Visibility.Hidden; - } - } - - #endregion Private Methods - } + /// + /// + /// This is a wrapper for around the custom anchorable content view of . + /// Implements the + /// + /// All DPs implemented here can be bound in a corresponding style to control parameters + /// in dependency properties via binding in MVVM. + /// + /// + public class LayoutAnchorableItem : LayoutItem + { + #region fields + private LayoutAnchorable _anchorable; // The content of this item + private ICommand _defaultHideCommand; + private ICommand _defaultAutoHideCommand; + private ICommand _defaultDockCommand; + private readonly ReentrantFlag _visibilityReentrantFlag = new ReentrantFlag(); + private readonly ReentrantFlag _anchorableVisibilityReentrantFlag = new ReentrantFlag(); + #endregion fields + + #region Constructors + /// Class constructor + internal LayoutAnchorableItem() + { + } + #endregion Constructors + + #region Properties + + #region HideCommand + + /// dependency property. + public static readonly DependencyProperty HideCommandProperty = DependencyProperty.Register(nameof(HideCommand), typeof(ICommand), typeof(LayoutAnchorableItem), + new FrameworkPropertyMetadata(null, OnHideCommandChanged, CoerceHideCommandValue)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the command to execute when an anchorable is hidden. + /// + public ICommand HideCommand + { + get => (ICommand)GetValue(HideCommandProperty); + set => SetValue(HideCommandProperty, value); + } + + /// Handles changes to the property. + private static void OnHideCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((LayoutAnchorableItem)d).OnHideCommandChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnHideCommandChanged(DependencyPropertyChangedEventArgs e) + { + } + + /// Coerces the value. + private static object CoerceHideCommandValue(DependencyObject d, object value) => value; + + private bool CanExecuteHideCommand(object parameter) => LayoutElement != null && _anchorable.CanHide; + + private void ExecuteHideCommand(object parameter) => _anchorable?.Root?.Manager?.ExecuteHideCommand(_anchorable); + + #endregion HideCommand + + #region AutoHideCommand + + /// dependency property. + public static readonly DependencyProperty AutoHideCommandProperty = DependencyProperty.Register(nameof(AutoHideCommand), typeof(ICommand), typeof(LayoutAnchorableItem), + new FrameworkPropertyMetadata(null, OnAutoHideCommandChanged, CoerceAutoHideCommandValue)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the command to execute when user click the auto hide button. + /// + /// By default this command toggles auto hide state for an anchorable. + public ICommand AutoHideCommand + { + get => (ICommand)GetValue(AutoHideCommandProperty); + set => SetValue(AutoHideCommandProperty, value); + } + + /// Handles changes to the property. + private static void OnAutoHideCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((LayoutAnchorableItem)d).OnAutoHideCommandChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnAutoHideCommandChanged(DependencyPropertyChangedEventArgs e) + { + } + + /// Coerces the value. + private static object CoerceAutoHideCommandValue(DependencyObject d, object value) => value; + + private bool CanExecuteAutoHideCommand(object parameter) + { + if (LayoutElement == null) return false; + if (LayoutElement.FindParent() != null) return false;//is floating + return _anchorable.CanAutoHide; + } + + private void ExecuteAutoHideCommand(object parameter) => _anchorable?.Root?.Manager?.ExecuteAutoHideCommand(_anchorable); + + #endregion AutoHideCommand + + #region DockCommand + + /// dependency property. + public static readonly DependencyProperty DockCommandProperty = DependencyProperty.Register(nameof(DockCommand), typeof(ICommand), typeof(LayoutAnchorableItem), + new FrameworkPropertyMetadata(null, OnDockCommandChanged, CoerceDockCommandValue)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the command to execute when user click the Dock button. + /// + /// By default this command moves the anchorable inside the container pane which previously hosted the object. + public ICommand DockCommand + { + get => (ICommand)GetValue(DockCommandProperty); + set => SetValue(DockCommandProperty, value); + } + + /// Handles changes to the property. + private static void OnDockCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((LayoutAnchorableItem)d).OnDockCommandChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnDockCommandChanged(DependencyPropertyChangedEventArgs e) + { + } + + /// Coerces the value. + private static object CoerceDockCommandValue(DependencyObject d, object value) => value; + + private bool CanExecuteDockCommand(object parameter) => LayoutElement?.FindParent() != null; + + private void ExecuteDockCommand(object parameter) => LayoutElement.Root.Manager.ExecuteDockCommand(_anchorable); + + #endregion DockCommand + + #region CanHide + + /// dependency property. + public static readonly DependencyProperty CanHideProperty = DependencyProperty.Register(nameof(CanHide), typeof(bool), typeof(LayoutAnchorableItem), new FrameworkPropertyMetadata((bool)true, + OnCanHideChanged)); + + /// + /// Gets or sets the property. This dependency property + /// indicates if user can hide the anchorable item. + /// + public bool CanHide + { + get => (bool)GetValue(CanHideProperty); + set => SetValue(CanHideProperty, value); + } + + /// Handles changes to the property. + private static void OnCanHideChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((LayoutAnchorableItem)d).OnCanHideChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnCanHideChanged(DependencyPropertyChangedEventArgs e) + { + if (_anchorable != null) _anchorable.CanHide = (bool)e.NewValue; + } + + #endregion CanHide + + #region CanMove + + /// dependency property. + public static readonly DependencyProperty CanMoveProperty = DependencyProperty.Register(nameof(CanMove), typeof(bool), typeof(LayoutAnchorableItem), new FrameworkPropertyMetadata((bool)true, + OnCanMoveChanged)); + + /// + /// Gets or sets the property. This dependency property + /// indicates if user can hide the anchorable item. + /// + public bool CanMove + { + get => (bool)GetValue(CanMoveProperty); + set => SetValue(CanMoveProperty, value); + } + + /// Handles changes to the property. + private static void OnCanMoveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((LayoutAnchorableItem)d).OnCanHideChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnCanMoveChanged(DependencyPropertyChangedEventArgs e) + { + if (_anchorable != null) _anchorable.CanMove = (bool)e.NewValue; + } + + #endregion CanMove + + #endregion Properties + + #region Overrides + + internal override void Attach(LayoutContent model) + { + _anchorable = model as LayoutAnchorable; + _anchorable.IsVisibleChanged += _anchorable_IsVisibleChanged; + base.Attach(model); + } + + internal override void Detach() + { + _anchorable.IsVisibleChanged -= _anchorable_IsVisibleChanged; + _anchorable = null; + base.Detach(); + } + + /// + protected override bool CanExecuteDockAsDocumentCommand() + { + var canExecute = base.CanExecuteDockAsDocumentCommand(); + if (canExecute && _anchorable != null) return _anchorable.CanDockAsTabbedDocument; + return canExecute; + } + + /// + protected override void Close() + { + if (_anchorable.Root?.Manager == null) return; + var dockingManager = _anchorable.Root.Manager; + dockingManager.ExecuteCloseCommand(_anchorable); + } + + /// + protected override void InitDefaultCommands() + { + _defaultHideCommand = new RelayCommand(ExecuteHideCommand, CanExecuteHideCommand); + _defaultAutoHideCommand = new RelayCommand(ExecuteAutoHideCommand, CanExecuteAutoHideCommand); + _defaultDockCommand = new RelayCommand(ExecuteDockCommand, CanExecuteDockCommand); + base.InitDefaultCommands(); + } + + /// + protected override void ClearDefaultBindings() + { + if (HideCommand == _defaultHideCommand) BindingOperations.ClearBinding(this, HideCommandProperty); + if (AutoHideCommand == _defaultAutoHideCommand) BindingOperations.ClearBinding(this, AutoHideCommandProperty); + if (DockCommand == _defaultDockCommand) BindingOperations.ClearBinding(this, DockCommandProperty); + base.ClearDefaultBindings(); + } + + /// + protected override void SetDefaultBindings() + { + if (HideCommand == null) HideCommand = _defaultHideCommand; + if (AutoHideCommand == null) AutoHideCommand = _defaultAutoHideCommand; + if (DockCommand == null) DockCommand = _defaultDockCommand; + Visibility = _anchorable.IsVisible ? Visibility.Visible : Visibility.Hidden; + base.SetDefaultBindings(); + } + + /// + protected override void OnVisibilityChanged() + { + if (_anchorable?.Root != null && _visibilityReentrantFlag.CanEnter) + { + using (_visibilityReentrantFlag.Enter()) + { + switch (Visibility) + { + case Visibility.Hidden: case Visibility.Collapsed: _anchorable.Hide(false); break; + case Visibility.Visible: _anchorable.Show(); break; + } + } + } + base.OnVisibilityChanged(); + } + + #endregion Overrides + + #region Private Methods + + private void _anchorable_IsVisibleChanged(object sender, EventArgs e) + { + if (_anchorable?.Root == null || !_anchorableVisibilityReentrantFlag.CanEnter) return; + using (_anchorableVisibilityReentrantFlag.Enter()) + { + Visibility = _anchorable.IsVisible ? Visibility.Visible : Visibility.Hidden; + } + } + + #endregion Private Methods + } } diff --git a/source/Components/AvalonDock/Controls/LayoutDocumentControl.cs b/source/Components/AvalonDock/Controls/LayoutDocumentControl.cs index f30c0422..8785b157 100644 --- a/source/Components/AvalonDock/Controls/LayoutDocumentControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutDocumentControl.cs @@ -134,7 +134,7 @@ protected override void OnMouseRightButtonDown(MouseButtonEventArgs e) private void SetIsActive() { - if (Model != null) Model.IsActive = true; + if (Model != null && !Model.IsActive) Model.IsActive = true; } #endregion Private Methods diff --git a/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs index 28dc53f4..40b488e6 100644 --- a/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs @@ -26,8 +26,8 @@ namespace AvalonDock.Controls /// public class LayoutDocumentFloatingWindowControl : LayoutFloatingWindowControl, IOverlayWindowHost { - #region fields - private LayoutDocumentFloatingWindow _model; + #region fields + private readonly LayoutDocumentFloatingWindow _model; private List _dropAreas = null; #endregion fields @@ -105,7 +105,7 @@ protected override void OnInitialized(EventArgs e) _model.RootPanel.ChildrenCollectionChanged += RootPanelOnChildrenCollectionChanged; } - void _model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + void Model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == nameof(LayoutDocumentFloatingWindow.RootPanel) && _model.RootPanel == null) InternalClose(); } @@ -159,7 +159,7 @@ protected override void OnClosed(EventArgs e) } base.OnClosed(e); if (!CloseInitiatedByUser) root?.FloatingWindows.Remove(_model); - _model.PropertyChanged -= _model_PropertyChanged; + _model.PropertyChanged -= Model_PropertyChanged; } #endregion @@ -240,7 +240,7 @@ public IEnumerable GetDropAreas(LayoutFloatingWindowControl draggingW var dockAsDocument = true; if (!isDraggingDocuments) { - if (draggingWindow.Model is LayoutAnchorableFloatingWindow toolWindow) + if (draggingWindow.Model is LayoutAnchorableFloatingWindow) { foreach (var item in GetAnchorableInFloatingWindow(draggingWindow)) { @@ -277,18 +277,17 @@ public IEnumerable GetDropAreas(LayoutFloatingWindowControl draggingW private IEnumerable GetAnchorableInFloatingWindow(LayoutFloatingWindowControl draggingWindow) { if (!(draggingWindow.Model is LayoutAnchorableFloatingWindow layoutAnchorableFloatingWindow)) yield break; - //big part of code for getting type - var layoutAnchorablePane = layoutAnchorableFloatingWindow.SinglePane as LayoutAnchorablePane; - - if (layoutAnchorablePane != null && (layoutAnchorableFloatingWindow.IsSinglePane && layoutAnchorablePane.SelectedContent != null)) - { - var layoutAnchorable = ((LayoutAnchorablePane)layoutAnchorableFloatingWindow.SinglePane).SelectedContent as LayoutAnchorable; - yield return layoutAnchorable; - } - else - foreach (var item in GetLayoutAnchorable(layoutAnchorableFloatingWindow.RootPanel)) - yield return item; - } + //big part of code for getting type + + if (layoutAnchorableFloatingWindow.SinglePane is LayoutAnchorablePane layoutAnchorablePane && (layoutAnchorableFloatingWindow.IsSinglePane && layoutAnchorablePane.SelectedContent != null)) + { + var layoutAnchorable = ((LayoutAnchorablePane)layoutAnchorableFloatingWindow.SinglePane).SelectedContent as LayoutAnchorable; + yield return layoutAnchorable; + } + else + foreach (var item in GetLayoutAnchorable(layoutAnchorableFloatingWindow.RootPanel)) + yield return item; + } /// /// Finds all objects (toolwindows) within a diff --git a/source/Components/AvalonDock/Controls/LayoutDocumentItem.cs b/source/Components/AvalonDock/Controls/LayoutDocumentItem.cs index dbaf4d38..34cb0367 100644 --- a/source/Components/AvalonDock/Controls/LayoutDocumentItem.cs +++ b/source/Components/AvalonDock/Controls/LayoutDocumentItem.cs @@ -69,7 +69,7 @@ protected override void Close() { if (_document.Root?.Manager == null) return; var dockingManager = _document.Root.Manager; - dockingManager._ExecuteCloseCommand(_document); + dockingManager.ExecuteCloseCommand(_document); } /// diff --git a/source/Components/AvalonDock/Controls/LayoutDocumentPaneControl.cs b/source/Components/AvalonDock/Controls/LayoutDocumentPaneControl.cs index 31e18401..79c52cc4 100644 --- a/source/Components/AvalonDock/Controls/LayoutDocumentPaneControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutDocumentPaneControl.cs @@ -69,7 +69,7 @@ internal LayoutDocumentPaneControl(LayoutDocumentPane model, bool isVirtualizing protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) { base.OnMouseLeftButtonDown(e); - if (!e.Handled && _model.SelectedContent != null) + if (!e.Handled && _model.SelectedContent != null && !_model.SelectedContent.IsActive) _model.SelectedContent.IsActive = true; } diff --git a/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs index 8383a222..74e48082 100644 --- a/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs @@ -38,7 +38,7 @@ public abstract class LayoutFloatingWindowControl : Window, ILayoutControl #region fields private ResourceDictionary currentThemeResourceDictionary; // = null private bool _isInternalChange; //false - private ILayoutElement _model; + private readonly ILayoutElement _model; private bool _attachDrag = false; private HwndSource _hwndSrc; private HwndSourceHook _hwndSrcHook; @@ -57,9 +57,10 @@ public abstract class LayoutFloatingWindowControl : Window, ILayoutControl static LayoutFloatingWindowControl() { - ContentProperty.OverrideMetadata(typeof(LayoutFloatingWindowControl), new FrameworkPropertyMetadata(null, null, CoerceContentValue)); AllowsTransparencyProperty.OverrideMetadata(typeof(LayoutFloatingWindowControl), new FrameworkPropertyMetadata(false)); + ContentProperty.OverrideMetadata(typeof(LayoutFloatingWindowControl), new FrameworkPropertyMetadata(null, null, CoerceContentValue)); ShowInTaskbarProperty.OverrideMetadata(typeof(LayoutFloatingWindowControl), new FrameworkPropertyMetadata(false)); + WindowStyleProperty.OverrideMetadata(typeof(LayoutFloatingWindowControl), new FrameworkPropertyMetadata(WindowStyle.None)); } protected LayoutFloatingWindowControl(ILayoutElement model) @@ -627,7 +628,7 @@ public virtual void DisableBindings() protected internal class FloatingWindowContentHost : HwndHost { #region fields - private LayoutFloatingWindowControl _owner; + private readonly LayoutFloatingWindowControl _owner; private HwndSource _wpfContentHost = null; private Border _rootPresenter = null; private DockingManager _manager = null; @@ -713,7 +714,8 @@ protected override HandleRef BuildWindowCore(HandleRef hwndParent) ParentWindow = hwndParent.Handle, WindowStyle = Win32Helper.WS_CHILD | Win32Helper.WS_VISIBLE | Win32Helper.WS_CLIPSIBLINGS | Win32Helper.WS_CLIPCHILDREN, Width = 1, - Height = 1 + Height = 1, + UsesPerPixelOpacity = true, }); _rootPresenter = new Border { Child = new AdornerDecorator { Child = Content }, Focusable = true }; diff --git a/source/Components/AvalonDock/Controls/LayoutItem.cs b/source/Components/AvalonDock/Controls/LayoutItem.cs index d9a55d33..608fea73 100644 --- a/source/Components/AvalonDock/Controls/LayoutItem.cs +++ b/source/Components/AvalonDock/Controls/LayoutItem.cs @@ -353,7 +353,7 @@ protected virtual void OnFloatCommandChanged(DependencyPropertyChangedEventArgs /// Executes to float the content of this LayoutItem in a separate . /// - private void ExecuteFloatCommand(object parameter) => LayoutElement.Root.Manager._ExecuteFloatCommand(LayoutElement); + private void ExecuteFloatCommand(object parameter) => LayoutElement.Root.Manager.ExecuteFloatCommand(LayoutElement); #endregion @@ -389,7 +389,7 @@ protected virtual void OnDockAsDocumentCommandChanged(DependencyPropertyChangedE private bool CanExecuteDockAsDocumentCommand(object parameter) => CanExecuteDockAsDocumentCommand(); - private void ExecuteDockAsDocumentCommand(object parameter) => LayoutElement.Root.Manager._ExecuteDockAsDocumentCommand(LayoutElement); + private void ExecuteDockAsDocumentCommand(object parameter) => LayoutElement.Root.Manager.ExecuteDockAsDocumentCommand(LayoutElement); #endregion @@ -427,7 +427,7 @@ private bool CanExecuteCloseAllButThisCommand(object parameter) return LayoutElement.Root.Manager.Layout.Descendents().OfType().Any(d => d != LayoutElement && (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)); } - private void ExecuteCloseAllButThisCommand(object parameter) => LayoutElement.Root.Manager._ExecuteCloseAllButThisCommand(LayoutElement); + private void ExecuteCloseAllButThisCommand(object parameter) => LayoutElement.Root.Manager.ExecuteCloseAllButThisCommand(LayoutElement); #endregion @@ -462,7 +462,7 @@ private bool CanExecuteCloseAllCommand(object parameter) return LayoutElement.Root.Manager.Layout.Descendents().OfType().Any(d => d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow); } - private void ExecuteCloseAllCommand(object parameter) => LayoutElement.Root.Manager._ExecuteCloseAllCommand(LayoutElement); + private void ExecuteCloseAllCommand(object parameter) => LayoutElement.Root.Manager.ExecuteCloseAllCommand(LayoutElement); #endregion @@ -495,7 +495,7 @@ protected virtual void OnActivateCommandChanged(DependencyPropertyChangedEventAr private bool CanExecuteActivateCommand(object parameter) => LayoutElement != null; - private void ExecuteActivateCommand(object parameter) => LayoutElement.Root.Manager._ExecuteContentActivateCommand(LayoutElement); + private void ExecuteActivateCommand(object parameter) => LayoutElement.Root.Manager.ExecuteContentActivateCommand(LayoutElement); #endregion diff --git a/source/Components/AvalonDock/Controls/OverlayWindow.cs b/source/Components/AvalonDock/Controls/OverlayWindow.cs index 9a4d4b51..c8c6c2fb 100644 --- a/source/Components/AvalonDock/Controls/OverlayWindow.cs +++ b/source/Components/AvalonDock/Controls/OverlayWindow.cs @@ -68,9 +68,9 @@ public class OverlayWindow : Window, IOverlayWindow #endregion DocumentPaneFullDropTargets private Path _previewBox; - private IOverlayWindowHost _host; + private readonly IOverlayWindowHost _host; private LayoutFloatingWindowControl _floatingWindow = null; - private List _visibleAreas = new List(); + private readonly List _visibleAreas = new List(); #endregion fields #region Constructors @@ -185,9 +185,9 @@ internal void UpdateThemeResources(Theme oldTheme = null) if (_host.Manager.Theme != null) { - if (_host.Manager.Theme is DictionaryTheme) + if (_host.Manager.Theme is DictionaryTheme theme) { - currentThemeResourceDictionary = ((DictionaryTheme)_host.Manager.Theme).ThemeResourceDictionary; + currentThemeResourceDictionary = theme.ThemeResourceDictionary; Resources.MergedDictionaries.Add(currentThemeResourceDictionary); } else @@ -275,73 +275,65 @@ private List GetAllLayoutContents(object source) { var result = new List(); - var documentFloatingWindow = source as LayoutDocumentFloatingWindow; - if (documentFloatingWindow != null) - { - foreach (var layoutElement in documentFloatingWindow.Children) - { - result.AddRange(GetAllLayoutContents(layoutElement)); - } - } - - var anchorableFloatingWindow = source as LayoutAnchorableFloatingWindow; - if (anchorableFloatingWindow != null) - { - foreach (var layoutElement in anchorableFloatingWindow.Children) - { - result.AddRange(GetAllLayoutContents(layoutElement)); - } - } - - var documentPaneGroup = source as LayoutDocumentPaneGroup; - if (documentPaneGroup != null) - { - foreach (var layoutDocumentPane in documentPaneGroup.Children) - { - result.AddRange(GetAllLayoutContents(layoutDocumentPane)); - } - } - - var anchorablePaneGroup = source as LayoutAnchorablePaneGroup; - if (anchorablePaneGroup != null) - { - foreach (var layoutDocumentPane in anchorablePaneGroup.Children) - { - result.AddRange(GetAllLayoutContents(layoutDocumentPane)); - } - } - - var documentPane = source as LayoutDocumentPane; - if (documentPane != null) - { - foreach (var layoutContent in documentPane.Children) - { - result.Add(layoutContent); - } - } - - var anchorablePane = source as LayoutAnchorablePane; - if (anchorablePane != null) - { - foreach (var layoutContent in anchorablePane.Children) - { - result.Add(layoutContent); - } - } - - var document = source as LayoutDocument; - if (document != null) - { - result.Add(document); - } - - var anchorable = source as LayoutAnchorable; - if (anchorable != null) - { - result.Add(anchorable); - } - - return result; + if (source is LayoutDocumentFloatingWindow documentFloatingWindow) + { + foreach (var layoutElement in documentFloatingWindow.Children) + { + result.AddRange(GetAllLayoutContents(layoutElement)); + } + } + + if (source is LayoutAnchorableFloatingWindow anchorableFloatingWindow) + { + foreach (var layoutElement in anchorableFloatingWindow.Children) + { + result.AddRange(GetAllLayoutContents(layoutElement)); + } + } + + if (source is LayoutDocumentPaneGroup documentPaneGroup) + { + foreach (var layoutDocumentPane in documentPaneGroup.Children) + { + result.AddRange(GetAllLayoutContents(layoutDocumentPane)); + } + } + + if (source is LayoutAnchorablePaneGroup anchorablePaneGroup) + { + foreach (var layoutDocumentPane in anchorablePaneGroup.Children) + { + result.AddRange(GetAllLayoutContents(layoutDocumentPane)); + } + } + + if (source is LayoutDocumentPane documentPane) + { + foreach (var layoutContent in documentPane.Children) + { + result.Add(layoutContent); + } + } + + if (source is LayoutAnchorablePane anchorablePane) + { + foreach (var layoutContent in anchorablePane.Children) + { + result.Add(layoutContent); + } + } + + if (source is LayoutDocument document) + { + result.Add(document); + } + + if (source is LayoutAnchorable anchorable) + { + result.Add(anchorable); + } + + return result; } #endregion diff --git a/source/Components/AvalonDock/Controls/Shell/SystemParameters2.cs b/source/Components/AvalonDock/Controls/Shell/SystemParameters2.cs index 927649d0..91357fc0 100644 --- a/source/Components/AvalonDock/Controls/Shell/SystemParameters2.cs +++ b/source/Components/AvalonDock/Controls/Shell/SystemParameters2.cs @@ -28,7 +28,7 @@ public class SystemParameters2 : INotifyPropertyChanged private delegate void _SystemMetricUpdate(IntPtr wParam, IntPtr lParam); [ThreadStatic] - private static SystemParameters2 _threadLocalSingleton; + private static readonly SystemParameters2 _threadLocalSingleton; private MessageWindow _messageHwnd; @@ -218,7 +218,7 @@ private void _InitializeThemeInfo() return; } - NativeMethods.GetCurrentThemeName(out var name, out var color, out var size); + NativeMethods.GetCurrentThemeName(out var name, out var color, out _); // Consider whether this is the most useful way to expose this... UxThemeName = System.IO.Path.GetFileNameWithoutExtension(name); @@ -237,18 +237,18 @@ private void _InitializeWindowCornerRadius() // There aren't any known variations based on theme color. Assert.IsNeitherNullNorEmpty(UxThemeName); - // These radii are approximate. The way WPF does rounding is different than how - // rounded-rectangle HRGNs are created, which is also different than the actual - // round corners on themed Windows. For now we're not exposing anything to - // mitigate the differences. - var cornerRadius = default(CornerRadius); - - // This list is known to be incomplete and very much not future-proof. - // On XP there are at least a couple of shipped themes that this won't catch, - // "Zune" and "Royale", but WPF doesn't know about these either. - // If a new theme was to replace Aero, then this will fall back on "classic" behaviors. - // This isn't ideal, but it's not the end of the world. WPF will generally have problems anyways. - switch (UxThemeName.ToUpperInvariant()) + // These radii are approximate. The way WPF does rounding is different than how + // rounded-rectangle HRGNs are created, which is also different than the actual + // round corners on themed Windows. For now we're not exposing anything to + // mitigate the differences. + CornerRadius cornerRadius; + + // This list is known to be incomplete and very much not future-proof. + // On XP there are at least a couple of shipped themes that this won't catch, + // "Zune" and "Royale", but WPF doesn't know about these either. + // If a new theme was to replace Aero, then this will fall back on "classic" behaviors. + // This isn't ideal, but it's not the end of the world. WPF will generally have problems anyways. + switch (UxThemeName.ToUpperInvariant()) { case "LUNA": cornerRadius = new CornerRadius(6, 6, 0, 0); @@ -331,7 +331,7 @@ private SystemParameters2() }; } - public static SystemParameters2 Current => _threadLocalSingleton ?? (_threadLocalSingleton = new SystemParameters2()); + public static SystemParameters2 Current => _threadLocalSingleton ?? new SystemParameters2(); private IntPtr _WndProc(IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam) { diff --git a/source/Components/AvalonDock/Controls/Shell/WindowChromeWorker.cs b/source/Components/AvalonDock/Controls/Shell/WindowChromeWorker.cs index a347f46e..d7b8fa8a 100644 --- a/source/Components/AvalonDock/Controls/Shell/WindowChromeWorker.cs +++ b/source/Components/AvalonDock/Controls/Shell/WindowChromeWorker.cs @@ -48,7 +48,7 @@ internal class WindowChromeWorker : DependencyObject private bool _isFixedUp = false; private bool _isUserResizing = false; private bool _hasUserMovedWindow = false; - private Point _windowPosAtStartOfUserMove = default(Point); + private Point _windowPosAtStartOfUserMove = default; // Field to track attempts to force off Device Bitmaps on Win7. private int _blackGlassFixupAttemptCount; @@ -415,6 +415,13 @@ private IntPtr _HandleNCCalcSize(WM uMsg, IntPtr wParam, IntPtr lParam, out bool // Since we always want the client size to equal the window size, we can unconditionally handle it // without having to modify the parameters. handled = true; + if (wParam != IntPtr.Zero) + { + var client = (RECT)Marshal.PtrToStructure(lParam, typeof(RECT)); + client.Bottom++; + Marshal.StructureToPtr(client, lParam, false); + return IntPtr.Zero; + } return new IntPtr((int)WVR.REDRAW); } @@ -424,7 +431,7 @@ private IntPtr _HandleNCHitTest(WM uMsg, IntPtr wParam, IntPtr lParam, out bool handled = false; // Give DWM a chance at this first. - if (Utility.IsOSVistaOrNewer && _chromeInfo.GlassFrameThickness != default(Thickness) && _isGlassEnabled) + if (Utility.IsOSVistaOrNewer && _chromeInfo.GlassFrameThickness != default && _isGlassEnabled) { // If we're on Vista, give the DWM a chance to handle the message first. handled = NativeMethods.DwmDefWindowProc(_hwnd, uMsg, wParam, lParam, out lRet); @@ -686,7 +693,7 @@ private void _UpdateFrameState(bool force) var frameState = NativeMethods.DwmIsCompositionEnabled(); if (!force && frameState == _isGlassEnabled) return; - _isGlassEnabled = frameState && _chromeInfo.GlassFrameThickness != default(Thickness); + _isGlassEnabled = frameState && _chromeInfo.GlassFrameThickness != default; if (_isGlassEnabled) { diff --git a/source/Components/AvalonDock/Converters/ActivateCommandLayoutItemFromLayoutModelConverter.cs b/source/Components/AvalonDock/Converters/ActivateCommandLayoutItemFromLayoutModelConverter.cs index 1d852fd8..c5bab8ae 100644 --- a/source/Components/AvalonDock/Converters/ActivateCommandLayoutItemFromLayoutModelConverter.cs +++ b/source/Components/AvalonDock/Converters/ActivateCommandLayoutItemFromLayoutModelConverter.cs @@ -9,58 +9,63 @@ This program is provided to you under the terms of the Microsoft Public using System; using System.Windows.Data; +using System.Windows.Markup; using AvalonDock.Layout; namespace AvalonDock.Converters { - /// - /// Converts a into an - /// and ensures that other essential properties (Root, Root.Manager) are available. - /// - /// Returns null or Binding.DoNothing otherwise. - /// - public class ActivateCommandLayoutItemFromLayoutModelConverter : IValueConverter - { - /// - /// Converts a into an - /// and ensures that other essential properties (Root, Root.Manager) are available. - /// - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// A converted value. If the method returns null, the valid null value is used. - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - //when this converter is called layout could be constructing so many properties here are potentially not valid - var layoutModel = value as LayoutContent; - if (layoutModel == null) - return null; + /// + /// Converts a into an + /// and ensures that other essential properties (Root, Root.Manager) are available. + /// + /// Returns null or Binding.DoNothing otherwise. + /// + public class ActivateCommandLayoutItemFromLayoutModelConverter : MarkupExtension, IValueConverter + { + /// + /// Converts a into an + /// and ensures that other essential properties (Root, Root.Manager) are available. + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. If the method returns null, the valid null value is used. + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + //when this converter is called layout could be constructing so many properties here are potentially not valid + if (!(value is LayoutContent layoutModel)) + return null; - if (layoutModel.Root == null) - return null; + if (layoutModel.Root == null) + return null; - if (layoutModel.Root.Manager == null) - return null; + if (layoutModel.Root.Manager == null) + return null; - var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel(layoutModel); - if (layoutItemModel == null) - return Binding.DoNothing; + var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel(layoutModel); + if (layoutItemModel == null) + return Binding.DoNothing; - return layoutItemModel.ActivateCommand; - } + return layoutItemModel.ActivateCommand; + } - /// - /// Method is not implemented and will raise when called. - /// - /// - /// - /// - /// - /// - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } - } + /// + /// Method is not implemented and will raise when called. + /// + /// + /// + /// + /// + /// + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return ConverterCreater.Get(); + } + } } diff --git a/source/Components/AvalonDock/Converters/AnchorSideToAngleConverter.cs b/source/Components/AvalonDock/Converters/AnchorSideToAngleConverter.cs index af1ae7a5..909aa52a 100644 --- a/source/Components/AvalonDock/Converters/AnchorSideToAngleConverter.cs +++ b/source/Components/AvalonDock/Converters/AnchorSideToAngleConverter.cs @@ -9,50 +9,56 @@ This program is provided to you under the terms of the Microsoft Public using System; using System.Windows.Data; +using System.Windows.Markup; using AvalonDock.Layout; namespace AvalonDock.Converters { - /// - /// Converts an value into a floating point value that - /// indicates whether the content should be rotated by 90.0 degrees or not. - /// - /// Returns Binding.DoNothing if not rotation is required. - /// - [ValueConversion(typeof(AnchorSide), typeof(double))] - public class AnchorSideToAngleConverter : IValueConverter - { - /// - /// Converts an value into a floating point value that - /// indicates whether the content should be rotated by 90.0 degrees or not. - /// - /// Returns Binding.DoNothing if not rotation is required. - /// - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// A converted value. - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - AnchorSide side = (AnchorSide)value; - if (side == AnchorSide.Left || side == AnchorSide.Right) - return 90.0; + /// + /// Converts an value into a floating point value that + /// indicates whether the content should be rotated by 90.0 degrees or not. + /// + /// Returns Binding.DoNothing if not rotation is required. + /// + [ValueConversion(typeof(AnchorSide), typeof(double))] + public class AnchorSideToAngleConverter : MarkupExtension, IValueConverter + { + /// + /// Converts an value into a floating point value that + /// indicates whether the content should be rotated by 90.0 degrees or not. + /// + /// Returns Binding.DoNothing if not rotation is required. + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + AnchorSide side = (AnchorSide)value; + if (side == AnchorSide.Left || side == AnchorSide.Right) + return 90.0; - return Binding.DoNothing; - } + return Binding.DoNothing; + } - /// - /// Method is not implemented and will raise when called. - /// - /// - /// - /// - /// - /// - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } - } + /// + /// Method is not implemented and will raise when called. + /// + /// + /// + /// + /// + /// + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return ConverterCreater.Get(); + } + } } diff --git a/source/Components/AvalonDock/Converters/AnchorSideToOrientationConverter.cs b/source/Components/AvalonDock/Converters/AnchorSideToOrientationConverter.cs index 0928f43a..4e217012 100644 --- a/source/Components/AvalonDock/Converters/AnchorSideToOrientationConverter.cs +++ b/source/Components/AvalonDock/Converters/AnchorSideToOrientationConverter.cs @@ -11,6 +11,7 @@ This program is provided to you under the terms of the Microsoft Public using System.Windows.Data; using System.Windows.Controls; using AvalonDock.Layout; +using System.Windows.Markup; namespace AvalonDock.Converters { @@ -21,7 +22,7 @@ namespace AvalonDock.Converters /// othrwise is returned. /// [ValueConversion(typeof(AnchorSide), typeof(Orientation))] - public class AnchorSideToOrientationConverter : IValueConverter + public class AnchorSideToOrientationConverter : MarkupExtension, IValueConverter { /// /// Converts an value into a WPF value. @@ -55,5 +56,10 @@ public object ConvertBack(object value, Type targetType, object parameter, Syste { throw new NotImplementedException(); } - } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return ConverterCreater.Get(); + } + } } diff --git a/source/Components/AvalonDock/Converters/AnchorableContextMenuHideVisibilityConverter.cs b/source/Components/AvalonDock/Converters/AnchorableContextMenuHideVisibilityConverter.cs index aa4e73a8..2a97a6ee 100644 --- a/source/Components/AvalonDock/Converters/AnchorableContextMenuHideVisibilityConverter.cs +++ b/source/Components/AvalonDock/Converters/AnchorableContextMenuHideVisibilityConverter.cs @@ -12,62 +12,68 @@ This program is provided to you under the terms of the Microsoft Public using System.Linq; using System.Windows; using System.Windows.Data; +using System.Windows.Markup; namespace AvalonDock.Converters { - /// - /// Converts a binding of 2 values: - /// 1) and - /// 2) bool - /// into a value. - /// - /// The actual value returned is 1) if 2) is true, - /// is returned otherwise. - /// - public class AnchorableContextMenuHideVisibilityConverter : IMultiValueConverter - { - /// - /// Converts a binding of 2 values: - /// 1) and - /// 2) bool - /// into a value. - /// - /// The actual value returned is 1) if 2) is true, - /// is returned otherwise. - /// - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// A converted value. If the method returns null, the valid null value is used. - public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) - { - if ((values.Count() == 2) - && (values[0] != DependencyProperty.UnsetValue) - && (values[1] != DependencyProperty.UnsetValue) - && (values[1] is bool)) - { - var canClose = (bool)values[1]; + /// + /// Converts a binding of 2 values: + /// 1) and + /// 2) bool + /// into a value. + /// + /// The actual value returned is 1) if 2) is true, + /// is returned otherwise. + /// + public class AnchorableContextMenuHideVisibilityConverter : MarkupExtension, IMultiValueConverter + { + /// + /// Converts a binding of 2 values: + /// 1) and + /// 2) bool + /// into a value. + /// + /// The actual value returned is 1) if 2) is true, + /// is returned otherwise. + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. If the method returns null, the valid null value is used. + public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) + { + if ((values.Count() == 2) + && (values[0] != DependencyProperty.UnsetValue) + && (values[1] != DependencyProperty.UnsetValue) + && (values[1] is bool boolean)) + { + var canClose = boolean; - return canClose ? Visibility.Collapsed : values[0]; - } - else - { - return values[0]; - } - } + return canClose ? Visibility.Collapsed : values[0]; + } + else + { + return values[0]; + } + } - /// - /// Method is not implemented and will raise when called. - /// - /// - /// - /// - /// - /// - public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } + /// + /// Method is not implemented and will raise when called. + /// + /// + /// + /// + /// + /// + public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return ConverterCreater.Get(); + } + } } diff --git a/source/Components/AvalonDock/Converters/AutoHideCommandLayoutItemFromLayoutModelConverter.cs b/source/Components/AvalonDock/Converters/AutoHideCommandLayoutItemFromLayoutModelConverter.cs index aa3ddcea..27cd3b0e 100644 --- a/source/Components/AvalonDock/Converters/AutoHideCommandLayoutItemFromLayoutModelConverter.cs +++ b/source/Components/AvalonDock/Converters/AutoHideCommandLayoutItemFromLayoutModelConverter.cs @@ -11,59 +11,63 @@ This program is provided to you under the terms of the Microsoft Public using System.Windows.Data; using AvalonDock.Layout; using AvalonDock.Controls; +using System.Windows.Markup; namespace AvalonDock.Converters { - /// - /// Converts a into a - /// and ensures that other essential properties (Root, Root.Manager) are available. - /// - /// Returns null or Binding.DoNothing otherwise. - /// - public class AutoHideCommandLayoutItemFromLayoutModelConverter : IValueConverter - { - /// - /// Converts a into a - /// and ensures that other essential properties (Root, Root.Manager) are available. - /// - /// Returns null or Binding.DoNothing otherwise. - /// - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// A converted value. - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - //when this converter is called layout could be constructing so many properties here are potentially not valid - var layoutModel = value as LayoutContent; - if (layoutModel == null) - return null; + /// + /// Converts a into a + /// and ensures that other essential properties (Root, Root.Manager) are available. + /// + /// Returns null or Binding.DoNothing otherwise. + /// + public class AutoHideCommandLayoutItemFromLayoutModelConverter : MarkupExtension, IValueConverter + { + /// + /// Converts a into a + /// and ensures that other essential properties (Root, Root.Manager) are available. + /// + /// Returns null or Binding.DoNothing otherwise. + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + //when this converter is called layout could be constructing so many properties here are potentially not valid + if (value as LayoutContent == null) + return null; - if (layoutModel.Root == null) - return null; + if ((value as LayoutContent).Root == null) + return null; - if (layoutModel.Root.Manager == null) - return null; + if ((value as LayoutContent).Root.Manager == null) + return null; - var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel(layoutModel) as LayoutAnchorableItem; - if (layoutItemModel == null) - return Binding.DoNothing; + if (!((value as LayoutContent).Root.Manager.GetLayoutItemFromModel(value as LayoutContent) is LayoutAnchorableItem layoutItemModel)) + return Binding.DoNothing; - return layoutItemModel.AutoHideCommand; - } + return layoutItemModel.AutoHideCommand; + } - /// - /// Method is not implemented and will raise when called. - /// - /// - /// - /// - /// - /// - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } - } + /// + /// Method is not implemented and will raise when called. + /// + /// + /// + /// + /// + /// + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return ConverterCreater.Get(); + } + } } diff --git a/source/Components/AvalonDock/Converters/BoolToVisibilityConverter.cs b/source/Components/AvalonDock/Converters/BoolToVisibilityConverter.cs index 63e06c62..1f8ba742 100644 --- a/source/Components/AvalonDock/Converters/BoolToVisibilityConverter.cs +++ b/source/Components/AvalonDock/Converters/BoolToVisibilityConverter.cs @@ -10,60 +10,66 @@ This program is provided to you under the terms of the Microsoft Public using System; using System.Windows.Data; using System.Windows; +using System.Windows.Markup; namespace AvalonDock.Converters { - /// - /// - /// Converts a bool value into a value and back. - /// - [ValueConversion(typeof(bool), typeof(Visibility))] - public class BoolToVisibilityConverter : IValueConverter - { - /// - /// - /// Converts a bool value into a value. - /// - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// - /// A converted value. If the method returns null, the valid null value is used. - /// - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - switch (value) - { - case bool val when targetType == typeof(Visibility): - if (val) return Visibility.Visible; - return parameter is Visibility ? parameter : Visibility.Collapsed; - case null when parameter is Visibility: - return parameter; - case null: - return Visibility.Collapsed; - default: - return Visibility.Visible; - ///throw new ArgumentException("Invalid argument/return type. Expected argument: bool and return type: Visibility"); - } - } + /// + /// + /// Converts a bool value into a value and back. + /// + [ValueConversion(typeof(bool), typeof(Visibility))] + public class BoolToVisibilityConverter : MarkupExtension, IValueConverter + { + /// + /// + /// Converts a bool value into a value. + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// + /// A converted value. If the method returns null, the valid null value is used. + /// + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + switch (value) + { + case bool val when targetType == typeof(Visibility): + if (val) return Visibility.Visible; + return parameter is Visibility ? parameter : Visibility.Collapsed; + case null when parameter is Visibility: + return parameter; + case null: + return Visibility.Collapsed; + default: + return Visibility.Visible; + ///throw new ArgumentException("Invalid argument/return type. Expected argument: bool and return type: Visibility"); + } + } - /// - /// - /// Converts a value into a bool value. - /// - /// The value that is produced by the binding target. - /// The type to convert to. - /// The converter parameter to use. - /// The culture to use in the converter. - /// - /// A converted value. If the method returns null, the valid null value is used. - /// - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (!(value is Visibility)) throw new ArgumentException("Invalid argument type. Expected argument: Visibility.", nameof(value)); - if (targetType != typeof(bool)) throw new ArgumentException("Invalid return type. Expected type: bool", nameof(targetType)); - return (Visibility)value == Visibility.Visible; - } - } + /// + /// + /// Converts a value into a bool value. + /// + /// The value that is produced by the binding target. + /// The type to convert to. + /// The converter parameter to use. + /// The culture to use in the converter. + /// + /// A converted value. If the method returns null, the valid null value is used. + /// + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (!(value is Visibility)) throw new ArgumentException("Invalid argument type. Expected argument: Visibility.", nameof(value)); + if (targetType != typeof(bool)) throw new ArgumentException("Invalid return type. Expected type: bool", nameof(targetType)); + return (Visibility)value == Visibility.Visible; + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return ConverterCreater.Get(); + } + } } diff --git a/source/Components/AvalonDock/Converters/ConverterCreater.cs b/source/Components/AvalonDock/Converters/ConverterCreater.cs new file mode 100644 index 00000000..63d81b6e --- /dev/null +++ b/source/Components/AvalonDock/Converters/ConverterCreater.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; + +namespace AvalonDock.Converters +{ + internal class ConverterCreater + { + #region Private fields + + private static readonly Dictionary ConverterMap = new Dictionary(); + + #endregion Private fields + + #region Public methods + + public static T Get() where T : new() + { + if (!ConverterMap.ContainsKey(typeof(T))) + { + ConverterMap.Add(typeof(T), new T()); + } + return (T)ConverterMap[typeof(T)]; + } + + #endregion Public methods + } +} \ No newline at end of file diff --git a/source/Components/AvalonDock/Converters/HideCommandLayoutItemFromLayoutModelConverter.cs b/source/Components/AvalonDock/Converters/HideCommandLayoutItemFromLayoutModelConverter.cs index 020e72d4..0958ba38 100644 --- a/source/Components/AvalonDock/Converters/HideCommandLayoutItemFromLayoutModelConverter.cs +++ b/source/Components/AvalonDock/Converters/HideCommandLayoutItemFromLayoutModelConverter.cs @@ -11,59 +11,63 @@ This program is provided to you under the terms of the Microsoft Public using System.Windows.Data; using AvalonDock.Layout; using AvalonDock.Controls; +using System.Windows.Markup; namespace AvalonDock.Converters { - /// - /// Converts a into a - /// and ensures that other essential properties (Root, Root.Manager) are available. - /// - /// Returns null or Binding.DoNothing otherwise. - /// - public class HideCommandLayoutItemFromLayoutModelConverter : IValueConverter - { - /// - /// Converts a into a - /// and ensures that other essential properties (Root, Root.Manager) are available. - /// - /// Returns null or Binding.DoNothing otherwise. - /// - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// A converted value. - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - //when this converter is called layout could be constructing so many properties here are potentially not valid - var layoutModel = value as LayoutContent; - if (layoutModel == null) - return null; + /// + /// Converts a into a + /// and ensures that other essential properties (Root, Root.Manager) are available. + /// + /// Returns null or Binding.DoNothing otherwise. + /// + public class HideCommandLayoutItemFromLayoutModelConverter : MarkupExtension, IValueConverter + { + /// + /// Converts a into a + /// and ensures that other essential properties (Root, Root.Manager) are available. + /// + /// Returns null or Binding.DoNothing otherwise. + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + //when this converter is called layout could be constructing so many properties here are potentially not valid + if (!(value is LayoutContent layoutModel)) + return null; - if (layoutModel.Root == null) - return null; + if (layoutModel.Root == null) + return null; - if (layoutModel.Root.Manager == null) - return null; + if (layoutModel.Root.Manager == null) + return null; - var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel(layoutModel) as LayoutAnchorableItem; - if (layoutItemModel == null) - return Binding.DoNothing; + if (!(layoutModel.Root.Manager.GetLayoutItemFromModel(layoutModel) is LayoutAnchorableItem layoutItemModel)) + return Binding.DoNothing; - return layoutItemModel.HideCommand; - } + return layoutItemModel.HideCommand; + } - /// - /// Method is not implemented and will raise when called. - /// - /// - /// - /// - /// - /// - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } - } + /// + /// Method is not implemented and will raise when called. + /// + /// + /// + /// + /// + /// + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return ConverterCreater.Get(); + } + } } diff --git a/source/Components/AvalonDock/Converters/InverseBoolToVisibilityConverter.cs b/source/Components/AvalonDock/Converters/InverseBoolToVisibilityConverter.cs index 177b1ac5..e13d6c5e 100644 --- a/source/Components/AvalonDock/Converters/InverseBoolToVisibilityConverter.cs +++ b/source/Components/AvalonDock/Converters/InverseBoolToVisibilityConverter.cs @@ -10,45 +10,51 @@ This program is provided to you under the terms of the Microsoft Public using System; using System.Windows.Data; using System.Windows; +using System.Windows.Markup; namespace AvalonDock.Converters { - /// - /// - /// Converts an inverted bool value into a value. - /// - [ValueConversion(typeof(bool), typeof(Visibility))] - public class InverseBoolToVisibilityConverter : IValueConverter - { - /// - /// Converts an inverted bool value into a value. - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// A converted value. If the method returns null, the valid null value is used. - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (!(value is bool)) throw new ArgumentException("Invalid argument type. Expected argument: bool.", nameof(value)); - if (targetType != typeof(Visibility)) throw new ArgumentException("Invalid return type. Expected type: Visibility", nameof(targetType)); - var val = !(bool)value; - if (val) return Visibility.Visible; - return parameter is Visibility ? parameter : Visibility.Collapsed; - } + /// + /// + /// Converts an inverted bool value into a value. + /// + [ValueConversion(typeof(bool), typeof(Visibility))] + public class InverseBoolToVisibilityConverter : MarkupExtension, IValueConverter + { + /// + /// Converts an inverted bool value into a value. + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. If the method returns null, the valid null value is used. + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (!(value is bool)) throw new ArgumentException("Invalid argument type. Expected argument: bool.", nameof(value)); + if (targetType != typeof(Visibility)) throw new ArgumentException("Invalid return type. Expected type: Visibility", nameof(targetType)); + var val = !(bool)value; + if (val) return Visibility.Visible; + return parameter is Visibility ? parameter : Visibility.Collapsed; + } - /// - /// Converts an inverted value into a bool value. - /// The value that is produced by the binding target. - /// The type to convert to. - /// The converter parameter to use. - /// The culture to use in the converter. - /// A converted value. If the method returns null, the valid null value is used. - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (!(value is Visibility)) throw new ArgumentException("Invalid argument type. Expected argument: Visibility.", nameof(value)); - if (targetType != typeof(bool)) throw new ArgumentException("Invalid return type. Expected type: bool", nameof(targetType)); - Visibility val = (Visibility)value; - return val != Visibility.Visible; - } - } + /// + /// Converts an inverted value into a bool value. + /// The value that is produced by the binding target. + /// The type to convert to. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. If the method returns null, the valid null value is used. + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (!(value is Visibility)) throw new ArgumentException("Invalid argument type. Expected argument: Visibility.", nameof(value)); + if (targetType != typeof(bool)) throw new ArgumentException("Invalid return type. Expected type: bool", nameof(targetType)); + Visibility val = (Visibility)value; + return val != Visibility.Visible; + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return ConverterCreater.Get(); + } + } } diff --git a/source/Components/AvalonDock/Converters/LayoutItemFromLayoutModelConverter.cs b/source/Components/AvalonDock/Converters/LayoutItemFromLayoutModelConverter.cs index 4fa3d134..be9b3549 100644 --- a/source/Components/AvalonDock/Converters/LayoutItemFromLayoutModelConverter.cs +++ b/source/Components/AvalonDock/Converters/LayoutItemFromLayoutModelConverter.cs @@ -9,59 +9,63 @@ This program is provided to you under the terms of the Microsoft Public using System; using System.Windows.Data; +using System.Windows.Markup; using AvalonDock.Layout; namespace AvalonDock.Converters { - /// - /// Converts a into a - /// and ensures that other essential properties (Root, Root.Manager) are available. - /// - /// Returns null or Binding.DoNothing otherwise. - /// - public class LayoutItemFromLayoutModelConverter : IValueConverter - { - /// - /// Converts a into a - /// and ensures that other essential properties (Root, Root.Manager) are available. - /// - /// Returns null or Binding.DoNothing otherwise. - /// - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// A converted value. - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - var layoutModel = value as LayoutContent; - if (layoutModel == null) - return null; + /// + /// Converts a into a + /// and ensures that other essential properties (Root, Root.Manager) are available. + /// + /// Returns null or Binding.DoNothing otherwise. + /// + public class LayoutItemFromLayoutModelConverter : MarkupExtension, IValueConverter + { + /// + /// Converts a into a + /// and ensures that other essential properties (Root, Root.Manager) are available. + /// + /// Returns null or Binding.DoNothing otherwise. + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (!(value is LayoutContent layoutModel)) + return null; - if (layoutModel.Root == null) - return null; + if (layoutModel.Root == null) + return null; - if (layoutModel.Root.Manager == null) - return null; + if (layoutModel.Root.Manager == null) + return null; - var layoutItemModel = layoutModel.Root.Manager.GetLayoutItemFromModel(layoutModel); - if (layoutItemModel == null) - return Binding.DoNothing; + if (layoutModel.Root.Manager.GetLayoutItemFromModel(layoutModel) == null) + return Binding.DoNothing; - return layoutItemModel; - } + return layoutModel.Root.Manager.GetLayoutItemFromModel(layoutModel); + } - /// - /// Method is not implemented and will raise when called. - /// - /// - /// - /// - /// - /// - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } - } + /// + /// Method is not implemented and will raise when called. + /// + /// + /// + /// + /// + /// + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return ConverterCreater.Get(); + } + } } diff --git a/source/Components/AvalonDock/Converters/NullToDoNothingConverter.cs b/source/Components/AvalonDock/Converters/NullToDoNothingConverter.cs index 86a7bd05..c8a6ee81 100644 --- a/source/Components/AvalonDock/Converters/NullToDoNothingConverter.cs +++ b/source/Components/AvalonDock/Converters/NullToDoNothingConverter.cs @@ -9,41 +9,47 @@ This program is provided to you under the terms of the Microsoft Public using System; using System.Windows.Data; +using System.Windows.Markup; namespace AvalonDock.Converters { - /// - /// Converts any null value into Binding.DoNothing and returns the bound value, otherwise. - /// - public class NullToDoNothingConverter : IValueConverter - { - /// - /// Converts any null value into Binding.DoNothing and returns the bound value, otherwise. - /// - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// A converted value. - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (value == null) - return Binding.DoNothing; + /// + /// Converts any null value into Binding.DoNothing and returns the bound value, otherwise. + /// + public class NullToDoNothingConverter : MarkupExtension, IValueConverter + { + /// + /// Converts any null value into Binding.DoNothing and returns the bound value, otherwise. + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (value == null) + return Binding.DoNothing; - return value; - } + return value; + } - /// - /// Method is not implemented and will raise when called. - /// - /// - /// - /// - /// - /// - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } - } + /// + /// Method is not implemented and will raise when called. + /// + /// + /// + /// + /// + /// + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return ConverterCreater.Get(); + } + } } diff --git a/source/Components/AvalonDock/Converters/OverlayWindowToVisibilityConverter.cs b/source/Components/AvalonDock/Converters/OverlayWindowToVisibilityConverter.cs index 2804c1a0..1dc6a76c 100644 --- a/source/Components/AvalonDock/Converters/OverlayWindowToVisibilityConverter.cs +++ b/source/Components/AvalonDock/Converters/OverlayWindowToVisibilityConverter.cs @@ -10,46 +10,52 @@ This program is provided to you under the terms of the Microsoft Public using System; using System.Windows; using System.Windows.Data; +using System.Windows.Markup; using AvalonDock.Controls; using AvalonDock.Layout; namespace AvalonDock.Converters { - /// - /// Converts a into a - /// and ensures that other essential properties (Root, Root.Manager) are available. - /// - /// Returns null or Binding.DoNothing otherwise. - /// - public class OverlayWindowToVisibilityConverter : IValueConverter - { - /// - /// Converts a into a . - /// - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// A converted value. - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - bool isHostedInFloatingWindow = value is OverlayWindow overlayWindow && overlayWindow.IsHostedInFloatingWindow; - if (parameter == null || !bool.TryParse(parameter.ToString(), out bool isLarge)) - { - isLarge = false; - } + /// + /// Converts a into a + /// and ensures that other essential properties (Root, Root.Manager) are available. + /// + /// Returns null or Binding.DoNothing otherwise. + /// + public class OverlayWindowToVisibilityConverter : MarkupExtension, IValueConverter + { + /// + /// Converts a into a . + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + bool isHostedInFloatingWindow = value is OverlayWindow overlayWindow && overlayWindow.IsHostedInFloatingWindow; + if (parameter == null || !bool.TryParse(parameter.ToString(), out bool isLarge)) + { + isLarge = false; + } - return isHostedInFloatingWindow && isLarge ? Visibility.Hidden : Visibility.Visible; - } + return isHostedInFloatingWindow && isLarge ? Visibility.Hidden : Visibility.Visible; + } - /// - /// Method is not implemented and will raise when called. - /// - /// The value that is produced by the binding target. - /// The type to convert to. - /// The converter parameter to use. - /// The culture to use in the converter. - /// - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) => throw new NotSupportedException(); - } + /// + /// Method is not implemented and will raise when called. + /// + /// The value that is produced by the binding target. + /// The type to convert to. + /// The converter parameter to use. + /// The culture to use in the converter. + /// + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) => throw new NotSupportedException(); + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return ConverterCreater.Get(); + } + } } diff --git a/source/Components/AvalonDock/Converters/UriSourceToBitmapImageConverter.cs b/source/Components/AvalonDock/Converters/UriSourceToBitmapImageConverter.cs index f0ddb0e2..86ef8ca2 100644 --- a/source/Components/AvalonDock/Converters/UriSourceToBitmapImageConverter.cs +++ b/source/Components/AvalonDock/Converters/UriSourceToBitmapImageConverter.cs @@ -11,47 +11,53 @@ This program is provided to you under the terms of the Microsoft Public using System.Windows.Data; using System.Windows.Media.Imaging; using System.Windows.Controls; +using System.Windows.Markup; namespace AvalonDock.Converters { - /// - /// Converts a object into a corresponding object - /// that is expected to be available at the given target of the uri. - /// - /// Returns null or Binding.DoNothing otherwise. - /// - public class UriSourceToBitmapImageConverter : IValueConverter - { - /// - /// Converts a object into a corresponding object - /// that is expected to be available at the given target of the uri. - /// - /// Returns null or Binding.DoNothing otherwise. - /// - /// The value produced by the binding source. - /// The type of the binding target property. - /// The converter parameter to use. - /// The culture to use in the converter. - /// A converted value. - public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - if (value == null) - return Binding.DoNothing; + /// + /// Converts a object into a corresponding object + /// that is expected to be available at the given target of the uri. + /// + /// Returns null or Binding.DoNothing otherwise. + /// + public class UriSourceToBitmapImageConverter : MarkupExtension, IValueConverter + { + /// + /// Converts a object into a corresponding object + /// that is expected to be available at the given target of the uri. + /// + /// Returns null or Binding.DoNothing otherwise. + /// + /// The value produced by the binding source. + /// The type of the binding target property. + /// The converter parameter to use. + /// The culture to use in the converter. + /// A converted value. + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (value == null) + return Binding.DoNothing; - return new Image() { Source = new BitmapImage((Uri)value) }; - } + return new Image() { Source = new BitmapImage((Uri)value) }; + } - /// - /// Method is not implemented and will raise when called. - /// - /// - /// - /// - /// - /// - public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) - { - throw new NotImplementedException(); - } - } + /// + /// Method is not implemented and will raise when called. + /// + /// + /// + /// + /// + /// + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + + public override object ProvideValue(IServiceProvider serviceProvider) + { + return ConverterCreater.Get(); + } + } } diff --git a/source/Components/AvalonDock/DockingManager.cs b/source/Components/AvalonDock/DockingManager.cs index b50dc10d..599b655b 100644 --- a/source/Components/AvalonDock/DockingManager.cs +++ b/source/Components/AvalonDock/DockingManager.cs @@ -24,857 +24,858 @@ This program is provided to you under the terms of the Microsoft Public using System.Windows.Threading; using AvalonDock.Themes; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace AvalonDock { - /// - /// - /// - /// The is the custom control at the root of the visual tree. - /// This control is the core control of AvalonDock. - /// It contains core dependency properties, events, and methods to customize and - /// manage many aspects of the docking framework. - /// - /// - /// - [ContentProperty(nameof(Layout))] - [TemplatePart(Name = "PART_AutoHideArea")] - public class DockingManager : Control, IOverlayWindowHost//, ILogicalChildrenContainer - { - #region fields - private ResourceDictionary currentThemeResourceDictionary; // = null - private AutoHideWindowManager _autoHideWindowManager; - private FrameworkElement _autohideArea; - private List _fwList = new List(); - private List _fwHiddenList = new List(); - private OverlayWindow _overlayWindow = null; - private List _areas = null; - private bool _insideInternalSetActiveContent = false; - - // Collection of LayoutDocumentItems & LayoutAnchorableItems attached to their corresponding - // LayoutDocument & LayoutAnchorable - private List _layoutItems = new List(); - - private bool _suspendLayoutItemCreation = false; - private DispatcherOperation _collectLayoutItemsOperations = null; - private NavigatorWindow _navigatorWindow = null; - - internal bool SuspendDocumentsSourceBinding = false; - internal bool SuspendAnchorablesSourceBinding = false; - #endregion fields - - #region Constructors - /// - /// Static class constructor to support WPF property control registration. - /// - static DockingManager() - { - DefaultStyleKeyProperty.OverrideMetadata(typeof(DockingManager), new FrameworkPropertyMetadata(typeof(DockingManager))); - FocusableProperty.OverrideMetadata(typeof(DockingManager), new FrameworkPropertyMetadata(false)); - HwndSource.DefaultAcquireHwndFocusInMenuMode = false; - } - - /// - /// Class constructor. - /// - public DockingManager() - { - IsVirtualizingDocument = true; - IsVirtualizingAnchorable = true; + /// + /// + /// + /// The is the custom control at the root of the visual tree. + /// This control is the core control of AvalonDock. + /// It contains core dependency properties, events, and methods to customize and + /// manage many aspects of the docking framework. + /// + /// + /// + [ContentProperty(nameof(Layout))] + [TemplatePart(Name = "PART_AutoHideArea")] + public class DockingManager : Control, IOverlayWindowHost//, ILogicalChildrenContainer + { + #region fields + private ResourceDictionary currentThemeResourceDictionary; // = null + private AutoHideWindowManager _autoHideWindowManager; + private FrameworkElement _autohideArea; + private readonly List _fwList = new List(); + private readonly List _fwHiddenList = new List(); + private OverlayWindow _overlayWindow = null; + private List _areas = null; + private bool _insideInternalSetActiveContent = false; + + // Collection of LayoutDocumentItems & LayoutAnchorableItems attached to their corresponding + // LayoutDocument & LayoutAnchorable + private readonly List _layoutItems = new List(); + + private bool _suspendLayoutItemCreation = false; + private DispatcherOperation _collectLayoutItemsOperations = null; + private NavigatorWindow _navigatorWindow = null; + + internal bool SuspendDocumentsSourceBinding = false; + internal bool SuspendAnchorablesSourceBinding = false; + #endregion fields + + #region Constructors + /// + /// Static class constructor to support WPF property control registration. + /// + static DockingManager() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(DockingManager), new FrameworkPropertyMetadata(typeof(DockingManager))); + FocusableProperty.OverrideMetadata(typeof(DockingManager), new FrameworkPropertyMetadata(false)); + HwndSource.DefaultAcquireHwndFocusInMenuMode = false; + } + + /// + /// Class constructor. + /// + public DockingManager() + { + IsVirtualizingDocument = true; + IsVirtualizingAnchorable = true; #if !VS2008 - Layout = new LayoutRoot { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) }; + Layout = new LayoutRoot { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) }; #else this.SetCurrentValue( DockingManager.LayoutProperty, new LayoutRoot() { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) } ); #endif - Loaded += DockingManager_Loaded; - Unloaded += DockingManager_Unloaded; - } - - #endregion Constructors - - #region Events - - /// Event fired when property changes. - /// - public event EventHandler LayoutChanged; - - /// Event fired when property is about to be changed. - /// - public event EventHandler LayoutChanging; - - /// Event fired when a document is about to be closed. - /// Subscribers have the opportunity to cancel the operation. - public event EventHandler DocumentClosing; - - /// Event fired after a document is closed. - public event EventHandler DocumentClosed; - - /// Event is raised when changes. - /// - public event EventHandler ActiveContentChanged; - - #endregion Events - - #region Public Properties - - #region Layout - - /// dependency property. - public static readonly DependencyProperty LayoutProperty = DependencyProperty.Register(nameof(Layout), typeof(LayoutRoot), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnLayoutChanged, CoerceLayoutValue)); - - /// Gets or sets the property. This dependency property indicates layout tree. - public LayoutRoot Layout - { - get => (LayoutRoot)GetValue(LayoutProperty); - set => SetValue(LayoutProperty, value); - } - - /// Coerces the value. - private static object CoerceLayoutValue(DependencyObject d, object value) - { - if (value == null) return new LayoutRoot { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) }; - ((DockingManager)d).OnLayoutChanging(value as LayoutRoot); - return value; - } - - /// Handles changes to the property. - private static void OnLayoutChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLayoutChanged(e.OldValue as LayoutRoot, e.NewValue as LayoutRoot); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnLayoutChanged(LayoutRoot oldLayout, LayoutRoot newLayout) - { - if (oldLayout != null) - { - oldLayout.PropertyChanged -= OnLayoutRootPropertyChanged; - oldLayout.Updated -= OnLayoutRootUpdated; - } - - foreach (var fwc in _fwList.ToArray()) - { - fwc.KeepContentVisibleOnClose = true; - fwc.InternalClose(); - } - - _fwList.Clear(); - - foreach (var fwc in _fwHiddenList.ToArray()) - { - fwc.InternalClose(); - } - - _fwHiddenList.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.ToArray()) - { - if (fw.Model is LayoutAnchorableFloatingWindow window && window.RootPanel.IsMaximized) - { - fw.WindowState = WindowState.Normal; - fw.Show(); - fw.WindowState = WindowState.Maximized; - } - else - { - if (fw.Content != null || (fw.Model as LayoutAnchorableFloatingWindow)?.IsVisible == true) - fw.Show(); - else - fw.Hide(); - } - - //fw.Owner = Window.GetWindow(this); - //fw.SetParentToMainWindowOf(this); - } - - // In order to prevent resource leaks, unsubscribe from SizeChanged event for case when user call loading of Layout Settigns. - SizeChanged -= OnSizeChanged; - SizeChanged += OnSizeChanged; - } - - if (newLayout != null) - { - newLayout.PropertyChanged += OnLayoutRootPropertyChanged; - newLayout.Updated += OnLayoutRootUpdated; - } - - LayoutChanged?.Invoke(this, EventArgs.Empty); - // Layout?.CollectGarbage(); - CommandManager.InvalidateRequerySuggested(); - } - - #endregion Layout - - #region LayoutUpdateStrategy - - /// dependency property. - public static readonly DependencyProperty LayoutUpdateStrategyProperty = DependencyProperty.Register(nameof(LayoutUpdateStrategy), typeof(ILayoutUpdateStrategy), typeof(DockingManager), - new FrameworkPropertyMetadata((ILayoutUpdateStrategy)null)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the strategy class to call when AvalonDock needs to positionate a LayoutAnchorable inside an existing layout. - /// - /// Sometimes it's impossible to automatically insert an anchorable in the layout without specifing the target parent pane. - /// Set this property to an object that will be asked to insert the anchorable to the desidered position. - public ILayoutUpdateStrategy LayoutUpdateStrategy - { - get => (ILayoutUpdateStrategy)GetValue(LayoutUpdateStrategyProperty); - set => SetValue(LayoutUpdateStrategyProperty, value); - } - - #endregion LayoutUpdateStrategy - - #region DocumentPaneTemplate - - /// dependency property. - public static readonly DependencyProperty DocumentPaneTemplateProperty = DependencyProperty.Register(nameof(DocumentPaneTemplate), typeof(ControlTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnDocumentPaneTemplateChanged)); - - /// - /// Gets or sets the property. This dependency property - /// indicates . - /// - public ControlTemplate DocumentPaneTemplate - { - get => (ControlTemplate)GetValue(DocumentPaneTemplateProperty); - set => SetValue(DocumentPaneTemplateProperty, value); - } - - /// Handles changes to the property. - private static void OnDocumentPaneTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).OnDocumentPaneTemplateChanged(e); - } - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnDocumentPaneTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - #endregion DocumentPaneTemplate - - #region AnchorablePaneTemplate - - /// - /// dependency property - /// - public static readonly DependencyProperty AnchorablePaneTemplateProperty = DependencyProperty.Register(nameof(AnchorablePaneTemplate), typeof(ControlTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnAnchorablePaneTemplateChanged)); - - /// - /// Gets or sets the property. This dependency property - /// indicates .... - /// - public ControlTemplate AnchorablePaneTemplate - { - get => (ControlTemplate)GetValue(AnchorablePaneTemplateProperty); - set => SetValue(AnchorablePaneTemplateProperty, value); - } - - /// Handles changes to the property. - private static void OnAnchorablePaneTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorablePaneTemplateChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnAnchorablePaneTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - #endregion AnchorablePaneTemplate - - #region AnchorSideTemplate - - /// The dependency property. - public static readonly DependencyProperty AnchorSideTemplateProperty = DependencyProperty.Register(nameof(AnchorSideTemplate), typeof(ControlTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((ControlTemplate)null)); - - /// - /// Gets or sets the property. This dependency property - /// indicates .... - /// - public ControlTemplate AnchorSideTemplate - { - get => (ControlTemplate)GetValue(AnchorSideTemplateProperty); - set => SetValue(AnchorSideTemplateProperty, value); - } - - #endregion AnchorSideTemplate - - #region AnchorGroupTemplate - - /// dependency property. - public static readonly DependencyProperty AnchorGroupTemplateProperty = DependencyProperty.Register(nameof(AnchorGroupTemplate), typeof(ControlTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((ControlTemplate)null)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the template used to render the AnchorGroup control. - /// - public ControlTemplate AnchorGroupTemplate - { - get => (ControlTemplate)GetValue(AnchorGroupTemplateProperty); - set => SetValue(AnchorGroupTemplateProperty, value); - } - - #endregion AnchorGroupTemplate - - #region AnchorTemplate - - /// dependency property. - public static readonly DependencyProperty AnchorTemplateProperty = DependencyProperty.Register(nameof(AnchorTemplate), typeof(ControlTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((ControlTemplate)null)); - - /// - /// Gets or sets the property. This dependency property - /// indicates .... - /// - public ControlTemplate AnchorTemplate - { - get => (ControlTemplate)GetValue(AnchorTemplateProperty); - set => SetValue(AnchorTemplateProperty, value); - } - - #endregion AnchorTemplate - - #region DocumentPaneControlStyle - - /// dependency property. - public static readonly DependencyProperty DocumentPaneControlStyleProperty = DependencyProperty.Register(nameof(DocumentPaneControlStyle), typeof(Style), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnDocumentPaneControlStyleChanged)); - - /// - /// Gets or sets the property. This dependency property - /// indicates .... - /// - public Style DocumentPaneControlStyle - { - get => (Style)GetValue(DocumentPaneControlStyleProperty); - set => SetValue(DocumentPaneControlStyleProperty, value); - } - - /// Handles changes to the DocumentPaneControlStyle property. - private static void OnDocumentPaneControlStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentPaneControlStyleChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnDocumentPaneControlStyleChanged(DependencyPropertyChangedEventArgs e) - { - } - - #endregion DocumentPaneControlStyle - - #region AnchorablePaneControlStyle - - /// dependency property. - public static readonly DependencyProperty AnchorablePaneControlStyleProperty = DependencyProperty.Register(nameof(AnchorablePaneControlStyle), typeof(Style), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnAnchorablePaneControlStyleChanged)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the style to apply to AnchorablePaneControl. - /// - public Style AnchorablePaneControlStyle - { - get => (Style)GetValue(AnchorablePaneControlStyleProperty); - set => SetValue(AnchorablePaneControlStyleProperty, value); - } - - /// Handles changes to the property. - private static void OnAnchorablePaneControlStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorablePaneControlStyleChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnAnchorablePaneControlStyleChanged(DependencyPropertyChangedEventArgs e) - { - } - - #endregion AnchorablePaneControlStyle - - #region DocumentHeaderTemplate - - /// dependency property. - public static readonly DependencyProperty DocumentHeaderTemplateProperty = DependencyProperty.Register(nameof(DocumentHeaderTemplate), typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplate)null, OnDocumentHeaderTemplateChanged, CoerceDocumentHeaderTemplateValue)); - - /// - /// Gets or sets the property. This dependency property - /// indicates data template to use for document header. - /// - public DataTemplate DocumentHeaderTemplate - { - get => (DataTemplate)GetValue(DocumentHeaderTemplateProperty); - set => SetValue(DocumentHeaderTemplateProperty, value); - } - - /// Handles changes to the property. - private static void OnDocumentHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentHeaderTemplateChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnDocumentHeaderTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// Coerces the value. - private static object CoerceDocumentHeaderTemplateValue(DependencyObject d, object value) - { - if (value != null && d.GetValue(DocumentHeaderTemplateSelectorProperty) != null) - return null; - return value; - } - - #endregion DocumentHeaderTemplate - - #region DocumentHeaderTemplateSelector - - /// dependency property. - public static readonly DependencyProperty DocumentHeaderTemplateSelectorProperty = DependencyProperty.Register(nameof(DocumentHeaderTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnDocumentHeaderTemplateSelectorChanged, CoerceDocumentHeaderTemplateSelectorValue)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the template selector that is used when selecting the data template for the header. - /// - public DataTemplateSelector DocumentHeaderTemplateSelector - { - get => (DataTemplateSelector)GetValue(DocumentHeaderTemplateSelectorProperty); - set => SetValue(DocumentHeaderTemplateSelectorProperty, value); - } - - /// Handles changes to the property. - private static void OnDocumentHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentHeaderTemplateSelectorChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnDocumentHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null && DocumentHeaderTemplate != null) - DocumentHeaderTemplate = null; - if (DocumentPaneMenuItemHeaderTemplateSelector == null) - DocumentPaneMenuItemHeaderTemplateSelector = DocumentHeaderTemplateSelector; - } - - /// Coerces the value. - private static object CoerceDocumentHeaderTemplateSelectorValue(DependencyObject d, object value) => value; - - #endregion DocumentHeaderTemplateSelector - - #region DocumentTitleTemplate - - /// dependency property. - public static readonly DependencyProperty DocumentTitleTemplateProperty = DependencyProperty.Register(nameof(DocumentTitleTemplate), typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnDocumentTitleTemplateChanged, CoerceDocumentTitleTemplateValue)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the data template to use when creating the title for a document. - /// - public DataTemplate DocumentTitleTemplate - { - get => (DataTemplate)GetValue(DocumentTitleTemplateProperty); - set => SetValue(DocumentTitleTemplateProperty, value); - } - - /// Handles changes to the property. - private static void OnDocumentTitleTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentTitleTemplateChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnDocumentTitleTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// Coerces the value. - private static object CoerceDocumentTitleTemplateValue(DependencyObject d, object value) - { - if (value != null && d.GetValue(DocumentTitleTemplateSelectorProperty) != null) - return null; - return value; - } - - #endregion DocumentTitleTemplate - - #region DocumentTitleTemplateSelector - - /// dependency property. - public static readonly DependencyProperty DocumentTitleTemplateSelectorProperty = DependencyProperty.Register(nameof(DocumentTitleTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnDocumentTitleTemplateSelectorChanged, CoerceDocumentTitleTemplateSelectorValue)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the data template selector to use when creating the data template for the title. - /// - public DataTemplateSelector DocumentTitleTemplateSelector - { - get => (DataTemplateSelector)GetValue(DocumentTitleTemplateSelectorProperty); - set => SetValue(DocumentTitleTemplateSelectorProperty, value); - } - - /// Handles changes to the property. - private static void OnDocumentTitleTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentTitleTemplateSelectorChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnDocumentTitleTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null) - DocumentTitleTemplate = null; - } - - /// Coerces the value. - private static object CoerceDocumentTitleTemplateSelectorValue(DependencyObject d, object value) => value; - - #endregion DocumentTitleTemplateSelector - - #region AnchorableTitleTemplate - - /// dependency property. - public static readonly DependencyProperty AnchorableTitleTemplateProperty = DependencyProperty.Register(nameof(AnchorableTitleTemplate), typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplate)null, OnAnchorableTitleTemplateChanged, CoerceAnchorableTitleTemplateValue)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the data template to use for anchorables title. - /// - public DataTemplate AnchorableTitleTemplate - { - get => (DataTemplate)GetValue(AnchorableTitleTemplateProperty); - set => SetValue(AnchorableTitleTemplateProperty, value); - } - - /// Handles changes to the property. - private static void OnAnchorableTitleTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorableTitleTemplateChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnAnchorableTitleTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// Coerces the value. - private static object CoerceAnchorableTitleTemplateValue(DependencyObject d, object value) - { - if (value != null && d.GetValue(AnchorableTitleTemplateSelectorProperty) != null) - return null; - return value; - } - - #endregion AnchorableTitleTemplate - - #region AnchorableTitleTemplateSelector - - /// dependency property. - public static readonly DependencyProperty AnchorableTitleTemplateSelectorProperty = DependencyProperty.Register(nameof(AnchorableTitleTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnAnchorableTitleTemplateSelectorChanged)); - - /// - /// Gets or sets the property. This dependency property - /// indicates which selector to use when selecting data template for the title of anchorables. - /// - public DataTemplateSelector AnchorableTitleTemplateSelector - { - get => (DataTemplateSelector)GetValue(AnchorableTitleTemplateSelectorProperty); - set => SetValue(AnchorableTitleTemplateSelectorProperty, value); - } - - /// Handles changes to the property. - private static void OnAnchorableTitleTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorableTitleTemplateSelectorChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnAnchorableTitleTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null && AnchorableTitleTemplate != null) - AnchorableTitleTemplate = null; - } - - #endregion AnchorableTitleTemplateSelector - - #region AnchorableHeaderTemplate - - /// dependency property. - public static readonly DependencyProperty AnchorableHeaderTemplateProperty = DependencyProperty.Register(nameof(AnchorableHeaderTemplate), typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnAnchorableHeaderTemplateChanged, CoerceAnchorableHeaderTemplateValue)); - - /// Gets or sets the property. This dependency property indicates the data template to use for anchorable templates. - public DataTemplate AnchorableHeaderTemplate - { - get => (DataTemplate)GetValue(AnchorableHeaderTemplateProperty); - set => SetValue(AnchorableHeaderTemplateProperty, value); - } - - /// Handles changes to the property. - private static void OnAnchorableHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorableHeaderTemplateChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnAnchorableHeaderTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// Coerces the value. - private static object CoerceAnchorableHeaderTemplateValue(DependencyObject d, object value) - { - if (value != null && d.GetValue(AnchorableHeaderTemplateSelectorProperty) != null) - return null; - return value; - } - - #endregion AnchorableHeaderTemplate - - #region AnchorableHeaderTemplateSelector - - /// dependency property. - public static readonly DependencyProperty AnchorableHeaderTemplateSelectorProperty = DependencyProperty.Register(nameof(AnchorableHeaderTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplateSelector)null, OnAnchorableHeaderTemplateSelectorChanged)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the selector to use when selecting the data template for anchorable headers. - /// - public DataTemplateSelector AnchorableHeaderTemplateSelector - { - get => (DataTemplateSelector)GetValue(AnchorableHeaderTemplateSelectorProperty); - set => SetValue(AnchorableHeaderTemplateSelectorProperty, value); - } - - /// Handles changes to the property. - private static void OnAnchorableHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorableHeaderTemplateSelectorChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnAnchorableHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null) - AnchorableHeaderTemplate = null; - } + Loaded += DockingManager_Loaded; + Unloaded += DockingManager_Unloaded; + } + + #endregion Constructors - #endregion AnchorableHeaderTemplateSelector - - #region LayoutRootPanel - - /// dependency property. - public static readonly DependencyProperty LayoutRootPanelProperty = DependencyProperty.Register(nameof(LayoutRootPanel), typeof(LayoutPanelControl), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnLayoutRootPanelChanged)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the layout panel control which is attached to the Layout.Root property. - /// - public LayoutPanelControl LayoutRootPanel - { - get => (LayoutPanelControl)GetValue(LayoutRootPanelProperty); - set => SetValue(LayoutRootPanelProperty, value); - } - - /// Handles changes to the property. - private static void OnLayoutRootPanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLayoutRootPanelChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnLayoutRootPanelChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - InternalRemoveLogicalChild(e.OldValue); - if (e.NewValue != null) - InternalAddLogicalChild(e.NewValue); - } - - #endregion LayoutRootPanel - - #region RightSidePanel - - /// dependency property. - public static readonly DependencyProperty RightSidePanelProperty = DependencyProperty.Register(nameof(RightSidePanel), typeof(LayoutAnchorSideControl), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnRightSidePanelChanged)); - - /// Gets or sets the property. This dependency property indicates right side anchor panel. - public LayoutAnchorSideControl RightSidePanel - { - get => (LayoutAnchorSideControl)GetValue(RightSidePanelProperty); - set => SetValue(RightSidePanelProperty, value); - } - - /// Handles changes to the property. - private static void OnRightSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnRightSidePanelChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnRightSidePanelChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - InternalRemoveLogicalChild(e.OldValue); - if (e.NewValue != null) - InternalAddLogicalChild(e.NewValue); - } - - #endregion RightSidePanel - - #region LeftSidePanel - - /// dependency property. - public static readonly DependencyProperty LeftSidePanelProperty = DependencyProperty.Register(nameof(LeftSidePanel), typeof(LayoutAnchorSideControl), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnLeftSidePanelChanged)); - - /// Gets or sets the property. This dependency property indicates the left side panel control. - public LayoutAnchorSideControl LeftSidePanel - { - get => (LayoutAnchorSideControl)GetValue(LeftSidePanelProperty); - set => SetValue(LeftSidePanelProperty, value); - } - - /// Handles changes to the property. - private static void OnLeftSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLeftSidePanelChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnLeftSidePanelChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - InternalRemoveLogicalChild(e.OldValue); - if (e.NewValue != null) - InternalAddLogicalChild(e.NewValue); - } - - #endregion LeftSidePanel - - #region TopSidePanel - - /// dependency property. - public static readonly DependencyProperty TopSidePanelProperty = DependencyProperty.Register(nameof(TopSidePanel), typeof(LayoutAnchorSideControl), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnTopSidePanelChanged)); - - /// Gets or sets the property. This dependency property indicates top side control panel. - public LayoutAnchorSideControl TopSidePanel - { - get => (LayoutAnchorSideControl)GetValue(TopSidePanelProperty); - set => SetValue(TopSidePanelProperty, value); - } - - /// Handles changes to the property. - private static void OnTopSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnTopSidePanelChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnTopSidePanelChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - InternalRemoveLogicalChild(e.OldValue); - if (e.NewValue != null) - InternalAddLogicalChild(e.NewValue); - } - - #endregion TopSidePanel - - #region BottomSidePanel - - /// dependency property. - public static readonly DependencyProperty BottomSidePanelProperty = DependencyProperty.Register(nameof(BottomSidePanel), typeof(LayoutAnchorSideControl), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnBottomSidePanelChanged)); - - /// Gets or sets the property. This dependency property indicates bottom side panel control. - public LayoutAnchorSideControl BottomSidePanel - { - get => (LayoutAnchorSideControl)GetValue(BottomSidePanelProperty); - set => SetValue(BottomSidePanelProperty, value); - } + #region Events + + /// Event fired when property changes. + /// + public event EventHandler LayoutChanged; + + /// Event fired when property is about to be changed. + /// + public event EventHandler LayoutChanging; + + /// Event fired when a document is about to be closed. + /// Subscribers have the opportunity to cancel the operation. + public event EventHandler DocumentClosing; + + /// Event fired after a document is closed. + public event EventHandler DocumentClosed; + + /// Event is raised when changes. + /// + public event EventHandler ActiveContentChanged; + + #endregion Events + + #region Public Properties + + #region Layout + + /// dependency property. + public static readonly DependencyProperty LayoutProperty = DependencyProperty.Register(nameof(Layout), typeof(LayoutRoot), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnLayoutChanged, CoerceLayoutValue)); + + /// Gets or sets the property. This dependency property indicates layout tree. + public LayoutRoot Layout + { + get => (LayoutRoot)GetValue(LayoutProperty); + set => SetValue(LayoutProperty, value); + } + + /// Coerces the value. + private static object CoerceLayoutValue(DependencyObject d, object value) + { + if (value == null) return new LayoutRoot { RootPanel = new LayoutPanel(new LayoutDocumentPaneGroup(new LayoutDocumentPane())) }; + ((DockingManager)d).OnLayoutChanging(value as LayoutRoot); + return value; + } + + /// Handles changes to the property. + private static void OnLayoutChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLayoutChanged(e.OldValue as LayoutRoot, e.NewValue as LayoutRoot); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnLayoutChanged(LayoutRoot oldLayout, LayoutRoot newLayout) + { + if (oldLayout != null) + { + oldLayout.PropertyChanged -= OnLayoutRootPropertyChanged; + oldLayout.Updated -= OnLayoutRootUpdated; + } + + foreach (var fwc in _fwList.ToArray()) + { + fwc.KeepContentVisibleOnClose = true; + fwc.InternalClose(); + } + + _fwList.Clear(); + + foreach (var fwc in _fwHiddenList.ToArray()) + { + fwc.InternalClose(); + } + + _fwHiddenList.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.ToArray()) + { + if (fw.Model is LayoutAnchorableFloatingWindow window && window.RootPanel.IsMaximized) + { + fw.WindowState = WindowState.Normal; + fw.Show(); + fw.WindowState = WindowState.Maximized; + } + else + { + if (fw.Content != null || (fw.Model as LayoutAnchorableFloatingWindow)?.IsVisible == true) + fw.Show(); + else + fw.Hide(); + } + + //fw.Owner = Window.GetWindow(this); + //fw.SetParentToMainWindowOf(this); + } + + // In order to prevent resource leaks, unsubscribe from SizeChanged event for case when user call loading of Layout Settigns. + SizeChanged -= OnSizeChanged; + SizeChanged += OnSizeChanged; + } + + if (newLayout != null) + { + newLayout.PropertyChanged += OnLayoutRootPropertyChanged; + newLayout.Updated += OnLayoutRootUpdated; + } + + LayoutChanged?.Invoke(this, EventArgs.Empty); + // Layout?.CollectGarbage(); + CommandManager.InvalidateRequerySuggested(); + } + + #endregion Layout + + #region LayoutUpdateStrategy + + /// dependency property. + public static readonly DependencyProperty LayoutUpdateStrategyProperty = DependencyProperty.Register(nameof(LayoutUpdateStrategy), typeof(ILayoutUpdateStrategy), typeof(DockingManager), + new FrameworkPropertyMetadata((ILayoutUpdateStrategy)null)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the strategy class to call when AvalonDock needs to positionate a LayoutAnchorable inside an existing layout. + /// + /// Sometimes it's impossible to automatically insert an anchorable in the layout without specifing the target parent pane. + /// Set this property to an object that will be asked to insert the anchorable to the desidered position. + public ILayoutUpdateStrategy LayoutUpdateStrategy + { + get => (ILayoutUpdateStrategy)GetValue(LayoutUpdateStrategyProperty); + set => SetValue(LayoutUpdateStrategyProperty, value); + } + + #endregion LayoutUpdateStrategy + + #region DocumentPaneTemplate + + /// dependency property. + public static readonly DependencyProperty DocumentPaneTemplateProperty = DependencyProperty.Register(nameof(DocumentPaneTemplate), typeof(ControlTemplate), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnDocumentPaneTemplateChanged)); + + /// + /// Gets or sets the property. This dependency property + /// indicates . + /// + public ControlTemplate DocumentPaneTemplate + { + get => (ControlTemplate)GetValue(DocumentPaneTemplateProperty); + set => SetValue(DocumentPaneTemplateProperty, value); + } + + /// Handles changes to the property. + private static void OnDocumentPaneTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((DockingManager)d).OnDocumentPaneTemplateChanged(e); + } + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnDocumentPaneTemplateChanged(DependencyPropertyChangedEventArgs e) + { + } + + #endregion DocumentPaneTemplate + + #region AnchorablePaneTemplate + + /// + /// dependency property + /// + public static readonly DependencyProperty AnchorablePaneTemplateProperty = DependencyProperty.Register(nameof(AnchorablePaneTemplate), typeof(ControlTemplate), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnAnchorablePaneTemplateChanged)); + + /// + /// Gets or sets the property. This dependency property + /// indicates .... + /// + public ControlTemplate AnchorablePaneTemplate + { + get => (ControlTemplate)GetValue(AnchorablePaneTemplateProperty); + set => SetValue(AnchorablePaneTemplateProperty, value); + } + + /// Handles changes to the property. + private static void OnAnchorablePaneTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorablePaneTemplateChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnAnchorablePaneTemplateChanged(DependencyPropertyChangedEventArgs e) + { + } + + #endregion AnchorablePaneTemplate + + #region AnchorSideTemplate + + /// The dependency property. + public static readonly DependencyProperty AnchorSideTemplateProperty = DependencyProperty.Register(nameof(AnchorSideTemplate), typeof(ControlTemplate), typeof(DockingManager), + new FrameworkPropertyMetadata((ControlTemplate)null)); + + /// + /// Gets or sets the property. This dependency property + /// indicates .... + /// + public ControlTemplate AnchorSideTemplate + { + get => (ControlTemplate)GetValue(AnchorSideTemplateProperty); + set => SetValue(AnchorSideTemplateProperty, value); + } + + #endregion AnchorSideTemplate + + #region AnchorGroupTemplate + + /// dependency property. + public static readonly DependencyProperty AnchorGroupTemplateProperty = DependencyProperty.Register(nameof(AnchorGroupTemplate), typeof(ControlTemplate), typeof(DockingManager), + new FrameworkPropertyMetadata((ControlTemplate)null)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the template used to render the AnchorGroup control. + /// + public ControlTemplate AnchorGroupTemplate + { + get => (ControlTemplate)GetValue(AnchorGroupTemplateProperty); + set => SetValue(AnchorGroupTemplateProperty, value); + } + + #endregion AnchorGroupTemplate + + #region AnchorTemplate + + /// dependency property. + public static readonly DependencyProperty AnchorTemplateProperty = DependencyProperty.Register(nameof(AnchorTemplate), typeof(ControlTemplate), typeof(DockingManager), + new FrameworkPropertyMetadata((ControlTemplate)null)); + + /// + /// Gets or sets the property. This dependency property + /// indicates .... + /// + public ControlTemplate AnchorTemplate + { + get => (ControlTemplate)GetValue(AnchorTemplateProperty); + set => SetValue(AnchorTemplateProperty, value); + } + + #endregion AnchorTemplate + + #region DocumentPaneControlStyle + + /// dependency property. + public static readonly DependencyProperty DocumentPaneControlStyleProperty = DependencyProperty.Register(nameof(DocumentPaneControlStyle), typeof(Style), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnDocumentPaneControlStyleChanged)); + + /// + /// Gets or sets the property. This dependency property + /// indicates .... + /// + public Style DocumentPaneControlStyle + { + get => (Style)GetValue(DocumentPaneControlStyleProperty); + set => SetValue(DocumentPaneControlStyleProperty, value); + } + + /// Handles changes to the DocumentPaneControlStyle property. + private static void OnDocumentPaneControlStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentPaneControlStyleChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnDocumentPaneControlStyleChanged(DependencyPropertyChangedEventArgs e) + { + } + + #endregion DocumentPaneControlStyle + + #region AnchorablePaneControlStyle + + /// dependency property. + public static readonly DependencyProperty AnchorablePaneControlStyleProperty = DependencyProperty.Register(nameof(AnchorablePaneControlStyle), typeof(Style), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnAnchorablePaneControlStyleChanged)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the style to apply to AnchorablePaneControl. + /// + public Style AnchorablePaneControlStyle + { + get => (Style)GetValue(AnchorablePaneControlStyleProperty); + set => SetValue(AnchorablePaneControlStyleProperty, value); + } + + /// Handles changes to the property. + private static void OnAnchorablePaneControlStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorablePaneControlStyleChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnAnchorablePaneControlStyleChanged(DependencyPropertyChangedEventArgs e) + { + } + + #endregion AnchorablePaneControlStyle + + #region DocumentHeaderTemplate + + /// dependency property. + public static readonly DependencyProperty DocumentHeaderTemplateProperty = DependencyProperty.Register(nameof(DocumentHeaderTemplate), typeof(DataTemplate), typeof(DockingManager), + new FrameworkPropertyMetadata((DataTemplate)null, OnDocumentHeaderTemplateChanged, CoerceDocumentHeaderTemplateValue)); + + /// + /// Gets or sets the property. This dependency property + /// indicates data template to use for document header. + /// + public DataTemplate DocumentHeaderTemplate + { + get => (DataTemplate)GetValue(DocumentHeaderTemplateProperty); + set => SetValue(DocumentHeaderTemplateProperty, value); + } + + /// Handles changes to the property. + private static void OnDocumentHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentHeaderTemplateChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnDocumentHeaderTemplateChanged(DependencyPropertyChangedEventArgs e) + { + } + + /// Coerces the value. + private static object CoerceDocumentHeaderTemplateValue(DependencyObject d, object value) + { + if (value != null && d.GetValue(DocumentHeaderTemplateSelectorProperty) != null) + return null; + return value; + } + + #endregion DocumentHeaderTemplate + + #region DocumentHeaderTemplateSelector + + /// dependency property. + public static readonly DependencyProperty DocumentHeaderTemplateSelectorProperty = DependencyProperty.Register(nameof(DocumentHeaderTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnDocumentHeaderTemplateSelectorChanged, CoerceDocumentHeaderTemplateSelectorValue)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the template selector that is used when selecting the data template for the header. + /// + public DataTemplateSelector DocumentHeaderTemplateSelector + { + get => (DataTemplateSelector)GetValue(DocumentHeaderTemplateSelectorProperty); + set => SetValue(DocumentHeaderTemplateSelectorProperty, value); + } + + /// Handles changes to the property. + private static void OnDocumentHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentHeaderTemplateSelectorChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnDocumentHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) + { + if (e.NewValue != null && DocumentHeaderTemplate != null) + DocumentHeaderTemplate = null; + if (DocumentPaneMenuItemHeaderTemplateSelector == null) + DocumentPaneMenuItemHeaderTemplateSelector = DocumentHeaderTemplateSelector; + } + + /// Coerces the value. + private static object CoerceDocumentHeaderTemplateSelectorValue(DependencyObject d, object value) => value; + + #endregion DocumentHeaderTemplateSelector + + #region DocumentTitleTemplate + + /// dependency property. + public static readonly DependencyProperty DocumentTitleTemplateProperty = DependencyProperty.Register(nameof(DocumentTitleTemplate), typeof(DataTemplate), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnDocumentTitleTemplateChanged, CoerceDocumentTitleTemplateValue)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the data template to use when creating the title for a document. + /// + public DataTemplate DocumentTitleTemplate + { + get => (DataTemplate)GetValue(DocumentTitleTemplateProperty); + set => SetValue(DocumentTitleTemplateProperty, value); + } + + /// Handles changes to the property. + private static void OnDocumentTitleTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentTitleTemplateChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnDocumentTitleTemplateChanged(DependencyPropertyChangedEventArgs e) + { + } + + /// Coerces the value. + private static object CoerceDocumentTitleTemplateValue(DependencyObject d, object value) + { + if (value != null && d.GetValue(DocumentTitleTemplateSelectorProperty) != null) + return null; + return value; + } + + #endregion DocumentTitleTemplate + + #region DocumentTitleTemplateSelector + + /// dependency property. + public static readonly DependencyProperty DocumentTitleTemplateSelectorProperty = DependencyProperty.Register(nameof(DocumentTitleTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnDocumentTitleTemplateSelectorChanged, CoerceDocumentTitleTemplateSelectorValue)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the data template selector to use when creating the data template for the title. + /// + public DataTemplateSelector DocumentTitleTemplateSelector + { + get => (DataTemplateSelector)GetValue(DocumentTitleTemplateSelectorProperty); + set => SetValue(DocumentTitleTemplateSelectorProperty, value); + } + + /// Handles changes to the property. + private static void OnDocumentTitleTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentTitleTemplateSelectorChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnDocumentTitleTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) + { + if (e.NewValue != null) + DocumentTitleTemplate = null; + } + + /// Coerces the value. + private static object CoerceDocumentTitleTemplateSelectorValue(DependencyObject d, object value) => value; + + #endregion DocumentTitleTemplateSelector + + #region AnchorableTitleTemplate + + /// dependency property. + public static readonly DependencyProperty AnchorableTitleTemplateProperty = DependencyProperty.Register(nameof(AnchorableTitleTemplate), typeof(DataTemplate), typeof(DockingManager), + new FrameworkPropertyMetadata((DataTemplate)null, OnAnchorableTitleTemplateChanged, CoerceAnchorableTitleTemplateValue)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the data template to use for anchorables title. + /// + public DataTemplate AnchorableTitleTemplate + { + get => (DataTemplate)GetValue(AnchorableTitleTemplateProperty); + set => SetValue(AnchorableTitleTemplateProperty, value); + } + + /// Handles changes to the property. + private static void OnAnchorableTitleTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorableTitleTemplateChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnAnchorableTitleTemplateChanged(DependencyPropertyChangedEventArgs e) + { + } + + /// Coerces the value. + private static object CoerceAnchorableTitleTemplateValue(DependencyObject d, object value) + { + if (value != null && d.GetValue(AnchorableTitleTemplateSelectorProperty) != null) + return null; + return value; + } + + #endregion AnchorableTitleTemplate + + #region AnchorableTitleTemplateSelector + + /// dependency property. + public static readonly DependencyProperty AnchorableTitleTemplateSelectorProperty = DependencyProperty.Register(nameof(AnchorableTitleTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnAnchorableTitleTemplateSelectorChanged)); + + /// + /// Gets or sets the property. This dependency property + /// indicates which selector to use when selecting data template for the title of anchorables. + /// + public DataTemplateSelector AnchorableTitleTemplateSelector + { + get => (DataTemplateSelector)GetValue(AnchorableTitleTemplateSelectorProperty); + set => SetValue(AnchorableTitleTemplateSelectorProperty, value); + } + + /// Handles changes to the property. + private static void OnAnchorableTitleTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorableTitleTemplateSelectorChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnAnchorableTitleTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) + { + if (e.NewValue != null && AnchorableTitleTemplate != null) + AnchorableTitleTemplate = null; + } + + #endregion AnchorableTitleTemplateSelector + + #region AnchorableHeaderTemplate + + /// dependency property. + public static readonly DependencyProperty AnchorableHeaderTemplateProperty = DependencyProperty.Register(nameof(AnchorableHeaderTemplate), typeof(DataTemplate), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnAnchorableHeaderTemplateChanged, CoerceAnchorableHeaderTemplateValue)); + + /// Gets or sets the property. This dependency property indicates the data template to use for anchorable templates. + public DataTemplate AnchorableHeaderTemplate + { + get => (DataTemplate)GetValue(AnchorableHeaderTemplateProperty); + set => SetValue(AnchorableHeaderTemplateProperty, value); + } + + /// Handles changes to the property. + private static void OnAnchorableHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorableHeaderTemplateChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnAnchorableHeaderTemplateChanged(DependencyPropertyChangedEventArgs e) + { + } + + /// Coerces the value. + private static object CoerceAnchorableHeaderTemplateValue(DependencyObject d, object value) + { + if (value != null && d.GetValue(AnchorableHeaderTemplateSelectorProperty) != null) + return null; + return value; + } + + #endregion AnchorableHeaderTemplate + + #region AnchorableHeaderTemplateSelector + + /// dependency property. + public static readonly DependencyProperty AnchorableHeaderTemplateSelectorProperty = DependencyProperty.Register(nameof(AnchorableHeaderTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), + new FrameworkPropertyMetadata((DataTemplateSelector)null, OnAnchorableHeaderTemplateSelectorChanged)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the selector to use when selecting the data template for anchorable headers. + /// + public DataTemplateSelector AnchorableHeaderTemplateSelector + { + get => (DataTemplateSelector)GetValue(AnchorableHeaderTemplateSelectorProperty); + set => SetValue(AnchorableHeaderTemplateSelectorProperty, value); + } + + /// Handles changes to the property. + private static void OnAnchorableHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorableHeaderTemplateSelectorChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnAnchorableHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) + { + if (e.NewValue != null) + AnchorableHeaderTemplate = null; + } + + #endregion AnchorableHeaderTemplateSelector + + #region LayoutRootPanel + + /// dependency property. + public static readonly DependencyProperty LayoutRootPanelProperty = DependencyProperty.Register(nameof(LayoutRootPanel), typeof(LayoutPanelControl), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnLayoutRootPanelChanged)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the layout panel control which is attached to the Layout.Root property. + /// + public LayoutPanelControl LayoutRootPanel + { + get => (LayoutPanelControl)GetValue(LayoutRootPanelProperty); + set => SetValue(LayoutRootPanelProperty, value); + } + + /// Handles changes to the property. + private static void OnLayoutRootPanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLayoutRootPanelChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnLayoutRootPanelChanged(DependencyPropertyChangedEventArgs e) + { + if (e.OldValue != null) + InternalRemoveLogicalChild(e.OldValue); + if (e.NewValue != null) + InternalAddLogicalChild(e.NewValue); + } + + #endregion LayoutRootPanel + + #region RightSidePanel + + /// dependency property. + public static readonly DependencyProperty RightSidePanelProperty = DependencyProperty.Register(nameof(RightSidePanel), typeof(LayoutAnchorSideControl), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnRightSidePanelChanged)); + + /// Gets or sets the property. This dependency property indicates right side anchor panel. + public LayoutAnchorSideControl RightSidePanel + { + get => (LayoutAnchorSideControl)GetValue(RightSidePanelProperty); + set => SetValue(RightSidePanelProperty, value); + } + + /// Handles changes to the property. + private static void OnRightSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnRightSidePanelChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnRightSidePanelChanged(DependencyPropertyChangedEventArgs e) + { + if (e.OldValue != null) + InternalRemoveLogicalChild(e.OldValue); + if (e.NewValue != null) + InternalAddLogicalChild(e.NewValue); + } + + #endregion RightSidePanel + + #region LeftSidePanel + + /// dependency property. + public static readonly DependencyProperty LeftSidePanelProperty = DependencyProperty.Register(nameof(LeftSidePanel), typeof(LayoutAnchorSideControl), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnLeftSidePanelChanged)); + + /// Gets or sets the property. This dependency property indicates the left side panel control. + public LayoutAnchorSideControl LeftSidePanel + { + get => (LayoutAnchorSideControl)GetValue(LeftSidePanelProperty); + set => SetValue(LeftSidePanelProperty, value); + } + + /// Handles changes to the property. + private static void OnLeftSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLeftSidePanelChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnLeftSidePanelChanged(DependencyPropertyChangedEventArgs e) + { + if (e.OldValue != null) + InternalRemoveLogicalChild(e.OldValue); + if (e.NewValue != null) + InternalAddLogicalChild(e.NewValue); + } + + #endregion LeftSidePanel + + #region TopSidePanel + + /// dependency property. + public static readonly DependencyProperty TopSidePanelProperty = DependencyProperty.Register(nameof(TopSidePanel), typeof(LayoutAnchorSideControl), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnTopSidePanelChanged)); + + /// Gets or sets the property. This dependency property indicates top side control panel. + public LayoutAnchorSideControl TopSidePanel + { + get => (LayoutAnchorSideControl)GetValue(TopSidePanelProperty); + set => SetValue(TopSidePanelProperty, value); + } + + /// Handles changes to the property. + private static void OnTopSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnTopSidePanelChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnTopSidePanelChanged(DependencyPropertyChangedEventArgs e) + { + if (e.OldValue != null) + InternalRemoveLogicalChild(e.OldValue); + if (e.NewValue != null) + InternalAddLogicalChild(e.NewValue); + } + + #endregion TopSidePanel + + #region BottomSidePanel + + /// dependency property. + public static readonly DependencyProperty BottomSidePanelProperty = DependencyProperty.Register(nameof(BottomSidePanel), typeof(LayoutAnchorSideControl), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnBottomSidePanelChanged)); + + /// Gets or sets the property. This dependency property indicates bottom side panel control. + public LayoutAnchorSideControl BottomSidePanel + { + get => (LayoutAnchorSideControl)GetValue(BottomSidePanelProperty); + set => SetValue(BottomSidePanelProperty, value); + } - /// Handles changes to the property. - private static void OnBottomSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnBottomSidePanelChanged(e); + /// Handles changes to the property. + private static void OnBottomSidePanelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnBottomSidePanelChanged(e); - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnBottomSidePanelChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - InternalRemoveLogicalChild(e.OldValue); - if (e.NewValue != null) - InternalAddLogicalChild(e.NewValue); - } + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnBottomSidePanelChanged(DependencyPropertyChangedEventArgs e) + { + if (e.OldValue != null) + InternalRemoveLogicalChild(e.OldValue); + if (e.NewValue != null) + InternalAddLogicalChild(e.NewValue); + } - #endregion BottomSidePanel - - #region LogicalChildren + #endregion BottomSidePanel + + #region LogicalChildren - List _logicalChildren = new List(); + private readonly List _logicalChildren = new List(); - /// - protected override IEnumerator LogicalChildren => _logicalChildren.Select(ch => ch.GetValueOrDefault()).GetEnumerator(); - - public IEnumerator LogicalChildrenPublic => LogicalChildren; + /// + protected override IEnumerator LogicalChildren => _logicalChildren.Select(ch => ch.GetValueOrDefault()).GetEnumerator(); + + public IEnumerator LogicalChildrenPublic => LogicalChildren; - internal void InternalAddLogicalChild(object element) - { + internal void InternalAddLogicalChild(object element) + { #if DEBUG - if (_logicalChildren.Select(ch => ch.GetValueOrDefault()).Contains(element)) - throw new InvalidOperationException(); + if (_logicalChildren.Select(ch => ch.GetValueOrDefault()).Contains(element)) + throw new InvalidOperationException(); #endif - if (_logicalChildren.Select(ch => ch.GetValueOrDefault()).Contains(element)) - return; - - _logicalChildren.Add(new WeakReference(element)); - AddLogicalChild(element); - } - - internal void InternalRemoveLogicalChild(object element) - { - var wrToRemove = _logicalChildren.FirstOrDefault(ch => ch.GetValueOrDefault() == element); - if (wrToRemove != null) - _logicalChildren.Remove(wrToRemove); - RemoveLogicalChild(element); - } - - private void ClearLogicalChildrenList() - { - foreach (var child in _logicalChildren.Select(ch => ch.GetValueOrDefault()).ToArray()) - RemoveLogicalChild(child); - _logicalChildren.Clear(); - } - - #endregion LogicalChildren - - #region AutoHideWindow - - /// Read-Only dependency property. - private static readonly DependencyPropertyKey AutoHideWindowPropertyKey = DependencyProperty.RegisterReadOnly(nameof(AutoHideWindow), typeof(LayoutAutoHideWindowControl), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnAutoHideWindowChanged)); - - public static readonly DependencyProperty AutoHideWindowProperty = AutoHideWindowPropertyKey.DependencyProperty; - - /// Gets the property. This dependency property indicates the currently shown autohide window. - public LayoutAutoHideWindowControl AutoHideWindow => (LayoutAutoHideWindowControl)GetValue(AutoHideWindowProperty); - - /// - /// Provides a secure method for setting the property. - /// This dependency property indicates the currently shown autohide window. - /// - /// The new value for the property. - protected void SetAutoHideWindow(LayoutAutoHideWindowControl value) => SetValue(AutoHideWindowPropertyKey, value); - - /// Handles changes to the property. - private static void OnAutoHideWindowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAutoHideWindowChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnAutoHideWindowChanged(DependencyPropertyChangedEventArgs e) - { - if (e.OldValue != null) - InternalRemoveLogicalChild(e.OldValue); - if (e.NewValue != null) - InternalAddLogicalChild(e.NewValue); - } - - #endregion AutoHideWindow + if (_logicalChildren.Select(ch => ch.GetValueOrDefault()).Contains(element)) + return; + + _logicalChildren.Add(new WeakReference(element)); + AddLogicalChild(element); + } + + internal void InternalRemoveLogicalChild(object element) + { + var wrToRemove = _logicalChildren.FirstOrDefault(ch => ch.GetValueOrDefault() == element); + if (wrToRemove != null) + _logicalChildren.Remove(wrToRemove); + RemoveLogicalChild(element); + } + + private void ClearLogicalChildrenList() + { + foreach (var child in _logicalChildren.Select(ch => ch.GetValueOrDefault()).ToArray()) + RemoveLogicalChild(child); + _logicalChildren.Clear(); + } + + #endregion LogicalChildren + + #region AutoHideWindow + + /// Read-Only dependency property. + private static readonly DependencyPropertyKey AutoHideWindowPropertyKey = DependencyProperty.RegisterReadOnly(nameof(AutoHideWindow), typeof(LayoutAutoHideWindowControl), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnAutoHideWindowChanged)); + + public static readonly DependencyProperty AutoHideWindowProperty = AutoHideWindowPropertyKey.DependencyProperty; + + /// Gets the property. This dependency property indicates the currently shown autohide window. + public LayoutAutoHideWindowControl AutoHideWindow => (LayoutAutoHideWindowControl)GetValue(AutoHideWindowProperty); + + /// + /// Provides a secure method for setting the property. + /// This dependency property indicates the currently shown autohide window. + /// + /// The new value for the property. + protected void SetAutoHideWindow(LayoutAutoHideWindowControl value) => SetValue(AutoHideWindowPropertyKey, value); + + /// Handles changes to the property. + private static void OnAutoHideWindowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAutoHideWindowChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnAutoHideWindowChanged(DependencyPropertyChangedEventArgs e) + { + if (e.OldValue != null) + InternalRemoveLogicalChild(e.OldValue); + if (e.NewValue != null) + InternalAddLogicalChild(e.NewValue); + } + + #endregion AutoHideWindow #region AutoHideDelay /// @@ -884,1761 +885,1774 @@ protected virtual void OnAutoHideWindowChanged(DependencyPropertyChangedEventArg DependencyProperty.Register("AutoHideDelay", typeof(int), typeof(DockingManager), new UIPropertyMetadata(500)); - /// - /// Gets/sets the wait time in milliseconds that is applicable when the system AutoHides - /// a (reduces it to a side anchor) after the user: - /// - /// 1) clicks on a that is anchored in one of the - /// property sides (top, right, left, or bottom) and - /// - /// 2) clicks somewhere else into a focusable element (different document). - /// - /// Expected behavior: The system waits for the configured time and reduces the (into its side anchor). - /// Recommended configuration value range should be between 0 and 1500 milliseconds. - /// - public int AutoHideDelay - { - get => (int)GetValue(AutoHideDelayProperty); - set => SetValue(AutoHideDelayProperty, value); - } - #endregion AutoHideDelay - - /// Floating Windows - public IEnumerable FloatingWindows => _fwList; - - #region LayoutItemTemplate - - /// dependency property. - public static readonly DependencyProperty LayoutItemTemplateProperty = DependencyProperty.Register(nameof(LayoutItemTemplate), typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplate)null, OnLayoutItemTemplateChanged)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the template to use to render anchorable and document contents. - /// - public DataTemplate LayoutItemTemplate - { - get => (DataTemplate)GetValue(LayoutItemTemplateProperty); - set => SetValue(LayoutItemTemplateProperty, value); - } - - /// Handles changes to the property. - private static void OnLayoutItemTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLayoutItemTemplateChanged(e); + /// + /// Gets/sets the wait time in milliseconds that is applicable when the system AutoHides + /// a (reduces it to a side anchor) after the user: + /// + /// 1) clicks on a that is anchored in one of the + /// property sides (top, right, left, or bottom) and + /// + /// 2) clicks somewhere else into a focusable element (different document). + /// + /// Expected behavior: The system waits for the configured time and reduces the (into its side anchor). + /// Recommended configuration value range should be between 0 and 1500 milliseconds. + /// + public int AutoHideDelay + { + get => (int)GetValue(AutoHideDelayProperty); + set => SetValue(AutoHideDelayProperty, value); + } + #endregion AutoHideDelay + + /// Floating Windows + public IEnumerable FloatingWindows => _fwList; + + #region LayoutItemTemplate + + /// dependency property. + public static readonly DependencyProperty LayoutItemTemplateProperty = DependencyProperty.Register(nameof(LayoutItemTemplate), typeof(DataTemplate), typeof(DockingManager), + new FrameworkPropertyMetadata((DataTemplate)null, OnLayoutItemTemplateChanged)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the template to use to render anchorable and document contents. + /// + public DataTemplate LayoutItemTemplate + { + get => (DataTemplate)GetValue(LayoutItemTemplateProperty); + set => SetValue(LayoutItemTemplateProperty, value); + } + + /// Handles changes to the property. + private static void OnLayoutItemTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLayoutItemTemplateChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnLayoutItemTemplateChanged(DependencyPropertyChangedEventArgs e) + { + } + + #endregion LayoutItemTemplate + + #region LayoutItemTemplateSelector + + /// dependency property. + public static readonly DependencyProperty LayoutItemTemplateSelectorProperty = DependencyProperty.Register(nameof(LayoutItemTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnLayoutItemTemplateSelectorChanged)); + + /// Gets or sets the property. This dependency property indicates selector object to use for anchorable templates. + public DataTemplateSelector LayoutItemTemplateSelector + { + get => (DataTemplateSelector)GetValue(LayoutItemTemplateSelectorProperty); + set => SetValue(LayoutItemTemplateSelectorProperty, value); + } + + /// Handles changes to the property. + private static void OnLayoutItemTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLayoutItemTemplateSelectorChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnLayoutItemTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) + { + } + + #endregion LayoutItemTemplateSelector + + #region DocumentsSource + + /// dependency property. + public static readonly DependencyProperty DocumentsSourceProperty = DependencyProperty.Register(nameof(DocumentsSource), typeof(IEnumerable), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnDocumentsSourceChanged)); + + /// Gets or sets the property. This dependency property indicates the source collection of documents. + public IEnumerable DocumentsSource + { + get => (IEnumerable)GetValue(DocumentsSourceProperty); + set => SetValue(DocumentsSourceProperty, value); + } + + /// Handles changes to the property. + private static void OnDocumentsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentsSourceChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnDocumentsSourceChanged(DependencyPropertyChangedEventArgs e) + { + DetachDocumentsSource(Layout, e.OldValue as IEnumerable); + AttachDocumentsSource(Layout, e.NewValue as IEnumerable); + } + + #endregion DocumentsSource + + #region DocumentContextMenu + + /// dependency property. + public static readonly DependencyProperty DocumentContextMenuProperty = DependencyProperty.Register(nameof(DocumentContextMenu), typeof(ContextMenu), typeof(DockingManager), + new FrameworkPropertyMetadata((ContextMenu)null, OnContextMenuPropertyChanged)); + + /// Gets or sets the property. This dependency property indicates context menu to show for documents. + public ContextMenu DocumentContextMenu + { + get => (ContextMenu)GetValue(DocumentContextMenuProperty); + set => SetValue(DocumentContextMenuProperty, value); + } + + #endregion DocumentContextMenu + + #region AnchorablesSource + + /// dependency property. + public static readonly DependencyProperty AnchorablesSourceProperty = DependencyProperty.Register(nameof(AnchorablesSource), typeof(IEnumerable), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnAnchorablesSourceChanged)); + + /// Gets or sets the property. This dependency property indicates source collection of anchorables. + public IEnumerable AnchorablesSource + { + get => (IEnumerable)GetValue(AnchorablesSourceProperty); + set => SetValue(AnchorablesSourceProperty, value); + } + + /// Handles changes to the property. + private static void OnAnchorablesSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorablesSourceChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnAnchorablesSourceChanged(DependencyPropertyChangedEventArgs e) + { + DetachAnchorablesSource(Layout, e.OldValue as IEnumerable); + AttachAnchorablesSource(Layout, e.NewValue as IEnumerable); + } + + #endregion AnchorablesSource + + #region ActiveContent + + /// dependency property. + public static readonly DependencyProperty ActiveContentProperty = DependencyProperty.Register(nameof(ActiveContent), typeof(object), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnActiveContentChanged)); + + /// Gets or sets the property. This dependency property indicates the content currently active. + public object ActiveContent + { + get => (object)GetValue(ActiveContentProperty); + set => SetValue(ActiveContentProperty, value); + } + + /// Handles changes to the property. + private static void OnActiveContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((DockingManager)d).InternalSetActiveContent(e.NewValue); + ((DockingManager)d).OnActiveContentChanged(e); + } + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnActiveContentChanged(DependencyPropertyChangedEventArgs e) => ActiveContentChanged?.Invoke(this, EventArgs.Empty); + + #endregion ActiveContent + + #region AnchorableContextMenu + + /// dependency property. + public static readonly DependencyProperty AnchorableContextMenuProperty = DependencyProperty.Register(nameof(AnchorableContextMenu), typeof(ContextMenu), typeof(DockingManager), + new FrameworkPropertyMetadata((ContextMenu)null, OnContextMenuPropertyChanged)); + + /// Gets or sets the property. This dependency property indicates the context menu to show up for anchorables. + public ContextMenu AnchorableContextMenu + { + get => (ContextMenu)GetValue(AnchorableContextMenuProperty); + set => SetValue(AnchorableContextMenuProperty, value); + } + + #endregion AnchorableContextMenu + + #region Theme + + /// dependency property. + public static readonly DependencyProperty ThemeProperty = DependencyProperty.Register(nameof(Theme), typeof(Theme), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnThemeChanged)); + + /// Gets or sets the property. This dependency property indicates the theme to use for AvalonDock controls. + public Theme Theme + { + get => (Theme)GetValue(ThemeProperty); + set => SetValue(ThemeProperty, value); + } + + /// Handles changes to the property. + private static void OnThemeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnThemeChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnThemeChanged(DependencyPropertyChangedEventArgs e) + { + var oldTheme = e.OldValue as Theme; + var resources = Resources; + if (oldTheme != null) + { + if (oldTheme is DictionaryTheme) + { + if (currentThemeResourceDictionary != null) + { + resources.MergedDictionaries.Remove(currentThemeResourceDictionary); + currentThemeResourceDictionary = null; + } + } + else + { + var resourceDictionaryToRemove = + resources.MergedDictionaries.FirstOrDefault(r => r.Source == oldTheme.GetResourceUri()); + if (resourceDictionaryToRemove != null) + resources.MergedDictionaries.Remove( + resourceDictionaryToRemove); + } + } + + if (e.NewValue as Theme != null) + { + if (e.NewValue as Theme is DictionaryTheme theme) + { + currentThemeResourceDictionary = theme.ThemeResourceDictionary; + resources.MergedDictionaries.Add(currentThemeResourceDictionary); + } + else + resources.MergedDictionaries.Add(new ResourceDictionary { Source = (e.NewValue as Theme).GetResourceUri() }); + } + + foreach (var fwc in _fwList) + fwc.UpdateThemeResources(oldTheme); + + _navigatorWindow?.UpdateThemeResources(); + _overlayWindow?.UpdateThemeResources(); + } + + #endregion Theme + + #region GridSplitterWidth + + /// dependency property. + public static readonly DependencyProperty GridSplitterWidthProperty = DependencyProperty.Register(nameof(GridSplitterWidth), typeof(double), typeof(DockingManager), + new FrameworkPropertyMetadata(6.0)); + + /// Gets or sets the property. This dependency property indicates width of grid splitters. + public double GridSplitterWidth + { + get => (double)GetValue(GridSplitterWidthProperty); + set => SetValue(GridSplitterWidthProperty, value); + } + + #endregion GridSplitterWidth + + #region GridSplitterHeight + + /// dependency property. + public static readonly DependencyProperty GridSplitterHeightProperty = DependencyProperty.Register(nameof(GridSplitterHeight), typeof(double), typeof(DockingManager), + new FrameworkPropertyMetadata(6.0)); + + /// Gets or sets the property. This dependency property indicates height of grid splitters. + public double GridSplitterHeight + { + get => (double)GetValue(GridSplitterHeightProperty); + set => SetValue(GridSplitterHeightProperty, value); + } + + #endregion GridSplitterHeight + + #region DocumentPaneMenuItemHeaderTemplate + + /// dependency property. + public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateProperty = DependencyProperty.Register(nameof(DocumentPaneMenuItemHeaderTemplate), typeof(DataTemplate), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnDocumentPaneMenuItemHeaderTemplateChanged, CoerceDocumentPaneMenuItemHeaderTemplateValue)); + + /// Gets or sets the property. This dependency property indicates the header template to use while creating menu items for the document panes. + public DataTemplate DocumentPaneMenuItemHeaderTemplate + { + get => (DataTemplate)GetValue(DocumentPaneMenuItemHeaderTemplateProperty); + set => SetValue(DocumentPaneMenuItemHeaderTemplateProperty, value); + } + + /// Handles changes to the property. + private static void OnDocumentPaneMenuItemHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentPaneMenuItemHeaderTemplateChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnDocumentPaneMenuItemHeaderTemplateChanged(DependencyPropertyChangedEventArgs e) + { + } + + /// Coerces the value. + private static object CoerceDocumentPaneMenuItemHeaderTemplateValue(DependencyObject d, object value) + { + if (value != null && d.GetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty) != null) + return null; + return value ?? d.GetValue(DocumentHeaderTemplateProperty); + } + + #endregion DocumentPaneMenuItemHeaderTemplate + + #region DocumentPaneMenuItemHeaderTemplateSelector + + /// dependency property. + public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateSelectorProperty = DependencyProperty.Register(nameof(DocumentPaneMenuItemHeaderTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnDocumentPaneMenuItemHeaderTemplateSelectorChanged, CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the data template selector to use for the menu items show when user select the DocumentPane document switch context menu. + /// + public DataTemplateSelector DocumentPaneMenuItemHeaderTemplateSelector + { + get => (DataTemplateSelector)GetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty); + set => SetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty, value); + } + + /// Handles changes to the property. + private static void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) + { + if (e.NewValue != null && DocumentPaneMenuItemHeaderTemplate != null) + DocumentPaneMenuItemHeaderTemplate = null; + } + + /// Coerces the value. + private static object CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue(DependencyObject d, object value) => value; - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnLayoutItemTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } + #endregion DocumentPaneMenuItemHeaderTemplateSelector - #endregion LayoutItemTemplate - - #region LayoutItemTemplateSelector + #region IconContentTemplate - /// dependency property. - public static readonly DependencyProperty LayoutItemTemplateSelectorProperty = DependencyProperty.Register(nameof(LayoutItemTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnLayoutItemTemplateSelectorChanged)); - - /// Gets or sets the property. This dependency property indicates selector object to use for anchorable templates. - public DataTemplateSelector LayoutItemTemplateSelector - { - get => (DataTemplateSelector)GetValue(LayoutItemTemplateSelectorProperty); - set => SetValue(LayoutItemTemplateSelectorProperty, value); - } + /// dependency property. + public static readonly DependencyProperty IconContentTemplateProperty = DependencyProperty.Register(nameof(IconContentTemplate), typeof(DataTemplate), typeof(DockingManager), + new FrameworkPropertyMetadata((DataTemplate)null)); - /// Handles changes to the property. - private static void OnLayoutItemTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLayoutItemTemplateSelectorChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnLayoutItemTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - } - - #endregion LayoutItemTemplateSelector - - #region DocumentsSource - - /// dependency property. - public static readonly DependencyProperty DocumentsSourceProperty = DependencyProperty.Register(nameof(DocumentsSource), typeof(IEnumerable), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnDocumentsSourceChanged)); - - /// Gets or sets the property. This dependency property indicates the source collection of documents. - public IEnumerable DocumentsSource - { - get => (IEnumerable)GetValue(DocumentsSourceProperty); - set => SetValue(DocumentsSourceProperty, value); - } - - /// Handles changes to the property. - private static void OnDocumentsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentsSourceChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnDocumentsSourceChanged(DependencyPropertyChangedEventArgs e) - { - DetachDocumentsSource(Layout, e.OldValue as IEnumerable); - AttachDocumentsSource(Layout, e.NewValue as IEnumerable); - } - - #endregion DocumentsSource - - #region DocumentContextMenu - - /// dependency property. - public static readonly DependencyProperty DocumentContextMenuProperty = DependencyProperty.Register(nameof(DocumentContextMenu), typeof(ContextMenu), typeof(DockingManager), - new FrameworkPropertyMetadata((ContextMenu)null)); - - /// Gets or sets the property. This dependency property indicates context menu to show for documents. - public ContextMenu DocumentContextMenu - { - get => (ContextMenu)GetValue(DocumentContextMenuProperty); - set => SetValue(DocumentContextMenuProperty, value); - } - - #endregion DocumentContextMenu - - #region AnchorablesSource - - /// dependency property. - public static readonly DependencyProperty AnchorablesSourceProperty = DependencyProperty.Register(nameof(AnchorablesSource), typeof(IEnumerable), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnAnchorablesSourceChanged)); - - /// Gets or sets the property. This dependency property indicates source collection of anchorables. - public IEnumerable AnchorablesSource - { - get => (IEnumerable)GetValue(AnchorablesSourceProperty); - set => SetValue(AnchorablesSourceProperty, value); - } - - /// Handles changes to the property. - private static void OnAnchorablesSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnAnchorablesSourceChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnAnchorablesSourceChanged(DependencyPropertyChangedEventArgs e) - { - DetachAnchorablesSource(Layout, e.OldValue as IEnumerable); - AttachAnchorablesSource(Layout, e.NewValue as IEnumerable); - } - - #endregion AnchorablesSource - - #region ActiveContent - - /// dependency property. - public static readonly DependencyProperty ActiveContentProperty = DependencyProperty.Register(nameof(ActiveContent), typeof(object), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnActiveContentChanged)); - - /// Gets or sets the property. This dependency property indicates the content currently active. - public object ActiveContent - { - get => (object)GetValue(ActiveContentProperty); - set => SetValue(ActiveContentProperty, value); - } - - /// Handles changes to the property. - private static void OnActiveContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - ((DockingManager)d).InternalSetActiveContent(e.NewValue); - ((DockingManager)d).OnActiveContentChanged(e); - } - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnActiveContentChanged(DependencyPropertyChangedEventArgs e) => ActiveContentChanged?.Invoke(this, EventArgs.Empty); - - #endregion ActiveContent - - #region AnchorableContextMenu - - /// dependency property. - public static readonly DependencyProperty AnchorableContextMenuProperty = DependencyProperty.Register(nameof(AnchorableContextMenu), typeof(ContextMenu), typeof(DockingManager), - new FrameworkPropertyMetadata((ContextMenu)null)); - - /// Gets or sets the property. This dependency property indicates the context menu to show up for anchorables. - public ContextMenu AnchorableContextMenu - { - get => (ContextMenu)GetValue(AnchorableContextMenuProperty); - set => SetValue(AnchorableContextMenuProperty, value); - } - - #endregion AnchorableContextMenu - - #region Theme - - /// dependency property. - public static readonly DependencyProperty ThemeProperty = DependencyProperty.Register(nameof(Theme), typeof(Theme), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnThemeChanged)); - - /// Gets or sets the property. This dependency property indicates the theme to use for AvalonDock controls. - public Theme Theme - { - get => (Theme)GetValue(ThemeProperty); - set => SetValue(ThemeProperty, value); - } - - /// Handles changes to the property. - private static void OnThemeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnThemeChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnThemeChanged(DependencyPropertyChangedEventArgs e) - { - var oldTheme = e.OldValue as Theme; - var newTheme = e.NewValue as Theme; - var resources = Resources; - if (oldTheme != null) - { - if (oldTheme is DictionaryTheme) - { - if (currentThemeResourceDictionary != null) - { - resources.MergedDictionaries.Remove(currentThemeResourceDictionary); - currentThemeResourceDictionary = null; - } - } - else - { - var resourceDictionaryToRemove = - resources.MergedDictionaries.FirstOrDefault(r => r.Source == oldTheme.GetResourceUri()); - if (resourceDictionaryToRemove != null) - resources.MergedDictionaries.Remove( - resourceDictionaryToRemove); - } - } - - if (newTheme != null) - { - if (newTheme is DictionaryTheme) - { - currentThemeResourceDictionary = ((DictionaryTheme)newTheme).ThemeResourceDictionary; - resources.MergedDictionaries.Add(currentThemeResourceDictionary); - } - else - resources.MergedDictionaries.Add(new ResourceDictionary { Source = newTheme.GetResourceUri() }); - } - - foreach (var fwc in _fwList) - fwc.UpdateThemeResources(oldTheme); - - _navigatorWindow?.UpdateThemeResources(); - _overlayWindow?.UpdateThemeResources(); - } - - #endregion Theme - - #region GridSplitterWidth - - /// dependency property. - public static readonly DependencyProperty GridSplitterWidthProperty = DependencyProperty.Register(nameof(GridSplitterWidth), typeof(double), typeof(DockingManager), - new FrameworkPropertyMetadata(6.0)); - - /// Gets or sets the property. This dependency property indicates width of grid splitters. - public double GridSplitterWidth - { - get => (double)GetValue(GridSplitterWidthProperty); - set => SetValue(GridSplitterWidthProperty, value); - } - - #endregion GridSplitterWidth - - #region GridSplitterHeight - - /// dependency property. - public static readonly DependencyProperty GridSplitterHeightProperty = DependencyProperty.Register(nameof(GridSplitterHeight), typeof(double), typeof(DockingManager), - new FrameworkPropertyMetadata(6.0)); - - /// Gets or sets the property. This dependency property indicates height of grid splitters. - public double GridSplitterHeight - { - get => (double)GetValue(GridSplitterHeightProperty); - set => SetValue(GridSplitterHeightProperty, value); - } - - #endregion GridSplitterHeight - - #region DocumentPaneMenuItemHeaderTemplate - - /// dependency property. - public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateProperty = DependencyProperty.Register(nameof(DocumentPaneMenuItemHeaderTemplate), typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnDocumentPaneMenuItemHeaderTemplateChanged, CoerceDocumentPaneMenuItemHeaderTemplateValue)); - - /// Gets or sets the property. This dependency property indicates the header template to use while creating menu items for the document panes. - public DataTemplate DocumentPaneMenuItemHeaderTemplate - { - get => (DataTemplate)GetValue(DocumentPaneMenuItemHeaderTemplateProperty); - set => SetValue(DocumentPaneMenuItemHeaderTemplateProperty, value); - } - - /// Handles changes to the property. - private static void OnDocumentPaneMenuItemHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentPaneMenuItemHeaderTemplateChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnDocumentPaneMenuItemHeaderTemplateChanged(DependencyPropertyChangedEventArgs e) - { - } - - /// Coerces the value. - private static object CoerceDocumentPaneMenuItemHeaderTemplateValue(DependencyObject d, object value) - { - if (value != null && d.GetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty) != null) - return null; - return value ?? d.GetValue(DocumentHeaderTemplateProperty); - } - - #endregion DocumentPaneMenuItemHeaderTemplate - - #region DocumentPaneMenuItemHeaderTemplateSelector - - /// dependency property. - public static readonly DependencyProperty DocumentPaneMenuItemHeaderTemplateSelectorProperty = DependencyProperty.Register(nameof(DocumentPaneMenuItemHeaderTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnDocumentPaneMenuItemHeaderTemplateSelectorChanged, CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the data template selector to use for the menu items show when user select the DocumentPane document switch context menu. - /// - public DataTemplateSelector DocumentPaneMenuItemHeaderTemplateSelector - { - get => (DataTemplateSelector)GetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty); - set => SetValue(DocumentPaneMenuItemHeaderTemplateSelectorProperty, value); - } - - /// Handles changes to the property. - private static void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnDocumentPaneMenuItemHeaderTemplateSelectorChanged(DependencyPropertyChangedEventArgs e) - { - if (e.NewValue != null && DocumentPaneMenuItemHeaderTemplate != null) - DocumentPaneMenuItemHeaderTemplate = null; - } - - /// Coerces the value. - private static object CoerceDocumentPaneMenuItemHeaderTemplateSelectorValue(DependencyObject d, object value) => value; - - #endregion DocumentPaneMenuItemHeaderTemplateSelector - - #region IconContentTemplate - - /// dependency property. - public static readonly DependencyProperty IconContentTemplateProperty = DependencyProperty.Register(nameof(IconContentTemplate), typeof(DataTemplate), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplate)null)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the data template to use while extracting the icon from model. - /// - public DataTemplate IconContentTemplate - { - get => (DataTemplate)GetValue(IconContentTemplateProperty); - set => SetValue(IconContentTemplateProperty, value); - } - - #endregion IconContentTemplate - - #region IconContentTemplateSelector - - /// dependency property. - public static readonly DependencyProperty IconContentTemplateSelectorProperty = DependencyProperty.Register(nameof(IconContentTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), - new FrameworkPropertyMetadata((DataTemplateSelector)null)); - - /// - /// Gets or sets the property. This dependency property - /// indicates data template selector to use while selecting the data template for content icons. - /// - public DataTemplateSelector IconContentTemplateSelector - { - get => (DataTemplateSelector)GetValue(IconContentTemplateSelectorProperty); - set => SetValue(IconContentTemplateSelectorProperty, value); - } - - #endregion IconContentTemplateSelector - - #region LayoutItemContainerStyle - - /// dependency property. - public static readonly DependencyProperty LayoutItemContainerStyleProperty = DependencyProperty.Register(nameof(LayoutItemContainerStyle), typeof(Style), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnLayoutItemContainerStyleChanged)); - - /// - /// Gets or sets the property. This dependency property - /// indicates the style to apply to objects. A object is created when a new is created inside the current Layout. - /// - public Style LayoutItemContainerStyle - { - get => (Style)GetValue(LayoutItemContainerStyleProperty); - set => SetValue(LayoutItemContainerStyleProperty, value); - } + /// + /// Gets or sets the property. This dependency property + /// indicates the data template to use while extracting the icon from model. + /// + public DataTemplate IconContentTemplate + { + get => (DataTemplate)GetValue(IconContentTemplateProperty); + set => SetValue(IconContentTemplateProperty, value); + } + + #endregion IconContentTemplate + + #region IconContentTemplateSelector - /// Handles changes to the property. - private static void OnLayoutItemContainerStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLayoutItemContainerStyleChanged(e); + /// dependency property. + public static readonly DependencyProperty IconContentTemplateSelectorProperty = DependencyProperty.Register(nameof(IconContentTemplateSelector), typeof(DataTemplateSelector), typeof(DockingManager), + new FrameworkPropertyMetadata((DataTemplateSelector)null)); + + /// + /// Gets or sets the property. This dependency property + /// indicates data template selector to use while selecting the data template for content icons. + /// + public DataTemplateSelector IconContentTemplateSelector + { + get => (DataTemplateSelector)GetValue(IconContentTemplateSelectorProperty); + set => SetValue(IconContentTemplateSelectorProperty, value); + } - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnLayoutItemContainerStyleChanged(DependencyPropertyChangedEventArgs e) => AttachLayoutItems(); + #endregion IconContentTemplateSelector - #endregion LayoutItemContainerStyle + #region LayoutItemContainerStyle - #region LayoutItemContainerStyleSelector - - /// dependency property. - public static readonly DependencyProperty LayoutItemContainerStyleSelectorProperty = DependencyProperty.Register(nameof(LayoutItemContainerStyleSelector), typeof(StyleSelector), typeof(DockingManager), - new FrameworkPropertyMetadata(null, OnLayoutItemContainerStyleSelectorChanged)); - - /// Gets or sets the property. This dependency property indicates style selector of the . - public StyleSelector LayoutItemContainerStyleSelector - { - get => (StyleSelector)GetValue(LayoutItemContainerStyleSelectorProperty); - set => SetValue(LayoutItemContainerStyleSelectorProperty, value); - } - - /// Handles changes to the property. - private static void OnLayoutItemContainerStyleSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLayoutItemContainerStyleSelectorChanged(e); - - /// Provides derived classes an opportunity to handle changes to the property. - protected virtual void OnLayoutItemContainerStyleSelectorChanged(DependencyPropertyChangedEventArgs e) => AttachLayoutItems(); - - #endregion LayoutItemContainerStyleSelector - - #region ShowSystemMenu - - /// dependency property. - public static readonly DependencyProperty ShowSystemMenuProperty = DependencyProperty.Register(nameof(ShowSystemMenu), typeof(bool), typeof(DockingManager), - new FrameworkPropertyMetadata(true)); - - /// Gets or sets the property. This dependency property indicates if floating windows should show the system menu when a custom context menu is not defined. - public bool ShowSystemMenu - { - get => (bool)GetValue(ShowSystemMenuProperty); - set => SetValue(ShowSystemMenuProperty, value); - } - - #endregion ShowSystemMenu - - #region AllowMixedOrientation - - /// dependency property. - public static readonly DependencyProperty AllowMixedOrientationProperty = DependencyProperty.Register(nameof(AllowMixedOrientation), typeof(bool), typeof(DockingManager), - new FrameworkPropertyMetadata(false)); - - /// Gets or sets the property. This dependency property indicates if the manager should allow mixed orientation for document panes. - public bool AllowMixedOrientation - { - get => (bool)GetValue(AllowMixedOrientationProperty); - set => SetValue(AllowMixedOrientationProperty, value); - } - - #endregion AllowMixedOrientation - - #region IsVirtualizingLayoutDocument IsVirtualizingLayoutAnchorable - - /// - /// Gets/sets (a simple non-dependency property) to determine whether the - /// is virtualizing its tabbed item child controls or not. - /// - public bool IsVirtualizingDocument { get; set; } - - /// - /// Gets/sets (a simple non-dependency property) to determine whether the - /// is virtualizing its tabbed item child controls or not. - /// - public bool IsVirtualizingAnchorable { get; set; } - - #endregion IsVirtualizingLayoutDocument IsVirtualizingLayoutAnchorable - - #endregion Public Properties - - #region Private Properties - - private bool IsNavigatorWindowActive => _navigatorWindow != null; - - #endregion Private Properties - - #region IOverlayWindowHost Interface - /// - bool IOverlayWindowHost.HitTest(Point dragPoint) - { - try - { - var detectionRect = new Rect(this.PointToScreenDPIWithoutFlowDirection(new Point()), this.TransformActualSizeToAncestor()); - return detectionRect.Contains(dragPoint); - } - catch - { - // Silently swallow exception that may occur if DockingManager is not visible (because its hidden by a tab) - } - - return false; - } - - /// - DockingManager IOverlayWindowHost.Manager => this; - - /// - IOverlayWindow IOverlayWindowHost.ShowOverlayWindow(LayoutFloatingWindowControl draggingWindow) - { - CreateOverlayWindow(); - _overlayWindow.Owner = draggingWindow; - _overlayWindow.EnableDropTargets(); - _overlayWindow.Show(); - return _overlayWindow; - } - - /// - void IOverlayWindowHost.HideOverlayWindow() - { - _areas = null; - _overlayWindow.Owner = null; - _overlayWindow.HideDropTargets(); - } - - /// - IEnumerable IOverlayWindowHost.GetDropAreas(LayoutFloatingWindowControl draggingWindow) - { - if (_areas != null) return _areas; - _areas = new List(); - var isDraggingDocuments = draggingWindow.Model is LayoutDocumentFloatingWindow; - if (!isDraggingDocuments) - { - _areas.Add(new DropArea(this, DropAreaType.DockingManager)); - foreach (var areaHost in this.FindVisualChildren()) - if (areaHost.Model.Descendents().Any()) _areas.Add(new DropArea(areaHost, DropAreaType.AnchorablePane)); - } - - // Determine if floatingWindow is configured to dock as document or not - var dockAsDocument = true; - if (!isDraggingDocuments) - { - if (draggingWindow.Model is LayoutAnchorableFloatingWindow toolWindow) - { - foreach (var item in GetAnchorableInFloatingWindow(draggingWindow)) - { - if (item.CanDockAsTabbedDocument != false) continue; - dockAsDocument = false; - break; - } - } - } - - // Dock only documents and tools in DocumentPane if configuration does allow that - if (dockAsDocument) - { - foreach (var areaHost in this.FindVisualChildren()) - _areas.Add(new DropArea(areaHost, DropAreaType.DocumentPane)); - } - - foreach (var areaHost in this.FindVisualChildren()) - { - var documentGroupModel = areaHost.Model as LayoutDocumentPaneGroup; - if (!documentGroupModel.Children.Any(c => c.IsVisible)) - _areas.Add(new DropArea(areaHost, DropAreaType.DocumentPaneGroup)); - } - - return _areas; - } - - /// - /// Finds all objects (tool windows) within a - /// (if any) and return them. - /// - /// - /// - private IEnumerable GetAnchorableInFloatingWindow(LayoutFloatingWindowControl draggingWindow) - { - if (!(draggingWindow.Model is LayoutAnchorableFloatingWindow layoutAnchorableFloatingWindow)) yield break; - //big part of code for getting type - var layoutAnchorablePane = layoutAnchorableFloatingWindow.SinglePane as LayoutAnchorablePane; - - if (layoutAnchorablePane != null && (layoutAnchorableFloatingWindow.IsSinglePane && layoutAnchorablePane.SelectedContent != null)) - { - var layoutAnchorable = ((LayoutAnchorablePane)layoutAnchorableFloatingWindow.SinglePane).SelectedContent as LayoutAnchorable; - yield return layoutAnchorable; - } - else - foreach (var item in GetLayoutAnchorable(layoutAnchorableFloatingWindow.RootPanel)) - yield return item; - } - - /// - /// Finds all objects (toolwindows) within a - /// (if any) and return them. - /// - /// - /// All the anchorable items found. - /// - /// - internal IEnumerable GetLayoutAnchorable(LayoutAnchorablePaneGroup layoutAnchPaneGroup) - { - if (layoutAnchPaneGroup == null) yield break; - foreach (var anchorable in layoutAnchPaneGroup.Descendents().OfType()) - yield return anchorable; - } - #endregion IOverlayWindowHost Interface - - #region Public Methods - - /// Return the LayoutItem wrapper for the content passed as argument. - /// LayoutContent to search - /// Either a or which contains the passed as argument. - public LayoutItem GetLayoutItemFromModel(LayoutContent content) - { - return _layoutItems.FirstOrDefault(item => item.LayoutElement == content); - } - - public LayoutFloatingWindowControl CreateFloatingWindow(LayoutContent contentModel, bool isContentImmutable) - { - LayoutFloatingWindowControl lfwc = null; - if (contentModel is LayoutAnchorable) - { - if (!(contentModel.Parent is ILayoutPane)) - { - var pane = new LayoutAnchorablePane((LayoutAnchorable)contentModel) - { - FloatingTop = contentModel.FloatingTop, - FloatingLeft = contentModel.FloatingLeft, - FloatingWidth = contentModel.FloatingWidth, - FloatingHeight = contentModel.FloatingHeight - }; - lfwc = CreateFloatingWindowForLayoutAnchorableWithoutParent(pane, isContentImmutable); - } - } - - return CreateFloatingWindowCore(contentModel, isContentImmutable); - } - - #endregion Public Methods - - #region Internal Methods - /// - /// Method is invoked to create the actual visible UI element from a given layout model. It is invoked when: - /// - /// 1. New UI items are created and layed out or - /// 2. Layout is deserialized, and the previous UI items are restored to the screen - /// (using the model who's information was serialized to XML). - /// - /// The layout element. - /// - 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(TemplateProperty, new Binding(AnchorSideTemplateProperty.Name) { Source = this }); - return templateModelView; - } - if (model is LayoutAnchorGroup) - { - var templateModelView = new LayoutAnchorGroupControl(model as LayoutAnchorGroup); - templateModelView.SetBinding(TemplateProperty, new Binding(AnchorGroupTemplateProperty.Name) { Source = this }); - return templateModelView; - } - - if (model is LayoutDocumentPane) - { - var templateModelView = new LayoutDocumentPaneControl(model as LayoutDocumentPane, IsVirtualizingDocument); - templateModelView.SetBinding(StyleProperty, new Binding(DocumentPaneControlStyleProperty.Name) { Source = this }); - return templateModelView; - } - if (model is LayoutAnchorablePane) - { - var templateModelView = new LayoutAnchorablePaneControl(model as LayoutAnchorablePane, IsVirtualizingAnchorable); - templateModelView.SetBinding(StyleProperty, new Binding(AnchorablePaneControlStyleProperty.Name) { Source = this }); - return templateModelView; - } - - if (model is LayoutAnchorableFloatingWindow) - { - if (DesignerProperties.GetIsInDesignMode(this)) return null; - var modelFW = model as LayoutAnchorableFloatingWindow; - var newFW = new LayoutAnchorableFloatingWindowControl(modelFW) - { - //Owner = Window.GetWindow(this) - }; - newFW.SetParentToMainWindowOf(this); - - // Floating Window can also contain only Pane Groups at its base (issue #27) so we check for - // RootPanel (which is a LayoutAnchorablePaneGroup) and make sure the window is positioned back - // in current (or nearest) monitor - var panegroup = modelFW.RootPanel; - if (panegroup != null) - { - panegroup.KeepInsideNearestMonitor(); // Check position is valid in current setup - - newFW.Left = panegroup.FloatingLeft; // Position the window to previous or nearest valid position - newFW.Top = panegroup.FloatingTop; - newFW.Width = panegroup.FloatingWidth; - newFW.Height = panegroup.FloatingHeight; - } - - newFW.ShowInTaskbar = false; - - Dispatcher.BeginInvoke(new Action(() => - { - if (newFW.Content != null || (newFW.Model as LayoutAnchorableFloatingWindow)?.IsVisible == true) - newFW.Show(); - else - newFW.Hide(); - }), DispatcherPriority.Send); - - if (panegroup != null && panegroup.IsMaximized) - newFW.WindowState = WindowState.Maximized; - return newFW; - } - - if (model is LayoutDocumentFloatingWindow) - { - if (DesignerProperties.GetIsInDesignMode(this)) - return null; - var modelFW = model as LayoutDocumentFloatingWindow; - var newFW = new LayoutDocumentFloatingWindowControl(modelFW) - { - //Owner = Window.GetWindow(this) - }; - newFW.SetParentToMainWindowOf(this); - - var paneForExtensions = modelFW.RootPanel; - if (paneForExtensions != null) - { - //ensure that floating window position is inside current (or nearest) monitor - paneForExtensions.KeepInsideNearestMonitor(); - - newFW.Left = paneForExtensions.FloatingLeft; - newFW.Top = paneForExtensions.FloatingTop; - newFW.Width = paneForExtensions.FloatingWidth; - newFW.Height = paneForExtensions.FloatingHeight; - } - newFW.ShowInTaskbar = false; - newFW.Show(); - // Do not set the WindowState before showing or it will be lost - if (paneForExtensions != null && paneForExtensions.IsMaximized) - newFW.WindowState = WindowState.Maximized; - return newFW; - } - if (model is LayoutDocument layoutDocument) - { - var templateModelView = new LayoutDocumentControl { Model = layoutDocument }; - return templateModelView; - } - return null; - } - - /// Method is invoked to pop put an Anchorable that was in AutoHide mode. - /// to pop out of the side panel. - internal void ShowAutoHideWindow(LayoutAnchorControl anchor) - { - _autoHideWindowManager.ShowAutoHideWindow(anchor); - } - - internal void HideAutoHideWindow(LayoutAnchorControl anchor) => _autoHideWindowManager.HideAutoWindow(anchor); - - internal FrameworkElement GetAutoHideAreaElement() => _autohideArea; - - /// - /// Executes when the user starts to drag a or - /// by dragging its TabItem Header. - /// - /// - /// - internal void StartDraggingFloatingWindowForContent(LayoutContent contentModel, bool startDrag = true) - { - // Ensure window can float only if corresponding property is set accordingly - if (contentModel == null) return; - if (!contentModel.CanFloat) return; - LayoutFloatingWindowControl fwc = null; - - // For last document re-use floating window - if (contentModel.Parent.ChildrenCount == 1) - { - foreach (var fw in _fwList) - { - var found = fw.Model.Descendents().OfType().Any(doc => doc == contentModel); - if (!found) continue; - if (fw.Model.Descendents().OfType().Count() + fw.Model.Descendents().OfType().Count() == 1) - fwc = fw; - break; - } - } - - var show = fwc == null; // Do not show already visible floating window - if (fwc == null) - fwc = CreateFloatingWindow(contentModel, false); - - if (fwc != null) - { - Dispatcher.BeginInvoke(new Action(() => - { - // Activate only inactive document - if (startDrag) fwc.AttachDrag(); - fwc.Show(); - }), DispatcherPriority.Send); - } - } - - /// - /// Executes when the user starts to drag a docked (tool window) - /// by dragging its title bar (top header of a tool window). - /// - /// - internal void StartDraggingFloatingWindowForPane(LayoutAnchorablePane paneModel) - { - var fwc = CreateFloatingWindowForLayoutAnchorableWithoutParent(paneModel, false); - if (fwc == null) return; - fwc.AttachDrag(); - fwc.Show(); - } - - internal IEnumerable GetFloatingWindowsByZOrder() - { - var parentWindow = Window.GetWindow(this); - var windowParentHandle = parentWindow != null ? new WindowInteropHelper(parentWindow).Handle : Process.GetCurrentProcess().MainWindowHandle; - var currentHandle = Win32Helper.GetWindow(windowParentHandle, (uint)Win32Helper.GetWindow_Cmd.GW_HWNDFIRST); - while (currentHandle != IntPtr.Zero) - { - var ctrl = _fwList.FirstOrDefault(fw => new WindowInteropHelper(fw).Handle == currentHandle); - if (ctrl != null && ctrl.Model.Root != null && ctrl.Model.Root.Manager == this) - yield return ctrl; - - currentHandle = Win32Helper.GetWindow(currentHandle, (uint)Win32Helper.GetWindow_Cmd.GW_HWNDNEXT); - } - } - - internal void RemoveFloatingWindow(LayoutFloatingWindowControl floatingWindow) => _fwList.Remove(floatingWindow); - - internal void _ExecuteCloseCommand(LayoutDocument document) - { - if (DocumentClosing != null) - { - var argsClosing = new DocumentClosingEventArgs(document); - DocumentClosing(this, argsClosing); - if (argsClosing.Cancel) return; - } - if (!document.CloseDocument()) return; - RemoveViewFromLogicalChild(document); - DocumentClosed?.Invoke(this, new DocumentClosedEventArgs(document)); - } - - internal void _ExecuteCloseAllButThisCommand(LayoutContent contentSelected) - { - foreach (var contentToClose in Layout.Descendents().OfType().Where(d => d != contentSelected && (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)).ToArray()) - Close(contentToClose); - } - - internal void _ExecuteCloseAllCommand(LayoutContent contentSelected) - { - foreach (var contentToClose in Layout.Descendents().OfType().Where(d => (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)).ToArray()) - Close(contentToClose); - } - - internal void _ExecuteCloseCommand(LayoutAnchorable anchorable) - { - if (!(anchorable is LayoutAnchorable model)) return; - model.CloseAnchorable(); - RemoveViewFromLogicalChild(anchorable); - } - - internal void _ExecuteHideCommand(LayoutAnchorable anchorable) => anchorable?.Hide(); - - internal void _ExecuteAutoHideCommand(LayoutAnchorable _anchorable) => _anchorable.ToggleAutoHide(); - - /// - /// Method executes when the user clicks the Float button in the context menu of an . - /// - /// This removes the content from the docked and inserts it into a - /// draggable . - /// - /// - internal void _ExecuteFloatCommand(LayoutContent contentToFloat) => contentToFloat.Float(); - - internal void _ExecuteDockCommand(LayoutAnchorable anchorable) => anchorable.Dock(); - - internal void _ExecuteDockAsDocumentCommand(LayoutContent content) => content.DockAsDocument(); - - internal void _ExecuteContentActivateCommand(LayoutContent content) => content.IsActive = true; - - #endregion Internal Methods - - #region Overrides - - public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - _autohideArea = GetTemplateChild("PART_AutoHideArea") as FrameworkElement; - } - - protected override Size ArrangeOverride(Size arrangeBounds) - { - _areas = null; - return base.ArrangeOverride(arrangeBounds); - } - - protected override void OnPreviewKeyDown(KeyEventArgs e) - { - if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) - { - if (e.IsDown && e.Key == Key.Tab) - { - if (!IsNavigatorWindowActive) - { - ShowNavigatorWindow(); - e.Handled = true; - } - } - } - - base.OnPreviewKeyDown(e); - } - - #endregion Overrides - - #region Private Methods - - private void OnLayoutRootPropertyChanged(object sender, PropertyChangedEventArgs e) - { - switch (e.PropertyName) - { - case nameof(LayoutRoot.RootPanel): - { - if (IsInitialized) - { - var layoutRootPanel = CreateUIElementForModel(Layout.RootPanel) as LayoutPanelControl; - LayoutRootPanel = layoutRootPanel; - } - break; - } - case nameof(LayoutRoot.ActiveContent): - { - //set focus on active element only after a layout pass is completed - //it's possible that it is not yet visible in the visual tree - //if (_setFocusAsyncOperation == null) - //{ - // _setFocusAsyncOperation = Dispatcher.BeginInvoke(new Action(() => - // { - if (Layout.ActiveContent != null) - FocusElementManager.SetFocusOnLastElement(Layout.ActiveContent); - //_setFocusAsyncOperation = null; - // } ), DispatcherPriority.Input ); - //} - - if (!_insideInternalSetActiveContent) - ActiveContent = Layout.ActiveContent?.Content; - break; - } - } - } - - private static void OnLayoutRootUpdated(object sender, EventArgs e) => CommandManager.InvalidateRequerySuggested(); - - private void OnLayoutChanging(LayoutRoot newLayout) => LayoutChanging?.Invoke(this, EventArgs.Empty); - - private void DockingManager_Loaded(object sender, RoutedEventArgs e) - { - if (DesignerProperties.GetIsInDesignMode(this)) return; - 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; - - // In order to prevent resource leaks, unsubscribe from SizeChanged event for case when we have no stored Layout settings. - SizeChanged -= OnSizeChanged; - SizeChanged += OnSizeChanged; - } - - SetupAutoHideWindow(); - - foreach (var fwc in _fwHiddenList) - { - fwc.EnableBindings(); - if (fwc.KeepContentVisibleOnClose) - { - fwc.Show(); - fwc.KeepContentVisibleOnClose = false; - } - - _fwList.Add(fwc); - } - _fwHiddenList.Clear(); - - // load floating windows not already loaded! (issue #59) - var items = new List(Layout.FloatingWindows.Where(fw => !_fwList.Any(fwc => fwc.Model == fw))); - foreach (var fw in items) - _fwList.Add(CreateUIElementForModel(fw) as LayoutFloatingWindowControl); - - //create the overlaywindow if it's possible - if (IsVisible) - CreateOverlayWindow(); - FocusElementManager.SetupFocusManagement(this); - } - - /// Method executes when the control has changed its height and/or width. - /// - /// - private void OnSizeChanged(object sender, SizeChangedEventArgs e) - { - // Lets make sure this always remains non-negative to avoid crach in layout system - var width = Math.Max(ActualWidth - GridSplitterWidth - RightSidePanel.ActualWidth - LeftSidePanel.ActualWidth, 0); - var height = Math.Max(ActualHeight - GridSplitterHeight - TopSidePanel.ActualHeight - BottomSidePanel.ActualHeight, 0); - - LayoutRootPanel.AdjustFixedChildrenPanelSizes(new Size(width, height)); - } - - private void DockingManager_Unloaded(object sender, RoutedEventArgs e) - { - SizeChanged -= OnSizeChanged; - - if (DesignerProperties.GetIsInDesignMode(this)) return; - _autoHideWindowManager?.HideAutoWindow(); - - AutoHideWindow?.Dispose(); - - foreach (var fw in _fwList.ToArray()) - { - ////fw.Owner = null; - //fw.SetParentWindowToNull(); - //fw.KeepContentVisibleOnClose = true; - //// To avoid calling Close method multiple times. - //fw.InternalClose(true); - - // Unloaded can occure not only after closing of the application, but after switching between tabs. - // For such case it's better to hide the floating windows instead of closing it. - // We clear bindings on visibility during the owner is unloaded. - if (fw.IsVisible) - { - fw.KeepContentVisibleOnClose = true; - fw.Hide(); - } - fw.DisableBindings(); - _fwHiddenList.Add(fw); - } - - _fwList.Clear(); - - DestroyOverlayWindow(); - FocusElementManager.FinalizeFocusManagement(this); - } - - private void SetupAutoHideWindow() - { - if (_autoHideWindowManager != null) - _autoHideWindowManager.HideAutoWindow(); - else - _autoHideWindowManager = new AutoHideWindowManager(this); - - AutoHideWindow?.Dispose(); - SetAutoHideWindow(new LayoutAutoHideWindowControl()); - } - - private void CreateOverlayWindow() - { - if (_overlayWindow == null) - _overlayWindow = new OverlayWindow(this); - var rectWindow = new Rect(this.PointToScreenDPIWithoutFlowDirection(new Point()), this.TransformActualSizeToAncestor()); - _overlayWindow.Left = rectWindow.Left; - _overlayWindow.Top = rectWindow.Top; - _overlayWindow.Width = rectWindow.Width; - _overlayWindow.Height = rectWindow.Height; - } - - private void DestroyOverlayWindow() - { - if (_overlayWindow == null) return; - _overlayWindow.Close(); - _overlayWindow = null; - } - - private void AttachDocumentsSource(LayoutRoot layout, IEnumerable documentsSource) - { - if (documentsSource == null) return; - if (layout == null) return; - - //if (layout.Descendents().OfType().Any()) - // throw new InvalidOperationException("Unable to set the DocumentsSource property if LayoutDocument objects are already present in the model"); - var documentsImported = layout.Descendents().OfType().Select(d => d.Content).ToArray(); - var documents = documentsSource as IEnumerable; - var listOfDocumentsToImport = new List(documents.OfType()); - - foreach (var document in listOfDocumentsToImport.ToArray()) - { - if (documentsImported.Contains(document)) - listOfDocumentsToImport.Remove(document); - } - - LayoutDocumentPane documentPane = null; - if (layout.LastFocusedDocument != null) - documentPane = layout.LastFocusedDocument.Parent as LayoutDocumentPane; - - if (documentPane == null) - documentPane = layout.Descendents().OfType().FirstOrDefault(); - - //if (documentPane == null) - // throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents"); - - _suspendLayoutItemCreation = true; - foreach (var documentContentToImport in listOfDocumentsToImport) - { - //documentPane.Children.Add(new LayoutDocument() { Content = documentToImport }); - var documentToImport = new LayoutDocument { Content = documentContentToImport }; - - var 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); - } - - LayoutUpdateStrategy?.AfterInsertDocument(layout, documentToImport); - CreateDocumentLayoutItem(documentToImport); - } - _suspendLayoutItemCreation = false; - if (documentsSource is INotifyCollectionChanged documentsSourceAsNotifier) - documentsSourceAsNotifier.CollectionChanged += documentsSourceElementsChanged; - } - - private void documentsSourceElementsChanged(object sender, NotifyCollectionChangedEventArgs e) - { - if (Layout == null) return; - //When deserializing documents are created automatically by the deserializer - if (SuspendDocumentsSourceBinding) return; - - //handle remove - if (e.Action == NotifyCollectionChangedAction.Remove || - e.Action == NotifyCollectionChangedAction.Replace) - { - if (e.OldItems != null) - { - var documentsToRemove = Layout.Descendents().OfType().Where(d => e.OldItems.Contains(d.Content)).ToArray(); - foreach (var documentToRemove in documentsToRemove) - { - documentToRemove.Parent.RemoveChild(documentToRemove); - RemoveViewFromLogicalChild(documentToRemove); - } - } - } - - //handle add - if (e.NewItems != null && (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace)) - { - if (e.NewItems != null) - { - LayoutDocumentPane documentPane = null; - if (Layout.LastFocusedDocument != null) - { - documentPane = Layout.LastFocusedDocument.Parent as LayoutDocumentPane; - } - if (documentPane == null) - { - documentPane = Layout.Descendents().OfType().FirstOrDefault(); - } - //if (documentPane == null) - // throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents"); - _suspendLayoutItemCreation = true; - foreach (var documentContentToImport in e.NewItems) - { - var documentToImport = new LayoutDocument - { - Content = documentContentToImport - }; - - var 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; - } - - LayoutUpdateStrategy?.AfterInsertDocument(Layout, documentToImport); - var root = documentToImport.Root; - if (root != null && root.Manager == this) - { - CreateDocumentLayoutItem(documentToImport); - } - } - _suspendLayoutItemCreation = false; - } - } - - if (e.Action == NotifyCollectionChangedAction.Reset) - { - //NOTE: I'm going to clear every document present in layout but - //some documents may have been added directly to the layout, for now I clear them too - var documentsToRemove = Layout.Descendents().OfType().ToArray(); - foreach (var documentToRemove in documentsToRemove) - { - (documentToRemove.Parent as ILayoutContainer).RemoveChild( - documentToRemove); - RemoveViewFromLogicalChild(documentToRemove); - } - } - - Layout?.CollectGarbage(); - } - - private void DetachDocumentsSource(LayoutRoot layout, IEnumerable documentsSource) - { - if (documentsSource == null) return; - if (layout == null) return; - - var documentsToRemove = layout.Descendents().OfType() - .Where(d => documentsSource.Contains(d.Content)).ToArray(); - - foreach (var documentToRemove in documentsToRemove) - { - (documentToRemove.Parent as ILayoutContainer).RemoveChild( - documentToRemove); - RemoveViewFromLogicalChild(documentToRemove); - } - - var documentsSourceAsNotifier = documentsSource as INotifyCollectionChanged; - if (documentsSourceAsNotifier != null) - documentsSourceAsNotifier.CollectionChanged -= documentsSourceElementsChanged; - } - - private void Close(LayoutContent contentToClose) - { - if (!contentToClose.CanClose) return; - - var layoutItem = GetLayoutItemFromModel(contentToClose); - if (layoutItem.CloseCommand != null) - { - if (layoutItem.CloseCommand.CanExecute(null)) - layoutItem.CloseCommand.Execute(null); - } - else - { - if (contentToClose is LayoutDocument document) - _ExecuteCloseCommand(document); - else if (contentToClose is LayoutAnchorable anchorable) - _ExecuteCloseCommand(anchorable); - } - } - - private void AttachAnchorablesSource(LayoutRoot layout, IEnumerable anchorablesSource) - { - if (anchorablesSource == null) return; - if (layout == null) return; - - //if (layout.Descendents().OfType().Any()) - // throw new InvalidOperationException("Unable to set the AnchorablesSource property if LayoutAnchorable objects are already present in the model"); - var anchorablesImported = layout.Descendents().OfType().Select(d => d.Content).ToArray(); - var anchorables = anchorablesSource as IEnumerable; - var listOfAnchorablesToImport = new List(anchorables.OfType()); - - foreach (var document in listOfAnchorablesToImport.ToArray()) - { - if (anchorablesImported.Contains(document)) - listOfAnchorablesToImport.Remove(document); - } - LayoutAnchorablePane anchorablePane = null; - if (layout.ActiveContent != null) - { - //look for active content parent pane - anchorablePane = layout.ActiveContent.Parent as LayoutAnchorablePane; - } - if (anchorablePane == null) - { - //look for a pane on the right side - anchorablePane = layout.Descendents().OfType().FirstOrDefault(pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right); - } - if (anchorablePane == null) - { - //look for an available pane - anchorablePane = layout.Descendents().OfType().FirstOrDefault(); - } - _suspendLayoutItemCreation = true; - foreach (var anchorableContentToImport in listOfAnchorablesToImport) - { - var anchorableToImport = new LayoutAnchorable { Content = anchorableContentToImport }; - var 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; - } - - LayoutUpdateStrategy?.AfterInsertAnchorable(layout, anchorableToImport); - CreateAnchorableLayoutItem(anchorableToImport); - } - _suspendLayoutItemCreation = false; - if (anchorablesSource is INotifyCollectionChanged anchorablesSourceAsNotifier) - anchorablesSourceAsNotifier.CollectionChanged += anchorablesSourceElementsChanged; - } - - private void anchorablesSourceElementsChanged(object sender, NotifyCollectionChangedEventArgs e) - { - if (Layout == null) return; - - //When deserializing documents are created automatically by the deserializer - if (SuspendAnchorablesSourceBinding) return; - - //handle remove - if (e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Replace) - { - if (e.OldItems != null) - { - var anchorablesToRemove = Layout.Descendents().OfType().Where(d => e.OldItems.Contains(d.Content)).ToArray(); - foreach (var anchorableToRemove in anchorablesToRemove) - { - anchorableToRemove.Content = null; - anchorableToRemove.Parent.RemoveChild(anchorableToRemove); - RemoveViewFromLogicalChild(anchorableToRemove); - } - } - } - - //handle add - if (e.NewItems != null && (e.Action == NotifyCollectionChangedAction.Add || e.Action == 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().FirstOrDefault(pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right); - } - if (anchorablePane == null) - { - //look for an available pane - anchorablePane = Layout.Descendents().OfType().FirstOrDefault(); - } - _suspendLayoutItemCreation = true; - foreach (var anchorableContentToImport in e.NewItems) - { - var anchorableToImport = new LayoutAnchorable { Content = anchorableContentToImport }; - var 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; - } - LayoutUpdateStrategy?.AfterInsertAnchorable(Layout, anchorableToImport); - var root = anchorableToImport.Root; - if (root != null && root.Manager == this) - CreateAnchorableLayoutItem(anchorableToImport); - } - _suspendLayoutItemCreation = false; - } - } - - if (e.Action == NotifyCollectionChangedAction.Reset) - { - //NOTE: I'm going to clear every anchorable present in layout but - //some anchorable may have been added directly to the layout, for now I clear them too - var anchorablesToRemove = Layout.Descendents().OfType().ToArray(); - foreach (var anchorableToRemove in anchorablesToRemove) - { - (anchorableToRemove.Parent as ILayoutContainer).RemoveChild( - anchorableToRemove); - RemoveViewFromLogicalChild(anchorableToRemove); - } - } - - Layout?.CollectGarbage(); - } - - private void DetachAnchorablesSource(LayoutRoot layout, IEnumerable anchorablesSource) - { - if (anchorablesSource == null) return; - if (layout == null) return; - - var anchorablesToRemove = layout.Descendents().OfType() - .Where(d => anchorablesSource.Contains(d.Content)).ToArray(); - - foreach (var anchorableToRemove in anchorablesToRemove) - { - anchorableToRemove.Parent.RemoveChild(anchorableToRemove); - RemoveViewFromLogicalChild(anchorableToRemove); - } - - if (anchorablesSource is INotifyCollectionChanged anchorablesSourceAsNotifier) - anchorablesSourceAsNotifier.CollectionChanged -= anchorablesSourceElementsChanged; - } - - private void RemoveViewFromLogicalChild(LayoutContent layoutContent) - { - if (layoutContent == null) return; - var layoutItem = GetLayoutItemFromModel(layoutContent); - if (layoutItem == null) return; - if (layoutItem.IsViewExists()) InternalRemoveLogicalChild(layoutItem.View); - } - - private void InternalSetActiveContent(object contentObject) - { - // BugFix for first issue in #59 - var list = Layout.Descendents().OfType().ToList(); - var layoutContent = list.FirstOrDefault(lc => lc == contentObject || lc.Content == contentObject); - _insideInternalSetActiveContent = true; - Layout.ActiveContent = layoutContent; - _insideInternalSetActiveContent = false; - } - - #region LayoutItems - /// - /// Implements the EventHandler for the event. - /// - /// - /// - private void Layout_ElementRemoved(object sender, LayoutElementEventArgs e) - { - if (_suspendLayoutItemCreation) return; - CollectLayoutItemsDeleted(); - } - - /// - /// Implements the EventHandler for the event. - /// - /// - /// - private void Layout_ElementAdded(object sender, LayoutElementEventArgs e) - { - if (_suspendLayoutItemCreation) return; - foreach (var content in Layout.Descendents().OfType().ToList()) - { - if (content is LayoutDocument) - CreateDocumentLayoutItem(content as LayoutDocument); - else //if (content is LayoutAnchorable) - CreateAnchorableLayoutItem(content as LayoutAnchorable); - } - CollectLayoutItemsDeleted(); - } - - /// - /// Detach and remove all LayoutItems that are no longer part of the . - /// - private void CollectLayoutItemsDeleted() - { - if (_collectLayoutItemsOperations != null) return; - _collectLayoutItemsOperations = Dispatcher.BeginInvoke(new Action(() => - { - _collectLayoutItemsOperations = null; - foreach (var itemToRemove in _layoutItems.Where(item => item.LayoutElement.Root != Layout).ToArray()) - { - itemToRemove.Detach(); - _layoutItems.Remove(itemToRemove); - } - })); - } - - /// - /// Detaches all LayoutItems from their content and clears the private collection of LayoutItems. - /// - private void DetachLayoutItems() - { - if (Layout == null) return; - _layoutItems.ForEach(i => i.Detach()); - _layoutItems.Clear(); - Layout.ElementAdded -= Layout_ElementAdded; - Layout.ElementRemoved -= Layout_ElementRemoved; - } - - /// - /// Attaches a: - /// - to each and - /// - to each - /// - /// in the property. - /// - private void AttachLayoutItems() - { - if (Layout == null) return; - foreach (var document in Layout.Descendents().OfType().ToArray()) - CreateDocumentLayoutItem(document); - - foreach (var anchorable in Layout.Descendents().OfType().ToArray()) - CreateAnchorableLayoutItem(anchorable); - - Layout.ElementAdded += Layout_ElementAdded; - Layout.ElementRemoved += Layout_ElementRemoved; - } - - /// - /// Applies the corresponding style to a either from: - /// 1) property or - /// 2) property - /// - /// - private void ApplyStyleToLayoutItem(LayoutItem layoutItem) - { - layoutItem._ClearDefaultBindings(); - if (LayoutItemContainerStyle != null) - layoutItem.Style = LayoutItemContainerStyle; - else if (LayoutItemContainerStyleSelector != null) - layoutItem.Style = LayoutItemContainerStyleSelector.SelectStyle(layoutItem.Model, layoutItem); - layoutItem._SetDefaultBindings(); - } - - /// - /// Creates a for each - /// or returns the existing if there is already one. - /// - /// - private void CreateAnchorableLayoutItem(LayoutAnchorable contentToAttach) - { - if (_layoutItems.Any(item => item.LayoutElement == contentToAttach)) - { - foreach (var item in _layoutItems) ApplyStyleToLayoutItem(item); - return; - } - - var layoutItem = new LayoutAnchorableItem(); - layoutItem.Attach(contentToAttach); - _layoutItems.Add(layoutItem); - ApplyStyleToLayoutItem(layoutItem); - if (contentToAttach?.Content is UIElement) InternalAddLogicalChild(contentToAttach.Content); - } - - /// - /// Creates a for each - /// or returns the existing if there is already one. - /// - /// - private void CreateDocumentLayoutItem(LayoutDocument contentToAttach) - { - if (_layoutItems.Any(item => item.LayoutElement == contentToAttach)) - { - foreach (var item in _layoutItems) ApplyStyleToLayoutItem(item); - return; - } - - var layoutItem = new LayoutDocumentItem(); - layoutItem.Attach(contentToAttach); - _layoutItems.Add(layoutItem); - ApplyStyleToLayoutItem(layoutItem); - if (contentToAttach?.Content is UIElement) InternalAddLogicalChild(contentToAttach.Content); - } - #endregion LayoutItems - - private void ShowNavigatorWindow() - { - if (_navigatorWindow == null) - _navigatorWindow = new NavigatorWindow(this) { Owner = Window.GetWindow(this), WindowStartupLocation = WindowStartupLocation.CenterOwner }; - _navigatorWindow.ShowDialog(); - _navigatorWindow = null; - } - - private LayoutFloatingWindowControl CreateFloatingWindowForLayoutAnchorableWithoutParent(LayoutAnchorablePane paneModel, bool isContentImmutable) - { - if (paneModel.Children.Any(c => !c.CanFloat)) - return null; - var paneAsPositionableElement = paneModel as ILayoutPositionableElement; - var paneAsWithActualSize = paneModel as ILayoutPositionableElementWithActualSize; - - var fwWidth = paneAsPositionableElement.FloatingWidth; - var fwHeight = paneAsPositionableElement.FloatingHeight; - var fwLeft = paneAsPositionableElement.FloatingLeft; - var fwTop = paneAsPositionableElement.FloatingTop; - - if (fwWidth == 0.0) - fwWidth = paneAsWithActualSize.ActualWidth + 10; //10 includes BorderThickness and Margins inside LayoutAnchorableFloatingWindowControl. - if (fwHeight == 0.0) - fwHeight = paneAsWithActualSize.ActualHeight + 10; //10 includes BorderThickness and Margins inside LayoutAnchorableFloatingWindowControl. - - var destPane = new LayoutAnchorablePane - { - DockWidth = paneAsPositionableElement.DockWidth, - DockHeight = paneAsPositionableElement.DockHeight, - DockMinHeight = paneAsPositionableElement.DockMinHeight, - DockMinWidth = paneAsPositionableElement.DockMinWidth, - FloatingLeft = paneAsPositionableElement.FloatingLeft, - FloatingTop = paneAsPositionableElement.FloatingTop, - FloatingWidth = paneAsPositionableElement.FloatingWidth, - FloatingHeight = paneAsPositionableElement.FloatingHeight, - }; - - var savePreviousContainer = paneModel.FindParent() == null; - var currentSelectedContentIndex = paneModel.SelectedContentIndex; - while (paneModel.Children.Count > 0) - { - var contentModel = paneModel.Children[paneModel.Children.Count - 1]; - - if (savePreviousContainer) - { - ((ILayoutPreviousContainer)contentModel).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((LayoutAnchorableFloatingWindow)fw, isContentImmutable) - { - Width = fwWidth, - Height = fwHeight, - Top = fwTop, - Left = fwLeft - }; - //fwc.Owner = Window.GetWindow(this); - //fwc.SetParentToMainWindowOf(this); - _fwList.Add(fwc); - Layout.CollectGarbage(); - InvalidateArrange(); - return fwc; - } - - private LayoutFloatingWindowControl CreateFloatingWindowCore(LayoutContent contentModel, bool isContentImmutable) - { - if (!contentModel.CanFloat) return null; - if (contentModel is LayoutAnchorable contentModelAsAnchorable && 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() == null) - { - ((ILayoutPreviousContainer)contentModel).PreviousContainer = parentPane; - contentModel.PreviousContainerIndex = contentModelParentChildrenIndex; - } - - parentPane.RemoveChildAt(contentModelParentChildrenIndex); - - var fwWidth = contentModel.FloatingWidth; - var fwHeight = contentModel.FloatingHeight; - - if (fwWidth == 0.0) - fwWidth = parentPaneAsPositionableElement.FloatingWidth; - if (fwHeight == 0.0) - fwHeight = parentPaneAsPositionableElement.FloatingHeight; - - if (fwWidth == 0.0) - fwWidth = parentPaneAsWithActualSize.ActualWidth + 10; //10 includes BorderThickness and Margins inside LayoutDocumentFloatingWindowControl. - if (fwHeight == 0.0) - fwHeight = parentPaneAsWithActualSize.ActualHeight + 10; //10 includes BorderThickness and Margins inside LayoutDocumentFloatingWindowControl. - - LayoutFloatingWindow fw; - LayoutFloatingWindowControl fwc; - if (contentModel is LayoutAnchorable) - { - var anchorableContent = contentModel as LayoutAnchorable; - fw = new LayoutAnchorableFloatingWindow - { - RootPanel = new LayoutAnchorablePaneGroup(new LayoutAnchorablePane(anchorableContent) - { - DockWidth = parentPaneAsPositionableElement.DockWidth, - DockHeight = parentPaneAsPositionableElement.DockHeight, - DockMinHeight = parentPaneAsPositionableElement.DockMinHeight, - DockMinWidth = parentPaneAsPositionableElement.DockMinWidth, - FloatingLeft = parentPaneAsPositionableElement.FloatingLeft, - FloatingTop = parentPaneAsPositionableElement.FloatingTop, - FloatingWidth = parentPaneAsPositionableElement.FloatingWidth, - FloatingHeight = parentPaneAsPositionableElement.FloatingHeight, - }) - }; - - Layout.FloatingWindows.Add(fw); - fwc = new LayoutAnchorableFloatingWindowControl((LayoutAnchorableFloatingWindow)fw, isContentImmutable) - { - Width = fwWidth, - Height = fwHeight, - Left = contentModel.FloatingLeft, - Top = contentModel.FloatingTop - }; - } - else - { - var anchorableDocument = contentModel as LayoutDocument; - fw = new LayoutDocumentFloatingWindow - { - RootPanel = new LayoutDocumentPaneGroup(new LayoutDocumentPane(anchorableDocument) - { - 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 LayoutDocumentFloatingWindowControl((LayoutDocumentFloatingWindow)fw, isContentImmutable) - { - Width = fwWidth, - Height = fwHeight, - Left = contentModel.FloatingLeft, - Top = contentModel.FloatingTop - }; - } - //fwc.Owner = Window.GetWindow(this); - //fwc.SetParentToMainWindowOf(this); - _fwList.Add(fwc); - Layout.CollectGarbage(); - UpdateLayout(); - return fwc; - } - - #endregion Private Methods - } + /// dependency property. + public static readonly DependencyProperty LayoutItemContainerStyleProperty = DependencyProperty.Register(nameof(LayoutItemContainerStyle), typeof(Style), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnLayoutItemContainerStyleChanged)); + + /// + /// Gets or sets the property. This dependency property + /// indicates the style to apply to objects. A object is created when a new is created inside the current Layout. + /// + public Style LayoutItemContainerStyle + { + get => (Style)GetValue(LayoutItemContainerStyleProperty); + set => SetValue(LayoutItemContainerStyleProperty, value); + } + + /// Handles changes to the property. + private static void OnLayoutItemContainerStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLayoutItemContainerStyleChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnLayoutItemContainerStyleChanged(DependencyPropertyChangedEventArgs e) => AttachLayoutItems(); + + #endregion LayoutItemContainerStyle + + #region LayoutItemContainerStyleSelector + + /// dependency property. + public static readonly DependencyProperty LayoutItemContainerStyleSelectorProperty = DependencyProperty.Register(nameof(LayoutItemContainerStyleSelector), typeof(StyleSelector), typeof(DockingManager), + new FrameworkPropertyMetadata(null, OnLayoutItemContainerStyleSelectorChanged)); + + /// Gets or sets the property. This dependency property indicates style selector of the . + public StyleSelector LayoutItemContainerStyleSelector + { + get => (StyleSelector)GetValue(LayoutItemContainerStyleSelectorProperty); + set => SetValue(LayoutItemContainerStyleSelectorProperty, value); + } + + /// Handles changes to the property. + private static void OnLayoutItemContainerStyleSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((DockingManager)d).OnLayoutItemContainerStyleSelectorChanged(e); + + /// Provides derived classes an opportunity to handle changes to the property. + protected virtual void OnLayoutItemContainerStyleSelectorChanged(DependencyPropertyChangedEventArgs e) => AttachLayoutItems(); + + #endregion LayoutItemContainerStyleSelector + + #region ShowSystemMenu + + /// dependency property. + public static readonly DependencyProperty ShowSystemMenuProperty = DependencyProperty.Register(nameof(ShowSystemMenu), typeof(bool), typeof(DockingManager), + new FrameworkPropertyMetadata(true)); + + /// Gets or sets the property. This dependency property indicates if floating windows should show the system menu when a custom context menu is not defined. + public bool ShowSystemMenu + { + get => (bool)GetValue(ShowSystemMenuProperty); + set => SetValue(ShowSystemMenuProperty, value); + } + + #endregion ShowSystemMenu + + #region AllowMixedOrientation + + /// dependency property. + public static readonly DependencyProperty AllowMixedOrientationProperty = DependencyProperty.Register(nameof(AllowMixedOrientation), typeof(bool), typeof(DockingManager), + new FrameworkPropertyMetadata(false)); + + /// Gets or sets the property. This dependency property indicates if the manager should allow mixed orientation for document panes. + public bool AllowMixedOrientation + { + get => (bool)GetValue(AllowMixedOrientationProperty); + set => SetValue(AllowMixedOrientationProperty, value); + } + + #endregion AllowMixedOrientation + + #region IsVirtualizingLayoutDocument IsVirtualizingLayoutAnchorable + + /// + /// Gets/sets (a simple non-dependency property) to determine whether the + /// is virtualizing its tabbed item child controls or not. + /// + public bool IsVirtualizingDocument { get; set; } + + /// + /// Gets/sets (a simple non-dependency property) to determine whether the + /// is virtualizing its tabbed item child controls or not. + /// + public bool IsVirtualizingAnchorable { get; set; } + + #endregion IsVirtualizingLayoutDocument IsVirtualizingLayoutAnchorable + + #endregion Public Properties + + #region Private Properties + + private bool IsNavigatorWindowActive => _navigatorWindow != null; + + #endregion Private Properties + + #region IOverlayWindowHost Interface + /// + bool IOverlayWindowHost.HitTest(Point dragPoint) + { + try + { + var detectionRect = new Rect(this.PointToScreenDPIWithoutFlowDirection(new Point()), this.TransformActualSizeToAncestor()); + return detectionRect.Contains(dragPoint); + } + catch + { + // Silently swallow exception that may occur if DockingManager is not visible (because its hidden by a tab) + } + + return false; + } + + /// + DockingManager IOverlayWindowHost.Manager => this; + + /// + IOverlayWindow IOverlayWindowHost.ShowOverlayWindow(LayoutFloatingWindowControl draggingWindow) + { + CreateOverlayWindow(); + _overlayWindow.Owner = draggingWindow; + _overlayWindow.EnableDropTargets(); + _overlayWindow.Show(); + return _overlayWindow; + } + + /// + void IOverlayWindowHost.HideOverlayWindow() + { + _areas = null; + _overlayWindow.Owner = null; + _overlayWindow.HideDropTargets(); + } + + /// + IEnumerable IOverlayWindowHost.GetDropAreas(LayoutFloatingWindowControl draggingWindow) + { + if (_areas != null) return _areas; + _areas = new List(); + var isDraggingDocuments = draggingWindow.Model is LayoutDocumentFloatingWindow; + if (!isDraggingDocuments) + { + _areas.Add(new DropArea(this, DropAreaType.DockingManager)); + foreach (var areaHost in this.FindVisualChildren()) + if (areaHost.Model.Descendents().Any()) _areas.Add(new DropArea(areaHost, DropAreaType.AnchorablePane)); + } + + // Determine if floatingWindow is configured to dock as document or not + var dockAsDocument = true; + if (!isDraggingDocuments) + { + if (draggingWindow.Model is LayoutAnchorableFloatingWindow toolWindow) + { + foreach (var item in GetAnchorableInFloatingWindow(draggingWindow)) + { + if (item.CanDockAsTabbedDocument != false) continue; + dockAsDocument = false; + break; + } + } + } + + // Dock only documents and tools in DocumentPane if configuration does allow that + if (dockAsDocument) + { + foreach (var areaHost in this.FindVisualChildren()) + _areas.Add(new DropArea(areaHost, DropAreaType.DocumentPane)); + } + + foreach (var areaHost in this.FindVisualChildren()) + { + var documentGroupModel = areaHost.Model as LayoutDocumentPaneGroup; + if (!documentGroupModel.Children.Any(c => c.IsVisible)) + _areas.Add(new DropArea(areaHost, DropAreaType.DocumentPaneGroup)); + } + + return _areas; + } + + /// + /// Finds all objects (tool windows) within a + /// (if any) and return them. + /// + /// + /// + private IEnumerable GetAnchorableInFloatingWindow(LayoutFloatingWindowControl draggingWindow) + { + if (!(draggingWindow.Model is LayoutAnchorableFloatingWindow layoutAnchorableFloatingWindow)) yield break; + //big part of code for getting type + + if (layoutAnchorableFloatingWindow.SinglePane is LayoutAnchorablePane layoutAnchorablePane && (layoutAnchorableFloatingWindow.IsSinglePane && layoutAnchorablePane.SelectedContent != null)) + { + var layoutAnchorable = ((LayoutAnchorablePane)layoutAnchorableFloatingWindow.SinglePane).SelectedContent as LayoutAnchorable; + yield return layoutAnchorable; + } + else + foreach (var item in GetLayoutAnchorable(layoutAnchorableFloatingWindow.RootPanel)) + yield return item; + } + + /// + /// Finds all objects (toolwindows) within a + /// (if any) and return them. + /// + /// + /// All the anchorable items found. + /// + /// + internal IEnumerable GetLayoutAnchorable(LayoutAnchorablePaneGroup layoutAnchPaneGroup) + { + if (layoutAnchPaneGroup == null) yield break; + foreach (var anchorable in layoutAnchPaneGroup.Descendents().OfType()) + yield return anchorable; + } + #endregion IOverlayWindowHost Interface + + #region Public Methods + + /// Return the LayoutItem wrapper for the content passed as argument. + /// LayoutContent to search + /// Either a or which contains the passed as argument. + public LayoutItem GetLayoutItemFromModel(LayoutContent content) + { + return _layoutItems.FirstOrDefault(item => item.LayoutElement == content); + } + + public LayoutFloatingWindowControl CreateFloatingWindow(LayoutContent contentModel, bool isContentImmutable) + { + if (contentModel is LayoutAnchorable anchorable) + { + if (!(contentModel.Parent is ILayoutPane)) + { + var pane = new LayoutAnchorablePane(anchorable) + { + FloatingTop = contentModel.FloatingTop, + FloatingLeft = contentModel.FloatingLeft, + FloatingWidth = contentModel.FloatingWidth, + FloatingHeight = contentModel.FloatingHeight + }; + _ = CreateFloatingWindowForLayoutAnchorableWithoutParent(pane, isContentImmutable); + } + } + + return CreateFloatingWindowCore(contentModel, isContentImmutable); + } + + #endregion Public Methods + + #region Internal Methods + /// + /// Method is invoked to create the actual visible UI element from a given layout model. It is invoked when: + /// + /// 1. New UI items are created and layed out or + /// 2. Layout is deserialized, and the previous UI items are restored to the screen + /// (using the model who's information was serialized to XML). + /// + /// The layout element. + /// + 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(TemplateProperty, new Binding(AnchorSideTemplateProperty.Name) { Source = this }); + return templateModelView; + } + if (model is LayoutAnchorGroup) + { + var templateModelView = new LayoutAnchorGroupControl(model as LayoutAnchorGroup); + templateModelView.SetBinding(TemplateProperty, new Binding(AnchorGroupTemplateProperty.Name) { Source = this }); + return templateModelView; + } + + if (model is LayoutDocumentPane) + { + var templateModelView = new LayoutDocumentPaneControl(model as LayoutDocumentPane, IsVirtualizingDocument); + templateModelView.SetBinding(StyleProperty, new Binding(DocumentPaneControlStyleProperty.Name) { Source = this }); + return templateModelView; + } + if (model is LayoutAnchorablePane) + { + var templateModelView = new LayoutAnchorablePaneControl(model as LayoutAnchorablePane, IsVirtualizingAnchorable); + templateModelView.SetBinding(StyleProperty, new Binding(AnchorablePaneControlStyleProperty.Name) { Source = this }); + return templateModelView; + } + + if (model is LayoutAnchorableFloatingWindow) + { + if (DesignerProperties.GetIsInDesignMode(this)) return null; + var modelFW = model as LayoutAnchorableFloatingWindow; + var newFW = new LayoutAnchorableFloatingWindowControl(modelFW) + { + //Owner = Window.GetWindow(this) + }; + newFW.SetParentToMainWindowOf(this); + + // Floating Window can also contain only Pane Groups at its base (issue #27) so we check for + // RootPanel (which is a LayoutAnchorablePaneGroup) and make sure the window is positioned back + // in current (or nearest) monitor + var panegroup = modelFW.RootPanel; + if (panegroup != null) + { + panegroup.KeepInsideNearestMonitor(); // Check position is valid in current setup + + newFW.Left = panegroup.FloatingLeft; // Position the window to previous or nearest valid position + newFW.Top = panegroup.FloatingTop; + newFW.Width = panegroup.FloatingWidth; + newFW.Height = panegroup.FloatingHeight; + } + + newFW.ShowInTaskbar = false; + + Dispatcher.BeginInvoke(new Action(() => + { + if (newFW.Content != null || (newFW.Model as LayoutAnchorableFloatingWindow)?.IsVisible == true) + newFW.Show(); + else + newFW.Hide(); + }), DispatcherPriority.Send); + + if (panegroup != null && panegroup.IsMaximized) + newFW.WindowState = WindowState.Maximized; + return newFW; + } + + if (model is LayoutDocumentFloatingWindow) + { + if (DesignerProperties.GetIsInDesignMode(this)) + return null; + var modelFW = model as LayoutDocumentFloatingWindow; + var newFW = new LayoutDocumentFloatingWindowControl(modelFW) + { + //Owner = Window.GetWindow(this) + }; + newFW.SetParentToMainWindowOf(this); + + var paneForExtensions = modelFW.RootPanel; + if (paneForExtensions != null) + { + //ensure that floating window position is inside current (or nearest) monitor + paneForExtensions.KeepInsideNearestMonitor(); + + newFW.Left = paneForExtensions.FloatingLeft; + newFW.Top = paneForExtensions.FloatingTop; + newFW.Width = paneForExtensions.FloatingWidth; + newFW.Height = paneForExtensions.FloatingHeight; + } + newFW.ShowInTaskbar = false; + newFW.Show(); + // Do not set the WindowState before showing or it will be lost + if (paneForExtensions != null && paneForExtensions.IsMaximized) + newFW.WindowState = WindowState.Maximized; + return newFW; + } + if (model is LayoutDocument layoutDocument) + { + var templateModelView = new LayoutDocumentControl { Model = layoutDocument }; + return templateModelView; + } + return null; + } + + /// Method is invoked to pop put an Anchorable that was in AutoHide mode. + /// to pop out of the side panel. + internal void ShowAutoHideWindow(LayoutAnchorControl anchor) + { + _autoHideWindowManager.ShowAutoHideWindow(anchor); + } + + internal void HideAutoHideWindow(LayoutAnchorControl anchor) => _autoHideWindowManager.HideAutoWindow(anchor); + + internal FrameworkElement GetAutoHideAreaElement() => _autohideArea; + + /// + /// Executes when the user starts to drag a or + /// by dragging its TabItem Header. + /// + /// + /// + internal void StartDraggingFloatingWindowForContent(LayoutContent contentModel, bool startDrag = true) + { + // Ensure window can float only if corresponding property is set accordingly + if (contentModel == null) return; + if (!contentModel.CanFloat) return; + LayoutFloatingWindowControl fwc = null; + + // For last document re-use floating window + if (contentModel.Parent.ChildrenCount == 1) + { + foreach (var fw in _fwList) + { + var found = fw.Model.Descendents().OfType().Any(doc => doc == contentModel); + if (!found) continue; + if (fw.Model.Descendents().OfType().Count() + fw.Model.Descendents().OfType().Count() == 1) + fwc = fw; + break; + } + } + + var show = fwc == null; // Do not show already visible floating window + if (fwc == null) + fwc = CreateFloatingWindow(contentModel, false); + + if (fwc != null) + { + Dispatcher.BeginInvoke(new Action(() => + { + // Activate only inactive document + if (startDrag) fwc.AttachDrag(); + fwc.Show(); + }), DispatcherPriority.Send); + } + } + + /// + /// Executes when the user starts to drag a docked (tool window) + /// by dragging its title bar (top header of a tool window). + /// + /// + internal void StartDraggingFloatingWindowForPane(LayoutAnchorablePane paneModel) + { + var fwc = CreateFloatingWindowForLayoutAnchorableWithoutParent(paneModel, false); + if (fwc == null) return; + fwc.AttachDrag(); + fwc.Show(); + } + + internal IEnumerable GetFloatingWindowsByZOrder() + { + var parentWindow = Window.GetWindow(this); + var windowParentHandle = parentWindow != null ? new WindowInteropHelper(parentWindow).Handle : Process.GetCurrentProcess().MainWindowHandle; + var currentHandle = Win32Helper.GetWindow(windowParentHandle, (uint)Win32Helper.GetWindow_Cmd.GW_HWNDFIRST); + while (currentHandle != IntPtr.Zero) + { + var ctrl = _fwList.FirstOrDefault(fw => new WindowInteropHelper(fw).Handle == currentHandle); + if (ctrl != null && ctrl.Model.Root != null && ctrl.Model.Root.Manager == this) + yield return ctrl; + + currentHandle = Win32Helper.GetWindow(currentHandle, (uint)Win32Helper.GetWindow_Cmd.GW_HWNDNEXT); + } + } + + internal void RemoveFloatingWindow(LayoutFloatingWindowControl floatingWindow) => _fwList.Remove(floatingWindow); + + internal void ExecuteCloseCommand(LayoutDocument document) + { + if (DocumentClosing != null) + { + var argsClosing = new DocumentClosingEventArgs(document); + DocumentClosing(this, argsClosing); + if (argsClosing.Cancel) return; + } + if (!document.CloseDocument()) return; + RemoveViewFromLogicalChild(document); + DocumentClosed?.Invoke(this, new DocumentClosedEventArgs(document)); + } + + internal void ExecuteCloseAllButThisCommand(LayoutContent contentSelected) + { + foreach (var contentToClose in Layout.Descendents().OfType().Where(d => d != contentSelected && (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)).ToArray()) + Close(contentToClose); + } + + [SuppressMessage("Style", "IDE0060:删除未使用的参数", Justification = "<挂起>")] + internal void ExecuteCloseAllCommand(LayoutContent contentSelected) + { + foreach (var contentToClose in Layout.Descendents().OfType().Where(d => (d.Parent is LayoutDocumentPane || d.Parent is LayoutDocumentFloatingWindow)).ToArray()) + Close(contentToClose); + } + + internal void ExecuteCloseCommand(LayoutAnchorable anchorable) + { + if (!(anchorable is LayoutAnchorable model)) return; + model.CloseAnchorable(); + RemoveViewFromLogicalChild(anchorable); + } + + internal void ExecuteHideCommand(LayoutAnchorable anchorable) => anchorable?.Hide(); + + internal void ExecuteAutoHideCommand(LayoutAnchorable _anchorable) => _anchorable.ToggleAutoHide(); + + /// + /// Method executes when the user clicks the Float button in the context menu of an . + /// + /// This removes the content from the docked and inserts it into a + /// draggable . + /// + /// + internal void ExecuteFloatCommand(LayoutContent contentToFloat) => contentToFloat.Float(); + + internal void ExecuteDockCommand(LayoutAnchorable anchorable) => anchorable.Dock(); + + internal void ExecuteDockAsDocumentCommand(LayoutContent content) => content.DockAsDocument(); + + internal void ExecuteContentActivateCommand(LayoutContent content) => content.IsActive = true; + + #endregion Internal Methods + + #region Overrides + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + _autohideArea = GetTemplateChild("PART_AutoHideArea") as FrameworkElement; + } + + protected override Size ArrangeOverride(Size arrangeBounds) + { + _areas = null; + return base.ArrangeOverride(arrangeBounds); + } + + protected override void OnPreviewKeyDown(KeyEventArgs e) + { + if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) + { + if (e.IsDown && e.Key == Key.Tab) + { + if (!IsNavigatorWindowActive) + { + ShowNavigatorWindow(); + e.Handled = true; + } + } + } + + base.OnPreviewKeyDown(e); + } + + #endregion Overrides + + #region Private Methods + + /// + /// OnContextMenuPropertyChanged(Fix ContextMenu's Resources is null,drop down menu style error) + /// + /// + /// + private static void OnContextMenuPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (e.NewValue is ContextMenu contextMenu) + { + contextMenu.Resources = ((DockingManager)d).Resources; + } + } + + private void OnLayoutRootPropertyChanged(object sender, PropertyChangedEventArgs e) + { + switch (e.PropertyName) + { + case nameof(LayoutRoot.RootPanel): + { + if (IsInitialized) + { + var layoutRootPanel = CreateUIElementForModel(Layout.RootPanel) as LayoutPanelControl; + LayoutRootPanel = layoutRootPanel; + } + break; + } + case nameof(LayoutRoot.ActiveContent): + { + //set focus on active element only after a layout pass is completed + //it's possible that it is not yet visible in the visual tree + //if (_setFocusAsyncOperation == null) + //{ + // _setFocusAsyncOperation = Dispatcher.BeginInvoke(new Action(() => + // { + if (Layout.ActiveContent != null) + FocusElementManager.SetFocusOnLastElement(Layout.ActiveContent); + //_setFocusAsyncOperation = null; + // } ), DispatcherPriority.Input ); + //} + + if (!_insideInternalSetActiveContent) + ActiveContent = Layout.ActiveContent?.Content; + break; + } + } + } + + private static void OnLayoutRootUpdated(object sender, EventArgs e) => CommandManager.InvalidateRequerySuggested(); + + + [SuppressMessage("Style", "IDE0060:删除未使用的参数", Justification = "<挂起>")] + private void OnLayoutChanging(LayoutRoot newLayout) => LayoutChanging?.Invoke(this, EventArgs.Empty); + + private void DockingManager_Loaded(object sender, RoutedEventArgs e) + { + if (DesignerProperties.GetIsInDesignMode(this)) return; + 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; + + // In order to prevent resource leaks, unsubscribe from SizeChanged event for case when we have no stored Layout settings. + SizeChanged -= OnSizeChanged; + SizeChanged += OnSizeChanged; + } + + SetupAutoHideWindow(); + + foreach (var fwc in _fwHiddenList) + { + fwc.EnableBindings(); + if (fwc.KeepContentVisibleOnClose) + { + fwc.Show(); + fwc.KeepContentVisibleOnClose = false; + } + + _fwList.Add(fwc); + } + _fwHiddenList.Clear(); + + // load floating windows not already loaded! (issue #59) + var items = new List(Layout.FloatingWindows.Where(fw => !_fwList.Any(fwc => fwc.Model == fw))); + foreach (var fw in items) + _fwList.Add(CreateUIElementForModel(fw) as LayoutFloatingWindowControl); + + //create the overlaywindow if it's possible + if (IsVisible) + CreateOverlayWindow(); + FocusElementManager.SetupFocusManagement(this); + } + + /// Method executes when the control has changed its height and/or width. + /// + /// + private void OnSizeChanged(object sender, SizeChangedEventArgs e) + { + // Lets make sure this always remains non-negative to avoid crach in layout system + var width = Math.Max(ActualWidth - GridSplitterWidth - RightSidePanel.ActualWidth - LeftSidePanel.ActualWidth, 0); + var height = Math.Max(ActualHeight - GridSplitterHeight - TopSidePanel.ActualHeight - BottomSidePanel.ActualHeight, 0); + + LayoutRootPanel.AdjustFixedChildrenPanelSizes(new Size(width, height)); + } + + private void DockingManager_Unloaded(object sender, RoutedEventArgs e) + { + SizeChanged -= OnSizeChanged; + + if (DesignerProperties.GetIsInDesignMode(this)) return; + _autoHideWindowManager?.HideAutoWindow(); + + AutoHideWindow?.Dispose(); + + foreach (var fw in _fwList.ToArray()) + { + ////fw.Owner = null; + //fw.SetParentWindowToNull(); + //fw.KeepContentVisibleOnClose = true; + //// To avoid calling Close method multiple times. + //fw.InternalClose(true); + + // Unloaded can occure not only after closing of the application, but after switching between tabs. + // For such case it's better to hide the floating windows instead of closing it. + // We clear bindings on visibility during the owner is unloaded. + if (fw.IsVisible) + { + fw.KeepContentVisibleOnClose = true; + fw.Hide(); + } + fw.DisableBindings(); + _fwHiddenList.Add(fw); + } + + _fwList.Clear(); + + DestroyOverlayWindow(); + FocusElementManager.FinalizeFocusManagement(this); + } + + private void SetupAutoHideWindow() + { + if (_autoHideWindowManager != null) + _autoHideWindowManager.HideAutoWindow(); + else + _autoHideWindowManager = new AutoHideWindowManager(this); + + AutoHideWindow?.Dispose(); + SetAutoHideWindow(new LayoutAutoHideWindowControl()); + } + + private void CreateOverlayWindow() + { + if (_overlayWindow == null) + _overlayWindow = new OverlayWindow(this); + var rectWindow = new Rect(this.PointToScreenDPIWithoutFlowDirection(new Point()), this.TransformActualSizeToAncestor()); + _overlayWindow.Left = rectWindow.Left; + _overlayWindow.Top = rectWindow.Top; + _overlayWindow.Width = rectWindow.Width; + _overlayWindow.Height = rectWindow.Height; + } + + private void DestroyOverlayWindow() + { + if (_overlayWindow == null) return; + _overlayWindow.Close(); + _overlayWindow = null; + } + + private void AttachDocumentsSource(LayoutRoot layout, IEnumerable documentsSource) + { + if (documentsSource == null) return; + if (layout == null) return; + + //if (layout.Descendents().OfType().Any()) + // throw new InvalidOperationException("Unable to set the DocumentsSource property if LayoutDocument objects are already present in the model"); + var documentsImported = layout.Descendents().OfType().Select(d => d.Content).ToArray(); + var documents = documentsSource as IEnumerable; + var listOfDocumentsToImport = new List(documents.OfType()); + + foreach (var document in listOfDocumentsToImport.ToArray()) + { + if (documentsImported.Contains(document)) + listOfDocumentsToImport.Remove(document); + } + + LayoutDocumentPane documentPane = null; + if (layout.LastFocusedDocument != null) + documentPane = layout.LastFocusedDocument.Parent as LayoutDocumentPane; + + if (documentPane == null) + documentPane = layout.Descendents().OfType().FirstOrDefault(); + + //if (documentPane == null) + // throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents"); + + _suspendLayoutItemCreation = true; + foreach (var documentContentToImport in listOfDocumentsToImport) + { + //documentPane.Children.Add(new LayoutDocument() { Content = documentToImport }); + var documentToImport = new LayoutDocument { Content = documentContentToImport }; + + var 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); + } + + LayoutUpdateStrategy?.AfterInsertDocument(layout, documentToImport); + CreateDocumentLayoutItem(documentToImport); + } + _suspendLayoutItemCreation = false; + if (documentsSource is INotifyCollectionChanged documentsSourceAsNotifier) + documentsSourceAsNotifier.CollectionChanged += DocumentsSourceElementsChanged; + } + + private void DocumentsSourceElementsChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (Layout == null) return; + //When deserializing documents are created automatically by the deserializer + if (SuspendDocumentsSourceBinding) return; + + //handle remove + if (e.Action == NotifyCollectionChangedAction.Remove || + e.Action == NotifyCollectionChangedAction.Replace) + { + if (e.OldItems != null) + { + var documentsToRemove = Layout.Descendents().OfType().Where(d => e.OldItems.Contains(d.Content)).ToArray(); + foreach (var documentToRemove in documentsToRemove) + { + documentToRemove.Parent.RemoveChild(documentToRemove); + RemoveViewFromLogicalChild(documentToRemove); + } + } + } + + //handle add + if (e.NewItems != null && (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace)) + { + if (e.NewItems != null) + { + LayoutDocumentPane documentPane = null; + if (Layout.LastFocusedDocument != null) + { + documentPane = Layout.LastFocusedDocument.Parent as LayoutDocumentPane; + } + if (documentPane == null) + { + documentPane = Layout.Descendents().OfType().FirstOrDefault(); + } + //if (documentPane == null) + // throw new InvalidOperationException("Layout must contains at least one LayoutDocumentPane in order to host documents"); + _suspendLayoutItemCreation = true; + foreach (var documentContentToImport in e.NewItems) + { + var documentToImport = new LayoutDocument + { + Content = documentContentToImport + }; + + var 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; + } + + LayoutUpdateStrategy?.AfterInsertDocument(Layout, documentToImport); + var root = documentToImport.Root; + if (root != null && root.Manager == this) + { + CreateDocumentLayoutItem(documentToImport); + } + } + _suspendLayoutItemCreation = false; + } + } + + if (e.Action == NotifyCollectionChangedAction.Reset) + { + //NOTE: I'm going to clear every document present in layout but + //some documents may have been added directly to the layout, for now I clear them too + var documentsToRemove = Layout.Descendents().OfType().ToArray(); + foreach (var documentToRemove in documentsToRemove) + { + (documentToRemove.Parent as ILayoutContainer).RemoveChild( + documentToRemove); + RemoveViewFromLogicalChild(documentToRemove); + } + } + + Layout?.CollectGarbage(); + } + + private void DetachDocumentsSource(LayoutRoot layout, IEnumerable documentsSource) + { + if (documentsSource == null) return; + if (layout == null) return; + + var documentsToRemove = layout.Descendents().OfType() + .Where(d => documentsSource.Contains(d.Content)).ToArray(); + + foreach (var documentToRemove in documentsToRemove) + { + (documentToRemove.Parent as ILayoutContainer).RemoveChild( + documentToRemove); + RemoveViewFromLogicalChild(documentToRemove); + } + + if (documentsSource is INotifyCollectionChanged documentsSourceAsNotifier) + documentsSourceAsNotifier.CollectionChanged -= DocumentsSourceElementsChanged; + } + + private void Close(LayoutContent contentToClose) + { + if (!contentToClose.CanClose) return; + + var layoutItem = GetLayoutItemFromModel(contentToClose); + if (layoutItem.CloseCommand != null) + { + if (layoutItem.CloseCommand.CanExecute(null)) + layoutItem.CloseCommand.Execute(null); + } + else + { + if (contentToClose is LayoutDocument document) + ExecuteCloseCommand(document); + else if (contentToClose is LayoutAnchorable anchorable) + ExecuteCloseCommand(anchorable); + } + } + + private void AttachAnchorablesSource(LayoutRoot layout, IEnumerable anchorablesSource) + { + if (anchorablesSource == null) return; + if (layout == null) return; + + //if (layout.Descendents().OfType().Any()) + // throw new InvalidOperationException("Unable to set the AnchorablesSource property if LayoutAnchorable objects are already present in the model"); + var anchorablesImported = layout.Descendents().OfType().Select(d => d.Content).ToArray(); + var anchorables = anchorablesSource as IEnumerable; + var listOfAnchorablesToImport = new List(anchorables.OfType()); + + foreach (var document in listOfAnchorablesToImport.ToArray()) + { + if (anchorablesImported.Contains(document)) + listOfAnchorablesToImport.Remove(document); + } + LayoutAnchorablePane anchorablePane = null; + if (layout.ActiveContent != null) + { + //look for active content parent pane + anchorablePane = layout.ActiveContent.Parent as LayoutAnchorablePane; + } + if (anchorablePane == null) + { + //look for a pane on the right side + anchorablePane = layout.Descendents().OfType().FirstOrDefault(pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right); + } + if (anchorablePane == null) + { + //look for an available pane + anchorablePane = layout.Descendents().OfType().FirstOrDefault(); + } + _suspendLayoutItemCreation = true; + foreach (var anchorableContentToImport in listOfAnchorablesToImport) + { + var anchorableToImport = new LayoutAnchorable { Content = anchorableContentToImport }; + var 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; + } + + LayoutUpdateStrategy?.AfterInsertAnchorable(layout, anchorableToImport); + CreateAnchorableLayoutItem(anchorableToImport); + } + _suspendLayoutItemCreation = false; + if (anchorablesSource is INotifyCollectionChanged anchorablesSourceAsNotifier) + anchorablesSourceAsNotifier.CollectionChanged += AnchorablesSourceElementsChanged; + } + + private void AnchorablesSourceElementsChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (Layout == null) return; + + //When deserializing documents are created automatically by the deserializer + if (SuspendAnchorablesSourceBinding) return; + + //handle remove + if (e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Replace) + { + if (e.OldItems != null) + { + var anchorablesToRemove = Layout.Descendents().OfType().Where(d => e.OldItems.Contains(d.Content)).ToArray(); + foreach (var anchorableToRemove in anchorablesToRemove) + { + anchorableToRemove.Content = null; + anchorableToRemove.Parent.RemoveChild(anchorableToRemove); + RemoveViewFromLogicalChild(anchorableToRemove); + } + } + } + + //handle add + if (e.NewItems != null && (e.Action == NotifyCollectionChangedAction.Add || e.Action == 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().FirstOrDefault(pane => !pane.IsHostedInFloatingWindow && pane.GetSide() == AnchorSide.Right); + } + if (anchorablePane == null) + { + //look for an available pane + anchorablePane = Layout.Descendents().OfType().FirstOrDefault(); + } + _suspendLayoutItemCreation = true; + foreach (var anchorableContentToImport in e.NewItems) + { + var anchorableToImport = new LayoutAnchorable { Content = anchorableContentToImport }; + var 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; + } + LayoutUpdateStrategy?.AfterInsertAnchorable(Layout, anchorableToImport); + var root = anchorableToImport.Root; + if (root != null && root.Manager == this) + CreateAnchorableLayoutItem(anchorableToImport); + } + _suspendLayoutItemCreation = false; + } + } + + if (e.Action == NotifyCollectionChangedAction.Reset) + { + //NOTE: I'm going to clear every anchorable present in layout but + //some anchorable may have been added directly to the layout, for now I clear them too + var anchorablesToRemove = Layout.Descendents().OfType().ToArray(); + foreach (var anchorableToRemove in anchorablesToRemove) + { + (anchorableToRemove.Parent as ILayoutContainer).RemoveChild( + anchorableToRemove); + RemoveViewFromLogicalChild(anchorableToRemove); + } + } + + Layout?.CollectGarbage(); + } + + private void DetachAnchorablesSource(LayoutRoot layout, IEnumerable anchorablesSource) + { + if (anchorablesSource == null) return; + if (layout == null) return; + + var anchorablesToRemove = layout.Descendents().OfType() + .Where(d => anchorablesSource.Contains(d.Content)).ToArray(); + + foreach (var anchorableToRemove in anchorablesToRemove) + { + anchorableToRemove.Parent.RemoveChild(anchorableToRemove); + RemoveViewFromLogicalChild(anchorableToRemove); + } + + if (anchorablesSource is INotifyCollectionChanged anchorablesSourceAsNotifier) + anchorablesSourceAsNotifier.CollectionChanged -= AnchorablesSourceElementsChanged; + } + + private void RemoveViewFromLogicalChild(LayoutContent layoutContent) + { + if (layoutContent == null) return; + var layoutItem = GetLayoutItemFromModel(layoutContent); + if (layoutItem == null) return; + if (layoutItem.IsViewExists()) InternalRemoveLogicalChild(layoutItem.View); + } + + private void InternalSetActiveContent(object contentObject) + { + // BugFix for first issue in #59 + var list = Layout.Descendents().OfType().ToList(); + var layoutContent = list.FirstOrDefault(lc => lc == contentObject || lc.Content == contentObject); + _insideInternalSetActiveContent = true; + Layout.ActiveContent = layoutContent; + _insideInternalSetActiveContent = false; + } + + #region LayoutItems + /// + /// Implements the EventHandler for the event. + /// + /// + /// + private void Layout_ElementRemoved(object sender, LayoutElementEventArgs e) + { + if (_suspendLayoutItemCreation) return; + CollectLayoutItemsDeleted(); + } + + /// + /// Implements the EventHandler for the event. + /// + /// + /// + private void Layout_ElementAdded(object sender, LayoutElementEventArgs e) + { + if (_suspendLayoutItemCreation) return; + foreach (var content in Layout.Descendents().OfType().ToList()) + { + if (content is LayoutDocument) + CreateDocumentLayoutItem(content as LayoutDocument); + else //if (content is LayoutAnchorable) + CreateAnchorableLayoutItem(content as LayoutAnchorable); + } + CollectLayoutItemsDeleted(); + } + + /// + /// Detach and remove all LayoutItems that are no longer part of the . + /// + private void CollectLayoutItemsDeleted() + { + if (_collectLayoutItemsOperations != null) return; + _collectLayoutItemsOperations = Dispatcher.BeginInvoke(new Action(() => + { + _collectLayoutItemsOperations = null; + foreach (var itemToRemove in _layoutItems.Where(item => item.LayoutElement.Root != Layout).ToArray()) + { + itemToRemove.Detach(); + _layoutItems.Remove(itemToRemove); + } + })); + } + + /// + /// Detaches all LayoutItems from their content and clears the private collection of LayoutItems. + /// + private void DetachLayoutItems() + { + if (Layout == null) return; + _layoutItems.ForEach(i => i.Detach()); + _layoutItems.Clear(); + Layout.ElementAdded -= Layout_ElementAdded; + Layout.ElementRemoved -= Layout_ElementRemoved; + } + + /// + /// Attaches a: + /// - to each and + /// - to each + /// + /// in the property. + /// + private void AttachLayoutItems() + { + if (Layout == null) return; + foreach (var document in Layout.Descendents().OfType().ToArray()) + CreateDocumentLayoutItem(document); + + foreach (var anchorable in Layout.Descendents().OfType().ToArray()) + CreateAnchorableLayoutItem(anchorable); + + Layout.ElementAdded += Layout_ElementAdded; + Layout.ElementRemoved += Layout_ElementRemoved; + } + + /// + /// Applies the corresponding style to a either from: + /// 1) property or + /// 2) property + /// + /// + private void ApplyStyleToLayoutItem(LayoutItem layoutItem) + { + layoutItem._ClearDefaultBindings(); + if (LayoutItemContainerStyle != null) + layoutItem.Style = LayoutItemContainerStyle; + else if (LayoutItemContainerStyleSelector != null) + layoutItem.Style = LayoutItemContainerStyleSelector.SelectStyle(layoutItem.Model, layoutItem); + layoutItem._SetDefaultBindings(); + } + + /// + /// Creates a for each + /// or returns the existing if there is already one. + /// + /// + private void CreateAnchorableLayoutItem(LayoutAnchorable contentToAttach) + { + if (_layoutItems.Any(item => item.LayoutElement == contentToAttach)) + { + foreach (var item in _layoutItems) ApplyStyleToLayoutItem(item); + return; + } + + var layoutItem = new LayoutAnchorableItem(); + layoutItem.Attach(contentToAttach); + _layoutItems.Add(layoutItem); + ApplyStyleToLayoutItem(layoutItem); + if (contentToAttach?.Content is UIElement) InternalAddLogicalChild(contentToAttach.Content); + } + + /// + /// Creates a for each + /// or returns the existing if there is already one. + /// + /// + private void CreateDocumentLayoutItem(LayoutDocument contentToAttach) + { + if (_layoutItems.Any(item => item.LayoutElement == contentToAttach)) + { + foreach (var item in _layoutItems) ApplyStyleToLayoutItem(item); + return; + } + + var layoutItem = new LayoutDocumentItem(); + layoutItem.Attach(contentToAttach); + _layoutItems.Add(layoutItem); + ApplyStyleToLayoutItem(layoutItem); + if (contentToAttach?.Content is UIElement) InternalAddLogicalChild(contentToAttach.Content); + } + #endregion LayoutItems + + private void ShowNavigatorWindow() + { + if (_navigatorWindow == null) + _navigatorWindow = new NavigatorWindow(this) { Owner = Window.GetWindow(this), WindowStartupLocation = WindowStartupLocation.CenterOwner }; + _navigatorWindow.ShowDialog(); + _navigatorWindow = null; + } + + [SuppressMessage("Style", "IDE0056:使用索引运算符", Justification = "<挂起>")] + private LayoutFloatingWindowControl CreateFloatingWindowForLayoutAnchorableWithoutParent(LayoutAnchorablePane paneModel, bool isContentImmutable) + { + if (paneModel.Children.Any(c => !c.CanFloat)) + return null; + var paneAsPositionableElement = paneModel as ILayoutPositionableElement; + var paneAsWithActualSize = paneModel as ILayoutPositionableElementWithActualSize; + + var fwWidth = paneAsPositionableElement.FloatingWidth; + var fwHeight = paneAsPositionableElement.FloatingHeight; + var fwLeft = paneAsPositionableElement.FloatingLeft; + var fwTop = paneAsPositionableElement.FloatingTop; + + if (fwWidth == 0.0) + fwWidth = paneAsWithActualSize.ActualWidth + 10; //10 includes BorderThickness and Margins inside LayoutAnchorableFloatingWindowControl. + if (fwHeight == 0.0) + fwHeight = paneAsWithActualSize.ActualHeight + 10; //10 includes BorderThickness and Margins inside LayoutAnchorableFloatingWindowControl. + + var destPane = new LayoutAnchorablePane + { + DockWidth = paneAsPositionableElement.DockWidth, + DockHeight = paneAsPositionableElement.DockHeight, + DockMinHeight = paneAsPositionableElement.DockMinHeight, + DockMinWidth = paneAsPositionableElement.DockMinWidth, + FloatingLeft = paneAsPositionableElement.FloatingLeft, + FloatingTop = paneAsPositionableElement.FloatingTop, + FloatingWidth = paneAsPositionableElement.FloatingWidth, + FloatingHeight = paneAsPositionableElement.FloatingHeight, + }; + + var savePreviousContainer = paneModel.FindParent() == null; + var currentSelectedContentIndex = paneModel.SelectedContentIndex; + while (paneModel.Children.Count > 0) + { + var contentModel = paneModel.Children[paneModel.Children.Count - 1]; + + if (savePreviousContainer) + { + ((ILayoutPreviousContainer)contentModel).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((LayoutAnchorableFloatingWindow)fw, isContentImmutable) + { + Width = fwWidth, + Height = fwHeight, + Top = fwTop, + Left = fwLeft + }; + //fwc.Owner = Window.GetWindow(this); + //fwc.SetParentToMainWindowOf(this); + _fwList.Add(fwc); + Layout.CollectGarbage(); + InvalidateArrange(); + return fwc; + } + + private LayoutFloatingWindowControl CreateFloatingWindowCore(LayoutContent contentModel, bool isContentImmutable) + { + if (!contentModel.CanFloat) return null; + if (contentModel is LayoutAnchorable contentModelAsAnchorable && 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() == null) + { + ((ILayoutPreviousContainer)contentModel).PreviousContainer = parentPane; + contentModel.PreviousContainerIndex = contentModelParentChildrenIndex; + } + + parentPane.RemoveChildAt(contentModelParentChildrenIndex); + + var fwWidth = contentModel.FloatingWidth; + var fwHeight = contentModel.FloatingHeight; + + if (fwWidth == 0.0) + fwWidth = parentPaneAsPositionableElement.FloatingWidth; + if (fwHeight == 0.0) + fwHeight = parentPaneAsPositionableElement.FloatingHeight; + + if (fwWidth == 0.0) + fwWidth = parentPaneAsWithActualSize.ActualWidth + 10; //10 includes BorderThickness and Margins inside LayoutDocumentFloatingWindowControl. + if (fwHeight == 0.0) + fwHeight = parentPaneAsWithActualSize.ActualHeight + 10; //10 includes BorderThickness and Margins inside LayoutDocumentFloatingWindowControl. + + LayoutFloatingWindow fw; + LayoutFloatingWindowControl fwc; + if (contentModel is LayoutAnchorable) + { + var anchorableContent = contentModel as LayoutAnchorable; + fw = new LayoutAnchorableFloatingWindow + { + RootPanel = new LayoutAnchorablePaneGroup(new LayoutAnchorablePane(anchorableContent) + { + DockWidth = parentPaneAsPositionableElement.DockWidth, + DockHeight = parentPaneAsPositionableElement.DockHeight, + DockMinHeight = parentPaneAsPositionableElement.DockMinHeight, + DockMinWidth = parentPaneAsPositionableElement.DockMinWidth, + FloatingLeft = parentPaneAsPositionableElement.FloatingLeft, + FloatingTop = parentPaneAsPositionableElement.FloatingTop, + FloatingWidth = parentPaneAsPositionableElement.FloatingWidth, + FloatingHeight = parentPaneAsPositionableElement.FloatingHeight, + }) + }; + + Layout.FloatingWindows.Add(fw); + fwc = new LayoutAnchorableFloatingWindowControl((LayoutAnchorableFloatingWindow)fw, isContentImmutable) + { + Width = fwWidth, + Height = fwHeight, + Left = contentModel.FloatingLeft, + Top = contentModel.FloatingTop + }; + } + else + { + var anchorableDocument = contentModel as LayoutDocument; + fw = new LayoutDocumentFloatingWindow + { + RootPanel = new LayoutDocumentPaneGroup(new LayoutDocumentPane(anchorableDocument) + { + 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 LayoutDocumentFloatingWindowControl((LayoutDocumentFloatingWindow)fw, isContentImmutable) + { + Width = fwWidth, + Height = fwHeight, + Left = contentModel.FloatingLeft, + Top = contentModel.FloatingTop + }; + } + //fwc.Owner = Window.GetWindow(this); + //fwc.SetParentToMainWindowOf(this); + _fwList.Add(fwc); + Layout.CollectGarbage(); + UpdateLayout(); + return fwc; + } + + #endregion Private Methods + } } diff --git a/source/Components/AvalonDock/Layout/LayoutAnchorable.cs b/source/Components/AvalonDock/Layout/LayoutAnchorable.cs index 335f8e57..d9cb1dff 100644 --- a/source/Components/AvalonDock/Layout/LayoutAnchorable.cs +++ b/source/Components/AvalonDock/Layout/LayoutAnchorable.cs @@ -485,9 +485,11 @@ public void ToggleAutoHide() case AnchorSide.Bottom: if (parentGroup.Root.RootPanel.Orientation == Orientation.Vertical) { - previousContainer = new LayoutAnchorablePane(); - previousContainer.DockMinHeight = AutoHideMinHeight; - parentGroup.Root.RootPanel.Children.Add(previousContainer); + previousContainer = new LayoutAnchorablePane + { + DockMinHeight = AutoHideMinHeight + }; + parentGroup.Root.RootPanel.Children.Add(previousContainer); } else { diff --git a/source/Components/AvalonDock/Layout/LayoutContent.cs b/source/Components/AvalonDock/Layout/LayoutContent.cs index fc8e3456..9c73f64e 100644 --- a/source/Components/AvalonDock/Layout/LayoutContent.cs +++ b/source/Components/AvalonDock/Layout/LayoutContent.cs @@ -179,8 +179,9 @@ public bool IsActive RaisePropertyChanging(nameof(IsActive)); var oldValue = _isActive; _isActive = value; + if (Root?.ActiveContent != this && value) Root.ActiveContent = this; var root = Root; - if (root != null && _isActive) root.ActiveContent = this; + if (root != null && _isActive && root.ActiveContent != this) root.ActiveContent = this; if (_isActive) IsSelected = true; OnIsActiveChanged(oldValue, value); RaisePropertyChanged(nameof(IsActive)); diff --git a/source/Components/AvalonDock/Layout/LayoutDocument.cs b/source/Components/AvalonDock/Layout/LayoutDocument.cs index 42579494..3fe144b9 100644 --- a/source/Components/AvalonDock/Layout/LayoutDocument.cs +++ b/source/Components/AvalonDock/Layout/LayoutDocument.cs @@ -98,7 +98,7 @@ public override void Close() if (Root?.Manager != null) { var dockingManager = Root.Manager; - dockingManager._ExecuteCloseCommand(this); + dockingManager.ExecuteCloseCommand(this); } else CloseDocument(); diff --git a/source/Components/AvalonDock/Layout/LayoutRoot.cs b/source/Components/AvalonDock/Layout/LayoutRoot.cs index c32adeb2..e82c9d76 100644 --- a/source/Components/AvalonDock/Layout/LayoutRoot.cs +++ b/source/Components/AvalonDock/Layout/LayoutRoot.cs @@ -367,8 +367,8 @@ public void CollectGarbage() foreach (var contentReferencingEmptyPane in this.Descendents().OfType() .Where(c => ((ILayoutPreviousContainer)c).PreviousContainer == emptyPane && !c.IsFloating)) { - if (contentReferencingEmptyPane is LayoutAnchorable && - !((LayoutAnchorable)contentReferencingEmptyPane).IsVisible) + if (contentReferencingEmptyPane is LayoutAnchorable anchorable && + !anchorable.IsVisible) continue; ((ILayoutPreviousContainer)contentReferencingEmptyPane).PreviousContainer = null; @@ -743,10 +743,10 @@ private void _hiddenAnchorables_CollectionChanged(object sender, System.Collecti private void InternalSetActiveContent(LayoutContent currentValue, LayoutContent newActiveContent) { RaisePropertyChanging(nameof(ActiveContent)); - if (currentValue != null) currentValue.IsActive = false; + if (currentValue != null && currentValue.IsActive) currentValue.IsActive = false; _activeContent = new WeakReference(newActiveContent); currentValue = ActiveContent; - if (currentValue != null) currentValue.IsActive = true; + if (currentValue != null&& !currentValue.IsActive) currentValue.IsActive = true; RaisePropertyChanged(nameof(ActiveContent)); _activeContentSet = currentValue != null; if (currentValue != null) @@ -850,15 +850,13 @@ private List ReadElementList(XmlReader reader, bool isFloatingWindow) { if (isFloatingWindow) { - var result = ReadElement(reader) as LayoutFloatingWindow; - if (result == null) break; - resultList.Add(result); + if (!(ReadElement(reader) is LayoutFloatingWindow result)) break; + resultList.Add(result); } else { - var result = ReadElement(reader) as LayoutAnchorable; - if (result == null) break; - resultList.Add(result); + if (!(ReadElement(reader) is LayoutAnchorable result)) break; + resultList.Add(result); } } @@ -937,13 +935,12 @@ void DumpElement(ILayoutElement element, StringBuilder indent, int childID, bool Debug.Write($"{indent}{(indent.Length > 0 ? isLastChild ? " └─ " : " ├─ " : "")}{childID:D2} 0x{element.GetHashCode():X8} " + $"{element.GetType().Name} {(shortPropertyNames ? "P" : "Parent")}:0x{element.Parent?.GetHashCode() ?? 0:X8} " + $"{(shortPropertyNames ? "R" : "Root")}:0x{element.Root?.GetHashCode() ?? 0:X8}"); - var containerElement = element as ILayoutContainer; - if (containerElement == null) - { - Debug.WriteLine(""); - return; - } - Debug.WriteLine($" {(shortPropertyNames ? "C" : "Children")}:{containerElement.ChildrenCount}"); + if (!(element is ILayoutContainer containerElement)) + { + Debug.WriteLine(""); + return; + } + Debug.WriteLine($" {(shortPropertyNames ? "C" : "Children")}:{containerElement.ChildrenCount}"); var nrChild = 0; indent.Append(isLastChild ? " " : " │ "); foreach (var child in containerElement.Children) diff --git a/source/Components/AvalonDock/Properties/AssemblyInfo.cs b/source/Components/AvalonDock/Properties/AssemblyInfo.cs index 11d67b6e..b5efdc77 100644 --- a/source/Components/AvalonDock/Properties/AssemblyInfo.cs +++ b/source/Components/AvalonDock/Properties/AssemblyInfo.cs @@ -43,5 +43,9 @@ This program is provided to you under the terms of the Microsoft Public [assembly: XmlnsDefinition("https://github.com/Dirkster99/AvalonDock", "AvalonDock.Converters")] [assembly: XmlnsDefinition("https://github.com/Dirkster99/AvalonDock", "AvalonDock.Layout")] [assembly: XmlnsDefinition("https://github.com/Dirkster99/AvalonDock", "AvalonDock.Themes")] - - +[assembly: XmlnsPrefix("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "avalondock")] +[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "AvalonDock")] +[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "AvalonDock.Controls")] +[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "AvalonDock.Converters")] +[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "AvalonDock.Layout")] +[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "AvalonDock.Themes")] \ No newline at end of file diff --git a/source/Components/AvalonDock/Properties/Resources.zh-Hans.resx b/source/Components/AvalonDock/Properties/Resources.zh-Hans.resx index fa4814ae..fea73fda 100644 --- a/source/Components/AvalonDock/Properties/Resources.zh-Hans.resx +++ b/source/Components/AvalonDock/Properties/Resources.zh-Hans.resx @@ -53,6 +53,7 @@ value : The object must be serialized with : System.Runtime.Serialization.Formatters.Soap.SoapFormatter : and then encoded with base64 encoding. + mimetype: application/x-microsoft.net.object.bytearray.base64 value : The object must be serialized into a byte array : using a System.ComponentModel.TypeConverter @@ -132,10 +133,10 @@ 停靠 - 停靠成标签式文档 + 作为选项卡式停靠 - 漂浮 + 浮动 隐藏 @@ -156,10 +157,10 @@ 窗口位置 - 停靠成标签式文档 + 作为选项卡式停靠 - 漂浮 + 浮动 移到下一标签组 diff --git a/source/Components/AvalonDock/Themes/generic.xaml b/source/Components/AvalonDock/Themes/generic.xaml index 35965dae..2c1b6372 100644 --- a/source/Components/AvalonDock/Themes/generic.xaml +++ b/source/Components/AvalonDock/Themes/generic.xaml @@ -1,1309 +1,1300 @@  + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:avalonDock="clr-namespace:AvalonDock" + xmlns:avalonDockControls="clr-namespace:AvalonDock.Controls" + xmlns:avalonDockConverters="clr-namespace:AvalonDock.Converters" + xmlns:avalonDockLayout="clr-namespace:AvalonDock.Layout" + xmlns:avalonDockProperties="clr-namespace:AvalonDock.Properties" + xmlns:shell="clr-namespace:Microsoft.Windows.Shell"> - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - + + + + - - - - - + + + + + + + - - - - - - - + + + + + + + + - - - - - - - - + - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - - - - + + + + + - - - - - + - + + + - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + - - - + + + - - - + + + - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - + + - - + + - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + - + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + diff --git a/source/Components/AvalonDock/Win32Helper.cs b/source/Components/AvalonDock/Win32Helper.cs index 7cf2b2a6..a865e74a 100644 --- a/source/Components/AvalonDock/Win32Helper.cs +++ b/source/Components/AvalonDock/Win32Helper.cs @@ -100,13 +100,13 @@ internal enum SetWindowPosFlags : uint [StructLayout(LayoutKind.Sequential)] internal class WINDOWPOS { - public IntPtr hwnd; - public IntPtr hwndInsertAfter; - public int x; - public int y; - public int cx; - public int cy; - public int flags; + public IntPtr Hwnd; + public IntPtr HwndInsertAfter; + public int X; + public int Y; + public int Cx; + public int Cy; + public int Flags; }; [DllImport("user32.dll")] @@ -285,15 +285,13 @@ public static implicit operator RECT(Rect rect) internal static RECT GetClientRect(IntPtr hWnd) { - RECT result = new RECT(); - GetClientRect(hWnd, out result); + GetClientRect(hWnd, out RECT result); return result; } internal static RECT GetWindowRect(IntPtr hWnd) { - RECT result = new RECT(); - GetWindowRect(hWnd, out result); + GetWindowRect(hWnd, out RECT result); return result; } diff --git a/source/Components/AvalonDock/WindowHelper.cs b/source/Components/AvalonDock/WindowHelper.cs index 75fd2c76..01c6b96d 100644 --- a/source/Components/AvalonDock/WindowHelper.cs +++ b/source/Components/AvalonDock/WindowHelper.cs @@ -18,7 +18,7 @@ static class WindowHelper { public static bool IsAttachedToPresentationSource(this Visual element) { - return PresentationSource.FromVisual(element as Visual) != null; + return PresentationSource.FromVisual(element) != null; } public static void SetParentToMainWindowOf(this Window window, Visual element) @@ -28,10 +28,9 @@ public static void SetParentToMainWindowOf(this Window window, Visual element) window.Owner = wndParent; else { - IntPtr parentHwnd; - if (GetParentWindowHandle(element, out parentHwnd)) - Win32Helper.SetOwner(new WindowInteropHelper(window).Handle, parentHwnd); - } + if (GetParentWindowHandle(element, out IntPtr parentHwnd)) + Win32Helper.SetOwner(new WindowInteropHelper(window).Handle, parentHwnd); + } } public static IntPtr GetParentWindowHandle(this Window window) @@ -46,12 +45,11 @@ public static IntPtr GetParentWindowHandle(this Window window) public static bool GetParentWindowHandle(this Visual element, out IntPtr hwnd) { hwnd = IntPtr.Zero; - HwndSource wpfHandle = PresentationSource.FromVisual(element) as HwndSource; - if (wpfHandle == null) - return false; + if (!(PresentationSource.FromVisual(element) is HwndSource wpfHandle)) + return false; - hwnd = Win32Helper.GetParent(wpfHandle.Handle); + hwnd = Win32Helper.GetParent(wpfHandle.Handle); if (hwnd == IntPtr.Zero) hwnd = wpfHandle.Handle; return true; diff --git a/source/MLibTest/MLibTest/App.xaml.cs b/source/MLibTest/MLibTest/App.xaml.cs index 56706481..d49d6407 100644 --- a/source/MLibTest/MLibTest/App.xaml.cs +++ b/source/MLibTest/MLibTest/App.xaml.cs @@ -116,11 +116,10 @@ private void Application_Startup(object sender, StartupEventArgs e) // Save session data and close application OnClosed(_appVM, _mainWindow); - var dispose = _appVM as IDisposable; - if (dispose != null) - dispose.Dispose(); + if (_appVM is IDisposable dispose) + dispose.Dispose(); - _mainWindow.DataContext = null; + _mainWindow.DataContext = null; }; MainWindow.Show(); @@ -165,14 +164,13 @@ private void ConstructMainWindowSession(AppViewModel workSpace, Application.Current.MainWindow = _mainWindow; _mainWindow.DataContext = _appVM; - // Establish command binding to accept user input via commanding framework - // workSpace.InitCommandBinding(win); + // Establish command binding to accept user input via commanding framework + // workSpace.InitCommandBinding(win); - ViewPosSizeModel viewSz; - settings.SessionData.WindowPosSz.TryGetValue(settings.SessionData.MainWindowName - , out viewSz); + settings.SessionData.WindowPosSz.TryGetValue(settings.SessionData.MainWindowName + , out ViewPosSizeModel viewSz); - viewSz.SetWindowsState(win); + viewSz.SetWindowsState(win); string lastActiveFile = settings.SessionData.LastActiveSolution; @@ -193,37 +191,33 @@ private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e) { try { - AppViewModel wsVM = base.MainWindow.DataContext as AppViewModel; - - if (wsVM != null) - { - var MainWindowCanClose = MainWindow as IMetroWindow; - - if (MainWindowCanClose != null) - { - if (MainWindowCanClose.IsContentDialogVisible == true) - { - e.Cancel = true; // Lets not close with open dialog - return; - } - } - - // Close all open files and check whether application is ready to close - if (wsVM.AppLifeCycle.Exit_CheckConditions(wsVM) == true) - { - // (other than exception and error handling) - wsVM.AppLifeCycle.OnRequestClose(true); - - _mainWindow.OnSaveLayout(); - e.Cancel = false; - } - else - { - wsVM.AppLifeCycle.CancelShutDown(); - e.Cancel = true; - } - } - } + if (base.MainWindow.DataContext is AppViewModel wsVM) + { + if (MainWindow is IMetroWindow MainWindowCanClose) + { + if (MainWindowCanClose.IsContentDialogVisible == true) + { + e.Cancel = true; // Lets not close with open dialog + return; + } + } + + // Close all open files and check whether application is ready to close + if (wsVM.AppLifeCycle.Exit_CheckConditions(wsVM) == true) + { + // (other than exception and error handling) + wsVM.AppLifeCycle.OnRequestClose(true); + + _mainWindow.OnSaveLayout(); + e.Cancel = false; + } + else + { + wsVM.AppLifeCycle.CancelShutDown(); + e.Cancel = true; + } + } + } catch (Exception exp) { Debug.WriteLine(exp); @@ -241,10 +235,9 @@ private void OnClosed(AppViewModel appVM, IViewSize win) { var settings = GetService(); - ViewPosSizeModel viewSz; - settings.SessionData.WindowPosSz.TryGetValue(settings.SessionData.MainWindowName - , out viewSz); - viewSz.GetWindowsState(win); + settings.SessionData.WindowPosSz.TryGetValue(settings.SessionData.MainWindowName + , out ViewPosSizeModel viewSz); + viewSz.GetWindowsState(win); _appVM.GetSessionData(settings.SessionData); diff --git a/source/MLibTest/MLibTest/Demos/ViewModels/Tools/ColorPickerViewModel.cs b/source/MLibTest/MLibTest/Demos/ViewModels/Tools/ColorPickerViewModel.cs index a3fe49f7..a00d2903 100644 --- a/source/MLibTest/MLibTest/Demos/ViewModels/Tools/ColorPickerViewModel.cs +++ b/source/MLibTest/MLibTest/Demos/ViewModels/Tools/ColorPickerViewModel.cs @@ -28,7 +28,7 @@ internal class ColorPickerViewModel : ToolViewModel /// public const string ToolTitle = "Color Picker"; - private IWorkSpaceViewModel _workSpaceViewModel = null; + private readonly IWorkSpaceViewModel _workSpaceViewModel = null; private Color _SelectedBackgroundColor; private Color _SelectedAccentColor; diff --git a/source/MLibTest/MLibTest/Demos/ViewModels/Tools/FileStatsViewModel.cs b/source/MLibTest/MLibTest/Demos/ViewModels/Tools/FileStatsViewModel.cs index 3b4329ca..f020f84c 100644 --- a/source/MLibTest/MLibTest/Demos/ViewModels/Tools/FileStatsViewModel.cs +++ b/source/MLibTest/MLibTest/Demos/ViewModels/Tools/FileStatsViewModel.cs @@ -22,7 +22,7 @@ internal class FileStatsViewModel : ToolViewModel /// public const string ToolTitle = "File Stats"; - private IWorkSpaceViewModel _workSpaceViewModel = null; + private readonly IWorkSpaceViewModel _workSpaceViewModel = null; private DateTime _lastModified; private long _fileSize; diff --git a/source/MLibTest/MLibTest/MainWindow.xaml b/source/MLibTest/MLibTest/MainWindow.xaml index 19ba3993..780c084c 100644 --- a/source/MLibTest/MLibTest/MainWindow.xaml +++ b/source/MLibTest/MLibTest/MainWindow.xaml @@ -1,204 +1,215 @@  - - - - - - - - - - + x:Class="MLibTest.MainWindow" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:MWindow="clr-namespace:MWindowLib;assembly=MWindowLib" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:demos="clr-namespace:MLibTest.Demos" + xmlns:demoviews="clr-namespace:MLibTest.Demos.Views" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + x:Name="mainWindow" + Title="MainWindow" + mc:Ignorable="d"> + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/MLibTest/MLibTest_Components/Settings/Settings/Settings.csproj b/source/MLibTest/MLibTest_Components/Settings/Settings/Settings.csproj index bffb5ccb..c00df423 100644 --- a/source/MLibTest/MLibTest_Components/Settings/Settings/Settings.csproj +++ b/source/MLibTest/MLibTest_Components/Settings/Settings/Settings.csproj @@ -106,6 +106,9 @@ + + .editorconfig + diff --git a/source/MVVMTestApp/App.xaml b/source/MVVMTestApp/App.xaml index c087d643..3cd782e8 100644 --- a/source/MVVMTestApp/App.xaml +++ b/source/MVVMTestApp/App.xaml @@ -1,8 +1,10 @@ - - - - + + + + diff --git a/source/MVVMTestApp/MVVMTestApp.csproj b/source/MVVMTestApp/MVVMTestApp.csproj index 5bb78ef0..147851a2 100644 --- a/source/MVVMTestApp/MVVMTestApp.csproj +++ b/source/MVVMTestApp/MVVMTestApp.csproj @@ -12,6 +12,11 @@ + + + + + diff --git a/source/MVVMTestApp/MainWindow.xaml b/source/MVVMTestApp/MainWindow.xaml index 4fd63b39..7708e4c2 100644 --- a/source/MVVMTestApp/MainWindow.xaml +++ b/source/MVVMTestApp/MainWindow.xaml @@ -1,117 +1,122 @@  - - - True - False - - - - - - - - - - - - - - - - - - - - - - - - + x:Class="AvalonDock.MVVMTestApp.MainWindow" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:conv="clr-namespace:AvalonDock.MVVMTestApp.Converters" + xmlns:local="clr-namespace:AvalonDock.MVVMTestApp" + xmlns:sys="clr-namespace:System;assembly=System.Runtime" + x:Name="mainWindow" + Title="MVVMTestApp" + Width="525" + Height="350" + UseLayoutRounding="True"> + + + True + False + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/MVVMTestApp/MainWindow.xaml.cs b/source/MVVMTestApp/MainWindow.xaml.cs index f11bae09..4129791d 100644 --- a/source/MVVMTestApp/MainWindow.xaml.cs +++ b/source/MVVMTestApp/MainWindow.xaml.cs @@ -60,19 +60,19 @@ public ICommand LoadLayoutCommand { if (_loadLayoutCommand == null) { - _loadLayoutCommand = new RelayCommand((p) => OnLoadLayout(p), (p) => CanLoadLayout(p)); + _loadLayoutCommand = new RelayCommand((p) => OnLoadLayout(), (p) => CanLoadLayout()); } return _loadLayoutCommand; } } - private bool CanLoadLayout(object parameter) + private bool CanLoadLayout() { return File.Exists(@".\AvalonDock.Layout.config"); } - private void OnLoadLayout(object parameter) + private void OnLoadLayout() { var layoutSerializer = new XmlLayoutSerializer(dockManager); @@ -103,19 +103,19 @@ public ICommand SaveLayoutCommand { if (_saveLayoutCommand == null) { - _saveLayoutCommand = new RelayCommand((p) => OnSaveLayout(p), (p) => CanSaveLayout(p)); + _saveLayoutCommand = new RelayCommand((p) => OnSaveLayout(), (p) => CanSaveLayout()); } return _saveLayoutCommand; } } - private bool CanSaveLayout(object parameter) + private bool CanSaveLayout() { return true; } - private void OnSaveLayout(object parameter) + private void OnSaveLayout() { var layoutSerializer = new XmlLayoutSerializer(dockManager); layoutSerializer.Serialize(@".\AvalonDock.Layout.config"); diff --git a/source/MVVMTestApp/Workspace.cs b/source/MVVMTestApp/Workspace.cs index 0f66fb4b..3ea348e5 100644 --- a/source/MVVMTestApp/Workspace.cs +++ b/source/MVVMTestApp/Workspace.cs @@ -6,178 +6,210 @@ using Microsoft.Win32; using System.IO; using System.Windows; +using AvalonDock.Themes; namespace AvalonDock.MVVMTestApp { - internal class Workspace : ViewModelBase - { - #region fields - static Workspace _this = new Workspace(); - - ToolViewModel[] _tools = null; - private ObservableCollection _files = new ObservableCollection(); - private ReadOnlyObservableCollection _readonyFiles = null; - private FileViewModel _activeDocument = null; - FileStatsViewModel _fileStats = null; - RelayCommand _openCommand = null; - RelayCommand _newCommand = null; - #endregion fields - - #region constructors - /// - /// Class constructor - /// - protected Workspace() - { - } - #endregion constructors - - public event EventHandler ActiveDocumentChanged; - - #region properties - public static Workspace This => _this; - - public ReadOnlyObservableCollection Files - { - get - { - if (_readonyFiles == null) - _readonyFiles = new ReadOnlyObservableCollection(_files); - - return _readonyFiles; - } - } - - public IEnumerable Tools - { - get - { - if (_tools == null) - _tools = new ToolViewModel[] { FileStats }; - return _tools; - } - } - - public FileStatsViewModel FileStats - { - get - { - if (_fileStats == null) - _fileStats = new FileStatsViewModel(); - - return _fileStats; - } - } - - public ICommand OpenCommand - { - get - { - if (_openCommand == null) - { - _openCommand = new RelayCommand((p) => OnOpen(p), (p) => CanOpen(p)); - } - - return _openCommand; - } - } - - public ICommand NewCommand - { - get - { - if (_newCommand == null) - { - _newCommand = new RelayCommand((p) => OnNew(p), (p) => CanNew(p)); - } - - return _newCommand; - } - } - - public FileViewModel ActiveDocument - { - get => _activeDocument; - set - { - if (_activeDocument != value) - { - _activeDocument = value; - RaisePropertyChanged(nameof(ActiveDocument)); - if (ActiveDocumentChanged != null) - ActiveDocumentChanged(this, EventArgs.Empty); - } - } - } - #endregion properties - - #region methods - internal void Close(FileViewModel fileToClose) - { - if (fileToClose.IsDirty) - { - var res = MessageBox.Show(string.Format("Save changes for file '{0}'?", fileToClose.FileName), "AvalonDock Test App", MessageBoxButton.YesNoCancel); - if (res == MessageBoxResult.Cancel) - return; - if (res == MessageBoxResult.Yes) - { - Save(fileToClose); - } - } - - _files.Remove(fileToClose); - } - - internal void Save(FileViewModel fileToSave, bool saveAsFlag = false) - { - if (fileToSave.FilePath == null || saveAsFlag) - { - var dlg = new SaveFileDialog(); - if (dlg.ShowDialog().GetValueOrDefault()) - fileToSave.FilePath = dlg.SafeFileName; - } - - File.WriteAllText(fileToSave.FilePath, fileToSave.TextContent); - ActiveDocument.IsDirty = false; - } - - internal FileViewModel Open(string filepath) - { - var fileViewModel = _files.FirstOrDefault(fm => fm.FilePath == filepath); - if (fileViewModel != null) - return fileViewModel; - - fileViewModel = new FileViewModel(filepath); - _files.Add(fileViewModel); - return fileViewModel; - } - - #region OpenCommand - private bool CanOpen(object parameter) => true; - - private void OnOpen(object parameter) - { - var dlg = new OpenFileDialog(); - if (dlg.ShowDialog().GetValueOrDefault()) - { - var fileViewModel = Open(dlg.FileName); - ActiveDocument = fileViewModel; - } - } - #endregion OpenCommand - - #region NewCommand - private bool CanNew(object parameter) - { - return true; - } - - private void OnNew(object parameter) - { - _files.Add(new FileViewModel()); - ActiveDocument = _files.Last(); - } - #endregion - #endregion methods - } + internal class Workspace : ViewModelBase + { + #region fields + static Workspace _this = new Workspace(); + + ToolViewModel[] _tools = null; + private ObservableCollection _files = new ObservableCollection(); + private ReadOnlyObservableCollection _readonyFiles = null; + private FileViewModel _activeDocument = null; + FileStatsViewModel _fileStats = null; + RelayCommand _openCommand = null; + RelayCommand _newCommand = null; + private Tuple selectedTheme; + #endregion fields + + #region constructors + /// + /// Class constructor + /// + protected Workspace() + { + this.Themes = new List> + { + new Tuple(nameof(AeroTheme),new AeroTheme()), + new Tuple(nameof(ExpressionDarkTheme),new ExpressionDarkTheme()), + new Tuple(nameof(ExpressionLightTheme),new ExpressionLightTheme()), + new Tuple(nameof(MetroTheme),new MetroTheme()), + new Tuple(nameof(VS2010Theme),new VS2010Theme()), + new Tuple(nameof(Vs2013BlueTheme),new Vs2013BlueTheme()), + new Tuple(nameof(Vs2013DarkTheme),new Vs2013DarkTheme()), + new Tuple(nameof(Vs2013LightTheme),new Vs2013LightTheme()), + }; + this.SelectedTheme = Themes.First(); + } + #endregion constructors + + public event EventHandler ActiveDocumentChanged; + + #region properties + public static Workspace This => _this; + + public ReadOnlyObservableCollection Files + { + get + { + if (_readonyFiles == null) + _readonyFiles = new ReadOnlyObservableCollection(_files); + + return _readonyFiles; + } + } + + public IEnumerable Tools + { + get + { + if (_tools == null) + _tools = new ToolViewModel[] { FileStats }; + return _tools; + } + } + + public FileStatsViewModel FileStats + { + get + { + if (_fileStats == null) + _fileStats = new FileStatsViewModel(); + + return _fileStats; + } + } + + public ICommand OpenCommand + { + get + { + if (_openCommand == null) + { + _openCommand = new RelayCommand((p) => OnOpen(p), (p) => CanOpen(p)); + } + + return _openCommand; + } + } + + public ICommand NewCommand + { + get + { + if (_newCommand == null) + { + _newCommand = new RelayCommand((p) => OnNew(p), (p) => CanNew(p)); + } + + return _newCommand; + } + } + + public FileViewModel ActiveDocument + { + get => _activeDocument; + set + { + if (_activeDocument != value) + { + _activeDocument = value; + RaisePropertyChanged(nameof(ActiveDocument)); + if (ActiveDocumentChanged != null) + ActiveDocumentChanged(this, EventArgs.Empty); + } + } + } + + + public List> Themes { get; set; } + + + public Tuple SelectedTheme + { + get { return selectedTheme; } + set + { + selectedTheme = value; + RaisePropertyChanged(nameof(SelectedTheme)); + } + } + + #endregion properties + + #region methods + internal void Close(FileViewModel fileToClose) + { + if (fileToClose.IsDirty) + { + var res = MessageBox.Show(string.Format("Save changes for file '{0}'?", fileToClose.FileName), "AvalonDock Test App", MessageBoxButton.YesNoCancel); + if (res == MessageBoxResult.Cancel) + return; + if (res == MessageBoxResult.Yes) + { + Save(fileToClose); + } + } + + _files.Remove(fileToClose); + } + + internal void Save(FileViewModel fileToSave, bool saveAsFlag = false) + { + if (fileToSave.FilePath == null || saveAsFlag) + { + var dlg = new SaveFileDialog(); + if (dlg.ShowDialog().GetValueOrDefault()) + fileToSave.FilePath = dlg.SafeFileName; + } + if (fileToSave.FilePath == null) + { + return; + } + File.WriteAllText(fileToSave.FilePath, fileToSave.TextContent); + ActiveDocument.IsDirty = false; + } + + internal FileViewModel Open(string filepath) + { + var fileViewModel = _files.FirstOrDefault(fm => fm.FilePath == filepath); + if (fileViewModel != null) + return fileViewModel; + + fileViewModel = new FileViewModel(filepath); + _files.Add(fileViewModel); + return fileViewModel; + } + + #region OpenCommand + private bool CanOpen(object parameter) => true; + + private void OnOpen(object parameter) + { + var dlg = new OpenFileDialog(); + if (dlg.ShowDialog().GetValueOrDefault()) + { + var fileViewModel = Open(dlg.FileName); + ActiveDocument = fileViewModel; + } + } + #endregion OpenCommand + + #region NewCommand + private bool CanNew(object parameter) + { + return true; + } + + private void OnNew(object parameter) + { + _files.Add(new FileViewModel()); + ActiveDocument = _files.Last(); + } + #endregion + #endregion methods + } } diff --git a/source/TestApp/App.xaml b/source/TestApp/App.xaml index 1a7b3785..b6cf5818 100644 --- a/source/TestApp/App.xaml +++ b/source/TestApp/App.xaml @@ -1,34 +1,32 @@  - - - - - + x:Class="TestApp.App" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + ShutdownMode="OnMainWindowClose" + StartupUri="MainWindow.xaml"> + + + + + diff --git a/source/TestApp/MainWindow.xaml b/source/TestApp/MainWindow.xaml index 59715cf4..6a4da229 100644 --- a/source/TestApp/MainWindow.xaml +++ b/source/TestApp/MainWindow.xaml @@ -1,149 +1,153 @@  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + x:Class="TestApp.MainWindow" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:avalonDock="https://github.com/Dirkster99/AvalonDock" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:local="clr-namespace:TestApp" + xmlns:winformsIntegration="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration" + Title="MainWindow" + Width="525" + Height="350" + UseLayoutRounding="True"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - -