moved from SVN to git
This commit is contained in:
141
DBToolControls/HighlightingRichTextBox.cs
Normal file
141
DBToolControls/HighlightingRichTextBox.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
[assembly: CLSCompliant(true)]
|
||||
namespace DBToolControls {
|
||||
public class HighlightingRichTextBox : RichTextBox {
|
||||
private bool textHandlingInProgress;
|
||||
private bool pasting;
|
||||
private string lineStartOffset;
|
||||
|
||||
private SyntaxProvider syntaxProvider = new SyntaxProvider();
|
||||
public SyntaxProvider SyntaxProvider {
|
||||
get { return syntaxProvider; }
|
||||
}
|
||||
|
||||
public string Text {
|
||||
set {
|
||||
Document.Blocks.Clear();
|
||||
if (value.Length > 2) {
|
||||
Document.Blocks.Add(new Paragraph(new Run(value.Substring(0, value.Length - 2))));
|
||||
RebuildContent();
|
||||
SelectAll();
|
||||
}
|
||||
}
|
||||
get { return new TextRange(Document.ContentStart, Document.ContentEnd).Text; }
|
||||
}
|
||||
|
||||
public HighlightingRichTextBox() {
|
||||
Document.LineHeight = 1;
|
||||
DataObject.AddPastingHandler(this, (sender, e) => pasting = true);
|
||||
}
|
||||
|
||||
// keep indentation in new lines
|
||||
|
||||
protected override void OnPreviewKeyDown(KeyEventArgs e) {
|
||||
if (e.Key == Key.Tab) {
|
||||
CaretPosition.InsertTextInRun("\t");
|
||||
if(CaretPosition.GetOffsetToPosition(Document.ContentEnd) != 0)
|
||||
CaretPosition = CaretPosition.GetPositionAtOffset(1);
|
||||
e.Handled = true;
|
||||
} else if (e.Key == Key.Enter) {
|
||||
TextRange range = new TextRange(CaretPosition.GetLineStartPosition(0), CaretPosition);
|
||||
string s = range.Text;
|
||||
lineStartOffset = s.Substring(0, s.Length - s.TrimStart().Length);
|
||||
if (new List<string> { ")", ");", "}", "};" }.Contains(s.Trim())) { // unindent
|
||||
if (lineStartOffset.EndsWith("\t")) {
|
||||
lineStartOffset = lineStartOffset.Remove(lineStartOffset.Length - 1);
|
||||
} else if (lineStartOffset.EndsWith(" ")) {
|
||||
lineStartOffset = lineStartOffset.Remove(lineStartOffset.Length - 2);
|
||||
}
|
||||
range.Text = lineStartOffset + range.Text.Trim();
|
||||
CaretPosition = range.End;
|
||||
} else if (CaretPosition.GetPositionAtOffset(-1) != null) { // indent if line ends with ( or {
|
||||
s = new TextRange(CaretPosition.GetPositionAtOffset(-1), CaretPosition).Text;
|
||||
if (s.Length > 0 && new List<char> { '(', '{' }.Contains(s[0]))
|
||||
lineStartOffset += " ";
|
||||
}
|
||||
}
|
||||
base.OnPreviewKeyDown(e);
|
||||
}
|
||||
|
||||
protected override void OnKeyUp(KeyEventArgs e) {
|
||||
if (e.Key == Key.Enter)
|
||||
CaretPosition.InsertTextInRun(lineStartOffset);
|
||||
base.OnKeyUp(e);
|
||||
}
|
||||
|
||||
// Syntax Highlighting
|
||||
|
||||
protected override void OnTextChanged(TextChangedEventArgs e) {
|
||||
if (pasting) {
|
||||
pasting = false;
|
||||
RebuildContent();
|
||||
} else if (!textHandlingInProgress) {
|
||||
FormatTextAt(CaretPosition);
|
||||
}
|
||||
base.OnTextChanged(e);
|
||||
}
|
||||
|
||||
private void FormatTextAt(TextPointer pointer) {
|
||||
textHandlingInProgress = true;
|
||||
TextRange range = WordBreaker.GetWordRange(pointer);
|
||||
|
||||
TextPointer temp = range.End.GetNextInsertionPosition(LogicalDirection.Backward);
|
||||
if (temp != null) {
|
||||
TextRange lastInput = new TextRange(range.End, temp);
|
||||
if (SyntaxProvider.Delimiters.Contains(lastInput.Text[0]))
|
||||
lastInput.ClearAllProperties();
|
||||
}
|
||||
|
||||
ApplyFormatting(range);
|
||||
temp = CaretPosition.GetPositionAtOffset(-3);
|
||||
if (temp != null && !range.Contains(temp)) ApplyFormatting(WordBreaker.GetWordRange(temp));
|
||||
textHandlingInProgress = false;
|
||||
}
|
||||
|
||||
private void RebuildContent() {
|
||||
textHandlingInProgress = true;
|
||||
string s = new TextRange(Document.ContentStart, Document.ContentEnd).Text;
|
||||
Paragraph p = new Paragraph();
|
||||
string[] words = Regex.Split(s, SyntaxProvider.DelimitersAsRegExPattern);
|
||||
if (words.Length < 2) return;
|
||||
foreach (string word in words.Take(words.Length - 2).Where(w => w.Length > 0))
|
||||
p.Inlines.Add(word.Trim().Length > 0 ? ApplyFormatting(new Run(word)) : new Run(word));
|
||||
|
||||
Document.Blocks.Clear();
|
||||
Document.Blocks.Add(p);
|
||||
CaretPosition = Document.ContentEnd;
|
||||
textHandlingInProgress = false;
|
||||
}
|
||||
|
||||
private void ApplyFormatting(TextRange range) {
|
||||
Dictionary<DependencyProperty, object> formatting = SyntaxProvider.GetFormattingFor(range.Text);
|
||||
if (formatting != null)
|
||||
foreach (KeyValuePair<DependencyProperty, object> pv in formatting)
|
||||
range.ApplyPropertyValue(pv.Key, pv.Value);
|
||||
else
|
||||
range.ClearAllProperties();
|
||||
}
|
||||
|
||||
private Run ApplyFormatting(Run r) {
|
||||
Dictionary<DependencyProperty, object> formatting = SyntaxProvider.GetFormattingFor(r.Text);
|
||||
if (formatting != null)
|
||||
foreach (KeyValuePair<DependencyProperty, object> pv in formatting)
|
||||
r.SetValue(pv.Key, pv.Value);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user