Support density independent pixel
authorSeungkeun Lee <sngn.lee@samsung.com>
Wed, 8 Feb 2017 01:17:28 +0000 (10:17 +0900)
committerKangho Hur <kangho.hur@samsung.com>
Mon, 24 Apr 2017 04:36:54 +0000 (13:36 +0900)
 - Support Enable/Disable of this feature
 - By default, it was disabled. if you want enabling DP support feature,
   Use Forms.Init(FormsApplication application, bool useDeviceIndependentPixel) API
 - Hard-coded pixel value was changed to DP units
 - If you deal with native coordinate, use Forms.ConvertToScaledPixel / Forms.ConvertToScaledDP
 - If you convert hard-coded DP to pixels, use Forms.ConvertToPixel
 - Update font size convert formula

Change-Id: I345115551e1c37d27b8a7152af5ef847d035c9a4

16 files changed:
Xamarin.Forms.Platform.Tizen/Cells/CellRenderer.cs
Xamarin.Forms.Platform.Tizen/Cells/EntryCellRenderer.cs
Xamarin.Forms.Platform.Tizen/Cells/ImageCellRenderer.cs
Xamarin.Forms.Platform.Tizen/Cells/ViewCellRenderer.cs
Xamarin.Forms.Platform.Tizen/Extensions/DensityIndependentPixelExtensions.cs [new file with mode: 0644]
Xamarin.Forms.Platform.Tizen/Forms.cs
Xamarin.Forms.Platform.Tizen/Native/ListView.cs
Xamarin.Forms.Platform.Tizen/Native/Span.cs
Xamarin.Forms.Platform.Tizen/Renderers/ButtonRenderer.cs
Xamarin.Forms.Platform.Tizen/Renderers/LayoutRenderer.cs
Xamarin.Forms.Platform.Tizen/Renderers/ScrollViewRenderer.cs [changed mode: 0755->0644]
Xamarin.Forms.Platform.Tizen/Renderers/SearchBarRenderer.cs
Xamarin.Forms.Platform.Tizen/Renderers/VisualElementRenderer.cs
Xamarin.Forms.Platform.Tizen/TizenPlatformServices.cs
Xamarin.Forms.Platform.Tizen/Xamarin.Forms.Platform.Tizen.csproj
packaging/xamarin-forms-tizen.spec

index 096c168..e66db63 100644 (file)
@@ -1,6 +1,5 @@
 using ElmSharp;
 using System.Collections.Generic;
-using EColor = ElmSharp.Color;
 
 namespace Xamarin.Forms.Platform.Tizen
 {
@@ -58,14 +57,14 @@ namespace Xamarin.Forms.Platform.Tizen
                        return null;
                }
 
