Multi style classes (#134)
authorStephane Delcroix <stephane@delcroix.org>
Mon, 25 Apr 2016 22:03:33 +0000 (00:03 +0200)
committerSamantha Houts <samantha@teamredwall.com>
Mon, 25 Apr 2016 22:03:33 +0000 (15:03 -0700)
* [C] StyleClass is IList<string>

* fix docs

* this might be required

Xamarin.Forms.Core.UnitTests/StyleTests.cs
Xamarin.Forms.Core/ListStringTypeConverter.cs [new file with mode: 0644]
Xamarin.Forms.Core/MergedStyle.cs
Xamarin.Forms.Core/VisualElement.cs
Xamarin.Forms.Core/Xamarin.Forms.Core.csproj
docs/Xamarin.Forms.Core/Xamarin.Forms/ListStringTypeConverter.xml [new file with mode: 0644]
docs/Xamarin.Forms.Core/Xamarin.Forms/VisualElement.xml
docs/Xamarin.Forms.Core/index.xml

index be1c799..d6927e5 100644 (file)
@@ -7,6 +7,13 @@ namespace Xamarin.Forms.Core.UnitTests
        [TestFixture]
        public class StyleTests : BaseTestFixture
        {
+               [SetUp]
+               public void Setup ()
+               {
+                       base.Setup ();
+                       Device.PlatformServices = new MockPlatformServices ();
+               }
+
                [Test]
                public void ApplyUnapplyStyle ()
                {
@@ -470,7 +477,7 @@ namespace Xamarin.Forms.Core.UnitTests
                        var view = new ContentView {
                                Resources = new ResourceDictionary { classstyle },
                                Content = new Label { 
-                                       StyleClass = "fooClass",
+                                       StyleClass = new [] {"fooClass"},
                                        Style = style
                                }
                        };
@@ -545,17 +552,17 @@ namespace Xamarin.Forms.Core.UnitTests
 
 
                        var button = new Button {
-                               StyleClass = "pink",
+                               StyleClass = new [] {"pink"},
                        };
                        var myButton = new MyButton {
-                               StyleClass = "pink",
+                               StyleClass = new [] {"pink"},
                        };
 
                        var label = new Label {
-                               StyleClass = "pink"
+                               StyleClass = new [] {"pink"},
                        };
                        var myLabel = new MyLabel {
-                               StyleClass = "pink"
+                               StyleClass = new [] {"pink"},
                        };
 
 
@@ -601,10 +608,10 @@ namespace Xamarin.Forms.Core.UnitTests
                        };
 
                        var button = new Button {
-                               StyleClass = "pink",
+                               StyleClass = new [] {"pink"},
                        };
                        var label = new Label {
-                               StyleClass = "pink"
+                               StyleClass = new [] {"pink"},
                        };
 
                        var cv = new ContentView {
@@ -644,10 +651,10 @@ namespace Xamarin.Forms.Core.UnitTests
                        };
 
                        var button = new Button {
-                               StyleClass = "pink",
+                               StyleClass = new [] {"pink"},
                        };
                        var label = new Label {
-                               StyleClass = "pink"
+                               StyleClass = new [] {"pink"},
                        };
 
                        var cv = new ContentView {
@@ -666,5 +673,35 @@ namespace Xamarin.Forms.Core.UnitTests
                        Assert.AreEqual (Color.Pink, label.BackgroundColor);
                        Assert.AreEqual (Color.Default, label.TextColor);
                }
+
+               [Test]
+               public void MultipleStyleClassAreApplied ()
+               {
+                       var pinkStyle = new Style (typeof (Button)) {
+                               Setters = {
+                                       new Setter { Property = Button.TextColorProperty, Value = Color.Pink },
+                               },
+                               Class = "pink",
+                               ApplyToDerivedTypes = true,
+                       };
+                       var bigStyle = new Style (typeof (Button)) {
+                               Setters = {
+                                       new Setter { Property = Button.FontSizeProperty, Value = 20 },
+                               },
+                               Class = "big",
+                               ApplyToDerivedTypes = true,
+                       };
+                       var button = new Button {
+                               StyleClass = new [] {"pink", "big"},
+                       };
+
+                       new ContentView {
+                               Resources = new ResourceDictionary { pinkStyle, bigStyle },
+                               Content = button
+                       };
+
+                       Assert.AreEqual (Color.Pink, button.TextColor);
+                       Assert.AreEqual (20d, button.FontSize);
+               }
        }
 }
