зеркало из https://github.com/DeGsoft/maui-linux.git
Implemented Editor Placeholder and PlaceholderColor in GTK (#3135)
This commit is contained in:
Родитель
295bcdfe5e
Коммит
673cffb1ab
|
@ -2,45 +2,134 @@
|
|||
|
||||
namespace Xamarin.Forms.Platform.GTK.Controls
|
||||
{
|
||||
public class ScrolledTextView : ScrolledWindow
|
||||
{
|
||||
private TextView _textView;
|
||||
private int _maxLength;
|
||||
public class ScrolledTextView : EventBox
|
||||
{
|
||||
private Table _table;
|
||||
private ScrolledWindow _scrolledWindow;
|
||||
private Gtk.Label _placeholder;
|
||||
private EventBox _placeholderContainer;
|
||||
private int _maxLength;
|
||||
|
||||
public ScrolledTextView()
|
||||
{
|
||||
ShadowType = ShadowType.In;
|
||||
HscrollbarPolicy = PolicyType.Never;
|
||||
VscrollbarPolicy = PolicyType.Always;
|
||||
public ScrolledTextView()
|
||||
{
|
||||
_table = new Table(1, 1, true);
|
||||
|
||||
_textView = new TextView
|
||||
{
|
||||
AcceptsTab = false,
|
||||
WrapMode = WrapMode.WordChar
|
||||
};
|
||||
TextView = new TextView
|
||||
{
|
||||
AcceptsTab = false,
|
||||
WrapMode = WrapMode.WordChar
|
||||
};
|
||||
|
||||
_textView.Buffer.InsertText += InsertText;
|
||||
Add(_textView);
|
||||
}
|
||||
TextView.Buffer.InsertText += InsertText;
|
||||
TextView.FocusOutEvent += FocusedOut;
|
||||
|
||||
public TextView TextView => _textView;
|
||||
_scrolledWindow = new ScrolledWindow
|
||||
{
|
||||
ShadowType = ShadowType.In,
|
||||
HscrollbarPolicy = PolicyType.Never,
|
||||
VscrollbarPolicy = PolicyType.Automatic
|
||||
};
|
||||
|
||||
public void SetMaxLength(int maxLength)
|
||||
{
|
||||
_maxLength = maxLength;
|
||||
_scrolledWindow.Add(TextView);
|
||||
|
||||
if (_textView.Buffer.CharCount > maxLength)
|
||||
_textView.Buffer.Text = _textView.Buffer.Text.Substring(0, maxLength);
|
||||
}
|
||||
_placeholder = new Gtk.Label();
|
||||
_placeholder.SetAlignment(0, 0);
|
||||
|
||||
protected override void OnFocusGrabbed()
|
||||
{
|
||||
_textView?.GrabFocus();
|
||||
}
|
||||
_placeholderContainer = new EventBox
|
||||
{
|
||||
BorderWidth = 2
|
||||
};
|
||||
|
||||
void InsertText(object o, InsertTextArgs args)
|
||||
{
|
||||
args.RetVal = args.Length <= _maxLength;
|
||||
}
|
||||
}
|
||||
_placeholderContainer.Add(_placeholder);
|
||||
|
||||
_placeholderContainer.ButtonPressEvent += PlaceHolderContainerPressed;
|
||||
|
||||
SetBackgroundColor(TextView.Style.BaseColors[(int)StateType.Normal]);
|
||||
|
||||
Add(_table);
|
||||
|
||||
_table.Attach(_placeholderContainer, 0, 1, 0, 1, AttachOptions.Fill, AttachOptions.Fill, 0, 0);
|
||||
_table.Attach(_scrolledWindow, 0, 1, 0, 1);
|
||||
}
|
||||
|
||||
public TextView TextView { get; }
|
||||
|
||||
public string PlaceholderText
|
||||
{
|
||||
get
|
||||
{
|
||||
return _placeholder.Text;
|
||||
}
|
||||
set
|
||||
{
|
||||
_placeholder.Text = GLib.Markup.EscapeText(value ?? string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBackgroundColor(Gdk.Color color)
|
||||
{
|
||||
ModifyBg(StateType.Normal, color);
|
||||
TextView.ModifyBase(StateType.Normal, color);
|
||||
_placeholderContainer.ModifyBg(StateType.Normal, color);
|
||||
}
|
||||
|
||||
public void SetPlaceholderTextColor(Gdk.Color color)
|
||||
{
|
||||
_placeholder.ModifyFg(StateType.Normal, color);
|
||||
}
|
||||
|
||||
public void SetMaxLength(int maxLength)
|
||||
{
|
||||
_maxLength = maxLength;
|
||||
|
||||
if (TextView.Buffer.CharCount > maxLength)
|
||||
TextView.Buffer.Text = TextView.Buffer.Text.Substring(0, maxLength);
|
||||
}
|
||||
|
||||
protected override void OnFocusGrabbed()
|
||||
{
|
||||
TextView?.GrabFocus();
|
||||
}
|
||||
|
||||
protected override void OnSizeAllocated(Gdk.Rectangle allocation)
|
||||
{
|
||||
base.OnSizeAllocated(allocation);
|
||||
|
||||
TextView.SetSizeRequest(allocation.Width, allocation.Height);
|
||||
|
||||
ShowPlaceholderIfNeeded();
|
||||
}
|
||||
|
||||
private void InsertText(object o, InsertTextArgs args)
|
||||
{
|
||||
args.RetVal = args.Length <= _maxLength;
|
||||
}
|
||||
|
||||
private void FocusedOut(object o, FocusOutEventArgs args)
|
||||
{
|
||||
ShowPlaceholderIfNeeded();
|
||||
}
|
||||
|
||||
private void ShowPlaceholderIfNeeded()
|
||||
{
|
||||
if (string.IsNullOrEmpty(TextView.Buffer.Text) && !string.IsNullOrEmpty(_placeholder.Text))
|
||||
{
|
||||
_placeholderContainer.VisibleWindow = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_placeholderContainer.VisibleWindow = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void PlaceHolderContainerPressed(object o, ButtonPressEventArgs args)
|
||||
{
|
||||
if (Sensitive)
|
||||
{
|
||||
TextView.Sensitive = true;
|
||||
TextView.HasFocus = true;
|
||||
TextView.GdkWindow?.Raise();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,158 +8,182 @@ using Xamarin.Forms.Platform.GTK.Helpers;
|
|||
|
||||
namespace Xamarin.Forms.Platform.GTK.Renderers
|
||||
{
|
||||
public class EditorRenderer : ViewRenderer<Editor, ScrolledTextView>
|
||||
{
|
||||
private const string TextColorTagName = "text-color";
|
||||
public class EditorRenderer : ViewRenderer<Editor, ScrolledTextView>
|
||||
{
|
||||
private const string TextColorTagName = "text-color";
|
||||
|
||||
private bool _disposed;
|
||||
private bool _disposed;
|
||||
|
||||
protected IEditorController EditorController => Element as IEditorController;
|
||||
protected IEditorController EditorController => Element as IEditorController;
|
||||
|
||||
protected override void UpdateBackgroundColor()
|
||||
{
|
||||
if (!Element.BackgroundColor.IsDefaultOrTransparent())
|
||||
{
|
||||
var color = Element.BackgroundColor.ToGtkColor();
|
||||
protected override void UpdateBackgroundColor()
|
||||
{
|
||||
if (!Element.BackgroundColor.IsDefaultOrTransparent())
|
||||
{
|
||||
var backgroundColor = Element.BackgroundColor.ToGtkColor();
|
||||
|
||||
Control.TextView.ModifyBg(StateType.Normal, color);
|
||||
Control.TextView.ModifyBase(StateType.Normal, color);
|
||||
}
|
||||
}
|
||||
Control.SetBackgroundColor(backgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
|
||||
{
|
||||
if (Control == null)
|
||||
{
|
||||
var scrolled = new ScrolledTextView();
|
||||
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
|
||||
{
|
||||
if (Control == null)
|
||||
{
|
||||
var scrolled = new ScrolledTextView();
|
||||
|
||||
scrolled.TextView.Buffer.TagTable.Add(new TextTag(TextColorTagName));
|
||||
scrolled.TextView.Buffer.Changed += TextViewBufferChanged;
|
||||
scrolled.TextView.Focused += TextViewFocused;
|
||||
scrolled.TextView.FocusOutEvent += TextViewFocusedOut;
|
||||
scrolled.TextView.Buffer.TagTable.Add(new TextTag(TextColorTagName));
|
||||
|
||||
SetNativeControl(scrolled);
|
||||
AdjustMinimumHeight(scrolled.TextView);
|
||||
}
|
||||
scrolled.TextView.Buffer.Changed += TextViewBufferChanged;
|
||||
scrolled.TextView.Focused += TextViewFocused;
|
||||
scrolled.TextView.FocusOutEvent += TextViewFocusedOut;
|
||||
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
UpdateText();
|
||||
UpdateFont();
|
||||
UpdateTextColor();
|
||||
UpdateMaxLength();
|
||||
}
|
||||
SetNativeControl(scrolled);
|
||||
AdjustMinimumHeight(scrolled.TextView);
|
||||
}
|
||||
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
if (e.NewElement != null)
|
||||
{
|
||||
UpdateText();
|
||||
UpdateFont();
|
||||
UpdateTextColor();
|
||||
UpdatePlaceholder();
|
||||
UpdatePlaceholderColor();
|
||||
UpdateMaxLength();
|
||||
}
|
||||
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
base.OnElementChanged(e);
|
||||
}
|
||||
|
||||
if (e.PropertyName == Editor.TextProperty.PropertyName)
|
||||
UpdateText();
|
||||
else if (e.PropertyName == Editor.TextColorProperty.PropertyName)
|
||||
UpdateTextColor();
|
||||
else if (e.PropertyName == Editor.FontAttributesProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == Editor.FontFamilyProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == Editor.FontSizeProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
|
||||
UpdateMaxLength();
|
||||
}
|
||||
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnElementPropertyChanged(sender, e);
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && !_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
if (e.PropertyName == Editor.TextProperty.PropertyName)
|
||||
UpdateText();
|
||||
else if (e.PropertyName == Editor.TextColorProperty.PropertyName)
|
||||
UpdateTextColor();
|
||||
else if (e.PropertyName == Editor.PlaceholderProperty.PropertyName)
|
||||
UpdatePlaceholder();
|
||||
else if (e.PropertyName == Editor.PlaceholderColorProperty.PropertyName)
|
||||
UpdatePlaceholderColor();
|
||||
else if (e.PropertyName == Editor.FontAttributesProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == Editor.FontFamilyProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == Editor.FontSizeProperty.PropertyName)
|
||||
UpdateFont();
|
||||
else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
|
||||
UpdateMaxLength();
|
||||
}
|
||||
|
||||
if (Control != null)
|
||||
{
|
||||
Control.TextView.Buffer.Changed -= TextViewBufferChanged;
|
||||
Control.TextView.Focused -= TextViewFocused;
|
||||
Control.TextView.FocusOutEvent += TextViewFocusedOut;
|
||||
}
|
||||
}
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && !_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
if (Control != null)
|
||||
{
|
||||
Control.TextView.Buffer.Changed -= TextViewBufferChanged;
|
||||
Control.TextView.Focused -= TextViewFocused;
|
||||
Control.TextView.FocusOutEvent += TextViewFocusedOut;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateText()
|
||||
{
|
||||
TextBuffer buffer = Control.TextView.Buffer;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
if (buffer.Text != Element.Text)
|
||||
{
|
||||
buffer.Text = Element.Text ?? string.Empty;
|
||||
UpdateTextColor();
|
||||
}
|
||||
}
|
||||
private void UpdateText()
|
||||
{
|
||||
TextBuffer buffer = Control.TextView.Buffer;
|
||||
|
||||
private void UpdateFont()
|
||||
{
|
||||
FontDescription fontDescription = FontDescriptionHelper.CreateFontDescription(
|
||||
Element.FontSize, Element.FontFamily, Element.FontAttributes);
|
||||
Control.TextView.ModifyFont(fontDescription);
|
||||
if (buffer.Text != Element.Text)
|
||||
{
|
||||
buffer.Text = Element.Text ?? string.Empty;
|
||||
UpdateTextColor();
|
||||
}
|
||||
}
|
||||
|
||||
AdjustMinimumHeight(Control.TextView, fontDescription);
|
||||
}
|
||||
private void UpdateFont()
|
||||
{
|
||||
FontDescription fontDescription = FontDescriptionHelper.CreateFontDescription(
|
||||
Element.FontSize, Element.FontFamily, Element.FontAttributes);
|
||||
Control.TextView.ModifyFont(fontDescription);
|
||||
|
||||
private void UpdateTextColor()
|
||||
{
|
||||
if (!Element.TextColor.IsDefaultOrTransparent())
|
||||
{
|
||||
var textColor = Element.TextColor.ToGtkColor();
|
||||
AdjustMinimumHeight(Control.TextView, fontDescription);
|
||||
}
|
||||
|
||||
TextBuffer buffer = Control.TextView.Buffer;
|
||||
TextTag tag = buffer.TagTable.Lookup(TextColorTagName);
|
||||
tag.ForegroundGdk = Element.IsEnabled ? textColor : Control.Style.Foregrounds[(int)StateType.Normal];
|
||||
Control.TextView.Buffer.ApplyTag(tag, buffer.StartIter, buffer.EndIter);
|
||||
}
|
||||
}
|
||||
private void UpdateTextColor()
|
||||
{
|
||||
if (!Element.TextColor.IsDefaultOrTransparent())
|
||||
{
|
||||
var textColor = Element.TextColor.ToGtkColor();
|
||||
|
||||
private void TextViewBufferChanged(object sender, EventArgs e)
|
||||
{
|
||||
TextBuffer buffer = Control.TextView.Buffer;
|
||||
TextBuffer buffer = Control.TextView.Buffer;
|
||||
TextTag tag = buffer.TagTable.Lookup(TextColorTagName);
|
||||
tag.ForegroundGdk = Element.IsEnabled ? textColor : Control.Style.Foregrounds[(int)StateType.Normal];
|
||||
Control.TextView.Buffer.ApplyTag(tag, buffer.StartIter, buffer.EndIter);
|
||||
}
|
||||
}
|
||||
|
||||
if (Element.Text != buffer.Text)
|
||||
ElementController.SetValueFromRenderer(Editor.TextProperty, buffer.Text);
|
||||
private void TextViewBufferChanged(object sender, EventArgs e)
|
||||
{
|
||||
TextBuffer buffer = Control.TextView.Buffer;
|
||||
|
||||
UpdateTextColor();
|
||||
}
|
||||
if (Element.Text != buffer.Text)
|
||||
ElementController.SetValueFromRenderer(Editor.TextProperty, buffer.Text);
|
||||
|
||||
private void TextViewFocused(object o, FocusedArgs args)
|
||||
{
|
||||
ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
|
||||
}
|
||||
UpdateTextColor();
|
||||
}
|
||||
|
||||
private void TextViewFocusedOut(object o, FocusOutEventArgs args)
|
||||
{
|
||||
ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
|
||||
EditorController.SendCompleted();
|
||||
}
|
||||
private void TextViewFocused(object o, FocusedArgs args)
|
||||
{
|
||||
ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
|
||||
}
|
||||
|
||||
private static void AdjustMinimumHeight(TextView textView, FontDescription font = null)
|
||||
{
|
||||
var fDescr = font != null ? font : textView.Style.FontDescription;
|
||||
var metrics = textView.PangoContext.GetMetrics(font, Language.Default);
|
||||
var pangoUnits = (metrics.Ascent + metrics.Descent) / Pango.Scale.PangoScale;
|
||||
private void TextViewFocusedOut(object o, FocusOutEventArgs args)
|
||||
{
|
||||
ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
|
||||
EditorController.SendCompleted();
|
||||
}
|
||||
|
||||
var resolution = textView.Screen.Resolution;
|
||||
var minHeight = (int)(pangoUnits * (resolution / 72.0));
|
||||
private static void AdjustMinimumHeight(TextView textView, FontDescription font = null)
|
||||
{
|
||||
var fDescr = font != null ? font : textView.Style.FontDescription;
|
||||
var metrics = textView.PangoContext.GetMetrics(font, Language.Default);
|
||||
var pangoUnits = (metrics.Ascent + metrics.Descent) / Pango.Scale.PangoScale;
|
||||
|
||||
if (textView.HeightRequest < minHeight)
|
||||
{
|
||||
textView.HeightRequest = minHeight;
|
||||
}
|
||||
}
|
||||
var resolution = textView.Screen.Resolution;
|
||||
var minHeight = (int)(pangoUnits * (resolution / 72.0));
|
||||
|
||||
private void UpdateMaxLength()
|
||||
{
|
||||
Control.SetMaxLength(Element.MaxLength);
|
||||
}
|
||||
}
|
||||
if (textView.HeightRequest < minHeight)
|
||||
{
|
||||
textView.HeightRequest = minHeight;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateMaxLength()
|
||||
{
|
||||
Control.SetMaxLength(Element.MaxLength);
|
||||
}
|
||||
|
||||
private void UpdatePlaceholder()
|
||||
{
|
||||
if (Element.Placeholder != Control.PlaceholderText)
|
||||
{
|
||||
Control.PlaceholderText = Element.Placeholder;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdatePlaceholderColor()
|
||||
{
|
||||
if (!Element.PlaceholderColor.IsDefaultOrTransparent())
|
||||
{
|
||||
var placeholderColor = Element.PlaceholderColor.ToGtkColor();
|
||||
|
||||
Control.SetPlaceholderTextColor(placeholderColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче