Skip to content

Commit

Permalink
Auto stash before checking out "origin/dui3/alpha"
Browse files Browse the repository at this point in the history
  • Loading branch information
Connor Ivy committed Jun 28, 2024
1 parent 0568a29 commit 487f7eb
Show file tree
Hide file tree
Showing 68 changed files with 1,119 additions and 57 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models.Card;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.Utils.Builders;
using Speckle.Connectors.Utils.Cancellation;
using Speckle.Connectors.Utils.Operations;
using Speckle.Autofac.DependencyInjection;
using Speckle.Connectors.Utils;

namespace Speckle.Connectors.Revit.Bindings;

internal class RevitReceiveBinding : IReceiveBinding
{
public string Name => "receiveBinding";
public IBridge Parent { get; }

private readonly CancellationManager _cancellationManager;
private readonly DocumentModelStore _store;
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
public ReceiveBindingUICommands Commands { get; }

public RevitReceiveBinding(
DocumentModelStore store,
CancellationManager cancellationManager,
IBridge parent,
IUnitOfWorkFactory unitOfWorkFactory
)
{
Parent = parent;
_store = store;
_unitOfWorkFactory = unitOfWorkFactory;
_cancellationManager = cancellationManager;
Commands = new ReceiveBindingUICommands(parent);
}

public void CancelReceive(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);

public async Task Receive(string modelCardId)
{
using var unitOfWork = _unitOfWorkFactory.Resolve<ReceiveOperation>();
try
{
// Get receiver card
if (_store.GetModelById(modelCardId) is not ReceiverModelCard modelCard)
{
// Handle as GLOBAL ERROR at BrowserBridge
throw new InvalidOperationException("No download model card was found.");
}

// Init cancellation token source -> Manager also cancel it if exist before
CancellationTokenSource cts = _cancellationManager.InitCancellationTokenSource(modelCardId);

// Receive host objects
HostObjectBuilderResult conversionResults = await unitOfWork.Service
.Execute(
modelCard.AccountId.NotNull(), // POC: I hear -you are saying why we're passing them separately. Not sure pass the DUI3-> Connectors.DUI project dependency to the SDK-> Connector.Utils
modelCard.ProjectId.NotNull(),
modelCard.ProjectName.NotNull(),
modelCard.ModelName.NotNull(),
modelCard.SelectedVersionId.NotNull(),
cts.Token,
(status, progress) => OnSendOperationProgress(modelCardId, status, progress)
)
.ConfigureAwait(false);

modelCard.BakedObjectIds = conversionResults.BakedObjectIds.ToList();
Commands.SetModelReceiveResult(
modelCardId,
conversionResults.BakedObjectIds,
conversionResults.ConversionResults
);
}
// Catch here specific exceptions if they related to model card.
catch (OperationCanceledException)
{
// SWALLOW -> UI handles it immediately, so we do not need to handle anything
return;
}
}

private void OnSendOperationProgress(string modelCardId, string status, double? progress)
{
Commands.SetModelProgress(modelCardId, new ModelCardProgress(modelCardId, status, progress));
}

public void CancelSend(string modelCardId) => _cancellationManager.CancelOperation(modelCardId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
using Speckle.Autofac.DependencyInjection;
using Speckle.Connectors.DUI;
using Speckle.Connectors.DUI.Bindings;
using Speckle.Connectors.DUI.Bridge;
using Speckle.Connectors.DUI.Models;
using Speckle.Connectors.Revit.Bindings;
using Speckle.Connectors.Revit.HostApp;
using Speckle.Connectors.Revit.Operations.Receive;
using Speckle.Connectors.Revit.Operations.Send;
using Speckle.Connectors.Revit.Plugin;
using Speckle.Connectors.Utils;
using Speckle.Connectors.Utils.Builders;
using Speckle.Connectors.Utils.Caching;
using Speckle.Connectors.Utils.Operations;
using Speckle.Core.Models.GraphTraversal;

namespace Speckle.Connectors.Revit.DependencyInjection;

Expand All @@ -27,7 +28,7 @@ public void Load(SpeckleContainerBuilder builder)
builder.AddDUI();
//builder.AddDUIView();

builder.AddSingletonInstance<ISyncToThread, SyncToCurrentThread>();
builder.AddSingletonInstance<ISyncToThread, RevitContextAccessor>();

// POC: different versons for different versions of CEF
builder.AddSingleton(BindingOptions.DefaultBinder);
Expand All @@ -49,20 +50,24 @@ public void Load(SpeckleContainerBuilder builder)
// and where the UoW should be
// register UI bindings
builder.AddSingleton<IBinding, TestBinding>();
builder.AddSingleton<IBinding, ConfigBinding>("connectorName", "ArcGIS"); // POC: Easier like this for now, should be cleaned up later
builder.AddSingleton<IBinding, ConfigBinding>("connectorName", "Revit"); // POC: Easier like this for now, should be cleaned up later
builder.AddSingleton<IBinding, AccountBinding>();
builder.AddSingleton<IBinding, BasicConnectorBindingRevit>();
builder.AddSingleton<IBasicConnectorBinding, BasicConnectorBindingRevit>();
builder.AddSingleton<IBinding, SelectionBinding>();
builder.AddSingleton<IBinding, RevitSendBinding>();
//no receive?
builder.AddSingleton<IBinding, RevitReceiveBinding>();
builder.AddSingleton<IRevitIdleManager, RevitIdleManager>();

// send operation and dependencies
builder.AddScoped<SendOperation<ElementId>>();
builder.AddScoped<IRootObjectBuilder<ElementId>, RevitRootObjectBuilder>();

// register send conversion cache
builder.AddSingleton<ISendConversionCache, SendConversionCache>();

// receive operation and dependencies
builder.AddScoped<ReceiveOperation>();
builder.AddScoped<IHostObjectBuilder, RevitHostObjectBuilder>();
builder.AddScoped<TransactionManager>();
builder.AddSingleton(DefaultTraversal.CreateTraversalFunc());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Revit.Async;
using Speckle.Connectors.Utils.Operations;

namespace Speckle.Connectors.Revit.Operations.Receive;

internal class RevitContextAccessor : ISyncToThread
{
public Task<T> RunOnThread<T>(Func<T> func) => RevitTask.RunAsync(func);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using Speckle.Connectors.Utils.Builders;
using Speckle.Connectors.Utils.Conversion;
using Speckle.Converters.Common;
using Speckle.Core.Logging;
using Speckle.Core.Models.GraphTraversal;
using Speckle.Core.Models;
using Speckle.Converters.RevitShared.Helpers;

namespace Speckle.Connectors.Revit.Operations.Receive;

internal class RevitHostObjectBuilder : IHostObjectBuilder
{
private readonly IRootToHostConverter _converter;
private readonly IRevitConversionContextStack _contextStack;
private readonly GraphTraversal _traverseFunction;
private readonly TransactionManager _transactionManager;

public RevitHostObjectBuilder(
IRootToHostConverter converter,
IRevitConversionContextStack contextStack,
GraphTraversal traverseFunction,
TransactionManager transactionManager
)
{
_converter = converter;
_contextStack = contextStack;
_traverseFunction = traverseFunction;
_transactionManager = transactionManager;
}

public HostObjectBuilderResult Build(
Base rootObject,
string projectName,
string modelName,
Action<string, double?>? onOperationProgressed,
CancellationToken cancellationToken
)
{
var objectsToConvert = _traverseFunction
.TraverseWithProgress(rootObject, onOperationProgressed, cancellationToken)
.Where(obj => obj.Current is not Collection);

_transactionManager.StartTransactionGroup($"Received data from {projectName}");

var conversionResults = BakeObjects(objectsToConvert);

_transactionManager.CommitTransactionGroup();
_transactionManager.Dispose();

return conversionResults;
}

// POC: Potentially refactor out into an IObjectBaker.
private HostObjectBuilderResult BakeObjects(IEnumerable<TraversalContext> objectsGraph)
{
var conversionResults = new List<ReceiveConversionResult>();
var bakedObjectIds = new List<string>();

foreach (TraversalContext tc in objectsGraph)
{
try
{
YieldToUiThread();
var result = _converter.Convert(tc.Current);
}
catch (Exception ex) when (!ex.IsFatal())
{
conversionResults.Add(new(Status.ERROR, tc.Current, null, null, ex));
}
}

return new(bakedObjectIds, conversionResults);
}

private DateTime _timerStarted = DateTime.MinValue;

private void YieldToUiThread()
{
var currentTime = DateTime.UtcNow;

if (currentTime.Subtract(_timerStarted) < TimeSpan.FromSeconds(.15))
{
return;
}

System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(
() => { },
System.Windows.Threading.DispatcherPriority.Background
);

_timerStarted = currentTime;
}
}
Loading

0 comments on commit 487f7eb

Please sign in to comment.