428 lines
14 KiB
C#
428 lines
14 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|
||
} |