using System; using ElmSharp; using EButton = ElmSharp.Button; using ESize = ElmSharp.Size; using EColor = ElmSharp.Color; namespace Xamarin.Forms.Platform.Tizen.Native { /// /// Extends the EButton control, providing basic formatting features, /// i.e. font color, size, additional image. /// public class Button : EButton, IMeasurable { /// /// Holds the formatted text of the button. /// readonly Span _span = new Span(); /// /// The internal padding of the button, helps to determine the size. /// ESize _internalPadding; /// /// Optional image, if set will be drawn on the button. /// Image _image; /// /// Initializes a new instance of the class. /// /// Parent evas object. public Button(EvasObject parent) : base(parent) { _internalPadding = GetInternalPadding(); } /// /// Gets or sets the button's text. /// /// The text. public override string Text { get { return _span.Text; } set { if (value != _span.Text) { _span.Text = value; ApplyTextAndStyle(); } } } /// /// 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 color of the text background. /// /// The color of the text background. public EColor TextBackgroundColor { get { return _span.BackgroundColor; } set { if (!_span.BackgroundColor.Equals(value)) { _span.BackgroundColor = value; ApplyTextAndStyle(); } } } /// /// Gets or sets the font family. /// /// The font family. public string FontFamily { get { return _span.FontFamily; } set { if (value != _span.FontFamily) { _span.FontFamily = value; ApplyTextAndStyle(); } } } /// /// Gets or sets the font attributes. /// /// The font attributes. public FontAttributes FontAttributes { get { return _span.FontAttributes; } set { if (value != _span.FontAttributes) { _span.FontAttributes = value; ApplyTextAndStyle(); } } } /// /// Gets or sets the size of the font. /// /// The size of the font. public double FontSize { get { return _span.FontSize; } set { if (value != _span.FontSize) { _span.FontSize = value; ApplyTextAndStyle(); } } } /// /// Gets or sets the image to be displayed next to the button's text. /// /// The image displayed on the button. public Image Image { get { return _image; } set { if (value != _image) { ApplyImage(value); } } } /// /// Implementation of the IMeasurable.Measure() method. /// public ESize Measure(int availableWidth, int availableHeight) { var size = Geometry; // resize the control using the whole available width Resize(availableWidth, size.Height); // measure the button's text, use it as a hint for the size var rawSize = Native.TextHelper.GetRawTextBlockSize(this); var formattedSize = Native.TextHelper.GetFormattedTextBlockSize(this); // restore the original size Resize(size.Width, size.Height); var padding = _internalPadding; if (Style == "circle") { var circleTextPadding = (EdjeObject["icon_text_padding"]?.Geometry.Height).GetValueOrDefault(0); var circleHeight = padding.Height + ((rawSize.Width == 0) ? 0 : circleTextPadding + formattedSize.Height); return new ESize { Width = padding.Width, Height = circleHeight }; } if (rawSize.Width > availableWidth) { // if the raw text width is larger than the available width, use // either formatted size or internal padding, whichever is bigger return new ESize() { Width = Math.Max(padding.Width, formattedSize.Width), Height = Math.Max(padding.Height, Math.Min(formattedSize.Height, Math.Max(rawSize.Height, availableHeight))), }; } else { // otherwise use the formatted size along with padding return new ESize() { Width = padding.Width + formattedSize.Width, Height = Math.Max(padding.Height, formattedSize.Height), }; } } /// /// Applies the button's text and its style. /// void ApplyTextAndStyle() { SetInternalTextAndStyle(_span.GetDecoratedText(), _span.GetStyle()); } /// /// Sets the button's internal text and its style. /// /// Formatted text, supports HTML tags. /// Style applied to the formattedText. void SetInternalTextAndStyle(string formattedText, string textStyle) { string emission = "elm,state,text,visible"; if (string.IsNullOrEmpty(formattedText)) { formattedText = null; textStyle = null; emission = "elm,state,text,hidden"; } base.Text = formattedText; var textblock = EdjeObject["elm.text"]; if (textblock != null) { textblock.TextStyle = textStyle; } EdjeObject.EmitSignal(emission, "elm"); } /// /// Gets the internal padding of the button. /// /// The internal padding. ESize GetInternalPadding() { var edje = EdjeObject; return new ESize { Width = (edje["padding_top_left"]?.Geometry.Width ?? 64) + (edje["padding_bottom_right"]?.Geometry.Width ?? 64), Height = edje["bg"]?.Geometry.Height ?? 64 }; } /// /// Applies the image to be displayed on the button. If value is null, /// image will be removed. /// /// Image to be displayed or null. void ApplyImage(Image image) { _image = image; SetInternalImage(); } /// /// Sets the internal image. If value is null, image will be removed. /// void SetInternalImage() { if (_image == null) { SetPartContent("icon", null); } else { SetPartContent("icon", _image); } } public void UpdateStyle(string style) { if (Style != style) { Style = style; if (Style == "circle") { var circleSize = (EdjeObject["bg"]?.Geometry.Width).GetValueOrDefault(0); _internalPadding = new ESize(circleSize, circleSize); _span.HorizontalTextAlignment = TextAlignment.Center; } else if (Style == "bottom") { _internalPadding = GetInternalPadding(); _span.HorizontalTextAlignment = TextAlignment.Auto; } else { _span.HorizontalTextAlignment = TextAlignment.Auto; } ApplyTextAndStyle(); } } } }