Skip to content

Commit 5e5e4d2

Browse files
author
RandomEngy
committed
Replaced slider with a seek bar: makes it easier to skip around without having to grab a little slider control.
1 parent ffc64af commit 5e5e4d2

8 files changed

Lines changed: 289 additions & 16 deletions

File tree

VidCoder/Controls/SeekBar.xaml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<UserControl x:Class="VidCoder.Controls.SeekBar"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
MouseLeftButtonDown="UserControl_MouseLeftButtonDown"
7+
MouseLeftButtonUp="UserControl_MouseLeftButtonUp"
8+
MouseMove="UserControl_MouseMove"
9+
mc:Ignorable="d"
10+
d:DesignHeight="41" d:DesignWidth="748">
11+
<UserControl.Resources>
12+
<Style x:Key="SeekBarMarker" TargetType="Polygon">
13+
<Setter Property="Points" Value="2,0 0,3 4,3" />
14+
<Setter Property="Fill" Value="White" />
15+
<Setter Property="HorizontalAlignment" Value="Center" />
16+
<Setter Property="VerticalAlignment" Value="Bottom" />
17+
</Style>
18+
</UserControl.Resources>
19+
<Grid>
20+
<Border
21+
Background="Black"
22+
CornerRadius="5"
23+
/>
24+
<Grid>
25+
<Grid.ColumnDefinitions>
26+
<ColumnDefinition Name="filledColumn" Width="30*" />
27+
<ColumnDefinition Name="emptyColumn" Width="70*" />
28+
</Grid.ColumnDefinitions>
29+
<Border
30+
Name="seekBarFilledBorder"
31+
Grid.Column="0"
32+
Margin="2,2,0,2"
33+
CornerRadius="5,0,0,5">
34+
<Border.Style>
35+
<Style TargetType="Border">
36+
<Style.Triggers>
37+
<DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Value="True">
38+
<Setter Property="Background">
39+
<Setter.Value>
40+
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
41+
<GradientStop Color="#6DAAED" Offset="0.0" />
42+
<GradientStop Color="#3890ED" Offset="1.0" />
43+
</LinearGradientBrush>
44+
</Setter.Value>
45+
</Setter>
46+
</DataTrigger>
47+
<DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Value="False">
48+
<Setter Property="Background">
49+
<Setter.Value>
50+
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
51+
<GradientStop Color="#999999" Offset="0.0" />
52+
<GradientStop Color="#7F7F7F" Offset="1.0" />
53+
</LinearGradientBrush>
54+
</Setter.Value>
55+
</Setter>
56+
</DataTrigger>
57+
</Style.Triggers>
58+
</Style>
59+
</Border.Style>
60+
</Border>
61+
</Grid>
62+
<Grid
63+
Name="markersGrid">
64+
</Grid>
65+
</Grid>
66+
</UserControl>

