aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.UI/Controls
diff options
context:
space:
mode:
authorLukePulverenti <luke.pulverenti@gmail.com>2013-02-20 20:33:05 -0500
committerLukePulverenti <luke.pulverenti@gmail.com>2013-02-20 20:33:05 -0500
commit767cdc1f6f6a63ce997fc9476911e2c361f9d402 (patch)
tree49add55976f895441167c66cfa95e5c7688d18ce /MediaBrowser.UI/Controls
parent845554722efaed872948a9e0f7202e3ef52f1b6e (diff)
Pushing missing changes
Diffstat (limited to 'MediaBrowser.UI/Controls')
-rw-r--r--MediaBrowser.UI/Controls/EnhancedScrollViewer.cs73
-rw-r--r--MediaBrowser.UI/Controls/ExtendedImage.cs92
-rw-r--r--MediaBrowser.UI/Controls/ModalWindow.xaml67
-rw-r--r--MediaBrowser.UI/Controls/ModalWindow.xaml.cs180
-rw-r--r--MediaBrowser.UI/Controls/NavigationBar.xaml55
-rw-r--r--MediaBrowser.UI/Controls/NavigationBar.xaml.cs318
-rw-r--r--MediaBrowser.UI/Controls/NotificationMessage.xaml33
-rw-r--r--MediaBrowser.UI/Controls/NotificationMessage.xaml.cs68
-rw-r--r--MediaBrowser.UI/Controls/TreeHelper.cs226
-rw-r--r--MediaBrowser.UI/Controls/WindowCommands.xaml191
-rw-r--r--MediaBrowser.UI/Controls/WindowCommands.xaml.cs132
11 files changed, 903 insertions, 532 deletions
diff --git a/MediaBrowser.UI/Controls/EnhancedScrollViewer.cs b/MediaBrowser.UI/Controls/EnhancedScrollViewer.cs
deleted file mode 100644
index 188715e1e5..0000000000
--- a/MediaBrowser.UI/Controls/EnhancedScrollViewer.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using System;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Input;
-
-namespace MediaBrowser.UI.Controls
-{
- /// <summary>
- /// Provides a ScrollViewer that can be scrolled by dragging the mouse
- /// </summary>
- public class EnhancedScrollViewer : ScrollViewer
- {
- private Point _scrollTarget;
- private Point _scrollStartPoint;
- private Point _scrollStartOffset;
- private const int PixelsToMoveToBeConsideredScroll = 5;
-
- protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
- {
- if (IsMouseOver)
- {
- // Save starting point, used later when determining how much to scroll.
- _scrollStartPoint = e.GetPosition(this);
- _scrollStartOffset.X = HorizontalOffset;
- _scrollStartOffset.Y = VerticalOffset;
-
- // Update the cursor if can scroll or not.
- Cursor = (ExtentWidth > ViewportWidth) ||
- (ExtentHeight > ViewportHeight) ?
- Cursors.ScrollAll : Cursors.Arrow;
-
- CaptureMouse();
- }
-
- base.OnPreviewMouseDown(e);
- }
-
- protected override void OnPreviewMouseMove(MouseEventArgs e)
- {
- if (IsMouseCaptured)
- {
- Point currentPoint = e.GetPosition(this);
-
- // Determine the new amount to scroll.
- var delta = new Point(_scrollStartPoint.X - currentPoint.X, _scrollStartPoint.Y - currentPoint.Y);
-
- if (Math.Abs(delta.X) < PixelsToMoveToBeConsideredScroll &&
- Math.Abs(delta.Y) < PixelsToMoveToBeConsideredScroll)
- return;
-
- _scrollTarget.X = _scrollStartOffset.X + delta.X;
- _scrollTarget.Y = _scrollStartOffset.Y + delta.Y;
-
- // Scroll to the new position.
- ScrollToHorizontalOffset(_scrollTarget.X);
- ScrollToVerticalOffset(_scrollTarget.Y);
- }
-
- base.OnPreviewMouseMove(e);
- }
-
- protected override void OnPreviewMouseUp(MouseButtonEventArgs e)
- {
- if (IsMouseCaptured)
- {
- Cursor = Cursors.Arrow;
- ReleaseMouseCapture();
- }
-
- base.OnPreviewMouseUp(e);
- }
- }
-}
diff --git a/MediaBrowser.UI/Controls/ExtendedImage.cs b/MediaBrowser.UI/Controls/ExtendedImage.cs
deleted file mode 100644
index 9d6ee3a7ae..0000000000
--- a/MediaBrowser.UI/Controls/ExtendedImage.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Media;
-
-namespace MediaBrowser.UI.Controls
-{
- /// <summary>
- /// Follow steps 1a or 1b and then 2 to use this custom control in a XAML file.
- ///
- /// Step 1a) Using this custom control in a XAML file that exists in the current project.
- /// Add this XmlNamespace attribute to the root element of the markup file where it is
- /// to be used:
- ///
- /// xmlns:MyNamespace="clr-namespace:MediaBrowser.UI.Controls"
- ///
- ///
- /// Step 1b) Using this custom control in a XAML file that exists in a different project.
- /// Add this XmlNamespace attribute to the root element of the markup file where it is
- /// to be used:
- ///
- /// xmlns:MyNamespace="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
- ///
- /// You will also need to add a project reference from the project where the XAML file lives
- /// to this project and Rebuild to avoid compilation errors:
- ///
- /// Right click on the target project in the Solution Explorer and
- /// "Add Reference"->"Projects"->[Browse to and select this project]
- ///
- ///
- /// Step 2)
- /// Go ahead and use your control in the XAML file.
- ///
- /// <MyNamespace:ExtendedImage/>
- ///
- /// </summary>
- public class ExtendedImage : Control
- {
- public static readonly DependencyProperty HasImageProperty = DependencyProperty.Register(
- "HasImage",
- typeof (bool),
- typeof (ExtendedImage),
- new PropertyMetadata(default(bool)));
-
- public bool HasImage
- {
- get { return (bool)GetValue(HasImageProperty); }
- set { SetValue(HasImageProperty, value); }
- }
-
- public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
- "Source",
- typeof(ImageSource),
- typeof(ExtendedImage),
- new PropertyMetadata(default(ImageBrush)));
-
- public ImageSource Source
- {
- get { return (ImageSource)GetValue(SourceProperty); }
- set { SetValue(SourceProperty, value); }
- }
-
- public static readonly DependencyProperty StretchProperty = DependencyProperty.Register(
- "Stretch",
- typeof (Stretch),
- typeof (ExtendedImage),
- new PropertyMetadata(default(Stretch)));
-
- public Stretch Stretch
- {
- get { return (Stretch) GetValue(StretchProperty); }
- set { SetValue(StretchProperty, value); }
- }
-
- public static readonly DependencyProperty PlaceHolderSourceProperty = DependencyProperty.Register(
- "PlaceHolderSource",
- typeof(ImageSource),
- typeof(ExtendedImage),
- new PropertyMetadata(default(ImageBrush)));
-
- public ImageSource PlaceHolderSource
- {
- get { return (ImageSource)GetValue(PlaceHolderSourceProperty); }
- set { SetValue(PlaceHolderSourceProperty, value); }
- }
-
- static ExtendedImage()
- {
- DefaultStyleKeyProperty.OverrideMetadata(typeof(ExtendedImage),
- new FrameworkPropertyMetadata(typeof(ExtendedImage)));
- }
- }
-}
diff --git a/MediaBrowser.UI/Controls/ModalWindow.xaml b/MediaBrowser.UI/Controls/ModalWindow.xaml
new file mode 100644
index 0000000000..c2afbe05e2
--- /dev/null
+++ b/MediaBrowser.UI/Controls/ModalWindow.xaml
@@ -0,0 +1,67 @@
+<controls:BaseModalWindow x:Class="MediaBrowser.UI.Controls.ModalWindow"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Controls="clr-namespace:MediaBrowser.UI.Controls"
+ xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
+ Title="ModalWindow"
+ AllowsTransparency="True"
+ Background="Transparent"
+ Style="{StaticResource ModalWindow}">
+
+ <Grid>
+ <Grid Style="{StaticResource ModalOverlayStyle}">
+
+ </Grid>
+ <Grid Style="{StaticResource ModalContentStyle}" RenderTransformOrigin="1,0">
+ <Grid Style="{StaticResource ModalContentInnerStyle}">
+
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="auto"></ColumnDefinition>
+ <ColumnDefinition Width="*"></ColumnDefinition>
+ </Grid.ColumnDefinitions>
+
+ <Grid.RowDefinitions>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="auto"></RowDefinition>
+ </Grid.RowDefinitions>
+
+ <Image Grid.Row="0" Grid.RowSpan="3" Grid.Column="0" Style="{StaticResource ModalButtonImage}"></Image>
+
+ <TextBlock x:Name="txtCaption" Text="{Binding Caption}" Style="{StaticResource Heading2TextBlockStyle}" Grid.Row="0" Grid.Column="1" Margin="0 30 0 10"></TextBlock>
+
+ <Grid x:Name="pnlContent" HorizontalAlignment="Stretch" Grid.Row="1" Grid.Column="1">
+
+ </Grid>
+
+ <StackPanel x:Name="pnlButtons" Style="{StaticResource ModalButtonPanel}" Grid.Row="2" Grid.Column="1">
+ <controls:ExtendedButton x:Name="btnYes" Content="Yes" Style="{StaticResource ModalButton}"></controls:ExtendedButton>
+ <controls:ExtendedButton x:Name="btnNo" Content="No" Style="{StaticResource ModalButton}"></controls:ExtendedButton>
+ <controls:ExtendedButton x:Name="btnOk" Content="OK" Style="{StaticResource ModalButton}"></controls:ExtendedButton>
+ <controls:ExtendedButton x:Name="btnCancel" Content="Cancel" Style="{StaticResource ModalButton}"></controls:ExtendedButton>
+ </StackPanel>
+ </Grid>
+ <!-- Animation -->
+ <Grid.Triggers>
+ <EventTrigger RoutedEvent="FrameworkElement.Loaded">
+ <BeginStoryboard>
+ <Storyboard>
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)">
+ <SplineDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
+ <SplineDoubleKeyFrame KeyTime="0:0:0.15" Value="1"/>
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ </BeginStoryboard>
+ </EventTrigger>
+ </Grid.Triggers>
+
+ <Grid.RenderTransform>
+ <ScaleTransform ScaleX="1" />
+ </Grid.RenderTransform>
+ </Grid>
+
+ <Grid.LayoutTransform>
+ <ScaleTransform ScaleX="{Binding Path=ContentScale}" ScaleY="{Binding Path=ContentScale}" CenterX="0" CenterY="0" />
+ </Grid.LayoutTransform>
+
+ </Grid>
+</controls:BaseModalWindow>
diff --git a/MediaBrowser.UI/Controls/ModalWindow.xaml.cs b/MediaBrowser.UI/Controls/ModalWindow.xaml.cs
new file mode 100644
index 0000000000..21f97b8ac0
--- /dev/null
+++ b/MediaBrowser.UI/Controls/ModalWindow.xaml.cs
@@ -0,0 +1,180 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media.Animation;
+
+namespace MediaBrowser.UI.Controls
+{
+ /// <summary>
+ /// Interaction logic for ModalWindow.xaml
+ /// </summary>
+ public partial class ModalWindow : BaseModalWindow
+ {
+ public MessageBoxResult MessageBoxResult { get; set; }
+
+ public UIElement TextContent
+ {
+ set
+ {
+ pnlContent.Children.Clear();
+
+ var textBlock = value as TextBlock;
+
+ if (textBlock != null)
+ {
+ textBlock.SetResourceReference(TextBlock.StyleProperty, "ModalTextStyle");
+ }
+ pnlContent.Children.Add(value);
+ }
+ }
+
+ public string Text
+ {
+ set { TextContent = new TextBlock { Text = value }; }
+ }
+
+ private MessageBoxButton _button;
+ public MessageBoxButton Button
+ {
+ get { return _button; }
+ set
+ {
+ _button = value;
+ UpdateButtonVisibility();
+ OnPropertyChanged("Button");
+ }
+ }
+
+ private MessageBoxIcon _messageBoxImage;
+ public MessageBoxIcon MessageBoxImage
+ {
+ get { return _messageBoxImage; }
+ set
+ {
+ _messageBoxImage = value;
+ OnPropertyChanged("MessageBoxImage");
+ }
+ }
+
+ private string _caption;
+ public string Caption
+ {
+ get { return _caption; }
+ set
+ {
+ _caption = value;
+ txtCaption.Visibility = string.IsNullOrEmpty(value) ? Visibility.Collapsed : Visibility.Visible;
+ OnPropertyChanged("Caption");
+ }
+ }
+
+ public ModalWindow()
+ : base()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnInitialized(EventArgs e)
+ {
+ base.OnInitialized(e);
+
+ btnOk.Click += btnOk_Click;
+ btnCancel.Click += btnCancel_Click;
+ btnYes.Click += btnYes_Click;
+ btnNo.Click += btnNo_Click;
+ }
+
+ void btnNo_Click(object sender, RoutedEventArgs e)
+ {
+ MessageBoxResult = MessageBoxResult.No;
+ CloseModal();
+ }
+
+ void btnYes_Click(object sender, RoutedEventArgs e)
+ {
+ MessageBoxResult = MessageBoxResult.Yes;
+ CloseModal();
+ }
+
+ void btnCancel_Click(object sender, RoutedEventArgs e)
+ {
+ MessageBoxResult = MessageBoxResult.Cancel;
+ CloseModal();
+ }
+
+ void btnOk_Click(object sender, RoutedEventArgs e)
+ {
+ MessageBoxResult = MessageBoxResult.OK;
+ CloseModal();
+ }
+
+ private void UpdateButtonVisibility()
+ {
+ btnYes.Visibility = Button == MessageBoxButton.YesNo || Button == MessageBoxButton.YesNoCancel
+ ? Visibility.Visible
+ : Visibility.Collapsed;
+
+ btnNo.Visibility = Button == MessageBoxButton.YesNo || Button == MessageBoxButton.YesNoCancel
+ ? Visibility.Visible
+ : Visibility.Collapsed;
+
+ btnOk.Visibility = Button == MessageBoxButton.OK || Button == MessageBoxButton.OKCancel
+ ? Visibility.Visible
+ : Visibility.Collapsed;
+
+ btnCancel.Visibility = Button == MessageBoxButton.OKCancel || Button == MessageBoxButton.YesNoCancel
+ ? Visibility.Visible
+ : Visibility.Collapsed;
+ }
+ }
+
+ /// <summary>
+ /// I had to make my own enum that essentially clones MessageBoxImage
+ /// Some of the options share the same enum int value, and this was preventing databinding from working properly.
+ /// </summary>
+ public enum MessageBoxIcon
+ {
+ // Summary:
+ // No icon is displayed.
+ None,
+ //
+ // Summary:
+ // The message box contains a symbol consisting of white X in a circle with
+ // a red background.
+ Error,
+ //
+ // Summary:
+ // The message box contains a symbol consisting of a white X in a circle with
+ // a red background.
+ Hand,
+ //
+ // Summary:
+ // The message box contains a symbol consisting of white X in a circle with
+ // a red background.
+ Stop,
+ //
+ // Summary:
+ // The message box contains a symbol consisting of a question mark in a circle.
+ Question,
+ //
+ // Summary:
+ // The message box contains a symbol consisting of an exclamation point in a
+ // triangle with a yellow background.
+ Exclamation,
+ //
+ // Summary:
+ // The message box contains a symbol consisting of an exclamation point in a
+ // triangle with a yellow background.
+ Warning,
+ //
+ // Summary:
+ // The message box contains a symbol consisting of a lowercase letter i in a
+ // circle.
+ Information,
+ //
+ // Summary:
+ // The message box contains a symbol consisting of a lowercase letter i in a
+ // circle.
+ Asterisk
+ }
+}
diff --git a/MediaBrowser.UI/Controls/NavigationBar.xaml b/MediaBrowser.UI/Controls/NavigationBar.xaml
new file mode 100644
index 0000000000..020fecd6d5
--- /dev/null
+++ b/MediaBrowser.UI/Controls/NavigationBar.xaml
@@ -0,0 +1,55 @@
+<controls:BaseUserControl x:Class="MediaBrowser.UI.Controls.NavigationBar"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid x:Name="NavBarGrid" Style="{StaticResource NavBarGrid}">
+
+ <Grid Style="{StaticResource NavBarBackgroundGrid}"></Grid>
+
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="auto"></RowDefinition>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="1*"></ColumnDefinition>
+ <ColumnDefinition Width="1*"></ColumnDefinition>
+ <ColumnDefinition Width="1*"></ColumnDefinition>
+ </Grid.ColumnDefinitions>
+
+ <Grid x:Name="SeekGrid" Grid.Row="0" Grid.ColumnSpan="3" Margin="150 15 150 5" Visibility="Collapsed">
+
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="auto"></ColumnDefinition>
+ <ColumnDefinition Width="*"></ColumnDefinition>
+ <ColumnDefinition Width="auto"></ColumnDefinition>
+ </Grid.ColumnDefinitions>
+
+ <TextBlock x:Name="TxtCurrentPosition" Grid.Column="0" Style="{StaticResource TextBlockStyle}" Margin="0 0 10 0"></TextBlock>
+ <Slider x:Name="CurrentPositionSlider" Grid.Column="1" VerticalAlignment="Center" Minimum="0" Thumb.DragStarted="CurrentPositionSlider_DragStarted" Thumb.DragCompleted="CurrentPositionSlider_DragCompleted" IsMoveToPointEnabled="True"></Slider>
+ <TextBlock x:Name="TxtDuration" Grid.Column="2" Style="{StaticResource TextBlockStyle}" Margin="10 0 0 0"></TextBlock>
+
+ </Grid>
+
+ <StackPanel Style="{StaticResource NavBarGridLeftPanel}" Grid.Row="1">
+ <Button x:Name="BackButton" Style="{StaticResource BackButton}"></Button>
+ </StackPanel>
+ <StackPanel Style="{StaticResource NavBarGridCenterPanel}" Grid.Row="1">
+ <Button x:Name="PreviousChapterButton" Style="{StaticResource PreviousChapterButton}" Visibility="Collapsed"></Button>
+ <Button x:Name="PlayButton" Style="{StaticResource PlayButton}" Visibility="Collapsed"></Button>
+ <Button x:Name="PauseButton" Style="{StaticResource PauseButton}" Visibility="Collapsed"></Button>
+ <Button x:Name="StopButton" Style="{StaticResource StopButton}" Visibility="Collapsed"></Button>
+ <Button x:Name="NextChapterButton" Style="{StaticResource NextChapterButton}" Visibility="Collapsed"></Button>
+ </StackPanel>
+ <StackPanel Style="{StaticResource NavBarGridRightPanel}" Grid.Row="1">
+ <Button x:Name="MuteButton" Style="{StaticResource MuteButton}" Visibility="Collapsed"></Button>
+ <Button x:Name="VolumeDownButton" Style="{StaticResource VolumeDownButton}" Visibility="Collapsed"></Button>
+ <Button x:Name="VolumeUpButton" Style="{StaticResource VolumeUpButton}" Visibility="Collapsed"></Button>
+ </StackPanel>
+ </Grid>
+ </Grid>
+</controls:BaseUserControl>
diff --git a/MediaBrowser.UI/Controls/NavigationBar.xaml.cs b/MediaBrowser.UI/Controls/NavigationBar.xaml.cs
new file mode 100644
index 0000000000..6d59a7d3a3
--- /dev/null
+++ b/MediaBrowser.UI/Controls/NavigationBar.xaml.cs
@@ -0,0 +1,318 @@
+using MediaBrowser.UI.Controller;
+using MediaBrowser.UI.Playback;
+using MediaBrowser.UI.Playback.InternalPlayer;
+using System;
+using System.Threading;
+using System.Windows;
+using System.Windows.Controls.Primitives;
+using System.Windows.Input;
+
+namespace MediaBrowser.UI.Controls
+{
+ /// <summary>
+ /// Interaction logic for NavigationBar.xaml
+ /// </summary>
+ public partial class NavigationBar : BaseUserControl
+ {
+ /// <summary>
+ /// Gets or sets the current player.
+ /// </summary>
+ /// <value>The current player.</value>
+ private BaseMediaPlayer CurrentPlayer { get; set; }
+
+ /// <summary>
+ /// Gets or sets the current position timer.
+ /// </summary>
+ /// <value>The current position timer.</value>
+ private Timer CurrentPositionTimer { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="NavigationBar" /> class.
+ /// </summary>
+ public NavigationBar()
+ {
+ InitializeComponent();
+
+ Loaded += NavigationBar_Loaded;
+ }
+
+ /// <summary>
+ /// Handles the Loaded event of the NavigationBar control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ void NavigationBar_Loaded(object sender, RoutedEventArgs e)
+ {
+ BackButton.Click += BtnApplicationBackClick;
+ MuteButton.Click += MuteButton_Click;
+
+ VolumeDownButton.PreviewMouseDown += VolumeDownButton_Click;
+ VolumeUpButton.PreviewMouseDown += VolumeUpButton_Click;
+
+ StopButton.Click += StopButton_Click;
+ PlayButton.Click += PlayButton_Click;
+ PauseButton.Click += PauseButton_Click;
+
+ NextChapterButton.Click += NextChapterButton_Click;
+ PreviousChapterButton.Click += PreviousChapterButton_Click;
+
+ UIKernel.Instance.PlaybackManager.PlaybackStarted += PlaybackManager_PlaybackStarted;
+ UIKernel.Instance.PlaybackManager.PlaybackCompleted += PlaybackManager_PlaybackCompleted;
+
+ CurrentPositionSlider.PreviewMouseUp += CurrentPositionSlider_PreviewMouseUp;
+ }
+
+ /// <summary>
+ /// Handles the Click event of the PreviousChapterButton control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ async void PreviousChapterButton_Click(object sender, RoutedEventArgs e)
+ {
+ await CurrentPlayer.GoToPreviousChapter();
+ }
+
+ /// <summary>
+ /// Handles the Click event of the NextChapterButton control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ async void NextChapterButton_Click(object sender, RoutedEventArgs e)
+ {
+ await CurrentPlayer.GoToNextChapter();
+ }
+
+ /// <summary>
+ /// Handles the Click event of the PauseButton control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ async void PauseButton_Click(object sender, RoutedEventArgs e)
+ {
+ await CurrentPlayer.Pause();
+ }
+
+ /// <summary>
+ /// Handles the Click event of the PlayButton control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ async void PlayButton_Click(object sender, RoutedEventArgs e)
+ {
+ await CurrentPlayer.UnPause();
+ }
+
+ /// <summary>
+ /// Handles the Click event of the StopButton control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ async void StopButton_Click(object sender, RoutedEventArgs e)
+ {
+ await CurrentPlayer.Stop();
+ }
+
+ /// <summary>
+ /// Handles the PlaybackCompleted event of the PlaybackManager control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="PlaybackEventArgs" /> instance containing the event data.</param>
+ void PlaybackManager_PlaybackCompleted(object sender, PlaybackStopEventArgs e)
+ {
+ if (e.Player == CurrentPlayer)
+ {
+ if (CurrentPositionTimer != null)
+ {
+ CurrentPositionTimer.Dispose();
+ }
+
+ CurrentPlayer.PlayStateChanged -= CurrentPlayer_PlayStateChanged;
+ CurrentPlayer = null;
+ ResetButtonVisibilities(null);
+
+ Dispatcher.InvokeAsync(() => TxtCurrentPosition.Text = string.Empty);
+ }
+ }
+
+ /// <summary>
+ /// Handles the Click event of the VolumeUpButton control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ void VolumeUpButton_Click(object sender, RoutedEventArgs e)
+ {
+ CurrentPlayer.Volume += 3;
+ }
+
+ /// <summary>
+ /// Handles the Click event of the VolumeDownButton control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ void VolumeDownButton_Click(object sender, RoutedEventArgs e)
+ {
+ CurrentPlayer.Volume -= 3;
+ }
+
+ /// <summary>
+ /// Handles the Click event of the MuteButton control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ void MuteButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (CurrentPlayer.CanMute)
+ {
+ CurrentPlayer.Mute = !CurrentPlayer.Mute;
+ }
+ }
+
+ /// <summary>
+ /// Handles the PlaybackStarted event of the PlaybackManager control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="PlaybackEventArgs" /> instance containing the event data.</param>
+ void PlaybackManager_PlaybackStarted(object sender, PlaybackEventArgs e)
+ {
+ if (e.Player is BaseInternalMediaPlayer)
+ {
+ CurrentPlayer = e.Player;
+ CurrentPlayer.PlayStateChanged += CurrentPlayer_PlayStateChanged;
+
+ ResetButtonVisibilities(e.Player);
+
+ Dispatcher.InvokeAsync(() =>
+ {
+ var runtime = e.Player.CurrentMedia.RunTimeTicks ?? 0;
+ CurrentPositionSlider.Maximum = runtime;
+
+ TxtDuration.Text = GetTimeString(runtime);
+
+ });
+
+ CurrentPositionTimer = new Timer(CurrentPositionTimerCallback, null, 250, 250);
+ }
+ }
+
+ /// <summary>
+ /// Currents the position timer callback.
+ /// </summary>
+ /// <param name="state">The state.</param>
+ private void CurrentPositionTimerCallback(object state)
+ {
+ var time = string.Empty;
+
+ var ticks = CurrentPlayer.CurrentPositionTicks;
+
+ if (ticks.HasValue)
+ {
+ time = GetTimeString(ticks.Value);
+ }
+
+ Dispatcher.InvokeAsync(() =>
+ {
+ TxtCurrentPosition.Text = time;
+
+ if (!_isPositionSliderDragging)
+ {
+ CurrentPositionSlider.Value = ticks ?? 0;
+ }
+ });
+ }
+
+ /// <summary>
+ /// Gets the time string.
+ /// </summary>
+ /// <param name="ticks">The ticks.</param>
+ /// <returns>System.String.</returns>
+ private string GetTimeString(long ticks)
+ {
+ var timespan = TimeSpan.FromTicks(ticks);
+
+ return timespan.TotalHours >= 1 ? timespan.ToString("hh':'mm':'ss") : timespan.ToString("mm':'ss");
+ }
+
+ /// <summary>
+ /// Handles the PlayStateChanged event of the CurrentPlayer control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
+ void CurrentPlayer_PlayStateChanged(object sender, EventArgs e)
+ {
+ ResetButtonVisibilities(CurrentPlayer);
+ }
+
+ /// <summary>
+ /// Resets the button visibilities.
+ /// </summary>
+ /// <param name="player">The player.</param>
+ private void ResetButtonVisibilities(BaseMediaPlayer player)
+ {
+ Dispatcher.Invoke(() =>
+ {
+ PlayButton.Visibility = player != null && player.PlayState == PlayState.Paused ? Visibility.Visible : Visibility.Collapsed;
+ PauseButton.Visibility = player != null && player.CanPause && player.PlayState == PlayState.Playing ? Visibility.Visible : Visibility.Collapsed;
+
+ StopButton.Visibility = player != null ? Visibility.Visible : Visibility.Collapsed;
+ MuteButton.Visibility = player != null && player.CanMute ? Visibility.Visible : Visibility.Collapsed;
+ VolumeUpButton.Visibility = player != null && player.CanControlVolume ? Visibility.Visible : Visibility.Collapsed;
+ VolumeDownButton.Visibility = player != null && player.CanControlVolume ? Visibility.Visible : Visibility.Collapsed;
+
+ var isSeekabke = player != null && player.CanSeek && player.CurrentMedia != null;
+ SeekGrid.Visibility = isSeekabke ? Visibility.Visible : Visibility.Collapsed;
+
+ var canSeekChapters = isSeekabke && player.CurrentMedia.Chapters != null && player.CurrentMedia.Chapters.Count > 1;
+
+ NextChapterButton.Visibility = canSeekChapters ? Visibility.Visible : Visibility.Collapsed;
+ PreviousChapterButton.Visibility = canSeekChapters ? Visibility.Visible : Visibility.Collapsed;
+ });
+ }
+
+ /// <summary>
+ /// BTNs the application back click.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ void BtnApplicationBackClick(object sender, RoutedEventArgs e)
+ {
+ App.Instance.ApplicationWindow.NavigateBack();
+ }
+
+ /// <summary>
+ /// The is position slider dragging
+ /// </summary>
+ private bool _isPositionSliderDragging;
+
+ /// <summary>
+ /// Handles the DragStarted event of the CurrentPositionSlider control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="DragStartedEventArgs" /> instance containing the event data.</param>
+ private void CurrentPositionSlider_DragStarted(object sender, DragStartedEventArgs e)
+ {
+ _isPositionSliderDragging = true;
+ }
+
+ /// <summary>
+ /// Handles the DragCompleted event of the CurrentPositionSlider control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="DragCompletedEventArgs" /> instance containing the event data.</param>
+ private void CurrentPositionSlider_DragCompleted(object sender, DragCompletedEventArgs e)
+ {
+ _isPositionSliderDragging = false;
+
+ //await CurrentPlayer.Seek(Convert.ToInt64(CurrentPositionSlider.Value));
+ }
+
+ /// <summary>
+ /// Handles the PreviewMouseUp event of the CurrentPositionSlider control.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="MouseButtonEventArgs" /> instance containing the event data.</param>
+ async void CurrentPositionSlider_PreviewMouseUp(object sender, MouseButtonEventArgs e)
+ {
+ await CurrentPlayer.Seek(Convert.ToInt64(CurrentPositionSlider.Value));
+ }
+ }
+}
diff --git a/MediaBrowser.UI/Controls/NotificationMessage.xaml b/MediaBrowser.UI/Controls/NotificationMessage.xaml
new file mode 100644
index 0000000000..6411b6f57a
--- /dev/null
+++ b/MediaBrowser.UI/Controls/NotificationMessage.xaml
@@ -0,0 +1,33 @@
+<controls:BaseUserControl x:Class="MediaBrowser.UI.Controls.NotificationMessage"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:Controls="clr-namespace:MediaBrowser.UI.Controls"
+ xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+ <Grid Style="{StaticResource NotificationContentStyle}">
+ <Grid Style="{StaticResource NotificationContentInnerStyle}">
+
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="auto"></ColumnDefinition>
+ <ColumnDefinition Width="*"></ColumnDefinition>
+ </Grid.ColumnDefinitions>
+
+ <Grid.RowDefinitions>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="auto"></RowDefinition>
+ <RowDefinition Height="auto"></RowDefinition>
+ </Grid.RowDefinitions>
+
+ <Image Grid.Row="0" Grid.RowSpan="3" Grid.Column="0" Style="{StaticResource NotificationButtonImage}"></Image>
+
+ <TextBlock x:Name="txtCaption" Text="{Binding Caption}" Style="{StaticResource NotificationCaptionStyle}" Grid.Row="0" Grid.Column="1"></TextBlock>
+
+ <Grid x:Name="pnlContent" HorizontalAlignment="Stretch" Grid.Row="1" Grid.Column="1">
+
+ </Grid>
+ </Grid>
+ </Grid>
+</controls:BaseUserControl>
diff --git a/MediaBrowser.UI/Controls/NotificationMessage.xaml.cs b/MediaBrowser.UI/Controls/NotificationMessage.xaml.cs
new file mode 100644
index 0000000000..06ed513b13
--- /dev/null
+++ b/MediaBrowser.UI/Controls/NotificationMessage.xaml.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace MediaBrowser.UI.Controls
+{
+ /// <summary>
+ /// Interaction logic for NotificationMessage.xaml
+ /// </summary>
+ public partial class NotificationMessage : BaseUserControl
+ {
+ public NotificationMessage()
+ {
+ InitializeComponent();
+ }
+
+ public UIElement TextContent
+ {
+ set
+ {
+ pnlContent.Children.Clear();
+
+ var textBlock = value as TextBlock;
+
+ if (textBlock != null)
+ {
+ textBlock.SetResourceReference(TextBlock.StyleProperty, "NotificationTextStyle");
+ }
+ pnlContent.Children.Add(value);
+ }
+ }
+
+ public string Text
+ {
+ set { TextContent = new TextBlock { Text = value }; }
+ }
+
+ private MessageBoxIcon _messageBoxImage;
+ public MessageBoxIcon MessageBoxImage
+ {
+ get { return _messageBoxImage; }
+ set
+ {
+ _messageBoxImage = value;
+ OnPropertyChanged("MessageBoxImage");
+ }
+ }
+
+ private string _caption;
+ public string Caption
+ {
+ get { return _caption; }
+ set
+ {
+ _caption = value;
+ OnPropertyChanged("Caption");
+ txtCaption.Visibility = string.IsNullOrEmpty(value) ? Visibility.Collapsed : Visibility.Visible;
+ }
+ }
+
+ protected override void OnInitialized(EventArgs e)
+ {
+ base.OnInitialized(e);
+
+ DataContext = this;
+ }
+ }
+}
diff --git a/MediaBrowser.UI/Controls/TreeHelper.cs b/MediaBrowser.UI/Controls/TreeHelper.cs
deleted file mode 100644
index bbe4895727..0000000000
--- a/MediaBrowser.UI/Controls/TreeHelper.cs
+++ /dev/null
@@ -1,226 +0,0 @@
-using System.Collections.Generic;
-using System.Windows;
-using System.Windows.Media;
-
-namespace MediaBrowser.UI.Controls
-{
- /// <summary>
- /// Helper methods for UI-related tasks.
- /// </summary>
- public static class TreeHelper
- {
- /// <summary>
- /// Finds a Child of a given item in the visual tree.
- /// </summary>
- /// <param name="parent">A direct parent of the queried item.</param>
- /// <typeparam name="T">The type of the queried item.</typeparam>
- /// <param name="childName">x:Name or Name of child. </param>
- /// <returns>The first parent item that matches the submitted type parameter.
- /// If not matching item can be found,
- /// a null parent is being returned.</returns>
- public static T FindChild<T>(DependencyObject parent, string childName)
- where T : DependencyObject
- {
- // Confirm parent and childName are valid.
- if (parent == null) return null;
-
- T foundChild = null;
-
- int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
- for (int i = 0; i < childrenCount; i++)
- {
- var child = VisualTreeHelper.GetChild(parent, i);
- // If the child is not of the request child type child
- T childType = child as T;
- if (childType == null)
- {
- // recursively drill down the tree
- foundChild = FindChild<T>(child, childName);
-
- // If the child is found, break so we do not overwrite the found child.
- if (foundChild != null) break;
- }
- else if (!string.IsNullOrEmpty(childName))
- {
- var frameworkElement = child as FrameworkElement;
- // If the child's name is set for search
- if (frameworkElement != null && frameworkElement.Name == childName)
- {
- // if the child's name is of the request name
- foundChild = (T)child;
- break;
- }
- }
- else
- {
- // child element found.
- foundChild = (T)child;
- break;
- }
- }
-
- return foundChild;
- }
-
- #region find parent
-
- /// <summary>
- /// Finds a parent of a given item on the visual tree.
- /// </summary>
- /// <typeparam name="T">The type of the queried item.</typeparam>
- /// <param name="child">A direct or indirect child of the
- /// queried item.</param>
- /// <returns>The first parent item that matches the submitted
- /// type parameter. If not matching item can be found, a null
- /// reference is being returned.</returns>
- public static T TryFindParent<T>(this DependencyObject child)
- where T : DependencyObject
- {
- //get parent item
- DependencyObject parentObject = GetParentObject(child);
-
- //we've reached the end of the tree
- if (parentObject == null) return null;
-
- //check if the parent matches the type we're looking for
- T parent = parentObject as T;
- if (parent != null)
- {
- return parent;
- }
-
- //use recursion to proceed with next level
- return TryFindParent<T>(parentObject);
- }
-
- /// <summary>
- /// This method is an alternative to WPF's
- /// <see cref="VisualTreeHelper.GetParent"/> method, which also
- /// supports content elements. Keep in mind that for content element,
- /// this method falls back to the logical tree of the element!
- /// </summary>
- /// <param name="child">The item to be processed.</param>
- /// <returns>The submitted item's parent, if available. Otherwise
- /// null.</returns>
- public static DependencyObject GetParentObject(this DependencyObject child)
- {
- if (child == null) return null;
-
- //handle content elements separately
- ContentElement contentElement = child as ContentElement;
- if (contentElement != null)
- {
- DependencyObject parent = ContentOperations.GetParent(contentElement);
- if (parent != null) return parent;
-
- FrameworkContentElement fce = contentElement as FrameworkContentElement;
- return fce != null ? fce.Parent : null;
- }
-
- //also try searching for parent in framework elements (such as DockPanel, etc)
- FrameworkElement frameworkElement = child as FrameworkElement;
- if (frameworkElement != null)
- {
- DependencyObject parent = frameworkElement.Parent;
- if (parent != null) return parent;
- }
-
- //if it's not a ContentElement/FrameworkElement, rely on VisualTreeHelper
- return VisualTreeHelper.GetParent(child);
- }
-
- #endregion
-
- #region find children
-
- /// <summary>
- /// Analyzes both visual and logical tree in order to find all elements of a given
- /// type that are descendants of the <paramref name="source"/> item.
- /// </summary>
- /// <typeparam name="T">The type of the queried items.</typeparam>
- /// <param name="source">The root element that marks the source of the search. If the
- /// source is already of the requested type, it will not be included in the result.</param>
- /// <returns>All descendants of <paramref name="source"/> that match the requested type.</returns>
- public static IEnumerable<T> FindChildren<T>(this DependencyObject source) where T : DependencyObject
- {
- if (source != null)
- {
- var childs = GetChildObjects(source);
- foreach (DependencyObject child in childs)
- {
- //analyze if children match the requested type
- if (child is T)
- {
- yield return (T)child;
- }
-
- //recurse tree
- foreach (T descendant in FindChildren<T>(child))
- {
- yield return descendant;
- }
- }
- }
- }
-
-
- /// <summary>
- /// This method is an alternative to WPF's
- /// <see cref="VisualTreeHelper.GetChild"/> method, which also
- /// supports content elements. Keep in mind that for content elements,
- /// this method falls back to the logical tree of the element.
- /// </summary>
- /// <param name="parent">The item to be processed.</param>
- /// <returns>The submitted item's child elements, if available.</returns>
- public static IEnumerable<DependencyObject> GetChildObjects(this DependencyObject parent)
- {
- if (parent == null) yield break;
-
- if (parent is ContentElement || parent is FrameworkElement)
- {
- //use the logical tree for content / framework elements
- foreach (object obj in LogicalTreeHelper.GetChildren(parent))
- {
- var depObj = obj as DependencyObject;
- if (depObj != null) yield return (DependencyObject)obj;
- }
- }
- else
- {
- //use the visual tree per default
- int count = VisualTreeHelper.GetChildrenCount(parent);
- for (int i = 0; i < count; i++)
- {
- yield return VisualTreeHelper.GetChild(parent, i);
- }
- }
- }
-
- #endregion
-
- #region find from point
-
- /// <summary>
- /// Tries to locate a given item within the visual tree,
- /// starting with the dependency object at a given position.
- /// </summary>
- /// <typeparam name="T">The type of the element to be found
- /// on the visual tree of the element at the given location.</typeparam>
- /// <param name="reference">The main element which is used to perform
- /// hit testing.</param>
- /// <param name="point">The position to be evaluated on the origin.</param>
- public static T TryFindFromPoint<T>(UIElement reference, Point point)
- where T : DependencyObject
- {
- DependencyObject element = reference.InputHitTest(point) as DependencyObject;
-
- if (element == null) return null;
-
- if (element is T) return (T)element;
-
- return TryFindParent<T>(element);
- }
-
- #endregion
- }
-}
diff --git a/MediaBrowser.UI/Controls/WindowCommands.xaml b/MediaBrowser.UI/Controls/WindowCommands.xaml
index 9209549185..bca8812385 100644
--- a/MediaBrowser.UI/Controls/WindowCommands.xaml
+++ b/MediaBrowser.UI/Controls/WindowCommands.xaml
@@ -1,91 +1,100 @@
-<UserControl x:Class="MediaBrowser.UI.Controls.WindowCommands"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- mc:Ignorable="d"
- d:DesignHeight="300" d:DesignWidth="300">
-
- <UserControl.Resources>
-
- <Style TargetType="StackPanel" x:Key="WindowCommandsPanel">
- <Setter Property="Orientation" Value="Horizontal"/>
- <Setter Property="HorizontalAlignment" Value="Right"/>
- </Style>
-
- <Style TargetType="Button" x:Key="WebdingsButton" BasedOn="{StaticResource ImageButton}">
- <Setter Property="Margin" Value="0 0 15 0"/>
- <Setter Property="KeyboardNavigation.IsTabStop" Value="false"/>
- </Style>
-
- <Style TargetType="TextBlock" x:Key="WebdingsTextBlock">
- <Setter Property="FontFamily" Value="Webdings"/>
- <Setter Property="FontSize" Value="14"/>
- <Setter Property="Foreground" Value="{StaticResource DefaultForeground}"/>
- </Style>
-
- <Style TargetType="Button" x:Key="MinimizeApplicationButton" BasedOn="{StaticResource WebdingsButton}">
- <Setter Property="ToolTip" Value="Minimize"/>
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate>
- <TextBlock Style="{StaticResource WebdingsTextBlock}">0</TextBlock>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
-
- <Style TargetType="Button" x:Key="MaximizeApplicationButton" BasedOn="{StaticResource WebdingsButton}">
- <Setter Property="ToolTip" Value="Maximize"/>
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate>
- <TextBlock Style="{StaticResource WebdingsTextBlock}">1</TextBlock>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- <Style.Triggers>
- <DataTrigger Binding="{Binding Path=WindowState, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="Maximized">
- <Setter Property="Visibility" Value="Collapsed" />
- </DataTrigger>
- </Style.Triggers>
- </Style>
-
- <Style TargetType="Button" x:Key="UndoMaximizeApplicationButton" BasedOn="{StaticResource WebdingsButton}">
- <Setter Property="Visibility" Value="Collapsed"/>
- <Setter Property="ToolTip" Value="Restore"/>
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate>
- <TextBlock Style="{StaticResource WebdingsTextBlock}">2</TextBlock>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- <Style.Triggers>
- <DataTrigger Binding="{Binding Path=WindowState, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="Maximized">
- <Setter Property="Visibility" Value="Visible" />
- </DataTrigger>
- </Style.Triggers>
- </Style>
-
- <Style TargetType="Button" x:Key="CloseApplicationButton" BasedOn="{StaticResource WebdingsButton}">
- <Setter Property="ToolTip" Value="Close"/>
- <Setter Property="Template">
- <Setter.Value>
- <ControlTemplate>
- <TextBlock Style="{StaticResource WebdingsTextBlock}">r</TextBlock>
- </ControlTemplate>
- </Setter.Value>
- </Setter>
- </Style>
-
- </UserControl.Resources>
-
- <StackPanel Style="{StaticResource WindowCommandsPanel}">
- <Button x:Name="MinimizeApplicationButton" Style="{StaticResource MinimizeApplicationButton}"></Button>
- <Button x:Name="MaximizeApplicationButton" Style="{StaticResource MaximizeApplicationButton}"></Button>
- <Button x:Name="UndoMaximizeApplicationButton" Style="{StaticResource UndoMaximizeApplicationButton}"></Button>
- <Button x:Name="CloseApplicationButton" Style="{StaticResource CloseApplicationButton}"></Button>
- </StackPanel>
-
-</UserControl>
+<UserControl x:Class="MediaBrowser.UI.Controls.WindowCommands"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ mc:Ignorable="d"
+ d:DesignHeight="300" d:DesignWidth="300">
+
+ <UserControl.Resources>
+
+ <Style TargetType="StackPanel" x:Key="WindowCommandsPanel">
+ <Setter Property="Orientation" Value="Horizontal"/>
+ <Setter Property="HorizontalAlignment" Value="Right"/>
+ </Style>
+
+ <Style TargetType="Button" x:Key="WebdingsButton">
+ <Setter Property="Margin" Value="0 0 15 0"/>
+ <Setter Property="KeyboardNavigation.IsTabStop" Value="false"/>
+ <Setter Property="Padding" Value="0"/>
+ <Setter Property="BorderThickness" Value="0"/>
+ <Style.Triggers>
+ <Trigger Property="IsMouseOver" Value="True">
+ <Setter Property="Opacity" Value=".5" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+
+ <Style TargetType="TextBlock" x:Key="WebdingsTextBlock">
+ <Setter Property="FontFamily" Value="Webdings"/>
+ <Setter Property="FontSize" Value="14"/>
+ <Setter Property="Foreground" Value="{StaticResource DefaultForeground}"/>
+ </Style>
+
+ <Style TargetType="Button" x:Key="MinimizeApplicationButton" BasedOn="{StaticResource WebdingsButton}">
+ <Setter Property="ToolTip" Value="Minimize"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <TextBlock Style="{StaticResource WebdingsTextBlock}">0</TextBlock>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ <Style TargetType="Button" x:Key="MaximizeApplicationButton" BasedOn="{StaticResource WebdingsButton}">
+ <Setter Property="ToolTip" Value="Maximize"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <TextBlock Style="{StaticResource WebdingsTextBlock}">1</TextBlock>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding Path=WindowState, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="Maximized">
+ <Setter Property="Visibility" Value="Collapsed" />
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+
+ <Style TargetType="Button" x:Key="UndoMaximizeApplicationButton" BasedOn="{StaticResource WebdingsButton}">
+ <Setter Property="Visibility" Value="Collapsed"/>
+ <Setter Property="ToolTip" Value="Restore"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <TextBlock Style="{StaticResource WebdingsTextBlock}">2</TextBlock>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding Path=WindowState, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Value="Maximized">
+ <Setter Property="Visibility" Value="Visible" />
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+
+ <Style TargetType="Button" x:Key="CloseApplicationButton" BasedOn="{StaticResource WebdingsButton}">
+ <Setter Property="ToolTip" Value="Close"/>
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate>
+ <TextBlock Style="{StaticResource WebdingsTextBlock}">r</TextBlock>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+
+ </UserControl.Resources>
+
+ <StackPanel Style="{StaticResource WindowCommandsPanel}">
+ <Button x:Name="MinimizeApplicationButton" Style="{StaticResource MinimizeApplicationButton}">
+ </Button>
+ <Button x:Name="MaximizeApplicationButton" Style="{StaticResource MaximizeApplicationButton}">
+ </Button>
+ <Button x:Name="UndoMaximizeApplicationButton" Style="{StaticResource UndoMaximizeApplicationButton}"></Button>
+ <Button x:Name="CloseApplicationButton" Style="{StaticResource CloseApplicationButton}"></Button>
+ </StackPanel>
+
+</UserControl>
diff --git a/MediaBrowser.UI/Controls/WindowCommands.xaml.cs b/MediaBrowser.UI/Controls/WindowCommands.xaml.cs
index 1810c5bf3f..e285cced12 100644
--- a/MediaBrowser.UI/Controls/WindowCommands.xaml.cs
+++ b/MediaBrowser.UI/Controls/WindowCommands.xaml.cs
@@ -1,50 +1,82 @@
-using System.Windows;
-using System.Windows.Controls;
-
-namespace MediaBrowser.UI.Controls
-{
- /// <summary>
- /// Interaction logic for WindowCommands.xaml
- /// </summary>
- public partial class WindowCommands : UserControl
- {
- public Window ParentWindow
- {
- get { return TreeHelper.TryFindParent<Window>(this); }
- }
-
- public WindowCommands()
- {
- InitializeComponent();
- Loaded += WindowCommandsLoaded;
- }
-
- void WindowCommandsLoaded(object sender, RoutedEventArgs e)
- {
- CloseApplicationButton.Click += CloseApplicationButtonClick;
- MinimizeApplicationButton.Click += MinimizeApplicationButtonClick;
- MaximizeApplicationButton.Click += MaximizeApplicationButtonClick;
- UndoMaximizeApplicationButton.Click += UndoMaximizeApplicationButtonClick;
- }
-
- void UndoMaximizeApplicationButtonClick(object sender, RoutedEventArgs e)
- {
- ParentWindow.WindowState = WindowState.Normal;
- }
-
- void MaximizeApplicationButtonClick(object sender, RoutedEventArgs e)
- {
- ParentWindow.WindowState = WindowState.Maximized;
- }
-
- void MinimizeApplicationButtonClick(object sender, RoutedEventArgs e)
- {
- ParentWindow.WindowState = WindowState.Minimized;
- }
-
- void CloseApplicationButtonClick(object sender, RoutedEventArgs e)
- {
- ParentWindow.Close();
- }
- }
-}
+using System.Windows;
+using System.Windows.Controls;
+
+namespace MediaBrowser.UI.Controls
+{
+ /// <summary>
+ /// Interaction logic for WindowCommands.xaml
+ /// </summary>
+ public partial class WindowCommands : UserControl
+ {
+ /// <summary>
+ /// Gets the parent window.
+ /// </summary>
+ /// <value>The parent window.</value>
+ public Window ParentWindow
+ {
+ get { return TreeHelper.TryFindParent<Window>(this); }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="WindowCommands" /> class.
+ /// </summary>
+ public WindowCommands()
+ {
+ InitializeComponent();
+ Loaded += WindowCommandsLoaded;
+ }
+
+ /// <summary>
+ /// Windows the commands loaded.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ void WindowCommandsLoaded(object sender, RoutedEventArgs e)
+ {
+ CloseApplicationButton.Click += CloseApplicationButtonClick;
+ MinimizeApplicationButton.Click += MinimizeApplicationButtonClick;
+ MaximizeApplicationButton.Click += MaximizeApplicationButtonClick;
+ UndoMaximizeApplicationButton.Click += UndoMaximizeApplicationButtonClick;
+ }
+
+ /// <summary>
+ /// Undoes the maximize application button click.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ void UndoMaximizeApplicationButtonClick(object sender, RoutedEventArgs e)
+ {
+ ParentWindow.WindowState = WindowState.Normal;
+ }
+
+ /// <summary>
+ /// Maximizes the application button click.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ void MaximizeApplicationButtonClick(object sender, RoutedEventArgs e)
+ {
+ ParentWindow.WindowState = WindowState.Maximized;
+ }
+
+ /// <summary>
+ /// Minimizes the application button click.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ void MinimizeApplicationButtonClick(object sender, RoutedEventArgs e)
+ {
+ ParentWindow.WindowState = WindowState.Minimized;
+ }
+
+ /// <summary>
+ /// Closes the application button click.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param>
+ void CloseApplicationButtonClick(object sender, RoutedEventArgs e)
+ {
+ App.Instance.Shutdown();
+ }
+ }
+}