diff --git a/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs b/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs index 319a6701832b..a6f79cb30fbd 100644 --- a/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs +++ b/src/Uno.UI.Runtime.Skia.Gtk/UI/Xaml/Controls/TextBoxViewExtension.cs @@ -14,6 +14,7 @@ using Point = Windows.Foundation.Point; using Scale = Pango.Scale; using System.Diagnostics; +using Windows.UI.Xaml.Media; namespace Uno.UI.Runtime.Skia.GTK.Extensions.UI.Xaml.Controls { @@ -329,5 +330,19 @@ public int GetSelectionLength() return 0; } + + public void SetForeground(Windows.UI.Xaml.Media.Brush brush) + { + if (brush is SolidColorBrush scb) + { + _currentInputWidget?.OverrideColor(StateFlags.Normal, new Gdk.RGBA + { + Red = scb.ColorWithOpacity.R, + Green = scb.ColorWithOpacity.G, + Blue = scb.ColorWithOpacity.B, + Alpha = scb.ColorWithOpacity.A + }); + } + } } } diff --git a/src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/Extensions.cs b/src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/Extensions.cs new file mode 100644 index 000000000000..22976d94a01e --- /dev/null +++ b/src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/Extensions.cs @@ -0,0 +1,148 @@ +#nullable enable + +using System.Linq; +using System.Diagnostics; + +namespace Uno.UI.Runtime.Skia.WPF.Extensions.UI.Xaml.Controls +{ + internal static class Extensions + { + public static System.Windows.Media.Brush? ToWpfBrush(this Windows.UI.Xaml.Media.Brush brush) + { + if (brush is Windows.UI.Xaml.Media.SolidColorBrush solidBrush) + { + return new System.Windows.Media.SolidColorBrush(solidBrush.Color.ToWpfColor()) { Opacity = solidBrush.Opacity }; + } + else if (brush is Windows.UI.Xaml.Media.LinearGradientBrush gradientBrush) + { + return new System.Windows.Media.LinearGradientBrush(gradientBrush.GradientStops.ToWpfGradientStopCollection(), gradientBrush.StartPoint.ToWpfPoint(), gradientBrush.EndPoint.ToWpfPoint()) + { + MappingMode = gradientBrush.MappingMode.ToWpfBrushMappingMode(), + Transform = gradientBrush.Transform.ToWpfTransform(), + RelativeTransform = gradientBrush.RelativeTransform.ToWpfTransform(), + }; + } + else if (brush is Windows.UI.Xaml.Media.ImageBrush imageBrush) + { + return new System.Windows.Media.ImageBrush(imageBrush.ImageSource.ToWpfImageSource()) + { + AlignmentX = imageBrush.AlignmentX.ToWpfAlignmentX(), + AlignmentY = imageBrush.AlignmentY.ToWpfAlignmentY(), + Opacity = imageBrush.Opacity, + Stretch = imageBrush.Stretch.ToWpfStretch(), + Transform = imageBrush.Transform.ToWpfTransform(), + RelativeTransform = imageBrush.RelativeTransform.ToWpfTransform(), + }; + } + + // TODO: Support more brushes. + return null; + } + + private static System.Windows.Media.Color ToWpfColor(this Windows.UI.Color color) + => System.Windows.Media.Color.FromArgb(color.A, color.R, color.G, color.B); + + private static System.Windows.Point ToWpfPoint(this Windows.Foundation.Point point) + => new System.Windows.Point(point.X, point.Y); + + private static System.Windows.Media.GradientStopCollection ToWpfGradientStopCollection(this Windows.UI.Xaml.Media.GradientStopCollection gradientStops) + => new System.Windows.Media.GradientStopCollection(gradientStops.Select(stop => stop.ToWpfGradientStop())); + + private static System.Windows.Media.GradientStop ToWpfGradientStop(this Windows.UI.Xaml.Media.GradientStop gradientStop) + => new System.Windows.Media.GradientStop(gradientStop.Color.ToWpfColor(), gradientStop.Offset); + + private static System.Windows.Media.ImageSource? ToWpfImageSource(this Windows.UI.Xaml.Media.ImageSource imageSource) + { + if (imageSource is Windows.UI.Xaml.Media.Imaging.BitmapImage bitmapSource) + { + new System.Windows.Media.Imaging.BitmapImage(bitmapSource.UriSource); + } + + // TODO: Support more image sources. + return null; + } + + private static System.Windows.Media.AlignmentX ToWpfAlignmentX(this Windows.UI.Xaml.Media.AlignmentX alignment) + { + Debug.Assert((int)System.Windows.Media.AlignmentX.Left == (int)Windows.UI.Xaml.Media.AlignmentX.Left); + Debug.Assert((int)System.Windows.Media.AlignmentX.Right == (int)Windows.UI.Xaml.Media.AlignmentX.Right); + Debug.Assert((int)System.Windows.Media.AlignmentX.Center == (int)Windows.UI.Xaml.Media.AlignmentX.Center); + return (System.Windows.Media.AlignmentX)alignment; + } + + private static System.Windows.Media.AlignmentY ToWpfAlignmentY(this Windows.UI.Xaml.Media.AlignmentY alignment) + { + Debug.Assert((int)System.Windows.Media.AlignmentY.Top == (int)Windows.UI.Xaml.Media.AlignmentY.Top); + Debug.Assert((int)System.Windows.Media.AlignmentY.Center == (int)Windows.UI.Xaml.Media.AlignmentY.Center); + Debug.Assert((int)System.Windows.Media.AlignmentY.Bottom == (int)Windows.UI.Xaml.Media.AlignmentY.Bottom); + return (System.Windows.Media.AlignmentY)alignment; + } + + private static System.Windows.Media.Stretch ToWpfStretch(this Windows.UI.Xaml.Media.Stretch stretch) + { + Debug.Assert((int)System.Windows.Media.Stretch.None == (int)Windows.UI.Xaml.Media.Stretch.None); + Debug.Assert((int)System.Windows.Media.Stretch.Fill == (int)Windows.UI.Xaml.Media.Stretch.Fill); + Debug.Assert((int)System.Windows.Media.Stretch.Uniform == (int)Windows.UI.Xaml.Media.Stretch.Uniform); + Debug.Assert((int)System.Windows.Media.Stretch.UniformToFill == (int)Windows.UI.Xaml.Media.Stretch.UniformToFill); + return (System.Windows.Media.Stretch)stretch; + } + + private static System.Windows.Media.Transform ToWpfTransform(this Windows.UI.Xaml.Media.Transform transform) + { + if (transform is Windows.UI.Xaml.Media.MatrixTransform matrixTransform) + { + return new System.Windows.Media.MatrixTransform( + m11: matrixTransform.Matrix.M11, + m12: matrixTransform.Matrix.M12, + m21: matrixTransform.Matrix.M21, + m22: matrixTransform.Matrix.M22, + offsetX: matrixTransform.Matrix.OffsetX, + offsetY: matrixTransform.Matrix.OffsetY); + } + else if (transform is Windows.UI.Xaml.Media.RotateTransform rotateTransform) + { + return new System.Windows.Media.RotateTransform( + angle: rotateTransform.Angle, + centerX: rotateTransform.CenterX, + centerY: rotateTransform.CenterY); + } + else if (transform is Windows.UI.Xaml.Media.ScaleTransform scaleTransform) + { + return new System.Windows.Media.ScaleTransform( + scaleX: scaleTransform.ScaleX, + scaleY: scaleTransform.ScaleY, + centerX: scaleTransform.CenterX, + centerY: scaleTransform.CenterY); + } + else if (transform is Windows.UI.Xaml.Media.SkewTransform skewTransform) + { + return new System.Windows.Media.SkewTransform( + angleX: skewTransform.AngleX, + angleY: skewTransform.AngleY, + centerX: skewTransform.CenterX, + centerY: skewTransform.CenterY); + } + else if (transform is Windows.UI.Xaml.Media.TransformGroup transformGroup) + { + return new System.Windows.Media.TransformGroup() + { + Children = new System.Windows.Media.TransformCollection(transformGroup.Children.Select(g => g.ToWpfTransform())) + }; + } + else if (transform is Windows.UI.Xaml.Media.TranslateTransform translateTransform) + { + return new System.Windows.Media.TranslateTransform(translateTransform.X, translateTransform.Y); + } + + return null; + } + + private static System.Windows.Media.BrushMappingMode ToWpfBrushMappingMode(this Windows.UI.Xaml.Media.BrushMappingMode mappingMode) + { + Debug.Assert((int)System.Windows.Media.BrushMappingMode.Absolute == (int)Windows.UI.Xaml.Media.BrushMappingMode.Absolute); + Debug.Assert((int)System.Windows.Media.BrushMappingMode.RelativeToBoundingBox == (int)Windows.UI.Xaml.Media.BrushMappingMode.RelativeToBoundingBox); + + return (System.Windows.Media.BrushMappingMode)mappingMode; + } + } +} diff --git a/src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/TextBoxViewExtension.cs b/src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/TextBoxViewExtension.cs index 011807e616fd..1eba74dfaa50 100644 --- a/src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/TextBoxViewExtension.cs +++ b/src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/TextBoxViewExtension.cs @@ -2,17 +2,13 @@ using System; using System.Windows; -using System.Windows.Media; -using System.Windows.Threading; using Windows.UI.Xaml.Controls; using Uno.Disposables; using Uno.UI.Runtime.Skia.WPF.Controls; using Uno.UI.Skia.Platform; using Uno.UI.Xaml.Controls.Extensions; using Point = Windows.Foundation.Point; -using SolidColorBrush = Windows.UI.Xaml.Media.SolidColorBrush; using WpfCanvas = System.Windows.Controls.Canvas; -using WpfTextBox = System.Windows.Controls.TextBox; namespace Uno.UI.Runtime.Skia.WPF.Extensions.UI.Xaml.Controls { @@ -101,12 +97,7 @@ public void UpdateNativeView() _currentInputWidget.TextWrapping = textBox.AcceptsReturn ? TextWrapping.Wrap : TextWrapping.NoWrap; _currentInputWidget.MaxLength = textBox.MaxLength; _currentInputWidget.IsReadOnly = textBox.IsReadOnly; - - if (textBox.Foreground is SolidColorBrush colorBrush) - { - var unoColor = colorBrush.Color; - _currentInputWidget.Foreground = new System.Windows.Media.SolidColorBrush(Color.FromArgb(unoColor.A, unoColor.R, unoColor.G, unoColor.B)); - } + _currentInputWidget.Foreground = textBox.Foreground.ToWpfBrush(); } public void UpdateSize() @@ -193,5 +184,13 @@ public void SetIsPassword(bool isPassword) public int GetSelectionStart() => _currentInputWidget?.SelectionStart ?? 0; public int GetSelectionLength() => _currentInputWidget?.SelectionLength ?? 0; + + public void SetForeground(Windows.UI.Xaml.Media.Brush brush) + { + if (_currentInputWidget != null) + { + _currentInputWidget.Foreground = brush.ToWpfBrush(); + } + } } } diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBox/ITextBoxExtension.skia.cs b/src/Uno.UI/UI/Xaml/Controls/TextBox/ITextBoxExtension.skia.cs index ea5ca16aea36..68e652ff811a 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBox/ITextBoxExtension.skia.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBox/ITextBoxExtension.skia.cs @@ -1,4 +1,5 @@ using Windows.Foundation; +using Windows.UI.Xaml.Media; namespace Uno.UI.Xaml.Controls.Extensions { @@ -23,5 +24,7 @@ internal interface ITextBoxViewExtension int GetSelectionStart(); int GetSelectionLength(); + + void SetForeground(Brush brush); } } diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.skia.cs b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.skia.cs index cfe54f8326f2..c9a255eec957 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.skia.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.skia.cs @@ -11,7 +11,7 @@ namespace Windows.UI.Xaml.Controls { internal class TextBoxView { - private readonly ITextBoxViewExtension _textBoxExtension; + private readonly ITextBoxViewExtension? _textBoxExtension; private readonly WeakReference _textBox; private readonly bool _isPasswordBox; @@ -54,7 +54,7 @@ public TextBox? TextBox internal void SetTextNative(string text) { // TODO: Inheritance hierarchy is wrong in Uno. PasswordBox shouldn't inherit TextBox. - // This needs to be moved to PasswordBox when it's separated from TextBox (likely in Uno 4). + // This needs to be moved to PasswordBox if it's separated from TextBox. if (_isPasswordBox && !_isPasswordRevealed) { // TODO: PasswordChar isn't currently implemented. It should be used here when implemented. @@ -70,10 +70,14 @@ internal void SetTextNative(string text) internal void Select(int start, int length) { - _textBoxExtension.Select(start, length); + _textBoxExtension?.Select(start, length); } - internal void OnForegroundChanged(Brush brush) => DisplayBlock.Foreground = brush; + internal void OnForegroundChanged(Brush brush) + { + DisplayBlock.Foreground = brush; + _textBoxExtension?.SetForeground(brush); + } internal void OnFocusStateChanged(FocusState focusState) {