From 28986641046c8ee1dc2aba0055dfa36b811b25d2 Mon Sep 17 00:00:00 2001 From: k0st1x Date: Sun, 30 Sep 2012 23:22:25 +0400 Subject: replace TextBlock by RichTextBox --- Juick/Classes/ParagraphBindingBehavior.cs | 36 ++++++++++++++++ Juick/Classes/RichTextConverter.cs | 68 ++++++++++++++++++------------- Juick/Juick.csproj | 4 +- Juick/MainPage.xaml | 21 ++++++---- Juick/MainPage.xaml.cs | 38 ----------------- Juick/ThreadView.xaml | 21 ++++++++-- Juick/packages.config | 2 +- 7 files changed, 108 insertions(+), 82 deletions(-) create mode 100644 Juick/Classes/ParagraphBindingBehavior.cs diff --git a/Juick/Classes/ParagraphBindingBehavior.cs b/Juick/Classes/ParagraphBindingBehavior.cs new file mode 100644 index 0000000..6a05579 --- /dev/null +++ b/Juick/Classes/ParagraphBindingBehavior.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Windows; +using System.Windows.Documents; + +namespace Juick.Classes +{ + public static class ParagraphBindingBehavior + { + static void AssignedInlinesCallback(DependencyObject target, DependencyPropertyChangedEventArgs e) + { + var inlines = ((Paragraph)target).Inlines; + inlines.Clear(); + var value = e.NewValue as IEnumerable; + if (value != null) + { + foreach (var inline in value) + { + inlines.Add(inline); + } + } + } + + public static IEnumerable GetAssignedInlines(DependencyObject obj) + { + return (IEnumerable)obj.GetValue(AssignedInlinesProperty); + } + + public static void SetAssignedInlines(DependencyObject obj, IEnumerable value) + { + obj.SetValue(AssignedInlinesProperty, value); + } + + public static readonly DependencyProperty AssignedInlinesProperty = + DependencyProperty.RegisterAttached("AssignedInlines", typeof(IEnumerable), typeof(Paragraph), new PropertyMetadata(null, AssignedInlinesCallback)); + } +} diff --git a/Juick/Classes/RichTextConverter.cs b/Juick/Classes/RichTextConverter.cs index ee6ffa7..cdc1938 100644 --- a/Juick/Classes/RichTextConverter.cs +++ b/Juick/Classes/RichTextConverter.cs @@ -1,53 +1,63 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Net; -using System.Windows; -using System.Windows.Controls; +using System.Linq; +using System.Text.RegularExpressions; using System.Windows.Data; using System.Windows.Documents; -using System.Windows.Ink; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Animation; -using System.Windows.Shapes; -using Microsoft.Phone.Tasks; namespace Juick.Classes { public class RichTextConverter : IValueConverter { + static readonly Regex UrlRegex = new Regex(@"http(s)?://([\w+?\.\w+])+([a-zA-Z0-9\~\!\@\#\$\%\^\&\*\(\)_\-\=\+\\\/\?\.\:\;\'\,]*)?", RegexOptions.Compiled); + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - var message = value as string; - var runs = new List(); - - foreach (var word in message.Split(new char[] {' ', '\n'})) + var stringValue = (string)value; + if (string.IsNullOrEmpty(stringValue)) { - Uri uri; + return Enumerable.Empty(); + } - if (Uri.TryCreate(word, UriKind.Absolute, out uri) || - (word.StartsWith("www.") && Uri.TryCreate("http://" + word, UriKind.Absolute, out uri))) + var result = new List(); + var index = 0; + foreach (var match in UrlRegex.Matches(stringValue).Cast()) + { + Uri uri = null; + if (!Uri.TryCreate(match.Value, UriKind.Absolute, out uri)) { - var link = new Hyperlink(); - link.Inlines.Add(new Run() { Text = word }); - link.Click += (sender, e) => - { - var hyperLink = (sender as Hyperlink); - new WebBrowserTask() { Uri = uri }.Show(); - }; - - runs.Add(link); + continue; } - else + if (match.Index > 0) { - runs.Add(new Run() { Text = word }); + var length = match.Index - index; + if (length > 0) + { + result.Add(new Run { Text = stringValue.Substring(index, length) }); + } } - runs.Add(new Run() { Text = " " }); + var hyperLink = new Hyperlink + { + NavigateUri = uri, + TargetName = "_blank" + }; + hyperLink.Inlines.Add(uri.Host); + result.Add(hyperLink); + + index = match.Index + match.Length; } - return runs; + 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) diff --git a/Juick/Juick.csproj b/Juick/Juick.csproj index 19a0714..eaff44f 100644 --- a/Juick/Juick.csproj +++ b/Juick/Juick.csproj @@ -53,9 +53,8 @@ - ..\packages\Newtonsoft.Json.4.0.8\lib\sl4-windowsphone71\Newtonsoft.Json.dll + ..\packages\Newtonsoft.Json.4.5.9\lib\sl4-windowsphone71\Newtonsoft.Json.dll - False ..\packages\RestSharp.102.7\lib\sl4-wp71\RestSharp.WindowsPhone.dll @@ -78,6 +77,7 @@ App.xaml + LoginView.xaml diff --git a/Juick/MainPage.xaml b/Juick/MainPage.xaml index 4b91832..d8e8742 100644 --- a/Juick/MainPage.xaml +++ b/Juick/MainPage.xaml @@ -6,19 +6,20 @@ xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" 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:Juick="clr-namespace:Juick" mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="728" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:bindings="clr-namespace:Juick.Classes" + mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="728" d:DataContext="{d:DesignData SampleData/MainViewModelSampleData.xaml}" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="PortraitOrLandscape" Orientation="Portrait" shell:SystemTray.IsVisible="False"> - + @@ -57,13 +58,17 @@ FontFamily="{StaticResource PhoneFontFamilySemiLight}" FontSize="{StaticResource PhoneFontSizeLarge}" Style="{StaticResource PhoneTextAccentStyle}" /> - - + TextWrapping="Wrap" HorizontalAlignment="Left" + IsReadOnly="True"> + + + + + ), - typeof(MainPage), - new PropertyMetadata(null, OnInlineListPropertyChanged)); - - private static void OnInlineListPropertyChanged(DependencyObject obj, - DependencyPropertyChangedEventArgs e) - { - var tb = obj as TextBlock; - if (tb != null) - { - // clear previous inlines - tb.Inlines.Clear(); - - // add new inlines - var inlines = e.NewValue as List; - if (inlines != null) - { - inlines.ForEach(inl => tb.Inlines.Add((inl))); - } - } - } - private void ApplicationBarIconButtonClick(object sender, EventArgs e) { App.MyFeedView.Items.Clear(); diff --git a/Juick/ThreadView.xaml b/Juick/ThreadView.xaml index d8f17a0..4c2c129 100644 --- a/Juick/ThreadView.xaml +++ b/Juick/ThreadView.xaml @@ -6,12 +6,19 @@ 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" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="PortraitOrLandscape" Orientation="Portrait" - mc:Ignorable="d" d:DesignHeight="696" d:DesignWidth="480" + mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray.IsVisible="True"> + + @@ -54,11 +61,17 @@ FontFamily="{StaticResource PhoneFontFamilySemiLight}" FontSize="{StaticResource PhoneFontSizeLarge}" Style="{StaticResource PhoneTextAccentStyle}" /> - + TextWrapping="Wrap" HorizontalAlignment="Left" + IsReadOnly="True"> + + + + +