diff --git a/src/Libraries/AvalonDock/Converters.cs b/src/Libraries/AvalonDock/Converters.cs
index bc2bcc9df3..8f9e498234 100644
--- a/src/Libraries/AvalonDock/Converters.cs
+++ b/src/Libraries/AvalonDock/Converters.cs
@@ -30,10 +30,11 @@ using System.Windows.Data;
using System.IO;
using System.Reflection;
using System.Windows.Media;
+using System.Windows;
namespace AvalonDock
{
- internal class FindResourcePathConverter : IValueConverter
+ public class FindResourcePathConverter : IValueConverter
{
#region IValueConverter Members
@@ -57,5 +58,42 @@ namespace AvalonDock
#endregion
}
+ ///
+ /// Converter from boolean values to visibility (inverse mode)
+ ///
+ [ValueConversion(typeof(object), typeof(Visibility))]
+ public class BoolToVisibilityConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter,
+ System.Globalization.CultureInfo culture)
+ {
+ return System.Convert.ToBoolean(value) ? Visibility.Visible :
+ (parameter != null && ((string)parameter) == "Hidden" ? Visibility.Hidden : Visibility.Collapsed);
+ }
+ public object ConvertBack(object value, Type targetType, object parameter,
+ System.Globalization.CultureInfo culture)
+ {
+ return null;
+ }
+ }
+
+
+ public static class Converters
+ {
+ static BoolToVisibilityConverter _BoolToVisibilityConverter = null;
+
+ public static BoolToVisibilityConverter BoolToVisibilityConverter
+ {
+ get
+ {
+ if (_BoolToVisibilityConverter == null)
+ _BoolToVisibilityConverter = new BoolToVisibilityConverter();
+
+
+ return _BoolToVisibilityConverter;
+ }
+ }
+
+ }
}
diff --git a/src/Libraries/AvalonDock/DockableContent.cs b/src/Libraries/AvalonDock/DockableContent.cs
index 261ed678fa..4ca992b6e4 100644
--- a/src/Libraries/AvalonDock/DockableContent.cs
+++ b/src/Libraries/AvalonDock/DockableContent.cs
@@ -415,7 +415,7 @@ namespace AvalonDock
}
else if (!e.Handled && e.Command == DockableContent.HideCommand)
{
- //Manager.Hide(this);
+ Manager.Hide(this);
e.Handled = true;
}
diff --git a/src/Libraries/AvalonDock/DockableFloatingWindow.cs b/src/Libraries/AvalonDock/DockableFloatingWindow.cs
index e0d0c08bb8..f1374d15ff 100644
--- a/src/Libraries/AvalonDock/DockableFloatingWindow.cs
+++ b/src/Libraries/AvalonDock/DockableFloatingWindow.cs
@@ -172,14 +172,18 @@ namespace AvalonDock
}
}
+
+
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
- while (HostedPane.Items.Count > 0)
+ DockableContent[] cntsToClose = new DockableContent[HostedPane.Items.Count];
+ HostedPane.Items.CopyTo(cntsToClose, 0);
+
+ foreach (DockableContent cntToClose in cntsToClose)
{
- //Manager.Hide(HostedPane.Items[0] as DockableContent);
- HostedPane.CloseOrHide(HostedPane.Items[0] as DockableContent);
+ HostedPane.CloseOrHide(HostedPane.Items[0] as DockableContent, ForcedClosing);
}
Manager.UnregisterFloatingWindow(this);
diff --git a/src/Libraries/AvalonDock/DockablePane.cs b/src/Libraries/AvalonDock/DockablePane.cs
index a58a7465bf..d0188c7d57 100644
--- a/src/Libraries/AvalonDock/DockablePane.cs
+++ b/src/Libraries/AvalonDock/DockablePane.cs
@@ -215,6 +215,8 @@ namespace AvalonDock
if (cxOptions != null)
{
+ cxOptions.DataContext = this.SelectedItem as DockableContent;
+
foreach (MenuItem menuItem in cxOptions.Items)
menuItem.CommandTarget = this.SelectedItem as DockableContent;
@@ -487,7 +489,7 @@ namespace AvalonDock
///
internal void CloseOrHide()
{
- CloseOrHide(SelectedItem as DockableContent);
+ CloseOrHide(SelectedItem as DockableContent, false);
}
diff --git a/src/Libraries/AvalonDock/DockingManager.cs b/src/Libraries/AvalonDock/DockingManager.cs
index be92b2756a..c55615c3db 100644
--- a/src/Libraries/AvalonDock/DockingManager.cs
+++ b/src/Libraries/AvalonDock/DockingManager.cs
@@ -1611,6 +1611,9 @@ namespace AvalonDock
if (content.State == DockableContentState.Hidden)
return;
+ if (!content.IsCloseable)
+ return;
+
content.SaveCurrentStateAndPosition();
if (content.State == DockableContentState.AutoHide)
@@ -2713,7 +2716,7 @@ namespace AvalonDock
parentContainer.Items.Count == 1)
{
FloatingWindow floatingWindow = Window.GetWindow(content) as FloatingWindow;
- floatingWindow.Close();
+ floatingWindow.Close(true);
}
}
//this content can be hidden also if was contained in closed floating window
@@ -2964,8 +2967,8 @@ namespace AvalonDock
if (doc.DocumentElement == null ||
doc.DocumentElement.Name != "DockingManager")
{
- Debug.Assert(false, "Layout file had not a valid structure!");
- return;
+ Debug.Assert(false, "Layout file hasn't a valid structure!");
+ throw new InvalidOperationException("Layout file had not a valid structure!");
}
if (doc.DocumentElement.ChildNodes.Count != 3 ||
@@ -2974,11 +2977,17 @@ namespace AvalonDock
doc.DocumentElement.ChildNodes[2].Name != "Windows")
{
Debug.Assert(false, "Layout file hasn't a valid structure!");
- return;
+ throw new InvalidOperationException("Layout file hasn't a valid structure!");
}
+ //Hide temp windows
+ HideAutoHideWindow();
+ HideNavigatorWindow();
+ HideDocumentNavigatorWindow();
+
DockableContent[] actualContents = DockableContents;
-
+
+
//show all hidden contents
ShowAllHiddenContents();
@@ -3022,6 +3031,9 @@ namespace AvalonDock
//restore floating windows
foreach (XmlElement flWindowElement in doc.DocumentElement.ChildNodes[2].ChildNodes)
{
+ if (flWindowElement.ChildNodes.Count != 1)
+ continue;//handles invalid layouts structures
+
bool isDockableWindow = XmlConvert.ToBoolean(flWindowElement.GetAttribute("IsDockableWindow"));
Point location = new Point(XmlConvert.ToDouble(flWindowElement.GetAttribute("Left")), XmlConvert.ToDouble(flWindowElement.GetAttribute("Top")));
Size size = new Size(XmlConvert.ToDouble(flWindowElement.GetAttribute("Width")), XmlConvert.ToDouble(flWindowElement.GetAttribute("Height")));
diff --git a/src/Libraries/AvalonDock/DocumentContent.cs b/src/Libraries/AvalonDock/DocumentContent.cs
index 0515782051..8b143cae7e 100644
--- a/src/Libraries/AvalonDock/DocumentContent.cs
+++ b/src/Libraries/AvalonDock/DocumentContent.cs
@@ -253,6 +253,9 @@ namespace AvalonDock
///
public bool Close()
{
+ if (!IsCloseable)
+ return false;
+
//if documents are attached to an external source via DockingManager.DocumentsSource
//let application host handle the document closing by itself
if (Manager.DocumentsSource != null)
diff --git a/src/Libraries/AvalonDock/DocumentFloatingWindow.cs b/src/Libraries/AvalonDock/DocumentFloatingWindow.cs
index bc2faadef9..da060daa99 100644
--- a/src/Libraries/AvalonDock/DocumentFloatingWindow.cs
+++ b/src/Libraries/AvalonDock/DocumentFloatingWindow.cs
@@ -210,12 +210,7 @@ namespace AvalonDock
else if (e.Command == CloseCommand)
{
DocumentContent docContent = this.HostedPane.Items[0] as DocumentContent;
- if (docContent.Close())
- {
- HostedPane.RemoveContent(0);
- Close();
- }
- e.Handled = true;
+ e.Handled = docContent.Close();
}
base.OnExecuteCommand(sender, e);
diff --git a/src/Libraries/AvalonDock/FloatingWindow.cs b/src/Libraries/AvalonDock/FloatingWindow.cs
index 8071ffbdd8..4b76cee13a 100644
--- a/src/Libraries/AvalonDock/FloatingWindow.cs
+++ b/src/Libraries/AvalonDock/FloatingWindow.cs
@@ -41,6 +41,7 @@ using System.Diagnostics;
using System.Windows.Threading;
using System.Windows.Media.Animation;
using System.Windows.Interop;
+using System.Runtime.InteropServices;
namespace AvalonDock
{
@@ -142,10 +143,30 @@ namespace AvalonDock
#endregion
#region IsClosing Flag Management
+ public void Close(bool force)
+ {
+ ForcedClosing = force;
+ base.Close();
+ }
+
+ protected bool ForcedClosing { get; private set; }
+
+
internal bool IsClosing { get; private set; }
protected override void OnClosing(CancelEventArgs e)
{
+ if (HostedPane.Items.Count > 0 && !ForcedClosing)
+ {
+ ManagedContent cntToClose = HostedPane.Items[0] as ManagedContent;
+ if (!cntToClose.IsCloseable)
+ {
+ e.Cancel = true;
+ base.OnClosing(e);
+ return;
+ }
+ }
+
IsClosing = true;
base.OnClosing(e);
}
@@ -159,6 +180,60 @@ namespace AvalonDock
public abstract Pane ClonePane();
+
+ #region Enable/Disable window Close Button
+ [DllImport("User32.dll", CharSet = CharSet.Auto)]
+ private static extern IntPtr GetSystemMenu(
+ IntPtr hWnd,
+ Int32 bRevert
+ );
+
+ [DllImport("User32.dll", CharSet = CharSet.Auto)]
+ private static extern int GetMenuItemCount(
+ IntPtr hMenu
+ );
+
+ [DllImport("User32.dll", CharSet = CharSet.Auto)]
+ private static extern int DrawMenuBar(
+ IntPtr hWnd
+ );
+
+ [DllImport("User32.dll", CharSet = CharSet.Auto)]
+ private static extern bool EnableMenuItem(
+ IntPtr hMenu,
+ Int32 uIDEnableItem,
+ Int32 uEnable
+ );
+
+ private const Int32 MF_BYPOSITION = 0x400;
+ private const Int32 MF_ENABLED = 0x0000;
+ private const Int32 MF_GRAYED = 0x0001;
+ private const Int32 MF_DISABLED = 0x0002;
+
+ void EnableXButton()
+ {
+ WindowInteropHelper helper = new WindowInteropHelper(this);
+ IntPtr hMenu = GetSystemMenu(helper.Handle, 0);
+
+ int menuItemCount = GetMenuItemCount(hMenu);
+
+ EnableMenuItem(hMenu, menuItemCount - 1, MF_BYPOSITION | MF_ENABLED);
+ DrawMenuBar(helper.Handle);
+ }
+
+ void DisableXButton()
+ {
+ WindowInteropHelper helper = new WindowInteropHelper(this);
+ IntPtr hMenu = GetSystemMenu(helper.Handle, 0);
+
+ int menuItemCount = GetMenuItemCount(hMenu);
+
+ EnableMenuItem(hMenu, menuItemCount - 1, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
+ DrawMenuBar(helper.Handle);
+ }
+
+ #endregion
+
#region Non-Client area management
protected const int WM_MOVE = 0x0003;
@@ -185,6 +260,15 @@ namespace AvalonDock
_hwndSource = HwndSource.FromHwnd(helper.Handle);
_wndProcHandler = new HwndSourceHook(FilterMessage);
_hwndSource.AddHook(_wndProcHandler);
+
+ if (HostedPane.Items.Count > 0)
+ {
+ ManagedContent cntHosted = HostedPane.Items[0] as ManagedContent;
+ if (!cntHosted.IsCloseable)
+ {
+ DisableXButton();
+ }
+ }
}
protected void OnUnloaded(object sender, EventArgs e)
{
diff --git a/src/Libraries/AvalonDock/FlyoutPaneWindow.cs b/src/Libraries/AvalonDock/FlyoutPaneWindow.cs
index f8cbc9556d..8651c3d76c 100644
--- a/src/Libraries/AvalonDock/FlyoutPaneWindow.cs
+++ b/src/Libraries/AvalonDock/FlyoutPaneWindow.cs
@@ -862,7 +862,13 @@ namespace AvalonDock
void ApplyRegion(Rect wndRect)
{
- //Debug.WriteLine(wndRect);
+ if (!this.CanTransform())
+ return;
+
+ wndRect = new Rect(
+ this.TransformFromDeviceDPI(wndRect.TopLeft),
+ this.TransformFromDeviceDPI(wndRect.Size));
+
_lastApplyRect = wndRect;
if (PresentationSource.FromVisual(this) == null)
diff --git a/src/Libraries/AvalonDock/HelperFunc.cs b/src/Libraries/AvalonDock/HelperFunc.cs
index 2a6e1851fa..7fee7302a3 100644
--- a/src/Libraries/AvalonDock/HelperFunc.cs
+++ b/src/Libraries/AvalonDock/HelperFunc.cs
@@ -174,5 +174,22 @@ namespace AvalonDock
Matrix m = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice;
return new Point(pt.X / m.M11, pt.Y /m.M22);
}
+
+ public static Size TransformFromDeviceDPI(this Visual visual, Size size)
+ {
+ Matrix m = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice;
+ return new Size(size.Width * m.M11, size.Height * m.M22);
+ }
+
+ public static Point TransformFromDeviceDPI(this Visual visual, Point pt)
+ {
+ Matrix m = PresentationSource.FromVisual(visual).CompositionTarget.TransformToDevice;
+ return new Point(pt.X * m.M11, pt.Y * m.M22);
+ }
+
+ public static bool CanTransform(this Visual visual)
+ {
+ return PresentationSource.FromVisual(visual) != null;
+ }
}
}
diff --git a/src/Libraries/AvalonDock/ManagedContent.cs b/src/Libraries/AvalonDock/ManagedContent.cs
index 514197a613..03744eeb3d 100644
--- a/src/Libraries/AvalonDock/ManagedContent.cs
+++ b/src/Libraries/AvalonDock/ManagedContent.cs
@@ -519,6 +519,16 @@ namespace AvalonDock
#endregion
+ public bool IsCloseable
+ {
+ get { return (bool)GetValue(IsCloseableProperty); }
+ set { SetValue(IsCloseableProperty, value); }
+ }
+
+ // Using a DependencyProperty as the backing store for IsCloseable. This enables animation, styling, binding, etc...
+ public static readonly DependencyProperty IsCloseableProperty =
+ DependencyProperty.Register("IsCloseable", typeof(bool), typeof(ManagedContent), new UIPropertyMetadata(true));
+
}
}
diff --git a/src/Libraries/AvalonDock/Pane.cs b/src/Libraries/AvalonDock/Pane.cs
index 9f06461243..e2fce0e78e 100644
--- a/src/Libraries/AvalonDock/Pane.cs
+++ b/src/Libraries/AvalonDock/Pane.cs
@@ -264,9 +264,20 @@ namespace AvalonDock
/// Closes or hides provided content depending on HideOnClose property
///
internal virtual void CloseOrHide(DockableContent cntToCloseOrHide)
+ {
+ CloseOrHide(cntToCloseOrHide, false);
+ }
+
+ ///
+ /// Closes or hides provided content depending on HideOnClose property
+ ///
+ internal virtual void CloseOrHide(DockableContent cntToCloseOrHide, bool force)
{
Debug.Assert(cntToCloseOrHide != null);
+ if (!force && !cntToCloseOrHide.IsCloseable)
+ return;
+
DockingManager manager = GetManager();
if (cntToCloseOrHide.HideOnClose && manager != null)
manager.Hide(cntToCloseOrHide);
diff --git a/src/Libraries/AvalonDock/Properties/AssemblyInfo.cs b/src/Libraries/AvalonDock/Properties/AssemblyInfo.cs
index 83b153ec55..0efa24fa45 100644
--- a/src/Libraries/AvalonDock/Properties/AssemblyInfo.cs
+++ b/src/Libraries/AvalonDock/Properties/AssemblyInfo.cs
@@ -59,4 +59,4 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersion("1.2.2648")]
+[assembly: AssemblyVersion("1.2.2663")]
diff --git a/src/Libraries/AvalonDock/Resources/DockablePaneStyles.xaml b/src/Libraries/AvalonDock/Resources/DockablePaneStyles.xaml
index a83ffc7b42..467055b6db 100644
--- a/src/Libraries/AvalonDock/Resources/DockablePaneStyles.xaml
+++ b/src/Libraries/AvalonDock/Resources/DockablePaneStyles.xaml
@@ -22,7 +22,7 @@
+ Command="ad:DockableContent.HideCommand" Visibility="{Binding Path=IsCloseable, Converter={x:Static ad:Converters.BoolToVisibilityConverter}}" />
@@ -138,7 +138,7 @@
BorderBrush="DarkGray"
Height="18">
-