Refactor of ComboBox underlying types (#84)

* Split type combobox into system combobox and disc type combobox

* corrected indentation for xaml file

* fixed merge with head

* fixed format

* fixed issues for PR, added KnownSystem.CUSTOM

* removed Updater.cs which ended by error in commit

* fixed GetOuptutName() for new drive/system combobox

* Refactored KnownSystem combobox management

- created KnownSystemComboBoxItem to manage both header and system items
- totally rewrote KnownSystem category (through KnownSystemCategory enum and markers)
- fixed null access in EnsureDiscInformation caused by null _drives
- rewrote cmb_SystemType management to use new classes

* - created Drive class to keep drive letters, volume label and is floppy flag altogether
- changed all the code to use the new Drive class in combobox and in DumpEnvironment

* fixed retrieval of value from cmb_KnownSystem combobox

* removed OrderedDictionary, not needed anymore
This commit is contained in:
Jacopo Santoni
2018-07-05 20:30:52 +02:00
committed by Matt Nadareski
parent 56eaf7c2c5
commit 48de63513e
17 changed files with 334 additions and 468 deletions

View File

@@ -65,6 +65,7 @@
<Compile Include="ResultTest.cs" />
<Compile Include="TasksTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utilities\DriveTest.cs" />
<Compile Include="Utilities\ConvertersTest.cs" />
<Compile Include="Utilities\DumpInformationTest.cs" />
<Compile Include="Utilities\KnownSystemExtensionsTest.cs" />

View File

@@ -1,4 +1,5 @@
using DICUI.Data;
using DICUI.Utilities;
using Xunit;
namespace DICUI.Test
@@ -6,18 +7,18 @@ namespace DICUI.Test
public class DumpEnvironmentTest
{
[Theory]
[InlineData(null, false, MediaType.NONE, false)]
[InlineData("", false, MediaType.NONE, false)]
[InlineData("cd F test.bin 8 /c2 20", false, MediaType.CD, true)]
[InlineData("fd A test.img", true, MediaType.Floppy, true)]
[InlineData("dvd X test.iso 8 /raw", false, MediaType.Floppy, false)]
[InlineData("stop D", false, MediaType.DVD, true)]
public void IsConfigurationValidTest(string parameters, bool isFloppy, MediaType? mediaType, bool expected)
[InlineData(null, 'D', false, MediaType.NONE, false)]
[InlineData("", 'D', false, MediaType.NONE, false)]
[InlineData("cd F test.bin 8 /c2 20", 'F', false, MediaType.CD, true)]
[InlineData("fd A test.img", 'A', true, MediaType.Floppy, true)]
[InlineData("dvd X test.iso 8 /raw", 'X', false, MediaType.Floppy, false)]
[InlineData("stop D", 'D', false, MediaType.DVD, true)]
public void IsConfigurationValidTest(string parameters, char letter, bool isFloppy, MediaType? mediaType, bool expected)
{
var env = new DumpEnvironment
{
DICParameters = parameters,
IsFloppy = isFloppy,
Drive = isFloppy ? Drive.Floppy(letter) : Drive.Optical(letter, ""),
Type = mediaType,
};
@@ -44,7 +45,7 @@ namespace DICUI.Test
Assert.Equal(parameters, env.DICParameters);
Assert.Equal(expectedMediaType, env.Type);
Assert.Equal(expectedKnownSystem, env.System);
Assert.Equal(expectedDriveLetter, env.DriveLetter);
Assert.Equal(expectedDriveLetter, env.Drive.Letter);
Assert.Equal(expectedOutputDirectory, env.OutputDirectory);
Assert.Equal(expectedOutputFilename, env.OutputFilename);
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using DICUI.Data;
using DICUI.Utilities;
using Xunit;
@@ -119,5 +120,39 @@ namespace DICUI.Test.Utilities
string actual = Converters.KnownSystemToString(knownSystem);
Assert.Equal(expected, actual);
}
[Fact]
public void KnownSystemHasValidCategory()
{
var values = Validators.CreateListOfSystems();
KnownSystem[] markers = { KnownSystem.MarkerArcadeEnd, KnownSystem.MarkerConsoleEnd, KnownSystem.MarkerComputerEnd, KnownSystem.MarkerOtherEnd };
values.ForEach(system => {
if (system == KnownSystem.NONE || system == KnownSystem.Custom)
return;
// we check that the category is the first category value higher than the system
KnownSystemCategory category = ((KnownSystem?)system).Category();
KnownSystem marker = KnownSystem.NONE;
switch (category)
{
case KnownSystemCategory.Arcade: marker = KnownSystem.MarkerArcadeEnd; break;
case KnownSystemCategory.Console: marker = KnownSystem.MarkerConsoleEnd; break;
case KnownSystemCategory.Computer: marker = KnownSystem.MarkerComputerEnd; break;
case KnownSystemCategory.Other: marker = KnownSystem.MarkerOtherEnd; break;
}
Assert.NotEqual(KnownSystem.NONE, marker);
Assert.True(marker > system);
Array.ForEach(markers, mmarker =>
{
// a marker can be the same of the found one, or one of a category before or a category after but never in the middle between
// the system and the mapped category
Assert.True(mmarker == marker || mmarker < system || mmarker > marker);
});
});
}
}
}

