├── .gitignore ├── tests └── EsapiEssentials.UnitTests │ ├── packages.config │ ├── EsapiEssentials.UnitTests.csproj.DotSettings │ ├── Properties │ └── AssemblyInfo.cs │ ├── PatientSearch │ └── PatientSummarySearchTests.cs │ └── EsapiEssentials.UnitTests.csproj ├── src ├── EsapiEssentials.PluginRunner │ ├── Application │ │ ├── PlanType.cs │ │ ├── PatientMatch.cs │ │ └── PlanOrPlanSum.cs │ ├── Persistence │ │ ├── IDataRepository.cs │ │ ├── Data.cs │ │ ├── DataRepository.cs │ │ └── RecentEntry.cs │ ├── packages.config │ ├── app.config │ ├── EsapiEssentials.PluginRunner.nuspec │ ├── View │ │ ├── MainWindow.xaml.cs │ │ └── UnderscoreConverter.cs │ ├── PlansAndPlanSumsConverter.cs │ ├── EsapiEssentials.PluginRunner.csproj.DotSettings │ ├── ViewModel │ │ ├── PlanOrSumViewModel.cs │ │ └── MainViewModel.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── ScriptRunner.cs └── EsapiEssentials │ ├── packages.config │ ├── Standalone │ ├── PatientSearch │ │ ├── SearchPatient.cs │ │ ├── PatientSearch.cs │ │ └── PatientSummarySearch.cs │ ├── Async │ │ ├── LogInRequiredException.cs │ │ ├── PatientNotOpenedException.cs │ │ └── AsyncRunner.cs │ └── StandaloneRunner │ │ ├── StandaloneRunnerException.cs │ │ ├── StandaloneRunner.cs │ │ └── ScriptContextArgs.cs │ ├── Core │ └── DoseUnit.cs │ ├── EsapiEssentials.nuspec │ ├── Plugin │ ├── Async │ │ ├── AsyncRunner.cs │ │ ├── EsapiServiceBase.cs │ │ └── UiRunner.cs │ ├── PluginRunner │ │ ├── ScriptBase.cs │ │ ├── ScriptBaseWithWindow.cs │ │ └── PluginScriptContext.cs │ └── Settings │ │ └── AssemblySettings.cs │ ├── Extensions │ ├── PatientExtensions.cs │ ├── DoseValueExtensions.cs │ ├── StructureExtensions.cs │ └── PlanningItemExtensions.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── EsapiEssentials.csproj.DotSettings │ └── EsapiEssentials.csproj ├── samples ├── EsapiEssentials.Samples.Async │ ├── DialogService │ │ ├── IDialogProgress.cs │ │ ├── IDialogService.cs │ │ ├── SimpleProgress.cs │ │ └── DialogService.cs │ ├── Esapi │ │ ├── Plan.cs │ │ ├── PatientMatch.cs │ │ ├── DoseMetricCalculator.cs │ │ ├── IEsapiService.cs │ │ └── EsapiService.cs │ ├── ViewModels │ │ ├── MetricResult.cs │ │ └── MainViewModel.cs │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── packages.config │ ├── App.xaml │ ├── Views │ │ ├── MainWindow.xaml.cs │ │ ├── ProgressDialog.xaml │ │ ├── UnderscoreConverter.cs │ │ └── ProgressDialog.xaml.cs │ ├── App.config │ ├── EsapiEssentials.Samples.Async.csproj.DotSettings │ └── App.xaml.cs ├── EsapiEssentials.Samples.AsyncPlugin │ ├── DialogService │ │ ├── IDialogProgress.cs │ │ ├── IDialogService.cs │ │ ├── SimpleProgress.cs │ │ └── DialogService.cs │ ├── Esapi │ │ ├── Plan.cs │ │ ├── IEsapiService.cs │ │ ├── DoseMetricCalculator.cs │ │ └── EsapiService.cs │ ├── ViewModels │ │ ├── MetricResult.cs │ │ └── MainViewModel.cs │ ├── packages.config │ ├── Views │ │ ├── MainWindow.xaml.cs │ │ ├── ProgressDialog.xaml │ │ ├── UnderscoreConverter.cs │ │ ├── ProgressDialog.xaml.cs │ │ └── MainWindow.xaml │ ├── app.config │ ├── Script.cs │ ├── EsapiEssentials.Samples.AsyncPlugin.csproj.DotSettings │ └── Properties │ │ └── AssemblyInfo.cs ├── EsapiEssentials.Samples.PluginScript │ ├── App.config │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Script.cs │ └── EsapiEssentials.Samples.PluginScript.csproj ├── EsapiEssentials.Samples.StandaloneApp │ ├── App.xaml.cs │ ├── App.config │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── App.xaml │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ └── EsapiEssentials.Samples.StandaloneApp.csproj ├── EsapiEssentials.Samples.AsyncPlugin.Runner │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── App.xaml │ ├── App.config │ ├── App.xaml.cs │ └── EsapiEssentials.Samples.AsyncPlugin.Runner.csproj ├── EsapiEssentials.Samples.PluginScript.Runner │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── App.xaml │ ├── App.config │ ├── App.xaml.cs │ └── EsapiEssentials.Samples.PluginScript.Runner.csproj └── EsapiEssentials.Samples.StandaloneApp.Runner │ ├── Script.cs │ ├── Properties │ └── AssemblyInfo.cs │ └── EsapiEssentials.Samples.StandaloneApp.Runner.csproj ├── README.md ├── Common.props └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific files 2 | *.suo 3 | *.user 4 | *.vs 5 | 6 | # Build results 7 | bin/ 8 | obj/ 9 | 10 | # NuGet packages 11 | packages/ 12 | -------------------------------------------------------------------------------- /tests/EsapiEssentials.UnitTests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/Application/PlanType.cs: -------------------------------------------------------------------------------- 1 | namespace EsapiEssentials.PluginRunner 2 | { 3 | internal enum PlanType 4 | { 5 | Plan, 6 | PlanSum 7 | } 8 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/DialogService/IDialogProgress.cs: -------------------------------------------------------------------------------- 1 | namespace EsapiEssentials.Samples.Async 2 | { 3 | public interface ISimpleProgress 4 | { 5 | void Increment(); 6 | } 7 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/DialogService/IDialogProgress.cs: -------------------------------------------------------------------------------- 1 | namespace EsapiEssentials.Samples.AsyncPlugin 2 | { 3 | public interface ISimpleProgress 4 | { 5 | void Increment(); 6 | } 7 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace EsapiEssentials.Samples.StandaloneRunner.App 4 | { 5 | public partial class App : Application 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/Persistence/IDataRepository.cs: -------------------------------------------------------------------------------- 1 | namespace EsapiEssentials.PluginRunner 2 | { 3 | internal interface IDataRepository 4 | { 5 | Data Load(); 6 | void Save(Data data); 7 | } 8 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Esapi/Plan.cs: -------------------------------------------------------------------------------- 1 | namespace EsapiEssentials.Samples.Async 2 | { 3 | public class Plan 4 | { 5 | public string CourseId { get; set; } 6 | public string PlanId { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/Esapi/Plan.cs: -------------------------------------------------------------------------------- 1 | namespace EsapiEssentials.Samples.AsyncPlugin 2 | { 3 | public class Plan 4 | { 5 | public string CourseId { get; set; } 6 | public string PlanId { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/ViewModels/MetricResult.cs: -------------------------------------------------------------------------------- 1 | namespace EsapiEssentials.Samples.Async 2 | { 3 | public class MetricResult 4 | { 5 | public string StructureId { get; set; } 6 | public double Result { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /src/EsapiEssentials/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/ViewModels/MetricResult.cs: -------------------------------------------------------------------------------- 1 | namespace EsapiEssentials.Samples.AsyncPlugin 2 | { 3 | public class MetricResult 4 | { 5 | public string StructureId { get; set; } 6 | public double Result { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin.Runner/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript.Runner/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Esapi/PatientMatch.cs: -------------------------------------------------------------------------------- 1 | namespace EsapiEssentials.Samples.Async 2 | { 3 | public class PatientMatch 4 | { 5 | public string Id { get; set; } 6 | public string FirstName { get; set; } 7 | public string LastName { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/Application/PatientMatch.cs: -------------------------------------------------------------------------------- 1 | namespace EsapiEssentials.PluginRunner 2 | { 3 | internal class PatientMatch 4 | { 5 | public string Id { get; set; } 6 | public string LastName { get; set; } 7 | public string FirstName { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin.Runner/App.xaml: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript.Runner/App.xaml: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp/App.xaml: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/App.xaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EsapiEssentials 2 | C# class library with extra functionality for ESAPI 3 | 4 | See the following related posts for more information: 5 | 6 | - [Introducing ESAPI Essentials](http://www.carlosjanderson.com/introducing-esapi-essentials) 7 | - [ESAPI Essentials 1.1 and 2.0](http://www.carlosjanderson.com/esapi-essentials-1-1-and-2-0) 8 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp.Runner/Script.cs: -------------------------------------------------------------------------------- 1 | using EsapiEssentials.Standalone; 2 | using VMS.TPS.Common.Model.API; 3 | 4 | namespace VMS.TPS 5 | { 6 | public class Script 7 | { 8 | public void Execute(ScriptContext context) 9 | { 10 | StandaloneRunner.RunWith(context); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/Persistence/Data.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace EsapiEssentials.PluginRunner 4 | { 5 | internal class Data 6 | { 7 | public Data() 8 | { 9 | Recents = new List(); 10 | } 11 | 12 | public List Recents { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /src/EsapiEssentials/Standalone/PatientSearch/SearchPatient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EsapiEssentials.Standalone 4 | { 5 | internal class SearchPatient 6 | { 7 | public string Id { get; set; } 8 | public string FirstName { get; set; } 9 | public string LastName { get; set; } 10 | public DateTime? CreationDateTime { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /src/EsapiEssentials/Standalone/Async/LogInRequiredException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EsapiEssentials.Standalone 4 | { 5 | public class LogInRequiredException : Exception 6 | { 7 | public LogInRequiredException() { } 8 | 9 | public LogInRequiredException(Exception innerException) 10 | : base("The user has not logged in to Eclipse.", innerException) { } 11 | } 12 | } -------------------------------------------------------------------------------- /src/EsapiEssentials/Core/DoseUnit.cs: -------------------------------------------------------------------------------- 1 | namespace EsapiEssentials.Core 2 | { 3 | /// 4 | /// Represents the dose unit (Gy or cGy). 5 | /// 6 | public enum DoseUnit 7 | { 8 | /// 9 | /// Gray (Gy) 10 | /// 11 | Gy, 12 | 13 | /// 14 | /// Centigray (cGy) 15 | /// 16 | CGy 17 | } 18 | } -------------------------------------------------------------------------------- /src/EsapiEssentials/Standalone/Async/PatientNotOpenedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EsapiEssentials.Standalone 4 | { 5 | public class PatientNotOpenedException : Exception 6 | { 7 | public PatientNotOpenedException() { } 8 | 9 | public PatientNotOpenedException(Exception innerException) 10 | : base("The patient has not been opened.", innerException) { } 11 | } 12 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/DialogService/IDialogService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace EsapiEssentials.Samples.Async 5 | { 6 | public interface IDialogService 7 | { 8 | void ShowProgressDialog(string message, Func workAsync); 9 | void ShowProgressDialog(string message, int maximum, Func workAsync); 10 | } 11 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/DialogService/IDialogService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace EsapiEssentials.Samples.AsyncPlugin 5 | { 6 | public interface IDialogService 7 | { 8 | void ShowProgressDialog(string message, Func workAsync); 9 | void ShowProgressDialog(string message, int maximum, Func workAsync); 10 | } 11 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/Esapi/IEsapiService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace EsapiEssentials.Samples.AsyncPlugin 4 | { 5 | public interface IEsapiService 6 | { 7 | Task GetPlansAsync(); 8 | Task GetStructureIdsAsync(string courseId, string planId); 9 | 10 | Task CalculateMeanDoseAsync(string courseId, string planId, string structureId); 11 | } 12 | } -------------------------------------------------------------------------------- /src/EsapiEssentials/Standalone/StandaloneRunner/StandaloneRunnerException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EsapiEssentials.Standalone 4 | { 5 | public class StandaloneRunnerException : Exception 6 | { 7 | public StandaloneRunnerException(string message) 8 | : base(message) { } 9 | 10 | public StandaloneRunnerException(string message, Exception innerException) 11 | : base(message, innerException) { } 12 | } 13 | } -------------------------------------------------------------------------------- /tests/EsapiEssentials.UnitTests/EsapiEssentials.UnitTests.csproj.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/Views/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Interactivity; 3 | 4 | namespace EsapiEssentials.Samples.AsyncPlugin 5 | { 6 | public partial class MainWindow : Window 7 | { 8 | public MainWindow() 9 | { 10 | // Force Interactivity assembly to be included in build files 11 | Interaction.GetBehaviors(this); 12 | 13 | InitializeComponent(); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/DialogService/SimpleProgress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EsapiEssentials.Samples.Async 4 | { 5 | public class SimpleProgress : ISimpleProgress 6 | { 7 | private readonly Action _onIncrement; 8 | 9 | public SimpleProgress(Action onIncrement) 10 | { 11 | _onIncrement = onIncrement; 12 | } 13 | 14 | public void Increment() 15 | { 16 | _onIncrement(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/DialogService/SimpleProgress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EsapiEssentials.Samples.AsyncPlugin 4 | { 5 | public class SimpleProgress : ISimpleProgress 6 | { 7 | private readonly Action _onIncrement; 8 | 9 | public SimpleProgress(Action onIncrement) 10 | { 11 | _onIncrement = onIncrement; 12 | } 13 | 14 | public void Increment() 15 | { 16 | _onIncrement(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Views/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace EsapiEssentials.Samples.Async 4 | { 5 | public partial class MainWindow : Window 6 | { 7 | public MainWindow(MainViewModel viewModel) 8 | { 9 | InitializeComponent(); 10 | DataContext = viewModel; 11 | } 12 | 13 | private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) 14 | { 15 | SearchTextBox.Focus(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/EsapiEssentials/EsapiEssentials.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | MIT 10 | https://github.com/redcurry/EsapiEssentials 11 | false 12 | $description$ 13 | Copyright 2019 14 | esapi varian 15 | 16 | 17 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/EsapiEssentials/Plugin/Async/AsyncRunner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Windows.Threading; 4 | 5 | namespace EsapiEssentials.Plugin 6 | { 7 | internal class AsyncRunner 8 | { 9 | private readonly Dispatcher _dispatcher; 10 | 11 | public AsyncRunner() 12 | { 13 | _dispatcher = Dispatcher.CurrentDispatcher; 14 | } 15 | 16 | public Task RunAsync(Action a) => 17 | _dispatcher.InvokeAsync(a).Task; 18 | 19 | public Task RunAsync(Func f) => 20 | _dispatcher.InvokeAsync(f).Task; 21 | } 22 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin.Runner/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript.Runner/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/EsapiEssentials.PluginRunner.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | MIT 10 | https://github.com/redcurry/EsapiEssentials 11 | false 12 | $description$ 13 | Copyright 2019 14 | esapi varian 15 | 16 | 17 | -------------------------------------------------------------------------------- /Common.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ESAPI_13;$(DefineConstants) 5 | C:\esapi\13.6 6 | 7 | 8 | ESAPI_15;$(DefineConstants) 9 | C:\esapi\15.6 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/View/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace EsapiEssentials.PluginRunner 5 | { 6 | internal partial class MainWindow : Window 7 | { 8 | public MainWindow(MainViewModel vm) 9 | { 10 | InitializeComponent(); 11 | DataContext = vm; 12 | } 13 | 14 | private void PlansAndPlanSums_OnSelectionChanged(object sender, SelectionChangedEventArgs e) 15 | { 16 | // Prevent selection for this ListBox 17 | var listBox = (ListBox)sender; 18 | listBox.UnselectAll(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin.Runner/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using EsapiEssentials.PluginRunner; 2 | using System.Windows; 3 | using VMS.TPS; 4 | using VMS.TPS.Common.Model.API; 5 | 6 | namespace EsapiEssentials.Samples.AsyncPlugin.Runner 7 | { 8 | public partial class App : System.Windows.Application 9 | { 10 | private void App_OnStartup(object sender, StartupEventArgs e) 11 | { 12 | // Note: EsapiEssentials and EsapiEssentials.PluginRunner must be referenced, 13 | // as well as the project that contains the Script class 14 | ScriptRunner.Run(new Script()); 15 | } 16 | 17 | public void Dummy(PlanSetup plan) { } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript.Runner/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using EsapiEssentials.PluginRunner; 3 | using VMS.TPS; 4 | using VMS.TPS.Common.Model.API; 5 | 6 | namespace EsapiEssentials.Samples.PluginScript.Runner 7 | { 8 | public partial class App : System.Windows.Application 9 | { 10 | private void App_OnStartup(object sender, StartupEventArgs e) 11 | { 12 | // Note: EsapiEssentials and EsapiEssentials.PluginRunner must be referenced, 13 | // as well as the project that contains the Script class 14 | ScriptRunner.Run(new Script()); 15 | } 16 | 17 | // Fix UnauthorizedScriptingAPIAccessException 18 | public void DoNothing(PlanSetup plan) { } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Views/ProgressDialog.xaml: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/Views/ProgressDialog.xaml: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/View/UnderscoreConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace EsapiEssentials.PluginRunner 6 | { 7 | // This converter duplicates all underscores 8 | // because WPF doesn't display single underscores 9 | public class UnderscoreConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | if (value is string s) 14 | return s.Replace("_", "__"); 15 | return null; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | return null; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Views/UnderscoreConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace EsapiEssentials.Samples.Async 6 | { 7 | // This converter duplicates all underscores 8 | // because WPF doesn't display single underscores 9 | public class UnderscoreConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | if (value is string s) 14 | return s.Replace("_", "__"); 15 | return null; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | return null; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/Views/UnderscoreConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace EsapiEssentials.Samples.AsyncPlugin 6 | { 7 | // This converter duplicates all underscores 8 | // because WPF doesn't display single underscores 9 | public class UnderscoreConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | if (value is string s) 14 | return s.Replace("_", "__"); 15 | return null; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | return null; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/PlansAndPlanSumsConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Windows.Data; 6 | 7 | namespace EsapiEssentials.PluginRunner 8 | { 9 | public class PlansAndPlanSumsConverter : IValueConverter 10 | { 11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 12 | { 13 | if (value is IEnumerable planAndPlanSums) 14 | return string.Join(", ", planAndPlanSums.Select(p => p.Id)); 15 | return null; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | return null; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/Script.cs: -------------------------------------------------------------------------------- 1 | using EsapiEssentials.Plugin; 2 | using EsapiEssentials.Samples.AsyncPlugin; 3 | 4 | namespace VMS.TPS 5 | { 6 | public class Script : ScriptBase 7 | { 8 | public override void Run(PluginScriptContext context) 9 | { 10 | var esapiService = new EsapiService(context); 11 | 12 | using (var ui = new UiRunner()) 13 | { 14 | ui.Run(() => 15 | { 16 | var window = new MainWindow(); 17 | var dialogService = new DialogService(window); 18 | var viewModel = new MainViewModel(esapiService, dialogService); 19 | window.DataContext = viewModel; 20 | window.ShowDialog(); 21 | }); 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/EsapiEssentials.Samples.Async.csproj.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True 3 | True 4 | True 5 | True -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/EsapiEssentials.Samples.AsyncPlugin.csproj.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True 3 | True 4 | True 5 | True -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace EsapiEssentials.Samples.Async 4 | { 5 | public partial class App : Application 6 | { 7 | private EsapiService _esapiService; 8 | 9 | private void App_OnStartup(object sender, StartupEventArgs e) 10 | { 11 | _esapiService = new EsapiService(); 12 | var dialogService = new DialogService(this); 13 | var viewModel = new MainViewModel(_esapiService, dialogService); 14 | var window = new MainWindow(viewModel); 15 | window.Show(); 16 | } 17 | 18 | // The EsapiService must be disposed before exiting; 19 | // otherwise, an exception from ESAPI is thrown 20 | private void App_OnExit(object sender, ExitEventArgs e) 21 | { 22 | _esapiService.Dispose(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/EsapiEssentials/Standalone/Async/AsyncRunner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using System.Threading.Tasks.Schedulers; 5 | 6 | namespace EsapiEssentials.Standalone 7 | { 8 | internal class AsyncRunner : IDisposable 9 | { 10 | private readonly StaTaskScheduler _taskScheduler; 11 | 12 | public AsyncRunner() 13 | { 14 | _taskScheduler = new StaTaskScheduler(1); 15 | } 16 | 17 | public Task RunAsync(Action a) => Task.Factory.StartNew( 18 | a, CancellationToken.None, TaskCreationOptions.None, _taskScheduler); 19 | 20 | public Task RunAsync(Func f) => Task.Factory.StartNew( 21 | f, CancellationToken.None, TaskCreationOptions.None, _taskScheduler); 22 | 23 | public void Dispose() 24 | { 25 | _taskScheduler.Dispose(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Views/ProgressDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace EsapiEssentials.Samples.Async 4 | { 5 | public partial class ProgressDialog : Window 6 | { 7 | public ProgressDialog() 8 | { 9 | InitializeComponent(); 10 | ProgressBar.IsIndeterminate = true; 11 | } 12 | 13 | public string Message 14 | { 15 | get => MessageTextBlock.Text; 16 | set => MessageTextBlock.Text = value; 17 | } 18 | 19 | public int MaxProgress 20 | { 21 | get => (int)ProgressBar.Maximum; 22 | set 23 | { 24 | ProgressBar.Maximum = value; 25 | ProgressBar.IsIndeterminate = false; 26 | } 27 | } 28 | 29 | public void IncrementProgress() 30 | { 31 | ProgressBar.Value += 1; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/Views/ProgressDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace EsapiEssentials.Samples.AsyncPlugin 4 | { 5 | public partial class ProgressDialog : Window 6 | { 7 | public ProgressDialog() 8 | { 9 | InitializeComponent(); 10 | ProgressBar.IsIndeterminate = true; 11 | } 12 | 13 | public string Message 14 | { 15 | get => MessageTextBlock.Text; 16 | set => MessageTextBlock.Text = value; 17 | } 18 | 19 | public int MaxProgress 20 | { 21 | get => (int)ProgressBar.Maximum; 22 | set 23 | { 24 | ProgressBar.Maximum = value; 25 | ProgressBar.IsIndeterminate = false; 26 | } 27 | } 28 | 29 | public void IncrementProgress() 30 | { 31 | ProgressBar.Value += 1; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/EsapiEssentials.PluginRunner.csproj.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True 3 | True 4 | True 5 | True 6 | True -------------------------------------------------------------------------------- /src/EsapiEssentials/Extensions/PatientExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using VMS.TPS.Common.Model.API; 4 | 5 | namespace EsapiEssentials 6 | { 7 | /// 8 | /// Extension methods for the Patient class. 9 | /// 10 | public static class PatientExtensions 11 | { 12 | /// 13 | /// Gets every PlanningItem (PlanSetup and PlanSum) of the given Patient. 14 | /// 15 | /// The Patient. 16 | /// Every PlanningItem of the given Patient. 17 | public static IEnumerable GetPlanningItems(this Patient patient) 18 | { 19 | var plans = patient.Courses?.SelectMany(c => c.PlanSetups) ?? new List(); 20 | var planSums = patient.Courses?.SelectMany(c => c.PlanSums) ?? new List(); 21 | return plans.Concat(planSums); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/EsapiEssentials/Extensions/DoseValueExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EsapiEssentials.Core; 3 | using VMS.TPS.Common.Model.Types; 4 | 5 | namespace EsapiEssentials 6 | { 7 | /// 8 | /// Extension methods for the DoseValue struct. 9 | /// 10 | public static class DoseValueExtensions 11 | { 12 | /// 13 | /// Converts the given DoseValue instance to a Dose object. 14 | /// 15 | /// 16 | /// The Dose object that represents the given DoseValue. 17 | public static Dose ToDose(this DoseValue doseValue) 18 | { 19 | switch (doseValue.Unit) 20 | { 21 | case DoseValue.DoseUnit.Gy: return new Dose(doseValue.Dose, DoseUnit.Gy); 22 | case DoseValue.DoseUnit.cGy: return new Dose(doseValue.Dose, DoseUnit.CGy); 23 | default: 24 | throw new ArgumentException($"Dose unit {doseValue.Unit} is not supported."); 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Carlos Anderson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/Persistence/DataRepository.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using YamlDotNet.Serialization; 3 | 4 | namespace EsapiEssentials.PluginRunner 5 | { 6 | internal class DataRepository : IDataRepository 7 | { 8 | private readonly string _path; 9 | 10 | private readonly ISerializer _serializer; 11 | private readonly IDeserializer _deserializer; 12 | 13 | public DataRepository(string path) 14 | { 15 | _path = path; 16 | 17 | _serializer = new SerializerBuilder().Build(); 18 | _deserializer = new DeserializerBuilder().Build(); 19 | } 20 | 21 | public Data Load() 22 | { 23 | if (!File.Exists(_path)) 24 | return new Data(); 25 | 26 | var dataString = File.ReadAllText(_path); 27 | return _deserializer.Deserialize(dataString); 28 | } 29 | 30 | public void Save(Data data) 31 | { 32 | var dataString = _serializer.Serialize(data); 33 | File.WriteAllText(_path, dataString); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/EsapiEssentials/Plugin/PluginRunner/ScriptBase.cs: -------------------------------------------------------------------------------- 1 | using VMS.TPS.Common.Model.API; 2 | 3 | namespace EsapiEssentials.Plugin 4 | { 5 | /// 6 | /// Provides the Execute method that the PluginRunner needs to call. 7 | /// Any script that will use the PluginRunner should derive from this class. 8 | /// Derive from this class if you're going to create your own Window. 9 | /// 10 | public abstract class ScriptBase 11 | { 12 | /// 13 | /// The method that Eclipse calls when the plugin script is started from there. 14 | /// This method is called automatically, you should never need to deal with it. 15 | /// 16 | public void Execute(ScriptContext context) 17 | { 18 | Run(new PluginScriptContext(context)); 19 | } 20 | 21 | /// 22 | /// The method you need to implement for your script to do anything. 23 | /// 24 | /// A copy of the script context of the Eclipse session. 25 | public abstract void Run(PluginScriptContext context); 26 | } 27 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Esapi/DoseMetricCalculator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using VMS.TPS.Common.Model.API; 3 | using VMS.TPS.Common.Model.Types; 4 | 5 | namespace EsapiEssentials.Samples.Async 6 | { 7 | // This class works directly with ESAPI objects, but it will be wrapped by EsapiService, 8 | // which doesn't expose ESAPI objects in order to isolate the app from ESAPI 9 | public class DoseMetricCalculator 10 | { 11 | public double CalculateMean(PlanningItem planningItem, Structure structure) 12 | { 13 | try 14 | { 15 | var dvhResult = planningItem.GetDVHCumulativeData( 16 | structure, DoseValuePresentation.Absolute, VolumePresentation.AbsoluteCm3, 0.001); 17 | return dvhResult.MeanDose.Dose; 18 | } 19 | catch (Exception e) 20 | { 21 | // There are many reasons the DVH calculation could fail, 22 | // so wrap any exception in a general exception 23 | throw new InvalidOperationException("Unable to calculate the mean dose.", e); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/Esapi/DoseMetricCalculator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using VMS.TPS.Common.Model.API; 3 | using VMS.TPS.Common.Model.Types; 4 | 5 | namespace EsapiEssentials.Samples.AsyncPlugin 6 | { 7 | // This class works directly with ESAPI objects, but it will be wrapped by EsapiService, 8 | // which doesn't expose ESAPI objects in order to isolate the script from ESAPI 9 | public class DoseMetricCalculator 10 | { 11 | public double CalculateMean(PlanningItem planningItem, Structure structure) 12 | { 13 | try 14 | { 15 | var dvhResult = planningItem.GetDVHCumulativeData( 16 | structure, DoseValuePresentation.Absolute, VolumePresentation.AbsoluteCm3, 0.001); 17 | return dvhResult?.MeanDose.Dose ?? double.NaN; 18 | } 19 | catch (Exception e) 20 | { 21 | // There are many reasons the DVH calculation could fail, 22 | // so wrap any exception in a general exception 23 | throw new InvalidOperationException("Unable to calculate the mean dose.", e); 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Esapi/IEsapiService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace EsapiEssentials.Samples.Async 4 | { 5 | // Interface to ESAPI functionality while not exposing ESAPI objects. 6 | // This allows the interface to be passed to other projects 7 | // without requiring those objects to depend on ESAPI. 8 | // Also, this interface allows for mocking in unit testing. 9 | // Finally, all the methods are asynchronous because the implementation 10 | // uses a separate thread to run ESAPI methods. 11 | // This prevents slow ESAPI methods from blocking the GUI thread. 12 | public interface IEsapiService 13 | { 14 | Task LogInAsync(); 15 | #if ESAPI_13 16 | Task LogInAsync(string userId, string password); 17 | #endif 18 | 19 | Task OpenPatientAsync(string patientId); 20 | Task ClosePatientAsync(); 21 | 22 | Task SearchAsync(string searchText); 23 | 24 | Task GetPlansAsync(); 25 | Task GetStructureIdsAsync(string courseId, string planId); 26 | 27 | Task CalculateMeanDoseAsync(string courseId, string planId, string structureId); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EsapiEssentials.Samples.Async.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EsapiEssentials.Samples.StandaloneApp.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/EsapiEssentials/Extensions/StructureExtensions.cs: -------------------------------------------------------------------------------- 1 | using VMS.TPS.Common.Model.API; 2 | 3 | namespace EsapiEssentials 4 | { 5 | /// 6 | /// Extension methods for the Structure class. 7 | /// 8 | public static class StructureExtensions 9 | { 10 | /// 11 | /// Determines whether the given Structure is a target (DICOM type: GTV, CTV, or PTV). 12 | /// 13 | /// The Structure to determine whether it is a target. 14 | /// true, if the given Structure is a target; false, otherwise. 15 | public static bool IsTarget(this Structure structure) => 16 | structure.DicomType == "GTV" || structure.DicomType == "CTV" || structure.DicomType == "PTV"; 17 | 18 | /// 19 | /// Determines whether the given Structure is an organ (DICOM type: ORGAN). 20 | /// 21 | /// The Structure to determine whether it is an organ. 22 | /// true, if the given Structure is an organ; false, otherwise. 23 | public static bool IsOrgan(this Structure structure) => 24 | structure.DicomType == "ORGAN"; 25 | } 26 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin.Runner/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EsapiEssentials.Samples.AsyncPlugin.Runner.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript.Runner/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EsapiEssentials.Samples.PluginScript.Runner.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/EsapiEssentials/Plugin/PluginRunner/ScriptBaseWithWindow.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using VMS.TPS.Common.Model.API; 3 | 4 | namespace EsapiEssentials.Plugin 5 | { 6 | /// 7 | /// Provides the Execute method that the PluginRunner needs to call. 8 | /// Any script that will use the PluginRunner should derive from this class. 9 | /// Derive from this class if you want to use the Window that Eclipse provides. 10 | /// 11 | public abstract class ScriptBaseWithWindow 12 | { 13 | /// 14 | /// The method that Eclipse calls when the plugin script is started from there. 15 | /// This method is called automatically, you should never need to deal with it. 16 | /// 17 | public void Execute(ScriptContext context, Window window) 18 | { 19 | Execute(new PluginScriptContext(context), window); 20 | } 21 | 22 | /// 23 | /// The method you need to implement for your script to do anything. 24 | /// 25 | /// A copy of the script context of the Eclipse session. 26 | /// The Window for your script that Eclipse will display. 27 | public abstract void Execute(PluginScriptContext context, Window window); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/EsapiEssentials/Plugin/Async/EsapiServiceBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace EsapiEssentials.Plugin 5 | { 6 | public abstract class EsapiServiceBase 7 | { 8 | private readonly TContext _context; 9 | private readonly AsyncRunner _runner; 10 | 11 | protected EsapiServiceBase(TContext context) 12 | { 13 | _context = context; 14 | _runner = new AsyncRunner(); 15 | } 16 | 17 | /// 18 | /// Runs the given Action on the ESAPI thread. 19 | /// 20 | /// The Action to run. 21 | /// A Task to perform this action. 22 | protected Task RunAsync(Action a) => 23 | RunAsync(() => a(_context)); 24 | 25 | /// 26 | /// Runs the given Func on the ESAPI thread. 27 | /// 28 | /// The type of the returned object. 29 | /// The Func to run. 30 | /// A Task to perform this action. 31 | protected Task RunAsync(Func f) => 32 | RunAsync(() => f(_context)); 33 | 34 | protected Task RunAsync(Action a) => 35 | _runner.RunAsync(a); 36 | 37 | protected Task RunAsync(Func f) => 38 | _runner.RunAsync(f); 39 | } 40 | } -------------------------------------------------------------------------------- /tests/EsapiEssentials.UnitTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("EsapiEssentials.UnitTests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("EsapiEssentials.UnitTests")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("46821c78-494d-4bd4-8ba1-cc3b430c24f0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("EsapiEssentials.Samples.AsyncPlugin")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("EsapiEssentials.Samples.AsyncPlugin")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("96e0ce2e-799b-473d-bf00-15ddc693a421")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/ViewModel/PlanOrSumViewModel.cs: -------------------------------------------------------------------------------- 1 | using GalaSoft.MvvmLight; 2 | 3 | namespace EsapiEssentials.PluginRunner 4 | { 5 | internal class PlanOrPlanSumViewModel : ViewModelBase 6 | { 7 | private PlanType _type; 8 | public PlanType Type 9 | { 10 | get => _type; 11 | set 12 | { 13 | if (Set(ref _type, value)) 14 | RaisePropertyChanged(nameof(CanBeActive)); 15 | } 16 | } 17 | 18 | private string _id; 19 | public string Id 20 | { 21 | get => _id; 22 | set => Set(ref _id, value); 23 | } 24 | 25 | private string _courseId; 26 | public string CourseId 27 | { 28 | get => _courseId; 29 | set => Set(ref _courseId, value); 30 | } 31 | 32 | private bool _isInScope; 33 | public bool IsInScope 34 | { 35 | get => _isInScope; 36 | set 37 | { 38 | if (Set(ref _isInScope, value)) 39 | { 40 | if (!IsInScope) 41 | IsActive = false; 42 | RaisePropertyChanged(nameof(CanBeActive)); 43 | } 44 | } 45 | } 46 | 47 | private bool _isActive; 48 | public bool IsActive 49 | { 50 | get => _isActive; 51 | set => Set(ref _isActive, value); 52 | } 53 | 54 | public bool CanBeActive => 55 | Type == PlanType.Plan && IsInScope; 56 | } 57 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("EsapiEssentials.Samples.PluginScript")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("EsapiEssentials.Samples.PluginScript")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("feb1e304-ccc9-4b61-acd2-fe76de6e1125")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/Application/PlanOrPlanSum.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace EsapiEssentials.PluginRunner 4 | { 5 | internal class PlanOrPlanSum : IEquatable 6 | { 7 | public PlanType Type { get; set; } 8 | public string Id { get; set; } 9 | public string CourseId { get; set; } 10 | 11 | public bool Equals(PlanOrPlanSum other) 12 | { 13 | if (ReferenceEquals(null, other)) return false; 14 | if (ReferenceEquals(this, other)) return true; 15 | return Type == other.Type && string.Equals(Id, other.Id) && string.Equals(CourseId, other.CourseId); 16 | } 17 | 18 | public override bool Equals(object obj) 19 | { 20 | if (ReferenceEquals(null, obj)) return false; 21 | if (ReferenceEquals(this, obj)) return true; 22 | if (obj.GetType() != this.GetType()) return false; 23 | return Equals((PlanOrPlanSum)obj); 24 | } 25 | 26 | public override int GetHashCode() 27 | { 28 | unchecked 29 | { 30 | var hashCode = (int)Type; 31 | hashCode = (hashCode * 397) ^ (Id != null ? Id.GetHashCode() : 0); 32 | hashCode = (hashCode * 397) ^ (CourseId != null ? CourseId.GetHashCode() : 0); 33 | return hashCode; 34 | } 35 | } 36 | 37 | public static bool operator ==(PlanOrPlanSum p1, PlanOrPlanSum p2) => 38 | Equals(p1, p2); 39 | 40 | public static bool operator !=(PlanOrPlanSum p1, PlanOrPlanSum p2) => 41 | !(p1 == p2); 42 | } 43 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp.Runner/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("EsapiEssentials.Samples.StandaloneApp.Runner")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("EsapiEssentials.Samples.StandaloneApp.Runner")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b6bd150a-2a22-4d28-9152-d6e02e97b218")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("EsapiEssentials.PluginRunner")] 9 | [assembly: AssemblyDescription("Plugin runner for EsapiEssentials (ESAPI 15.6)")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Carlos Anderson")] 12 | [assembly: AssemblyProduct("EsapiEssentials.PluginRunner")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e575892d-81d0-4a2f-9fb1-495d3f404502")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("2.0.0.0")] 36 | [assembly: AssemblyFileVersion("2.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/EsapiEssentials/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("EsapiEssentials")] 9 | [assembly: AssemblyDescription("Essential tools for working with ESAPI 15.6")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Carlos Anderson")] 12 | [assembly: AssemblyProduct("EsapiEssentials")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("fdc15e5d-0179-42cf-b352-48b74b234454")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("2.0.0.0")] 36 | [assembly: AssemblyFileVersion("2.0.0.0")] 37 | 38 | [assembly: InternalsVisibleTo("EsapiEssentials.UnitTests")] 39 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/DialogService/DialogService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace EsapiEssentials.Samples.Async 5 | { 6 | public class DialogService : IDialogService 7 | { 8 | private readonly App _app; 9 | 10 | public DialogService(App app) 11 | { 12 | _app = app; 13 | } 14 | 15 | public void ShowProgressDialog(string message, Func workAsync) 16 | { 17 | CreateProgressDialog(message, workAsync).ShowDialog(); 18 | } 19 | 20 | public void ShowProgressDialog(string message, int maximum, Func workAsync) 21 | { 22 | CreateProgressDialog(message, maximum, workAsync).ShowDialog(); 23 | } 24 | 25 | private ProgressDialog CreateProgressDialog(string message, Func workAsync) 26 | { 27 | var progressDialog = new ProgressDialog(); 28 | progressDialog.Owner = _app.MainWindow; 29 | progressDialog.Message = message; 30 | progressDialog.Loaded += async (sender, args) => 31 | { 32 | var progress = new SimpleProgress(() => progressDialog.IncrementProgress()); 33 | await workAsync(progress); 34 | progressDialog.Close(); 35 | }; 36 | return progressDialog; 37 | } 38 | 39 | private ProgressDialog CreateProgressDialog(string message, int maximum, Func workAsync) 40 | { 41 | var progressDialog = CreateProgressDialog(message, workAsync); 42 | progressDialog.MaxProgress = maximum; 43 | return progressDialog; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/EsapiEssentials/Plugin/Async/UiRunner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | using System.Threading.Tasks.Schedulers; 5 | using System.Windows.Threading; 6 | 7 | namespace EsapiEssentials.Plugin 8 | { 9 | public class UiRunner : IDisposable 10 | { 11 | private readonly DispatcherFrame _frame = new DispatcherFrame(); 12 | private readonly StaTaskScheduler _scheduler = new StaTaskScheduler(1); 13 | 14 | /// 15 | /// Runs the given Action on a new UI thread. 16 | /// 17 | /// The Action to run, passing a DispatcherWorker, 18 | /// which allows the Action to run code on the calling thread. 19 | public void Run(Action a) 20 | { 21 | Task.Factory.StartNew(() => 22 | { 23 | a(); 24 | _frame.Continue = false; 25 | }, CancellationToken.None, TaskCreationOptions.None, _scheduler); 26 | 27 | Dispatcher.PushFrame(_frame); 28 | } 29 | 30 | /// 31 | /// Runs the given Func on a new UI thread. 32 | /// 33 | /// The Func to run, passing a DispatcherWorker, 34 | /// which allows the Func to run code on the calling thread. 35 | public void Run(Func f) 36 | { 37 | Task.Factory.StartNew(async () => 38 | { 39 | await f(); 40 | _frame.Continue = false; 41 | }, CancellationToken.None, TaskCreationOptions.None, _scheduler); 42 | 43 | Dispatcher.PushFrame(_frame); 44 | } 45 | 46 | public void Dispose() 47 | { 48 | _scheduler?.Dispose(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/DialogService/DialogService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace EsapiEssentials.Samples.AsyncPlugin 5 | { 6 | public class DialogService : IDialogService 7 | { 8 | private readonly MainWindow _mainWindow; 9 | 10 | public DialogService(MainWindow mainWindow) 11 | { 12 | _mainWindow = mainWindow; 13 | } 14 | 15 | public void ShowProgressDialog(string message, Func workAsync) 16 | { 17 | CreateProgressDialog(message, workAsync).ShowDialog(); 18 | } 19 | 20 | public void ShowProgressDialog(string message, int maximum, Func workAsync) 21 | { 22 | CreateProgressDialog(message, maximum, workAsync).ShowDialog(); 23 | } 24 | 25 | private ProgressDialog CreateProgressDialog(string message, Func workAsync) 26 | { 27 | var progressDialog = new ProgressDialog(); 28 | progressDialog.Owner = _mainWindow; 29 | progressDialog.Message = message; 30 | progressDialog.Loaded += async (sender, args) => 31 | { 32 | var progress = new SimpleProgress(() => progressDialog.IncrementProgress()); 33 | await workAsync(progress); 34 | progressDialog.Close(); 35 | }; 36 | return progressDialog; 37 | } 38 | 39 | private ProgressDialog CreateProgressDialog(string message, int maximum, Func workAsync) 40 | { 41 | var progressDialog = CreateProgressDialog(message, workAsync); 42 | progressDialog.MaxProgress = maximum; 43 | return progressDialog; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/EsapiEssentials/Plugin/Settings/AssemblySettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using System.Reflection; 4 | 5 | namespace EsapiEssentials.Plugin 6 | { 7 | /// 8 | /// Provides read-only access to an assembly's settings. 9 | /// The settings must be in the assembly's App.config file, 10 | /// in a section called appSettings (see the Microsoft documentation). 11 | /// 12 | public class AssemblySettings 13 | { 14 | private readonly Assembly _assembly; 15 | 16 | /// 17 | /// Instantiates a new instance of the AssemblySettings class. 18 | /// 19 | /// The assembly that has the settings. 20 | public AssemblySettings(Assembly assembly) 21 | { 22 | _assembly = assembly; 23 | } 24 | 25 | /// 26 | /// Gets the value of the setting with the given key (i.e., name). 27 | /// 28 | /// The name of the setting. 29 | /// The value of the setting. 30 | /// 31 | /// An exception occured while trying to obtain the setting. 32 | /// 33 | public string GetSetting(string key) 34 | { 35 | try 36 | { 37 | var asmPath = _assembly.Location; 38 | var config = ConfigurationManager.OpenExeConfiguration(asmPath); 39 | var setting = config.AppSettings.Settings[key]; 40 | return setting.Value; 41 | } 42 | catch (Exception e) 43 | { 44 | throw new InvalidOperationException("Unable to read the configuration setting.", e); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/EsapiEssentials/Extensions/PlanningItemExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using VMS.TPS.Common.Model.API; 3 | 4 | namespace EsapiEssentials 5 | { 6 | /// 7 | /// Extension methods for the PlanningItem class. 8 | /// 9 | public static class PlanningItemExtensions 10 | { 11 | /// 12 | /// Gets the parent Course of the given PlanningItem. 13 | /// 14 | /// The PlanningItem whose Course will be obtained. 15 | /// The parent Course of the given PlanningItem. 16 | public static Course GetCourse(this PlanningItem planningItem) 17 | { 18 | if (planningItem is PlanSetup plan) 19 | return plan.Course; 20 | 21 | if (planningItem is PlanSum planSum) 22 | return planSum.Course; 23 | 24 | throw new ArgumentException(GetUnknownSubclassMessage(planningItem)); 25 | } 26 | 27 | /// 28 | /// Gets the StructureSet of the given PlanningItem. 29 | /// 30 | /// The PlanningItem whose StructureSet will be obtained. 31 | /// The StructureSet of the given PlanningItem. 32 | public static StructureSet GetStructureSet(this PlanningItem planningItem) 33 | { 34 | if (planningItem is PlanSetup plan) 35 | return plan.StructureSet; 36 | 37 | if (planningItem is PlanSum planSum) 38 | return planSum.StructureSet; 39 | 40 | throw new ArgumentException(GetUnknownSubclassMessage(planningItem)); 41 | } 42 | 43 | private static string GetUnknownSubclassMessage(PlanningItem planningItem) => 44 | $"{planningItem.GetType()} is not a known subclass of {nameof(PlanningItem)}."; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/Persistence/RecentEntry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace EsapiEssentials.PluginRunner 6 | { 7 | internal class RecentEntry : IEquatable 8 | { 9 | public string PatientId { get; set; } 10 | public List PlansAndPlanSumsInScope { get; set; } 11 | public PlanOrPlanSum ActivePlan { get; set; } 12 | 13 | public bool Equals(RecentEntry other) 14 | { 15 | if (ReferenceEquals(null, other)) return false; 16 | if (ReferenceEquals(this, other)) return true; 17 | return string.Equals(PatientId, other.PatientId) && 18 | Enumerable.SequenceEqual(PlansAndPlanSumsInScope, other.PlansAndPlanSumsInScope) && 19 | Equals(ActivePlan, other.ActivePlan); 20 | } 21 | 22 | public override bool Equals(object obj) 23 | { 24 | if (ReferenceEquals(null, obj)) return false; 25 | if (ReferenceEquals(this, obj)) return true; 26 | if (obj.GetType() != this.GetType()) return false; 27 | return Equals((RecentEntry)obj); 28 | } 29 | 30 | public override int GetHashCode() 31 | { 32 | unchecked 33 | { 34 | var hashCode = (PatientId != null ? PatientId.GetHashCode() : 0); 35 | hashCode = (hashCode * 397) ^ (PlansAndPlanSumsInScope != null ? PlansAndPlanSumsInScope.GetHashCode() : 0); 36 | hashCode = (hashCode * 397) ^ (ActivePlan != null ? ActivePlan.GetHashCode() : 0); 37 | return hashCode; 38 | } 39 | } 40 | 41 | public static bool operator ==(RecentEntry r1, RecentEntry r2) => 42 | Equals(r1, r2); 43 | 44 | public static bool operator !=(RecentEntry r1, RecentEntry r2) => 45 | !(r1 == r2); 46 | } 47 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript/Script.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using System.Windows; 5 | using EsapiEssentials.Plugin; 6 | using VMS.TPS.Common.Model.Types; 7 | 8 | namespace VMS.TPS 9 | { 10 | // This script demonstrates deriving from ScriptBase in order to use the PluginRunner, 11 | // which needs to be referenced from a separate WPF project. 12 | 13 | // This script also demonstrates using AssemblySettings in order to obtain 14 | // the desired structure ID from the App.config file. 15 | // This file is not automatically created in a class library project, 16 | // so it must be added manually to the project (via Add New Item). 17 | public class Script : ScriptBase 18 | { 19 | public override void Run(PluginScriptContext context) 20 | { 21 | // Define the desired structure ID 22 | var structureId = GetStructureIdFromSettings(); 23 | 24 | // Find the structure in the current structure set 25 | var structure = context?.StructureSet?.Structures?.FirstOrDefault(x => x.Id == structureId); 26 | 27 | if (structure == null) 28 | throw new InvalidOperationException("Unable to find the structure."); 29 | 30 | // Calculate D2cc[Gy] 31 | var d2cc = context?.PlanSetup?.GetDoseAtVolume(structure, 2, VolumePresentation.AbsoluteCm3, DoseValuePresentation.Absolute); 32 | 33 | if (d2cc == null) 34 | throw new InvalidOperationException("Unable to calculate the dose metric."); 35 | 36 | // Show the result 37 | MessageBox.Show($"{structureId} D2cc[Gy] = {d2cc}"); 38 | } 39 | 40 | private string GetStructureIdFromSettings() 41 | { 42 | var settings = new AssemblySettings(Assembly.GetExecutingAssembly()); 43 | return settings.GetSetting("StructureId"); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/ScriptRunner.cs: -------------------------------------------------------------------------------- 1 | using EsapiEssentials.Plugin; 2 | 3 | namespace EsapiEssentials.PluginRunner 4 | { 5 | /// 6 | /// Provides the functionality to start the PluginRunner and run your script. 7 | /// 8 | public static class ScriptRunner 9 | { 10 | #if ESAPI_13 11 | /// 12 | /// Runs the plugin runner for the given script (accepts a Window). 13 | /// 14 | /// The script to run. This script accepts the Window provided by Eclipse. 15 | /// The optional user ID to log in to Eclipse. 16 | /// The optional user password to log in to Eclipse. 17 | public static void Run(ScriptBaseWithWindow script, string userId = null, string password = null) => 18 | RunWith(new PluginRunner(script, userId, password)); 19 | #elif ESAPI_15 20 | public static void Run(ScriptBaseWithWindow script) => 21 | RunWith(new PluginRunner(script)); 22 | #endif 23 | 24 | #if ESAPI_13 25 | /// 26 | /// Runs the plugin runner for the given script (does not accept a Window). 27 | /// 28 | /// The script to run. This script does not use an Eclipse-provided Window. 29 | /// The optional user ID to log in to Eclipse. 30 | /// The optional user password to log in to Eclipse. 31 | public static void Run(ScriptBase script, string userId = null, string password = null) => 32 | RunWith(new PluginRunner(script, userId, password)); 33 | #elif ESAPI_15 34 | public static void Run(ScriptBase script) => 35 | RunWith(new PluginRunner(script)); 36 | #endif 37 | 38 | private static void RunWith(PluginRunner runner) 39 | { 40 | var vm = new MainViewModel(runner); 41 | var window = new MainWindow(vm); 42 | window.Closed += (o, e) => runner.Dispose(); 43 | window.Show(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/EsapiEssentials/Plugin/PluginRunner/PluginScriptContext.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using VMS.TPS.Common.Model.API; 3 | 4 | namespace EsapiEssentials.Plugin 5 | { 6 | /// 7 | /// Duplicates all the properties from the ESAPI ScriptContext class, 8 | /// so that they can be accessed from a plugin script using the PluginScriptRunner. 9 | /// 10 | public class PluginScriptContext 11 | { 12 | public PluginScriptContext() { } 13 | 14 | public PluginScriptContext(ScriptContext context) 15 | { 16 | CurrentUser = context.CurrentUser; 17 | Course = context.Course; 18 | Image = context.Image; 19 | StructureSet = context.StructureSet; 20 | Patient = context.Patient; 21 | PlanSetup = context.PlanSetup; 22 | ExternalPlanSetup = context.ExternalPlanSetup; 23 | BrachyPlanSetup = context.BrachyPlanSetup; 24 | PlansInScope = context.PlansInScope; 25 | ExternalPlansInScope = context.ExternalPlansInScope; 26 | BrachyPlansInScope = context.BrachyPlansInScope; 27 | PlanSumsInScope = context.PlanSumsInScope; 28 | ApplicationName = context.ApplicationName; 29 | VersionInfo = context.VersionInfo; 30 | } 31 | 32 | public User CurrentUser { get; set; } 33 | public Course Course { get; set; } 34 | public Image Image { get; set; } 35 | public StructureSet StructureSet { get; set; } 36 | public Patient Patient { get; set; } 37 | public PlanSetup PlanSetup { get; set; } 38 | public ExternalPlanSetup ExternalPlanSetup { get; set; } 39 | public BrachyPlanSetup BrachyPlanSetup { get; set; } 40 | public IEnumerable PlansInScope { get; set; } 41 | public IEnumerable ExternalPlansInScope { get; set; } 42 | public IEnumerable BrachyPlansInScope { get; set; } 43 | public IEnumerable PlanSumsInScope { get; set; } 44 | public string ApplicationName { get; set; } 45 | public string VersionInfo { get; set; } 46 | } 47 | } -------------------------------------------------------------------------------- /tests/EsapiEssentials.UnitTests/PatientSearch/PatientSummarySearchTests.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using EsapiEssentials.Standalone; 3 | using NUnit.Framework; 4 | 5 | namespace EsapiEssentials.UnitTests 6 | { 7 | [TestFixture] 8 | public class PatientSummarySearchTests 9 | { 10 | private SearchPatient[] _patients; 11 | 12 | [SetUp] 13 | public void SetUp() 14 | { 15 | _patients = new[] 16 | { 17 | new SearchPatient {Id = "001", FirstName = "Yvonne", LastName = "McCarthy"}, 18 | new SearchPatient {Id = "002", FirstName = "Marlene", LastName = "Lyons"}, 19 | new SearchPatient {Id = "003", FirstName = "Carl", LastName = "Butler"}, 20 | new SearchPatient {Id = "004", FirstName = "Lamar", LastName = "Nguyen"}, 21 | new SearchPatient {Id = "005", FirstName = "Terence", LastName = "Hampton"}, 22 | new SearchPatient {Id = "006", FirstName = "Mike", LastName = "Massey"}, 23 | new SearchPatient {Id = "007", FirstName = "Hernietta", LastName = "Reid"}, 24 | new SearchPatient {Id = "008", FirstName = "Carol", LastName = "Dawson"}, 25 | new SearchPatient {Id = "009", FirstName = "Katie", LastName = "Wagner"}, 26 | new SearchPatient {Id = "010", FirstName = "Kelley", LastName = "Houston"}, 27 | }; 28 | } 29 | 30 | [TestCase("", new string[0])] 31 | [TestCase(" ", new string[0])] 32 | [TestCase("car", new[] {"003", "008"})] 33 | [TestCase("mike", new[] {"006"})] 34 | [TestCase("robert", new string[0])] 35 | [TestCase("ngu lam", new[] {"004"})] 36 | [TestCase("ngu lam", new[] {"004"})] 37 | [TestCase("dawson,c", new[] {"008"})] 38 | public void SearchTest(string searchText, string[] resultIds) 39 | { 40 | var search = new PatientSearch(_patients, 10); 41 | 42 | var results = search.FindMatches(searchText).ToArray(); 43 | 44 | Assert.That(results.Select(x => x.Id).ToArray(), Is.EqualTo(resultIds)); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/EsapiEssentials/Standalone/StandaloneRunner/StandaloneRunner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | using VMS.TPS.Common.Model.API; 7 | 8 | namespace EsapiEssentials.Standalone 9 | { 10 | /// 11 | /// Allows a binary plugin script to run a standalone application, 12 | /// while preserving the script context (sent via command-line arguments). 13 | /// The plugin script assembly must be in the same directory as the 14 | /// standalone application. One way to do that is to reference 15 | /// the script project from the standalone application project. 16 | /// 17 | public class StandaloneRunner 18 | { 19 | /// 20 | /// Run the standalone application with the given script context. 21 | /// 22 | /// The script context from the plugin script. 23 | /// 24 | /// An exception occurred while trying to run the standalone application. 25 | /// Perhaps the application was not found or an error occurred while 26 | /// building the command-line arguments from the script context. 27 | /// 28 | public static void RunWith(ScriptContext context) 29 | { 30 | try 31 | { 32 | var contextArgs = ScriptContextArgs.From(context); 33 | Process.Start(GetStandalonePath(), contextArgs.ToArgs()); 34 | } 35 | catch (Exception) 36 | { 37 | throw new StandaloneRunnerException("Unable to launch the application."); 38 | } 39 | } 40 | 41 | private static string GetStandalonePath() => 42 | FirstExeIn(DirectoryOf(Assembly())); 43 | 44 | private static string FirstExeIn(string dir) => 45 | Directory.GetFiles(dir, "*.exe").First(); 46 | 47 | private static string DirectoryOf(Assembly asm) => 48 | Path.GetDirectoryName(asm.Location); 49 | 50 | private static Assembly Assembly() => 51 | System.Reflection.Assembly.GetExecutingAssembly(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/Esapi/EsapiService.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using EsapiEssentials.Plugin; 4 | using VMS.TPS.Common.Model.API; 5 | 6 | namespace EsapiEssentials.Samples.AsyncPlugin 7 | { 8 | public class EsapiService : EsapiServiceBase, IEsapiService 9 | { 10 | private readonly DoseMetricCalculator _metricCalc; 11 | 12 | public EsapiService(PluginScriptContext context) : base(context) 13 | { 14 | _metricCalc = new DoseMetricCalculator(); 15 | } 16 | 17 | public Task GetPlansAsync() => 18 | RunAsync(context => context.Patient.Courses? 19 | .SelectMany(x => x.PlanSetups) 20 | .Select(x => new Plan 21 | { 22 | PlanId = x.Id, 23 | CourseId = x.Course?.Id 24 | }) 25 | .ToArray()); 26 | 27 | public Task GetStructureIdsAsync(string courseId, string planId) => 28 | RunAsync(context => 29 | { 30 | var plan = GetPlan(context.Patient, courseId, planId); 31 | return plan?.StructureSet?.Structures?.Select(x => x.Id).ToArray() ?? new string[0]; 32 | }); 33 | 34 | public Task CalculateMeanDoseAsync(string courseId, string planId, string structureId) => 35 | RunAsync(context => CalculateMeanDose(context.Patient, courseId, planId, structureId)); 36 | 37 | private double CalculateMeanDose(Patient patient, string courseId, string planId, string structureId) 38 | { 39 | var plan = GetPlan(patient, courseId, planId); 40 | var structure = GetStructure(plan, structureId); 41 | return _metricCalc.CalculateMean(plan, structure); 42 | } 43 | 44 | private PlanSetup GetPlan(Patient patient, string courseId, string planId) => 45 | GetCourse(patient, courseId)?.PlanSetups?.FirstOrDefault(x => x.Id == planId); 46 | 47 | private Course GetCourse(Patient patient, string courseId) => 48 | patient?.Courses?.FirstOrDefault(x => x.Id == courseId); 49 | 50 | private Structure GetStructure(PlanSetup plan, string structureId) => 51 | plan?.StructureSet?.Structures?.FirstOrDefault(x => x.Id == structureId); 52 | } 53 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | using System.Windows; 5 | using EsapiEssentials.Standalone; 6 | using Application = VMS.TPS.Common.Model.API.Application; 7 | 8 | namespace EsapiEssentials.Samples.StandaloneRunner.App 9 | { 10 | public partial class MainWindow : Window 11 | { 12 | private Application _app; 13 | private StandaloneScriptContext _scriptContext; 14 | 15 | public MainWindow() 16 | { 17 | InitializeComponent(); 18 | InitializeEsapi(); 19 | InitializeControls(); 20 | } 21 | 22 | private void InitializeEsapi() 23 | { 24 | // The ESAPI Application object must be created before the PluginScriptContext 25 | #if ESAPI_13 26 | _app = Application.CreateApplication(null, null); 27 | #elif ESAPI_15 28 | _app = Application.CreateApplication(); 29 | #endif 30 | 31 | // The PluginScriptContext requires the command-line arguments and the Application object 32 | // (if there are no command-line arguments, the return is null) 33 | _scriptContext = StandaloneScriptContext.From(Environment.GetCommandLineArgs(), _app); 34 | } 35 | 36 | private void InitializeControls() 37 | { 38 | // Display some information from the created PluginScriptContext object (if not null) 39 | // (for simplicity, we're not using data-binding but directly accessing the controls) 40 | PatientTextBlock.Text = $"Patient: {_scriptContext?.Patient?.LastName}, {_scriptContext?.Patient?.FirstName}"; 41 | CourseTextBlock.Text = $"Course: {_scriptContext?.Course?.Id}"; 42 | PlanTextBlock.Text = $"Plan: {_scriptContext?.PlanSetup?.Id}"; 43 | PlanSumsInScopeTextBlock.Text = $"Plan sums in scope: {GetFormattedPlanSumIds()}"; 44 | } 45 | 46 | private string GetFormattedPlanSumIds() => 47 | string.Join(", ", _scriptContext?.PlanSumsInScope?.Select(x => x.Id) ?? new string[0]); 48 | 49 | private void MainWindow_OnClosing(object sender, CancelEventArgs e) 50 | { 51 | // Always dispose of the ESAPI Application object before exiting the program 52 | _app.Dispose(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/EsapiEssentials/EsapiEssentials.csproj.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | True 3 | True 4 | True 5 | True 6 | False 7 | True 8 | True 9 | True 10 | True 11 | True 12 | False 13 | True 14 | True 15 | True 16 | True -------------------------------------------------------------------------------- /src/EsapiEssentials/Standalone/PatientSearch/PatientSearch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace EsapiEssentials.Standalone 6 | { 7 | internal class PatientSearch 8 | { 9 | private readonly IEnumerable _patients; 10 | private readonly int _maxResults; 11 | 12 | public PatientSearch(IEnumerable patients, int maxResults) 13 | { 14 | _patients = patients; 15 | _maxResults = maxResults; 16 | } 17 | 18 | public IEnumerable FindMatches(string searchText) 19 | { 20 | if (string.IsNullOrWhiteSpace(searchText)) 21 | return Enumerable.Empty(); 22 | 23 | var searchTerms = GetSearchTerms(searchText); 24 | return _patients 25 | .Where(p => IsMatch(p, searchTerms)) 26 | .OrderByDescending(p => p.CreationDateTime) 27 | .Take(_maxResults); 28 | } 29 | 30 | private bool IsMatch(SearchPatient patient, string[] searchTerms) 31 | { 32 | switch (searchTerms.Length) 33 | { 34 | case 0: 35 | return false; 36 | case 1: 37 | return IsMatchWithOneSearchTerm(patient, searchTerms[0]); 38 | default: 39 | return IsMatchWithTwoSearchTerms(patient, searchTerms[0], searchTerms[1]); 40 | } 41 | } 42 | 43 | private string[] GetSearchTerms(string searchText) => 44 | searchText.Split(' ', ',').ToArray(); 45 | 46 | private bool IsMatchWithOneSearchTerm(SearchPatient patient, string term) => 47 | IsSubstring(term, patient.Id) || 48 | IsSubstring(term, patient.LastName) || 49 | IsSubstring(term, patient.FirstName); 50 | 51 | private bool IsMatchWithTwoSearchTerms(SearchPatient patient, string term1, string term2) => 52 | IsMatchWithLastThenFirstName(patient, term1, term2) || 53 | IsMatchWithLastThenFirstName(patient, term2, term1); 54 | 55 | private bool IsMatchWithLastThenFirstName(SearchPatient patient, string lastName, string firstName) => 56 | IsSubstring(lastName, patient.LastName) && IsSubstring(firstName, patient.FirstName); 57 | 58 | private bool IsSubstring(string small, string large) => 59 | large.StartsWith(small, StringComparison.OrdinalIgnoreCase); 60 | } 61 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("EsapiEssentials.Samples.Async")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("EsapiEssentials.Samples.Async")] 15 | [assembly: AssemblyCopyright("Copyright © 2019")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("EsapiEssentials.Samples.StandaloneApp")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("EsapiEssentials.Samples.StandaloneApp")] 15 | [assembly: AssemblyCopyright("Copyright © 2019")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin.Runner/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("EsapiEssentials.Samples.AsyncPlugin.Runner")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("EsapiEssentials.Samples.AsyncPlugin.Runner")] 15 | [assembly: AssemblyCopyright("Copyright © 2019")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript.Runner/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("EsapiEssentials.Samples.PluginScript.Runner")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("EsapiEssentials.Samples.PluginScript.Runner")] 15 | [assembly: AssemblyCopyright("Copyright © 2019")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/ViewModels/MainViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using System.Windows.Input; 3 | using GalaSoft.MvvmLight; 4 | using GalaSoft.MvvmLight.CommandWpf; 5 | 6 | namespace EsapiEssentials.Samples.AsyncPlugin 7 | { 8 | public class MainViewModel : ViewModelBase 9 | { 10 | private readonly IEsapiService _esapiService; 11 | private readonly IDialogService _dialogService; 12 | 13 | public MainViewModel(IEsapiService esapiService, IDialogService dialogService) 14 | { 15 | _esapiService = esapiService; 16 | _dialogService = dialogService; 17 | } 18 | 19 | private Plan[] _plans; 20 | public Plan[] Plans 21 | { 22 | get => _plans; 23 | set => Set(ref _plans, value); 24 | } 25 | 26 | private Plan _selectedPlan; 27 | public Plan SelectedPlan 28 | { 29 | get => _selectedPlan; 30 | set => Set(ref _selectedPlan, value); 31 | } 32 | 33 | private ObservableCollection _metricResults; 34 | public ObservableCollection MetricResults 35 | { 36 | get => _metricResults; 37 | set => Set(ref _metricResults, value); 38 | } 39 | 40 | public ICommand StartCommand => new RelayCommand(Start); 41 | 42 | private async void Start() 43 | { 44 | Plans = await _esapiService.GetPlansAsync(); 45 | } 46 | 47 | public ICommand AnalyzePlanCommand => new RelayCommand(AnalyzePlan); 48 | 49 | private async void AnalyzePlan() 50 | { 51 | var courseId = SelectedPlan?.CourseId; 52 | var planId = SelectedPlan?.PlanId; 53 | 54 | if (courseId == null || planId == null) 55 | return; 56 | 57 | var structureIds = await _esapiService.GetStructureIdsAsync(courseId, planId); 58 | 59 | _dialogService.ShowProgressDialog("Calculating dose metrics", structureIds.Length, 60 | async progress => 61 | { 62 | MetricResults = new ObservableCollection(); 63 | foreach (var structureId in structureIds) 64 | { 65 | double result; 66 | 67 | try 68 | { 69 | result = await _esapiService.CalculateMeanDoseAsync(courseId, planId, structureId); 70 | } 71 | catch 72 | { 73 | result = double.NaN; 74 | } 75 | 76 | MetricResults.Add(new MetricResult 77 | { 78 | StructureId = structureId, 79 | Result = result 80 | }); 81 | 82 | progress.Increment(); 83 | } 84 | }); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EsapiEssentials.Samples.Async.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EsapiEssentials.Samples.Async.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EsapiEssentials.Samples.StandaloneApp.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EsapiEssentials.Samples.StandaloneApp.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin.Runner/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EsapiEssentials.Samples.AsyncPlugin.Runner.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EsapiEssentials.Samples.AsyncPlugin.Runner.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript.Runner/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace EsapiEssentials.Samples.PluginScript.Runner.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("EsapiEssentials.Samples.PluginScript.Runner.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/EsapiEssentials/Standalone/PatientSearch/PatientSummarySearch.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using VMS.TPS.Common.Model.API; 4 | 5 | namespace EsapiEssentials.Standalone 6 | { 7 | public class PatientSummarySearch 8 | { 9 | private readonly IEnumerable _patients; 10 | private readonly PatientSearch _search; 11 | 12 | /// 13 | /// Initializes a new instance of the PatientSummarySearch class. 14 | /// 15 | /// The list of patients to search. 16 | /// The maximum number of results to return. 17 | public PatientSummarySearch(IEnumerable patients, int maxResults) 18 | { 19 | // Need to convert patients to an array, 20 | // or the IEnumerable will be iterated multiple times 21 | _patients = patients.ToArray(); 22 | 23 | // Adapt each PatientSummary to a SearchPatient object 24 | // to make PatientSearch testable without referencing ESAPI 25 | var searchPatients = CreateSearchPatients(); 26 | _search = new PatientSearch(searchPatients, maxResults); 27 | } 28 | 29 | /// 30 | /// Finds the patients that match the given search string. 31 | /// 32 | /// The search string. 33 | /// The patients that match the given search string. 34 | /// 35 | /// If the search string is a single word, a patient matches it 36 | /// if the patient's ID, first name, or last name start with it. 37 | /// If the search string contains two or more words, a patient matches it 38 | /// if the patient's first name or last name start with any of the first 39 | /// two words in the search string (the remaining words are ignored). 40 | /// The words in a search string may be separated by a space, a comma, or 41 | /// a semicolon. 42 | /// 43 | public IEnumerable FindMatches(string searchText) 44 | { 45 | // Need to convert matches to an array, 46 | // or the IEnumerable will be iterated multiple times 47 | var matches = _search.FindMatches(searchText); 48 | return GetPatientSummaries(matches.ToArray()); 49 | } 50 | 51 | private IEnumerable CreateSearchPatients() => 52 | _patients.Select(CreateSearchPatient); 53 | 54 | private SearchPatient CreateSearchPatient(PatientSummary patientSummary) => 55 | new SearchPatient 56 | { 57 | Id = patientSummary.Id, 58 | FirstName = patientSummary.FirstName, 59 | LastName = patientSummary.LastName, 60 | CreationDateTime = patientSummary.CreationDateTime 61 | }; 62 | 63 | private IEnumerable GetPatientSummaries(IEnumerable patients) => 64 | _patients.Where(ps => ContainsById(ps, patients)); 65 | 66 | private bool ContainsById(PatientSummary patientSummary, IEnumerable patients) => 67 | patients.FirstOrDefault(p => p.Id == patientSummary.Id) != null; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Esapi/EsapiService.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Threading.Tasks; 3 | using EsapiEssentials.Standalone; 4 | using VMS.TPS.Common.Model.API; 5 | 6 | namespace EsapiEssentials.Samples.Async 7 | { 8 | // Sample implementation of IEsapiService using EsapiServiceBase 9 | public class EsapiService : EsapiServiceBase, IEsapiService 10 | { 11 | private readonly DoseMetricCalculator _metricCalc; 12 | 13 | private PatientSummarySearch _search; 14 | 15 | public EsapiService() 16 | { 17 | _metricCalc = new DoseMetricCalculator(); 18 | } 19 | 20 | // Override the default LogInAsync functionality 21 | // so that the patients are obtained after logging in 22 | public override async Task LogInAsync() 23 | { 24 | await base.LogInAsync(); 25 | await InitializeSearchAsync(); 26 | } 27 | 28 | #if ESAPI_13 29 | public override async Task LogInAsync(string userId, string password) 30 | { 31 | await base.LogInAsync(userId, password); 32 | await InitializeSearchAsync(); 33 | } 34 | #endif 35 | 36 | // Use the RunAsync set of methods to run ESAPI-related actions on a separate thread 37 | public Task SearchAsync(string searchText) => 38 | RunAsync(() => _search.FindMatches(searchText) 39 | .Select(ps => new PatientMatch 40 | { 41 | Id = ps.Id, 42 | FirstName = ps.FirstName, 43 | LastName = ps.LastName 44 | }) 45 | .ToArray()); 46 | 47 | public Task GetPlansAsync() => 48 | RunAsync(patient => patient.Courses? 49 | .SelectMany(x => x.PlanSetups) 50 | .Select(x => new Plan 51 | { 52 | PlanId = x.Id, 53 | CourseId = x.Course?.Id 54 | }) 55 | .ToArray()); 56 | 57 | public Task GetStructureIdsAsync(string courseId, string planId) => 58 | RunAsync(patient => 59 | { 60 | var plan = GetPlan(patient, courseId, planId); 61 | return plan?.StructureSet?.Structures?.Select(x => x.Id).ToArray() ?? new string[0]; 62 | }); 63 | 64 | public Task CalculateMeanDoseAsync(string courseId, string planId, string structureId) => 65 | RunAsync(patient => CalculateMeanDose(patient, courseId, planId, structureId)); 66 | 67 | private Task InitializeSearchAsync() => 68 | RunAsync(app => _search = new PatientSummarySearch(app.PatientSummaries, 10)); 69 | 70 | private double CalculateMeanDose(Patient patient, string courseId, string planId, string structureId) 71 | { 72 | var plan = GetPlan(patient, courseId, planId); 73 | var structure = GetStructure(plan, structureId); 74 | return _metricCalc.CalculateMean(plan, structure); 75 | } 76 | 77 | private PlanSetup GetPlan(Patient patient, string courseId, string planId) => 78 | GetCourse(patient, courseId)?.PlanSetups?.FirstOrDefault(x => x.Id == planId); 79 | 80 | private Course GetCourse(Patient patient, string courseId) => 81 | patient?.Courses?.FirstOrDefault(x => x.Id == courseId); 82 | 83 | private Structure GetStructure(PlanSetup plan, string structureId) => 84 | plan?.StructureSet?.Structures?.FirstOrDefault(x => x.Id == structureId); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/EsapiEssentials/Standalone/StandaloneRunner/ScriptContextArgs.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using CommandLine; 4 | using VMS.TPS.Common.Model.API; 5 | 6 | namespace EsapiEssentials.Standalone 7 | { 8 | internal class ScriptContextArgs 9 | { 10 | [Option("user-id", Required = true)] 11 | public string CurrentUserId { get; set; } 12 | 13 | [Option("course-id")] 14 | public string CourseId { get; set; } 15 | 16 | // Used to find the exact image 17 | [Option("series-uid")] 18 | public string SeriesUid { get; set; } 19 | 20 | [Option("image-id")] 21 | public string ImageId { get; set; } 22 | 23 | [Option("structure-set-id")] 24 | public string StructureSetId { get; set; } 25 | 26 | [Option("patient-id")] 27 | public string PatientId { get; set; } 28 | 29 | [Option("plan-id")] 30 | public string PlanSetupId { get; set; } 31 | 32 | [Option("external-plan-id")] 33 | public string ExternalPlanSetupId { get; set; } 34 | 35 | [Option("brachy-plan-id")] 36 | public string BrachyPlanSetupId { get; set; } 37 | 38 | [Option("plans-in-scope-uids")] 39 | public IEnumerable PlansInScopeUids { get; set; } 40 | 41 | [Option("external-plans-in-scope-uids")] 42 | public IEnumerable ExternalPlansInScopeUids { get; set; } 43 | 44 | [Option("brachy-plans-in-scope-uids")] 45 | public IEnumerable BrachyPlansInScopeUids { get; set; } 46 | 47 | // Used to find the exact plan sums 48 | [Option("plan-sums-in-scope-course-ids")] 49 | public IEnumerable PlanSumsInScopeCourseIds { get; set; } 50 | 51 | [Option("plan-sums-in-scope-ids")] 52 | public IEnumerable PlanSumsInScopeIds { get; set; } 53 | 54 | [Option("app-name")] 55 | public string ApplicationName { get; set; } 56 | 57 | [Option("version")] 58 | public string VersionInfo { get; set; } 59 | 60 | public static ScriptContextArgs From(ScriptContext context) 61 | { 62 | return new ScriptContextArgs 63 | { 64 | CurrentUserId = context.CurrentUser?.Id, 65 | CourseId = context.Course?.Id, 66 | SeriesUid = context.Image?.Series?.UID, 67 | ImageId = context.Image?.Id, 68 | StructureSetId = context.StructureSet?.Id, 69 | PatientId = context.Patient?.Id, 70 | PlanSetupId = context.PlanSetup?.Id, 71 | ExternalPlanSetupId = context.ExternalPlanSetup?.Id, 72 | BrachyPlanSetupId = context.BrachyPlanSetup?.Id, 73 | PlansInScopeUids = context.PlansInScope?.Select(x => x.UID), 74 | ExternalPlansInScopeUids = context.ExternalPlansInScope?.Select(x => x.UID), 75 | BrachyPlansInScopeUids = context.BrachyPlansInScope?.Select(x => x.UID), 76 | PlanSumsInScopeCourseIds = context.PlanSumsInScope?.Select(x => x.Course?.Id), 77 | PlanSumsInScopeIds = context.PlanSumsInScope?.Select(x => x.Id), 78 | ApplicationName = context.ApplicationName, 79 | VersionInfo = context.VersionInfo 80 | }; 81 | } 82 | 83 | public static ScriptContextArgs From(string[] args) 84 | { 85 | ScriptContextArgs scriptContextArgs = null; 86 | Parser.Default.ParseArguments(args) 87 | .WithParsed(parsedArgs => scriptContextArgs = parsedArgs); 88 | return scriptContextArgs; 89 | } 90 | 91 | public string ToArgs() 92 | { 93 | return Parser.Default.FormatCommandLine(this); 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /tests/EsapiEssentials.UnitTests/EsapiEssentials.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | {46821C78-494D-4BD4-8BA1-CC3B430C24F0} 9 | Library 10 | Properties 11 | EsapiEssentials.UnitTests 12 | EsapiEssentials.UnitTests 13 | v4.5 14 | 512 15 | 16 | 17 | 18 | 19 | true 20 | bin\x64\Debug\ 21 | DEBUG;TRACE 22 | full 23 | x64 24 | prompt 25 | MinimumRecommendedRules.ruleset 26 | 27 | 28 | bin\x64\Release\ 29 | TRACE 30 | true 31 | pdbonly 32 | x64 33 | prompt 34 | MinimumRecommendedRules.ruleset 35 | 36 | 37 | 38 | ..\..\packages\NUnit.3.12.0\lib\net45\nunit.framework.dll 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | {fdc15e5d-0179-42cf-b352-48b74b234454} 57 | EsapiEssentials 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp.Runner/EsapiEssentials.Samples.StandaloneApp.Runner.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {B6BD150A-2A22-4D28-9152-D6E02E97B218} 8 | Library 9 | Properties 10 | EsapiEssentials.Samples.StandaloneApp.Runner 11 | EsapiEssentials.Samples.StandaloneApp.Runner.esapi 12 | v4.5 13 | 512 14 | true 15 | 16 | 17 | true 18 | bin\x64\Debug-13.6\ 19 | DEBUG;TRACE 20 | full 21 | x64 22 | prompt 23 | MinimumRecommendedRules.ruleset 24 | 25 | 26 | bin\x64\Release-13.6\ 27 | TRACE 28 | true 29 | pdbonly 30 | x64 31 | prompt 32 | MinimumRecommendedRules.ruleset 33 | 34 | 35 | true 36 | bin\x64\Debug-15.6\ 37 | DEBUG;TRACE 38 | full 39 | x64 40 | prompt 41 | MinimumRecommendedRules.ruleset 42 | 43 | 44 | bin\x64\Release-15.6\ 45 | TRACE 46 | true 47 | pdbonly 48 | x64 49 | prompt 50 | MinimumRecommendedRules.ruleset 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | $(EsapiPath)\VMS.TPS.Common.Model.API.dll 64 | 65 | 66 | $(EsapiPath)\VMS.TPS.Common.Model.Types.dll 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | {fdc15e5d-0179-42cf-b352-48b74b234454} 76 | EsapiEssentials 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript/EsapiEssentials.Samples.PluginScript.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {FEB1E304-CCC9-4B61-ACD2-FE76DE6E1125} 8 | Library 9 | Properties 10 | EsapiEssentials.Samples.PluginScript 11 | EsapiEssentials.Samples.PluginScript.esapi 12 | v4.5 13 | 512 14 | true 15 | 16 | 17 | true 18 | bin\x64\Debug-13.6\ 19 | DEBUG;TRACE 20 | full 21 | x64 22 | prompt 23 | MinimumRecommendedRules.ruleset 24 | 25 | 26 | bin\x64\Release-13.6\ 27 | TRACE 28 | true 29 | pdbonly 30 | x64 31 | prompt 32 | MinimumRecommendedRules.ruleset 33 | 34 | 35 | true 36 | bin\x64\Debug-15.6\ 37 | DEBUG;TRACE 38 | full 39 | x64 40 | prompt 41 | MinimumRecommendedRules.ruleset 42 | 43 | 44 | bin\x64\Release-15.6\ 45 | TRACE 46 | true 47 | pdbonly 48 | x64 49 | prompt 50 | MinimumRecommendedRules.ruleset 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | $(EsapiPath)\VMS.TPS.Common.Model.API.dll 65 | 66 | 67 | $(EsapiPath)\VMS.TPS.Common.Model.Types.dll 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | {FDC15E5D-0179-42CF-B352-48B74B234454} 77 | EsapiEssentials 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/ViewModels/MainViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using System.Windows.Input; 3 | using GalaSoft.MvvmLight; 4 | using GalaSoft.MvvmLight.CommandWpf; 5 | 6 | namespace EsapiEssentials.Samples.Async 7 | { 8 | public class MainViewModel : ViewModelBase 9 | { 10 | private readonly IEsapiService _esapiService; 11 | private readonly IDialogService _dialogService; 12 | 13 | public MainViewModel(IEsapiService esapiService, IDialogService dialogService) 14 | { 15 | _esapiService = esapiService; 16 | _dialogService = dialogService; 17 | } 18 | 19 | private string _searchText; 20 | public string SearchText 21 | { 22 | get => _searchText; 23 | set => Set(ref _searchText, value); 24 | } 25 | 26 | private PatientMatch[] _patientMatches; 27 | public PatientMatch[] PatientMatches 28 | { 29 | get => _patientMatches; 30 | set => Set(ref _patientMatches, value); 31 | } 32 | 33 | private PatientMatch _selectedPatientMatch; 34 | public PatientMatch SelectedPatientMatch 35 | { 36 | get => _selectedPatientMatch; 37 | set => Set(ref _selectedPatientMatch, value); 38 | } 39 | 40 | private Plan[] _plans; 41 | public Plan[] Plans 42 | { 43 | get => _plans; 44 | set => Set(ref _plans, value); 45 | } 46 | 47 | private Plan _selectedPlan; 48 | public Plan SelectedPlan 49 | { 50 | get => _selectedPlan; 51 | set => Set(ref _selectedPlan, value); 52 | } 53 | 54 | private ObservableCollection _metricResults; 55 | public ObservableCollection MetricResults 56 | { 57 | get => _metricResults; 58 | set => Set(ref _metricResults, value); 59 | } 60 | 61 | public ICommand StartCommand => new RelayCommand(Start); 62 | public ICommand SearchPatientCommand => new RelayCommand(SearchPatient); 63 | public ICommand OpenPatientCommand => new RelayCommand(OpenPatient); 64 | public ICommand AnalyzePlanCommand => new RelayCommand(AnalyzePlan); 65 | 66 | private void Start() 67 | { 68 | _dialogService.ShowProgressDialog("Logging in to Eclipse. Please wait.", 69 | async progress => await _esapiService.LogInAsync()); 70 | } 71 | 72 | private async void SearchPatient() 73 | { 74 | PatientMatches = await _esapiService.SearchAsync(SearchText); 75 | } 76 | 77 | private async void OpenPatient() 78 | { 79 | if (SelectedPatientMatch?.Id == null) 80 | return; 81 | 82 | await _esapiService.ClosePatientAsync(); 83 | await _esapiService.OpenPatientAsync(SelectedPatientMatch.Id); 84 | Plans = await _esapiService.GetPlansAsync(); 85 | } 86 | 87 | private async void AnalyzePlan() 88 | { 89 | var courseId = SelectedPlan?.CourseId; 90 | var planId = SelectedPlan?.PlanId; 91 | 92 | if (courseId == null || planId == null) 93 | return; 94 | 95 | var structureIds = await _esapiService.GetStructureIdsAsync(courseId, planId); 96 | 97 | _dialogService.ShowProgressDialog("Calculating dose metrics", structureIds.Length, 98 | async progress => 99 | { 100 | MetricResults = new ObservableCollection(); 101 | foreach (var structureId in structureIds) 102 | { 103 | double result; 104 | 105 | try 106 | { 107 | result = await _esapiService.CalculateMeanDoseAsync(courseId, planId, structureId); 108 | } 109 | catch 110 | { 111 | result = double.NaN; 112 | } 113 | 114 | MetricResults.Add(new MetricResult 115 | { 116 | StructureId = structureId, 117 | Result = result 118 | }); 119 | 120 | progress.Increment(); 121 | } 122 | }); 123 | } 124 | } 125 | } -------------------------------------------------------------------------------- /src/EsapiEssentials.PluginRunner/ViewModel/MainViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Windows.Input; 4 | using GalaSoft.MvvmLight; 5 | using GalaSoft.MvvmLight.CommandWpf; 6 | 7 | namespace EsapiEssentials.PluginRunner 8 | { 9 | internal class MainViewModel : ViewModelBase 10 | { 11 | private readonly PluginRunner _runner; 12 | 13 | public MainViewModel(PluginRunner runner) 14 | { 15 | _runner = runner; 16 | Recents = _runner.GetRecentEntries().Reverse().ToList(); 17 | } 18 | 19 | private string _searchText; 20 | public string SearchText 21 | { 22 | get => _searchText; 23 | set => Set(ref _searchText, value); 24 | } 25 | 26 | private IEnumerable _patientMatches; 27 | public IEnumerable PatientMatches 28 | { 29 | get => _patientMatches; 30 | set => Set(ref _patientMatches, value); 31 | } 32 | 33 | private PatientMatch _selectedPatientMatch; 34 | public PatientMatch SelectedPatientMatch 35 | { 36 | get => _selectedPatientMatch; 37 | set => Set(ref _selectedPatientMatch, value); 38 | } 39 | 40 | // Must not be IEnumerable or it re-creates the view models 41 | // when accessed in OpenPatient(), losing which items are active 42 | private IList _plansAndPlanSums; 43 | public IList PlansAndPlanSums 44 | { 45 | get => _plansAndPlanSums; 46 | set => Set(ref _plansAndPlanSums, value); 47 | } 48 | 49 | private IList _recents; 50 | public IList Recents 51 | { 52 | get => _recents; 53 | set => Set(ref _recents, value); 54 | } 55 | 56 | private RecentEntry _selectedRecent; 57 | public RecentEntry SelectedRecent 58 | { 59 | get => _selectedRecent; 60 | set => Set(ref _selectedRecent, value); 61 | } 62 | 63 | public ICommand SearchPatientCommand => new RelayCommand(SearchPatient); 64 | public ICommand OpenPatientCommand => new RelayCommand(OpenPatient); 65 | public ICommand OpenRecentEntryCommand => new RelayCommand(OpenRecentEntry); 66 | public ICommand RunCommand => new RelayCommand(Run); 67 | 68 | private void SearchPatient() 69 | { 70 | PatientMatches = _runner.FindPatientMatches(SearchText); 71 | 72 | SelectedPatientMatch = null; 73 | PlansAndPlanSums = null; 74 | } 75 | 76 | private void OpenPatient() 77 | { 78 | var plansAndPlanSums = _runner.GetPlansAndPlanSumsFor(SelectedPatientMatch?.Id); 79 | PlansAndPlanSums = plansAndPlanSums?.Select(CreatePlanOrPlanSumViewModel).ToList(); 80 | } 81 | 82 | private PlanOrPlanSumViewModel CreatePlanOrPlanSumViewModel(PlanOrPlanSum planOrPlanSum) => 83 | new PlanOrPlanSumViewModel 84 | { 85 | Type = planOrPlanSum.Type, 86 | Id = planOrPlanSum.Id, 87 | CourseId = planOrPlanSum.CourseId 88 | }; 89 | 90 | private void OpenRecentEntry() 91 | { 92 | SearchText = SelectedRecent?.PatientId; 93 | SearchPatient(); 94 | SelectedPatientMatch = PatientMatches?.FirstOrDefault(); 95 | OpenPatient(); 96 | CheckInScopeOrActiveFromRecent(); 97 | } 98 | 99 | private void CheckInScopeOrActiveFromRecent() 100 | { 101 | if (PlansAndPlanSums == null) return; 102 | 103 | foreach (var planOrPlanSumVm in PlansAndPlanSums) 104 | { 105 | if (IsRecentInScope(planOrPlanSumVm)) 106 | planOrPlanSumVm.IsInScope = true; 107 | if (IsRecentActive(planOrPlanSumVm)) 108 | planOrPlanSumVm.IsActive = true; 109 | } 110 | } 111 | 112 | private bool IsRecentInScope(PlanOrPlanSumViewModel planOrPlanSumVm) => 113 | SelectedRecent?.PlansAndPlanSumsInScope?.Any(p => p.CourseId == planOrPlanSumVm?.CourseId && p.Id == planOrPlanSumVm?.Id) ?? false; 114 | 115 | private bool IsRecentActive(PlanOrPlanSumViewModel planOrPlanSumVm) => 116 | SelectedRecent?.ActivePlan?.CourseId == planOrPlanSumVm?.CourseId && SelectedRecent?.ActivePlan?.Id == planOrPlanSumVm?.Id; 117 | 118 | private void Run() 119 | { 120 | _runner.RunScript(SelectedPatientMatch?.Id, GetPlansAndPlanSumsInScope(), GetActivePlan()); 121 | 122 | var recents = Recents; 123 | var selectedRecent = SelectedRecent; 124 | 125 | Recents = _runner.GetRecentEntries().Reverse().ToList(); 126 | 127 | // If recents changed, it means a new recent was added, so select it as the recent; 128 | // otherwise, select the previously selected recent 129 | SelectedRecent = recents.Count != Recents.Count 130 | ? Recents.FirstOrDefault() 131 | : selectedRecent; 132 | OpenRecentEntry(); 133 | } 134 | 135 | private PlanOrPlanSum[] GetPlansAndPlanSumsInScope() => 136 | PlansAndPlanSums?.Where(p => p.IsInScope).Select(CreatePlanOrPlanSum).ToArray(); 137 | 138 | private PlanOrPlanSum GetActivePlan() => 139 | PlansAndPlanSums?.Where(p => p.IsActive).Select(CreatePlanOrPlanSum).FirstOrDefault(); 140 | 141 | private PlanOrPlanSum CreatePlanOrPlanSum(PlanOrPlanSumViewModel vm) => 142 | new PlanOrPlanSum 143 | { 144 | Type = vm.Type, 145 | Id = vm.Id, 146 | CourseId = vm.CourseId 147 | }; 148 | } 149 | } -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.Async/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin.Runner/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin/Views/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 44 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 70 | 71 | 72 | 73 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 98 | 102 | 106 | 111 | 112 | 116 | 120 | 121 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript.Runner/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /src/EsapiEssentials/EsapiEssentials.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {FDC15E5D-0179-42CF-B352-48B74B234454} 8 | Library 9 | Properties 10 | EsapiEssentials 11 | EsapiEssentials 12 | v4.5 13 | 512 14 | true 15 | 16 | 17 | true 18 | bin\x64\Debug-13.6\ 19 | DEBUG;TRACE 20 | full 21 | x64 22 | prompt 23 | MinimumRecommendedRules.ruleset 24 | 25 | 26 | true 27 | bin\x64\Debug-15.6\ 28 | DEBUG;TRACE 29 | full 30 | x64 31 | prompt 32 | MinimumRecommendedRules.ruleset 33 | 34 | 35 | bin\x64\Release-13.6\ 36 | TRACE 37 | true 38 | pdbonly 39 | x64 40 | prompt 41 | MinimumRecommendedRules.ruleset 42 | 43 | 44 | bin\x64\Release-15.6\ 45 | TRACE 46 | true 47 | pdbonly 48 | x64 49 | prompt 50 | MinimumRecommendedRules.ruleset 51 | 52 | 53 | 54 | 55 | ..\..\packages\CommandLineParser.2.5.0\lib\net45\CommandLine.dll 56 | 57 | 58 | ..\..\packages\MSFT.ParallelExtensionsExtras.1.2.0\lib\ParallelExtensionsExtras.dll 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | $(EsapiPath)\VMS.TPS.Common.Model.API.dll 72 | 73 | 74 | $(EsapiPath)\VMS.TPS.Common.Model.Types.dll 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.AsyncPlugin.Runner/EsapiEssentials.Samples.AsyncPlugin.Runner.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {79D069B9-3FFA-4584-A132-C444937EDF9E} 8 | WinExe 9 | EsapiEssentials.Samples.AsyncPlugin.Runner 10 | EsapiEssentials.Samples.AsyncPlugin.Runner 11 | v4.5 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | 17 | 18 | true 19 | bin\x64\Debug-13.6\ 20 | DEBUG;TRACE 21 | full 22 | x64 23 | prompt 24 | MinimumRecommendedRules.ruleset 25 | true 26 | 27 | 28 | true 29 | bin\x64\Debug-15.6\ 30 | DEBUG;TRACE 31 | full 32 | x64 33 | prompt 34 | MinimumRecommendedRules.ruleset 35 | true 36 | 37 | 38 | bin\x64\Release-13.6\ 39 | TRACE 40 | true 41 | pdbonly 42 | x64 43 | prompt 44 | MinimumRecommendedRules.ruleset 45 | true 46 | 47 | 48 | bin\x64\Release-15.6\ 49 | TRACE 50 | true 51 | pdbonly 52 | x64 53 | prompt 54 | MinimumRecommendedRules.ruleset 55 | true 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 4.0 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | MSBuild:Compile 77 | Designer 78 | 79 | 80 | App.xaml 81 | Code 82 | 83 | 84 | 85 | 86 | Code 87 | 88 | 89 | True 90 | True 91 | Resources.resx 92 | 93 | 94 | True 95 | Settings.settings 96 | True 97 | 98 | 99 | ResXFileCodeGenerator 100 | Resources.Designer.cs 101 | 102 | 103 | SettingsSingleFileGenerator 104 | Settings.Designer.cs 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | {E575892D-81D0-4A2F-9FB1-495D3F404502} 113 | EsapiEssentials.PluginRunner 114 | 115 | 116 | {FDC15E5D-0179-42CF-B352-48B74B234454} 117 | EsapiEssentials 118 | 119 | 120 | {96E0CE2E-799B-473D-BF00-15DDC693A421} 121 | EsapiEssentials.Samples.AsyncPlugin 122 | 123 | 124 | $(EsapiPath)\VMS.TPS.Common.Model.API.dll 125 | 126 | 127 | $(EsapiPath)\VMS.TPS.Common.Model.Types.dll 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.PluginScript.Runner/EsapiEssentials.Samples.PluginScript.Runner.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {CC28EBAC-C301-4CC1-91D0-EF99533C5F08} 8 | WinExe 9 | EsapiEssentials.Samples.PluginScript.Runner 10 | EsapiEssentials.Samples.PluginScript.Runner 11 | v4.5 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | 17 | 18 | true 19 | bin\x64\Debug-13.6\ 20 | DEBUG;TRACE 21 | full 22 | x64 23 | prompt 24 | MinimumRecommendedRules.ruleset 25 | true 26 | 27 | 28 | true 29 | bin\x64\Debug-15.6\ 30 | DEBUG;TRACE 31 | full 32 | x64 33 | prompt 34 | MinimumRecommendedRules.ruleset 35 | true 36 | 37 | 38 | bin\x64\Release-13.6\ 39 | TRACE 40 | true 41 | pdbonly 42 | x64 43 | prompt 44 | MinimumRecommendedRules.ruleset 45 | true 46 | 47 | 48 | bin\x64\Release-15.6\ 49 | TRACE 50 | true 51 | pdbonly 52 | x64 53 | prompt 54 | MinimumRecommendedRules.ruleset 55 | true 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 4.0 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | MSBuild:Compile 77 | Designer 78 | 79 | 80 | App.xaml 81 | Code 82 | 83 | 84 | 85 | 86 | Code 87 | 88 | 89 | True 90 | True 91 | Resources.resx 92 | 93 | 94 | True 95 | Settings.settings 96 | True 97 | 98 | 99 | ResXFileCodeGenerator 100 | Resources.Designer.cs 101 | 102 | 103 | SettingsSingleFileGenerator 104 | Settings.Designer.cs 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | {E575892D-81D0-4A2F-9FB1-495D3F404502} 113 | EsapiEssentials.PluginRunner 114 | 115 | 116 | {fdc15e5d-0179-42cf-b352-48b74b234454} 117 | EsapiEssentials 118 | 119 | 120 | {feb1e304-ccc9-4b61-acd2-fe76de6e1125} 121 | EsapiEssentials.Samples.PluginScript 122 | 123 | 124 | $(EsapiPath)\VMS.TPS.Common.Model.API.dll 125 | 126 | 127 | $(EsapiPath)\VMS.TPS.Common.Model.Types.dll 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /samples/EsapiEssentials.Samples.StandaloneApp/EsapiEssentials.Samples.StandaloneApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {407BAEEF-029F-4F27-89F0-12B8EAAC790C} 8 | WinExe 9 | EsapiEssentials.Samples.StandaloneApp 10 | EsapiEssentials.Samples.StandaloneApp 11 | v4.5 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | 17 | 18 | true 19 | bin\x64\Debug-13.6\ 20 | DEBUG;TRACE 21 | full 22 | x64 23 | prompt 24 | MinimumRecommendedRules.ruleset 25 | true 26 | 27 | 28 | bin\x64\Release-13.6\ 29 | TRACE 30 | true 31 | pdbonly 32 | x64 33 | prompt 34 | MinimumRecommendedRules.ruleset 35 | true 36 | 37 | 38 | true 39 | bin\x64\Debug-15.6\ 40 | DEBUG;TRACE 41 | full 42 | x64 43 | prompt 44 | MinimumRecommendedRules.ruleset 45 | true 46 | 47 | 48 | bin\x64\Release-15.6\ 49 | TRACE 50 | true 51 | pdbonly 52 | x64 53 | prompt 54 | MinimumRecommendedRules.ruleset 55 | true 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 4.0 69 | 70 | 71 | $(EsapiPath)\VMS.TPS.Common.Model.API.dll 72 | 73 | 74 | $(EsapiPath)\VMS.TPS.Common.Model.Types.dll 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | MSBuild:Compile 83 | Designer 84 | 85 | 86 | MSBuild:Compile 87 | Designer 88 | 89 | 90 | App.xaml 91 | Code 92 | 93 | 94 | MainWindow.xaml 95 | Code 96 | 97 | 98 | 99 | 100 | Code 101 | 102 | 103 | True 104 | True 105 | Resources.resx 106 | 107 | 108 | True 109 | Settings.settings 110 | True 111 | 112 | 113 | ResXFileCodeGenerator 114 | Resources.Designer.cs 115 | 116 | 117 | SettingsSingleFileGenerator 118 | Settings.Designer.cs 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | {fdc15e5d-0179-42cf-b352-48b74b234454} 127 | EsapiEssentials 128 | 129 | 130 | {b6bd150a-2a22-4d28-9152-d6e02e97b218} 131 | EsapiEssentials.Samples.StandaloneApp.Runner 132 | 133 | 134 | 135 | --------------------------------------------------------------------------------