Skip to content

Commit

Permalink
feat(GTK): Support for some GTK TextBox visual properties, clear button
Browse files Browse the repository at this point in the history
- Some visual properties of TextBox now properly flow to native
- Clear button works
  • Loading branch information
MartinZikmund committed Apr 15, 2021
1 parent 19e6680 commit 8f7ab5c
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#nullable enable
using System;
using System.Runtime.InteropServices;
using Gtk;
using Windows.Graphics.Display;
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/Uno.UI.Runtime.Skia.Gtk/Theming/UnoGtk.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.textboxview, .textboxview:active, .textboxview:hover, .textboxview:focus {
.textboxview, .textboxview:active, .textboxview:hover, .textboxview:focus, .textboxview text {
min-height: 0px;
background-color: transparent;
border-color: transparent;
Expand Down
16 changes: 16 additions & 0 deletions src/Uno.UI.Runtime.Skia.Gtk/UI/Text/FontWeightExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Windows.UI.Text;
using Pango;

namespace Uno.UI.Runtime.Skia.GTK.UI.Text
{
public static class FontWeightExtensions
{
/// <summary>
/// Based on <see cref="https://github.com/GNOME/pango/blob/master/pango/pango-font.h" />
/// and <see cref="https://docs.microsoft.com/en-us/uwp/api/windows.ui.text.fontweights?view=winrt-19041" />.
/// </summary>
/// <param name="weight">Font weight.</param>
/// <returns>Pango weight.</returns>
public static Weight ToPangoWeight(this FontWeight weight) => (Weight)weight.Weight;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
using System.Linq;
using Gtk;
using Uno.UI.Xaml.Controls.Extensions;
using Windows.Foundation;
using Windows.UI.Xaml.Controls;
using GLib;
using Pango;
using Uno.Disposables;
using Uno.UI.Runtime.Skia.GTK.UI.Text;
using GtkWindow = Gtk.Window;
using Object = GLib.Object;
using Point = Windows.Foundation.Point;
using Scale = Pango.Scale;

namespace Uno.UI.Runtime.Skia.GTK.Extensions.UI.Xaml.Controls
{
Expand All @@ -21,6 +25,8 @@ internal class TextBoxViewExtension : ITextBoxViewExtension
private ContentControl? _contentElement;
private Widget? _currentInputWidget;

private SerialDisposable _textChangedDisposable = new SerialDisposable();

public TextBoxViewExtension(TextBoxView owner, GtkWindow window)
{
_owner = owner ?? throw new ArgumentNullException(nameof(owner));
Expand Down Expand Up @@ -48,10 +54,10 @@ public void StartEntry()
var textInputLayer = GetWindowTextInputLayer();
textInputLayer.Put(_currentInputWidget!, 0, 0);

_contentElement.SizeChanged += _contentElement_SizeChanged;
_contentElement.LayoutUpdated += _contentElement_LayoutUpdated;
_contentElement.SizeChanged += ContentElementSizeChanged;
_contentElement.LayoutUpdated += ContentElementLayoutUpdated;
UpdateNativeView();
SetInputText(textBox.Text);
SetWidgetText(textBox.Text);

UpdateSize();
UpdatePosition();
Expand All @@ -60,29 +66,17 @@ public void StartEntry()
_currentInputWidget!.HasFocus = true;
}

private void _contentElement_LayoutUpdated(object sender, object e)
{
UpdateSize();
UpdatePosition();
}

private void _contentElement_SizeChanged(object sender, Windows.UI.Xaml.SizeChangedEventArgs args)
{
UpdateSize();
UpdatePosition();
}

public void EndEntry()
{
if (GetInputText() is { } inputText)
{
_owner.UpdateText(inputText);
_owner.UpdateTextFromNative(inputText);
}

if (_contentElement != null)
{
_contentElement.SizeChanged -= _contentElement_SizeChanged;
_contentElement.LayoutUpdated -= _contentElement_LayoutUpdated;
_contentElement.SizeChanged -= ContentElementSizeChanged;
_contentElement.LayoutUpdated -= ContentElementLayoutUpdated;
}

var textInputLayer = GetWindowTextInputLayer();
Expand All @@ -106,8 +100,68 @@ public void UpdateNativeView()

EnsureWidgetForAcceptsReturn(textBox.AcceptsReturn);

var fontSize = new Value(GType.Double) { Val = textBox.FontSize };
_currentInputWidget.StyleContext.SetProperty("font-size", fontSize);
var fontDescription = new FontDescription
{
Weight = textBox.FontWeight.ToPangoWeight(),
AbsoluteSize = textBox.FontSize * Scale.PangoScale,
};
#pragma warning disable CS0612 // Type or member is obsolete
_currentInputWidget.OverrideFont(fontDescription);
#pragma warning restore CS0612 // Type or member is obsolete

switch (_currentInputWidget)
{
case Entry entry:
UpdateEntryProperties(entry, textBox);
break;
case TextView textView:
UpdateTextViewProperties(textView, textBox);
break;
}
}

public void UpdateSize()
{
if (_contentElement == null || _currentInputWidget == null)
{
return;
}

var textInputLayer = GetWindowTextInputLayer();
if (textInputLayer.Children.Contains(_currentInputWidget))
{
_currentInputWidget?.SetSizeRequest((int)_contentElement.ActualWidth, (int)_contentElement.ActualHeight);
}
}

public void UpdatePosition()
{
if (_contentElement == null || _currentInputWidget == null)
{
return;
}

var transformToRoot = _contentElement.TransformToVisual(Windows.UI.Xaml.Window.Current.Content);
var point = transformToRoot.TransformPoint(new Point(0, 0));
var textInputLayer = GetWindowTextInputLayer();
if (textInputLayer.Children.Contains(_currentInputWidget))
{
textInputLayer.Move(_currentInputWidget, (int)point.X, (int)point.Y);
}
}

public void SetTextNative(string text) => SetWidgetText(text);

private void UpdateTextViewProperties(TextView textView, TextBox textBox)
{
textView.Editable = !textBox.IsReadOnly;
}

private void UpdateEntryProperties(Entry entry, TextBox textBox)
{
entry.IsEditable = !textBox.IsReadOnly;
entry.MaxLength = textBox.MaxLength;

}

private void EnsureWidgetForAcceptsReturn(bool acceptsReturn)
Expand All @@ -119,7 +173,7 @@ private void EnsureWidgetForAcceptsReturn(bool acceptsReturn)
{
var inputText = GetInputText();
_currentInputWidget = CreateInputWidget(acceptsReturn);
SetInputText(inputText ?? string.Empty);
SetWidgetText(inputText ?? string.Empty);
}
}

Expand All @@ -128,16 +182,25 @@ private Widget CreateInputWidget(bool acceptsReturn)
Widget widget;
if (acceptsReturn)
{
widget = new TextView();
var textView = new TextView();
textView.Buffer.Changed += WidgetTextChanged;
_textChangedDisposable.Disposable = Disposable.Create(() => textView.Buffer.Changed -= WidgetTextChanged);
widget = textView;
}
else
{
widget = new Entry();
var entry = new Entry();
entry.Changed += WidgetTextChanged;
_textChangedDisposable.Disposable = Disposable.Create(() => entry.Changed -= WidgetTextChanged);
widget = entry;
}
widget.StyleContext.AddClass(TextBoxViewCssClass);
return widget;
}

private void WidgetTextChanged(object? sender, EventArgs e) =>
_owner.UpdateTextFromNative(GetInputText() ?? string.Empty);

private string? GetInputText() =>
_currentInputWidget switch
{
Expand All @@ -146,7 +209,7 @@ private Widget CreateInputWidget(bool acceptsReturn)
_ => null
};

private void SetInputText(string text)
private void SetWidgetText(string text)
{
switch (_currentInputWidget)
{
Expand All @@ -159,34 +222,16 @@ private void SetInputText(string text)
};
}

public void UpdateSize()
private void ContentElementLayoutUpdated(object? sender, object e)
{
if (_contentElement == null || _currentInputWidget == null)
{
return;
}

var textInputLayer = GetWindowTextInputLayer();
if (textInputLayer.Children.Contains(_currentInputWidget))
{
_currentInputWidget?.SetSizeRequest((int)_contentElement.ActualWidth, (int)_contentElement.ActualHeight);
}
UpdateSize();
UpdatePosition();
}

public void UpdatePosition()
private void ContentElementSizeChanged(object sender, Windows.UI.Xaml.SizeChangedEventArgs args)
{
if (_contentElement == null || _currentInputWidget == null)
{
return;
}

var transformToRoot = _contentElement.TransformToVisual(Windows.UI.Xaml.Window.Current.Content);
var point = transformToRoot.TransformPoint(new Point(0, 0));
var textInputLayer = GetWindowTextInputLayer();
if (textInputLayer.Children.Contains(_currentInputWidget))
{
textInputLayer.Move(_currentInputWidget, (int)point.X, (int)point.Y);
}
UpdateSize();
UpdatePosition();
}
}
}

0 comments on commit 8f7ab5c

Please sign in to comment.