]> granicus.if.org Git - handbrake/commitdiff
WinGui: Rework of the preset system
authorsr55 <sr55.hb@outlook.com>
Sat, 4 Mar 2017 17:22:26 +0000 (17:22 +0000)
committersr55 <sr55.hb@outlook.com>
Sat, 4 Mar 2017 17:22:26 +0000 (17:22 +0000)
- Better support for categories.
- Switched from a List to Treeview Control.
- Remember the expansion state of each group
- Put User Presets on top after next save.
Closes #445

13 files changed:
win/CS/HandBrakeWPF/Converters/PresetsMenuConverter.cs
win/CS/HandBrakeWPF/HandBrakeWPF.csproj
win/CS/HandBrakeWPF/Helpers/TreeViewHelper.cs [new file with mode: 0644]
win/CS/HandBrakeWPF/Services/Presets/Interfaces/IPresetObject.cs [new file with mode: 0644]
win/CS/HandBrakeWPF/Services/Presets/Interfaces/IPresetService.cs
win/CS/HandBrakeWPF/Services/Presets/Model/Preset.cs
win/CS/HandBrakeWPF/Services/Presets/Model/PresetDisplayCategory.cs [new file with mode: 0644]
win/CS/HandBrakeWPF/Services/Presets/PresetService.cs
win/CS/HandBrakeWPF/UserSettingConstants.cs
win/CS/HandBrakeWPF/ViewModels/Interfaces/IMainViewModel.cs
win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs
win/CS/HandBrakeWPF/Views/MainView.xaml
win/CS/HandBrakeWPF/Views/MainView.xaml.cs

index 098d9e952826faee9e54a21995e3b29d65503e80..bbcfd891d7084f45961543b5d6caf4db2a03accd 100644 (file)
@@ -11,13 +11,13 @@ namespace HandBrakeWPF.Converters
 {
     using System;
     using System.Collections.Generic;
-    using System.Linq;
     using System.Globalization;
+    using System.Linq;
     using System.Windows;
     using System.Windows.Controls;
     using System.Windows.Data;
-
     using HandBrakeWPF.Commands;
+    using HandBrakeWPF.Services.Presets.Interfaces;
     using HandBrakeWPF.Services.Presets.Model;
 
     /// <summary>
@@ -33,7 +33,7 @@ namespace HandBrakeWPF.Converters
         /// <param name="culture">The culture to use in the converter.</param>
         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            IEnumerable<Preset> presets = value as IEnumerable<Preset>;
+            IEnumerable<IPresetObject> presets = value as IEnumerable<IPresetObject>;
 
             if (presets == null)
             {
@@ -41,31 +41,19 @@ namespace HandBrakeWPF.Converters
             }
             
             Dictionary<string, MenuItem> groupedMenu = new Dictionary<string, MenuItem>();
-            foreach (Preset item in presets)
+            foreach (IPresetObject item in presets)
             {
-                if (groupedMenu.ContainsKey(item.Category))
+                PresetDisplayCategory category = item as PresetDisplayCategory;
+                if (category != null)
                 {
-                    MenuItem newMeuItem = new MenuItem { Header = item.Name, Tag = item, Command = new PresetMenuSelectCommand(item) };
-                    if (item.IsDefault)
-                    {
-                        newMeuItem.FontStyle = FontStyles.Italic;
-                    }
-
-                    groupedMenu[item.Category].Items.Add(newMeuItem);
+                    ProcessCategory(groupedMenu, category);
+                    continue;
                 }
-                else
-                {
-                    MenuItem group = new MenuItem();
-                    group.Header = item.Category;
-
-                    MenuItem newMeuItem = new MenuItem { Header = item.Name, Tag = item, Command = new PresetMenuSelectCommand(item) };
-                    if (item.IsDefault)
-                    {
-                        newMeuItem.FontStyle = FontStyles.Italic;
-                    }
 
-                    group.Items.Add(newMeuItem);
-                    groupedMenu[item.Category] = group;
+                Preset preset = item as Preset;
+                if (preset != null)
+                {
+                    ProcessPreset(groupedMenu, preset);
                 }
             }
 
@@ -82,5 +70,41 @@ namespace HandBrakeWPF.Converters
         {
             throw new NotImplementedException();
         }
+
+        private void ProcessPreset(Dictionary<string, MenuItem> groupedMenu, Preset preset)
+        {
+            if (groupedMenu.ContainsKey(preset.Category))
+            {
+                MenuItem newMeuItem = new MenuItem { Header = preset.Name, Tag = preset, Command = new PresetMenuSelectCommand(preset) };
+                if (preset.IsDefault)
+                {
+                    newMeuItem.FontStyle = FontStyles.Italic;
+                }
+
+                groupedMenu[preset.Category].Items.Add(newMeuItem);
+            }
+            else
+            {
+                MenuItem group = new MenuItem();
+                group.Header = preset.Category;
+
+                MenuItem newMeuItem = new MenuItem { Header = preset.Name, Tag = preset, Command = new PresetMenuSelectCommand(preset) };
+                if (preset.IsDefault)
+                {
+                    newMeuItem.FontStyle = FontStyles.Italic;
+                }
+
+                group.Items.Add(newMeuItem);
+                groupedMenu[preset.Category] = group;
+            }
+        }
+
+        private void ProcessCategory(Dictionary<string, MenuItem> groupedMenu, PresetDisplayCategory category)
+        {
+            foreach (Preset preset in category.Presets)
+            {
+                this.ProcessPreset(groupedMenu, preset);
+            }
+        }
     }
 }
index e28bec1dd233b8a97c57040b78daae358aa09bdc..d37f10acd05b3ff9daf45df4c77421796d7d65b5 100644 (file)
     <Compile Include="EventArgs\SettingChangedEventArgs.cs" />\r
     <Compile Include="Exceptions\GeneralApplicationException.cs" />\r
     <Compile Include="Extensions\StringExtensions.cs" />\r
+    <Compile Include="Helpers\TreeViewHelper.cs" />\r
     <Compile Include="Helpers\LogManager.cs" />\r
     <Compile Include="Helpers\MP4Helper.cs" />\r
     <Compile Include="Helpers\TimeSpanHelper.cs" />\r
     <Compile Include="Services\Encode\Model\Models\Video\VideoProfile.cs" />\r
     <Compile Include="Services\Encode\Model\Models\Video\VideoTune.cs" />\r
     <Compile Include="Services\Presets\Factories\JsonPresetFactory.cs" />\r
+    <Compile Include="Services\Presets\Interfaces\IPresetObject.cs" />\r
+    <Compile Include="Services\Presets\Model\PresetDisplayCategory.cs" />\r
     <Compile Include="Services\Queue\Interfaces\IQueueProcessor.cs" />\r
     <Compile Include="Helpers\FileHelper.cs" />\r
     <Compile Include="Services\Presets\Model\Preset.cs" />\r
