Files
speckle-sharp-connectors/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSelectionBinding.cs
T
Oğuzhan Koral 93246157c7 Fix: threading on browser bridge + remove event aggr (#574)
* Fix threading bug

* untangle revit

* revert rhino

* revert autocad

* revert rest

* remove event agg and rhino implementation

* remove event aggr from revit

* remove event aggr from autocad and civil

* remove event aggr tests

* remove event aggr from tekla

* Remove event aggr for navis

* remove event aggr from csi etabs

* remove event aggr for arcgis

* remove remaining pieces

* push autocad to run operations on main thread

* adds teklaidlemanager

* bring navis idle manager back

* run send on main

* remove unused function

---------

Co-authored-by: Dogukan Karatas <karatasdogukan@gmail.com>
2025-02-10 17:50:26 +03:00

101 lines
3.5 KiB
C#

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Speckle.Connectors.Autocad.HostApp.Extensions;
using Speckle.Connectors.Common.Threading;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
namespace Speckle.Connectors.Autocad.Bindings;
public class AutocadSelectionBinding : ISelectionBinding
{
private readonly ITopLevelExceptionHandler _topLevelExceptionHandler;
private readonly IThreadContext _threadContext;
private const string SELECTION_EVENT = "setSelection";
private readonly HashSet<Document> _visitedDocuments = new();
public string Name => "selectionBinding";
public IBrowserBridge Parent { get; }
public AutocadSelectionBinding(
IBrowserBridge parent,
ITopLevelExceptionHandler topLevelExceptionHandler,
IThreadContext threadContext
)
{
_topLevelExceptionHandler = topLevelExceptionHandler;
_threadContext = threadContext;
Parent = parent;
// POC: Use here Context for doc. In converters it's OK but we are still lacking to use context into bindings.
// It is with the case of if binding created with already a document
// This is valid when user opens acad file directly double clicking
TryRegisterDocumentForSelection(Application.DocumentManager.MdiActiveDocument);
Application.DocumentManager.DocumentActivated += (_, e) =>
_topLevelExceptionHandler.CatchUnhandled(() => OnDocumentChanged(e.Document));
}
private void OnDocumentChanged(Document? document) => TryRegisterDocumentForSelection(document);
private void TryRegisterDocumentForSelection(Document? document)
{
if (document == null)
{
return;
}
if (!_visitedDocuments.Contains(document))
{
document.ImpliedSelectionChanged += (_, _) =>
_topLevelExceptionHandler.FireAndForget(async () => await _threadContext.RunOnMainAsync(OnSelectionChanged));
_visitedDocuments.Add(document);
}
}
// NOTE: Autocad 2022 caused problems, so we need to refactor things a bit in here to always store
// selection info locally (and get it updated by the event, which we can control to run on the main thread).
// Ui requests to GetSelection() should just return this local copy that is kept up to date by the event handler.
private SelectionInfo _selectionInfo;
private async Task OnSelectionChanged()
{
_selectionInfo = GetSelectionInternal();
await Parent.Send(SELECTION_EVENT, _selectionInfo);
}
public SelectionInfo GetSelection() => _selectionInfo;
private SelectionInfo GetSelectionInternal()
{
// POC: Will be addressed to move it into AutocadContext! https://spockle.atlassian.net/browse/CNX-9319
Document? doc = Application.DocumentManager.MdiActiveDocument;
List<string> objs = new();
List<string> objectTypes = new();
if (doc != null)
{
using var tr = doc.TransactionManager.StartTransaction();
PromptSelectionResult selection = doc.Editor.SelectImplied();
if (selection.Status == PromptStatus.OK)
{
foreach (SelectedObject obj in selection.Value)
{
var dbObject = tr.GetObject(obj.ObjectId, OpenMode.ForRead);
if (dbObject == null)
{
continue;
}
objectTypes.Add(dbObject.GetType().Name);
objs.Add(dbObject.GetSpeckleApplicationId());
}
tr.Commit();
}
}
List<string> flatObjectTypes = objectTypes.Select(o => o).Distinct().ToList();
return new SelectionInfo(objs, $"{objs.Count} objects ({string.Join(", ", flatObjectTypes)})");
}
}