VidCoder/Controls/SeekBar.xaml.cs

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Windows;
6+
using System.Windows.Controls;
7+
using System.Windows.Data;
8+
using System.Windows.Documents;
9+
using System.Windows.Input;
10+
using System.Windows.Media;
11+
using System.Windows.Media.Imaging;
12+
using System.Windows.Navigation;
13+
using System.Windows.Shapes;
14+
15+
namespace VidCoder.Controls
16+
{
17+
/// <summary>
18+
/// Interaction logic for SeekBar.xaml
19+
/// </summary>
20+
public partial class SeekBar : UserControl
21+
{
22+
public SeekBar()
23+
{
24+
InitializeComponent();
25+
26+
this.UpdateSeekBarUI();
27+
this.UpdateMarkers();
28+
}
29+
30+
public static readonly DependencyProperty SlotProperty = DependencyProperty.Register(
31+
"Slot",
32+
typeof(int),
33+
typeof(SeekBar),
34+
new PropertyMetadata(new PropertyChangedCallback(OnSlotChanged)));
35+
public int Slot
36+
{
37+
get
38+
{
39+
return (int)GetValue(SlotProperty);
40+
}
41+
42+
set
43+
{
44+
SetValue(SlotProperty, value);
45+
}
46+
}
47+
48+
public static readonly DependencyProperty NumSlotsProperty = DependencyProperty.Register(
49+
"NumSlots",
50+
typeof(int),
51+
typeof(SeekBar),
52+
new PropertyMetadata(new PropertyChangedCallback(OnNumSlotsChanged)));
53+
public int NumSlots
54+
{
55+
get
56+
{
57+
return (int)GetValue(NumSlotsProperty);
58+
}
59+
60+
set
61+
{
62+
SetValue(NumSlotsProperty, value);
63+
}
64+
}
65+
66+
private static void OnSlotChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
67+
{
68+
if (eventArgs.NewValue != eventArgs.OldValue)
69+
{
70+
var seekBar = dependencyObject as SeekBar;
71+
72+
seekBar.UpdateSeekBarUI();
73+
}
74+
}
75+
76+
private static void OnNumSlotsChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
77+
{
78+
if (eventArgs.NewValue != eventArgs.OldValue)
79+
{
80+
var seekBar = dependencyObject as SeekBar;
81+
82+
seekBar.UpdateSeekBarUI();
83+
seekBar.UpdateMarkers();
84+
}
85+
}
86+
87+
private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
88+
{
89+
this.HandleMouseEvent(e);
90+
this.CaptureMouse();
91+
}
92+
93+
private void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
94+
{
95+
this.ReleaseMouseCapture();
96+
}
97+
98+
private void UserControl_MouseMove(object sender, MouseEventArgs e)
99+
{
100+
if (e.LeftButton == MouseButtonState.Pressed)
101+
{
102+
this.HandleMouseEvent(e);
103+
}
104+
}
105+
106+
private void HandleMouseEvent(MouseEventArgs e)
107+
{
108+
if (!this.IsEnabled)
109+
{
110+
return;
111+
}
112+
113+
Point location = e.GetPosition(this);
114+
115+
double width = this.ActualWidth;
116+
117+
if (location.X < 0 || location.X > this.ActualWidth)
118+
{
119+
return;
120+
}
121+
122+
double slotWidth = width / (this.NumSlots - 1);
123+
124+
int newSlot = (int)(location.X / slotWidth + 0.5);
125+
if (newSlot >= 0 && newSlot < this.NumSlots && newSlot != this.Slot)
126+
{
127+
this.Slot = newSlot;
128+
}
129+
}
130+
131+
private void UpdateSeekBarUI()
132+
{
133+
if (this.NumSlots <= 0)
134+
{
135+
return;
136+
}
137+
138+
this.filledColumn.Width = new GridLength(this.Slot, GridUnitType.Star);
139+
this.emptyColumn.Width = new GridLength(this.NumSlots - this.Slot - 1, GridUnitType.Star);
140+
141+
if (this.Slot == this.NumSlots - 1)
142+
{
143+
this.seekBarFilledBorder.CornerRadius = new CornerRadius(5);
144+
}
145+
else
146+
{
147+
this.seekBarFilledBorder.CornerRadius = new CornerRadius(5,0,0,5);
148+
}
149+
}
150+
151+
private void UpdateMarkers()
152+
{
153+
if (this.NumSlots <= 0)
154+
{
155+
return;
156+
}
157+
158+
this.markersGrid.ColumnDefinitions.Clear();
159+
this.markersGrid.Children.Clear();
160+
161+
this.markersGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.5, GridUnitType.Star) });
162+
163+
for (int i = 0; i < this.NumSlots - 2; i++)
164+
{
165+
this.markersGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1.0, GridUnitType.Star) });
166+
var marker = new Polygon
167+
{
168+
Style = this.FindResource("SeekBarMarker") as Style
169+
};
170+
171+
Grid.SetColumn(marker, i + 1);
172+
173+
this.markersGrid.Children.Add(marker);
174+
}
175+
176+
this.markersGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(0.5, GridUnitType.Star) });
177+
}
178+
}
179+
}

VidCoder/Utilities/Utilities.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,13 @@ public static string CleanFileName(string fileName)
198198
return cleanName;
199199
}
200200