diff --git a/win/CS/HandBrakeWPF/Helpers/TreeViewHelper.cs b/win/CS/HandBrakeWPF/Helpers/TreeViewHelper.cs
new file mode 100644 (file)
index 0000000..99b4588
--- /dev/null
@@ -0,0 +1,88 @@
+// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="TreeViewHelper.cs" company="HandBrake Project (http://handbrake.fr)">
+//   This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+//   Helper functions for handling <see cref="TimeSpan" /> structures
+//   Based of https://social.technet.microsoft.com/wiki/contents/articles/18188.wpf-treeview-selecteditem-twoway-mvvm-plus-expand-to-selected-and-close-all-others.aspx
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+namespace HandBrakeWPF.Helpers
+{
+    using System.Windows;
+    using System.Windows.Controls;
+
+    public class TreeViewHelper
+    {
+        public static object GetTreeViewSelectedItem(DependencyObject obj)
+        {
+            return (object)obj.GetValue(TreeViewSelectedItemProperty);
+        }
+
+        public static void SetTreeViewSelectedItem(DependencyObject obj, object value)
+        {
+            obj.SetValue(TreeViewSelectedItemProperty, value);
+        }
+
+        public static readonly DependencyProperty TreeViewSelectedItemProperty =
+            DependencyProperty.RegisterAttached("TreeViewSelectedItem", typeof(object), typeof(TreeViewHelper), new PropertyMetadata(new object(), TreeViewSelectedItemChanged));
+
+        private static void TreeViewSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
+        {
+            TreeView treeView = sender as TreeView;
+            if (treeView == null)
+            {
+                return;
+            }
+
+            treeView.SelectedItemChanged -= TreeView_SelectedItemChanged;
+            treeView.SelectedItemChanged += TreeView_SelectedItemChanged;
+
+            TreeViewItem thisItem = treeView.ItemContainerGenerator.ContainerFromItem(e.NewValue) as TreeViewItem;
+            if (thisItem != null)
+            {
+                thisItem.IsSelected = true;
+                return;
+            }
+
+            for (int i = 0; i < treeView.Items.Count; i++)
+            {
+                if (SelectItem(e.NewValue, treeView.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem))
+                {
+                    return; // Break out the loop. We've found the item and expanded it's parent if necessary.
+                }
+            }
+        }
+
+        private static void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
+        {
+            TreeView treeView = sender as TreeView;
+            SetTreeViewSelectedItem(treeView, e.NewValue);
+        }
+
+        private static bool SelectItem(object o, TreeViewItem parentItem)
+        {
+            bool found = false;
+            foreach (var item in parentItem.Items)
+            {
+                if (item.Equals(o))
+                {
+                    found = true;
+                    break;
+                }
+            }
+
+            if (found)
+            {
+                bool isExpanded = parentItem.IsExpanded;
+                if (!isExpanded)
+                {
+                    parentItem.IsExpanded = true;
+                    parentItem.UpdateLayout();
+                }
+            }
+
+            return found;
+        }
+    }
+}
\ No newline at end of file
diff --git a/win/CS/HandBrakeWPF/Services/Presets/Interfaces/IPresetObject.cs b/win/CS/HandBrakeWPF/Services/Presets/Interfaces/IPresetObject.cs
new file mode 100644 (file)
index 0000000..07c3d4d
--- /dev/null
@@ -0,0 +1,17 @@
+// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="IPresetObject.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+//   The Preset Service Interface
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.Services.Presets.Interfaces
+{
+    public interface IPresetObject
+    {      
+        bool IsSelected { get; set; }
+        string Category { get; }
+    }
+}
\ No newline at end of file
index fb46b932ffb4867c37c10d6010c0c6a602606bdd..f75c054c5dcc4efba0a1e3af02b15c0dc876eb16 100644 (file)
@@ -23,7 +23,7 @@ namespace HandBrakeWPF.Services.Presets.Interfaces
         /// <summary>\r
         /// Gets a Collection of presets.\r
         /// </summary>\r
-        ObservableCollection<Preset> Presets { get; }\r
+        ObservableCollection<IPresetObject> Presets { get; }\r
 \r
         /// <summary>\r
         /// Gets DefaultPreset.\r
@@ -35,6 +35,16 @@ namespace HandBrakeWPF.Services.Presets.Interfaces
         /// </summary>\r
         void Load();\r
 \r
+        /// <summary>\r
+        /// Save the state of the Preset Treview\r
+        /// </summary>\r
+        void SaveCategoryStates();\r
+\r
+        /// <summary>\r
+        /// Load the state of the Preset Treeview.\r
+        /// </summary>\r
+        void LoadCategoryStates();\r
+\r
         /// <summary>\r
         /// Add a new preset to the system\r
         /// </summary>\r
@@ -83,7 +93,10 @@ namespace HandBrakeWPF.Services.Presets.Interfaces
         /// <param name="preset">\r
         /// The Preset to remove\r
         /// </param>\r
-        void Remove(Preset preset);\r
+        /// <returns>\r
+        /// True if it was removed successfully, false otherwise.\r
+        /// </returns>\r
+        bool Remove(Preset preset);\r
 \r
         /// <summary>\r
         /// Remove a group of presets by category\r
@@ -155,5 +168,11 @@ namespace HandBrakeWPF.Services.Presets.Interfaces
         /// The replacement.\r
         /// </param>\r
         void Replace(Preset existing, Preset replacement);\r
+\r
+        /// <summary>\r
+        /// Set the selected preset\r
+        /// </summary>\r
+        /// <param name="selectedPreset">The preset we want to select.</param>\r
+        void SetSelected(Preset selectedPreset);\r
     }\r
 }