\ No newline at end of file
diff --git a/Xamarin.Forms.Core/ListStringTypeConverter.cs b/Xamarin.Forms.Core/ListStringTypeConverter.cs
new file mode 100644 (file)
index 0000000..647f014
--- /dev/null
@@ -0,0 +1,16 @@
+using System;
+using System.Linq;
+
+namespace Xamarin.Forms
+{
+       public class ListStringTypeConverter : TypeConverter
+       {
+               public override object ConvertFromInvariantString(string value)
+               {
+                       if (value == null)
+                               return null;
+                       
+                       return value.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).ToList();
+               }
+       }
+}
\ No newline at end of file
index 9f9c68b..59a1dea 100644 (file)
@@ -13,18 +13,17 @@ namespace Xamarin.Forms
                        ////The last one (typeof(Element)) is a safety guard as we might be creating VisualElement directly in internal code
                        static readonly IList<Type> s_stopAtTypes = new List<Type> { typeof(View), typeof(Layout<>), typeof(VisualElement), typeof(Element) };
 
-                       readonly BindableProperty _classStyleProperty = BindableProperty.Create("ClassStyle", typeof(IList<Style>), typeof(VisualElement), default(IList<Style>),
-                               propertyChanged: (bindable, oldvalue, newvalue) => ((VisualElement)bindable)._mergedStyle.OnClassStyleChanged());
+                       IList<BindableProperty> _classStyleProperties;
 
                        readonly List<BindableProperty> _implicitStyles = new List<BindableProperty>();
 
-                       IStyle _classStyle;
+                       IList<Style> _classStyles;
 
                        IStyle _implicitStyle;
 
                        IStyle _style;
 
-                       string _styleClass;
+                       IList<string> _styleClass;
 
                        public MergedStyle(Type targetType, BindableObject target)
                        {
@@ -37,46 +36,55 @@ namespace Xamarin.Forms
                        public IStyle Style
                        {
                                get { return _style; }
-                               set { SetStyle(ImplicitStyle, ClassStyle, value); }
+                               set { SetStyle(ImplicitStyle, ClassStyles, value); }
                        }
 
-                       public string StyleClass
+                       public IList<string> StyleClass
                        {
                                get { return _styleClass; }
                                set
                                {
-                                       string val = string.IsNullOrWhiteSpace(value) ? null : value.Trim();
-                                       if (_styleClass == val)
+                                       if (_styleClass == value)
                                                return;
 
-                                       if (_styleClass != null)
-                                               Target.RemoveDynamicResource(_classStyleProperty);
+                                       if (_styleClass != null && _classStyles != null)
+                                               foreach (var classStyleProperty in _classStyleProperties)
+                                                       Target.RemoveDynamicResource(classStyleProperty);
 
-                                       _styleClass = val;
+                                       _styleClass = value;
 
-                                       if (_styleClass != null)
-                                               Target.SetDynamicResource(_classStyleProperty, Forms.Style.StyleClassPrefix + _styleClass);
+                                       if (_styleClass != null) {
+                                               _classStyleProperties = new List<BindableProperty> ();
+                                               foreach (var styleClass in _styleClass) {
+                                                       var classStyleProperty = BindableProperty.Create ("ClassStyle", typeof(IList<Style>), typeof(VisualElement), default(IList<Style>),
+                                                               propertyChanged: (bindable, oldvalue, newvalue) => ((VisualElement)bindable)._mergedStyle.OnClassStyleChanged());
+                                                       _classStyleProperties.Add (classStyleProperty);
+                                                       Target.OnSetDynamicResource (classStyleProperty, Forms.Style.StyleClassPrefix + styleClass);
+                                               }
+                                       }
                                }
                        }
 
                        public BindableObject Target { get; }
 
-                       IStyle ClassStyle
+                       IList<Style> ClassStyles
                        {
-                               get { return _classStyle; }
+                               get { return _classStyles; }
                                set { SetStyle(ImplicitStyle, value, Style); }
                        }
 
                        IStyle ImplicitStyle
                        {
                                get { return _implicitStyle; }
-                               set { SetStyle(value, ClassStyle, Style); }
+                               set { SetStyle(value, ClassStyles, Style); }
                        }
 
                        public void Apply(BindableObject bindable)
                        {
                                ImplicitStyle?.Apply(bindable);
-                               ClassStyle?.Apply(bindable);
+                               if (ClassStyles != null)
+                                       foreach (var classStyle in ClassStyles)
+                                               ((IStyle)classStyle)?.Apply(bindable);
                                Style?.Apply(bindable);
                        }
 
@@ -85,19 +93,15 @@ namespace Xamarin.Forms
                        public void UnApply(BindableObject bindable)
                        {
                                Style?.UnApply(bindable);
-                               ClassStyle?.UnApply(bindable);
+                               if (ClassStyles != null)
+                                       foreach (var classStyle in ClassStyles)
+                                               ((IStyle)classStyle)?.UnApply(bindable);
                                ImplicitStyle?.UnApply(bindable);
                        }
 
                        void OnClassStyleChanged()
                        {
-                               var classStyles = Target.GetValue(_classStyleProperty) as IList<Style>;
-                               if (classStyles == null)
-                                       ClassStyle = null;
-                               else
-                               {
-                                       ClassStyle = classStyles.FirstOrDefault(s => s.CanBeAppliedTo(TargetType));
-                               }
+                               ClassStyles = _classStyleProperties.Select (p => (Target.GetValue (p) as IList<Style>)?.FirstOrDefault (s => s.CanBeAppliedTo (TargetType))).ToList ();
                        }
 
                        void OnImplicitStyleChanged()
@@ -133,27 +137,29 @@ namespace Xamarin.Forms
                                }
                        }
 
