Merge branch 'main' into davidortinau/template-tweaks

This commit is contained in:
Jonathan Peppers 2021-03-11 21:42:55 -06:00 коммит произвёл GitHub
Родитель 409a13c646 c926e8ea36
Коммит 02940314e0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
34 изменённых файлов: 394 добавлений и 29 удалений

Просмотреть файл

@ -296,10 +296,15 @@
<!-- iOS Only -->
<!-- If on Windows, using build host, copy the files over to build server host too -->
<ItemGroup Condition="'$(BuildSessionId)' != '' And '$(_ResizetizerIsiOSApp)' == 'True' And '$(IsMacEnabled)'=='true'">
<_SharedFontsToCopyToBuildServer Include="@(_SharedFontBundleResource);@(_SharedFontPListFiles)">
<TargetPath>%(Identity)</TargetPath>
</_SharedFontsToCopyToBuildServer>
</ItemGroup>
<CopyFilesToBuildServer
Condition="'$(BuildSessionId)' != '' And '$(_ResizetizerIsiOSApp)' == 'True' And '$(IsMacEnabled)'=='true'"
SessionId="$(BuildSessionId)"
Files="@(_SharedFontBundleResource);@(_SharedFontPListFiles)" />
Files="@(_SharedFontsToCopyToBuildServer)" />
<!-- Touch/create our stamp file for outputs -->
<Touch Files="$(_SharedFontStampFile)" AlwaysCreate="True" />
@ -367,10 +372,15 @@
<!-- iOS Only -->
<!-- If on Windows, using build host, copy the files over to build server host too -->
<ItemGroup Condition="'$(BuildSessionId)' != '' And '$(_ResizetizerIsiOSApp)' == 'True' And '$(IsMacEnabled)'=='true'">
<_SharedImagesToCopyToBuildServer Include="@(_ResizetizerCollectedBundleResourceImages)">
<TargetPath>%(Identity)</TargetPath>
</_SharedImagesToCopyToBuildServer>
</ItemGroup>
<CopyFilesToBuildServer
Condition="'$(BuildSessionId)' != '' And '$(_ResizetizerIsiOSApp)' == 'True' And '$(IsMacEnabled)'=='true'"
SessionId="$(BuildSessionId)"
Files="@(_ResizetizerCollectedBundleResourceImages)" />
Files="@(_SharedImagesToCopyToBuildServer)" />
<!-- Android -->
<ItemGroup Condition="'$(_ResizetizerIsAndroidApp)' == 'True'">

Просмотреть файл

@ -25,7 +25,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuspec", ".nuspec", "{7E12
.nuspec\Microsoft.Maui.Controls.MultiTargeting.targets = .nuspec\Microsoft.Maui.Controls.MultiTargeting.targets
.nuspec\Microsoft.Maui.Controls.nuspec = .nuspec\Microsoft.Maui.Controls.nuspec
.nuspec\Microsoft.Maui.Controls.props = .nuspec\Microsoft.Maui.Controls.props
.nuspec\Microsoft.Maui.Controls.SingleProject.props = .nuspec\Microsoft.Maui.Controls.SingleProject.props
.nuspec\Microsoft.Maui.Controls.SingleProject.targets = .nuspec\Microsoft.Maui.Controls.SingleProject.targets
.nuspec\Microsoft.Maui.Controls.targets = .nuspec\Microsoft.Maui.Controls.targets
.nuspec\Microsoft.Maui.Resizetizer.targets = .nuspec\Microsoft.Maui.Resizetizer.targets
.nuspec\package.ps1 = .nuspec\package.ps1
.nuspec\proguard.cfg = .nuspec\proguard.cfg
EndProjectSection
EndProject

Просмотреть файл

@ -328,6 +328,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android.FastRenderers
}
}
[PortHandler]
void UpdateTextDecorations()
{
if (!Element.IsSet(Label.TextDecorationsProperty))

Просмотреть файл

@ -21,6 +21,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
{
}
[PortHandler]
protected override FormsEditText CreateNativeControl()
{
return new FormsEditText(Context)
@ -100,6 +101,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
}
}
[PortHandler("Partially ported")]
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
@ -249,6 +251,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.Android
}
}
[PortHandler]
void UpdateText()
{
string newText = Element.UpdateFormsText(Element.Text, Element.TextTransform);

Просмотреть файл

@ -1,11 +1,5 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Maui;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Compatibility;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Hosting;
namespace Microsoft.Maui.Controls.Compatibility
@ -18,6 +12,7 @@ namespace Microsoft.Maui.Controls.Compatibility
var defaultHandlers = new List<Type>
{
typeof(Button) ,
typeof(Editor),
typeof(Entry) ,
typeof(ContentPage) ,
typeof(Page) ,
@ -58,7 +53,6 @@ namespace Microsoft.Maui.Controls.Compatibility
return builder;
}
public static IAppHostBuilder RegisterCompatibilityRenderer<TControlType, TMauiType, TRenderer>(this IAppHostBuilder builder)
where TMauiType : IFrameworkElement
{
@ -75,6 +69,5 @@ namespace Microsoft.Maui.Controls.Compatibility
public static IAppHostBuilder RegisterCompatibilityRenderer<TControlType, TRenderer>(this IAppHostBuilder builder)
where TControlType : IFrameworkElement =>
builder.RegisterCompatibilityRenderer<TControlType, TControlType, TRenderer>();
}
}
}