-               protected int FindCellContentHeight(Cell cell)
+               protected double FindCellContentHeight(Cell cell)
                {
                        ViewCell viewCell = cell as ViewCell;
                        if (viewCell != null)
                        {
                                var parentWidth = (cell.Parent as VisualElement).Width;
                                var view = viewCell.View;
-                               return (int)view.Measure(parentWidth, double.PositiveInfinity).Request.Height;
+                               return view.Measure(parentWidth, double.PositiveInfinity).Request.Height;
                        }
                        else
                                return -1;
index b74a6f9..5db9239 100644 (file)
@@ -8,7 +8,7 @@ namespace Xamarin.Forms.Platform.Tizen
 {
        public class EntryCellRenderer : ViewCellRenderer
        {
-               static readonly int s_defaultHeight = 120;
+               static readonly double s_defaultHeight = 65;
                static readonly EColor s_defaultLabelColor = EColor.Black;
 
                readonly Dictionary<EvasObject, VisualElement> _cacheCandidate = new Dictionary<EvasObject, VisualElement>();
@@ -22,8 +22,8 @@ namespace Xamarin.Forms.Platform.Tizen
                        if (part == MainContentPart)
                        {
                                var entryCell = cell as EntryCell;
-                               int height = (int)entryCell.RenderHeight;
-                               height = height > 0 ? height : s_defaultHeight;
+                               int pixelHeight = Forms.ConvertToScaledPixel(entryCell.RenderHeight);
+                               pixelHeight = pixelHeight > 0 ? pixelHeight : Forms.ConvertToPixel(s_defaultHeight);
 
                                var label = new Label()
                                {
@@ -56,10 +56,10 @@ namespace Xamarin.Forms.Platform.Tizen
                                };
                                layout.Parent = cell.Parent;
                                layout.BindingContext = entryCell;
-                               layout.MinimumHeightRequest = height;
+                               layout.MinimumHeightRequest = Forms.ConvertToScaledDP(pixelHeight);
 
                                var nativeView = Platform.GetOrCreateRenderer(layout).NativeView;
-                               nativeView.MinimumHeight = height;
+                               nativeView.MinimumHeight = pixelHeight;
                                _cacheCandidate[nativeView] = layout;
                                nativeView.Deleted += (sender, e) =>
                                {
@@ -79,8 +79,8 @@ namespace Xamarin.Forms.Platform.Tizen
 
                        var layout = _cacheCandidate[old];
                        layout.BindingContext = cell;
-                       int height = (int)cell.RenderHeight;
-                       height = height > 0 ? height : s_defaultHeight;
+                       int height = Forms.ConvertToScaledPixel(cell.RenderHeight);
+                       height = height > 0 ? height : Forms.ConvertToPixel(s_defaultHeight);
                        old.MinimumHeight = height;
                        return old;
                }
index 7bee5c8..2bf64b4 100644 (file)
@@ -5,7 +5,7 @@ namespace Xamarin.Forms.Platform.Tizen
 {
        public class ImageCellRenderer : TextCellRenderer
        {
-               const int _defaultHeight = 100;
+               const int _defaultHeight = 55;
                Dictionary<EvasObject, Native.Image> _realizedViews = new Dictionary<EvasObject, Native.Image>();
 
                public ImageCellRenderer() : this("type1")
@@ -21,16 +21,16 @@ namespace Xamarin.Forms.Platform.Tizen
                        if (part == ImagePart)
                        {
                                var imgCell = cell as ImageCell;
-                               var size = imgCell.RenderHeight;
-                               if (size <= 0)
+                               int pixelSize = Forms.ConvertToScaledPixel(imgCell.RenderHeight);
+                               if (pixelSize <= 0)
                                {
-                                       size = _defaultHeight;
+                                       pixelSize = Forms.ConvertToPixel(_defaultHeight);
                                }
 
                                var image = new Native.Image(Forms.Context.MainWindow)
                                {
-                                       MinimumWidth = (int)size,
-                                       MinimumHeight = (int)size
+                                       MinimumWidth = pixelSize,
+                                       MinimumHeight = pixelSize
                                };
                                image.SetAlignment(-1.0, -1.0); // fill
                                image.SetWeight(1.0, 1.0); // expand
index bb17ec8..38062c7 100644 (file)
@@ -45,10 +45,10 @@ namespace Xamarin.Forms.Platform.Tizen
 
                                Platform.GetRenderer(viewCell.View)?.Dispose();
                                var renderer = Platform.GetOrCreateRenderer(viewCell.View);
-                               int height = (int)viewCell.RenderHeight;
+                               double height = viewCell.RenderHeight;
                                height = height > 0 ? height : FindCellContentHeight(viewCell);
 
-                               renderer.NativeView.MinimumHeight = height;
+                               renderer.NativeView.MinimumHeight = Forms.ConvertToScaledPixel(height);
                                return renderer.NativeView;
                        }
                        return null;
@@ -71,9 +71,9 @@ namespace Xamarin.Forms.Platform.Tizen
                        duplicatedCell.Parent = listView;
 
                        var renderer = Platform.GetOrCreateRenderer(duplicatedCell.View);
-                       int height = (int)duplicatedCell.RenderHeight;
+                       double height = duplicatedCell.RenderHeight;
                        height = height > 0 ? height : FindCellContentHeight(duplicatedCell);
-                       renderer.NativeView.MinimumHeight = height;
+                       renderer.NativeView.MinimumHeight = Forms.ConvertToScaledPixel(height);
 
                        _cacheCandidate[renderer.NativeView] = duplicatedCell;
                        renderer.NativeView.Deleted += (sender, e) =>
diff --git a/Xamarin.Forms.Platform.Tizen/Extensions/DensityIndependentPixelExtensions.cs b/Xamarin.Forms.Platform.Tizen/Extensions/DensityIndependentPixelExtensions.cs
new file mode 100644 (file)
index 0000000..96a49d0
--- /dev/null
@@ -0,0 +1,31 @@
+using ERect = ElmSharp.Rect;
+using ESize = ElmSharp.Size;
+
+namespace Xamarin.Forms.Platform.Tizen
+{
+       /// <summary>
+       /// Extension class, provides DIP convert functionalities
+       /// </summary>
+       public static class DensityIndependentPixelExtensions
+       {
+               public static Rectangle ToDP(this ERect rect)
+               {
+                       return new Rectangle(Forms.ConvertToScaledDP(rect.X), Forms.ConvertToScaledDP(rect.Y), Forms.ConvertToScaledDP(rect.Width), Forms.ConvertToScaledDP(rect.Height));
+               }
+
+               public static ERect ToPixel(this Rectangle rect)
+               {
+                       return new ERect(Forms.ConvertToScaledPixel(rect.X), Forms.ConvertToScaledPixel(rect.Y), Forms.ConvertToScaledPixel(rect.Width), Forms.ConvertToScaledPixel(rect.Height));
+               }
+
+               public static Size ToDP(this ESize size)
+               {
+                       return new Size(Forms.ConvertToScaledDP(size.Width), Forms.ConvertToScaledDP(size.Height));
+               }
+
+               public static ESize ToPixel(this Size size)
+               {
+                       return new ESize(Forms.ConvertToScaledPixel(size.Width), Forms.ConvertToScaledPixel(size.Height));
+               }
+       }
+}
index 892faf5..1a2d7bd 100644 (file)
@@ -17,6 +17,13 @@ namespace Xamarin.Forms.Platform.Tizen
                        TSystemInfo.TryGetValue<int>("http://tizen.org/feature/screen.dpi", out dpi);
                        return dpi;
                });
+
+               static Lazy<double> s_elmScale = new Lazy<double>(() =>
+               {
+                       // 72.0 is from EFL which is using fixed DPI value (72.0) to determine font size internally. Thus, we are restoring the size by deviding the DPI by 72.0 here.
+                       return s_dpi.Value / 72.0 / Elementary.GetScale();
+               });
+
                class TizenDeviceInfo : DeviceInfo
                {
                        readonly Size pixelScreenSize;
@@ -68,6 +75,11 @@ namespace Xamarin.Forms.Platform.Tizen
                                TSystemInfo.TryGetValue("http://tizen.org/feature/screen.height", out height);
 
                                scalingFactor = 1.0;  // scaling is disabled, we're using pixels as Xamarin's geometry units
+                               if (_useDeviceIndependentPixel)
+                               {
+                                       scalingFactor = s_dpi.Value / 160.0;
+                               }
+
                                pixelScreenSize = new Size(width, height);
                                scaledScreenSize = new Size(width / scalingFactor, height / scalingFactor);
 
@@ -76,6 +88,8 @@ namespace Xamarin.Forms.Platform.Tizen
                        }
                }
 
+               static bool _useDeviceIndependentPixel = false;
+
                public static event EventHandler<ViewInitializedEventArgs> ViewInitialized;
 
                public static FormsApplication Context
@@ -116,6 +130,12 @@ namespace Xamarin.Forms.Platform.Tizen
 
                public static void Init(FormsApplication application)
                {
+                       Init(application, false);
+               }
+
+               public static void Init(FormsApplication application, bool useDeviceIndependentPixel)
+               {
+                       _useDeviceIndependentPixel = useDeviceIndependentPixel;
                        SetupInit(application);
                }
 
@@ -186,7 +206,7 @@ namespace Xamarin.Forms.Platform.Tizen
                        {
                                Device.Idiom = TargetIdiom.TV;
                        }
-                       else if ( profile == "desktop")
+                       else if (profile == "desktop")
                        {
                                Device.Idiom = TargetIdiom.Desktop;
                        }
@@ -210,10 +230,78 @@ namespace Xamarin.Forms.Platform.Tizen
                        return Color.Black;
                }
 
+               /// <summary>
+               /// Converts the dp into pixel considering current DPI value.
+               /// </summary>
+               /// <remarks>
+               /// Use this API if you want to get pixel size without scaling factor.
+               /// </remarks>
+               /// <param name="dp"></param>
+               /// <returns></returns>
                internal static int ConvertToPixel(double dp)
                {
                        return (int)Math.Round(dp * s_dpi.Value / 160.0);
                }
+
+               /// <summary>
+               /// Converts the dp into pixel by using scaling factor.
+               /// </summary>
+               /// <remarks>
+               /// Use this API if you want to get pixel size from dp by using scaling factor. 
+               /// If the scaling factor is 1.0 by user setting, the same value is returned. This is mean that user doesn't want to pixel independent metric.
+               /// </remarks>
+               /// <param name="dp"></param>
+               /// <returns></returns>
+               internal static int ConvertToScaledPixel(double dp)
+               {
+                       return (int)Math.Round(dp * Device.Info.ScalingFactor);
+               }
+
+               /// <summary>
+               /// Converts the pixel into dp value by using scaling factor.
+               /// </summary>
+               /// <remarks>
+               /// If the scaling factor is 1.0 by user setting, the same value is returned. This is mean that user doesn't want to pixel independent metric.
+               /// </remarks>
+               /// <param name="pixel"></param>
+               /// <returns></returns>
+               internal static double ConvertToScaledDP(int pixel)
+               {
+                       return pixel / Device.Info.ScalingFactor;
+               }
+
+               /// <summary>
+               /// Converts the pixel into dp value by using scaling factor.
+               /// </summary>
+               /// <remarks>
+               /// If the scaling factor is 1.0 by user setting, the same value is returned. This is mean that user doesn't want to pixel independent metric.
+               /// </remarks>
+               /// <param name="pixel"></param>
+               /// <returns></returns>
+               internal static double ConvertToScaledDP(double pixel)
+               {
+                       return pixel / Device.Info.ScalingFactor;
+               }
+
+               /// <summary>
+               /// Converts the sp into EFL's font size metric (EFL point).
+               /// </summary>
+               /// <param name="sp"></param>
+               /// <returns></returns>
+               internal static int ConvertToEflFontPoint(double sp)
+               {
+                       return (int)Math.Round(sp * s_elmScale.Value);
+               }
+
+               /// <summary>
+               /// Convert the EFL's point into sp.
+               /// </summary>
+               /// <param name="eflPt"></param>
+               /// <returns></returns>
+               internal static double ConvertToDPFont(int eflPt)
+               {
+                       return eflPt / s_elmScale.Value;
+               }
        }
 
        class TizenExpressionSearch : ExpressionVisitor, IExpressionSearch
index a94282a..7947c3e 100644 (file)
@@ -587,11 +587,11 @@ namespace Xamarin.Forms.Platform.Tizen.Native
                                                if (element.MinimumHeightRequest == -1)
                                                {
                                                        SizeRequest request = element.Measure(double.PositiveInfinity, double.PositiveInfinity);
-                                                       renderer.NativeView.MinimumHeight = (int)request.Request.Height;
+                                                       renderer.NativeView.MinimumHeight = Forms.ConvertToScaledPixel(request.Request.Height);
                                                }
                                                else
                                                {
-                                                       renderer.NativeView.MinimumHeight = (int)element.MinimumHeightRequest;
+                                                       renderer.NativeView.MinimumHeight = Forms.ConvertToScaledPixel(element.MinimumHeightRequest);
                                                }
 
                                                return renderer.NativeView;
index 8120105..99fe008 100644 (file)
@@ -183,7 +183,7 @@ namespace Xamarin.Forms.Platform.Tizen.Native
 
                        if (FontSize != -1)
                        {
-                               _formattingString.AppendFormat("font_size={0} ", Forms.ConvertToPixel(FontSize));
+                               _formattingString.AppendFormat("font_size={0} ", Forms.ConvertToEflFontPoint(FontSize));
                        }
 
                        if ((FontAttributes & FontAttributes.Bold) != 0)
index 39f26b4..456bb0d 100644 (file)
@@ -1,5 +1,6 @@
 using System;
 using EColor = ElmSharp.Color;
+using ESize = ElmSharp.Size;
 using Specific = Xamarin.Forms.PlatformConfiguration.TizenSpecific.VisualElement;
 
 namespace Xamarin.Forms.Platform.Tizen
@@ -46,7 +47,7 @@ namespace Xamarin.Forms.Platform.Tizen
 
                protected override Size MinimumSize()
                {
-                       return new Size(Control.MinimumWidth, Control.MinimumHeight);
+                       return new ESize(Control.MinimumWidth, Control.MinimumHeight).ToDP();
                }
 
                void ButtonClickedHandler(object sender, EventArgs e)
index 61421c7..99e422e 100644 (file)
@@ -23,8 +23,8 @@ namespace Xamarin.Forms.Platform.Tizen
                        if (scrollView != null)
                        {
                                Size size = scrollView.ContentSize;
-                               Control.MinimumWidth = ToNativeDimension(Math.Max(size.Width, scrollView.Content.Width));
-                               Control.MinimumHeight = ToNativeDimension(Math.Max(size.Height, scrollView.Content.Height));
+                               Control.MinimumWidth = Forms.ConvertToScaledPixel(Math.Max(size.Width, scrollView.Content.Width));
+                               Control.MinimumHeight = Forms.ConvertToScaledPixel(Math.Max(size.Height, scrollView.Content.Height));
                        }
 
                        base.UpdateLayout();
old mode 100755 (executable)
new mode 100644 (file)
index 1119538..f35a275
@@ -132,7 +132,7 @@ namespace Xamarin.Forms.Platform.Tizen
                                y = itemPosition.Y;
                        }
 
