diff options
-rw-r--r-- | Juick/Classes/ParagraphBindingBehavior.cs | 36 | ||||
-rw-r--r-- | Juick/Controls/HyperLinkRichTextBox.cs (renamed from Juick/Classes/RichTextConverter.cs) | 158 | ||||
-rw-r--r-- | Juick/Juick.csproj | 3 | ||||
-rw-r--r-- | Juick/MainPage.xaml | 21 | ||||
-rw-r--r-- | Juick/ThreadView.xaml | 16 |
5 files changed, 91 insertions, 143 deletions
diff --git a/Juick/Classes/ParagraphBindingBehavior.cs b/Juick/Classes/ParagraphBindingBehavior.cs deleted file mode 100644 index 524f4db..0000000 --- a/Juick/Classes/ParagraphBindingBehavior.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Collections.Generic;
-using System.Windows;
-using System.Windows.Documents;
-
-namespace Juick.Classes
-{
- public static class ParagraphBindingBehavior
- {
- public static readonly DependencyProperty AssignedInlinesProperty =
- DependencyProperty.RegisterAttached("AssignedInlines", typeof(IEnumerable<Inline>), typeof(Paragraph), new PropertyMetadata(null, AssignedInlinesCallback));
-
- static void AssignedInlinesCallback(DependencyObject target, DependencyPropertyChangedEventArgs e)
- {
- var inlines = ((Paragraph)target).Inlines;
- inlines.Clear();
- var value = e.NewValue as IEnumerable<Inline>;
- if (value != null)
- {
- foreach (var inline in value)
- {
- inlines.Add(inline);
- }
- }
- }
-
- public static IEnumerable<Inline> GetAssignedInlines(DependencyObject obj)
- {
- return (IEnumerable<Inline>)obj.GetValue(AssignedInlinesProperty);
- }
-
- public static void SetAssignedInlines(DependencyObject obj, IEnumerable<Inline> value)
- {
- obj.SetValue(AssignedInlinesProperty, value);
- }
- }
-}
diff --git a/Juick/Classes/RichTextConverter.cs b/Juick/Controls/HyperLinkRichTextBox.cs index 4f78b96..6ec6883 100644 --- a/Juick/Classes/RichTextConverter.cs +++ b/Juick/Controls/HyperLinkRichTextBox.cs @@ -1,78 +1,80 @@ -using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Text.RegularExpressions;
-using System.Windows.Data;
-using System.Windows.Documents;
-
-namespace Juick.Classes
-{
- public class RichTextConverter : IValueConverter
- {
- 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 object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- var stringValue = (string)value;
- if (string.IsNullOrEmpty(stringValue))
- {
- return Enumerable.Empty<Inline>();
- }
-
- var result = new List<Inline>();
- 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)
- {
- result.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);
- }
- result.Add(hyperLink);
-
- index = match.Index + match.Length;
- }
-
- if (index == 0 || index < stringValue.Length - 1)
- {
- var lastRunText = stringValue.Substring(index);
- if (lastRunText.Length > 0)
- {
- result.Add(new Run { Text = lastRunText });
- }
- }
- return result;
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- return value;
- }
- }
-}
+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); + } + } +} diff --git a/Juick/Juick.csproj b/Juick/Juick.csproj index 7bd452a..d161046 100644 --- a/Juick/Juick.csproj +++ b/Juick/Juick.csproj @@ -76,9 +76,8 @@ <Compile Include="Classes\BindingChangedEventArgs.cs" />
<Compile Include="Classes\DelegateCommand.cs" />
<Compile Include="Classes\DependencyPropertyListener.cs" />
- <Compile Include="Classes\ParagraphBindingBehavior.cs" />
- <Compile Include="Classes\RichTextConverter.cs" />
<Compile Include="Classes\ScrollViewerMonitor.cs" />
+ <Compile Include="Controls\HyperLinkRichTextBox.cs" />
<Compile Include="LoginView.xaml.cs">
<DependentUpon>LoginView.xaml</DependentUpon>
</Compile>
diff --git a/Juick/MainPage.xaml b/Juick/MainPage.xaml index bffd94f..ded6d33 100644 --- a/Juick/MainPage.xaml +++ b/Juick/MainPage.xaml @@ -7,7 +7,7 @@ xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:bindings="clr-namespace:Juick.Classes"
+ xmlns:bindings="clr-namespace:Juick.Classes" xmlns:controls1="clr-namespace:Juick.Controls"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="728"
d:DataContext="{d:DesignData SampleData/MainViewModelSampleData.xaml}"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
@@ -15,12 +15,7 @@ Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
phoneshell:SystemTray.IsVisible="True">
- <phone:PhoneApplicationPage.Resources>
- <ResourceDictionary>
- <bindings:RichTextConverter x:Key="inlineConverter" />
- </ResourceDictionary>
- </phone:PhoneApplicationPage.Resources>
-
+
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
@@ -80,13 +75,11 @@ FontSize="{StaticResource PhoneFontSizeLarge}"
Style="{StaticResource PhoneTextAccentStyle}" />
<!--Style="{StaticResource PhoneTextNormalStyle}"-->
- <RichTextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
+ <controls1:HyperLinkRichTextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
TextWrapping="Wrap" HorizontalAlignment="Left"
Foreground="{StaticResource PhoneForegroundBrush}"
Margin="5,0,5,5" VerticalAlignment="Top"
- IsReadOnly="True">
- <Paragraph bindings:ParagraphBindingBehavior.AssignedInlines="{Binding MessageText, Converter={StaticResource inlineConverter}}" />
- </RichTextBox>
+ IsReadOnly="True" Text="{Binding MessageText}" />
<Image Source="{Binding Attachment}" Grid.Row="2" Grid.Column="0" Margin="3" Grid.ColumnSpan="2" />
<TextBlock Text="{Binding Status}" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"
Foreground="{StaticResource PhoneForegroundBrush}"
@@ -136,13 +129,11 @@ FontFamily="{StaticResource PhoneFontFamilySemiLight}"
FontSize="{StaticResource PhoneFontSizeLarge}"
Style="{StaticResource PhoneTextAccentStyle}" />
- <RichTextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
+ <controls1:HyperLinkRichTextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
TextWrapping="Wrap" HorizontalAlignment="Left"
Foreground="{StaticResource PhoneForegroundBrush}"
Margin="5,0,5,5" VerticalAlignment="Top"
- IsReadOnly="True">
- <Paragraph bindings:ParagraphBindingBehavior.AssignedInlines="{Binding MessageText, Converter={StaticResource inlineConverter}}" />
- </RichTextBox>
+ IsReadOnly="True" Text="{Binding MessageText}" />
<Image Source="{Binding Attachment}" Grid.Row="2" Grid.Column="0" Margin="3" Grid.ColumnSpan="2" />
<TextBlock Text="{Binding Status}" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"
Foreground="{StaticResource PhoneForegroundBrush}"
diff --git a/Juick/ThreadView.xaml b/Juick/ThreadView.xaml index 4f622c7..7de5533 100644 --- a/Juick/ThreadView.xaml +++ b/Juick/ThreadView.xaml @@ -6,20 +6,14 @@ xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:bindings="clr-namespace:Juick.Classes"
+ xmlns:controls="clr-namespace:Juick.Controls"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
shell:SystemTray.IsVisible="True">
-
- <phone:PhoneApplicationPage.Resources>
- <ResourceDictionary>
- <bindings:RichTextConverter x:Key="inlineConverter"/>
- </ResourceDictionary>
- </phone:PhoneApplicationPage.Resources>
-
+
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
@@ -62,13 +56,11 @@ FontSize="{StaticResource PhoneFontSizeLarge}"
Style="{StaticResource PhoneTextAccentStyle}" />
<!--Style="{StaticResource PhoneTextNormalStyle}"-->
- <RichTextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
+ <controls:HyperLinkRichTextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
Foreground="{StaticResource PhoneForegroundBrush}"
Margin="5,0,5,5" VerticalAlignment="Top"
TextWrapping="Wrap" HorizontalAlignment="Left"
- IsReadOnly="True">
- <Paragraph bindings:ParagraphBindingBehavior.AssignedInlines="{Binding MessageText, Converter={StaticResource inlineConverter}}" />
- </RichTextBox>
+ IsReadOnly="True" Text="{Binding MessageText}" />
<Image Source="{Binding Attachment}" Grid.Row="2" Grid.Column="0" Margin="3" Grid.ColumnSpan="2" />
<!-- TextBlock Text="{Binding Status}" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"
Foreground="{StaticResource PhoneForegroundBrush}"
|