Просмотреть файл

@ -20,6 +20,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS
Frame = new RectangleF(0, 20, 320, 40);
}
[PortHandler]
protected override UITextView CreateNativeControl()
{
return new FormsUITextView(RectangleF.Empty);
@ -328,6 +329,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.iOS
TextView.ReloadInputViews();
}
[PortHandler]
protected internal virtual void UpdateText()
{
var text = Element.UpdateFormsText(Element.Text, Element.TextTransform);

Просмотреть файл

@ -249,6 +249,7 @@ namespace Microsoft.Maui.Controls.Compatibility.Platform.MacOS
_perfectSizeValid = false;
}
[PortHandler]
void UpdateTextDecorations()
{
if (IsElementOrControlEmpty)

Просмотреть файл

@ -9,6 +9,7 @@ namespace Maui.Controls.Sample.Pages
public class MainPage : ContentPage, IPage
{
MainPageViewModel _viewModel;
public MainPage() : this(App.Current.Services.GetService<MainPageViewModel>())
{
@ -35,6 +36,9 @@ namespace Maui.Controls.Sample.Pages
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 });
var underlineLabel = new Label { Text = "underline", TextDecorations = TextDecorations.Underline };
verticalStack.Add(underlineLabel);
var button = new Button() { Text = _viewModel.Text, WidthRequest = 200 };
var button2 = new Button()
{
@ -50,6 +54,9 @@ namespace Maui.Controls.Sample.Pages
verticalStack.Add(horizontalStack);
verticalStack.Add(new Editor());
verticalStack.Add(new Editor { Text = "Editor" });
var entry = new Entry();
entry.TextChanged += (sender, e) =>
{
@ -124,4 +131,4 @@ namespace Maui.Controls.Sample.Pages
public IView View { get => (IView)Content; set => Content = (View)value; }
}
}
}

Просмотреть файл

@ -4,7 +4,7 @@ using Microsoft.Maui.Controls.Internals;
namespace Microsoft.Maui.Controls
{
public class Editor : InputView, IEditorController, IFontElement, IElementConfiguration<Editor>
public partial class Editor : InputView, IEditorController, IFontElement, IElementConfiguration<Editor>
{
public new static readonly BindableProperty TextProperty = InputView.TextProperty;
@ -62,6 +62,9 @@ namespace Microsoft.Maui.Controls
protected void UpdateAutoSizeOption()
{
// Null out the Maui font value so it will be recreated next time it's accessed
_font = null;
if (AutoSize == EditorAutoSizeOption.TextChanges)
{
InvalidateMeasure();

Просмотреть файл

@ -0,0 +1,9 @@
namespace Microsoft.Maui.Controls
{
public partial class Editor : IEditor
{
Font? _font;
Font IText.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes);
}
}

Просмотреть файл

@ -4,17 +4,6 @@
{
Font? _font;
Font IText.Font
{
get
{
if (_font == null)
{
_font = Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes);
}
return _font.Value;
}
}
Font IText.Font => _font ??= Font.OfSize(FontFamily, FontSize).WithAttributes(FontAttributes);
}
}

Просмотреть файл

@ -0,0 +1,10 @@
namespace Microsoft.Maui
{
/// <summary>
/// Represents a View used to accept multi-line input.
/// </summary>
public interface IEditor : IView, IText
{
}
}

Просмотреть файл

@ -9,5 +9,11 @@ namespace Microsoft.Maui
/// Gets the space between the text of the Label and it's border.
/// </summary>
Thickness Padding { get; }
/// <summary>
/// Gets the text decoration applied to the Label.
/// Underline and strikethrough text decorations can be applied.
/// </summary>
TextDecorations TextDecorations { get; }
}
}

Просмотреть файл

