diff --git a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs index 75f417da..16551443 100644 --- a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs @@ -7,10 +7,6 @@ This program is provided to you under the terms of the Microsoft Public License (Ms-PL) as published at https://opensource.org/licenses/MS-PL ************************************************************************/ -using AvalonDock.Commands; -using AvalonDock.Converters; -using AvalonDock.Layout; -using Microsoft.Windows.Shell; using System; using System.Collections.Generic; using System.ComponentModel; @@ -20,6 +16,12 @@ This program is provided to you under the terms of the Microsoft Public using System.Windows.Data; using System.Windows.Input; +using AvalonDock.Commands; +using AvalonDock.Converters; +using AvalonDock.Layout; + +using Microsoft.Windows.Shell; + namespace AvalonDock.Controls { /// @@ -244,17 +246,17 @@ protected override IntPtr FilterMessage(IntPtr hwnd, int msg, IntPtr wParam, Int switch (msg) { case Win32Helper.WM_ACTIVATE: - var anchorablePane = _model.Descendents().OfType() - .FirstOrDefault(p => p.ChildrenCount > 0 && p.SelectedContent != null); - - if (anchorablePane != null) + var isInactive = ((int)wParam & 0xFFFF) == Win32Helper.WA_INACTIVE; + if (_model.IsSinglePane) { - var isActive = !(((int)wParam & 0xFFFF) == Win32Helper.WA_INACTIVE); - anchorablePane.SelectedContent.IsActive = isActive; - - handled = true; + LayoutFloatingWindowControlHelper.ActiveTheContentOfSinglePane(this, !isInactive); + } + else + { + LayoutFloatingWindowControlHelper.ActiveTheContentOfMultiPane(this, !isInactive); } + handled = true; break; case Win32Helper.WM_NCRBUTTONUP: diff --git a/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs index c25e67e7..44bb0a79 100644 --- a/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs @@ -7,9 +7,6 @@ This program is provided to you under the terms of the Microsoft Public License (Ms-PL) as published at https://opensource.org/licenses/MS-PL ************************************************************************/ -using AvalonDock.Commands; -using AvalonDock.Layout; -using Microsoft.Windows.Shell; using System; using System.Collections.Generic; using System.Linq; @@ -17,6 +14,11 @@ This program is provided to you under the terms of the Microsoft Public using System.Windows.Controls.Primitives; using System.Windows.Input; +using AvalonDock.Commands; +using AvalonDock.Layout; + +using Microsoft.Windows.Shell; + namespace AvalonDock.Controls { /// @@ -113,119 +115,6 @@ private void Model_PropertyChanged(object sender, System.ComponentModel.Property if (e.PropertyName == nameof(LayoutDocumentFloatingWindow.RootPanel) && _model.RootPanel == null) InternalClose(); } - private void ActiveOfSinglePane(bool isActive) - { - var layoutDocumentPane = _model.Descendents().OfType() - .FirstOrDefault(p => p.ChildrenCount > 0 && p.SelectedContent != null); - - if (layoutDocumentPane != null) - { - layoutDocumentPane.SelectedContent.IsActive = isActive; - } - // When the floating tool window is mixed with the floating document window - // and the document pane in the floating document window is dragged out. - - // Only the Tool panes is left in the floating document window. - // The Children Count is greater than 0 and the Selected Content is null. - - // Then we only need to activate the last active content. - else - { - ActiveLastActivationOfItems(isActive); - } - } - - private LayoutDocumentPaneControl FindDocumentPaneControlByMousePoint() - { - var mousePosition = Win32Helper.GetMousePosition(); - var rootVisual = ((FloatingWindowContentHost)Content).RootVisual; - var areaHosts = rootVisual.FindVisualChildren(); - - foreach (var areaHost in areaHosts) - { - var area = areaHost.GetScreenArea(); - var pos = areaHost.TransformFromDeviceDPI(mousePosition); - var b = area.Contains(pos); - - if (b) - { - return areaHost; - } - } - - return null; - } - - private void ActiveLastActivationOfPane(LayoutDocumentPane model) - { - if (model.Children.Count > 0) - { - var index = 0; - if (model.Children.Count > 1) - { - var tmTimeStamp = model.Children[0].LastActivationTimeStamp; - for (var i = 1; i < model.Children.Count; i++) - { - var item = model.Children[i]; - if (item.LastActivationTimeStamp > tmTimeStamp) - { - tmTimeStamp = item.LastActivationTimeStamp; - index = i; - } - } - } - - model.SelectedContentIndex = index; - } - } - - private void ActiveLastActivationOfItems(bool isActive) - { - var items = _model.Descendents().OfType().ToList(); - if (items.Count > 0) - { - var index = 0; - if (items.Count > 1) - { - var tmpTimeStamp2 = items[0].LastActivationTimeStamp; - for (var i = 1; i < items.Count; i++) - { - var item = items[i]; - if (item.LastActivationTimeStamp > tmpTimeStamp2) - { - tmpTimeStamp2 = item.LastActivationTimeStamp; - index = i; - } - } - } - - items[index].IsActive = isActive; - } - } - - private void ActiveOfMultiPane(bool isActive) - { - if (isActive) - { - var documentPane = FindDocumentPaneControlByMousePoint(); - if (documentPane != null) - { - var model = (LayoutDocumentPane)documentPane.Model; - if (model.SelectedContent != null) - { - model.SelectedContent.IsActive = true; - return; - } - else - { - ActiveLastActivationOfPane(model); - return; - } - } - } - ActiveLastActivationOfItems(isActive); - } - /// protected override IntPtr FilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { @@ -235,11 +124,11 @@ protected override IntPtr FilterMessage(IntPtr hwnd, int msg, IntPtr wParam, Int var isInactive = ((int)wParam & 0xFFFF) == Win32Helper.WA_INACTIVE; if (_model.IsSinglePane) { - ActiveOfSinglePane(!isInactive); + LayoutFloatingWindowControlHelper.ActiveTheContentOfSinglePane(this, !isInactive); } else { - ActiveOfMultiPane(!isInactive); + LayoutFloatingWindowControlHelper.ActiveTheContentOfMultiPane(this, !isInactive); } handled = true; diff --git a/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs index 725cf6aa..f13ab5d6 100644 --- a/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs @@ -7,8 +7,6 @@ This program is provided to you under the terms of the Microsoft Public License (Ms-PL) as published at https://opensource.org/licenses/MS-PL ************************************************************************/ -using AvalonDock.Layout; -using AvalonDock.Themes; using System; using System.ComponentModel; using System.Linq; @@ -22,6 +20,9 @@ This program is provided to you under the terms of the Microsoft Public using System.Windows.Interop; using System.Windows.Media; +using AvalonDock.Layout; +using AvalonDock.Themes; + namespace AvalonDock.Controls { /// @@ -52,7 +53,7 @@ public abstract class LayoutFloatingWindowControl : Window, ILayoutControl /// /// private bool _isTotalMarginSet = false; - + #endregion fields #region Constructors @@ -542,24 +543,24 @@ protected override void OnInitialized(EventArgs e) } protected override void OnClosing(CancelEventArgs e) - { - base.OnClosing(e); - AssureOwnerIsNotMinimized(); - } + { + base.OnClosing(e); + AssureOwnerIsNotMinimized(); + } - /// + /// /// Prevents a known bug in WPF, which wronlgy minimizes the parent window, when closing this control - /// - private void AssureOwnerIsNotMinimized() - { - try - { - Owner?.Activate(); - } - catch (Exception) - { - } - } + /// + private void AssureOwnerIsNotMinimized() + { + try + { + Owner?.Activate(); + } + catch (Exception) + { + } + } #endregion Overrides diff --git a/source/Components/AvalonDock/Controls/LayoutFloatingWindowControlHelper.cs b/source/Components/AvalonDock/Controls/LayoutFloatingWindowControlHelper.cs new file mode 100644 index 00000000..ca2a0c0c --- /dev/null +++ b/source/Components/AvalonDock/Controls/LayoutFloatingWindowControlHelper.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using System.Windows.Input; + +using AvalonDock.Layout; + + +namespace AvalonDock.Controls +{ + internal static class LayoutFloatingWindowControlHelper + { + private const string Excp_NotSupportedFloatingWindowType = "Not Supported Floating Window Type: {0}"; + + public static void ActiveTheContentOfSinglePane(T fwc, bool isActive) where T : LayoutFloatingWindowControl + { + ILayoutContentSelector selector = null; + if (fwc is LayoutAnchorableFloatingWindowControl) + { + selector = fwc.Model + .Descendents() + .OfType() + .FirstOrDefault(p => p.ChildrenCount > 0 && p.SelectedContent != null); + } + else if (fwc is LayoutDocumentFloatingWindowControl) + { + selector = fwc.Model + .Descendents() + .OfType() + .FirstOrDefault(p => p.ChildrenCount > 0 && p.SelectedContent != null); + } + else + { + throw new NotSupportedException(string.Format(Excp_NotSupportedFloatingWindowType, fwc.GetType())); + } + + if (selector != null) + { + selector.SelectedContent.IsActive = isActive; + } + else + { + // When the floating tool window is mixed with the floating document window + // and the document pane in the floating document window is dragged out. + + // Only the Tool panes is left in the floating document window. + // The Children Count is greater than 0 and the Selected Content is null. + + // Then we only need to activate the last active content. + ActiveTheLastActivedContent(fwc, isActive); + } + } + + public static void ActiveTheContentOfMultiPane(T fwc, bool isActive) where T : LayoutFloatingWindowControl + { + if (isActive) + { + if (fwc is LayoutAnchorableFloatingWindowControl) + { + var paneControl = GetLayoutControlByMousePosition(fwc); + if (paneControl != null && paneControl.Model is LayoutAnchorablePane pane) + { + if (pane.SelectedContent != null) + pane.SelectedContent.IsActive = true; + else + ActiveTheLastActivedContentOfPane(pane); + + return; + } + } + else if (fwc is LayoutDocumentFloatingWindowControl) + { + var paneControl = GetLayoutControlByMousePosition(fwc); + if (paneControl != null && paneControl.Model is LayoutDocumentPane pane) + { + if (pane.SelectedContent != null) + pane.SelectedContent.IsActive = true; + else + ActiveTheLastActivedContentOfPane(pane); + + return; + } + } + else + { + throw new NotSupportedException(string.Format(Excp_NotSupportedFloatingWindowType, fwc.GetType())); + } + } + + ActiveTheLastActivedContent(fwc, isActive); + } + + public static void ActiveTheLastActivedContent(LayoutFloatingWindowControl fwc, bool isActive) + { + var items = fwc.Model.Descendents().OfType().ToList(); + var index = IndexOfLastActivedContent(items); + if (index != -1) + { + items[index].IsActive = isActive; + } + } + + public static void ActiveTheLastActivedContentOfPane(LayoutAnchorablePane anchorablePane) + { + var index = IndexOfLastActivedContent(anchorablePane.Children); + if (index != -1) + { + anchorablePane.SelectedContentIndex = index; + if (!anchorablePane.SelectedContent.IsActive) + { + anchorablePane.SelectedContent.IsActive = true; + } + } + } + + public static void ActiveTheLastActivedContentOfPane(LayoutDocumentPane documentPane) + { + var index = IndexOfLastActivedContent(documentPane.Children); + if (index != -1) + { + documentPane.SelectedContentIndex = index; + if (!documentPane.SelectedContent.IsActive) + { + documentPane.SelectedContent.IsActive = true; + } + } + } + + private static T GetLayoutControlByMousePosition(LayoutFloatingWindowControl fwc) where T : FrameworkElement, ILayoutControl + { + var mousePosition = fwc.PointToScreenDPI(Mouse.GetPosition(fwc)); + var rootVisual = ((LayoutFloatingWindowControl.FloatingWindowContentHost)fwc.Content).RootVisual; + + foreach (var areaHost in rootVisual.FindVisualChildren()) + { + var rect = areaHost.GetScreenArea(); + if (rect.Contains(mousePosition)) + { + return areaHost; + } + } + + return null; + } + + private static int IndexOfLastActivedContent(IList list) where T : LayoutContent + { + if (list.Count > 0) + { + var index = 0; + if (list.Count > 1) + { + var tmpTimeStamp = list[0].LastActivationTimeStamp; + for (var i = 1; i < list.Count; i++) + { + var item = list[i]; + if (item.LastActivationTimeStamp > tmpTimeStamp) + { + tmpTimeStamp = item.LastActivationTimeStamp; + index = i; + } + } + } + + return index; + } + + return -1; + } + } +}