using MediaBrowser.Common.Extensions; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; using MediaBrowser.UI.Controller; using MediaBrowser.UI.Controls; using System; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using MediaBrowser.UI.Extensions; namespace MediaBrowser.UI { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : BaseWindow, IDisposable { /// /// Gets or sets the mouse idle timer. /// /// The mouse idle timer. private Timer MouseIdleTimer { get; set; } /// /// Gets or sets the backdrop timer. /// /// The backdrop timer. private Timer BackdropTimer { get; set; } /// /// Gets or sets the current backdrops. /// /// The current backdrops. private string[] CurrentBackdrops { get; set; } /// /// The _current backdrop index /// private int _currentBackdropIndex; /// /// Gets or sets the index of the current backdrop. /// /// The index of the current backdrop. public int CurrentBackdropIndex { get { return _currentBackdropIndex; } set { _currentBackdropIndex = value; OnPropertyChanged("CurrentBackdropIndex"); Dispatcher.InvokeAsync(OnBackdropIndexChanged); } } /// /// The _is mouse idle /// private bool _isMouseIdle = true; /// /// Gets or sets a value indicating whether this instance is mouse idle. /// /// true if this instance is mouse idle; otherwise, false. public bool IsMouseIdle { get { return _isMouseIdle; } set { _isMouseIdle = value; Dispatcher.InvokeAsync(() => Cursor = value ? Cursors.None : Cursors.Arrow); OnPropertyChanged("IsMouseIdle"); } } private readonly ILogger _logger; /// /// Initializes a new instance of the class. /// public MainWindow(ILogger logger) : base() { _logger = logger; InitializeComponent(); } /// /// Called when [loaded]. /// protected override void OnLoaded() { base.OnLoaded(); DragBar.MouseDown += DragableGridMouseDown; DataContext = App.Instance; } /// /// Loads the initial UI. /// /// Task. internal Task LoadInitialUI() { return LoadInitialPage(); } /// /// Called when [backdrop index changed]. /// private async void OnBackdropIndexChanged() { var currentBackdropIndex = CurrentBackdropIndex; if (currentBackdropIndex == -1 ) { // Setting this to null doesn't seem to clear out the content // Have to check it for null or get startup errors if (BackdropContainer.Content != null) { BackdropContainer.Content = new FrameworkElement(); } return; } try { var bitmap = await App.Instance.GetRemoteBitmapAsync(CurrentBackdrops[currentBackdropIndex]); var img = new Image { Source = bitmap }; img.SetResourceReference(StyleProperty, "BackdropImage"); BackdropContainer.Content = img; } catch (HttpException) { if (currentBackdropIndex == 0) { BackdropContainer.Content = new FrameworkElement(); } } } /// /// Loads the initial page. /// /// Task. private Task LoadInitialPage() { return App.Instance.LogoutUser(); } /// /// Dragables the grid mouse down. /// /// The sender. /// The instance containing the event data. private void DragableGridMouseDown(object sender, MouseButtonEventArgs e) { if (e.ClickCount == 2) { WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized; } else if (e.LeftButton == MouseButtonState.Pressed) { DragMove(); } } /// /// Gets the page frame. /// /// The page frame. private TransitionFrame PageFrame { get { // Finding the grid that is generated by the ControlTemplate of the Button return TreeHelper.FindChild(PageContent, "PageFrame"); } } /// /// Navigates the specified page. /// /// The page. internal void Navigate(Page page) { _logger.Info("Navigating to " + page.GetType().Name); Dispatcher.InvokeAsync(() => PageFrame.NavigateWithTransition(page)); } /// /// Sets the backdrop based on a BaseItemDto /// /// The item. public void SetBackdrops(BaseItemDto item) { var urls = App.Instance.ApiClient.GetBackdropImageUrls(item, new ImageOptions { MaxWidth = Convert.ToInt32(SystemParameters.VirtualScreenWidth), MaxHeight = Convert.ToInt32(SystemParameters.VirtualScreenHeight) }); SetBackdrops(urls); } /// /// Sets the backdrop based on a list of image files /// /// The backdrops. public void SetBackdrops(string[] backdrops) { // Don't reload the same backdrops if (CurrentBackdrops != null && backdrops.SequenceEqual(CurrentBackdrops)) { return; } DisposeBackdropTimer(); CurrentBackdrops = backdrops; if (backdrops == null || backdrops.Length == 0) { CurrentBackdropIndex = -1; // Setting this to null doesn't seem to clear out the content // Have to check it for null or get startup errors if (BackdropContainer.Content != null) { BackdropContainer.Content = new FrameworkElement(); } return; } CurrentBackdropIndex = 0; // We only need the timer if there's more than one backdrop if (backdrops != null && backdrops.Length > 1) { BackdropTimer = new Timer(state => { // Don't display backdrops during video playback if (UIKernel.Instance.PlaybackManager.ActivePlayers.Any(p => p.CurrentMedia.IsVideo)) { return; } var index = CurrentBackdropIndex + 1; if (index >= backdrops.Length) { index = 0; } CurrentBackdropIndex = index; }, null, 5000, 5000); } } /// /// Disposes the backdrop timer. /// public void DisposeBackdropTimer() { if (BackdropTimer != null) { BackdropTimer.Dispose(); } } /// /// Disposes the mouse idle timer. /// public void DisposeMouseIdleTimer() { if (MouseIdleTimer != null) { MouseIdleTimer.Dispose(); } } /// /// Clears the backdrops. /// public void ClearBackdrops() { SetBackdrops(new string[] { }); } /// /// Navigates the back. /// public void NavigateBack() { Dispatcher.InvokeAsync(() => { if (PageFrame.NavigationService.CanGoBack) { PageFrame.GoBackWithTransition(); } }); } /// /// Navigates the forward. /// public void NavigateForward() { Dispatcher.InvokeAsync(() => { if (PageFrame.NavigationService.CanGoForward) { PageFrame.GoForwardWithTransition(); } }); } /// /// Called when [browser back]. /// protected override void OnBrowserBack() { base.OnBrowserBack(); NavigateBack(); } /// /// Called when [browser forward]. /// protected override void OnBrowserForward() { base.OnBrowserForward(); NavigateForward(); } /// /// Shows the control bar then starts a timer to hide it /// private void StartMouseIdleTimer() { IsMouseIdle = false; const int duration = 4000; // Start the timer if it's null, otherwise reset it if (MouseIdleTimer == null) { MouseIdleTimer = new Timer(MouseIdleTimerCallback, null, duration, Timeout.Infinite); } else { MouseIdleTimer.Change(duration, Timeout.Infinite); } } /// /// This is the Timer callback method to hide the control bar /// /// The state info. private void MouseIdleTimerCallback(object stateInfo) { IsMouseIdle = true; if (MouseIdleTimer != null) { MouseIdleTimer.Dispose(); MouseIdleTimer = null; } } /// /// The _last mouse move point /// private Point _lastMouseMovePoint; /// /// Handles OnMouseMove to show the control box /// /// The that contains the event data. protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); // Store the last position for comparison purposes // Even if the mouse is not moving this event will fire as elements are showing and hiding var pos = e.GetPosition(this); if (pos == _lastMouseMovePoint) { return; } _lastMouseMovePoint = pos; StartMouseIdleTimer(); } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { DisposeBackdropTimer(); DisposeMouseIdleTimer(); } /// /// Shows a notification message that will disappear on it's own /// /// The text. /// The caption. /// The icon. public void ShowNotificationMessage(string text, string caption = null, MessageBoxIcon icon = MessageBoxIcon.None) { var control = new NotificationMessage { Caption = caption, Text = text, MessageBoxImage = icon }; mainGrid.Children.Add(control); Dispatcher.InvokeWithDelay(() => mainGrid.Children.Remove(control), 5000); } /// /// Shows a notification message that will disappear on it's own /// /// The text. /// The caption. /// The icon. public void ShowNotificationMessage(UIElement text, string caption = null, MessageBoxIcon icon = MessageBoxIcon.None) { var control = new NotificationMessage { Caption = caption, TextContent = text, MessageBoxImage = icon }; mainGrid.Children.Add(control); Dispatcher.InvokeWithDelay(() => mainGrid.Children.Remove(control), 5000); } /// /// Shows a modal message box and asynchronously returns a MessageBoxResult /// /// The text. /// The caption. /// The button. /// The icon. /// MessageBoxResult. public MessageBoxResult ShowModalMessage(string text, string caption = null, MessageBoxButton button = MessageBoxButton.OK, MessageBoxIcon icon = MessageBoxIcon.None) { var win = new ModalWindow { Caption = caption, Button = button, MessageBoxImage = icon, Text = text }; win.ShowModal(this); return win.MessageBoxResult; } /// /// Shows a modal message box and asynchronously returns a MessageBoxResult /// /// The text. /// The caption. /// The button. /// The icon. /// MessageBoxResult. public MessageBoxResult ShowModalMessage(UIElement text, string caption = null, MessageBoxButton button = MessageBoxButton.OK, MessageBoxIcon icon = MessageBoxIcon.None) { var win = new ModalWindow { Caption = caption, Button = button, MessageBoxImage = icon, TextContent = text }; win.ShowModal(this); return win.MessageBoxResult; } } }