Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement LineBreakMode property in LabelHandlers #458

Merged
merged 10 commits into from
Mar 13, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static void SetLineBreakMode(this TextView textView, Label label)
public static void SetLineBreakMode(this TextView textView, Button button) =>
SetLineBreak(textView, button.LineBreakMode);


[PortHandler]
public static int SetLineBreak(TextView textView, LineBreakMode lineBreakMode)
{
int maxLines = Int32.MaxValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ void UpdateCharacterSpacing()
}
}

[PortHandler]
void UpdateLineBreakMode()
{
this.SetLineBreakMode(Element);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ void UpdateHorizontalTextAlignment()
#endif
}

[PortHandler]
void UpdateLineBreakMode()
{
#if __MOBILE__
Expand Down
14 changes: 13 additions & 1 deletion src/Controls/samples/Controls.Sample/Pages/MainPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

namespace Maui.Controls.Sample.Pages
{

public class MainPage : ContentPage, IPage
{
MainPageViewModel _viewModel;
Expand All @@ -24,6 +23,15 @@ public MainPage(MainPageViewModel viewModel)

void SetupMauiLayout()
{
const string loremIpsum =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
"Quisque ut dolor metus. Duis vel iaculis mauris, sit amet finibus mi. " +
"Etiam congue ornare risus, in facilisis libero tempor eget. " +
"Phasellus mattis mollis libero ut semper. In sit amet sapien odio. " +
"Sed interdum ullamcorper dui eu rutrum. Vestibulum non sagittis justo. " +
"Cras rutrum scelerisque elit, et porta est lobortis ac. " +
"Pellentesque eu ornare tortor. Sed bibendum a nisl at laoreet.";

var verticalStack = new VerticalStackLayout() { Spacing = 5, BackgroundColor = Color.AntiqueWhite };
var horizontalStack = new HorizontalStackLayout() { Spacing = 2, BackgroundColor = Color.CornflowerBlue };

Expand All @@ -35,6 +43,10 @@ void SetupMauiLayout()
verticalStack.Add(new Label { Text = "This should be BOLD text!", FontAttributes = FontAttributes.Bold });
verticalStack.Add(new Label { Text = "This should be a CUSTOM font!", FontFamily = "Dokdo" });
verticalStack.Add(new Label { Text = "This should have padding", Padding = new Thickness(40), BackgroundColor = Color.LightBlue });
verticalStack.Add(new Label { Text = loremIpsum });
verticalStack.Add(new Label { Text = loremIpsum, MaxLines = 2 });
verticalStack.Add(new Label { Text = loremIpsum, LineBreakMode = LineBreakMode.TailTruncation });
verticalStack.Add(new Label { Text = loremIpsum, MaxLines = 2, LineBreakMode = LineBreakMode.TailTruncation });

var underlineLabel = new Label { Text = "underline", TextDecorations = TextDecorations.Underline };
verticalStack.Add(underlineLabel);
Expand Down
5 changes: 5 additions & 0 deletions src/Core/src/Core/ILabel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ namespace Microsoft.Maui
/// </summary>
public interface ILabel : IView, IText
{
/// <summary>
/// Gets the option for line breaking.
/// </summary>
LineBreakMode LineBreakMode { get; }

/// <summary>
/// Gets the maximum number of lines allowed in the Label.
/// </summary>
Expand Down
5 changes: 5 additions & 0 deletions src/Core/src/Handlers/Label/LabelHandler.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ public static void MapCharacterSpacing(LabelHandler handler, ILabel label)
handler.TypedNativeView?.UpdateCharacterSpacing(label);
}

public static void MapLineBreakMode(LabelHandler handler, ILabel label)
{
handler.TypedNativeView?.UpdateLineBreakMode(label);
}

public static void MapMaxLines(LabelHandler handler, ILabel label)
{
handler.TypedNativeView?.UpdateMaxLines(label);
Expand Down
1 change: 1 addition & 0 deletions src/Core/src/Handlers/Label/LabelHandler.Standard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public static void MapText(IViewHandler handler, ILabel label) { }
public static void MapTextColor(IViewHandler handler, ILabel label) { }
public static void MapCharacterSpacing(IViewHandler handler, ILabel label) { }
public static void MapFont(LabelHandler handler, ILabel label) { }
public static void MapLineBreakMode(LabelHandler handler, ILabel label) { }
public static void MapTextDecorations(LabelHandler handler, ILabel label) { }
public static void MapMaxLines(IViewHandler handler, ILabel label) { }
public static void MapPadding(LabelHandler handler, ILabel label) { }
Expand Down
1 change: 1 addition & 0 deletions src/Core/src/Handlers/Label/LabelHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public partial class LabelHandler
[nameof(ILabel.CharacterSpacing)] = MapCharacterSpacing,
[nameof(ILabel.MaxLines)] = MapMaxLines,
[nameof(ILabel.Font)] = MapFont,
[nameof(ILabel.LineBreakMode)] = MapLineBreakMode,
[nameof(ILabel.Padding)] = MapPadding,
[nameof(ILabel.TextDecorations)] = MapTextDecorations
};
Expand Down
5 changes: 5 additions & 0 deletions src/Core/src/Handlers/Label/LabelHandler.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ public static void MapCharacterSpacing(LabelHandler handler, ILabel label)
handler.TypedNativeView?.UpdateCharacterSpacing(label);
}

public static void MapLineBreakMode(LabelHandler handler, ILabel label)
{
handler.TypedNativeView?.UpdateLineBreakMode(label);
}

public static void MapMaxLines(LabelHandler handler, ILabel label)
{
handler.TypedNativeView?.UpdateMaxLines(label);
Expand Down
48 changes: 48 additions & 0 deletions src/Core/src/Platform/Android/LabelExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Android.Graphics;
using Android.Text;
using Android.Util;
using Android.Widget;

Expand Down Expand Up @@ -39,6 +40,11 @@ public static void UpdateFont(this TextView textView, ILabel label, IFontManager
textView.SetTextSize(ComplexUnitType.Sp, sp);
}

public static void UpdateLineBreakMode(this TextView textView, ILabel label)
{
textView.SetLineBreakMode(label);
}

public static void UpdateMaxLines(this TextView textView, ILabel label)
{
int maxLinex = label.MaxLines;
Expand Down Expand Up @@ -76,5 +82,47 @@ public static void UpdateTextDecorations(this TextView textView, ILabel label)
else
textView.PaintFlags |= PaintFlags.UnderlineText;
}

internal static void SetLineBreakMode(this TextView textView, ILabel label)
{
var lineBreakMode = label.LineBreakMode;

int maxLines = label.MaxLines;
if (maxLines <= 0)
maxLines = int.MaxValue;

bool singleLine = false;

switch (lineBreakMode)
{
case LineBreakMode.NoWrap:
maxLines = 1;
textView.Ellipsize = null;
break;
case LineBreakMode.WordWrap:
textView.Ellipsize = null;
break;
case LineBreakMode.CharacterWrap:
textView.Ellipsize = null;
break;
case LineBreakMode.HeadTruncation:
maxLines = 1;
singleLine = true; // Workaround for bug in older Android API versions (https://bugzilla.xamarin.com/show_bug.cgi?id=49069)
textView.Ellipsize = TextUtils.TruncateAt.Start;
break;
case LineBreakMode.TailTruncation:
maxLines = 1;
textView.Ellipsize = TextUtils.TruncateAt.End;
break;
case LineBreakMode.MiddleTruncation:
maxLines = 1;
singleLine = true; // Workaround for bug in older Android API versions (https://bugzilla.xamarin.com/show_bug.cgi?id=49069)
textView.Ellipsize = TextUtils.TruncateAt.Middle;
break;
}

textView.SetSingleLine(singleLine);
textView.SetMaxLines(maxLines);
}
}
}
40 changes: 40 additions & 0 deletions src/Core/src/Platform/iOS/LabelExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ public static void UpdateFont(this UILabel nativeLabel, ILabel label, IFontManag
nativeLabel.UpdateCharacterSpacing(label);
}

public static void UpdateLineBreakMode(this UILabel nativeLabel, ILabel label)
{
SetLineBreakMode(nativeLabel, label);
}

public static void UpdateMaxLines(this UILabel nativeLabel, ILabel label)
{
int maxLines = label.MaxLines;
Expand All @@ -66,6 +71,41 @@ public static void UpdatePadding(this MauiLabel nativeLabel, ILabel label)
(float)label.Padding.Right);
}

internal static void SetLineBreakMode(this UILabel nativeLabel, ILabel label)
{
int maxLines = label.MaxLines;
if (maxLines < 0)
maxLines = 0;

switch (label.LineBreakMode)
{
case LineBreakMode.NoWrap:
nativeLabel.LineBreakMode = UILineBreakMode.Clip;
maxLines = 1;
break;
case LineBreakMode.WordWrap:
nativeLabel.LineBreakMode = UILineBreakMode.WordWrap;
break;
case LineBreakMode.CharacterWrap:
nativeLabel.LineBreakMode = UILineBreakMode.CharacterWrap;
break;
case LineBreakMode.HeadTruncation:
nativeLabel.LineBreakMode = UILineBreakMode.HeadTruncation;
maxLines = 1;
break;
case LineBreakMode.MiddleTruncation:
nativeLabel.LineBreakMode = UILineBreakMode.MiddleTruncation;
maxLines = 1;
break;
case LineBreakMode.TailTruncation:
nativeLabel.LineBreakMode = UILineBreakMode.TailTruncation;
maxLines = 1;
break;
}

nativeLabel.Lines = maxLines;
}

public static void UpdateTextDecorations(this UILabel nativeLabel, ILabel label)
{
if (nativeLabel.AttributedText != null && !(nativeLabel.AttributedText?.Length > 0))
Expand Down
13 changes: 13 additions & 0 deletions src/Core/tests/DeviceTests/AssertionExtensions.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.IO;
using System.Threading.Tasks;
using Android.Graphics;
using Android.Text;
using Android.Views;
using Android.Widget;
using Xunit;
Expand Down Expand Up @@ -168,5 +169,17 @@ public static async Task<Bitmap> AssertColorAtTopRight(this AView view, AColor e
var bitmap = await view.ToBitmap();
return bitmap.AssertColorAtTopRight(expectedColor);
}

public static TextUtils.TruncateAt ToNative(this LineBreakMode mode) =>
mode switch
{
LineBreakMode.NoWrap => null,
LineBreakMode.WordWrap => null,
LineBreakMode.CharacterWrap => null,
LineBreakMode.HeadTruncation => TextUtils.TruncateAt.Start,
LineBreakMode.TailTruncation => TextUtils.TruncateAt.End,
LineBreakMode.MiddleTruncation => TextUtils.TruncateAt.Middle,
_ => throw new ArgumentOutOfRangeException(nameof(mode))
};
}
}
12 changes: 12 additions & 0 deletions src/Core/tests/DeviceTests/AssertionExtensions.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,5 +183,17 @@ public static UIImage AssertContainsColor(this UIImage bitmap, UIColor expectedC
Assert.True(false, CreateColorError(bitmap, $"Color {expectedColor} not found."));
return bitmap;
}

