PageRenderTime 45ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/Code/Client/Inbox2/UI/Resources/ResourceConverters.cs

http://github.com/waseems/inbox2_desktop
C# | 1263 lines | 937 code | 301 blank | 25 comment | 117 complexity | ff2fd7f556a322404c2f5525cc231374 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Drawing;
  5. using System.Drawing.Imaging;
  6. using System.Globalization;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Runtime.InteropServices;
  10. using System.Text;
  11. using System.Text.RegularExpressions;
  12. using System.Windows;
  13. using System.Windows.Controls;
  14. using System.Windows.Data;
  15. using System.Windows.Documents;
  16. using System.Windows.Media;
  17. using System.Windows.Media.Imaging;
  18. using Inbox2.Core.Configuration.Channels;
  19. using Inbox2.Framework;
  20. using Inbox2.Framework.Extensions;
  21. using Inbox2.Framework.Interfaces.Enumerations;
  22. using Inbox2.Framework.Localization;
  23. using Inbox2.Framework.Threading;
  24. using Inbox2.Framework.UI;
  25. using Inbox2.Framework.UI.AsyncImage;
  26. using Inbox2.Framework.VirtualMailBox.Entities;
  27. using Inbox2.Platform.Channels;
  28. using Inbox2.Platform.Channels.Configuration;
  29. using Inbox2.Platform.Channels.Entities;
  30. using Inbox2.Platform.Channels.Extensions;
  31. using Inbox2.Platform.Channels.Interfaces;
  32. using Inbox2.Platform.Channels.Text;
  33. using Inbox2.Platform.Interfaces.Enumerations;
  34. using Microsoft.Win32;
  35. using Brush = System.Windows.Media.Brush;
  36. using Color = System.Windows.Media.Color;
  37. using Label = Inbox2.Framework.VirtualMailBox.Entities.Label;
  38. using Point = System.Windows.Point;
  39. namespace Inbox2.UI.Resources
  40. {
  41. #region PassThroughMultiValueConverter
  42. public class MultiValueResult
  43. {
  44. public object Object1 { get; set; }
  45. public object Object2 { get; set; }
  46. }
  47. public class PassThroughMultiValueConverter : IMultiValueConverter
  48. {
  49. public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  50. {
  51. return new MultiValueResult { Object1 = values[0], Object2 = values[1] };
  52. }
  53. public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  54. {
  55. throw new NotImplementedException();
  56. }
  57. }
  58. #endregion
  59. #region PassThroughConverter
  60. public class PassThroughConverter : IValueConverter
  61. {
  62. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  63. {
  64. return value;
  65. }
  66. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  67. {
  68. throw new NotImplementedException();
  69. }
  70. }
  71. #endregion
  72. // Message converters
  73. #region MessageDateConverter
  74. public class MessageDateConverter : IValueConverter
  75. {
  76. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  77. {
  78. if (value == null)
  79. return String.Empty;
  80. Message message = (Message)value;
  81. return String.Format("on {0:dd-MM-yy} at {0:HH:mm}", message.DateReceived ?? message.DateSent);
  82. }
  83. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  84. {
  85. throw new NotImplementedException();
  86. }
  87. }
  88. #endregion
  89. #region DateToRelativeTimeConverter
  90. public class DateToRelativeTimeConverter : IValueConverter
  91. {
  92. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  93. {
  94. if (value == null)
  95. return String.Empty;
  96. DateTime dt = (DateTime)value;
  97. return dt.ToRelativeTime();
  98. }
  99. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  100. {
  101. throw new NotImplementedException();
  102. }
  103. }
  104. #endregion
  105. // Channel converters
  106. #region ChannelIconConverter
  107. public class ChannelIconConverter : IValueConverter
  108. {
  109. public static readonly BitmapSource _Fallback;
  110. static readonly Dictionary<string, BitmapSource> _SmallIconsCache;
  111. static readonly Dictionary<string, BitmapSource> _MediumIconsCache;
  112. static readonly Dictionary<string, BitmapSource> _LargeIconsCache;
  113. static object synclock = new object();
  114. static ChannelIconConverter()
  115. {
  116. _SmallIconsCache = new Dictionary<string, BitmapSource>();
  117. _MediumIconsCache = new Dictionary<string, BitmapSource>();
  118. _LargeIconsCache = new Dictionary<string, BitmapSource>();
  119. _Fallback = new BitmapImage(new Uri("pack://application:,,,/Inbox2.UI.Resources;component/icons/newmessage-icon.png"));
  120. _Fallback.Freeze();
  121. }
  122. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  123. {
  124. if (value == null)
  125. return _Fallback;
  126. int size = 10;
  127. var channel = (ChannelConfiguration)value;
  128. if (parameter != null)
  129. size = Int32.Parse(parameter.ToString());
  130. bool contains;
  131. lock (synclock)
  132. contains = _SmallIconsCache.ContainsKey(channel.DisplayName);
  133. if (!contains)
  134. {
  135. lock (synclock)
  136. {
  137. // Icon not loaded yet
  138. // Get the assembly this channel is loaded from
  139. var assembly = channel.GetType().Assembly;
  140. var resourceNameFormat = assembly.GetName().Name + ".Resources.icon-{0}.png";
  141. using (var stream = assembly.GetManifestResourceStream(String.Format(resourceNameFormat, 10)))
  142. {
  143. if (stream == null) throw new ApplicationException("Channel has no small icon configured");
  144. _SmallIconsCache.Add(channel.DisplayName, new PngBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad).Frames[0]);
  145. }
  146. using (var stream = assembly.GetManifestResourceStream(String.Format(resourceNameFormat, 13)))
  147. {
  148. if (stream == null) throw new ApplicationException("Channel has no medium icon configured");
  149. _MediumIconsCache.Add(channel.DisplayName, new PngBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad).Frames[0]);
  150. }
  151. using (var stream = assembly.GetManifestResourceStream(String.Format(resourceNameFormat, 64)))
  152. {
  153. if (stream == null) throw new ApplicationException("Channel has no large icon configured");
  154. _LargeIconsCache.Add(channel.DisplayName, new PngBitmapDecoder(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad).Frames[0]);
  155. }
  156. }
  157. }
  158. switch (size)
  159. {
  160. case 10: return _SmallIconsCache[channel.DisplayName];
  161. case 13: return _MediumIconsCache[channel.DisplayName];
  162. case 64: return _LargeIconsCache[channel.DisplayName];
  163. default: throw new ArgumentException("Channel icon size not supported: only 10, 13 and 64 are allowed");
  164. }
  165. }
  166. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  167. {
  168. throw new NotImplementedException();
  169. }
  170. }
  171. #endregion
  172. #region ChannelAvatarConverter
  173. public class ChannelAvatarConverter : IValueConverter
  174. {
  175. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  176. {
  177. var channel = (ChannelInstance)value;
  178. if (channel.Configuration.Charasteristics.SupportsStatusUpdates)
  179. {
  180. var image = new AsyncHttpImage(delegate
  181. {
  182. ChannelContext.Current.ClientContext =
  183. new ChannelClientContext(ClientState.Current.Context, channel.Configuration);
  184. var profile = channel.StatusUpdatesChannel.GetProfile();
  185. return profile.AvatarUrl;
  186. });
  187. return image;
  188. }
  189. return null;
  190. }
  191. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  192. {
  193. throw new NotImplementedException();
  194. }
  195. }
  196. #endregion
  197. #region ChannelSourceAddressConverter
  198. public class ChannelSourceAddressConverter : IValueConverter
  199. {
  200. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  201. {
  202. if (value == null)
  203. return String.Empty;
  204. if (value is IClientInputChannel)
  205. {
  206. IClientInputChannel channel = (IClientInputChannel)value;
  207. return channel.GetSourceAddress().Address;
  208. }
  209. if (value is long)
  210. {
  211. IClientInputChannel channel =
  212. ChannelsManager.GetChannelObject((long)value).InputChannel;
  213. return channel.GetSourceAddress().Address;
  214. }
  215. return String.Empty;
  216. }
  217. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  218. {
  219. throw new NotImplementedException();
  220. }
  221. }
  222. #endregion
  223. #region ChannelSourceDisplayNameConverter
  224. public class ChannelSourceDisplayNameConverter : IValueConverter
  225. {
  226. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  227. {
  228. if (value == null)
  229. return null;
  230. if (value != null)
  231. {
  232. var channel = ChannelsManager.GetChannelObject((long)value);
  233. return channel.Configuration.DisplayName;
  234. }
  235. return String.Empty;
  236. }
  237. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  238. {
  239. throw new NotImplementedException();
  240. }
  241. }
  242. #endregion
  243. // Filename converters
  244. #region FilenameToIconConverter
  245. public class FilenameToIconConverter : IValueConverter
  246. {
  247. private static Dictionary<string, ImageSource> _internalCache;
  248. [StructLayout(LayoutKind.Sequential)]
  249. private struct SHFILEINFO
  250. {
  251. public IntPtr hIcon;
  252. public IntPtr iIcon;
  253. public uint dwAttributes;
  254. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
  255. public string szDisplayName;
  256. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
  257. public string szTypeName;
  258. };
  259. private class Interop
  260. {
  261. public const uint SHGFI_ICON = 0x100;
  262. public const uint SHGFI_LARGEICON = 0x0; // 'Large icon
  263. public const uint SHGFI_SMALLICON = 0x1; // 'Small icon
  264. [DllImport("shell32.dll")]
  265. public static extern IntPtr SHGetFileInfo(string pszPath,
  266. uint dwFileAttributes,
  267. ref SHFILEINFO psfi,
  268. uint cbSizeFileInfo,
  269. uint uFlags);
  270. }
  271. /// <summary>
  272. /// Couldn't get it to work with the proper colour-mode. But after modifying our code to use
  273. /// the version from http://www.bendewey.name/code/FilenameIconImageConverter.html everything
  274. /// was fixed.
  275. /// </summary>
  276. /// <param name="value"></param>
  277. /// <param name="targetType"></param>
  278. /// <param name="parameter"></param>
  279. /// <param name="culture"></param>
  280. /// <returns></returns>
  281. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  282. {
  283. ImageSource source = null;
  284. lock (this)
  285. {
  286. if (_internalCache == null)
  287. _internalCache = new Dictionary<string, ImageSource>();
  288. string ext = Path.GetExtension(value == null ? "unknown.unknown" : value.ToString());
  289. int index = ext.IndexOf('?');
  290. if (index > -1)
  291. ext = ext.Substring(0, index);
  292. if (_internalCache.ContainsKey(ext))
  293. {
  294. return _internalCache[ext];
  295. }
  296. else
  297. {
  298. string resourcePath = Path.Combine(Path.GetTempPath(), "file" + ext);
  299. FileInfo resource = new FileInfo(resourcePath);
  300. try
  301. {
  302. if (!resource.Exists)
  303. {
  304. using (StreamWriter strm = resource.CreateText())
  305. strm.Close();
  306. }
  307. SHFILEINFO shinfo = new SHFILEINFO();
  308. uint size = parameter == null ? Interop.SHGFI_SMALLICON : Interop.SHGFI_LARGEICON;
  309. Interop.SHGetFileInfo(resource.FullName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Interop.SHGFI_ICON | size);
  310. Icon fileIcon = Icon.FromHandle(shinfo.hIcon);
  311. using (MemoryStream memStream = new MemoryStream())
  312. {
  313. Bitmap iconBitmap = fileIcon.ToBitmap();
  314. iconBitmap.Save(memStream, ImageFormat.Png);
  315. iconBitmap.Dispose();
  316. memStream.Seek(0, SeekOrigin.Begin);
  317. PngBitmapDecoder bitmapDecoder = new PngBitmapDecoder(memStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
  318. source = bitmapDecoder.Frames[0];
  319. source.Freeze();
  320. }
  321. }
  322. finally
  323. {
  324. resource.Delete();
  325. }
  326. if (source != null)
  327. _internalCache.Add(ext, source);
  328. }
  329. }
  330. return source;
  331. }
  332. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  333. {
  334. throw new NotImplementedException();
  335. }
  336. }
  337. #endregion
  338. #region FilenameToDescriptionConverter
  339. public class FilenameToDescriptionConverter : IValueConverter
  340. {
  341. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  342. {
  343. if (value == null)
  344. return "Unknown";
  345. string filename = value.ToString();
  346. string ext = Path.GetExtension(filename);
  347. RegistryKey key = Registry.ClassesRoot.OpenSubKey(ext);
  348. if (key == null)
  349. return "Unknown";
  350. string type = key.GetValue("") as string;
  351. if (String.IsNullOrEmpty(type))
  352. return "Unknown";
  353. key = Registry.ClassesRoot.OpenSubKey(type);
  354. if (key == null)
  355. return "Unknown";
  356. string desc = key.GetValue("") as string;
  357. return desc;
  358. }
  359. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  360. {
  361. throw new NotImplementedException();
  362. }
  363. }
  364. #endregion
  365. // Object converters
  366. #region ObjectToObjectHolderConverter
  367. public class ObjectToObjectHolderConverter : IValueConverter
  368. {
  369. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  370. {
  371. if (value == null)
  372. return null;
  373. Type genericType = typeof(ObjectHolder<>).MakeGenericType(value.GetType());
  374. return Activator.CreateInstance(genericType, value);
  375. }
  376. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  377. {
  378. throw new NotImplementedException();
  379. }
  380. }
  381. #endregion
  382. #region ObjectToEnumerableConverter
  383. public class ObjectToEnumerableConverter : IValueConverter
  384. {
  385. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  386. {
  387. List<object> list = new List<object>();
  388. if (value == null)
  389. return list;
  390. list.Add(value);
  391. return list;
  392. }
  393. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  394. {
  395. throw new NotImplementedException();
  396. }
  397. }
  398. #endregion
  399. #region MultiObjectSelectConverter
  400. public class MultiObjectSelectConverter : IMultiValueConverter
  401. {
  402. public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
  403. {
  404. foreach (var value in values)
  405. {
  406. if (value != null)
  407. return value;
  408. }
  409. return null;
  410. }
  411. public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
  412. {
  413. throw new NotImplementedException();
  414. }
  415. }
  416. #endregion
  417. // Visibility converters
  418. #region NotBooleanToVisibilityConverter
  419. public class NotBooleanToVisibilityConverter : IValueConverter
  420. {
  421. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  422. {
  423. bool oldValue = (bool)value;
  424. return new BooleanToVisibilityConverter().Convert(!oldValue, targetType, parameter, culture);
  425. }
  426. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  427. {
  428. bool newValue = (bool)new BooleanToVisibilityConverter().ConvertBack(value, targetType, parameter, culture);
  429. return !newValue;
  430. }
  431. }
  432. #endregion
  433. #region BooleanToVisibilityCollapsedConverter
  434. public class BooleanToVisibilityCollapsedConverter : IValueConverter
  435. {
  436. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  437. {
  438. bool oldValue = (bool)value;
  439. var visib = (Visibility)new BooleanToVisibilityConverter().Convert(oldValue, targetType, parameter, culture);
  440. return visib == Visibility.Collapsed ? Visibility.Hidden : visib;
  441. }
  442. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  443. {
  444. bool newValue = (bool)new BooleanToVisibilityConverter().ConvertBack(value, targetType, parameter, culture);
  445. return !newValue;
  446. }
  447. }
  448. #endregion
  449. #region CountToVisibilityConverter
  450. public class CountToVisibilityConverter : IValueConverter
  451. {
  452. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  453. {
  454. if (value == null)
  455. return Visibility.Collapsed;
  456. long count = 0;
  457. if (value is IList)
  458. {
  459. IList list = (IList)value;
  460. count = list.Count;
  461. }
  462. else if (value is SourceAddressCollection)
  463. {
  464. count = (value as SourceAddressCollection).Count();
  465. }
  466. else if (value is IEnumerable)
  467. {
  468. IEnumerable enumerable = (IEnumerable) value;
  469. foreach (var item in enumerable)
  470. count++;
  471. }
  472. if (value is Int16)
  473. count = (Int16)value;
  474. if (value is Int32)
  475. count = (Int32)value;
  476. if (value is Int64)
  477. count = (Int64)value;
  478. long min = 0;
  479. if (parameter is string)
  480. {
  481. Int64.TryParse((string)parameter, out min);
  482. }
  483. return count > min ? Visibility.Visible : Visibility.Collapsed;
  484. }
  485. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  486. {
  487. throw new NotImplementedException();
  488. }
  489. }
  490. #endregion
  491. #region EmptyStringToVisibilityConverter
  492. public class EmptyStringToVisibilityConverter : IValueConverter
  493. {
  494. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  495. {
  496. BooleanToVisibilityConverter conv = new BooleanToVisibilityConverter();
  497. string str = (value as string);
  498. if (str == null)
  499. return Visibility.Collapsed;
  500. return String.IsNullOrEmpty(str.Trim()) ? Visibility.Collapsed : Visibility.Visible;
  501. }
  502. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  503. {
  504. throw new NotImplementedException();
  505. }
  506. }
  507. #endregion
  508. #region NullToVisibilityConverter
  509. public class NullToVisibilityConverter : IValueConverter
  510. {
  511. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  512. {
  513. if (value == null)
  514. return Visibility.Collapsed;
  515. return Visibility.Visible;
  516. }
  517. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  518. {
  519. throw new NotImplementedException();
  520. }
  521. }
  522. #endregion
  523. // String converters
  524. #region SnipStringConverter
  525. public class SnipStringConverter : IValueConverter
  526. {
  527. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  528. {
  529. if (parameter == null)
  530. throw new ArgumentNullException("parameter");
  531. if (value is string)
  532. {
  533. string str = (string)value;
  534. int chars = Int32.Parse(parameter.ToString());
  535. // Remove redundant spaces
  536. str = Regex.Replace(str, @"[\s]+", " ", RegexOptions.Singleline | RegexOptions.IgnoreCase);
  537. if (str.Length <= chars)
  538. return str.Replace(" ", "") + "...";
  539. return str.Substring(0, chars).Replace(" ", "") + "...";
  540. }
  541. else if (value is Stream)
  542. {
  543. SnipStringConverter converter = new SnipStringConverter();
  544. return converter.Convert(
  545. (value as Stream).ReadString(),
  546. targetType,
  547. parameter,
  548. culture);
  549. }
  550. else
  551. {
  552. throw new ApplicationException("Unsupported parameter type");
  553. }
  554. }
  555. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  556. {
  557. throw new NotImplementedException();
  558. }
  559. }
  560. #endregion
  561. #region BytesDisplayConverter
  562. public class BytesDisplayConverter : IValueConverter
  563. {
  564. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  565. {
  566. Int64 bytes = Int64.Parse(value.ToString());
  567. Int64 kiloBytes = bytes / 1024;
  568. Int64 megaBytes = kiloBytes / 1024;
  569. if (kiloBytes > 1024)
  570. return String.Format("{0} MB", megaBytes);
  571. return String.Format("{0} KB", kiloBytes);
  572. }
  573. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  574. {
  575. throw new NotImplementedException();
  576. }
  577. }
  578. #endregion
  579. #region StreamToStringConverter
  580. public class StreamToStringConverter : IValueConverter
  581. {
  582. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  583. {
  584. Stream s = (Stream)value;
  585. return s.ReadString();
  586. }
  587. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  588. {
  589. throw new NotImplementedException();
  590. }
  591. }
  592. #endregion
  593. #region HtmlStringToTextElementConverter
  594. public class HtmlStringToTextElementConverter : IValueConverter
  595. {
  596. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  597. {
  598. var str = value as string;
  599. if (String.IsNullOrEmpty(str))
  600. return new TextBlock();
  601. var text = new TextBlock { TextWrapping = TextWrapping.Wrap };
  602. HtmlParser.AppendTo(text, str.MakeLinksClickableIncludingMailto());
  603. return text;
  604. }
  605. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  606. {
  607. throw new NotImplementedException();
  608. }
  609. }
  610. #endregion
  611. #region Messages
  612. public class MessageBodyConverter : IValueConverter
  613. {
  614. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  615. {
  616. var message = (Message) value;
  617. var text = new TextBlock { TextWrapping = TextWrapping.Wrap, Style = (Style)Application.Current.FindResource("TextBlockContentForegroundStyle") };
  618. if (String.IsNullOrEmpty(message.BodyPreview))
  619. {
  620. text.Inlines.Add(new TextBlock { Text = Strings.MessageHasNoBody, FontStyle = FontStyles.Italic });
  621. }
  622. else
  623. {
  624. HtmlParser.AppendTo(text, message.BodyPreview.MakeLinksClickableIncludingMailto());
  625. }
  626. return text;
  627. }
  628. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  629. {
  630. throw new NotImplementedException();
  631. }
  632. }
  633. #endregion
  634. #region UserStatusBodyConverter
  635. public class UserStatusBodyConverter : IValueConverter
  636. {
  637. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  638. {
  639. var status = (UserStatus)value;
  640. var channel = status.SourceChannel ?? ChannelsManager.Channels.First(c => c.Configuration.DisplayName == "Twitter").Configuration;
  641. var profileuri = channel.ProfileInfoBuilder.BuildServiceProfileUrl(status.From);
  642. Uri uri = Uri.IsWellFormedUriString(profileuri, UriKind.Absolute) ? new Uri(profileuri) : new Uri("http://www.google.com");
  643. var sender = new WebHyperlink { NavigateUri = uri, FontWeight = FontWeights.Bold, Style = (Style)Application.Current.FindResource("TitleNameHyperlink") };
  644. sender.Inlines.Add(new Run(status.From.DisplayName));
  645. var text = new TextBlock { TextWrapping = TextWrapping.Wrap, Foreground = (Brush)Application.Current.FindResource("SlightlyDimmedForegroundColor") };
  646. text.Inlines.Add(sender);
  647. text.Inlines.Add(" ");
  648. if (status.To != null)
  649. {
  650. var toProfileuri = channel.ProfileInfoBuilder.BuildServiceProfileUrl(status.To);
  651. Uri toUri = Uri.IsWellFormedUriString(toProfileuri, UriKind.Absolute) ? new Uri(toProfileuri) : new Uri("http://www.google.com");
  652. var recipient = new WebHyperlink { NavigateUri = toUri, FontWeight = FontWeights.Bold, Style = (Style)Application.Current.FindResource("TitleNameHyperlink") };
  653. recipient.Inlines.Add(new Run(status.To.DisplayName));
  654. text.Inlines.Add(" » ");
  655. text.Inlines.Add(recipient);
  656. text.Inlines.Add(" ");
  657. }
  658. var source = status.Status.MakeLinksClickableIncludingMailto();
  659. if (channel.DisplayName == "Twitter")
  660. source = source.MakeTwitterLinksClickable();
  661. HtmlParser.AppendTo(text, source);
  662. foreach (var inline in text.Inlines)
  663. {
  664. // Attach markread handler to status updates
  665. if (inline is Hyperlink)
  666. (inline as Hyperlink).Click += delegate { status.TrackAction(ActionType.Read); };
  667. }
  668. text.Inlines.Add("\n");
  669. text.Inlines.Add(new TextBlock { Text = status.SortDate.ToRelativeTime(), Opacity = 0.35, Style = (Style)Application.Current.FindResource("NormalTextBlock") });
  670. return text;
  671. }
  672. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  673. {
  674. throw new NotImplementedException();
  675. }
  676. }
  677. #endregion
  678. #region UserStatusReplyConverter
  679. public class UserStatusReplyConverter : IValueConverter
  680. {
  681. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  682. {
  683. if (value == null)
  684. return null;
  685. var status = (UserStatus)value;
  686. var channel = status.SourceChannel ?? ChannelsManager.Channels.First(c => c.Configuration.DisplayName == "Twitter").Configuration;
  687. var profileuri = channel.ProfileInfoBuilder.BuildServiceProfileUrl(status.From);
  688. Uri uri = Uri.IsWellFormedUriString(profileuri, UriKind.Absolute) ? new Uri(profileuri) : new Uri("http://www.google.com");
  689. var sender = new WebHyperlink { NavigateUri = uri, FontWeight = FontWeights.Bold, Style = (Style)Application.Current.FindResource("TitleNameHyperlink") };
  690. sender.Inlines.Add(new Run(status.From.DisplayName));
  691. var intro = new TextBlock { Text = "Reply to ", Style = (Style)Application.Current.FindResource("NormalTextBlock") };
  692. var text = new TextBlock { TextTrimming = TextTrimming.CharacterEllipsis, Foreground = (Brush)Application.Current.FindResource("SlightlyDimmedForegroundColor") };
  693. text.Inlines.Add(intro);
  694. text.Inlines.Add(" ");
  695. text.Inlines.Add(sender);
  696. text.Inlines.Add(" ");
  697. text.Inlines.Add(status.Status);
  698. return text;
  699. }
  700. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  701. {
  702. throw new NotImplementedException();
  703. }
  704. }
  705. #endregion
  706. #region FromSummaryConverter
  707. public class FromSummaryConverter : IValueConverter, IEqualityComparer<string>
  708. {
  709. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  710. {
  711. var conv = (Conversation) value;
  712. var sb = new StringBuilder();
  713. var uniques = conv.Messages
  714. .Where(m => m.MessageFolder != Folders.SentItems)
  715. .Select(c => c.From)
  716. .Distinct(new SourceAddressComparer())
  717. .Select(GetAppendAddress)
  718. .Distinct(this)
  719. .ToList();
  720. if (conv.Messages.Any(m => m.MessageFolder == Folders.SentItems))
  721. uniques.Add(Strings.Me);
  722. for (int i = 0; i < uniques.Count; i++)
  723. {
  724. sb.Append(uniques[i]);
  725. if (i == 0 && uniques.Count > 3)
  726. sb.Append(" ... ");
  727. else if (i < uniques.Count - 1)
  728. sb.Append(", ");
  729. }
  730. return sb.ToString();
  731. }
  732. string GetAppendAddress(SourceAddress address)
  733. {
  734. if (String.IsNullOrEmpty(address.DisplayName))
  735. {
  736. return SourceAddress.IsValidEmail(address.Address) ?
  737. address.Address.Split('@')[0] :
  738. address.ToString();
  739. }
  740. else
  741. {
  742. return SourceAddress.IsValidEmail(address.DisplayName) ?
  743. address.DisplayName.Split('@')[0] :
  744. PersonName.Parse(address.DisplayName).Firstname;
  745. }
  746. }
  747. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  748. {
  749. throw new NotImplementedException();
  750. }
  751. public bool Equals(string x, string y)
  752. {
  753. return x.Equals(y, StringComparison.InvariantCultureIgnoreCase);
  754. }
  755. public int GetHashCode(string obj)
  756. {
  757. return obj.GetHashCode();
  758. }
  759. }
  760. #endregion
  761. // General converters
  762. #region ExecutionStatusToBrushConverter
  763. public class ExecutionStatusToBrushConverter : IValueConverter
  764. {
  765. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  766. {
  767. if (value == null)
  768. return null;
  769. BackgroundTask task = (BackgroundTask)value;
  770. switch (task.ExecutionStatus)
  771. {
  772. case ExecutionStatus.Pending:
  773. {
  774. if (task.ExecuteAfter > DateTime.MinValue)
  775. {
  776. return Application.Current.FindResource("DelayedBrush");
  777. }
  778. return Application.Current.FindResource("PendingBrush");
  779. }
  780. case ExecutionStatus.Running:
  781. return Application.Current.FindResource("RunningBrush");
  782. case ExecutionStatus.Error:
  783. return Application.Current.FindResource("ErrorBrush");
  784. case ExecutionStatus.Submitted:
  785. return Application.Current.FindResource("PendingBrush");
  786. case ExecutionStatus.Success:
  787. return Application.Current.FindResource("SuccessBrush");
  788. }
  789. return null;
  790. }
  791. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  792. {
  793. throw new NotImplementedException();
  794. }
  795. }
  796. #endregion
  797. // Bitmap converters
  798. #region BitmapFormatConverter
  799. public class BitmapFormatConverter : IValueConverter
  800. {
  801. #region IValueConverter Members
  802. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  803. {
  804. if (value == null)
  805. return null;
  806. BitmapSource source = (BitmapSource) value;
  807. return new FormatConvertedBitmap(source,
  808. (System.Windows.Media.PixelFormat)new PixelFormatConverter().ConvertFrom(parameter), null, 0);
  809. }
  810. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  811. {
  812. throw new NotImplementedException();
  813. }
  814. #endregion
  815. }
  816. #endregion
  817. // Document converters
  818. #region DocumentDescriptionConverter
  819. public class DocumentDescriptionConverter : IValueConverter
  820. {
  821. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  822. {
  823. if (value == null)
  824. return String.Empty;
  825. Document document = (Document)value;
  826. string description = (string)new FilenameToDescriptionConverter().Convert(document.Filename, targetType, parameter, culture);
  827. string size = (string)new BytesDisplayConverter().Convert(document.Size, targetType, parameter, culture);
  828. return String.Format("{0} {1}", description, size);
  829. }
  830. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  831. {
  832. throw new NotImplementedException();
  833. }
  834. }
  835. #endregion
  836. // Label converters
  837. #region LabelBrushConverter
  838. public class LabelBrushConverter : IValueConverter
  839. {
  840. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  841. {
  842. if (value == null)
  843. return null;
  844. var label = (Label) value;
  845. int index = label.Labelname.Length == 0 ? 5 : ((label.Labelname[0] % 7) + 4);
  846. switch (label.LabelType)
  847. {
  848. case LabelType.Todo:
  849. return Application.Current.FindResource("LabelBackgroundBrush1");
  850. case LabelType.WaitingFor:
  851. return Application.Current.FindResource("LabelBackgroundBrush2");
  852. case LabelType.Someday:
  853. return Application.Current.FindResource("LabelBackgroundBrush3");
  854. default:
  855. return Application.Current.FindResource("LabelBackgroundBrush" + index);
  856. }
  857. }
  858. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  859. {
  860. throw new NotImplementedException();
  861. }
  862. }
  863. #endregion
  864. #region LabelsContainerBrushConverter
  865. public class LabelsContainerBrushConverter : IValueConverter
  866. {
  867. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  868. {
  869. if (value == null)
  870. return null;
  871. var label = (LabelsContainer)value;
  872. if (label.Labelname == Strings.Todo)
  873. return Application.Current.FindResource("LabelBackgroundBrush1");
  874. else if (label.Labelname == Strings.WaitingFor)
  875. return Application.Current.FindResource("LabelBackgroundBrush2");
  876. else if (label.Labelname == Strings.Someday)
  877. return Application.Current.FindResource("LabelBackgroundBrush3");
  878. else
  879. {
  880. int index = label.Labelname.Length == 0 ? 5 : ((label.Labelname[0] % 7) + 4);
  881. return Application.Current.FindResource("LabelBackgroundBrush" + index);
  882. }
  883. }
  884. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  885. {
  886. throw new NotImplementedException();
  887. }
  888. }
  889. #endregion
  890. // Color converters
  891. #region BrushToGradientBrushConverter
  892. public class BrushToGradientBrushConverter : IValueConverter
  893. {
  894. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  895. {
  896. var color = (Color) value;
  897. var gradient = new LinearGradientBrush { StartPoint = new Point(0.5, 0), EndPoint = new Point(0.5, 1) };
  898. gradient.GradientStops.Add(new GradientStop(color, 0.2));
  899. gradient.GradientStops.Add(new GradientStop { Offset = 1 });
  900. return gradient;
  901. }
  902. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  903. {
  904. throw new NotImplementedException();
  905. }
  906. }
  907. #endregion
  908. #region ColorToBrushConverter
  909. public class ColorToBrushConverter : IValueConverter
  910. {
  911. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  912. {
  913. var color = (Color)value;
  914. return new SolidColorBrush(color);
  915. }
  916. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  917. {
  918. throw new NotImplementedException();
  919. }
  920. }
  921. #endregion
  922. #region WindowStateToMarginConverter
  923. public class WindowStateToMarginConverter : IValueConverter
  924. {
  925. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  926. {
  927. WindowState state = (WindowState) value;
  928. return state == WindowState.Maximized && GlassHelper.IsGlassEnabled() ? new Thickness(5) : new Thickness(0);
  929. }
  930. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  931. {
  932. throw new NotImplementedException();
  933. }
  934. }
  935. #endregion
  936. #region GlassMarginConverter
  937. public class GlassMarginConverter : IValueConverter
  938. {
  939. public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  940. {
  941. return GlassHelper.IsGlassEnabled() ? new Thickness(0, 32, 0, 0) : new Thickness(0);
  942. }
  943. public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  944. {
  945. throw new NotImplementedException();
  946. }
  947. }
  948. #endregion
  949. internal static class GlassHelper
  950. {
  951. [DllImport("dwmapi.dll", EntryPoint = "DwmIsCompositionEnabled", PreserveSig = false)]
  952. private static extern void _DwmIsCompositionEnabled([Out, MarshalAs(UnmanagedType.Bool)] out bool pfEnabled);
  953. public static bool IsGlassEnabled()
  954. {
  955. if (Environment.OSVersion.Version.Major < 6)
  956. return false;
  957. bool glassEnabled;
  958. _DwmIsCompositionEnabled(out glassEnabled);
  959. return glassEnabled;
  960. }
  961. }
  962. }