201+
/// <summary>
202+
/// Creates a unique file name with the given constraints.
203+
/// </summary>
204+
/// <param name="baseName">The base file name to work with.</param>
205+
/// <param name="outputDirectory">The directory the file should be written to.</param>
206+
/// <param name="excludedPaths">Any paths to be excluded (expected to be normalized with ToLowerInvariant).</param>
207+
/// <returns>A file name that does not exist and does not match any of the given paths.</returns>
201208
public static string CreateUniqueFileName(string baseName, string outputDirectory, HashSet<string> excludedPaths)
202209
{
203210
string fileName = Path.GetFileName(baseName);

VidCoder/VidCoder.csproj

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@
180180
<Generator>MSBuild:Compile</Generator>
181181
<SubType>Designer</SubType>
182182
</Page>
183+
<Page Include="Controls\SeekBar.xaml">
184+
<SubType>Designer</SubType>
185+
<Generator>MSBuild:Compile</Generator>
186+
</Page>
183187
<Page Include="View\AddAutoPauseProcessDialog.xaml">
184188
<SubType>Designer</SubType>
185189
<Generator>MSBuild:Compile</Generator>
@@ -272,6 +276,9 @@
272276
<DependentUpon>App.xaml</DependentUpon>
273277
<SubType>Code</SubType>
274278
</Compile>
279+
<Compile Include="Controls\SeekBar.xaml.cs">
280+
<DependentUpon>SeekBar.xaml</DependentUpon>
281+
</Compile>
275282
<Compile Include="Converters\DoubleDisplayConverter.cs" />
276283
<Compile Include="Converters\EnumVisibilityConverter.cs" />
277284
<Compile Include="Converters\EnumVisibilityInverseConverter.cs" />

VidCoder/View/MainWindow.xaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,8 @@
293293
Gesture="LeftDoubleClick"
294294
Command="{Binding ToggleSourceMenuCommand}" />
295295
</Grid.InputBindings>
296+
297+
<!-- Hover effect -->
296298
<Grid
297299
Visibility="{Binding ScanningSource, Converter={StaticResource VisibilityConverter}, ConverterParameter=True}">
298300
<Border
@@ -307,6 +309,8 @@
307309
</Border.Background>
308310
</Border>
309311
</Grid>
312+
313+
<!-- Selected effect -->
310314
<Border
311315
BorderBrush="DarkBlue" CornerRadius="3"
312316
BorderThickness="1"

VidCoder/View/PreviewWindow.xaml

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<Window x:Class="VidCoder.View.PreviewWindow"
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:controls="clr-namespace:VidCoder.Controls"
45
Title="{Binding Title}"
56
Width="864" Height="514"
67
MinWidth="300" MinHeight="200"
@@ -39,7 +40,7 @@
3940
Source="{Binding PreviewImage}"
4041
Visibility="{Binding HasPreview, Converter={StaticResource VisibilityConverter}}"/>
4142
<Grid
42-
Name="previewControls" Margin="6,0,6,6" Height="66" VerticalAlignment="Bottom">
43+
Name="previewControls" Margin="6,0,6,6" Height="71" VerticalAlignment="Bottom">
4344
<Grid.Style>
4445
<Style TargetType="Grid">
4546
<Style.Triggers>
@@ -60,16 +61,12 @@
6061
</Style>
6162
</Grid.Style>
6263
<Border CornerRadius="10" Background="#111" Opacity="0.9" />
63-
<Slider
64-
Height="22" Margin="10,8,10,0" VerticalAlignment="Top"
65-
TickPlacement="BottomRight"
66-
Minimum="0"
67-
Maximum="{Binding SliderMax}"
68-
TickFrequency="1"
69-
IsSnapToTickEnabled="True"
70-
IsEnabled="{Binding SliderEnabled}"
71-
FocusVisualStyle="{x:Null}"
72-
Value="{Binding SelectedPreview}" />
64+
<controls:SeekBar
65+
Height="24" Margin="10,8,10,0" VerticalAlignment="Top"
66+
Slot="{Binding SelectedPreview, Mode=TwoWay}"
67+
NumSlots="{Binding PreviewCount, Mode=OneWay}"
68+
IsEnabled="{Binding SeekBarEnabled}"
69+
/>
7370
<StackPanel
7471
Orientation="Horizontal" Margin="0,0,0,8" VerticalAlignment="Bottom" HorizontalAlignment="Center"
7572
Visibility="{Binding GeneratingPreview, Converter={StaticResource VisibilityConverter}, ConverterParameter=True}">

VidCoder/ViewModel/MainViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ public void UpdateDriveCollection()
262262
IList<DriveInformation> newDriveCollection = this.driveService.GetDriveInformation();
263263

264264
// If our current drive is not present
265-
if (this.SelectedSource.Type == SourceType.Dvd)
265+
if (this.SelectedSource != null && this.SelectedSource.Type == SourceType.Dvd)
266266
{
267267
string currentRootDirectory = this.SelectedSource.DriveInfo.RootDirectory;
268268
bool currentDrivePresent = newDriveCollection.Any(driveInfo => driveInfo.RootDirectory == currentRootDirectory);

0 commit comments

Comments
 (0)