\ No newline at end of file
index 8b6aee917b03636a6e8e22386cafc4bd2651761d..5f179f67e3352583fb977dd959d23f50ee71c578 100644 (file)
@@ -11,6 +11,7 @@ namespace HandBrakeWPF.Services.Presets.Model
 {\r
     using HandBrakeWPF.Model.Audio;\r
     using HandBrakeWPF.Model.Subtitles;\r
+    using HandBrakeWPF.Services.Presets.Interfaces;\r
     using HandBrakeWPF.Utilities;\r
 \r
     using EncodeTask = HandBrakeWPF.Services.Encode.Model.EncodeTask;\r
@@ -24,7 +25,7 @@ namespace HandBrakeWPF.Services.Presets.Model
     /// https://github.com/Caliburn-Micro/Caliburn.Micro/issues/89\r
     /// https://github.com/Caliburn-Micro/Caliburn.Micro/issues/96\r
     /// </remarks>\r
-    public class Preset : PropertyChangedBase // Delibery not \r
+    public class Preset : PropertyChangedBase, IPresetObject // Delibery not \r
     {\r
         #region Constants and Fields\r
 \r
@@ -33,6 +34,8 @@ namespace HandBrakeWPF.Services.Presets.Model
         /// </summary>\r
         private bool isDefault;\r
 \r
+        private bool isSelected;\r
+\r
         #endregion\r
 \r
         /// <summary>\r
@@ -72,6 +75,24 @@ namespace HandBrakeWPF.Services.Presets.Model
         /// </summary>\r
         public string Description { get; set; }\r
 \r
+        /// <summary>\r
+        /// Reflects the visual state of this preset.\r
+        /// </summary>\r
+        public bool IsExpanded { get; set; }\r
+\r
+        public bool IsSelected\r
+        {\r
+            get\r
+            {\r
+                return this.isSelected;\r
+            }\r
+            set\r
+            {\r
+                this.isSelected = value;\r
+                this.NotifyOfPropertyChange(() => this.IsSelected);\r
+            }\r
+        }\r
+\r
         /// <summary>\r
         /// Gets or sets a value indicating whether this is a built in preset\r
         /// </summary>\r
diff --git a/win/CS/HandBrakeWPF/Services/Presets/Model/PresetDisplayCategory.cs b/win/CS/HandBrakeWPF/Services/Presets/Model/PresetDisplayCategory.cs
new file mode 100644 (file)
index 0000000..95d2213
--- /dev/null
@@ -0,0 +1,78 @@
+// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="PresetDisplayCategory.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+//   A Preset Category encoding with.
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.Services.Presets.Model
+{
+    using System.ComponentModel;
+    using Caliburn.Micro;
+    using HandBrakeWPF.Services.Presets.Interfaces;
+
+    public class PresetDisplayCategory : PropertyChangedBase, IPresetObject
+    {
+        private bool isSelected;
+        private bool isExpanded;
+
+        public PresetDisplayCategory(string category, BindingList<Preset> presets)
+        {
+            this.Category = category;
+            this.Presets = presets;
+        }
+
+        public string Category { get; private set; }
+        public BindingList<Preset> Presets { get; private set; }
+
+        public string Description => this.Category;
+
+        public bool IsExpanded
+        {
+            get
+            {
+                return this.isExpanded;
+            }
+            set
+            {
+                if (value == this.isExpanded) return;
+                this.isExpanded = value;
+                this.NotifyOfPropertyChange(() => this.IsExpanded);
+            }
+        }
+
+        public bool IsSelected
+        {
+            get
+            {
+                return this.isSelected;
+            }
+            set
+            {
+                if (value == this.isSelected) return;
+                this.isSelected = value;
+                this.NotifyOfPropertyChange(() => this.IsSelected);
+            }
+        }
+
+        protected bool Equals(PresetDisplayCategory other)
+        {
+            return string.Equals(this.Category, other.Category);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            if (ReferenceEquals(this, obj)) return true;
+            if (obj.GetType() != this.GetType()) return false;
+            return Equals((PresetDisplayCategory)obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return (this.Category != null ? this.Category.GetHashCode() : 0);
+        }
+    }
+}
index 78387e54e59f248b170eef4d30a6b46b815ebabd..a90bf1543c8cd7c02e46c16580d36c5dd7536887 100644 (file)
@@ -12,6 +12,8 @@ namespace HandBrakeWPF.Services.Presets
     using System;\r
     using System.Collections.Generic;\r
     using System.Collections.ObjectModel;\r
+    using System.Collections.Specialized;\r
+    using System.ComponentModel;\r
     using System.Diagnostics;\r
     using System.IO;\r
     using System.Linq;\r
@@ -46,7 +48,8 @@ namespace HandBrakeWPF.Services.Presets
         public const int ForcePresetReset = 3;\r
         public static string UserPresetCatgoryName = "User Presets";\r
         private readonly string presetFile = Path.Combine(DirectoryUtilities.GetUserStoragePath(VersionHelper.IsNightly()), "presets.json");\r
-        private readonly ObservableCollection<Preset> presets = new ObservableCollection<Preset>();\r
+        private readonly ObservableCollection<IPresetObject> presets = new ObservableCollection<IPresetObject>(); // Can store Presets and PresetDisplayCategory objects.\r
+        private readonly Dictionary<string, Preset> flatPresetList = new Dictionary<string, Preset>();\r
         private readonly IErrorService errorService;\r
         private readonly IUserSettingService userSettingService;\r
 \r
@@ -70,7 +73,7 @@ namespace HandBrakeWPF.Services.Presets
         /// <summary>\r
         /// Gets a Collection of presets.\r
         /// </summary>\r
-        public ObservableCollection<Preset> Presets\r
+        public ObservableCollection<IPresetObject> Presets\r
         {\r
             get\r
             {\r
@@ -85,7 +88,7 @@ namespace HandBrakeWPF.Services.Presets
         {\r
             get\r
             {\r
-                return this.presets.FirstOrDefault(p => p.IsDefault);\r
+                return this.flatPresetList.Values.FirstOrDefault(p => p.IsDefault);\r
             }\r
         }\r
 \r
@@ -100,12 +103,18 @@ namespace HandBrakeWPF.Services.Presets
             if (!File.Exists(this.presetFile))\r
             {\r
                 this.UpdateBuiltInPresets();\r
+                return;\r
             }\r
 \r
             // Load the presets from file\r
             this.LoadPresets();\r
         }\r
 \r
+        public bool Add(Preset preset)\r
+        {\r
+            return this.Add(preset, false);\r
+        }\r
+\r
         /// <summary>\r
         /// Add a new preset to the system.\r
         /// Performs an Update if it already exists\r
@@ -113,23 +122,45 @@ namespace HandBrakeWPF.Services.Presets
         /// <param name="preset">\r
         /// A Preset to add\r
         /// </param>\r
+        /// <param name="isLoading">\r
+        /// Prevents Saving of presets.\r
+        /// </param>\r
         /// <returns>\r
         /// True if added,\r
         /// False if name already exists\r
         /// </returns>\r
-        public bool Add(Preset preset)\r
+        public bool Add(Preset preset, bool isLoading)\r
         {\r
             if (!this.CheckIfPresetExists(preset.Name))\r
             {\r
-                this.presets.Add(preset);\r
+                // Check to see if the category already exists.\r
+                PresetDisplayCategory category = this.presets.FirstOrDefault(a => a.Category == preset.Category) as PresetDisplayCategory; // TODO build Dict for this.\r
+                if (category != null)\r
+                {\r
+                    category.Presets.Add(preset);\r
+                }\r
+                else if (!string.IsNullOrEmpty(preset.Category))\r
+                {\r
+                    // Otherwise, if we have category but it doesn't exist, create it.\r
+                    this.presets.Add(new PresetDisplayCategory(preset.Category, new BindingList<Preset> { preset }));\r
+                }\r
+                else\r
+                {\r
+                    // Preset has no category. \r
+                    this.presets.Add(preset);\r
+                }\r
+\r
+                this.flatPresetList.Add(preset.Name, preset);\r
 \r
                 // Update the presets file\r
-                this.SavePresetFiles();\r
+                if (!isLoading)\r
+                {\r
+                    this.SavePresetFiles();\r
+                }\r
                 return true;\r
             }\r
 \r
-            this.Update(preset);\r
-            return true;\r
+            return false;\r
         }\r
 \r
         /// <summary>\r
@@ -170,7 +201,7 @@ namespace HandBrakeWPF.Services.Presets
                         try\r
                         {\r
                             preset = JsonPresetFactory.ImportPreset(hbPreset);\r
-                            preset.Category = UserPresetCatgoryName;\r
+                            preset.Category = UserPresetCatgoryName; // TODO can we get this from the preset?\r
 \r
                             // IF we are using Source Max, Set the Max Width / Height values.\r
                             if (preset.PictureSettingsMode == PresetPictureSettingsMode.SourceMaximum)\r
@@ -206,13 +237,10 @@ namespace HandBrakeWPF.Services.Presets
                         }\r
                         else\r
                         {\r
-                            this.Add(preset);\r
+                            this.Add(preset, false);\r
                         }\r
                     }\r
                 }\r
-\r
-                // Category Handling.\r
-                // TODO maybe for a future release.\r
             }\r
         }\r
 \r
@@ -243,22 +271,18 @@ namespace HandBrakeWPF.Services.Presets
         /// </param>\r
         public void Update(Preset update)\r
         {\r
-            // TODO - Change this to be a lookup\r
-            foreach (Preset preset in this.presets)\r
+            Preset preset;\r
+            if (this.flatPresetList.TryGetValue(update.Name, out preset))\r
             {\r
-                if (preset.Name == update.Name)\r
-                {\r
-                    preset.Task = update.Task;\r
-                    preset.PictureSettingsMode = update.PictureSettingsMode;\r
-                    preset.Category = update.Category;\r
-                    preset.Description = update.Description;\r
-                    preset.AudioTrackBehaviours = update.AudioTrackBehaviours;\r
-                    preset.SubtitleTrackBehaviours = update.SubtitleTrackBehaviours;\r
-\r
-                    // Update the presets file\r
-                    this.SavePresetFiles();\r
-                    break;\r
-                }\r
+                preset.Task = update.Task;\r
+                preset.PictureSettingsMode = update.PictureSettingsMode;\r
+                preset.Category = update.Category;\r
+                preset.Description = update.Description;\r
+                preset.AudioTrackBehaviours = update.AudioTrackBehaviours;\r
+                preset.SubtitleTrackBehaviours = update.SubtitleTrackBehaviours;\r
+\r
+                // Update the presets file\r
+                this.SavePresetFiles();\r
             }\r
         }\r
 \r
