[XamlC] compile ThicknessTypeConverter (#603)
authorStephane Delcroix <stephane@delcroix.org>
Mon, 12 Dec 2016 09:35:42 +0000 (10:35 +0100)
committerGitHub <noreply@github.com>
Mon, 12 Dec 2016 09:35:42 +0000 (10:35 +0100)
Xamarin.Forms.Build.Tasks/CompiledConverters/ThicknessTypeConverter.cs [new file with mode: 0644]
Xamarin.Forms.Build.Tasks/Xamarin.Forms.Build.Tasks.csproj
Xamarin.Forms.Core/ThicknessTypeConverter.cs
Xamarin.Forms.Xaml.UnitTests/CompiledTypeConverter.xaml
Xamarin.Forms.Xaml.UnitTests/CompiledTypeConverter.xaml.cs

diff --git a/Xamarin.Forms.Build.Tasks/CompiledConverters/ThicknessTypeConverter.cs b/Xamarin.Forms.Build.Tasks/CompiledConverters/ThicknessTypeConverter.cs
new file mode 100644 (file)
index 0000000..e16a8b0
--- /dev/null
@@ -0,0 +1,51 @@
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Core.XamlC
+{
+       class ThicknessTypeConverter : ICompiledTypeConverter
+       {
+               public IEnumerable<Instruction> ConvertFromString(string value, ModuleDefinition module, BaseNode node)
+               {
+                       if (!string.IsNullOrEmpty(value)) {
+                               double l, t, r, b;
+                               var thickness = value.Split(',');
+                               switch (thickness.Length) {
+                               case 1:
+                                       if (double.TryParse(thickness[0], NumberStyles.Number, CultureInfo.InvariantCulture, out l))
+                                               return GenerateIL(module, l);
+                                       break;
+                               case 2:
+                                       if (double.TryParse(thickness[0], NumberStyles.Number, CultureInfo.InvariantCulture, out l) &&
+                                           double.TryParse(thickness[1], NumberStyles.Number, CultureInfo.InvariantCulture, out t))
+                                               return GenerateIL(module, l, t);
+                                       break;
+                               case 4:
+                                       if (double.TryParse(thickness[0], NumberStyles.Number, CultureInfo.InvariantCulture, out l) &&
+                                           double.TryParse(thickness[1], NumberStyles.Number, CultureInfo.InvariantCulture, out t) &&
+                                               double.TryParse(thickness[2], NumberStyles.Number, CultureInfo.InvariantCulture, out r) &&
+                                           double.TryParse(thickness[3], NumberStyles.Number, CultureInfo.InvariantCulture, out b))
+                                               return GenerateIL(module, l, t, r, b);
+                                       break;
+                               }
+                       }
+                       throw new XamlParseException($"Cannot convert \"{value}\" into {typeof(Thickness)}", node);
+               }
+
+               IEnumerable<Instruction> GenerateIL(ModuleDefinition module, params double[] args)
+               {
+                       foreach (var d in args)
+                               yield return Instruction.Create(OpCodes.Ldc_R8, d);
+                       var thicknessCtor = module.Import(typeof(Thickness)).Resolve().Methods.FirstOrDefault(md => md.IsConstructor && md.Parameters.Count == args.Length);
+                       var thicknessCtorRef = module.Import(thicknessCtor);
+                       yield return Instruction.Create(OpCodes.Newobj, thicknessCtorRef);
+               }
+       }
+       
+}
\ No newline at end of file
index 9507ea3..1ccace2 100644 (file)
     <Compile Include="XamlTask.cs" />
     <Compile Include="CompiledMarkupExtensions\ArrayExtension.cs" />
     <Compile Include="CompiledConverters\ConstraintTypeConverter.cs" />
+    <Compile Include="CompiledConverters\ThicknessTypeConverter.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <Target Name="AfterBuild">
index 5e79d25..fa60267 100644 (file)
@@ -3,6 +3,7 @@ using System.Globalization;
 
 namespace Xamarin.Forms
 {
+       [Xaml.ProvideCompiled("Xamarin.Forms.Core.XamlC.ThicknessTypeConverter")]
        public class ThicknessTypeConverter : TypeConverter
        {
                public override object ConvertFromInvariantString(string value)
@@ -29,7 +30,7 @@ namespace Xamarin.Forms
                                }
                        }
 
-                       throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Thickness)));
+                       throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(Thickness)}");
                }
        }
 }
\ No newline at end of file
index b163064..296f9ee 100644 (file)
@@ -7,5 +7,5 @@
                         BackgroundColor="Pink">
        <Label x:Name="label"
                HorizontalOptions="EndAndExpand"
-               RelativeLayout.XConstraint="2" />
-</ContentPage>
\ No newline at end of file
+               RelativeLayout.XConstraint="2" Margin="2,3"/>
+</ContentPage>
index 834a55c..1ef319a 100644 (file)
@@ -38,7 +38,8 @@ namespace Xamarin.Forms.Xaml.UnitTests
                                Assert.AreEqual(LayoutOptions.EndAndExpand, p.label.GetValue(View.HorizontalOptionsProperty));
                                var xConstraint = RelativeLayout.GetXConstraint(p.label);
                                Assert.AreEqual(2, xConstraint.Compute(null));
+                               Assert.AreEqual(new Thickness(2, 3), p.label.Margin);
                        }
                }
        }
-}
\ No newline at end of file
+}