Adding icons. Progress Bar.

This commit is contained in:
Jordan Wages 2018-07-04 18:11:25 -05:00
parent 980cb790d4
commit 9af3ad400b
13 changed files with 355 additions and 19 deletions

View File

@ -1,4 +1,5 @@
using System;
using csmic;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@ -17,8 +18,12 @@ namespace butterflow_ui
/// <summary> The RegEx string for matching probed resolution. </summary>
private const string REGEX_RESOLUTION = @"Resolution\s*:\s(?<Width>\d+)x(?<Height>\d+)";
/// <summary> The RegEx string for matching the probed playback rate.. </summary>
/// <summary> The RegEx string for matching the probed playback rate. </summary>
private const string REGEX_RATE = @"Rate\s*:\s(?<Rate>\d+\.\d+) fps";
/// <summary> The RegEx string for detecting progress made when rendering a video. </summary>
private const string REGEX_PROGRESS = @"To write\:\s*\w*\s*\w*\,*\w*\s*(?<Progress>\d+\.*\d*)%";
/// <summary> An alternative RegEx string for detecting progress made when rendering a video. </summary>
private const string REGEX_PROGRESS_ALT = @"\<Rendering progress\:\s*(?<Progress>\d+\.*\d*)%\>";
/// <summary> Full pathname of the butterflow executable file. </summary>
private Lazy<string> executablePath = new Lazy<string>(() => Path.Combine(Directory.GetCurrentDirectory(), "ThirdPartyCompiled", "butterflow.exe"));
@ -26,6 +31,12 @@ namespace butterflow_ui
private string consoleOutput = string.Empty;
/// <summary> True if butterflow is running, false if not. </summary>
private bool isRunning;
/// <summary> The progress percentage as reported by butterflow. </summary>
private double progressPercentage;
/// <summary> The running butterflow process. </summary>
private Process runningProcess;
/// <summary> An input interpreter used for converting string values to numeric values. </summary>
private InputInterpreter interpreter = new InputInterpreter();
/// <summary> Event queue for all listeners interested in ParsedConsoleOutputRecieved events. </summary>
public event EventHandler<ButterflowOutputArgs> ParsedConsoleOutputRecieved;
@ -48,7 +59,7 @@ namespace butterflow_ui
}
}
/// <summary> Gets or sets a value indicating whether butterflow is currently running. </summary>
/// <summary> Gets a value indicating whether butterflow is currently running. </summary>
/// <value> True if butterflow is running, false if not. </value>
public bool IsRunning
{
@ -56,13 +67,28 @@ namespace butterflow_ui
{
return this.isRunning;
}
set
private set
{
this.isRunning = value;
OnPropertyChanged();
}
}
/// <summary> Gets the progress percentage as reported by butterflow. </summary>
/// <value> The progress percentage as reported by butterflow. </value>
public double ProgressPercentage
{
get
{
return this.progressPercentage;
}
private set
{
this.progressPercentage = value;
OnPropertyChanged();
}
}
#endregion
#region Methods
@ -76,6 +102,15 @@ namespace butterflow_ui
Run(arguments);
}
/// <summary> Kills the running instance of butterflow, cancelling its current operation. </summary>
public void Cancel()
{
if(this.IsRunning && this.runningProcess != null)
{
this.runningProcess.Kill();
}
}
/// <summary> Probes a video file. </summary>
/// <param name="videoFile"> The video file to be probed. </param>
public void Probe(string videoFile)
@ -107,6 +142,7 @@ namespace butterflow_ui
process.BeginErrorReadLine();
this.IsRunning = true;
this.runningProcess = process;
}
}
@ -116,6 +152,7 @@ namespace butterflow_ui
private void Process_Exited(object sender, EventArgs e)
{
this.IsRunning = false;
this.runningProcess = null;
}
/// <summary>
@ -131,7 +168,7 @@ namespace butterflow_ui
return;
}
//Test for resolution
// Test for resolution
var regex = new Regex(REGEX_RESOLUTION);
foreach (Match match in regex.Matches(consoleOutput))
{
@ -142,7 +179,7 @@ namespace butterflow_ui
OnParsedConsoleOutputRecieved(ButterflowOutputType.Height, height, consoleOutput);
}
//Test for playback rate
// Test for playback rate
regex = new Regex(REGEX_RATE);
foreach(Match match in regex.Matches(consoleOutput))
{
@ -150,6 +187,29 @@ namespace butterflow_ui
OnParsedConsoleOutputRecieved(ButterflowOutputType.Rate, rate, consoleOutput);
}
// Test for progress being made when rendering a video
regex = new Regex(REGEX_PROGRESS);
foreach(Match match in regex.Matches(consoleOutput))
{
var progress = match.Groups["Progress"].Value;
this.interpreter.Interpret(progress);
this.ProgressPercentage = this.interpreter.Double;
OnParsedConsoleOutputRecieved(ButterflowOutputType.Progress, progress, consoleOutput);
}
regex = new Regex(REGEX_PROGRESS_ALT);
foreach (Match match in regex.Matches(consoleOutput))
{
var progress = match.Groups["Progress"].Value;
this.interpreter.Interpret(progress);
this.ProgressPercentage = this.interpreter.Double;
OnParsedConsoleOutputRecieved(ButterflowOutputType.Progress, progress, consoleOutput);
}
}
/// <summary> Executes the parsed console output recieved action. </summary>

