From b3ca512963a6ed8488ec9ecfd09cc8c9c9312d53 Mon Sep 17 00:00:00 2001 From: Matteo Cominetti Date: Sat, 27 Jun 2020 15:36:49 +0100 Subject: [PATCH] init --- xUnitRevit/App.cs | 41 +++++++++ xUnitRevit/CmdAvailabilityViews.cs | 22 +++++ xUnitRevit/Command.cs | 46 ++++++++++ xUnitRevit/ExternalEventHandler.cs | 47 ++++++++++ xUnitRevit/Properties/AssemblyInfo.cs | 36 ++++++++ xUnitRevit/TestRunner.cs | 76 ++++++++++++++++ xUnitRevit/xUnitRevit.addin | 20 +++++ xUnitRevit/xUnitRevit.csproj | 98 +++++++++++++++++++++ xUnitRevitUtils/xUnitRevitUtils.csproj | 12 +++ xUnitRevitUtils/xru.cs | 115 +++++++++++++++++++++++++ 10 files changed, 513 insertions(+) create mode 100644 xUnitRevit/App.cs create mode 100644 xUnitRevit/CmdAvailabilityViews.cs create mode 100644 xUnitRevit/Command.cs create mode 100644 xUnitRevit/ExternalEventHandler.cs create mode 100644 xUnitRevit/Properties/AssemblyInfo.cs create mode 100644 xUnitRevit/TestRunner.cs create mode 100644 xUnitRevit/xUnitRevit.addin create mode 100644 xUnitRevit/xUnitRevit.csproj create mode 100644 xUnitRevitUtils/xUnitRevitUtils.csproj create mode 100644 xUnitRevitUtils/xru.cs diff --git a/xUnitRevit/App.cs b/xUnitRevit/App.cs new file mode 100644 index 0000000..81878e1 --- /dev/null +++ b/xUnitRevit/App.cs @@ -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; + } + } +} diff --git a/xUnitRevit/CmdAvailabilityViews.cs b/xUnitRevit/CmdAvailabilityViews.cs new file mode 100644 index 0000000..1797c5f --- /dev/null +++ b/xUnitRevit/CmdAvailabilityViews.cs @@ -0,0 +1,22 @@ +using Autodesk.Revit.DB; +using Autodesk.Revit.UI; + +namespace xUnitRevit +{ + internal class CmdAvailabilityViews : IExternalCommandAvailability + { + + /// + /// Command Availability - Views + /// + /// + /// + /// + public bool IsCommandAvailable(UIApplication applicationData, CategorySet selectedCategories) + { + //Can be run from any view/state + return true; + + } + } +} \ No newline at end of file diff --git a/xUnitRevit/Command.cs b/xUnitRevit/Command.cs new file mode 100644 index 0000000..f972d8f --- /dev/null +++ b/xUnitRevit/Command.cs @@ -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; + + + + } + + + + + + } + + +} diff --git a/xUnitRevit/ExternalEventHandler.cs b/xUnitRevit/ExternalEventHandler.cs new file mode 100644 index 0000000..3f5688d --- /dev/null +++ b/xUnitRevit/ExternalEventHandler.cs @@ -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 +{ + /// + /// 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. + /// + public class ExternalEventHandler : IExternalEventHandler + { + + public bool Running = false; + public List Queue { get; set; } + + public ExternalEventHandler(List 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"; + } + } +} + + diff --git a/xUnitRevit/Properties/AssemblyInfo.cs b/xUnitRevit/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..830c8cb --- /dev/null +++ b/xUnitRevit/Properties/AssemblyInfo.cs @@ -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")] diff --git a/xUnitRevit/TestRunner.cs b/xUnitRevit/TestRunner.cs new file mode 100644 index 0000000..627a15d --- /dev/null +++ b/xUnitRevit/TestRunner.cs @@ -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(); + 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() { @"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 queue { get; set; } + // private ExternalEvent eventHandler { get; set; } + + // public Injector(UIApplication uiapp, SynchronizationContext uiContext, ExternalEvent eventHandler, List 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); + // } + // } + // } + // } + + //} +} diff --git a/xUnitRevit/xUnitRevit.addin b/xUnitRevit/xUnitRevit.addin new file mode 100644 index 0000000..b1d1b67 --- /dev/null +++ b/xUnitRevit/xUnitRevit.addin @@ -0,0 +1,20 @@ + + + + xUnitRevit + xUnitRevit + xUnitRevit\xUnitRevit.dll + xUnitRevit.Command + 9d179887-9fae-41f9-940a-697b59cafe4a + speckle + Speckle + + + Application xUnitRevit + xUnitRevit\xUnitRevit.dll + xUnitRevit.App + d9c9ed6f-7b2a-4c47-8f87-a6f33a553d50 + speckle + Speckle + + diff --git a/xUnitRevit/xUnitRevit.csproj b/xUnitRevit/xUnitRevit.csproj new file mode 100644 index 0000000..ab1dfeb --- /dev/null +++ b/xUnitRevit/xUnitRevit.csproj @@ -0,0 +1,98 @@ + + + + + + None + + + + + + + Debug + AnyCPU + {27A79ACA-7EA8-4406-8BB8-216578CC3AB7} + Library + Properties + xUnitRevit + xUnitRevit + v4.8 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + Program + $(ProgramW6432)\Autodesk\Revit 2021\Revit.exe + 2021 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + Program + $(ProgramW6432)\Autodesk\Revit 2021\Revit.exe + 2021 + + + + + + $(ProgramW6432)\Autodesk\Revit 2021\RevitAPI.dll + False + + + $(ProgramW6432)\Autodesk\Revit 2021\RevitAPIUI.dll + False + + + + + + + + + + + + + + + + + + {4120f4ac-1b24-4b7c-86a9-0a3c75e526cd} + xunit.runner.wpf + + + {9406d1d6-0751-4f22-9a0e-87acfbe17365} + xUnitRevitUtils + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xUnitRevitUtils/xUnitRevitUtils.csproj b/xUnitRevitUtils/xUnitRevitUtils.csproj new file mode 100644 index 0000000..fe19c8d --- /dev/null +++ b/xUnitRevitUtils/xUnitRevitUtils.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.0 + + + + + + + + diff --git a/xUnitRevitUtils/xru.cs b/xUnitRevitUtils/xru.cs new file mode 100644 index 0000000..e8b0912 --- /dev/null +++ b/xUnitRevitUtils/xru.cs @@ -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 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 queue) + { + Uiapp = uiapp; + UiContext = uiContext; + EventHandler = eventHandler; + Queue = queue; + } + + public static List GetActiveSelection() + { + if (Uiapp.ActiveUIDocument != null) + return Uiapp.ActiveUIDocument.Selection.GetElementIds().Select(x => Uiapp.ActiveUIDocument.Document.GetElement(x)).ToList(); + return new List(); + } + /// + /// Opens and activates a document if not open already + /// + /// + 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; + } + + + /// + /// Creates a new empty document + /// + /// + 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(); + 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; + } + } +}