using System; using System.ComponentModel; using System.Diagnostics; using Ooui.Forms.Extensions; using Xamarin.Forms; using NativeLabel = Ooui.Span; namespace Ooui.Forms.Renderers { public class LabelRenderer : ViewRenderer { SizeRequest _perfectSize; bool _perfectSizeValid; public override SizeRequest GetDesiredSize (double widthConstraint, double heightConstraint) { // System.Console.WriteLine($"Label.GetDesiredSize ({widthConstraint}, {heightConstraint})"); if (!_perfectSizeValid) { var size = Element.Text.MeasureSize (Element.FontFamily, Element.FontSize, Element.FontAttributes, double.PositiveInfinity, double.PositiveInfinity); size.Width = Math.Ceiling (size.Width); size.Height = Math.Ceiling (size.Height); _perfectSize = new SizeRequest (size, new Size (Element.FontSize, Element.FontSize)); _perfectSizeValid = true; } var widthFits = widthConstraint >= _perfectSize.Request.Width; var heightFits = heightConstraint >= _perfectSize.Request.Height; if (widthFits && heightFits) return _perfectSize; var resultRequestSize = Element.Text.MeasureSize (Element.FontFamily, Element.FontSize, Element.FontAttributes, widthConstraint, heightConstraint); var result = new SizeRequest (resultRequestSize, resultRequestSize); var tinyWidth = Math.Min (10, result.Request.Width); result.Minimum = new Size (tinyWidth, result.Request.Height); if (widthFits || Element.LineBreakMode == LineBreakMode.NoWrap) return result; bool containerIsNotInfinitelyWide = !double.IsInfinity (widthConstraint); if (containerIsNotInfinitelyWide) { bool textCouldHaveWrapped = Element.LineBreakMode == LineBreakMode.WordWrap || Element.LineBreakMode == LineBreakMode.CharacterWrap; bool textExceedsContainer = result.Request.Width > widthConstraint; if (textExceedsContainer || textCouldHaveWrapped) { var expandedWidth = Math.Max (tinyWidth, widthConstraint); result.Request = new Size (expandedWidth, result.Request.Height); } } return result; } protected override void OnElementChanged (ElementChangedEventArgs e) { if (e.NewElement != null) { if (Control == null) { SetNativeControl (new NativeLabel ()); } UpdateText (); UpdateTextColor (); UpdateFont (); UpdateLineBreakMode (); UpdateAlignment (); } base.OnElementChanged (e); } protected override void OnElementPropertyChanged (object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged (sender, e); if (Control == null) return; if (e.PropertyName == Xamarin.Forms.Label.HorizontalTextAlignmentProperty.PropertyName) UpdateAlignment (); else if (e.PropertyName == Xamarin.Forms.Label.VerticalTextAlignmentProperty.PropertyName) UpdateAlignment (); else if (e.PropertyName == Xamarin.Forms.Label.TextColorProperty.PropertyName) UpdateTextColor (); else if (e.PropertyName == Xamarin.Forms.Label.FontProperty.PropertyName) UpdateFont (); else if (e.PropertyName == Xamarin.Forms.Label.TextProperty.PropertyName) UpdateText (); else if (e.PropertyName == Xamarin.Forms.Label.FormattedTextProperty.PropertyName) UpdateText (); else if (e.PropertyName == Xamarin.Forms.Label.LineBreakModeProperty.PropertyName) UpdateLineBreakMode (); } protected override void SetBackgroundColor (Xamarin.Forms.Color color) { Style.BackgroundColor = color.ToOouiColor (Colors.Clear); } void UpdateAlignment () { this.Style.Display = "table"; Control.Style.Display = "table-cell"; this.Style.TextAlign = Element.HorizontalTextAlignment.ToOouiTextAlign (); Control.Style.VerticalAlign = Element.VerticalTextAlignment.ToOouiVerticalAlign (); } void UpdateLineBreakMode () { _perfectSizeValid = false; //switch (Element.LineBreakMode) //{ // case LineBreakMode.NoWrap: // Control.LineBreakMode = UILineBreakMode.Clip; // Control.Lines = 1; // break; // case LineBreakMode.WordWrap: // Control.LineBreakMode = UILineBreakMode.WordWrap; // Control.Lines = 0; // break; // case LineBreakMode.CharacterWrap: // Control.LineBreakMode = UILineBreakMode.CharacterWrap; // Control.Lines = 0; // break; // case LineBreakMode.HeadTruncation: // Control.LineBreakMode = UILineBreakMode.HeadTruncation; // Control.Lines = 1; // break; // case LineBreakMode.MiddleTruncation: // Control.LineBreakMode = UILineBreakMode.MiddleTruncation; // Control.Lines = 1; // break; // case LineBreakMode.TailTruncation: // Control.LineBreakMode = UILineBreakMode.TailTruncation; // Control.Lines = 1; // break; //} } bool isTextFormatted; void UpdateText () { _perfectSizeValid = false; var values = Element.GetValues (Xamarin.Forms.Label.FormattedTextProperty, Xamarin.Forms.Label.TextProperty, Xamarin.Forms.Label.TextColorProperty); var formatted = values[0] as FormattedString; if (formatted != null) { Control.Text = (string)values[1]; isTextFormatted = true; } else { Control.Text = (string)values[1]; isTextFormatted = false; } } void UpdateFont () { if (isTextFormatted) return; _perfectSizeValid = false; Element.SetStyleFont (Element.FontFamily, Element.FontSize, Element.FontAttributes, Control.Style); } void UpdateTextColor () { if (isTextFormatted) return; _perfectSizeValid = false; var textColor = (Xamarin.Forms.Color)Element.GetValue (Xamarin.Forms.Label.TextColorProperty); Control.Style.Color = textColor.ToOouiColor(Xamarin.Forms.Color.Black); } } }