/MaterialDesignColors.Wpf/SwatchesProvider.cs

https://github.com/ButchersBoy/MaterialDesignInXamlToolkit · C# · 107 lines · 83 code · 13 blank · 11 comment · 12 complexity · 26679d706919a14b7717f0875b96444d MD5 · raw file

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Linq;
  6. using System.Reflection;
  7. using System.Resources;
  8. using System.Text.RegularExpressions;
  9. using System.Windows;
  10. using System.Windows.Media;
  11. namespace MaterialDesignColors
  12. {
  13. /// <summary>
  14. /// Provides access to all colour swatches. For information regarding Material Design colours see https://www.google.com/design/spec/style/color.html
  15. /// </summary>
  16. public class SwatchesProvider
  17. {
  18. /// <summary>
  19. /// Generates an instance reading swatches from the provided assembly, allowing
  20. /// colours outside of the standard material palette to be loaded provided the are stored in the expected XAML format.
  21. /// </summary>
  22. /// <param name="assembly"></param>
  23. public SwatchesProvider(Assembly assembly)
  24. {
  25. var resourcesName = assembly.GetName().Name + ".g";
  26. var manager = new ResourceManager(resourcesName, assembly);
  27. var resourceSet = manager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
  28. var dictionaryEntries = resourceSet.OfType<DictionaryEntry>().ToList();
  29. var assemblyName = assembly.GetName().Name;
  30. var regex = new Regex(@"^themes\/materialdesigncolor\.(?<name>[a-z]+)\.(?<type>primary|accent)\.baml$");
  31. Swatches =
  32. dictionaryEntries
  33. .Select(x => new { key = x.Key.ToString(), match = regex.Match(x.Key.ToString()) })
  34. .Where(x => x.match.Success && x.match.Groups["name"].Value != "black")
  35. .GroupBy(x => x.match.Groups["name"].Value)
  36. .Select(x =>
  37. CreateSwatch
  38. (
  39. x.Key,
  40. Read(assemblyName, x.SingleOrDefault(y => y.match.Groups["type"].Value == "primary")?.key),
  41. Read(assemblyName, x.SingleOrDefault(y => y.match.Groups["type"].Value == "accent")?.key)
  42. ))
  43. .ToList();
  44. }
  45. /// <summary>
  46. /// Creates a new swatch provider based on standard Material Design colors.
  47. /// </summary>
  48. public SwatchesProvider() : this(Assembly.GetExecutingAssembly())
  49. { }
  50. public IEnumerable<Swatch> Swatches { get; }
  51. private static Swatch CreateSwatch(string name, ResourceDictionary primaryDictionary, ResourceDictionary accentDictionary)
  52. {
  53. var primaryHues = new List<Hue>();
  54. var accentHues = new List<Hue>();
  55. if (primaryDictionary != null)
  56. {
  57. foreach (var entry in primaryDictionary.OfType<DictionaryEntry>()
  58. .OrderBy(de => de.Key)
  59. .Where(de => !de.Key.ToString().EndsWith("Foreground", StringComparison.Ordinal)))
  60. {
  61. var colour = (Color)entry.Value;
  62. var foregroundColour = (Color)
  63. primaryDictionary.OfType<DictionaryEntry>()
  64. .Single(de => de.Key.ToString().Equals(entry.Key.ToString() + "Foreground"))
  65. .Value;
  66. primaryHues.Add(new Hue(entry.Key.ToString(), colour, foregroundColour));
  67. }
  68. }
  69. if (accentDictionary != null)
  70. {
  71. foreach (var entry in accentDictionary.OfType<DictionaryEntry>()
  72. .OrderBy(de => de.Key)
  73. .Where(de => !de.Key.ToString().EndsWith("Foreground", StringComparison.Ordinal)))
  74. {
  75. var colour = (Color)entry.Value;
  76. var foregroundColour = (Color)
  77. accentDictionary.OfType<DictionaryEntry>()
  78. .Single(de => de.Key.ToString().Equals(entry.Key.ToString() + "Foreground"))
  79. .Value;
  80. accentHues.Add(new Hue(entry.Key.ToString(), colour, foregroundColour));
  81. }
  82. }
  83. return new Swatch(name, primaryHues, accentHues);
  84. }
  85. private static ResourceDictionary Read(string assemblyName, string path)
  86. {
  87. if (assemblyName == null || path == null)
  88. return null;
  89. return (ResourceDictionary)Application.LoadComponent(new Uri(
  90. $"/{assemblyName};component/{path.Replace(".baml", ".xaml")}",
  91. UriKind.RelativeOrAbsolute));
  92. }
  93. }
  94. }