A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

371 lines
13 KiB

// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Reactive;
using System.Reactive.Linq;
using Perspex.Media;
namespace Perspex.Controls
{
/// <summary>
/// A control that displays a block of text.
/// </summary>
public class TextBlock : Control
{
/// <summary>
/// Defines the <see cref="Background"/> property.
/// </summary>
public static readonly PerspexProperty<Brush> BackgroundProperty =
Border.BackgroundProperty.AddOwner<TextBlock>();
/// <summary>
/// Defines the <see cref="FontFamily"/> property.
/// </summary>
public static readonly PerspexProperty<string> FontFamilyProperty =
PerspexProperty.RegisterAttached<TextBlock, Control, string>(
nameof(FontFamily),
inherits: true);
/// <summary>
/// Defines the <see cref="FontSize"/> property.
/// </summary>
public static readonly PerspexProperty<double> FontSizeProperty =
PerspexProperty.RegisterAttached<TextBlock, Control, double>(
nameof(FontSize),
inherits: true);
/// <summary>
/// Defines the <see cref="FontStyle"/> property.
/// </summary>
public static readonly PerspexProperty<FontStyle> FontStyleProperty =
PerspexProperty.RegisterAttached<TextBlock, Control, FontStyle>(
nameof(FontStyle),
inherits: true);
/// <summary>
/// Defines the <see cref="FontWeight"/> property.
/// </summary>
public static readonly PerspexProperty<FontWeight> FontWeightProperty =
PerspexProperty.RegisterAttached<TextBlock, Control, FontWeight>(
nameof(FontWeight),
inherits: true,
defaultValue: FontWeight.Normal);
/// <summary>
/// Defines the <see cref="Foreground"/> property.
/// </summary>
public static readonly PerspexProperty<Brush> ForegroundProperty =
PerspexProperty.RegisterAttached<TextBlock, Control, Brush>(
nameof(Foreground),
new SolidColorBrush(0xff000000),
inherits: true);
/// <summary>
/// Defines the <see cref="Text"/> property.
/// </summary>
public static readonly PerspexProperty<string> TextProperty =
PerspexProperty.Register<TextBlock, string>(nameof(Text), defaultBindingMode: BindingMode.TwoWay);
/// <summary>
/// Defines the <see cref="TextAlignment"/> property.
/// </summary>
public static readonly PerspexProperty<TextAlignment> TextAlignmentProperty =
PerspexProperty.Register<TextBlock, TextAlignment>(nameof(TextAlignment));
/// <summary>
/// Defines the <see cref="TextWrapping"/> property.
/// </summary>
public static readonly PerspexProperty<TextWrapping> TextWrappingProperty =
PerspexProperty.Register<TextBlock, TextWrapping>(nameof(TextWrapping));
/// <summary>
/// The formatted text used for rendering.
/// </summary>
private FormattedText _formattedText;
/// <summary>
/// Stores the last constraint passed to MeasureOverride.
/// </summary>
private Size _constraint;
/// <summary>
/// Initializes static members of the <see cref="TextBlock"/> class.
/// </summary>
static TextBlock()
{
AffectsRender(ForegroundProperty);
}
/// <summary>
/// Initializes a new instance of the <see cref="TextBlock"/> class.
/// </summary>
public TextBlock()
{
Observable.Merge(
GetObservable(TextProperty).Select(_ => Unit.Default),
GetObservable(TextAlignmentProperty).Select(_ => Unit.Default),
GetObservable(FontSizeProperty).Select(_ => Unit.Default),
GetObservable(FontStyleProperty).Select(_ => Unit.Default))
.Subscribe(_ =>
{
InvalidateFormattedText();
});
}
/// <summary>
/// Gets or sets a brush used to paint the control's background.
/// </summary>
public Brush Background
{
get { return GetValue(BackgroundProperty); }
set { SetValue(BackgroundProperty, value); }
}
/// <summary>
/// Gets or sets the text.
/// </summary>
public string Text
{
get { return GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
/// <summary>
/// Gets or sets the font family.
/// </summary>
public string FontFamily
{
get { return GetValue(FontFamilyProperty); }
set { SetValue(FontFamilyProperty, value); }
}
/// <summary>
/// Gets or sets the font size.
/// </summary>
public double FontSize
{
get { return GetValue(FontSizeProperty); }
set { SetValue(FontSizeProperty, value); }
}
/// <summary>
/// Gets or sets the font style.
/// </summary>
public FontStyle FontStyle
{
get { return GetValue(FontStyleProperty); }
set { SetValue(FontStyleProperty, value); }
}
/// <summary>
/// Gets or sets the font weight.
/// </summary>
public FontWeight FontWeight
{
get { return GetValue(FontWeightProperty); }
set { SetValue(FontWeightProperty, value); }
}
/// <summary>
/// Gets or sets a brush used to paint the text.
/// </summary>
public Brush Foreground
{
get { return GetValue(ForegroundProperty); }
set { SetValue(ForegroundProperty, value); }
}
/// <summary>
/// Gets the <see cref="FormattedText"/> used to render the text.
/// </summary>
public FormattedText FormattedText
{
get
{
if (_formattedText == null)
{
_formattedText = CreateFormattedText(_constraint);
}
return _formattedText;
}
}
/// <summary>
/// Gets or sets the control's text wrapping mode.
/// </summary>
public TextWrapping TextWrapping
{
get { return GetValue(TextWrappingProperty); }
set { SetValue(TextWrappingProperty, value); }
}
/// <summary>
/// Gets or sets the text alignment.
/// </summary>
public TextAlignment TextAlignment
{
get { return GetValue(TextAlignmentProperty); }
set { SetValue(TextAlignmentProperty, value); }
}
/// <summary>
/// Gets the value of the attached <see cref="FontFamilyProperty"/> on a control.
/// </summary>
/// <param name="control">The control.</param>
/// <returns>The font family.</returns>
public static string GetFontFamily(Control control)
{
return control.GetValue(FontFamilyProperty);
}
/// <summary>
/// Gets the value of the attached <see cref="FontSizeProperty"/> on a control.
/// </summary>
/// <param name="control">The control.</param>
/// <returns>The font family.</returns>
public static double GetFontSize(Control control)
{
return control.GetValue(FontSizeProperty);
}
/// <summary>
/// Gets the value of the attached <see cref="FontStyleProperty"/> on a control.
/// </summary>
/// <param name="control">The control.</param>
/// <returns>The font family.</returns>
public static FontStyle GetFontStyle(Control control)
{
return control.GetValue(FontStyleProperty);
}
/// <summary>
/// Gets the value of the attached <see cref="FontWeightProperty"/> on a control.
/// </summary>
/// <param name="control">The control.</param>
/// <returns>The font family.</returns>
public static FontWeight GetFontWeight(Control control)
{
return control.GetValue(FontWeightProperty);
}
/// <summary>
/// Sets the value of the attached <see cref="FontFamilyProperty"/> on a control.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="value">The property value to set.</param>
/// <returns>The font family.</returns>
public static void SetFontFamily(Control control, string value)
{
control.SetValue(FontFamilyProperty, value);
}
/// <summary>
/// Sets the value of the attached <see cref="FontSizeProperty"/> on a control.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="value">The property value to set.</param>
/// <returns>The font family.</returns>
public static void SetFontSize(Control control, double value)
{
control.SetValue(FontSizeProperty, value);
}
/// <summary>
/// Sets the value of the attached <see cref="FontStyleProperty"/> on a control.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="value">The property value to set.</param>
/// <returns>The font family.</returns>
public static void SetFontStyle(Control control, FontStyle value)
{
control.SetValue(FontStyleProperty, value);
}
/// <summary>
/// Sets the value of the attached <see cref="FontWeightProperty"/> on a control.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="value">The property value to set.</param>
/// <returns>The font family.</returns>
public static void SetFontWeight(Control control, FontWeight value)
{
control.SetValue(FontWeightProperty, value);
}
/// <summary>
/// Renders the <see cref="TextBlock"/> to a drawing context.
/// </summary>
/// <param name="context">The drawing context.</param>
public override void Render(DrawingContext context)
{
Brush background = Background;
if (background != null)
{
context.FillRectangle(background, new Rect(Bounds.Size));
}
FormattedText.Constraint = Bounds.Size;
context.DrawText(Foreground, new Point(), FormattedText);
}
/// <summary>
/// Creates the <see cref="FormattedText"/> used to render the text.
/// </summary>
/// <param name="constraint">The constraint of the text.</param>
/// <returns>A <see cref="FormattedText"/> object.</returns>
protected virtual FormattedText CreateFormattedText(Size constraint)
{
var result = new FormattedText(
Text ?? string.Empty,
FontFamily ?? "Arial",
FontSize > 0 ? FontSize : 12,
FontStyle,
TextAlignment,
FontWeight);
result.Constraint = constraint;
return result;
}
/// <summary>
/// Invalidates <see cref="FormattedText"/>.
/// </summary>
protected void InvalidateFormattedText()
{
if (_formattedText != null)
{
_constraint = _formattedText.Constraint;
_formattedText.Dispose();
_formattedText = null;
}
InvalidateMeasure();
}
/// <summary>
/// Measures the control.
/// </summary>
/// <param name="availableSize">The available size for the control.</param>
/// <returns>The desired size.</returns>
protected override Size MeasureOverride(Size availableSize)
{
if (!string.IsNullOrEmpty(Text))
{
if (TextWrapping == TextWrapping.Wrap)
{
FormattedText.Constraint = new Size(availableSize.Width, double.PositiveInfinity);
}
else
{
FormattedText.Constraint = Size.Infinity;
}
return FormattedText.Measure();
}
return new Size();
}
}
}