@ -0,0 +1,29 @@
using Android.Views;
using Android.Views.InputMethods;
using Android.Widget;
namespace Microsoft.Maui.Handlers
{
public partial class EditorHandler : AbstractViewHandler<IEditor, EditText>
{
protected override EditText CreateNativeView()
{
var editText = new EditText(Context)
{
ImeOptions = ImeAction.Done
};
editText.SetSingleLine(false);
editText.Gravity = GravityFlags.Top;
editText.TextAlignment = global::Android.Views.TextAlignment.ViewStart;
editText.SetHorizontallyScrolling(false);
return editText;
}
public static void MapText(EditorHandler handler, IEditor editor)
{
handler.TypedNativeView?.UpdateText(editor);
}
}
}

Просмотреть файл

@ -0,0 +1,11 @@
using System;
namespace Microsoft.Maui.Handlers
{
public partial class EditorHandler : AbstractViewHandler<IEditor, object>
{
protected override object CreateNativeView() => throw new NotImplementedException();
public static void MapText(IViewHandler handler, IEditor editor) { }
}
}

Просмотреть файл

@ -0,0 +1,20 @@
namespace Microsoft.Maui.Handlers
{
public partial class EditorHandler
{
public static PropertyMapper<IEditor, EditorHandler> EditorMapper = new PropertyMapper<IEditor, EditorHandler>(ViewHandler.ViewMapper)
{
[nameof(IEditor.Text)] = MapText
};
public EditorHandler() : base(EditorMapper)
{
}
public EditorHandler(PropertyMapper mapper) : base(mapper ?? EditorMapper)
{
}
}
}

Просмотреть файл

@ -0,0 +1,23 @@
using CoreGraphics;
using UIKit;
namespace Microsoft.Maui.Handlers
{
public partial class EditorHandler : AbstractViewHandler<IEditor, UITextView>
{
static readonly int BaseHeight = 30;
protected override UITextView CreateNativeView()
{
return new UITextView(CGRect.Empty);
}
public override Size GetDesiredSize(double widthConstraint, double heightConstraint) =>
new SizeRequest(new Size(widthConstraint, BaseHeight));
public static void MapText(EditorHandler handler, IEditor editor)
{
handler.TypedNativeView?.UpdateText(editor);
}
}
}

Просмотреть файл

@ -42,7 +42,12 @@ namespace Microsoft.Maui.Handlers
handler.TypedNativeView?.UpdatePadding(label);
}
public static void MapFont(LabelHandler handler, ILabel label)
public static void MapTextDecorations(LabelHandler handler, ILabel label)
{
handler.TypedNativeView?.UpdateTextDecorations(label);
}
static void MapFont(LabelHandler handler, ILabel label)
{
var services = App.Current?.Services
?? throw new InvalidOperationException($"Unable to find service provider, the App.Current.Services was null.");

Просмотреть файл

@ -11,5 +11,6 @@ namespace Microsoft.Maui.Handlers
public static void MapCharacterSpacing(IViewHandler handler, ILabel label) { }
public static void MapFont(LabelHandler handler, ILabel label) { }
public static void MapPadding(LabelHandler handler, ILabel label) { }
public static void MapTextDecorations(LabelHandler handler, ILabel label) { }
}
}

Просмотреть файл

@ -9,6 +9,7 @@ namespace Microsoft.Maui.Handlers
[nameof(ILabel.CharacterSpacing)] = MapCharacterSpacing,
[nameof(ILabel.Font)] = MapFont,
[nameof(ILabel.Padding)] = MapPadding,
[nameof(ILabel.TextDecorations)] = MapTextDecorations
};
public LabelHandler() : base(LabelMapper)

Просмотреть файл

