-
Notifications
You must be signed in to change notification settings - Fork 57
Expand file tree
/
Copy pathRichTextBlockFormatter.cs
More file actions
157 lines (131 loc) · 5.79 KB
/
RichTextBlockFormatter.cs
File metadata and controls
157 lines (131 loc) · 5.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
using System.Collections.Generic;
using ColorCode.Parsing;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Documents;
using ColorCode.Styling;
using Windows.UI.Text;
using ColorCode.UWP.Common;
using ColorCode.Common;
using Windows.UI.Xaml;
namespace ColorCode
{
/// <summary>
/// Creates a <see cref="RichTextBlockFormatter"/>, for rendering Syntax Highlighted code to a RichTextBlock.
/// </summary>
public class RichTextBlockFormatter : CodeColorizerBase
{
/// <summary>
/// Creates a <see cref="RichTextBlockFormatter"/>, for rendering Syntax Highlighted code to a RichTextBlock.
/// </summary>
/// <param name="Theme">The Theme to use, determines whether to use Default Light or Default Dark.</param>
public RichTextBlockFormatter(ElementTheme Theme, ILanguageParser languageParser = null) : this(Theme == ElementTheme.Dark ? StyleDictionary.DefaultDark : StyleDictionary.DefaultLight, languageParser)
{
}
/// <summary>
/// Creates a <see cref="RichTextBlockFormatter"/>, for rendering Syntax Highlighted code to a RichTextBlock.
/// </summary>
/// <param name="Style">The Custom styles to Apply to the formatted Code.</param>
/// <param name="languageParser">The language parser that the <see cref="RichTextBlockFormatter"/> instance will use for its lifetime.</param>
public RichTextBlockFormatter(StyleDictionary Style = null, ILanguageParser languageParser = null) : base(Style, languageParser)
{
}
/// <summary>
/// Adds Syntax Highlighted Source Code to the provided RichTextBlock.
/// </summary>
/// <param name="sourceCode">The source code to colorize.</param>
/// <param name="language">The language to use to colorize the source code.</param>
/// <param name="RichText">The Control to add the Text to.</param>
public void FormatRichTextBlock(string sourceCode, ILanguage Language, RichTextBlock RichText)
{
var paragraph = new Paragraph();
RichText.Blocks.Add(paragraph);
FormatInlines(sourceCode, Language, paragraph.Inlines);
}
/// <summary>
/// Adds Syntax Highlighted Source Code to the provided InlineCollection.
/// </summary>
/// <param name="sourceCode">The source code to colorize.</param>
/// <param name="language">The language to use to colorize the source code.</param>
/// <param name="InlineCollection">InlineCollection to add the Text to.</param>
public void FormatInlines(string sourceCode, ILanguage Language, InlineCollection InlineCollection)
{
this.InlineCollection = InlineCollection;
languageParser.Parse(sourceCode, Language, (parsedSourceCode, captures) => Insert(parsedSourceCode, captures));
}
private InlineCollection InlineCollection { get; set; }
protected void Insert(string parsedSourceCode, IList<Scope> scopes)
{
var styleInsertions = new List<TextInsertion>();
foreach (Scope scope in scopes)
GetStyleInsertionsForCapturedStyle(scope, styleInsertions);
styleInsertions.SortStable((x, y) => x.Index.CompareTo(y.Index));
int offset = 0;
Scope PreviousScope = null;
foreach (var styleinsertion in styleInsertions)
{
var text = parsedSourceCode.Substring(offset, styleinsertion.Index - offset);
CreateSpan(text, PreviousScope);
if (!string.IsNullOrWhiteSpace(styleinsertion.Text))
{
CreateSpan(text, PreviousScope);
}
offset = styleinsertion.Index;
PreviousScope = styleinsertion.Scope;
}
var remaining = parsedSourceCode.Substring(offset);
// Ensures that those loose carriages don't run away!
if (remaining != "\r")
{
CreateSpan(remaining, null);
}
}
private void CreateSpan(string Text, Scope scope)
{
var span = new Span();
var run = new Run
{
Text = Text
};
// Styles and writes the text to the span.
if (scope != null) StyleRun(run, scope);
span.Inlines.Add(run);
InlineCollection.Add(span);
}
private void StyleRun(Run Run, Scope Scope)
{
string foreground = null;
string background = null;
bool italic = false;
bool bold = false;
if (Styles.Contains(Scope.Name))
{
Styling.Style style = Styles[Scope.Name];
foreground = style.Foreground;
background = style.Background;
italic = style.Italic;
bold = style.Bold;
}
if (!string.IsNullOrWhiteSpace(foreground))
Run.Foreground = foreground.GetSolidColorBrush();
//Background isn't supported, but a workaround could be created.
if (italic)
Run.FontStyle = FontStyle.Italic;
if (bold)
Run.FontWeight = FontWeights.Bold;
}
private void GetStyleInsertionsForCapturedStyle(Scope scope, ICollection<TextInsertion> styleInsertions)
{
styleInsertions.Add(new TextInsertion
{
Index = scope.Index,
Scope = scope
});
foreach (Scope childScope in scope.Children)
GetStyleInsertionsForCapturedStyle(childScope, styleInsertions);
styleInsertions.Add(new TextInsertion
{
Index = scope.Index + scope.Length
});
}
}
}