View File

@@ -0,0 +1,21 @@
using DICUI.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
namespace DICUI.Test.Utilities
{
public class DriveTest
{
[Fact]
public void DriveConstructorsTest()
{
Assert.True(Drive.Floppy('a').IsFloppy);
Assert.False(Drive.Optical('d', "test").IsFloppy);
}
}
}

View File

@@ -1,4 +1,5 @@
using DICUI.Data;
using System;
using DICUI.Data;
using DICUI.Utilities;
using Xunit;
@@ -6,6 +7,20 @@ namespace DICUI.Test.Utilities
{
public class KnownSystemExtensionsTest
{
[Fact]
public void NameTest()
{
var values = (KnownSystem[])Enum.GetValues(typeof(KnownSystem));
Array.ForEach(values, system =>
{
string expected = Converters.KnownSystemToString(system);
string actual = ((KnownSystem?)system).Name();
Assert.Equal(expected, actual);
});
}
[Theory]
[InlineData(KnownSystem.AppleMacintosh, true)]
[InlineData(KnownSystem.MicrosoftXBOX, false)]
@@ -17,5 +32,38 @@ namespace DICUI.Test.Utilities
bool actual = knownSystem.DoesSupportDriveSpeed();
Assert.Equal(expected, actual);
}
[Fact]
public void IsMarkerTest()
{
var values = (KnownSystem[])Enum.GetValues(typeof(KnownSystem));
Array.ForEach(values, system =>
{
bool expected = system == KnownSystem.MarkerArcadeEnd || system == KnownSystem.MarkerComputerEnd ||
system == KnownSystem.MarkerOtherEnd || system == KnownSystem.MarkerConsoleEnd;
bool actual = ((KnownSystem?)system).IsMarker();
Assert.Equal(expected, actual);
});
}
[Fact]
public void CategoryNameNotEmptyTest()
{
var values = (KnownSystemCategory[])Enum.GetValues(typeof(KnownSystemCategory));
Array.ForEach(values, system =>
{
string actual = ((KnownSystem?)system).Name();
Assert.NotEqual("", actual);
});
}
}
}

View File

@@ -23,7 +23,7 @@ namespace DICUI.Test.Utilities
[Fact]
public void CreateListOfSystemsTest()
{
int expected = Enum.GetValues(typeof(KnownSystem)).Length + 4; // + 4 for the separators
int expected = Enum.GetValues(typeof(KnownSystem)).Length - 4; // - 4 for markers categories
var actual = Validators.CreateListOfSystems();
Assert.Equal(expected, actual.Count);
}

View File

@@ -92,8 +92,6 @@
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Data\Constants.cs" />
<Compile Include="External\OrderedDictionary.cs" />
<Compile Include="External\IOrderedDictionary.cs" />
<Compile Include="Options.cs" />
<Compile Include="Tasks.cs" />
<Compile Include="Utilities\DumpInformation.cs" />

View File

@@ -1,4 +1,5 @@
using System;
using DICUI.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;
@@ -12,7 +13,6 @@ namespace DICUI.Data
{
public const string StartDumping = "Start Dumping";
public const string StopDumping = "Stop Dumping";
public const string FloppyDriveString = "<<FLOPPY>>";
// Private lists of known drive speed ranges
private static IReadOnlyList<int> AllowedDriveSpeedsForCD { get; } = new List<int> { 1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72 };
@@ -50,6 +50,32 @@ namespace DICUI.Data
public static DoubleCollection AllowedDriveSpeedsForBDAsCollection { get; } = GetDoubleCollectionFromIntList(AllowedDriveSpeedsForBD);
private static DoubleCollection GetDoubleCollectionFromIntList(IReadOnlyList<int> list)
=> new DoubleCollection(list.Select(i => Convert.ToDouble(i)).ToList());
public class KnownSystemComboBoxItem
{
private object data;
public KnownSystemComboBoxItem(KnownSystem? system) => data = system;
public KnownSystemComboBoxItem(KnownSystemCategory? category) => data = category;
public Brush Foreground { get => IsHeader() ? Brushes.Gray : Brushes.Black; }
public bool IsHeader() => data is KnownSystemCategory?;
public bool IsSystem() => data is KnownSystem?;
public static implicit operator KnownSystem? (KnownSystemComboBoxItem item) => item.data as KnownSystem?;
public string Name
{
get
{
if (IsHeader())
return "---------- " + (data as KnownSystemCategory?).Name() + " ----------";
else
return (data as KnownSystem?).Name();
}
}
}
}
/// <summary>