-                       void SetStyle(IStyle implicitStyle, IStyle classStyle, IStyle style)
+                       void SetStyle(IStyle implicitStyle, IList<Style> classStyles, IStyle style)
                        {
-                               bool shouldReApplyStyle = implicitStyle != ImplicitStyle || classStyle != ClassStyle || Style != style;
-                               bool shouldReApplyClassStyle = implicitStyle != ImplicitStyle || classStyle != ClassStyle;
+                               bool shouldReApplyStyle = implicitStyle != ImplicitStyle || classStyles != ClassStyles || Style != style;
+                               bool shouldReApplyClassStyle = implicitStyle != ImplicitStyle || classStyles != ClassStyles;
                                bool shouldReApplyImplicitStyle = implicitStyle != ImplicitStyle && (Style as Style == null || ((Style)Style).CanCascade);
 
                                if (shouldReApplyStyle)
                                        Style?.UnApply(Target);
-                               if (shouldReApplyClassStyle)
-                                       ClassStyle?.UnApply(Target);
+                               if (shouldReApplyClassStyle && ClassStyles != null)
+                                       foreach (var classStyle in ClassStyles)
+                                               ((IStyle)classStyle)?.UnApply(Target);
                                if (shouldReApplyImplicitStyle)
                                        ImplicitStyle?.UnApply(Target);
 
                                _implicitStyle = implicitStyle;
-                               _classStyle = classStyle;
+                               _classStyles = classStyles;
                                _style = style;
 
                                if (shouldReApplyImplicitStyle)
                                        ImplicitStyle?.Apply(Target);
-                               if (shouldReApplyClassStyle)
-                                       ClassStyle?.Apply(Target);
+                               if (shouldReApplyClassStyle && ClassStyles != null)
+                                       foreach (var classStyle in ClassStyles)
+                                               ((IStyle)classStyle)?.Apply(Target);
                                if (shouldReApplyStyle)
                                        Style?.Apply(Target);
                        }
index fa53386..e93dea6 100644 (file)
@@ -247,7 +247,8 @@ namespace Xamarin.Forms
                        set { SetValue(StyleProperty, value); }
                }
 
