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
{
///
/// 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;
}
}
///
/// Applies entry's text and its style.
///
void ApplyTextAndStyle()
{
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 ?? "");
}
}
}