From 134ed84c0bfdeb854f6fe3b22ce14ce116b10caa Mon Sep 17 00:00:00 2001 From: Jerome Laban Date: Thu, 6 May 2021 11:04:17 -0400 Subject: [PATCH 1/3] chore: Move UIElement TextHelper file to UIElement --- .../UIElementTextHelper.wasm.cs => UIElement.TextHelper.wasm.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/Uno.UI/UI/Xaml/{Documents/UIElementTextHelper.wasm.cs => UIElement.TextHelper.wasm.cs} (100%) diff --git a/src/Uno.UI/UI/Xaml/Documents/UIElementTextHelper.wasm.cs b/src/Uno.UI/UI/Xaml/UIElement.TextHelper.wasm.cs similarity index 100% rename from src/Uno.UI/UI/Xaml/Documents/UIElementTextHelper.wasm.cs rename to src/Uno.UI/UI/Xaml/UIElement.TextHelper.wasm.cs From c1a776b3b53a05f419808f188c12b3319dd38132 Mon Sep 17 00:00:00 2001 From: Jerome Laban Date: Thu, 6 May 2021 11:10:06 -0400 Subject: [PATCH 2/3] perf: Move all UIElement TextHelpers to UIElement --- .../UI/Xaml/UIElement.TextHelper.wasm.cs | 146 +++++++++--------- 1 file changed, 74 insertions(+), 72 deletions(-) diff --git a/src/Uno.UI/UI/Xaml/UIElement.TextHelper.wasm.cs b/src/Uno.UI/UI/Xaml/UIElement.TextHelper.wasm.cs index a54f88752404..8f28489fbb0e 100644 --- a/src/Uno.UI/UI/Xaml/UIElement.TextHelper.wasm.cs +++ b/src/Uno.UI/UI/Xaml/UIElement.TextHelper.wasm.cs @@ -10,11 +10,11 @@ using Uno.Disposables; using Uno.Extensions; -namespace Uno.UI.UI.Xaml.Documents +namespace Windows.UI.Xaml { - internal static class UIElementTextHelper + partial class UIElement { - internal static void SetText(this UIElement element, string text) + internal void SetText(string text) { if (string.IsNullOrWhiteSpace(text)) { @@ -33,14 +33,14 @@ internal static void SetText(this UIElement element, string text) } } - element.SetProperty("textContent", text); + this.SetProperty("textContent", text); } - internal static void SetFontStyle(this UIElement element, object localValue) + internal void SetFontStyle(object localValue) { if (localValue is UnsetValue) { - element.ResetStyle("font-style"); + this.ResetStyle("font-style"); } else { @@ -48,35 +48,35 @@ internal static void SetFontStyle(this UIElement element, object localValue) switch (value) { case FontStyle.Normal: - element.SetStyle("font-style", "normal"); + this.SetStyle("font-style", "normal"); break; case FontStyle.Italic: - element.SetStyle("font-style", "italic"); + this.SetStyle("font-style", "italic"); break; case FontStyle.Oblique: - element.SetStyle("font-style", "oblique"); + this.SetStyle("font-style", "oblique"); break; } } } - internal static void SetFontWeight(this UIElement element, object localValue) + internal void SetFontWeight(object localValue) { if (localValue is UnsetValue) { - element.ResetStyle("font-weight"); + this.ResetStyle("font-weight"); } else { - element.SetStyle("font-weight", ((FontWeight)localValue).ToCssString()); + this.SetStyle("font-weight", ((FontWeight)localValue).ToCssString()); } } - internal static void SetFontFamily(this UIElement element, object localValue) + internal void SetFontFamily(object localValue) { if (localValue is UnsetValue) { - element.ResetStyle("font-family"); + this.ResetStyle("font-family"); } else { @@ -89,94 +89,96 @@ internal static void SetFontFamily(this UIElement element, object localValue) value = FontFamily.Default; } - element.SetStyle("font-family", value.ParsedSource); + this.SetStyle("font-family", value.ParsedSource); } } } - internal static void SetFontSize(this UIElement element, object localValue) + internal void SetFontSize(object localValue) { if (localValue is UnsetValue) { - element.ResetStyle("font-size"); + this.ResetStyle("font-size"); } else { var value = (double)localValue; - element.SetStyle("font-size", value.ToStringInvariant() + "px"); + this.SetStyle("font-size", value.ToStringInvariant() + "px"); } } - internal static void SetMaxLines(this UIElement element, object localValue) + internal void SetMaxLines(object localValue) { if (localValue is UnsetValue) { - element.ResetStyle("display", "-webkit-line-clamp", "webkit-box-orient"); + this.ResetStyle("display", "-webkit-line-clamp", "webkit-box-orient"); } else { var value = (int)localValue; - element.SetStyle(("display", "-webkit-box"), ("-webkit-line-clamp", value.ToStringInvariant()), ("-webkit-box-orient", "vertical")); + this.SetStyle(("display", "-webkit-box"), ("-webkit-line-clamp", value.ToStringInvariant()), ("-webkit-box-orient", "vertical")); } } - private static void SetTextTrimming(this UIElement element, object localValue) + private void SetTextTrimming(object localValue) { switch (localValue) { case TextTrimming.CharacterEllipsis: case TextTrimming.WordEllipsis: // Word-level ellipsis not supported by HTML/CSS - element.SetStyle("text-overflow", "ellipsis"); + this.SetStyle("text-overflow", "ellipsis"); break; case TextTrimming.Clip: - element.SetStyle("text-overflow", "clip"); + this.SetStyle("text-overflow", "clip"); break; case UnsetValue uv: - element.ResetStyle("text-overflow"); + this.ResetStyle("text-overflow"); break; default: - element.SetStyle("text-overflow", ""); + this.SetStyle("text-overflow", ""); break; } } - private static WeakAttachedDictionary _imageBrushSubscription = - new WeakAttachedDictionary(); + private SerialDisposable _brushSubscription; - internal static void SetForeground(this UIElement element, object localValue) + internal void SetForeground(object localValue) { - var brushSubscription = _imageBrushSubscription.GetValue(element, "foreground", () => new SerialDisposable()); - - brushSubscription.Disposable = null; + if (_brushSubscription != null) + { + _brushSubscription.Disposable = null; + } switch (localValue) { case SolidColorBrush scb: - element.SetStyle("color", scb.ColorWithOpacity.ToHexString()); + this.SetStyle("color", scb.ColorWithOpacity.ToHexString()); break; case GradientBrush gradient: - element.SetStyle( - ("background", gradient.ToCssString(element.RenderSize)), + this.SetStyle( + ("background", gradient.ToCssString(this.RenderSize)), ("color", "transparent"), ("background-clip", "text") ); break; case ImageBrush imageBrush: - brushSubscription.Disposable = imageBrush.Subscribe(img => + _brushSubscription ??= new SerialDisposable(); + + _brushSubscription.Disposable = imageBrush.Subscribe(img => { switch (img.Kind) { case ImageDataKind.Empty: case ImageDataKind.Error: - element.ResetStyle( + this.ResetStyle( "background-color", "background-image", "background-size"); - element.SetStyle( + this.SetStyle( ("color", "transparent"), ("background-clip", "text")); break; @@ -184,7 +186,7 @@ internal static void SetForeground(this UIElement element, object localValue) case ImageDataKind.DataUri: case ImageDataKind.Url: default: - element.SetStyle( + this.SetStyle( ("color", "transparent"), ("background-clip", "text"), ("background-color", ""), @@ -198,58 +200,58 @@ internal static void SetForeground(this UIElement element, object localValue) }); break; case AcrylicBrush acrylic: - acrylic.Apply(element); - element.SetStyle("background-clip", "text"); + acrylic.Apply(this); + this.SetStyle("background-clip", "text"); break; case UnsetValue uv: // TODO: support other foreground types default: - element.ResetStyle("color", "background", "background-clip"); - AcrylicBrush.ResetStyle(element); + this.ResetStyle("color", "background", "background-clip"); + AcrylicBrush.ResetStyle(this); break; } } - internal static void SetCharacterSpacing(this UIElement element, object localValue) + internal void SetCharacterSpacing(object localValue) { if (localValue is UnsetValue) { - element.ResetStyle("letter-spacing"); + this.ResetStyle("letter-spacing"); } else { var value = (int)localValue; - element.SetStyle("letter-spacing", (value / 1000.0).ToStringInvariant() + "em"); + this.SetStyle("letter-spacing", (value / 1000.0).ToStringInvariant() + "em"); } } - internal static void SetLineHeight(this UIElement element, object localValue) + internal void SetLineHeight(object localValue) { if (localValue is UnsetValue) { - element.ResetStyle("line-height"); + this.ResetStyle("line-height"); } else { var value = (double)localValue; if (Math.Abs(value) < 0.0001) { - element.ResetStyle("line-height"); + this.ResetStyle("line-height"); } else { - element.SetStyle("line-height", value.ToStringInvariant() + "px"); + this.SetStyle("line-height", value.ToStringInvariant() + "px"); } } } - internal static void SetTextAlignment(this UIElement element, object localValue) + internal void SetTextAlignment(object localValue) { if (localValue is UnsetValue) { - element.ResetStyle("text-align"); + this.ResetStyle("text-align"); } else { @@ -257,30 +259,30 @@ internal static void SetTextAlignment(this UIElement element, object localValue) switch (value) { case TextAlignment.Left: - element.SetStyle("text-align", "left"); + this.SetStyle("text-align", "left"); break; case TextAlignment.Center: - element.SetStyle("text-align", "center"); + this.SetStyle("text-align", "center"); break; case TextAlignment.Right: - element.SetStyle("text-align", "right"); + this.SetStyle("text-align", "right"); break; case TextAlignment.Justify: - element.SetStyle("text-align", "justify"); + this.SetStyle("text-align", "justify"); break; case TextAlignment.DetectFromContent: default: - element.ResetStyle("text-align"); + this.ResetStyle("text-align"); break; } } } - internal static void SetTextWrappingAndTrimming(this UIElement element, object textWrapping, object textTrimming) + internal void SetTextWrappingAndTrimming(object textWrapping, object textTrimming) { if (textWrapping is UnsetValue) { - element.ResetStyle("white-space", "word-break", "text-overflow"); + this.ResetStyle("white-space", "word-break", "text-overflow"); } else { @@ -288,7 +290,7 @@ internal static void SetTextWrappingAndTrimming(this UIElement element, object t switch (value) { case TextWrapping.NoWrap: - element.SetStyle( + this.SetStyle( ("white-space", "pre"), ("word-break", "")); @@ -296,16 +298,16 @@ internal static void SetTextWrappingAndTrimming(this UIElement element, object t // https://drafts.csswg.org/css-overflow-3/#propdef-block-ellipsis // // For now, trimming isonly supported when wrapping is disabled. - SetTextTrimming(element, textTrimming); + SetTextTrimming(textTrimming); break; case TextWrapping.Wrap: - element.SetStyle( + this.SetStyle( ("white-space", "pre-wrap"), ("word-break", "break-word"), // This is required to still wrap words that are longer than the ViewPort ("text-overflow", "")); break; case TextWrapping.WrapWholeWords: - element.SetStyle( + this.SetStyle( ("white-space", "pre-wrap"), ("word-break", "keep-all"), // This is required to still wrap words that are longer than the ViewPort ("text-overflow", "")); @@ -314,11 +316,11 @@ internal static void SetTextWrappingAndTrimming(this UIElement element, object t } } - internal static void SetTextDecorations(this UIElement element, object localValue) + internal void SetTextDecorations(object localValue) { if (localValue is UnsetValue) { - element.ResetStyle("text-decoration"); + this.ResetStyle("text-decoration"); } else { @@ -326,26 +328,26 @@ internal static void SetTextDecorations(this UIElement element, object localValu switch (value) { case TextDecorations.None: - element.SetStyle("text-decoration", "none"); + this.SetStyle("text-decoration", "none"); break; case TextDecorations.Underline: - element.SetStyle("text-decoration", "underline"); + this.SetStyle("text-decoration", "underline"); break; case TextDecorations.Strikethrough: - element.SetStyle("text-decoration", "line-through"); + this.SetStyle("text-decoration", "line-through"); break; case TextDecorations.Underline | TextDecorations.Strikethrough: - element.SetStyle("text-decoration", "underline line-through"); + this.SetStyle("text-decoration", "underline line-through"); break; } } } - internal static void SetTextPadding(this UIElement element, object localValue) + internal void SetTextPadding(object localValue) { if (localValue is UnsetValue) { - element.ResetStyle("padding"); + this.ResetStyle("padding"); } else { @@ -362,7 +364,7 @@ internal static void SetTextPadding(this UIElement element, object localValue) "px" }; - element.SetStyle("padding", string.Concat(paddingStr)); + this.SetStyle("padding", string.Concat(paddingStr)); } } } From 07c794ba5c9689241893b001e8b61b1d5a852ee9 Mon Sep 17 00:00:00 2001 From: Jerome Laban Date: Thu, 6 May 2021 14:06:00 -0400 Subject: [PATCH 3/3] perf: [Wasm] Improve text set color --- .../TSBindings/TSBindingsGenerator.cs | 115 +++++++++++++++++- .../Xaml/Controls/TextBlock/TextBlock.wasm.cs | 1 - .../UI/Xaml/Controls/TextBox/TextBox.wasm.cs | 1 - .../Xaml/Controls/TextBox/TextBoxView.wasm.cs | 1 - src/Uno.UI/UI/Xaml/Documents/Run.wasm.cs | 1 - .../UI/Xaml/Documents/TextElement.wasm.cs | 4 +- .../UI/Xaml/UIElement.TextHelper.wasm.cs | 3 +- .../UI/Xaml/WindowManagerInterop.wasm.cs | 38 ++++++ src/Uno.UI/WasmScripts/Uno.UI.d.ts | 11 ++ src/Uno.UI/WasmScripts/Uno.UI.js | 29 +++++ src/Uno.UI/ts/WindowManager.ts | 21 ++++ .../WindowManagerSetElementColorParams.ts | 20 +++ 12 files changed, 232 insertions(+), 13 deletions(-) create mode 100644 src/Uno.UI/tsBindings/WindowManagerSetElementColorParams.ts diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/TSBindings/TSBindingsGenerator.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/TSBindings/TSBindingsGenerator.cs index ea335625cfea..aa7094372783 100644 --- a/src/SourceGenerators/Uno.UI.SourceGenerators/TSBindings/TSBindingsGenerator.cs +++ b/src/SourceGenerators/Uno.UI.SourceGenerators/TSBindings/TSBindingsGenerator.cs @@ -27,6 +27,7 @@ class TSBindingsGenerator : ISourceGenerator private static INamedTypeSymbol _stringSymbol; private static INamedTypeSymbol _intSymbol; + private static INamedTypeSymbol _uintSymbol; private static INamedTypeSymbol _floatSymbol; private static INamedTypeSymbol _doubleSymbol; private static INamedTypeSymbol _byteSymbol; @@ -54,6 +55,7 @@ public void Execute(GeneratorExecutionContext context) { _stringSymbol = context.Compilation.GetTypeByMetadataName("System.String"); _intSymbol = context.Compilation.GetTypeByMetadataName("System.Int32"); + _uintSymbol = context.Compilation.GetTypeByMetadataName("System.UInt32") ?? throw new Exception($"System.UInt32"); _floatSymbol = context.Compilation.GetTypeByMetadataName("System.Single"); _doubleSymbol = context.Compilation.GetTypeByMetadataName("System.Double"); _byteSymbol = context.Compilation.GetTypeByMetadataName("System.Byte"); @@ -108,7 +110,7 @@ from type in GetNamespaceTypes(module) if (messageType.Name.EndsWith("Params")) { - GenerateUmarshaler(messageType, sb, packValue); + GenerateUnmarshaler(messageType, sb, packValue); } if (messageType.Name.EndsWith("Return")) @@ -263,7 +265,7 @@ private void GenerateMarshaler(INamedTypeSymbol parametersType, IndentedStringBu } } - private void GenerateUmarshaler(INamedTypeSymbol parametersType, IndentedStringBuilder sb, int packValue) + private void GenerateUnmarshaler(INamedTypeSymbol parametersType, IndentedStringBuilder sb, int packValue) { using (sb.BlockInvariant($"public static unmarshal(pData:number) : {parametersType.Name}")) { @@ -344,7 +346,14 @@ private void GenerateUmarshaler(INamedTypeSymbol parametersType, IndentedStringB } else { - sb.AppendLineInvariant($"ret.{field.Name} = {GetTSType(field.Type)}(Module.getValue(pData + {fieldOffset}, \"{GetEMField(field.Type)}\"));"); + if (CanUseEMHeapProperty(field.Type)) + { + sb.AppendLineInvariant($"ret.{field.Name} = Module.{GetEMHeapProperty(field.Type)}[(pData + {fieldOffset}) >> {GetEMTypeShift(field)}];"); + } + else + { + sb.AppendLineInvariant($"ret.{field.Name} = {GetTSType(field.Type)}(Module.getValue(pData + {fieldOffset}, \"{GetEMField(field.Type)}\"));"); + } } } } @@ -362,11 +371,15 @@ private void GenerateUmarshaler(INamedTypeSymbol parametersType, IndentedStringB } } + private bool CanUseEMHeapProperty(ITypeSymbol type) + => SymbolEqualityComparer.Default.Equals(type, _uintSymbol); + private int GetNativeFieldSize(IFieldSymbol field) { - if( + if ( SymbolEqualityComparer.Default.Equals(field.Type, _stringSymbol) || SymbolEqualityComparer.Default.Equals(field.Type, _intSymbol) + || SymbolEqualityComparer.Default.Equals(field.Type, _uintSymbol) || SymbolEqualityComparer.Default.Equals(field.Type, _intPtrSymbol) || SymbolEqualityComparer.Default.Equals(field.Type, _floatSymbol) || SymbolEqualityComparer.Default.Equals(field.Type, _boolSymbol) @@ -375,7 +388,7 @@ private int GetNativeFieldSize(IFieldSymbol field) { return 4; } - else if(SymbolEqualityComparer.Default.Equals(field.Type, _doubleSymbol)) + else if (SymbolEqualityComparer.Default.Equals(field.Type, _doubleSymbol)) { return 8; } @@ -385,6 +398,52 @@ private int GetNativeFieldSize(IFieldSymbol field) } } + private int GetEMTypeShift(IFieldSymbol field) + { + var fieldType = field.Type; + + if ( + SymbolEqualityComparer.Default.Equals(fieldType, _stringSymbol) + || SymbolEqualityComparer.Default.Equals(fieldType, _intPtrSymbol) + || fieldType is IArrayTypeSymbol + ) + { + return 2; + } + else if ( + SymbolEqualityComparer.Default.Equals(fieldType, _intSymbol) + || SymbolEqualityComparer.Default.Equals(fieldType, _uintSymbol) + || SymbolEqualityComparer.Default.Equals(fieldType, _boolSymbol) + ) + { + return 2; + } + else if (SymbolEqualityComparer.Default.Equals(fieldType, _longSymbol)) + { + return 3; + } + else if (SymbolEqualityComparer.Default.Equals(fieldType, _shortSymbol)) + { + return 1; + } + else if (SymbolEqualityComparer.Default.Equals(fieldType, _byteSymbol)) + { + return 0; + } + else if (SymbolEqualityComparer.Default.Equals(fieldType, _floatSymbol)) + { + return 2; + } + else if (SymbolEqualityComparer.Default.Equals(fieldType, _doubleSymbol)) + { + return 3; + } + else + { + throw new NotSupportedException($"Unsupported EM type conversion [{fieldType}]"); + } + } + private static string GetEMField(ITypeSymbol fieldType) { if ( @@ -397,6 +456,7 @@ private static string GetEMField(ITypeSymbol fieldType) } else if ( SymbolEqualityComparer.Default.Equals(fieldType, _intSymbol) + || SymbolEqualityComparer.Default.Equals(fieldType, _uintSymbol) || SymbolEqualityComparer.Default.Equals(fieldType, _boolSymbol) ) { @@ -428,6 +488,49 @@ private static string GetEMField(ITypeSymbol fieldType) } } + private object GetEMHeapProperty(ITypeSymbol fieldType) + { + if ( + SymbolEqualityComparer.Default.Equals(fieldType, _stringSymbol) + || SymbolEqualityComparer.Default.Equals(fieldType, _intPtrSymbol) + || fieldType is IArrayTypeSymbol + || SymbolEqualityComparer.Default.Equals(fieldType, _intSymbol) + || SymbolEqualityComparer.Default.Equals(fieldType, _boolSymbol) + ) + { + return "HEAP32"; + } + else if (SymbolEqualityComparer.Default.Equals(fieldType, _uintSymbol)) + { + return "HEAPU32"; + } + else if (SymbolEqualityComparer.Default.Equals(fieldType, _longSymbol)) + { + // Might overflow + return "HEAP32"; + } + else if (SymbolEqualityComparer.Default.Equals(fieldType, _shortSymbol)) + { + return "HEAP16"; + } + else if (SymbolEqualityComparer.Default.Equals(fieldType, _byteSymbol)) + { + return "HEAP8"; + } + else if (SymbolEqualityComparer.Default.Equals(fieldType, _floatSymbol)) + { + return "HEAPF32"; + } + else if (SymbolEqualityComparer.Default.Equals(fieldType, _doubleSymbol)) + { + return "HEAPF64"; + } + else + { + throw new NotSupportedException($"Unsupported EM type conversion [{fieldType}]"); + } + } + private static string GetTSType(ITypeSymbol type) { if (type == null) @@ -445,6 +548,7 @@ private static string GetTSType(ITypeSymbol type) } else if ( SymbolEqualityComparer.Default.Equals(type, _intSymbol) + || SymbolEqualityComparer.Default.Equals(type, _uintSymbol) || SymbolEqualityComparer.Default.Equals(type, _floatSymbol) || SymbolEqualityComparer.Default.Equals(type, _doubleSymbol) || SymbolEqualityComparer.Default.Equals(type, _byteSymbol) @@ -481,6 +585,7 @@ private static string GetTSFieldType(ITypeSymbol type) } else if ( SymbolEqualityComparer.Default.Equals(type, _intSymbol) + || SymbolEqualityComparer.Default.Equals(type, _uintSymbol) || SymbolEqualityComparer.Default.Equals(type, _floatSymbol) || SymbolEqualityComparer.Default.Equals(type, _doubleSymbol) || SymbolEqualityComparer.Default.Equals(type, _byteSymbol) diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.wasm.cs b/src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.wasm.cs index 3369736d1f2a..c614f39d7f78 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.wasm.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.wasm.cs @@ -6,7 +6,6 @@ using Uno.Extensions; using Uno.Foundation; using System.Linq; -using Uno.UI.UI.Xaml.Documents; using Microsoft.Extensions.Logging; using Windows.UI.Text; using Windows.UI.Xaml.Media; diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.wasm.cs b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.wasm.cs index eae55a306eb2..b8fb07f0afef 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.wasm.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.wasm.cs @@ -1,5 +1,4 @@ using Uno.Extensions; -using Uno.UI.UI.Xaml.Documents; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.wasm.cs b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.wasm.cs index 827e9759432e..1af845163cce 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.wasm.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.wasm.cs @@ -7,7 +7,6 @@ using Uno.Logging; using Windows.Foundation; using System.Globalization; -using Uno.UI.UI.Xaml.Documents; using Uno.Disposables; namespace Windows.UI.Xaml.Controls diff --git a/src/Uno.UI/UI/Xaml/Documents/Run.wasm.cs b/src/Uno.UI/UI/Xaml/Documents/Run.wasm.cs index 24486b168060..a3cb754b767f 100644 --- a/src/Uno.UI/UI/Xaml/Documents/Run.wasm.cs +++ b/src/Uno.UI/UI/Xaml/Documents/Run.wasm.cs @@ -1,5 +1,4 @@ using System.Web; -using Uno.UI.UI.Xaml.Documents; namespace Windows.UI.Xaml.Documents { diff --git a/src/Uno.UI/UI/Xaml/Documents/TextElement.wasm.cs b/src/Uno.UI/UI/Xaml/Documents/TextElement.wasm.cs index 0bcdb15bc2fb..fc8410b8b246 100644 --- a/src/Uno.UI/UI/Xaml/Documents/TextElement.wasm.cs +++ b/src/Uno.UI/UI/Xaml/Documents/TextElement.wasm.cs @@ -1,6 +1,4 @@ -using Uno.UI.UI.Xaml.Documents; - -namespace Windows.UI.Xaml.Documents +namespace Windows.UI.Xaml.Documents { partial class TextElement { diff --git a/src/Uno.UI/UI/Xaml/UIElement.TextHelper.wasm.cs b/src/Uno.UI/UI/Xaml/UIElement.TextHelper.wasm.cs index 8f28489fbb0e..b5c50fd0a923 100644 --- a/src/Uno.UI/UI/Xaml/UIElement.TextHelper.wasm.cs +++ b/src/Uno.UI/UI/Xaml/UIElement.TextHelper.wasm.cs @@ -9,6 +9,7 @@ using Uno.Collections; using Uno.Disposables; using Uno.Extensions; +using Uno.UI.Xaml; namespace Windows.UI.Xaml { @@ -155,7 +156,7 @@ internal void SetForeground(object localValue) switch (localValue) { case SolidColorBrush scb: - this.SetStyle("color", scb.ColorWithOpacity.ToHexString()); + WindowManagerInterop.SetElementColor(HtmlId, scb.ColorWithOpacity); break; case GradientBrush gradient: this.SetStyle( diff --git a/src/Uno.UI/UI/Xaml/WindowManagerInterop.wasm.cs b/src/Uno.UI/UI/Xaml/WindowManagerInterop.wasm.cs index 6b7f06e98538..02063e3e2e0f 100644 --- a/src/Uno.UI/UI/Xaml/WindowManagerInterop.wasm.cs +++ b/src/Uno.UI/UI/Xaml/WindowManagerInterop.wasm.cs @@ -10,6 +10,7 @@ using Uno.Foundation; using Uno.Foundation.Interop; using Windows.Foundation; +using Windows.UI; using Windows.UI.Xaml; namespace Uno.UI.Xaml @@ -826,6 +827,43 @@ private struct WindowManagerSetPropertyParams #endregion + #region SetVisibility + + internal static void SetElementColor(IntPtr htmlId, Color color) + { + var colorAsInteger = + (uint)(color.R << 24) + | (uint)(color.G << 16) + | (uint)(color.B << 8) + | color.A; + + if (UseJavascriptEval) + { + var command = $"Uno.UI.WindowManager.current.setElementColor(\"{htmlId}\", {color});"; + WebAssemblyRuntime.InvokeJS(command); + } + else + { + var parms = new WindowManagerSetElementColorParams() + { + HtmlId = htmlId, + Color = colorAsInteger, + }; + + TSInteropMarshaller.InvokeJS("Uno:setElementColorNative", parms); + } + } + + [TSInteropMessage] + [StructLayout(LayoutKind.Sequential, Pack = 4)] + private struct WindowManagerSetElementColorParams + { + public IntPtr HtmlId; + + public uint Color; + } + #endregion + #region RemoveView internal static void RemoveView(IntPtr htmlId, IntPtr childId) { diff --git a/src/Uno.UI/WasmScripts/Uno.UI.d.ts b/src/Uno.UI/WasmScripts/Uno.UI.d.ts index 7b6e0c56eba4..54d53790b4a0 100644 --- a/src/Uno.UI/WasmScripts/Uno.UI.d.ts +++ b/src/Uno.UI/WasmScripts/Uno.UI.d.ts @@ -318,6 +318,12 @@ declare namespace Uno.UI { private setAsArranged; private setAsUnarranged; /** + * Sets the visibility of the specified element + */ + setElementColor(elementId: number, color: number): string; + setElementColorNative(pParam: number): boolean; + private setElementColorInternal; + /** * Sets the transform matrix of an element * */ @@ -1332,6 +1338,11 @@ declare class WindowManagerSetContentHtmlParams { Html: string; static unmarshal(pData: number): WindowManagerSetContentHtmlParams; } +declare class WindowManagerSetElementColorParams { + HtmlId: number; + Color: number; + static unmarshal(pData: number): WindowManagerSetElementColorParams; +} declare class WindowManagerSetElementTransformParams { HtmlId: number; M11: number; diff --git a/src/Uno.UI/WasmScripts/Uno.UI.js b/src/Uno.UI/WasmScripts/Uno.UI.js index 298164977f66..936476a487d7 100644 --- a/src/Uno.UI/WasmScripts/Uno.UI.js +++ b/src/Uno.UI/WasmScripts/Uno.UI.js @@ -830,6 +830,22 @@ var Uno; } } /** + * Sets the visibility of the specified element + */ + setElementColor(elementId, color) { + this.setElementColorInternal(elementId, color); + return "ok"; + } + setElementColorNative(pParam) { + const params = WindowManagerSetElementColorParams.unmarshal(pParam); + this.setElementColorInternal(params.HtmlId, params.Color); + return true; + } + setElementColorInternal(elementId, color) { + const element = this.getView(elementId); + element.style.setProperty("color", "#" + color.toString(16).padStart(8, '0')); + } + /** * Sets the transform matrix of an element * */ @@ -4783,6 +4799,19 @@ class WindowManagerSetContentHtmlParams { } } /* TSBindingsGenerator Generated code -- this code is regenerated on each build */ +class WindowManagerSetElementColorParams { + static unmarshal(pData) { + const ret = new WindowManagerSetElementColorParams(); + { + ret.HtmlId = Number(Module.getValue(pData + 0, "*")); + } + { + ret.Color = Module.HEAPU32[(pData + 4) >> 2]; + } + return ret; + } +} +/* TSBindingsGenerator Generated code -- this code is regenerated on each build */ class WindowManagerSetElementTransformParams { static unmarshal(pData) { const ret = new WindowManagerSetElementTransformParams(); diff --git a/src/Uno.UI/ts/WindowManager.ts b/src/Uno.UI/ts/WindowManager.ts index d7cbf2fe3d76..ad368f7d9ee0 100644 --- a/src/Uno.UI/ts/WindowManager.ts +++ b/src/Uno.UI/ts/WindowManager.ts @@ -679,6 +679,27 @@ namespace Uno.UI { } } + + /** + * Sets the color property of the specified element + */ + public setElementColor(elementId: number, color: number): string { + this.setElementColorInternal(elementId, color); + return "ok"; + } + + public setElementColorNative(pParam: number): boolean { + const params = WindowManagerSetElementColorParams.unmarshal(pParam); + this.setElementColorInternal(params.HtmlId, params.Color); + return true; + } + + private setElementColorInternal(elementId: number, color: number): void { + const element = this.getView(elementId); + + element.style.setProperty("color", "#" + color.toString(16).padStart(8, '0')); + } + /** * Sets the transform matrix of an element * diff --git a/src/Uno.UI/tsBindings/WindowManagerSetElementColorParams.ts b/src/Uno.UI/tsBindings/WindowManagerSetElementColorParams.ts new file mode 100644 index 000000000000..116d4b865c00 --- /dev/null +++ b/src/Uno.UI/tsBindings/WindowManagerSetElementColorParams.ts @@ -0,0 +1,20 @@ +/* TSBindingsGenerator Generated code -- this code is regenerated on each build */ +class WindowManagerSetElementColorParams +{ + /* Pack=4 */ + public HtmlId : number; + public Color : number; + public static unmarshal(pData:number) : WindowManagerSetElementColorParams + { + const ret = new WindowManagerSetElementColorParams(); + + { + ret.HtmlId = Number(Module.getValue(pData + 0, "*")); + } + + { + ret.Color = Module.HEAPU32[(pData + 4) >> 2]; + } + return ret; + } +}