// ----------------------------------------------------------------------- // // Copyright 2014 MIT Licence. See licence.md for more information. // // ----------------------------------------------------------------------- namespace Perspex.Controls { using System; using System.Reactive; using System.Reactive.Linq; using Perspex.Media; public class TextBlock : Control { public static readonly PerspexProperty BackgroundProperty = Border.BackgroundProperty.AddOwner(); public static readonly PerspexProperty FontFamilyProperty = PerspexProperty.RegisterAttached("FontFamily", inherits: true); public static readonly PerspexProperty FontSizeProperty = PerspexProperty.RegisterAttached("FontSize", inherits: true); public static readonly PerspexProperty FontStyleProperty = PerspexProperty.RegisterAttached("FontStyle", inherits: true); public static readonly PerspexProperty FontWeightProperty = PerspexProperty.RegisterAttached("FontWeight", inherits: true, defaultValue: FontWeight.Normal); public static readonly PerspexProperty ForegroundProperty = PerspexProperty.RegisterAttached("Foreground", new SolidColorBrush(0xff000000), inherits: true); public static readonly PerspexProperty TextProperty = PerspexProperty.Register("Text"); public static readonly PerspexProperty TextWrappingProperty = PerspexProperty.Register("TextWrapping"); public static readonly PerspexProperty TextAlignmentProperty = PerspexProperty.Register("TextAlignment"); private FormattedText formattedText; private Size constraint; public TextBlock() { Observable.Merge( this.GetObservable(TextProperty).Select(_ => Unit.Default), this.GetObservable(TextAlignmentProperty).Select(_ => Unit.Default), this.GetObservable(FontSizeProperty).Select(_ => Unit.Default), this.GetObservable(FontStyleProperty).Select(_ => Unit.Default)) .Subscribe(_ => { this.InvalidateFormattedText(); }); } public Brush Background { get { return this.GetValue(BackgroundProperty); } set { this.SetValue(BackgroundProperty, value); } } public string Text { get { return this.GetValue(TextProperty); } set { this.SetValue(TextProperty, value); } } public string FontFamily { get { return this.GetValue(FontFamilyProperty); } set { this.SetValue(FontFamilyProperty, value); } } public double FontSize { get { return this.GetValue(FontSizeProperty); } set { this.SetValue(FontSizeProperty, value); } } public FontStyle FontStyle { get { return this.GetValue(FontStyleProperty); } set { this.SetValue(FontStyleProperty, value); } } public FontWeight FontWeight { get { return this.GetValue(FontWeightProperty); } set { this.SetValue(FontWeightProperty, value); } } public Brush Foreground { get { return this.GetValue(ForegroundProperty); } set { this.SetValue(ForegroundProperty, value); } } public FormattedText FormattedText { get { if (this.formattedText == null) { this.formattedText = this.CreateFormattedText(); } return this.formattedText; } } public TextWrapping TextWrapping { get { return this.GetValue(TextWrappingProperty); } set { this.SetValue(TextWrappingProperty, value); } } public TextAlignment TextAlignment { get { return this.GetValue(TextAlignmentProperty); } set { this.SetValue(TextAlignmentProperty, value); } } public override void Render(IDrawingContext context) { Brush background = this.Background; if (background != null) { context.FillRectange(background, new Rect(this.Bounds.Size)); } this.FormattedText.Constraint = this.Bounds.Size; context.DrawText(this.Foreground, new Point(), this.FormattedText); } protected virtual FormattedText CreateFormattedText() { var result = new FormattedText( this.Text, this.FontFamily, this.FontSize, this.FontStyle, this.TextAlignment, this.FontWeight); result.Constraint = this.constraint; return result; } protected void InvalidateFormattedText() { if (this.formattedText != null) { this.constraint = this.formattedText.Constraint; this.formattedText.Dispose(); this.formattedText = null; } this.InvalidateMeasure(); } protected override Size MeasureOverride(Size availableSize) { if (!string.IsNullOrEmpty(this.Text)) { if (this.TextWrapping == TextWrapping.Wrap) { this.FormattedText.Constraint = new Size(availableSize.Width, double.PositiveInfinity); } else { this.FormattedText.Constraint = Size.Infinity; } return this.FormattedText.Measure(); } return new Size(); } } }