-                       Rect region = new Rect(ToNativeDimension(x), ToNativeDimension(y), ToNativeDimension(Element.Width), ToNativeDimension(Element.Height));
+                       Rect region = new Rectangle(x, y, Element.Width, Element.Height).ToPixel();
                        Control.ScrollTo(region, e.ShouldAnimate);
                }
        }
index 798a049..3c9734d 100644 (file)
@@ -58,7 +58,7 @@ namespace Xamarin.Forms.Platform.Tizen
 
                protected override Size MinimumSize()
                {
-                       return new Size(250, 120);
+                       return new Size(136, 65);
                }
 
                /// <summary>
index 4bde705..37a5faf 100644 (file)
@@ -9,7 +9,6 @@ using ERect = ElmSharp.Rect;
 using ERectangle = ElmSharp.Rectangle;
 using Specific = Xamarin.Forms.PlatformConfiguration.TizenSpecific.VisualElement;
 
-
 namespace Xamarin.Forms.Platform.Tizen
 {
        /// <summary>
@@ -138,21 +137,26 @@ namespace Xamarin.Forms.Platform.Tizen
                        }
                        else
                        {
-                               int availableWidth = ToNativeDimension(widthConstraint);
-                               int availableHeight = ToNativeDimension(heightConstraint);
-                               ESize measured;
+                               int availableWidth = Forms.ConvertToScaledPixel(widthConstraint);
+                               int availableHeight = Forms.ConvertToScaledPixel(heightConstraint);
+
+                               if (availableWidth < 0)
+                                       availableWidth = int.MaxValue;
+                               if (availableHeight < 0)
+                                       availableHeight = int.MaxValue;
 
+                               Size measured;
                                var nativeViewMeasurable = NativeView as Native.IMeasurable;
                                if (nativeViewMeasurable != null)
                                {
-                                       measured = nativeViewMeasurable.Measure(availableWidth, availableHeight);
+                                       measured = nativeViewMeasurable.Measure(availableWidth, availableHeight).ToDP();
                                }
                                else
                                {
-                                       measured = Measure(availableWidth, availableHeight);
+                                       measured = Measure(availableWidth, availableHeight).ToDP();
                                }
 
-                               return new SizeRequest(new Size(measured.Width, measured.Height), MinimumSize());
+                               return new SizeRequest(measured, MinimumSize());
                        }
                }
 