@@ -274,7 +298,7 @@ namespace HandBrakeWPF.Services.Presets
         public void Replace(Preset existing, Preset replacement)\r
         {\r
             this.Remove(existing);\r
-            this.Add(replacement);\r
+            this.Add(replacement, false);\r
         }\r
 \r
         /// <summary>\r
@@ -283,54 +307,86 @@ namespace HandBrakeWPF.Services.Presets
         /// <param name="preset">\r
         /// The Preset to remove\r
         /// </param>\r
-        public void Remove(Preset preset)\r
+        /// <returns>True if successfully removed, false otherwise.</returns>\r
+        public bool Remove(Preset preset)\r
         {\r
             if (preset == null || preset.IsDefault)\r
             {\r
-                return;\r
+                return false;\r
+            }\r
+\r
+            PresetDisplayCategory cateogry = this.presets.FirstOrDefault(p => p.Category == preset.Category) as PresetDisplayCategory;\r
+            if (cateogry != null)\r
+            {\r
+                // Remove the preset, and cleanup the category if it's not got any presets in it.\r
+                cateogry.Presets.Remove(preset);\r
+                this.flatPresetList.Remove(preset.Name);\r
+                if (cateogry.Presets.Count == 0)\r
+                {\r
+                    this.presets.Remove(cateogry);\r
+                }\r
+            }\r
+            else\r
+            {\r
+                this.presets.Remove(preset);\r
+                this.flatPresetList.Remove(preset.Name);\r
             }\r
 \r
-            this.presets.Remove(preset);\r
             this.SavePresetFiles();\r
+\r
+            return true;\r
         }\r
 \r
         /// <summary>\r
         /// Remove a group of presets by category\r
         /// </summary>\r
-        /// <param name="category">\r
+        /// <param name="categoryName">\r
         /// The Category to remove\r
         /// </param>\r
-        public void RemoveGroup(string category)\r
+        public void RemoveGroup(string categoryName)\r
         {\r
-            List<Preset> removeList = this.presets.Where(p => p.Category == category).ToList();\r
-            foreach (Preset preset in removeList)\r
+            PresetDisplayCategory category = this.presets.FirstOrDefault(p => p.Category == categoryName) as PresetDisplayCategory;\r
+            if (category != null)\r
             {\r
-                if (preset.IsDefault)\r
+                foreach (Preset preset in category.Presets)\r
                 {\r
-                    // Skip default preset\r
-                    continue;\r
+                    if (preset.IsDefault)\r
+                    {\r
+                        // Skip default preset\r
+                        continue;\r
+                    }\r
+\r
+                    this.presets.Remove(preset);\r
+                    this.flatPresetList.Remove(preset.Name);\r
                 }\r
 \r
-                this.presets.Remove(preset);\r
-            }\r
+                // Cleanup the category if we can.\r
+                if (category.Presets.Count == 0)\r
+                {\r
+                    this.presets.Remove(category);\r
+                }\r
 \r
-            this.SavePresetFiles();\r
+                this.SavePresetFiles();\r
+            }\r
         }\r
 \r
         /// <summary>\r
         /// Set Default Preset\r
         /// </summary>\r
-        /// <param name="name">\r
+        /// <param name="preset">\r
         /// The name.\r
         /// </param>\r
-        public void SetDefault(Preset name)\r
+        public void SetDefault(Preset preset)\r
         {\r
-            foreach (Preset preset in this.presets)\r
+            // Set IsDefault false for everything.\r
+            foreach (Preset item in this.flatPresetList.Values)\r
             {\r
-                preset.IsDefault = false;\r
+                item.IsDefault = false;\r
             }\r
 \r
-            name.IsDefault = true;\r
+            // Set the new preset to default.\r
+            preset.IsDefault = true;\r
+\r
             this.SavePresetFiles();\r
         }\r
 \r
@@ -345,7 +401,13 @@ namespace HandBrakeWPF.Services.Presets
         /// </returns>\r
         public Preset GetPreset(string name)\r
         {\r
-            return this.presets.FirstOrDefault(item => item.Name == name);\r
+            Preset preset;\r
+            if (this.flatPresetList.TryGetValue(name, out preset))\r
+            {\r
+                return preset;\r
+            }\r
+\r
+            return null;\r
         }\r
 \r
         /// <summary>\r
@@ -353,10 +415,54 @@ namespace HandBrakeWPF.Services.Presets
         /// </summary>\r
         public void ClearBuiltIn()\r
         {\r
-            List<Preset> remove = this.presets.Where(p => p.IsBuildIn).ToList();\r
-            foreach (Preset preset in remove)\r
+            List<IPresetObject> topLevel = new List<IPresetObject>();\r
+            foreach (IPresetObject item in this.presets)\r
             {\r
-                this.presets.Remove(preset);\r
+                // We either have a Preset\r
+                Preset foundPreset = item as Preset;\r
+                if (foundPreset != null && foundPreset.IsBuildIn)\r
+                {\r
+                    topLevel.Add(item);\r
+                }\r
+\r
+                // Or a Category.\r
+                PresetDisplayCategory foundCategory = item as PresetDisplayCategory;\r
+                if (foundCategory != null)\r
+                {\r
+                    // Find all the presets in this category to remove\r
+                    List<Preset> presetsToRemove = new List<Preset>();\r
+                    foreach (Preset categoryPreset in foundCategory.Presets)\r
+                    {\r
+                        if (categoryPreset.IsBuildIn)\r
+                        {\r
+                            presetsToRemove.Add(categoryPreset);\r
+                        }\r
+                    }\r
+\r
+                    // Then remove them.\r
+                    foreach (Preset toRemove in presetsToRemove)\r
+                    {\r
+                        foundCategory.Presets.Remove(toRemove);\r
+                        this.flatPresetList.Remove(toRemove.Name);\r
+                    }\r
+\r
+                    // Check if we can remove this category.\r
+                    if (foundCategory.Presets.Count == 0)\r
+                    {\r
+                        topLevel.Add(foundCategory);\r
+                    }\r
+                }\r
+            }\r
+\r
+            // Remove any top level items we need to remove.\r
+            foreach (var item in topLevel)\r
+            {\r
+                this.presets.Remove(item);\r
+\r
+                if (item.GetType() == typeof(Preset))\r
+                {\r
+                    this.flatPresetList.Remove(((Preset)item).Name);\r
+                }\r
             }\r
         }\r
 \r
@@ -366,6 +472,7 @@ namespace HandBrakeWPF.Services.Presets
         public void ClearAll()\r
         {\r
             this.presets.Clear();\r
+            this.flatPresetList.Clear();\r
         }\r
 \r
         /// <summary>\r
@@ -385,15 +492,9 @@ namespace HandBrakeWPF.Services.Presets
                     Preset preset = JsonPresetFactory.ImportPreset(hbpreset);\r
                     preset.IsBuildIn = true; \r
                     preset.Category = category.PresetName;\r
