// -----------------------------------------------------------------------
//
// Copyright 2015 MIT Licence. See licence.md for more information.
//
// -----------------------------------------------------------------------
namespace Perspex.Controls
{
using System;
using System.Reactive;
using System.Reactive.Linq;
using Perspex.Media;
///
/// A control that displays a block of text.
///
public class TextBlock : Control
{
///
/// Defines the property.
///
public static readonly PerspexProperty BackgroundProperty =
Border.BackgroundProperty.AddOwner();
///
/// Defines the property.
///
public static readonly PerspexProperty FontFamilyProperty =
PerspexProperty.RegisterAttached(
nameof(FontFamily),
inherits: true);
///
/// Defines the property.
///
public static readonly PerspexProperty FontSizeProperty =
PerspexProperty.RegisterAttached(
nameof(FontSize),
inherits: true);
///
/// Defines the property.
///
public static readonly PerspexProperty FontStyleProperty =
PerspexProperty.RegisterAttached(
nameof(FontStyle),
inherits: true);
///
/// Defines the property.
///
public static readonly PerspexProperty FontWeightProperty =
PerspexProperty.RegisterAttached(
nameof(FontWeight),
inherits: true,
defaultValue: FontWeight.Normal);
///
/// Defines the property.
///
public static readonly PerspexProperty ForegroundProperty =
PerspexProperty.RegisterAttached(
nameof(Foreground),
new SolidColorBrush(0xff000000),
inherits: true);
///
/// Defines the property.
///
public static readonly PerspexProperty TextProperty =
PerspexProperty.Register(nameof(Text));
///
/// Defines the property.
///
public static readonly PerspexProperty TextAlignmentProperty =
PerspexProperty.Register(nameof(TextAlignment));
///
/// Defines the property.
///
public static readonly PerspexProperty TextWrappingProperty =
PerspexProperty.Register(nameof(TextWrapping));
///
/// The formatted text used for rendering.
///
private FormattedText formattedText;
///
/// Stores the last constraint passed to MeasureOverride.
///
private Size constraint;
///
/// Initializes static members of the class.
///
static TextBlock()
{
AffectsRender(ForegroundProperty);
}
///
/// Initializes a new instance of the class.
///
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();
});
}
///
/// Gets or sets a brush used to paint the control's background.
///
public Brush Background
{
get { return this.GetValue(BackgroundProperty); }
set { this.SetValue(BackgroundProperty, value); }
}
///
/// Gets or sets the text.
///
public string Text
{
get { return this.GetValue(TextProperty); }
set { this.SetValue(TextProperty, value); }
}
///
/// Gets or sets the font family.
///
public string FontFamily
{
get { return this.GetValue(FontFamilyProperty); }
set { this.SetValue(FontFamilyProperty, value); }
}
///
/// Gets or sets the font size.
///
public double FontSize
{
get { return this.GetValue(FontSizeProperty); }
set { this.SetValue(FontSizeProperty, value); }
}
///
/// Gets or sets the font style.
///
public FontStyle FontStyle
{
get { return this.GetValue(FontStyleProperty); }
set { this.SetValue(FontStyleProperty, value); }
}
///
/// Gets or sets the font weight.
///
public FontWeight FontWeight
{
get { return this.GetValue(FontWeightProperty); }
set { this.SetValue(FontWeightProperty, value); }
}
///
/// Gets or sets a brush used to paint the text.
///
public Brush Foreground
{
get { return this.GetValue(ForegroundProperty); }
set { this.SetValue(ForegroundProperty, value); }
}
///
/// Gets the used to render the text.
///
public FormattedText FormattedText
{
get
{
if (this.formattedText == null)
{
this.formattedText = this.CreateFormattedText(this.constraint);
}
return this.formattedText;
}
}
///
/// Gets or sets the control's text wrapping mode.
///
public TextWrapping TextWrapping
{
get { return this.GetValue(TextWrappingProperty); }
set { this.SetValue(TextWrappingProperty, value); }
}
///
/// Gets or sets the text alignment.
///
public TextAlignment TextAlignment
{
get { return this.GetValue(TextAlignmentProperty); }
set { this.SetValue(TextAlignmentProperty, value); }
}
///
/// Renders the to a drawing context.
///
/// The drawing context.
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);
}
///
/// Creates the used to render the text.
///
/// The constraint of the text.
/// A object.
protected virtual FormattedText CreateFormattedText(Size constraint)
{
var result = new FormattedText(
this.Text,
this.FontFamily,
this.FontSize,
this.FontStyle,
this.TextAlignment,
this.FontWeight);
result.Constraint = constraint;
return result;
}
///
/// Invalidates .
///
protected void InvalidateFormattedText()
{
if (this.formattedText != null)
{
this.constraint = this.formattedText.Constraint;
this.formattedText.Dispose();
this.formattedText = null;
}
this.InvalidateMeasure();
}
///
/// Measures the control.
///
/// The available size for the control.
/// The desired size.
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();
}
}
}