[Win] Labels will now wrap when inside horizontally infinite layouts (#639)
authorSamantha Houts <samantha@teamredwall.com>
Tue, 14 Mar 2017 10:51:28 +0000 (03:51 -0700)
committerRui Marinho <me@ruimarinho.net>
Wed, 22 Mar 2017 10:52:57 +0000 (10:52 +0000)
* Add repro for 42559

* [Win] Override GetDesiredSize for LabelRenderer

* [Win] Invalidate size on font/align change

Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla42599.cs [new file with mode: 0644]
Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
Xamarin.Forms.Platform.WinRT/LabelRenderer.cs

diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla42599.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla42599.cs
new file mode 100644 (file)
index 0000000..f10b3f4
--- /dev/null
@@ -0,0 +1,67 @@
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+using System.Linq;
+using System;
+
+namespace Xamarin.Forms.Controls.Issues
+{
+       [Preserve(AllMembers = true)]
+       [Issue(IssueTracker.Bugzilla, 42599, "LineBreakMode does not work on UWP", PlatformAffected.WinRT)]
+       public class Bugzilla42599 : TestContentPage
+       {
+               protected override void Init()
+               {
+                       var scrollView = new ScrollView();
+                       var layout = new StackLayout();
+
+                       foreach (var lineBreakMode in Enum.GetValues(typeof(LineBreakMode)).Cast<LineBreakMode>())
+                       {
+                               layout.Children.Add(GetLayout(lineBreakMode));
+                       }
+                       scrollView.Content = layout;
+                       Content = scrollView;
+               }
+
+               static StackLayout GetLayout(LineBreakMode lineBreakMode)
+               {
+                       var text = "";
+
+                       switch (lineBreakMode)
+                       {
+                               default:
+                               case LineBreakMode.NoWrap:
+                                       text = "This is a long sentence that should NOT wrap. If this sentence has wrapped, then this test has failed.";
+                                       break;
+                               case LineBreakMode.WordWrap:
+                                       text = "This is a long sentence that should word wrap. If this sentence has NOT wrapped, then this test has failed.";
+                                       break;
+                               case LineBreakMode.CharacterWrap:
+                                       text = "This is a long sentence that should character wrap. If this sentence has NOT wrapped, then this test has failed.";
+                                       break;
+                               case LineBreakMode.HeadTruncation:
+                                       text = "This is a long sentence that should truncate at the beginning. If this sentence has NOT truncated, then this test has failed.";
+                                       break;
+                               case LineBreakMode.TailTruncation:
+                                       text = "This is a long sentence that should truncate at the end. If this sentence has NOT truncated, then this test has failed.";
+                                       break;
+                               case LineBreakMode.MiddleTruncation:
+                                       text = "This is a long sentence that should truncate at the middle. If this sentence has NOT truncated, then this test has failed.";
+                                       break;
+                       }
+
+                       var label = new Label
+                       {
+                               LineBreakMode = lineBreakMode,
+                               Text = text,
+                       };
+
+                       var layout = new StackLayout
+                       {
+                               Children = { label },
+                               Orientation = StackOrientation.Horizontal
+                       };
+
+                       return layout;
+               }
+       }
+}
\ No newline at end of file
index 866b23f..4709777 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla28650.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla37431.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla44777.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Bugzilla42599.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla51503.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla51505.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Bugzilla52533.cs" />
index 33f1fee..5101b16 100644 (file)
@@ -35,6 +35,8 @@ namespace Xamarin.Forms.Platform.WinRT
        {
                bool _fontApplied;
                bool _isInitiallyDefault;
+               SizeRequest _perfectSize;
+               bool _perfectSizeValid;
 
                protected override Windows.Foundation.Size ArrangeOverride(Windows.Foundation.Size finalSize)
                {
@@ -61,6 +63,29 @@ namespace Xamarin.Forms.Platform.WinRT
                        return finalSize;
                }
 
+               public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+               {
+                       if (!_perfectSizeValid)
+                       {
+                               _perfectSize = base.GetDesiredSize(double.PositiveInfinity, double.PositiveInfinity);
+                               _perfectSize.Minimum = new Size(Math.Min(10, _perfectSize.Request.Width), _perfectSize.Request.Height);
+                               _perfectSizeValid = true;
+                       }
+
+                       if (widthConstraint >= _perfectSize.Request.Width && heightConstraint >= _perfectSize.Request.Height)
+                               return _perfectSize;
+
+                       var result = base.GetDesiredSize(widthConstraint, heightConstraint);
+                       result.Minimum = new Size(Math.Min(10, result.Request.Width), result.Request.Height);
+                       if (Element.LineBreakMode != LineBreakMode.NoWrap)
+                       {
+                               if (result.Request.Width > widthConstraint || Element.LineBreakMode == LineBreakMode.WordWrap || Element.LineBreakMode == LineBreakMode.CharacterWrap)
+                                       result.Request = new Size(Math.Max(result.Minimum.Width, widthConstraint), result.Request.Height);
+                       }
+
+                       return result;
+               }
+
                protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
                {
                        base.OnElementChanged(e);
@@ -100,6 +125,8 @@ namespace Xamarin.Forms.Platform.WinRT
 
                void UpdateAlign(TextBlock textBlock)
                {
+                       _perfectSizeValid = false;
+
                        if (textBlock == null)
                                return;
 
@@ -129,6 +156,8 @@ namespace Xamarin.Forms.Platform.WinRT
 
                void UpdateFont(TextBlock textBlock)
                {
+                       _perfectSizeValid = false;
+
                        if (textBlock == null)
                                return;
 
@@ -146,6 +175,8 @@ namespace Xamarin.Forms.Platform.WinRT
 
                void UpdateLineBreakMode(TextBlock textBlock)
                {
+                       _perfectSizeValid = false;
+
                        if (textBlock == null)
                                return;
 
@@ -164,6 +195,7 @@ namespace Xamarin.Forms.Platform.WinRT
                                        textBlock.TextWrapping = TextWrapping.Wrap;
                                        break;
                                case LineBreakMode.HeadTruncation:
+                                       // TODO: This truncates at the end.
                                        textBlock.TextTrimming = TextTrimming.WordEllipsis;
                                        textBlock.TextWrapping = TextWrapping.NoWrap;
                                        break;
@@ -172,6 +204,7 @@ namespace Xamarin.Forms.Platform.WinRT
                                        textBlock.TextWrapping = TextWrapping.NoWrap;
                                        break;
                                case LineBreakMode.MiddleTruncation:
+                                       // TODO: This truncates at the end.
                                        textBlock.TextTrimming = TextTrimming.WordEllipsis;
                                        textBlock.TextWrapping = TextWrapping.NoWrap;
                                        break;
@@ -182,6 +215,8 @@ namespace Xamarin.Forms.Platform.WinRT
 
                void UpdateText(TextBlock textBlock)
                {
+                       _perfectSizeValid = false;
+
                        if (textBlock == null)
                                return;