From 895646cdf2195ec7b3739a536d99cb774ae73609 Mon Sep 17 00:00:00 2001 From: Noisrev Date: Thu, 12 Jan 2023 22:37:38 +0800 Subject: [PATCH 1/4] Improve the active item handler and add to LayoutAnchorableFloatingWindow --- .../LayoutAnchorableFloatingWindowControl.cs | 143 ++++++++++- .../LayoutDocumentFloatingWindowControl.cs | 242 +++++++++--------- 2 files changed, 255 insertions(+), 130 deletions(-) diff --git a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs index 75f417da..381b755a 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; + ActiveItemOfSinglePane(!isInactive); + } + else + { + ActiveItemOfMultiPane(!isInactive); } + handled = true; break; case Win32Helper.WM_NCRBUTTONUP: @@ -431,6 +433,123 @@ private void OnExecuteCloseWindowCommand(object parameter) #endregion CloseWindowCommand + #region ActiveItem + + private void ActiveItemOfSinglePane(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 + { + ActiveTheLastActivedItemOfItems(isActive); + } + } + + private LayoutAnchorablePaneControl FindPaneControlByMousePoint() + { + var mousePosition = Win32Helper.GetMousePosition(); + var rootVisual = ((FloatingWindowContentHost)Content).RootVisual; + var areaHosts = rootVisual.FindVisualChildren(); + + foreach (var areaHost in areaHosts) + { + var rect = areaHost.GetScreenArea(); + var pos = areaHost.TransformFromDeviceDPI(mousePosition); + var b = rect.Contains(pos); + + if (b) + { + return areaHost; + } + } + + return null; + } + + private static void ActiveTheLastActivedItemOfPane(LayoutAnchorablePane pane) + { + if (pane.Children.Count > 0) + { + var index = 0; + if (pane.Children.Count > 1) + { + var tmTimeStamp = pane.Children[0].LastActivationTimeStamp; + for (var i = 1; i < pane.Children.Count; i++) + { + var item = pane.Children[i]; + if (item.LastActivationTimeStamp > tmTimeStamp) + { + tmTimeStamp = item.LastActivationTimeStamp; + index = i; + } + } + } + + pane.SelectedContentIndex = index; + } + } + + private void ActiveTheLastActivedItemOfItems(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 ActiveItemOfMultiPane(bool isActive) + { + if (isActive) + { + var documentPane = FindPaneControlByMousePoint(); + if (documentPane != null) + { + var model = (LayoutAnchorablePane)documentPane.Model; + if (model.SelectedContent != null) + { + model.SelectedContent.IsActive = true; + return; + } + else + { + ActiveTheLastActivedItemOfPane(model); + return; + } + } + } + ActiveTheLastActivedItemOfItems(isActive); + } + + #endregion ActiveItem + #endregion Private Methods } } diff --git a/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs index c25e67e7..baa4ce29 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); + ActiveItemOfSinglePane(!isInactive); } else { - ActiveOfMultiPane(!isInactive); + ActiveItemOfMultiPane(!isInactive); } handled = true; @@ -543,6 +432,123 @@ private void OnExecuteCloseWindowCommand(object parameter) #endregion CloseWindowCommand + #region ActiveItem + + private void ActiveItemOfSinglePane(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 + { + ActiveTheLastActivedItemOfItems(isActive); + } + } + + private LayoutDocumentPaneControl FindPaneControlByMousePoint() + { + var mousePosition = Win32Helper.GetMousePosition(); + var rootVisual = ((FloatingWindowContentHost)Content).RootVisual; + var areaHosts = rootVisual.FindVisualChildren(); + + foreach (var areaHost in areaHosts) + { + var rect = areaHost.GetScreenArea(); + var pos = areaHost.TransformFromDeviceDPI(mousePosition); + var b = rect.Contains(pos); + + if (b) + { + return areaHost; + } + } + + return null; + } + + private static void ActiveTheLastActivedItemOfPane(LayoutDocumentPane pane) + { + if (pane.Children.Count > 0) + { + var index = 0; + if (pane.Children.Count > 1) + { + var tmTimeStamp = pane.Children[0].LastActivationTimeStamp; + for (var i = 1; i < pane.Children.Count; i++) + { + var item = pane.Children[i]; + if (item.LastActivationTimeStamp > tmTimeStamp) + { + tmTimeStamp = item.LastActivationTimeStamp; + index = i; + } + } + } + + pane.SelectedContentIndex = index; + } + } + + private void ActiveTheLastActivedItemOfItems(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 ActiveItemOfMultiPane(bool isActive) + { + if (isActive) + { + var documentPane = FindPaneControlByMousePoint(); + if (documentPane != null) + { + var model = (LayoutDocumentPane)documentPane.Model; + if (model.SelectedContent != null) + { + model.SelectedContent.IsActive = true; + return; + } + else + { + ActiveTheLastActivedItemOfPane(model); + return; + } + } + } + ActiveTheLastActivedItemOfItems(isActive); + } + + #endregion + #endregion Private Methods } } From b63b9668884dc4b910f4dfd77a40e177dcfd93cc Mon Sep 17 00:00:00 2001 From: Noisrev Date: Thu, 12 Jan 2023 23:01:28 +0800 Subject: [PATCH 2/4] Fix types and variable names --- .../LayoutAnchorableFloatingWindowControl.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs index 381b755a..84743360 100644 --- a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs @@ -437,12 +437,12 @@ private void OnExecuteCloseWindowCommand(object parameter) private void ActiveItemOfSinglePane(bool isActive) { - var layoutDocumentPane = _model.Descendents().OfType() + var layoutAnchorablePane = _model.Descendents().OfType() .FirstOrDefault(p => p.ChildrenCount > 0 && p.SelectedContent != null); - if (layoutDocumentPane != null) + if (layoutAnchorablePane != null) { - layoutDocumentPane.SelectedContent.IsActive = isActive; + layoutAnchorablePane.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. @@ -529,10 +529,10 @@ private void ActiveItemOfMultiPane(bool isActive) { if (isActive) { - var documentPane = FindPaneControlByMousePoint(); - if (documentPane != null) + var anchorablePane = FindPaneControlByMousePoint(); + if (anchorablePane != null) { - var model = (LayoutAnchorablePane)documentPane.Model; + var model = (LayoutAnchorablePane)anchorablePane.Model; if (model.SelectedContent != null) { model.SelectedContent.IsActive = true; From fa58dfe01aeb1c963ee61d6f5acd82d9560d25c1 Mon Sep 17 00:00:00 2001 From: Noisrev Date: Fri, 13 Jan 2023 00:17:23 +0800 Subject: [PATCH 3/4] Improve and optimize the active item handlers --- .../LayoutAnchorableFloatingWindowControl.cs | 86 ++------------ .../LayoutDocumentFloatingWindowControl.cs | 88 ++------------ .../Controls/LayoutFloatingWindowControl.cs | 108 +++++++++++++++--- 3 files changed, 108 insertions(+), 174 deletions(-) diff --git a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs index 84743360..29ec53a9 100644 --- a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs @@ -435,14 +435,14 @@ private void OnExecuteCloseWindowCommand(object parameter) #region ActiveItem - private void ActiveItemOfSinglePane(bool isActive) + internal void ActiveItemOfSinglePane(bool isActive) { - var layoutAnchorablePane = _model.Descendents().OfType() + var pane = _model.Descendents().OfType() .FirstOrDefault(p => p.ChildrenCount > 0 && p.SelectedContent != null); - if (layoutAnchorablePane != null) + if (pane != null) { - layoutAnchorablePane.SelectedContent.IsActive = isActive; + pane.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. @@ -457,82 +457,14 @@ private void ActiveItemOfSinglePane(bool isActive) } } - private LayoutAnchorablePaneControl FindPaneControlByMousePoint() - { - var mousePosition = Win32Helper.GetMousePosition(); - var rootVisual = ((FloatingWindowContentHost)Content).RootVisual; - var areaHosts = rootVisual.FindVisualChildren(); - - foreach (var areaHost in areaHosts) - { - var rect = areaHost.GetScreenArea(); - var pos = areaHost.TransformFromDeviceDPI(mousePosition); - var b = rect.Contains(pos); - - if (b) - { - return areaHost; - } - } - - return null; - } - - private static void ActiveTheLastActivedItemOfPane(LayoutAnchorablePane pane) - { - if (pane.Children.Count > 0) - { - var index = 0; - if (pane.Children.Count > 1) - { - var tmTimeStamp = pane.Children[0].LastActivationTimeStamp; - for (var i = 1; i < pane.Children.Count; i++) - { - var item = pane.Children[i]; - if (item.LastActivationTimeStamp > tmTimeStamp) - { - tmTimeStamp = item.LastActivationTimeStamp; - index = i; - } - } - } - - pane.SelectedContentIndex = index; - } - } - - private void ActiveTheLastActivedItemOfItems(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 ActiveItemOfMultiPane(bool isActive) + internal void ActiveItemOfMultiPane(bool isActive) { if (isActive) { - var anchorablePane = FindPaneControlByMousePoint(); - if (anchorablePane != null) + var paneControl = FindPaneControlByMousePoint(); + if (paneControl != null) { - var model = (LayoutAnchorablePane)anchorablePane.Model; + var model = (LayoutAnchorablePane)paneControl.Model; if (model.SelectedContent != null) { model.SelectedContent.IsActive = true; @@ -540,7 +472,7 @@ private void ActiveItemOfMultiPane(bool isActive) } else { - ActiveTheLastActivedItemOfPane(model); + ActiveTheLastActivedItemOfPane(model); return; } } diff --git a/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs index baa4ce29..18fada33 100644 --- a/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs @@ -434,14 +434,14 @@ private void OnExecuteCloseWindowCommand(object parameter) #region ActiveItem - private void ActiveItemOfSinglePane(bool isActive) + internal void ActiveItemOfSinglePane(bool isActive) { - var layoutDocumentPane = _model.Descendents().OfType() + var pane = _model.Descendents().OfType() .FirstOrDefault(p => p.ChildrenCount > 0 && p.SelectedContent != null); - if (layoutDocumentPane != null) + if (pane != null) { - layoutDocumentPane.SelectedContent.IsActive = isActive; + pane.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. @@ -456,82 +456,14 @@ private void ActiveItemOfSinglePane(bool isActive) } } - private LayoutDocumentPaneControl FindPaneControlByMousePoint() - { - var mousePosition = Win32Helper.GetMousePosition(); - var rootVisual = ((FloatingWindowContentHost)Content).RootVisual; - var areaHosts = rootVisual.FindVisualChildren(); - - foreach (var areaHost in areaHosts) - { - var rect = areaHost.GetScreenArea(); - var pos = areaHost.TransformFromDeviceDPI(mousePosition); - var b = rect.Contains(pos); - - if (b) - { - return areaHost; - } - } - - return null; - } - - private static void ActiveTheLastActivedItemOfPane(LayoutDocumentPane pane) - { - if (pane.Children.Count > 0) - { - var index = 0; - if (pane.Children.Count > 1) - { - var tmTimeStamp = pane.Children[0].LastActivationTimeStamp; - for (var i = 1; i < pane.Children.Count; i++) - { - var item = pane.Children[i]; - if (item.LastActivationTimeStamp > tmTimeStamp) - { - tmTimeStamp = item.LastActivationTimeStamp; - index = i; - } - } - } - - pane.SelectedContentIndex = index; - } - } - - private void ActiveTheLastActivedItemOfItems(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 ActiveItemOfMultiPane(bool isActive) + internal void ActiveItemOfMultiPane(bool isActive) { if (isActive) { - var documentPane = FindPaneControlByMousePoint(); - if (documentPane != null) + var paneControl = FindPaneControlByMousePoint(); + if (paneControl != null) { - var model = (LayoutDocumentPane)documentPane.Model; + var model = (LayoutDocumentPane)paneControl.Model; if (model.SelectedContent != null) { model.SelectedContent.IsActive = true; @@ -539,7 +471,7 @@ private void ActiveItemOfMultiPane(bool isActive) } else { - ActiveTheLastActivedItemOfPane(model); + ActiveTheLastActivedItemOfPane(model); return; } } @@ -547,7 +479,7 @@ private void ActiveItemOfMultiPane(bool isActive) ActiveTheLastActivedItemOfItems(isActive); } - #endregion + #endregion ActiveItem #endregion Private Methods } diff --git a/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs index c1377a92..fdc308d8 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 @@ -491,6 +492,75 @@ internal void InternalClose(bool closeInitiatedByUser = false) Close(); } + internal T FindPaneControlByMousePoint() where T : FrameworkElement, ILayoutControl + { + var mousePosition = this.PointToScreenDPI(Mouse.GetPosition(this)); + var rootVisual = ((FloatingWindowContentHost)Content).RootVisual; + var areaHosts = rootVisual.FindVisualChildren(); + + foreach (var areaHost in areaHosts) + { + var rect = areaHost.GetScreenArea(); + var b = rect.Contains(mousePosition); + + if (b) + { + return areaHost; + } + } + + return null; + } + + internal void ActiveTheLastActivedItemOfItems(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; + } + } + + internal static void ActiveTheLastActivedItemOfPane(TPane pane) + where TPane : LayoutPositionableGroup, ILayoutContentSelector + where TChild : LayoutContent + { + if (pane.Children.Count > 0) + { + var index = 0; + if (pane.Children.Count > 1) + { + var tmTimeStamp = pane.Children[0].LastActivationTimeStamp; + for (var i = 1; i < pane.Children.Count; i++) + { + var item = pane.Children[i]; + if (item.LastActivationTimeStamp > tmTimeStamp) + { + tmTimeStamp = item.LastActivationTimeStamp; + index = i; + } + } + } + + pane.SelectedContentIndex = index; + } + } + #endregion Internal Methods #region Overrides @@ -528,24 +598,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 From ce7de8d94ab28e6dc364fb7717f72ca0a7cec026 Mon Sep 17 00:00:00 2001 From: Noisrev Date: Tue, 24 Jan 2023 22:02:58 +0800 Subject: [PATCH 4/4] Improve and optimize the codes of active content for floating windows * Remove the codes of active content in the floating windows * Add a common class LayoutFloatingWindowControlHelper for active/inactive the content when floating window is active or inactive --- .../LayoutAnchorableFloatingWindowControl.cs | 53 +----- .../LayoutDocumentFloatingWindowControl.cs | 53 +----- .../Controls/LayoutFloatingWindowControl.cs | 69 ------- .../LayoutFloatingWindowControlHelper.cs | 172 ++++++++++++++++++ 4 files changed, 176 insertions(+), 171 deletions(-) create mode 100644 source/Components/AvalonDock/Controls/LayoutFloatingWindowControlHelper.cs diff --git a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs index 29ec53a9..16551443 100644 --- a/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutAnchorableFloatingWindowControl.cs @@ -249,11 +249,11 @@ protected override IntPtr FilterMessage(IntPtr hwnd, int msg, IntPtr wParam, Int var isInactive = ((int)wParam & 0xFFFF) == Win32Helper.WA_INACTIVE; if (_model.IsSinglePane) { - ActiveItemOfSinglePane(!isInactive); + LayoutFloatingWindowControlHelper.ActiveTheContentOfSinglePane(this, !isInactive); } else { - ActiveItemOfMultiPane(!isInactive); + LayoutFloatingWindowControlHelper.ActiveTheContentOfMultiPane(this, !isInactive); } handled = true; @@ -433,55 +433,6 @@ private void OnExecuteCloseWindowCommand(object parameter) #endregion CloseWindowCommand - #region ActiveItem - - internal void ActiveItemOfSinglePane(bool isActive) - { - var pane = _model.Descendents().OfType() - .FirstOrDefault(p => p.ChildrenCount > 0 && p.SelectedContent != null); - - if (pane != null) - { - pane.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 - { - ActiveTheLastActivedItemOfItems(isActive); - } - } - - internal void ActiveItemOfMultiPane(bool isActive) - { - if (isActive) - { - var paneControl = FindPaneControlByMousePoint(); - if (paneControl != null) - { - var model = (LayoutAnchorablePane)paneControl.Model; - if (model.SelectedContent != null) - { - model.SelectedContent.IsActive = true; - return; - } - else - { - ActiveTheLastActivedItemOfPane(model); - return; - } - } - } - ActiveTheLastActivedItemOfItems(isActive); - } - - #endregion ActiveItem - #endregion Private Methods } } diff --git a/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs index 18fada33..44bb0a79 100644 --- a/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutDocumentFloatingWindowControl.cs @@ -124,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) { - ActiveItemOfSinglePane(!isInactive); + LayoutFloatingWindowControlHelper.ActiveTheContentOfSinglePane(this, !isInactive); } else { - ActiveItemOfMultiPane(!isInactive); + LayoutFloatingWindowControlHelper.ActiveTheContentOfMultiPane(this, !isInactive); } handled = true; @@ -432,55 +432,6 @@ private void OnExecuteCloseWindowCommand(object parameter) #endregion CloseWindowCommand - #region ActiveItem - - internal void ActiveItemOfSinglePane(bool isActive) - { - var pane = _model.Descendents().OfType() - .FirstOrDefault(p => p.ChildrenCount > 0 && p.SelectedContent != null); - - if (pane != null) - { - pane.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 - { - ActiveTheLastActivedItemOfItems(isActive); - } - } - - internal void ActiveItemOfMultiPane(bool isActive) - { - if (isActive) - { - var paneControl = FindPaneControlByMousePoint(); - if (paneControl != null) - { - var model = (LayoutDocumentPane)paneControl.Model; - if (model.SelectedContent != null) - { - model.SelectedContent.IsActive = true; - return; - } - else - { - ActiveTheLastActivedItemOfPane(model); - return; - } - } - } - ActiveTheLastActivedItemOfItems(isActive); - } - - #endregion ActiveItem - #endregion Private Methods } } diff --git a/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs b/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs index fdc308d8..c7af3acf 100644 --- a/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs +++ b/source/Components/AvalonDock/Controls/LayoutFloatingWindowControl.cs @@ -492,75 +492,6 @@ internal void InternalClose(bool closeInitiatedByUser = false) Close(); } - internal T FindPaneControlByMousePoint() where T : FrameworkElement, ILayoutControl - { - var mousePosition = this.PointToScreenDPI(Mouse.GetPosition(this)); - var rootVisual = ((FloatingWindowContentHost)Content).RootVisual; - var areaHosts = rootVisual.FindVisualChildren(); - - foreach (var areaHost in areaHosts) - { - var rect = areaHost.GetScreenArea(); - var b = rect.Contains(mousePosition); - - if (b) - { - return areaHost; - } - } - - return null; - } - - internal void ActiveTheLastActivedItemOfItems(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; - } - } - - internal static void ActiveTheLastActivedItemOfPane(TPane pane) - where TPane : LayoutPositionableGroup, ILayoutContentSelector - where TChild : LayoutContent - { - if (pane.Children.Count > 0) - { - var index = 0; - if (pane.Children.Count > 1) - { - var tmTimeStamp = pane.Children[0].LastActivationTimeStamp; - for (var i = 1; i < pane.Children.Count; i++) - { - var item = pane.Children[i]; - if (item.LastActivationTimeStamp > tmTimeStamp) - { - tmTimeStamp = item.LastActivationTimeStamp; - index = i; - } - } - } - - pane.SelectedContentIndex = index; - } - } - #endregion Internal Methods #region 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; + } + } +}