mirror of
https://github.com/SabreTools/MPF.git
synced 2026-07-02 17:24:48 +00:00
General UI Cleanup (#438)
* Update Nuget packages to newest stable * Simplify path selection in UI * Update changelog * Fix broken normalization test * Update drive info before dumping
This commit is contained in:
@@ -7,6 +7,10 @@
|
||||
- Add .NET 6.0 to tests, remove msbuild args
|
||||
- Add HD-DVD to speed definitions
|
||||
- Add PS3 internal serial and version parsing (tjanas)
|
||||
- Update Nuget packages to newest stable
|
||||
- Simplify path selection in UI
|
||||
- Fix broken normalization test
|
||||
- Update drive info before dumping
|
||||
|
||||
### 2.4 (2022-10-26)
|
||||
- Update to DIC 20211001
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.3.4" GeneratePathProperty="true">
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.5.0" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.3">
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace MPF.Check
|
||||
if (!string.IsNullOrWhiteSpace(path))
|
||||
drive = Drive.Create(null, path);
|
||||
|
||||
var env = new DumpEnvironment(options, "", filepath, drive, knownSystem, mediaType, null);
|
||||
var env = new DumpEnvironment(options, filepath, drive, knownSystem, mediaType, null);
|
||||
|
||||
// Finally, attempt to do the output dance
|
||||
var result = env.VerifyAndSaveDumpOutput(resultProgress, protectionProgress).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
|
||||
@@ -56,9 +56,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
|
||||
<PackageReference Include="System.Management" Version="6.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
|
||||
<PackageReference Include="System.Management" Version="7.0.0" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -19,14 +19,9 @@ namespace MPF.Library
|
||||
#region Output paths
|
||||
|
||||
/// <summary>
|
||||
/// Base output directory to write files to
|
||||
/// Base output file path to write files to
|
||||
/// </summary>
|
||||
public string OutputDirectory { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Base output filename for output
|
||||
/// </summary>
|
||||
public string OutputFilename { get; private set; }
|
||||
public string OutputPath { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -87,15 +82,13 @@ namespace MPF.Library
|
||||
/// Constructor for a full DumpEnvironment object from user information
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="outputDirectory"></param>
|
||||
/// <param name="outputFilename"></param>
|
||||
/// <param name="outputPath"></param>
|
||||
/// <param name="drive"></param>
|
||||
/// <param name="system"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="parameters"></param>
|
||||
public DumpEnvironment(Options options,
|
||||
string outputDirectory,
|
||||
string outputFilename,
|
||||
string outputPath,
|
||||
Drive drive,
|
||||
RedumpSystem? system,
|
||||
MediaType? type,
|
||||
@@ -105,7 +98,7 @@ namespace MPF.Library
|
||||
this.Options = options;
|
||||
|
||||
// Output paths
|
||||
(this.OutputDirectory, this.OutputFilename) = InfoTool.NormalizeOutputPaths(outputDirectory, outputFilename);
|
||||
this.OutputPath = InfoTool.NormalizeOutputPaths(outputPath);
|
||||
|
||||
// UI information
|
||||
this.Drive = drive;
|
||||
@@ -127,20 +120,26 @@ namespace MPF.Library
|
||||
if (this.Parameters.InternalProgram != InternalProgram.DiscImageCreator)
|
||||
return;
|
||||
|
||||
// Replace all instances in the output directory
|
||||
this.OutputDirectory = this.OutputDirectory.Replace('.', '_');
|
||||
try
|
||||
{
|
||||
// Replace all instances in the output directory
|
||||
string outputDirectory = Path.GetDirectoryName(this.OutputPath);
|
||||
outputDirectory = outputDirectory.Replace(".", "_");
|
||||
|
||||
// Currently, only periods in directories matter
|
||||
// Leave the following code commented in case filename handling breaks again
|
||||
// Replace all instances in the output filename
|
||||
string outputFilename = Path.GetFileNameWithoutExtension(this.OutputPath);
|
||||
outputFilename = outputFilename.Replace(".", "_");
|
||||
|
||||
// Replace all instances in the output filename, except the extension
|
||||
//string tempFilename = Path.GetFileNameWithoutExtension(this.OutputFilename)
|
||||
// .Replace('.', '_');
|
||||
//string tempExtension = Path.GetExtension(this.OutputFilename)?.TrimStart('.');
|
||||
//this.OutputFilename = $"{tempFilename}.{tempExtension}";
|
||||
// Get the extension for recreating the path
|
||||
string outputExtension = Path.GetExtension(this.OutputPath).TrimStart('.');
|
||||
|
||||
// Assign the path to the filename as well for dumping
|
||||
((Modules.DiscImageCreator.Parameters)this.Parameters).Filename = Path.Combine(this.OutputDirectory, this.OutputFilename);
|
||||
// Rebuild the output path
|
||||
this.OutputPath = Path.Combine(outputDirectory, $"{outputFilename}.{outputExtension}");
|
||||
|
||||
// Assign the path to the filename as well for dumping
|
||||
((Modules.DiscImageCreator.Parameters)this.Parameters).Filename = this.OutputPath;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -207,28 +206,27 @@ namespace MPF.Library
|
||||
return null;
|
||||
|
||||
// Set the proper parameters
|
||||
string filename = OutputDirectory + Path.DirectorySeparatorChar + OutputFilename;
|
||||
switch (Options.InternalProgram)
|
||||
{
|
||||
case InternalProgram.Aaru:
|
||||
Parameters = new Modules.Aaru.Parameters(System, Type, Drive.Letter, filename, driveSpeed, Options);
|
||||
Parameters = new Modules.Aaru.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
|
||||
break;
|
||||
|
||||
case InternalProgram.DD:
|
||||
Parameters = new Modules.DD.Parameters(System, Type, Drive.Letter, filename, driveSpeed, Options);
|
||||
Parameters = new Modules.DD.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
|
||||
break;
|
||||
|
||||
case InternalProgram.DiscImageCreator:
|
||||
Parameters = new Modules.DiscImageCreator.Parameters(System, Type, Drive.Letter, filename, driveSpeed, Options);
|
||||
Parameters = new Modules.DiscImageCreator.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
|
||||
break;
|
||||
|
||||
case InternalProgram.Redumper:
|
||||
Parameters = new Modules.Redumper.Parameters(System, Type, Drive.Letter, filename, driveSpeed, Options);
|
||||
Parameters = new Modules.Redumper.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
|
||||
break;
|
||||
|
||||
// This should never happen, but it needs a fallback
|
||||
default:
|
||||
Parameters = new Modules.DiscImageCreator.Parameters(System, Type, Drive.Letter, filename, driveSpeed, Options);
|
||||
Parameters = new Modules.DiscImageCreator.Parameters(System, Type, Drive.Letter, this.OutputPath, driveSpeed, Options);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -280,7 +278,7 @@ namespace MPF.Library
|
||||
|
||||
// Execute internal tool
|
||||
progress?.Report(Result.Success($"Executing {Options.InternalProgram}... {(Options.ToolsInSeparateWindow ? "please wait!" : "see log for output!")}"));
|
||||
Directory.CreateDirectory(OutputDirectory);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(this.OutputPath));
|
||||
await Task.Run(() => Parameters.ExecuteInternalProgram(Options.ToolsInSeparateWindow));
|
||||
progress?.Report(Result.Success($"{Options.InternalProgram} has finished!"));
|
||||
|
||||
@@ -313,8 +311,12 @@ namespace MPF.Library
|
||||
{
|
||||
resultProgress?.Report(Result.Success("Gathering submission information... please wait!"));
|
||||
|
||||
// Get the output directory and filename separately
|
||||
string outputDirectory = Path.GetDirectoryName(this.OutputPath);
|
||||
string outputFilename = Path.GetFileName(this.OutputPath);
|
||||
|
||||
// Check to make sure that the output had all the correct files
|
||||
(bool foundFiles, List<string> missingFiles) = InfoTool.FoundAllFiles(this.OutputDirectory, this.OutputFilename, this.Parameters, false);
|
||||
(bool foundFiles, List<string> missingFiles) = InfoTool.FoundAllFiles(outputDirectory, outputFilename, this.Parameters, false);
|
||||
if (!foundFiles)
|
||||
{
|
||||
resultProgress?.Report(Result.Failure($"There were files missing from the output:\n{string.Join("\n", missingFiles)}"));
|
||||
@@ -324,8 +326,7 @@ namespace MPF.Library
|
||||
// Extract the information from the output files
|
||||
resultProgress?.Report(Result.Success("Extracting output information from output files..."));
|
||||
SubmissionInfo submissionInfo = await InfoTool.ExtractOutputInformation(
|
||||
this.OutputDirectory,
|
||||
this.OutputFilename,
|
||||
this.OutputPath,
|
||||
this.Drive,
|
||||
this.System,
|
||||
this.Type,
|
||||
@@ -378,7 +379,7 @@ namespace MPF.Library
|
||||
|
||||
// Write the text output
|
||||
resultProgress?.Report(Result.Success("Writing information to !submissionInfo.txt..."));
|
||||
(bool txtSuccess, string txtResult) = InfoTool.WriteOutputData(this.OutputDirectory, formattedValues);
|
||||
(bool txtSuccess, string txtResult) = InfoTool.WriteOutputData(outputDirectory, formattedValues);
|
||||
if (txtSuccess)
|
||||
resultProgress?.Report(Result.Success(txtResult));
|
||||
else
|
||||
@@ -388,7 +389,7 @@ namespace MPF.Library
|
||||
if (Options.ScanForProtection && Options.OutputSeparateProtectionFile)
|
||||
{
|
||||
resultProgress?.Report(Result.Success("Writing protection to !protectionInfo.txt..."));
|
||||
bool scanSuccess = InfoTool.WriteProtectionData(this.OutputDirectory, submissionInfo);
|
||||
bool scanSuccess = InfoTool.WriteProtectionData(outputDirectory, submissionInfo);
|
||||
if (scanSuccess)
|
||||
resultProgress?.Report(Result.Success("Writing complete!"));
|
||||
else
|
||||
@@ -399,7 +400,7 @@ namespace MPF.Library
|
||||
if (Options.OutputSubmissionJSON)
|
||||
{
|
||||
resultProgress?.Report(Result.Success($"Writing information to !submissionInfo.json{(Options.IncludeArtifacts ? ".gz" : string.Empty)}..."));
|
||||
bool jsonSuccess = InfoTool.WriteOutputData(this.OutputDirectory, submissionInfo, Options.IncludeArtifacts);
|
||||
bool jsonSuccess = InfoTool.WriteOutputData(outputDirectory, submissionInfo, Options.IncludeArtifacts);
|
||||
if (jsonSuccess)
|
||||
resultProgress?.Report(Result.Success("Writing complete!"));
|
||||
else
|
||||
@@ -410,7 +411,7 @@ namespace MPF.Library
|
||||
if (Options.CompressLogFiles)
|
||||
{
|
||||
resultProgress?.Report(Result.Success("Compressing log files..."));
|
||||
(bool compressSuccess, string compressResult) = InfoTool.CompressLogFiles(this.OutputDirectory, this.OutputFilename, this.Parameters);
|
||||
(bool compressSuccess, string compressResult) = InfoTool.CompressLogFiles(outputDirectory, outputFilename, this.Parameters);
|
||||
if (compressSuccess)
|
||||
resultProgress?.Report(Result.Success(compressResult));
|
||||
else
|
||||
@@ -491,12 +492,11 @@ namespace MPF.Library
|
||||
return Result.Failure("Error! Current configuration is not supported!");
|
||||
|
||||
// Fix the output paths, just in case
|
||||
(OutputDirectory, OutputFilename) = InfoTool.NormalizeOutputPaths(OutputDirectory, OutputFilename);
|
||||
this.OutputPath = InfoTool.NormalizeOutputPaths(this.OutputPath);
|
||||
|
||||
// Validate that the output path isn't on the dumping drive
|
||||
string fullOutputPath = Path.GetFullPath(Path.Combine(OutputDirectory, OutputFilename));
|
||||
if (fullOutputPath[0] == Drive.Letter)
|
||||
return Result.Failure($"Error! Cannot output to same drive that is being dumped!");
|
||||
if (this.OutputPath[0] == Drive.Letter)
|
||||
return Result.Failure("Error! Cannot output to same drive that is being dumped!");
|
||||
|
||||
// Validate that the required program exists
|
||||
if (!File.Exists(Parameters.ExecutablePath))
|
||||
@@ -505,7 +505,7 @@ namespace MPF.Library
|
||||
// Validate that the dumping drive doesn't contain the executable
|
||||
string fullExecutablePath = Path.GetFullPath(Parameters.ExecutablePath);
|
||||
if (fullExecutablePath[0] == Drive.Letter)
|
||||
return Result.Failure("$Error! Cannot dump same drive that executable resides on!");
|
||||
return Result.Failure("Error! Cannot dump same drive that executable resides on!");
|
||||
|
||||
// Validate that the current configuration is supported
|
||||
return Tools.GetSupportStatus(System, Type);
|
||||
|
||||
@@ -26,8 +26,7 @@ namespace MPF.Library
|
||||
/// <summary>
|
||||
/// Extract all of the possible information from a given input combination
|
||||
/// </summary>
|
||||
/// <param name="outputDirectory">Output folder to write to</param>
|
||||
/// <param name="outputFilename">Output filename to use as the base path</param>
|
||||
/// <param name="outputPath">Output path to write to</param>
|
||||
/// <param name="drive">Drive object representing the current drive</param>
|
||||
/// <param name="system">Currently selected system</param>
|
||||
/// <param name="mediaType">Currently selected media type</param>
|
||||
@@ -37,8 +36,7 @@ namespace MPF.Library
|
||||
/// <param name="protectionProgress">Optional protection progress callback</param>
|
||||
/// <returns>SubmissionInfo populated based on outputs, null on error</returns>
|
||||
public static async Task<SubmissionInfo> ExtractOutputInformation(
|
||||
string outputDirectory,
|
||||
string outputFilename,
|
||||
string outputPath,
|
||||
Drive drive,
|
||||
RedumpSystem? system,
|
||||
MediaType? mediaType,
|
||||
@@ -51,6 +49,10 @@ namespace MPF.Library
|
||||
if (!system.MediaTypes().Contains(mediaType))
|
||||
return null;
|
||||
|
||||
// Split the output path for easier use
|
||||
string outputDirectory = Path.GetDirectoryName(outputPath);
|
||||
string outputFilename = Path.GetFileName(outputPath);
|
||||
|
||||
// Check that all of the relevant files are there
|
||||
(bool foundFiles, List<string> missingFiles) = FoundAllFiles(outputDirectory, outputFilename, parameters, false);
|
||||
if (!foundFiles)
|
||||
@@ -1655,57 +1657,31 @@ namespace MPF.Library
|
||||
/// <summary>
|
||||
/// Normalize a split set of paths
|
||||
/// </summary>
|
||||
/// <param name="directory">Directory name to normalize</param>
|
||||
/// <param name="filename">Filename to normalize</param>
|
||||
public static (string, string) NormalizeOutputPaths(string directory, string filename)
|
||||
/// <param name="path">Path value to normalize</param>
|
||||
public static string NormalizeOutputPaths(string path)
|
||||
{
|
||||
// The easy way
|
||||
try
|
||||
{
|
||||
// Cache if we had a directory separator or not
|
||||
bool endedWithDirectorySeparator = directory.EndsWith(Path.DirectorySeparatorChar.ToString())
|
||||
|| directory.EndsWith(Path.AltDirectorySeparatorChar.ToString());
|
||||
// Trim quotes from the path
|
||||
path = path.Trim('"');
|
||||
|
||||
// Combine the path to make things separate easier
|
||||
string combinedPath = Path.Combine(directory, filename);
|
||||
// Try getting the combined path and returning that directly
|
||||
string fullPath = Path.GetFullPath(path);
|
||||
string fullDirectory = Path.GetDirectoryName(fullPath);
|
||||
string fullFile = Path.GetFileName(fullPath);
|
||||
|
||||
// If we have have a blank path, just return
|
||||
if (string.IsNullOrWhiteSpace(combinedPath))
|
||||
return (directory, filename);
|
||||
|
||||
// Now get the normalized paths
|
||||
directory = Path.GetDirectoryName(combinedPath);
|
||||
filename = Path.GetFileName(combinedPath);
|
||||
|
||||
// Take care of extra path characters
|
||||
directory = new StringBuilder(directory)
|
||||
.Replace(':', '_', 0, directory.LastIndexOf(':') == -1 ? 0 : directory.LastIndexOf(':'))
|
||||
.ToString();
|
||||
|
||||
// Sanitize the directory path
|
||||
directory = directory.Replace('?', '_');
|
||||
// Remove invalid path characters
|
||||
foreach (char c in Path.GetInvalidPathChars())
|
||||
directory = directory.Replace(c, '_');
|
||||
fullDirectory = fullDirectory.Replace(c, '_');
|
||||
|
||||
// Sanitize the filename
|
||||
filename = filename.Replace('?', '_');
|
||||
// Remove invalid filename characters
|
||||
foreach (char c in Path.GetInvalidFileNameChars())
|
||||
filename = filename.Replace(c, '_');
|
||||
|
||||
// If we had a directory separator at the end before, add it again
|
||||
if (endedWithDirectorySeparator)
|
||||
directory += Path.DirectorySeparatorChar;
|
||||
|
||||
// If we have a root directory, sanitize
|
||||
if (Directory.Exists(directory))
|
||||
{
|
||||
var possibleRootDir = new DirectoryInfo(directory);
|
||||
if (possibleRootDir.Parent == null)
|
||||
directory = directory.Replace($"{Path.DirectorySeparatorChar}{Path.DirectorySeparatorChar}", $"{Path.DirectorySeparatorChar}");
|
||||
}
|
||||
fullFile = fullFile.Replace(c, '_');
|
||||
}
|
||||
catch { }
|
||||
|
||||
return (directory, filename);
|
||||
return path;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.3.4" GeneratePathProperty="true">
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.5.0" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
|
||||
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
|
||||
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" />
|
||||
|
||||
@@ -242,7 +242,7 @@ namespace MPF.Modules
|
||||
/// </summary>
|
||||
/// <param name="parameters">String possibly representing parameters</param>
|
||||
/// <returns>True if the parameters were set correctly, false otherwise</returns>
|
||||
protected virtual bool ValidateAndSetParameters(string parameters) => true;
|
||||
protected virtual bool ValidateAndSetParameters(string parameters) => !string.IsNullOrWhiteSpace(parameters);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace MPF.Test.Library
|
||||
? Drive.Create(InternalDriveType.Floppy, letter.ToString())
|
||||
: Drive.Create(InternalDriveType.Optical, letter.ToString());
|
||||
|
||||
var env = new DumpEnvironment(options, string.Empty, string.Empty, drive, RedumpSystem.IBMPCcompatible, mediaType, parameters);
|
||||
var env = new DumpEnvironment(options, string.Empty, drive, RedumpSystem.IBMPCcompatible, mediaType, parameters);
|
||||
|
||||
bool actual = env.ParametersValid();
|
||||
Assert.Equal(expected, actual);
|
||||
|
||||
@@ -48,19 +48,18 @@ namespace MPF.Test.Library
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, null, null, null)]
|
||||
[InlineData(" ", "", " ", "")]
|
||||
[InlineData("super", "blah.bin", "super", "blah.bin")]
|
||||
[InlineData("super\\hero", "blah.bin", "super\\hero", "blah.bin")]
|
||||
[InlineData("super.hero", "blah.bin", "super.hero", "blah.bin")]
|
||||
[InlineData("superhero", "blah.rev.bin", "superhero", "blah.rev.bin")]
|
||||
[InlineData("super&hero", "blah.bin", "super&hero", "blah.bin")]
|
||||
[InlineData("superhero", "blah&foo.bin", "superhero", "blah&foo.bin")]
|
||||
public void NormalizeOutputPathsTest(string outputDirectory, string outputFilename, string expectedOutputDirectory, string expectedOutputFilename)
|
||||
[InlineData(null, null)]
|
||||
[InlineData(" ", " ")]
|
||||
[InlineData("super\\blah.bin", "super\\blah.bin")]
|
||||
[InlineData("super\\hero\\blah.bin", "super\\hero\\blah.bin")]
|
||||
[InlineData("super.hero\\blah.bin", "super.hero\\blah.bin")]
|
||||
[InlineData("superhero\\blah.rev.bin", "superhero\\blah.rev.bin")]
|
||||
[InlineData("super&hero\\blah.bin", "super&hero\\blah.bin")]
|
||||
[InlineData("superhero\\blah&foo.bin", "superhero\\blah&foo.bin")]
|
||||
public void NormalizeOutputPathsTest(string outputPath, string expectedPath)
|
||||
{
|
||||
(string actualOutputDirectory, string actualOutputFilename) = InfoTool.NormalizeOutputPaths(outputDirectory, outputFilename);
|
||||
Assert.Equal(expectedOutputDirectory, actualOutputDirectory);
|
||||
Assert.Equal(expectedOutputFilename, actualOutputFilename);
|
||||
string actualPath = InfoTool.NormalizeOutputPaths(outputPath);
|
||||
Assert.Equal(expectedPath, actualPath);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -35,12 +35,12 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.3.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Microsoft.CodeCoverage" Version="17.4.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.abstractions" Version="2.0.3" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.0.0" />
|
||||
<PackageReference Include="xunit.analyzers" Version="1.1.0" />
|
||||
<PackageReference Include="xunit.assert" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.core" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.4.2" />
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<NrtRevisionFormat>$(Version)-{chash:8}</NrtRevisionFormat>
|
||||
<NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes>
|
||||
<NrtShowRevision>false</NrtShowRevision>
|
||||
<UserSecretsId>27abb4ca-bf7a-431e-932f-49153303d5ff</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.3.4" GeneratePathProperty="true">
|
||||
<PackageReference Include="BurnOutSharp" PrivateAssets="build; analyzers" ExcludeAssets="contentFiles" Version="2.5.0" GeneratePathProperty="true">
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
|
||||
<PackageReference Include="Unclassified.NetRevisionTask" Version="0.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -60,11 +60,6 @@ namespace MPF.UI.ViewModels
|
||||
/// </summary>
|
||||
private bool _canExecuteSelectionChanged = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if TextChanged events can be executed
|
||||
/// </summary>
|
||||
private bool _canExecuteTextChanged = false;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
@@ -249,11 +244,11 @@ namespace MPF.UI.ViewModels
|
||||
public void ExitApplication() => Application.Current.Shutdown();
|
||||
|
||||
/// <summary>
|
||||
/// Set the output directory from a dialog box
|
||||
/// Set the output path from a dialog box
|
||||
/// </summary>
|
||||
public void SetOutputDirectory()
|
||||
public void SetOutputPath()
|
||||
{
|
||||
BrowseFolder();
|
||||
BrowseFile();
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
@@ -572,7 +567,7 @@ namespace MPF.UI.ViewModels
|
||||
App.Instance.EnableParametersCheckBox.Click += EnableParametersCheckBoxClick;
|
||||
App.Instance.MediaScanButton.Click += MediaScanButtonClick;
|
||||
App.Instance.UpdateVolumeLabel.Click += UpdateVolumeLabelClick;
|
||||
App.Instance.OutputDirectoryBrowseButton.Click += OutputDirectoryBrowseButtonClick;
|
||||
App.Instance.OutputPathBrowseButton.Click += OutputPathBrowseButtonClick;
|
||||
App.Instance.StartStopButton.Click += StartStopButtonClick;
|
||||
|
||||
// User Area SelectionChanged
|
||||
@@ -580,10 +575,6 @@ namespace MPF.UI.ViewModels
|
||||
App.Instance.MediaTypeComboBox.SelectionChanged += MediaTypeComboBoxSelectionChanged;
|
||||
App.Instance.DriveLetterComboBox.SelectionChanged += DriveLetterComboBoxSelectionChanged;
|
||||
App.Instance.DriveSpeedComboBox.SelectionChanged += DriveSpeedComboBoxSelectionChanged;
|
||||
|
||||
// User Area TextChanged
|
||||
App.Instance.OutputFilenameTextBox.TextChanged += OutputFilenameTextBoxTextChanged;
|
||||
App.Instance.OutputDirectoryTextBox.TextChanged += OutputDirectoryTextBoxTextChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -592,7 +583,6 @@ namespace MPF.UI.ViewModels
|
||||
private void EnableEventHandlers()
|
||||
{
|
||||
_canExecuteSelectionChanged = true;
|
||||
EnablePathEventHandlers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -601,23 +591,6 @@ namespace MPF.UI.ViewModels
|
||||
private void DisableEventHandlers()
|
||||
{
|
||||
_canExecuteSelectionChanged = false;
|
||||
DisablePathEventHandlers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enable path textbox event handlers
|
||||
/// </summary>
|
||||
private void EnablePathEventHandlers()
|
||||
{
|
||||
_canExecuteTextChanged = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disable path textbox event handlers
|
||||
/// </summary>
|
||||
private void DisablePathEventHandlers()
|
||||
{
|
||||
_canExecuteTextChanged = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -628,9 +601,8 @@ namespace MPF.UI.ViewModels
|
||||
App.Instance.OptionsMenuItem.IsEnabled = false;
|
||||
App.Instance.SystemTypeComboBox.IsEnabled = false;
|
||||
App.Instance.MediaTypeComboBox.IsEnabled = false;
|
||||
App.Instance.OutputFilenameTextBox.IsEnabled = false;
|
||||
App.Instance.OutputDirectoryTextBox.IsEnabled = false;
|
||||
App.Instance.OutputDirectoryBrowseButton.IsEnabled = false;
|
||||
App.Instance.OutputPathTextBox.IsEnabled = false;
|
||||
App.Instance.OutputPathBrowseButton.IsEnabled = false;
|
||||
App.Instance.DriveLetterComboBox.IsEnabled = false;
|
||||
App.Instance.DriveSpeedComboBox.IsEnabled = false;
|
||||
App.Instance.EnableParametersCheckBox.IsEnabled = false;
|
||||
@@ -648,9 +620,8 @@ namespace MPF.UI.ViewModels
|
||||
App.Instance.OptionsMenuItem.IsEnabled = true;
|
||||
App.Instance.SystemTypeComboBox.IsEnabled = true;
|
||||
App.Instance.MediaTypeComboBox.IsEnabled = true;
|
||||
App.Instance.OutputFilenameTextBox.IsEnabled = true;
|
||||
App.Instance.OutputDirectoryTextBox.IsEnabled = true;
|
||||
App.Instance.OutputDirectoryBrowseButton.IsEnabled = true;
|
||||
App.Instance.OutputPathTextBox.IsEnabled = true;
|
||||
App.Instance.OutputPathBrowseButton.IsEnabled = true;
|
||||
App.Instance.DriveLetterComboBox.IsEnabled = true;
|
||||
App.Instance.DriveSpeedComboBox.IsEnabled = true;
|
||||
App.Instance.EnableParametersCheckBox.IsEnabled = true;
|
||||
@@ -798,24 +769,37 @@ namespace MPF.UI.ViewModels
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Browse for an output folder
|
||||
/// Browse for an output file path
|
||||
/// </summary>
|
||||
private void BrowseFolder()
|
||||
private void BrowseFile()
|
||||
{
|
||||
string currentPath = App.Options.DefaultOutputPath;
|
||||
if (string.IsNullOrWhiteSpace(currentPath) || !Directory.Exists(currentPath))
|
||||
currentPath = System.AppDomain.CurrentDomain.BaseDirectory;
|
||||
// Get the current path, if possible
|
||||
string currentPath = App.Instance.OutputPathTextBox.Text;
|
||||
if (string.IsNullOrWhiteSpace(currentPath))
|
||||
currentPath = Path.Combine(App.Options.DefaultOutputPath, "track.bin");
|
||||
if (string.IsNullOrWhiteSpace(currentPath))
|
||||
currentPath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "track.bin");
|
||||
|
||||
WinForms.FolderBrowserDialog folderDialog = new WinForms.FolderBrowserDialog
|
||||
// Get the full path
|
||||
currentPath = Path.GetFullPath(currentPath);
|
||||
|
||||
// Get the directory
|
||||
string directory = Path.GetDirectoryName(currentPath);
|
||||
Directory.CreateDirectory(directory);
|
||||
|
||||
// Get the filename
|
||||
string filename = Path.GetFileName(currentPath);
|
||||
|
||||
WinForms.FileDialog fileDialog = new WinForms.SaveFileDialog
|
||||
{
|
||||
ShowNewFolderButton = false,
|
||||
SelectedPath = currentPath,
|
||||
FileName = filename,
|
||||
InitialDirectory = directory,
|
||||
};
|
||||
WinForms.DialogResult result = folderDialog.ShowDialog();
|
||||
WinForms.DialogResult result = fileDialog.ShowDialog();
|
||||
|
||||
if (result == WinForms.DialogResult.OK)
|
||||
{
|
||||
App.Instance.OutputDirectoryTextBox.Text = folderDialog.SelectedPath;
|
||||
App.Instance.OutputPathTextBox.Text = fileDialog.FileName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -881,39 +865,12 @@ namespace MPF.UI.ViewModels
|
||||
/// <returns>Filled DumpEnvironment instance</returns>
|
||||
private DumpEnvironment DetermineEnvironment()
|
||||
{
|
||||
// Populate the new environment
|
||||
var env = new DumpEnvironment(App.Options,
|
||||
App.Instance.OutputDirectoryTextBox.Text,
|
||||
App.Instance.OutputFilenameTextBox.Text,
|
||||
return new DumpEnvironment(App.Options,
|
||||
App.Instance.OutputPathTextBox.Text,
|
||||
App.Instance.DriveLetterComboBox.SelectedItem as Drive,
|
||||
App.Instance.SystemTypeComboBox.SelectedItem as RedumpSystemComboBoxItem,
|
||||
App.Instance.MediaTypeComboBox.SelectedItem as Element<MediaType>,
|
||||
App.Instance.ParametersTextBox.Text);
|
||||
|
||||
// Disable automatic reprocessing of the textboxes until we're done
|
||||
DisablePathEventHandlers();
|
||||
|
||||
// Save the current cursor positions
|
||||
int outputDirectorySelectionStart = App.Instance.OutputDirectoryTextBox.SelectionStart;
|
||||
int outputFilenameSelectionStart = App.Instance.OutputFilenameTextBox.SelectionStart;
|
||||
|
||||
// Set the new text
|
||||
App.Instance.OutputDirectoryTextBox.Text = env.OutputDirectory;
|
||||
App.Instance.OutputFilenameTextBox.Text = env.OutputFilename;
|
||||
|
||||
// Set the cursor position back to where it was
|
||||
App.Instance.OutputDirectoryTextBox.SelectionStart = outputDirectorySelectionStart;
|
||||
App.Instance.OutputDirectoryTextBox.SelectionLength = 0;
|
||||
App.Instance.OutputFilenameTextBox.SelectionStart = outputFilenameSelectionStart;
|
||||
App.Instance.OutputFilenameTextBox.SelectionLength = 0;
|
||||
|
||||
// Re-enable automatic reprocessing of textboxes
|
||||
EnablePathEventHandlers();
|
||||
|
||||
// Ensure the UI gets updated
|
||||
App.Instance.UpdateLayout();
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -991,33 +948,25 @@ namespace MPF.UI.ViewModels
|
||||
// Get the extension for the file for the next two statements
|
||||
string extension = Env.Parameters?.GetDefaultExtension(mediaType);
|
||||
|
||||
// Disable automatic reprocessing of the textboxes until we're done
|
||||
DisablePathEventHandlers();
|
||||
// Set the output filename, if it's not already
|
||||
if (string.IsNullOrEmpty(App.Instance.OutputPathTextBox.Text))
|
||||
{
|
||||
string label = drive?.FormattedVolumeLabel ?? systemType.LongName();
|
||||
string directory = App.Options.DefaultOutputPath;
|
||||
string filename = $"{label}{extension ?? ".bin"}";
|
||||
|
||||
// Save the current cursor positions
|
||||
int outputDirectorySelectionStart = App.Instance.OutputDirectoryTextBox.SelectionStart;
|
||||
int outputFilenameSelectionStart = App.Instance.OutputFilenameTextBox.SelectionStart;
|
||||
App.Instance.OutputPathTextBox.Text = Path.Combine(directory, label, filename);
|
||||
}
|
||||
|
||||
// Set the output filename, if we changed drives or it's not already
|
||||
if (driveChanged || string.IsNullOrEmpty(App.Instance.OutputFilenameTextBox.Text))
|
||||
App.Instance.OutputFilenameTextBox.Text = (drive?.FormattedVolumeLabel ?? systemType.LongName()) + (extension ?? ".bin");
|
||||
// Set the output filename, if we changed drives
|
||||
else if (driveChanged)
|
||||
{
|
||||
string label = drive?.FormattedVolumeLabel ?? systemType.LongName();
|
||||
string directory = Path.GetDirectoryName(App.Instance.OutputPathTextBox.Text);
|
||||
string filename = $"{label}{extension ?? ".bin"}";
|
||||
|
||||
// If the extension for the file changed, update that automatically
|
||||
else if (Path.GetExtension(App.Instance.OutputFilenameTextBox.Text) != extension)
|
||||
App.Instance.OutputFilenameTextBox.Text = Path.GetFileNameWithoutExtension(App.Instance.OutputFilenameTextBox.Text) + (extension ?? ".bin");
|
||||
|
||||
// Set the output directory, if we changed drives or it's not already
|
||||
if (driveChanged || string.IsNullOrEmpty(App.Instance.OutputDirectoryTextBox.Text))
|
||||
App.Instance.OutputDirectoryTextBox.Text = Path.Combine(App.Options.DefaultOutputPath, Path.GetFileNameWithoutExtension(App.Instance.OutputFilenameTextBox.Text) ?? string.Empty);
|
||||
|
||||
// Set the cursor position back to where it was
|
||||
App.Instance.OutputDirectoryTextBox.SelectionStart = outputDirectorySelectionStart;
|
||||
App.Instance.OutputDirectoryTextBox.SelectionLength = 0;
|
||||
App.Instance.OutputFilenameTextBox.SelectionStart = outputFilenameSelectionStart;
|
||||
App.Instance.OutputFilenameTextBox.SelectionLength = 0;
|
||||
|
||||
// Re-enable automatic reprocessing of textboxes
|
||||
EnablePathEventHandlers();
|
||||
App.Instance.OutputPathTextBox.Text = Path.Combine(directory, label, filename);
|
||||
}
|
||||
|
||||
// Ensure the UI gets updated
|
||||
App.Instance.UpdateLayout();
|
||||
@@ -1047,34 +996,9 @@ namespace MPF.UI.ViewModels
|
||||
else
|
||||
Env.Parameters.Speed = App.Instance.DriveSpeedComboBox.SelectedValue as int?;
|
||||
|
||||
// Disable automatic reprocessing of the textboxes until we're done
|
||||
DisablePathEventHandlers();
|
||||
|
||||
// Save the current cursor positions
|
||||
int outputDirectorySelectionStart = App.Instance.OutputDirectoryTextBox.SelectionStart;
|
||||
int outputFilenameSelectionStart = App.Instance.OutputFilenameTextBox.SelectionStart;
|
||||
|
||||
string trimmedPath = Env.Parameters.OutputPath?.Trim('"') ?? string.Empty;
|
||||
string outputDirectory = Path.GetDirectoryName(trimmedPath);
|
||||
string outputFilename = Path.GetFileName(trimmedPath);
|
||||
(outputDirectory, outputFilename) = InfoTool.NormalizeOutputPaths(outputDirectory, outputFilename);
|
||||
if (!string.IsNullOrWhiteSpace(outputDirectory))
|
||||
App.Instance.OutputDirectoryTextBox.Text = outputDirectory;
|
||||
else
|
||||
outputDirectory = App.Instance.OutputDirectoryTextBox.Text;
|
||||
if (!string.IsNullOrWhiteSpace(outputFilename))
|
||||
App.Instance.OutputFilenameTextBox.Text = outputFilename;
|
||||
else
|
||||
outputFilename = App.Instance.OutputFilenameTextBox.Text;
|
||||
|
||||
// Set the cursor position back to where it was
|
||||
App.Instance.OutputDirectoryTextBox.SelectionStart = outputDirectorySelectionStart;
|
||||
App.Instance.OutputDirectoryTextBox.SelectionLength = 0;
|
||||
App.Instance.OutputFilenameTextBox.SelectionStart = outputFilenameSelectionStart;
|
||||
App.Instance.OutputFilenameTextBox.SelectionLength = 0;
|
||||
|
||||
// Re-enable automatic reprocessing of textboxes
|
||||
EnablePathEventHandlers();
|
||||
trimmedPath = InfoTool.NormalizeOutputPaths(trimmedPath);
|
||||
App.Instance.OutputPathTextBox.Text = trimmedPath;
|
||||
|
||||
MediaType? mediaType = Env.Parameters.GetMediaType();
|
||||
int mediaTypeIndex = MediaTypes.FindIndex(m => m == mediaType);
|
||||
@@ -1271,6 +1195,10 @@ namespace MPF.UI.ViewModels
|
||||
// Disable all UI elements apart from dumping button
|
||||
DisableAllUIElements();
|
||||
|
||||
// Refresh the drive, if it wasn't null
|
||||
if (Env.Drive != null)
|
||||
Env.Drive.RefreshDrive();
|
||||
|
||||
// Output to the label and log
|
||||
App.Instance.StatusLabel.Text = "Starting dumping process... Please wait!";
|
||||
App.Logger.LogLn("Starting dumping process... Please wait!");
|
||||
@@ -1330,6 +1258,14 @@ namespace MPF.UI.ViewModels
|
||||
/// <returns>True if dumping should start, false otherwise</returns>
|
||||
private bool ValidateBeforeDumping()
|
||||
{
|
||||
// Validate that we have an output path of any sort
|
||||
if (string.IsNullOrWhiteSpace(Env.OutputPath))
|
||||
{
|
||||
MessageBoxResult mbresult = CustomMessageBox.Show("No output path was provided so dumping cannot continue.", "Missing Path", MessageBoxButton.OK, MessageBoxImage.Exclamation);
|
||||
App.Logger.LogLn("Dumping aborted!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate that the user explicitly wants an inactive drive to be considered for dumping
|
||||
if (!Env.Drive.MarkedActive)
|
||||
{
|
||||
@@ -1345,8 +1281,12 @@ namespace MPF.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-split the output path
|
||||
string outputDirectory = Path.GetDirectoryName(Env.OutputPath);
|
||||
string outputFilename = Path.GetFileName(Env.OutputPath);
|
||||
|
||||
// If a complete dump already exists
|
||||
(bool foundFiles, List<string> _) = InfoTool.FoundAllFiles(Env.OutputDirectory, Env.OutputFilename, Env.Parameters, true);
|
||||
(bool foundFiles, List<string> _) = InfoTool.FoundAllFiles(outputDirectory, outputFilename, Env.Parameters, true);
|
||||
if (foundFiles)
|
||||
{
|
||||
MessageBoxResult mbresult = CustomMessageBox.Show("A complete dump already exists! Are you sure you want to overwrite?", "Overwrite?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation);
|
||||
@@ -1359,7 +1299,7 @@ namespace MPF.UI.ViewModels
|
||||
|
||||
// Validate that at least some space exists
|
||||
// TODO: Tie this to the size of the disc, type of disc, etc.
|
||||
string fullPath = Path.GetFullPath(Env.OutputDirectory);
|
||||
string fullPath = Path.GetFullPath(outputDirectory);
|
||||
var driveInfo = new DriveInfo(Path.GetPathRoot(fullPath));
|
||||
if (driveInfo.AvailableFreeSpace < Math.Pow(2, 30))
|
||||
{
|
||||
@@ -1514,28 +1454,10 @@ namespace MPF.UI.ViewModels
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OutputDirectoryBrowseButton Click event
|
||||
/// Handler for OutputPathBrowseButton Click event
|
||||
/// </summary>
|
||||
private void OutputDirectoryBrowseButtonClick(object sender, RoutedEventArgs e) =>
|
||||
SetOutputDirectory();
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OutputFilenameTextBox TextInput event
|
||||
/// </summary>
|
||||
private void OutputDirectoryTextBoxTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (_canExecuteTextChanged)
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for OutputFilenameTextBox TextInput event
|
||||
/// </summary>
|
||||
private void OutputFilenameTextBoxTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (_canExecuteTextChanged)
|
||||
EnsureDiscInformation();
|
||||
}
|
||||
private void OutputPathBrowseButtonClick(object sender, RoutedEventArgs e) =>
|
||||
SetOutputPath();
|
||||
|
||||
/// <summary>
|
||||
/// Handler for StartStopButton Click event
|
||||
|
||||
@@ -119,7 +119,6 @@
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label x:Name="SystemMediaTypeLabel" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Content="System/Media Type" />
|
||||
@@ -136,16 +135,13 @@
|
||||
</ComboBox>
|
||||
<ComboBox x:Name="MediaTypeComboBox" Grid.Row="0" Grid.Column="1" Height="22" Width="140" HorizontalAlignment="Right" Style="{DynamicResource CustomComboBoxStyle}" />
|
||||
|
||||
<Label x:Name="OutputFilenameLabel" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Content="Output Filename"/>
|
||||
<TextBox x:Name="OutputFilenameTextBox" Grid.Row="1" Grid.Column="1" Height="22" VerticalContentAlignment="Center" />
|
||||
|
||||
<Label x:Name="OutputDirectoryLabel" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Content="Output Directory"/>
|
||||
<TextBox x:Name="OutputDirectoryTextBox" Grid.Row="2" Grid.Column="1" Height="22" Width="345" HorizontalAlignment="Left" VerticalContentAlignment="Center" />
|
||||
<Button x:Name="OutputDirectoryBrowseButton" Grid.Row="2" Grid.Column="1" Height="22" Width="50" HorizontalAlignment="Right" Content="Browse"
|
||||
<Label x:Name="OutputPathLabel" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Content="Output Path"/>
|
||||
<TextBox x:Name="OutputPathTextBox" Grid.Row="1" Grid.Column="1" Height="22" Width="345" HorizontalAlignment="Left" VerticalContentAlignment="Center" />
|
||||
<Button x:Name="OutputPathBrowseButton" Grid.Row="1" Grid.Column="1" Height="22" Width="50" HorizontalAlignment="Right" Content="Browse"
|
||||
Style="{DynamicResource CustomButtonStyle}"/>
|
||||
|
||||
<Label x:Name="DriveLetterLabel" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Content="Drive Letter"/>
|
||||
<ComboBox x:Name="DriveLetterComboBox" Grid.Row="3" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="Left" Style="{DynamicResource CustomComboBoxStyle}">
|
||||
<Label x:Name="DriveLetterLabel" Grid.Row="2" Grid.Column="0" VerticalAlignment="Center" Content="Drive Letter"/>
|
||||
<ComboBox x:Name="DriveLetterComboBox" Grid.Row="2" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="Left" Style="{DynamicResource CustomComboBoxStyle}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Letter}" />
|
||||
@@ -153,12 +149,12 @@
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<Label x:Name="DriveSpeedLabel" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" Content="Drive Speed"/>
|
||||
<ComboBox x:Name="DriveSpeedComboBox" Grid.Row="4" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="Left" Style="{DynamicResource CustomComboBoxStyle}" />
|
||||
<Label x:Name="DriveSpeedLabel" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" Content="Drive Speed"/>
|
||||
<ComboBox x:Name="DriveSpeedComboBox" Grid.Row="3" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="Left" Style="{DynamicResource CustomComboBoxStyle}" />
|
||||
|
||||
<Label x:Name="ParametersLabel" Grid.Row="5" Grid.Column="0" VerticalAlignment="Center" Content="Parameters"/>
|
||||
<TextBox x:Name="ParametersTextBox" Grid.Row="5" Grid.Column="1" Height="22" Width="370" HorizontalAlignment="Left" IsEnabled="False" VerticalContentAlignment="Center" />
|
||||
<CheckBox x:Name="EnableParametersCheckBox" Grid.Row="5" Grid.Column="1" Height="22" HorizontalAlignment="Right" IsChecked="False" />
|
||||
<Label x:Name="ParametersLabel" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" Content="Parameters"/>
|
||||
<TextBox x:Name="ParametersTextBox" Grid.Row="4" Grid.Column="1" Height="22" Width="370" HorizontalAlignment="Left" IsEnabled="False" VerticalContentAlignment="Center" />
|
||||
<CheckBox x:Name="EnableParametersCheckBox" Grid.Row="4" Grid.Column="1" Height="22" HorizontalAlignment="Right" IsChecked="False" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user