CustomTileImagePushPatternViewModel.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.ComponentModel.Composition;
  6. using System.Windows.Input;
  7. using System.Windows.Controls;
  8. using System.Windows.Media.Imaging;
  9. using System.Windows;
  10. using System.Windows.Controls.Primitives;
  11. using System.Windows.Media;
  12. using System.IO;
  13. using System.Reflection;
  14. using Microsoft.Win32;
  15. using WindowsPhone.Recipes.Push.Server.Behaviors;
  16. using WindowsPhone.Recipes.Push.Messasges;
  17. using WindowsPhone.Recipes.Push.Server.Models;
  18. using WindowsPhone.Recipes.Push.Server.Services;
  19. namespace WindowsPhone.Recipes.Push.Server.ViewModels
  20. {
  21. /// <summary>
  22. /// Represents the Custom Tile Image push notification pattern.
  23. /// </summary>
  24. /// <remarks>
  25. /// Send a tile update with a dynamically created image located in the remote server (in our case localhost).
  26. /// The image will be dynamically generated upon each request. The tile Count and Title in the
  27. /// payload are optional.
  28. /// </remarks>
  29. [Export(typeof(PushPatternViewModel)), PartCreationPolicy(CreationPolicy.Shared)]
  30. internal sealed class CustomTileImagePushPatternViewModel : PushPatternViewModel, IVisualHost
  31. {
  32. #region Constants
  33. /// <value>Tile image maximum width.</value>
  34. public const int TileImageWidth = 173;
  35. /// <value>Tile image maximum height.</value>
  36. public const int TileImageHeight = 173;
  37. /// <value>Tile image dpi.</value>
  38. public const int TileImageDpi = 96;
  39. #endregion
  40. #region Fields
  41. /// <value>Collection of brushes for choosing text message color.</value>
  42. private Brush[] _textColors;
  43. /// <value>Selected tile image background.</value>
  44. private ImageSource _tileBackground;
  45. /// <value>Text for diplaying on the tile custom image.</value>
  46. private string _freeText;
  47. /// <value>Tile custom image text size.</value>
  48. private double _textSize;
  49. #endregion
  50. #region Properties
  51. [Import]
  52. private ImageService ImageService { get; set; }
  53. /// <summary>
  54. /// Gets a list of brushes for choosing text message color.
  55. /// </summary>
  56. public Brush[] TextColors
  57. {
  58. get
  59. {
  60. if (_textColors == null)
  61. {
  62. _textColors = (from property in typeof(Brushes).GetProperties(BindingFlags.Static | BindingFlags.Public)
  63. select (Brush)property.GetValue(null, null)).ToArray();
  64. }
  65. return _textColors;
  66. }
  67. }
  68. /// <summary>
  69. /// Gets or sets the visual element used for generating a custom image from.
  70. /// </summary>
  71. public Visual Visual
  72. {
  73. get;
  74. set;
  75. }
  76. /// <summary>
  77. /// Get or sets the prefered tile background image source.
  78. /// </summary>
  79. public ImageSource TileBackground
  80. {
  81. get { return _tileBackground; }
  82. set
  83. {
  84. if (_tileBackground != value)
  85. {
  86. _tileBackground = value;
  87. NotifyPropertyChanged("TileBackground");
  88. }
  89. }
  90. }
  91. /// <summary>
  92. /// Gets or sets a text to be displayed on the tile generated image.
  93. /// </summary>
  94. public string FreeText
  95. {
  96. get { return _freeText; }
  97. set
  98. {
  99. if (_freeText != value)
  100. {
  101. _freeText = value;
  102. NotifyPropertyChanged("FreeText");
  103. }
  104. }
  105. }
  106. /// <summary>
  107. /// Gets or sets the text size of the tile generated image.
  108. /// </summary>
  109. public double TextSize
  110. {
  111. get { return _textSize; }
  112. set
  113. {
  114. if (_textSize != value)
  115. {
  116. _textSize = value;
  117. NotifyPropertyChanged("TextSize");
  118. }
  119. }
  120. }
  121. #endregion
  122. #region Commands
  123. /// <summary>
  124. /// Gets the command for picking a tile background image.
  125. /// </summary>
  126. public ICommand PickImageCommand { get; private set; }
  127. #endregion
  128. #region Ctor
  129. /// <summary>
  130. /// Initialize new instance of this type with defaults.
  131. /// </summary>
  132. public CustomTileImagePushPatternViewModel()
  133. {
  134. InitializeDefaults();
  135. PickImageCommand = new RelayCommand(
  136. p =>
  137. {
  138. // On execution, open file dialog for picking tile background image.
  139. var openDialog = new OpenFileDialog
  140. {
  141. Title = "Tile Background",
  142. Filter = "Jpeg|*.jpg|Bmp|*.bmp",
  143. InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures),
  144. Multiselect = false
  145. };
  146. if (openDialog.ShowDialog() == true)
  147. {
  148. TileBackground = new BitmapImage(new Uri(openDialog.FileName));
  149. }
  150. });
  151. }
  152. #endregion
  153. #region Protected
  154. protected override void OnActivated()
  155. {
  156. base.OnActivated();
  157. // Register to the ImageService.ImageRequest event. This event is raised
  158. // whenever ImageService.GetTileImage is called.
  159. ImageService.ImageRequest += Service_ImageRequest;
  160. }
  161. protected override void OnDeactivated()
  162. {
  163. base.OnDeactivated();
  164. ImageService.ImageRequest -= Service_ImageRequest;
  165. }
  166. protected override void OnSend()
  167. {
  168. // Starts by sending a tile notification to all relvant subscribers.
  169. // This tile notification updates the tile with custom image.
  170. var tileMsg = new TilePushNotificationMessage(MessageSendPriority.High)
  171. {
  172. Count = Count,
  173. Title = Title
  174. };
  175. foreach (var subscriber in PushService.Subscribers)
  176. {
  177. // Set the tile background image uri with the address of the ImageService.GetTileImage,
  178. // REST service, using current subscriber channel uri as a parameter to bo sent to the service.
  179. tileMsg.BackgroundImageUri = new Uri(string.Format(ImageService.GetTileImageService, string.Empty));
  180. tileMsg.SendAsync(subscriber.ChannelUri, Log, Log);
  181. }
  182. }
  183. #endregion
  184. #region Privates
  185. private void Service_ImageRequest(object sender, Services.ImageRequestEventArgs e)
  186. {
  187. // This event is raised by our local push-service as result of
  188. // the tile msg we've sent to each subscriber. This is the time
  189. // to pick the right tile image for the subscriber.
  190. if (Visual != null)
  191. {
  192. RenderImage(Visual, e.ImageStream);
  193. }
  194. }
  195. private static void RenderImage(Visual visual, Stream stream)
  196. {
  197. // The next lines of code uses WPF to dynamically create an image.
  198. // In a real server we shouldn't use WPF, hence a 3rd party image generator library is required.
  199. var renderer = new RenderTargetBitmap(TileImageWidth, TileImageHeight, TileImageDpi, TileImageDpi, PixelFormats.Pbgra32);
  200. renderer.Render(visual);
  201. var pngEncoder = new PngBitmapEncoder();
  202. pngEncoder.Frames.Add(BitmapFrame.Create(renderer));
  203. pngEncoder.Save(stream);
  204. }
  205. private void InitializeDefaults()
  206. {
  207. DisplayName = "Custom Tile";
  208. Description = "Send a tile update with a dynamically created image located in the remote server (in our case localhost). The image will be dynamically generated upon each request. The tile Count and Title in the payload are optional.";
  209. TextSize = 20;
  210. }
  211. #endregion
  212. }
  213. }