-               public string StyleClass
+               [TypeConverter (typeof(ListStringTypeConverter))]
+               public IList<string> StyleClass
                {
                        get { return _mergedStyle.StyleClass; }
                        set { _mergedStyle.StyleClass = value; }
index c9f7a5b..e72a2be 100644 (file)
     <Compile Include="AppLinkEntry.cs" />
     <Compile Include="IApplicationController.cs" />
     <Compile Include="IAppIndexingProvider.cs" />
+    <Compile Include="ListStringTypeConverter.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
   <ItemGroup>
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/ListStringTypeConverter.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/ListStringTypeConverter.xml
new file mode 100644 (file)
index 0000000..cfe2cb9
--- /dev/null
@@ -0,0 +1,51 @@
+<Type Name="ListStringTypeConverter" FullName="Xamarin.Forms.ListStringTypeConverter">
+  <TypeSignature Language="C#" Value="public class ListStringTypeConverter : Xamarin.Forms.TypeConverter" />
+  <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit ListStringTypeConverter extends Xamarin.Forms.TypeConverter" />
+  <AssemblyInfo>
+    <AssemblyName>Xamarin.Forms.Core</AssemblyName>
+    <AssemblyVersion>2.0.0.0</AssemblyVersion>
+  </AssemblyInfo>
+  <Base>
+    <BaseTypeName>Xamarin.Forms.TypeConverter</BaseTypeName>
+  </Base>
+  <Interfaces />
+  <Docs>
+    <summary>To be added.</summary>
+    <remarks>To be added.</remarks>
+  </Docs>
+  <Members>
+    <Member MemberName=".ctor">
+      <MemberSignature Language="C#" Value="public ListStringTypeConverter ();" />
+      <MemberSignature Language="ILAsm" Value=".method public hidebysig specialname rtspecialname instance void .ctor() cil managed" />
+      <MemberType>Constructor</MemberType>
+      <AssemblyInfo>
+        <AssemblyVersion>2.0.0.0</AssemblyVersion>
+      </AssemblyInfo>
+      <Parameters />
+      <Docs>
+        <summary>To be added.</summary>
+        <remarks>To be added.</remarks>
+      </Docs>
+    </Member>
+    <Member MemberName="ConvertFromInvariantString">
+      <MemberSignature Language="C#" Value="public override object ConvertFromInvariantString (string value);" />
+      <MemberSignature Language="ILAsm" Value=".method public hidebysig virtual instance object ConvertFromInvariantString(string value) cil managed" />
+      <MemberType>Method</MemberType>
+      <AssemblyInfo>
+        <AssemblyVersion>2.0.0.0</AssemblyVersion>
+      </AssemblyInfo>
+      <ReturnValue>
+        <ReturnType>System.Object</ReturnType>
+      </ReturnValue>
+      <Parameters>
+        <Parameter Name="value" Type="System.String" />
+      </Parameters>
+      <Docs>
+        <param name="value">To be added.</param>
+        <summary>To be added.</summary>
+        <returns>To be added.</returns>
+        <remarks>To be added.</remarks>
+      </Docs>
+    </Member>
+  </Members>
+</Type>
index b4ee09d..bd8e615 100644 (file)
       </Docs>
     </Member>
     <Member MemberName="StyleClass">
-      <MemberSignature Language="C#" Value="public string StyleClass { get; set; }" />
-      <MemberSignature Language="ILAsm" Value=".property instance string StyleClass" />
+      <MemberSignature Language="C#" Value="public System.Collections.Generic.IList&lt;string&gt; StyleClass { get; set; }" />
+      <MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IList`1&lt;string&gt; StyleClass" />
       <MemberType>Property</MemberType>
       <AssemblyInfo>
         <AssemblyVersion>2.0.0.0</AssemblyVersion>
       </AssemblyInfo>
+      <Attributes>
+        <Attribute>
+          <AttributeName>Xamarin.Forms.TypeConverter(typeof(Xamarin.Forms.ListStringTypeConverter))</AttributeName>
+        </Attribute>
+      </Attributes>
       <ReturnValue>
-        <ReturnType>System.String</ReturnType>
+        <ReturnType>System.Collections.Generic.IList&lt;System.String&gt;</ReturnType>
       </ReturnValue>
       <Docs>
         <summary>To be added.</summary>
index 70d5da7..077b8f2 100644 (file)
       <Type Name="LayoutOptions" Kind="Structure" />
       <Type Name="LayoutOptionsConverter" Kind="Class" />
       <Type Name="LineBreakMode" Kind="Enumeration" />
+      <Type Name="ListStringTypeConverter" Kind="Class" />
       <Type Name="ListView" Kind="Class" />
       <Type Name="ListViewCachingStrategy" Kind="Enumeration" />
       <Type Name="MasterBehavior" Kind="Enumeration" />