-\r
-                    if (preset.Name == "iPod")\r
-                    {\r
-                        preset.Task.KeepDisplayAspect = true;\r
-                    }\r
-\r
                     preset.Task.AllowedPassthruOptions = new AllowedPassthru(true); // We don't want to override the built-in preset\r
 \r
-                    this.presets.Add(preset);\r
+                    this.Add(preset, true);\r
                 }\r
             }\r
 \r
@@ -418,7 +519,12 @@ namespace HandBrakeWPF.Services.Presets
         /// </returns>\r
         public bool CheckIfPresetExists(string name)\r
         {\r
-            return name == string.Empty || this.presets.Any(item => item.Name == name);\r
+            if (this.flatPresetList.ContainsKey(name))\r
+            {\r
+                return true;\r
+            }\r
+\r
+            return false;\r
         }\r
 \r
         /// <summary>\r
@@ -432,7 +538,60 @@ namespace HandBrakeWPF.Services.Presets
         /// </returns>\r
         public bool CanUpdatePreset(string name)\r
         {\r
-            return this.presets.Where(preset => preset.Name == name).Any(preset => preset.IsBuildIn == false);\r
+            Preset preset;\r
+            if (this.flatPresetList.TryGetValue(name, out preset))\r
+            {\r
+                return !preset.IsBuildIn;\r
+            }\r
+\r
+            return true;\r
+        }\r
+\r
+        /// <summary>\r
+        /// Set the selected preset\r
+        /// </summary>\r
+        /// <param name="selectedPreset">The preset we want to select.</param>\r
+        public void SetSelected(Preset selectedPreset)\r
+        {\r
+            foreach (var item in this.flatPresetList.Values)\r
+            {\r
+                item.IsSelected = false;\r
+            }\r
+\r
+            selectedPreset.IsSelected = true;\r
+        }\r
+\r
+        public void SaveCategoryStates()\r
+        {\r
+            StringCollection expandedPresets = new StringCollection();\r
+            foreach (IPresetObject presetObject in this.presets)\r
+            {\r
+                PresetDisplayCategory category = presetObject as PresetDisplayCategory;\r
+                if (category != null && category.IsExpanded)\r
+                {\r
+                    expandedPresets.Add(category.Category);\r
+                }\r
+            }\r
+\r
+            this.userSettingService.SetUserSetting(UserSettingConstants.PresetExpandedStateList, expandedPresets);\r
+        }\r
+\r
+        public void LoadCategoryStates()\r
+        {\r
+            StringCollection expandedPresets = this.userSettingService.GetUserSetting<StringCollection>(UserSettingConstants.PresetExpandedStateList);\r
+            if (expandedPresets == null || expandedPresets.Count == 0)\r
+            {\r
+                return;\r
+            }\r
+\r
+            foreach (IPresetObject presetObject in this.presets)\r
+            {\r
+                PresetDisplayCategory category = presetObject as PresetDisplayCategory;\r
+                if (category != null && expandedPresets.Contains(category.Category))\r
+                {\r
+                    category.IsExpanded = true;\r
+                }\r
+            }\r
         }\r
 \r
         #endregion\r
@@ -609,7 +768,7 @@ namespace HandBrakeWPF.Services.Presets
                                 preset.Task.MaxHeight = preset.Task.Width;\r
                             }\r
 \r
-                            this.presets.Add(preset);\r
+                            this.Add(preset, true);\r
                         }\r
                     }\r
 \r
@@ -629,7 +788,7 @@ namespace HandBrakeWPF.Services.Presets
                             preset.Task.MaxHeight = preset.Task.Width;\r
                         }\r
 \r
-                        this.presets.Add(preset);\r
+                        this.Add(preset, true);\r
                     }\r
                 }\r
             }\r
@@ -658,7 +817,7 @@ namespace HandBrakeWPF.Services.Presets
                 // Orgamise the Presets list into Json Equivilent objects.\r
                 Dictionary<string, PresetCategory> presetCategories = new Dictionary<string, PresetCategory>();\r
                 List<HBPreset> uncategorisedPresets = new List<HBPreset>();      \r
-                foreach (Preset item in this.presets)\r
+                foreach (Preset item in this.flatPresetList.Values.OrderBy(o => o.IsBuildIn)) // Handle User Presets first.\r
                 {\r
                     if (string.IsNullOrEmpty(item.Category))\r
                     {\r
index 80b740b90e5ef5b95d4aff49ffc85c52eb4ceb4b..a5ba0c7ffb290dbf66e5dafb158cd78ba8b7f088 100644 (file)
@@ -226,6 +226,11 @@ namespace HandBrakeWPF
         /// </summary>\r
         public const string ForcePresetReset = "ForcePresetReset";\r
 \r
+        /// <summary>\r
+        /// Setting to record the expansion state of preset categories. \r
+        /// </summary>\r
+        public const string PresetExpandedStateList = "PresetExpandedStateList";\r
+\r
         #endregion\r
     }\r
 }
