using System; using ElmSharp; using EEntry = ElmSharp.Entry; using EColor = ElmSharp.Color; using ESize = ElmSharp.Size; namespace Xamarin.Forms.Platform.Tizen.Native { /// /// Extends the Entry control, providing basic formatting features, /// i.e. font color, size, placeholder. /// public class Entry : EEntry, IMeasurable, IBatchable { /// /// Holds the formatted text of the entry. /// readonly Span _span = new Span(); /// /// Holds the formatted text of the placeholder. /// readonly Span _placeholderSpan = new Span(); /// /// Helps to detect whether the text change was initiated by the user /// or via the Text property. /// int _changedByUserCallbackDepth; /// /// The type of the keyboard used by the entry. /// Keyboard _keyboard; /// /// Initializes a new instance of the class. /// /// Parent evas object. public Entry(EvasObject parent) : base(parent) { Scrollable = true; ChangedByUser += (s, e) => { _changedByUserCallbackDepth++; Text = GetInternalText(); _changedByUserCallbackDepth--; }; ApplyKeyboard(Keyboard.Normal); } /// /// Occurs when the text has changed. /// public event EventHandler TextChanged; /// /// Gets or sets the text. /// /// The text. public override string Text { get { return _span.Text; } set { if (value != _span.Text) { var old = _span.Text; _span.Text = value; ApplyTextAndStyle(); Device.StartTimer(TimeSpan.FromTicks(1), () => { TextChanged?.Invoke(this, new TextChangedEventArgs(old, value)); return false; }); } } } /// /// Gets or sets the color of the text. /// /// The color of the text. public EColor TextColor { get { return _span.ForegroundColor; } set { if (!_span.ForegroundColor.Equals(value)) { _span.ForegroundColor = value; ApplyTextAndStyle(); } } } /// /// Gets or sets the font family of the text and the placeholder. /// /// The font family of the text and the placeholder. public string FontFamily { get { return _span.FontFamily; } set { if (value != _span.FontFamily) { _span.FontFamily = value; ApplyTextAndStyle(); _placeholderSpan.FontFamily = value; ApplyPlaceholderAndStyle(); } } } /// /// Gets or sets the font attributes of the text and the placeholder. /// /// The font attributes of the text and the placeholder. public FontAttributes FontAttributes { get { return _span.FontAttributes; } set { if (value != _span.FontAttributes) { _span.FontAttributes = value; ApplyTextAndStyle(); _placeholderSpan.FontAttributes = value; ApplyPlaceholderAndStyle(); } } } /// /// Gets or sets the size of the font of both text and placeholder. /// /// The size of the font of both text and placeholder. public double FontSize { get { return _span.FontSize; } set { if (value != _span.FontSize) { _span.FontSize = value; ApplyTextAndStyle(); _placeholderSpan.FontSize = value; ApplyPlaceholderAndStyle(); } } } /// /// Gets or sets the font weight for the text. /// /// The weight of the font. public string FontWeight { get { return _span.FontWeight; } set { if (value != _span.FontWeight) { _span.FontWeight = value; ApplyTextAndStyle(); _placeholderSpan.FontWeight = value; ApplyPlaceholderAndStyle(); } } } /// /// Gets or sets the horizontal text alignment of both text and placeholder. /// /// The horizontal text alignment of both text and placeholder. public TextAlignment HorizontalTextAlignment { get { return _span.HorizontalTextAlignment; } set { if (value != _span.HorizontalTextAlignment) { _span.HorizontalTextAlignment = value; ApplyTextAndStyle(); _placeholderSpan.HorizontalTextAlignment = value; ApplyPlaceholderAndStyle(); } } } /// /// Gets or sets the keyboard type used by the entry. /// /// The keyboard type. public Keyboard Keyboard { get { return _keyboard; } set { if (value != _keyboard) { ApplyKeyboard(value); } } } /// /// Gets or sets the placeholder's text. /// /// The placeholder's text. public string Placeholder { get { return _placeholderSpan.Text; } set { if (value != _placeholderSpan.Text) { _placeholderSpan.Text = value; ApplyPlaceholderAndStyle(); } } } /// /// Gets or sets the color of the placeholder's text. /// /// The color of the placeholder's text. public EColor PlaceholderColor { get { return _placeholderSpan.ForegroundColor; } set { if (!_placeholderSpan.ForegroundColor.Equals(value)) { _placeholderSpan.ForegroundColor = value; ApplyPlaceholderAndStyle(); } } } /// /// Implementation of the IMeasurable.Measure() method. /// public ESize Measure(int availableWidth, int availableHeight) { var originalSize = Geometry; // resize the control using the whole available width Resize(availableWidth, originalSize.Height); ESize rawSize; ESize formattedSize; var edjeTextBlock = EdjeObject["elm.guide"]; // if there's no text, but there's a placeholder, use it for measurements if (string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Placeholder) && edjeTextBlock != null) { rawSize = edjeTextBlock.TextBlockNativeSize; formattedSize = edjeTextBlock.TextBlockFormattedSize; } else { // there's text in the entry, use it instead rawSize = Native.TextHelper.GetRawTextBlockSize(this); formattedSize = Native.TextHelper.GetFormattedTextBlockSize(this); } // restore the original size Resize(originalSize.Width, originalSize.Height); // Set bottom padding for lower case letters that have segments below the bottom line of text (g, j, p, q, y). var verticalPadding = (int)Math.Ceiling(0.05 * FontSize); var horizontalPadding = (int)Math.Ceiling(0.2 * FontSize); rawSize.Height += verticalPadding; formattedSize.Height += verticalPadding; formattedSize.Width += horizontalPadding; // if the raw text width is larger than available width, we use the available width, // while height is set to the smallest height value if (rawSize.Width > availableWidth) { return new ESize { Width = availableWidth, Height = Math.Min(formattedSize.Height, Math.Max(rawSize.Height, availableHeight)), }; } else { // width is fine, return the formatted text size return formattedSize; } } void IBatchable.OnBatchCommitted() { ApplyTextAndStyle(); } /// /// Applies entry's text and its style. /// void ApplyTextAndStyle() { if (!this.IsBatched()) { SetInternalTextAndStyle(_span.GetDecoratedText(), _span.GetStyle()); } } /// /// Sets entry's internal text and its style. /// /// Formatted text, supports HTML tags. /// Style applied to the formattedText. void SetInternalTextAndStyle(string formattedText, string textStyle) { if (_changedByUserCallbackDepth == 0) { base.Text = formattedText; base.TextStyle = textStyle; } } /// /// Gets the internal text representation of the entry. /// /// The internal text representation. string GetInternalText() { return Entry.ConvertMarkupToUtf8(base.Text); } /// /// Applies the keyboard type to be used by the entry. /// /// Keyboard type to be used. void ApplyKeyboard(Keyboard keyboard) { SetInternalKeyboard(_keyboard = keyboard); } /// /// Configures the ElmSharp.Entry with specified keyboard type and displays /// the keyboard automatically unless the provided type is Keyboard.None. /// /// Keyboard type to be used. void SetInternalKeyboard(Keyboard keyboard) { if (keyboard == Keyboard.None) { SetInputPanelEnabled(false); } else { SetInputPanelEnabled(true); SetInputPanelLayout((InputPanelLayout)keyboard); } } /// /// Applies placeholders's text and its style. /// void ApplyPlaceholderAndStyle() { SetInternalPlaceholderAndStyle(_placeholderSpan.GetMarkupText()); } /// /// Sets placeholder's internal text and style. /// /// Markup text to be used as a placeholder. void SetInternalPlaceholderAndStyle(string markupText) { SetPartText("elm.guide", markupText ?? ""); } } }