From c454772019b37ea63ee8eb61218a2d361047d989 Mon Sep 17 00:00:00 2001 From: Matthew Asplund Date: Thu, 16 Dec 2021 23:06:11 -0800 Subject: [PATCH] Create Soup View GUI (#103) Create Soup View Build Visualizer --- Docs/Posts-Of-Interest.md | 1 + .../{GenerateSharp => }/Directory.Build.props | 9 +- .../Generate/BuildTaskManager.cs | 8 +- Source/GenerateSharp/GenerateSharp.sln | 192 ++++++++++++++- Source/GenerateSharp/SoupView.sln | 171 ++++++++++++++ Source/GenerateSharp/SoupView/App.xaml | 12 + Source/GenerateSharp/SoupView/App.xaml.cs | 49 ++++ .../Assets/LockScreenLogo.scale-200.png | Bin 0 -> 1139 bytes Source/GenerateSharp/SoupView/Assets/Soup.ico | Bin 0 -> 32038 bytes .../Assets/SplashScreen.scale-200.png | Bin 0 -> 19427 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 7248 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 0 -> 2037 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 648 bytes .../SoupView/Assets/StoreLogo.png | Bin 0 -> 1227 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 7808 bytes .../SoupView/Package.appxmanifest | 48 ++++ .../SoupView/Properties/launchSettings.json | 15 ++ Source/GenerateSharp/SoupView/SoupView.csproj | 57 +++++ .../SoupView/Themes/Generic.xaml | 111 +++++++++ .../SoupView/View/DependencyGraphPage.xaml | 48 ++++ .../SoupView/View/DependencyGraphPage.xaml.cs | 26 ++ .../SoupView/View/GraphViewer.cs | 223 ++++++++++++++++++ .../SoupView/View/GraphViewerItem.cs | 35 +++ .../SoupView/View/MainWindow.xaml | 68 ++++++ .../SoupView/View/MainWindow.xaml.cs | 105 +++++++++ .../SoupView/View/OperationGraphPage.xaml | 48 ++++ .../SoupView/View/OperationGraphPage.xaml.cs | 26 ++ .../SoupView/View/SettingsPage.xaml | 14 ++ .../SoupView/View/SettingsPage.xaml.cs | 19 ++ .../SoupView/View/TaskGraphPage.xaml | 108 +++++++++ .../SoupView/View/TaskGraphPage.xaml.cs | 28 +++ .../View/ValueTableItemTemplateSelector.cs | 34 +++ .../ViewModel/DependencyGraphPageModel.cs | 189 +++++++++++++++ .../SoupView/ViewModel/GraphNode.cs | 21 ++ .../SoupView/ViewModel/MainWindowModel.cs | 51 ++++ .../SoupView/ViewModel/Observable.cs | 22 ++ .../ViewModel/OperationDetailsViewModel.cs | 28 +++ .../ViewModel/OperationGraphPageModel.cs | 207 ++++++++++++++++ .../ViewModel/ProjectDetailsViewModel.cs | 27 +++ .../SoupView/ViewModel/PropertyValue.cs | 18 ++ .../ViewModel/TaskDetailsViewModel.cs | 121 ++++++++++ .../SoupView/ViewModel/TaskGraphPageModel.cs | 197 ++++++++++++++++ .../ViewModel/ValueTableItemViewModel.cs | 57 +++++ Source/GenerateSharp/SoupView/app.manifest | 15 ++ .../GenerateSharp/Utilities/BuildConstants.cs | 5 + .../OperationGraph/OperationGraphManager.cs | 12 +- .../OperationGraph/OperationGraphReader.cs | 8 +- .../OperationGraph/OperationGraphWriter.cs | 2 +- .../Utilities/Recipe/RecipeExtensions.cs | 2 +- .../ValueTable/ValueTableTomlUtilities.cs | 1 - Source/{GenerateSharp => }/Soup.Rules.ruleset | 0 Source/{GenerateSharp => }/stylecop.json | 0 52 files changed, 2412 insertions(+), 26 deletions(-) rename Source/{GenerateSharp => }/Directory.Build.props (75%) create mode 100644 Source/GenerateSharp/SoupView.sln create mode 100644 Source/GenerateSharp/SoupView/App.xaml create mode 100644 Source/GenerateSharp/SoupView/App.xaml.cs create mode 100644 Source/GenerateSharp/SoupView/Assets/LockScreenLogo.scale-200.png create mode 100644 Source/GenerateSharp/SoupView/Assets/Soup.ico create mode 100644 Source/GenerateSharp/SoupView/Assets/SplashScreen.scale-200.png create mode 100644 Source/GenerateSharp/SoupView/Assets/Square150x150Logo.scale-200.png create mode 100644 Source/GenerateSharp/SoupView/Assets/Square44x44Logo.scale-200.png create mode 100644 Source/GenerateSharp/SoupView/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 Source/GenerateSharp/SoupView/Assets/StoreLogo.png create mode 100644 Source/GenerateSharp/SoupView/Assets/Wide310x150Logo.scale-200.png create mode 100644 Source/GenerateSharp/SoupView/Package.appxmanifest create mode 100644 Source/GenerateSharp/SoupView/Properties/launchSettings.json create mode 100644 Source/GenerateSharp/SoupView/SoupView.csproj create mode 100644 Source/GenerateSharp/SoupView/Themes/Generic.xaml create mode 100644 Source/GenerateSharp/SoupView/View/DependencyGraphPage.xaml create mode 100644 Source/GenerateSharp/SoupView/View/DependencyGraphPage.xaml.cs create mode 100644 Source/GenerateSharp/SoupView/View/GraphViewer.cs create mode 100644 Source/GenerateSharp/SoupView/View/GraphViewerItem.cs create mode 100644 Source/GenerateSharp/SoupView/View/MainWindow.xaml create mode 100644 Source/GenerateSharp/SoupView/View/MainWindow.xaml.cs create mode 100644 Source/GenerateSharp/SoupView/View/OperationGraphPage.xaml create mode 100644 Source/GenerateSharp/SoupView/View/OperationGraphPage.xaml.cs create mode 100644 Source/GenerateSharp/SoupView/View/SettingsPage.xaml create mode 100644 Source/GenerateSharp/SoupView/View/SettingsPage.xaml.cs create mode 100644 Source/GenerateSharp/SoupView/View/TaskGraphPage.xaml create mode 100644 Source/GenerateSharp/SoupView/View/TaskGraphPage.xaml.cs create mode 100644 Source/GenerateSharp/SoupView/View/ValueTableItemTemplateSelector.cs create mode 100644 Source/GenerateSharp/SoupView/ViewModel/DependencyGraphPageModel.cs create mode 100644 Source/GenerateSharp/SoupView/ViewModel/GraphNode.cs create mode 100644 Source/GenerateSharp/SoupView/ViewModel/MainWindowModel.cs create mode 100644 Source/GenerateSharp/SoupView/ViewModel/Observable.cs create mode 100644 Source/GenerateSharp/SoupView/ViewModel/OperationDetailsViewModel.cs create mode 100644 Source/GenerateSharp/SoupView/ViewModel/OperationGraphPageModel.cs create mode 100644 Source/GenerateSharp/SoupView/ViewModel/ProjectDetailsViewModel.cs create mode 100644 Source/GenerateSharp/SoupView/ViewModel/PropertyValue.cs create mode 100644 Source/GenerateSharp/SoupView/ViewModel/TaskDetailsViewModel.cs create mode 100644 Source/GenerateSharp/SoupView/ViewModel/TaskGraphPageModel.cs create mode 100644 Source/GenerateSharp/SoupView/ViewModel/ValueTableItemViewModel.cs create mode 100644 Source/GenerateSharp/SoupView/app.manifest rename Source/GenerateSharp/{Generate => Utilities}/OperationGraph/OperationGraphManager.cs (94%) rename Source/GenerateSharp/{Generate => Utilities}/OperationGraph/OperationGraphReader.cs (96%) rename Source/GenerateSharp/{Generate => Utilities}/OperationGraph/OperationGraphWriter.cs (99%) rename Source/{GenerateSharp => }/Soup.Rules.ruleset (100%) rename Source/{GenerateSharp => }/stylecop.json (100%) diff --git a/Docs/Posts-Of-Interest.md b/Docs/Posts-Of-Interest.md index dc5b6b401..f4bfab32c 100644 --- a/Docs/Posts-Of-Interest.md +++ b/Docs/Posts-Of-Interest.md @@ -8,6 +8,7 @@ * [CppCon 2019: Boris Kolpackov “Practical C++ Modules”](https://www.youtube.com/watch?v=szHV6RdQdg8) * [CppCon 2019: Nathan Sidwell “Converting to C++20 Modules”](https://www.youtube.com/watch?v=KVsWIEw3TTw) * [CppCon 2019: Michael Spencer “Building Modules”](https://www.youtube.com/watch?v=L0SHHkBenss) +* [C++ MODULES: A BRIEF TOUR](https://accu.org/journals/overload/28/159/sidwell/) ## Hooking OS Calls * [Detours](https://www.microsoft.com/en-us/research/project/detours/?from=http%3A%2F%2Fresearch.microsoft.com%2Fsn%2Fdetours) diff --git a/Source/GenerateSharp/Directory.Build.props b/Source/Directory.Build.props similarity index 75% rename from Source/GenerateSharp/Directory.Build.props rename to Source/Directory.Build.props index a1bd8b69b..5e63c5fc0 100644 --- a/Source/GenerateSharp/Directory.Build.props +++ b/Source/Directory.Build.props @@ -1,8 +1,9 @@ - $(MSBuildThisFileDirectory.TrimEnd('\')) - $([System.IO.Path]::GetDirectoryName($(GenerateSharpDirectory))) + $(MSBuildThisFileDirectory.TrimEnd('\')) + $(RootDirectory)\GenerateSharp + $(RootDirectory)\GenerateSharp $([System.IO.Path]::GetDirectoryName($(SourceDirectory))) $(RootDirectory)\out\msbuild $(OutDirectory)\obj @@ -28,10 +29,10 @@ - + - $(GenerateSharpDirectory)\Soup.Rules.ruleset + $(SourceDirectory)\Soup.Rules.ruleset diff --git a/Source/GenerateSharp/Generate/BuildTaskManager.cs b/Source/GenerateSharp/Generate/BuildTaskManager.cs index 00e19577f..16905997f 100644 --- a/Source/GenerateSharp/Generate/BuildTaskManager.cs +++ b/Source/GenerateSharp/Generate/BuildTaskManager.cs @@ -155,12 +155,6 @@ public void Execute(BuildState state, Path soupTargetDirectory) Log.Info("TaskDone: " + currentTask.Name); - // Write the output from the task to be used for debugging - var activeStateFile = soupTargetDirectory + new Path($"ActiveState_{currentTask.Name}.bvt"); - var sharedStateFile = soupTargetDirectory + new Path($"SharedState_{currentTask.Name}.bvt"); - ValueTableManager.SaveState(activeStateFile, state.ActiveState); - ValueTableManager.SaveState(sharedStateFile, state.SharedState); - // Build the task info var taskInfo = new ValueTable(); taskInfo.Add("ActiveState", new Value(state.ActiveStateImpl.Clone())); @@ -178,7 +172,7 @@ public void Execute(BuildState state, Path soupTargetDirectory) generateInfoTable.Add("TaskInfo", new Value(taskInfoTable)); // Save the runtime information - var generateInfoStateFile = soupTargetDirectory + new Path($"GenerateInfo.bvt"); + var generateInfoStateFile = soupTargetDirectory + BuildConstants.GenerateTaskInfoFileName; ValueTableManager.SaveState(generateInfoStateFile, generateInfoTable); } diff --git a/Source/GenerateSharp/GenerateSharp.sln b/Source/GenerateSharp/GenerateSharp.sln index 33d1f5537..91e70b8f2 100644 --- a/Source/GenerateSharp/GenerateSharp.sln +++ b/Source/GenerateSharp/GenerateSharp.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30907.101 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.31911.260 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Soup.Build.Generate", "Generate\Soup.Build.Generate.csproj", "{E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}" EndProject @@ -52,195 +52,383 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|arm64 = Debug|arm64 Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|arm64 = Release|arm64 Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Debug|arm64.ActiveCfg = Debug|Any CPU + {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Debug|arm64.Build.0 = Debug|Any CPU {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Debug|x64.ActiveCfg = Debug|x64 {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Debug|x64.Build.0 = Debug|x64 + {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Debug|x86.ActiveCfg = Debug|Any CPU + {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Debug|x86.Build.0 = Debug|Any CPU {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Release|Any CPU.ActiveCfg = Release|Any CPU {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Release|Any CPU.Build.0 = Release|Any CPU + {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Release|arm64.ActiveCfg = Release|Any CPU + {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Release|arm64.Build.0 = Release|Any CPU {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Release|x64.ActiveCfg = Release|x64 {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Release|x64.Build.0 = Release|x64 + {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Release|x86.ActiveCfg = Release|Any CPU + {E2C26B2D-EA0C-4E3D-B58D-EAFFFDC11F43}.Release|x86.Build.0 = Release|Any CPU {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Debug|arm64.ActiveCfg = Debug|Any CPU + {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Debug|arm64.Build.0 = Debug|Any CPU {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Debug|x64.ActiveCfg = Debug|x64 {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Debug|x64.Build.0 = Debug|x64 + {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Debug|x86.ActiveCfg = Debug|Any CPU + {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Debug|x86.Build.0 = Debug|Any CPU {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Release|Any CPU.ActiveCfg = Release|Any CPU {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Release|Any CPU.Build.0 = Release|Any CPU + {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Release|arm64.ActiveCfg = Release|Any CPU + {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Release|arm64.Build.0 = Release|Any CPU {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Release|x64.ActiveCfg = Release|x64 {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Release|x64.Build.0 = Release|x64 + {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Release|x86.ActiveCfg = Release|Any CPU + {76A76C21-BFB1-4DDC-83F7-35F1E176EF22}.Release|x86.Build.0 = Release|Any CPU {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|arm64.ActiveCfg = Debug|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|arm64.Build.0 = Debug|Any CPU {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|x64.ActiveCfg = Debug|x64 {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|x64.Build.0 = Debug|x64 + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|x86.ActiveCfg = Debug|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|x86.Build.0 = Debug|Any CPU {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|Any CPU.ActiveCfg = Release|Any CPU {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|Any CPU.Build.0 = Release|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|arm64.ActiveCfg = Release|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|arm64.Build.0 = Release|Any CPU {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|x64.ActiveCfg = Release|x64 {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|x64.Build.0 = Release|x64 + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|x86.ActiveCfg = Release|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|x86.Build.0 = Release|Any CPU {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Debug|arm64.ActiveCfg = Debug|Any CPU + {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Debug|arm64.Build.0 = Debug|Any CPU {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Debug|x64.ActiveCfg = Debug|x64 {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Debug|x64.Build.0 = Debug|x64 + {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Debug|x86.ActiveCfg = Debug|Any CPU + {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Debug|x86.Build.0 = Debug|Any CPU {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Release|Any CPU.ActiveCfg = Release|Any CPU {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Release|Any CPU.Build.0 = Release|Any CPU + {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Release|arm64.ActiveCfg = Release|Any CPU + {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Release|arm64.Build.0 = Release|Any CPU {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Release|x64.ActiveCfg = Release|x64 {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Release|x64.Build.0 = Release|x64 + {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Release|x86.ActiveCfg = Release|Any CPU + {0589B4F1-3A9B-4B35-BE92-3EF34D43EEB3}.Release|x86.Build.0 = Release|Any CPU {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Debug|arm64.ActiveCfg = Debug|Any CPU + {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Debug|arm64.Build.0 = Debug|Any CPU {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Debug|x64.ActiveCfg = Debug|x64 {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Debug|x64.Build.0 = Debug|x64 + {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Debug|x86.ActiveCfg = Debug|Any CPU + {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Debug|x86.Build.0 = Debug|Any CPU {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Release|Any CPU.ActiveCfg = Release|Any CPU {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Release|Any CPU.Build.0 = Release|Any CPU + {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Release|arm64.ActiveCfg = Release|Any CPU + {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Release|arm64.Build.0 = Release|Any CPU {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Release|x64.ActiveCfg = Release|x64 {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Release|x64.Build.0 = Release|x64 + {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Release|x86.ActiveCfg = Release|Any CPU + {6B7849BF-3087-4E4D-91C6-BC4E89AE0268}.Release|x86.Build.0 = Release|Any CPU {4545B940-4076-4EE3-9597-B9254C1E2997}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4545B940-4076-4EE3-9597-B9254C1E2997}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4545B940-4076-4EE3-9597-B9254C1E2997}.Debug|arm64.ActiveCfg = Debug|Any CPU + {4545B940-4076-4EE3-9597-B9254C1E2997}.Debug|arm64.Build.0 = Debug|Any CPU {4545B940-4076-4EE3-9597-B9254C1E2997}.Debug|x64.ActiveCfg = Debug|x64 {4545B940-4076-4EE3-9597-B9254C1E2997}.Debug|x64.Build.0 = Debug|x64 + {4545B940-4076-4EE3-9597-B9254C1E2997}.Debug|x86.ActiveCfg = Debug|Any CPU + {4545B940-4076-4EE3-9597-B9254C1E2997}.Debug|x86.Build.0 = Debug|Any CPU {4545B940-4076-4EE3-9597-B9254C1E2997}.Release|Any CPU.ActiveCfg = Release|Any CPU {4545B940-4076-4EE3-9597-B9254C1E2997}.Release|Any CPU.Build.0 = Release|Any CPU + {4545B940-4076-4EE3-9597-B9254C1E2997}.Release|arm64.ActiveCfg = Release|Any CPU + {4545B940-4076-4EE3-9597-B9254C1E2997}.Release|arm64.Build.0 = Release|Any CPU {4545B940-4076-4EE3-9597-B9254C1E2997}.Release|x64.ActiveCfg = Release|x64 {4545B940-4076-4EE3-9597-B9254C1E2997}.Release|x64.Build.0 = Release|x64 + {4545B940-4076-4EE3-9597-B9254C1E2997}.Release|x86.ActiveCfg = Release|Any CPU + {4545B940-4076-4EE3-9597-B9254C1E2997}.Release|x86.Build.0 = Release|Any CPU {B1040AA7-40A3-4586-9358-4784BC657471}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B1040AA7-40A3-4586-9358-4784BC657471}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B1040AA7-40A3-4586-9358-4784BC657471}.Debug|arm64.ActiveCfg = Debug|Any CPU + {B1040AA7-40A3-4586-9358-4784BC657471}.Debug|arm64.Build.0 = Debug|Any CPU {B1040AA7-40A3-4586-9358-4784BC657471}.Debug|x64.ActiveCfg = Debug|x64 {B1040AA7-40A3-4586-9358-4784BC657471}.Debug|x64.Build.0 = Debug|x64 + {B1040AA7-40A3-4586-9358-4784BC657471}.Debug|x86.ActiveCfg = Debug|Any CPU + {B1040AA7-40A3-4586-9358-4784BC657471}.Debug|x86.Build.0 = Debug|Any CPU {B1040AA7-40A3-4586-9358-4784BC657471}.Release|Any CPU.ActiveCfg = Release|Any CPU {B1040AA7-40A3-4586-9358-4784BC657471}.Release|Any CPU.Build.0 = Release|Any CPU + {B1040AA7-40A3-4586-9358-4784BC657471}.Release|arm64.ActiveCfg = Release|Any CPU + {B1040AA7-40A3-4586-9358-4784BC657471}.Release|arm64.Build.0 = Release|Any CPU {B1040AA7-40A3-4586-9358-4784BC657471}.Release|x64.ActiveCfg = Release|x64 {B1040AA7-40A3-4586-9358-4784BC657471}.Release|x64.Build.0 = Release|x64 + {B1040AA7-40A3-4586-9358-4784BC657471}.Release|x86.ActiveCfg = Release|Any CPU + {B1040AA7-40A3-4586-9358-4784BC657471}.Release|x86.Build.0 = Release|Any CPU {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Debug|Any CPU.Build.0 = Debug|Any CPU + {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Debug|arm64.ActiveCfg = Debug|Any CPU + {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Debug|arm64.Build.0 = Debug|Any CPU {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Debug|x64.ActiveCfg = Debug|x64 {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Debug|x64.Build.0 = Debug|x64 + {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Debug|x86.ActiveCfg = Debug|Any CPU + {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Debug|x86.Build.0 = Debug|Any CPU {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Release|Any CPU.ActiveCfg = Release|Any CPU {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Release|Any CPU.Build.0 = Release|Any CPU + {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Release|arm64.ActiveCfg = Release|Any CPU + {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Release|arm64.Build.0 = Release|Any CPU {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Release|x64.ActiveCfg = Release|x64 {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Release|x64.Build.0 = Release|x64 + {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Release|x86.ActiveCfg = Release|Any CPU + {267A6951-97FD-4270-93B3-A2FAAE9D1A38}.Release|x86.Build.0 = Release|Any CPU {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Debug|arm64.ActiveCfg = Debug|Any CPU + {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Debug|arm64.Build.0 = Debug|Any CPU {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Debug|x64.ActiveCfg = Debug|x64 {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Debug|x64.Build.0 = Debug|x64 + {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Debug|x86.ActiveCfg = Debug|Any CPU + {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Debug|x86.Build.0 = Debug|Any CPU {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Release|Any CPU.ActiveCfg = Release|Any CPU {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Release|Any CPU.Build.0 = Release|Any CPU + {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Release|arm64.ActiveCfg = Release|Any CPU + {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Release|arm64.Build.0 = Release|Any CPU {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Release|x64.ActiveCfg = Release|x64 {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Release|x64.Build.0 = Release|x64 + {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Release|x86.ActiveCfg = Release|Any CPU + {4ECFAFBA-B418-4082-8584-E8EF642E31ED}.Release|x86.Build.0 = Release|Any CPU {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|arm64.ActiveCfg = Debug|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|arm64.Build.0 = Debug|Any CPU {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|x64.ActiveCfg = Debug|x64 {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|x64.Build.0 = Debug|x64 + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|x86.ActiveCfg = Debug|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|x86.Build.0 = Debug|Any CPU {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|Any CPU.ActiveCfg = Release|Any CPU {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|Any CPU.Build.0 = Release|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|arm64.ActiveCfg = Release|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|arm64.Build.0 = Release|Any CPU {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|x64.ActiveCfg = Release|x64 {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|x64.Build.0 = Release|x64 + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|x86.ActiveCfg = Release|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|x86.Build.0 = Release|Any CPU {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|arm64.ActiveCfg = Debug|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|arm64.Build.0 = Debug|Any CPU {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|x64.ActiveCfg = Debug|x64 {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|x64.Build.0 = Debug|x64 + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|x86.ActiveCfg = Debug|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|x86.Build.0 = Debug|Any CPU {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|Any CPU.ActiveCfg = Release|Any CPU {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|Any CPU.Build.0 = Release|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|arm64.ActiveCfg = Release|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|arm64.Build.0 = Release|Any CPU {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|x64.ActiveCfg = Release|x64 {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|x64.Build.0 = Release|x64 + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|x86.ActiveCfg = Release|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|x86.Build.0 = Release|Any CPU {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|arm64.ActiveCfg = Debug|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|arm64.Build.0 = Debug|Any CPU {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|x64.ActiveCfg = Debug|x64 {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|x64.Build.0 = Debug|x64 + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|x86.ActiveCfg = Debug|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|x86.Build.0 = Debug|Any CPU {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|Any CPU.ActiveCfg = Release|Any CPU {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|Any CPU.Build.0 = Release|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|arm64.ActiveCfg = Release|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|arm64.Build.0 = Release|Any CPU {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|x64.ActiveCfg = Release|x64 {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|x64.Build.0 = Release|x64 + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|x86.ActiveCfg = Release|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|x86.Build.0 = Release|Any CPU {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Debug|arm64.ActiveCfg = Debug|Any CPU + {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Debug|arm64.Build.0 = Debug|Any CPU {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Debug|x64.ActiveCfg = Debug|x64 {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Debug|x64.Build.0 = Debug|x64 + {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Debug|x86.ActiveCfg = Debug|Any CPU + {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Debug|x86.Build.0 = Debug|Any CPU {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Release|Any CPU.ActiveCfg = Release|Any CPU {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Release|Any CPU.Build.0 = Release|Any CPU + {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Release|arm64.ActiveCfg = Release|Any CPU + {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Release|arm64.Build.0 = Release|Any CPU {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Release|x64.ActiveCfg = Release|x64 {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Release|x64.Build.0 = Release|x64 + {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Release|x86.ActiveCfg = Release|Any CPU + {66FA6F08-F50B-4CB1-B172-94E7596AE830}.Release|x86.Build.0 = Release|Any CPU {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Debug|arm64.ActiveCfg = Debug|Any CPU + {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Debug|arm64.Build.0 = Debug|Any CPU {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Debug|x64.ActiveCfg = Debug|x64 {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Debug|x64.Build.0 = Debug|x64 + {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Debug|x86.ActiveCfg = Debug|Any CPU + {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Debug|x86.Build.0 = Debug|Any CPU {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Release|Any CPU.ActiveCfg = Release|Any CPU {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Release|Any CPU.Build.0 = Release|Any CPU + {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Release|arm64.ActiveCfg = Release|Any CPU + {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Release|arm64.Build.0 = Release|Any CPU {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Release|x64.ActiveCfg = Release|x64 {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Release|x64.Build.0 = Release|x64 + {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Release|x86.ActiveCfg = Release|Any CPU + {5DEF6E0F-0B23-46E4-8419-7B08D6A45627}.Release|x86.Build.0 = Release|Any CPU {3DC9C67E-940B-4051-917C-77888E4029F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3DC9C67E-940B-4051-917C-77888E4029F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3DC9C67E-940B-4051-917C-77888E4029F0}.Debug|arm64.ActiveCfg = Debug|Any CPU + {3DC9C67E-940B-4051-917C-77888E4029F0}.Debug|arm64.Build.0 = Debug|Any CPU {3DC9C67E-940B-4051-917C-77888E4029F0}.Debug|x64.ActiveCfg = Debug|x64 {3DC9C67E-940B-4051-917C-77888E4029F0}.Debug|x64.Build.0 = Debug|x64 + {3DC9C67E-940B-4051-917C-77888E4029F0}.Debug|x86.ActiveCfg = Debug|Any CPU + {3DC9C67E-940B-4051-917C-77888E4029F0}.Debug|x86.Build.0 = Debug|Any CPU {3DC9C67E-940B-4051-917C-77888E4029F0}.Release|Any CPU.ActiveCfg = Release|Any CPU {3DC9C67E-940B-4051-917C-77888E4029F0}.Release|Any CPU.Build.0 = Release|Any CPU + {3DC9C67E-940B-4051-917C-77888E4029F0}.Release|arm64.ActiveCfg = Release|Any CPU + {3DC9C67E-940B-4051-917C-77888E4029F0}.Release|arm64.Build.0 = Release|Any CPU {3DC9C67E-940B-4051-917C-77888E4029F0}.Release|x64.ActiveCfg = Release|x64 {3DC9C67E-940B-4051-917C-77888E4029F0}.Release|x64.Build.0 = Release|x64 + {3DC9C67E-940B-4051-917C-77888E4029F0}.Release|x86.ActiveCfg = Release|Any CPU + {3DC9C67E-940B-4051-917C-77888E4029F0}.Release|x86.Build.0 = Release|Any CPU {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Debug|arm64.ActiveCfg = Debug|Any CPU + {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Debug|arm64.Build.0 = Debug|Any CPU {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Debug|x64.ActiveCfg = Debug|x64 {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Debug|x64.Build.0 = Debug|x64 + {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Debug|x86.ActiveCfg = Debug|Any CPU + {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Debug|x86.Build.0 = Debug|Any CPU {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Release|Any CPU.ActiveCfg = Release|Any CPU {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Release|Any CPU.Build.0 = Release|Any CPU + {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Release|arm64.ActiveCfg = Release|Any CPU + {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Release|arm64.Build.0 = Release|Any CPU {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Release|x64.ActiveCfg = Release|x64 {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Release|x64.Build.0 = Release|x64 + {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Release|x86.ActiveCfg = Release|Any CPU + {8C55ACD1-23F1-42E2-9EBE-38E8F6F25A65}.Release|x86.Build.0 = Release|Any CPU {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Debug|arm64.ActiveCfg = Debug|Any CPU + {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Debug|arm64.Build.0 = Debug|Any CPU {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Debug|x64.ActiveCfg = Debug|x64 {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Debug|x64.Build.0 = Debug|x64 + {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Debug|x86.ActiveCfg = Debug|Any CPU + {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Debug|x86.Build.0 = Debug|Any CPU {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Release|Any CPU.ActiveCfg = Release|Any CPU {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Release|Any CPU.Build.0 = Release|Any CPU + {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Release|arm64.ActiveCfg = Release|Any CPU + {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Release|arm64.Build.0 = Release|Any CPU {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Release|x64.ActiveCfg = Release|x64 {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Release|x64.Build.0 = Release|x64 + {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Release|x86.ActiveCfg = Release|Any CPU + {00F65850-77EA-4CE5-AFFD-826CA34476AE}.Release|x86.Build.0 = Release|Any CPU {770620D6-444F-4FE9-80F7-08217CCBFD59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {770620D6-444F-4FE9-80F7-08217CCBFD59}.Debug|Any CPU.Build.0 = Debug|Any CPU + {770620D6-444F-4FE9-80F7-08217CCBFD59}.Debug|arm64.ActiveCfg = Debug|Any CPU + {770620D6-444F-4FE9-80F7-08217CCBFD59}.Debug|arm64.Build.0 = Debug|Any CPU {770620D6-444F-4FE9-80F7-08217CCBFD59}.Debug|x64.ActiveCfg = Debug|Any CPU {770620D6-444F-4FE9-80F7-08217CCBFD59}.Debug|x64.Build.0 = Debug|Any CPU + {770620D6-444F-4FE9-80F7-08217CCBFD59}.Debug|x86.ActiveCfg = Debug|Any CPU + {770620D6-444F-4FE9-80F7-08217CCBFD59}.Debug|x86.Build.0 = Debug|Any CPU {770620D6-444F-4FE9-80F7-08217CCBFD59}.Release|Any CPU.ActiveCfg = Release|Any CPU {770620D6-444F-4FE9-80F7-08217CCBFD59}.Release|Any CPU.Build.0 = Release|Any CPU + {770620D6-444F-4FE9-80F7-08217CCBFD59}.Release|arm64.ActiveCfg = Release|Any CPU + {770620D6-444F-4FE9-80F7-08217CCBFD59}.Release|arm64.Build.0 = Release|Any CPU {770620D6-444F-4FE9-80F7-08217CCBFD59}.Release|x64.ActiveCfg = Release|Any CPU {770620D6-444F-4FE9-80F7-08217CCBFD59}.Release|x64.Build.0 = Release|Any CPU + {770620D6-444F-4FE9-80F7-08217CCBFD59}.Release|x86.ActiveCfg = Release|Any CPU + {770620D6-444F-4FE9-80F7-08217CCBFD59}.Release|x86.Build.0 = Release|Any CPU {7B533719-1983-4851-B9A8-788F032BD2AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7B533719-1983-4851-B9A8-788F032BD2AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B533719-1983-4851-B9A8-788F032BD2AA}.Debug|arm64.ActiveCfg = Debug|Any CPU + {7B533719-1983-4851-B9A8-788F032BD2AA}.Debug|arm64.Build.0 = Debug|Any CPU {7B533719-1983-4851-B9A8-788F032BD2AA}.Debug|x64.ActiveCfg = Debug|Any CPU {7B533719-1983-4851-B9A8-788F032BD2AA}.Debug|x64.Build.0 = Debug|Any CPU + {7B533719-1983-4851-B9A8-788F032BD2AA}.Debug|x86.ActiveCfg = Debug|Any CPU + {7B533719-1983-4851-B9A8-788F032BD2AA}.Debug|x86.Build.0 = Debug|Any CPU {7B533719-1983-4851-B9A8-788F032BD2AA}.Release|Any CPU.ActiveCfg = Release|Any CPU {7B533719-1983-4851-B9A8-788F032BD2AA}.Release|Any CPU.Build.0 = Release|Any CPU + {7B533719-1983-4851-B9A8-788F032BD2AA}.Release|arm64.ActiveCfg = Release|Any CPU + {7B533719-1983-4851-B9A8-788F032BD2AA}.Release|arm64.Build.0 = Release|Any CPU {7B533719-1983-4851-B9A8-788F032BD2AA}.Release|x64.ActiveCfg = Release|Any CPU {7B533719-1983-4851-B9A8-788F032BD2AA}.Release|x64.Build.0 = Release|Any CPU + {7B533719-1983-4851-B9A8-788F032BD2AA}.Release|x86.ActiveCfg = Release|Any CPU + {7B533719-1983-4851-B9A8-788F032BD2AA}.Release|x86.Build.0 = Release|Any CPU {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|arm64.ActiveCfg = Debug|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|arm64.Build.0 = Debug|Any CPU {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|x64.ActiveCfg = Debug|x64 {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|x64.Build.0 = Debug|x64 + {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|x86.ActiveCfg = Debug|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|x86.Build.0 = Debug|Any CPU {CD73104E-C7DE-4400-89F2-A04950649235}.Release|Any CPU.ActiveCfg = Release|Any CPU {CD73104E-C7DE-4400-89F2-A04950649235}.Release|Any CPU.Build.0 = Release|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Release|arm64.ActiveCfg = Release|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Release|arm64.Build.0 = Release|Any CPU {CD73104E-C7DE-4400-89F2-A04950649235}.Release|x64.ActiveCfg = Release|x64 {CD73104E-C7DE-4400-89F2-A04950649235}.Release|x64.Build.0 = Release|x64 + {CD73104E-C7DE-4400-89F2-A04950649235}.Release|x86.ActiveCfg = Release|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Release|x86.Build.0 = Release|Any CPU {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|arm64.ActiveCfg = Debug|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|arm64.Build.0 = Debug|Any CPU {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|x64.ActiveCfg = Debug|x64 {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|x64.Build.0 = Debug|x64 + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|x86.ActiveCfg = Debug|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|x86.Build.0 = Debug|Any CPU {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|Any CPU.ActiveCfg = Release|Any CPU {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|Any CPU.Build.0 = Release|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|arm64.ActiveCfg = Release|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|arm64.Build.0 = Release|Any CPU {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|x64.ActiveCfg = Release|x64 {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|x64.Build.0 = Release|x64 + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|x86.ActiveCfg = Release|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|x86.Build.0 = Release|Any CPU {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Debug|arm64.ActiveCfg = Debug|Any CPU + {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Debug|arm64.Build.0 = Debug|Any CPU {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Debug|x64.ActiveCfg = Debug|Any CPU {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Debug|x64.Build.0 = Debug|Any CPU + {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Debug|x86.ActiveCfg = Debug|Any CPU + {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Debug|x86.Build.0 = Debug|Any CPU {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Release|Any CPU.ActiveCfg = Release|Any CPU {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Release|Any CPU.Build.0 = Release|Any CPU + {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Release|arm64.ActiveCfg = Release|Any CPU + {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Release|arm64.Build.0 = Release|Any CPU {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Release|x64.ActiveCfg = Release|Any CPU {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Release|x64.Build.0 = Release|Any CPU + {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Release|x86.ActiveCfg = Release|Any CPU + {2FBD7ED6-C001-4DC8-86B6-CAE7358B4A62}.Release|x86.Build.0 = Release|Any CPU {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|arm64.ActiveCfg = Debug|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|arm64.Build.0 = Debug|Any CPU {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|x64.ActiveCfg = Debug|x64 {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|x64.Build.0 = Debug|x64 + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|x86.ActiveCfg = Debug|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|x86.Build.0 = Debug|Any CPU {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|Any CPU.ActiveCfg = Release|Any CPU {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|Any CPU.Build.0 = Release|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|arm64.ActiveCfg = Release|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|arm64.Build.0 = Release|Any CPU {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|x64.ActiveCfg = Release|x64 {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|x64.Build.0 = Release|x64 + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|x86.ActiveCfg = Release|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Source/GenerateSharp/SoupView.sln b/Source/GenerateSharp/SoupView.sln new file mode 100644 index 000000000..adb000d1c --- /dev/null +++ b/Source/GenerateSharp/SoupView.sln @@ -0,0 +1,171 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.31911.260 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Soup.Utilities", "Utilities\Soup.Utilities.csproj", "{274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Opal", "Opal\Opal.csproj", "{D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Opal.UnitTests", "Opal.UnitTests\Opal.UnitTests.csproj", "{0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Soup.Build.Runtime", "Runtime\Soup.Build.Runtime.csproj", "{32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Soup.Build", "Build\Soup.Build.csproj", "{CD73104E-C7DE-4400-89F2-A04950649235}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Soup.Build.Extensions", "Build.Extensions\Soup.Build.Extensions.csproj", "{C81003D5-1FA4-464C-AE8F-38F79305FEDA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Soup.Build.Runtime.UnitTests", "Runtime.UnitTests\Soup.Build.Runtime.UnitTests.csproj", "{C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SoupView", "SoupView\SoupView.csproj", "{2B65A2B3-2342-4030-A194-5B1394BFCE6D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|arm64 = Debug|arm64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|arm64 = Release|arm64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|arm64.ActiveCfg = Debug|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|arm64.Build.0 = Debug|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|x64.ActiveCfg = Debug|x64 + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|x64.Build.0 = Debug|x64 + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|x86.ActiveCfg = Debug|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Debug|x86.Build.0 = Debug|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|Any CPU.Build.0 = Release|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|arm64.ActiveCfg = Release|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|arm64.Build.0 = Release|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|x64.ActiveCfg = Release|x64 + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|x64.Build.0 = Release|x64 + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|x86.ActiveCfg = Release|Any CPU + {274AD7F0-D11F-4B6B-8BFC-51DEBFE40DF8}.Release|x86.Build.0 = Release|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|arm64.ActiveCfg = Debug|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|arm64.Build.0 = Debug|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|x64.ActiveCfg = Debug|x64 + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|x64.Build.0 = Debug|x64 + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|x86.ActiveCfg = Debug|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Debug|x86.Build.0 = Debug|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|Any CPU.Build.0 = Release|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|arm64.ActiveCfg = Release|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|arm64.Build.0 = Release|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|x64.ActiveCfg = Release|x64 + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|x64.Build.0 = Release|x64 + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|x86.ActiveCfg = Release|Any CPU + {D01AC47E-1A6A-4EDE-97F5-2D05D1BC7120}.Release|x86.Build.0 = Release|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|arm64.ActiveCfg = Debug|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|arm64.Build.0 = Debug|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|x64.ActiveCfg = Debug|x64 + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|x64.Build.0 = Debug|x64 + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|x86.ActiveCfg = Debug|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Debug|x86.Build.0 = Debug|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|Any CPU.Build.0 = Release|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|arm64.ActiveCfg = Release|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|arm64.Build.0 = Release|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|x64.ActiveCfg = Release|x64 + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|x64.Build.0 = Release|x64 + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|x86.ActiveCfg = Release|Any CPU + {0DD0DB83-90BE-4FDC-B470-6A25C11C1DE9}.Release|x86.Build.0 = Release|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|arm64.ActiveCfg = Debug|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|arm64.Build.0 = Debug|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|x64.ActiveCfg = Debug|x64 + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|x64.Build.0 = Debug|x64 + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|x86.ActiveCfg = Debug|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Debug|x86.Build.0 = Debug|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|Any CPU.Build.0 = Release|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|arm64.ActiveCfg = Release|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|arm64.Build.0 = Release|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|x64.ActiveCfg = Release|x64 + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|x64.Build.0 = Release|x64 + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|x86.ActiveCfg = Release|Any CPU + {32DB1BF4-77A3-4A49-8AC2-DE250D2CFCCE}.Release|x86.Build.0 = Release|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|arm64.ActiveCfg = Debug|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|arm64.Build.0 = Debug|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|x64.ActiveCfg = Debug|x64 + {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|x64.Build.0 = Debug|x64 + {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|x86.ActiveCfg = Debug|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Debug|x86.Build.0 = Debug|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Release|Any CPU.Build.0 = Release|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Release|arm64.ActiveCfg = Release|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Release|arm64.Build.0 = Release|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Release|x64.ActiveCfg = Release|x64 + {CD73104E-C7DE-4400-89F2-A04950649235}.Release|x64.Build.0 = Release|x64 + {CD73104E-C7DE-4400-89F2-A04950649235}.Release|x86.ActiveCfg = Release|Any CPU + {CD73104E-C7DE-4400-89F2-A04950649235}.Release|x86.Build.0 = Release|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|arm64.ActiveCfg = Debug|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|arm64.Build.0 = Debug|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|x64.ActiveCfg = Debug|x64 + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|x64.Build.0 = Debug|x64 + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|x86.ActiveCfg = Debug|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Debug|x86.Build.0 = Debug|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|Any CPU.Build.0 = Release|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|arm64.ActiveCfg = Release|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|arm64.Build.0 = Release|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|x64.ActiveCfg = Release|x64 + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|x64.Build.0 = Release|x64 + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|x86.ActiveCfg = Release|Any CPU + {C81003D5-1FA4-464C-AE8F-38F79305FEDA}.Release|x86.Build.0 = Release|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|arm64.ActiveCfg = Debug|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|arm64.Build.0 = Debug|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|x64.ActiveCfg = Debug|x64 + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|x64.Build.0 = Debug|x64 + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|x86.ActiveCfg = Debug|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Debug|x86.Build.0 = Debug|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|Any CPU.Build.0 = Release|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|arm64.ActiveCfg = Release|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|arm64.Build.0 = Release|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|x64.ActiveCfg = Release|x64 + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|x64.Build.0 = Release|x64 + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|x86.ActiveCfg = Release|Any CPU + {C2D73DDF-AEA8-43CF-B634-BC7F1D4E2F16}.Release|x86.Build.0 = Release|Any CPU + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Debug|Any CPU.ActiveCfg = Debug|x64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Debug|Any CPU.Build.0 = Debug|x64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Debug|Any CPU.Deploy.0 = Debug|x64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Debug|arm64.ActiveCfg = Debug|arm64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Debug|arm64.Build.0 = Debug|arm64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Debug|x64.ActiveCfg = Debug|x64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Debug|x64.Build.0 = Debug|x64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Debug|x86.ActiveCfg = Debug|x86 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Debug|x86.Build.0 = Debug|x86 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Release|Any CPU.ActiveCfg = Release|x64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Release|Any CPU.Build.0 = Release|x64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Release|Any CPU.Deploy.0 = Release|x64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Release|arm64.ActiveCfg = Release|arm64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Release|arm64.Build.0 = Release|arm64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Release|x64.ActiveCfg = Release|x64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Release|x64.Build.0 = Release|x64 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Release|x86.ActiveCfg = Release|x86 + {2B65A2B3-2342-4030-A194-5B1394BFCE6D}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6974AB2C-3FEE-4C5B-8775-A4C9DFB8D635} + EndGlobalSection +EndGlobal diff --git a/Source/GenerateSharp/SoupView/App.xaml b/Source/GenerateSharp/SoupView/App.xaml new file mode 100644 index 000000000..0f46d0bb7 --- /dev/null +++ b/Source/GenerateSharp/SoupView/App.xaml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/Source/GenerateSharp/SoupView/App.xaml.cs b/Source/GenerateSharp/SoupView/App.xaml.cs new file mode 100644 index 000000000..211d7f56f --- /dev/null +++ b/Source/GenerateSharp/SoupView/App.xaml.cs @@ -0,0 +1,49 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Microsoft.UI.Xaml; +using Opal; +using Opal.System; +using SoupView.View; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. +namespace SoupView +{ + /// + /// Provides application-specific behavior to supplement the default Application class. + /// + public partial class App : Application + { + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + // Register the runtime services + Log.RegisterListener(new ConsoleTraceListener()); + LifetimeManager.RegisterSingleton(); + + this.InitializeComponent(); + } + + /// + /// Invoked when the application is launched normally by the end user. Other entry points + /// will be used such as when the application is launched to open a specific file. + /// + /// Details about the launch request and process. + protected override void OnLaunched(LaunchActivatedEventArgs args) + { + m_window = new MainWindow(); + + //m_window.ExtendsContentIntoTitleBar = true; + // m_window.SetTitleBar(new TextBlock()); + + m_window.Activate(); + } + + private Window m_window; + } +} diff --git a/Source/GenerateSharp/SoupView/Assets/LockScreenLogo.scale-200.png b/Source/GenerateSharp/SoupView/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..c755b25a4d4e83447a89a0d169d7d1c56743a3d8 GIT binary patch literal 1139 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 B;e7xA literal 0 HcmV?d00001 diff --git a/Source/GenerateSharp/SoupView/Assets/SplashScreen.scale-200.png b/Source/GenerateSharp/SoupView/Assets/SplashScreen.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..7f40b29ffa6efa30429c2143d3ad703ca8581b19 GIT binary patch literal 19427 zcmeHv`B&0uAGS_o&9wP6WldSyRBG;%W~QdrRGRyw0=b}8Dk(0x@8Z-nm5o|1kbC8p zBB&_1OHEUXsH6snh*U15s3b0kh`cvF=lvJn^ZxL7j(Ic>-rswKR@o;EQ6EtL<+J_<_SS;G6Fe7o09AC^Tg4 z*to6)zW?#|6^|$dh23xDpNie#FZ~r19OCURU2u>0ndkgiK z`2NAsqlyH_z(m#W_H22uGyR;^9jiNO>Akx6S}Us;FO(nbFx-AD{f9lr{761pKb|`O z_~`XVM}NAKR(l?8XT&iP2%L+*I`{M~chcz`I)^LZMOpKT*pQfT4sJm#G7}{$gF*f8 z<9{>ozZv-74E%2f{x<{vn}PptX5c;dOzu7~8b*^YzU9UQ9p;-d_Wu2QsoS}b)YQ#_ zi^`VEvu@62Q||_J721x!+Nw}%hbT>1?aX}OpVfg3Zf3_VjCV@bgGXDVcq@pKgy~Q^ zQt=u)FfcIn7<1E?U4Q+}!vF?nGCaqtJ5j#H`Ge`<$Z{n7;(xy%s8!wG`lhum& z?+3M0MMVC(qwmiL54Lu=c^4YAe7tji*Up{ijF<~Ijd$g-lKk0YPmvouQV2_^9soT) zJUkpuMOcyd@#D{vL@)=nXZsb;DEL9_??p#t^90~Y{&p`~VCS>cj~i};-(M3ckGhg zqA-n4or(~C{PeGkmd=9TpFY-F?N8+^pR`~{q)JMxYa>7j~hp1&y&^E z)l0P-6%ua*2hXnHpnRr71G;1LwO4bP)Kwdw2*%EwDoAzIHu&=F?(Q}LMXPip!`1tJ zUtb?rOI+<-OC{SpSf@9$lzyUxlq6bctxKNLgE?C*NOotENa{e+Ry^}; z4_L`(hE6UnWFv}~@sT!!O{txRNLf=$tMppB0-ObYGs%HO>fm{3v2vY}JGu5E! z#GSi#6+;NbfP?f`CY&`v_IDqSfo;BAToZFm=W?C)+b)w|f2~Ki1uNjyWNPSQRkRf5-M*$`5F^*sK&&Rs@erxM&lHlOX2c zk-|9U#YnqhhHJNrlT)#)5bJtCk@OD7)bSXgYp{FrU_RQfwx0erfD9Ikh0qcYI|nVg z{?e{bq1)B)vy}FK$W zXJtN&o>b47kr;=zFgq7wZnbm93z#y`N>pF88_#W)nv{9cBMndV#I39zCRJ`>7RB^x zSIy~(Z6fDoODEK4a%WlK(5u?-e@5D+p`>u_s$jC^$eXFj= zeRY?L6|-t@X?%Xn`Gk3%YeJI0_IJ_x%u*Lk@pG`9pFGtULvAJ}uCrSQ7-6r`%*~On zU%yHm8X6uxd}yn@dw174R_Q_?t1b)S5#CGK#OEpo?*&^5IyN^qw>MTWE**3YIUz{m zeED+Aqmz?mIXIN|(I3KTc;^g`=;?0{k zWcPIJKg-L@!;Rwz%#9$=-M_z3CJ`(rE~p?NdDEh{k+( zT2qdXE$%G?E>qK#ifdlraT(xoCH4(GE8&x@F$swsCgJ#_T8(*XR*$!{h5-N}!SrNZ z5we`COLTrc4OYQh8^67EoNURIlxn{<-{g8De6I-=QmDoNJ5=)Qr%rLcXSz0QJgnG> zhmhaM)`iCMz>@(@oo;)jhecN9gl7{rXCBd3(v0=x$I6*!F5*dP2R1 z%N`C43~b)Yeq&K_FCfX=#L8;C|Ku|TslqfWL+o7HAz zapuhGO!l^GQD;I&m&d(T<1jb$RS)exT>o2vRk$19#1Haqgs#I1>^u#nYdL4a$CIND z(9|q$#Kx}XYjEpQJIaYWckfQzJXBxvL%pJcu4Z13K%dpt<>Q)Wg5`vnhIJC#v$k2t z>%?)p`Gx1=O?9*Rrr{>&R;Y@+0BM+nzFzIm{;t;J=FOWB)4^~sf`k-q?A{|k|NLv> z$@=NgliCWe2!;9i)izX%PB+hMI*$cMjvV3mr0e~o0`qQInZ))0AX?|H*%|5sKB%xXtun=@lJpRYkm`4!0W`q~h+77{5}`IVEV% z_QsHXVM=4dalUYzR&lO)J~e^|ks`Y@kBF%2YUaQGdb?+AZ0xm%pe8bb+HcBDp3evD z!VCP)^~gwJ%j?&#FA|EC`xAEuq=e%bqJMT6ZuBC3mI`7MSlPXci|zDpo?Q# z#r1D?O9Xpe&NZ0t-mk%1Wh4jE^}p^3NW4<{hhvfiT3MIMjE>DDQgiT0tiP%ds!-XV zFZCt$g3TYF+>}cWA^7m_>BNYhjg5_%ix)4_ zt$)TF8qOeDC0hQR(t?{4_Zx8wh09iU*k_(Ga9J2VAtiJ(b{-y785Pz(PeNHv{B68& zvd$y+fN%1mG;U!m;Tqxow0TQ)0VX9Ps*6dNE@zc^A1BwXJ5fj$r}=0nrr3#M4rSJK zU6rm*nflWNb}JGXj)#Z0*Ti&QXOlwdG3Wp}#MeG`KPodayE4lPaC!AQ z*sM=j&Mw%>5Vn3mtYNZlsabKfj;V0iB~_SX&Cc%>3X8e9_U{{oDFWZXd1_VTCMtJ= zcch|Y&eg-hi2s#Q%e#^;TIlO+-{>qRqmJcmat{N}aiP^bc9RetS!`v-oUwLX zwPPt?EN&I$#;glAq~Vb}Wj^`D+L~vcjOXT1XXl7g+O9rsIE8C%b@uF9c3v{nFLTB; zz_JGaNz!TK4>zPCeRAd#V)NhrB-|POG12g%dM#+?bbZhbNKV00Vd)-KYQI%Tk~CBwkZ-TS<;8-6}Z&GOCA zX`jFfu=LH3d1>Q1hPaK(Cc{L$ESG?FPO({M-uz0GT}k28oH5{Y+#2W$@}Rc9Uia%6 zGefS4wY4uXQ#{e<>3AC_{5N?(RZg8_tR#2Eb6UA#{?%c`6A12m6d`9`HN*1*CxKUN ziQ4qcEW=Dbt;v*1m6$rVQzq=llFggibuE!_@+s!s>U}8v;TLz2dC9crjdPgYzH z5~=)Uu94OS%OsO~+Db6e`V$w5lVjiq z!I%7`%n2TPj?nt?&W;+?2X}oXWHsI;Cnv{g8*=ucCR?jcy09SDlT%Z$Po|p+(?3K- z?oECM{ek}v;M6&82iwlF>l6QznA3Z+E+e3zr)^`&JUpn0G1q+0OGC2Gy04zPhKSsd z{+3VtFn-$7QmX6#5er}dnla^(V=paYS1HB@t&`bz9U>}B4p}yVCJI8}yW-2Vrp{Vh zv*H31zn0`v`7mYkFVAGXi5*S3Nt)eLsN4`Zb^K1~?c4PcJH*L#qgzZ?>{n^W31hP? zG;xwxs^@`zs-UV+e{cdh<^4_GQm}e0(jf^8${3gFc*BbE>v!YKCo9pVQZ@>1kP(eFSHu z;b!-ity{NhE=f@@`etpzK_wOEWh3%>PsL{K4*?X?{$6wNJ>lnpqAAQu;%%KK0p7+{ zuaVKw+S>XK*G4FYb`;*C_nzSomM2YkbpHH0)}*&}<=tUso&MXd$0@KFH))ltcT@0W z|He3~X&;ip#}HM#(9E;1&?3F09i&_PKByi#6ny&7Db6?QF)DEwy%M(RYXz1x+tqui z=Hok1N8G#ORutA#MOq$QX6`xc?>ZTA$k%7g%shxE^81=T|A8yoVynD!X9rSaTkSPx zfcV(0hC%zDJ}|Cf;5Ep{2&IQ<YQ0e8P%nYWH~FB*wg=tI?9rq=zr3ZXoTDlnCF9 zf;PRHXDOMicQh`b@*V@|SeSRj+jl33TS8cWVM=00gJ5~b931~k>Q2U`ES0FTO=*37 z8vc2I;n7agU&dWj)8=)qLZ z`+UP>dwl>a%R;uXgnG6QsF7Ld}CWR(R)+k zv|}flUF{N*tZrV^uG0oXqdy3Q+@4Reh-$-xy0>Z$2jtiE&UqP0uM1I_ro>9Gm7|m4 z{<9C=zoN8N8o4JgLot@{OHmu4wA2lZKNh+dPCW&+d?_2wUl=hi+ZO43PM^2wi~d{y z_@(N$5kd;Iw(!<~B-sB`nVb;AnQ%UF_E3?4v+_e4|=IFaX;_PUw{3zTm8rp z%M-(&!1mp8_wHR=UbylAvgFB3f4&tn0Rc-r!5bA|l9_}sby}i(Ss4Q@Xz=D-QdPcv z8t~r+{_PxtV1z1Wmt1h48Cz>{VTUA*JTt#cW-p zBh3h#xUOQ=IaGC}T)o*6QxXv^p2DanzS(7Z&Qu_#IKpA(3r41J%d0nu; zBgi=0{lqH2H0A@bs)U(oV7ra9`(q+ODob*>YUAtvELSLJ5Y`BPr+UdF09dc zk17?Rbn+%>@@-Sv&zoD=m`Up5y?A7h_z}<&HFN@`xhA;jpV{ZLaEE(QdW?;W9aWW; znqD}lNpSey?&+V~x+XDBnT@7e)tq~%)YR1IdFP& zp-pg>C1a7jOr_$2g{XU zPFqjm|H8?B53`bO3^^EDcJ%qsT^rVhPr#L!fUO23!b$UcK#yqM8N+9w@Dhc^ZmZRX z=FE(YPLsTX!Ps^SEtL#VNHl`8D?=)L`$Aw%?z4a zmctVwk6g1oDYF@ue@N+Ob2!(kRMfG!&aacbKJ3e}%354L?CYW{HsKFg2tp3~QBxD3 z6obMe7O{U%7u9hrPxD9Ob3f2)>A@zcX95N?;-<|vmH}Oa;V}F4nJXgD%0%duCVAvT zm=jTW{n^$kk5wg)1yj(un4xR9iyHHq1vl&Yyt?@S%9aqbSb&TDqM!V{0s+-H@B6d5 zy38i5T!zp#fYR^G$1ve>aFtt0;-vAV5{Swzs=0cO>WsDaTTT4HnK2`C^U6S*4$w8nJ(s*NQGueWCIWLZ4 zhc-hL3wKyV1xs*1Si8I{K0EY%i;9;W=F$KbG^CG4sXcLR2FxiFZcG85wPo6yS>aD#@MRb-QmSvRx)0L2z*tYsI4-4r+O!$2O zojoCTZ@>AO8MSrF+)^d(CA8vjsY|d){OYyEC6-mVzPKc5bhspT_?P>KU6n}TU;3&M zetsVT_h??%d=*R4z#J~R89PWj)Q>pqLmbz8TY_a6Gv8_Ik2LvsDSlfhyL(bmRN4Bf z>s(&&X(CK5`Ri*SYw}zGhN!tti;DB}^K*pKQdl|>@|qaZo|XGKyEn3i5tGqwHkD*q zaqi+@bb(gX;f(}}$lXc=i#ms@1VY^+{X~7E4m@Eh4-vpVJ!|g^SGA9&^bZU`|47%o z3$3kMcy8@A)HYt9`Avo#X6PJm)p?#;~1G&?yv zZ{E)5ni5hCfdnfonWsmE+DCYle}-8;?OHT$B;eteu*|N(0juQ5Rav`3LiI+lU19tv zkb5s^kTpBM-ZLD_o96;~)CV;LxTFa4IUC6F5ai2I;d;!V@z6h!j+W-+=T5dw(##xZ^BJ~SdbSQw79&i#iWj2{gBw8Wy+W_lauW6H zifOAucS4oEZLgr{=%(2_gcJJyI<4a5%~!8pb-Vq7iX(qN3J!5cS=7z3mw6X`P*6IN zv=2iEbcSkAA_cc&^sv9Lij5;XoWSx>#HiHF`AYcZZALip>)kIF#pA(5G`8@IOKwx9 za#lvh%H(sYG%PG^0TDHig^LD|zMceX^`ICXu#!hHLEKyjeyRLyR>f3{1UJ@H(7 zIXsByneknS8R;)AP0fO6YoFgu6s}l_A}U7qihV4@-vWv!zGxS0J^CVa`MrwVWmzVU zEyM1rxt9$=UKeTP6wdK@@7AJ#?1hRQPvBWT>+^wn+^?j4Nsx|=T+7*hl@A(A-CV&VE{0h+M91j&1KW zC?TIQF^LHz$&Q1kF=L`PT9J~R0CJ;0|E&Lw8!z}DKQM4!EiM1m)Ap%GMx&)A^KxHd0%y|1n+NepF3lpPxI`mC6b5GyzEmw zfH_i0yHV?TB@?qzkhdK*;fEMsa?@yc4^}pM5@QygoV+pX>OCBp5;7FJdK~md!y4o{ z!1l+1tUtNpa*`E>yJb2!SJ+1Ll|0Hecu5boH0zGbdHuueE#U_75fJ6qiLU7-9(rJJ-sQz6`$Eh6} zPXv)b9~}y7=E4ZNVPMwEcIgH{?gcdHt3!+3lkLM+dd$frf7rh>Ri&xOOq_##1NyL+ zR_$(zJWsk=b~ELnx6hE0{;GKi zS4fRamBF+PPEsu@w@;%#zi{XMW+k{#(clHMifQ#XjYNs zRNKBkBpNpuHR9STeVq;GAKF$8Rv+zudN5>3lXHG=N)%qv za)U5XdXie)Hq;fzKqMgLB6%m zk4o~6(;xZbtn<`qoB1_h`p6~nNzeBues-M^-+Ixi88#qJ4gu4}?=bMJgAm{a(aN2Z z_Y9M-4=dhGG>}vcTGs;6ES{V_&#;f#i?ew3xg zK9!yrdQU!)$bY~AQjJ|06TceUN$vWv?WV*+7tge=6+Z@7*glj{2&hud}5(F>W9|p3|9JE|601WAo!xNQnlB*qnop8|S zrTiB5ptR)1yv&@LM@tz8PL!@gL_O~$o#@WujQDI zpfvscDt^?J=TJUz&6!WMUkxhb)fYz%m=)T0>9#JI%&66@c&cBExp;4jLUdW8^Y7W1 zz{G))gPlub?vb*FNmXj%k(@~j*)P6VbdEIx4@k{BJw+pLUc}Rs9jv(4E$byo_}Kz` zw76HVaW!hu^)&bpc+%FQ!ZTHay&ywx6re-h;LOchw;C

%CEG$+i31(E%{_8pfhx3zf)6w#IVE z`!Ep3(u!Rw@HpNlXBNK(WfkqQYvU{4xfFNZ=^8WN9Ir zJa4zu-2PU{h)ijm@OeDHvYIXE{rBI0_kebrtM}G?p+nfKtIS``k7?cS!m}_~+es3O z#adZeSuVMs)mU|O>p2o=ZqX@A%MA?;v!nED!=Z$y0fQEv;280L(@{8pSbqq`#sr65 zl2!EiG`Tx&F5KB+5bv)YTQ-Q2xoNN6psW^$JgWRdSAXOsc5taWQcul?fE)+?)CBbU z7Ry6Ur`fHmU!J$d;;ImJ5XG!YX0zLB38AygxWb#bZ;aWFlBf}|gV?4O|0j+Ch z-7G}DVcPC596oY{eg~&4XKwsnP`?c+PD{qF;)7JDnTmi|W@MRFOT@%GuKwG1!2ZwF zVR;e;Owl1+yMWJ?**GK|9E#f9!%kBz;mgT2A^e!VeyZ}WiR4n&8$)u*`QyjcAmArV zCOZQ+3;4%~yt%{%AAI;l4S1~$=Tg*MjEY~obd`;aQ|>ofSo9w3^Fs6Lr_?I!ZZG(X zh5+_^2 z6GJ%Ia{g}vot3yZnS})fHJ&yxIN+|$EF@2@t*u?wAp5icxBl$e7Cl8$M;$m5y_^zq zEJhBs8e*FB%qv3eePCk7T0C{h`B=n2ru-(CxtKP#w!VdvKeopSx;j7~R~-^-@$o{L z{WV5okZwbOv9&eIfx@Wx&K@r3a4rm|9i(0$f@2lD%6M0S4}LjjFQ@+cMKBSqR`_NH zlD-O$W>V-!C98am_LEh`v7@M|4xFVhE|a_s2x;f!VF9CHq91jWjYz}2dR$VStP4xzzBRD1g=XErnvLOE?KT!%%qX&w*LR(LB%M#4!nK+k!h+EltPc zC&XrWB=P5dLn-$WYhyG@wnt@_F~}olmYR?~y~p6ZhM4Nv_sO!^?1T*KEE5U?($;+Bwa{k`2hG$d|30WqJ(0wQNz zboS^Uf+F7%GQ(CL((ZBy`-(EKGu3~ai5xw4!c^$AMe%-Kle!7qRPjtOC1L0#6*2HB z92}P6(@*K~rw73boI91bE*+z9mYFCUhy)^n-Qb= z8=?7OPMc^)h-h|JH0MQu4VxNsa;vw$8-KjK?#K+Nv6;o$luHvU>oibKmDn6vaAn;I z6r|En%U9|3<|)Za11M60-VPt+hhs=Tzh`#3q_*P^ob#f|gk8bb_w|G0#A8iCZu5TL zj8A(3og{Ac_Di@`xm%%L8Az9gJ^g%c?v1@DBS3zT8sukSckwh55LNC}>&YdoXt@|r z%~F>NLhJ!{2p0zGNmu2*_UwQzBWkVmU{q9;GM5zUMJqY@;SyuT(u1j~n6b^@7e$;* zI@Zk=oJfF!U0N&nvHDdCX&=myA*rwfrNZ-CCXPGMup+5w3G=te(8~XkJDU&G6XDug z{Jd!L>}Jm417z3q9jqre<696y58$&V5j3OEeS3&#L^Boh(Xiok5N z<)uKB`Ud6!J&BSEqVPb>8mj~P%3i=2t>EdBJX-s)(&mpnrF-}8?FJc>)UJKXCrc9` zR!b6x#k5GlBB^6jToHfXOxYL1k80kc*YJH4XgEjik2OI}Tj{99!r&oz1tHM0ekxG* zUXG+hKZk(!$uGZ^;Rjg^J|SijoM``S!#H^>X>!D=NnREH!c!T@Ja1)HfC_w5^jsVI z=32)IC(p;s;MZq<{q=nguZ~l(ZtJA-x9;05y$Gw@apRE4%Odbug$cilYM=(kLV z)h~6R6Nw(KbmE_R#W>w#VQtN&aby@s=BLp=$_{6B&jI_yL0hfoik8lIWcsjo6_q0%uR;ZdZ&eD6krS&$5 zJ)pCF--Ec1l1D6u8QwXW?XY`Ixg{A23d8l~_g3;QtzNzLmpYpepK~ntXZH3lPVW3~x6v`w?h96ia`(;+ct~S+6!^brSb6D?%D8 zY1dU9l>n1$aRJ*Dq~(lh=Nf~)CONT)NEmL9rbzfS`zNz3RpJfRpMM?+*Ci!0T%(ma z$4faU{?o!$@Up6kx8lZ2CdNYv4EDUdAYuL zbacpSO9;k0lJdG$Q}67n3uqW|dwYvK&R1~mekhrCjcU$F-Sk9PC*3NQD@$kVC%`@q zO9m$uJ820BLF*pbVD`Lfb+YUVP;{B16JWmwf%)T;$^IT1k*Oc>@zC!_y2^rdNeIlG zrFZn;Sh4)CeO2F zne1?KXINTSgy_9JV~J`vi|0u}#MW6y+#VEJY_a_QqSDBEu6)NUmJbb|e6>Hrt3Kc$ zQTO`WHwXkm9VSfqCGRc*9ik5+QtS%AN<6~K3|@e$w?_l~fzpg)qwnQxnH92wWX1AY zZBX#Cow%?y63#+A4h;*#1LrP=n;2@CQDSUnZ7nO$t|*JuC3$Q871lb1PHMV=O_KKT z56L%I>V0{0hZGE|oaS*T9-AouG=-Z>KxHfs#~e$s0elO9!?2|1gj4&2Ghwe|r7KL+ z;MY)!)9SE&>|1%XR6p--nOs#9(SXQukeT=SMHA3};Fr{Wh5};bMpi+&@3yLuI`=gZ zYxG7daDz;OJE4>Y@YH}<_&N=hOFUz&<{N=K#~M{6LErGmxB#>Lpv@x`Bjet{l_RAd z%eP+SH~Z6k*$z2Nb83pDqBtjflxN+_DZon8q&-f8d^vaxsW$tuyHX^@)!(1qMd*A{ zE`0{J@!6{KN9dFf(P>ZRhC_WP*;@$vC5_Axu13eU)mPK&Go@YGG<2aAh~S<_F~1)!}8Q~WPE zV@JPcjC;Jp^hWJy2TnxWamudZp+5proCmBn7Z}0BZD)HVyKcYlmXnXwx~pmWrZY?3 zN8-j>D@NRh4RY>JYf2L|$TxbwJU0ZD(@yDAxP7cVOC1Zz_EahS{Jy%n+D5tGw^pu5 zPg@A${%lWWg8bY-+*#s2V9W_-p9@?BxxvGU!G`w_M_!qjKV@Md;owGsn`?R_!X$#J zTsLP{KKGs`Z4Wlpw#1Ea=}p?uU24qDEYM%I;h1fSo1<~noOFH3nuQ_})LDtYSPS!6 zaVkaq$iag_Ki&SX>^65XEV1-y;kX+>yN=C^-Rh`~BNZbcF1pFi4*e|Co=HD=_;4~D zNN^*IQWe5doO5i{%I z#6o3|?C_W4kS0$>Nt>g`z>*~H_whl!8uVrshGbRhlU6qoHXKx?US-l3wbs=Ssk^

={lzv_pl_wR7jr4JhTz;7Y#$bRJ~h)|AS9{PpK@ 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 TmmHtj00000NkvXXu0mjfQ&qxz literal 0 HcmV?d00001 diff --git a/Source/GenerateSharp/SoupView/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/Source/GenerateSharp/SoupView/Assets/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000000000000000000000000000000000000..3d36669e7e3f3904ec0c3aca660a29c1dff2788e GIT binary patch literal 648 zcmV;30(bq1P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0v$<2K~zXf#g#p1 zQ&AMh-wPy=5>U5dGnB4^nFK*XKH3n-s8a>0t)NIKv~+865vP99p=+Ty2nJn(j`^UQ z)WNA#L8NsPM2kXb0!e@O-IJo+`(By{;tww8BQNKld+s|o&cDVL8%Vugzl9m^^?DPL zNTlVu?&nUYvsWk-zUwFa2^45F8d=N}R^CgP?6g{~a;a20mDnI6)*6Ybn7Es3G`t%Ns2C0^s%Ir$S!j-E1|(q0)4nf z?jZ6?LM3t&k#`dQh3{1n1jSxcbX`Jqt=tgTAe4ZDqUXODu?cYvLJLszs<=vQUt9yL z0EhXKH>V__L8VfOQS|(p=FjK7xCYik<`BP9Ac?C6t%BXpWHN_b8Dm_8Ic8vqTuMF5 zPPRCcMdjPD3Q*_;U!0aOh#E66CB7AFi6n0Z7#=!}8t`ShUTih*+=e?Fs#U7}q_ ih=0WP^r!zF$2kLndbm*lF-CO&0000Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1Yk)-K~!i%?V4L? z6ImF?o3_|SAzcu>qAOKcL5jDcEwyc$TE$%-)(eWhC`IauqCO~!ih?32irCdB71Re& z!BrMDi}seN4=RG9ASh_ddbhMvp}t5{e<$-Y&kWeTz6#-jumtfB#WV!JdduR_WhRW}l-XhdhU29c@g4^$XDz~(& zt7{VH?w7P}v@62UIKa@@Bw-Xf@`)=tM8c$^T@gg&i)-eo*rem+t~Fk44~WxV(43+z zgkjVwu9=}?la7<2^-f$flUU{Fh@VuPROF_(F(9xu91f3>FllHD$;rvNByJ1{naHj5 z-@3ZGqz*G}Atfax@2Scj31dLa)U2$mn=E!qB$aR+?|xa~?_s7JQCxxu-p%@QN8*Iw zScrOvq5>fa`vozVXh$n6D;p){DvpIH5HlBZ3_)X!O#dK82{}ZCt{NG4a7BnhO>X9e z64SGr{SMb@2iRxT8=*5?6Y>@2%qp(>b_9)+)PQj8DWA_*Q&?E|SyEcKF61i=w`~|D zXt0qPkVmu{s&m^2?UOJe3Z5W+xw*M(aR0JWA*!>Ox$}>Nwn(TDGYq+vbaV%T`fN5$ zyvokbE+{Q6{UEVrv=>CXFlF0F zScdR(;#(qV6*0r2_yqGOm5KK#ps@XFDJ4P_T=56Ym$-W|1O~*lOv;2P5EG))@!tK8 z5Nnx~3Q;guUW(fTmGW|z`$a-aq+CdUcQC)--yyCgegq+t#WmATRl3EuL`sDqg8q7@ zNNA=-tYx%>sMnmd1rln*er%n%y|J~1D71udB{$M8G9e$*nMIPe1&d;UiT<~QF|bWJ zFRo>Dg^UunfT3{#L01s8RC3>i1#;n~qu8T0EznWzL*rC#=4nc8u%KBlY$5r3}5{R7(9wKz&oIekjm}-=?bP p^?L6W7Z=BS0iGsJnuL*&@dcVPkBYhAa)kf@002ovPDHLkV1m>yI;;Qy literal 0 HcmV?d00001 diff --git a/Source/GenerateSharp/SoupView/Assets/Wide310x150Logo.scale-200.png b/Source/GenerateSharp/SoupView/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..ec71c7bac80d43eec6fc948cbfd1acd98941bdde GIT binary patch literal 7808 zcmeIX_g53?8#fG!u;?P+#kEpwAWKJ(4najlq`6d+072;`AcSHd5R_GRb%muRhOSaX zdIEt!2(m0K5l})kBtapB7$8D`fC2K1@Bi@r^gMIUoGItb-1l7fb$!Y;f8BPmS2%d; zpp=x9g2T;gZcsA~t5P}gN1OK0O&N_JdCxXO-b<_g1@ZbKguiMPkNMeZWj+jh@!(T>=o*j)~o z+W*`BZ;60#?p?vYnTVei6jWy>Cq+WYAG;G3SikRS>58DX#JITikG{UXlZuLpFiI4& z9bIRDFgWMGAJgnyXjP9N1kXF~s?DE%GO1|+;(x-$voISe2!H=sgML_NKSmE) zk~djj-77Eu$*T_5wRfmxp!1J3g*!QJzmyhJ8$J45PnFWM1%clOo*vaN``@j zGmdfNzxq3zP*Fi$)oxd)US#3E_&jR)l8xJ246zkYw?29D zfARGAImbJh!pA07*B2y^p%oKvSjxs(hrPK6VNaihTV5aT>7(J77YNPrQ)wEXa~$=- zCAT(>tKVnV6ADoJ0;FhhaZ!1VA}L<;uT<{y!&S<_O=wCJ%`KpIQE$KfD%{D6!^eXr@qtGC2(?FmPZuZ^;^6P4913ygY`_|pVrsO z+={`yj8%(((vG)XU6OK0pgfJ_4rzlxC`!$$wuXk^h9ENm>FMdmH7*xXN=D{qP+mi= z1H?|@C5%Iz7E*^wuWTCB5ZUYpdwA`xV>hz`*&K?Ip(7NKBg^l<4zf zF2!EYWq{n70B+{RhGJ|{+~P!2R+lUti0*a4yZwqjzJw!gC--WB&)tC(<;L?TQUZVs ztZ5lgN?ajvGcSaZvUIuQa~V&bxYYLAymY z*ZHp3vgPUj)LQZRw3iB^`lFD^#TUuIIMJb@i#iS^hJFS2kuVqxN$mz<4<=9lNYt@R zRV(V0pQ1w=_(rS5Va-8ptU0V-+z>tzzX-%p&RT?~7>eZbqGq8Q^pA2v<&oI^l48_L4( zA-SFAjAY){3~8`^rIfP+$GER_>SS4IgG&7uTlvrhb(;8Ej^;ANYb|}6$Uc=EBfIUx z8@ltv33+EUwpsxDE*3+RE>DPdZ?HtKEF+$hz0^A5Qe9m~*mYpS!on&^Xu#OWRBt$C zz&y_&T@d4A{(SB-ze6^pZH+@zas^x7(`E(@y+pjTz;U!tB(OZ@&AmguztqdTZ8@QC zm<+-532m%ZQXRhC=-RL*zFu(>OrVN(VB7EAHR1f{;7R2**TMWb!Qy+MSW_>S>afLa z_}X$Sqx{_sTPh!sy(=no7^dD+%W01EMm`!uBDVd+hp^WkUN^A)*IBVAb!K*U);%J% zJMUnV$A`gGEqWmV4o`16*I;|j0r~y|*Nx;;0QWQA{C7sBl#`cvyrSZ*uHbWZnV%n| zvCpqKJ<@I)MPi5F1LLUwXcli(pehY`uX90X>Ba=|UtZ;?){GE#-dU|%Y0ML~N0H0r zPJ$C^YI{i_2|s?5%wJiFGP}Tt5*^dW+6jFtWg^CFffJ^qfa@J-sZaZDq}xWHj#D;^ z($%|%$T_ok950X z&gh{#0%+9r#d-D}KZZg`VA3s2Q$&YaY0B-AQ2gRgK=vBgzI$GGdi!B&NcEfW7*<8B zxCe69)bm5Jc}q=AgroL^+1Of6c8V}(2`j*I05FwmVP>4L{diEHsIj*s;sO z#7yEcxa?!=SUOi$_HCca*=1qQ12YVB~`nBb_P;1xKQAd5bn&q zS5|ohzbqOueb1A>aNOs9_fvH}{)mV~4nBTVTDfsi4@M!!ocXvjaN5?$Xsud7*;M8C zkfB14r<~X!i@AzTr4LL`0z9aLol~|njrHn(dt@Q-3HadkE}u^!(HT1tGoWPYj!|t z9PzVOi+N4$9L3?3z-EXzthHseHgKMHu~3N{c(QeKb5ozHdHqKO1@pPCd%vgt$@Y2X zUjFZcdx?pn2^kO0=m7cVWY$nC=(Upbz({gN#s3IbV^UI5G((cER_+(Jy6JZjXZpQ6FL09> zySJeV(aJzE()i|6LzJ*E-@?H9x_DK+`we5L6fbg~B;#lu-qdU@0Q;R`{{H^%#BGsLzBruaxnTA{ z3{+$Sw}iNRW3vZmVs(LI5QN?pFFoUOJ4#E}pO(Yk?~xkga&G#smy_!%u%RG#ORr|@ zq{wJ!YZS93NErx(1?(8y_|8iFHia|FCp&)g+{fwZa}*7j7Ul2m;hkVLgbTF*&a|s! zB<2U?eZlr~S?7h4b7*_Tn%-mJ1VL@9eLJCN(hTc_()6K38nC< zGBVE6A77j@be3OB7;H*rUTww)+34x{<63q3D_eUVZ!1FJbUe3bVW`m2^#jI>v&2yP zt*h%8<8A+&u%$L}vlZw%1?GM^ZY>DwyIEFHI^?7mDfhFYV&bnm96?815)Pz78@M8; zs_wskYSQf&xI>WJlhG}#WzFxY1Eqy&;f4>PxDvmR5wQGse64$U%+(1=RrNQJ`!m%+ zVwYBF1kXB~V{6O@=XHL%Kub)9Q36g5@!aX;*t~#a}q1;$^r|DJoe3QJ%+5Y(6b~`>sL2Uqip;+sU`- zyIhX}S6Xab)^XFi@A2EEZEGO_jplVbyFyfD&!su4(G;qSnd88klMc)2HeMHTG82~U~oe84}#g%{w zM~no2>~vo8JLU@r$7Kta^PK$fsZb6=uPy@T-REDpG-fm#Jv34tlp?>WoIcol6%aEP z{KrMQ zty#gAYi#j(Ja9AC?ht^FffabI*RLh_w2N#9F7fS%?iM=>L^z|~!O%1!EsxqdlgB)l z&xvZOcOH#nGaAO?J`RF*?+p!uy}iBZhQHWzw(_KdxZ~Y&r)N$ywnTUq*ZLiXTiC8m zA0VOi_)+anlDYz>s@{J05G4Kd0kfC9w%+}S83-`~A1TT^qr-7_SeSt%{t#T9l%VBL zEw*pAuR8!?M9P0+eHWHWcHVdxHH=(>K7*2q)*k~-!i0I>=4`%$`~OVvfXTp=#3Qn) zD{l*m|A}X!=lY%-vlxV5Id^v11;zDngWk@d@wc9>7s5`lqbIm@B2Ts5L~mNhR{TL#QppC`-bH#%u>68H3M0Xn(Gx5 z6qsiGa9%b}u=bWrM6TtbZ#_wH&JOfhOV6#+ZTPvxh?#8yud2?kgO`m1=6zRbp$^D9 z$<;k+ZN>RgwYJl(NZ~^N1S*#vZixess!2=qRO5cK2fiXCxWn(6qOJbfRnY^{Iyxil1@9&&5rQTEH8nNX;+Ee@Dh2Z~a}`?0 z)cv3Jy#rnGCS8L<rPn4ppZi z5_LEnW2WKnmfe?gt3W^EM;dtmw|rm_&^ z^7U#dYUqwLM7xiS&e~6eMv*F*DW;aUf9mu zPc#)CPvJw(`tM&Emz9;J_E1W5Pk%4$=Qf9$&DhhV>Z|V%CzqnE=KeOO8bKht_!N4E z*_|~P>(&3(ilLifo4slRt_$adDe-Ukr{-#39fop*PkBD)4dPEuuSfb-=B%ZXO+S?BqL{B{0D6Q)WFfh#Fz(@1- zYuZl}T(50~Icr+It?YpJJW=RZ5Bm;}g0OQEHpacN{o45xSgqJvNQt)vEH)~SN~ypG zHvhZ?P0j$3k7?>ciILrEnnC^fb$uB_}i46!028N@nY*Z&SE_#u3tkO8F= zdC6z0+U7E?{JaQ9)+mQuEjW4b7IT48qlqlR0!=AIpyqt4S|TQ+ZnYx;%e7YSt=@^( zkM%+dxCBAv>6#wuk*ndUPAucjp6+Y>PwINu>xAg4b=hJ+eWM1gP@g=RNGVTm@5w~K zdZ&K#p0^cMipLAI`)m$R;b$<%3hq64(6(Gwg@l&}WAm28eQA2^*6Q8}mikl}xg00F zM@9JA+uK9+Gcy1FTlWqh5(6DuipzS#dlY`e(7E|<_)OdCOXP^bqyF*?8vbjNFiu&U%qB-_|H! z#u<%=3$^L{62pPabYIcNP?=}-};;Z^CcX*2S6h>1X>_lQvB1@SI!45JKuTZ z#C4I#U}`s_mseGqnmCbcr|07JgaE$pjJ>Xz^%|36+8JLbL(-FmBIiAGcv*+65&)!G zlcLb~x0P;gY?vsJJARX&l6t%I&g?lWH9|YT*u?g1z6-sqo(b-Y9@~i;H<>2M*_z9kScc~DyU zviko9q9tRF#-4NjZGf+ZQ9}xnbSQ5s5kvsbjt43i$j%ox<0-1r9lyE4G3s#teTiFf}2n>(jdl`Hj(m{LGp`X4d0%Cu=tE?^}_fpGc zkQL+8=60#Dg4Hz{Yhf%2{QCgJqJ(ax0^kABkpP z?SbehYoFcM)0(ag+nIs3rkQB00C{Cd{|$vgX;2RfBT+YZQae>FQ~vx5UA){jgpG9X zxLm=s05#xkp7$h=(QxjvqeH2Y%8i^8D80e>xr!JhTJl6e`EVf$7mro7N&rf5^Z52> zbbO^N(4q4!Ec5T($+*ha5xT|Et%tmgbmvg$P0A@IC|6EnEy`!V5wJei` z5)K*vc&sjxhS5v*%h8gkbHp&z*Xk-3_?hD)z&wnt^`PR0O8$BJQs%(%s(%e^XH^Hq zBUJ9G^jErKRUiYS7*+^od%PWTWCBtY8IMWc<6vQ|P3h^}pk!D+=aP*qzi^t^IH2a+P&J({&b_KQJ)R1h9H(%s&&c;3|NFee@&TN)9FY zO>7K4eE3i+i$|Kzaa>9K)-5N2;0C0Xza=A2Q)*)u0o#Z7P7#|>89vGf)B_nA|*QrqbwLvHfX^LHnJR8M4((p zG|#9h!=iqW&F1?0ju$@qHx6$NH#B{mV}TWW47a{iX;@nt!l5+9H9%O|)6o^a9E#YnqZG*0P9p8Qzm@pn@lbk!Ulv zz{Z4~9Z4%(+eSn*6`KW;&_EpxTX2i&SuB=SPVwqrhl^KU_x|V@hF6cVvgbYLDmp8z zd)7`?TU(ww+vzjx^w<>2AIUPx@8{>K6$g=tebTXsgKK^`DNbk0RJKf(fivg(Lr5eS zqnnJ>9_jmRzxGKe{KUw$NkR>`+59v`6~UpT;1rEUeMP4(_Eyo2#HxLMr3c%pO%PW! zzHJpp3SeXRtfFaqNhw1DqK(4T(?~&Oq`>LnN@DEK^{z?wEbj@=Bnap?p;}RFhgwg^ zkw(Dp7RH!kY7s%h+XfT&px_BjLM?afUT)nq#l)m5uuc7-Za4sB(SwR9^#3V$Xwbgj z$jJm+N0L>nnC)lj7hcnhvH`i1CWHI@_56$`{p(Hu?LYsV>3#j@-KI?rL?j075eO_H zK{2XMxOoTT39-9n{{$oV@HjXGne(4hHv~C?5M}t+E%JD{4OTOXo01^;6bI-5Fm^eN zr(!&Ko`9ajrWB!&)=;F(cz}D971iw&{h)Y*(&3;SjfkZMfrSlv-41#y2yRL8N+^+gV32Z_VLHdzJ)Aevr9so_{EMsGkFOSX zzaX1JL(=89)r@5$fnO5)Ow)EfA3d^ly&mh7`hJ8O_j{#FsTo*bu2Vyr_FCygk*{{! z>NEno0mCfcDU8R)^y@n$iMDi>$Ct@x^4|-E({%jbHY*1#fZle2uIMB#_>gti3sF&i zJP7g0CV?}${0F%zYlWDy9yn%ozcY}oOzjyAQ{ zW810G_0u+(U6Y~>C*)5_R5R7sfwPDx=^^~yd|CS8?~hTGbxLOfD$1TxI)b{udlsvE zcqA6mSI8d&5P=;6em-~V2IDiLl1BPI0v?tOj$Qg~^@+@QMLudUMiH=dfGCNH2Sj|j zuw$>xqntx2isdb1=4mNDW`OKS-2bi;TBmXjfrq!#`=xQ{n+@n(2 zT{_CeGMY*_MNp)EP^-x8K95%oIzv~+D@+D6z4JtuNMD}nWU8sD>5DGz#sR_v@b1o{ z#-J4T&Drs_KdZ^2Etw!qjoT?66EP1g)Nm>8YcMDO59=r1><$BM(jLNYMlb^#a+=)^ zAk1mZ#nrF0WakNl&xG(DKw~p&V^yG*Fmk6w$NH$_>3^hF%9jL90D6?-63Ta88)?8Q z8}epDca9{x+GzG$8mj*(9;|C+eeW?IHV+sc>CqEy^O4 zDK({2u#dPEtNl@P(z>zGN9lk+XebGM;ze1lNEdIVO#^D^g_+!hi`=`CUmB$i zOJyP(j{}dsa7C=_$~7xBN=q$q0YNDxwvbkqdY9_*PWByZO<3SEb<*U}lC-O(lz+p? zQ>QGOYHIk|Jv}{gz$!=@TU!(DQsn>t|4EpZ!cW`3r|>Q99#hHA{qBze9j?1vtH0|1 G=>Gud<0IMt literal 0 HcmV?d00001 diff --git a/Source/GenerateSharp/SoupView/Package.appxmanifest b/Source/GenerateSharp/SoupView/Package.appxmanifest new file mode 100644 index 000000000..f4ca696f5 --- /dev/null +++ b/Source/GenerateSharp/SoupView/Package.appxmanifest @@ -0,0 +1,48 @@ + + + + + + + + Soup View + Soup Build + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/GenerateSharp/SoupView/Properties/launchSettings.json b/Source/GenerateSharp/SoupView/Properties/launchSettings.json new file mode 100644 index 000000000..f80f2546c --- /dev/null +++ b/Source/GenerateSharp/SoupView/Properties/launchSettings.json @@ -0,0 +1,15 @@ +{ + "profiles": { + "SoupView (Package)": { + "commandName": "MsixPackage" + }, + "SoupView (Unpackaged)": { + "commandName": "Project" + }, + "WSL": { + "commandName": "WSL2", + "environmentVariables": {}, + "distributionName": "" + } + } +} \ No newline at end of file diff --git a/Source/GenerateSharp/SoupView/SoupView.csproj b/Source/GenerateSharp/SoupView/SoupView.csproj new file mode 100644 index 000000000..c71648a0e --- /dev/null +++ b/Source/GenerateSharp/SoupView/SoupView.csproj @@ -0,0 +1,57 @@ + + + WinExe + net6.0-windows10.0.19041.0 + 10.0.17763.0 + SoupView + app.manifest + x86;x64;arm64 + win10-x86;win10-x64;win10-arm64 + win10-$(Platform).pubxml + true + true + + + + + + + + + + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + + + + MSBuild:Compile + + + $(DefaultXamlRuntime) + + + diff --git a/Source/GenerateSharp/SoupView/Themes/Generic.xaml b/Source/GenerateSharp/SoupView/Themes/Generic.xaml new file mode 100644 index 000000000..f71ccb704 --- /dev/null +++ b/Source/GenerateSharp/SoupView/Themes/Generic.xaml @@ -0,0 +1,111 @@ + + + + + + diff --git a/Source/GenerateSharp/SoupView/View/DependencyGraphPage.xaml b/Source/GenerateSharp/SoupView/View/DependencyGraphPage.xaml new file mode 100644 index 000000000..5798e33e4 --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/DependencyGraphPage.xaml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/GenerateSharp/SoupView/View/DependencyGraphPage.xaml.cs b/Source/GenerateSharp/SoupView/View/DependencyGraphPage.xaml.cs new file mode 100644 index 000000000..21333bf46 --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/DependencyGraphPage.xaml.cs @@ -0,0 +1,26 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Navigation; +using SoupView.ViewModel; + +namespace SoupView.View +{ + ///

+ /// The dependency graph page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class DependencyGraphPage : Page + { + public DependencyGraphPage() + { + this.InitializeComponent(); + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + DataContext = (DependencyGraphPageModel)e.Parameter; + } + } +} diff --git a/Source/GenerateSharp/SoupView/View/GraphViewer.cs b/Source/GenerateSharp/SoupView/View/GraphViewer.cs new file mode 100644 index 000000000..72918b61e --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/GraphViewer.cs @@ -0,0 +1,223 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using System; +using System.Collections.Generic; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Shapes; +using SoupView.ViewModel; +using Windows.Foundation; +using Windows.UI; + +namespace SoupView.View +{ + public sealed class GraphViewer : Control + { + private static int NodeWidth = 200; + private static int NodeHeight = 50; + + private static int NodeSpacingHorizontal = 80; + private static int NodeSpacingVertical = 50; + + private static int InternalPadding = 20; + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty GraphProperty = DependencyProperty.Register( + nameof(Graph), + typeof(IList>), + typeof(GraphViewer), + new PropertyMetadata(null, new PropertyChangedCallback(OnPropertyChanged))); + + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty SelectedNodeProperty = DependencyProperty.Register( + nameof(SelectedNode), + typeof(GraphNode), + typeof(GraphViewer), + new PropertyMetadata(null)); + + public GraphViewer() + { + this.DefaultStyleKey = typeof(GraphViewer); + this.SizeChanged += GraphViewer_SizeChanged; + } + + /// + /// Gets or sets the Graph + /// + public IList> Graph + { + get { return (IList>)GetValue(GraphProperty); } + set { SetValue(GraphProperty, value); } + } + + /// + /// Gets or sets the Selected Node + /// + public GraphNode SelectedNode + { + get { return (GraphNode)GetValue(SelectedNodeProperty); } + set { SetValue(SelectedNodeProperty, value); } + } + + private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((GraphViewer)d).LayoutGraph(); + } + + private void GraphViewer_SizeChanged(object sender, SizeChangedEventArgs e) + { + this.LayoutGraph(); + } + + protected override void OnApplyTemplate() + { + this.LayoutGraph(); + base.OnApplyTemplate(); + } + + private void LayoutGraph() + { + var canvas = this.GetTemplateChild("RootCanvas") as Canvas; + if (canvas is null) + return; + + canvas.Children.Clear(); + + if (this.Graph is null) + return; + + int maxHeight = 0; + int currentOffsetX = 0; + int currentOffsetY; + var nodeState = new Dictionary(); + foreach (var column in this.Graph) + { + // Reset vertical offset for each column + currentOffsetY = 0; + + // Update X offset for the current column location + if (currentOffsetX == 0) + currentOffsetX += InternalPadding; + else + currentOffsetX += NodeSpacingHorizontal; + + foreach (var value in column) + { + // Update Y for the current row location + if (currentOffsetY == 0) + currentOffsetY += InternalPadding; + else + currentOffsetY += NodeSpacingVertical; + + if (value is not null) + { + var node = new GraphViewerItem() + { + Title = value.Title, + Width = NodeWidth, + Height = NodeHeight, + }; + node.DataContext = value; + node.Click += Node_Click; + + Canvas.SetLeft(node, currentOffsetX); + Canvas.SetTop(node, currentOffsetY); + + canvas.Children.Add(node); + + // Save the node state + var inConnect = new Point(currentOffsetX, currentOffsetY + (NodeHeight / 2)); + var outConnect = new Point(currentOffsetX + NodeWidth, currentOffsetY + (NodeHeight / 2)); + nodeState.Add(value.Id, (node, inConnect, outConnect)); + } + + // Update for the next row location + currentOffsetY += NodeHeight; + } + + // Update for the next column location + currentOffsetX += NodeWidth; + + // Check the max height + maxHeight = Math.Max(maxHeight, currentOffsetY); + } + + // Connect all the known nodes + foreach (var column in Graph) + { + foreach (var value in column) + { + if (value is not null) + { + var startNode = nodeState[value.Id]; + foreach (var child in value.ChildNodes) + { + var endNode = nodeState[child]; + var path = ConnectNodes(startNode.OutConnect, endNode.InConnect); + canvas.Children.Add(path); + } + } + } + } + + // Add the final internal padding to get the total size + canvas.Width = currentOffsetX + InternalPadding; + canvas.Height = maxHeight + InternalPadding; + } + + private void Node_Click(object sender, RoutedEventArgs e) + { + var node = (GraphViewerItem)sender; + this.SelectedNode = (GraphNode)node.DataContext; + } + + private Path ConnectNodes(Point start, Point end) + { + var control1 = new Point( + start.X + (NodeSpacingHorizontal / 2), + start.Y); + var control2 = new Point( + end.X - (NodeSpacingHorizontal / 2), + end.Y); + + return CreateBezier(start, control1, control2, end); + } + + private Path CreateBezier(Point start, Point control1, Point control2, Point end) + { + var path = new Path() + { + Stroke = new SolidColorBrush((Color)Resources["SystemBaseLowColor"]), + StrokeThickness = 1, + Data = new PathGeometry() + { + Figures = new PathFigureCollection() + { + new PathFigure() + { + StartPoint = start, + Segments = new PathSegmentCollection() + { + new BezierSegment() + { + Point1 = control1, + Point2 = control2, + Point3 = end, + } + }, + }, + }, + }, + }; + + return path; + } + } +} diff --git a/Source/GenerateSharp/SoupView/View/GraphViewerItem.cs b/Source/GenerateSharp/SoupView/View/GraphViewerItem.cs new file mode 100644 index 000000000..4fc887883 --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/GraphViewerItem.cs @@ -0,0 +1,35 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; + +namespace SoupView.View +{ + public sealed class GraphViewerItem : Button + { + /// + /// Identifies the dependency property. + /// + public static readonly DependencyProperty TitleProperty = DependencyProperty.Register( + nameof(Title), + typeof(string), + typeof(GraphViewerItem), + new PropertyMetadata(string.Empty)); + + public GraphViewerItem() + { + this.DefaultStyleKey = typeof(GraphViewerItem); + } + + /// + /// Gets or sets the title + /// + public string Title + { + get { return (string)GetValue(TitleProperty); } + set { SetValue(TitleProperty, value); } + } + } +} diff --git a/Source/GenerateSharp/SoupView/View/MainWindow.xaml b/Source/GenerateSharp/SoupView/View/MainWindow.xaml new file mode 100644 index 000000000..cd53e64af --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/MainWindow.xaml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/GenerateSharp/SoupView/View/MainWindow.xaml.cs b/Source/GenerateSharp/SoupView/View/MainWindow.xaml.cs new file mode 100644 index 000000000..d99ede131 --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/MainWindow.xaml.cs @@ -0,0 +1,105 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using System; +using System.Threading.Tasks; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Opal; +using SoupView.ViewModel; +using Windows.Storage.Pickers; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. +namespace SoupView.View +{ + /// + /// An main window that can be used on its own or navigated to within a Frame. + /// + public sealed partial class MainWindow : Window + { + private MainWindowModel ViewModel => (MainWindowModel)this.Root.DataContext; + + public MainWindow() + { + this.InitializeComponent(); + + this.ExtendsContentIntoTitleBar = true; + this.SetTitleBar(AppTitleBar); + + this.Title = "Soup View"; + LoadIcon("Assets/Soup.ico"); + + Navigation.SelectedItem = DependencyGraphNavigationItem; + } + + private void LoadIcon(string iconName) + { + // Get the Window's HWND + var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); + var iconHandle = PInvoke.User32.LoadImage( + IntPtr.Zero, + iconName, + PInvoke.User32.ImageType.IMAGE_ICON, + 32, + 32, + PInvoke.User32.LoadImageFlags.LR_LOADFROMFILE); + + PInvoke.User32.SendMessage(hwnd, PInvoke.User32.WindowMessage.WM_SETICON, (IntPtr)0, iconHandle); + } + + private async void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) + { + if (args.IsSettingsSelected) + { + ContentFrame.Navigate(typeof(SettingsPage)); + } + else + { + var selectedItem = (NavigationViewItem)args.SelectedItem; + if (selectedItem == DependencyGraphNavigationItem) + { + ContentFrame.Navigate(typeof(DependencyGraphPage), ViewModel.DependencyGraph); + } + else if (selectedItem == TaskGraphNavigationItem) + { + ContentFrame.Navigate(typeof(TaskGraphPage), ViewModel.TaskGraph); + } + else if (selectedItem == OperationGraphNavigationItem) + { + ContentFrame.Navigate(typeof(OperationGraphPage), ViewModel.OperationGraph); + } + else if (selectedItem == OpenFileNavigationItem) + { + await LoadFileAsync(); + this.Navigation.SelectedItem = DependencyGraphNavigationItem; + } + else + { + throw new InvalidOperationException("Unknown selection."); + } + } + } + + private async Task LoadFileAsync() + { + var filePicker = new FileOpenPicker(); + + // Get the current window's HWND by passing in the Window object + var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this); + + // Associate the HWND with the file picker + WinRT.Interop.InitializeWithWindow.Initialize(filePicker, hwnd); + + // Use file picker like normal! + filePicker.FileTypeFilter.Add(".toml"); + var file = await filePicker.PickSingleFileAsync(); + + if (file != null) + { + ViewModel.RecipeFile = new Path(file.Path); + } + } + } +} diff --git a/Source/GenerateSharp/SoupView/View/OperationGraphPage.xaml b/Source/GenerateSharp/SoupView/View/OperationGraphPage.xaml new file mode 100644 index 000000000..cdddcb030 --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/OperationGraphPage.xaml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/GenerateSharp/SoupView/View/OperationGraphPage.xaml.cs b/Source/GenerateSharp/SoupView/View/OperationGraphPage.xaml.cs new file mode 100644 index 000000000..667e6a4f7 --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/OperationGraphPage.xaml.cs @@ -0,0 +1,26 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Navigation; +using SoupView.ViewModel; + +namespace SoupView.View +{ + /// + /// The operation graph page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class OperationGraphPage : Page + { + public OperationGraphPage() + { + this.InitializeComponent(); + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + DataContext = (OperationGraphPageModel)e.Parameter; + } + } +} diff --git a/Source/GenerateSharp/SoupView/View/SettingsPage.xaml b/Source/GenerateSharp/SoupView/View/SettingsPage.xaml new file mode 100644 index 000000000..9d5590a82 --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/SettingsPage.xaml @@ -0,0 +1,14 @@ + + + + + + diff --git a/Source/GenerateSharp/SoupView/View/SettingsPage.xaml.cs b/Source/GenerateSharp/SoupView/View/SettingsPage.xaml.cs new file mode 100644 index 000000000..3f4d18b3e --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/SettingsPage.xaml.cs @@ -0,0 +1,19 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Microsoft.UI.Xaml.Controls; + +namespace SoupView.View +{ + /// + /// The settings page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class SettingsPage : Page + { + public SettingsPage() + { + this.InitializeComponent(); + } + } +} diff --git a/Source/GenerateSharp/SoupView/View/TaskGraphPage.xaml b/Source/GenerateSharp/SoupView/View/TaskGraphPage.xaml new file mode 100644 index 000000000..aabfacaab --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/TaskGraphPage.xaml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/GenerateSharp/SoupView/View/TaskGraphPage.xaml.cs b/Source/GenerateSharp/SoupView/View/TaskGraphPage.xaml.cs new file mode 100644 index 000000000..8fc092c06 --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/TaskGraphPage.xaml.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Navigation; +using SoupView.ViewModel; + +namespace SoupView.View +{ + /// + /// The task graph page that can be used on its own or navigated to within a Frame. + /// + public sealed partial class TaskGraphPage : Page + { + public TaskGraphPage() + { + this.InitializeComponent(); + } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + DataContext = (TaskGraphPageModel)e.Parameter; + } + + private TaskGraphPageModel ViewModel => (TaskGraphPageModel)DataContext; + } +} diff --git a/Source/GenerateSharp/SoupView/View/ValueTableItemTemplateSelector.cs b/Source/GenerateSharp/SoupView/View/ValueTableItemTemplateSelector.cs new file mode 100644 index 000000000..171404ce6 --- /dev/null +++ b/Source/GenerateSharp/SoupView/View/ValueTableItemTemplateSelector.cs @@ -0,0 +1,34 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using System; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using SoupView.ViewModel; + +namespace SoupView.View +{ + internal class ValueTableItemTemplateSelector : DataTemplateSelector + { + public DataTemplate TableTemplate { get; set; } + public DataTemplate ListTemplate { get; set; } + public DataTemplate ValueTemplate { get; set; } + + protected override DataTemplate SelectTemplateCore(object item) + { + var explorerItem = (ValueTableItemViewModel)item; + switch (explorerItem.Type) + { + case ValueTableItemType.Table: + return TableTemplate; + case ValueTableItemType.List: + return ListTemplate; + case ValueTableItemType.Value: + return ValueTemplate; + default: + throw new InvalidOperationException("Unknown ValueTableItemType"); + } + } + } +} diff --git a/Source/GenerateSharp/SoupView/ViewModel/DependencyGraphPageModel.cs b/Source/GenerateSharp/SoupView/ViewModel/DependencyGraphPageModel.cs new file mode 100644 index 000000000..e16aae1eb --- /dev/null +++ b/Source/GenerateSharp/SoupView/ViewModel/DependencyGraphPageModel.cs @@ -0,0 +1,189 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Microsoft.Toolkit.Mvvm.Input; +using Opal; +using Opal.System; +using Soup.Build; +using Soup.Build.Utilities; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Input; + +namespace SoupView.ViewModel +{ + internal class DependencyGraphPageModel : Observable + { + private GraphNode selectedNode = null; + private ProjectDetailsViewModel selectedProject = null; + private string errorBarMessage = string.Empty; + private bool isErrorBarOpen = false; + private IList> graph = null; + private uint uniqueId = 0; + private Dictionary projectDetailsLookup = new Dictionary(); + + public string ErrorBarMessage + { + get { return errorBarMessage; } + set + { + if (value != errorBarMessage) + { + errorBarMessage = value; + NotifyPropertyChanged(); + } + } + } + + public IList> Graph + { + get { return graph; } + set + { + if (value != graph) + { + graph = value; + NotifyPropertyChanged(); + } + } + } + + public GraphNode SelectedNode + { + get { return selectedNode; } + set + { + if (value != selectedNode) + { + selectedNode = value; + NotifyPropertyChanged(); + SelectedProject = this.projectDetailsLookup[selectedNode.Id]; + } + } + } + + public bool IsErrorBarOpen + { + get { return isErrorBarOpen; } + set + { + if (value != isErrorBarOpen) + { + isErrorBarOpen = value; + NotifyPropertyChanged(); + } + } + } + + public ProjectDetailsViewModel SelectedProject + { + get { return selectedProject; } + set + { + if (value != selectedProject) + { + selectedProject = value; + NotifyPropertyChanged(); + } + } + } + + public async Task LoadProjectAsync(Path recipeFilePath) + { + this.uniqueId = 1; + this.projectDetailsLookup.Clear(); + var activeGraph = new List>(); + var recipeFiles = new List<(Path Path, uint Id)>() + { + (recipeFilePath, this.uniqueId++), + }; + await BuildGraphAsync(recipeFiles, activeGraph); + Graph = activeGraph; + } + + private void NotifyError(string message) + { + ErrorBarMessage = message; + IsErrorBarOpen = true; + } + + private async Task BuildGraphAsync(IList<(Path Path, uint Id)> recipeFiles, IList> activeGraph) + { + var column = new List(); + var childRecipeFiles = new List<(Path Path, uint Id)>(); + foreach (var recipeFile in recipeFiles) + { + var loadResult = await RecipeExtensions.TryLoadRecipeFromFileAsync(recipeFile.Path); + if (!loadResult.IsSuccess) + { + NotifyError($"Failed to load Recipe file: {recipeFile.Path}"); + } + + var packageFolder = recipeFile.Path.GetParent(); + var recipe = loadResult.Result; + + var currentChildRecipes = new List<(Path Path, uint Id)>(); + if (recipe.HasBuildDependencies) + AddRecipeFiles(recipe.BuildDependencies, recipe.Language, packageFolder, currentChildRecipes); + if (recipe.HasTestDependencies) + AddRecipeFiles(recipe.TestDependencies, recipe.Language, packageFolder, currentChildRecipes); + if (recipe.HasRuntimeDependencies) + AddRecipeFiles(recipe.RuntimeDependencies, recipe.Language, packageFolder, currentChildRecipes); + + column.Add(new GraphNode(recipe.Name, recipeFile.Id) + { + ChildNodes = currentChildRecipes.Select(value => value.Id).ToList(), + }); + + this.projectDetailsLookup.Add( + recipeFile.Id, + new ProjectDetailsViewModel( + recipe, + packageFolder)); + + childRecipeFiles.AddRange(currentChildRecipes); + } + + activeGraph.Add(column); + + if (childRecipeFiles.Count > 0) + { + await BuildGraphAsync(childRecipeFiles, activeGraph); + } + } + + private void AddRecipeFiles( + IEnumerable packageReferences, + string recipeLanguage, + Path packageFolder, + IList<(Path Path, uint Id)> recipeFiles) + { + foreach (var packageReference in packageReferences) + { + if (packageReference.IsLocal) + { + var recipeFile = packageReference.Path + BuildConstants.RecipeFileName; + if (!recipeFile.HasRoot) + { + recipeFile = packageFolder + recipeFile; + } + + recipeFiles.Add((recipeFile, this.uniqueId++)); + } + else + { + var packagesDirectory = LifetimeManager.Get().GetUserProfileDirectory() + + new Path(".soup/packages/"); + var languageRootFolder = packagesDirectory + new Path(recipeLanguage); + var packageRootFolder = languageRootFolder + new Path(packageReference.GetName); + var packageVersionFolder = packageRootFolder + new Path(packageReference.Version.ToString()) + new Path("/"); + var recipeFile = packageVersionFolder + BuildConstants.RecipeFileName; + + recipeFiles.Add((recipeFile, this.uniqueId++)); + } + } + } + } +} diff --git a/Source/GenerateSharp/SoupView/ViewModel/GraphNode.cs b/Source/GenerateSharp/SoupView/ViewModel/GraphNode.cs new file mode 100644 index 000000000..456f6785d --- /dev/null +++ b/Source/GenerateSharp/SoupView/ViewModel/GraphNode.cs @@ -0,0 +1,21 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using System.Collections.Generic; + +namespace SoupView.ViewModel +{ + public class GraphNode + { + public GraphNode(string title, uint id) + { + this.Title = title; + this.Id = id; + } + + public string Title { get; set; } = string.Empty; + public uint Id { get; set; } = 0; + public IList ChildNodes { get; set;} = new List(); + } +} diff --git a/Source/GenerateSharp/SoupView/ViewModel/MainWindowModel.cs b/Source/GenerateSharp/SoupView/ViewModel/MainWindowModel.cs new file mode 100644 index 000000000..cdf6fd171 --- /dev/null +++ b/Source/GenerateSharp/SoupView/ViewModel/MainWindowModel.cs @@ -0,0 +1,51 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Opal; + +namespace SoupView.ViewModel +{ + internal class MainWindowModel : Observable + { + private Path recipeFile = new Path(); + + public Path RecipeFile + { + get { return recipeFile; } + set + { + if (value != recipeFile) + { + recipeFile = value; + NotifyPropertyChanged(); + NotifyPropertyChanged("Title"); + _ = DependencyGraph.LoadProjectAsync(recipeFile); + _ = TaskGraph.LoadProjectAsync(recipeFile); + _ = OperationGraph.LoadProjectAsync(recipeFile); + } + } + } + + public string Title + { + get + { + if (RecipeFile == null || RecipeFile.IsEmpty) + { + return string.Empty; + } + else + { + + + return RecipeFile.ToString(); + } + } + } + + public DependencyGraphPageModel DependencyGraph { get; private set; } = new DependencyGraphPageModel(); + public TaskGraphPageModel TaskGraph { get; private set; } = new TaskGraphPageModel(); + public OperationGraphPageModel OperationGraph { get; private set; } = new OperationGraphPageModel(); + } +} diff --git a/Source/GenerateSharp/SoupView/ViewModel/Observable.cs b/Source/GenerateSharp/SoupView/ViewModel/Observable.cs new file mode 100644 index 000000000..8c3f36437 --- /dev/null +++ b/Source/GenerateSharp/SoupView/ViewModel/Observable.cs @@ -0,0 +1,22 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace SoupView.ViewModel +{ + internal class Observable : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null) + { + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + } +} diff --git a/Source/GenerateSharp/SoupView/ViewModel/OperationDetailsViewModel.cs b/Source/GenerateSharp/SoupView/ViewModel/OperationDetailsViewModel.cs new file mode 100644 index 000000000..81e237d74 --- /dev/null +++ b/Source/GenerateSharp/SoupView/ViewModel/OperationDetailsViewModel.cs @@ -0,0 +1,28 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Soup.Build.Runtime; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace SoupView.ViewModel +{ + internal class OperationDetailsViewModel : Observable + { + private ObservableCollection properties = new ObservableCollection(); + + public OperationDetailsViewModel(OperationInfo operation) + { + properties.Clear(); + properties.Add(new PropertyValue("Title", operation.Title)); + properties.Add(new PropertyValue("Id", operation.Id.ToString())); + properties.Add(new PropertyValue("DependencyCount", operation.DependencyCount.ToString())); + properties.Add(new PropertyValue("Executable", operation.Command.Executable.ToString())); + properties.Add(new PropertyValue("WorkingDirectory", operation.Command.WorkingDirectory.ToString())); + properties.Add(new PropertyValue("Arguments", operation.Command.Arguments)); + } + + public IList Properties => properties; + } +} diff --git a/Source/GenerateSharp/SoupView/ViewModel/OperationGraphPageModel.cs b/Source/GenerateSharp/SoupView/ViewModel/OperationGraphPageModel.cs new file mode 100644 index 000000000..ca6f2105e --- /dev/null +++ b/Source/GenerateSharp/SoupView/ViewModel/OperationGraphPageModel.cs @@ -0,0 +1,207 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Opal; +using Soup.Build.Runtime; +using Soup.Build.Utilities; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; + +namespace SoupView.ViewModel +{ + internal class OperationGraphPageModel : Observable + { + private GraphNode selectedNode = null; + private OperationDetailsViewModel selectedOperation = null; + private string errorBarMessage = string.Empty; + private bool isErrorBarOpen = false; + private IList> graph = null; + private Dictionary operationDetailsLookup = new Dictionary(); + + public string ErrorBarMessage + { + get { return errorBarMessage; } + set + { + if (value != errorBarMessage) + { + errorBarMessage = value; + NotifyPropertyChanged(); + } + } + } + + public IList> Graph + { + get { return graph; } + set + { + if (value != graph) + { + graph = value; + NotifyPropertyChanged(); + } + } + } + + public GraphNode SelectedNode + { + get { return selectedNode; } + set + { + if (value != selectedNode) + { + selectedNode = value; + NotifyPropertyChanged(); + SelectedOperation = this.operationDetailsLookup[selectedNode.Id]; + } + } + } + + public OperationDetailsViewModel SelectedOperation + { + get { return selectedOperation; } + set + { + if (value != selectedOperation) + { + selectedOperation = value; + NotifyPropertyChanged(); + } + } + } + + public bool IsErrorBarOpen + { + get { return isErrorBarOpen; } + set + { + if (value != isErrorBarOpen) + { + isErrorBarOpen = value; + NotifyPropertyChanged(); + } + } + } + + public async Task LoadProjectAsync(Path recipeFilePath) + { + var loadResult = await RecipeExtensions.TryLoadRecipeFromFileAsync(recipeFilePath); + if (loadResult.IsSuccess) + { + var packageDirectory = recipeFilePath.GetParent(); + var targetPath = await GetTargetPathAsync(packageDirectory); + + var soupTargetDirectory = targetPath + new Path(".soup/"); + + var evaluateGraphFile = soupTargetDirectory + BuildConstants.GenerateEvaluateOperationGraphFileName; + var fileSystemState = new FileSystemState(); + if (!OperationGraphManager.TryLoadState(evaluateGraphFile, fileSystemState, out var evaluateGraph)) + { + NotifyError($"Failed to load Operation Graph: {evaluateGraphFile}"); + return; + } + + Graph = BuildGraph(evaluateGraph); + } + else + { + NotifyError($"Failed to load Recipe file: {recipeFilePath}"); + } + } + + private void NotifyError(string message) + { + ErrorBarMessage = message; + IsErrorBarOpen = true; + } + + private IList> BuildGraph(OperationGraph evaluateGraph) + { + this.operationDetailsLookup.Clear(); + var activeIds = evaluateGraph.GetRootOperationIds(); + var activeGraph = new List>(); + var knownIds = new HashSet(); + BuildGraphColumn(evaluateGraph, activeGraph, activeIds, knownIds); + + return activeGraph; + } + + private void BuildGraphColumn( + OperationGraph evaluateGraph, + IList> activeGraph, + IList activeIds, + HashSet knownIds) + { + // Build up the total set of nodes in the next level + var nextIds = new List(); + foreach (var operationId in activeIds) + { + var operation = evaluateGraph.GetOperationInfo(operationId); + foreach (var childId in operation.Children) + { + nextIds.Add(childId); + } + } + + // Find the depest level first + if (nextIds.Count > 0) + { + BuildGraphColumn(evaluateGraph, activeGraph, nextIds, knownIds); + } + + // Build up all the nodes at this level that have not already been added + var column = new List(); + foreach (var operationId in activeIds) + { + if (!knownIds.Contains(operationId)) + { + var operation = evaluateGraph.GetOperationInfo(operationId); + + var node = new GraphNode(operation.Title, operationId.value) + { + ChildNodes = operation.Children.Select(value => value.value).ToList(), + }; + + knownIds.Add(operationId); + column.Add(node); + + this.operationDetailsLookup.Add(operationId.value, new OperationDetailsViewModel(operation)); + } + } + + // Add the new column at the start + activeGraph.Insert(0, column); + } + + private async Task GetTargetPathAsync(Path packageDirectory) + { + var processInfo = new ProcessStartInfo("soup.exe", $"target {packageDirectory}") + { + RedirectStandardOutput = true, + CreateNoWindow = true, + }; + var process = new Process() + { + StartInfo = processInfo, + }; + + process.Start(); + + await process.WaitForExitAsync(); + + if (process.ExitCode != 0) + { + NotifyError($"Soup process exited with error: {process.ExitCode}"); + throw new InvalidOperationException(); + } + + var output = await process.StandardOutput.ReadToEndAsync(); + return new Path(output); + } + } +} diff --git a/Source/GenerateSharp/SoupView/ViewModel/ProjectDetailsViewModel.cs b/Source/GenerateSharp/SoupView/ViewModel/ProjectDetailsViewModel.cs new file mode 100644 index 000000000..a4c723996 --- /dev/null +++ b/Source/GenerateSharp/SoupView/ViewModel/ProjectDetailsViewModel.cs @@ -0,0 +1,27 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Opal; +using Soup.Build.Utilities; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace SoupView.ViewModel +{ + internal class ProjectDetailsViewModel : Observable + { + private ObservableCollection properties = new ObservableCollection(); + + public ProjectDetailsViewModel(Recipe recipe, Path path) + { + properties.Clear(); + properties.Add(new PropertyValue("Name", recipe.Name)); + properties.Add(new PropertyValue("Version", recipe.Version.ToString())); + properties.Add(new PropertyValue("Language", recipe.Language)); + properties.Add(new PropertyValue("Path", path.ToString())); + } + + public IList Properties => properties; + } +} diff --git a/Source/GenerateSharp/SoupView/ViewModel/PropertyValue.cs b/Source/GenerateSharp/SoupView/ViewModel/PropertyValue.cs new file mode 100644 index 000000000..3943f2a7e --- /dev/null +++ b/Source/GenerateSharp/SoupView/ViewModel/PropertyValue.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +namespace SoupView.ViewModel +{ + public class PropertyValue + { + public PropertyValue(string name, string value) + { + this.Name = name; + this.Value = value; + } + + public string Name { get; set; } = string.Empty; + public string Value { get; set; } = string.Empty; + } +} diff --git a/Source/GenerateSharp/SoupView/ViewModel/TaskDetailsViewModel.cs b/Source/GenerateSharp/SoupView/ViewModel/TaskDetailsViewModel.cs new file mode 100644 index 000000000..47826e4df --- /dev/null +++ b/Source/GenerateSharp/SoupView/ViewModel/TaskDetailsViewModel.cs @@ -0,0 +1,121 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Soup.Build; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using ValueType = Soup.Build.ValueType; + +namespace SoupView.ViewModel +{ + internal class TaskDetailsViewModel : Observable + { + private ObservableCollection properties = new ObservableCollection(); + + public TaskDetailsViewModel(string name, IValueTable taskInfo) + { + properties.Clear(); + properties.Add(new PropertyValue("Name", name)); + + State = new ObservableCollection(); + BuildValueTable(taskInfo, State); + } + + public IList Properties => properties; + + + public ObservableCollection State { get; init; } + + private void BuildValueTable( + IValueTable table, + ObservableCollection viewModelList) + { + viewModelList.Clear(); + foreach (var value in table) + { + var viewModel = new ValueTableItemViewModel(); + + switch (value.Value.Type) + { + case ValueType.Boolean: + viewModel.Title = $"{value.Key} - {value.Value.AsBoolean()}"; + viewModel.Type = ValueTableItemType.Value; + break; + case ValueType.String: + viewModel.Title = $"{value.Key} - {value.Value.AsString()}"; + viewModel.Type = ValueTableItemType.Value; + break; + case ValueType.Float: + viewModel.Title = $"{value.Key} - {value.Value.AsFloat()}"; + viewModel.Type = ValueTableItemType.Value; + break; + case ValueType.Integer: + viewModel.Title = $"{value.Key} - {value.Value.AsInteger()}"; + viewModel.Type = ValueTableItemType.Value; + break; + case ValueType.List: + viewModel.Title = $"{value.Key}"; + viewModel.Type = ValueTableItemType.List; + BuildValueList(value.Value.AsList(), viewModel.Children); + break; + case ValueType.Table: + viewModel.Title = $"{value.Key}"; + viewModel.Type = ValueTableItemType.Table; + BuildValueTable(value.Value.AsTable(), viewModel.Children); + break; + default: + throw new InvalidOperationException("Unknown Value type"); + } + + viewModelList.Add(viewModel); + } + } + + private void BuildValueList( + IValueList list, + ObservableCollection viewModelList) + { + viewModelList.Clear(); + foreach (var value in list) + { + var viewModel = new ValueTableItemViewModel(); + + switch (value.Type) + { + case ValueType.Boolean: + viewModel.Title = $"{value.AsBoolean()}"; + viewModel.Type = ValueTableItemType.Value; + break; + case ValueType.String: + viewModel.Title = $"{value.AsString()}"; + viewModel.Type = ValueTableItemType.Value; + break; + case ValueType.Float: + viewModel.Title = $"{value.AsFloat()}"; + viewModel.Type = ValueTableItemType.Value; + break; + case ValueType.Integer: + viewModel.Title = $"{value.AsInteger()}"; + viewModel.Type = ValueTableItemType.Value; + break; + case ValueType.List: + viewModel.Title = string.Empty; + viewModel.Type = ValueTableItemType.List; + BuildValueList(value.AsList(), viewModel.Children); + break; + case ValueType.Table: + viewModel.Title = string.Empty; + viewModel.Type = ValueTableItemType.Table; + BuildValueTable(value.AsTable(), viewModel.Children); + break; + default: + throw new InvalidOperationException("Unknown Value type"); + } + + viewModelList.Add(viewModel); + } + } + } +} diff --git a/Source/GenerateSharp/SoupView/ViewModel/TaskGraphPageModel.cs b/Source/GenerateSharp/SoupView/ViewModel/TaskGraphPageModel.cs new file mode 100644 index 000000000..dc42dc3d1 --- /dev/null +++ b/Source/GenerateSharp/SoupView/ViewModel/TaskGraphPageModel.cs @@ -0,0 +1,197 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using Opal; +using Soup.Build; +using Soup.Build.Utilities; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading.Tasks; + +namespace SoupView.ViewModel +{ + internal class TaskGraphPageModel : Observable + { + private GraphNode selectedNode = null; + private TaskDetailsViewModel selectedTask = null; + private string errorBarMessage = string.Empty; + private uint uniqueId = 0; + private bool isErrorBarOpen = false; + private IList> graph = null; + private Dictionary taskDetailsLookup = new Dictionary(); + + public string ErrorBarMessage + { + get { return errorBarMessage; } + set + { + if (value != errorBarMessage) + { + errorBarMessage = value; + NotifyPropertyChanged(); + } + } + } + + public IList> Graph + { + get { return graph; } + set + { + if (value != graph) + { + graph = value; + NotifyPropertyChanged(); + } + } + } + + public GraphNode SelectedNode + { + get { return selectedNode; } + set + { + if (value != selectedNode) + { + selectedNode = value; + NotifyPropertyChanged(); + SelectedTask = this.taskDetailsLookup[selectedNode.Id]; + } + } + } + + public TaskDetailsViewModel SelectedTask + { + get { return selectedTask; } + set + { + if (value != selectedTask) + { + selectedTask = value; + NotifyPropertyChanged(); + } + } + } + + public bool IsErrorBarOpen + { + get { return isErrorBarOpen; } + set + { + if (value != isErrorBarOpen) + { + isErrorBarOpen = value; + NotifyPropertyChanged(); + } + } + } + + public async Task LoadProjectAsync(Path recipeFilePath) + { + var loadResult = await RecipeExtensions.TryLoadRecipeFromFileAsync(recipeFilePath); + if (loadResult.IsSuccess) + { + var packageDirectory = recipeFilePath.GetParent(); + var targetPath = await GetTargetPathAsync(packageDirectory); + + var soupTargetDirectory = targetPath + new Path(".soup/"); + + var generateInfoStateFile = soupTargetDirectory + BuildConstants.GenerateTaskInfoFileName; + if (!ValueTableManager.TryLoadState(generateInfoStateFile, out var generateInfoTable)) + { + NotifyError($"Failed to load Value Table: {generateInfoStateFile}"); + return; + } + + Graph = BuildGraph(generateInfoTable); + } + else + { + NotifyError($"Failed to load Recipe file: {recipeFilePath}"); + } + } + + private void NotifyError(string message) + { + ErrorBarMessage = message; + IsErrorBarOpen = true; + } + + private IList> BuildGraph(IValueTable generateInfoTable) + { + var activeGraph = new List>(); + this.taskDetailsLookup.Clear(); + this.uniqueId = 1; + + if (!generateInfoTable.TryGetValue("RuntimeOrder", out var runtimeOrderList) || runtimeOrderList.Type != Soup.Build.ValueType.List) + { + NotifyError($"Generate Info Table missing RuntimeOrder List"); + return activeGraph; + } + + if (!generateInfoTable.TryGetValue("TaskInfo", out var taskInfoTable) || taskInfoTable.Type != Soup.Build.ValueType.Table) + { + NotifyError($"Generate Info Table missing TaskInfo Table"); + return activeGraph; + } + + BuildGraph(runtimeOrderList.AsList(), taskInfoTable.AsTable(), activeGraph); + + return activeGraph; + } + + private void BuildGraph( + IValueList runtimeOrderList, + IValueTable taskInfoTable, + IList> activeGraph) + { + // Add each task to its own column + foreach (var taskNameValue in runtimeOrderList) + { + var taskName = taskNameValue.AsString(); + + var node = new GraphNode(taskName, this.uniqueId++); + + // Find the Task Info + var taskInfo = taskInfoTable[taskName].AsTable(); + + this.taskDetailsLookup.Add(node.Id, new TaskDetailsViewModel(taskName, taskInfo)); + + // Add the new column at the start + var column = new List() + { + node + }; + activeGraph.Add(column); + } + } + + private async Task GetTargetPathAsync(Path packageDirectory) + { + var processInfo = new ProcessStartInfo("soup.exe", $"target {packageDirectory}") + { + RedirectStandardOutput = true, + CreateNoWindow = true, + }; + var process = new Process() + { + StartInfo = processInfo, + }; + + process.Start(); + + await process.WaitForExitAsync(); + + if (process.ExitCode != 0) + { + NotifyError($"Soup process exited with error: {process.ExitCode}"); + throw new InvalidOperationException(); + } + + var output = await process.StandardOutput.ReadToEndAsync(); + return new Path(output); + } + } +} diff --git a/Source/GenerateSharp/SoupView/ViewModel/ValueTableItemViewModel.cs b/Source/GenerateSharp/SoupView/ViewModel/ValueTableItemViewModel.cs new file mode 100644 index 000000000..3e0ca93a9 --- /dev/null +++ b/Source/GenerateSharp/SoupView/ViewModel/ValueTableItemViewModel.cs @@ -0,0 +1,57 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +using System.Collections.ObjectModel; + +namespace SoupView.ViewModel +{ + public enum ValueTableItemType + { + Table, + List, + Value, + }; + + class ValueTableItemViewModel : Observable + { + public string Title { get; set; } + + public ValueTableItemType Type { get; set; } + + private ObservableCollection m_children = new ObservableCollection(); + public ObservableCollection Children + { + get { return m_children; } + set { m_children = value; } + } + + private bool m_isExpanded; + public bool IsExpanded + { + get { return m_isExpanded; } + set + { + if (m_isExpanded != value) + { + m_isExpanded = value; + NotifyPropertyChanged(); + } + } + } + + private bool m_isSelected; + public bool IsSelected + { + get { return m_isSelected; } + set + { + if (m_isSelected != value) + { + m_isSelected = value; + NotifyPropertyChanged(); + } + } + } + } +} diff --git a/Source/GenerateSharp/SoupView/app.manifest b/Source/GenerateSharp/SoupView/app.manifest new file mode 100644 index 000000000..e7f41e80b --- /dev/null +++ b/Source/GenerateSharp/SoupView/app.manifest @@ -0,0 +1,15 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + diff --git a/Source/GenerateSharp/Utilities/BuildConstants.cs b/Source/GenerateSharp/Utilities/BuildConstants.cs index a551edfa5..05a502ce6 100644 --- a/Source/GenerateSharp/Utilities/BuildConstants.cs +++ b/Source/GenerateSharp/Utilities/BuildConstants.cs @@ -40,5 +40,10 @@ public static class BuildConstants /// Gets the Generate Parameters Value Table file name /// public static Path GenerateEvaluateOperationGraphFileName => new Path("GenerateEvaluateGraph.bog"); + + /// + /// Gets the Generate task info Value Table file name + /// + public static Path GenerateTaskInfoFileName => new Path("GenerateTaskInfo.bvt"); } } diff --git a/Source/GenerateSharp/Generate/OperationGraph/OperationGraphManager.cs b/Source/GenerateSharp/Utilities/OperationGraph/OperationGraphManager.cs similarity index 94% rename from Source/GenerateSharp/Generate/OperationGraph/OperationGraphManager.cs rename to Source/GenerateSharp/Utilities/OperationGraph/OperationGraphManager.cs index b887b15ce..1ffe3e32b 100644 --- a/Source/GenerateSharp/Generate/OperationGraph/OperationGraphManager.cs +++ b/Source/GenerateSharp/Utilities/OperationGraph/OperationGraphManager.cs @@ -4,29 +4,28 @@ using Opal; using Soup.Build.Runtime; -using Soup.Build.Utilities; -using System; using System.Collections.Generic; -namespace Soup.Build.Generate +namespace Soup.Build.Utilities { /// /// The operation state manager /// - internal static class OperationGraphManager + public static class OperationGraphManager { /// /// Load the operation state from the provided directory /// public static bool TryLoadState( Path operationGraphFile, - OperationGraph result, - FileSystemState fileSystemState) + FileSystemState fileSystemState, + out OperationGraph result) { // Verify the requested file exists if (!System.IO.File.Exists(operationGraphFile.ToString())) { Log.Info("Operation graph file does not exist"); + result = new OperationGraph(); return false; } @@ -67,6 +66,7 @@ public static bool TryLoadState( catch { Log.Error("Failed to parse operation graph"); + result = new OperationGraph(); return false; } } diff --git a/Source/GenerateSharp/Generate/OperationGraph/OperationGraphReader.cs b/Source/GenerateSharp/Utilities/OperationGraph/OperationGraphReader.cs similarity index 96% rename from Source/GenerateSharp/Generate/OperationGraph/OperationGraphReader.cs rename to Source/GenerateSharp/Utilities/OperationGraph/OperationGraphReader.cs index ba8c3ee73..1d4e5ad30 100644 --- a/Source/GenerateSharp/Generate/OperationGraph/OperationGraphReader.cs +++ b/Source/GenerateSharp/Utilities/OperationGraph/OperationGraphReader.cs @@ -7,7 +7,7 @@ using System; using System.Collections.Generic; -namespace Soup.Build.Generate +namespace Soup.Build.Utilities { /// /// The operation graph state reader @@ -83,7 +83,7 @@ public static OperationGraph Deserialize(System.IO.BinaryReader reader) var operations = new List(); for (var i = 0; i < operationCount; i++) { - operations[i] = ReadOperationInfo(reader); + operations.Add(ReadOperationInfo(reader)); } if (reader.BaseStream.Position != reader.BaseStream.Length) @@ -180,7 +180,7 @@ private static List ReadFileIdList(System.IO.BinaryReader reader) var result = new List((int)size); for (var i = 0; i < size; i++) { - result[i] = new FileId(reader.ReadUInt32()); + result.Add(new FileId(reader.ReadUInt32())); } return result; @@ -192,7 +192,7 @@ private static List ReadOperationIdList(System.IO.BinaryReader read var result = new List((int)size); for (var i = 0; i < size; i++) { - result[i] = new OperationId(reader.ReadUInt32()); + result.Add(new OperationId(reader.ReadUInt32())); } return result; diff --git a/Source/GenerateSharp/Generate/OperationGraph/OperationGraphWriter.cs b/Source/GenerateSharp/Utilities/OperationGraph/OperationGraphWriter.cs similarity index 99% rename from Source/GenerateSharp/Generate/OperationGraph/OperationGraphWriter.cs rename to Source/GenerateSharp/Utilities/OperationGraph/OperationGraphWriter.cs index 1fcbb37d0..d106aba31 100644 --- a/Source/GenerateSharp/Generate/OperationGraph/OperationGraphWriter.cs +++ b/Source/GenerateSharp/Utilities/OperationGraph/OperationGraphWriter.cs @@ -5,7 +5,7 @@ using Soup.Build.Runtime; using System.Collections.Generic; -namespace Soup.Build.Generate +namespace Soup.Build.Utilities { /// /// The operation graph state writer diff --git a/Source/GenerateSharp/Utilities/Recipe/RecipeExtensions.cs b/Source/GenerateSharp/Utilities/Recipe/RecipeExtensions.cs index 25aa4db81..771faffe5 100644 --- a/Source/GenerateSharp/Utilities/Recipe/RecipeExtensions.cs +++ b/Source/GenerateSharp/Utilities/Recipe/RecipeExtensions.cs @@ -17,7 +17,7 @@ public static class RecipeExtensions /// /// Attempt to load from file /// - public static async Task<(bool IsSuccess, Recipe result)> TryLoadRecipeFromFileAsync(Path recipeFile) + public static async Task<(bool IsSuccess, Recipe Result)> TryLoadRecipeFromFileAsync(Path recipeFile) { // Verify the requested file exists Log.Diag("Load Recipe: " + recipeFile.ToString()); diff --git a/Source/GenerateSharp/Utilities/ValueTable/ValueTableTomlUtilities.cs b/Source/GenerateSharp/Utilities/ValueTable/ValueTableTomlUtilities.cs index c5a232911..030b90545 100644 --- a/Source/GenerateSharp/Utilities/ValueTable/ValueTableTomlUtilities.cs +++ b/Source/GenerateSharp/Utilities/ValueTable/ValueTableTomlUtilities.cs @@ -4,7 +4,6 @@ using Opal; using Soup.Build.Runtime; -using System; using System.Threading.Tasks; using Tomlyn; using Tomlyn.Syntax; diff --git a/Source/GenerateSharp/Soup.Rules.ruleset b/Source/Soup.Rules.ruleset similarity index 100% rename from Source/GenerateSharp/Soup.Rules.ruleset rename to Source/Soup.Rules.ruleset diff --git a/Source/GenerateSharp/stylecop.json b/Source/stylecop.json similarity index 100% rename from Source/GenerateSharp/stylecop.json rename to Source/stylecop.json