\ No newline at end of file
index 17f4601238d2b6cea45aa015f7de71b303410ed2..bcc72b9dd4ae3afa531f4bb1b57ca2552998ab5c 100644 (file)
@@ -11,8 +11,6 @@ namespace HandBrakeWPF.ViewModels.Interfaces
 {\r
     using System.Windows;\r
 \r
-    using HandBrakeWPF.Services.Presets.Model;\r
-\r
     using EncodeTask = HandBrakeWPF.Services.Encode.Model.EncodeTask;\r
 \r
     /// <summary>\r
@@ -20,11 +18,6 @@ namespace HandBrakeWPF.ViewModels.Interfaces
     /// </summary>\r
     public interface IMainViewModel\r
     {\r
-        /// <summary>\r
-        /// Sets SelectedPreset.\r
-        /// </summary>\r
-        Preset SelectedPreset { set; }\r
-\r
         /// <summary>\r
         /// The preset select.\r
         /// </summary>\r
index db7c608ff08b8cde64a29da8a2f4efa5a1100737..f48902aecf8b999837b54cd22db8a5a26bcd9d3b 100644 (file)
@@ -18,6 +18,7 @@ namespace HandBrakeWPF.ViewModels
     using System.Linq;\r
     using System.Threading;\r
     using System.Windows;\r
+    using System.Windows.Data;\r
     using System.Windows.Input;\r
 \r
     using Caliburn.Micro;\r
@@ -206,7 +207,7 @@ namespace HandBrakeWPF.ViewModels
             this.queueProcessor.EncodeService.EncodeStatusChanged += this.EncodeStatusChanged;\r
             this.userSettingService.SettingChanged += this.UserSettingServiceSettingChanged;\r
 \r
-            this.Presets = this.presetService.Presets;\r
+            this.Presets = new BindingList<IPresetObject>();\r
             this.Drives = new BindingList<SourceMenuItem>();\r
 \r
             // Set Process Priority\r
@@ -359,22 +360,30 @@ namespace HandBrakeWPF.ViewModels
         /// <summary>\r
         /// Gets or sets Presets.\r
         /// </summary>\r
-        public IEnumerable<Preset> Presets { get; set; }\r
+        public IEnumerable<IPresetObject> Presets { get; set; }\r
 \r
         /// <summary>\r
         /// Gets or sets SelectedPreset.\r
         /// </summary>\r
-        public Preset SelectedPreset\r
+        public object SelectedPreset\r
         {\r
             get\r
             {\r
                 return this.selectedPreset;\r
             }\r
+\r
             set\r
             {\r
-                this.selectedPreset = value;\r
+                if (value == null || value.GetType() != typeof(Preset))\r
+                {\r
+                    return;\r
+                }\r
+\r
+                this.selectedPreset = (Preset)value;\r
 \r
-                if (this.SelectedPreset != null)\r
+                this.presetService.SetSelected(selectedPreset);\r
+  \r
+                if (this.selectedPreset != null)\r
                 {\r
                     // Main Window Settings\r
                     this.OptimizeMP4 = selectedPreset.Task.OptimizeMP4;\r
@@ -382,14 +391,14 @@ namespace HandBrakeWPF.ViewModels
                     this.SelectedOutputFormat = selectedPreset.Task.OutputFormat;\r
 \r
                     // Tab Settings\r
-                    this.PictureSettingsViewModel.SetPreset(this.SelectedPreset, this.CurrentTask);\r
-                    this.VideoViewModel.SetPreset(this.SelectedPreset, this.CurrentTask);\r
-                    this.FiltersViewModel.SetPreset(this.SelectedPreset, this.CurrentTask);\r
-                    this.AudioViewModel.SetPreset(this.SelectedPreset, this.CurrentTask);\r
-                    this.SubtitleViewModel.SetPreset(this.SelectedPreset, this.CurrentTask);\r
-                    this.ChaptersViewModel.SetPreset(this.SelectedPreset, this.CurrentTask);\r
-                    this.AdvancedViewModel.SetPreset(this.SelectedPreset, this.CurrentTask);\r
-                    this.MetaDataViewModel.SetPreset(this.SelectedPreset, this.CurrentTask);\r
+                    this.PictureSettingsViewModel.SetPreset(this.selectedPreset, this.CurrentTask);\r
+                    this.VideoViewModel.SetPreset(this.selectedPreset, this.CurrentTask);\r
+                    this.FiltersViewModel.SetPreset(this.selectedPreset, this.CurrentTask);\r
+                    this.AudioViewModel.SetPreset(this.selectedPreset, this.CurrentTask);\r
+                    this.SubtitleViewModel.SetPreset(this.selectedPreset, this.CurrentTask);\r
+                    this.ChaptersViewModel.SetPreset(this.selectedPreset, this.CurrentTask);\r
+                    this.AdvancedViewModel.SetPreset(this.selectedPreset, this.CurrentTask);\r
+                    this.MetaDataViewModel.SetPreset(this.selectedPreset, this.CurrentTask);\r
 \r
                     // Do this again to force an update for m4v/mp4 selection\r
                     this.SelectedOutputFormat = selectedPreset.Task.OutputFormat;\r
@@ -399,6 +408,12 @@ namespace HandBrakeWPF.ViewModels
             }\r
         }\r
 \r
+        public void TrickPresetDisplayUpdate()\r
+        {\r
+            this.NotifyOfPropertyChange(() => this.SelectedPreset);\r
+            this.selectedPreset.IsSelected = true;\r
+        }\r
+\r
         /// <summary>\r
         /// Optimise MP4 Checkbox\r
         /// </summary>\r
@@ -787,7 +802,7 @@ namespace HandBrakeWPF.ViewModels
                     {\r
                         if (this.userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNameFormat) != null)\r
                         {\r
-                            this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName, this.SelectedPreset);\r
+                            this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName, this.selectedPreset);\r
                         }\r
                     }\r
                     this.NotifyOfPropertyChange(() => this.CurrentTask);\r
@@ -842,7 +857,7 @@ namespace HandBrakeWPF.ViewModels
                     if (this.SelectedPointToPoint == PointToPointMode.Chapters && this.userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNameFormat) != null &&\r
                         this.userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNameFormat).Contains(Constants.Chapters))\r
                     {\r
-                        this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName, this.SelectedPreset);\r
+                        this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName, this.selectedPreset);\r
                     }\r
                 }\r
 \r
@@ -871,7 +886,7 @@ namespace HandBrakeWPF.ViewModels
                 if (this.SelectedPointToPoint == PointToPointMode.Chapters && this.userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNameFormat) != null &&\r
                     this.userSettingService.GetUserSetting<string>(UserSettingConstants.AutoNameFormat).Contains(Constants.Chapters))\r
                 {\r
-                    this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName, this.SelectedPreset);\r
+                    this.Destination = AutoNameHelper.AutoName(this.CurrentTask, this.SourceName, this.selectedPreset);\r
                 }\r
 \r
                 if (this.SelectedStartPoint > this.SelectedEndPoint && this.SelectedPointToPoint == PointToPointMode.Chapters)\r
@@ -1243,7 +1258,9 @@ namespace HandBrakeWPF.ViewModels
 \r
             // Setup the presets.\r
             this.presetService.Load();\r
+            this.Presets = this.presetService.Presets;\r
             this.NotifyOfPropertyChange(() => this.Presets);\r
+            this.presetService.LoadCategoryStates();\r
 \r
             // Queue Recovery\r
             bool queueRecovered = QueueRecoveryHelper.RecoverQueue(this.queueProcessor, this.errorService, StartupOptions.AutoRestartQueue);\r
@@ -1287,6 +1304,7 @@ namespace HandBrakeWPF.ViewModels
         {\r
             // Shutdown Service\r
             this.encodeService.Stop();\r
+            this.presetService.SaveCategoryStates();\r
 \r
             // Unsubscribe from Events.\r
             this.scanService.ScanStarted -= this.ScanStared;\r
@@ -1876,9 +1894,11 @@ namespace HandBrakeWPF.ViewModels
         /// </summary>\r
         public void PresetAdd()\r
         {\r
+            // TODO select the new preset.\r
             IAddPresetViewModel presetViewModel = IoC.Get<IAddPresetViewModel>();\r
             presetViewModel.Setup(this.CurrentTask, this.SelectedTitle, this.AudioViewModel.AudioBehaviours, this.SubtitleViewModel.SubtitleBehaviours);\r
-            this.windowManager.ShowWindow(presetViewModel);\r
+            this.windowManager.ShowDialog(presetViewModel);\r
+            this.NotifyOfPropertyChange(() => this.Presets);\r
         }\r
 \r
         /// <summary>\r
@@ -1894,7 +1914,7 @@ namespace HandBrakeWPF.ViewModels
                 return;\r
             }\r
 \r
