MainWindow.xaml.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. using MediaBrowser.Model.DTO;
  2. using MediaBrowser.UI.Controller;
  3. using MediaBrowser.UI.Controls;
  4. using System;
  5. using System.ComponentModel;
  6. using System.Linq;
  7. using System.Threading;
  8. using System.Windows;
  9. using System.Windows.Controls;
  10. using System.Windows.Input;
  11. using System.Windows.Media.Animation;
  12. using System.Windows.Media.Imaging;
  13. namespace MediaBrowser.UI
  14. {
  15. /// <summary>
  16. /// Interaction logic for MainWindow.xaml
  17. /// </summary>
  18. public partial class MainWindow : Window, INotifyPropertyChanged
  19. {
  20. private Timer MouseIdleTimer { get; set; }
  21. private Timer BackdropTimer { get; set; }
  22. private Image BackdropImage { get; set; }
  23. private string[] CurrentBackdrops { get; set; }
  24. private int CurrentBackdropIndex { get; set; }
  25. public MainWindow()
  26. {
  27. InitializeComponent();
  28. BackButton.Click += BtnApplicationBackClick;
  29. ExitButton.Click += ExitButtonClick;
  30. ForwardButton.Click += ForwardButtonClick;
  31. DragBar.MouseDown += DragableGridMouseDown;
  32. Loaded += MainWindowLoaded;
  33. }
  34. public event PropertyChangedEventHandler PropertyChanged;
  35. public void OnPropertyChanged(String info)
  36. {
  37. if (PropertyChanged != null)
  38. {
  39. PropertyChanged(this, new PropertyChangedEventArgs(info));
  40. }
  41. }
  42. private bool _isMouseIdle = true;
  43. public bool IsMouseIdle
  44. {
  45. get { return _isMouseIdle; }
  46. set
  47. {
  48. _isMouseIdle = value;
  49. OnPropertyChanged("IsMouseIdle");
  50. }
  51. }
  52. void MainWindowLoaded(object sender, RoutedEventArgs e)
  53. {
  54. DataContext = App.Instance;
  55. if (App.Instance.ServerConfiguration == null)
  56. {
  57. App.Instance.PropertyChanged += ApplicationPropertyChanged;
  58. }
  59. else
  60. {
  61. LoadInitialPage();
  62. }
  63. }
  64. void ForwardButtonClick(object sender, RoutedEventArgs e)
  65. {
  66. NavigateForward();
  67. }
  68. void ExitButtonClick(object sender, RoutedEventArgs e)
  69. {
  70. Close();
  71. }
  72. void ApplicationPropertyChanged(object sender, PropertyChangedEventArgs e)
  73. {
  74. if (e.PropertyName.Equals("ServerConfiguration"))
  75. {
  76. App.Instance.PropertyChanged -= ApplicationPropertyChanged;
  77. LoadInitialPage();
  78. }
  79. }
  80. private async void LoadInitialPage()
  81. {
  82. await App.Instance.LogoutUser().ConfigureAwait(false);
  83. }
  84. private void DragableGridMouseDown(object sender, MouseButtonEventArgs e)
  85. {
  86. if (e.ClickCount == 2)
  87. {
  88. WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
  89. }
  90. else if (e.LeftButton == MouseButtonState.Pressed)
  91. {
  92. DragMove();
  93. }
  94. }
  95. void BtnApplicationBackClick(object sender, RoutedEventArgs e)
  96. {
  97. NavigateBack();
  98. }
  99. private Frame PageFrame
  100. {
  101. get
  102. {
  103. // Finding the grid that is generated by the ControlTemplate of the Button
  104. return TreeHelper.FindChild<Frame>(PageContent, "PageFrame");
  105. }
  106. }
  107. public void Navigate(Uri uri)
  108. {
  109. PageFrame.Navigate(uri);
  110. }
  111. /// <summary>
  112. /// Sets the backdrop based on an ApiBaseItemWrapper
  113. /// </summary>
  114. public void SetBackdrops(DtoBaseItem item)
  115. {
  116. SetBackdrops(UIKernel.Instance.ApiClient.GetBackdropImageUrls(item, null, null, 1920, 1080));
  117. }
  118. /// <summary>
  119. /// Sets the backdrop based on a list of image files
  120. /// </summary>
  121. public async void SetBackdrops(string[] backdrops)
  122. {
  123. // Don't reload the same backdrops
  124. if (CurrentBackdrops != null && backdrops.SequenceEqual(CurrentBackdrops))
  125. {
  126. return;
  127. }
  128. if (BackdropTimer != null)
  129. {
  130. BackdropTimer.Dispose();
  131. }
  132. BackdropGrid.Children.Clear();
  133. if (backdrops.Length == 0)
  134. {
  135. CurrentBackdrops = null;
  136. return;
  137. }
  138. CurrentBackdropIndex = GetFirstBackdropIndex();
  139. Image image = await App.Instance.GetImage(backdrops.ElementAt(CurrentBackdropIndex));
  140. image.SetResourceReference(Image.StyleProperty, "BackdropImage");
  141. BackdropGrid.Children.Add(image);
  142. CurrentBackdrops = backdrops;
  143. BackdropImage = image;
  144. const int backdropRotationTime = 7000;
  145. if (backdrops.Count() > 1)
  146. {
  147. BackdropTimer = new Timer(BackdropTimerCallback, null, backdropRotationTime, backdropRotationTime);
  148. }
  149. }
  150. public void ClearBackdrops()
  151. {
  152. if (BackdropTimer != null)
  153. {
  154. BackdropTimer.Dispose();
  155. }
  156. BackdropGrid.Children.Clear();
  157. CurrentBackdrops = null;
  158. }
  159. private void BackdropTimerCallback(object stateInfo)
  160. {
  161. // Need to do this on the UI thread
  162. Application.Current.Dispatcher.InvokeAsync(() =>
  163. {
  164. var animFadeOut = new Storyboard();
  165. animFadeOut.Completed += AnimFadeOutCompleted;
  166. var fadeOut = new DoubleAnimation();
  167. fadeOut.From = 1.0;
  168. fadeOut.To = 0.5;
  169. fadeOut.Duration = new Duration(TimeSpan.FromSeconds(1));
  170. animFadeOut.Children.Add(fadeOut);
  171. Storyboard.SetTarget(fadeOut, BackdropImage);
  172. Storyboard.SetTargetProperty(fadeOut, new PropertyPath(Image.OpacityProperty));
  173. animFadeOut.Begin(this);
  174. });
  175. }
  176. async void AnimFadeOutCompleted(object sender, System.EventArgs e)
  177. {
  178. if (CurrentBackdrops == null)
  179. {
  180. return;
  181. }
  182. int backdropIndex = GetNextBackdropIndex();
  183. BitmapImage image = await App.Instance.GetBitmapImage(CurrentBackdrops[backdropIndex]);
  184. CurrentBackdropIndex = backdropIndex;
  185. // Need to do this on the UI thread
  186. BackdropImage.Source = image;
  187. Storyboard imageFadeIn = new Storyboard();
  188. DoubleAnimation fadeIn = new DoubleAnimation();
  189. fadeIn.From = 0.25;
  190. fadeIn.To = 1.0;
  191. fadeIn.Duration = new Duration(TimeSpan.FromSeconds(1));
  192. imageFadeIn.Children.Add(fadeIn);
  193. Storyboard.SetTarget(fadeIn, BackdropImage);
  194. Storyboard.SetTargetProperty(fadeIn, new PropertyPath(Image.OpacityProperty));
  195. imageFadeIn.Begin(this);
  196. }
  197. private int GetFirstBackdropIndex()
  198. {
  199. return 0;
  200. }
  201. private int GetNextBackdropIndex()
  202. {
  203. if (CurrentBackdropIndex < CurrentBackdrops.Length - 1)
  204. {
  205. return CurrentBackdropIndex + 1;
  206. }
  207. return 0;
  208. }
  209. public void NavigateBack()
  210. {
  211. if (PageFrame.NavigationService.CanGoBack)
  212. {
  213. PageFrame.NavigationService.GoBack();
  214. }
  215. }
  216. public void NavigateForward()
  217. {
  218. if (PageFrame.NavigationService.CanGoForward)
  219. {
  220. PageFrame.NavigationService.GoForward();
  221. }
  222. }
  223. /// <summary>
  224. /// Shows the control bar then starts a timer to hide it
  225. /// </summary>
  226. private void StartMouseIdleTimer()
  227. {
  228. IsMouseIdle = false;
  229. const int duration = 10000;
  230. // Start the timer if it's null, otherwise reset it
  231. if (MouseIdleTimer == null)
  232. {
  233. MouseIdleTimer = new Timer(MouseIdleTimerCallback, null, duration, Timeout.Infinite);
  234. }
  235. else
  236. {
  237. MouseIdleTimer.Change(duration, Timeout.Infinite);
  238. }
  239. }
  240. /// <summary>
  241. /// This is the Timer callback method to hide the control bar
  242. /// </summary>
  243. private void MouseIdleTimerCallback(object stateInfo)
  244. {
  245. IsMouseIdle = true;
  246. if (MouseIdleTimer != null)
  247. {
  248. MouseIdleTimer.Dispose();
  249. MouseIdleTimer = null;
  250. }
  251. }
  252. /// <summary>
  253. /// Handles OnMouseMove to show the control box
  254. /// </summary>
  255. protected override void OnMouseMove(MouseEventArgs e)
  256. {
  257. base.OnMouseMove(e);
  258. StartMouseIdleTimer();
  259. }
  260. /// <summary>
  261. /// Handles OnKeyUp to provide keyboard based navigation
  262. /// </summary>
  263. protected override void OnKeyUp(KeyEventArgs e)
  264. {
  265. base.OnKeyUp(e);
  266. if (IsBackPress(e))
  267. {
  268. NavigateBack();
  269. }
  270. else if (IsForwardPress(e))
  271. {
  272. NavigateForward();
  273. }
  274. }
  275. /// <summary>
  276. /// Determines if a keypress should be treated as a backward press
  277. /// </summary>
  278. private bool IsBackPress(KeyEventArgs e)
  279. {
  280. if (e.Key == Key.BrowserBack || e.Key == Key.Back)
  281. {
  282. return true;
  283. }
  284. if (e.SystemKey == Key.Left && e.KeyboardDevice.Modifiers.HasFlag(ModifierKeys.Alt))
  285. {
  286. return true;
  287. }
  288. return false;
  289. }
  290. /// <summary>
  291. /// Determines if a keypress should be treated as a forward press
  292. /// </summary>
  293. private bool IsForwardPress(KeyEventArgs e)
  294. {
  295. if (e.Key == Key.BrowserForward)
  296. {
  297. return true;
  298. }
  299. if (e.SystemKey == Key.RightAlt && e.KeyboardDevice.Modifiers.HasFlag(ModifierKeys.Alt))
  300. {
  301. return true;
  302. }
  303. return false;
  304. }
  305. }
  306. }