@ -28,7 +28,12 @@ namespace Microsoft.Maui.Handlers
handler.TypedNativeView?.UpdatePadding(label);
}
public static void MapFont(LabelHandler handler, ILabel label)
public static void MapTextDecorations(LabelHandler handler, ILabel label)
{
handler.TypedNativeView?.UpdateTextDecorations(label);
}
static void MapFont(LabelHandler handler, ILabel label)
{
var services = App.Current?.Services ??
throw new InvalidOperationException($"Unable to find service provider, the App.Current.Services was null.");

Просмотреть файл

@ -37,6 +37,7 @@ namespace Microsoft.Maui.Hosting
builder.RegisterHandlers(new Dictionary<Type, Type>
{
{ typeof(IButton), typeof(ButtonHandler) },
{ typeof(IEditor), typeof(EditorHandler) },
{ typeof(IEntry), typeof(EntryHandler) },
{ typeof(ILayout), typeof(LayoutHandler) },
{ typeof(ILabel), typeof(LabelHandler) },

Просмотреть файл

@ -0,0 +1,22 @@
using Android.Widget;
namespace Microsoft.Maui
{
public static class EditorExtensions
{
public static void UpdateText(this EditText editText, IEditor editor)
{
string text = editor.Text;
if (editText.Text == text)
return;
editText.Text = text;
if (string.IsNullOrEmpty(text))
return;
editText.SetSelection(text.Length);
}
}
}

Просмотреть файл

@ -1,3 +1,4 @@
using Android.Graphics;
using Android.Util;
using Android.Widget;
@ -53,5 +54,20 @@ namespace Microsoft.Maui
(int)context.ToPixels(label.Padding.Right),
(int)context.ToPixels(label.Padding.Bottom));
}
public static void UpdateTextDecorations(this TextView textView, ILabel label)
{
var textDecorations = label.TextDecorations;
if ((textDecorations & TextDecorations.Strikethrough) == 0)
textView.PaintFlags &= ~PaintFlags.StrikeThruText;
else
textView.PaintFlags |= PaintFlags.StrikeThruText;
if ((textDecorations & TextDecorations.Underline) == 0)
textView.PaintFlags &= ~PaintFlags.UnderlineText;
else
textView.PaintFlags |= PaintFlags.UnderlineText;
}
}
}

Просмотреть файл

@ -0,0 +1,17 @@
using UIKit;
namespace Microsoft.Maui
{
public static class EditorExtensions
{
public static void UpdateText(this UITextView textView, IEditor editor)
{
string text = editor.Text;
if (textView.Text != text)
{
textView.Text = text;
}
}
}
}

Просмотреть файл

@ -1,3 +1,4 @@
using Foundation;
using Microsoft.Maui.Platform.iOS;
using UIKit;
@ -54,5 +55,31 @@ namespace Microsoft.Maui
(float)label.Padding.Bottom,
(float)label.Padding.Right);
}
public static void UpdateTextDecorations(this UILabel nativeLabel, ILabel label)
{
if (nativeLabel.AttributedText != null && !(nativeLabel.AttributedText?.Length > 0))
return;
var textDecorations = label?.TextDecorations;
var newAttributedText = nativeLabel.AttributedText != null ? new NSMutableAttributedString(nativeLabel.AttributedText) : new NSMutableAttributedString(label?.Text ?? string.Empty);
var strikeThroughStyleKey = UIStringAttributeKey.StrikethroughStyle;
var underlineStyleKey = UIStringAttributeKey.UnderlineStyle;
var range = new NSRange(0, newAttributedText.Length);
if ((textDecorations & TextDecorations.Strikethrough) == 0)
newAttributedText.RemoveAttribute(strikeThroughStyleKey, range);
else
newAttributedText.AddAttribute(strikeThroughStyleKey, NSNumber.FromInt32((int)NSUnderlineStyle.Single), range);
if ((textDecorations & TextDecorations.Underline) == 0)
newAttributedText.RemoveAttribute(underlineStyleKey, range);
else
newAttributedText.AddAttribute(underlineStyleKey, NSNumber.FromInt32((int)NSUnderlineStyle.Single), range);
nativeLabel.AttributedText = newAttributedText;
}
}
}

Просмотреть файл

@ -0,0 +1,15 @@
using Android.Text;
using Android.Widget;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.DeviceTests
{
public partial class EditorHandlerTests
{
EditText GetNativeEditor(EditorHandler editorHandler) =>
(EditText)editorHandler.View;
string GetNativeText(EditorHandler editorHandler) =>
GetNativeEditor(editorHandler).Text;
}
}

Просмотреть файл

@ -0,0 +1,49 @@
using System.Threading.Tasks;
using Microsoft.Maui.DeviceTests.Stubs;
using Microsoft.Maui.Handlers;
using Xunit;
namespace Microsoft.Maui.DeviceTests
{
[Category(TestCategory.Editor)]
public partial class EditorHandlerTests : HandlerTestBase<EditorHandler>
{
public EditorHandlerTests(HandlerTestFixture fixture) : base(fixture)
{
}
[Fact(DisplayName = "Text Initializes Correctly")]
public async Task TextInitializesCorrectly()
{
var editor = new EditorStub()
{
Text = "Test"
};
await ValidatePropertyInitValue(editor, () => editor.Text, GetNativeText, editor.Text);
}
[Theory(DisplayName = "Text Updates Correctly")]
[InlineData(null, null)]
[InlineData(null, "Hello")]
[InlineData("Hello", null)]
[InlineData("Hello", "Goodbye")]
public async Task TextUpdatesCorrectly(string setValue, string unsetValue)
{
var editor = new EditorStub();
await ValidatePropertyUpdatesValue(
editor,
nameof(IEditor.Text),
h =>
{
var n = GetNativeText(h);
if (string.IsNullOrEmpty(n))
n = null; // native platforms may not upport null text
return n;
},
setValue,
unsetValue);
}
}
}

