diff options
Diffstat (limited to 'MediaBrowser.Plugins.DefaultTheme/Controls')
23 files changed, 1627 insertions, 0 deletions
diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml new file mode 100644 index 000000000..a66b1c403 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml @@ -0,0 +1,23 @@ +<controls:BaseUserControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.BaseItemTile" + 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="mainGrid" HorizontalAlignment="Center"> + + <Border x:Name="border"> + <Image x:Name="image" Stretch="Uniform"></Image> + </Border> + + <Grid HorizontalAlignment="Stretch" VerticalAlignment="Bottom"> + <Grid.Background> + <SolidColorBrush Color="#A6000000"></SolidColorBrush> + </Grid.Background> + <TextBlock x:Name="txtName" Margin="10 5 0 10" Foreground="White" TextWrapping="Wrap" Style="{StaticResource TextBlockStyle}"></TextBlock> + </Grid> + </Grid> +</controls:BaseUserControl> diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml.cs new file mode 100644 index 000000000..7789584ed --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/BaseItemTile.xaml.cs @@ -0,0 +1,177 @@ +using MediaBrowser.Model.DTO; +using MediaBrowser.Model.Net; +using MediaBrowser.UI; +using MediaBrowser.UI.Controls; +using MediaBrowser.UI.Converters; +using MediaBrowser.UI.ViewModels; +using System; +using System.ComponentModel; +using System.Windows; + +namespace MediaBrowser.Plugins.DefaultTheme.Controls +{ + /// <summary> + /// Interaction logic for BaseItemTile.xaml + /// </summary> + public partial class BaseItemTile : BaseUserControl + { + /// <summary> + /// Gets the view model. + /// </summary> + /// <value>The view model.</value> + public DtoBaseItemViewModel ViewModel + { + get { return DataContext as DtoBaseItemViewModel; } + } + + /// <summary> + /// Gets the item. + /// </summary> + /// <value>The item.</value> + private DtoBaseItem Item + { + get { return ViewModel.Item; } + } + + /// <summary> + /// Initializes a new instance of the <see cref="BaseItemTile" /> class. + /// </summary> + public BaseItemTile() + { + InitializeComponent(); + + DataContextChanged += BaseItemTile_DataContextChanged; + Loaded += BaseItemTile_Loaded; + Unloaded += BaseItemTile_Unloaded; + } + + /// <summary> + /// Handles the Unloaded event of the BaseItemTile 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 BaseItemTile_Unloaded(object sender, RoutedEventArgs e) + { + if (ViewModel != null) + { + ViewModel.PropertyChanged -= ViewModel_PropertyChanged; + } + } + + /// <summary> + /// Handles the Loaded event of the BaseItemTile 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 BaseItemTile_Loaded(object sender, RoutedEventArgs e) + { + if (ViewModel != null) + { + ViewModel.PropertyChanged -= ViewModel_PropertyChanged; + ViewModel.PropertyChanged += ViewModel_PropertyChanged; + } + } + + /// <summary> + /// Handles the DataContextChanged event of the BaseItemTile control. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs" /> instance containing the event data.</param> + void BaseItemTile_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) + { + OnItemChanged(); + + if (ViewModel != null) + { + ViewModel.PropertyChanged -= ViewModel_PropertyChanged; + ViewModel.PropertyChanged += ViewModel_PropertyChanged; + } + } + + /// <summary> + /// Handles the PropertyChanged event of the ViewModel control. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="PropertyChangedEventArgs" /> instance containing the event data.</param> + void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + ReloadImage(); + } + + /// <summary> + /// Called when [item changed]. + /// </summary> + private void OnItemChanged() + { + ReloadImage(); + + var visibility = Item.HasPrimaryImage && !Item.IsType("Episode") ? Visibility.Collapsed : Visibility.Visible; + + if (Item.IsType("Person") || Item.IsType("IndexFolder")) + { + visibility = Visibility.Visible; + } + + txtName.Visibility = visibility; + + var name = Item.Name; + + if (Item.IndexNumber.HasValue) + { + name = Item.IndexNumber + " - " + name; + } + + txtName.Text = name; + } + + /// <summary> + /// Reloads the image. + /// </summary> + private async void ReloadImage() + { + mainGrid.Height = ViewModel.ParentDisplayPreferences.PrimaryImageHeight; + mainGrid.Width = ViewModel.ParentDisplayPreferences.PrimaryImageWidth; + + if (Item.HasPrimaryImage) + { + var url = ViewModel.GetImageUrl(ViewModel.ParentDisplayPreferences.PrimaryImageType); + + border.Background = null; + + try + { + image.Source = await App.Instance.GetRemoteBitmapAsync(url); + } + catch (HttpException) + { + SetDefaultImage(); + } + } + else + { + SetDefaultImage(); + } + } + + /// <summary> + /// Sets the default image. + /// </summary> + private void SetDefaultImage() + { + if (Item.IsAudio || Item.IsType("MusicAlbum") || Item.IsType("MusicArtist")) + { + var imageUri = new Uri("../Resources/Images/AudioDefault.png", UriKind.Relative); + + border.Background = MetroTileBackgroundConverter.GetRandomBackground(); + image.Source = App.Instance.GetBitmapImage(imageUri); + } + else + { + var imageUri = new Uri("../Resources/Images/VideoDefault.png", UriKind.Relative); + + border.Background = MetroTileBackgroundConverter.GetRandomBackground(); + image.Source = App.Instance.GetBitmapImage(imageUri); + } + } + } +} diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/BaseDetailsControl.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/BaseDetailsControl.cs new file mode 100644 index 000000000..66dbb9c98 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/BaseDetailsControl.cs @@ -0,0 +1,44 @@ +using MediaBrowser.Model.DTO; +using MediaBrowser.UI.Controls; + +namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details +{ + /// <summary> + /// Class BaseDetailsControl + /// </summary> + public abstract class BaseDetailsControl : BaseUserControl + { + /// <summary> + /// Initializes a new instance of the <see cref="BaseDetailsControl" /> class. + /// </summary> + protected BaseDetailsControl() + { + DataContext = this; + } + + /// <summary> + /// The _item + /// </summary> + private DtoBaseItem _item; + /// <summary> + /// Gets or sets the item. + /// </summary> + /// <value>The item.</value> + public DtoBaseItem Item + { + get { return _item; } + + set + { + _item = value; + OnPropertyChanged("Item"); + OnItemChanged(); + } + } + + /// <summary> + /// Called when [item changed]. + /// </summary> + protected abstract void OnItemChanged(); + } +} diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml new file mode 100644 index 000000000..4282316b4 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml @@ -0,0 +1,23 @@ +<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemChapters" + 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:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details" + xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls" + mc:Ignorable="d" + d:DesignHeight="300" d:DesignWidth="300"> + <Grid> + <controls:ExtendedScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Disabled" CanContentScroll="True"> + <controls:ScrollingPanel CanHorizontallyScroll="True" CanVerticallyScroll="False"> + <controls:ExtendedListBox x:Name="lstItems" HorizontalAlignment="Center" VerticalAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemTemplate="{StaticResource ItemChaptersTemplate}" Style="{StaticResource ListBoxStyle}" ItemContainerStyle="{StaticResource ListBoxItemStyle}"> + <controls:ExtendedListBox.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel Orientation="Vertical" Margin="50" /> + </ItemsPanelTemplate> + </controls:ExtendedListBox.ItemsPanel> + </controls:ExtendedListBox> + </controls:ScrollingPanel> + </controls:ExtendedScrollViewer> + </Grid> +</details:BaseDetailsControl> diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml.cs new file mode 100644 index 000000000..196b92b69 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemChapters.xaml.cs @@ -0,0 +1,67 @@ +using MediaBrowser.Model.DTO; +using MediaBrowser.UI.Controller; +using MediaBrowser.UI.Controls; +using MediaBrowser.UI.Playback; +using MediaBrowser.UI.ViewModels; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details +{ + /// <summary> + /// Interaction logic for ItemChapters.xaml + /// </summary> + public partial class ItemChapters : BaseDetailsControl + { + /// <summary> + /// Initializes a new instance of the <see cref="ItemChapters" /> class. + /// </summary> + public ItemChapters() + { + InitializeComponent(); + + lstItems.ItemInvoked += lstItems_ItemInvoked; + } + + /// <summary> + /// LSTs the items_ item invoked. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="e">The e.</param> + void lstItems_ItemInvoked(object sender, ItemEventArgs<object> e) + { + var chapterViewModel = (ChapterInfoDtoViewModel) e.Argument; + + UIKernel.Instance.PlaybackManager.Play(new PlayOptions + { + Items = new List<DtoBaseItem> { Item }, + StartPositionTicks = chapterViewModel.Chapter.StartPositionTicks + }); + } + + /// <summary> + /// Called when [item changed]. + /// </summary> + protected override void OnItemChanged() + { + const double height = 297; + + var width = ChapterInfoDtoViewModel.GetChapterImageWidth(Item, height, 528); + + var chapters = Item.Chapters ?? new List<ChapterInfoDto> { }; + + lstItems.ItemsSource = new ObservableCollection<ChapterInfoDtoViewModel>(chapters.Select(i => new ChapterInfoDtoViewModel + { + Item = Item, + Chapter = i, + ImageWidth = width, + ImageHeight = height, + ImageDownloadOptions = new ImageOptions + { + MaxHeight = 400 + } + })); + } + } +} diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml new file mode 100644 index 000000000..312742558 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml @@ -0,0 +1,23 @@ +<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemGallery" + 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:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details" + xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls" + mc:Ignorable="d" + d:DesignHeight="300" d:DesignWidth="300"> + <Grid> + <controls:ExtendedScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Disabled" CanContentScroll="True"> + <controls:ScrollingPanel CanHorizontallyScroll="True" CanVerticallyScroll="False"> + <controls:ExtendedListBox VerticalAlignment="Top" HorizontalAlignment="Center" x:Name="lstItems" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemTemplate="{StaticResource ItemGalleryTemplate}" Style="{StaticResource ListBoxStyle}" ItemContainerStyle="{StaticResource ListBoxItemStyle}"> + <controls:ExtendedListBox.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel Orientation="Vertical" Margin="50" /> + </ItemsPanelTemplate> + </controls:ExtendedListBox.ItemsPanel> + </controls:ExtendedListBox> + </controls:ScrollingPanel> + </controls:ExtendedScrollViewer> + </Grid> +</details:BaseDetailsControl> diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml.cs new file mode 100644 index 000000000..d0fa85bf2 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemGallery.xaml.cs @@ -0,0 +1,163 @@ +using MediaBrowser.Model.DTO; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Net; +using MediaBrowser.UI; +using MediaBrowser.UI.Controller; +using MediaBrowser.UI.Controls; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; + +namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details +{ + /// <summary> + /// Interaction logic for ItemGallery.xaml + /// </summary> + public partial class ItemGallery : BaseDetailsControl + { + /// <summary> + /// Initializes a new instance of the <see cref="ItemGallery" /> class. + /// </summary> + public ItemGallery() + : base() + { + InitializeComponent(); + lstItems.ItemInvoked += lstItems_ItemInvoked; + } + + /// <summary> + /// LSTs the items_ item invoked. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="e">The e.</param> + void lstItems_ItemInvoked(object sender, ItemEventArgs<object> e) + { + var img = (BitmapImage)e.Argument; + + var index = Images.IndexOf(img); + + //App.Instance.OpenImageViewer(new Uri(ImageUrls[index]), Item.Name); + } + + /// <summary> + /// The _images + /// </summary> + private List<BitmapImage> _images; + /// <summary> + /// Gets or sets the images. + /// </summary> + /// <value>The images.</value> + public List<BitmapImage> Images + { + get { return _images; } + set + { + _images = value; + lstItems.ItemsSource = value; + OnPropertyChanged("Images"); + } + } + + /// <summary> + /// Gets or sets the image urls. + /// </summary> + /// <value>The image urls.</value> + private List<string> ImageUrls { get; set; } + + /// <summary> + /// Called when [item changed]. + /// </summary> + protected override async void OnItemChanged() + { + ImageUrls = GetImages(Item); + + var tasks = ImageUrls.Select(GetImage); + + var results = await Task.WhenAll(tasks); + + Images = results.Where(i => i != null).ToList(); + } + + /// <summary> + /// Gets the image. + /// </summary> + /// <param name="url">The URL.</param> + /// <returns>Task{BitmapImage}.</returns> + private async Task<BitmapImage> GetImage(string url) + { + try + { + return await App.Instance.GetRemoteBitmapAsync(url); + } + catch (HttpException) + { + return null; + } + } + + /// <summary> + /// Gets the images. + /// </summary> + /// <param name="item">The item.</param> + /// <returns>List{System.String}.</returns> + internal static List<string> GetImages(DtoBaseItem item) + { + var images = new List<string> { }; + + if (item.BackdropCount > 0) + { + for (var i = 0; i < item.BackdropCount; i++) + { + images.Add(UIKernel.Instance.ApiClient.GetImageUrl(item, new ImageOptions + { + ImageType = ImageType.Backdrop, + ImageIndex = i + })); + } + } + + if (item.HasThumb) + { + images.Add(UIKernel.Instance.ApiClient.GetImageUrl(item, new ImageOptions + { + ImageType = ImageType.Thumb + })); + } + + if (item.HasArtImage) + { + images.Add(UIKernel.Instance.ApiClient.GetImageUrl(item, new ImageOptions + { + ImageType = ImageType.Art + })); + } + + if (item.HasDiscImage) + { + images.Add(UIKernel.Instance.ApiClient.GetImageUrl(item, new ImageOptions + { + ImageType = ImageType.Disc + })); + } + + if (item.HasMenuImage) + { + images.Add(UIKernel.Instance.ApiClient.GetImageUrl(item, new ImageOptions + { + ImageType = ImageType.Menu + })); + } + + if (item.HasBoxImage) + { + images.Add(UIKernel.Instance.ApiClient.GetImageUrl(item, new ImageOptions + { + ImageType = ImageType.Box + })); + } + + return images; + } + } +} diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml new file mode 100644 index 000000000..0cae37a35 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml @@ -0,0 +1,22 @@ +<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemMediaInfo" + 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:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details" + mc:Ignorable="d" + d:DesignHeight="300" d:DesignWidth="300"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="auto"></RowDefinition> + <RowDefinition Height="auto"></RowDefinition> + <RowDefinition Height="*"></RowDefinition> + </Grid.RowDefinitions> + + <TextBlock Style="{StaticResource TextBlockStyle}" Grid.Row="0" x:Name="TxtPath"></TextBlock> + + <TextBlock Style="{StaticResource TextBlockStyle}" Grid.Row="1" Margin="0 20 0 0" x:Name="TxtVideoFormat"></TextBlock> + + <StackPanel Orientation="Vertical" x:Name="MediaStreams" Grid.Row="2" Margin="0 20 0 0"></StackPanel> + </Grid> +</details:BaseDetailsControl> diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml.cs new file mode 100644 index 000000000..3912093c7 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemMediaInfo.xaml.cs @@ -0,0 +1,49 @@ +using MediaBrowser.Model.Entities; +using System.Collections.Generic; +using System.Windows; + +namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details +{ + /// <summary> + /// Interaction logic for ItemMediaInfo.xaml + /// </summary> + public partial class ItemMediaInfo : BaseDetailsControl + { + /// <summary> + /// Initializes a new instance of the <see cref="ItemMediaInfo" /> class. + /// </summary> + public ItemMediaInfo() + { + InitializeComponent(); + } + + /// <summary> + /// Called when [item changed]. + /// </summary> + protected override void OnItemChanged() + { + MediaStreams.Children.Clear(); + + TxtPath.Text = Item.Path; + + if (Item.VideoFormat.HasValue && Item.VideoFormat.Value != VideoFormat.Standard) + { + TxtVideoFormat.Visibility = Visibility.Visible; + + TxtVideoFormat.Text = Item.VideoFormat.Value == VideoFormat.Digital3D ? "Digital 3D" : "SBS 3D"; + } + else + { + TxtVideoFormat.Visibility = Visibility.Collapsed; + } + + foreach (var stream in Item.MediaStreams ?? new List<MediaStream> {}) + { + MediaStreams.Children.Add(new MediaStreamControl + { + MediaStream = stream + }); + } + } + } +} diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml new file mode 100644 index 000000000..32e16ce9d --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml @@ -0,0 +1,68 @@ +<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemOverview" + 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:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details" + mc:Ignorable="d" + d:DesignHeight="300" d:DesignWidth="300"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="auto"></RowDefinition> + <RowDefinition Height="auto"></RowDefinition> + <RowDefinition Height="auto"></RowDefinition> + <RowDefinition Height="auto"></RowDefinition> + <RowDefinition Height="auto"></RowDefinition> + <RowDefinition Height="auto"></RowDefinition> + <RowDefinition Height="auto"></RowDefinition> + <RowDefinition Height="*"></RowDefinition> + </Grid.RowDefinitions> + + <StackPanel Orientation="Horizontal" Grid.Row="0" x:Name="PnlAlbum" Visibility="Collapsed"> + + <TextBlock Style="{StaticResource TextBlockStyle}" Width="250" Text="album"></TextBlock> + <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="Album"></TextBlock> + </StackPanel> + + <StackPanel Orientation="Horizontal" Grid.Row="1" x:Name="PnlArtist" Visibility="Collapsed"> + + <TextBlock Style="{StaticResource TextBlockStyle}" Width="250" Text="artist"></TextBlock> + <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="Artist"></TextBlock> + </StackPanel> + + <StackPanel Orientation="Horizontal" Grid.Row="2" x:Name="PnlAlbumArtist" Visibility="Collapsed"> + + <TextBlock Style="{StaticResource TextBlockStyle}" Width="250" Text="album artist"></TextBlock> + <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="AlbumArtist"></TextBlock> + </StackPanel> + + <StackPanel Orientation="Horizontal" Grid.Row="3" x:Name="PnlDirectors" Visibility="Collapsed"> + + <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="DirectorLabel" Width="250"></TextBlock> + <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="Directors"></TextBlock> + </StackPanel> + + <StackPanel Orientation="Horizontal" Grid.Row="4" x:Name="PnlGenres" Visibility="Collapsed"> + + <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="GenreLabel" Width="250"></TextBlock> + <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="Genres"></TextBlock> + </StackPanel> + + <StackPanel Orientation="Horizontal" Grid.Row="5" x:Name="PnlStudios" Visibility="Collapsed"> + + <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="StudiosLabel" Width="250"></TextBlock> + <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="Studios"></TextBlock> + </StackPanel> + + <StackPanel Orientation="Horizontal" Grid.Row="6" x:Name="PnlPremiereDate" Visibility="Collapsed"> + + <TextBlock Style="{StaticResource TextBlockStyle}" Width="250" Text="premiere date"></TextBlock> + <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="PremiereDate"></TextBlock> + </StackPanel> + + <Grid Grid.Row="7"> + + <TextBlock Style="{StaticResource TextBlockStyle}" x:Name="Overview" Margin="0 20 0 0"></TextBlock> + </Grid> + </Grid> +</details:BaseDetailsControl> diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml.cs new file mode 100644 index 000000000..1654c2c7b --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemOverview.xaml.cs @@ -0,0 +1,109 @@ +using MediaBrowser.Model.DTO; +using System; +using System.Linq; +using System.Windows; + +namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details +{ + /// <summary> + /// Interaction logic for ItemOverview.xaml + /// </summary> + public partial class ItemOverview : BaseDetailsControl + { + /// <summary> + /// Initializes a new instance of the <see cref="ItemOverview" /> class. + /// </summary> + public ItemOverview() + : base() + { + InitializeComponent(); + } + + /// <summary> + /// Called when [item changed]. + /// </summary> + protected override void OnItemChanged() + { + var directors = (Item.People ?? new BaseItemPerson[] { }).Where(p => string.Equals(p.Type, "director", StringComparison.OrdinalIgnoreCase)).ToList(); + + if (directors.Count > 0) + { + PnlDirectors.Visibility = Visibility.Visible; + + Directors.Text = string.Join(" / ", directors.Take(3).Select(d => d.Name).ToArray()); + DirectorLabel.Text = directors.Count > 1 ? "directors" : "director"; + } + else + { + PnlDirectors.Visibility = Visibility.Collapsed; + } + + if (Item.Genres != null && Item.Genres.Count > 0) + { + PnlGenres.Visibility = Visibility.Visible; + + Genres.Text = string.Join(" / ", Item.Genres.Take(4).ToArray()); + GenreLabel.Text = Item.Genres.Count > 1 ? "genres" : "genre"; + } + else + { + PnlGenres.Visibility = Visibility.Collapsed; + } + + if (Item.Studios != null && Item.Studios.Count > 0) + { + PnlStudios.Visibility = Visibility.Visible; + + Studios.Text = string.Join(" / ", Item.Studios.Take(3).ToArray()); + StudiosLabel.Text = Item.Studios.Count > 1 ? "studios" : "studio"; + } + else + { + PnlStudios.Visibility = Visibility.Collapsed; + } + + if (Item.PremiereDate.HasValue) + { + PnlPremiereDate.Visibility = Visibility.Visible; + + PremiereDate.Text = Item.PremiereDate.Value.ToShortDateString(); + } + else + { + PnlPremiereDate.Visibility = Visibility.Collapsed; + } + + if (!string.IsNullOrEmpty(Item.Artist)) + { + PnlArtist.Visibility = Visibility.Visible; + Artist.Text = Item.Artist; + } + else + { + PnlArtist.Visibility = Visibility.Collapsed; + } + + if (!string.IsNullOrEmpty(Item.Album)) + { + PnlAlbum.Visibility = Visibility.Visible; + Album.Text = Item.Artist; + } + else + { + PnlAlbum.Visibility = Visibility.Collapsed; + } + + if (!string.IsNullOrEmpty(Item.AlbumArtist)) + { + PnlAlbumArtist.Visibility = Visibility.Visible; + AlbumArtist.Text = Item.Artist; + } + else + { + PnlAlbumArtist.Visibility = Visibility.Collapsed; + } + + Overview.Text = Item.Overview; + } + } +} diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml new file mode 100644 index 000000000..6e2bc9f57 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml @@ -0,0 +1,23 @@ +<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemPerformers" + 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:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details" + xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls" + mc:Ignorable="d" + d:DesignHeight="300" d:DesignWidth="300"> + <Grid> + <controls:ExtendedScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Disabled" CanContentScroll="True"> + <controls:ScrollingPanel CanHorizontallyScroll="False" CanVerticallyScroll="True"> + <controls:ExtendedListBox VerticalAlignment="Center" x:Name="lstItems" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding Path=People}" ItemTemplate="{StaticResource ItemPerformersTemplate}" Style="{StaticResource ListBoxStyle}" ItemContainerStyle="{StaticResource ListBoxItemStyle}"> + <controls:ExtendedListBox.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel Orientation="Vertical" Margin="50" /> + </ItemsPanelTemplate> + </controls:ExtendedListBox.ItemsPanel> + </controls:ExtendedListBox> + </controls:ScrollingPanel> + </controls:ExtendedScrollViewer> + </Grid> +</details:BaseDetailsControl> diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml.cs new file mode 100644 index 000000000..9ad5fdcac --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemPerformers.xaml.cs @@ -0,0 +1,72 @@ +using MediaBrowser.Model.DTO; +using MediaBrowser.UI; +using MediaBrowser.UI.Controller; +using MediaBrowser.UI.ViewModels; +using System.Collections.ObjectModel; + +namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details +{ + /// <summary> + /// Interaction logic for ItemPerformers.xaml + /// </summary> + public partial class ItemPerformers : BaseDetailsControl + { + /// <summary> + /// Initializes a new instance of the <see cref="ItemPerformers" /> class. + /// </summary> + public ItemPerformers() + { + InitializeComponent(); + } + + /// <summary> + /// The _itemsResult + /// </summary> + private ItemsResult _itemsResult; + /// <summary> + /// Gets or sets the children of the Folder being displayed + /// </summary> + /// <value>The children.</value> + public ItemsResult ItemsResult + { + get { return _itemsResult; } + + private set + { + _itemsResult = value; + OnPropertyChanged("ItemsResult"); + + Items = DtoBaseItemViewModel.GetObservableItems(ItemsResult.Items); + } + } + + /// <summary> + /// The _display children + /// </summary> + private ObservableCollection<DtoBaseItemViewModel> _items; + /// <summary> + /// Gets the actual children that should be displayed. + /// Subclasses should bind to this, not ItemsResult. + /// </summary> + /// <value>The display children.</value> + public ObservableCollection<DtoBaseItemViewModel> Items + { + get { return _items; } + + private set + { + _items = value; + //lstItems.ItemsSource = value; + OnPropertyChanged("Items"); + } + } + + /// <summary> + /// Called when [item changed]. + /// </summary> + protected override async void OnItemChanged() + { + ItemsResult = await UIKernel.Instance.ApiClient.GetAllPeopleAsync(App.Instance.CurrentUser.Id, itemId: Item.Id); + } + } +} diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml new file mode 100644 index 000000000..09d64612e --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml @@ -0,0 +1,23 @@ +<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemSpecialFeatures" + 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:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details" + xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls" + mc:Ignorable="d" + d:DesignHeight="300" d:DesignWidth="300"> + <Grid> + <controls:ExtendedScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Disabled" CanContentScroll="True"> + <controls:ScrollingPanel CanHorizontallyScroll="True" CanVerticallyScroll="False"> + <controls:ExtendedListBox x:Name="lstItems" HorizontalAlignment="Center" VerticalAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemTemplate="{StaticResource ItemSpecialFeaturesTemplate}" Style="{StaticResource ListBoxStyle}" ItemContainerStyle="{StaticResource ListBoxItemStyle}"> + <controls:ExtendedListBox.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel Orientation="Vertical" Margin="50" /> + </ItemsPanelTemplate> + </controls:ExtendedListBox.ItemsPanel> + </controls:ExtendedListBox> + </controls:ScrollingPanel> + </controls:ExtendedScrollViewer> + </Grid> +</details:BaseDetailsControl> diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml.cs new file mode 100644 index 000000000..46b9ac311 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemSpecialFeatures.xaml.cs @@ -0,0 +1,77 @@ +using MediaBrowser.Model.DTO; +using MediaBrowser.Model.Net; +using MediaBrowser.UI; +using MediaBrowser.UI.Controller; +using MediaBrowser.UI.Controls; +using MediaBrowser.UI.Playback; +using MediaBrowser.UI.ViewModels; +using System.Collections.Generic; +using System.Linq; + +namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details +{ + /// <summary> + /// Interaction logic for ItemSpecialFeatures.xaml + /// </summary> + public partial class ItemSpecialFeatures : BaseDetailsControl + { + /// <summary> + /// Initializes a new instance of the <see cref="ItemSpecialFeatures" /> class. + /// </summary> + public ItemSpecialFeatures() + { + InitializeComponent(); + + lstItems.ItemInvoked += lstItems_ItemInvoked; + } + + /// <summary> + /// LSTs the items_ item invoked. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="e">The e.</param> + void lstItems_ItemInvoked(object sender, ItemEventArgs<object> e) + { + var viewModel = (SpecialFeatureViewModel) e.Argument; + + UIKernel.Instance.PlaybackManager.Play(new PlayOptions + { + Items = new List<DtoBaseItem> { viewModel.Item } + }); + } + + /// <summary> + /// Called when [item changed]. + /// </summary> + protected override async void OnItemChanged() + { + DtoBaseItem[] result; + + try + { + result = await UIKernel.Instance.ApiClient.GetSpecialFeaturesAsync(App.Instance.CurrentUser.Id, Item.Id); + } + catch (HttpException) + { + App.Instance.ShowDefaultErrorMessage(); + + return; + } + + var resultItems = result ?? new DtoBaseItem[] { }; + + const int height = 297; + var aspectRatio = DtoBaseItemViewModel.GetAveragePrimaryImageAspectRatio(resultItems); + + var width = aspectRatio == 0 ? 528 : height * aspectRatio; + + lstItems.ItemsSource = resultItems.Select(i => new SpecialFeatureViewModel + { + Item = i, + ImageHeight = height, + ImageWidth = width + + }).ToList(); + } + } +} diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml new file mode 100644 index 000000000..129885271 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml @@ -0,0 +1,23 @@ +<details:BaseDetailsControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.ItemTrailers" + 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:details="clr-namespace:MediaBrowser.Plugins.DefaultTheme.Controls.Details" + xmlns:controls="clr-namespace:MediaBrowser.UI.Controls;assembly=MediaBrowser.UI.Controls" + mc:Ignorable="d" + d:DesignHeight="300" d:DesignWidth="300"> + <Grid> + <controls:ExtendedScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Disabled" CanContentScroll="True"> + <controls:ScrollingPanel CanHorizontallyScroll="True" CanVerticallyScroll="False"> + <controls:ExtendedListBox x:Name="lstItems" HorizontalAlignment="Center" VerticalAlignment="Top" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemTemplate="{StaticResource ItemSpecialFeaturesTemplate}" Style="{StaticResource ListBoxStyle}" ItemContainerStyle="{StaticResource ListBoxItemStyle}"> + <controls:ExtendedListBox.ItemsPanel> + <ItemsPanelTemplate> + <WrapPanel Orientation="Vertical" Margin="50" /> + </ItemsPanelTemplate> + </controls:ExtendedListBox.ItemsPanel> + </controls:ExtendedListBox> + </controls:ScrollingPanel> + </controls:ExtendedScrollViewer> + </Grid> +</details:BaseDetailsControl> diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml.cs new file mode 100644 index 000000000..e8134b634 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/ItemTrailers.xaml.cs @@ -0,0 +1,82 @@ +using MediaBrowser.Model.DTO; +using MediaBrowser.Model.Net; +using MediaBrowser.UI; +using MediaBrowser.UI.Controller; +using MediaBrowser.UI.Controls; +using MediaBrowser.UI.Playback; +using MediaBrowser.UI.ViewModels; +using System.Collections.Generic; +using System.Linq; + +namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details +{ + /// <summary> + /// Interaction logic for ItemTrailers.xaml + /// </summary> + public partial class ItemTrailers : BaseDetailsControl + { + /// <summary> + /// Initializes a new instance of the <see cref="ItemSpecialFeatures" /> class. + /// </summary> + public ItemTrailers() + { + InitializeComponent(); + + lstItems.ItemInvoked += lstItems_ItemInvoked; + } + + /// <summary> + /// LSTs the items_ item invoked. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="e">The e.</param> + void lstItems_ItemInvoked(object sender, ItemEventArgs<object> e) + { + var viewModel = (SpecialFeatureViewModel)e.Argument; + + UIKernel.Instance.PlaybackManager.Play(new PlayOptions + { + Items = new List<DtoBaseItem> { viewModel.Item } + }); + } + + /// <summary> + /// Called when [item changed]. + /// </summary> + protected override async void OnItemChanged() + { + DtoBaseItem[] result; + + try + { + result = await UIKernel.Instance.ApiClient.GetLocalTrailersAsync(App.Instance.CurrentUser.Id, Item.Id); + } + catch (HttpException) + { + App.Instance.ShowDefaultErrorMessage(); + + return; + } + + var resultItems = result ?? new DtoBaseItem[] { }; + + const int height = 297; + var aspectRatio = DtoBaseItemViewModel.GetAveragePrimaryImageAspectRatio(resultItems); + + var width = aspectRatio == 0 ? 528 : height * aspectRatio; + + if (Item.TrailerUrls != null) + { + //resultItems.AddRange(Item.TrailerUrls.Select(i => UIKernel.Instance.PlaybackManager.GetPlayableItem(new Uri(i), "Trailer"))); + } + + lstItems.ItemsSource = resultItems.Select(i => new SpecialFeatureViewModel + { + Item = i, + ImageHeight = height, + ImageWidth = width + + }).ToList(); + } + } +} diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml new file mode 100644 index 000000000..e841693fe --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml @@ -0,0 +1,18 @@ +<controls:BaseUserControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.Details.MediaStreamControl" + 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> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="150"></ColumnDefinition> + <ColumnDefinition Width="*"></ColumnDefinition> + </Grid.ColumnDefinitions> + + <TextBlock Style="{StaticResource TextBlockStyle}" Grid.Column="0" x:Name="StreamName"></TextBlock> + <StackPanel Orientation="Vertical" Grid.Column="1" x:Name="StreamDetails"></StackPanel> + </Grid> +</controls:BaseUserControl> diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml.cs new file mode 100644 index 000000000..c0271cdab --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/Details/MediaStreamControl.xaml.cs @@ -0,0 +1,142 @@ +using MediaBrowser.Model.Entities; +using MediaBrowser.UI.Controls; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Windows.Controls; + +namespace MediaBrowser.Plugins.DefaultTheme.Controls.Details +{ + /// <summary> + /// Interaction logic for MediaStreamControl.xaml + /// </summary> + public partial class MediaStreamControl : BaseUserControl + { + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + /// <summary> + /// Initializes a new instance of the <see cref="MediaStreamControl" /> class. + /// </summary> + public MediaStreamControl() + { + InitializeComponent(); + } + + /// <summary> + /// The _media stream + /// </summary> + private MediaStream _mediaStream; + /// <summary> + /// Gets or sets the media stream. + /// </summary> + /// <value>The media stream.</value> + public MediaStream MediaStream + { + get { return _mediaStream; } + set + { + _mediaStream = value; + OnPropertyChanged("MediaStream"); + OnStreamChanged(); + } + } + + /// <summary> + /// Called when [stream changed]. + /// </summary> + private void OnStreamChanged() + { + if (MediaStream == null) + { + StreamName.Text = string.Empty; + StreamDetails.Children.Clear(); + return; + } + + var details = new List<string> { }; + + if (MediaStream.Type != MediaStreamType.Video) + { + AddDetail(details, MediaStream.Language); + } + + if (!string.IsNullOrEmpty(MediaStream.Path)) + { + AddDetail(details, Path.GetFileName(MediaStream.Path)); + } + + if (MediaStream.Type == MediaStreamType.Video) + { + var resolution = string.Format("{0}*{1}", MediaStream.Width, MediaStream.Height); + + AddDetail(details, resolution); + } + + AddDetail(details, MediaStream.AspectRatio); + + if (MediaStream.Type != MediaStreamType.Video) + { + if (MediaStream.IsDefault) + { + //AddDetail(details, "default"); + } + if (MediaStream.IsForced) + { + AddDetail(details, "forced"); + } + } + + AddDetail(details, MediaStream.Codec); + + if (MediaStream.Channels.HasValue) + { + AddDetail(details, MediaStream.Channels.Value.ToString(UsCulture) + "ch"); + } + + if (MediaStream.BitRate.HasValue) + { + var text = (MediaStream.BitRate.Value / 1000).ToString(UsCulture) + "kbps"; + + AddDetail(details, text); + } + + var framerate = MediaStream.AverageFrameRate ?? MediaStream.RealFrameRate ?? 0; + + if (framerate > 0) + { + AddDetail(details, framerate.ToString(UsCulture)); + } + + if (MediaStream.SampleRate.HasValue) + { + AddDetail(details, MediaStream.SampleRate.Value.ToString(UsCulture) + "khz"); + } + + AddDetail(string.Join(" \u2022 ", details.ToArray())); + + StreamName.Text = MediaStream.Type.ToString(); + } + + private void AddDetail(string text) + { + if (string.IsNullOrEmpty(text)) + { + return; + } + + var control = new TextBlock() { Text = text }; + control.SetResourceReference(StyleProperty, "TextBlockStyle"); + StreamDetails.Children.Add(control); + } + + private void AddDetail(ICollection<string> list, string text) + { + if (string.IsNullOrEmpty(text)) + { + return; + } + + list.Add(text); + } + } +} diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml new file mode 100644 index 000000000..8de68eff9 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml @@ -0,0 +1,22 @@ +<controls:BaseUserControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.HomePageTile" + 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 HorizontalAlignment="Left" Width="400" Height="225"> + + <Border Background="{Binding Converter={StaticResource MetroTileBackgroundConverter}}"> + <Image x:Name="image" Stretch="Uniform"></Image> + </Border> + + <Grid HorizontalAlignment="Stretch" VerticalAlignment="Bottom"> + <Grid.Background> + <SolidColorBrush Color="#A6000000"></SolidColorBrush> + </Grid.Background> + <TextBlock Margin="10 5 0 10" Foreground="White" Text="{Binding Path=Item.Name}" TextWrapping="Wrap"></TextBlock> + </Grid> + </Grid> +</controls:BaseUserControl> diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml.cs new file mode 100644 index 000000000..a8e238681 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/HomePageTile.xaml.cs @@ -0,0 +1,128 @@ +using MediaBrowser.Model.DTO; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Net; +using MediaBrowser.UI; +using MediaBrowser.UI.Controls; +using MediaBrowser.UI.ViewModels; +using System; +using System.Windows; + +namespace MediaBrowser.Plugins.DefaultTheme.Controls +{ + /// <summary> + /// Interaction logic for BaseItemTile.xaml + /// </summary> + public partial class HomePageTile : BaseUserControl + { + /// <summary> + /// Gets the view model. + /// </summary> + /// <value>The view model.</value> + public DtoBaseItemViewModel ViewModel + { + get { return DataContext as DtoBaseItemViewModel; } + } + + /// <summary> + /// Gets the item. + /// </summary> + /// <value>The item.</value> + private DtoBaseItem Item + { + get { return ViewModel.Item; } + } + + /// <summary> + /// Initializes a new instance of the <see cref="HomePageTile" /> class. + /// </summary> + public HomePageTile() + { + InitializeComponent(); + + DataContextChanged += BaseItemTile_DataContextChanged; + } + + /// <summary> + /// Handles the DataContextChanged event of the BaseItemTile control. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs" /> instance containing the event data.</param> + void BaseItemTile_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) + { + OnItemChanged(); + } + + /// <summary> + /// Called when [item changed]. + /// </summary> + private void OnItemChanged() + { + ReloadImage(); + } + + /// <summary> + /// Reloads the image. + /// </summary> + private void ReloadImage() + { + if (Item.HasPrimaryImage) + { + var url = App.Instance.ApiClient.GetImageUrl(Item, new ImageOptions + { + ImageType = ImageType.Primary, + Height = 225 + }); + + SetImage(url); + } + else if (Item.BackdropCount > 0) + { + var url = App.Instance.ApiClient.GetImageUrl(Item, new ImageOptions + { + ImageType = ImageType.Backdrop, + Height = 225, + Width = 400 + }); + + SetImage(url); + } + else if (Item.HasThumb) + { + var url = App.Instance.ApiClient.GetImageUrl(Item, new ImageOptions + { + ImageType = ImageType.Thumb, + Height = 225, + Width = 400 + }); + + SetImage(url); + } + else + { + SetDefaultImage(); + } + } + + /// <summary> + /// Sets the image. + /// </summary> + /// <param name="url">The URL.</param> + private async void SetImage(string url) + { + try + { + image.Source = await App.Instance.GetRemoteBitmapAsync(url); + } + catch (HttpException) + { + SetDefaultImage(); + } + } + + private void SetDefaultImage() + { + var imageUri = new Uri("../Resources/Images/VideoDefault.png", UriKind.Relative); + image.Source = App.Instance.GetBitmapImage(imageUri); + } + } +} diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml b/MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml new file mode 100644 index 000000000..000fc9584 --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml @@ -0,0 +1,30 @@ +<controls:BaseUserControl x:Class="MediaBrowser.Plugins.DefaultTheme.Controls.MultiItemTile" + 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="mainGrid" HorizontalAlignment="Left"> + + <Border Background="{Binding Converter={StaticResource MetroTileBackgroundConverter}}"> + <controls:TransitionControl x:Name="transitionControl"> + <controls:TransitionControl.TransitionAnimation> + <DoubleAnimation Duration="0:0:1" > + <DoubleAnimation.EasingFunction> + <ExponentialEase EasingMode="EaseInOut"></ExponentialEase> + </DoubleAnimation.EasingFunction> + </DoubleAnimation> + </controls:TransitionControl.TransitionAnimation> + </controls:TransitionControl> + </Border> + + <Grid HorizontalAlignment="Stretch" VerticalAlignment="Bottom"> + <Grid.Background> + <SolidColorBrush Color="#A6000000"></SolidColorBrush> + </Grid.Background> + <TextBlock x:Name="txtName" Margin="10 5 0 10" Foreground="White" TextWrapping="Wrap"></TextBlock> + </Grid> + </Grid> +</controls:BaseUserControl> diff --git a/MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml.cs b/MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml.cs new file mode 100644 index 000000000..66a30bfff --- /dev/null +++ b/MediaBrowser.Plugins.DefaultTheme/Controls/MultiItemTile.xaml.cs @@ -0,0 +1,219 @@ +using MediaBrowser.Model.DTO; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Net; +using MediaBrowser.UI; +using MediaBrowser.UI.Controls; +using MediaBrowser.UI.ViewModels; +using Microsoft.Expression.Media.Effects; +using System; +using System.ComponentModel; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +namespace MediaBrowser.Plugins.DefaultTheme.Controls +{ + /// <summary> + /// Interaction logic for MultiItemTile.xaml + /// </summary> + public partial class MultiItemTile : BaseUserControl + { + /// <summary> + /// The _image width + /// </summary> + private int _imageWidth; + /// <summary> + /// Gets or sets the width of the image. + /// </summary> + /// <value>The width of the image.</value> + public int ImageWidth + { + get { return _imageWidth; } + set + { + _imageWidth = value; + mainGrid.Width = value; + } + } + + /// <summary> + /// The _image height + /// </summary> + private int _imageHeight; + /// <summary> + /// Gets or sets the height of the image. + /// </summary> + /// <value>The height of the image.</value> + public int ImageHeight + { + get { return _imageHeight; } + set + { + _imageHeight = value; + mainGrid.Height = value; + } + } + + /// <summary> + /// The _effects + /// </summary> + TransitionEffect[] _effects = new TransitionEffect[] + { + new BlindsTransitionEffect { Orientation = BlindOrientation.Horizontal }, + new BlindsTransitionEffect { Orientation = BlindOrientation.Vertical }, + new CircleRevealTransitionEffect { }, + new FadeTransitionEffect { }, + new SlideInTransitionEffect { SlideDirection= SlideDirection.TopToBottom}, + new SlideInTransitionEffect { SlideDirection= SlideDirection.RightToLeft}, + new WipeTransitionEffect { WipeDirection = WipeDirection.RightToLeft}, + new WipeTransitionEffect { WipeDirection = WipeDirection.TopLeftToBottomRight} + }; + + /// <summary> + /// Gets or sets the random. + /// </summary> + /// <value>The random.</value> + private Random Random { get; set; } + + /// <summary> + /// Gets the collection. + /// </summary> + /// <value>The collection.</value> + public ItemCollectionViewModel Collection + { + get { return DataContext as ItemCollectionViewModel; } + } + + /// <summary> + /// Initializes a new instance of the <see cref="MultiItemTile" /> class. + /// </summary> + public MultiItemTile() + { + InitializeComponent(); + + Random = new Random(Guid.NewGuid().GetHashCode()); + + mainGrid.Width = ImageWidth; + mainGrid.Height = ImageHeight; + DataContextChanged += BaseItemTile_DataContextChanged; + } + + /// <summary> + /// Handles the DataContextChanged event of the BaseItemTile control. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs" /> instance containing the event data.</param> + void BaseItemTile_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) + { + OnCurrentItemChanged(); + + if (Collection != null) + { + Collection.PropertyChanged += Collection_PropertyChanged; + } + } + + /// <summary> + /// Handles the PropertyChanged event of the Collection control. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="PropertyChangedEventArgs" /> instance containing the event data.</param> + void Collection_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName.Equals("CurrentItem")) + { + OnCurrentItemChanged(); + } + } + + /// <summary> + /// Called when [current item changed]. + /// </summary> + private async void OnCurrentItemChanged() + { + if (Collection == null) + { + // Setting this to null doesn't seem to clear out the content + transitionControl.Content = new FrameworkElement(); + txtName.Text = null; + return; + } + + var currentItem = Collection.CurrentItem; + + if (currentItem == null) + { + // Setting this to null doesn't seem to clear out the content + transitionControl.Content = new FrameworkElement(); + txtName.Text = Collection.Name; + return; + } + + var img = new Image + { + Stretch = Stretch.Uniform, + Width = ImageWidth, + Height = ImageHeight + }; + + var url = GetImageSource(currentItem); + + if (!string.IsNullOrEmpty(url)) + { + try + { + img.Source = await App.Instance.GetRemoteBitmapAsync(url); + txtName.Text = Collection.Name ?? currentItem.Name; + } + catch (HttpException) + { + } + } + + transitionControl.TransitionType = _effects[Random.Next(0, _effects.Length)]; + transitionControl.Content = img; + } + + /// <summary> + /// Gets the image source. + /// </summary> + /// <param name="item">The item.</param> + /// <returns>Uri.</returns> + private string GetImageSource(DtoBaseItem item) + { + if (item != null) + { + if (item.BackdropCount > 0) + { + return App.Instance.ApiClient.GetImageUrl(item, new ImageOptions + { + ImageType = ImageType.Backdrop, + Height = ImageHeight, + Width = ImageWidth + }); + } + + if (item.HasThumb) + { + return App.Instance.ApiClient.GetImageUrl(item, new ImageOptions + { + ImageType = ImageType.Thumb, + Height = ImageHeight, + Width = ImageWidth + }); + } + + if (item.HasPrimaryImage) + { + return App.Instance.ApiClient.GetImageUrl(item, new ImageOptions + { + ImageType = ImageType.Primary, + Height = ImageHeight + }); + } + } + + return null; + } + } +} |
