Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/xamarin/Xamarin.PropertyEditing.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Xamarin.PropertyEditing.Tests/MaterialDesignColorViewModelTests.cs243
-rw-r--r--Xamarin.PropertyEditing.Tests/Xamarin.PropertyEditing.Tests.csproj1
-rw-r--r--Xamarin.PropertyEditing.Windows.Standalone/MainWindow.xaml.cs5
-rw-r--r--Xamarin.PropertyEditing.Windows.Standalone/MockedSampleControlButton.cs15
-rw-r--r--Xamarin.PropertyEditing.Windows/BrushBoxControl.cs11
-rw-r--r--Xamarin.PropertyEditing.Windows/BrushChoiceTemplateSelector.cs7
-rw-r--r--Xamarin.PropertyEditing.Windows/BrushTabbedEditorControl.cs73
-rw-r--r--Xamarin.PropertyEditing.Windows/BrushToDarknessConverter.cs29
-rw-r--r--Xamarin.PropertyEditing.Windows/ChoiceControl.cs1
-rw-r--r--Xamarin.PropertyEditing.Windows/ColorToTransparentColorConverter.cs (renamed from Xamarin.PropertyEditing.Windows/ObjectToTypeNameConverter.cs)20
-rw-r--r--Xamarin.PropertyEditing.Windows/MaterialDesignColorEditorControl.cs11
-rw-r--r--Xamarin.PropertyEditing.Windows/Themes/Resources.xaml271
-rw-r--r--Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj6
-rw-r--r--Xamarin.PropertyEditing/Drawing/CommonColor.cs20
-rw-r--r--Xamarin.PropertyEditing/Properties/Resources.Designer.cs180
-rw-r--r--Xamarin.PropertyEditing/Properties/Resources.resx63
-rw-r--r--Xamarin.PropertyEditing/TargetPlatform.cs9
-rw-r--r--Xamarin.PropertyEditing/ViewModels/BrushPropertyViewModel.cs4
-rw-r--r--Xamarin.PropertyEditing/ViewModels/MaterialColorScale.cs32
-rw-r--r--Xamarin.PropertyEditing/ViewModels/MaterialDesignColorViewModel.cs251
-rw-r--r--Xamarin.PropertyEditing/Xamarin.PropertyEditing.csproj2
21 files changed, 1214 insertions, 40 deletions
diff --git a/Xamarin.PropertyEditing.Tests/MaterialDesignColorViewModelTests.cs b/Xamarin.PropertyEditing.Tests/MaterialDesignColorViewModelTests.cs
new file mode 100644
index 0000000..b6866fd
--- /dev/null
+++ b/Xamarin.PropertyEditing.Tests/MaterialDesignColorViewModelTests.cs
@@ -0,0 +1,243 @@
+using System;
+using System.Linq;
+using Moq;
+using NUnit.Framework;
+using Xamarin.PropertyEditing.Drawing;
+using Xamarin.PropertyEditing.ViewModels;
+
+namespace Xamarin.PropertyEditing.Tests
+{
+ internal class MaterialDesignColorViewModelTests : BrushPropertyViewModelTests
+ {
+ [Test]
+ public void ValueChangesTriggerPropertyChanges ()
+ {
+ BrushPropertyViewModel vm = PrepareMockViewModel ();
+
+ var colorChanged = false;
+ var colorNameChanged = false;
+ var alphaChanged = false;
+ var accentChanged = false;
+ var normalChanged = false;
+ var scaleChanged = false;
+ var accentScaleChanged = false;
+ var normalScaleChanged = false;
+
+ vm.MaterialDesign.PropertyChanged += (s, e) => {
+ switch (e.PropertyName) {
+ case nameof (MaterialDesignColorViewModel.Color):
+ colorChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.ColorName):
+ colorNameChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.Alpha):
+ alphaChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.AccentColor):
+ accentChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.NormalColor):
+ normalChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.Scale):
+ scaleChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.AccentColorScale):
+ accentScaleChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.NormalColorScale):
+ normalScaleChanged = true;
+ break;
+ }
+ };
+
+ CommonColor newColor = GetNewRandomColor (Random, vm.MaterialDesign.Color);
+ vm.Value = new CommonSolidBrush (newColor);
+
+ Assert.AreEqual (newColor, vm.MaterialDesign.Color);
+ Assert.IsTrue (colorChanged);
+ Assert.IsTrue (colorNameChanged);
+ Assert.IsTrue (alphaChanged);
+ Assert.IsTrue (accentChanged);
+ Assert.IsTrue (normalChanged);
+ Assert.IsTrue (scaleChanged);
+ Assert.IsTrue (accentScaleChanged);
+ Assert.IsTrue (normalScaleChanged);
+ }
+
+ [Test]
+ public void AccentAndNormalChangesTriggerPropertyChanges ()
+ {
+ BrushPropertyViewModel vm = PrepareMockViewModel ();
+
+ var colorChanged = false;
+ var colorNameChanged = false;
+ var alphaChanged = false;
+ var accentChanged = false;
+ var normalChanged = false;
+ var scaleChanged = false;
+ var accentScaleChanged = false;
+ var normalScaleChanged = false;
+
+ CommonColor originalColor = GetNewRandomColor (Random, vm.MaterialDesign.Color);
+ vm.Value = new CommonSolidBrush (originalColor);
+
+ vm.MaterialDesign.PropertyChanged += (s, e) => {
+ switch (e.PropertyName) {
+ case nameof (MaterialDesignColorViewModel.Color):
+ colorChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.ColorName):
+ colorNameChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.Alpha):
+ alphaChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.AccentColor):
+ accentChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.NormalColor):
+ normalChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.Scale):
+ scaleChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.AccentColorScale):
+ accentScaleChanged = true;
+ break;
+ case nameof (MaterialDesignColorViewModel.NormalColorScale):
+ normalScaleChanged = true;
+ break;
+ }
+ };
+
+ MaterialColorScale scale = GetRandomScale (Random, true);
+ CommonColor newColor = GetNewRandomScaledColor (Random, scale, originalColor);
+ var newOpaqueColor = new CommonColor (newColor.R, newColor.G, newColor.B);
+ var newTransparentColor = new CommonColor (newColor.R, newColor.G, newColor.B, originalColor.A);
+ vm.MaterialDesign.AccentColor = newOpaqueColor;
+
+ Assert.AreEqual (newTransparentColor, vm.MaterialDesign.Color);
+ Assert.AreEqual (newOpaqueColor, vm.MaterialDesign.AccentColor);
+ Assert.AreEqual (scale.Name, vm.MaterialDesign.ColorName);
+ Assert.IsNull (vm.MaterialDesign.NormalColor);
+ Assert.IsTrue (colorChanged);
+ Assert.IsTrue (colorNameChanged);
+ Assert.IsTrue (alphaChanged);
+ Assert.IsTrue (accentChanged);
+ Assert.IsTrue (normalChanged);
+ Assert.IsTrue (scaleChanged);
+ Assert.IsTrue (accentScaleChanged);
+ Assert.IsTrue (normalScaleChanged);
+
+ colorChanged = false; colorNameChanged = false; alphaChanged = false; accentChanged = false;
+ normalChanged = false; scaleChanged = false; accentScaleChanged = false; normalScaleChanged = false;
+
+ scale = GetRandomScale (Random, false);
+ newColor = GetNewRandomScaledColor (Random, scale, originalColor);
+ newOpaqueColor = new CommonColor (newColor.R, newColor.G, newColor.B);
+ newTransparentColor = new CommonColor (newColor.R, newColor.G, newColor.B, originalColor.A);
+ vm.MaterialDesign.NormalColor = newOpaqueColor;
+
+ Assert.AreEqual (newTransparentColor, vm.MaterialDesign.Color);
+ Assert.AreEqual (newOpaqueColor, vm.MaterialDesign.NormalColor);
+ Assert.AreEqual (scale.Name, vm.MaterialDesign.ColorName);
+ Assert.IsNull (vm.MaterialDesign.AccentColor);
+ Assert.IsTrue (colorChanged);
+ Assert.IsTrue (colorNameChanged);
+ Assert.IsTrue (alphaChanged);
+ Assert.IsTrue (accentChanged);
+ Assert.IsTrue (normalChanged);
+ Assert.IsTrue (scaleChanged);
+ Assert.IsTrue (accentScaleChanged);
+ Assert.IsTrue (normalScaleChanged);
+ }
+
+ [Test]
+ public void ColorNameChangesScalesAndKeepsAlphaAndAccent ()
+ {
+ BrushPropertyViewModel vm = PrepareMockViewModel ();
+ MaterialColorScale scale = GetRandomScale (Random, true); // Accent color
+ CommonColor scaledColor = GetNewRandomScaledColor (Random, scale, new CommonColor());
+ var color = new CommonColor (scaledColor.R, scaledColor.G, scaledColor.B, Random.NextByte ());
+ vm.Value = new CommonSolidBrush (color);
+
+ Assert.AreEqual (scale.Colors, vm.MaterialDesign.AccentColorScale);
+
+ MaterialColorScale expectedNormalScale = MaterialDesignColorViewModel.MaterialPalettes
+ .First (p => !p.IsAccent && p.Name == scale.Name);
+ Assert.AreEqual (expectedNormalScale.Colors, vm.MaterialDesign.NormalColorScale);
+ Assert.AreEqual (color.A, vm.MaterialDesign.Alpha);
+
+ var accentIndex = Array.IndexOf (scale.Colors.ToArray(), scaledColor);
+
+ var newScale = GetRandomScale (Random, true);
+ var newColorName = newScale.Name;
+ while (newColorName == scale.Name) newColorName = GetRandomScale (Random, true).Name;
+ vm.MaterialDesign.ColorName = newColorName;
+
+ Assert.AreEqual (newColorName, vm.MaterialDesign.ColorName);
+ Assert.AreEqual (newScale.Colors, vm.MaterialDesign.AccentColorScale);
+ Assert.AreEqual (accentIndex, Array.IndexOf (newScale.Colors.ToArray (), vm.MaterialDesign.AccentColor));
+ expectedNormalScale = MaterialDesignColorViewModel.MaterialPalettes
+ .First (p => !p.IsAccent && p.Name == newScale.Name);
+ Assert.AreEqual (expectedNormalScale.Colors, vm.MaterialDesign.NormalColorScale);
+ Assert.AreEqual (color.A, vm.MaterialDesign.Alpha);
+ }
+
+ protected override CommonBrush GetRandomTestValue (Random rand)
+ {
+ CommonColor color = rand.NextColor ();
+ var colorSpace = rand.NextString ();
+ var opacity = rand.NextDouble ();
+
+ return new CommonSolidBrush (color, colorSpace, opacity);
+ }
+
+ private static CommonColor GetNewRandomColor (Random rand, CommonColor oldColor)
+ {
+ CommonColor newColor = rand.NextColor ();
+ while (newColor.Equals (oldColor, true)) newColor = rand.NextColor ();
+ return newColor;
+ }
+
+ private static MaterialColorScale GetRandomScale (Random rand, bool isAccent)
+ {
+ MaterialColorScale[] accentedScales = MaterialDesignColorViewModel.MaterialPalettes
+ .Where (s => s.IsAccent == isAccent).ToArray ();
+ return accentedScales[rand.Next (accentedScales.Length)];
+ }
+
+ private static CommonColor GetNewRandomScaledColor (Random rand, MaterialColorScale scale, CommonColor oldColor)
+ {
+ CommonColor newAccent = scale.Colors[rand.Next (scale.Colors.Count)];
+ while (newAccent.Equals (oldColor, true)) newAccent = scale.Colors[rand.Next (scale.Colors.Count)];
+ return newAccent;
+ }
+
+ private static CommonColor GetNewRandomAccent (Random rand, CommonColor oldColor)
+ {
+ MaterialColorScale scale = GetRandomScale (rand, true);
+ return GetNewRandomScaledColor (rand, scale, oldColor);
+ }
+
+ private static CommonColor GetNewRandomNormal (Random rand, CommonColor oldColor)
+ {
+ MaterialColorScale scale = GetRandomScale (rand, false);
+ return GetNewRandomScaledColor (rand, scale, oldColor);
+ }
+
+ private static BrushPropertyViewModel PrepareMockViewModel ()
+ {
+ var platform = new TargetPlatform {
+ SupportsMaterialDesign = true
+ };
+ var mockProperty = new Mock<IPropertyInfo> ();
+ mockProperty.SetupGet (pi => pi.Type).Returns (typeof (CommonSolidBrush));
+ var mockEditor = new MockObjectEditor (mockProperty.Object);
+
+ return new BrushPropertyViewModel (platform, mockProperty.Object, new[] { mockEditor });
+ }
+ }
+}
diff --git a/Xamarin.PropertyEditing.Tests/Xamarin.PropertyEditing.Tests.csproj b/Xamarin.PropertyEditing.Tests/Xamarin.PropertyEditing.Tests.csproj
index d35a070..a7741b5 100644
--- a/Xamarin.PropertyEditing.Tests/Xamarin.PropertyEditing.Tests.csproj
+++ b/Xamarin.PropertyEditing.Tests/Xamarin.PropertyEditing.Tests.csproj
@@ -67,6 +67,7 @@
<Compile Include="BoolViewModelTests.cs" />
<Compile Include="BrushPropertyViewModelTests.cs" />
<Compile Include="BytePropertyViewModelTests.cs" />
+ <Compile Include="MaterialDesignColorViewModelTests.cs" />
<Compile Include="MockControls\MockResourceProvider.cs" />
<Compile Include="NumericTests.cs" />
<Compile Include="NumericViewModelTests.cs" />
diff --git a/Xamarin.PropertyEditing.Windows.Standalone/MainWindow.xaml.cs b/Xamarin.PropertyEditing.Windows.Standalone/MainWindow.xaml.cs
index 0d5727a..eb5751a 100644
--- a/Xamarin.PropertyEditing.Windows.Standalone/MainWindow.xaml.cs
+++ b/Xamarin.PropertyEditing.Windows.Standalone/MainWindow.xaml.cs
@@ -17,6 +17,7 @@ namespace Xamarin.PropertyEditing.Windows.Standalone
InitializeComponent ();
this.panel.TargetPlatform = new TargetPlatform {
SupportsCustomExpressions = true,
+ SupportsMaterialDesign = true,
GroupedTypes = new Dictionary<Type, string> {
{ typeof(CommonBrush), "Brush" }
}
@@ -36,6 +37,7 @@ namespace Xamarin.PropertyEditing.Windows.Standalone
if (mockedControl is MockedSampleControlButton mockedButton) {
IObjectEditor editor = await this.panel.EditorProvider.GetObjectEditorAsync (inspectedObject);
await mockedButton.SetBrushInitialValueAsync (editor, new CommonSolidBrush (20, 120, 220, 240, "sRGB"));
+ await mockedButton.SetMaterialDesignBrushInitialValueAsync (editor, new CommonSolidBrush (0x65, 0x1F, 0xFF, 200));
await mockedButton.SetReadOnlyBrushInitialValueAsync (editor, new CommonSolidBrush (240, 220, 15, 190));
}
}
@@ -48,8 +50,7 @@ namespace Xamarin.PropertyEditing.Windows.Standalone
private void Theme_Click (object sender, RoutedEventArgs e)
{
- var rb = e.Source as RadioButton;
- if (rb != null) {
+ if (e.Source is RadioButton rb) {
switch (rb.Content.ToString()) {
case "Dark Theme":
PropertyEditorPanel.ThemeManager.Theme = PropertyEditing.Themes.PropertyEditorTheme.Dark;
diff --git a/Xamarin.PropertyEditing.Windows.Standalone/MockedSampleControlButton.cs b/Xamarin.PropertyEditing.Windows.Standalone/MockedSampleControlButton.cs
index 5a7765e..624d84f 100644
--- a/Xamarin.PropertyEditing.Windows.Standalone/MockedSampleControlButton.cs
+++ b/Xamarin.PropertyEditing.Windows.Standalone/MockedSampleControlButton.cs
@@ -16,6 +16,12 @@ namespace Xamarin.PropertyEditing.Windows.Standalone
colorSpaces: new[] { "RGB", "sRGB" });
MockedControl.AddProperty<CommonBrush> (this.brushPropertyInfo);
+ this.materialDesignBrushPropertyInfo = new BrushPropertyInfo (
+ name: "MaterialDesignBrush",
+ category: "Windows Only",
+ canWrite: true);
+ MockedControl.AddProperty<CommonBrush> (this.materialDesignBrushPropertyInfo);
+
this.readOnlyBrushPropertyInfo = new BrushPropertyInfo (
name: "ReadOnlySolidBrush",
category: "Windows Only",
@@ -30,6 +36,13 @@ namespace Xamarin.PropertyEditing.Windows.Standalone
this.brushSet = true;
}
+ public async Task SetMaterialDesignBrushInitialValueAsync (IObjectEditor editor, CommonBrush brush)
+ {
+ if (this.materialDesignBrushSet) return;
+ await editor.SetValueAsync (this.materialDesignBrushPropertyInfo, new ValueInfo<CommonBrush> { Value = brush });
+ this.materialDesignBrushSet = true;
+ }
+
public async Task SetReadOnlyBrushInitialValueAsync (IObjectEditor editor, CommonBrush brush)
{
if (this.readOnlyBrushSet) return;
@@ -38,8 +51,10 @@ namespace Xamarin.PropertyEditing.Windows.Standalone
}
private IPropertyInfo brushPropertyInfo;
+ private IPropertyInfo materialDesignBrushPropertyInfo;
private IPropertyInfo readOnlyBrushPropertyInfo;
private bool brushSet = false;
+ private bool materialDesignBrushSet = false;
private bool readOnlyBrushSet = false;
}
}
diff --git a/Xamarin.PropertyEditing.Windows/BrushBoxControl.cs b/Xamarin.PropertyEditing.Windows/BrushBoxControl.cs
index 4e8a733..217b42e 100644
--- a/Xamarin.PropertyEditing.Windows/BrushBoxControl.cs
+++ b/Xamarin.PropertyEditing.Windows/BrushBoxControl.cs
@@ -35,5 +35,16 @@ namespace Xamarin.PropertyEditing.Windows
get => (Visibility)GetValue (NoBrushVisibleProperty);
set => SetValue (NoBrushVisibleProperty, value);
}
+
+ public static readonly DependencyProperty LabelProperty =
+ DependencyProperty.Register (
+ nameof (Label), typeof (string), typeof (BrushBoxControl),
+ new PropertyMetadata (""));
+
+ public string Label
+ {
+ get => (string)GetValue (LabelProperty);
+ set => SetValue (LabelProperty, value);
+ }
}
}
diff --git a/Xamarin.PropertyEditing.Windows/BrushChoiceTemplateSelector.cs b/Xamarin.PropertyEditing.Windows/BrushChoiceTemplateSelector.cs
index 65c90f7..f178237 100644
--- a/Xamarin.PropertyEditing.Windows/BrushChoiceTemplateSelector.cs
+++ b/Xamarin.PropertyEditing.Windows/BrushChoiceTemplateSelector.cs
@@ -16,6 +16,12 @@ namespace Xamarin.PropertyEditing.Windows
set;
}
+ public DataTemplate MaterialDesignBrushTemplate
+ {
+ get;
+ set;
+ }
+
public override DataTemplate SelectTemplate (object item, DependencyObject container)
{
if (item == null)
@@ -25,6 +31,7 @@ namespace Xamarin.PropertyEditing.Windows
var choice = choiceItem.Value as string;
if (choice == BrushTabbedEditorControl.None) return NoBrushTemplate;
if (choice == BrushTabbedEditorControl.Solid) return SolidBrushTemplate;
+ if (choice == BrushTabbedEditorControl.MaterialDesign) return MaterialDesignBrushTemplate;
}
return base.SelectTemplate (item, container);
diff --git a/Xamarin.PropertyEditing.Windows/BrushTabbedEditorControl.cs b/Xamarin.PropertyEditing.Windows/BrushTabbedEditorControl.cs
index 7c0fb13..ee0d5b3 100644
--- a/Xamarin.PropertyEditing.Windows/BrushTabbedEditorControl.cs
+++ b/Xamarin.PropertyEditing.Windows/BrushTabbedEditorControl.cs
@@ -1,4 +1,7 @@
using System;
+using System.Collections;
+using System.Linq;
+using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Xamarin.PropertyEditing.Drawing;
@@ -9,7 +12,7 @@ namespace Xamarin.PropertyEditing.Windows
public class BrushTabbedEditorControl
: Control
{
- public BrushTabbedEditorControl()
+ public BrushTabbedEditorControl ()
{
DefaultStyleKey = typeof (BrushTabbedEditorControl);
}
@@ -19,13 +22,26 @@ namespace Xamarin.PropertyEditing.Windows
base.OnApplyTemplate ();
this.brushChoice = GetTemplateChild ("brushChoice") as ChoiceControl;
+ this.advancedPropertyPanel = GetTemplateChild ("advancedPropertyPanel") as Expander;
+ this.solidBrushEditor = GetTemplateChild ("solidBrushEditor") as SolidBrushEditorControl;
+ this.materialDesignColorEditor = GetTemplateChild ("materialDesignColorEditor") as MaterialDesignColorEditorControl;
if (this.brushChoice == null)
- throw new InvalidOperationException ($"{nameof(BrushTabbedEditorControl)} is missing a child ChoiceControl named \"brushChoice\"");
+ throw new InvalidOperationException ($"{nameof (BrushTabbedEditorControl)} is missing a child ChoiceControl named \"brushChoice\"");
+ if (this.advancedPropertyPanel == null)
+ throw new InvalidOperationException ($"{nameof (BrushTabbedEditorControl)} is missing a child Expander named \"advancedPropertyPanel\"");
+ if (this.solidBrushEditor == null)
+ throw new InvalidOperationException ($"{nameof (BrushTabbedEditorControl)} is missing a child SolidBrushEditorControl named \"solidBrushEditor\"");
+ if (this.materialDesignColorEditor == null)
+ throw new InvalidOperationException ($"{nameof (BrushTabbedEditorControl)} is missing a child MaterialDesignColorEditorControl named \"materialDesignColorEditor\"");
StorePreviousBrush ();
SelectTabFromBrush ();
+ if (ViewModel.MaterialDesign == null) {
+ this.brushChoice.Items.Filter = o => ((ChoiceItem)o).Name != "materialDesignTab";
+ }
+
this.brushChoice.SelectedItemChanged += (s, e) => {
if (ViewModel == null) return;
StorePreviousBrush ();
@@ -38,7 +54,11 @@ namespace Xamarin.PropertyEditing.Windows
ViewModel.Solid.CommitLastColor ();
ViewModel.Solid.CommitHue ();
break;
+ case materialDesign:
+ ViewModel.Value = ViewModel.Solid?.PreviousSolidBrush ?? new CommonSolidBrush (new CommonColor (0, 0, 0));
+ break;
}
+ ShowSelectedTab ();
};
this.brushChoice.KeyUp += (s, e) => {
@@ -48,28 +68,40 @@ namespace Xamarin.PropertyEditing.Windows
case Key.N:
e.Handled = true;
this.brushChoice.SelectedValue = none;
+ ShowSelectedTab ();
break;
case Key.S:
e.Handled = true;
this.brushChoice.SelectedValue = solid;
+ ShowSelectedTab ();
break;
- // TODO: add G, T, R for the other brush types when they are available.
+ case Key.M:
+ e.Handled = true;
+ this.brushChoice.SelectedValue = materialDesign;
+ ShowSelectedTab ();
+ break;
+ // TODO: add G, T, R for the other brush types when they are available.
}
};
}
public static readonly string None = none;
public static readonly string Solid = solid;
+ public static readonly string MaterialDesign = materialDesign;
- internal void FocusFirstChild()
+ internal void FocusFirstChild ()
{
- this.brushChoice?.FocusSelectedItem();
+ this.brushChoice?.FocusSelectedItem ();
}
private const string none = nameof (none);
private const string solid = nameof (solid);
+ private const string materialDesign = nameof (materialDesign);
private ChoiceControl brushChoice;
+ private Expander advancedPropertyPanel;
+ private SolidBrushEditorControl solidBrushEditor;
+ private MaterialDesignColorEditorControl materialDesignColorEditor;
private BrushPropertyViewModel ViewModel => DataContext as BrushPropertyViewModel;
@@ -83,14 +115,43 @@ namespace Xamarin.PropertyEditing.Windows
internal void SelectTabFromBrush ()
{
+ if (ViewModel != null && ViewModel.MaterialDesign != null
+ && (ViewModel.MaterialDesign.NormalColor.HasValue || ViewModel.MaterialDesign.AccentColor.HasValue)) {
+ this.brushChoice.SelectedValue = materialDesign;
+ ShowSelectedTab ();
+ return;
+ }
switch (ViewModel?.Value) {
case null:
this.brushChoice.SelectedValue = none;
+ ShowSelectedTab ();
break;
case CommonSolidBrush _:
this.brushChoice.SelectedValue = solid;
+ ShowSelectedTab ();
+ break;
+ }
+ }
+
+ private void ShowSelectedTab()
+ {
+ switch ((string)((ChoiceItem)(this.brushChoice.SelectedItem)).Value) {
+ case none:
+ this.advancedPropertyPanel.Visibility = Visibility.Collapsed;
+ this.solidBrushEditor.Visibility = Visibility.Collapsed;
+ this.materialDesignColorEditor.Visibility = Visibility.Collapsed;
+ break;
+ case solid:
+ this.advancedPropertyPanel.Visibility = Visibility.Visible;
+ this.solidBrushEditor.Visibility = Visibility.Visible;
+ this.materialDesignColorEditor.Visibility = Visibility.Collapsed;
+ break;
+ case materialDesign:
+ this.advancedPropertyPanel.Visibility = Visibility.Visible;
+ this.solidBrushEditor.Visibility = Visibility.Collapsed;
+ this.materialDesignColorEditor.Visibility = Visibility.Visible;
break;
}
}
}
-}
+} \ No newline at end of file
diff --git a/Xamarin.PropertyEditing.Windows/BrushToDarknessConverter.cs b/Xamarin.PropertyEditing.Windows/BrushToDarknessConverter.cs
new file mode 100644
index 0000000..eaf0d7f
--- /dev/null
+++ b/Xamarin.PropertyEditing.Windows/BrushToDarknessConverter.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+using System.Windows.Markup;
+using System.Windows.Media;
+using Xamarin.PropertyEditing.Drawing;
+
+namespace Xamarin.PropertyEditing.Windows
+{
+ [ValueConversion (typeof (CommonColor), typeof (Darkness))]
+ internal class BrushToDarknessConverter : MarkupExtension, IValueConverter
+ {
+ public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (!(value is SolidColorBrush brush)) return Darkness.Unknown;
+ return brush.Color.ToCommonColor ().Lightness > 0.667 ? Darkness.Light : Darkness.Dark;
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
+ => throw new NotImplementedException ();
+
+ public override object ProvideValue (IServiceProvider serviceProvider) => this;
+ }
+
+ internal enum Darkness
+ {
+ Dark, Light, Unknown
+ }
+}
diff --git a/Xamarin.PropertyEditing.Windows/ChoiceControl.cs b/Xamarin.PropertyEditing.Windows/ChoiceControl.cs
index ce36791..f80ad63 100644
--- a/Xamarin.PropertyEditing.Windows/ChoiceControl.cs
+++ b/Xamarin.PropertyEditing.Windows/ChoiceControl.cs
@@ -66,6 +66,7 @@ namespace Xamarin.PropertyEditing.Windows
protected override void OnSelectionChanged (SelectionChangedEventArgs e)
{
+ if (e.AddedItems.Count == 0) return;
var presenter = (ContentPresenter) ItemContainerGenerator.ContainerFromItem (e.AddedItems[0]);
if (presenter == null)
return;
diff --git a/Xamarin.PropertyEditing.Windows/ObjectToTypeNameConverter.cs b/Xamarin.PropertyEditing.Windows/ColorToTransparentColorConverter.cs
index e22e846..4874104 100644
--- a/Xamarin.PropertyEditing.Windows/ObjectToTypeNameConverter.cs
+++ b/Xamarin.PropertyEditing.Windows/ColorToTransparentColorConverter.cs
@@ -2,28 +2,18 @@ using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;
+using System.Windows.Media;
namespace Xamarin.PropertyEditing.Windows
{
- [ValueConversion (typeof (object), typeof (string))]
- internal class ObjectToTypeNameConverter : MarkupExtension, IValueConverter
+ [ValueConversion (typeof (Color), typeof (Color))]
+ public class ColorToTransparentColorConverter : MarkupExtension, IValueConverter
{
public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
- {
- switch (value) {
- case null:
- return "null";
- case Type type:
- return type.Name;
- default:
- return value.GetType ().Name;
- }
- }
+ => value is Color color ? Color.FromArgb (0, color.R, color.G, color.B) : Color.FromArgb (0, 0, 0, 0);
public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
- {
- throw new NotImplementedException ();
- }
+ => throw new NotImplementedException ();
public override object ProvideValue (IServiceProvider serviceProvider) => this;
}
diff --git a/Xamarin.PropertyEditing.Windows/MaterialDesignColorEditorControl.cs b/Xamarin.PropertyEditing.Windows/MaterialDesignColorEditorControl.cs
new file mode 100644
index 0000000..f7d9d50
--- /dev/null
+++ b/Xamarin.PropertyEditing.Windows/MaterialDesignColorEditorControl.cs
@@ -0,0 +1,11 @@
+namespace Xamarin.PropertyEditing.Windows
+{
+ internal class MaterialDesignColorEditorControl
+ : PropertyEditorControl
+ {
+ public MaterialDesignColorEditorControl ()
+ {
+ DefaultStyleKey = typeof (MaterialDesignColorEditorControl);
+ }
+ }
+}
diff --git a/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml b/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml
index 4661368..82ce2df 100644
--- a/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml
+++ b/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml
@@ -530,6 +530,83 @@
</Setter>
</Style>
+ <Style x:Key="NoBrushIcon" TargetType="Image">
+ <Setter Property="Source">
+ <Setter.Value>
+ <DrawingImage>
+ <DrawingImage.Drawing>
+ <DrawingGroup/>
+ </DrawingImage.Drawing>
+ </DrawingImage>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="SolidBrushIcon" TargetType="Image">
+ <Setter Property="Source">
+ <Setter.Value>
+ <DrawingImage>
+ <DrawingImage.Drawing>
+ <DrawingGroup/>
+ </DrawingImage.Drawing>
+ </DrawingImage>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style x:Key="MaterialDesignIcon" TargetType="Image">
+ <Setter Property="DataContext" Value="{DynamicResource ToggleItemForegroundBrush}"/>
+ <Setter Property="Source">
+ <Setter.Value>
+ <DrawingImage>
+ <DrawingImage.Drawing>
+ <DrawingGroup>
+ <DrawingGroup x:Name="DrawingLayer">
+ <DrawingGroup.ClipGeometry>
+ <RectangleGeometry Rect="0,0,32,32" />
+ </DrawingGroup.ClipGeometry>
+ <DrawingGroup x:Name="Canvas" Transform="1,0,0,1,-240,-928">
+ <DrawingGroup x:Name="property_brush_gradient_16">
+ <DrawingGroup.ClipGeometry>
+ <PathGeometry FillRule="Nonzero" Figures="M240,928L272,928 272,960 240,960 240,928z" />
+ </DrawingGroup.ClipGeometry>
+ <DrawingGroup x:Name="glyph">
+ <DrawingGroup Transform="1,0,0,1,242,935">
+ <GeometryDrawing x:Name="path0_fill">
+ <GeometryDrawing.Brush>
+ <SolidColorBrush Color="{Binding Color}"/>
+ </GeometryDrawing.Brush>
+ <GeometryDrawing.Geometry>
+ <PathGeometry FillRule="EvenOdd" Figures="M2.5,0C1.11929,0,0,1.11926,0,2.5L0,15.5C0,16.8807,1.11929,18,2.5,18L25.5,18C26.8807,18,28,16.8807,28,15.5L28,2.5C28,1.11926,26.8807,0,25.5,0L2.5,0z M2.5,2C2.22386,2,2,2.22388,2,2.5L2,15.5C2,15.7761,2.22386,16,2.5,16L25.5,16C25.7762,16,26,15.7761,26,15.5L26,2.5C26,2.22388,25.7762,2,25.5,2L2.5,2z" />
+ </GeometryDrawing.Geometry>
+ </GeometryDrawing>
+ </DrawingGroup>
+ </DrawingGroup>
+ <DrawingGroup x:Name="mask">
+ <DrawingGroup Transform="1,0,0,1,245,938">
+ <GeometryDrawing x:Name="path1_fill">
+ <GeometryDrawing.Brush>
+ <LinearGradientBrush StartPoint="0,0" EndPoint="1,0" MappingMode="Absolute" Opacity="1" Transform="22,3.00507E-07,-5.50929E-07,40.3333,2.75465E-07,-8.16667">
+ <GradientStop Color="{Binding Color}" Offset="0" />
+ <GradientStop Color="{Binding Color, Converter={local:ColorToTransparentColorConverter}}" Offset="1" />
+ </LinearGradientBrush>
+ </GeometryDrawing.Brush>
+ <GeometryDrawing.Geometry>
+ <PathGeometry FillRule="Nonzero" Figures="M0,0L22,0 22,12 0,12 0,0z" />
+ </GeometryDrawing.Geometry>
+ </GeometryDrawing>
+ </DrawingGroup>
+ </DrawingGroup>
+ </DrawingGroup>
+ </DrawingGroup>
+ </DrawingGroup>
+ </DrawingGroup>
+ </DrawingImage.Drawing>
+ </DrawingImage>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
<local:BrushChoiceTemplateSelector x:Key="BrushChoiceTemplateSelector">
<local:BrushChoiceTemplateSelector.NoBrushTemplate>
<DataTemplate>
@@ -545,6 +622,14 @@
</RadioButton>
</DataTemplate>
</local:BrushChoiceTemplateSelector.SolidBrushTemplate>
+ <local:BrushChoiceTemplateSelector.MaterialDesignBrushTemplate>
+ <DataTemplate>
+ <RadioButton Style="{DynamicResource ChoiceControlItem}" GroupName="{Binding Name,RelativeSource={RelativeSource FindAncestor,AncestorType=local:ChoiceControl},Mode=OneTime}">
+ <Image Style="{DynamicResource MaterialDesignIcon}"
+ HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="30" Height="20"/>
+ </RadioButton>
+ </DataTemplate>
+ </local:BrushChoiceTemplateSelector.MaterialDesignBrushTemplate>
</local:BrushChoiceTemplateSelector>
<Style TargetType="local:BrushTabbedEditorControl">
@@ -557,8 +642,10 @@
<local:ChoiceControl x:Name="brushChoice" ItemTemplateSelector="{StaticResource BrushChoiceTemplateSelector}" ItemTemplate="{x:Null}" HorizontalAlignment="Stretch">
<local:ChoiceItem Value="{x:Static local:BrushTabbedEditorControl.None}" Name="noBrushTab" Tooltip="{x:Static prop:Resources.NoBrush}"/>
<local:ChoiceItem Value="{x:Static local:BrushTabbedEditorControl.Solid}" Name="solidColorTab" Tooltip="{x:Static prop:Resources.SolidBrush}"/>
+ <local:ChoiceItem Value="{x:Static local:BrushTabbedEditorControl.MaterialDesign}" Name="materialDesignTab" Tooltip="{x:Static prop:Resources.MaterialDesignColorBrush}"/>
</local:ChoiceControl>
<local:SolidBrushEditorControl x:Name="solidBrushEditor"/>
+ <local:MaterialDesignColorEditorControl x:Name="materialDesignColorEditor" Visibility="Collapsed"/>
</StackPanel>
</Border>
<Border Padding="1">
@@ -577,16 +664,6 @@
</Expander>
</Border>
</StackPanel>
- <ControlTemplate.Triggers>
- <DataTrigger Binding="{Binding Path=Value}" Value="{x:Null}">
- <Setter Property="Visibility" TargetName="advancedPropertyPanel" Value="Collapsed"/>
- <Setter Property="Visibility" TargetName="solidBrushEditor" Value="Collapsed"/>
- </DataTrigger>
- <DataTrigger Binding="{Binding Path=Value, Converter={local:ObjectToTypeNameConverter}}" Value="CommonSolidBrush">
- <Setter Property="Visibility" TargetName="advancedPropertyPanel" Value="Visible"/>
- <Setter Property="Visibility" TargetName="solidBrushEditor" Value="Visible"/>
- </DataTrigger>
- </ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
@@ -1099,6 +1176,150 @@
</Setter>
</Style>
+ <Style x:Key="BrushChoiceControlItem" BasedOn="{StaticResource {x:Type RadioButton}}" TargetType="RadioButton">
+ <Setter Property="Background" Value="{DynamicResource ToggleItemBackgroundBrush}" />
+ <Setter Property="BorderBrush" Value="{DynamicResource ToggleItemBorderBrush}" />
+ <Setter Property="ToolTip" Value="{Binding Name}" />
+ <Setter Property="AutomationProperties.Name" Value="{Binding Name}" />
+ <Setter Property="AutomationProperties.HelpText" Value="{Binding Name}" />
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="RadioButton">
+ <Border Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}"
+ BorderBrush="{TemplateBinding BorderBrush}" Padding="{TemplateBinding Padding}">
+ <ContentPresenter />
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <Trigger Property="IsChecked" Value="True">
+ <Setter Property="BorderBrush" Value="{DynamicResource ToggleItemSelectedBorderBrush}" />
+ <Setter Property="Background" Value="{DynamicResource ToggleItemSelectedBackgroundBrush}" />
+ <Setter Property="Foreground" Value="{DynamicResource ToggleItemSelectedForegroundBrush}" />
+ <Setter Property="Padding" Value="1"/>
+ </Trigger>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Background" Value="{DynamicResource ToggleItemMouseOverBackgroundBrush}" />
+ <Setter Property="Foreground" Value="{DynamicResource ToggleItemMouseOverForegroundBrush}" />
+ </Trigger>
+ <Trigger Property="IsFocused" Value="True">
+ <Setter Property="Background" Value="{DynamicResource ToggleItemMouseOverBackgroundBrush}" />
+ </Trigger>
+ <Trigger Property="IsPressed" Value="True">
+ <Setter Property="BorderBrush" Value="{DynamicResource ToggleItemPressedBorderBrush}" />
+ <Setter Property="Background" Value="{DynamicResource ToggleItemPressedBackgroundBrush}" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+
+ <SolidColorBrush x:Key="DarkeningBrush" Color="#40000000"/>
+
+ <Style TargetType="local:MaterialDesignColorEditorControl">
+ <Setter Property="DataContext" Value="{Binding MaterialDesign}"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="local:MaterialDesignColorEditorControl">
+ <Border BorderThickness="0" Padding="2,0,2,0">
+ <StackPanel Orientation="Vertical">
+ <Grid Margin="0,2,0,2" Background="Transparent">
+ <local:ChoiceControl x:Name="palettePicker" Background="Transparent"
+ Grid.Column="0" Grid.Row="0" Panel.ZIndex="0" BorderThickness="0"
+ ItemsSource="{Binding Palettes}"
+ SelectedValue="{Binding ColorName, Mode=TwoWay}"
+ SelectedValuePath="Name">
+ <local:ChoiceControl.ItemTemplate>
+ <DataTemplate>
+ <RadioButton Style="{DynamicResource BrushChoiceControlItem}"
+ GroupName="{Binding Name, RelativeSource={RelativeSource FindAncestor,AncestorType=local:ChoiceControl}, Mode=OneTime}">
+ <Grid Margin="0">
+ <local:BrushBoxControl>
+ <local:BrushBoxControl.Brush>
+ <SolidColorBrush Color="{Binding MainColor, Converter={local:CommonColorToColorConverter}}"/>
+ </local:BrushBoxControl.Brush>
+ </local:BrushBoxControl>
+ <Border BorderBrush="{StaticResource DarkeningBrush}" BorderThickness="1" Grid.Column="0" Grid.Row="0" Panel.ZIndex="1"/>
+ </Grid>
+ </RadioButton>
+ </DataTemplate>
+ </local:ChoiceControl.ItemTemplate>
+ <local:ChoiceControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <UniformGrid Columns="10"/>
+ </ItemsPanelTemplate>
+ </local:ChoiceControl.ItemsPanel>
+ </local:ChoiceControl>
+ </Grid>
+ <TextBlock Name="colorLabel" Text="{Binding ColorName}" FontWeight="Bold"/>
+ <Grid Margin="0,2,0,2">
+ <local:ChoiceControl x:Name="normalColorPicker" Background="Transparent"
+ Grid.Column="0" Grid.Row="0" Panel.ZIndex="0" BorderThickness="0"
+ ItemsSource="{Binding NormalColorScale}"
+ SelectedItem="{Binding NormalColor, Mode=TwoWay}">
+ <local:ChoiceControl.ItemTemplate>
+ <DataTemplate>
+ <RadioButton Style="{DynamicResource BrushChoiceControlItem}"
+ GroupName="MaterialDesignAccentOrNormal">
+ <RadioButton.BorderBrush>
+ <SolidColorBrush Color="{Binding Converter={local:CommonColorToColorConverter}}"/>
+ </RadioButton.BorderBrush>
+ <local:BrushBoxControl Label="{Binding Name}" FontSize="10">
+ <local:BrushBoxControl.Brush>
+ <SolidColorBrush Color="{Binding Converter={local:CommonColorToColorConverter}}"/>
+ </local:BrushBoxControl.Brush>
+ </local:BrushBoxControl>
+ </RadioButton>
+ </DataTemplate>
+ </local:ChoiceControl.ItemTemplate>
+ <local:ChoiceControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <UniformGrid Columns="10" Height="26"/>
+ </ItemsPanelTemplate>
+ </local:ChoiceControl.ItemsPanel>
+ </local:ChoiceControl>
+ <Border BorderBrush="{StaticResource DarkeningBrush}" BorderThickness="1" Grid.Column="0" Grid.Row="0" Panel.ZIndex="1"/>
+ </Grid>
+ <Grid Margin="0,2,0,2">
+ <local:ChoiceControl x:Name="accentColorPicker" Background="Transparent"
+ Grid.Column="0" Grid.Row="0" Panel.ZIndex="0" BorderThickness="0"
+ ItemsSource="{Binding AccentColorScale}"
+ SelectedItem="{Binding AccentColor, Mode=TwoWay}">
+ <local:ChoiceControl.ItemTemplate>
+ <DataTemplate>
+ <RadioButton Style="{DynamicResource BrushChoiceControlItem}"
+ GroupName="MaterialDesignAccentOrNormal">
+ <RadioButton.BorderBrush>
+ <SolidColorBrush Color="{Binding Converter={local:CommonColorToColorConverter}}"/>
+ </RadioButton.BorderBrush>
+ <local:BrushBoxControl Label="{Binding Name}" FontSize="10">
+ <local:BrushBoxControl.Brush>
+ <SolidColorBrush Color="{Binding Converter={local:CommonColorToColorConverter}}"/>
+ </local:BrushBoxControl.Brush>
+ </local:BrushBoxControl>
+ </RadioButton>
+ </DataTemplate>
+ </local:ChoiceControl.ItemTemplate>
+ <local:ChoiceControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <UniformGrid Columns="4" Height="26"/>
+ </ItemsPanelTemplate>
+ </local:ChoiceControl.ItemsPanel>
+ </local:ChoiceControl>
+ <Border BorderBrush="{StaticResource DarkeningBrush}" BorderThickness="1" Grid.Column="0" Grid.Row="0" Panel.ZIndex="1"/>
+ </Grid>
+ <local:PropertyPresenter x:Name="alpha" Label="{x:Static prop:Resources.Alpha}" ShowPropertyButton="False"
+ AutomationProperties.Name="{x:Static prop:Resources.Alpha}" AutomationProperties.HelpText="{x:Static prop:Resources.Alpha}" ToolTip="{x:Static prop:Resources.Alpha}">
+ <local:ColorComponentBox x:Name="alphaEntry" HorizontalAlignment="Stretch" VerticalAlignment="Center"
+ AutomationProperties.Name="{x:Static prop:Resources.Alpha}" AutomationProperties.HelpText="{x:Static prop:Resources.Alpha}" ToolTip="{x:Static prop:Resources.Alpha}"
+ Value="{Binding Alpha, Converter={local:ByteToPercentageConverter}, Mode=TwoWay}" Unit="%"/>
+ </local:PropertyPresenter>
+ </StackPanel>
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
<Style TargetType="local:BrushBoxControl">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
@@ -1117,7 +1338,37 @@
Stroke="{Binding BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" StrokeThickness="1"
Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Brush}" Visibility="{TemplateBinding BrushVisible}"
Height="{Binding Height, RelativeSource={RelativeSource TemplatedParent}}"/>
+ <TextBlock Name="labelOutline" HorizontalAlignment="Center" VerticalAlignment="Bottom"
+ Text="{Binding Label, RelativeSource={RelativeSource TemplatedParent}}"
+ Foreground="Transparent"
+ Grid.Column="0" Grid.Row="0" Panel.ZIndex="2" Visibility="{Binding BrushVisible, RelativeSource={RelativeSource TemplatedParent}}"
+ Height="{Binding Height, RelativeSource={RelativeSource TemplatedParent}}">
+ <TextBlock.Effect>
+ <BlurEffect Radius="3"/>
+ </TextBlock.Effect>
+ </TextBlock>
+ <TextBlock Name="label" HorizontalAlignment="Center" VerticalAlignment="Bottom"
+ Text="{Binding Label, RelativeSource={RelativeSource TemplatedParent}}"
+ Grid.Column="0" Grid.Row="0" Panel.ZIndex="3" Visibility="{Binding BrushVisible, RelativeSource={RelativeSource TemplatedParent}}"
+ Height="{Binding Height, RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid>
+ <ControlTemplate.Triggers>
+ <DataTrigger Binding="{Binding Brush, RelativeSource={RelativeSource Self}, Converter={local:BrushToDarknessConverter}}"
+ Value="Dark">
+ <Setter TargetName="label" Property="Foreground" Value="#FFFFFFFF"/>
+ <Setter TargetName="labelOutline" Property="Foreground" Value="Transparent"/>
+ </DataTrigger>
+ <DataTrigger Binding="{Binding Brush, RelativeSource={RelativeSource Self}, Converter={local:BrushToDarknessConverter}}"
+ Value="Light">
+ <Setter TargetName="label" Property="Foreground" Value="#FF000000"/>
+ <Setter TargetName="labelOutline" Property="Foreground" Value="Transparent"/>
+ </DataTrigger>
+ <DataTrigger Binding="{Binding Brush, RelativeSource={RelativeSource Self}, Converter={local:BrushToDarknessConverter}}"
+ Value="Unknown">
+ <Setter TargetName="label" Property="Foreground" Value="#FF000000"/>
+ <Setter TargetName="labelOutline" Property="Foreground" Value="#FFFFFFFF"/>
+ </DataTrigger>
+ </ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
diff --git a/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj b/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj
index 255879d..57f07d4 100644
--- a/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj
+++ b/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj
@@ -62,7 +62,9 @@
<Compile Include="BrushChoiceTemplateSelector.cs" />
<Compile Include="BrushEditorControl.cs" />
<Compile Include="BrushTabbedEditorControl.cs" />
+ <Compile Include="BrushToDarknessConverter.cs" />
<Compile Include="CategoryExpander.cs" />
+ <Compile Include="ColorToTransparentColorConverter.cs" />
<Compile Include="CommonBrushToBrushConverter.cs" />
<Compile Include="ByteToPercentageConverter.cs" />
<Compile Include="ChoiceControl.cs" />
@@ -77,6 +79,7 @@
<Compile Include="CurrentColorEditorControl.cs" />
<Compile Include="DoubleToPercentageConverter.cs" />
<Compile Include="DoubleToQuantityConverter.cs" />
+ <Compile Include="MaterialDesignColorEditorControl.cs" />
<Compile Include="MultiplyMarginConverter.cs" />
<Compile Include="ObjectEditorControl.cs" />
<Compile Include="ResourceSelectorWindow.xaml.cs">
@@ -94,7 +97,6 @@
<Compile Include="NumericEditorControl.cs" />
<Compile Include="NumericTemplateSelector.cs" />
<Compile Include="NumericUpDownControl.cs" />
- <Compile Include="ObjectToTypeNameConverter.cs" />
<Compile Include="OppositeBoolConverter.cs" />
<Compile Include="PointEditorControl.cs" />
<Compile Include="PointHelper.cs" />
@@ -157,4 +159,4 @@
</Page>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/Xamarin.PropertyEditing/Drawing/CommonColor.cs b/Xamarin.PropertyEditing/Drawing/CommonColor.cs
index 46423b9..d024da8 100644
--- a/Xamarin.PropertyEditing/Drawing/CommonColor.cs
+++ b/Xamarin.PropertyEditing/Drawing/CommonColor.cs
@@ -8,12 +8,13 @@ namespace Xamarin.PropertyEditing.Drawing
[Serializable]
public struct CommonColor : IEquatable<CommonColor>
{
- public CommonColor (byte r, byte g, byte b, byte a = 255)
+ public CommonColor (byte r, byte g, byte b, byte a = 255, string name = "")
{
A = a;
R = r;
G = g;
B = b;
+ Name = name;
c = null;
m = null;
y = null;
@@ -43,6 +44,10 @@ namespace Xamarin.PropertyEditing.Drawing
/// Blue component
/// </summary>
public byte B { get; }
+ /// <summary>
+ /// An optional label for the color, that does not affect equality or anything else.
+ /// </summary>
+ public string Name { get; set; }
double? k;
/// <summary>
@@ -474,7 +479,7 @@ namespace Xamarin.PropertyEditing.Drawing
return color;
}
- static double Mod (double a, double b) => a - b * Math.Floor (a / b);
+ private static double Mod (double a, double b) => a - b * Math.Floor (a / b);
public override bool Equals (object obj)
{
@@ -483,9 +488,11 @@ namespace Xamarin.PropertyEditing.Drawing
return base.Equals ((CommonColor)obj);
}
- public bool Equals (CommonColor other)
+ public bool Equals (CommonColor other) => Equals (other, false);
+
+ public bool Equals (CommonColor other, bool ignoreAlpha)
{
- return A == other.A &&
+ return (ignoreAlpha || A == other.A) &&
R == other.R &&
G == other.G &&
B == other.B;
@@ -494,6 +501,11 @@ namespace Xamarin.PropertyEditing.Drawing
public static bool operator == (CommonColor left, CommonColor right) => Equals (left, right);
public static bool operator != (CommonColor left, CommonColor right) => !Equals (left, right);
+ public static double SquaredDistance (CommonColor left, CommonColor right)
+ => (left.R - right.R) * (left.R - right.R)
+ + (left.G - right.G) * (left.G - right.G)
+ + (left.B - right.B) * (left.B - right.B);
+
public override int GetHashCode ()
{
var hashCode = 466501756;
diff --git a/Xamarin.PropertyEditing/Properties/Resources.Designer.cs b/Xamarin.PropertyEditing/Properties/Resources.Designer.cs
index bfef509..400fe10 100644
--- a/Xamarin.PropertyEditing/Properties/Resources.Designer.cs
+++ b/Xamarin.PropertyEditing/Properties/Resources.Designer.cs
@@ -421,6 +421,186 @@ namespace Xamarin.PropertyEditing.Properties {
}
/// <summary>
+ /// Looks up a localized string similar to Amber.
+ /// </summary>
+ public static string MaterialColorAmber {
+ get {
+ return ResourceManager.GetString("MaterialColorAmber", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Blue.
+ /// </summary>
+ public static string MaterialColorBlue {
+ get {
+ return ResourceManager.GetString("MaterialColorBlue", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Blue Grey.
+ /// </summary>
+ public static string MaterialColorBlueGrey {
+ get {
+ return ResourceManager.GetString("MaterialColorBlueGrey", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Brown.
+ /// </summary>
+ public static string MaterialColorBrown {
+ get {
+ return ResourceManager.GetString("MaterialColorBrown", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Cyan.
+ /// </summary>
+ public static string MaterialColorCyan {
+ get {
+ return ResourceManager.GetString("MaterialColorCyan", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Deep Orange.
+ /// </summary>
+ public static string MaterialColorDeepOrange {
+ get {
+ return ResourceManager.GetString("MaterialColorDeepOrange", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Deep Purple.
+ /// </summary>
+ public static string MaterialColorDeepPurple {
+ get {
+ return ResourceManager.GetString("MaterialColorDeepPurple", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Green.
+ /// </summary>
+ public static string MaterialColorGreen {
+ get {
+ return ResourceManager.GetString("MaterialColorGreen", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Grey.
+ /// </summary>
+ public static string MaterialColorGrey {
+ get {
+ return ResourceManager.GetString("MaterialColorGrey", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Indigo.
+ /// </summary>
+ public static string MaterialColorIndigo {
+ get {
+ return ResourceManager.GetString("MaterialColorIndigo", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Light Blue.
+ /// </summary>
+ public static string MaterialColorLightBlue {
+ get {
+ return ResourceManager.GetString("MaterialColorLightBlue", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Light Green.
+ /// </summary>
+ public static string MaterialColorLightGreen {
+ get {
+ return ResourceManager.GetString("MaterialColorLightGreen", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Lime.
+ /// </summary>
+ public static string MaterialColorLime {
+ get {
+ return ResourceManager.GetString("MaterialColorLime", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Orange.
+ /// </summary>
+ public static string MaterialColorOrange {
+ get {
+ return ResourceManager.GetString("MaterialColorOrange", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Pink.
+ /// </summary>
+ public static string MaterialColorPink {
+ get {
+ return ResourceManager.GetString("MaterialColorPink", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Purple.
+ /// </summary>
+ public static string MaterialColorPurple {
+ get {
+ return ResourceManager.GetString("MaterialColorPurple", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Red.
+ /// </summary>
+ public static string MaterialColorRed {
+ get {
+ return ResourceManager.GetString("MaterialColorRed", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Teal.
+ /// </summary>
+ public static string MaterialColorTeal {
+ get {
+ return ResourceManager.GetString("MaterialColorTeal", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Yellow.
+ /// </summary>
+ public static string MaterialColorYellow {
+ get {
+ return ResourceManager.GetString("MaterialColorYellow", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Material Design Colors.
+ /// </summary>
+ public static string MaterialDesignColorBrush {
+ get {
+ return ResourceManager.GetString("MaterialDesignColorBrush", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to {0} objects selected.
/// </summary>
public static string MultipleObjectsSelected {
diff --git a/Xamarin.PropertyEditing/Properties/Resources.resx b/Xamarin.PropertyEditing/Properties/Resources.resx
index e79d31f..67f0c90 100644
--- a/Xamarin.PropertyEditing/Properties/Resources.resx
+++ b/Xamarin.PropertyEditing/Properties/Resources.resx
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@@ -373,4 +373,65 @@
<data name="Unset" xml:space="preserve">
<value>Unset</value>
</data>
+ <data name="MaterialColorRed" xml:space="preserve">
+ <value>Red</value>
+ </data>
+ <data name="MaterialColorPink" xml:space="preserve">
+ <value>Pink</value>
+ </data>
+ <data name="MaterialColorPurple" xml:space="preserve">
+ <value>Purple</value>
+ </data>
+ <data name="MaterialColorDeepPurple" xml:space="preserve">
+ <value>Deep Purple</value>
+ </data>
+ <data name="MaterialColorIndigo" xml:space="preserve">
+ <value>Indigo</value>
+ </data>
+ <data name="MaterialColorBlue" xml:space="preserve">
+ <value>Blue</value>
+ </data>
+ <data name="MaterialColorLightBlue" xml:space="preserve">
+ <value>Light Blue</value>
+ </data>
+ <data name="MaterialColorCyan" xml:space="preserve">
+ <value>Cyan</value>
+ </data>
+ <data name="MaterialColorTeal" xml:space="preserve">
+ <value>Teal</value>
+ </data>
+ <data name="MaterialColorGreen" xml:space="preserve">
+ <value>Green</value>
+ </data>
+ <data name="MaterialColorLightGreen" xml:space="preserve">
+ <value>Light Green</value>
+ </data>
+ <data name="MaterialColorLime" xml:space="preserve">
+ <value>Lime</value>
+ </data>
+ <data name="MaterialColorYellow" xml:space="preserve">
+ <value>Yellow</value>
+ </data>
+ <data name="MaterialColorAmber" xml:space="preserve">
+ <value>Amber</value>
+ </data>
+ <data name="MaterialColorOrange" xml:space="preserve">
+ <value>Orange</value>
+ </data>
+ <data name="MaterialColorDeepOrange" xml:space="preserve">
+ <value>Deep Orange</value>
+ </data>
+ <data name="MaterialColorBrown" xml:space="preserve">
+ <value>Brown</value>
+ </data>
+ <data name="MaterialColorGrey" xml:space="preserve">
+ <value>Grey</value>
+ </data>
+ <data name="MaterialColorBlueGrey" xml:space="preserve">
+ <value>Blue Grey</value>
+ </data>
+ <data name="MaterialDesignColorBrush" xml:space="preserve">
+ <value>Material Design Colors</value>
+ <comment>Material design help text</comment>
+ </data>
</root> \ No newline at end of file
diff --git a/Xamarin.PropertyEditing/TargetPlatform.cs b/Xamarin.PropertyEditing/TargetPlatform.cs
index cab4366..fe8cc47 100644
--- a/Xamarin.PropertyEditing/TargetPlatform.cs
+++ b/Xamarin.PropertyEditing/TargetPlatform.cs
@@ -20,6 +20,15 @@ namespace Xamarin.PropertyEditing
}
/// <summary>
+ /// Specifies whether Material Design is relevant to theplatform.
+ /// </summary>
+ public bool SupportsMaterialDesign
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
/// Gets a dictionary defining the property types will be grouped into a single editor and their groups resource name.
/// </summary>
public IReadOnlyDictionary<Type, string> GroupedTypes
diff --git a/Xamarin.PropertyEditing/ViewModels/BrushPropertyViewModel.cs b/Xamarin.PropertyEditing/ViewModels/BrushPropertyViewModel.cs
index 56933bd..246fc0b 100644
--- a/Xamarin.PropertyEditing/ViewModels/BrushPropertyViewModel.cs
+++ b/Xamarin.PropertyEditing/ViewModels/BrushPropertyViewModel.cs
@@ -13,10 +13,14 @@ namespace Xamarin.PropertyEditing.ViewModels
if (property.Type.IsAssignableFrom (typeof (CommonSolidBrush))) {
Solid = new SolidBrushViewModel (this,
property is IColorSpaced colorSpacedPropertyInfo ? colorSpacedPropertyInfo.ColorSpaces : null);
+ if (platform.SupportsMaterialDesign) {
+ MaterialDesign = new MaterialDesignColorViewModel (this);
+ }
}
}
public SolidBrushViewModel Solid { get; }
+ public MaterialDesignColorViewModel MaterialDesign { get; }
// TODO: make this its own property view model so we can edit bindings, set to resources, etc.
public double Opacity {
diff --git a/Xamarin.PropertyEditing/ViewModels/MaterialColorScale.cs b/Xamarin.PropertyEditing/ViewModels/MaterialColorScale.cs
new file mode 100644
index 0000000..9b2c8ad
--- /dev/null
+++ b/Xamarin.PropertyEditing/ViewModels/MaterialColorScale.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using Xamarin.PropertyEditing.Drawing;
+
+namespace Xamarin.PropertyEditing.ViewModels
+{
+ internal struct MaterialColorScale
+ {
+ public MaterialColorScale (string name, bool isAccent, int lightIndex, params CommonColor[] colors) : this ()
+ {
+ Name = name;
+ IsAccent = isAccent;
+ LightScriptureIndex = lightIndex;
+ Colors = colors;
+ }
+
+ public IReadOnlyList<CommonColor> Colors { get; set; }
+ // At which index in the scale the rendering should switch to use a light color for the color label
+ public int LightScriptureIndex { get; set; }
+ public bool IsAccent { get; set; }
+ public string Name { get; set; }
+
+ // 500 for main color, A200 for accents
+ public CommonColor MainColor
+ {
+ get {
+ return IsAccent ? Colors[1] : Colors[5];
+ }
+ }
+
+ public override string ToString () => Name;
+ }
+}
diff --git a/Xamarin.PropertyEditing/ViewModels/MaterialDesignColorViewModel.cs b/Xamarin.PropertyEditing/ViewModels/MaterialDesignColorViewModel.cs
new file mode 100644
index 0000000..faa3d0d
--- /dev/null
+++ b/Xamarin.PropertyEditing/ViewModels/MaterialDesignColorViewModel.cs
@@ -0,0 +1,251 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Linq;
+using Xamarin.PropertyEditing.Drawing;
+using Strings = Xamarin.PropertyEditing.Properties.Resources;
+
+namespace Xamarin.PropertyEditing.ViewModels
+{
+ internal class MaterialDesignColorViewModel : NotifyingObject
+ {
+ public MaterialDesignColorViewModel (BrushPropertyViewModel parent)
+ {
+ Parent = parent ?? throw new ArgumentNullException (nameof (parent));
+ parent.PropertyChanged += Parent_PropertyChanged;
+ }
+
+ public CommonColor Color
+ {
+ get => Parent.Value is CommonSolidBrush solidBrush ? solidBrush.Color : new CommonColor (0, 0, 0);
+ private set {
+ if (!Color.Equals (value)) {
+ Parent.Value = new CommonSolidBrush (value, null, Parent.Value.Opacity);
+ OnPropertyChanged (nameof (Alpha));
+ OnPropertyChanged ();
+ }
+ }
+ }
+
+ public string ColorName
+ {
+ get {
+ if (this.colorName != null) return this.colorName;
+ if (Parent.Value is CommonSolidBrush solidBrush) {
+ return (this.colorName = Scale.Name);
+ }
+ return (this.colorName = Strings.MaterialColorGrey);
+ }
+ set {
+ // Attempt to retain normal and accent selections
+ if (NormalColor != null) {
+ var normalColorIndex = Array.IndexOf (NormalColorScale.ToArray (), NormalColor);
+ this.colorName = value;
+ CommonColor?[] newScale = NormalColorScale.ToArray();
+ if (newScale.Length > normalColorIndex) {
+ NormalColor = newScale[normalColorIndex];
+ }
+ ReplaceColor (NormalColor.Value);
+ } else if (AccentColor != null) {
+ var accentColorIndex = Array.IndexOf (AccentColorScale.ToArray (), AccentColor);
+ this.colorName = value;
+ CommonColor?[] newScale = AccentColorScale.ToArray ();
+ if (newScale.Length > accentColorIndex) {
+ AccentColor = newScale[accentColorIndex];
+ }
+ ReplaceColor (AccentColor.Value);
+ } else {
+ this.colorName = value;
+ }
+ OnPropertyChanged ();
+ OnPropertyChanged (nameof (Scale));
+ OnPropertyChanged (nameof (AccentColorScale));
+ OnPropertyChanged (nameof (NormalColorScale));
+ }
+ }
+
+ public byte Alpha
+ {
+ get => Parent.Value is CommonSolidBrush solidBrush ? solidBrush.Color.A : (byte)255;
+ set {
+ CommonColor oldColor = Color;
+ Color = new CommonColor (oldColor.R, oldColor.G, oldColor.B, value);
+ }
+ }
+
+ public MaterialColorScale Scale
+ => MaterialPalettes
+ .OrderBy (palette => palette.Colors.Min (
+ paletteColor => CommonColor.SquaredDistance (paletteColor, Color)))
+ .First ();
+
+ public CommonColor? NormalColor
+ {
+ get {
+ if (this.normalColor.HasValue) return this.normalColor.Value;
+ MaterialColorScale scale = FindPalette (ColorName, false);
+ foreach (CommonColor normalColor in scale.Colors) {
+ if (Color.Equals (normalColor, true)) return (this.normalColor = normalColor).Value;
+ }
+ return null;
+ }
+ set {
+ Debug.Assert (value == null || value.Value.A == 255, "NormalColor should never be set with a transparent color.");
+ Debug.Assert (value == null || MaterialPalettes.Where (p => !p.IsAccent).SelectMany (p => p.Colors).Contains (value.Value), "NormalColor values should exist in the Material Design palette.");
+ this.normalColor = value;
+ if (ColorName != null && value.HasValue) {
+ ReplaceColor (value.Value);
+ }
+ if (value.HasValue) {
+ this.accentColor = null;
+ OnPropertyChanged (nameof (AccentColor));
+ }
+ OnPropertyChanged ();
+ }
+ }
+
+ public CommonColor? AccentColor
+ {
+ get {
+ if (this.accentColor.HasValue) return this.accentColor.Value;
+ MaterialColorScale scale = FindPalette (ColorName, true);
+ foreach (CommonColor accent in scale.Colors) {
+ if (Color.Equals (accent, true)) return (this.accentColor = accent).Value;
+ }
+ return null;
+ }
+ set {
+ Debug.Assert (value?.A == 255, "AccentColor should never be set with a transparent color.");
+ Debug.Assert (value == null || MaterialPalettes.Where (p => p.IsAccent).SelectMany (p => p.Colors).Contains (value.Value), "AccentColor values should exist in the Material Design palette.");
+ this.accentColor = value;
+ if (ColorName != null && value.HasValue) {
+ ReplaceColor (value.Value);
+ }
+ if (value.HasValue) {
+ this.normalColor = null;
+ OnPropertyChanged (nameof (NormalColor));
+ }
+ OnPropertyChanged ();
+ }
+ }
+
+ public IEnumerable<MaterialColorScale> Palettes => MaterialPalettes
+ .Where (palette => !palette.IsAccent);
+ public IEnumerable<CommonColor?> AccentColorScale => FindPalette(ColorName, true).Colors
+ .Select((color, index) => new CommonColor?(new CommonColor(color.R, color.G, color.B, 255, AccentNames[index])));
+ public IEnumerable<CommonColor?> NormalColorScale => FindPalette(ColorName, false).Colors
+ .Select ((color, index) => new CommonColor? (new CommonColor (color.R, color.G, color.B, 255, NormalNames[index])));
+
+ private string colorName;
+ private CommonColor? normalColor = null;
+ private CommonColor? accentColor = null;
+ private BrushPropertyViewModel Parent { get; }
+
+ private void Parent_PropertyChanged (object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof (BrushPropertyViewModel.Value)) {
+ OnPropertyChanged (nameof (Color));
+ OnPropertyChanged (nameof (Alpha));
+ this.colorName = null;
+ this.normalColor = null;
+ this.accentColor = null;
+ OnPropertyChanged (nameof (ColorName));
+ OnPropertyChanged (nameof (AccentColor));
+ OnPropertyChanged (nameof (NormalColor));
+ OnPropertyChanged (nameof (Scale));
+ OnPropertyChanged (nameof (AccentColorScale));
+ OnPropertyChanged (nameof (NormalColorScale));
+ }
+ }
+
+ /// <summary>
+ /// Replaces the current color with a new one, keeping the alpha channel intact.
+ /// </summary>
+ private void ReplaceColor(CommonColor newColor)
+ {
+ var alpha = Color.A;
+ Color = new CommonColor (newColor.R, newColor.G, newColor.B, alpha);
+ }
+
+ private static string[] NormalNames = new[] { "50", "100", "200", "300", "400", "500", "600", "700", "800", "900" };
+ private static string[] AccentNames = new[] { "A100", "A200", "A400", "A700" };
+
+ private static MaterialColorScale FindPalette (string colorName, bool isAccent = false)
+ {
+ return MaterialPalettes.FirstOrDefault (palette => palette.IsAccent == isAccent && palette.Name == colorName);
+ }
+
+ internal static readonly MaterialColorScale[] MaterialPalettes = new [] {
+ new MaterialColorScale (Strings.MaterialColorRed, false, 4, new CommonColor(0xFF, 0xEB, 0xEE), new CommonColor(0xFF, 0xCD, 0xD2), new CommonColor(0xEF, 0x9A, 0x9A), new CommonColor(0xE5, 0x73, 0x73), new CommonColor(0xEF, 0x53, 0x50), new CommonColor(0xF4, 0x43, 0x36), new CommonColor(0xE5, 0x39, 0x35), new CommonColor(0xD3, 0x2F, 0x2F), new CommonColor(0xC6, 0x28, 0x28), new CommonColor(0xB7, 0x1C, 0x1C)),
+
+ new MaterialColorScale (Strings.MaterialColorRed, true, 1, new CommonColor(0xFF, 0x8A, 0x80), new CommonColor(0xFF, 0x52, 0x52), new CommonColor(0xFF, 0x17, 0x44), new CommonColor(0xD5, 0x00, 0x00)),
+
+ new MaterialColorScale (Strings.MaterialColorPink, false, 3, new CommonColor(0xFC, 0xE4, 0xEC), new CommonColor(0xF8, 0xBB, 0xD0), new CommonColor(0xF4, 0x8F, 0xB1), new CommonColor(0xF0, 0x62, 0x92), new CommonColor(0xEC, 0x40, 0x7A), new CommonColor(0xE9, 0x1E, 0x63), new CommonColor(0xD8, 0x1B, 0x60), new CommonColor(0xC2, 0x18, 0x5B), new CommonColor(0xAD, 0x14, 0x57), new CommonColor(0x88, 0x0E, 0x4F)),
+
+ new MaterialColorScale (Strings.MaterialColorPink, true, 1, new CommonColor(0xFF, 0x80, 0xAB), new CommonColor(0xFF, 0x40, 0x81), new CommonColor(0xF5, 0x00, 0x57), new CommonColor(0xC5, 0x11, 0x62)),
+
+ new MaterialColorScale (Strings.MaterialColorPurple, false, 3, new CommonColor(0xF3, 0xE5, 0xF5), new CommonColor(0xE1, 0xBE, 0xE7), new CommonColor(0xCE, 0x93, 0xD8), new CommonColor(0xBA, 0x68, 0xC8), new CommonColor(0xAB, 0x47, 0xBC), new CommonColor(0x9C, 0x27, 0xB0), new CommonColor(0x8E, 0x24, 0xAA), new CommonColor(0x7B, 0x1F, 0xA2), new CommonColor(0x6A, 0x1B, 0x9A), new CommonColor(0x4A, 0x14, 0x8C)),
+
+ new MaterialColorScale (Strings.MaterialColorPurple, true, 1, new CommonColor(0xEA, 0x80, 0xFC), new CommonColor(0xE0, 0x40, 0xFB), new CommonColor(0xD5, 0x00, 0xF9), new CommonColor(0xAA, 0x00, 0xFF)),
+
+ new MaterialColorScale (Strings.MaterialColorDeepPurple, false, 3, new CommonColor(0xED, 0xE7, 0xF6), new CommonColor(0xD1, 0xC4, 0xE9), new CommonColor(0xB3, 0x9D, 0xDB), new CommonColor(0x95, 0x75, 0xCD), new CommonColor(0x7E, 0x57, 0xC2), new CommonColor(0x67, 0x3A, 0xB7), new CommonColor(0x5E, 0x35, 0xB1), new CommonColor(0x51, 0x2D, 0xA8), new CommonColor(0x45, 0x27, 0xA0), new CommonColor(0x31, 0x1B, 0x92)),
+
+ new MaterialColorScale (Strings.MaterialColorDeepPurple, true, 1, new CommonColor(0xB3, 0x88, 0xFF), new CommonColor(0x7C, 0x4D, 0xFF), new CommonColor(0x65, 0x1F, 0xFF), new CommonColor(0x62, 0x00, 0xEA)),
+
+ new MaterialColorScale (Strings.MaterialColorIndigo, false, 3, new CommonColor(0xE8, 0xEA, 0xF6), new CommonColor(0xC5, 0xCA, 0xE9), new CommonColor(0x9F, 0xA8, 0xDA), new CommonColor(0x79, 0x86, 0xCB), new CommonColor(0x5C, 0x6B, 0xC0), new CommonColor(0x3F, 0x51, 0xB5), new CommonColor(0x39, 0x49, 0xAB), new CommonColor(0x30, 0x3F, 0x9F), new CommonColor(0x28, 0x35, 0x93), new CommonColor(0x1A, 0x23, 0x7E)),
+
+ new MaterialColorScale (Strings.MaterialColorIndigo, true, 1, new CommonColor(0x8C, 0x9E, 0xFF), new CommonColor(0x53, 0x6D, 0xFE), new CommonColor(0x3D, 0x5A, 0xFE), new CommonColor(0x30, 0x4F, 0xFE)),
+
+ new MaterialColorScale (Strings.MaterialColorBlue, false, 5, new CommonColor(0xE3, 0xF2, 0xFD), new CommonColor(0xBB, 0xDE, 0xFB), new CommonColor(0x90, 0xCA, 0xF9), new CommonColor(0x64, 0xB5, 0xF6), new CommonColor(0x42, 0xA5, 0xF5), new CommonColor(0x21, 0x96, 0xF3), new CommonColor(0x1E, 0x88, 0xE5), new CommonColor(0x19, 0x76, 0xD2), new CommonColor(0x15, 0x65, 0xC0), new CommonColor(0x0D, 0x47, 0xA1)),
+
+ new MaterialColorScale (Strings.MaterialColorBlue, true, 1, new CommonColor(0x82, 0xB1, 0xFF), new CommonColor(0x44, 0x8A, 0xFF), new CommonColor(0x29, 0x79, 0xFF), new CommonColor(0x29, 0x62, 0xFF)),
+
+ new MaterialColorScale (Strings.MaterialColorLightBlue, false, 6, new CommonColor(0xE1, 0xF5, 0xFE), new CommonColor(0xB3, 0xE5, 0xFC), new CommonColor(0x81, 0xD4, 0xFA), new CommonColor(0x4F, 0xC3, 0xF7), new CommonColor(0x29, 0xB6, 0xF6), new CommonColor(0x03, 0xA9, 0xF4), new CommonColor(0x03, 0x9B, 0xE5), new CommonColor(0x02, 0x88, 0xD1), new CommonColor(0x02, 0x77, 0xBD), new CommonColor(0x01, 0x57, 0x9B)),
+
+ new MaterialColorScale (Strings.MaterialColorLightBlue, true, 3, new CommonColor(0x80, 0xD8, 0xFF), new CommonColor(0x40, 0xC4, 0xFF), new CommonColor(0x00, 0xB0, 0xFF), new CommonColor(0x00, 0x91, 0xEA)),
+
+ new MaterialColorScale (Strings.MaterialColorCyan, false, 7, new CommonColor(0xE0, 0xF7, 0xFA), new CommonColor(0xB2, 0xEB, 0xF2), new CommonColor(0x80, 0xDE, 0xEA), new CommonColor(0x4D, 0xD0, 0xE1), new CommonColor(0x26, 0xC6, 0xDA), new CommonColor(0x00, 0xBC, 0xD4), new CommonColor(0x00, 0xAC, 0xC1), new CommonColor(0x00, 0x97, 0xA7), new CommonColor(0x00, 0x83, 0x8F), new CommonColor(0x00, 0x60, 0x64)),
+
+ new MaterialColorScale (Strings.MaterialColorCyan, true, 4, new CommonColor(0x84, 0xFF, 0xFF), new CommonColor(0x18, 0xFF, 0xFF), new CommonColor(0x00, 0xE5, 0xFF), new CommonColor(0x00, 0xB8, 0xD4)),
+
+ new MaterialColorScale (Strings.MaterialColorTeal, false, 5, new CommonColor(0xE0, 0xF2, 0xF1), new CommonColor(0xB2, 0xDF, 0xDB), new CommonColor(0x80, 0xCB, 0xC4), new CommonColor(0x4D, 0xB6, 0xAC), new CommonColor(0x26, 0xA6, 0x9A), new CommonColor(0x00, 0x96, 0x88), new CommonColor(0x00, 0x89, 0x7B), new CommonColor(0x00, 0x79, 0x6B), new CommonColor(0x00, 0x69, 0x5C), new CommonColor(0x00, 0x4D, 0x40)),
+
+ new MaterialColorScale (Strings.MaterialColorTeal, true, 4, new CommonColor(0xA7, 0xFF, 0xEB), new CommonColor(0x64, 0xFF, 0xDA), new CommonColor(0x1D, 0xE9, 0xB6), new CommonColor(0x00, 0xBF, 0xA5)),
+
+ new MaterialColorScale (Strings.MaterialColorGreen, false, 6, new CommonColor(0xE8, 0xF5, 0xE9), new CommonColor(0xC8, 0xE6, 0xC9), new CommonColor(0xA5, 0xD6, 0xA7), new CommonColor(0x81, 0xC7, 0x84), new CommonColor(0x66, 0xBB, 0x6A), new CommonColor(0x4C, 0xAF, 0x50), new CommonColor(0x43, 0xA0, 0x47), new CommonColor(0x38, 0x8E, 0x3C), new CommonColor(0x2E, 0x7D, 0x32), new CommonColor(0x1B, 0x5E, 0x20)),
+
+ new MaterialColorScale (Strings.MaterialColorGreen, true, 4, new CommonColor(0xB9, 0xF6, 0xCA), new CommonColor(0x69, 0xF0, 0xAE), new CommonColor(0x00, 0xE6, 0x76), new CommonColor(0x00, 0xC8, 0x53)),
+
+ new MaterialColorScale (Strings.MaterialColorLightGreen, false, 7, new CommonColor(0xF1, 0xF8, 0xE9), new CommonColor(0xDC, 0xED, 0xC8), new CommonColor(0xC5, 0xE1, 0xA5), new CommonColor(0xAE, 0xD5, 0x81), new CommonColor(0x9C, 0xCC, 0x65), new CommonColor(0x8B, 0xC3, 0x4A), new CommonColor(0x7C, 0xB3, 0x42), new CommonColor(0x68, 0x9F, 0x38), new CommonColor(0x55, 0x8B, 0x2F), new CommonColor(0x33, 0x69, 0x1E)),
+
+ new MaterialColorScale (Strings.MaterialColorLightGreen, true, 4, new CommonColor(0xCC, 0xFF, 0x90), new CommonColor(0xB2, 0xFF, 0x59), new CommonColor(0x76, 0xFF, 0x03), new CommonColor(0x64, 0xDD, 0x17)),
+
+ new MaterialColorScale (Strings.MaterialColorLime, false, 9, new CommonColor(0xF9, 0xFB, 0xE7), new CommonColor(0xF0, 0xF4, 0xC3), new CommonColor(0xE6, 0xEE, 0x9C), new CommonColor(0xDC, 0xE7, 0x75), new CommonColor(0xD4, 0xE1, 0x57), new CommonColor(0xCD, 0xDC, 0x39), new CommonColor(0xC0, 0xCA, 0x33), new CommonColor(0xAF, 0xB4, 0x2B), new CommonColor(0x9E, 0x9D, 0x24), new CommonColor(0x82, 0x77, 0x17)),
+
+ new MaterialColorScale (Strings.MaterialColorLime, true, 4, new CommonColor(0xF4, 0xFF, 0x81), new CommonColor(0xEE, 0xFF, 0x41), new CommonColor(0xC6, 0xFF, 0x00), new CommonColor(0xAE, 0xEA, 0x00)),
+
+ new MaterialColorScale (Strings.MaterialColorYellow, false, 10, new CommonColor(0xFF, 0xFD, 0xE7), new CommonColor(0xFF, 0xF9, 0xC4), new CommonColor(0xFF, 0xF5, 0x9D), new CommonColor(0xFF, 0xF1, 0x76), new CommonColor(0xFF, 0xEE, 0x58), new CommonColor(0xFF, 0xEB, 0x3B), new CommonColor(0xFD, 0xD8, 0x35), new CommonColor(0xFB, 0xC0, 0x2D), new CommonColor(0xF9, 0xA8, 0x25), new CommonColor(0xF5, 0x7F, 0x17)),
+
+ new MaterialColorScale (Strings.MaterialColorYellow, true, 4, new CommonColor(0xFF, 0xFF, 0x8D), new CommonColor(0xFF, 0xFF, 0x00), new CommonColor(0xFF, 0xEA, 0x00), new CommonColor(0xFF, 0xD6, 0x00)),
+
+ new MaterialColorScale (Strings.MaterialColorAmber, false, 10, new CommonColor(0xFF, 0xF8, 0xE1), new CommonColor(0xFF, 0xEC, 0xB3), new CommonColor(0xFF, 0xE0, 0x82), new CommonColor(0xFF, 0xD5, 0x4F), new CommonColor(0xFF, 0xCA, 0x28), new CommonColor(0xFF, 0xC1, 0x07), new CommonColor(0xFF, 0xB3, 0x00), new CommonColor(0xFF, 0xA0, 0x00), new CommonColor(0xFF, 0x8F, 0x00), new CommonColor(0xFF, 0x6F, 0x00)),
+
+ new MaterialColorScale (Strings.MaterialColorAmber, true, 4, new CommonColor(0xFF, 0xE5, 0x7F), new CommonColor(0xFF, 0xD7, 0x40), new CommonColor(0xFF, 0xC4, 0x00), new CommonColor(0xFF, 0xAB, 0x00)),
+
+ new MaterialColorScale (Strings.MaterialColorOrange, false, 8, new CommonColor(0xFF, 0xF3, 0xE0), new CommonColor(0xFF, 0xE0, 0xB2), new CommonColor(0xFF, 0xCC, 0x80), new CommonColor(0xFF, 0xB7, 0x4D), new CommonColor(0xFF, 0xA7, 0x26), new CommonColor(0xFF, 0x98, 0x00), new CommonColor(0xFB, 0x8C, 0x00), new CommonColor(0xF5, 0x7C, 0x00), new CommonColor(0xEF, 0x6C, 0x00), new CommonColor(0xE6, 0x51, 0x00)),
+
+ new MaterialColorScale (Strings.MaterialColorOrange, true, 4, new CommonColor(0xFF, 0xD1, 0x80), new CommonColor(0xFF, 0xAB, 0x40), new CommonColor(0xFF, 0x91, 0x00), new CommonColor(0xFF, 0x6D, 0x00)),
+
+ new MaterialColorScale (Strings.MaterialColorDeepOrange, false, 5, new CommonColor(0xFB, 0xE9, 0xE7), new CommonColor(0xFF, 0xCC, 0xBC), new CommonColor(0xFF, 0xAB, 0x91), new CommonColor(0xFF, 0x8A, 0x65), new CommonColor(0xFF, 0x70, 0x43), new CommonColor(0xFF, 0x57, 0x22), new CommonColor(0xF4, 0x51, 0x1E), new CommonColor(0xE6, 0x4A, 0x19), new CommonColor(0xD8, 0x43, 0x15), new CommonColor(0xBF, 0x36, 0x0C)),
+
+ new MaterialColorScale (Strings.MaterialColorDeepOrange, true, 2, new CommonColor(0xFF, 0x9E, 0x80), new CommonColor(0xFF, 0x6E, 0x40), new CommonColor(0xFF, 0x3D, 0x00), new CommonColor(0xDD, 0x2C, 0x00)),
+
+ new MaterialColorScale (Strings.MaterialColorBrown, false, 3, new CommonColor(0xEF, 0xEB, 0xE9), new CommonColor(0xD7, 0xCC, 0xC8), new CommonColor(0xBC, 0xAA, 0xA4), new CommonColor(0xA1, 0x88, 0x7F), new CommonColor(0x8D, 0x6E, 0x63), new CommonColor(0x79, 0x55, 0x48), new CommonColor(0x6D, 0x4C, 0x41), new CommonColor(0x5D, 0x40, 0x37), new CommonColor(0x4E, 0x34, 0x2E), new CommonColor(0x3E, 0x27, 0x23)),
+
+ new MaterialColorScale (Strings.MaterialColorGrey, false, 6, new CommonColor(0xFA, 0xFA, 0xFA), new CommonColor(0xF5, 0xF5, 0xF5), new CommonColor(0xEE, 0xEE, 0xEE), new CommonColor(0xE0, 0xE0, 0xE0), new CommonColor(0xBD, 0xBD, 0xBD), new CommonColor(0x9E, 0x9E, 0x9E), new CommonColor(0x75, 0x75, 0x75), new CommonColor(0x61, 0x61, 0x61), new CommonColor(0x42, 0x42, 0x42), new CommonColor(0x21, 0x21, 0x21)),
+
+ new MaterialColorScale (Strings.MaterialColorBlueGrey, false, 4, new CommonColor(0xEC, 0xEF, 0xF1), new CommonColor(0xCF, 0xD8, 0xDC), new CommonColor(0xB0, 0xBE, 0xC5), new CommonColor(0x90, 0xA4, 0xAE), new CommonColor(0x78, 0x90, 0x9C), new CommonColor(0x60, 0x7D, 0x8B), new CommonColor(0x54, 0x6E, 0x7A), new CommonColor(0x45, 0x5A, 0x64), new CommonColor(0x37, 0x47, 0x4F), new CommonColor(0x26, 0x32, 0x38)),
+ };
+ }
+}
diff --git a/Xamarin.PropertyEditing/Xamarin.PropertyEditing.csproj b/Xamarin.PropertyEditing/Xamarin.PropertyEditing.csproj
index cd0c5cb..d86b13c 100644
--- a/Xamarin.PropertyEditing/Xamarin.PropertyEditing.csproj
+++ b/Xamarin.PropertyEditing/Xamarin.PropertyEditing.csproj
@@ -108,6 +108,8 @@
<Compile Include="ValueSource.cs" />
<Compile Include="ViewModels\ArrangeModeViewModel.cs" />
<Compile Include="ViewModels\BrushPropertyViewModel.cs" />
+ <Compile Include="ViewModels\MaterialColorScale.cs" />
+ <Compile Include="ViewModels\MaterialDesignColorViewModel.cs" />
<Compile Include="ViewModels\ResourceRequestedEventArgs.cs" />
<Compile Include="ViewModels\ResourceSelectorViewModel.cs" />
<Compile Include="ViewModels\SimpleCollectionView.cs" />