summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--win/CS/HandBrakeWPF/Controls/SplitButton/SplitMenuButton.cs295
-rw-r--r--win/CS/HandBrakeWPF/Converters/Audio/AudioEncoderConverter.cs7
-rw-r--r--win/CS/HandBrakeWPF/HandBrakeWPF.csproj7
-rw-r--r--win/CS/HandBrakeWPF/Views/AudioView.xaml19
-rw-r--r--win/CS/HandBrakeWPF/Views/SubtitlesView.xaml20
5 files changed, 326 insertions, 22 deletions
diff --git a/win/CS/HandBrakeWPF/Controls/SplitButton/SplitMenuButton.cs b/win/CS/HandBrakeWPF/Controls/SplitButton/SplitMenuButton.cs
new file mode 100644
index 000000000..46e662620
--- /dev/null
+++ b/win/CS/HandBrakeWPF/Controls/SplitButton/SplitMenuButton.cs
@@ -0,0 +1,295 @@
+// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="SplitMenuButton.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 Split Menu Button Control
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.Controls.SplitButton
+{
+ using System;
+ using System.Collections.ObjectModel;
+ using System.Windows;
+ using System.Windows.Controls;
+ using System.Windows.Input;
+
+ /// <summary>
+ /// A Split Menu Button Control
+ /// </summary>
+ [TemplatePart(Name = SplitElementName, Type = typeof(UIElement))]
+ public class SplitMenuButton : Button
+ {
+ #region Fields and Constants
+
+ /// <summary>
+ /// The split element name.
+ /// </summary>
+ private const string SplitElementName = "SplitElement";
+
+ /// <summary>
+ /// The item source for the context menu
+ /// </summary>
+ private readonly ObservableCollection<object> itemSource = new ObservableCollection<object>();
+
+ /// <summary>
+ /// The is mouse over split element.
+ /// </summary>
+ private bool IsMouseOverSplitElement;
+
+ /// <summary>
+ /// The context menu.
+ /// </summary>
+ private ContextMenu contextMenu;
+
+ /// <summary>
+ /// The context menu initial offset.
+ /// </summary>
+ private Point contextMenuInitialOffset;
+
+ /// <summary>
+ /// The logical child.
+ /// </summary>
+ private DependencyObject logicalChild;
+
+ /// <summary>
+ /// The split element.
+ /// </summary>
+ private UIElement splitElement;
+
+ #endregion
+
+ #region Constructors and Destructors
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SplitMenuButton" /> class.
+ /// </summary>
+ public SplitMenuButton()
+ {
+ this.DefaultStyleKey = typeof(SplitMenuButton);
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ /// <summary>
+ /// Gets the ItemSource for the Context Menu
+ /// </summary>
+ public Collection<object> ItemSource
+ {
+ get
+ {
+ return this.itemSource;
+ }
+ }
+
+ #endregion
+
+ #region Public Methods and Operators
+
+ /// <summary>
+ /// Called when the template is changed.
+ /// </summary>
+ public override void OnApplyTemplate()
+ {
+ // Unhook existing handlers
+ if (this.splitElement != null)
+ {
+ this.splitElement.MouseEnter -= this.SplitElement_MouseEnter;
+ this.splitElement.MouseLeave -= this.SplitElement_MouseLeave;
+ this.splitElement = null;
+ }
+ if (this.contextMenu != null)
+ {
+ this.contextMenu.Opened -= this.ContextMenu_Opened;
+ this.contextMenu.Closed -= this.ContextMenu_Closed;
+ this.contextMenu = null;
+ }
+
+ if (this.logicalChild != null)
+ {
+ this.RemoveLogicalChild(this.logicalChild);
+ this.logicalChild = null;
+ }
+
+ // Apply new template
+ base.OnApplyTemplate();
+
+ // Hook new event handlers
+ this.splitElement = this.GetTemplateChild(SplitElementName) as UIElement;
+ if (this.splitElement != null)
+ {
+ this.splitElement.MouseEnter += this.SplitElement_MouseEnter;
+ this.splitElement.MouseLeave += this.SplitElement_MouseLeave;
+
+ this.contextMenu = ContextMenuService.GetContextMenu(this.splitElement);
+ if (this.contextMenu != null)
+ {
+ // Add the ContextMenu as a logical child (for DataContext and RoutedCommands)
+ this.contextMenu.IsOpen = true;
+ DependencyObject current = this.contextMenu;
+ do
+ {
+ this.logicalChild = current;
+ current = LogicalTreeHelper.GetParent(current);
+ }
+ while (null != current);
+
+ this.contextMenu.IsOpen = false;
+ this.AddLogicalChild(this.logicalChild);
+
+ this.contextMenu.Opened += this.ContextMenu_Opened;
+ this.contextMenu.Closed += this.ContextMenu_Closed;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Called when the Button is clicked.
+ /// </summary>
+ protected override void OnClick()
+ {
+ if (this.IsMouseOverSplitElement)
+ {
+ this.OpenButtonMenu();
+ }
+ else
+ {
+ base.OnClick();
+ }
+ }
+
+ /// <summary>
+ /// Called when a key is pressed.
+ /// </summary>
+ /// <param name="e">
+ /// The e.
+ /// </param>
+ protected override void OnKeyDown(KeyEventArgs e)
+ {
+ if (null == e)
+ {
+ throw new ArgumentNullException("e");
+ }
+
+ if (Key.Down == e.Key || Key.Up == e.Key)
+ {
+ this.Dispatcher.BeginInvoke((Action)this.OpenButtonMenu);
+ }
+ else
+ {
+ base.OnKeyDown(e);
+ }
+ }
+
+ /// <summary>
+ /// The open button menu.
+ /// </summary>
+ protected void OpenButtonMenu()
+ {
+ if ((0 < this.ItemSource.Count) && (null != this.contextMenu))
+ {
+ this.contextMenu.HorizontalOffset = 0;
+ this.contextMenu.VerticalOffset = 0;
+ this.contextMenu.IsOpen = true;
+ }
+ }
+
+ /// <summary>
+ /// The context menu closed.
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The RoutedEventArgs.
+ /// </param>
+ private void ContextMenu_Closed(object sender, RoutedEventArgs e)
+ {
+ this.LayoutUpdated -= this.SplitButton_LayoutUpdated;
+ this.Focus();
+ }
+
+ /// <summary>
+ /// The context menu opened.
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The RoutedEventArgs.
+ /// </param>
+ private void ContextMenu_Opened(object sender, RoutedEventArgs e)
+ {
+ this.contextMenuInitialOffset = this.TranslatePoint(new Point(0, this.ActualHeight), this.contextMenu);
+ this.UpdateContextMenuOffsets();
+ this.LayoutUpdated += this.SplitButton_LayoutUpdated;
+ }
+
+ /// <summary>
+ /// The split button layout updated.
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The EventArgs.
+ /// </param>
+ private void SplitButton_LayoutUpdated(object sender, EventArgs e)
+ {
+ this.UpdateContextMenuOffsets();
+ }
+
+ /// <summary>
+ /// The split element_ mouse enter.
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The MouseEventArgs.
+ /// </param>
+ private void SplitElement_MouseEnter(object sender, MouseEventArgs e)
+ {
+ this.IsMouseOverSplitElement = true;
+ }
+
+ /// <summary>
+ /// The split element mouse leave.
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The MouseEventArgs
+ /// </param>
+ private void SplitElement_MouseLeave(object sender, MouseEventArgs e)
+ {
+ this.IsMouseOverSplitElement = false;
+ }
+
+ /// <summary>
+ /// The update context menu offsets.
+ /// </summary>
+ private void UpdateContextMenuOffsets()
+ {
+ var currentOffset = new Point();
+ Point desiredOffset = this.contextMenuInitialOffset;
+
+ this.contextMenu.HorizontalOffset = desiredOffset.X - currentOffset.X;
+ this.contextMenu.VerticalOffset = desiredOffset.Y - currentOffset.Y;
+ if (FlowDirection.RightToLeft == this.FlowDirection)
+ {
+ this.contextMenu.HorizontalOffset *= -1;
+ }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrakeWPF/Converters/Audio/AudioEncoderConverter.cs b/win/CS/HandBrakeWPF/Converters/Audio/AudioEncoderConverter.cs
index 27cb2e5de..0b1c2258d 100644
--- a/win/CS/HandBrakeWPF/Converters/Audio/AudioEncoderConverter.cs
+++ b/win/CS/HandBrakeWPF/Converters/Audio/AudioEncoderConverter.cs
@@ -73,7 +73,12 @@ namespace HandBrakeWPF.Converters.Audio
return EnumHelper<AudioEncoder>.GetEnumDisplayValuesSubset(encoders);
}
- return EnumHelper<AudioEncoder>.GetDisplay((AudioEncoder)values[0]);
+ if (values.Any())
+ {
+ return EnumHelper<AudioEncoder>.GetDisplay((AudioEncoder)values[0]);
+ }
+
+ return EnumHelper<AudioEncoder>.GetDisplay(AudioEncoder.ffaac);
}
/// <summary>
diff --git a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj
index 331bbc331..204774d82 100644
--- a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj
+++ b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj
@@ -100,6 +100,7 @@
<HintPath>..\libraries\OokiiDialogs\Ookii.Dialogs.Wpf.dll</HintPath>
</Reference>
<Reference Include="PresentationFramework" />
+ <Reference Include="PresentationFramework.Aero" />
<Reference Include="System" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Drawing" />
@@ -133,6 +134,7 @@
<Compile Include="Commands\SourceMenuCommand.cs" />
<Compile Include="Commands\AdvancedEncoderOptionsCommand.cs" />
<Compile Include="Constants.cs" />
+ <Compile Include="Controls\SplitButton\SplitMenuButton.cs" />
<Compile Include="ViewModels\CountdownAlertViewModel.cs" />
<Compile Include="ViewModels\Interfaces\ICountdownAlertViewModel.cs" />
<Compile Include="Views\CountdownAlertView.xaml.cs">
@@ -340,6 +342,10 @@
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
+ <Page Include="Themes\Generic.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Views\CountdownAlertView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -512,6 +518,7 @@
<ItemGroup>
<Resource Include="Views\Images\Advanced.png" />
</ItemGroup>
+ <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(ProgramFiles)\MSBuild\StyleCop\v4.*\StyleCop.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
diff --git a/win/CS/HandBrakeWPF/Views/AudioView.xaml b/win/CS/HandBrakeWPF/Views/AudioView.xaml
index c71f71858..9eaacd48f 100644
--- a/win/CS/HandBrakeWPF/Views/AudioView.xaml
+++ b/win/CS/HandBrakeWPF/Views/AudioView.xaml
@@ -10,6 +10,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:NumericUpDown="clr-namespace:EagleBoost.Wpf.Presentation.Controls.NumericUpDown;assembly=EagleBoost.Wpf.Presentation"
xmlns:dropButton="clr-namespace:HandBrakeWPF.Controls.DropButton"
+ xmlns:splitButton="clr-namespace:HandBrakeWPF.Controls.SplitButton"
d:DesignHeight="170"
d:DesignWidth="616"
mc:Ignorable="d"
@@ -43,16 +44,14 @@
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
- <dropButton:DropButton Content="Add Track" FontWeight="Bold" Margin="0,0,10,0" Style="{StaticResource DropButtonStyle}">
- <dropButton:DropButton.DropDown>
- <ContextMenu>
- <MenuItem Header="Add New Track" cal:Message.Attach="[Event Click] = [Action Add]" />
- <MenuItem Header="Add All Remaining Tracks" cal:Message.Attach="[Event Click] = [Action AddAllRemaining]" />
- <MenuItem Header="Add All Remaining Selected Languages" cal:Message.Attach="[Event Click] = [Action AddAllRemainingForSelectedLanguages]" />
- </ContextMenu>
- </dropButton:DropButton.DropDown>
- </dropButton:DropButton>
-
+ <splitButton:SplitMenuButton Content="Add Track" cal:Message.Attach="[Event Click] = [Action Add]" FontWeight="Bold" Margin="0,0,10,0">
+ <splitButton:SplitMenuButton.ItemSource>
+ <MenuItem Header="Add New Track" cal:Message.Attach="[Event Click] = [Action Add]" />
+ <MenuItem Header="Add All Remaining Tracks" cal:Message.Attach="[Event Click] = [Action AddAllRemaining]" />
+ <MenuItem Header="Add All Remaining Selected Languages" cal:Message.Attach="[Event Click] = [Action AddAllRemainingForSelectedLanguages]" />
+ </splitButton:SplitMenuButton.ItemSource>
+ </splitButton:SplitMenuButton>
+
<Button MinWidth="65"
Margin="0,0,10,0"
cal:Message.Attach="[Event Click] = [Action Clear]"
diff --git a/win/CS/HandBrakeWPF/Views/SubtitlesView.xaml b/win/CS/HandBrakeWPF/Views/SubtitlesView.xaml
index b6a90b98f..101d8ec44 100644
--- a/win/CS/HandBrakeWPF/Views/SubtitlesView.xaml
+++ b/win/CS/HandBrakeWPF/Views/SubtitlesView.xaml
@@ -9,6 +9,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="clr-namespace:HandBrakeWPF.Controls"
xmlns:dropButton="clr-namespace:HandBrakeWPF.Controls.DropButton"
+ xmlns:splitButton="clr-namespace:HandBrakeWPF.Controls.SplitButton"
d:DesignHeight="153"
d:DesignWidth="319"
mc:Ignorable="d"
@@ -30,23 +31,20 @@
Text="Subtitles" />
<StackPanel Grid.Row="1" Margin="10,5,10,0" Orientation="Horizontal">
- <dropButton:DropButton Content="Add Track" FontWeight="Bold" Margin="0,0,10,0" Style="{StaticResource DropButtonStyle}">
- <dropButton:DropButton.DropDown>
- <ContextMenu>
- <MenuItem Header="Add New Track" cal:Message.Attach="[Event Click] = [Action Add]" />
- <MenuItem Header="Add All Remaining Tracks" cal:Message.Attach="[Event Click] = [Action AddAllRemaining]" />
- <MenuItem Header="Add All Remaining Closed Captions" cal:Message.Attach="[Event Click] = [Action AddAllClosedCaptions]" />
- <MenuItem Header="Add All Remaining Selected Languages" cal:Message.Attach="[Event Click] = [Action AddAllRemainingForSelectedLanguages]" />
- </ContextMenu>
- </dropButton:DropButton.DropDown>
- </dropButton:DropButton>
+ <splitButton:SplitMenuButton Content="Add Track" cal:Message.Attach="[Event Click] = [Action Add]" FontWeight="Bold" Margin="0,0,10,0">
+ <splitButton:SplitMenuButton.ItemSource>
+ <MenuItem Header="Add New Track" cal:Message.Attach="[Event Click] = [Action Add]" />
+ <MenuItem Header="Add All Remaining Tracks" cal:Message.Attach="[Event Click] = [Action AddAllRemaining]" />
+ <MenuItem Header="Add All Remaining Closed Captions" cal:Message.Attach="[Event Click] = [Action AddAllClosedCaptions]" />
+ <MenuItem Header="Add All Remaining Selected Languages" cal:Message.Attach="[Event Click] = [Action AddAllRemainingForSelectedLanguages]" />
+ </splitButton:SplitMenuButton.ItemSource>
+ </splitButton:SplitMenuButton>
<Button MinWidth="75"
cal:Message.Attach="[Event Click] = [Action Import]"
Content="Import SRT"
Margin="0,0,10,0"/>
<Button MinWidth="65"
- Grid.Column="3"
Margin="0,0,10,0"
cal:Message.Attach="[Event Click] = [Action Clear]"
Content="Clear" />