diff --git a/NavisworksTransport.UnitTests.csproj b/NavisworksTransport.UnitTests.csproj index ec90fa9..6de6ee0 100644 --- a/NavisworksTransport.UnitTests.csproj +++ b/NavisworksTransport.UnitTests.csproj @@ -57,6 +57,7 @@ + diff --git a/TransportPlugin.csproj b/TransportPlugin.csproj index 4b86f88..8912ebe 100644 --- a/TransportPlugin.csproj +++ b/TransportPlugin.csproj @@ -372,6 +372,7 @@ + diff --git a/UnitTests/Core/SelectionClipBoxLockStateTests.cs b/UnitTests/Core/SelectionClipBoxLockStateTests.cs new file mode 100644 index 0000000..c4a5a23 --- /dev/null +++ b/UnitTests/Core/SelectionClipBoxLockStateTests.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NavisworksTransport.Utils; + +namespace NavisworksTransport.UnitTests.Core +{ + [TestClass] + public class SelectionClipBoxLockStateTests + { + [TestMethod] + public void ShouldRefreshOnSelectionChanged_ReturnsFalse_WhenSelectionClipBoxIsLocked() + { + var state = new SelectionClipBoxLockState(); + state.LockSelection(new object[] { new object(), new object() }); + + bool shouldRefresh = state.ShouldRefreshOnSelectionChanged(isSelectionClipBoxMode: true); + + Assert.IsFalse(shouldRefresh); + Assert.AreEqual(2, state.LockedSelectionCount); + } + + [TestMethod] + public void ShouldRefreshOnSelectionChanged_ReturnsTrue_WhenSelectionClipBoxModeHasNoLockedSelection() + { + var state = new SelectionClipBoxLockState(); + + bool shouldRefresh = state.ShouldRefreshOnSelectionChanged(isSelectionClipBoxMode: true); + + Assert.IsTrue(shouldRefresh); + Assert.AreEqual(0, state.LockedSelectionCount); + } + + [TestMethod] + public void Clear_UnlocksSelectionClipBoxState() + { + var state = new SelectionClipBoxLockState(); + state.LockSelection(new List { new object() }); + + state.Clear(); + + Assert.IsFalse(state.IsLocked); + Assert.AreEqual(0, state.LockedSelectionCount); + } + } +} diff --git a/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs b/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs index 29ff351..182f913 100644 --- a/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs +++ b/src/UI/WPF/ViewModels/LogisticsControlViewModel.cs @@ -154,6 +154,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels private bool _isSelectionClipBoxEnabled; private bool _isUpdatingClipBoxState; private ClipBoxFocusMode _clipBoxFocusMode = ClipBoxFocusMode.None; + private readonly SelectionClipBoxLockState _selectionClipBoxLockState = new SelectionClipBoxLockState(); /// /// 是否启用剖面盒(聚焦当前路径) @@ -394,6 +395,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels private void ClearActiveClipBox() { SetClipBoxState(ClipBoxFocusMode.None); + _selectionClipBoxLockState.Clear(); SectionClipHelper.ClearClipBox(); LogManager.Info("[剖面盒] 已关闭"); } @@ -432,6 +434,12 @@ namespace NavisworksTransport.UI.WPF.ViewModels return; } + if (!_selectionClipBoxLockState.ShouldRefreshOnSelectionChanged(isSelectionClipBoxMode: true)) + { + LogManager.Info($"[剖面盒] 选择已变化,但当前剖面盒保持锁定,锁定对象数: {_selectionClipBoxLockState.LockedSelectionCount}"); + return; + } + LogManager.Info("[剖面盒] 选择已变化,重新聚焦到当前选择对象"); EnableClipBoxForCurrentSelection(); } @@ -518,11 +526,13 @@ namespace NavisworksTransport.UI.WPF.ViewModels if (selectedItems == null || selectedItems.Count == 0) { LogManager.Warning("[剖面盒] 当前没有选中的模型对象,无法设置剖面盒"); + _selectionClipBoxLockState.Clear(); SectionClipHelper.ClearClipBox(); SetClipBoxState(ClipBoxFocusMode.None); return; } + _selectionClipBoxLockState.LockSelection(selectedItems); SectionClipHelper.ClearClipBox(); bool success = SectionClipHelper.SetClipBoxByModelItems( @@ -538,6 +548,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels else { LogManager.Warning("[剖面盒] 按选择对象设置失败"); + _selectionClipBoxLockState.Clear(); SectionClipHelper.ClearClipBox(); SetClipBoxState(ClipBoxFocusMode.None); } @@ -545,6 +556,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels catch (Exception ex) { LogManager.Error($"[剖面盒] 按选择对象启用失败: {ex.Message}"); + _selectionClipBoxLockState.Clear(); SectionClipHelper.ClearClipBox(); SetClipBoxState(ClipBoxFocusMode.None); } diff --git a/src/Utils/SelectionClipBoxLockState.cs b/src/Utils/SelectionClipBoxLockState.cs new file mode 100644 index 0000000..22d0060 --- /dev/null +++ b/src/Utils/SelectionClipBoxLockState.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace NavisworksTransport.Utils +{ + /// + /// 管理“按选择对象聚焦”的剖面盒锁定状态。 + /// 一旦剖面盒按当前选择启用,就保持该场景稳定,直到用户主动关闭。 + /// + public class SelectionClipBoxLockState + { + private IReadOnlyList _lockedSelection = Array.Empty(); + + public bool IsLocked => _lockedSelection.Count > 0; + + public int LockedSelectionCount => _lockedSelection.Count; + + public void LockSelection(IEnumerable selectedItems) + { + if (selectedItems == null) + { + throw new ArgumentNullException(nameof(selectedItems)); + } + + var lockedItems = selectedItems + .Cast() + .Where(item => item != null) + .ToList(); + + if (lockedItems.Count == 0) + { + throw new InvalidOperationException("锁定剖面盒前必须提供至少一个选中对象。"); + } + + _lockedSelection = lockedItems; + } + + public bool ShouldRefreshOnSelectionChanged(bool isSelectionClipBoxMode) + { + return isSelectionClipBoxMode && !IsLocked; + } + + public void Clear() + { + _lockedSelection = Array.Empty(); + } + } +}