public static UILineBreakMode ToNative(this LineBreakMode mode) =>
mode switch
{
LineBreakMode.NoWrap => UILineBreakMode.Clip,
LineBreakMode.WordWrap => UILineBreakMode.WordWrap,
LineBreakMode.CharacterWrap => UILineBreakMode.CharacterWrap,
LineBreakMode.HeadTruncation => UILineBreakMode.HeadTruncation,
LineBreakMode.TailTruncation => UILineBreakMode.TailTruncation,
LineBreakMode.MiddleTruncation => UILineBreakMode.MiddleTruncation,
_ => throw new ArgumentOutOfRangeException(nameof(mode))
};
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Threading.Tasks;
using Android.Graphics;
using Android.Text;
using Android.Widget;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui.DeviceTests.Stubs;
Expand Down Expand Up @@ -38,6 +39,21 @@ public async Task FontFamilyInitializesCorrectly(string family)
Assert.NotEqual(fontManager.DefaultTypeface, nativeLabel.Typeface);
}

[Fact(DisplayName = "Negative MaxLines value with wrap is correct")]
public async Task NegativeMaxValueWithWrapIsCorrect()
{
var label = new LabelStub()
{
Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit",
MaxLines = -1,
LineBreakMode = LineBreakMode.WordWrap
};

var nativeValue = await GetValueAsync(label, GetNativeMaxLines);

Assert.Equal(int.MaxValue, nativeValue);
}

[Fact(DisplayName = "Padding Initializes Correctly")]
public async Task PaddingInitializesCorrectly()
{
Expand Down Expand Up @@ -128,6 +144,9 @@ Task ValidateNativeBackgroundColor(ILabel label, Color color)
double GetNativeCharacterSpacing(LabelHandler labelHandler) =>
Math.Round(GetNativeLabel(labelHandler).LetterSpacing / UnitExtensions.EmCoefficient, 4);

TextUtils.TruncateAt GetNativeLineBreakMode(LabelHandler labelHandler) =>
GetNativeLabel(labelHandler).Ellipsize;

PaintFlags GetNativeTextDecorations(LabelHandler labelHandler) =>
GetNativeLabel(labelHandler).PaintFlags;
}
Expand Down
Loading