This commit is contained in:
Matteo Cominetti
2020-06-27 15:36:49 +01:00
parent bbb3415a59
commit b3ca512963
10 changed files with 513 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
#region Namespaces
using System;
using System.Collections.Generic;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
#endregion
namespace xUnitRevit
{
class App : IExternalApplication
{
public Result OnStartup(UIControlledApplication a)
{
#if DEBUG
a.ControlledApplication.ApplicationInitialized += ControlledApplication_ApplicationInitialized; ;
#endif
return Result.Succeeded;
}
private void ControlledApplication_ApplicationInitialized(object sender, Autodesk.Revit.DB.Events.ApplicationInitializedEventArgs e)
{
Application app = sender as Application;
UIApplication uiapp = new UIApplication(app);
// uiapp.OpenAndActivateDocument(@"C:\Code\Speckle-Next\SpeckleKitRevit\TestModels\Walls.rvt");
TestRunner.Launch(uiapp);
}
public Result OnShutdown(UIControlledApplication a)
{
return Result.Succeeded;
}
}
}
+22
View File
@@ -0,0 +1,22 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace xUnitRevit
{
internal class CmdAvailabilityViews : IExternalCommandAvailability
{
/// <summary>
/// Command Availability - Views
/// </summary>
/// <param name="applicationData"></param>
/// <param name="selectedCategories"></param>
/// <returns></returns>
public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories)
{
//Can be run from any view/state
return true;
}
}
}
+46
View File
@@ -0,0 +1,46 @@
#region Namespaces
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Threading;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Xunit.Runner.Wpf;
using Xunit.Runner.Wpf.ViewModel;
#endregion
namespace xUnitRevit
{
[Transaction(TransactionMode.Manual)]
public class Command : IExternalCommand
{
static object consoleLock = new object();
static ManualResetEvent finished = new ManualResetEvent(false);
static Result result = Result.Succeeded;
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
UIApplication uiapp = commandData.Application;
TestRunner.Launch(uiapp);
return Result.Succeeded;
}
}
}
+47
View File
@@ -0,0 +1,47 @@
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace xUnitRevit
{
/// <summary>
/// Speckle custom event invoker. Has a queue of actions that, in theory, this things should iterate through.
/// Actions are added to the queue from the ui bindings (mostly) and then raised.
/// </summary>
public class ExternalEventHandler : IExternalEventHandler
{
public bool Running = false;
public List<Action> Queue { get; set; }
public ExternalEventHandler(List<Action> queue)
{
Queue = queue;
}
public void Execute(UIApplication app)
{
Debug.WriteLine("Current queue len is: " + Queue.Count);
if (Running) return; // queue will run itself through
Running = true;
Queue[0]();
Queue.RemoveAt(0);
Running = false;
}
public string GetName()
{
return "xUnit Revit";
}
}
}
+36
View File
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SpeckleRevitTests")]
[assembly: AssemblyDescription("Revit Add-In Description for SpeckleRevitTests")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Autodesk Inc.")]
[assembly: AssemblyProduct("SpeckleRevitTests Revit C# .NET Add-In")]
[assembly: AssemblyCopyright("Copyright (C) 2020 by Jeremy Tammik, Autodesk Inc.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("321044f7-b0b2-4b1c-af18-e71a19252be0")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2021.0.0.0")]
[assembly: AssemblyFileVersion("2021.0.0.0")]
+76
View File
@@ -0,0 +1,76 @@
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xunit.Runner.Wpf;
using Xunit.Runner.Wpf.ViewModel;
using xUnitRevitUtils;
namespace xUnitRevit
{
public static class TestRunner
{
public static void Launch(UIApplication uiapp)
{
try
{
var queue = new List<Action>();
var eventHandler = ExternalEvent.Create(new ExternalEventHandler(queue));
xru.Initialize(uiapp, SynchronizationContext.Current, eventHandler, queue);
var main = new MainWindow();
main.Title = "xUnit Revit by Speckle";
/// (main.DataContext as MainViewModel).Injector =
(main.DataContext as MainViewModel).StartupAssemblies = new List<string>() { @"C:\Code\Speckle-Next\SpeckleKitRevit\SpeckleRevitTests\bin\Debug\SpeckleRevitTests.dll" };
main.Show();
}
catch (Exception e)
{
}
//return Result.Succeeded;
}
}
//public class Injector : IAssemblyInjector
//{
// private UIApplication uiapp { get; set; }
// SynchronizationContext uiContext { get; set; }
// private List<Action> queue { get; set; }
// private ExternalEvent eventHandler { get; set; }
// public Injector(UIApplication uiapp, SynchronizationContext uiContext, ExternalEvent eventHandler, List<Action> queue)
// {
// this.uiapp = uiapp;
// this.uiContext = uiContext;
// this.eventHandler = eventHandler;
// this.queue = queue;
// }
// public void Inject(Assembly assembly)
// {
// var types = assembly.GetTypes();
// foreach (var type in types)
// {
// if (type.Name == "xru")
// {
// if (type.GetProperties().Select(p => p.Name).Contains("Uiapp"))
// {
// type.GetProperty("Uiapp").SetValue(null, uiapp);
// type.GetProperty("UiContext").SetValue(null, uiContext);
// type.GetProperty("Queue").SetValue(null, queue);
// type.GetProperty("EventHandler").SetValue(null, eventHandler);
// }
// }
// }
// }
//}
}
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
<AddIn Type="Command">
<Text>xUnitRevit</Text>
<Description>xUnitRevit</Description>
<Assembly>xUnitRevit\xUnitRevit.dll</Assembly>
<FullClassName>xUnitRevit.Command</FullClassName>
<ClientId>9d179887-9fae-41f9-940a-697b59cafe4a</ClientId>
<VendorId>speckle</VendorId>
<VendorDescription>Speckle</VendorDescription>
</AddIn>
<AddIn Type="Application">
<Name>Application xUnitRevit</Name>
<Assembly>xUnitRevit\xUnitRevit.dll</Assembly>
<FullClassName>xUnitRevit.App</FullClassName>
<ClientId>d9c9ed6f-7b2a-4c47-8f87-a6f33a553d50</ClientId>
<VendorId>speckle</VendorId>
<VendorDescription>Speckle</VendorDescription>
</AddIn>
</RevitAddIns>
+98
View File
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
None
</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{27A79ACA-7EA8-4406-8BB8-216578CC3AB7}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>xUnitRevit</RootNamespace>
<AssemblyName>xUnitRevit</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\Revit 2021\Revit.exe</StartProgram>
<RevitVersion>2021</RevitVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<StartAction>Program</StartAction>
<StartProgram>$(ProgramW6432)\Autodesk\Revit 2021\Revit.exe</StartProgram>
<RevitVersion>2021</RevitVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="RevitAPI">
<HintPath>$(ProgramW6432)\Autodesk\Revit 2021\RevitAPI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="RevitAPIUI">
<HintPath>$(ProgramW6432)\Autodesk\Revit 2021\RevitAPIUI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="App.cs" />
<Compile Include="CmdAvailabilityViews.cs" />
<Compile Include="Command.cs" />
<Compile Include="ExternalEventHandler.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestRunner.cs" />
</ItemGroup>
<ItemGroup>
<None Include="xUnitRevit.addin" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\xunit.runner.wpf\xunit.runner.wpf\xunit.runner.wpf.csproj">
<Project>{4120f4ac-1b24-4b7c-86a9-0a3c75e526cd}</Project>
<Name>xunit.runner.wpf</Name>
</ProjectReference>
<ProjectReference Include="..\xUnitRevitUtils\xUnitRevitUtils.csproj">
<Project>{9406d1d6-0751-4f22-9a0e-87acfbe17365}</Project>
<Name>xUnitRevitUtils</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<Target Name="AfterBuild">
<ItemGroup>
<SourceDLLs Include="$(TargetDir)\**\*.*" />
<SourceManifest Include="$(ProjectDir)*.addin" />
</ItemGroup>
<Copy DestinationFolder="$(AppData)\Autodesk\REVIT\Addins\$(RevitVersion)\$(ProjectName)\%(RecursiveDir)" SourceFiles="@(SourceDLLs)" />
<Copy DestinationFolder="$(AppData)\Autodesk\REVIT\Addins\$(RevitVersion)\" SourceFiles="@(SourceManifest)" />
</Target>
<Target Name="AfterClean">
<Delete Files="$(AppData)\Autodesk\REVIT\Addins\2021\SpeckleRevitTests.addin" />
<Delete Files="$(AppData)\Autodesk\REVIT\Addins\2021\SpeckleRevitTests.dll" />
</Target>
</Project>
+12
View File
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ModPlus.Revit.API.2021" Version="1.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
</ItemGroup>
</Project>
+115
View File
@@ -0,0 +1,115 @@
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace xUnitRevitUtils
{
public static class xru
{
private static UIApplication Uiapp { get; set; }
private static List<Action> Queue { get; set; }
private static ExternalEvent EventHandler { get; set; }
private static SynchronizationContext UiContext { get; set; }
public static Document ActiveDoc { get { return Uiapp.ActiveUIDocument.Document; } }
public static Selection CuerrentSelection { get { return Uiapp.ActiveUIDocument.Selection; } }
public static void Initialize(UIApplication uiapp, SynchronizationContext uiContext, ExternalEvent eventHandler, List<Action> queue)
{
Uiapp = uiapp;
UiContext = uiContext;
EventHandler = eventHandler;
Queue = queue;
}
public static List<Element> GetActiveSelection()
{
if (Uiapp.ActiveUIDocument != null)
return Uiapp.ActiveUIDocument.Selection.GetElementIds().Select(x => Uiapp.ActiveUIDocument.Document.GetElement(x)).ToList();
return new List<Element>();
}
/// <summary>
/// Opens and activates a document if not open already
/// </summary>
/// <param name="path"></param>
public static Document OpenDoc(string path)
{
Assert.NotNull(Uiapp);
Document doc = null;
//OpenAndActivateDocument only works if run from the current context
UiContext.Send(x => { doc = Uiapp.OpenAndActivateDocument(path).Document; }, null);
Assert.NotNull(doc);
return doc;
}
/// <summary>
/// Creates a new empty document
/// </summary>
/// <param name="path"></param>
public static Document CreateNewDoc(string templatePath, string filePath)
{
Assert.NotNull(Uiapp);
Document doc = null;
try
{
if (File.Exists(filePath))
File.Delete(filePath);
}
catch { }
//OpenAndActivateDocument only works if run from the current context
UiContext.Send(x =>
{
if (!File.Exists(filePath))
{
doc = Uiapp.Application.NewProjectDocument(templatePath);
doc.SaveAs(filePath);
doc.Close();
}
doc = Uiapp.OpenAndActivateDocument(filePath).Document;
}
, null);
Assert.NotNull(doc);
return doc;
}
public static Task RunInTransaction(Action action, Document doc)
{
var tcs = new TaskCompletionSource<string>();
Queue.Add(new Action(() =>
{
try
{
using (Transaction transaction = new Transaction(doc, "test transaction"))
{
transaction.Start();
action.Invoke();
transaction.Commit();
}
}
catch (Exception e)
{
tcs.TrySetException(e);
}
tcs.TrySetResult("");
}));
EventHandler.Raise();
return tcs.Task;
}
}
}