View File

@@ -39,6 +39,8 @@
VTechVFlashVSmilePro,
ZAPiTGamesGameWaveFamilyEntertainmentSystem,
MarkerConsoleEnd,
#endregion
#region Computers
@@ -52,6 +54,8 @@
NECPC98,
SharpX68000,
MarkerComputerEnd,
#endregion
#region Arcade
@@ -110,6 +114,8 @@
TandyMemorexVisualInformationSystem,
TsunamiTsuMoMultiGameMotionSystem,
MarkerArcadeEnd,
#endregion
#region Other
@@ -127,11 +133,25 @@
TomyKissSite,
VideoCD,
MarkerOtherEnd,
#endregion
Custom = -1
Custom = 0x0EADBEEF
}
/// <summary>
/// Known system category
/// </summary>
public enum KnownSystemCategory
{
Console = 0,
Computer,
Arcade,
Other,
Custom
};
/// <summary>
/// Known media types
/// </summary>

View File

@@ -1,10 +0,0 @@
using System.Collections.Generic;
using System.Collections.Specialized;
namespace DICUI.External
{
// Adapted from https://www.codeproject.com/Articles/18615/OrderedDictionary-T-A-generic-implementation-of-IO
public interface IOrderedDictionary<TKey, TValue> : IOrderedDictionary, IDictionary<TKey, TValue>
{
}
}

View File