-            if (this.SelectedPreset.IsBuildIn)\r
+            if (this.selectedPreset.IsBuildIn)\r
             {\r
                 this.errorService.ShowMessageBox(\r
                     Resources.Main_NoUpdateOfBuiltInPresets, Resources.Main_NoPresetSelected, MessageBoxButton.OK, MessageBoxImage.Warning);\r
@@ -1903,8 +1923,8 @@ namespace HandBrakeWPF.ViewModels
 \r
             if (this.errorService.ShowMessageBox(Resources.Main_PresetUpdateConfrimation, Resources.AreYouSure, MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)\r
             {\r
-                this.SelectedPreset.Update(new EncodeTask(this.CurrentTask), new AudioBehaviours(this.AudioViewModel.AudioBehaviours), new SubtitleBehaviours(this.SubtitleViewModel.SubtitleBehaviours));\r
-                this.presetService.Update(this.SelectedPreset);\r
+                this.selectedPreset.Update(new EncodeTask(this.CurrentTask), new AudioBehaviours(this.AudioViewModel.AudioBehaviours), new SubtitleBehaviours(this.SubtitleViewModel.SubtitleBehaviours));\r
+                this.presetService.Update(this.selectedPreset);\r
 \r
                 this.errorService.ShowMessageBox(\r
                         Resources.Main_PresetUpdated, Resources.Updated, MessageBoxButton.OK, MessageBoxImage.Information);\r
@@ -1924,7 +1944,7 @@ namespace HandBrakeWPF.ViewModels
                 return;\r
             }\r
 \r
-            if (this.SelectedPreset.IsBuildIn)\r
+            if (this.selectedPreset.IsBuildIn)\r
             {\r
                 this.errorService.ShowMessageBox(\r
                     Resources.Main_NoUpdateOfBuiltInPresets, Resources.Main_NoPresetSelected, MessageBoxButton.OK, MessageBoxImage.Warning);\r
@@ -1932,7 +1952,7 @@ namespace HandBrakeWPF.ViewModels
             }\r
 \r
             IManagePresetViewModel presetViewModel = IoC.Get<IManagePresetViewModel>();\r
-            presetViewModel.Setup(this.SelectedPreset);\r
+            presetViewModel.Setup(this.selectedPreset);\r
             this.windowManager.ShowDialog(presetViewModel);\r
             Preset preset = presetViewModel.Preset;\r
 \r
@@ -1970,6 +1990,7 @@ namespace HandBrakeWPF.ViewModels
                 }\r
 \r
                 this.presetService.Remove(this.selectedPreset);\r
+                this.NotifyOfPropertyChange(() => this.Presets);\r
             }\r
             else\r
             {\r
@@ -1985,7 +2006,6 @@ namespace HandBrakeWPF.ViewModels
             if (this.selectedPreset != null)\r
             {\r
                 this.presetService.SetDefault(this.selectedPreset);\r
-                this.NotifyOfPropertyChange(() => this.Presets);\r
                 MessageBox.Show(string.Format(Resources.Main_NewDefaultPreset, this.selectedPreset.Name), Resources.Main_Presets, MessageBoxButton.OK, MessageBoxImage.Information);\r
             }\r
             else\r
@@ -2195,14 +2215,14 @@ namespace HandBrakeWPF.ViewModels
             // Setup the Tabs\r
             if (this.selectedTitle != null)\r
             {\r
-                this.PictureSettingsViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.SelectedPreset, this.CurrentTask);\r
-                this.VideoViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.SelectedPreset, this.CurrentTask);\r
-                this.FiltersViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.SelectedPreset, this.CurrentTask);\r
-                this.AudioViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.SelectedPreset, this.CurrentTask);\r
-                this.SubtitleViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.SelectedPreset, this.CurrentTask);\r
-                this.ChaptersViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.SelectedPreset, this.CurrentTask);\r
-                this.AdvancedViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.SelectedPreset, this.CurrentTask);\r
-                this.MetaDataViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.SelectedPreset, this.CurrentTask);\r
+                this.PictureSettingsViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.selectedPreset, this.CurrentTask);\r
+                this.VideoViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.selectedPreset, this.CurrentTask);\r
+                this.FiltersViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.selectedPreset, this.CurrentTask);\r
+                this.AudioViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.selectedPreset, this.CurrentTask);\r
+                this.SubtitleViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.selectedPreset, this.CurrentTask);\r
+                this.ChaptersViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.selectedPreset, this.CurrentTask);\r
+                this.AdvancedViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.selectedPreset, this.CurrentTask);\r
+                this.MetaDataViewModel.SetSource(this.ScannedSource, this.SelectedTitle, this.selectedPreset, this.CurrentTask);\r
             }\r
         }\r
 \r
index 7d7556c8528c3b0273faab1d15dd6731ec5578c2..507ceb41d627b423514e9207167ac68e4c56cc20 100644 (file)
@@ -7,8 +7,9 @@
              xmlns:commands="clr-namespace:HandBrakeWPF.Commands"\r
              xmlns:Properties="clr-namespace:HandBrakeWPF.Properties"\r
              xmlns:cal="http://www.caliburnproject.org"\r
-             xmlns:attachedProperties="clr-namespace:HandBrakeWPF.AttachedProperties"\r
              xmlns:menu="clr-namespace:HandBrakeWPF.Commands.Menu"\r
+             xmlns:loc="clr-namespace:HandBrakeWPF.Services.Presets.Model"\r
+             xmlns:helpers="clr-namespace:HandBrakeWPF.Helpers"\r
              AllowDrop="True"\r
         FontSize="11"\r
         cal:Message.Attach="[Event Loaded] = [Action Load]"\r
@@ -21,9 +22,7 @@
         <Converters:EnumComboConverter x:Key="enumComboConverter" />\r
         <Converters:PresetsMenuConverter x:Key="presetsMenuConverter"/>\r
 \r
-\r
         <Style TargetType="Button">\r
-\r
             <Setter Property="Padding" Value="8,2" />\r
             <Setter Property="FontSize" Value="11.5" />\r
             <Setter Property="VerticalAlignment" Value="Center" />\r
             <Setter Property="Padding" Value="5,5" />\r
         </Style>\r
 \r
-        <CollectionViewSource x:Key="presetsCvs" Source="{Binding Presets}">\r
-            <CollectionViewSource.GroupDescriptions>\r
-                <PropertyGroupDescription PropertyName="Category" />\r
-            </CollectionViewSource.GroupDescriptions>\r
-        </CollectionViewSource>\r
-\r
-        <Style x:Key="ContainerStyle" TargetType="{x:Type GroupItem}">\r
-            <Setter Property="Template">\r
-                <Setter.Value>\r
-                    <ControlTemplate>\r
-                        <Expander Header="{Binding Name}" IsExpanded="True">\r
-                            <ItemsPresenter />\r
-                        </Expander>\r
-                    </ControlTemplate>\r
-                </Setter.Value>\r
-            </Setter>\r
-        </Style>\r
-\r
         <Converters:BooleanToVisibilityConverter x:Key="boolToVisConverter" />\r
 \r
     </UserControl.Resources>\r
                       Margin="0,0,5,5"\r
                       IsEnabled="{Binding HasSource, Converter={StaticResource booleanConverter}, ConverterParameter=false}"\r
                       Visibility="{Binding IsPresetPanelShowing, Converter={StaticResource boolToVisConverter}}">\r
+                \r
 \r
                 <Grid>\r
                     <Grid.RowDefinitions>\r
                         <RowDefinition Height="*" />\r
                         <RowDefinition Height="Auto" />\r
                     </Grid.RowDefinitions>\r
-\r
-                    <ListBox HorizontalAlignment="Stretch" AutomationProperties.Name="Presets List" ToolTip="{x:Static Properties:ResourcesTooltips.MainView_Presets}"\r
-                             VerticalAlignment="Stretch" ItemsSource="{Binding Source={StaticResource presetsCvs}}"\r
-                             SelectedItem="{Binding SelectedPreset, Mode=TwoWay}" BorderThickness="0,0,0,1"\r
-                             BorderBrush="LightGray"\r
-                            >\r
-                        <ListBox.Resources>\r
-\r
-                            <Style TargetType="ToolTip">\r
-                                <Style.Resources>\r
-                                    <Style TargetType="ContentPresenter">\r
-                                        <Style.Resources>\r
-                                            <Style TargetType="TextBlock">\r
-                                                <Setter Property="TextWrapping" Value="Wrap" />\r
-                                            </Style>\r
-                                        </Style.Resources>\r
+                    \r
+                    <Grid.Resources>\r
+\r
+                        <HierarchicalDataTemplate DataType="{x:Type loc:Preset}">\r
+                            <StackPanel Orientation="Horizontal" >\r
+                                <StackPanel.Resources>\r
+                                    <Style TargetType="TextBlock">\r
+                                        <Style.Triggers>\r
+                                            <DataTrigger Binding="{Binding IsDefault}" Value="True" >\r
+                                                <Setter Property="FontStyle" Value="Italic" />\r
+                                            </DataTrigger>\r
+                                            <DataTrigger Binding="{Binding IsDefault}" Value="False" >\r
+                                                <Setter Property="FontStyle" Value="Normal" />\r
+                                            </DataTrigger>\r
+                                            <DataTrigger Binding="{Binding IsSelected}" Value="True">\r
+                                                <Setter Property="FontWeight" Value="Bold"/>\r
+                                            </DataTrigger>\r
+                                        </Style.Triggers>\r
                                     </Style>\r
