-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
650 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using Avalonia.Media; | ||
|
||
namespace Avalonia.Controls.Documents | ||
{ | ||
/// <summary> | ||
/// Bold element - markup helper for indicating bolded content. | ||
/// Equivalent to a Span with FontWeight property set to FontWeights.Bold. | ||
/// Can contain other inline elements. | ||
/// </summary> | ||
public sealed class Bold : Span | ||
{ | ||
static Bold() | ||
{ | ||
FontWeightProperty.OverrideDefaultValue<Bold>(FontWeight.Bold); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using Avalonia.Media; | ||
using Avalonia.Media.TextFormatting; | ||
using Avalonia.Utilities; | ||
|
||
namespace Avalonia.Controls.Documents | ||
{ | ||
/// <summary> | ||
/// Inline element. | ||
/// </summary> | ||
public abstract class Inline : TextElement | ||
{ | ||
/// <summary> | ||
/// AvaloniaProperty for <see cref="TextDecorations" /> property. | ||
/// </summary> | ||
public static readonly StyledProperty<TextDecorationCollection> TextDecorationsProperty = | ||
AvaloniaProperty.Register<Inline, TextDecorationCollection>( | ||
nameof(TextDecorations)); | ||
|
||
/// <summary> | ||
/// AvaloniaProperty for <see cref="BaselineAlignment" /> property. | ||
/// </summary> | ||
public static readonly StyledProperty<BaselineAlignment> BaselineAlignmentProperty = | ||
AvaloniaProperty.Register<Inline, BaselineAlignment>( | ||
nameof(BaselineAlignment), | ||
BaselineAlignment.Baseline); | ||
|
||
/// <summary> | ||
/// The TextDecorations property specifies decorations that are added to the text of an element. | ||
/// </summary> | ||
public TextDecorationCollection TextDecorations | ||
{ | ||
get { return GetValue(TextDecorationsProperty); } | ||
set { SetValue(TextDecorationsProperty, value); } | ||
} | ||
|
||
/// <summary> | ||
/// Describes how the baseline for a text-based element is positioned on the vertical axis, | ||
/// relative to the established baseline for text. | ||
/// </summary> | ||
public BaselineAlignment BaselineAlignment | ||
{ | ||
get { return GetValue(BaselineAlignmentProperty); } | ||
set { SetValue(BaselineAlignmentProperty, value); } | ||
} | ||
|
||
internal abstract int BuildRun(StringBuilder stringBuilder, IList<ValueSpan<TextRunProperties>> textStyleOverrides, int firstCharacterIndex); | ||
|
||
protected TextRunProperties CreateTextRunProperties() | ||
{ | ||
return new GenericTextRunProperties(new Typeface(FontFamily, FontStyle, FontWeight), FontSize, | ||
TextDecorations, Foreground, Background, BaselineAlignment); | ||
} | ||
|
||
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change) | ||
{ | ||
base.OnPropertyChanged(change); | ||
|
||
switch (change.Property.Name) | ||
{ | ||
case nameof(TextDecorations): | ||
case nameof(BaselineAlignment): | ||
Invalidate(); | ||
break; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
using System; | ||
using Avalonia.Collections; | ||
using Avalonia.LogicalTree; | ||
|
||
namespace Avalonia.Controls.Documents | ||
{ | ||
/// <summary> | ||
/// A collection of <see cref="Inline"/>s. | ||
/// </summary> | ||
public class InlineCollection : AvaloniaList<Inline> | ||
{ | ||
private string _text = string.Empty; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="InlineCollection"/> class. | ||
/// </summary> | ||
public InlineCollection(ILogical parent) : base(0) | ||
{ | ||
ResetBehavior = ResetBehavior.Remove; | ||
|
||
this.ForEachItem( | ||
x => | ||
{ | ||
((ISetLogicalParent)x).SetParent(parent); | ||
x.Invalidated += Invalidate; | ||
Invalidate(); | ||
}, | ||
x => | ||
{ | ||
((ISetLogicalParent)x).SetParent(null); | ||
x.Invalidated -= Invalidate; | ||
Invalidate(); | ||
}, | ||
() => throw new NotSupportedException()); | ||
} | ||
|
||
public bool HasComplexContent => Count > 0; | ||
|
||
/// <summary> | ||
/// Gets or adds the text held by the inlines collection. | ||
/// <remarks> | ||
/// Can be null for complex content. | ||
/// </remarks> | ||
/// </summary> | ||
public string Text | ||
{ | ||
get => _text; | ||
set | ||
{ | ||
if (Count > 0) | ||
{ | ||
Add(new Run(value)); | ||
} | ||
else | ||
{ | ||
_text = value; | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Add a text segment to the collection. | ||
/// <remarks> | ||
/// For non complex content this appends the text to the end of currently held text. | ||
/// For complex content this adds a <see cref="Run"/> to the collection. | ||
/// </remarks> | ||
/// </summary> | ||
/// <param name="text"></param> | ||
public void Add(string text) | ||
{ | ||
if (Count == 0) | ||
{ | ||
Text += text; | ||
} | ||
else | ||
{ | ||
Add(new Run(text)); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Raised when an inline in the collection changes. | ||
/// </summary> | ||
public event EventHandler Invalidated; | ||
|
||
/// <summary> | ||
/// Raises the <see cref="Invalidated"/> event. | ||
/// </summary> | ||
protected void Invalidate() => Invalidated?.Invoke(this, EventArgs.Empty); | ||
|
||
private void Invalidate(object sender, EventArgs e) => Invalidate(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using Avalonia.Media; | ||
|
||
namespace Avalonia.Controls.Documents | ||
{ | ||
/// <summary> | ||
/// Italic element - markup helper for indicating italicized content. | ||
/// Equivalent to a Span with FontStyle property set to FontStyles.Italic. | ||
/// Can contain other inline elements. | ||
/// </summary> | ||
public sealed class Italic : Span | ||
{ | ||
static Italic() | ||
{ | ||
FontStyleProperty.OverrideDefaultValue<Italic>(FontStyle.Italic); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using Avalonia.Media.TextFormatting; | ||
using Avalonia.Utilities; | ||
|
||
namespace Avalonia.Controls.Documents | ||
{ | ||
/// <summary> | ||
/// LineBreak element that forces a line breaking. | ||
/// </summary> | ||
public class LineBreak : Inline | ||
{ | ||
/// <summary> | ||
/// Creates a new LineBreak instance. | ||
/// </summary> | ||
public LineBreak() | ||
{ | ||
} | ||
|
||
internal override int BuildRun(StringBuilder stringBuilder, | ||
IList<ValueSpan<TextRunProperties>> textStyleOverrides, int firstCharacterIndex) | ||
{ | ||
var text = Environment.NewLine; | ||
|
||
stringBuilder.Append(text); | ||
|
||
textStyleOverrides.Add(new ValueSpan<TextRunProperties>(firstCharacterIndex, text.Length, | ||
CreateTextRunProperties())); | ||
|
||
return text.Length; | ||
} | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using Avalonia.Data; | ||
using Avalonia.Media.TextFormatting; | ||
using Avalonia.Metadata; | ||
using Avalonia.Utilities; | ||
|
||
namespace Avalonia.Controls.Documents | ||
{ | ||
/// <summary> | ||
/// A terminal element in text flow hierarchy - contains a uniformatted run of unicode characters | ||
/// </summary> | ||
public class Run : Inline | ||
{ | ||
/// <summary> | ||
/// Initializes an instance of Run class. | ||
/// </summary> | ||
public Run() | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Initializes an instance of Run class specifying its text content. | ||
/// </summary> | ||
/// <param name="text"> | ||
/// Text content assigned to the Run. | ||
/// </param> | ||
public Run(string text) | ||
{ | ||
Text = text; | ||
} | ||
|
||
/// <summary> | ||
/// Dependency property backing Text. | ||
/// </summary> | ||
/// <remarks> | ||
/// Note that when a TextRange that intersects with this Run gets modified (e.g. by editing | ||
/// a selection in RichTextBox), we will get two changes to this property since we delete | ||
/// and then insert when setting the content of a TextRange. | ||
/// </remarks> | ||
public static readonly StyledProperty<string> TextProperty = AvaloniaProperty.Register<Run, string> ( | ||
nameof (Text), | ||
string.Empty, defaultBindingMode: BindingMode.TwoWay, | ||
coerce: CoerceText); | ||
|
||
/// <summary> | ||
/// The content spanned by this TextElement. | ||
/// </summary> | ||
[Content] | ||
public string Text { | ||
get { return GetValue (TextProperty); } | ||
set { SetValue (TextProperty, value); } | ||
} | ||
|
||
/// <summary> | ||
/// Coercion callback for the Text property. | ||
/// </summary> | ||
/// <param name="d">The object that the property exists on.</param> | ||
/// <param name="baseValue">The new value of the property, prior to any coercion attempt.</param> | ||
/// <returns>The coerced value.</returns> | ||
private static string CoerceText (IAvaloniaObject d, string baseValue) | ||
{ | ||
return baseValue ?? string.Empty; | ||
} | ||
|
||
internal override int BuildRun(StringBuilder stringBuilder, | ||
IList<ValueSpan<TextRunProperties>> textStyleOverrides, int firstCharacterIndex) | ||
{ | ||
var text = Text; | ||
|
||
stringBuilder.Append(text); | ||
|
||
textStyleOverrides.Add(new ValueSpan<TextRunProperties>(firstCharacterIndex, text.Length, | ||
CreateTextRunProperties())); | ||
|
||
return text.Length; | ||
} | ||
|
||
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change) | ||
{ | ||
base.OnPropertyChanged(change); | ||
|
||
switch (change.Property.Name) | ||
{ | ||
case nameof(Text): | ||
Invalidate(); | ||
break; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using Avalonia.Media.TextFormatting; | ||
using Avalonia.Metadata; | ||
using Avalonia.Utilities; | ||
|
||
namespace Avalonia.Controls.Documents | ||
{ | ||
/// <summary> | ||
/// Span element used for grouping other Inline elements. | ||
/// </summary> | ||
public class Span : Inline | ||
{ | ||
/// <summary> | ||
/// Defines the <see cref="Inlines"/> property. | ||
/// </summary> | ||
public static readonly DirectProperty<Span, InlineCollection> InlinesProperty = | ||
AvaloniaProperty.RegisterDirect<Span, InlineCollection>( | ||
nameof(Inlines), | ||
o => o.Inlines); | ||
|
||
/// <summary> | ||
/// Initializes a new instance of a Span element. | ||
/// </summary> | ||
public Span() | ||
{ | ||
Inlines = new InlineCollection(this); | ||
|
||
Inlines.Invalidated += (s, e) => Invalidate(); | ||
} | ||
|
||
/// <summary> | ||
/// Gets or sets the inlines. | ||
/// </summary> | ||
[Content] | ||
public InlineCollection Inlines { get; } | ||
|
||
internal override int BuildRun(StringBuilder stringBuilder, IList<ValueSpan<TextRunProperties>> textStyleOverrides, int firstCharacterIndex) | ||
{ | ||
var length = 0; | ||
|
||
if (Inlines.HasComplexContent) | ||
{ | ||
foreach (var inline in Inlines) | ||
{ | ||
var inlineLength = inline.BuildRun(stringBuilder, textStyleOverrides, firstCharacterIndex); | ||
|
||
firstCharacterIndex += inlineLength; | ||
|
||
length += inlineLength; | ||
} | ||
} | ||
else | ||
{ | ||
stringBuilder.Append(Inlines.Text); | ||
|
||
length = Inlines.Text.Length; | ||
|
||
textStyleOverrides.Add(new ValueSpan<TextRunProperties>(firstCharacterIndex, length, | ||
CreateTextRunProperties())); | ||
} | ||
|
||
return length; | ||
} | ||
} | ||
} |
Oops, something went wrong.