@@ -1,330 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
namespace DICUI.External
{
// Adapted from https://www.codeproject.com/Articles/18615/OrderedDictionary-T-A-generic-implementation-of-IO
public class OrderedDictionary<TKey, TValue> : IOrderedDictionary<TKey, TValue>
{
private List<KeyValuePair<TKey, TValue>> _list;
private Dictionary<TKey, TValue> _dictionary;
#region Interface properties
public int Count { get; private set; }
int ICollection.Count => Count;
int ICollection<KeyValuePair<TKey, TValue>>.Count => Count;
ICollection IDictionary.Keys => _dictionary.Keys;
ICollection<TKey> IDictionary<TKey, TValue>.Keys => _dictionary.Keys;
ICollection IDictionary.Values => _dictionary.Values;
ICollection<TValue> IDictionary<TKey, TValue>.Values => _dictionary.Values;
bool IDictionary.IsReadOnly => false;
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
bool IDictionary.IsFixedSize => false;
object ICollection.SyncRoot => new object();
bool ICollection.IsSynchronized => true;
public TValue this[int index]
{
get
{
return _list[index].Value;
}
set
{
if (index >= Count || index < 0)
throw new ArgumentOutOfRangeException("index",
"'index' must be non-negative and less than" +
" the size of the collection");
TKey key = _list[index].Key;
_list[index] = new KeyValuePair<TKey, TValue>(key, value);
_dictionary[key] = value;
}
}
object IOrderedDictionary.this[int index]
{
get
{
return _list[index].Value;
}
set
{
if (index >= Count || index < 0)
throw new ArgumentOutOfRangeException("index",
"'index' must be non-negative and less than" +
" the size of the collection");
var valueObj = (TValue)value;
if (valueObj == null)
throw new ArgumentException($"Value must be of type {typeof(TValue)}");
TKey key = _list[index].Key;
_list[index] = new KeyValuePair<TKey, TValue>(key, valueObj);
_dictionary[key] = valueObj;
}
}
object IDictionary.this[object key]
{
get
{
var keyObj = (TKey)key;
if (keyObj == null)
throw new ArgumentException($"Key must be of type {typeof(TKey)}");
return _dictionary[keyObj];
}
set
{
var keyObj = (TKey)key;
if (keyObj == null)
throw new ArgumentException($"Key must be of type {typeof(TKey)}");
var valueObj = (TValue)value;
if (valueObj == null)
throw new ArgumentException($"Value must be of type {typeof(TValue)}");
if (_dictionary.ContainsKey(keyObj))
{
_dictionary[keyObj] = valueObj;
_list[IndexOfKey(keyObj)] = new KeyValuePair<TKey, TValue>(keyObj, valueObj);
}
else
{
Add(keyObj, valueObj);
}
}
}
TValue IDictionary<TKey, TValue>.this[TKey key]
{
get
{
return _dictionary[key];
}
set
{
if (_dictionary.ContainsKey(key))
{
_dictionary[key] = value;
_list[IndexOfKey(key)] = new KeyValuePair<TKey, TValue>(key, value);
}
else
{
Add(key, value);
}
}
}
#endregion
public OrderedDictionary()
{
_list = new List<KeyValuePair<TKey, TValue>>();
_dictionary = new Dictionary<TKey, TValue>();
Count = 0;
}
public int Add(TKey key, TValue value)
{
_dictionary.Add(key, value);
_list.Add(new KeyValuePair<TKey, TValue>(key, value));
Count++;
return Count - 1;
}
public void Insert(int index, TKey key, TValue value)
{
if (index > Count || index < 0)
throw new ArgumentOutOfRangeException("index");
_dictionary.Add(key, value);
_list.Insert(index, new KeyValuePair<TKey, TValue>(key, value));
Count++;
}
void IOrderedDictionary.RemoveAt(int index)
{
if (index >= Count || index < 0)
throw new ArgumentOutOfRangeException("index",
"'index' must be non-negative and less than " +
"the size of the collection");
TKey key = _list[index].Key;
_list.RemoveAt(index);
_dictionary.Remove(key);
Count--;
}
public bool Remove(TKey key)
{
if (null == key)
throw new ArgumentNullException("key");
int index = IndexOfKey(key);
if (index >= 0)
{
if (_dictionary.Remove(key))
{
_list.RemoveAt(index);
Count--;
return true;
}
}
return false;
}
public bool ContainsKey(TKey key)
{
return _dictionary.ContainsKey(key);
}
private int IndexOfKey(TKey key)
{
return _list.FindIndex(kvp => kvp.Key.Equals(key));
}
#region Interface methods
IDictionaryEnumerator IOrderedDictionary.GetEnumerator()
{
return _dictionary.GetEnumerator();
}
void IOrderedDictionary.Insert(int index, object key, object value)
{
var keyObj = (TKey)key;
if (keyObj == null)
throw new ArgumentException($"Key must be of type {typeof(TKey)}");
var valueObj = (TValue)value;
if (valueObj == null)
throw new ArgumentException($"Value must be of type {typeof(TValue)}");
Insert(index, keyObj, valueObj);
}
bool IDictionary.Contains(object key)
{
var keyObj = (TKey)key;
if (keyObj == null)
throw new ArgumentException($"Key must be of type {typeof(TKey)}");
return _dictionary.ContainsKey(keyObj);
}
void IDictionary.Add(object key, object value)
{
var keyObj = (TKey)key;
if (keyObj == null)
throw new ArgumentException($"Key must be of type {typeof(TKey)}");
var valueObj = (TValue)value;
if (valueObj == null)
throw new ArgumentException($"Value must be of type {typeof(TValue)}");
Add(keyObj, valueObj);
}
void IDictionary.Clear()
{
_dictionary.Clear();
_list.Clear();
}
IDictionaryEnumerator IDictionary.GetEnumerator()
{
return _dictionary.GetEnumerator();
}
void IDictionary.Remove(object key)
{
var keyObj = (TKey)key;
if (keyObj == null)
throw new ArgumentException($"Key must be of type {typeof(TKey)}");
Remove(keyObj);
}
void ICollection.CopyTo(Array array, int index)
{
var arrayObj = array as KeyValuePair<TKey, TValue>[];
if (arrayObj == null)
throw new ArgumentException($"Key must be of type {typeof(KeyValuePair<TKey, TValue>[])}");
_list.CopyTo(arrayObj, index);
}
bool IDictionary<TKey, TValue>.ContainsKey(TKey key)
{
return ContainsKey(key);
}
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
{
Add(key, value);
}
bool IDictionary<TKey, TValue>.Remove(TKey key)
{
return Remove(key);
}
bool IDictionary<TKey, TValue>.TryGetValue(TKey key, out TValue value)
{
return _dictionary.TryGetValue(key, out value);
}
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
Add(item.Key, item.Value);
}
void ICollection<KeyValuePair<TKey, TValue>>.Clear()
{
_dictionary.Clear();
_list.Clear();
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
return _list.Contains(item);
}
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
_list.CopyTo(array, arrayIndex);
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
return Remove(item.Key);
}
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _list.GetEnumerator();
}
#endregion
}
}

View File

@@ -48,7 +48,13 @@
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" Content="System/Media Type" />
<ComboBox x:Name="cmb_SystemType" Grid.Row="0" Grid.Column="1" Height="22" Width="250" HorizontalAlignment="left" SelectionChanged="cmb_SystemType_SelectionChanged" />
<ComboBox x:Name="cmb_SystemType" Grid.Row="0" Grid.Column="1" Height="22" Width="250" HorizontalAlignment="left" SelectionChanged="cmb_SystemType_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" Foreground="{Binding Path=Foreground}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ComboBox x:Name="cmb_MediaType" Grid.Row="0" Grid.Column="1" Height="22" Width="140" HorizontalAlignment="right" SelectionChanged="cmb_MediaType_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
@@ -65,7 +71,13 @@
<Button x:Name="btn_OutputDirectoryBrowse" Grid.Row="2" Grid.Column="1" Height="22" Width="50" HorizontalAlignment="Right" Content="Browse" Click="btn_OutputDirectoryBrowse_Click"/>
<Label Grid.Row="3" Grid.Column="0" VerticalAlignment="Center">Drive Letter</Label>
<ComboBox x:Name="cmb_DriveLetter" Grid.Row="3" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="left" SelectionChanged="cmb_DriveLetter_SelectionChanged" />
<ComboBox x:Name="cmb_DriveLetter" Grid.Row="3" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="left" SelectionChanged="cmb_DriveLetter_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Letter}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Label Grid.Row="4" Grid.Column="0" VerticalAlignment="Center">Drive Speed</Label>
<ComboBox x:Name="cmb_DriveSpeed" Grid.Row="4" Grid.Column="1" Height="22" Width="60" HorizontalAlignment="left" SelectionChanged="cmb_DriveSpeed_SelectionChanged" />