-                                </Style.Resources>\r
-                                <Setter Property="MaxWidth" Value="300" />\r
-                            </Style>\r
+                                </StackPanel.Resources>\r
+                                <TextBlock Text="{Binding Name}"/>\r
+                            </StackPanel>\r
+                        </HierarchicalDataTemplate>\r
 \r
-                            <Style TargetType="ListBoxItem">\r
-                                <Setter Property="Padding" Value="0,2,0,2" />\r
+                        <HierarchicalDataTemplate DataType="{x:Type loc:PresetDisplayCategory}" ItemsSource="{Binding Presets}">\r
+                            <StackPanel Orientation="Horizontal" >\r
+                                <TextBlock Text="{Binding Category}" FontSize="14" />\r
+                            </StackPanel>\r
+                        </HierarchicalDataTemplate>\r
+                    </Grid.Resources>\r
+                        \r
+                        <TreeView x:Name="presetListTree" HorizontalAlignment="Stretch" AutomationProperties.Name="Presets List" ToolTip="{x:Static Properties:ResourcesTooltips.MainView_Presets}"\r
+                                  VerticalAlignment="Stretch" BorderThickness="0,0,0,1" BorderBrush="LightGray"\r
+                                  ItemsSource="{Binding Presets}"\r
+                                  helpers:TreeViewHelper.TreeViewSelectedItem="{Binding Path=SelectedPreset, Mode=TwoWay}"\r
+                                  PreviewMouseRightButtonDown="PresetListTree_OnPreviewMouseRightButtonDown">\r
+\r
+                        <TreeView.ItemContainerStyle>\r
+                            <Style BasedOn="{StaticResource {x:Type TreeViewItem}}" TargetType="TreeViewItem">\r
+                                <Setter Property="HorizontalAlignment" Value="Stretch" />\r
+                                <Setter Property="Padding" Value="4" />\r
                                 <Setter Property="ToolTip" Value="{Binding Description}" />\r
                                 <Setter Property="ToolTipService.InitialShowDelay" Value="1500"/>\r
+                                <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />\r
+                                <EventSetter Event="TreeViewItem.Collapsed" Handler="PresetTreeviewItemCollasped" />\r
                                 <Style.Triggers>\r
-                                    <Trigger Property="IsSelected" Value="True">\r
-                                        <Setter Property="FontWeight" Value="Bold"/>\r
-                                        <Setter Property="Background" Value="Transparent"/>\r
+                                    <Trigger Property="HasItems" Value="True">\r
+                                        <Setter Property="Focusable" Value="false" />\r
                                     </Trigger>\r
-                                    <DataTrigger Binding="{Binding IsDefault}" Value="True" >\r
-                                        <Setter Property="FontStyle" Value="Italic" />\r
-                                    </DataTrigger>\r
-                                    <DataTrigger Binding="{Binding IsDefault}" Value="False" >\r
-                                        <Setter Property="FontStyle" Value="Normal" />\r
-                                    </DataTrigger>\r
+                                \r
                                 </Style.Triggers>\r
                             </Style>\r
-                        </ListBox.Resources>\r
+                        </TreeView.ItemContainerStyle>\r
                         \r
-                        <ListBox.ContextMenu>\r
+                        <TreeView.ContextMenu>\r
                             <ContextMenu AutomationProperties.Name="Presets List Context Menu">\r
                                 <MenuItem Header="{x:Static Properties:ResourcesUI.MainView_SetDefault}" cal:Message.Attach="[Event Click] = [Action PresetSetDefault]" />\r
                                 <Separator />\r
                                 <MenuItem Header="{x:Static Properties:ResourcesUI.MainView_ResetBuiltInPresets}" cal:Message.Attach="[Event Click] = [Action PresetReset]" />\r
                             </ContextMenu>\r
 \r
-                        </ListBox.ContextMenu>\r
-                        \r
+                        </TreeView.ContextMenu>\r
+                   \r
                         <i:Interaction.Triggers>\r
                             <commands:InputBindingTrigger>\r
                                 <commands:InputBindingTrigger.InputBinding>\r
                             </commands:InputBindingTrigger>\r
                         </i:Interaction.Triggers>\r
 \r
-                        <ListBox.GroupStyle>\r
-                            <GroupStyle ContainerStyle="{StaticResource ContainerStyle}"/>\r
-                        </ListBox.GroupStyle>\r
-\r
-                        <ListBox.ItemTemplate>\r
-                            <DataTemplate>\r
-                                <TextBlock Text="{Binding Name}" Margin="24,0,0,0" Padding="8,1" />\r
-                            </DataTemplate>\r
-                        </ListBox.ItemTemplate>\r
-\r
-                    </ListBox>\r
+                    </TreeView>\r
 \r
                     <ToolBar Name="presetsToolBar"\r
                              Grid.Row="1"\r
                              Background="Transparent"\r
                              ToolBarTray.IsLocked="True"\r
                              Loaded="ToolBarLoaded"\r
-                             KeyboardNavigation.TabNavigation="Continue"\r
-                             >\r
+                             KeyboardNavigation.TabNavigation="Continue" >\r
 \r
                         <ToolBar.Resources>\r
                             <Style TargetType="{x:Type ToolBarPanel}">\r
         </StatusBar>\r
     </Grid>\r
 </UserControl>\r
+\r
index 636705b65e301970dd0a932100ad18dbc8d1f060..8a180cf0317f4b275a2b67eda85a798f96a4ad18 100644 (file)
@@ -9,7 +9,6 @@
 \r
 namespace HandBrakeWPF.Views\r
 {\r
-    using System;\r
     using System.Windows;\r
     using System.Windows.Controls;\r
     using System.Windows.Input;\r
@@ -86,5 +85,33 @@ namespace HandBrakeWPF.Views
             // Otherwise assume it's a main area click and add to queue.\r
             ((IMainViewModel)this.DataContext).AddToQueue();\r
         }\r
+\r
+        private void PresetTreeviewItemCollasped(object sender, RoutedEventArgs e)\r
+        {\r
+            if (e.Source.GetType() == typeof(TreeViewItem))\r
+            {\r
+                TreeViewItem item = e.Source as TreeViewItem;\r
+                if (item != null) item.IsSelected = false;\r
+            }\r
+        }\r
+\r
+        private void PresetListTree_OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)\r
+        {\r
+            TreeViewItem treeViewItem = VisualUpwardSearch(e.OriginalSource as DependencyObject);\r
+\r
+            if (treeViewItem != null)\r
+            {\r
+                treeViewItem.Focus();\r
+                e.Handled = true;\r
+            }\r
+        }\r
+\r
+        private static TreeViewItem VisualUpwardSearch(DependencyObject source)\r
+        {\r
+            while (source != null && !(source is TreeViewItem))\r
+                source = VisualTreeHelper.GetParent(source);\r
+\r
+            return source as TreeViewItem;\r
+        }\r
     }\r
 }\r