diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/BasicConnectorBindingRevit.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/BasicConnectorBindingRevit.cs
index 781b0a046..9a2db88a4 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/BasicConnectorBindingRevit.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/BasicConnectorBindingRevit.cs
@@ -20,13 +20,13 @@ internal sealed class BasicConnectorBindingRevit : IBasicConnectorBinding
public BasicConnectorBindingCommands Commands { get; }
private readonly DocumentModelStore _store;
- private readonly RevitContext _revitContext;
+ private readonly IRevitContext _revitContext;
private readonly ISpeckleApplication _speckleApplication;
public BasicConnectorBindingRevit(
DocumentModelStore store,
IBrowserBridge parent,
- RevitContext revitContext,
+ IRevitContext revitContext,
ISpeckleApplication speckleApplication,
IEventAggregator eventAggregator
)
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitBaseBinding.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitBaseBinding.cs
index 04c363a18..6f71371f0 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitBaseBinding.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitBaseBinding.cs
@@ -1,7 +1,5 @@
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
-using Speckle.Connectors.DUI.Models;
-using Speckle.Converters.RevitShared.Helpers;
namespace Speckle.Connectors.Revit.Bindings;
@@ -11,14 +9,9 @@ internal abstract class RevitBaseBinding : IBinding
public string Name { get; }
public IBrowserBridge Parent { get; }
- protected readonly DocumentModelStore Store;
- protected readonly RevitContext RevitContext;
-
- protected RevitBaseBinding(string name, DocumentModelStore store, IBrowserBridge parent, RevitContext revitContext)
+ protected RevitBaseBinding(string name, IBrowserBridge parent)
{
Name = name;
Parent = parent;
- Store = store;
- RevitContext = revitContext;
}
}
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitSendBinding.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitSendBinding.cs
index 95438ad70..e16ae8d28 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitSendBinding.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitSendBinding.cs
@@ -17,6 +17,7 @@
using Speckle.Connectors.DUI.Settings;
using Speckle.Connectors.Revit.HostApp;
using Speckle.Connectors.Revit.Operations.Send.Settings;
+using Speckle.Connectors.Revit.Plugin;
using Speckle.Connectors.RevitShared.Operations.Send.Filters;
using Speckle.Converters.Common;
using Speckle.Converters.RevitShared.Helpers;
@@ -28,7 +29,8 @@ namespace Speckle.Connectors.Revit.Bindings;
internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
{
- private readonly IAppIdleManager _idleManager;
+ private readonly IRevitContext _revitContext;
+ private readonly DocumentModelStore _store;
private readonly CancellationManager _cancellationManager;
private readonly IServiceProvider _serviceProvider;
private readonly ISendConversionCache _sendConversionCache;
@@ -38,6 +40,7 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
private readonly ElementUnpacker _elementUnpacker;
private readonly IRevitConversionSettingsFactory _revitConversionSettingsFactory;
private readonly ISpeckleApplication _speckleApplication;
+ private readonly IEventAggregator _eventAggregator;
///
/// Used internally to aggregate the changed objects' id. Note we're using a concurrent dictionary here as the expiry check method is not thread safe, and this was causing problems. See:
@@ -48,8 +51,7 @@ internal sealed class RevitSendBinding : RevitBaseBinding, ISendBinding
private ConcurrentDictionary ChangedObjectIds { get; set; } = new();
public RevitSendBinding(
- IAppIdleManager idleManager,
- RevitContext revitContext,
+ IRevitContext revitContext,
DocumentModelStore store,
CancellationManager cancellationManager,
IBrowserBridge bridge,
@@ -61,12 +63,12 @@ public RevitSendBinding(
ElementUnpacker elementUnpacker,
IRevitConversionSettingsFactory revitConversionSettingsFactory,
ISpeckleApplication speckleApplication,
- IEventAggregator eventAggregator,
- ITopLevelExceptionHandler topLevelExceptionHandler
+ IEventAggregator eventAggregator
)
- : base("sendBinding", store, bridge, revitContext)
+ : base("sendBinding", bridge)
{
- _idleManager = idleManager;
+ _revitContext = revitContext;
+ _store = store;
_cancellationManager = cancellationManager;
_serviceProvider = serviceProvider;
_sendConversionCache = sendConversionCache;
@@ -76,13 +78,13 @@ ITopLevelExceptionHandler topLevelExceptionHandler
_elementUnpacker = elementUnpacker;
_revitConversionSettingsFactory = revitConversionSettingsFactory;
_speckleApplication = speckleApplication;
+ _eventAggregator = eventAggregator;
Commands = new SendBindingUICommands(bridge);
// TODO expiry events
// TODO filters need refresh events
- revitContext.UIApplication.NotNull().Application.DocumentChanged += (_, e) =>
- topLevelExceptionHandler.CatchUnhandled(() => DocChangeHandler(e));
+ eventAggregator.GetEvent().Subscribe(DocChangeHandler);
eventAggregator.GetEvent().Subscribe(OnDocumentStoreChangedEvent);
}
@@ -91,8 +93,8 @@ ITopLevelExceptionHandler topLevelExceptionHandler
public List GetSendFilters() =>
[
new RevitSelectionFilter() { IsDefault = true },
- new RevitViewsFilter(RevitContext),
- new RevitCategoriesFilter(RevitContext)
+ new RevitViewsFilter(_revitContext),
+ new RevitCategoriesFilter(_revitContext)
];
public List GetSendSettings() =>
@@ -111,7 +113,7 @@ public async Task Send(string modelCardId)
// Note: removed top level handling thing as it was confusing me
try
{
- if (Store.GetModelById(modelCardId) is not SenderModelCard modelCard)
+ if (_store.GetModelById(modelCardId) is not SenderModelCard modelCard)
{
// Handle as GLOBAL ERROR at BrowserBridge
throw new InvalidOperationException("No publish model card was found.");
@@ -171,12 +173,12 @@ public async Task Send(string modelCardId)
private async Task> RefreshElementsOnSender(SenderModelCard modelCard)
{
var activeUIDoc =
- RevitContext.UIApplication?.ActiveUIDocument
+ _revitContext.UIApplication.ActiveUIDocument
?? throw new SpeckleException("Unable to retrieve active UI document");
if (modelCard.SendFilter is IRevitSendFilter viewFilter)
{
- viewFilter.SetContext(RevitContext);
+ viewFilter.SetContext(_revitContext);
}
var selectedObjects = modelCard.SendFilter.NotNull().RefreshObjectIds();
@@ -247,13 +249,13 @@ private void DocChangeHandler(Autodesk.Revit.DB.Events.DocumentChangedEventArgs
if (addedElementIds.Count > 0)
{
- _idleManager.SubscribeToIdle(nameof(PostSetObjectIds), PostSetObjectIds);
+ _eventAggregator.GetEvent().OneTimeSubscribe(nameof(PostSetObjectIds), PostSetObjectIds);
}
if (HaveUnitsChanged(e.GetDocument()))
{
var objectIds = new List();
- foreach (var sender in Store.GetSenders().ToList())
+ foreach (var sender in _store.GetSenders().ToList())
{
if (sender.SendFilter is null)
{
@@ -267,8 +269,8 @@ private void DocChangeHandler(Autodesk.Revit.DB.Events.DocumentChangedEventArgs
_sendConversionCache.EvictObjects(unpackedObjectIds);
}
- _idleManager.SubscribeToIdle(nameof(CheckFilterExpiration), CheckFilterExpiration);
- _idleManager.SubscribeToIdle(nameof(RunExpirationChecks), RunExpirationChecks);
+ _eventAggregator.GetEvent().OneTimeSubscribe(nameof(CheckFilterExpiration), CheckFilterExpiration);
+ _eventAggregator.GetEvent().OneTimeSubscribe(nameof(RunExpirationChecks), RunExpirationChecks);
}
// Keeps track of doc and current units
@@ -305,9 +307,9 @@ private bool HaveUnitsChanged(Document doc)
return false;
}
- private async Task PostSetObjectIds()
+ private async Task PostSetObjectIds(object _)
{
- foreach (var sender in Store.GetSenders().ToList())
+ foreach (var sender in _store.GetSenders().ToList())
{
await RefreshElementsOnSender(sender);
}
@@ -316,7 +318,7 @@ private async Task PostSetObjectIds()
///
/// Notifies ui if any filters need refreshing. Currently, this only applies for view filters.
///
- private async Task CheckFilterExpiration()
+ private async Task CheckFilterExpiration(object _)
{
// NOTE: below code seems like more make sense in terms of performance but it causes unmanaged exception on Revit
// using var viewCollector = new FilteredElementCollector(RevitContext.UIApplication?.ActiveUIDocument.Document);
@@ -327,17 +329,17 @@ private async Task CheckFilterExpiration()
// await Commands.RefreshSendFilters();
// }
- if (ChangedObjectIds.Keys.Any(e => RevitContext.UIApplication?.ActiveUIDocument.Document.GetElement(e) is View))
+ if (ChangedObjectIds.Keys.Any(e => _revitContext.UIApplication.ActiveUIDocument.Document.GetElement(e) is View))
{
await Commands.RefreshSendFilters();
}
}
- private async Task RunExpirationChecks()
+ private async Task RunExpirationChecks(object _)
{
- var senders = Store.GetSenders().ToList();
+ var senders = _store.GetSenders().ToList();
// string[] objectIdsList = ChangedObjectIds.Keys.ToArray();
- var doc = RevitContext.UIApplication?.ActiveUIDocument.Document;
+ var doc = _revitContext.UIApplication.ActiveUIDocument.Document;
if (doc == null)
{
@@ -388,7 +390,7 @@ private async Task RunExpirationChecks()
{
if (modelCard.SendFilter is IRevitSendFilter viewFilter)
{
- viewFilter.SetContext(RevitContext);
+ viewFilter.SetContext(_revitContext);
}
var selectedObjects = modelCard.SendFilter.NotNull().IdMap.NotNull().Values;
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/SelectionBinding.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/SelectionBinding.cs
index a5903928f..6c194ce67 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/SelectionBinding.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/SelectionBinding.cs
@@ -1,42 +1,27 @@
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
-using Speckle.Connectors.DUI.Models;
+using Speckle.Connectors.DUI.Eventing;
+using Speckle.Connectors.Revit.Plugin;
using Speckle.Converters.RevitShared.Helpers;
using Speckle.Sdk.Common;
namespace Speckle.Connectors.Revit.Bindings;
// POC: we need a base a RevitBaseBinding
-internal sealed class SelectionBinding : RevitBaseBinding, ISelectionBinding, IDisposable
+internal sealed class SelectionBinding : RevitBaseBinding, ISelectionBinding
{
-#if REVIT2022
- private readonly System.Timers.Timer _selectionTimer;
-#endif
+ private readonly IRevitContext _revitContext;
- public SelectionBinding(
- RevitContext revitContext,
- DocumentModelStore store,
- IAppIdleManager revitIdleManager,
- ITopLevelExceptionHandler topLevelExceptionHandler,
- IBrowserBridge parent
- )
- : base("selectionBinding", store, parent, revitContext)
+ public SelectionBinding(IRevitContext revitContext, IBrowserBridge parent, IEventAggregator eventAggregator)
+ : base("selectionBinding", parent)
{
-#if REVIT2022
- // NOTE: getting the selection data should be a fast function all, even for '000s of elements - and having a timer hitting it every 1s is ok.
- _selectionTimer = new System.Timers.Timer(1000);
- _selectionTimer.Elapsed += (_, _) => topLevelExceptionHandler.CatchUnhandled(OnSelectionChanged);
- _selectionTimer.Start();
-#else
-
- RevitContext.UIApplication.NotNull().SelectionChanged += (_, _) =>
- revitIdleManager.SubscribeToIdle(nameof(SelectionBinding), OnSelectionChanged);
-#endif
+ _revitContext = revitContext;
+ eventAggregator.GetEvent().Subscribe(OnSelectionChanged);
}
- private void OnSelectionChanged()
+ private void OnSelectionChanged(object _)
{
- if (RevitContext.UIApplication == null || RevitContext.UIApplication.ActiveUIDocument == null)
+ if (_revitContext.UIApplication.ActiveUIDocument == null)
{
return;
}
@@ -45,12 +30,12 @@ private void OnSelectionChanged()
public SelectionInfo GetSelection()
{
- if (RevitContext.UIApplication == null || RevitContext.UIApplication.ActiveUIDocument == null)
+ if (_revitContext.UIApplication.ActiveUIDocument == null)
{
return new SelectionInfo(Array.Empty(), "No objects selected.");
}
- var activeUIDoc = RevitContext.UIApplication.ActiveUIDocument.NotNull();
+ var activeUIDoc = _revitContext.UIApplication.ActiveUIDocument.NotNull();
// POC: this was also being called on shutdown
// probably the bridge needs to be able to know if the plugin has been terminated
@@ -61,11 +46,4 @@ public SelectionInfo GetSelection()
.ToList();
return new SelectionInfo(selectionIds, $"{selectionIds.Count} objects selected.");
}
-
- public void Dispose()
- {
-#if REVIT2022
- _selectionTimer.Dispose();
-#endif
- }
}
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/DependencyInjection/RevitConnectorModule.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/DependencyInjection/RevitConnectorModule.cs
index 59dc9da5f..7910a0400 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/DependencyInjection/RevitConnectorModule.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/DependencyInjection/RevitConnectorModule.cs
@@ -15,6 +15,7 @@
using Speckle.Connectors.Revit.Operations.Send.Settings;
using Speckle.Connectors.Revit.Plugin;
using Speckle.Converters.Common;
+using Speckle.Converters.RevitShared.Helpers;
using Speckle.Sdk.Models.GraphTraversal;
namespace Speckle.Connectors.Revit.DependencyInjection;
@@ -41,10 +42,10 @@ public static void AddRevit(this IServiceCollection serviceCollection)
serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
serviceCollection.AddSingleton();
- serviceCollection.AddSingleton();
serviceCollection.AddSingleton(sp => sp.GetRequiredService());
serviceCollection.AddSingleton();
+ serviceCollection.AddSingleton(sp => sp.GetRequiredService());
// send operation and dependencies
serviceCollection.AddScoped>();
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/ElementUnpacker.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/ElementUnpacker.cs
index b30ec74b0..e2ccb5fa1 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/ElementUnpacker.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/ElementUnpacker.cs
@@ -9,9 +9,9 @@ namespace Speckle.Connectors.Revit.HostApp;
///
public class ElementUnpacker
{
- private readonly RevitContext _revitContext;
+ private readonly IRevitContext _revitContext;
- public ElementUnpacker(RevitContext revitContext)
+ public ElementUnpacker(IRevitContext revitContext)
{
_revitContext = revitContext;
}
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/RevitDocumentStore.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/RevitDocumentStore.cs
index 6647f8b63..ceedd2d3a 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/RevitDocumentStore.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/RevitDocumentStore.cs
@@ -1,13 +1,11 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExtensibleStorage;
-using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Events;
-using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Eventing;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.DUI.Utils;
+using Speckle.Connectors.Revit.Plugin;
using Speckle.Converters.RevitShared.Helpers;
-using Speckle.Sdk.Common;
namespace Speckle.Connectors.Revit.HostApp;
@@ -17,51 +15,43 @@ internal sealed class RevitDocumentStore : DocumentModelStore
// POC: move to somewhere central?
private static readonly Guid s_revitDocumentStoreId = new("D35B3695-EDC9-4E15-B62A-D3FC2CB83FA3");
- private readonly RevitContext _revitContext;
- private readonly IAppIdleManager _idleManager;
+ private readonly IRevitContext _revitContext;
private readonly DocumentModelStorageSchema _documentModelStorageSchema;
private readonly IdStorageSchema _idStorageSchema;
private readonly IEventAggregator _eventAggregator;
public RevitDocumentStore(
- IAppIdleManager idleManager,
- RevitContext revitContext,
+ IRevitContext revitContext,
IJsonSerializer jsonSerializer,
DocumentModelStorageSchema documentModelStorageSchema,
IdStorageSchema idStorageSchema,
- IEventAggregator eventAggregator,
- ITopLevelExceptionHandler topLevelExceptionHandler
+ IEventAggregator eventAggregator
)
: base(jsonSerializer)
{
- _idleManager = idleManager;
_revitContext = revitContext;
_documentModelStorageSchema = documentModelStorageSchema;
_idStorageSchema = idStorageSchema;
_eventAggregator = eventAggregator;
- UIApplication uiApplication = _revitContext.UIApplication.NotNull();
-
- uiApplication.ViewActivated += (s, e) => topLevelExceptionHandler.CatchUnhandled(() => OnViewActivated(s, e));
-
- uiApplication.Application.DocumentOpening += (_, _) =>
- topLevelExceptionHandler.CatchUnhandled(() => IsDocumentInit = false);
-
- uiApplication.Application.DocumentOpened += (_, _) =>
- topLevelExceptionHandler.CatchUnhandled(() => IsDocumentInit = false);
+ eventAggregator.GetEvent().Subscribe(OnDocumentOpen);
+ eventAggregator.GetEvent().Subscribe(OnDocumentOpen);
+ eventAggregator.GetEvent().Subscribe(OnViewActivated);
// There is no event that we can hook here for double-click file open...
// It is kind of harmless since we create this object as "SingleInstance".
LoadState();
}
+ private void OnDocumentOpen(object _) => IsDocumentInit = false;
+
public override Task OnDocumentStoreInitialized() =>
_eventAggregator.GetEvent().PublishAsync(new object());
///
/// This is the place where we track document switch for new document -> Responsible to Read from new doc
///
- private void OnViewActivated(object? _, ViewActivatedEventArgs e)
+ private void OnViewActivated(ViewActivatedEventArgs e)
{
if (e.Document == null)
{
@@ -75,14 +65,13 @@ private void OnViewActivated(object? _, ViewActivatedEventArgs e)
}
IsDocumentInit = true;
- _idleManager.SubscribeToIdle(
- nameof(RevitDocumentStore),
- async () =>
- {
- LoadState();
- await _eventAggregator.GetEvent().PublishAsync(new object());
- }
- );
+ _eventAggregator.GetEvent().OneTimeSubscribe(nameof(RevitDocumentStore), OnIdleEvent);
+ }
+
+ private async Task OnIdleEvent(object _)
+ {
+ LoadState();
+ await _eventAggregator.GetEvent().PublishAsync(new object());
}
protected override void HostAppSaveState(string modelCardState)
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Filters/IRevitSendFilter.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Filters/IRevitSendFilter.cs
index fe576b8b3..628721059 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Filters/IRevitSendFilter.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Filters/IRevitSendFilter.cs
@@ -4,5 +4,5 @@ namespace Speckle.Connectors.RevitShared.Operations.Send.Filters;
public interface IRevitSendFilter
{
- public void SetContext(RevitContext revitContext);
+ public void SetContext(IRevitContext revitContext);
}
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Filters/RevitCategoriesFilter.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Filters/RevitCategoriesFilter.cs
index 5a3f9b3ee..b926089a6 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Filters/RevitCategoriesFilter.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Filters/RevitCategoriesFilter.cs
@@ -11,7 +11,7 @@ public record CategoryData(string Name, string Id);
public class RevitCategoriesFilter : DiscriminatedObject, ISendFilter, IRevitSendFilter
{
- private RevitContext _revitContext;
+ private IRevitContext _revitContext;
private Document? _doc;
public string Id { get; set; } = "revitCategories";
public string Name { get; set; } = "Categories";
@@ -24,10 +24,10 @@ public class RevitCategoriesFilter : DiscriminatedObject, ISendFilter, IRevitSen
public RevitCategoriesFilter() { }
- public RevitCategoriesFilter(RevitContext revitContext)
+ public RevitCategoriesFilter(IRevitContext revitContext)
{
_revitContext = revitContext;
- _doc = _revitContext.UIApplication?.ActiveUIDocument.Document;
+ _doc = _revitContext.UIApplication.ActiveUIDocument.Document;
GetCategories();
}
@@ -83,7 +83,7 @@ private void GetCategories()
/// NOTE: this is needed since we need doc on `GetObjectIds()` function after it deserialized.
/// DI doesn't help here to pass RevitContext from constructor.
///
- public void SetContext(RevitContext revitContext)
+ public void SetContext(IRevitContext revitContext)
{
_revitContext = revitContext;
_doc = _revitContext.UIApplication?.ActiveUIDocument.Document;
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Filters/RevitViewsFilter.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Filters/RevitViewsFilter.cs
index ac54ab0c6..41af5b1b9 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Filters/RevitViewsFilter.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Filters/RevitViewsFilter.cs
@@ -8,7 +8,7 @@ namespace Speckle.Connectors.RevitShared.Operations.Send.Filters;
public class RevitViewsFilter : DiscriminatedObject, ISendFilter, IRevitSendFilter
{
- private RevitContext _revitContext;
+ private IRevitContext _revitContext;
private Document? _doc;
public string Id { get; set; } = "revitViews";
public string Name { get; set; } = "Views";
@@ -21,7 +21,7 @@ public class RevitViewsFilter : DiscriminatedObject, ISendFilter, IRevitSendFilt
public RevitViewsFilter() { }
- public RevitViewsFilter(RevitContext revitContext)
+ public RevitViewsFilter(IRevitContext revitContext)
{
_revitContext = revitContext;
_doc = _revitContext.UIApplication?.ActiveUIDocument.Document;
@@ -109,7 +109,7 @@ or ViewType.AreaPlan
/// NOTE: this is needed since we need doc on `GetObjectIds()` function after it deserialized.
/// DI doesn't help here to pass RevitContext from constructor.
///
- public void SetContext(RevitContext revitContext)
+ public void SetContext(IRevitContext revitContext)
{
_revitContext = revitContext;
_doc = _revitContext.UIApplication?.ActiveUIDocument.Document;
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Settings/ToSpeckleSettingsManager.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Settings/ToSpeckleSettingsManager.cs
index f1e55df9b..5fd21feed 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Settings/ToSpeckleSettingsManager.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Operations/Send/Settings/ToSpeckleSettingsManager.cs
@@ -13,7 +13,7 @@ namespace Speckle.Connectors.Revit.Operations.Send.Settings;
[GenerateAutoInterface]
public class ToSpeckleSettingsManager : IToSpeckleSettingsManager
{
- private readonly RevitContext _revitContext;
+ private readonly IRevitContext _revitContext;
private readonly ISendConversionCache _sendConversionCache;
private readonly ElementUnpacker _elementUnpacker;
@@ -23,7 +23,7 @@ public class ToSpeckleSettingsManager : IToSpeckleSettingsManager
private readonly Dictionary _sendNullParamsCache = new();
public ToSpeckleSettingsManager(
- RevitContext revitContext,
+ IRevitContext revitContext,
ISendConversionCache sendConversionCache,
ElementUnpacker elementUnpacker
)
@@ -68,7 +68,7 @@ out ReferencePointType referencePoint
{
// get the current transform from setting first
// we are doing this because we can't track if reference points were changed between send operations.
- Transform? currentTransform = GetTransform(_revitContext, referencePoint);
+ Transform? currentTransform = GetTransform(referencePoint);
if (_referencePointCache.TryGetValue(modelCard.ModelCardId.NotNull(), out Transform? previousTransform))
{
@@ -109,11 +109,11 @@ private void EvictCacheForModelCard(SenderModelCard modelCard)
_sendConversionCache.EvictObjects(unpackedObjectIds);
}
- private Transform? GetTransform(RevitContext context, ReferencePointType referencePointType)
+ private Transform? GetTransform(ReferencePointType referencePointType)
{
Transform? referencePointTransform = null;
- if (context.UIApplication is UIApplication uiApplication)
+ if (_revitContext.UIApplication is UIApplication uiApplication)
{
// first get the main doc base points and reference setting transform
using FilteredElementCollector filteredElementCollector = new(uiApplication.ActiveUIDocument.Document);
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Plugin/IRevitPlugin.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Plugin/IRevitPlugin.cs
index fb88ffc44..5ba7f1d52 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Plugin/IRevitPlugin.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Plugin/IRevitPlugin.cs
@@ -1,6 +1,8 @@
+using Speckle.Converters.RevitShared.Helpers;
+
namespace Speckle.Connectors.Revit.Plugin;
-internal interface IRevitPlugin
+internal interface IRevitPlugin : IRevitContext
{
void Initialise();
void Shutdown();
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Plugin/RevitCefPlugin.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Plugin/RevitCefPlugin.cs
index fb23025c7..1cbc084ee 100644
--- a/Connectors/Revit/Speckle.Connectors.RevitShared/Plugin/RevitCefPlugin.cs
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Plugin/RevitCefPlugin.cs
@@ -3,16 +3,13 @@
using System.Reflection;
using System.Windows.Media;
using System.Windows.Media.Imaging;
-using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.UI;
using CefSharp;
using Microsoft.Extensions.DependencyInjection;
-using Revit.Async;
using Speckle.Connectors.Common;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
-using Speckle.Connectors.DUI.Models;
-using Speckle.Converters.RevitShared.Helpers;
+using Speckle.Connectors.DUI.Eventing;
using Speckle.Sdk;
namespace Speckle.Connectors.Revit.Plugin;
@@ -22,7 +19,6 @@ internal sealed class RevitCefPlugin : IRevitPlugin
private readonly UIControlledApplication _uIControlledApplication;
private readonly IServiceProvider _serviceProvider; // should be lazy to ensure the bindings are not created too early
private readonly BindingOptions _bindingOptions;
- private readonly RevitContext _revitContext;
private readonly CefSharpPanel _cefSharpPanel;
private readonly ISpeckleApplication _speckleApplication;
@@ -30,17 +26,17 @@ public RevitCefPlugin(
UIControlledApplication uIControlledApplication,
IServiceProvider serviceProvider,
BindingOptions bindingOptions,
- RevitContext revitContext,
CefSharpPanel cefSharpPanel,
- ISpeckleApplication speckleApplication
+ ISpeckleApplication speckleApplication,
+ IEventAggregator eventAggregator
)
{
_uIControlledApplication = uIControlledApplication;
_serviceProvider = serviceProvider;
_bindingOptions = bindingOptions;
- _revitContext = revitContext;
_cefSharpPanel = cefSharpPanel;
_speckleApplication = speckleApplication;
+ eventAggregator.GetEvent().Subscribe(OnApplicationInitialized);
}
public void Initialise()
@@ -48,7 +44,6 @@ public void Initialise()
// Create and register panels before app initialized. this is needed for double-click file open
CreateTabAndRibbonPanel(_uIControlledApplication);
RegisterDockablePane();
- _uIControlledApplication.ControlledApplication.ApplicationInitialized += OnApplicationInitialized;
}
public void Shutdown()
@@ -100,26 +95,10 @@ private void CreateTabAndRibbonPanel(UIControlledApplication application)
dui3Button.SetContextualHelp(new ContextualHelp(ContextualHelpType.Url, "https://speckle.systems"));
}
- private async void OnApplicationInitialized(
- object? sender,
- Autodesk.Revit.DB.Events.ApplicationInitializedEventArgs e
- )
+ private void OnApplicationInitialized(UIApplication uiApplication)
{
- var uiApplication = new UIApplication(sender as Application);
- _revitContext.UIApplication = uiApplication;
-
- // POC: might be worth to interface this out, we shall see...
- RevitTask.Initialize(uiApplication);
- await _serviceProvider.GetRequiredService().OnDocumentStoreInitialized();
-
- PostApplicationInit(); // for double-click file open
- }
+ UIApplication = uiApplication;
- ///
- /// Actions to run after UiApplication initialized. This is needed for double-click file open issue.
- ///
- private void PostApplicationInit()
- {
var bindings = _serviceProvider.GetRequiredService>();
// binding the bindings to each bridge
foreach (IBinding binding in bindings)
@@ -128,7 +107,7 @@ private void PostApplicationInit()
binding.Parent.AssociateWithBinding(binding);
}
- _cefSharpPanel.Browser.IsBrowserInitializedChanged += (sender, e) =>
+ _cefSharpPanel.Browser.IsBrowserInitializedChanged += (_, e) =>
{
if (e.NewValue is false)
{
@@ -186,4 +165,6 @@ private void RegisterDockablePane()
return null;
}
+
+ public UIApplication UIApplication { get; private set; }
}
diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Plugin/RevitEvents.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Plugin/RevitEvents.cs
new file mode 100644
index 000000000..7d5add3b1
--- /dev/null
+++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Plugin/RevitEvents.cs
@@ -0,0 +1,77 @@
+using Autodesk.Revit.ApplicationServices;
+using Autodesk.Revit.UI;
+using Autodesk.Revit.UI.Events;
+using Speckle.Connectors.Common.Threading;
+using Speckle.Connectors.DUI.Bridge;
+using Speckle.Connectors.DUI.Eventing;
+
+namespace Speckle.Connectors.Revit.Plugin;
+
+public class ApplicationInitializedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
+ : ThreadedEvent(threadContext, exceptionHandler);
+
+public class ViewActivatedEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
+ : ThreadedEvent(threadContext, exceptionHandler);
+
+public class DocumentOpeningEvent(IThreadContext threadContext, ITopLevelExceptionHandler exceptionHandler)
+ : ThreadedEvent