BIN
butterflow-ui/Icon/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
butterflow-ui/Icon/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

100
butterflow-ui/Icon/icon.svg Normal file
View File

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
viewBox="0 0 64 64"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="icon.svg">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="13.90625"
inkscape:cx="32"
inkscape:cy="32"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1858"
inkscape:window-height="1057"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs815">
<linearGradient
inkscape:collect="always"
id="linearGradient1386">
<stop
style="stop-color:#ffdc3f;stop-opacity:1;"
offset="0"
id="stop1382" />
<stop
style="stop-color:#ffc820;stop-opacity:1"
offset="1"
id="stop1384" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1386"
id="linearGradient1388"
x1="11.749363"
y1="-9.0087662"
x2="52.848633"
y2="-29.566347"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.060401,0,0,1.2239724,-1.8709853,6.7167357)" />
</defs>
<metadata
id="metadata818">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1"
transform="translate(0,48)">
<path
style="opacity:1;fill:url(#linearGradient1388);fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 10.313536,-31.470442 c 0,0 23.745103,-0.995305 21.686464,6.68764 -1.957898,7.306975 21.686464,-6.68764 21.686464,-6.68764 v 30.94088382 c 0,0 -23.644362,0.61933472 -21.686464,-6.68764042 2.469776,-9.2173294 -21.686464,6.68764042 -21.686464,6.68764042 z"
id="rect1380"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csccscc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:21.84967232px;line-height:1.25;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#ffecb4;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;"
x="35.388515"
y="7.5709825"
id="text1378"
transform="scale(1.0056423,0.99438936)"><tspan
sodipodi:role="line"
id="tspan1376"
x="35.388515"
y="7.5709825"
style="stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;fill:#ffecb4;fill-opacity:1;">UI</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
viewBox="0 0 64 64"
version="1.1"
id="SVGRoot"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="icon_plain.svg"
inkscape:export-filename="C:\Users\wages\Documents\GitHub\butterflow-ui\butterflow-ui\Icon\icon.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="13.90625"
inkscape:cx="32"
inkscape:cy="32"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1858"
inkscape:window-height="1057"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:grid-bbox="true" />
<defs
id="defs815">
<linearGradient
inkscape:collect="always"
id="linearGradient1386">
<stop
style="stop-color:#ffdc3f;stop-opacity:1;"
offset="0"
id="stop1382" />
<stop
style="stop-color:#ffc820;stop-opacity:1"
offset="1"
id="stop1384" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1386"
id="linearGradient1388"
x1="11.749363"
y1="-9.0087662"
x2="52.848633"
y2="-29.566347"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.060401,0,0,1.2239724,-1.8709853,6.7167357)" />
</defs>
<metadata
id="metadata818">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1"
transform="translate(0,48)">
<path
style="opacity:1;fill:url(#linearGradient1388);fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 10.313536,-31.470442 c 0,0 23.745103,-0.995305 21.686464,6.68764 -1.957898,7.306975 21.686464,-6.68764 21.686464,-6.68764 v 30.94088382 c 0,0 -23.644362,0.61933472 -21.686464,-6.68764042 2.469776,-9.2173294 -21.686464,6.68764042 -21.686464,6.68764042 z"
id="rect1380"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csccscc" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:21.84967232px;line-height:1.25;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#ffecb4;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
x="65.778839"
y="10.969828"
id="text1378"
transform="scale(1.0056423,0.99438936)"><tspan
sodipodi:role="line"
id="tspan1376"
x="65.778839"
y="10.969828"
style="fill:#ffecb4;fill-opacity:1;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none">UI</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -157,4 +157,13 @@
</Path>
</Viewbox>
</ControlTemplate>
<ControlTemplate x:Key="CancelIcon">
<Viewbox>
<Path Fill="#000000">
<Path.Data>
<PathGeometry Figures="M12 0c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm4.151 17.943l-4.143-4.102-4.117 4.159-1.833-1.833 4.104-4.157-4.162-4.119 1.833-1.833 4.155 4.102 4.106-4.16 1.849 1.849-4.1 4.141 4.157 4.104-1.849 1.849z" FillRule="NonZero"/>
</Path.Data>
</Path>
</Viewbox>
</ControlTemplate>
</ResourceDictionary>