@@ -203,7 +207,7 @@ namespace Xamarin.Forms.Platform.Tizen
                {
                        var x = ComputeAbsoluteX(Element);
                        var y = ComputeAbsoluteY(Element);
-                       NativeView.Geometry = new ERect(ToNativeDimension(x), ToNativeDimension(y), ToNativeDimension(Element.Width), ToNativeDimension(Element.Height));
+                       NativeView.Geometry = new Rectangle(x, y, Element.Width, Element.Height).ToPixel();
                        ApplyTransformation();
                        UpdateOpacityLayer();
                }
@@ -545,7 +549,8 @@ namespace Xamarin.Forms.Platform.Tizen
                protected void DoLayout(Native.LayoutEventArgs e)
                {
                        Settings.StartIgnoringBatchCommitted();
-                       Element.Layout(new Rectangle(Element.X, Element.Y, e.Width, e.Height));
+
+                       Element.Layout(new Rectangle(Element.X, Element.Y, Forms.ConvertToScaledDP(e.Width), Forms.ConvertToScaledDP(e.Height)));
                        if (e.HasChanged)
                        {
                                UpdateLayout();
@@ -579,24 +584,14 @@ namespace Xamarin.Forms.Platform.Tizen
                        }
                }
 
-               /// <summary>
-               /// Converts provided value to native dimension.
-               /// </summary>
-               /// <param name="v">value to be converted.</param>
-               /// <returns>converted value</returns>
-               protected static int ToNativeDimension(double v)
-               {
-                       return (int)Math.Round(v);
-               }
-
                static double ComputeAbsoluteX(VisualElement e)
                {
-                       return e.X + (e.RealParent is VisualElement ? Platform.GetRenderer(e.RealParent).NativeView.Geometry.X : 0.0);
+                       return e.X + (e.RealParent is VisualElement ? Forms.ConvertToScaledDP(Platform.GetRenderer(e.RealParent).NativeView.Geometry.X) : 0.0);
                }
 
                static double ComputeAbsoluteY(VisualElement e)
                {
-                       return e.Y + (e.RealParent is VisualElement ? Platform.GetRenderer(e.RealParent).NativeView.Geometry.Y : 0.0);
+                       return e.Y + (e.RealParent is VisualElement ? Forms.ConvertToScaledDP(Platform.GetRenderer(e.RealParent).NativeView.Geometry.Y) : 0.0);
                }
 
                /// <summary>
@@ -830,8 +825,8 @@ namespace Xamarin.Forms.Platform.Tizen
 
                void ApplyTranslation(EvasMap map, ERect geometry, ref bool changed)
                {
-                       var shiftX = ToNativeDimension(Element.TranslationX);
-                       var shiftY = ToNativeDimension(Element.TranslationY);
+                       var shiftX = Forms.ConvertToScaledPixel(Element.TranslationX);
+                       var shiftY = Forms.ConvertToScaledPixel(Element.TranslationY);
 
                        // apply translation, i.e. move/shift the object a little
                        if (shiftX != 0 || shiftY != 0)
index f3a72d0..a34c2fa 100644 (file)
@@ -50,15 +50,15 @@ namespace Xamarin.Forms.Platform.Tizen
 
                public double GetNamedSize(NamedSize size, Type targetElementType, bool useOldSizes)
                {
-                       double baseSize = 10;
-                       double baseSizeSpan = 2;
+                       double baseSize = Forms.ConvertToDPFont(19);
+                       double baseSizeSpan = 3;
 
                        // In case of TV profile The base named size sholud be lager than mobile profile
-                       if (Device.Idiom == TargetIdiom.TV)
+                       if (Device.Idiom != TargetIdiom.Phone)
                        {
                                // TODO: These valuse should be updated when TV profile UX guideline released.
-                               baseSize = 60;
-                               baseSizeSpan = 5;
+                               baseSize = 50;
+                               baseSizeSpan = 12;
                        }
 
                        switch (size)
index 0096bc4..c51c4e7 100644 (file)
@@ -51,6 +51,7 @@
     <Compile Include="Extensions\PlatformConfigurationExtensions.cs" />
     <Compile Include="Extensions\ColorExtensions.cs" />
     <Compile Include="Extensions\KeyboardExtensions.cs" />
+    <Compile Include="Extensions\DensityIndependentPixelExtensions.cs" />
     <Compile Include="Extensions\LayoutExtensions.cs" />
     <Compile Include="Extensions\NativeBindingExtensions.cs" />
     <Compile Include="Extensions\ScrollToPositionExtensions.cs" />
index d718bf3..a8ade35 100644 (file)
@@ -1,7 +1,7 @@
 %define XF_VERSION 2.3.4
 
 # Increase this XF_TIZEN_VERSION when any public APIs of Xamarin.Forms.Platform.Tizen are changed.
-%define XF_TIZEN_VERSION r192-001
+%define XF_TIZEN_VERSION r192-002
 
 Name: xamarin-forms-tizen
 Summary: Xamarin.Forms for Tizen platform