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:
authorBertrand Le Roy <beleroy@microsoft.com>2018-01-13 00:59:03 +0300
committerBertrand Le Roy <beleroy@microsoft.com>2018-01-13 00:59:03 +0300
commit1454871225d3e69cf94e33270bbabb0abb9a87ff (patch)
treef0bdedd599af2e52cbba2aa33eecb141088d879c
parent3209d96cb4db998373c2d7876a33b423d860eed0 (diff)
Allow for properties with subproperties, and implement it on Brush opacity, color space, and color.bleroy-subproperties-archived
-- Note: we decided against this implementation, this branch is only for reference.
-rw-r--r--Xamarin.PropertyEditing.Tests/ComplexPropertyViewModelTests.cs28
-rw-r--r--Xamarin.PropertyEditing.Tests/MockObjectEditor.cs25
-rw-r--r--Xamarin.PropertyEditing.Tests/MockPropertyInfo/MockPropertyInfo.cs53
-rw-r--r--Xamarin.PropertyEditing.Tests/Xamarin.PropertyEditing.Tests.csproj1
-rw-r--r--Xamarin.PropertyEditing.Windows/DoubleToPercentageConverter.cs26
-rw-r--r--Xamarin.PropertyEditing.Windows/SolidBrushEditorControl.cs16
-rw-r--r--Xamarin.PropertyEditing.Windows/StringValueInfoConverter.cs32
-rw-r--r--Xamarin.PropertyEditing.Windows/Themes/Resources.xaml81
-rw-r--r--Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj1
-rw-r--r--Xamarin.PropertyEditing/BrushPropertyInfo.cs104
-rw-r--r--Xamarin.PropertyEditing/IComplexPropertyInfo.cs9
-rw-r--r--Xamarin.PropertyEditing/ISubPropertyInfo.cs7
-rw-r--r--Xamarin.PropertyEditing/ViewModels/BrushPropertyViewModel.cs23
-rw-r--r--Xamarin.PropertyEditing/ViewModels/SolidBrushViewModel.cs85
-rw-r--r--Xamarin.PropertyEditing/Xamarin.PropertyEditing.csproj2
15 files changed, 389 insertions, 104 deletions
diff --git a/Xamarin.PropertyEditing.Tests/ComplexPropertyViewModelTests.cs b/Xamarin.PropertyEditing.Tests/ComplexPropertyViewModelTests.cs
new file mode 100644
index 0000000..1036128
--- /dev/null
+++ b/Xamarin.PropertyEditing.Tests/ComplexPropertyViewModelTests.cs
@@ -0,0 +1,28 @@
+using NUnit.Framework;
+using Xamarin.PropertyEditing.Tests.MockPropertyInfo;
+using System.Threading.Tasks;
+
+namespace Xamarin.PropertyEditing.Tests
+{
+ internal class ComplexPropertyViewModelTests
+ {
+ [Test]
+ public async Task SubPropertyCanBeEdited ()
+ {
+ var property = new MockComplexPropertyInfo<int> ("Property");
+ MockSubPropertyInfo<double> subProperty = property.AddSubProperty<double> ("SubProperty");
+ var editor = new MockObjectEditor (property);
+
+ var changed = false;
+ editor.PropertyChanged += (s, e) => {
+ if (e.Property == subProperty) {
+ changed = true;
+ }
+ };
+ Assert.AreEqual (default (double), (await editor.GetValueAsync<double> (subProperty)).Value);
+ await editor.SetValueAsync (subProperty, new ValueInfo<double> { Source = ValueSource.Local, Value = 1.0 });
+ Assert.IsTrue (changed);
+ Assert.AreEqual (1.0, (await editor.GetValueAsync<double> (subProperty)).Value);
+ }
+ }
+}
diff --git a/Xamarin.PropertyEditing.Tests/MockObjectEditor.cs b/Xamarin.PropertyEditing.Tests/MockObjectEditor.cs
index 714f527..28fb0c3 100644
--- a/Xamarin.PropertyEditing.Tests/MockObjectEditor.cs
+++ b/Xamarin.PropertyEditing.Tests/MockObjectEditor.cs
@@ -15,7 +15,11 @@ namespace Xamarin.PropertyEditing.Tests
public MockObjectEditor (params IPropertyInfo[] properties)
{
- Properties = properties.ToArray ();
+ Properties = properties
+ .Union(properties
+ .OfType<IComplexPropertyInfo>()
+ .SelectMany(p => p.Properties)
+ ).ToArray ();
}
public MockObjectEditor (MockControl control)
@@ -99,8 +103,7 @@ namespace Xamarin.PropertyEditing.Tests
public Task<IReadOnlyList<string>> GetHandlersAsync (IEventInfo ev)
{
- string handler;
- if (this.events.TryGetValue (ev, out handler))
+ if (this.events.TryGetValue (ev, out string handler))
return Task.FromResult<IReadOnlyList<string>> (new[] { handler });
return Task.FromResult<IReadOnlyList<string>> (new string[0]);
@@ -119,11 +122,8 @@ namespace Xamarin.PropertyEditing.Tests
object softValue = value;
if (typeof(T) != property.Type) {
- IPropertyConverter converter = property as IPropertyConverter;
-
- object v;
- if (converter != null && converter.TryConvert (value.Value, property.Type, out v)) {
- var softType = typeof(ValueInfo<>).MakeGenericType (property.Type);
+ if (property is IPropertyConverter converter && converter.TryConvert (value.Value, property.Type, out object v)) {
+ Type softType = typeof (ValueInfo<>).MakeGenericType (property.Type);
softValue = Activator.CreateInstance (softType);
softType.GetProperty ("Value").SetValue (softValue, v);
softType.GetProperty ("Source").SetValue (softValue, value.Source);
@@ -139,8 +139,7 @@ namespace Xamarin.PropertyEditing.Tests
if (variation != null)
throw new NotSupportedException (); // TODO
- object value;
- if (this.values.TryGetValue (property, out value)) {
+ if (this.values.TryGetValue (property, out object value)) {
var info = value as ValueInfo<T>;
if (info != null)
return info;
@@ -152,14 +151,12 @@ namespace Xamarin.PropertyEditing.Tests
} else {
ValueSource source = ValueSource.Local;
Type valueType = value.GetType ();
- if (valueType.IsConstructedGenericType && valueType.GetGenericTypeDefinition () == typeof(ValueInfo<>)) {
+ if (valueType.IsConstructedGenericType && valueType.GetGenericTypeDefinition () == typeof (ValueInfo<>)) {
source = (ValueSource)valueType.GetProperty ("Source").GetValue (value);
value = valueType.GetProperty ("Value").GetValue (value);
}
- object newValue;
- IPropertyConverter converter = property as IPropertyConverter;
- if (converter != null && converter.TryConvert (value, typeof(T), out newValue)) {
+ if (property is IPropertyConverter converter && converter.TryConvert (value, typeof (T), out object newValue)) {
return new ValueInfo<T> {
Source = source,
Value = (T)newValue
diff --git a/Xamarin.PropertyEditing.Tests/MockPropertyInfo/MockPropertyInfo.cs b/Xamarin.PropertyEditing.Tests/MockPropertyInfo/MockPropertyInfo.cs
index dc44742..47046ca 100644
--- a/Xamarin.PropertyEditing.Tests/MockPropertyInfo/MockPropertyInfo.cs
+++ b/Xamarin.PropertyEditing.Tests/MockPropertyInfo/MockPropertyInfo.cs
@@ -2,13 +2,13 @@ using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
-using Xamarin.PropertyEditing.Tests.MockControls;
namespace Xamarin.PropertyEditing.Tests.MockPropertyInfo
{
public class MockPropertyInfo<T> : IPropertyInfo, IPropertyConverter, IEquatable<MockPropertyInfo<T>>
{
- public MockPropertyInfo (string name, string category = "", bool canWrite = true, IEnumerable<Type> converterTypes = null)
+ public MockPropertyInfo (string name, string category = "",
+ bool canWrite = true, IEnumerable<Type> converterTypes = null)
{
Name = name;
Category = category;
@@ -17,7 +17,7 @@ namespace Xamarin.PropertyEditing.Tests.MockPropertyInfo
this.typeConverters = converterTypes
.Where (type => type != null && typeof (TypeConverter).IsAssignableFrom (type))
.Select (type => (TypeConverter)Activator.CreateInstance (type))
- .ToArray();
+ .ToArray ();
}
}
@@ -35,7 +35,7 @@ namespace Xamarin.PropertyEditing.Tests.MockPropertyInfo
{
toValue = null;
if (this.typeConverters != null) {
- foreach (var converter in this.typeConverters) {
+ foreach (TypeConverter converter in this.typeConverters) {
if (converter.CanConvertTo (toType)) {
toValue = converter.ConvertTo (fromValue, toType);
return true;
@@ -43,7 +43,7 @@ namespace Xamarin.PropertyEditing.Tests.MockPropertyInfo
}
}
- if (toType == typeof(string)) {
+ if (toType == typeof (string)) {
toValue = fromValue?.ToString ();
return true;
}
@@ -52,15 +52,15 @@ namespace Xamarin.PropertyEditing.Tests.MockPropertyInfo
toValue = Convert.ChangeType (fromValue, toType);
return true;
} catch {
-
+
}
-
+
return false;
}
public bool Equals (MockPropertyInfo<T> other)
{
- if (ReferenceEquals (null, other))
+ if (other is null)
return false;
if (ReferenceEquals (this, other))
return true;
@@ -72,11 +72,11 @@ namespace Xamarin.PropertyEditing.Tests.MockPropertyInfo
public override bool Equals (object obj)
{
- if (ReferenceEquals (null, obj))
+ if (obj is null)
return false;
if (ReferenceEquals (this, obj))
return true;
- if (GetType() != obj.GetType ())
+ if (GetType () != obj.GetType ())
return false;
return Equals ((MockPropertyInfo<T>)obj);
@@ -95,6 +95,37 @@ namespace Xamarin.PropertyEditing.Tests.MockPropertyInfo
return hashCode;
}
- private readonly IReadOnlyList<TypeConverter> typeConverters;
+ readonly IReadOnlyList<TypeConverter> typeConverters;
+ }
+
+ public class MockComplexPropertyInfo<T> : MockPropertyInfo<T>, IComplexPropertyInfo
+ {
+ public MockComplexPropertyInfo (string name, string category = "",
+ bool canWrite = true, IEnumerable<Type> converterTypes = null) : base (name, category, canWrite, converterTypes)
+ {
+ this.subProperties = new List<ISubPropertyInfo> ();
+ }
+
+ public IReadOnlyCollection<ISubPropertyInfo> Properties => this.subProperties.ToArray ();
+
+ public MockSubPropertyInfo<V> AddSubProperty<V> (string name, string category = "",
+ bool canWrite = true, IEnumerable<Type> converterTypes = null)
+ {
+ var subProperty = new MockSubPropertyInfo<V> (this, name, category, canWrite, converterTypes);
+ this.subProperties.Add (subProperty);
+ return subProperty;
+ }
+
+ readonly List<ISubPropertyInfo> subProperties;
+ }
+
+ public class MockSubPropertyInfo<T> : MockPropertyInfo<T>, ISubPropertyInfo
+ {
+ public MockSubPropertyInfo (IComplexPropertyInfo parentProperty, string name, string category = "", bool canWrite = true, IEnumerable<Type> converterTypes = null) : base (name, category, canWrite, converterTypes)
+ {
+ ParentProperty = parentProperty;
+ }
+
+ public IComplexPropertyInfo ParentProperty { get; }
}
}
diff --git a/Xamarin.PropertyEditing.Tests/Xamarin.PropertyEditing.Tests.csproj b/Xamarin.PropertyEditing.Tests/Xamarin.PropertyEditing.Tests.csproj
index 7fcba52..13fbc09 100644
--- a/Xamarin.PropertyEditing.Tests/Xamarin.PropertyEditing.Tests.csproj
+++ b/Xamarin.PropertyEditing.Tests/Xamarin.PropertyEditing.Tests.csproj
@@ -61,6 +61,7 @@
<Compile Include="BrushPropertyViewModelTests.cs" />
<Compile Include="BytePropertyViewModelTests.cs" />
<Compile Include="CommonColorTests.cs" />
+ <Compile Include="ComplexPropertyViewModelTests.cs" />
<Compile Include="Helpers.cs" />
<Compile Include="IPropertyConverter.cs" />
<Compile Include="MockControls\MockControl.cs" />
diff --git a/Xamarin.PropertyEditing.Windows/DoubleToPercentageConverter.cs b/Xamarin.PropertyEditing.Windows/DoubleToPercentageConverter.cs
index 1d8074d..af3da92 100644
--- a/Xamarin.PropertyEditing.Windows/DoubleToPercentageConverter.cs
+++ b/Xamarin.PropertyEditing.Windows/DoubleToPercentageConverter.cs
@@ -11,11 +11,19 @@ namespace Xamarin.PropertyEditing.Windows
{
public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
{
- if (!(value is double)) return DependencyProperty.UnsetValue;
+ if (!(value is double) && !(value is ValueInfo<double>)) return DependencyProperty.UnsetValue;
- var doubleValue = (double)value;
- if (doubleValue < 0 || doubleValue > 1) return DependencyProperty.UnsetValue;
- return doubleValue * 100;
+ double doubleValue;
+ if (value is double) {
+ doubleValue = (double)value;
+ } else if (value is ValueInfo<double> doubleValueInfo && doubleValueInfo.Source == ValueSource.Local) {
+ doubleValue = doubleValueInfo.Value;
+ } else {
+ return DependencyProperty.UnsetValue;
+ }
+
+ if (doubleValue< 0 || doubleValue> 1) return DependencyProperty.UnsetValue;
+ return doubleValue* 100;
}
public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
@@ -24,7 +32,15 @@ namespace Xamarin.PropertyEditing.Windows
var doubleValue = (double)value;
if ((doubleValue < 0) || (doubleValue > 100)) return DependencyProperty.UnsetValue;
- return doubleValue / 100;
+
+ var convertedValue = doubleValue / 100;
+
+ if (targetType.IsAssignableFrom (typeof (double))) return convertedValue;
+ if (targetType.IsAssignableFrom (typeof (ValueInfo<double>))) return new ValueInfo<double> {
+ Source = ValueSource.Local,
+ Value = convertedValue
+ };
+ return DependencyProperty.UnsetValue;
}
public override object ProvideValue (IServiceProvider serviceProvider) => this;
diff --git a/Xamarin.PropertyEditing.Windows/SolidBrushEditorControl.cs b/Xamarin.PropertyEditing.Windows/SolidBrushEditorControl.cs
index 5e3a1df..b7e1074 100644
--- a/Xamarin.PropertyEditing.Windows/SolidBrushEditorControl.cs
+++ b/Xamarin.PropertyEditing.Windows/SolidBrushEditorControl.cs
@@ -13,26 +13,22 @@ namespace Xamarin.PropertyEditing.Windows
DefaultStyleKey = typeof (SolidBrushEditorControl);
}
- ComboBox colorSpacePicker;
-
- BrushPropertyViewModel ViewModel => DataContext as BrushPropertyViewModel;
-
public override void OnApplyTemplate ()
{
base.OnApplyTemplate ();
if (ViewModel == null) return;
- colorSpacePicker = (ComboBox)GetTemplateChild ("colorSpacePicker");
+ this.colorSpacePicker = (ComboBox)GetTemplateChild ("colorSpacePicker");
if (ViewModel.Solid.ColorSpaces == null || ViewModel.Solid.ColorSpaces.Count == 0) {
- colorSpacePicker.Visibility = Visibility.Collapsed;
+ this.colorSpacePicker.Visibility = Visibility.Collapsed;
}
if (ViewModel.Property.CanWrite) {
// Handle color space changes
- colorSpacePicker.SelectionChanged += (s, e) => {
+ this.colorSpacePicker.SelectionChanged += (s, e) => {
if (ViewModel != null && ViewModel.Value != null) {
- ViewModel.Value = new CommonSolidBrush (ViewModel.Solid.Color, (string)e.AddedItems[0]);
+ ViewModel.Value = new CommonSolidBrush (ViewModel.Solid.Color.Value, (string)e.AddedItems[0]);
}
};
}
@@ -45,5 +41,9 @@ namespace Xamarin.PropertyEditing.Windows
ViewModel.Solid.CommitShade ();
}));
}
+
+ ComboBox colorSpacePicker;
+
+ BrushPropertyViewModel ViewModel => DataContext as BrushPropertyViewModel;
}
}
diff --git a/Xamarin.PropertyEditing.Windows/StringValueInfoConverter.cs b/Xamarin.PropertyEditing.Windows/StringValueInfoConverter.cs
new file mode 100644
index 0000000..24f2dcb
--- /dev/null
+++ b/Xamarin.PropertyEditing.Windows/StringValueInfoConverter.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Globalization;
+using System.Windows;
+using System.Windows.Data;
+using System.Windows.Markup;
+
+namespace Xamarin.PropertyEditing.Windows
+{
+ [ValueConversion (typeof (ValueInfo<string>), typeof (string))]
+ internal class StringValueInfoConverter : MarkupExtension, IValueConverter
+ {
+ public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (!(value is string) && !(value is ValueInfo<string>)) return DependencyProperty.UnsetValue;
+
+ if (value is ValueInfo<string> stringValueInfo) return stringValueInfo.Value;
+ return (string)value;
+ }
+
+ public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (!(value is string stringValue)) return DependencyProperty.UnsetValue;
+
+ return new ValueInfo<string> {
+ Source = ValueSource.Local,
+ Value = stringValue
+ };
+ }
+
+ public override object ProvideValue (IServiceProvider serviceProvider) => this;
+ }
+}
diff --git a/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml b/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml
index c07f23e..cccc5ed 100644
--- a/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml
+++ b/Xamarin.PropertyEditing.Windows/Themes/Resources.xaml
@@ -567,37 +567,56 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:SolidBrushEditorControl">
- <Grid VerticalAlignment="Top" Margin="0,6,0,0" MinHeight="180">
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="*"/>
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="*" MinWidth="200"/>
- <ColumnDefinition Width="Auto"/>
- </Grid.ColumnDefinitions>
- <ComboBox Name="colorSpacePicker" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Solid.ColorSpaces}"
- SelectedItem="{Binding Solid.ColorSpace, Mode=OneTime}" VerticalContentAlignment="Center"
- AutomationProperties.Name="{x:Static prop:Resources.ColorSpace}" AutomationProperties.HelpText="{x:Static prop:Resources.ColorSpace}" ToolTip="{x:Static prop:Resources.ColorSpace}"/>
- <Grid Grid.Row="1" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
- <Grid.RowDefinitions>
- <RowDefinition Height="*"/>
- <RowDefinition Height="Auto"/>
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="*"/>
- <ColumnDefinition Width="Auto"/>
- </Grid.ColumnDefinitions>
- <local:ShadeEditorControl x:Name="shadeChooser" Color="{Binding Path=Solid.Shade, Mode=TwoWay}" HueColor="{Binding Path=Solid.HueColor, Mode=OneWay}"
- Grid.Column="0" Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="0,6,0,1" Panel.ZIndex="1"/>
- <local:HueEditorControl x:Name="hueChooser" HueColor="{Binding Path=Solid.HueColor, Mode=TwoWay}"
- Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="1,6,3,1" Panel.ZIndex="0" Focusable="False"/>
- <local:CurrentColorEditorControl Color="{Binding Path=Solid.Shade, Mode=TwoWay}" InitialColor="{Binding Solid.InitialColor}" LastColor="{Binding Solid.LastColor}"
- Grid.Column="0" Grid.Row="1" HorizontalAlignment="Stretch" Height="20" Margin="0,0,0,0" Panel.ZIndex="0" Focusable="False"/>
- </Grid>
- <local:ColorComponentsEditorControl x:Name="componentEditor" Color="{Binding Path=Solid.Shade, Mode=TwoWay}" Margin="0,4,0,0"
- Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Focusable="False"/>
- </Grid>
+ <TabControl Margin="0,4,0,0">
+ <TabItem>
+ <TabItem.Header>
+ <local:PropertyPresenter Label="{x:Static prop:Resources.ColorEditorTabLabel}"/>
+ </TabItem.Header>
+ <Grid VerticalAlignment="Top" Margin="0,6,0,0" MinHeight="180">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*" MinWidth="150"/>
+ <ColumnDefinition Width="Auto"/>
+ </Grid.ColumnDefinitions>
+ <local:PropertyPresenter Label="{x:Static prop:Resources.ColorSpace}" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="0">
+ <ComboBox
+ Name="colorSpacePicker" ItemsSource="{Binding Solid.ColorSpaces}"
+ SelectedItem="{Binding Solid.ColorSpace, Mode=OneTime, Converter={local:StringValueInfoConverter}}" VerticalContentAlignment="Center"
+ AutomationProperties.Name="{x:Static prop:Resources.ColorSpace}" AutomationProperties.HelpText="{x:Static prop:Resources.ColorSpace}" ToolTip="{x:Static prop:Resources.ColorSpace}"/>
+ </local:PropertyPresenter>
+ <Grid Grid.Row="1" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="*"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="*"/>
+ <ColumnDefinition Width="Auto"/>
+ </Grid.ColumnDefinitions>
+ <local:ShadeEditorControl
+ x:Name="shadeChooser" Color="{Binding Path=Solid.Shade, Mode=TwoWay}" HueColor="{Binding Path=Solid.HueColor, Mode=OneWay}"
+ Grid.Column="0" Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="0,6,0,1" Panel.ZIndex="1"/>
+ <local:HueEditorControl
+ x:Name="hueChooser" HueColor="{Binding Path=Solid.HueColor, Mode=TwoWay}"
+ Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="1,6,3,1" Panel.ZIndex="0" Focusable="False"/>
+ <local:CurrentColorEditorControl
+ Color="{Binding Path=Solid.Shade, Mode=TwoWay}" InitialColor="{Binding Solid.InitialColor}" LastColor="{Binding Solid.LastColor}"
+ Grid.Column="0" Grid.Row="1" HorizontalAlignment="Stretch" Height="20" Margin="0,0,0,0" Panel.ZIndex="0" Focusable="False"/>
+ </Grid>
+ <local:ColorComponentsEditorControl x:Name="componentEditor"
+ Color="{Binding Path=Solid.Shade, Mode=TwoWay}" Margin="0,4,0,0"
+ Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Focusable="False"/>
+ </Grid>
+ </TabItem>
+ <!--<TabItem>
+ <TabItem.Header>
+ <Label>Color Resources</Label>
+ </TabItem.Header>
+ </TabItem>-->
+ </TabControl>
</ControlTemplate>
</Setter.Value>
</Setter>
diff --git a/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj b/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj
index 037d0d4..c2fb458 100644
--- a/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj
+++ b/Xamarin.PropertyEditing.Windows/Xamarin.PropertyEditing.Windows.csproj
@@ -70,6 +70,7 @@
<Compile Include="DoubleToPercentageConverter.cs" />
<Compile Include="DoubleToQuantityConverter.cs" />
<Compile Include="TextBoxEx.cs" />
+ <Compile Include="StringValueInfoConverter.cs" />
<Compile Include="ToggleButtonEx.cs" />
<Compile Include="EditorPropertySelector.cs" />
<Compile Include="EnumEditorControl.cs" />
diff --git a/Xamarin.PropertyEditing/BrushPropertyInfo.cs b/Xamarin.PropertyEditing/BrushPropertyInfo.cs
index 7c2e3bc..a040efc 100644
--- a/Xamarin.PropertyEditing/BrushPropertyInfo.cs
+++ b/Xamarin.PropertyEditing/BrushPropertyInfo.cs
@@ -1,10 +1,11 @@
using System;
using System.Collections.Generic;
using Xamarin.PropertyEditing.Drawing;
+using Xamarin.PropertyEditing.ViewModels;
namespace Xamarin.PropertyEditing
{
- public class BrushPropertyInfo : IPropertyInfo, IColorSpaced
+ public class BrushPropertyInfo : IComplexPropertyInfo, IColorSpaced
{
public BrushPropertyInfo (string name, string category, bool canWrite,
IReadOnlyList<string> colorSpaces = null, ValueSources valueSources = ValueSources.Local,
@@ -24,7 +25,7 @@ namespace Xamarin.PropertyEditing
public string Name { get; }
- public Type Type => typeof(CommonBrush);
+ public Type Type => typeof (CommonBrush);
public string Category { get; }
@@ -35,5 +36,104 @@ namespace Xamarin.PropertyEditing
public IReadOnlyList<PropertyVariation> Variations { get; }
public IReadOnlyList<IAvailabilityConstraint> AvailabilityConstraints { get; }
+
+ public IReadOnlyCollection<ISubPropertyInfo> Properties =>
+ this.properties ?? (
+ this.properties = new ISubPropertyInfo[] {
+ OpacityInfo,
+ ColorSpaceInfo,
+ ColorInfo
+ });
+
+ public OpacityPropertyInfo OpacityInfo =>
+ this.opacityInfo ?? (
+ this.opacityInfo = new OpacityPropertyInfo (this));
+
+ public ColorSpacePropertyInfo ColorSpaceInfo =>
+ this.colorSpaceInfo ?? (
+ this.colorSpaceInfo = new ColorSpacePropertyInfo (this));
+
+ public ColorPropertyInfo ColorInfo =>
+ this.colorInfo ?? (
+ this.colorInfo = new ColorPropertyInfo (this));
+
+ OpacityPropertyInfo opacityInfo;
+ ColorSpacePropertyInfo colorSpaceInfo;
+ ColorPropertyInfo colorInfo;
+ IReadOnlyCollection<ISubPropertyInfo> properties;
+
+ public class OpacityPropertyInfo : ISubPropertyInfo
+ {
+ public OpacityPropertyInfo (BrushPropertyInfo parent)
+ {
+ ParentProperty = parent;
+ }
+
+ public IComplexPropertyInfo ParentProperty { get; }
+
+ public string Name => nameof(BrushPropertyViewModel.Opacity);
+
+ public Type Type => typeof (double);
+
+ public string Category => null;
+
+ public bool CanWrite => true;
+
+ public ValueSources ValueSources =>
+ ValueSources.Local | ValueSources.Default;
+
+ public IReadOnlyList<PropertyVariation> Variations => null;
+
+ public IReadOnlyList<IAvailabilityConstraint> AvailabilityConstraints => null;
+ }
+
+ public class ColorSpacePropertyInfo : ISubPropertyInfo
+ {
+ public ColorSpacePropertyInfo (BrushPropertyInfo parent)
+ {
+ ParentProperty = parent;
+ }
+
+ public IComplexPropertyInfo ParentProperty { get; }
+
+ public string Name => nameof (SolidBrushViewModel.ColorSpace);
+
+ public Type Type => typeof (string);
+
+ public string Category => null;
+
+ public bool CanWrite => true;
+
+ public ValueSources ValueSources =>
+ ValueSources.Local | ValueSources.Default;
+
+ public IReadOnlyList<PropertyVariation> Variations => null;
+
+ public IReadOnlyList<IAvailabilityConstraint> AvailabilityConstraints => null;
+ }
+
+ public class ColorPropertyInfo : ISubPropertyInfo
+ {
+ public ColorPropertyInfo(BrushPropertyInfo parent)
+ {
+ ParentProperty = parent;
+ }
+
+ public IComplexPropertyInfo ParentProperty { get; }
+
+ public string Name => nameof(SolidBrushViewModel.Color);
+
+ public Type Type => typeof(CommonColor);
+
+ public string Category => null;
+
+ public bool CanWrite => true;
+
+ public ValueSources ValueSources => ValueSources.Local | ValueSources.Default;
+
+ public IReadOnlyList<PropertyVariation> Variations => null;
+
+ public IReadOnlyList<IAvailabilityConstraint> AvailabilityConstraints => null;
+ }
}
}
diff --git a/Xamarin.PropertyEditing/IComplexPropertyInfo.cs b/Xamarin.PropertyEditing/IComplexPropertyInfo.cs
new file mode 100644
index 0000000..3d1cb5f
--- /dev/null
+++ b/Xamarin.PropertyEditing/IComplexPropertyInfo.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace Xamarin.PropertyEditing
+{
+ public interface IComplexPropertyInfo : IPropertyInfo
+ {
+ IReadOnlyCollection<ISubPropertyInfo> Properties { get; }
+ }
+}
diff --git a/Xamarin.PropertyEditing/ISubPropertyInfo.cs b/Xamarin.PropertyEditing/ISubPropertyInfo.cs
new file mode 100644
index 0000000..7793d51
--- /dev/null
+++ b/Xamarin.PropertyEditing/ISubPropertyInfo.cs
@@ -0,0 +1,7 @@
+namespace Xamarin.PropertyEditing
+{
+ public interface ISubPropertyInfo : IPropertyInfo
+ {
+ IComplexPropertyInfo ParentProperty { get; }
+ }
+}
diff --git a/Xamarin.PropertyEditing/ViewModels/BrushPropertyViewModel.cs b/Xamarin.PropertyEditing/ViewModels/BrushPropertyViewModel.cs
index 2eee16d..5139267 100644
--- a/Xamarin.PropertyEditing/ViewModels/BrushPropertyViewModel.cs
+++ b/Xamarin.PropertyEditing/ViewModels/BrushPropertyViewModel.cs
@@ -17,25 +17,32 @@ namespace Xamarin.PropertyEditing.ViewModels
public SolidBrushViewModel Solid { get; }
- public double Opacity {
- get => Value == null ? 1.0 : Value.Opacity;
+ public ValueInfo<double> Opacity
+ {
+ get => this.opacity ?? (
+ this.opacity = new ValueInfo<double> {
+ Source = ValueSource.Local,
+ Value = Value == null ? 1.0 : Value.Opacity
+ });
set {
- if (Value is null) return;
+ this.opacity = value;
+ if (Value is null || value.Source != ValueSource.Local) return;
+ var opacity = value.Value;
if (Value is CommonSolidBrush solid) {
- Value = new CommonSolidBrush (solid.Color, solid.ColorSpace, value);
+ Value = new CommonSolidBrush (solid.Color, solid.ColorSpace, opacity);
} else if (Value is CommonImageBrush img) {
Value = new CommonImageBrush (
img.ImageSource, img.AlignmentX, img.AlignmentY, img.Stretch, img.TileMode,
- img.ViewBox, img.ViewBoxUnits, img.ViewPort, img.ViewPortUnits, value);
+ img.ViewBox, img.ViewBoxUnits, img.ViewPort, img.ViewPortUnits, opacity);
} else if (Value is CommonLinearGradientBrush linear) {
Value = new CommonLinearGradientBrush (
linear.StartPoint, linear.EndPoint, linear.GradientStops,
- linear.ColorInterpolationMode, linear.MappingMode, linear.SpreadMethod, value);
+ linear.ColorInterpolationMode, linear.MappingMode, linear.SpreadMethod, opacity);
} else if (Value is CommonRadialGradientBrush radial) {
Value = new CommonRadialGradientBrush (
radial.Center, radial.GradientOrigin, radial.RadiusX, radial.RadiusY,
radial.GradientStops, radial.ColorInterpolationMode, radial.MappingMode,
- radial.SpreadMethod, value);
+ radial.SpreadMethod, opacity);
} else {
throw new InvalidOperationException ("Value is an unsupported brush type.");
}
@@ -48,5 +55,7 @@ namespace Xamarin.PropertyEditing.ViewModels
base.UpdateCurrentValue ();
OnPropertyChanged (nameof (Opacity));
}
+
+ ValueInfo<double> opacity;
}
}
diff --git a/Xamarin.PropertyEditing/ViewModels/SolidBrushViewModel.cs b/Xamarin.PropertyEditing/ViewModels/SolidBrushViewModel.cs
index b8bdb32..4f13b64 100644
--- a/Xamarin.PropertyEditing/ViewModels/SolidBrushViewModel.cs
+++ b/Xamarin.PropertyEditing/ViewModels/SolidBrushViewModel.cs
@@ -18,18 +18,32 @@ namespace Xamarin.PropertyEditing.ViewModels
public CommonSolidBrush PreviousSolidBrush { get; set; }
- public string ColorSpace => Parent.Value is CommonSolidBrush solidBrush ? solidBrush.ColorSpace : null;
+ public ValueInfo<string> ColorSpace
+ {
+ get => this.colorSpace ?? (this.colorSpace = new ValueInfo<string> {
+ Source = ValueSource.Local,
+ Value = Parent.Value is CommonSolidBrush solidBrush ? solidBrush.ColorSpace : null
+ });
+ set {
+ this.colorSpace = value;
+ OnPropertyChanged ();
+ SetParentValue (Color.Value, value.Value, Parent.Value.Opacity);
+ }
+ }
public CommonColor HueColor {
get => (this.hueColor ?? (this.hueColor = LastColor.HueColor)).Value;
set {
if (!this.hueColor.Equals (value)) {
- var saturation = Color.Saturation;
- var brightness = Color.Brightness;
- Color = CommonColor.FromHSB (value.Hue, saturation, brightness, Color.A);
+ var saturation = Color.Value.Saturation;
+ var brightness = Color.Value.Brightness;
+ Color = new ValueInfo<CommonColor> {
+ Source = ValueSource.Local,
+ Value = CommonColor.FromHSB (value.Hue, saturation, brightness, Color.Value.A)
+ };
this.hueColor = value;
OnPropertyChanged ();
- Parent.Value = new CommonSolidBrush (Color, ColorSpace, Parent.Value.Opacity);
+ SetParentValue (Color.Value, ColorSpace.Value, Parent.Value.Opacity);
}
}
}
@@ -40,48 +54,54 @@ namespace Xamarin.PropertyEditing.ViewModels
if (!this.shade.Equals (value)) {
this.shade = value;
OnPropertyChanged ();
- Parent.Value = new CommonSolidBrush (value, ColorSpace, Parent.Value.Opacity);
+ SetParentValue (value, ColorSpace.Value, Parent.Value.Opacity);
}
}
}
- public CommonColor Color {
- get => Parent.Value is CommonSolidBrush solidBrush ? solidBrush.Color : new CommonColor (0, 0, 0);
+ public ValueInfo<CommonColor> Color {
+ get => this.color ?? (
+ this.color = new ValueInfo<CommonColor> {
+ Source = ValueSource.Local,
+ Value = Parent.Value is CommonSolidBrush solidBrush ? solidBrush.Color : new CommonColor (0, 0, 0)
+ });
set {
if (!Color.Equals (value)) {
+ this.color = value;
CommonColor oldHue = HueColor;
- CommonColor newHue = value.HueColor;
- Parent.Value = new CommonSolidBrush (value, ColorSpace, Parent.Value.Opacity);
+ CommonColor newColor = value.Value;
+ CommonColor newHue = newColor.HueColor;
+ SetParentValue (newColor, ColorSpace.Value, Parent.Value.Opacity);
OnPropertyChanged ();
if (!newHue.Equals (oldHue)) {
- hueColor = newHue;
+ this.hueColor = newHue;
OnPropertyChanged (nameof (HueColor));
}
- if (!value.Equals (shade)) {
- shade = value;
+ if (!newColor.Equals (this.shade)) {
+ this.shade = newColor;
OnPropertyChanged (nameof (Shade));
}
if (!this.initialColor.HasValue) {
- this.initialColor = value;
+ this.initialColor = newColor;
}
}
}
}
- public CommonColor InitialColor => this.initialColor ?? (this.initialColor = Color).Value;
+ public CommonColor InitialColor => this.initialColor ?? (this.initialColor = Color.Value).Value;
- public CommonColor LastColor => this.lastColor ?? (this.lastColor = Color).Value;
+ public CommonColor LastColor => this.lastColor ?? (this.lastColor = Color.Value).Value;
public void CommitLastColor ()
{
- this.lastColor = Color;
- this.shade = Color;
- this.hueColor = Color.HueColor;
+ this.lastColor = Color.Value;
+ this.shade = Color.Value;
+ this.hueColor = Color.Value.HueColor;
var opacity = Parent.Value != null ? Parent.Value.Opacity : 1.0;
OnPropertyChanged (nameof (LastColor));
OnPropertyChanged (nameof (Shade));
OnPropertyChanged (nameof (HueColor));
- Parent.Value = new CommonSolidBrush (Color, ColorSpace, opacity);
+ SetParentValue (Color.Value, ColorSpace.Value, opacity);
}
public void CommitShade ()
@@ -89,15 +109,28 @@ namespace Xamarin.PropertyEditing.ViewModels
this.lastColor = Shade;
var opacity = Parent.Value != null ? Parent.Value.Opacity : 1.0;
OnPropertyChanged (nameof (LastColor));
- Parent.Value = new CommonSolidBrush (Shade, ColorSpace, opacity);
+ SetParentValue (Shade, ColorSpace.Value, opacity);
}
- private BrushPropertyViewModel Parent { get; }
+ public void SetParentValue (CommonColor color, string colorSpace, double opacity)
+ {
+ Parent.Value = new CommonSolidBrush (color, colorSpace, opacity);
+ // If the new value corresponds to a different color, we want to reset the Color value info,
+ // but not otherwise.
+ if (this.color != null && this.color.Value != color) {
+ this.color = null;
+ }
+ }
+
+ BrushPropertyViewModel Parent { get; }
+
+ CommonColor? hueColor;
+ CommonColor? shade;
+ CommonColor? initialColor;
+ CommonColor? lastColor;
- private CommonColor? hueColor;
- private CommonColor? shade;
- private CommonColor? initialColor;
- private CommonColor? lastColor;
+ ValueInfo<string> colorSpace;
+ ValueInfo<CommonColor> color;
private void Parent_PropertyChanged (object sender, PropertyChangedEventArgs e)
{
diff --git a/Xamarin.PropertyEditing/Xamarin.PropertyEditing.csproj b/Xamarin.PropertyEditing/Xamarin.PropertyEditing.csproj
index b2ee7d7..39c4796 100644
--- a/Xamarin.PropertyEditing/Xamarin.PropertyEditing.csproj
+++ b/Xamarin.PropertyEditing/Xamarin.PropertyEditing.csproj
@@ -66,6 +66,7 @@
<Compile Include="IAvailabilityConstraint.cs" />
<Compile Include="IClampedPropertyInfo.cs" />
<Compile Include="IColorSpaced.cs" />
+ <Compile Include="IComplexPropertyInfo.cs" />
<Compile Include="IEditorProvider.cs" />
<Compile Include="IObjectEventEditor.cs" />
<Compile Include="IEventInfo.cs" />
@@ -75,6 +76,7 @@
<Compile Include="IPropertyInfo.cs" />
<Compile Include="IResourceProvider.cs" />
<Compile Include="ISelfConstrainedPropertyInfo.cs" />
+ <Compile Include="ISubPropertyInfo.cs" />
<Compile Include="MultiAvailabilityConstraint.cs" />
<Compile Include="NotifyingObject.cs" />
<Compile Include="ObservableCollectionEx.cs" />