diff options
Diffstat (limited to 'Juick/Controls')
-rw-r--r-- | Juick/Controls/HyperLinkRichTextBox.cs | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/Juick/Controls/HyperLinkRichTextBox.cs b/Juick/Controls/HyperLinkRichTextBox.cs new file mode 100644 index 0000000..6ec6883 --- /dev/null +++ b/Juick/Controls/HyperLinkRichTextBox.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Media; + +namespace Juick.Controls +{ + public class HyperLinkRichTextBox : RichTextBox + { + static readonly Regex UrlRegex = new Regex(@"http(s)?://([\w+?\.\w+])+([a-zA-Z0-9\~\!\@\#\$\%\^\&\*\(\)_\-\=\+\\\/\?\.\:\;\'\,]*)?", RegexOptions.Compiled); + // TODO: Add more entities + static readonly Regex JuickEntityRegex = new Regex(@"#(\d+)(/\d+)?", RegexOptions.Compiled); + public static readonly DependencyProperty TextProperty = + DependencyProperty.Register("Text", typeof(string), typeof(HyperLinkRichTextBox), new PropertyMetadata(default(string), TextPropertyChanged)); + + public string Text + { + get { return (string)GetValue(TextProperty); } + set { SetValue(TextProperty, value); } + } + + private static void TextPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) + { + var richTextBox = (HyperLinkRichTextBox)dependencyObject; + var stringValue = (string)dependencyPropertyChangedEventArgs.NewValue; + var paragraph = new Paragraph(); + + var index = 0; + foreach (var match in UrlRegex.Matches(stringValue).OfType<Match>().Union(JuickEntityRegex.Matches(stringValue).OfType<Match>())) + { + Uri uri = null; + if (!Uri.TryCreate(match.Value, UriKind.Absolute, out uri)) + { + // Juick entity + uri = new Uri(string.Format("/ThreadView.xaml?mid={0}", JuickEntityRegex.Replace(match.Value, "$1")), UriKind.Relative); + } + if (match.Index > 0) + { + var length = match.Index - index; + if (length > 0) + { + paragraph.Inlines.Add(new Run { Text = stringValue.Substring(index, length) }); + } + } + + var hyperLink = new Hyperlink + { + NavigateUri = uri + }; + if (uri.IsAbsoluteUri) + { + hyperLink.TargetName = "_blank"; + hyperLink.Inlines.Add(uri.Host); + } + else + { + hyperLink.Inlines.Add(match.Value); + } + paragraph.Inlines.Add(hyperLink); + + index = match.Index + match.Length; + } + + if (index == 0 || index < stringValue.Length - 1) + { + var lastRunText = stringValue.Substring(index); + if (lastRunText.Length > 0) + { + paragraph.Inlines.Add(new Run { Text = lastRunText }); + } + } + richTextBox.Blocks.Clear(); + richTextBox.Blocks.Add(paragraph); + } + } +} |