Просмотреть файл

@ -0,0 +1,14 @@
using Microsoft.Maui.Handlers;
using UIKit;
namespace Microsoft.Maui.DeviceTests
{
public partial class EditorHandlerTests
{
UITextView GetNativeEditor(EditorHandler editorHandler) =>
(UITextView)editorHandler.View;
string GetNativeText(EditorHandler editorHandler) =>
GetNativeEditor(editorHandler).Text;
}
}

Просмотреть файл

@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using Android.Graphics;
using Android.Widget;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui.DeviceTests.Stubs;
@ -62,6 +63,31 @@ namespace Microsoft.Maui.DeviceTests
Assert.Equal(expectedBottom, bottom);
}
[Fact(DisplayName = "[LabelHandler] TextDecorations Initializes Correctly")]
public async Task TextDecorationsInitializesCorrectly()
{
var xplatTextDecorations = TextDecorations.Underline;
var labelHandler = new LabelStub()
{
TextDecorations = xplatTextDecorations
};
var values = await GetValueAsync(labelHandler, (handler) =>
{
return new
{
ViewValue = labelHandler.TextDecorations,
NativeViewValue = GetNativeTextDecorations(handler)
};
});
PaintFlags expectedValue = PaintFlags.UnderlineText;
Assert.Equal(xplatTextDecorations, values.ViewValue);
Assert.True(values.NativeViewValue.HasFlag(expectedValue));
}
TextView GetNativeLabel(LabelHandler labelHandler) =>
(TextView)labelHandler.View;
@ -98,5 +124,8 @@ namespace Microsoft.Maui.DeviceTests
double GetNativeCharacterSpacing(LabelHandler labelHandler) =>
Math.Round(GetNativeLabel(labelHandler).LetterSpacing / UnitExtensions.EmCoefficient, 4);
PaintFlags GetNativeTextDecorations(LabelHandler labelHandler) =>
GetNativeLabel(labelHandler).PaintFlags;
}
}

Просмотреть файл

@ -54,6 +54,29 @@ namespace Microsoft.Maui.DeviceTests
Assert.Equal(20, insets.Bottom);
}
[Fact(DisplayName = "TextDecorations Initializes Correctly")]
public async Task TextDecorationsInitializesCorrectly()
{
var xplatTextDecorations = TextDecorations.Underline;
var labelHandler = new LabelStub()
{
TextDecorations = xplatTextDecorations
};
var values = await GetValueAsync(labelHandler, (handler) =>
{
return new
{
ViewValue = labelHandler.TextDecorations,
NativeViewValue = GetNativeTextDecorations(handler)
};
});
Assert.Equal(xplatTextDecorations, values.ViewValue);
Assert.True(values.NativeViewValue != null);
}
UILabel GetNativeLabel(LabelHandler labelHandler) =>
(UILabel)labelHandler.View;
@ -97,5 +120,8 @@ namespace Microsoft.Maui.DeviceTests
return GetNativeLabel(CreateHandler(label)).AssertContainsColor(color);
});
}
NSAttributedString GetNativeTextDecorations(LabelHandler labelHandler) =>
GetNativeLabel(labelHandler).AttributedText;
}
}

Просмотреть файл

@ -0,0 +1,13 @@
namespace Microsoft.Maui.DeviceTests.Stubs
{
public partial class EditorStub : StubBase, IEditor
{
public string Text { get; set; }
public Color TextColor { get; set; }
public Font Font { get; set; }
public double CharacterSpacing { get; set; }
}
}

Просмотреть файл

@ -11,5 +11,7 @@ namespace Microsoft.Maui.DeviceTests.Stubs
public Thickness Padding { get; set; }
public Font Font { get; set; }
public TextDecorations TextDecorations { get; set; }
}
}

Просмотреть файл

@ -3,10 +3,11 @@
public static class TestCategory
{
public const string Button = "Button";
public const string Editor = "Editor";
public const string Entry = "Entry";
public const string Label = "Label";
public const string Layout = "Layout";
public const string Slider = "Slider";
public const string Switch = "Switch";
public const string Layout = "Layout";
}
}
}