View File

@@ -9,15 +9,16 @@ using System.Windows.Controls;
using WinForms = System.Windows.Forms;
using DICUI.Data;
using DICUI.Utilities;
using static DICUI.Data.UIElements;
namespace DICUI
{
public partial class MainWindow : Window
{
// Private UI-related variables
private List<KeyValuePair<char, string>> _drives { get; set; }
private List<Drive> _drives { get; set; }
private MediaType? _currentMediaType { get; set; }
private List<KeyValuePair<string, KnownSystem?>> _systems { get; set; }
private List<KnownSystem?> _systems { get; set; }
private List<MediaType?> _mediaTypes { get; set; }
private DumpEnvironment _env;
@@ -74,6 +75,13 @@ namespace DICUI
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;
}
PopulateMediaTypeAccordingToChosenSystem();
}
@@ -145,11 +153,11 @@ namespace DICUI
/// </summary>
private void PopulateMediaTypeAccordingToChosenSystem()
{
var currentSystem = cmb_SystemType.SelectedItem as KeyValuePair<string, KnownSystem?>?;
KnownSystem? currentSystem = cmb_SystemType.SelectedItem as KnownSystemComboBoxItem;
if (currentSystem != null)
{
_mediaTypes = Validators.GetValidMediaTypes(currentSystem?.Value).ToList();
_mediaTypes = Validators.GetValidMediaTypes(currentSystem).ToList();
cmb_MediaType.ItemsSource = _mediaTypes;
cmb_MediaType.IsEnabled = _mediaTypes.Count > 1;
@@ -168,11 +176,26 @@ namespace DICUI
/// </summary>
private void PopulateSystems()
{
_systems = Validators.CreateListOfSystems()
.Select(i => new KeyValuePair<string, KnownSystem?>(i.Key, i.Value))
.ToList();
cmb_SystemType.ItemsSource = _systems;
cmb_SystemType.DisplayMemberPath = "Key";
_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;
@@ -185,11 +208,8 @@ namespace DICUI
private void PopulateDrives()
{
// Populate the list of drives and add it to the combo box
_drives = Validators.CreateListOfDrives()
.Select(i => new KeyValuePair<char, string>(i.Key, i.Value))
.ToList();
_drives = Validators.CreateListOfDrives();
cmb_DriveLetter.ItemsSource = _drives;
cmb_DriveLetter.DisplayMemberPath = "Key";
if (cmb_DriveLetter.Items.Count > 0)
{
@@ -226,8 +246,6 @@ namespace DICUI
private DumpEnvironment DetermineEnvironment()
{
// Populate all KVPs
var driveKvp = cmb_DriveLetter.SelectedItem as KeyValuePair<char, string>?;
var systemKvp = cmb_SystemType.SelectedValue as KeyValuePair<string, KnownSystem?>?;
return new DumpEnvironment()
{
@@ -239,12 +257,11 @@ namespace DICUI
OutputFilename = txt_OutputFilename.Text,
// Get the currently selected options
DriveLetter = (char)driveKvp?.Key,
IsFloppy = (driveKvp?.Value == UIElements.FloppyDriveString),
Drive = cmb_DriveLetter.SelectedItem as Drive,
DICParameters = txt_Parameters.Text,
System = systemKvp?.Value,
System = (KnownSystem?)(cmb_SystemType.SelectedItem as KnownSystemComboBoxItem),
Type = cmb_MediaType.SelectedItem as MediaType?
};
}
@@ -274,23 +291,14 @@ namespace DICUI
/// </summary>
private void EnsureDiscInformation()
{
var systemKvp = cmb_SystemType.SelectedItem as KeyValuePair<string, KnownSystem?>?;
// If we're on a separator, go to the next item and return
if (systemKvp?.Value == null)
{
cmb_SystemType.SelectedIndex++;
return;
}
// Get the selected system info
var selectedSystem = systemKvp?.Value;
KnownSystem? selectedSystem = (KnownSystem?)(cmb_SystemType.SelectedItem as KnownSystemComboBoxItem) ?? KnownSystem.NONE;
MediaType? selectedMediaType = cmb_MediaType.SelectedItem as MediaType? ?? MediaType.NONE;
Result result = GetSupportStatus(selectedSystem, selectedMediaType);
lbl_Status.Content = result.Message;
btn_StartStop.IsEnabled = result && (_drives.Count > 0 ? true : false);
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 = selectedMediaType.DoesSupportDriveSpeed() && selectedSystem.DoesSupportDriveSpeed();
@@ -318,16 +326,16 @@ namespace DICUI
// Populate with the correct params for inputs (if we're not on the default option)
if (selectedSystem != KnownSystem.NONE && selectedMediaType != MediaType.NONE)
{
var driveletter = cmb_DriveLetter.SelectedValue as KeyValuePair<char, string>?;
Drive drive = cmb_DriveLetter.SelectedValue as Drive;
// If drive letter is invalid, skip this
if (driveletter == null)
if (drive == null)
return;
string command = Converters.KnownSystemAndMediaTypeToBaseCommand(selectedSystem, selectedMediaType);
List<string> defaultParams = Converters.KnownSystemAndMediaTypeToParameters(selectedSystem, selectedMediaType);
txt_Parameters.Text = command
+ " " + driveletter?.Key
+ " " + drive.Letter
+ " \"" + Path.Combine(txt_OutputDirectory.Text, txt_OutputFilename.Text) + "\" "
+ (selectedMediaType != MediaType.Floppy
&& selectedMediaType != MediaType.BluRay
@@ -413,18 +421,18 @@ namespace DICUI
/// </summary>
private void GetOutputNames()
{
var driveKvp = cmb_DriveLetter.SelectedItem as KeyValuePair<char, string>?;
var systemKvp = cmb_SystemType.SelectedItem as KeyValuePair<string, KnownSystem?>?;
Drive drive = cmb_DriveLetter.SelectedItem as Drive;
KnownSystem? systemType = (KnownSystem?)(cmb_SystemType.SelectedItem as KnownSystemComboBoxItem);
MediaType? mediaType = cmb_MediaType.SelectedItem as MediaType?;
if (driveKvp != null
&& !String.IsNullOrWhiteSpace(driveKvp?.Value)
&& driveKvp?.Value != UIElements.FloppyDriveString
&& systemKvp != null
if (drive != null
&& !String.IsNullOrWhiteSpace(drive.VolumeLabel)
&& !drive.IsFloppy
&& systemType != null
&& mediaType != null)
{
txt_OutputDirectory.Text = Path.Combine(_options.defaultOutputPath, driveKvp?.Value);
txt_OutputFilename.Text = driveKvp?.Value + mediaType.Extension();
txt_OutputDirectory.Text = Path.Combine(_options.defaultOutputPath, drive.VolumeLabel);
txt_OutputFilename.Text = drive.VolumeLabel + mediaType.Extension();
}
else
{
@@ -444,11 +452,9 @@ namespace DICUI
cmb_DriveSpeed.SelectedIndex = values.Count / 2;
// Get the drive letter from the selected item
var selected = cmb_DriveLetter.SelectedItem as KeyValuePair<char, string>?;
if (selected == null || (selected?.Value == UIElements.FloppyDriveString))
{
Drive drive = cmb_DriveLetter.SelectedItem as Drive;
if (drive == null || drive.IsFloppy)
return;
}
//Validators.GetDriveSpeed((char)selected?.Key);
//Validators.GetDriveSpeedEx((char)selected?.Key, _currentMediaType);
@@ -460,13 +466,12 @@ namespace DICUI
return;
}
char driveLetter = (char)selected?.Key;
Process childProcess = new Process()
{
StartInfo = new ProcessStartInfo()
{
FileName = _options.dicPath,
Arguments = DICCommands.DriveSpeed + " " + driveLetter,
Arguments = DICCommands.DriveSpeed + " " + drive.Letter,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
@@ -499,14 +504,12 @@ namespace DICUI
private void SetCurrentDiscType()
{
// Get the drive letter from the selected item
var selected = cmb_DriveLetter.SelectedItem as KeyValuePair<char, string>?;
if (selected == null || (selected?.Value == UIElements.FloppyDriveString))
{
Drive drive = cmb_DriveLetter.SelectedItem as Drive;
if (drive == null || drive.IsFloppy)
return;
}
// Get the current optical disc type
_currentMediaType = Validators.GetDiscType(selected?.Key);
_currentMediaType = Validators.GetDiscType(drive.Letter);
// If we have an invalid current type, we don't care and return
if (_currentMediaType == null || _currentMediaType == MediaType.NONE)

View File

@@ -49,15 +49,16 @@ namespace DICUI
public string OutputFilename;
// UI information
public char DriveLetter;
public Drive Drive;
public KnownSystem? System;
public MediaType? Type;
public bool IsFloppy;
public string DICParameters;
// External process information
public Process dicProcess;
public bool IsFloppy { get => Drive.IsFloppy; }
/// <summary>
/// Checks if the configuration is valid
/// </summary>
@@ -66,7 +67,7 @@ namespace DICUI
{
return !((string.IsNullOrWhiteSpace(DICParameters)
|| !Validators.ValidateParameters(DICParameters)
|| (IsFloppy ^ Type == MediaType.Floppy)));
|| (Drive.IsFloppy ^ Type == MediaType.Floppy)));
}
/// <summary>
@@ -78,7 +79,7 @@ namespace DICUI
if (System == KnownSystem.Custom)
{
Validators.DetermineFlags(DICParameters, out Type, out System, out string letter, out string path);
DriveLetter = (String.IsNullOrWhiteSpace(letter) ? new char() : letter[0]);
Drive = Drive.Optical(String.IsNullOrWhiteSpace(letter) ? new char() : letter[0], "");
OutputDirectory = Path.GetDirectoryName(path);
OutputFilename = Path.GetFileName(path);
}
@@ -129,7 +130,7 @@ namespace DICUI
StartInfo = new ProcessStartInfo()
{
FileName = env.DICPath,
Arguments = DICCommands.Eject + " " + env.DriveLetter,
Arguments = DICCommands.Eject + " " + env.Drive.Letter,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
@@ -269,7 +270,7 @@ namespace DICUI
StartInfo = new ProcessStartInfo()
{
FileName = env.SubdumpPath,
Arguments = "-i " + env.DriveLetter + ": -f " + Path.Combine(env.OutputDirectory, Path.GetFileNameWithoutExtension(env.OutputFilename) + "_subdump.sub") + "-mode 6 -rereadnum 25 -fix 2",
Arguments = "-i " + env.Drive.Letter + ": -f " + Path.Combine(env.OutputDirectory, Path.GetFileNameWithoutExtension(env.OutputFilename) + "_subdump.sub") + "-mode 6 -rereadnum 25 -fix 2",
},
};
childProcess.Start();
@@ -288,7 +289,7 @@ namespace DICUI
if (!DumpInformation.FoundAllFiles(env.OutputDirectory, env.OutputFilename, env.Type))
return Result.Failure("Error! Please check output directory as dump may be incomplete!");
Dictionary<string, string> templateValues = DumpInformation.ExtractOutputInformation(env.OutputDirectory, env.OutputFilename, env.System, env.Type, env.DriveLetter);
Dictionary<string, string> templateValues = DumpInformation.ExtractOutputInformation(env.OutputDirectory, env.OutputFilename, env.System, env.Type, env.Drive.Letter);
List<string> formattedValues = DumpInformation.FormatOutputData(templateValues, env.System, env.Type);
bool success = DumpInformation.WriteOutputData(env.OutputDirectory, env.OutputFilename, formattedValues);

View File

@@ -4,6 +4,7 @@ using System.Globalization;
using System.Windows.Data;
using IMAPI2;
using DICUI.Data;
using static DICUI.Data.UIElements;
namespace DICUI.Utilities
{
@@ -44,12 +45,67 @@ namespace DICUI.Utilities
/// </summary>
public static class KnownSystemExtensions
{
public static string Name(this KnownSystem? system)
{
return Converters.KnownSystemToString(system);
}
public static bool DoesSupportDriveSpeed(this KnownSystem? system)
{
return system != KnownSystem.MicrosoftXBOX
&& system != KnownSystem.MicrosoftXBOX360XDG2
&& system != KnownSystem.MicrosoftXBOX360XDG3;
}
public static KnownSystemCategory Category(this KnownSystem? system)
{
if (system < KnownSystem.MarkerConsoleEnd)
return KnownSystemCategory.Console;
else if (system < KnownSystem.MarkerComputerEnd)
return KnownSystemCategory.Computer;
else if (system < KnownSystem.MarkerArcadeEnd)
return KnownSystemCategory.Arcade;
else if (system < KnownSystem.MarkerOtherEnd)
return KnownSystemCategory.Other;
else
return KnownSystemCategory.Custom;
}
public static bool IsMarker(this KnownSystem? system)
{
switch (system)
{
case KnownSystem.MarkerArcadeEnd:
case KnownSystem.MarkerComputerEnd:
case KnownSystem.MarkerConsoleEnd:
case KnownSystem.MarkerOtherEnd:
return true;
default:
return false;
}
}
}
/// <summary>
/// Extensions for KnownSystemCategory?
/// </summary>
public static class KnownSystemCategoryExtensions
{
/// <summary>
/// Get the string representation of a KnownSystemCategory
/// </summary>
public static string Name(this KnownSystemCategory? category)
{
switch (category)
{
case KnownSystemCategory.Arcade: return "Arcade";
case KnownSystemCategory.Computer: return "Computers";
case KnownSystemCategory.Console: return "Consoles";
case KnownSystemCategory.Other: return "Other";
case KnownSystemCategory.Custom: return "Custom";
default: return "";
}
}
}
/// <summary>

View File

@@ -143,8 +143,8 @@ namespace DICUI.Utilities
{ Template.TitleField, Template.RequiredValue },
{ Template.DiscNumberField, Template.OptionalValue },
{ Template.DiscTitleField, Template.OptionalValue },
{ Template.SystemField, Converters.KnownSystemToString(sys) },
{ Template.MediaTypeField, Converters.MediaTypeToString(type) },
{ Template.SystemField, sys.Name() },
{ Template.MediaTypeField, type.Name() },
{ Template.CategoryField, "Games" },
{ Template.RegionField, "World (CHANGE THIS)" },
{ Template.LanguagesField, "Klingon (CHANGE THIS)" },

View File

@@ -8,9 +8,27 @@ using System.Text.RegularExpressions;
using IMAPI2;
using DICUI.Data;
using DICUI.External;
using static DICUI.Data.UIElements;
namespace DICUI.Utilities
{
public class Drive
{
public char Letter { get; private set; }
public bool IsFloppy { get; private set; }
public string VolumeLabel { get; private set; }
private Drive(char letter, string volumeLabel, bool isFloppy)
{
this.Letter = letter;
this.IsFloppy = isFloppy;
this.VolumeLabel = volumeLabel;
}
public static Drive Floppy(char letter) => new Drive(letter, null, true);
public static Drive Optical(char letter, string volumeLabel) => new Drive(letter, volumeLabel, false);
}
public static class Validators
{
/// <summary>
@@ -378,54 +396,27 @@ namespace DICUI.Utilities
/// If something has a "string, null" value, it should be assumed that it is a separator
/// </remarks>
/// TODO: Figure out a way that the sections can be generated more automatically
public static OrderedDictionary<string, KnownSystem?> CreateListOfSystems()
public static List<KnownSystem?> CreateListOfSystems()
{
var systemsDict = new OrderedDictionary<string, KnownSystem?>();
foreach (KnownSystem system in Enum.GetValues(typeof(KnownSystem)))
{
// In the special cases of breaks, we want to add the proper mappings for sections
switch (system)
{
// Consoles section
case KnownSystem.BandaiPlaydiaQuickInteractiveSystem:
systemsDict.Add("---------- Consoles ----------", null);
break;
// Computers section
case KnownSystem.AcornArchimedes:
systemsDict.Add("---------- Computers ----------", null);
break;
// Arcade section
case KnownSystem.AmigaCUBOCD32:
systemsDict.Add("---------- Arcade ----------", null);
break;
// Other section
case KnownSystem.AudioCD:
systemsDict.Add("---------- Others ----------", null);
break;
}
systemsDict.Add(Converters.KnownSystemToString(system), system);
}
return systemsDict;
return Enum.GetValues(typeof(KnownSystem))
.OfType<KnownSystem?>()
.Where(s => !s.IsMarker())
.ToList();
}
/// <summary>
/// Create a list of active optical drives matched to their volume labels
/// Create a list of active drives matched to their volume labels
/// </summary>
/// <returns>Active drives, matched to labels, if possible</returns>
/// <remarks>
/// https://stackoverflow.com/questions/3060796/how-to-distinguish-between-usb-and-floppy-devices?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
/// https://msdn.microsoft.com/en-us/library/aa394173(v=vs.85).aspx
/// </remarks>
public static OrderedDictionary<char, string> CreateListOfDrives()
public static List<Drive> CreateListOfDrives()
{
var drives = new List<Drive>();
// Get the floppy drives
var floppyDrives = new List<KeyValuePair<char, string>>();
try
{
ManagementObjectSearcher searcher =
@@ -439,7 +430,7 @@ namespace DICUI.Utilities
if (mediaType != null && ((mediaType > 0 && mediaType < 11) || (mediaType > 12 && mediaType < 22)))
{
char devId = queryObj["DeviceID"].ToString()[0];
floppyDrives.Add(new KeyValuePair<char, string>(devId, UIElements.FloppyDriveString));
drives.Add(Drive.Floppy(devId));
}
}
}
@@ -449,23 +440,16 @@ namespace DICUI.Utilities
}
// Get the optical disc drives
List<KeyValuePair<char, string>> discDrives = DriveInfo.GetDrives()
List<Drive> discDrives = DriveInfo.GetDrives()
.Where(d => d.DriveType == DriveType.CDRom && d.IsReady)
.Select(d => new KeyValuePair<char, string>(d.Name[0], d.VolumeLabel))
.Select(d => Drive.Optical(d.Name[0], d.VolumeLabel))
.ToList();
// Add the two lists together and order
floppyDrives.AddRange(discDrives);
floppyDrives = floppyDrives.OrderBy(i => i.Key).ToList();
drives.AddRange(discDrives);
drives = drives.OrderBy(i => i.Letter).ToList();
// Add to the ordered dictionary and return
var drivesDict = new OrderedDictionary<char, string>();
foreach (var drive in floppyDrives)
{
drivesDict.Add(drive.Key, drive.Value);
}
return drivesDict;
return drives;
}
/// <summary>