View File

@ -159,6 +159,24 @@ namespace butterflow_ui.Localization {
}
}
/// <summary>
/// Looks up a localized string similar to Cancel.
/// </summary>
public static string CancelLabel {
get {
return ResourceManager.GetString("CancelLabel", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cancel the current butterflow operation..
/// </summary>
public static string CancelTooltip {
get {
return ResourceManager.GetString("CancelTooltip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Clip a subregion in the video..
/// </summary>

View File

@ -234,6 +234,12 @@
<data name="_60fpsLabel" xml:space="preserve">
<value>60 fps</value>
</data>
<data name="CancelLabel" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="CancelTooltip" xml:space="preserve">
<value>Cancel the current butterflow operation.</value>
</data>
<data name="FastPyramidsLabel" xml:space="preserve">
<value>Use Fast Pyramids</value>
</data>

View File

@ -9,7 +9,8 @@
xmlns:butterflow_ui="clr-namespace:butterflow_ui"
mc:Ignorable="d"
x:Name="butterflowUIWindow"
Title="{x:Static loc:Localization.Title}" Height="600" Width="800">
Title="{x:Static loc:Localization.Title}" Height="600" Width="800"
Icon="./Icon/icon.ico">
<Window.Resources>
<ObjectDataProvider x:Key="enumRegionTypeDataProvider" MethodName="GetValues"
ObjectType="{x:Type System:Enum}">
@ -103,12 +104,24 @@
</Grid>
</GroupBox>
</StackPanel>
<Button Grid.Column="4" Grid.Row="0" Name="btnProcess" ToolTip="{x:Static loc:Localization.ProcessTooltip}" IsEnabled="{Binding ButterflowWrapper.IsRunning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type butterflow_ui:MainWindow}}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InverseBoolConverter}}" Click="btnProcess_Click">
<StackPanel>
<ContentControl MaxWidth="32" HorizontalAlignment="Center" Name="btnRun" Template="{StaticResource RadarIcon}" />
<Label Content="{x:Static loc:Localization.ProcessLabel}" />
</StackPanel>
</Button>
<Grid Grid.Column="4" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Grid.Row="0" Name="btnProcess" ToolTip="{x:Static loc:Localization.ProcessTooltip}" IsEnabled="{Binding ButterflowWrapper.IsRunning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type butterflow_ui:MainWindow}}, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource InverseBoolConverter}}" Click="btnProcess_Click">
<StackPanel Orientation="Horizontal">
<ContentControl MaxWidth="16" HorizontalAlignment="Center" Template="{StaticResource RadarIcon}" />
<Label Content="{x:Static loc:Localization.ProcessLabel}" />
</StackPanel>
</Button>
<Button Grid.Row="1" Name="btnCancel" ToolTip="{x:Static loc:Localization.CancelTooltip}" IsEnabled="{Binding ButterflowWrapper.IsRunning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type butterflow_ui:MainWindow}}, UpdateSourceTrigger=PropertyChanged}" Click="btnProcess_Click">
<StackPanel Orientation="Horizontal">
<ContentControl MaxWidth="16" HorizontalAlignment="Center" Template="{StaticResource CancelIcon}" />
<Label Content="{x:Static loc:Localization.CancelLabel}" />
</StackPanel>
</Button>
</Grid>
<GroupBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Header="{x:Static loc:Localization.CommonOptionsGroupBox}">
<ScrollViewer>
<StackPanel>
@ -263,9 +276,27 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Auto" ScrollChanged="ScrollViewer_ScrollChanged">
<TextBlock Grid.Row="0" Name="txtConsoleOutput" Background="Black" Foreground="White" TextWrapping="Wrap" Text="{Binding ButterflowWrapper.ConsoleOutput, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type butterflow_ui:MainWindow}}, UpdateSourceTrigger=PropertyChanged}" />
</ScrollViewer>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto" ScrollChanged="ScrollViewer_ScrollChanged">
<TextBlock Name="txtConsoleOutput" Background="Black" Foreground="White" TextWrapping="Wrap" Text="{Binding ButterflowWrapper.ConsoleOutput, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type butterflow_ui:MainWindow}}, UpdateSourceTrigger=PropertyChanged}" />
</ScrollViewer>
<ProgressBar Name="progressBar" Grid.Row="1" Height="10" Minimum="0" Maximum="100" IsEnabled="{Binding ButterflowWrapper.IsRunning, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type butterflow_ui:MainWindow}}, UpdateSourceTrigger=PropertyChanged}" Value="{Binding ButterflowWrapper.ProgressPercentage, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type butterflow_ui:MainWindow}}, UpdateSourceTrigger=PropertyChanged}">
<ProgressBar.Style>
<Style TargetType="ProgressBar">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="true">
<Setter Property="Visibility" Value="Visible" />
</Trigger>
</Style.Triggers>
</Style>
</ProgressBar.Style>
</ProgressBar>
</Grid>
<gu:MediaElementWrapper Grid.Row="1" Name="mediaPreview" Stretch="Uniform" ScrubbingEnabled="True" Source="{Binding OptionsConfiguration.VideoInput, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type butterflow_ui:MainWindow}}, UpdateSourceTrigger=PropertyChanged}" MediaOpened="mediaPreview_MediaOpened" MediaEnded="mediaPreview_MediaEnded" />
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>

View File

@ -94,7 +94,8 @@ namespace butterflow_ui
this.OptionsConfiguration.Height = e.Value;
break;
case ButterflowWrapper.ButterflowOutputType.Progress:
break;
// This case doesn't need to be considered since we're binding the progress bar's value to a property on the butterflow wrapper.
// We may use this in the future, though.
default:
break;
}
@ -112,7 +113,7 @@ namespace butterflow_ui
if (result.HasValue && result.Value)
{
this.OptionsConfiguration.VideoInput = ofd.FileName;
this.ButterflowWrapper.Probe(ofd.FileName);
//Hack to get the first frame to display in the media preview element.

View File

@ -24,7 +24,7 @@ namespace butterflow_ui
private const decimal DEFAULT_SMOOTH_DERIVATIVE_STANDARD_DEVIATION = 1.1m;
private const FlowFilterType DEFAULT_FLOW_FILTER_TYPE = FlowFilterType.box;
/// <summary> An interpreter used to ensure numeric input is correctly calculated. </summary>
/// <summary> An input interpreter used for converting string values to numeric values. </summary>
private InputInterpreter interpreter = new InputInterpreter();
/// <summary> The aspect ratio used for calculating heights when the aspect ratio is locked. </summary>
private decimal aspectRatio = 0;

View File

@ -33,6 +33,9 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="csmic, Version=1.1.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\csmic.1.1.4\lib\net40\csmic.dll</HintPath>
@ -173,6 +176,11 @@
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Resource Include="icon.ico" />
<Resource Include="Icon\icon.ico" />
<Resource Include="Icon\icon.png" />
<Content Include="Icon\icon.svg" />
<Content Include="Icon\icon_plain.svg" />
<Content Include="ThirdPartyCompiled\avcodec-57.dll" />
<Content Include="ThirdPartyCompiled\avdevice-57.dll" />
<Content Include="ThirdPartyCompiled\avfilter-6.dll" />

BIN
butterflow-ui/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB