├── .build ├── .editorconfig ├── Build.cs ├── Configuration.cs ├── Directory.build.props ├── Directory.build.targets ├── _build.csproj └── _build.csproj.DotSettings ├── .github └── dependabot.yml ├── .gitignore ├── .nuke ├── build.schema.json └── parameters.json ├── Directory.Build.props ├── Directory.Build.targets ├── GitVersion.yml ├── LICENSE ├── README.md ├── XamlColorSchemeGenerator.sln ├── XamlColorSchemeGenerator.sln.DotSettings ├── appveyor.yml ├── build.cmd ├── build.ps1 ├── build.sh ├── global.json └── src ├── App.net.config ├── App.netcoreapp.config ├── ColorSchemeGenerator.cs ├── GeneratorParameters.json ├── Program.cs ├── SharedKey.snk ├── Theme.Template.xaml ├── ThemeGenerator.cs ├── XamlColorSchemeGenerator.csproj ├── app.manifest ├── build └── XamlColorSchemeGenerator.props └── buildMultiTargeting └── XamlColorSchemeGenerator.props /.build/.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | dotnet_style_qualification_for_field = false:warning 3 | dotnet_style_qualification_for_property = false:warning 4 | dotnet_style_qualification_for_method = false:warning 5 | dotnet_style_qualification_for_event = false:warning 6 | dotnet_style_require_accessibility_modifiers = never:warning 7 | 8 | csharp_style_expression_bodied_methods = true:silent 9 | csharp_style_expression_bodied_properties = true:warning 10 | csharp_style_expression_bodied_indexers = true:warning 11 | csharp_style_expression_bodied_accessors = true:warning 12 | -------------------------------------------------------------------------------- /.build/Build.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Nuke.Common; 4 | using Nuke.Common.Execution; 5 | using Nuke.Common.Git; 6 | using Nuke.Common.IO; 7 | using Nuke.Common.ProjectModel; 8 | using Nuke.Common.Tooling; 9 | using Nuke.Common.Tools.DotNet; 10 | using Nuke.Common.Tools.GitVersion; 11 | using Nuke.Common.Utilities.Collections; 12 | using static Nuke.Common.EnvironmentInfo; 13 | using static Nuke.Common.IO.FileSystemTasks; 14 | using static Nuke.Common.IO.PathConstruction; 15 | using static Nuke.Common.Tools.DotNet.DotNetTasks; 16 | 17 | [CheckBuildProjectConfigurations] 18 | [UnsetVisualStudioEnvironmentVariables] 19 | class Build : NukeBuild 20 | { 21 | /// Support plugins are available for: 22 | /// - JetBrains ReSharper https://nuke.build/resharper 23 | /// - JetBrains Rider https://nuke.build/rider 24 | /// - Microsoft VisualStudio https://nuke.build/visualstudio 25 | /// - Microsoft VSCode https://nuke.build/vscode 26 | 27 | public static int Main () => Execute(x => x.Compile); 28 | 29 | protected override void OnBuildInitialized() 30 | { 31 | base.OnBuildInitialized(); 32 | 33 | ProcessTasks.DefaultLogInvocation = true; 34 | ProcessTasks.DefaultLogOutput = true; 35 | 36 | Console.WriteLine("IsLocalBuild : {0}", IsLocalBuild); 37 | Console.WriteLine("Informational Version: {0}", GitVersion.InformationalVersion); 38 | Console.WriteLine("SemVer Version: {0}", GitVersion.SemVer); 39 | Console.WriteLine("AssemblySemVer Version: {0}", GitVersion.AssemblySemVer); 40 | Console.WriteLine("MajorMinorPatch Version: {0}", GitVersion.MajorMinorPatch); 41 | Console.WriteLine("NuGet Version: {0}", GitVersion.NuGetVersion); 42 | } 43 | 44 | [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] 45 | readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release; 46 | 47 | [Solution] readonly Solution Solution; 48 | 49 | [GitRepository] readonly GitRepository GitRepository; 50 | 51 | [GitVersion(Framework = "netcoreapp3.1")] readonly GitVersion GitVersion; 52 | 53 | AbsolutePath SourceDirectory => RootDirectory / "src"; 54 | 55 | [Parameter] 56 | readonly AbsolutePath ArtifactsDirectory = RootDirectory / "artifacts"; 57 | 58 | Target Restore => _ => _ 59 | .Executes(() => 60 | { 61 | DotNetRestore(s => s 62 | .SetProjectFile(Solution)); 63 | }); 64 | 65 | Target Compile => _ => _ 66 | .DependsOn(Restore) 67 | .Executes(() => 68 | { 69 | DotNetBuild(s => s 70 | .SetProjectFile(Solution) 71 | .SetConfiguration(Configuration) 72 | .SetVersion(GitVersion.MajorMinorPatch) 73 | .SetAssemblyVersion(GitVersion.AssemblySemVer) 74 | .SetFileVersion(GitVersion.AssemblySemFileVer) 75 | .SetInformationalVersion(GitVersion.InformationalVersion) 76 | .EnableNoRestore()); 77 | }); 78 | 79 | Target Pack => _ => _ 80 | .DependsOn(Compile) 81 | .Executes(() => 82 | { 83 | EnsureCleanDirectory(ArtifactsDirectory); 84 | 85 | DotNetPublish(s => s 86 | .SetConfiguration(Configuration) 87 | .SetVersion(GitVersion.MajorMinorPatch) 88 | .SetAssemblyVersion(GitVersion.AssemblySemVer) 89 | .SetFileVersion(GitVersion.AssemblySemFileVer) 90 | .SetInformationalVersion(GitVersion.InformationalVersion) 91 | .SetFramework("net45")); 92 | 93 | DotNetPublish(s => s 94 | .SetConfiguration(Configuration) 95 | .SetVersion(GitVersion.MajorMinorPatch) 96 | .SetAssemblyVersion(GitVersion.AssemblySemVer) 97 | .SetFileVersion(GitVersion.AssemblySemFileVer) 98 | .SetInformationalVersion(GitVersion.InformationalVersion) 99 | .SetFramework("netcoreapp3.1")); 100 | 101 | DotNetPack(s => s 102 | .SetVersion(GitVersion.NuGetVersion) 103 | .SetConfiguration(Configuration) 104 | .SetOutputDirectory(ArtifactsDirectory) 105 | .EnableNoBuild() 106 | .EnableNoRestore()); 107 | }); 108 | 109 | Target CI => _ => _ 110 | .DependsOn(Pack); 111 | } 112 | -------------------------------------------------------------------------------- /.build/Configuration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | using Nuke.Common.Tooling; 5 | 6 | [TypeConverter(typeof(TypeConverter))] 7 | public class Configuration : Enumeration 8 | { 9 | public static Configuration Debug = new Configuration { Value = nameof(Debug) }; 10 | public static Configuration Release = new Configuration { Value = nameof(Release) }; 11 | 12 | public static implicit operator string(Configuration configuration) 13 | { 14 | return configuration.Value; 15 | } 16 | } -------------------------------------------------------------------------------- /.build/Directory.build.props: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /.build/Directory.build.targets: -------------------------------------------------------------------------------- 1 |  2 | -------------------------------------------------------------------------------- /.build/_build.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net5.0 6 | 7 | CS0649;CS0169 8 | .. 9 | .. 10 | 1 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /.build/_build.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | DO_NOT_SHOW 3 | DO_NOT_SHOW 4 | DO_NOT_SHOW 5 | DO_NOT_SHOW 6 | Implicit 7 | Implicit 8 | ExpressionBody 9 | 0 10 | NEXT_LINE 11 | True 12 | False 13 | 120 14 | IF_OWNER_IS_SINGLE_LINE 15 | WRAP_IF_LONG 16 | False 17 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> 18 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> 19 | True 20 | True 21 | True 22 | True 23 | True 24 | True 25 | True 26 | True 27 | True 28 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: nuget 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | ignore: 9 | - dependency-name: System.Text.Json 10 | versions: 11 | - ">= 5.a, < 6" 12 | - dependency-name: Nuke.Common 13 | versions: 14 | - 5.1.0 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | [Ll]og/ 25 | 26 | # Visual Studio 2015 cache/options directory 27 | .vs/ 28 | # Uncomment if you have tasks that create the project's static files in wwwroot 29 | #wwwroot/ 30 | 31 | # MSTest test Results 32 | [Tt]est[Rr]esult*/ 33 | [Bb]uild[Ll]og.* 34 | 35 | # NUNIT 36 | *.VisualState.xml 37 | TestResult.xml 38 | 39 | # Build Results of an ATL Project 40 | [Dd]ebugPS/ 41 | [Rr]eleasePS/ 42 | dlldata.c 43 | 44 | # DNX 45 | project.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.binlog 67 | *.vspscc 68 | *.vssscc 69 | .builds 70 | *.pidb 71 | *.svclog 72 | *.scc 73 | 74 | # Chutzpah Test files 75 | _Chutzpah* 76 | 77 | # Visual C++ cache files 78 | ipch/ 79 | *.aps 80 | *.ncb 81 | *.opendb 82 | *.opensdf 83 | *.sdf 84 | *.cachefile 85 | *.VC.db 86 | *.VC.VC.opendb 87 | 88 | # Visual Studio profiler 89 | *.psess 90 | *.vsp 91 | *.vspx 92 | *.sap 93 | 94 | # TFS 2012 Local Workspace 95 | $tf/ 96 | 97 | # Guidance Automation Toolkit 98 | *.gpState 99 | 100 | # ReSharper is a .NET coding add-in 101 | _ReSharper*/ 102 | *.[Rr]e[Ss]harper 103 | *.DotSettings.user 104 | 105 | # JustCode is a .NET coding add-in 106 | .JustCode 107 | 108 | # TeamCity is a build add-in 109 | _TeamCity* 110 | 111 | # DotCover is a Code Coverage Tool 112 | *.dotCover 113 | 114 | # NCrunch 115 | _NCrunch_* 116 | .*crunch*.local.xml 117 | nCrunchTemp_* 118 | 119 | # MightyMoose 120 | *.mm.* 121 | AutoTest.Net/ 122 | 123 | # Web workbench (sass) 124 | .sass-cache/ 125 | 126 | # Installshield output folder 127 | [Ee]xpress/ 128 | 129 | # DocProject is a documentation generator add-in 130 | DocProject/buildhelp/ 131 | DocProject/Help/*.HxT 132 | DocProject/Help/*.HxC 133 | DocProject/Help/*.hhc 134 | DocProject/Help/*.hhk 135 | DocProject/Help/*.hhp 136 | DocProject/Help/Html2 137 | DocProject/Help/html 138 | 139 | # Click-Once directory 140 | publish/ 141 | 142 | # Publish Web Output 143 | *.[Pp]ublish.xml 144 | *.azurePubxml 145 | # TODO: Comment the next line if you want to checkin your web deploy settings 146 | # but database connection strings (with potential passwords) will be unencrypted 147 | *.pubxml 148 | *.publishproj 149 | 150 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 151 | # checkin your Azure Web App publish settings, but sensitive information contained 152 | # in these scripts will be unencrypted 153 | PublishScripts/ 154 | 155 | # NuGet Packages 156 | *.nupkg 157 | # The packages folder can be ignored because of Package Restore 158 | **/packages/* 159 | # except build/, which is used as an MSBuild target. 160 | !**/packages/build/ 161 | # Uncomment if necessary however generally it will be regenerated when needed 162 | #!**/packages/repositories.config 163 | # NuGet v3's project.json files produces more ignoreable files 164 | *.nuget.props 165 | *.nuget.targets 166 | 167 | # scriptcs 168 | **/scriptcs_packages/* 169 | 170 | # Microsoft Azure Build Output 171 | csx/ 172 | *.build.csdef 173 | 174 | # Microsoft Azure Emulator 175 | ecf/ 176 | rcf/ 177 | 178 | # Windows Store app package directories and files 179 | AppPackages/ 180 | BundleArtifacts/ 181 | Package.StoreAssociation.xml 182 | _pkginfo.txt 183 | 184 | # Visual Studio cache files 185 | # files ending in .cache can be ignored 186 | *.[Cc]ache 187 | # but keep track of directories ending in .cache 188 | !*.[Cc]ache/ 189 | 190 | # Others 191 | ClientBin/ 192 | ~$* 193 | *~ 194 | *.dbmdl 195 | *.dbproj.schemaview 196 | *.pfx 197 | *.publishsettings 198 | node_modules/ 199 | orleans.codegen.cs 200 | 201 | # Since there are multiple workflows, uncomment next line to ignore bower_components 202 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 203 | #bower_components/ 204 | 205 | # RIA/Silverlight projects 206 | Generated_Code/ 207 | 208 | # Backup & report files from converting an old project file 209 | # to a newer Visual Studio version. Backup files are not needed, 210 | # because we have git ;-) 211 | _UpgradeReport_Files/ 212 | Backup*/ 213 | UpgradeLog*.XML 214 | UpgradeLog*.htm 215 | 216 | # SQL Server files 217 | *.mdf 218 | *.ldf 219 | 220 | # Business Intelligence projects 221 | *.rdl.data 222 | *.bim.layout 223 | *.bim_*.settings 224 | 225 | # Microsoft Fakes 226 | FakesAssemblies/ 227 | 228 | # GhostDoc plugin setting file 229 | *.GhostDoc.xml 230 | 231 | # Node.js Tools for Visual Studio 232 | .ntvs_analysis.dat 233 | 234 | # Visual Studio 6 build log 235 | *.plg 236 | 237 | # Visual Studio 6 workspace options file 238 | *.opt 239 | 240 | # Visual Studio LightSwitch build output 241 | **/*.HTMLClient/GeneratedArtifacts 242 | **/*.DesktopClient/GeneratedArtifacts 243 | **/*.DesktopClient/ModelManifest.xml 244 | **/*.Server/GeneratedArtifacts 245 | **/*.Server/ModelManifest.xml 246 | _Pvt_Extensions 247 | 248 | # Paket dependency manager 249 | #.paket/paket.exe 250 | paket-files/ 251 | 252 | # FAKE - F# Make 253 | .fake/ 254 | 255 | # JetBrains Rider 256 | .idea/ 257 | *.sln.iml 258 | 259 | # cake 260 | tools/* 261 | !tools/packages.config 262 | 263 | # XamlStyler 264 | !XamlStyler/ -------------------------------------------------------------------------------- /.nuke/build.schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-04/schema#", 3 | "title": "Build Schema", 4 | "$ref": "#/definitions/build", 5 | "definitions": { 6 | "build": { 7 | "type": "object", 8 | "properties": { 9 | "ArtifactsDirectory": { 10 | "type": "string" 11 | }, 12 | "Configuration": { 13 | "type": "string", 14 | "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)", 15 | "enum": [ 16 | "Debug", 17 | "Release" 18 | ] 19 | }, 20 | "Continue": { 21 | "type": "boolean", 22 | "description": "Indicates to continue a previously failed build attempt" 23 | }, 24 | "Help": { 25 | "type": "boolean", 26 | "description": "Shows the help text for this build assembly" 27 | }, 28 | "Host": { 29 | "type": "string", 30 | "description": "Host for execution. Default is 'automatic'", 31 | "enum": [ 32 | "AppVeyor", 33 | "AzurePipelines", 34 | "Bamboo", 35 | "Bitrise", 36 | "GitHubActions", 37 | "GitLab", 38 | "Jenkins", 39 | "Rider", 40 | "SpaceAutomation", 41 | "TeamCity", 42 | "Terminal", 43 | "TravisCI", 44 | "VisualStudio", 45 | "VSCode" 46 | ] 47 | }, 48 | "NoLogo": { 49 | "type": "boolean", 50 | "description": "Disables displaying the NUKE logo" 51 | }, 52 | "Partition": { 53 | "type": "string", 54 | "description": "Partition to use on CI" 55 | }, 56 | "Plan": { 57 | "type": "boolean", 58 | "description": "Shows the execution plan (HTML)" 59 | }, 60 | "Profile": { 61 | "type": "array", 62 | "description": "Defines the profiles to load", 63 | "items": { 64 | "type": "string" 65 | } 66 | }, 67 | "Root": { 68 | "type": "string", 69 | "description": "Root directory during build execution" 70 | }, 71 | "Skip": { 72 | "type": "array", 73 | "description": "List of targets to be skipped. Empty list skips all dependencies", 74 | "items": { 75 | "type": "string", 76 | "enum": [ 77 | "CI", 78 | "Compile", 79 | "Pack", 80 | "Restore" 81 | ] 82 | } 83 | }, 84 | "Solution": { 85 | "type": "string", 86 | "description": "Path to a solution file that is automatically loaded" 87 | }, 88 | "Target": { 89 | "type": "array", 90 | "description": "List of targets to be invoked. Default is '{default_target}'", 91 | "items": { 92 | "type": "string", 93 | "enum": [ 94 | "CI", 95 | "Compile", 96 | "Pack", 97 | "Restore" 98 | ] 99 | } 100 | }, 101 | "Verbosity": { 102 | "type": "string", 103 | "description": "Logging verbosity during build execution. Default is 'Normal'", 104 | "enum": [ 105 | "Minimal", 106 | "Normal", 107 | "Quiet", 108 | "Verbose" 109 | ] 110 | } 111 | } 112 | } 113 | } 114 | } -------------------------------------------------------------------------------- /.nuke/parameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./build.schema.json", 3 | "Solution": "XamlColorSchemeGenerator.sln" 4 | } -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | true 4 | 5 | 6 | 7 | 8 | 9 | 10 | net45;netcoreapp3.1 11 | true 12 | true 13 | false 14 | Release 15 | true 16 | $(NoWarn);CS1591 17 | $(NoError);CS1591 18 | 19 | $(MSBuildThisFileDirectory)/bin/$(Configuration)/ 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 6 | https://github.com/batzen/XamlColorSchemeGenerator 7 | XamlColorSchemeGenerator 8 | Copyright © 2015 - $([System.DateTime]::Today.ToString(yyyy)) Bastian Schmidt 9 | 10 | 4.0 11 | 12 | 13 | 14 | 15 | 16 | true 17 | 18 | true 19 | 20 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 21 | 22 | 23 | True 24 | 25 | 26 | 27 | 28 | 29 | 30 | full 31 | 32 | -------------------------------------------------------------------------------- /GitVersion.yml: -------------------------------------------------------------------------------- 1 | assembly-versioning-scheme: Major 2 | assembly-file-versioning-scheme: MajorMinorPatchTag 3 | mode: ContinuousDeployment 4 | next-version: 4.0.0 5 | branches: 6 | master: 7 | mode: ContinuousDeployment 8 | tag: rc 9 | prevent-increment-of-merged-branch-version: true 10 | track-merge-target: false 11 | is-release-branch: true 12 | develop: 13 | mode: ContinuousDeployment 14 | tag: alpha 15 | prevent-increment-of-merged-branch-version: true 16 | track-merge-target: true 17 | pull-request: 18 | mode: ContinuousDelivery 19 | ignore: 20 | sha: [] 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 - 2020 Bastian Schmidt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deprecation notice 2 | 3 | This project has been deprecated and superseeded by [XAMLTools](https://github.com/batzen/XAMLTools). 4 | 5 | # XamlColorSchemeGenerator 6 | 7 | [![Build status](https://img.shields.io/appveyor/ci/batzen/XamlColorSchemeGenerator.svg?style=flat-square)](https://ci.appveyor.com/project/batzen/XamlColorSchemeGenerator) 8 | [![Release](https://img.shields.io/github/release/batzen/XamlColorSchemeGenerator.svg?style=flat-square)](https://github.com/batzen/XamlColorSchemeGenerator/releases/latest) 9 | [![Issues](https://img.shields.io/github/issues/batzen/XamlColorSchemeGenerator.svg?style=flat-square)](https://github.com/batzen/XamlColorSchemeGenerator/issues) 10 | [![Downloads](https://img.shields.io/nuget/dt/XamlColorSchemeGenerator.svg?style=flat-square)](http://www.nuget.org/packages/XamlColorSchemeGenerator/) 11 | [![Nuget](https://img.shields.io/nuget/vpre/XamlColorSchemeGenerator.svg?style=flat-square)](http://nuget.org/packages/XamlColorSchemeGenerator) 12 | [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://github.com/batzen/XamlColorSchemeGenerator/blob/master/License.txt) 13 | 14 | Generates color scheme xaml files while replacing certain parts of a template file. 15 | 16 | For an example on how this tool works see the [generator input](src/GeneratorParameters.json) and [template](src/Theme.Template.xaml) files. 17 | 18 | ## Using the tool 19 | 20 | ### Usage with commandline parameters 21 | 22 | `XamlColorSchemeGenerator` accepts the following commandline parameters: 23 | 24 | - `-g "Path_To_Your_GeneratorParameters.json"` 25 | - `-t "Path_To_Your_Theme.Template.xaml"` 26 | - `-o "Path_To_Your_Output_Folder"` 27 | - `-v` = enables verbose console output 28 | 29 | ### Usage without commandline parameters 30 | 31 | Just set the working directory to a directory containing `GeneratorParameters.json` and `Theme.Template.xaml` and call `XamlColorSchemeGenerator.exe`. 32 | The tool then also uses the current working dir as the output folder. 33 | 34 | ### Usage during build 35 | 36 | ```xml 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | ``` 47 | -------------------------------------------------------------------------------- /XamlColorSchemeGenerator.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29806.167 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "XamlColorSchemeGenerator", "src\XamlColorSchemeGenerator.csproj", "{9572E64E-0B2F-407B-AC14-141941CB7D6E}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{246A4888-9B8A-4EED-88A9-1162D7C9AF7D}" 9 | ProjectSection(SolutionItems) = preProject 10 | appveyor.yml = appveyor.yml 11 | Directory.Build.props = Directory.Build.props 12 | Directory.Build.targets = Directory.Build.targets 13 | GitVersion.yml = GitVersion.yml 14 | global.json = global.json 15 | README.md = README.md 16 | EndProjectSection 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", ".build\_build.csproj", "{5AF6F03B-F91D-4A74-83E6-7982BC836BAD}" 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Release|Any CPU = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {5AF6F03B-F91D-4A74-83E6-7982BC836BAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {5AF6F03B-F91D-4A74-83E6-7982BC836BAD}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {9572E64E-0B2F-407B-AC14-141941CB7D6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {9572E64E-0B2F-407B-AC14-141941CB7D6E}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {9572E64E-0B2F-407B-AC14-141941CB7D6E}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {9572E64E-0B2F-407B-AC14-141941CB7D6E}.Release|Any CPU.Build.0 = Release|Any CPU 32 | EndGlobalSection 33 | GlobalSection(SolutionProperties) = preSolution 34 | HideSolutionNode = FALSE 35 | EndGlobalSection 36 | GlobalSection(ExtensibilityGlobals) = postSolution 37 | SolutionGuid = {854C6F4F-4D88-4024-BEDC-34E4FCE36013} 38 | EndGlobalSection 39 | EndGlobal 40 | -------------------------------------------------------------------------------- /XamlColorSchemeGenerator.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | Required 3 | Required 4 | Required 5 | Required 6 | 7 | All 8 | True 9 | True 10 | True 11 | True 12 | True 13 | NEXT_LINE 14 | NEXT_LINE 15 | True 16 | True 17 | True 18 | NEXT_LINE 19 | NEXT_LINE 20 | NEVER 21 | NEVER 22 | True 23 | ALWAYS_USE 24 | False 25 | False 26 | False 27 | True 28 | True 29 | False 30 | CHOP_ALWAYS 31 | True 32 | True 33 | True 34 | HSL 35 | QAT 36 | <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" /> 37 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> 38 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> 39 | True 40 | 1 41 | True 42 | True 43 | True 44 | True 45 | True 46 | True 47 | True 48 | True 49 | True 50 | True -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # http://www.appveyor.com/docs/appveyor-yml 2 | branches: 3 | only: 4 | - develop 5 | - master 6 | - /v\d*\.\d*\.\d*/ 7 | 8 | image: Visual Studio 2019 9 | test: off 10 | 11 | pull_requests: 12 | do_not_increment_build_number: false 13 | 14 | install: 15 | - ps: Invoke-WebRequest 'https://dot.net/v1/dotnet-install.ps1' -OutFile 'dotnet-install.ps1' 16 | - ps: ./dotnet-install.ps1 -Version 5.0.400 -InstallDir "C:\Program Files\dotnet" 17 | 18 | build_script: 19 | - cmd: dotnet --info 20 | - cmd: build.cmd CI 21 | 22 | artifacts: 23 | - path: \artifacts\*.* 24 | 25 | nuget: 26 | disable_publish_on_pr: true 27 | 28 | skip_commits: 29 | files: 30 | - '**/*.md' -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | :; set -eo pipefail 2 | :; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) 3 | :; ${SCRIPT_DIR}/build.sh "$@" 4 | :; exit $? 5 | 6 | @ECHO OFF 7 | powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %* 8 | -------------------------------------------------------------------------------- /build.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding()] 2 | Param( 3 | [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] 4 | [string[]]$BuildArguments 5 | ) 6 | 7 | Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)" 8 | 9 | Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 } 10 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent 11 | 12 | ########################################################################### 13 | # CONFIGURATION 14 | ########################################################################### 15 | 16 | $BuildProjectFile = "$PSScriptRoot\.build\_build.csproj" 17 | $TempDirectory = "$PSScriptRoot\\.nuke\temp" 18 | 19 | $DotNetGlobalFile = "$PSScriptRoot\\global.json" 20 | $DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1" 21 | $DotNetChannel = "Current" 22 | 23 | $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1 24 | $env:DOTNET_CLI_TELEMETRY_OPTOUT = 1 25 | $env:DOTNET_MULTILEVEL_LOOKUP = 0 26 | 27 | ########################################################################### 28 | # EXECUTION 29 | ########################################################################### 30 | 31 | function ExecSafe([scriptblock] $cmd) { 32 | & $cmd 33 | if ($LASTEXITCODE) { exit $LASTEXITCODE } 34 | } 35 | 36 | # If dotnet CLI is installed globally and it matches requested version, use for execution 37 | if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and ` 38 | $(dotnet --version) -and $LASTEXITCODE -eq 0) { 39 | $env:DOTNET_EXE = (Get-Command "dotnet").Path 40 | } 41 | else { 42 | # Download install script 43 | $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1" 44 | New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null 45 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 46 | (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile) 47 | 48 | # If global.json exists, load expected version 49 | if (Test-Path $DotNetGlobalFile) { 50 | $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json) 51 | if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) { 52 | $DotNetVersion = $DotNetGlobal.sdk.version 53 | } 54 | } 55 | 56 | # Install by channel or version 57 | $DotNetDirectory = "$TempDirectory\dotnet-win" 58 | if (!(Test-Path variable:DotNetVersion)) { 59 | ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath } 60 | } else { 61 | ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath } 62 | } 63 | $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe" 64 | } 65 | 66 | Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)" 67 | 68 | ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet } 69 | ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments } 70 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | bash --version 2>&1 | head -n 1 4 | 5 | set -eo pipefail 6 | SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) 7 | 8 | ########################################################################### 9 | # CONFIGURATION 10 | ########################################################################### 11 | 12 | BUILD_PROJECT_FILE="$SCRIPT_DIR/.build/_build.csproj" 13 | TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp" 14 | 15 | DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" 16 | DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh" 17 | DOTNET_CHANNEL="Current" 18 | 19 | export DOTNET_CLI_TELEMETRY_OPTOUT=1 20 | export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 21 | export DOTNET_MULTILEVEL_LOOKUP=0 22 | 23 | ########################################################################### 24 | # EXECUTION 25 | ########################################################################### 26 | 27 | function FirstJsonValue { 28 | perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}" 29 | } 30 | 31 | # If dotnet CLI is installed globally and it matches requested version, use for execution 32 | if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then 33 | export DOTNET_EXE="$(command -v dotnet)" 34 | else 35 | # Download install script 36 | DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh" 37 | mkdir -p "$TEMP_DIRECTORY" 38 | curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL" 39 | chmod +x "$DOTNET_INSTALL_FILE" 40 | 41 | # If global.json exists, load expected version 42 | if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then 43 | DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")") 44 | if [[ "$DOTNET_VERSION" == "" ]]; then 45 | unset DOTNET_VERSION 46 | fi 47 | fi 48 | 49 | # Install by channel or version 50 | DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix" 51 | if [[ -z ${DOTNET_VERSION+x} ]]; then 52 | "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path 53 | else 54 | "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path 55 | fi 56 | export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet" 57 | fi 58 | 59 | echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)" 60 | 61 | "$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet 62 | "$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@" 63 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "5.0.400", 4 | "rollForward": "latestFeature" 5 | } 6 | } -------------------------------------------------------------------------------- /src/App.net.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/App.netcoreapp.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ColorSchemeGenerator.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | namespace XamlColorSchemeGenerator 3 | { 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Text; 10 | 11 | public class ColorSchemeGenerator 12 | { 13 | private const int BufferSize = 32768; // 32 Kilobytes 14 | 15 | public void GenerateColorSchemeFiles(string generatorParametersFile, string templateFile, string? outputPath = null) 16 | { 17 | var parameters = GetParametersFromFile(generatorParametersFile); 18 | 19 | outputPath ??= Path.GetDirectoryName(Path.GetFullPath(templateFile)); 20 | 21 | if (string.IsNullOrEmpty(outputPath)) 22 | { 23 | throw new Exception("OutputPath could not be determined."); 24 | } 25 | 26 | Directory.CreateDirectory(outputPath); 27 | 28 | var templateContent = File.ReadAllText(templateFile, Encoding.UTF8); 29 | 30 | var colorSchemesWithoutVariantName = parameters.ColorSchemes 31 | .Where(x => string.IsNullOrEmpty(x.ForColorSchemeVariant) || x.ForColorSchemeVariant == "None") 32 | .ToList(); 33 | var colorSchemesWithVariantName = parameters.ColorSchemes 34 | .Where(x => string.IsNullOrEmpty(x.ForColorSchemeVariant) == false && x.ForColorSchemeVariant != "None") 35 | .ToList(); 36 | 37 | foreach (var baseColorScheme in parameters.BaseColorSchemes) 38 | { 39 | if (colorSchemesWithoutVariantName.Count == 0 40 | && colorSchemesWithVariantName.Count == 0) 41 | { 42 | var themeName = baseColorScheme.Name; 43 | var colorSchemeName = string.Empty; 44 | var alternativeColorSchemeName = string.Empty; 45 | var themeDisplayName = baseColorScheme.Name; 46 | 47 | this.GenerateColorSchemeFile(outputPath, templateContent, themeName, themeDisplayName, baseColorScheme.Name, colorSchemeName, alternativeColorSchemeName, false, baseColorScheme.Values, parameters.DefaultValues); 48 | } 49 | 50 | foreach (var colorScheme in colorSchemesWithoutVariantName) 51 | { 52 | if (string.IsNullOrEmpty(colorScheme.ForBaseColor) == false 53 | && colorScheme.ForBaseColor != baseColorScheme.Name) 54 | { 55 | continue; 56 | } 57 | 58 | var themeName = $"{baseColorScheme.Name}.{colorScheme.Name}"; 59 | var colorSchemeName = colorScheme.Name; 60 | var alternativeColorSchemeName = colorScheme.Name; 61 | var themeDisplayName = $"{colorSchemeName} ({baseColorScheme.Name})"; 62 | 63 | this.GenerateColorSchemeFile(outputPath, templateContent, themeName, themeDisplayName, baseColorScheme.Name, colorSchemeName, alternativeColorSchemeName, colorScheme.IsHighContrast, colorScheme.Values, baseColorScheme.Values, parameters.DefaultValues); 64 | } 65 | 66 | foreach (var colorSchemeVariant in parameters.AdditionalColorSchemeVariants) 67 | { 68 | foreach (var colorScheme in colorSchemesWithoutVariantName.Concat(colorSchemesWithVariantName)) 69 | { 70 | if (string.IsNullOrEmpty(colorScheme.ForBaseColor) == false 71 | && colorScheme.ForBaseColor != baseColorScheme.Name) 72 | { 73 | continue; 74 | } 75 | 76 | if (colorScheme.ForColorSchemeVariant == "None") 77 | { 78 | continue; 79 | } 80 | 81 | var themeName = $"{baseColorScheme.Name}.{colorScheme.Name}.{colorSchemeVariant.Name}"; 82 | var colorSchemeName = $"{colorScheme.Name}.{colorSchemeVariant.Name}"; 83 | var alternativeColorSchemeName = colorScheme.Name; 84 | var themeDisplayName = $"{colorSchemeName} ({baseColorScheme.Name})"; 85 | 86 | this.GenerateColorSchemeFile(outputPath, templateContent, themeName, themeDisplayName, baseColorScheme.Name, colorSchemeName, alternativeColorSchemeName, colorScheme.IsHighContrast, colorScheme.Values, colorSchemeVariant.Values, baseColorScheme.Values, parameters.DefaultValues); 87 | } 88 | } 89 | } 90 | } 91 | 92 | public static ThemeGenerator.ThemeGeneratorParameters GetParametersFromFile(string inputFile) 93 | { 94 | return ThemeGenerator.Current.GetParametersFromString(ReadAllTextShared(inputFile)); 95 | } 96 | 97 | private static string ReadAllTextShared(string file) 98 | { 99 | Stream? stream = null; 100 | try 101 | { 102 | stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize); 103 | 104 | using (var textReader = new StreamReader(stream, Encoding.UTF8)) 105 | { 106 | stream = null; 107 | return textReader.ReadToEnd(); 108 | } 109 | } 110 | finally 111 | { 112 | stream?.Dispose(); 113 | } 114 | } 115 | 116 | public void GenerateColorSchemeFile(string templateDirectory, string templateContent, string themeName, string themeDisplayName, string baseColorScheme, string colorScheme, string alternativeColorScheme, bool isHighContrast, params Dictionary[] valueSources) 117 | { 118 | if (isHighContrast) 119 | { 120 | themeDisplayName += " HighContrast"; 121 | } 122 | 123 | var themeTempFileContent = ThemeGenerator.Current.GenerateColorSchemeFileContent(templateContent, themeName, themeDisplayName, baseColorScheme, colorScheme, alternativeColorScheme, isHighContrast, valueSources); 124 | 125 | var themeFilename = $"{themeName}"; 126 | 127 | if (isHighContrast) 128 | { 129 | themeFilename += ".HighContrast"; 130 | } 131 | 132 | var themeFile = Path.Combine(templateDirectory, $"{themeFilename}.xaml"); 133 | 134 | Trace.WriteLine($"Checking \"{themeFile}\"..."); 135 | 136 | var fileHasToBeWritten = File.Exists(themeFile) == false 137 | || ReadAllTextShared(themeFile) != themeTempFileContent; 138 | 139 | if (fileHasToBeWritten) 140 | { 141 | using (var sw = new StreamWriter(themeFile, false, Encoding.UTF8, BufferSize)) 142 | { 143 | sw.Write(themeTempFileContent); 144 | } 145 | 146 | Trace.WriteLine($"Resource Dictionary saved to \"{themeFile}\"."); 147 | } 148 | else 149 | { 150 | Trace.WriteLine("New Resource Dictionary did not differ from existing file. No new file written."); 151 | } 152 | } 153 | } 154 | } -------------------------------------------------------------------------------- /src/GeneratorParameters.json: -------------------------------------------------------------------------------- 1 | { 2 | "DefaultValues": { 3 | "Fluent.Ribbon.Colors.IdealForegroundColor": "White", 4 | "Fluent.Ribbon.Colors.DarkIdealForegroundDisabledColor": "#ADADAD", 5 | "Fluent.Ribbon.Colors.ExtremeHighlightColor": "#FFFFD232", 6 | "Fluent.Ribbon.Colors.DarkExtremeHighlightColor": "#FFF29536", 7 | "Fluent.Ribbon.Brushes.ApplicationMenuItem.CheckBox.Background": "#FFFCF1C2", 8 | "Fluent.Ribbon.Brushes.ApplicationMenuItem.CheckBox.BorderBrush": "#FFF29536" 9 | }, 10 | "BaseColorSchemes": [ 11 | { 12 | "Name": "Dark", 13 | "Values": { 14 | "BlackColor": "#FFFFFFFF", 15 | "WhiteColor": "#FF252525", 16 | "Gray1": "#FFF9F9F9", 17 | "Gray2": "#FF7F7F7F", 18 | "Gray3": "#FF9D9D9D", 19 | "Gray4": "#FFA59F93", 20 | "Gray5": "#FFB9B9B9", 21 | "Gray6": "#FFCCCCCC", 22 | "Gray7": "#FF7E7E7E", 23 | "Gray8": "#FF454545", 24 | "Gray9": "#5EC9C9C9", 25 | "Gray10": "#FF2F2F2F", 26 | "Fluent.Ribbon.Brushes.LabelTextBrush": "{StaticResource Gray6}", 27 | "Fluent.Ribbon.Brushes.RibbonContextualTabGroup.TabItemMouseOverForeground": "{StaticResource BlackBrush}", 28 | "Fluent.Ribbon.Brushes.RibbonGroupBox.Header.Foreground": "{StaticResource Gray6}", 29 | "Fluent.Ribbon.Brushes.RibbonTabControl.Content.Background": "#363636", 30 | "Fluent.Ribbon.Brushes.RibbonTabControl.Content.Foreground": "{StaticResource Gray6}", 31 | "Fluent.Ribbon.Brushes.RibbonTabItem.Foreground": "{StaticResource Gray5}", 32 | "Fluent.Ribbon.Brushes.RibbonTabItem.Active.Background": "#363636", 33 | "Fluent.Ribbon.Brushes.RibbonTabItem.MouseOver.Background": "#444444", 34 | "Fluent.Ribbon.Brushes.RibbonTabItem.MouseOver.Foreground": "{StaticResource BlackBrush}" 35 | } 36 | }, 37 | { 38 | "Name": "Light", 39 | "Values": { 40 | "BlackColor": "#FF000000", 41 | "WhiteColor": "#FFFFFFFF", 42 | "Gray1": "#FF333333", 43 | "Gray2": "#FF7F7F7F", 44 | "Gray3": "#FF9D9D9D", 45 | "Gray4": "#FFA59F93", 46 | "Gray5": "#FFB9B9B9", 47 | "Gray6": "#FFCCCCCC", 48 | "Gray7": "#FFD8D8D9", 49 | "Gray8": "#FFE0E0E0", 50 | "Gray9": "#5EC9C9C9", 51 | "Gray10": "#FFF7F7F7", 52 | "Fluent.Ribbon.Brushes.LabelTextBrush": "{StaticResource BlackColor}", 53 | "Fluent.Ribbon.Brushes.RibbonGroupBox.Header.Foreground": "{StaticResource Gray2}", 54 | "Fluent.Ribbon.Brushes.RibbonContextualTabGroup.TabItemMouseOverForeground": "{StaticResource Fluent.Ribbon.Colors.HighlightColor}", 55 | "Fluent.Ribbon.Brushes.RibbonTabControl.Content.Background": "{StaticResource WhiteColor}", 56 | "Fluent.Ribbon.Brushes.RibbonTabControl.Content.Foreground": "{StaticResource BlackColor}", 57 | "Fluent.Ribbon.Brushes.RibbonTabItem.Foreground": "{StaticResource BlackColor}", 58 | "Fluent.Ribbon.Brushes.RibbonTabItem.Active.Background": "{StaticResource WhiteColor}", 59 | "Fluent.Ribbon.Brushes.RibbonTabItem.MouseOver.Background": "Transparent", 60 | "Fluent.Ribbon.Brushes.RibbonTabItem.MouseOver.Foreground": "{StaticResource Fluent.Ribbon.Colors.HighlightColor}" 61 | } 62 | } 63 | ], 64 | "AdditionalColorSchemeVariants": [ 65 | { 66 | "Name": "Colorful", 67 | "Values": { 68 | "Fluent.Ribbon.Colors.Images.DefaultColor": "{StaticResource Fluent.Ribbon.Colors.IdealForegroundColor}", 69 | "Fluent.Ribbon.Brushes.RibbonTabControl.Background": "{StaticResource Fluent.Ribbon.Colors.AccentBaseColor}", 70 | "Fluent.Ribbon.Brushes.RibbonContextualTabGroup.TabItemSelectedForeground": "{StaticResource Gray1}", 71 | "Fluent.Ribbon.Brushes.RibbonContextualTabGroup.TabItemMouseOverForeground": "{StaticResource Fluent.Ribbon.Colors.IdealForegroundColor}", 72 | "Fluent.Ribbon.Brushes.RibbonContextualTabGroup.TabItemSelectedMouseOverForeground": "{StaticResource Gray1}", 73 | "Fluent.Ribbon.Brushes.RibbonTabItem.Foreground": "{StaticResource Fluent.Ribbon.Colors.IdealForegroundColor}", 74 | "Fluent.Ribbon.Brushes.RibbonTabItem.MouseOver.Background": "#44FFFFFF", 75 | "Fluent.Ribbon.Brushes.RibbonTabItem.MouseOver.Foreground": "{StaticResource WhiteColor}", 76 | "Fluent.Ribbon.Brushes.RibbonTabItem.Selected.MouseOver.Foreground": "{StaticResource Gray1}", 77 | "Fluent.Ribbon.Brushes.RibbonWindow.TitleBackground": "{StaticResource Fluent.Ribbon.Colors.AccentBaseColor}", 78 | "Fluent.Ribbon.Brushes.RibbonWindow.TitleForeground": "{StaticResource Fluent.Ribbon.Colors.IdealForegroundColor}", 79 | "Fluent.Ribbon.Brushes.WindowCommands.CaptionButton.Foreground": "{StaticResource Fluent.Ribbon.Colors.IdealForegroundColor}" 80 | } 81 | } 82 | ], 83 | "ColorSchemes": [ 84 | { 85 | "Name": "Blue", 86 | "ForColorSchemeVariant": "Colorful", 87 | "Values": { 88 | "Fluent.Ribbon.Colors.AccentBaseColor": "#FF2B579A", 89 | "Fluent.Ribbon.Colors.AccentColor80": "#CC2B579A", 90 | "Fluent.Ribbon.Colors.AccentColor60": "#992B579A", 91 | "Fluent.Ribbon.Colors.AccentColor40": "#662B579A", 92 | "Fluent.Ribbon.Colors.AccentColor20": "#332B579A", 93 | "Fluent.Ribbon.Colors.HighlightColor": "#FF086F9E" 94 | } 95 | }, 96 | { 97 | "Name": "Green", 98 | "ForBaseColor": "Light", 99 | "ForColorSchemeVariant": "None", 100 | "IsHighContrast": true, 101 | "Values": { 102 | "Fluent.Ribbon.Colors.AccentBaseColor": "#FF60A917", 103 | "Fluent.Ribbon.Colors.AccentColor80": "#CC60A917", 104 | "Fluent.Ribbon.Colors.AccentColor60": "#9960A917", 105 | "Fluent.Ribbon.Colors.AccentColor40": "#6660A917", 106 | "Fluent.Ribbon.Colors.AccentColor20": "#3360A917", 107 | "Fluent.Ribbon.Colors.HighlightColor": "#FF477D11" 108 | } 109 | }, 110 | { 111 | "Name": "Green", 112 | "ForBaseColor": "Dark", 113 | "IsHighContrast": true, 114 | "Values": { 115 | "Fluent.Ribbon.Colors.AccentBaseColor": "#FF60A917", 116 | "Fluent.Ribbon.Colors.AccentColor80": "#CC60A917", 117 | "Fluent.Ribbon.Colors.AccentColor60": "#9960A917", 118 | "Fluent.Ribbon.Colors.AccentColor40": "#6660A917", 119 | "Fluent.Ribbon.Colors.AccentColor20": "#3360A917", 120 | "Fluent.Ribbon.Colors.HighlightColor": "#FF477D11" 121 | } 122 | }, 123 | { 124 | "Name": "Blue", 125 | "Values": { 126 | "Fluent.Ribbon.Colors.AccentBaseColor": "#FF2B579A", 127 | "Fluent.Ribbon.Colors.AccentColor80": "#CC2B579A", 128 | "Fluent.Ribbon.Colors.AccentColor60": "#992B579A", 129 | "Fluent.Ribbon.Colors.AccentColor40": "#662B579A", 130 | "Fluent.Ribbon.Colors.AccentColor20": "#332B579A", 131 | "Fluent.Ribbon.Colors.HighlightColor": "#FF086F9E" 132 | } 133 | }, 134 | { 135 | "Name": "Yellow", 136 | "Values": { 137 | "Fluent.Ribbon.Colors.AccentBaseColor": "#FFFEDE06", 138 | "Fluent.Ribbon.Colors.AccentColor80": "#CCFEDE06", 139 | "Fluent.Ribbon.Colors.AccentColor60": "#99FEDE06", 140 | "Fluent.Ribbon.Colors.AccentColor40": "#66FEDE06", 141 | "Fluent.Ribbon.Colors.AccentColor20": "#33FEDE06", 142 | "Fluent.Ribbon.Colors.HighlightColor": "#FFBBA404", 143 | "Fluent.Ribbon.Colors.IdealForegroundColor": "Black", 144 | "Fluent.Ribbon.Colors.DarkIdealForegroundDisabledColor": "Pink", 145 | "Fluent.Ribbon.Colors.ExtremeHighlightColor": "#FFFFD232", 146 | "Fluent.Ribbon.Colors.DarkExtremeHighlightColor": "#FFF29536" 147 | } 148 | } 149 | ] 150 | } -------------------------------------------------------------------------------- /src/Program.cs: -------------------------------------------------------------------------------- 1 | namespace XamlColorSchemeGenerator 2 | { 3 | using System; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Runtime; 9 | using System.Threading; 10 | 11 | internal class Program 12 | { 13 | private static int Main(string[] args) 14 | { 15 | const string ProfileFile = "XamlColorSchemeGenerator.profile"; 16 | 17 | ProfileOptimization.SetProfileRoot(Environment.GetEnvironmentVariable("temp")); 18 | ProfileOptimization.StartProfile(ProfileFile); 19 | 20 | var stopwatch = Stopwatch.StartNew(); 21 | 22 | var nologo = args.Any(x => x.Equals("-nologo", StringComparison.OrdinalIgnoreCase)); 23 | var verbose = args.Any(x => x.Equals("-v", StringComparison.OrdinalIgnoreCase)); 24 | var indexForGeneratorParametersFile = Array.IndexOf(args, "-g") + 1; 25 | var indexForTemplateFile = Array.IndexOf(args, "-t") + 1; 26 | var indexForOutputPath = Array.IndexOf(args, "-o") + 1; 27 | 28 | try 29 | { 30 | if (nologo == false) 31 | { 32 | var attribute = (AssemblyFileVersionAttribute)Attribute.GetCustomAttribute(typeof(Program).Assembly, typeof(AssemblyFileVersionAttribute)); 33 | var version = attribute.Version; 34 | Console.WriteLine($"XamlColorSchemeGenerator - {version}"); 35 | } 36 | 37 | if (verbose) 38 | { 39 | Console.WriteLine("Starting file generation with args:"); 40 | Console.WriteLine(string.Join(" ", args)); 41 | } 42 | 43 | var generatorParametersFile = indexForGeneratorParametersFile > 0 && args.Length >= indexForGeneratorParametersFile 44 | ? args[indexForGeneratorParametersFile] 45 | : "GeneratorParameters.json"; 46 | var templateFile = indexForTemplateFile > 0 && args.Length >= indexForTemplateFile 47 | ? args[indexForTemplateFile] 48 | : "Theme.Template.xaml"; 49 | var outputPath = indexForOutputPath > 0 && args.Length >= indexForOutputPath 50 | ? args[indexForOutputPath] 51 | : null; 52 | 53 | using (var mutex = Lock(generatorParametersFile)) 54 | { 55 | try 56 | { 57 | var generator = new ColorSchemeGenerator(); 58 | 59 | generator.GenerateColorSchemeFiles(generatorParametersFile, templateFile, outputPath); 60 | } 61 | finally 62 | { 63 | mutex.ReleaseMutex(); 64 | stopwatch.Stop(); 65 | } 66 | } 67 | 68 | // TODO: Add help output. 69 | 70 | if (verbose) 71 | { 72 | Console.WriteLine($"Generation time: {stopwatch.Elapsed}"); 73 | } 74 | 75 | return 0; 76 | } 77 | catch (Exception e) 78 | { 79 | Trace.WriteLine(e); 80 | Console.WriteLine(e); 81 | 82 | if (Debugger.IsAttached) 83 | { 84 | Console.ReadLine(); 85 | } 86 | 87 | return 1; 88 | } 89 | } 90 | 91 | private static Mutex Lock(string file) 92 | { 93 | var mutexName = "Local\\XamlColorSchemeGenerator_" + Path.GetFileName(file); 94 | 95 | var mutex = new Mutex(false, mutexName); 96 | 97 | if (mutex.WaitOne(TimeSpan.FromSeconds(10)) == false) 98 | { 99 | throw new TimeoutException("Another instance of this application blocked the concurrent execution."); 100 | } 101 | 102 | return mutex; 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /src/SharedKey.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/batzen/XamlColorSchemeGenerator/ae98c80b478d407e1bde53c56793975bde72bf5b/src/SharedKey.snk -------------------------------------------------------------------------------- /src/Theme.Template.xaml: -------------------------------------------------------------------------------- 1 |  8 | {{ThemeName}} 9 | Fluent.Ribbon 10 | {{ThemeDisplayName}} 11 | {{BaseColorScheme}} 12 | {{ColorScheme}} 13 | {{AlternativeColorScheme}} 14 | {{Fluent.Ribbon.Colors.AccentBaseColor}} 15 | 16 | {{IsHighContrast}} 17 | 18 | 19 | 20 | 21 | {{Fluent.Ribbon.Colors.AccentBaseColor}} 22 | 23 | {{Fluent.Ribbon.Colors.AccentColor80}} 24 | 25 | {{Fluent.Ribbon.Colors.AccentColor60}} 26 | 27 | {{Fluent.Ribbon.Colors.AccentColor40}} 28 | 29 | {{Fluent.Ribbon.Colors.AccentColor20}} 30 | 31 | {{Fluent.Ribbon.Colors.HighlightColor}} 32 | 33 | 34 | {{BlackColor}} 35 | {{WhiteColor}} 36 | {{Gray1}} 37 | {{Gray2}} 38 | {{Gray3}} 39 | {{Gray4}} 40 | {{Gray5}} 41 | {{Gray6}} 42 | {{Gray7}} 43 | {{Gray8}} 44 | {{Gray9}} 45 | {{Gray10}} 46 | 47 | #00FFFFFF 48 | #17FFFFFF 49 | 50 | 51 | {{Fluent.Ribbon.Colors.IdealForegroundColor}} 52 | {{Fluent.Ribbon.Colors.DarkIdealForegroundDisabledColor}} 53 | 54 | 55 | {{Fluent.Ribbon.Colors.ExtremeHighlightColor}} 56 | {{Fluent.Ribbon.Colors.DarkExtremeHighlightColor}} 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | -------------------------------------------------------------------------------- /src/ThemeGenerator.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | namespace XamlColorSchemeGenerator 3 | { 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using JetBrains.Annotations; 7 | 8 | // This class has to be kept in sync with https://github.com/ControlzEx/ControlzEx/blob/develop/src/ControlzEx/Theming/ThemeGenerator.cs 9 | // Please do not remove unused code/properties here as it makes syncing more difficult. 10 | [PublicAPI] 11 | public class ThemeGenerator 12 | { 13 | public static ThemeGenerator Current { get; set; } 14 | 15 | static ThemeGenerator() 16 | { 17 | Current = new ThemeGenerator(); 18 | } 19 | 20 | public virtual ThemeGeneratorParameters GetParametersFromString(string input) 21 | { 22 | #if NETCOREAPP || NET5_0_OR_GREATER 23 | return System.Text.Json.JsonSerializer.Deserialize(input) ?? new ThemeGeneratorParameters(); 24 | #else 25 | return new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize(input); 26 | #endif 27 | } 28 | 29 | // The order of the passed valueSources is important. 30 | // More specialized/concrete values must be passed first and more generic ones must follow. 31 | public virtual string GenerateColorSchemeFileContent(string templateContent, string themeName, string themeDisplayName, string baseColorScheme, string colorScheme, string alternativeColorScheme, bool isHighContrast, params Dictionary[] valueSources) 32 | { 33 | templateContent = templateContent.Replace("{{ThemeName}}", themeName); 34 | templateContent = templateContent.Replace("{{ThemeDisplayName}}", themeDisplayName); 35 | templateContent = templateContent.Replace("{{BaseColorScheme}}", baseColorScheme); 36 | templateContent = templateContent.Replace("{{ColorScheme}}", colorScheme); 37 | templateContent = templateContent.Replace("{{AlternativeColorScheme}}", alternativeColorScheme); 38 | templateContent = templateContent.Replace("{{IsHighContrast}}", isHighContrast.ToString()); 39 | 40 | foreach (var valueSource in valueSources) 41 | { 42 | foreach (var value in valueSource) 43 | { 44 | templateContent = templateContent.Replace($"{{{{{value.Key}}}}}", value.Value); 45 | } 46 | } 47 | 48 | return templateContent; 49 | } 50 | 51 | [PublicAPI] 52 | public class ThemeGeneratorParameters 53 | { 54 | public Dictionary DefaultValues { get; set; } = new Dictionary(); 55 | 56 | public ThemeGeneratorBaseColorScheme[] BaseColorSchemes { get; set; } = new ThemeGeneratorBaseColorScheme[0]; 57 | 58 | public ThemeGeneratorColorScheme[] ColorSchemes { get; set; } = new ThemeGeneratorColorScheme[0]; 59 | 60 | public AdditionalColorSchemeVariant[] AdditionalColorSchemeVariants { get; set; } = new AdditionalColorSchemeVariant[0]; 61 | } 62 | 63 | [PublicAPI] 64 | [DebuggerDisplay("{" + nameof(Name) + "}")] 65 | public class ThemeGeneratorBaseColorScheme 66 | { 67 | public string Name { get; set; } = string.Empty; 68 | 69 | public Dictionary Values { get; set; } = new Dictionary(); 70 | } 71 | 72 | [PublicAPI] 73 | [DebuggerDisplay("{" + nameof(Name) + "}")] 74 | public class AdditionalColorSchemeVariant 75 | { 76 | public string Name { get; set; } = string.Empty; 77 | 78 | public Dictionary Values { get; set; } = new Dictionary(); 79 | } 80 | 81 | [PublicAPI] 82 | [DebuggerDisplay("{" + nameof(Name) + "}")] 83 | public class ThemeGeneratorColorScheme 84 | { 85 | public string Name { get; set; } = string.Empty; 86 | 87 | public string ForBaseColor { get; set; } = string.Empty; 88 | 89 | public string ForColorSchemeVariant { get; set; } = string.Empty; 90 | 91 | public bool IsHighContrast { get; set; } 92 | 93 | public Dictionary Values { get; set; } = new Dictionary(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/XamlColorSchemeGenerator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | Generates color scheme xaml files while replacing certain parts of a template file. 7 | 8 | 9 | 10 | Exe 11 | app.manifest 12 | 13 | latest 14 | 15 | 16 | 17 | 18 | $(AssemblyName).exe.config 19 | 20 | 21 | 22 | $(AssemblyName).exe.config 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | Bastian Schmidt 47 | MIT 48 | https://github.com/batzen/XamlColorSchemeGenerator 49 | 50 | xaml color scheme generator 51 | https://github.com/batzen/XamlColorSchemeGenerator/releases 52 | https://github.com/batzen/XamlColorSchemeGenerator.git 53 | git 54 | 55 | false 56 | true 57 | true 58 | 59 | 60 | 61 | 62 | True 63 | $(MSBuildProjectDirectory)\SharedKey.snk 64 | false 65 | true 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | PreserveNewest 76 | 77 | 78 | PreserveNewest 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 6 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/build/XamlColorSchemeGenerator.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildThisFileDirectory)..\tools\net45\XamlColorSchemeGenerator.exe 5 | $(MSBuildThisFileDirectory)..\tools\netcoreapp3.1\XamlColorSchemeGenerator.exe 6 | 7 | -------------------------------------------------------------------------------- /src/buildMultiTargeting/XamlColorSchemeGenerator.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | --------------------------------------------------------------------------------