NavisworksTransport/src/Utils/NavisworksSelectionHelper.cs

428 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Autodesk.Navisworks.Api;
namespace NavisworksTransport.Utils
{
/// <summary>
/// Navisworks选择状态管理帮助类
/// 提供统一的选择状态查询、格式化和事件处理功能
/// </summary>
public static class NavisworksSelectionHelper
{
#region
/// <summary>
/// 获取当前选择状态信息
/// </summary>
/// <returns>选择状态信息结果</returns>
public static SelectionStateResult GetCurrentSelectionState()
{
try
{
var document = Application.ActiveDocument;
if (document?.CurrentSelection?.SelectedItems?.Count > 0)
{
var selectedCount = document.CurrentSelection.SelectedItems.Count;
var selectedItems = document.CurrentSelection.SelectedItems.Cast<ModelItem>().ToList();
return new SelectionStateResult
{
Success = true,
Count = selectedCount,
SelectedItems = selectedItems,
HasSelection = true
};
}
else
{
return new SelectionStateResult
{
Success = true,
Count = 0,
SelectedItems = new List<ModelItem>(),
HasSelection = false
};
}
}
catch (Exception ex)
{
return new SelectionStateResult
{
Success = false,
Count = 0,
SelectedItems = new List<ModelItem>(),
HasSelection = false,
ErrorMessage = $"检查选择状态失败: {ex.Message}"
};
}
}
/// <summary>
/// 异步获取当前选择状态信息
/// </summary>
/// <returns>选择状态信息结果</returns>
public static async Task<SelectionStateResult> GetCurrentSelectionStateAsync()
{
return await Task.Run(() => GetCurrentSelectionState());
}
/// <summary>
/// 检查是否有选中的项目
/// </summary>
/// <returns>是否有选择</returns>
public static bool HasSelectedItems()
{
try
{
var document = Application.ActiveDocument;
return document?.CurrentSelection?.SelectedItems?.Count > 0;
}
catch
{
return false;
}
}
/// <summary>
/// 设置Navisworks选择状态
/// </summary>
/// <param name="modelItem">要选择的模型项如果为null则清除选择</param>
/// <returns>操作是否成功</returns>
public static bool SetModelSelection(ModelItem modelItem)
{
try
{
var document = Application.ActiveDocument;
if (document?.CurrentSelection == null)
{
return false;
}
// 清除当前选择
document.CurrentSelection.Clear();
// 如果提供了模型项,则选择它
if (modelItem != null)
{
// 使用示例代码中的模式创建数组并使用CopyFrom
var items = new ModelItem[] { modelItem };
document.CurrentSelection.CopyFrom(items);
}
return true;
}
catch (Exception ex)
{
LogManager.Error($"设置Navisworks选择失败: {ex.Message}", ex);
return false;
}
}
/// <summary>
/// 设置Navisworks选择状态多个项目
/// </summary>
/// <param name="modelItems">要选择的模型项集合如果为null或空则清除选择</param>
/// <returns>操作是否成功</returns>
public static bool SetModelSelection(IEnumerable<ModelItem> modelItems)
{
try
{
var document = Application.ActiveDocument;
if (document?.CurrentSelection == null)
{
return false;
}
// 清除当前选择
document.CurrentSelection.Clear();
// 如果提供了模型项集合,则选择它们
if (modelItems != null && modelItems.Any())
{
// 使用示例代码中的模式直接传递IEnumerable给CopyFrom
document.CurrentSelection.CopyFrom(modelItems);
}
return true;
}
catch (Exception ex)
{
LogManager.Error($"设置Navisworks选择失败: {ex.Message}", ex);
return false;
}
}
#endregion
#region
/// <summary>
/// 格式化选择状态文本,包含节点名称
/// </summary>
/// <param name="count">选择数量</param>
/// <param name="selectedItems">选择的项目集合</param>
/// <param name="unitName">单位名称(如"个模型"、"个节点"</param>
/// <param name="maxDisplayCount">最大显示名称数量</param>
/// <param name="maxTotalLength">最大总长度</param>
/// <returns>格式化后的选择状态文本</returns>
public static string FormatSelectionText(int count, IEnumerable<ModelItem> selectedItems = null,
string unitName = "个模型", int maxDisplayCount = 3, int maxTotalLength = 80)
{
if (count == 0)
{
return $"请在主界面中选择需要设置的{unitName.Replace("", "")}";
}
var baseText = $"已选择{count}{unitName}";
if (selectedItems == null)
{
return baseText;
}
var itemsList = selectedItems.Take(maxDisplayCount + 1).ToList();
if (itemsList.Count == 0)
{
return baseText;
}
var names = new List<string>();
foreach (var item in itemsList.Take(maxDisplayCount))
{
var name = item?.DisplayName;
if (!string.IsNullOrWhiteSpace(name))
{
names.Add(name);
}
}
if (names.Count == 0)
{
return baseText;
}
string namesText;
if (count == 1)
{
// 单选时显示完整名称,但限制长度
var fullName = names[0];
if (fullName.Length > 50)
{
fullName = fullName.Substring(0, 47) + "...";
}
namesText = fullName;
}
else
{
// 多选时显示前几个名称
var joinedNames = string.Join(", ", names);
if (count > maxDisplayCount)
{
if (joinedNames.Length + 20 > maxTotalLength)
{
// 如果名称太长,截断并添加省略号
var truncatedLength = Math.Max(20, maxTotalLength - 20);
joinedNames = joinedNames.Substring(0, Math.Min(joinedNames.Length, truncatedLength)) + "...";
}
namesText = joinedNames + "...";
}
else
{
if (joinedNames.Length > maxTotalLength)
{
joinedNames = joinedNames.Substring(0, maxTotalLength - 3) + "...";
}
namesText = joinedNames;
}
}
return $"{baseText}: {namesText}";
}
/// <summary>
/// 基于选择状态结果格式化选择文本
/// </summary>
/// <param name="selectionResult">选择状态结果</param>
/// <param name="unitName">单位名称</param>
/// <param name="maxDisplayCount">最大显示名称数量</param>
/// <param name="maxTotalLength">最大总长度</param>
/// <returns>格式化后的选择状态文本</returns>
public static string FormatSelectionText(SelectionStateResult selectionResult,
string unitName = "个模型", int maxDisplayCount = 3, int maxTotalLength = 80)
{
if (!selectionResult.Success)
{
return selectionResult.ErrorMessage ?? "检查选择状态异常";
}
return FormatSelectionText(selectionResult.Count, selectionResult.SelectedItems,
unitName, maxDisplayCount, maxTotalLength);
}
#endregion
#region
/// <summary>
/// 选择变化事件委托
/// </summary>
/// <param name="selectionResult">新的选择状态</param>
public delegate Task SelectionChangedEventHandler(SelectionStateResult selectionResult);
/// <summary>
/// 订阅选择变化事件的包装器
/// </summary>
/// <param name="handler">事件处理器</param>
/// <param name="uiStateManager">UI状态管理器可选用于确保UI更新在正确线程执行</param>
/// <returns>事件订阅管理器</returns>
public static SelectionEventSubscription SubscribeToSelectionChanges(
SelectionChangedEventHandler handler,
Core.UIStateManager uiStateManager = null)
{
return new SelectionEventSubscription(handler, uiStateManager);
}
#endregion
}
/// <summary>
/// 选择状态结果
/// </summary>
public class SelectionStateResult
{
/// <summary>
/// 操作是否成功
/// </summary>
public bool Success { get; set; }
/// <summary>
/// 选择的数量
/// </summary>
public int Count { get; set; }
/// <summary>
/// 选择的项目集合
/// </summary>
public List<ModelItem> SelectedItems { get; set; } = new List<ModelItem>();
/// <summary>
/// 是否有选择
/// </summary>
public bool HasSelection { get; set; }
/// <summary>
/// 错误信息(如果操作失败)
/// </summary>
public string ErrorMessage { get; set; }
}
/// <summary>
/// 选择事件订阅管理器
/// 负责管理Navisworks选择变化事件的订阅和取消订阅
/// </summary>
public class SelectionEventSubscription : IDisposable
{
private readonly NavisworksSelectionHelper.SelectionChangedEventHandler _handler;
private readonly Core.UIStateManager _uiStateManager;
private bool _isSubscribed = false;
private bool _disposed = false;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="handler">事件处理器</param>
/// <param name="uiStateManager">UI状态管理器</param>
public SelectionEventSubscription(
NavisworksSelectionHelper.SelectionChangedEventHandler handler,
Core.UIStateManager uiStateManager = null)
{
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
_uiStateManager = uiStateManager;
Subscribe();
}
/// <summary>
/// 订阅事件
/// </summary>
private void Subscribe()
{
try
{
if (!_isSubscribed && Application.ActiveDocument?.CurrentSelection != null)
{
Application.ActiveDocument.CurrentSelection.Changed += OnNavisworksSelectionChanged;
_isSubscribed = true;
LogManager.Info("[NavisworksSelectionHelper] 已订阅Navisworks选择变化事件");
}
}
catch (Exception ex)
{
LogManager.Error($"[NavisworksSelectionHelper] 订阅选择事件失败: {ex.Message}", ex);
}
}
/// <summary>
/// 取消订阅事件
/// </summary>
private void Unsubscribe()
{
try
{
if (_isSubscribed && Application.ActiveDocument?.CurrentSelection != null)
{
Application.ActiveDocument.CurrentSelection.Changed -= OnNavisworksSelectionChanged;
_isSubscribed = false;
LogManager.Info("[NavisworksSelectionHelper] 已取消订阅Navisworks选择变化事件");
}
}
catch (Exception ex)
{
LogManager.Error($"[NavisworksSelectionHelper] 取消选择事件订阅失败: {ex.Message}", ex);
}
}
/// <summary>
/// Navisworks选择变化事件处理器
/// </summary>
private async void OnNavisworksSelectionChanged(object sender, EventArgs e)
{
try
{
// 获取最新的选择状态
var selectionResult = await NavisworksSelectionHelper.GetCurrentSelectionStateAsync();
// 如果有UI状态管理器确保在正确的线程上执行
if (_uiStateManager != null)
{
await _uiStateManager.ExecuteUIUpdateAsync(async () =>
{
await _handler(selectionResult);
});
}
else
{
await _handler(selectionResult);
}
}
catch (Exception ex)
{
LogManager.Error($"[NavisworksSelectionHelper] 处理选择变化事件异常: {ex.Message}", ex);
}
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (!_disposed)
{
Unsubscribe();
_disposed = true;
}
}
}
}