Lock selection clip box after activation

This commit is contained in:
tian 2026-04-15 16:02:12 +08:00
parent 1a9d0972f0
commit 28d0708858
5 changed files with 108 additions and 0 deletions

View File

@ -57,6 +57,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="UnitTests\Core\PathHelperTests.cs" />
<Compile Include="UnitTests\Core\SelectionClipBoxLockStateTests.cs" />
<Compile Include="UnitTests\Core\PathPlanningManagerHoistingCompletionTests.cs" />
<Compile Include="UnitTests\Core\PathPersistenceTests.cs" />
<Compile Include="UnitTests\Core\PathRouteCloneTests.cs" />

View File

@ -372,6 +372,7 @@
<Compile Include="src\Utils\VisibilityHelper.cs" />
<Compile Include="src\Utils\NwdExportHelper.cs" />
<Compile Include="src\Utils\ModelItemTransformHelper.cs" />
<Compile Include="src\Utils\SelectionClipBoxLockState.cs" />
<Compile Include="src\Utils\CachedTriangle3D.cs" />
<Compile Include="src\Utils\ClipboardHelper.cs" />
<Compile Include="src\Utils\PathHelper.cs" />

View File

@ -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<object> { new object() });
state.Clear();
Assert.IsFalse(state.IsLocked);
Assert.AreEqual(0, state.LockedSelectionCount);
}
}
}

View File

@ -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();
/// <summary>
/// 是否启用剖面盒(聚焦当前路径)
@ -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);
}

View File

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace NavisworksTransport.Utils
{
/// <summary>
/// 管理“按选择对象聚焦”的剖面盒锁定状态。
/// 一旦剖面盒按当前选择启用,就保持该场景稳定,直到用户主动关闭。
/// </summary>
public class SelectionClipBoxLockState
{
private IReadOnlyList<object> _lockedSelection = Array.Empty<object>();
public bool IsLocked => _lockedSelection.Count > 0;
public int LockedSelectionCount => _lockedSelection.Count;
public void LockSelection<T>(IEnumerable<T> selectedItems)
{
if (selectedItems == null)
{
throw new ArgumentNullException(nameof(selectedItems));
}
var lockedItems = selectedItems
.Cast<object>()
.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<object>();
}
}
}