From 0f411d363f58c1cca7fe9365f1d5b553abdeeeb2 Mon Sep 17 00:00:00 2001 From: Oliver Atkins Date: Mon, 3 May 2021 17:41:13 +0000 Subject: [PATCH] Support minimizing floating windows independently of main window --- .../Controls/LayoutFloatingWindowControl.cs | 73 ++++++++++++++++++- .../Components/AvalonDock/DockingManager.cs | 6 +- 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs index 2d721ec8..5e282414 100644 --- a/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs @@ -152,11 +152,54 @@ protected virtual void OnIsDraggingChanged(DependencyPropertyChangedEventArgs e) internal bool KeepContentVisibleOnClose { get; set; } + #region OwnedByDockingManagerWindow + + /// dependency property. + public static readonly DependencyProperty OwnedByDockingManagerWindowProperty = + DependencyProperty.Register("OwnedByDockingManagerWindow", typeof(bool), typeof(LayoutFloatingWindowControl), new PropertyMetadata(true, OwnedByDockingManagerWindowPropertyChanged)); + + /// + /// Gets or sets a value indicating whether an undocked child window should be "owned" by the window + /// that hosts the docking manager or whether it should be an independent window. + /// + public bool OwnedByDockingManagerWindow + { + get { return (bool)GetValue(OwnedByDockingManagerWindowProperty); } + set { SetValue(OwnedByDockingManagerWindowProperty, value); } + } + + private static void OwnedByDockingManagerWindowPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (d is LayoutFloatingWindowControl w && w.IsLoaded) + { + w.UpdateOwnership(); + } + } + + #endregion + + #region AllowMinimize + + /// dependency property. + public static readonly DependencyProperty AllowMinimizeProperty = + DependencyProperty.Register("AllowMinimize", typeof(bool), typeof(LayoutFloatingWindowControl), new PropertyMetadata(false)); + + /// + /// Gets/sets whether the floating window supports being minimized. + /// + public bool AllowMinimize + { + get { return (bool)GetValue(AllowMinimizeProperty); } + set { SetValue(AllowMinimizeProperty, value); } + } + + #endregion AllowMinimize + #region IsMaximized /// dependency property. public static readonly DependencyProperty IsMaximizedProperty = DependencyProperty.Register(nameof(IsMaximized), typeof(bool), typeof(LayoutFloatingWindowControl), - new FrameworkPropertyMetadata(false)); + new FrameworkPropertyMetadata(false)); /// Gets/sets the property. This dependency property indicates if the window is maximized. /// Provides a secure method for setting the property. @@ -505,7 +548,9 @@ private static object CoerceContentValue(DependencyObject sender, object content private void OnLoaded(object sender, RoutedEventArgs e) { Loaded -= OnLoaded; - this.SetParentToMainWindowOf(Model.Root.Manager); + + this.UpdateOwnership(); + _hwndSrc = PresentationSource.FromDependencyObject(this) as HwndSource; _hwndSrcHook = FilterMessage; _hwndSrc.AddHook(_hwndSrcHook); @@ -514,6 +559,17 @@ private void OnLoaded(object sender, RoutedEventArgs e) UpdateMaximizedState(maximized); } + internal void UpdateOwnership() + { + // Determine whether the child window should be owned by the parent or act independently + // according to OwnedByDockingManagerWindow property. + var manager = Model?.Root?.Manager; + if (OwnedByDockingManagerWindow && manager != null) + this.SetParentToMainWindowOf(manager); + else + this.SetParentWindowToNull(); + } + private void OnUnloaded(object sender, RoutedEventArgs e) { Unloaded -= OnUnloaded; @@ -578,7 +634,18 @@ private void UpdateMaximizedState(bool isMaximized) posElement.IsMaximized = isMaximized; IsMaximized = isMaximized; _isInternalChange = true; - WindowState = isMaximized ? WindowState.Maximized : WindowState.Normal; + + if (isMaximized) + { + WindowState = WindowState.Maximized; + } + else if (!this.AllowMinimize || this.WindowState != WindowState.Minimized) + { + // If minimize is not supported, this prevents the window from being minimized. + // by resetting it to the normal state. + WindowState = WindowState.Normal; + } + _isInternalChange = false; } diff --git a/source/Components/AvalonDock/DockingManager.cs b/source/Components/AvalonDock/DockingManager.cs index f7819482..9a4797c1 100644 --- a/source/Components/AvalonDock/DockingManager.cs +++ b/source/Components/AvalonDock/DockingManager.cs @@ -1560,7 +1560,8 @@ internal UIElement CreateUIElementForModel(ILayoutElement model) { //Owner = Window.GetWindow(this) }; - newFW.SetParentToMainWindowOf(this); + + newFW.UpdateOwnership(); // Fill list before calling Show (issue #254) _fwList.Add(newFW); @@ -1603,7 +1604,8 @@ internal UIElement CreateUIElementForModel(ILayoutElement model) { //Owner = Window.GetWindow(this) }; - newFW.SetParentToMainWindowOf(this); + + newFW.UpdateOwnership(); // Fill list before calling Show (issue #254) _fwList.Add(newFW);