Files
MPF/DICUI/MainWindow.xaml.cs
Matt Nadareski c034df4266 More and more cleanup (#86)
* Namespace cleanups

* Make dump validation instanced

* Add note to Tasks

* Move stuff to DumpEnvironment

Most of the stuff in Tasks.cs acted on a single input parameter, namely a DumpEnvironment. Since that's the case, it was more logical to wrap those into DumpEnvironment and make them instance methods rather than keep them static. Due to this change, quite a few methods changed access, and some had to be marked internal due to wanting them to be tested separately.

* Gut Tasks

* One less thing in MainWindow

* Remove explicit cast

* Wrong check

* Create helper method

* Disable scan button on dump

* Remove unnecessary getters/setters

* Method name/description cleanup

* Address TODO

* Namespace cleanups

* Make dump validation instanced

* Add note to Tasks

* Move stuff to DumpEnvironment

Most of the stuff in Tasks.cs acted on a single input parameter, namely a DumpEnvironment. Since that's the case, it was more logical to wrap those into DumpEnvironment and make them instance methods rather than keep them static. Due to this change, quite a few methods changed access, and some had to be marked internal due to wanting them to be tested separately.

* Gut Tasks

* One less thing in MainWindow

* Remove explicit cast

* Wrong check

* Create helper method

* Disable scan button on dump

* Remove unnecessary getters/setters

* Method name/description cleanup

* Address TODO

* Clean up OnContentRendered

* Namespace cleanups

* Make dump validation instanced

* Add note to Tasks

* Move stuff to DumpEnvironment

Most of the stuff in Tasks.cs acted on a single input parameter, namely a DumpEnvironment. Since that's the case, it was more logical to wrap those into DumpEnvironment and make them instance methods rather than keep them static. Due to this change, quite a few methods changed access, and some had to be marked internal due to wanting them to be tested separately.

* Gut Tasks

* One less thing in MainWindow

* Remove explicit cast

* Wrong check

* Create helper method

* Disable scan button on dump

* Remove unnecessary getters/setters

* Method name/description cleanup

* Address TODO

* Clean up OnContentRendered

* Update event handlers
2018-07-05 21:34:04 -07:00

493 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using WinForms = System.Windows.Forms;
using DICUI.Data;
using DICUI.Utilities;
using DICUI.UI;
namespace DICUI
{
public partial class MainWindow : Window
{
// Private UI-related variables
private List<Drive> _drives;
private MediaType? _currentMediaType;
private List<KnownSystem?> _systems;
private List<MediaType?> _mediaTypes;
private bool _alreadyShown;
private DumpEnvironment _env;
// Option related
private Options _options;
private OptionsWindow _optionsWindow;
public MainWindow()
{
InitializeComponent();
// Initializes and load Options object
_options = new Options();
_options.Load();
// Disable buttons until we load fully
btn_StartStop.IsEnabled = false;
btn_Search.IsEnabled = false;
btn_Scan.IsEnabled = false;
}
#region Events
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
if (_alreadyShown)
return;
_alreadyShown = true;
// Populate the list of systems
lbl_Status.Content = "Creating system list, please wait!";
PopulateSystems();
// Populate the list of drives
lbl_Status.Content = "Creating drive list, please wait!";
PopulateDrives();
}
private void btn_StartStop_Click(object sender, RoutedEventArgs e)
{
// Dump or stop the dump
if ((string)btn_StartStop.Content == UIElements.StartDumping)
{
StartDumping();
}
else if ((string)btn_StartStop.Content == UIElements.StopDumping)
{
_env.CancelDumping();
btn_Scan.IsEnabled = true;
if (chk_EjectWhenDone.IsChecked == true)
_env.EjectDisc();
}
}
private void btn_OutputDirectoryBrowse_Click(object sender, RoutedEventArgs e)
{
BrowseFolder();
EnsureDiscInformation();
}
private void btn_Search_Click(object sender, RoutedEventArgs e)
{
PopulateDrives();
}
private void btn_Scan_Click(object sender, RoutedEventArgs e)
{
ScanAndShowProtection();
}
private void cmb_SystemType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// If we're on a separator, go to the next item and return
if ((cmb_SystemType.SelectedItem as KnownSystemComboBoxItem).IsHeader())
{
cmb_SystemType.SelectedIndex++;
return;
}
PopulateMediaType();
}
private void cmb_MediaType_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
// Only change the media type if the selection and not the list has changed
if (e.RemovedItems.Count == 1 && e.AddedItems.Count == 1)
{
_currentMediaType = cmb_MediaType.SelectedItem as MediaType?;
}
// TODO: This is giving people the benefit of the doubt that their change is valid
SetSupportedDriveSpeed();
GetOutputNames();
}
private void cmb_DriveLetter_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
CacheCurrentDiscType();
SetCurrentDiscType();
GetOutputNames();
SetSupportedDriveSpeed();
}
private void cmb_DriveSpeed_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
EnsureDiscInformation();
}
private void txt_OutputFilename_TextChanged(object sender, TextChangedEventArgs e)
{
EnsureDiscInformation();
}
private void txt_OutputDirectory_TextChanged(object sender, TextChangedEventArgs e)
{
EnsureDiscInformation();
}
// Toolbar Events
private void AppExitClick(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
private void AboutClick(object sender, RoutedEventArgs e)
{
MessageBox.Show($"ReignStumble - Project Lead / UI Design{Environment.NewLine}" +
$"darksabre76 - Project Co-Lead / Backend Design{Environment.NewLine}" +
$"Jakz - Feature Contributor{Environment.NewLine}" +
$"NHellFire - Feature Contributor{Environment.NewLine}" +
$"Dizzzy - Concept/Ideas/Beta tester{Environment.NewLine}", "About", MessageBoxButton.OK, MessageBoxImage.Information);
}
private void OptionsClick(object sender, RoutedEventArgs e)
{
// lazy initialization
if (_optionsWindow == null)
{
_optionsWindow = new OptionsWindow(this, _options);
_optionsWindow.Closed += delegate
{
_optionsWindow = null;
};
}
_optionsWindow.Owner = this;
_optionsWindow.WindowStartupLocation = WindowStartupLocation.CenterOwner;
_optionsWindow.Refresh();
_optionsWindow.Show();
}
public void OnOptionsUpdated()
{
GetOutputNames();
SetSupportedDriveSpeed();
}
#endregion
#region Helpers
/// <summary>
/// Populate media type according to system type
/// </summary>
private void PopulateMediaType()
{
KnownSystem? currentSystem = cmb_SystemType.SelectedItem as KnownSystemComboBoxItem;
if (currentSystem != null)
{
_mediaTypes = Validators.GetValidMediaTypes(currentSystem).ToList();
cmb_MediaType.ItemsSource = _mediaTypes;
cmb_MediaType.IsEnabled = _mediaTypes.Count > 1;
cmb_MediaType.SelectedIndex = (_mediaTypes.IndexOf(_currentMediaType) >= 0 ? _mediaTypes.IndexOf(_currentMediaType) : 0);
}
else
{
cmb_MediaType.IsEnabled = false;
cmb_MediaType.ItemsSource = null;
cmb_MediaType.SelectedIndex = -1;
}
}
/// <summary>
/// Get a complete list of supported systems and fill the combo box
/// </summary>
private void PopulateSystems()
{
_systems = Validators.CreateListOfSystems();
Dictionary<KnownSystemCategory, List<KnownSystem?>> mapping = _systems
.GroupBy(s => s.Category())
.ToDictionary(
k => k.Key,
v => v
.OrderBy(s => s.Name())
.ToList()
);
List<KnownSystemComboBoxItem> comboBoxItems = new List<KnownSystemComboBoxItem>();
foreach (var group in mapping)
{
comboBoxItems.Add(new KnownSystemComboBoxItem(group.Key));
group.Value.ForEach(system => comboBoxItems.Add(new KnownSystemComboBoxItem(system)));
}
cmb_SystemType.ItemsSource = comboBoxItems;
cmb_SystemType.SelectedIndex = 0;
btn_StartStop.IsEnabled = false;
}
/// <summary>
/// Get a complete list of active disc drives and fill the combo box
/// </summary>
/// <remarks>TODO: Find a way for this to periodically run, or have it hook to a "drive change" event</remarks>
private void PopulateDrives()
{
// Populate the list of drives and add it to the combo box
_drives = Validators.CreateListOfDrives();
cmb_DriveLetter.ItemsSource = _drives;
if (cmb_DriveLetter.Items.Count > 0)
{
cmb_DriveLetter.SelectedIndex = 0;
lbl_Status.Content = "Valid media found! Choose your Media Type";
btn_StartStop.IsEnabled = true;
btn_Scan.IsEnabled = true;
}
else
{
cmb_DriveLetter.SelectedIndex = -1;
lbl_Status.Content = "No valid media found!";
btn_StartStop.IsEnabled = false;
btn_Scan.IsEnabled = false;
}
}
/// <summary>
/// Browse for an output folder
/// </summary>
private void BrowseFolder()
{
WinForms.FolderBrowserDialog folderDialog = new WinForms.FolderBrowserDialog { ShowNewFolderButton = false, SelectedPath = System.AppDomain.CurrentDomain.BaseDirectory };
WinForms.DialogResult result = folderDialog.ShowDialog();
if (result == WinForms.DialogResult.OK)
{
txt_OutputDirectory.Text = folderDialog.SelectedPath;
}
}
/// <summary>
/// Create a DumpEnvironment with all current settings
/// </summary>
/// <returns>Filled DumpEnvironment instance</returns>
private DumpEnvironment DetermineEnvironment()
{
return new DumpEnvironment()
{
// Paths to tools
SubdumpPath = _options.subdumpPath,
DICPath = _options.dicPath,
OutputDirectory = txt_OutputDirectory.Text,
OutputFilename = txt_OutputFilename.Text,
// Get the currently selected options
Drive = cmb_DriveLetter.SelectedItem as Drive,
DICParameters = txt_Parameters.Text,
System = cmb_SystemType.SelectedItem as KnownSystemComboBoxItem,
Type = cmb_MediaType.SelectedItem as MediaType?
};
}
/// <summary>
/// Begin the dumping process using the given inputs
/// </summary>
private async void StartDumping()
{
_env = DetermineEnvironment();
btn_StartStop.Content = UIElements.StopDumping;
btn_Scan.IsEnabled = false;
lbl_Status.Content = "Beginning dumping process";
Result result = await _env.StartDumping();
lbl_Status.Content = result ? "Dumping complete!" : result.Message;
btn_StartStop.Content = UIElements.StartDumping;
btn_Scan.IsEnabled = true;
if (chk_EjectWhenDone.IsChecked == true)
_env.EjectDisc();
}
/// <summary>
/// Ensure information is consistent with the currently selected disc type
/// </summary>
private void EnsureDiscInformation()
{
// Get the current environment information
_env = DetermineEnvironment();
// Take care of null cases
if (_env.System == null)
_env.System = KnownSystem.NONE;
if (_env.Type == null)
_env.Type = MediaType.NONE;
// Get the status to write out
Result result = Validators.GetSupportStatus(_env.System, _env.Type);
lbl_Status.Content = result.Message;
// Set the index for the current disc type
SetCurrentDiscType();
btn_StartStop.IsEnabled = result && (_drives != null && _drives.Count > 0 ? true : false);
// If we're in a type that doesn't support drive speeds
cmb_DriveSpeed.IsEnabled = _env.Type.DoesSupportDriveSpeed() && _env.System.DoesSupportDriveSpeed();
// Special case for Custom input
if (_env.System == KnownSystem.Custom)
{
txt_Parameters.IsEnabled = true;
txt_OutputFilename.IsEnabled = false;
txt_OutputDirectory.IsEnabled = false;
btn_OutputDirectoryBrowse.IsEnabled = false;
cmb_DriveLetter.IsEnabled = false;
cmb_DriveSpeed.IsEnabled = false;
btn_StartStop.IsEnabled = (_drives.Count > 0 ? true : false);
lbl_Status.Content = "User input mode";
}
else
{
txt_Parameters.IsEnabled = false;
txt_OutputFilename.IsEnabled = true;
txt_OutputDirectory.IsEnabled = true;
btn_OutputDirectoryBrowse.IsEnabled = true;
cmb_DriveLetter.IsEnabled = true;
// Generate the full parameters from the environment
string generated = _env.GetFullParameters((int?)cmb_DriveSpeed.SelectedItem);
if (generated != null)
txt_Parameters.Text = generated;
}
}
/// <summary>
/// Get the default output directory name from the currently selected drive
/// </summary>
private void GetOutputNames()
{
Drive drive = cmb_DriveLetter.SelectedItem as Drive;
KnownSystem? systemType = cmb_SystemType.SelectedItem as KnownSystemComboBoxItem;
MediaType? mediaType = cmb_MediaType.SelectedItem as MediaType?;
if (drive != null
&& !String.IsNullOrWhiteSpace(drive.VolumeLabel)
&& !drive.IsFloppy
&& systemType != null
&& mediaType != null)
{
txt_OutputDirectory.Text = Path.Combine(_options.defaultOutputPath, drive.VolumeLabel);
txt_OutputFilename.Text = drive.VolumeLabel + mediaType.Extension();
}
else
{
txt_OutputDirectory.Text = _options.defaultOutputPath;
txt_OutputFilename.Text = "disc.bin";
}
}
/// <summary>
/// Scan and show copy protection for the current disc
/// </summary>
private async void ScanAndShowProtection()
{
var env = DetermineEnvironment();
if (env.Drive.Letter != default(char))
{
var tempContent = lbl_Status.Content;
lbl_Status.Content = "Scanning for copy protection... this might take a while!";
btn_StartStop.IsEnabled = false;
btn_Search.IsEnabled = false;
btn_Scan.IsEnabled = false;
string protections = await Validators.RunProtectionScanOnPath(env.Drive.Letter + ":\\");
MessageBox.Show(protections, "Detected Protection", MessageBoxButton.OK, MessageBoxImage.Information);
lbl_Status.Content = tempContent;
btn_StartStop.IsEnabled = true;
btn_Search.IsEnabled = true;
btn_Scan.IsEnabled = true;
}
}
/// <summary>
/// Set the drive speed based on reported maximum and user-defined option
/// </summary>
private async void SetSupportedDriveSpeed()
{
// Set the drive speed list that's appropriate
var values = AllowedSpeeds.GetForMediaType(_currentMediaType);
cmb_DriveSpeed.ItemsSource = values;
cmb_DriveSpeed.SelectedIndex = values.Count / 2;
// Get the current environment
_env = DetermineEnvironment();
// Get the drive speed
int speed = await _env.GetDiscSpeed();
// If we have an invalid speed, we need to jump out
// TODO: Should we disable dumping in this case?
if (speed == -1)
return;
// Choose the lower of the two speeds between the allowed speeds and the user-defined one
int chosenSpeed = Math.Min(
AllowedSpeeds.GetForMediaType(_currentMediaType).Where(s => s <= speed).Last(),
_options.preferredDumpSpeedCD
);
cmb_DriveSpeed.SelectedValue = chosenSpeed;
}
/// <summary>
/// Cache the current disc type to internal variable
/// </summary>
private void CacheCurrentDiscType()
{
// Get the drive letter from the selected item
Drive drive = cmb_DriveLetter.SelectedItem as Drive;
if (drive == null || drive.IsFloppy)
return;
// Get the current optical disc type
_currentMediaType = Validators.GetDiscType(drive.Letter);
}
/// <summary>
/// Set the current disc type in the combo box
/// </summary>
private void SetCurrentDiscType()
{
// If we have an invalid current type, we don't care and return
if (_currentMediaType == null || _currentMediaType == MediaType.NONE)
return;
// Now set the selected item, if possible
int index = _mediaTypes.FindIndex(kvp => kvp.Value == _currentMediaType);
if (index != -1)
cmb_MediaType.SelectedIndex = index;
else
lbl_Status.Content = $"Disc of type '{Converters.MediaTypeToString(_currentMediaType)}' found, but the current system does not support it!";
}
#endregion
}
}