From ec23502275ae92249b54581fabb807db13fa99fb Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Mon, 8 Oct 2018 11:06:22 -0700 Subject: [PATCH] Abstract out non-UI code to separate DLL (#122) * Abstract out non-UI code to separate DLL This change seems rather large, but it's mostly just moving anything that is not directly driving the UI to its own, separate library. This will make it easier at a later date for any UI improvements or changes as well as making the code much more discrete. One TODO has been added as a result of this change. * Remove MessageBox from library This change removes the last UI-driven elements from the library. This now makes the library (in theory) UI-agnostic and removes the TODO. * Options is more UI-related * Fix Nuget references in csproj * Add Winforms UI This is a clone of the current WPF UI but implemented in Windows Forms. WPF is not currently supported by Mono for Linux and macOS, so this can provide an alternative to those users who want to run on those systems instead. This also adds a second artifact for the Winforms build. --- DICUI.Forms/App.config | 6 + .../Constants.cs | 19 +- DICUI.Forms/DICUI.Forms.csproj | 116 ++ DICUI.Forms/EnumDescriptionConverter.cs | 33 + DICUI.Forms/Icon.ico | Bin 0 -> 73123 bytes DICUI.Forms/KnownSystemComboBoxItem.cs | 35 + DICUI.Forms/Options.cs | 97 ++ DICUI.Forms/Program.cs | 20 + DICUI.Forms/Properties/AssemblyInfo.cs | 36 + DICUI.Forms/Properties/Settings1.Designer.cs | 26 + DICUI.Forms/Properties/Settings1.settings | 6 + DICUI.Forms/ViewModels.cs | 107 ++ DICUI.Forms/Windows/LogWindow.Designer.cs | 175 +++ DICUI.Forms/Windows/LogWindow.cs | 380 +++++ DICUI.Forms/Windows/LogWindow.resx | 123 ++ DICUI.Forms/Windows/MainWindow.Designer.cs | 530 +++++++ DICUI.Forms/Windows/MainWindow.cs | 723 +++++++++ DICUI.Forms/Windows/MainWindow.resx | 1395 +++++++++++++++++ DICUI.Forms/Windows/OptionsWindow.Designer.cs | 565 +++++++ DICUI.Forms/Windows/OptionsWindow.cs | 179 +++ DICUI.Forms/Windows/OptionsWindow.resx | 123 ++ DICUI.Library/DICUI.Library.csproj | 101 ++ {DICUI => DICUI.Library}/Data/Constants.cs | 13 +- {DICUI => DICUI.Library}/Data/Enumerations.cs | 0 DICUI.Library/Properties/AssemblyInfo.cs | 36 + .../Utilities/Converters.cs | 30 +- .../Utilities/DumpEnvironment.cs | 161 +- .../Utilities/Extensions.cs | 0 .../Utilities/Parameters.cs | 0 {DICUI => DICUI.Library}/Utilities/Result.cs | 0 .../Utilities/Validators.cs | 2 +- {DICUI => DICUI.Library}/mspack.dll | Bin {DICUI => DICUI.Library}/packages.config | 0 DICUI.Test/DICUI.Test.csproj | 10 +- DICUI.Test/UI/AllowedSpeedsTest.cs | 3 +- DICUI.sln | 12 + DICUI/App.xaml | 2 +- DICUI/App.xaml.cs | 8 +- DICUI/Constants.cs | 56 + DICUI/DICUI.csproj | 77 +- DICUI/EnumDescriptionConverter.cs | 33 + DICUI/{UI => }/KnownSystemComboBoxItem.cs | 2 +- DICUI/{UI => }/ViewModels.cs | 3 +- DICUI/{ => Windows}/LogWindow.xaml | 8 +- DICUI/{ => Windows}/LogWindow.xaml.cs | 6 +- DICUI/{ => Windows}/MainWindow.xaml | 8 +- DICUI/{ => Windows}/MainWindow.xaml.cs | 48 +- DICUI/{ => Windows}/OptionsWindow.xaml | 21 +- DICUI/{ => Windows}/OptionsWindow.xaml.cs | 2 +- appveyor.yml | 8 +- 50 files changed, 5087 insertions(+), 257 deletions(-) create mode 100644 DICUI.Forms/App.config rename DICUI/UI/AllowedSpeeds.cs => DICUI.Forms/Constants.cs (71%) create mode 100644 DICUI.Forms/DICUI.Forms.csproj create mode 100644 DICUI.Forms/EnumDescriptionConverter.cs create mode 100644 DICUI.Forms/Icon.ico create mode 100644 DICUI.Forms/KnownSystemComboBoxItem.cs create mode 100644 DICUI.Forms/Options.cs create mode 100644 DICUI.Forms/Program.cs create mode 100644 DICUI.Forms/Properties/AssemblyInfo.cs create mode 100644 DICUI.Forms/Properties/Settings1.Designer.cs create mode 100644 DICUI.Forms/Properties/Settings1.settings create mode 100644 DICUI.Forms/ViewModels.cs create mode 100644 DICUI.Forms/Windows/LogWindow.Designer.cs create mode 100644 DICUI.Forms/Windows/LogWindow.cs create mode 100644 DICUI.Forms/Windows/LogWindow.resx create mode 100644 DICUI.Forms/Windows/MainWindow.Designer.cs create mode 100644 DICUI.Forms/Windows/MainWindow.cs create mode 100644 DICUI.Forms/Windows/MainWindow.resx create mode 100644 DICUI.Forms/Windows/OptionsWindow.Designer.cs create mode 100644 DICUI.Forms/Windows/OptionsWindow.cs create mode 100644 DICUI.Forms/Windows/OptionsWindow.resx create mode 100644 DICUI.Library/DICUI.Library.csproj rename {DICUI => DICUI.Library}/Data/Constants.cs (94%) rename {DICUI => DICUI.Library}/Data/Enumerations.cs (100%) create mode 100644 DICUI.Library/Properties/AssemblyInfo.cs rename {DICUI => DICUI.Library}/Utilities/Converters.cs (96%) rename {DICUI => DICUI.Library}/Utilities/DumpEnvironment.cs (97%) rename {DICUI => DICUI.Library}/Utilities/Extensions.cs (100%) rename {DICUI => DICUI.Library}/Utilities/Parameters.cs (100%) rename {DICUI => DICUI.Library}/Utilities/Result.cs (100%) rename {DICUI => DICUI.Library}/Utilities/Validators.cs (99%) rename {DICUI => DICUI.Library}/mspack.dll (100%) rename {DICUI => DICUI.Library}/packages.config (100%) create mode 100644 DICUI/Constants.cs create mode 100644 DICUI/EnumDescriptionConverter.cs rename DICUI/{UI => }/KnownSystemComboBoxItem.cs (98%) rename DICUI/{UI => }/ViewModels.cs (98%) rename DICUI/{ => Windows}/LogWindow.xaml (90%) rename DICUI/{ => Windows}/LogWindow.xaml.cs (98%) rename DICUI/{ => Windows}/MainWindow.xaml (96%) rename DICUI/{ => Windows}/MainWindow.xaml.cs (91%) rename DICUI/{ => Windows}/OptionsWindow.xaml (94%) rename DICUI/{ => Windows}/OptionsWindow.xaml.cs (99%) diff --git a/DICUI.Forms/App.config b/DICUI.Forms/App.config new file mode 100644 index 00000000..731f6de6 --- /dev/null +++ b/DICUI.Forms/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/DICUI/UI/AllowedSpeeds.cs b/DICUI.Forms/Constants.cs similarity index 71% rename from DICUI/UI/AllowedSpeeds.cs rename to DICUI.Forms/Constants.cs index 747caae6..678aef96 100644 --- a/DICUI/UI/AllowedSpeeds.cs +++ b/DICUI.Forms/Constants.cs @@ -4,13 +4,18 @@ using System.Linq; using System.Windows.Media; using DICUI.Data; -namespace DICUI.UI +namespace DICUI { /// - /// Gets allowed drive speeds for a given media type + /// Variables for UI elements /// - public static class AllowedSpeeds + public static class Constants { + public const string StartDumping = "Start Dumping"; + public const string StopDumping = "Stop Dumping"; + + public const int LogWindowMarginFromMainWindow = 10; + // Private lists of known drive speed ranges private static IReadOnlyList cd { get; } = new List { 1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72 }; private static IReadOnlyList dvd { get; } = cd.Where(s => s <= 24).ToList(); @@ -22,7 +27,7 @@ namespace DICUI.UI /// /// MediaType? that represents the current item /// Read-only list of drive speeds - public static IReadOnlyList GetForMediaType(MediaType? type) + public static IReadOnlyList GetSpeedsForMediaType(MediaType? type) { switch (type) { @@ -42,9 +47,9 @@ namespace DICUI.UI } // Create collections for UI based on known drive speeds - public static DoubleCollection ForCDAsCollection { get; } = GetDoubleCollectionFromIntList(cd); - public static DoubleCollection ForDVDAsCollection { get; } = GetDoubleCollectionFromIntList(dvd); - public static DoubleCollection ForBDAsCollection { get; } = GetDoubleCollectionFromIntList(bd); + public static DoubleCollection SpeedsForCDAsCollection { get; } = GetDoubleCollectionFromIntList(cd); + public static DoubleCollection SpeedsForDVDAsCollection { get; } = GetDoubleCollectionFromIntList(dvd); + public static DoubleCollection SpeedsForBDAsCollection { get; } = GetDoubleCollectionFromIntList(bd); private static DoubleCollection GetDoubleCollectionFromIntList(IReadOnlyList list) => new DoubleCollection(list.Select(i => Convert.ToDouble(i)).ToList()); } diff --git a/DICUI.Forms/DICUI.Forms.csproj b/DICUI.Forms/DICUI.Forms.csproj new file mode 100644 index 00000000..b3251bcd --- /dev/null +++ b/DICUI.Forms/DICUI.Forms.csproj @@ -0,0 +1,116 @@ + + + + + Debug + AnyCPU + {A6719A99-BF0E-4637-9A8E-CB38B1E16971} + WinExe + DICUI.Forms + DICUI.Forms + v4.6.1 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Icon.ico + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + Settings1.settings + + + + Form + + + LogWindow.cs + + + Form + + + MainWindow.cs + + + + + Form + + + OptionsWindow.cs + + + LogWindow.cs + + + MainWindow.cs + Designer + + + OptionsWindow.cs + + + + + + SettingsSingleFileGenerator + Settings1.Designer.cs + + + + + + + + {51ab0928-13f9-44bf-a407-b6957a43a056} + DICUI.Library + + + + \ No newline at end of file diff --git a/DICUI.Forms/EnumDescriptionConverter.cs b/DICUI.Forms/EnumDescriptionConverter.cs new file mode 100644 index 00000000..1526b272 --- /dev/null +++ b/DICUI.Forms/EnumDescriptionConverter.cs @@ -0,0 +1,33 @@ +using System; +using System.Globalization; +using System.Windows.Data; +using DICUI.Data; +using DICUI.Utilities; + +namespace DICUI.Forms +{ + /// + /// Used to provide a converter to XAML files to render comboboxes with enum values + /// + public class EnumDescriptionConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is DICCommand) + return ((DICCommand)value).Name(); + else if (value is DICFlag) + return ((DICFlag)value).Name(); + else if (value is MediaType?) + return ((MediaType?)value).Name(); + else if (value is KnownSystem?) + return ((KnownSystem?)value).Name(); + else + return ""; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return string.Empty; + } + } +} diff --git a/DICUI.Forms/Icon.ico b/DICUI.Forms/Icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..370e65596a58d2b2e5213a0df6bea51812727df6 GIT binary patch literal 73123 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 GgeCwv0vOZ) literal 0 HcmV?d00001 diff --git a/DICUI.Forms/KnownSystemComboBoxItem.cs b/DICUI.Forms/KnownSystemComboBoxItem.cs new file mode 100644 index 00000000..c9c70b56 --- /dev/null +++ b/DICUI.Forms/KnownSystemComboBoxItem.cs @@ -0,0 +1,35 @@ +using System.Windows.Media; +using DICUI.Data; +using DICUI.Utilities; + +namespace DICUI +{ + /// + /// Represents a single item in the System combo box + /// + 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; } // TODO: Re-enable this + + 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(); + } + } + } +} diff --git a/DICUI.Forms/Options.cs b/DICUI.Forms/Options.cs new file mode 100644 index 00000000..aef39fa1 --- /dev/null +++ b/DICUI.Forms/Options.cs @@ -0,0 +1,97 @@ +using System; +using System.Configuration; +using System.Reflection; +using DICUI.Data; + +namespace DICUI +{ + public class Options + { + public string DefaultOutputPath { get; private set; } + public string DICPath { get; private set; } + public string SubDumpPath { get; private set; } + + public int preferredDumpSpeedCD { get; set; } + public int preferredDumpSpeedDVD { get; set; } + public int preferredDumpSpeedBD { get; set; } + + public bool QuietMode { get; set; } + public bool ParanoidMode { get; set; } + public bool ScanForProtection { get; set; } + public int RereadAmountForC2 { get; set; } + + public bool SkipMediaTypeDetection { get; set; } + + public bool VerboseLogging { get; set; } + public bool OpenLogWindowAtStartup { get; set; } + + public void Save() + { + Configuration configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + + //TODO: reflection is used + //TODO: is remove needed, doesn't the value get directly overridden + Array.ForEach( + GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance), + p => { + configFile.AppSettings.Settings.Remove(p.Name); + configFile.AppSettings.Settings.Add(p.Name, Convert.ToString(p.GetValue(this))); + } + ); + + configFile.Save(ConfigurationSaveMode.Modified); + } + + public void Load() + { + //TODO: hardcoded, we should find a better way + DICPath = ConfigurationManager.AppSettings["DICPath"] ?? @"Programs\DiscImageCreator.exe"; + SubDumpPath = ConfigurationManager.AppSettings["SubDumpPath"] ?? "subdump.exe"; + DefaultOutputPath = ConfigurationManager.AppSettings["DefaultOutputPath"] ?? "ISO"; + + this.preferredDumpSpeedCD = Int32.TryParse(ConfigurationManager.AppSettings["preferredDumpSpeedCD"], out int maxDumpSpeedCD) ? maxDumpSpeedCD : 72; + this.preferredDumpSpeedDVD = Int32.TryParse(ConfigurationManager.AppSettings["preferredDumpSpeedDVD"], out int maxDumpSpeedDVD) ? maxDumpSpeedDVD : 24; + this.preferredDumpSpeedBD = Int32.TryParse(ConfigurationManager.AppSettings["preferredDumpSpeedBD"], out int maxDumpSpeedBD) ? maxDumpSpeedBD : 16; + + this.QuietMode = Boolean.TryParse(ConfigurationManager.AppSettings["QuietMode"], out bool quietMode) ? quietMode : false; + this.ParanoidMode = Boolean.TryParse(ConfigurationManager.AppSettings["ParanoidMode"], out bool paranoidMode) ? paranoidMode : false; + this.ScanForProtection = Boolean.TryParse(ConfigurationManager.AppSettings["ScanForProtection"], out bool scanForProtection) ? scanForProtection : true; + this.SkipMediaTypeDetection = Boolean.TryParse(ConfigurationManager.AppSettings["SkipMediaTypeDetection"], out bool skipMediaTypeDetection) ? skipMediaTypeDetection : false; + this.RereadAmountForC2 = Int32.TryParse(ConfigurationManager.AppSettings["RereadAmountForC2"], out int rereadAmountForC2) ? rereadAmountForC2 : 20; + this.VerboseLogging = Boolean.TryParse(ConfigurationManager.AppSettings["VerboseLogging"], out bool verboseLogging) ? verboseLogging : true; + this.OpenLogWindowAtStartup = Boolean.TryParse(ConfigurationManager.AppSettings["OpenLogWindowAtStartup"], out bool openLogWindowAtStartup) ? openLogWindowAtStartup : true; + } + + + //TODO: probably should be generic for non-string options + //TODO: using reflection for Set and Get is orthodox but it works, should be changed to a key,value map probably + public void Set(string key, string value) + { + GetType().GetProperty(key, BindingFlags.Public | BindingFlags.Instance).SetValue(this, value); + } + + public string Get(string key) + { + return GetType().GetProperty(key, BindingFlags.Public | BindingFlags.Instance).GetValue(this) as string; + } + + public int GetPreferredDumpSpeedForMediaType(MediaType? type) + { + switch (type) + { + case MediaType.CDROM: + case MediaType.GDROM: + return preferredDumpSpeedCD; + case MediaType.DVD: + case MediaType.HDDVD: + case MediaType.NintendoGameCube: + case MediaType.NintendoWiiOpticalDisc: + return preferredDumpSpeedDVD; + case MediaType.BluRay: + return preferredDumpSpeedBD; + default: + return 8; + } + } + } +} diff --git a/DICUI.Forms/Program.cs b/DICUI.Forms/Program.cs new file mode 100644 index 00000000..c33e7636 --- /dev/null +++ b/DICUI.Forms/Program.cs @@ -0,0 +1,20 @@ +using System; +using System.Windows.Forms; +using DICUI.Forms.Windows; + +namespace DICUI.Forms +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainWindow()); + } + } +} diff --git a/DICUI.Forms/Properties/AssemblyInfo.cs b/DICUI.Forms/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..87137edc --- /dev/null +++ b/DICUI.Forms/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DICUI.Forms")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DICUI.Forms")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a6719a99-bf0e-4637-9a8e-cb38b1e16971")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/DICUI.Forms/Properties/Settings1.Designer.cs b/DICUI.Forms/Properties/Settings1.Designer.cs new file mode 100644 index 00000000..2a34933b --- /dev/null +++ b/DICUI.Forms/Properties/Settings1.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace DICUI.Forms.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")] + internal sealed partial class Settings1 : global::System.Configuration.ApplicationSettingsBase { + + private static Settings1 defaultInstance = ((Settings1)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings1()))); + + public static Settings1 Default { + get { + return defaultInstance; + } + } + } +} diff --git a/DICUI.Forms/Properties/Settings1.settings b/DICUI.Forms/Properties/Settings1.settings new file mode 100644 index 00000000..049245f4 --- /dev/null +++ b/DICUI.Forms/Properties/Settings1.settings @@ -0,0 +1,6 @@ + + + + + + diff --git a/DICUI.Forms/ViewModels.cs b/DICUI.Forms/ViewModels.cs new file mode 100644 index 00000000..445c7fb0 --- /dev/null +++ b/DICUI.Forms/ViewModels.cs @@ -0,0 +1,107 @@ +using System; +using System.Windows.Media; +using DICUI.Forms.Windows; + +namespace DICUI.Forms +{ + public class OptionsViewModel + { + private Options _options; + + public OptionsViewModel(Options options) + { + this._options = options; + } + + public bool QuietMode + { + get { return _options.QuietMode; } + set { _options.QuietMode = value; } + } + + public bool ParanoidMode + { + get { return _options.ParanoidMode; } + set { _options.ParanoidMode = value; } + } + + public bool ScanForProtection + { + get { return _options.ScanForProtection; } + set { _options.ScanForProtection = value; } + } + + public bool SkipMediaTypeDetection + { + get { return _options.SkipMediaTypeDetection; } + set { _options.SkipMediaTypeDetection = value; } + } + + public string RereadAmountForC2 + { + get { return Convert.ToString(_options.RereadAmountForC2); } + set + { + if (Int32.TryParse(value, out int result)) + _options.RereadAmountForC2 = result; + } + } + + public bool VerboseLogging + { + get { return _options.VerboseLogging; } + set + { + _options.VerboseLogging = value; + _options.Save(); + } + } + + public bool OpenLogWindowAtStartup + { + get { return _options.OpenLogWindowAtStartup; } + set + { + _options.OpenLogWindowAtStartup = value; + _options.Save(); + } + } + } + + public class LoggerViewModel + { + private LogWindow _logWindow; + + public void SetWindow(LogWindow logWindow) => _logWindow = logWindow; + + public bool WindowVisible + { + get => _logWindow != null ? _logWindow.Visible : false; + set + { + if (value) + { + _logWindow.AdjustPositionToMainWindow(); + _logWindow.Show(); + } + else + _logWindow.Hide(); + } + } + + public void VerboseLog(string text) + { + if (ViewModels.OptionsViewModel.VerboseLogging) + _logWindow.AppendToTextBox(text, System.Drawing.Color.Yellow); + } + + public void VerboseLog(string format, params object[] args) => VerboseLog(string.Format(format, args)); + public void VerboseLogLn(string format, params object[] args) => VerboseLog(string.Format(format, args) + "\n"); + } + + public static class ViewModels + { + public static OptionsViewModel OptionsViewModel { get; set; } + public static LoggerViewModel LoggerViewModel { get; set; } = new LoggerViewModel(); + } +} diff --git a/DICUI.Forms/Windows/LogWindow.Designer.cs b/DICUI.Forms/Windows/LogWindow.Designer.cs new file mode 100644 index 00000000..b6c67a69 --- /dev/null +++ b/DICUI.Forms/Windows/LogWindow.Designer.cs @@ -0,0 +1,175 @@ +namespace DICUI.Forms.Windows +{ + partial class LogWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.progressBar = new System.Windows.Forms.ProgressBar(); + this.output = new System.Windows.Forms.RichTextBox(); + this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.Verbose = new System.Windows.Forms.CheckBox(); + this.OpenAtStartupCheckBox = new System.Windows.Forms.CheckBox(); + this.ClearButton = new System.Windows.Forms.Button(); + this.HideButton = new System.Windows.Forms.Button(); + this.tableLayoutPanel1.SuspendLayout(); + this.tableLayoutPanel2.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 1; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel1.Controls.Add(this.progressBar, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.output, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel2, 0, 2); + this.tableLayoutPanel1.Location = new System.Drawing.Point(12, 12); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 3; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(560, 287); + this.tableLayoutPanel1.TabIndex = 0; + // + // progressBar + // + this.progressBar.Dock = System.Windows.Forms.DockStyle.Fill; + this.progressBar.Location = new System.Drawing.Point(3, 3); + this.progressBar.Name = "progressBar"; + this.progressBar.Size = new System.Drawing.Size(554, 34); + this.progressBar.TabIndex = 0; + // + // output + // + this.output.BackColor = System.Drawing.Color.DimGray; + this.output.Dock = System.Windows.Forms.DockStyle.Fill; + this.output.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.output.Location = new System.Drawing.Point(3, 43); + this.output.Name = "output"; + this.output.ReadOnly = true; + this.output.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical; + this.output.Size = new System.Drawing.Size(554, 201); + this.output.TabIndex = 1; + this.output.Text = ""; + this.output.TextChanged += new System.EventHandler(this.OnTextChanged); + // + // tableLayoutPanel2 + // + this.tableLayoutPanel2.ColumnCount = 5; + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 15F)); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 20F)); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 35F)); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 15F)); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 15F)); + this.tableLayoutPanel2.Controls.Add(this.Verbose, 0, 0); + this.tableLayoutPanel2.Controls.Add(this.OpenAtStartupCheckBox, 1, 0); + this.tableLayoutPanel2.Controls.Add(this.ClearButton, 3, 0); + this.tableLayoutPanel2.Controls.Add(this.HideButton, 4, 0); + this.tableLayoutPanel2.Location = new System.Drawing.Point(3, 250); + this.tableLayoutPanel2.Name = "tableLayoutPanel2"; + this.tableLayoutPanel2.RowCount = 1; + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(554, 34); + this.tableLayoutPanel2.TabIndex = 2; + // + // Verbose + // + this.Verbose.AutoSize = true; + this.Verbose.Dock = System.Windows.Forms.DockStyle.Left; + this.Verbose.Location = new System.Drawing.Point(3, 3); + this.Verbose.Name = "Verbose"; + this.Verbose.Size = new System.Drawing.Size(65, 28); + this.Verbose.TabIndex = 1; + this.Verbose.Text = "Verbose"; + this.Verbose.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + this.Verbose.UseVisualStyleBackColor = true; + // + // OpenAtStartupCheckBox + // + this.OpenAtStartupCheckBox.AutoSize = true; + this.OpenAtStartupCheckBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.OpenAtStartupCheckBox.Location = new System.Drawing.Point(86, 3); + this.OpenAtStartupCheckBox.Name = "OpenAtStartupCheckBox"; + this.OpenAtStartupCheckBox.Size = new System.Drawing.Size(104, 28); + this.OpenAtStartupCheckBox.TabIndex = 2; + this.OpenAtStartupCheckBox.Text = "Open at startup"; + this.OpenAtStartupCheckBox.UseVisualStyleBackColor = true; + // + // ClearButton + // + this.ClearButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.ClearButton.Location = new System.Drawing.Point(389, 3); + this.ClearButton.Name = "ClearButton"; + this.ClearButton.Size = new System.Drawing.Size(77, 28); + this.ClearButton.TabIndex = 3; + this.ClearButton.Text = "Clear"; + this.ClearButton.UseVisualStyleBackColor = true; + this.ClearButton.Click += new System.EventHandler(this.OnClearButton); + // + // HideButton + // + this.HideButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.HideButton.Location = new System.Drawing.Point(472, 3); + this.HideButton.Name = "HideButton"; + this.HideButton.Size = new System.Drawing.Size(79, 28); + this.HideButton.TabIndex = 4; + this.HideButton.Text = "Hide"; + this.HideButton.UseVisualStyleBackColor = true; + this.HideButton.SizeChanged += new System.EventHandler(this.ScrollViewer_SizeChanged); + this.HideButton.Click += new System.EventHandler(this.OnHideButton); + // + // LogWindow + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(584, 311); + this.Controls.Add(this.tableLayoutPanel1); + this.Name = "LogWindow"; + this.ShowIcon = false; + this.Text = "Log Window"; + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.OnWindowClosed); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel2.ResumeLayout(false); + this.tableLayoutPanel2.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.ProgressBar progressBar; + private System.Windows.Forms.RichTextBox output; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; + private System.Windows.Forms.CheckBox Verbose; + private System.Windows.Forms.CheckBox OpenAtStartupCheckBox; + private System.Windows.Forms.Button ClearButton; + private System.Windows.Forms.Button HideButton; + } +} \ No newline at end of file diff --git a/DICUI.Forms/Windows/LogWindow.cs b/DICUI.Forms/Windows/LogWindow.cs new file mode 100644 index 00000000..d828f557 --- /dev/null +++ b/DICUI.Forms/Windows/LogWindow.cs @@ -0,0 +1,380 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Windows.Threading; + +namespace DICUI.Forms.Windows +{ + public partial class LogWindow : Form + { + private const int GWL_STYLE = -16; + private const int WS_SYSMENU = 0x80000; + [DllImport("user32.dll", SetLastError = true)] + private static extern int GetWindowLong(IntPtr hWnd, int nIndex); + [DllImport("user32.dll")] + private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); + + private MainWindow _mainWindow; + + private List _matchers; + + volatile Process _process; + + public LogWindow(MainWindow mainWindow) + { + InitializeComponent(); + + this._mainWindow = mainWindow; + + _matchers = new List(); + + _matchers.Add(new Matcher( + "Descrambling data sector of img (LBA)", + @"\s*(\d+)\/\s*(\d+)$", + match => { + if (UInt32.TryParse(match.Groups[1].Value, out uint current) && UInt32.TryParse(match.Groups[2].Value, out uint total)) + { + float percentProgress = (current / (float)total) * 100; + progressBar.Value = (int)percentProgress; + //progressBar.Text = string.Format("Descrambling image.. ({0:##.##}%)", percentProgress); + } + })); + + _matchers.Add(new Matcher( + @"Creating .scm (LBA)", + @"\s*(\d+)\/\s*(\d+)$", + match => { + if (UInt32.TryParse(match.Groups[1].Value, out uint current) && UInt32.TryParse(match.Groups[2].Value, out uint total)) + { + float percentProgress = (current / (float)total) * 100; + progressBar.Value = (int)percentProgress; + //progressBar.Text = string.Format("Creating scrambled image.. ({0:##.##}%)", percentProgress); + } + })); + + _matchers.Add(new Matcher( + "Checking sectors (LBA)", + @"\s*(\d+)\/\s*(\d+)$", + match => { + if (UInt32.TryParse(match.Groups[1].Value, out uint current) && UInt32.TryParse(match.Groups[2].Value, out uint total)) + { + float percentProgress = (current / (float)total) * 100; + progressBar.Value = (int)percentProgress; + //progressBar.Text = string.Format("Checking for errors.. ({0:##.##}%)", percentProgress); + } + })); + + _matchers.Add(new Matcher( + "Scanning sector (LBA)", + @"\s*(\d+)\/\s*(\d+)$", + match => { + if (UInt32.TryParse(match.Groups[1].Value, out uint current) && UInt32.TryParse(match.Groups[2].Value, out uint total)) + { + float percentProgress = (current / (float)total) * 100; + progressBar.Value = (int)percentProgress; + //progressBar.Text = string.Format("Scanning sectors for protection.. ({0:##.##}%)", percentProgress); + } + })); + } + + protected override bool ShowWithoutActivation + { + get { return true; } + } + + public void StartDump(string args) + { + AppendToTextBox(string.Format("Launching DIC with args: {0}\r\n", args), System.Drawing.Color.Orange); + + Task.Run(() => + { + _process = new Process() + { + StartInfo = new ProcessStartInfo() + { + FileName = @"Programs/DiscImageCreator.exe", + Arguments = args, + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }, + }; + + StreamState stdoutState = new StreamState(false); + StreamState stderrState = new StreamState(true); + + //_cmd.ErrorDataReceived += (process, text) => Dispatcher.CurrentDispatcher.Invoke(() => UpdateConsole(text.Data, Brushes.Red)); + _process.Start(); + + var _1 = ConsumeOutput(_process.StandardOutput, s => Dispatcher.CurrentDispatcher.Invoke(() => UpdateConsole(s, stdoutState))); + var _2 = ConsumeOutput(_process.StandardError, s => Dispatcher.CurrentDispatcher.Invoke(() => UpdateConsole(s, stderrState))); + + _process.EnableRaisingEvents = true; + _process.Exited += OnProcessExit; + }); + } + + public void AdjustPositionToMainWindow() + { + this.Left = _mainWindow.Left; + this.Top = _mainWindow.Top + _mainWindow.Height + Constants.LogWindowMarginFromMainWindow; + this.BringToFront(); + } + + private void GracefullyTerminateProcess() + { + if (_process != null) + { + _process.Exited -= OnProcessExit; + bool isForced = !_process.HasExited; + + if (isForced) + { + AppendToTextBox("\r\nForcefully Killing the process\r\n", System.Drawing.Color.Red); + _process.Kill(); + _process.WaitForExit(); + } + + AppendToTextBox(string.Format("\r\nExit Code: {0}\r\n", _process.ExitCode), _process.ExitCode == 0 ? System.Drawing.Color.Green : System.Drawing.Color.Red); + if (_process.ExitCode == 0) + { + Dispatcher.CurrentDispatcher.Invoke(() => + { + //progressBar.Text = "Done!"; + progressBar.Value = 100; + progressBar.ForeColor = System.Drawing.Color.Green; + }); + } + else + { + Dispatcher.CurrentDispatcher.Invoke(() => + { + //progressBar.Text = isForced ? "Aborted by user" : "Error, please check log!"; + progressBar.Value = 100; + progressBar.ForeColor = System.Drawing.Color.Red; + }); + } + + _process.Close(); + } + + _process = null; + } + + private void ScrollViewer_SizeChanged(object sender, EventArgs e) + { + output.ScrollToCaret(); + } + + async Task ConsumeOutput(TextReader reader, Action callback) + { + char[] buffer = new char[256]; + int cch; + + while ((cch = await reader.ReadAsync(buffer, 0, buffer.Length)) > 0) + { + callback(new string(buffer, 0, cch)); + } + } + + // this is used to optimize the work since we need to process A LOT of text + struct Matcher + { + private readonly String prefix; + private readonly Regex regex; + private readonly int start; + private readonly Action lambda; + + public Matcher(String prefix, String regex, Action lambda) + { + this.prefix = prefix; + this.regex = new Regex(regex); + this.start = prefix.Length; + this.lambda = lambda; + } + + public bool Matches(ref string text) => text.StartsWith(prefix); + + public void Apply(ref string text) + { + Match match = regex.Match(text, start); + lambda.Invoke(match); + } + } + + private void ProcessStringForProgressBar(string text) + { + foreach (Matcher matcher in _matchers) + { + if (matcher.Matches(ref text)) + { + matcher.Apply(ref text); + return; + } + } + } + + class StreamState + { + public enum State + { + BEGIN, + READ_CARRIAGE, + }; + + public State state; + public readonly StringBuilder buffer; + public readonly bool isError; + + public StreamState(bool isError) + { + this.state = State.BEGIN; + this.buffer = new StringBuilder(); + this.isError = isError; + } + + public bool HasData() => buffer.Length > 0; + public string Fetch() => buffer.ToString(); + public void Clear() => buffer.Clear(); + public void Append(char c) => buffer.Append(c); + + public bool Is(State state) => this.state == state; + public void Set(State state) => this.state = state; + } + + public void AppendToTextBox(string text, System.Drawing.Color color) + { + if (Dispatcher.CurrentDispatcher.CheckAccess()) + { + output.ForeColor = color; + output.AppendText(text); + } + else + Dispatcher.CurrentDispatcher.Invoke(() => + { + output.ForeColor = color; + output.AppendText(text); + }); + } + + private void UpdateConsole(string text, StreamState state) + { + /*if (c == '\r') { output.Inlines.Add(@"\r"); file.Write("\\r"); } + else if (c == '\n') { output.Inlines.Add(@"\n"); file.Write("\\n\n"); } + output.Inlines.Add(""+c); + file.Write(c); + file.Flush(); + continue;*/ + + if (text != null) + { + foreach (char c in text) + { + switch (c) + { + case '\r' when (state.Is(StreamState.State.BEGIN)): + { + state.Set(StreamState.State.READ_CARRIAGE); + break; + } + + case '\n' when (state.Is(StreamState.State.READ_CARRIAGE)): + { + if (state.buffer.Length > 0) + { + string buffer = state.Fetch(); + + AppendToTextBox(buffer, state.isError ? System.Drawing.Color.Red : System.Drawing.Color.White); + + if (!state.isError) + ProcessStringForProgressBar(buffer); + } + output.AppendText(Environment.NewLine); + state.Clear(); + state.Set(StreamState.State.BEGIN); + break; + } + + default: + if (state.Is(StreamState.State.READ_CARRIAGE) && state.HasData()) + { + if (!String.IsNullOrEmpty(output.Lines.Last())) + output.Lines[output.Lines.Length] = string.Empty; + + string buffer = state.Fetch(); + + AppendToTextBox(buffer, state.isError ? System.Drawing.Color.Red : System.Drawing.Color.White); + + if (!state.isError) + ProcessStringForProgressBar(buffer); + + state.Clear(); + } + + state.Set(StreamState.State.BEGIN); + state.Append(c); + break; + + } + } + } + } + + #region EventHandlers + + private void OnWindowClosed(object sender, FormClosedEventArgs e) + { + GracefullyTerminateProcess(); + } + + private void OnWindowLoaded(object sender, EventArgs e) + { + var hwnd = this.Handle; + SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU); + } + + void OnProcessExit(object sender, EventArgs e) + { + //Dispatcher.CurrentDispatcher.Invoke(() => AbortButton.IsEnabled = false); + GracefullyTerminateProcess(); + } + + private void OnHideButton(object sender, EventArgs e) + { + ViewModels.LoggerViewModel.WindowVisible = false; + //TODO: this should be bound directly to WindowVisible property in two way fashion + // we need to study how to properly do it in XAML + _mainWindow.showLogWindowToolStripMenuItem.Checked = false; + } + + private void OnClearButton(object sender, EventArgs e) + { + output.Clear(); + } + + private void OnAbortButton(object sender, EventArgs args) + { + GracefullyTerminateProcess(); + } + + private void OnStartButton(object sender, EventArgs args) + { + StartDump("cd e Gam.iso 16"); + } + + private void OnTextChanged(object sender, EventArgs e) + { + output.ScrollToCaret(); + } + + #endregion + } +} diff --git a/DICUI.Forms/Windows/LogWindow.resx b/DICUI.Forms/Windows/LogWindow.resx new file mode 100644 index 00000000..61bc649b --- /dev/null +++ b/DICUI.Forms/Windows/LogWindow.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + \ No newline at end of file diff --git a/DICUI.Forms/Windows/MainWindow.Designer.cs b/DICUI.Forms/Windows/MainWindow.Designer.cs new file mode 100644 index 00000000..faaf6143 --- /dev/null +++ b/DICUI.Forms/Windows/MainWindow.Designer.cs @@ -0,0 +1,530 @@ +namespace DICUI.Forms.Windows +{ + partial class MainWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow)); + this.MenuBar = new System.Windows.Forms.MenuStrip(); + this.mainWindowLayout = new System.Windows.Forms.TableLayoutPanel(); + this.settingsGroupBox = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.parametersLabel = new System.Windows.Forms.Label(); + this.driveSpeedLabel = new System.Windows.Forms.Label(); + this.driveLetterLabel = new System.Windows.Forms.Label(); + this.outputDirectoryLabel = new System.Windows.Forms.Label(); + this.outputFilenameLabel = new System.Windows.Forms.Label(); + this.systemMediaTypeLabel = new System.Windows.Forms.Label(); + this.OutputFilenameTextBox = new System.Windows.Forms.TextBox(); + this.SystemTypeComboBox = new System.Windows.Forms.ComboBox(); + this.MediaTypeComboBox = new System.Windows.Forms.ComboBox(); + this.OutputDirectoryTextBox = new System.Windows.Forms.TextBox(); + this.OutputDirectoryBrowseButton = new System.Windows.Forms.Button(); + this.DriveLetterComboBox = new System.Windows.Forms.ComboBox(); + this.DriveSpeedComboBox = new System.Windows.Forms.ComboBox(); + this.ParametersTextBox = new System.Windows.Forms.TextBox(); + this.EnableParametersCheckBox = new System.Windows.Forms.CheckBox(); + this.controlsGroupBox = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.StartStopButton = new System.Windows.Forms.Button(); + this.DiscScanButton = new System.Windows.Forms.Button(); + this.CopyProtectScanButton = new System.Windows.Forms.Button(); + this.EjectWhenDoneCheckBox = new System.Windows.Forms.CheckBox(); + this.statusGroupBox = new System.Windows.Forms.GroupBox(); + this.StatusLabel = new System.Windows.Forms.TextBox(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.showLogWindowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.MenuBar.SuspendLayout(); + this.mainWindowLayout.SuspendLayout(); + this.settingsGroupBox.SuspendLayout(); + this.tableLayoutPanel2.SuspendLayout(); + this.controlsGroupBox.SuspendLayout(); + this.tableLayoutPanel3.SuspendLayout(); + this.statusGroupBox.SuspendLayout(); + this.SuspendLayout(); + // + // MenuBar + // + this.MenuBar.Location = new System.Drawing.Point(0, 0); + this.MenuBar.Name = "MenuBar"; + this.MenuBar.Size = new System.Drawing.Size(584, 24); + this.MenuBar.TabIndex = 0; + this.MenuBar.Text = "menuStrip1"; + this.MenuBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + fileToolStripMenuItem, toolsToolStripMenuItem, helpToolStripMenuItem}); + // + // mainWindowLayout + // + this.mainWindowLayout.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.mainWindowLayout.ColumnCount = 1; + this.mainWindowLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.mainWindowLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.mainWindowLayout.Controls.Add(this.settingsGroupBox, 0, 0); + this.mainWindowLayout.Controls.Add(this.controlsGroupBox, 0, 1); + this.mainWindowLayout.Controls.Add(this.statusGroupBox, 0, 2); + this.mainWindowLayout.Location = new System.Drawing.Point(13, 28); + this.mainWindowLayout.Name = "mainWindowLayout"; + this.mainWindowLayout.RowCount = 3; + this.mainWindowLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 82.66254F)); + this.mainWindowLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 17.33746F)); + this.mainWindowLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 47F)); + this.mainWindowLayout.Size = new System.Drawing.Size(559, 371); + this.mainWindowLayout.TabIndex = 1; + // + // settingsGroupBox + // + this.settingsGroupBox.Controls.Add(this.tableLayoutPanel2); + this.settingsGroupBox.Location = new System.Drawing.Point(3, 3); + this.settingsGroupBox.Name = "settingsGroupBox"; + this.settingsGroupBox.Size = new System.Drawing.Size(553, 259); + this.settingsGroupBox.TabIndex = 0; + this.settingsGroupBox.TabStop = false; + this.settingsGroupBox.Text = "Settings"; + // + // tableLayoutPanel2 + // + this.tableLayoutPanel2.ColumnCount = 3; + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 26.32794F)); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 73.67206F)); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 144F)); + this.tableLayoutPanel2.Controls.Add(this.parametersLabel, 0, 5); + this.tableLayoutPanel2.Controls.Add(this.driveSpeedLabel, 0, 4); + this.tableLayoutPanel2.Controls.Add(this.driveLetterLabel, 0, 3); + this.tableLayoutPanel2.Controls.Add(this.outputDirectoryLabel, 0, 2); + this.tableLayoutPanel2.Controls.Add(this.outputFilenameLabel, 0, 1); + this.tableLayoutPanel2.Controls.Add(this.systemMediaTypeLabel, 0, 0); + this.tableLayoutPanel2.Controls.Add(this.OutputFilenameTextBox, 1, 1); + this.tableLayoutPanel2.Controls.Add(this.SystemTypeComboBox, 1, 0); + this.tableLayoutPanel2.Controls.Add(this.MediaTypeComboBox, 2, 0); + this.tableLayoutPanel2.Controls.Add(this.OutputDirectoryTextBox, 1, 2); + this.tableLayoutPanel2.Controls.Add(this.OutputDirectoryBrowseButton, 2, 2); + this.tableLayoutPanel2.Controls.Add(this.DriveLetterComboBox, 1, 3); + this.tableLayoutPanel2.Controls.Add(this.DriveSpeedComboBox, 1, 4); + this.tableLayoutPanel2.Controls.Add(this.ParametersTextBox, 1, 5); + this.tableLayoutPanel2.Controls.Add(this.EnableParametersCheckBox, 2, 5); + this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 19); + this.tableLayoutPanel2.Name = "tableLayoutPanel2"; + this.tableLayoutPanel2.Padding = new System.Windows.Forms.Padding(0, 5, 0, 5); + this.tableLayoutPanel2.RowCount = 6; + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 16.66667F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(553, 234); + this.tableLayoutPanel2.TabIndex = 0; + // + // parametersLabel + // + this.parametersLabel.AutoSize = true; + this.parametersLabel.Dock = System.Windows.Forms.DockStyle.Fill; + this.parametersLabel.Location = new System.Drawing.Point(3, 190); + this.parametersLabel.Name = "parametersLabel"; + this.parametersLabel.Size = new System.Drawing.Size(101, 39); + this.parametersLabel.TabIndex = 10; + this.parametersLabel.Text = "Parameters"; + this.parametersLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // driveSpeedLabel + // + this.driveSpeedLabel.AutoSize = true; + this.driveSpeedLabel.Dock = System.Windows.Forms.DockStyle.Fill; + this.driveSpeedLabel.Location = new System.Drawing.Point(3, 153); + this.driveSpeedLabel.Name = "driveSpeedLabel"; + this.driveSpeedLabel.Size = new System.Drawing.Size(101, 37); + this.driveSpeedLabel.TabIndex = 8; + this.driveSpeedLabel.Text = "Drive Speed"; + this.driveSpeedLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // driveLetterLabel + // + this.driveLetterLabel.AutoSize = true; + this.driveLetterLabel.Dock = System.Windows.Forms.DockStyle.Fill; + this.driveLetterLabel.Location = new System.Drawing.Point(3, 116); + this.driveLetterLabel.Name = "driveLetterLabel"; + this.driveLetterLabel.Size = new System.Drawing.Size(101, 37); + this.driveLetterLabel.TabIndex = 6; + this.driveLetterLabel.Text = "Drive Letter"; + this.driveLetterLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // outputDirectoryLabel + // + this.outputDirectoryLabel.AutoSize = true; + this.outputDirectoryLabel.Dock = System.Windows.Forms.DockStyle.Fill; + this.outputDirectoryLabel.Location = new System.Drawing.Point(3, 79); + this.outputDirectoryLabel.Name = "outputDirectoryLabel"; + this.outputDirectoryLabel.Size = new System.Drawing.Size(101, 37); + this.outputDirectoryLabel.TabIndex = 4; + this.outputDirectoryLabel.Text = "Output Directory"; + this.outputDirectoryLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // outputFilenameLabel + // + this.outputFilenameLabel.AutoSize = true; + this.outputFilenameLabel.Dock = System.Windows.Forms.DockStyle.Fill; + this.outputFilenameLabel.Location = new System.Drawing.Point(3, 42); + this.outputFilenameLabel.Name = "outputFilenameLabel"; + this.outputFilenameLabel.Size = new System.Drawing.Size(101, 37); + this.outputFilenameLabel.TabIndex = 2; + this.outputFilenameLabel.Text = "Output Filename"; + this.outputFilenameLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // systemMediaTypeLabel + // + this.systemMediaTypeLabel.AutoSize = true; + this.systemMediaTypeLabel.Dock = System.Windows.Forms.DockStyle.Fill; + this.systemMediaTypeLabel.Location = new System.Drawing.Point(3, 5); + this.systemMediaTypeLabel.Name = "systemMediaTypeLabel"; + this.systemMediaTypeLabel.Size = new System.Drawing.Size(101, 37); + this.systemMediaTypeLabel.TabIndex = 0; + this.systemMediaTypeLabel.Text = "System/Media Type"; + this.systemMediaTypeLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // OutputFilenameTextBox + // + this.OutputFilenameTextBox.Anchor = System.Windows.Forms.AnchorStyles.None; + this.tableLayoutPanel2.SetColumnSpan(this.OutputFilenameTextBox, 2); + this.OutputFilenameTextBox.Location = new System.Drawing.Point(111, 50); + this.OutputFilenameTextBox.Name = "OutputFilenameTextBox"; + this.OutputFilenameTextBox.Size = new System.Drawing.Size(438, 20); + this.OutputFilenameTextBox.TabIndex = 11; + this.OutputFilenameTextBox.TextChanged += new System.EventHandler(this.OutputFilenameTextBoxTextChanged); + // + // SystemTypeComboBox + // + this.SystemTypeComboBox.Anchor = System.Windows.Forms.AnchorStyles.None; + this.SystemTypeComboBox.DisplayMember = "Name"; + this.SystemTypeComboBox.DropDownWidth = 250; + this.SystemTypeComboBox.FormattingEnabled = true; + this.SystemTypeComboBox.Location = new System.Drawing.Point(110, 13); + this.SystemTypeComboBox.Name = "SystemTypeComboBox"; + this.SystemTypeComboBox.Size = new System.Drawing.Size(295, 21); + this.SystemTypeComboBox.TabIndex = 13; + this.SystemTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.SystemTypeComboBoxSelectionChanged); + // + // MediaTypeComboBox + // + this.MediaTypeComboBox.Anchor = System.Windows.Forms.AnchorStyles.None; + this.MediaTypeComboBox.DisplayMember = "Name"; + this.MediaTypeComboBox.FormattingEnabled = true; + this.MediaTypeComboBox.Location = new System.Drawing.Point(415, 13); + this.MediaTypeComboBox.Name = "MediaTypeComboBox"; + this.MediaTypeComboBox.Size = new System.Drawing.Size(131, 21); + this.MediaTypeComboBox.TabIndex = 14; + this.MediaTypeComboBox.SelectedIndexChanged += new System.EventHandler(this.MediaTypeComboBoxSelectionChanged); + // + // OutputDirectoryTextBox + // + this.OutputDirectoryTextBox.Anchor = System.Windows.Forms.AnchorStyles.None; + this.OutputDirectoryTextBox.Location = new System.Drawing.Point(110, 87); + this.OutputDirectoryTextBox.Name = "OutputDirectoryTextBox"; + this.OutputDirectoryTextBox.Size = new System.Drawing.Size(295, 20); + this.OutputDirectoryTextBox.TabIndex = 15; + this.OutputDirectoryTextBox.TextChanged += new System.EventHandler(this.OutputDirectoryTextBoxTextChanged); + // + // OutputDirectoryBrowseButton + // + this.OutputDirectoryBrowseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); + this.OutputDirectoryBrowseButton.Location = new System.Drawing.Point(411, 84); + this.OutputDirectoryBrowseButton.Name = "OutputDirectoryBrowseButton"; + this.OutputDirectoryBrowseButton.Size = new System.Drawing.Size(139, 26); + this.OutputDirectoryBrowseButton.TabIndex = 16; + this.OutputDirectoryBrowseButton.Text = "Browse"; + this.OutputDirectoryBrowseButton.UseVisualStyleBackColor = true; + this.OutputDirectoryBrowseButton.Click += new System.EventHandler(this.OutputDirectoryBrowseButtonClick); + // + // DriveLetterComboBox + // + this.DriveLetterComboBox.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.DriveLetterComboBox.DisplayMember = "Letter"; + this.DriveLetterComboBox.FormattingEnabled = true; + this.DriveLetterComboBox.Location = new System.Drawing.Point(110, 124); + this.DriveLetterComboBox.Name = "DriveLetterComboBox"; + this.DriveLetterComboBox.Size = new System.Drawing.Size(121, 21); + this.DriveLetterComboBox.TabIndex = 17; + this.DriveLetterComboBox.SelectedIndexChanged += new System.EventHandler(this.DriveLetterComboBoxSelectionChanged); + // + // DriveSpeedComboBox + // + this.DriveSpeedComboBox.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.DriveSpeedComboBox.FormattingEnabled = true; + this.DriveSpeedComboBox.Location = new System.Drawing.Point(110, 161); + this.DriveSpeedComboBox.Name = "DriveSpeedComboBox"; + this.DriveSpeedComboBox.Size = new System.Drawing.Size(121, 21); + this.DriveSpeedComboBox.TabIndex = 18; + this.DriveSpeedComboBox.SelectedIndexChanged += new System.EventHandler(this.DriveSpeedComboBoxSelectionChanged); + // + // ParametersTextBox + // + this.ParametersTextBox.Anchor = System.Windows.Forms.AnchorStyles.None; + this.ParametersTextBox.Enabled = false; + this.ParametersTextBox.Location = new System.Drawing.Point(110, 199); + this.ParametersTextBox.Name = "ParametersTextBox"; + this.ParametersTextBox.ReadOnly = true; + this.ParametersTextBox.Size = new System.Drawing.Size(295, 20); + this.ParametersTextBox.TabIndex = 19; + // + // EnableParametersCheckBox + // + this.EnableParametersCheckBox.AutoSize = true; + this.EnableParametersCheckBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.EnableParametersCheckBox.Location = new System.Drawing.Point(411, 193); + this.EnableParametersCheckBox.Name = "EnableParametersCheckBox"; + this.EnableParametersCheckBox.Size = new System.Drawing.Size(139, 33); + this.EnableParametersCheckBox.TabIndex = 20; + this.EnableParametersCheckBox.Text = "Enable Editing"; + this.EnableParametersCheckBox.UseVisualStyleBackColor = true; + this.EnableParametersCheckBox.CheckedChanged += new System.EventHandler(this.EnableParametersCheckBoxClick); + // + // controlsGroupBox + // + this.controlsGroupBox.Controls.Add(this.tableLayoutPanel3); + this.controlsGroupBox.Location = new System.Drawing.Point(3, 270); + this.controlsGroupBox.Name = "controlsGroupBox"; + this.controlsGroupBox.Size = new System.Drawing.Size(553, 50); + this.controlsGroupBox.TabIndex = 1; + this.controlsGroupBox.TabStop = false; + this.controlsGroupBox.Text = "Controls"; + // + // tableLayoutPanel3 + // + this.tableLayoutPanel3.ColumnCount = 4; + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tableLayoutPanel3.Controls.Add(this.StartStopButton, 0, 0); + this.tableLayoutPanel3.Controls.Add(this.DiscScanButton, 1, 0); + this.tableLayoutPanel3.Controls.Add(this.CopyProtectScanButton, 2, 0); + this.tableLayoutPanel3.Controls.Add(this.EjectWhenDoneCheckBox, 3, 0); + this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 20); + this.tableLayoutPanel3.Name = "tableLayoutPanel3"; + this.tableLayoutPanel3.RowCount = 1; + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.Size = new System.Drawing.Size(553, 32); + this.tableLayoutPanel3.TabIndex = 0; + // + // StartStopButton + // + this.StartStopButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.StartStopButton.Enabled = false; + this.StartStopButton.Location = new System.Drawing.Point(3, 3); + this.StartStopButton.Name = "StartStopButton"; + this.StartStopButton.Size = new System.Drawing.Size(132, 26); + this.StartStopButton.TabIndex = 0; + this.StartStopButton.Text = "Start Dumping"; + this.StartStopButton.UseVisualStyleBackColor = true; + this.StartStopButton.Click += new System.EventHandler(this.StartStopButtonClick); + // + // DiscScanButton + // + this.DiscScanButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.DiscScanButton.Location = new System.Drawing.Point(141, 3); + this.DiscScanButton.Name = "DiscScanButton"; + this.DiscScanButton.Size = new System.Drawing.Size(132, 26); + this.DiscScanButton.TabIndex = 1; + this.DiscScanButton.Text = "Scan For Discs"; + this.DiscScanButton.UseVisualStyleBackColor = true; + this.DiscScanButton.Click += new System.EventHandler(this.DiscScanButtonClick); + // + // CopyProtectScanButton + // + this.CopyProtectScanButton.Dock = System.Windows.Forms.DockStyle.Fill; + this.CopyProtectScanButton.Location = new System.Drawing.Point(279, 3); + this.CopyProtectScanButton.Name = "CopyProtectScanButton"; + this.CopyProtectScanButton.Size = new System.Drawing.Size(132, 26); + this.CopyProtectScanButton.TabIndex = 2; + this.CopyProtectScanButton.Text = "Scan For Protection"; + this.CopyProtectScanButton.UseVisualStyleBackColor = true; + this.CopyProtectScanButton.Click += new System.EventHandler(this.CopyProtectScanButtonClick); + // + // EjectWhenDoneCheckBox + // + this.EjectWhenDoneCheckBox.AutoSize = true; + this.EjectWhenDoneCheckBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.EjectWhenDoneCheckBox.Location = new System.Drawing.Point(417, 3); + this.EjectWhenDoneCheckBox.Name = "EjectWhenDoneCheckBox"; + this.EjectWhenDoneCheckBox.Size = new System.Drawing.Size(133, 26); + this.EjectWhenDoneCheckBox.TabIndex = 3; + this.EjectWhenDoneCheckBox.Text = "Eject When Done"; + this.EjectWhenDoneCheckBox.UseVisualStyleBackColor = true; + // + // statusGroupBox + // + this.statusGroupBox.Controls.Add(this.StatusLabel); + this.statusGroupBox.Location = new System.Drawing.Point(3, 326); + this.statusGroupBox.Name = "statusGroupBox"; + this.statusGroupBox.Size = new System.Drawing.Size(553, 42); + this.statusGroupBox.TabIndex = 2; + this.statusGroupBox.TabStop = false; + this.statusGroupBox.Text = "Status"; + // + // StatusLabel + // + this.StatusLabel.Dock = System.Windows.Forms.DockStyle.Fill; + this.StatusLabel.Enabled = false; + this.StatusLabel.Location = new System.Drawing.Point(3, 16); + this.StatusLabel.Name = "StatusLabel"; + this.StatusLabel.ReadOnly = true; + this.StatusLabel.Size = new System.Drawing.Size(547, 20); + this.StatusLabel.TabIndex = 0; + this.StatusLabel.Text = "Waiting for media..."; + this.StatusLabel.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.F))); + this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); + this.fileToolStripMenuItem.Text = "File"; + // + // toolsToolStripMenuItem + // + this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; + this.toolsToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.T))); + this.toolsToolStripMenuItem.Size = new System.Drawing.Size(47, 20); + this.toolsToolStripMenuItem.Text = "Tools"; + // + // helpToolStripMenuItem + // + this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; + this.helpToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.H))); + this.helpToolStripMenuItem.Size = new System.Drawing.Size(44, 20); + this.helpToolStripMenuItem.Text = "Help"; + // + // exitToolStripMenuItem + // + this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; + this.exitToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.X))); + this.exitToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.exitToolStripMenuItem.Text = "Exit"; + this.exitToolStripMenuItem.Click += new System.EventHandler(this.AppExitClick); + // + // optionsToolStripMenuItem + // + this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; + this.optionsToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.O))); + this.optionsToolStripMenuItem.Size = new System.Drawing.Size(209, 22); + this.optionsToolStripMenuItem.Text = "Options"; + this.optionsToolStripMenuItem.Click += new System.EventHandler(this.OptionsClick); + // + // showLogWindowToolStripMenuItem + // + this.showLogWindowToolStripMenuItem.Checked = true; + this.showLogWindowToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; + this.showLogWindowToolStripMenuItem.Name = "showLogWindowToolStripMenuItem"; + this.showLogWindowToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.L))); + this.showLogWindowToolStripMenuItem.Size = new System.Drawing.Size(209, 22); + this.showLogWindowToolStripMenuItem.Text = "Show Log Window"; + // + // aboutToolStripMenuItem + // + this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; + this.aboutToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Alt | System.Windows.Forms.Keys.A))); + this.aboutToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.aboutToolStripMenuItem.Text = "About"; + this.aboutToolStripMenuItem.Click += new System.EventHandler(this.AboutClick); + // + // MainWindow + // + this.AcceptButton = this.StartStopButton; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(584, 411); + this.Controls.Add(this.mainWindowLayout); + this.Controls.Add(this.MenuBar); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MainMenuStrip = this.MenuBar; + this.Name = "MainWindow"; + this.Text = "DiscImageCreator GUI"; + this.Activated += new System.EventHandler(this.MainWindowActivated); + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainWindowClosing); + this.Load += new System.EventHandler(this.OnContentRendered); + this.LocationChanged += new System.EventHandler(this.MainWindowLocationChanged); + this.MenuBar.ResumeLayout(false); + this.MenuBar.PerformLayout(); + this.mainWindowLayout.ResumeLayout(false); + this.settingsGroupBox.ResumeLayout(false); + this.tableLayoutPanel2.ResumeLayout(false); + this.tableLayoutPanel2.PerformLayout(); + this.controlsGroupBox.ResumeLayout(false); + this.tableLayoutPanel3.ResumeLayout(false); + this.tableLayoutPanel3.PerformLayout(); + this.statusGroupBox.ResumeLayout(false); + this.statusGroupBox.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip MenuBar; + private System.Windows.Forms.TableLayoutPanel mainWindowLayout; + private System.Windows.Forms.GroupBox settingsGroupBox; + private System.Windows.Forms.GroupBox controlsGroupBox; + private System.Windows.Forms.GroupBox statusGroupBox; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; + private System.Windows.Forms.Label systemMediaTypeLabel; + private System.Windows.Forms.Label parametersLabel; + private System.Windows.Forms.Label driveSpeedLabel; + private System.Windows.Forms.Label driveLetterLabel; + private System.Windows.Forms.Label outputDirectoryLabel; + private System.Windows.Forms.Label outputFilenameLabel; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; + private System.Windows.Forms.Button StartStopButton; + private System.Windows.Forms.Button DiscScanButton; + private System.Windows.Forms.Button CopyProtectScanButton; + private System.Windows.Forms.CheckBox EjectWhenDoneCheckBox; + private System.Windows.Forms.TextBox OutputFilenameTextBox; + private System.Windows.Forms.ComboBox SystemTypeComboBox; + private System.Windows.Forms.ComboBox MediaTypeComboBox; + private System.Windows.Forms.TextBox OutputDirectoryTextBox; + private System.Windows.Forms.Button OutputDirectoryBrowseButton; + private System.Windows.Forms.ComboBox DriveLetterComboBox; + private System.Windows.Forms.ComboBox DriveSpeedComboBox; + private System.Windows.Forms.TextBox ParametersTextBox; + private System.Windows.Forms.CheckBox EnableParametersCheckBox; + private System.Windows.Forms.TextBox StatusLabel; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; + internal System.Windows.Forms.ToolStripMenuItem showLogWindowToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem; + } +} + diff --git a/DICUI.Forms/Windows/MainWindow.cs b/DICUI.Forms/Windows/MainWindow.cs new file mode 100644 index 00000000..6db59218 --- /dev/null +++ b/DICUI.Forms/Windows/MainWindow.cs @@ -0,0 +1,723 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Windows; +using System.Windows.Forms; +using DICUI.Data; +using DICUI.Utilities; + +namespace DICUI.Forms.Windows +{ + public partial class MainWindow : Form + { + // Private UI-related variables + private List _drives; + private MediaType? _currentMediaType; + private List _systems; + private List _mediaTypes; + private bool _alreadyShown; + + private DumpEnvironment _env; + + // Option related + private Options _options; + private OptionsWindow _optionsWindow; + + private LogWindow _logWindow; + + public MainWindow() + { + InitializeComponent(); + + // Initializes and load Options object + _options = new Options(); + _options.Load(); + ViewModels.OptionsViewModel = new OptionsViewModel(_options); + + _logWindow = new LogWindow(this); + ViewModels.LoggerViewModel.SetWindow(_logWindow); + + // Disable buttons until we load fully + StartStopButton.Enabled = false; + DiscScanButton.Enabled = false; + CopyProtectScanButton.Enabled = false; + + if (_options.OpenLogWindowAtStartup) + { + this.StartPosition = FormStartPosition.CenterScreen; + double combinedHeight = this.Height + _logWindow.Height + Constants.LogWindowMarginFromMainWindow; + Rectangle bounds = GetScaledCoordinates(Screen.PrimaryScreen.WorkingArea); + + this.Left = (int)(bounds.Left + (bounds.Width - this.Width) / 2); + this.Top = (int)(bounds.Top + (bounds.Height - combinedHeight) / 2); + } + } + + #region Events + + private void OnContentRendered(object sender, EventArgs e) + { + if (_alreadyShown) + return; + + _alreadyShown = true; + + if (_options.OpenLogWindowAtStartup) + { + //TODO: this should be bound directly to WindowVisible property in two way fashion + // we need to study how to properly do it in XAML + showLogWindowToolStripMenuItem.Checked = true; + ViewModels.LoggerViewModel.WindowVisible = true; + } + + // Populate the list of systems + StatusLabel.Text = "Creating system list, please wait!"; + PopulateSystems(); + + // Populate the list of drives + StatusLabel.Text = "Creating drive list, please wait!"; + PopulateDrives(); + + // Set the position of the log window + if (_logWindow.Visible) + { + _logWindow.AdjustPositionToMainWindow(); + this.Focus(); + } + } + + private void StartStopButtonClick(object sender, EventArgs e) + { + // Dump or stop the dump + if (StartStopButton.Text == Constants.StartDumping) + { + StartDumping(); + } + else if (StartStopButton.Text == Constants.StopDumping) + { + ViewModels.LoggerViewModel.VerboseLogLn("Canceling dumping process..."); + _env.CancelDumping(); + CopyProtectScanButton.Enabled = true; + + if (EjectWhenDoneCheckBox.Checked == true) + { + ViewModels.LoggerViewModel.VerboseLogLn($"Ejecting disc in drive {_env.Drive.Letter}"); + _env.EjectDisc(); + } + } + } + + private void OutputDirectoryBrowseButtonClick(object sender, EventArgs e) + { + BrowseFolder(); + EnsureDiscInformation(); + } + + private void DiscScanButtonClick(object sender, EventArgs e) + { + PopulateDrives(); + } + + private void CopyProtectScanButtonClick(object sender, EventArgs e) + { + ScanAndShowProtection(); + } + + private void SystemTypeComboBoxSelectionChanged(object sender, EventArgs e) + { + // If we're on a separator, go to the next item and return + if ((SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem).IsHeader()) + { + SystemTypeComboBox.SelectedIndex++; + return; + } + + ViewModels.LoggerViewModel.VerboseLogLn("Changed system to: {0}", (SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem).Name); + PopulateMediaType(); + EnsureDiscInformation(); + } + + private void MediaTypeComboBoxSelectionChanged(object sender, EventArgs e) + { + _currentMediaType = MediaTypeComboBox.SelectedItem as MediaType?; + SetSupportedDriveSpeed(); + GetOutputNames(); + EnsureDiscInformation(); + } + + private void DriveLetterComboBoxSelectionChanged(object sender, EventArgs e) + { + CacheCurrentDiscType(); + SetCurrentDiscType(); + GetOutputNames(); + SetSupportedDriveSpeed(); + } + + private void DriveSpeedComboBoxSelectionChanged(object sender, EventArgs e) + { + EnsureDiscInformation(); + } + + private void OutputFilenameTextBoxTextChanged(object sender, EventArgs e) + { + EnsureDiscInformation(); + } + + private void OutputDirectoryTextBoxTextChanged(object sender, EventArgs e) + { + EnsureDiscInformation(); + } + + private void ProgressUpdated(object sender, Result value) + { + StatusLabel.Text = value.Message; + ViewModels.LoggerViewModel.VerboseLogLn(value.Message); + } + + private void MainWindowLocationChanged(object sender, EventArgs e) + { + if (_logWindow.Visible) + _logWindow.AdjustPositionToMainWindow(); + } + + private void MainWindowActivated(object sender, EventArgs e) + { + if (!_logWindow.Visible) + _logWindow.BringToFront(); + this.BringToFront(); + } + + private void MainWindowClosing(object sender, FormClosingEventArgs e) + { + if (_logWindow.Visible) + _logWindow.Close(); + } + + private void EnableParametersCheckBoxClick(object sender, EventArgs e) + { + if (EnableParametersCheckBox.Checked) + { + ParametersTextBox.ReadOnly = false; + ParametersTextBox.Enabled = true; + } + else + { + ParametersTextBox.ReadOnly = true; + ParametersTextBox.Enabled = false; + ProcessCustomParameters(); + } + } + + // Toolbar Events + + private void AppExitClick(object sender, EventArgs e) + { + System.Windows.Application.Current.Shutdown(); + } + + private void AboutClick(object sender, EventArgs e) + { + System.Windows.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, EventArgs e) + { + // lazy initialization + if (_optionsWindow == null) + { + _optionsWindow = new OptionsWindow(this, _options); + _optionsWindow.Closed += delegate + { + _optionsWindow = null; + }; + } + + _optionsWindow.Owner = this; + _optionsWindow.StartPosition = FormStartPosition.CenterParent; + _optionsWindow.RefreshSettings(); + _optionsWindow.Show(); + } + + public void OnOptionsUpdated() + { + GetOutputNames(); + SetSupportedDriveSpeed(); + EnsureDiscInformation(); + } + + #endregion + + #region Helpers + + /// + /// Populate media type according to system type + /// + private void PopulateMediaType() + { + KnownSystem? currentSystem = SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem; + + if (currentSystem != null) + { + _mediaTypes = Validators.GetValidMediaTypes(currentSystem).ToList(); + MediaTypeComboBox.DataSource = _mediaTypes; + + MediaTypeComboBox.Enabled = _mediaTypes.Count > 1; + MediaTypeComboBox.SelectedIndex = (_mediaTypes.IndexOf(_currentMediaType) >= 0 ? _mediaTypes.IndexOf(_currentMediaType) : 0); + } + else + { + MediaTypeComboBox.Enabled = false; + MediaTypeComboBox.DataSource = null; + MediaTypeComboBox.SelectedIndex = -1; + } + } + + /// + /// Get a complete list of supported systems and fill the combo box + /// + private void PopulateSystems() + { + _systems = Validators.CreateListOfSystems(); + + ViewModels.LoggerViewModel.VerboseLogLn("Populating systems, {0} systems found.", _systems.Count); + + Dictionary> mapping = _systems + .GroupBy(s => s.Category()) + .ToDictionary( + k => k.Key, + v => v + .OrderBy(s => s.Name()) + .ToList() + ); + + List comboBoxItems = new List(); + + comboBoxItems.Add(new KnownSystemComboBoxItem(KnownSystem.NONE)); + + foreach (var group in mapping) + { + comboBoxItems.Add(new KnownSystemComboBoxItem(group.Key)); + group.Value.ForEach(system => comboBoxItems.Add(new KnownSystemComboBoxItem(system))); + } + + SystemTypeComboBox.DataSource = comboBoxItems; + SystemTypeComboBox.SelectedIndex = 0; + + StartStopButton.Enabled = false; + } + + /// + /// Get a complete list of active disc drives and fill the combo box + /// + /// TODO: Find a way for this to periodically run, or have it hook to a "drive change" event + private void PopulateDrives() + { + ViewModels.LoggerViewModel.VerboseLogLn("Scanning for drives.."); + + // Always enable the disk scan + DiscScanButton.Enabled = true; + + // Populate the list of drives and add it to the combo box + _drives = Validators.CreateListOfDrives(); + DriveLetterComboBox.DataSource = _drives; + + if (DriveLetterComboBox.Items.Count > 0) + { + int index = _drives.FindIndex(d => d.MarkedActive); + DriveLetterComboBox.SelectedIndex = (index != -1 ? index : 0); + StatusLabel.Text = "Valid drive found! Choose your Media Type"; + StartStopButton.Enabled = true; + CopyProtectScanButton.Enabled = true; + + ViewModels.LoggerViewModel.VerboseLogLn("Found {0} drives: {1}", _drives.Count, String.Join(", ", _drives.Select(d => d.Letter))); + } + else + { + DriveLetterComboBox.SelectedIndex = -1; + StatusLabel.Text = "No valid drive found!"; + StartStopButton.Enabled = false; + CopyProtectScanButton.Enabled = false; + + ViewModels.LoggerViewModel.VerboseLogLn("Found no drives"); + } + } + + /// + /// Browse for an output folder + /// + private void BrowseFolder() + { + FolderBrowserDialog folderDialog = new FolderBrowserDialog { ShowNewFolderButton = false, SelectedPath = System.AppDomain.CurrentDomain.BaseDirectory }; + DialogResult result = folderDialog.ShowDialog(); + + if (result == DialogResult.OK) + { + OutputDirectoryTextBox.Text = folderDialog.SelectedPath; + } + } + + /// + /// Create a DumpEnvironment with all current settings + /// + /// Filled DumpEnvironment instance + private DumpEnvironment DetermineEnvironment() + { + // Populate the new environment + var env = new DumpEnvironment() + { + // Paths to tools + SubdumpPath = _options.SubDumpPath, + DICPath = _options.DICPath, + + OutputDirectory = OutputDirectoryTextBox.Text, + OutputFilename = OutputFilenameTextBox.Text, + + // Get the currently selected options + Drive = DriveLetterComboBox.SelectedItem as Drive, + + DICParameters = new Parameters(ParametersTextBox.Text), + + QuietMode = _options.QuietMode, + ParanoidMode = _options.ParanoidMode, + ScanForProtection = _options.ScanForProtection, + RereadAmountC2 = _options.RereadAmountForC2, + + System = SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem, + Type = MediaTypeComboBox.SelectedItem as MediaType? + }; + + // Fix the output paths + env.FixOutputPaths(); + + // Disable automatic reprocessing of the textboxes until we're done + OutputDirectoryTextBox.TextChanged -= OutputDirectoryTextBoxTextChanged; + OutputFilenameTextBox.TextChanged -= OutputFilenameTextBoxTextChanged; + + OutputDirectoryTextBox.Text = env.OutputDirectory; + OutputFilenameTextBox.Text = env.OutputFilename; + + OutputDirectoryTextBox.TextChanged += OutputDirectoryTextBoxTextChanged; + OutputFilenameTextBox.TextChanged += OutputFilenameTextBoxTextChanged; + + return env; + } + + /// + /// Begin the dumping process using the given inputs + /// + private async void StartDumping() + { + if (_env == null) + _env = DetermineEnvironment(); + + // If still in custom parameter mode, check that users meant to continue or not + if (EnableParametersCheckBox.Checked == true) + { + MessageBoxResult result = System.Windows.MessageBox.Show("It looks like you have custom parameters that have not been saved. Would you like to apply those changes before starting to dump?", "Custom Changes", MessageBoxButton.YesNoCancel, MessageBoxImage.Question); + if (result == MessageBoxResult.Yes) + { + EnableParametersCheckBox.Checked = false; + ParametersTextBox.Enabled = false; + ProcessCustomParameters(); + } + else if (result == MessageBoxResult.Cancel) + return; + // If "No", then we continue with the current known environment + } + + try + { + // Check for the firmware first + // TODO: Remove this (and method) once DIC end-to-end logging becomes a thing + if (!await _env.DriveHasLatestFimrware()) + { + System.Windows.MessageBox.Show($"DiscImageCreator has reported that drive {_env.Drive.Letter} is not updated to the most recent firmware. Please update the firmware for your drive and try again.", "Outdated Firmware", MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + + // Validate that the user explicitly wants an inactive drive to be considered for dumping + if (!_env.Drive.MarkedActive) + { + MessageBoxResult mbresult = System.Windows.MessageBox.Show("The currently selected drive does not appear to contain a disc! Are you sure you want to continue?", "Missing Disc", MessageBoxButton.YesNo, MessageBoxImage.Exclamation); + if (mbresult == MessageBoxResult.No || mbresult == MessageBoxResult.Cancel || mbresult == MessageBoxResult.None) + { + ViewModels.LoggerViewModel.VerboseLogLn("Dumping aborted!"); + return; + } + } + + // If a complete dump already exists + if (_env.FoundAllFiles()) + { + MessageBoxResult mbresult = System.Windows.MessageBox.Show("A complete dump already exists! Are you sure you want to overwrite?", "Overwrite?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation); + if (mbresult == MessageBoxResult.No || mbresult == MessageBoxResult.Cancel || mbresult == MessageBoxResult.None) + { + ViewModels.LoggerViewModel.VerboseLogLn("Dumping aborted!"); + return; + } + } + + StartStopButton.Text = Constants.StopDumping; + CopyProtectScanButton.Enabled = false; + StatusLabel.Text = "Beginning dumping process"; + ViewModels.LoggerViewModel.VerboseLogLn("Starting dumping process.."); + + var progress = new Progress(); + progress.ProgressChanged += ProgressUpdated; + Result result = await _env.StartDumping(progress); + + StatusLabel.Text = result ? "Dumping complete!" : result.Message; + ViewModels.LoggerViewModel.VerboseLogLn(result ? "Dumping complete!" : result.Message); + } + catch + { + // No-op, we don't care what it was + } + finally + { + StartStopButton.Text = Constants.StartDumping; + CopyProtectScanButton.Enabled = true; + } + + if (EjectWhenDoneCheckBox.Checked == true) + { + ViewModels.LoggerViewModel.VerboseLogLn($"Ejecting disc in drive {_env.Drive.Letter}"); + _env.EjectDisc(); + } + } + + /// + /// Ensure information is consistent with the currently selected disc type + /// + 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); + StatusLabel.Text = result.Message; + + // Set the index for the current disc type + SetCurrentDiscType(); + + StartStopButton.Enabled = result && (_drives != null && _drives.Count > 0 ? true : false); + + // If we're in a type that doesn't support drive speeds + DriveSpeedComboBox.Enabled = _env.Type.DoesSupportDriveSpeed(); + + // If input params are not enabled, generate the full parameters from the environment + if (!ParametersTextBox.Enabled) + { + string generated = _env.GetFullParameters((int?)DriveSpeedComboBox.SelectedItem); + if (generated != null) + ParametersTextBox.Text = generated; + } + } + + /// + /// Get the default output directory name from the currently selected drive + /// + private void GetOutputNames() + { + Drive drive = DriveLetterComboBox.SelectedItem as Drive; + KnownSystem? systemType = SystemTypeComboBox.SelectedItem as KnownSystemComboBoxItem; + MediaType? mediaType = MediaTypeComboBox.SelectedItem as MediaType?; + + OutputDirectoryTextBox.Text = Path.Combine(_options.DefaultOutputPath, drive?.VolumeLabel ?? string.Empty); + OutputFilenameTextBox.Text = (drive?.VolumeLabel ?? "disc") + (mediaType.Extension() ?? ".bin"); + } + + /// + /// Scan and show copy protection for the current disc + /// + private async void ScanAndShowProtection() + { + if (_env == null) + _env = DetermineEnvironment(); + + if (_env.Drive.Letter != default(char)) + { + ViewModels.LoggerViewModel.VerboseLogLn("Scanning for copy protection in {0}", _env.Drive.Letter); + + var tempContent = StatusLabel.Text; + StatusLabel.Text = "Scanning for copy protection... this might take a while!"; + StartStopButton.Enabled = false; + DiscScanButton.Enabled = false; + CopyProtectScanButton.Enabled = false; + + string protections = await Validators.RunProtectionScanOnPath(_env.Drive.Letter + ":\\"); + if (!ViewModels.LoggerViewModel.WindowVisible) + System.Windows.MessageBox.Show(protections, "Detected Protection", MessageBoxButton.OK, MessageBoxImage.Information); + ViewModels.LoggerViewModel.VerboseLog("Detected the following protections in {0}:\r\n\r\n{1}", _env.Drive.Letter, protections); + + StatusLabel.Text = tempContent; + StartStopButton.Enabled = true; + DiscScanButton.Enabled = true; + CopyProtectScanButton.Enabled = true; + } + } + + /// + /// Set the drive speed based on reported maximum and user-defined option + /// + private void SetSupportedDriveSpeed() + { + // Set the drive speed list that's appropriate + var values = Constants.GetSpeedsForMediaType(_currentMediaType); + DriveSpeedComboBox.DataSource = values; + ViewModels.LoggerViewModel.VerboseLogLn("Supported media speeds: {0}", string.Join(",", values)); + + // Find the minimum set to compare against + int preferred = 100; + switch (_currentMediaType) + { + case MediaType.CDROM: + case MediaType.GDROM: + preferred = _options.preferredDumpSpeedCD; + break; + case MediaType.DVD: + case MediaType.HDDVD: + case MediaType.NintendoGameCube: + case MediaType.NintendoWiiOpticalDisc: + preferred = _options.preferredDumpSpeedDVD; + break; + case MediaType.BluRay: + preferred = _options.preferredDumpSpeedBD; + break; + default: + preferred = _options.preferredDumpSpeedCD; + break; + } + + // Choose the lower of the two speeds between the allowed speeds and the user-defined one + // TODO: Inform more users about setting preferences in the settings so this comparison doesn't need to happen + int chosenSpeed = Math.Min( + values.Where(s => s <= values[values.Count / 2]).Last(), + preferred + ); + + // Set the selected speed + ViewModels.LoggerViewModel.VerboseLogLn("Setting drive speed to: {0}", chosenSpeed); + DriveSpeedComboBox.SelectedIndex = values.ToList().IndexOf(chosenSpeed); + } + + /// + /// Cache the current disc type to internal variable + /// + private void CacheCurrentDiscType() + { + // Get the drive letter from the selected item + Drive drive = DriveLetterComboBox.SelectedItem as Drive; + if (drive == null || drive.IsFloppy) + return; + + // Get the current optical disc type + if (!_options.SkipMediaTypeDetection) + { + ViewModels.LoggerViewModel.VerboseLog("Trying to detect media type for drive {0}.. ", drive.Letter); + _currentMediaType = Validators.GetDiscType(drive.Letter); + ViewModels.LoggerViewModel.VerboseLogLn(_currentMediaType != null ? "unable to detect." : ("detected " + _currentMediaType.Name() + ".")); + } + } + + /// + /// Set the current disc type in the combo box + /// + 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) + MediaTypeComboBox.SelectedIndex = index; + else + StatusLabel.Text = $"Disc of type '{Converters.MediaTypeToString(_currentMediaType)}' found, but the current system does not support it!"; + } + + /// + /// Process the current custom parameters back into UI values + /// + private void ProcessCustomParameters() + { + _env.DICParameters = new Parameters(ParametersTextBox.Text); + + int driveIndex = _drives.Select(d => d.Letter).ToList().IndexOf(_env.DICParameters.DriveLetter[0]); + if (driveIndex > -1) + DriveLetterComboBox.SelectedIndex = driveIndex; + + int driveSpeed = _env.DICParameters.DriveSpeed ?? -1; + if (driveSpeed > 0) + DriveSpeedComboBox.SelectedIndex = ((IReadOnlyList)(DriveSpeedComboBox.DataSource)).ToList().IndexOf(driveSpeed); + else + _env.DICParameters.DriveSpeed = (int?)DriveSpeedComboBox.SelectedValue; + + string trimmedPath = _env.DICParameters.Filename?.Trim('"') ?? string.Empty; + string outputDirectory = Path.GetDirectoryName(trimmedPath); + string outputFilename = Path.GetFileName(trimmedPath); + if (!String.IsNullOrWhiteSpace(outputDirectory)) + OutputDirectoryTextBox.Text = outputDirectory; + else + outputDirectory = OutputDirectoryTextBox.Text; + if (!String.IsNullOrWhiteSpace(outputFilename)) + OutputFilenameTextBox.Text = outputFilename; + else + outputFilename = OutputFilenameTextBox.Text; + + MediaType? mediaType = Converters.BaseCommmandToMediaType(_env.DICParameters.Command); + int mediaTypeIndex = _mediaTypes.IndexOf(mediaType); + if (mediaTypeIndex > -1) + MediaTypeComboBox.SelectedIndex = mediaTypeIndex; + } + + #endregion + + #region UI Helpers + + /// + /// Get pixel coordinates based on DPI scaling + /// + /// Rectangle representing the bounds to transform + /// Rectangle representing the scaled bounds + private Rectangle GetScaledCoordinates(Rectangle bounds) + { + using (Graphics g = Graphics.FromHwnd(IntPtr.Zero)) + { + return new Rectangle( + TransformCoordinate(bounds.Left, g.DpiX), + TransformCoordinate(bounds.Top, g.DpiY), + TransformCoordinate(bounds.Width, g.DpiX), + TransformCoordinate(bounds.Height, g.DpiY)); + } + } + + /// + /// Transform an individual coordinate using DPI scaling + /// + /// Current integer coordinate + /// DPI scaling factor + /// Scaled integer coordinate + private int TransformCoordinate(int coord, float dpi) + { + return (int)(coord / ((double)dpi / 96)); + } + + #endregion + } +} diff --git a/DICUI.Forms/Windows/MainWindow.resx b/DICUI.Forms/Windows/MainWindow.resx new file mode 100644 index 00000000..a9219137 --- /dev/null +++ b/DICUI.Forms/Windows/MainWindow.resx @@ -0,0 +1,1395 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + True + + + 84 + + + + + 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 + + + \ No newline at end of file diff --git a/DICUI.Forms/Windows/OptionsWindow.Designer.cs b/DICUI.Forms/Windows/OptionsWindow.Designer.cs new file mode 100644 index 00000000..8f5aeec4 --- /dev/null +++ b/DICUI.Forms/Windows/OptionsWindow.Designer.cs @@ -0,0 +1,565 @@ +namespace DICUI.Forms.Windows +{ + partial class OptionsWindow + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.pathsGroupBox = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.DefaultOutputPathButton = new System.Windows.Forms.Button(); + this.SubDumpPathButton = new System.Windows.Forms.Button(); + this.discImageCreatorPathLabel = new System.Windows.Forms.Label(); + this.subdumpPathLabel = new System.Windows.Forms.Label(); + this.defaultOutputPathLabel = new System.Windows.Forms.Label(); + this.DICPathTextBox = new System.Windows.Forms.TextBox(); + this.SubDumpPathTextBox = new System.Windows.Forms.TextBox(); + this.DefaultOutputPathTextBox = new System.Windows.Forms.TextBox(); + this.DICPathButton = new System.Windows.Forms.Button(); + this.preferredSpeedGroupBox = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.DumpSpeedCDLabel = new System.Windows.Forms.Label(); + this.DumpSpeedDVDLabel = new System.Windows.Forms.Label(); + this.DumpSpeedBDLabel = new System.Windows.Forms.Label(); + this.DumpSpeedCDSlider = new System.Windows.Forms.TrackBar(); + this.DumpSpeedDVDSlider = new System.Windows.Forms.TrackBar(); + this.DumpSpeedBDSlider = new System.Windows.Forms.TrackBar(); + this.DumpSpeedCDTextBox = new System.Windows.Forms.TextBox(); + this.DumpSpeedDVDTextBox = new System.Windows.Forms.TextBox(); + this.DumpSpeedBDTextBox = new System.Windows.Forms.TextBox(); + this.optionsGroupBox = new System.Windows.Forms.GroupBox(); + this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); + this.QuietModeCheckBox = new System.Windows.Forms.CheckBox(); + this.AutoScanCheckBox = new System.Windows.Forms.CheckBox(); + this.ParanoidModeCheckBox = new System.Windows.Forms.CheckBox(); + this.SkipDetectionCheckBox = new System.Windows.Forms.CheckBox(); + this.C2RereadTimesTextBox = new System.Windows.Forms.TextBox(); + this.C2RereadLabel = new System.Windows.Forms.Label(); + this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel(); + this.AcceptButton = new System.Windows.Forms.Button(); + this.CancelButton = new System.Windows.Forms.Button(); + this.tableLayoutPanel1.SuspendLayout(); + this.pathsGroupBox.SuspendLayout(); + this.tableLayoutPanel2.SuspendLayout(); + this.preferredSpeedGroupBox.SuspendLayout(); + this.tableLayoutPanel3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.DumpSpeedCDSlider)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.DumpSpeedDVDSlider)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.DumpSpeedBDSlider)).BeginInit(); + this.optionsGroupBox.SuspendLayout(); + this.tableLayoutPanel4.SuspendLayout(); + this.tableLayoutPanel5.SuspendLayout(); + this.SuspendLayout(); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 1; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Controls.Add(this.pathsGroupBox, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.preferredSpeedGroupBox, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.optionsGroupBox, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.tableLayoutPanel5, 0, 3); + this.tableLayoutPanel1.Location = new System.Drawing.Point(12, 12); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 4; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 150F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 100F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(475, 417); + this.tableLayoutPanel1.TabIndex = 0; + this.tableLayoutPanel1.UseWaitCursor = true; + // + // pathsGroupBox + // + this.pathsGroupBox.Controls.Add(this.tableLayoutPanel2); + this.pathsGroupBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.pathsGroupBox.Location = new System.Drawing.Point(3, 3); + this.pathsGroupBox.Name = "pathsGroupBox"; + this.pathsGroupBox.Size = new System.Drawing.Size(469, 121); + this.pathsGroupBox.TabIndex = 0; + this.pathsGroupBox.TabStop = false; + this.pathsGroupBox.Text = "Paths"; + this.pathsGroupBox.UseWaitCursor = true; + // + // tableLayoutPanel2 + // + this.tableLayoutPanel2.ColumnCount = 3; + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 29.41176F)); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 58.82353F)); + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 11.76471F)); + this.tableLayoutPanel2.Controls.Add(this.DefaultOutputPathButton, 2, 2); + this.tableLayoutPanel2.Controls.Add(this.SubDumpPathButton, 2, 1); + this.tableLayoutPanel2.Controls.Add(this.discImageCreatorPathLabel, 0, 0); + this.tableLayoutPanel2.Controls.Add(this.subdumpPathLabel, 0, 1); + this.tableLayoutPanel2.Controls.Add(this.defaultOutputPathLabel, 0, 2); + this.tableLayoutPanel2.Controls.Add(this.DICPathTextBox, 1, 0); + this.tableLayoutPanel2.Controls.Add(this.SubDumpPathTextBox, 1, 1); + this.tableLayoutPanel2.Controls.Add(this.DefaultOutputPathTextBox, 1, 2); + this.tableLayoutPanel2.Controls.Add(this.DICPathButton, 2, 0); + this.tableLayoutPanel2.Location = new System.Drawing.Point(6, 15); + this.tableLayoutPanel2.Name = "tableLayoutPanel2"; + this.tableLayoutPanel2.RowCount = 3; + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(457, 100); + this.tableLayoutPanel2.TabIndex = 0; + this.tableLayoutPanel2.UseWaitCursor = true; + // + // DefaultOutputPathButton + // + this.DefaultOutputPathButton.Location = new System.Drawing.Point(405, 69); + this.DefaultOutputPathButton.Name = "DefaultOutputPathButton"; + this.DefaultOutputPathButton.Size = new System.Drawing.Size(49, 23); + this.DefaultOutputPathButton.TabIndex = 8; + this.DefaultOutputPathButton.Text = "..."; + this.DefaultOutputPathButton.UseVisualStyleBackColor = true; + this.DefaultOutputPathButton.UseWaitCursor = true; + this.DefaultOutputPathButton.Click += new System.EventHandler(this.BrowseForPathClick); + // + // SubDumpPathButton + // + this.SubDumpPathButton.Location = new System.Drawing.Point(405, 36); + this.SubDumpPathButton.Name = "SubDumpPathButton"; + this.SubDumpPathButton.Size = new System.Drawing.Size(49, 23); + this.SubDumpPathButton.TabIndex = 7; + this.SubDumpPathButton.Text = "..."; + this.SubDumpPathButton.UseVisualStyleBackColor = true; + this.SubDumpPathButton.UseWaitCursor = true; + this.SubDumpPathButton.Click += new System.EventHandler(this.BrowseForPathClick); + // + // discImageCreatorPathLabel + // + this.discImageCreatorPathLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.discImageCreatorPathLabel.AutoSize = true; + this.discImageCreatorPathLabel.Cursor = System.Windows.Forms.Cursors.WaitCursor; + this.discImageCreatorPathLabel.Location = new System.Drawing.Point(15, 10); + this.discImageCreatorPathLabel.Name = "discImageCreatorPathLabel"; + this.discImageCreatorPathLabel.Size = new System.Drawing.Size(116, 13); + this.discImageCreatorPathLabel.TabIndex = 0; + this.discImageCreatorPathLabel.Text = "DiscImageCreator Path"; + // + // subdumpPathLabel + // + this.subdumpPathLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.subdumpPathLabel.AutoSize = true; + this.subdumpPathLabel.Location = new System.Drawing.Point(56, 43); + this.subdumpPathLabel.Name = "subdumpPathLabel"; + this.subdumpPathLabel.Size = new System.Drawing.Size(75, 13); + this.subdumpPathLabel.TabIndex = 1; + this.subdumpPathLabel.Text = "subdump Path"; + this.subdumpPathLabel.UseWaitCursor = true; + // + // defaultOutputPathLabel + // + this.defaultOutputPathLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.defaultOutputPathLabel.AutoSize = true; + this.defaultOutputPathLabel.Location = new System.Drawing.Point(30, 76); + this.defaultOutputPathLabel.Name = "defaultOutputPathLabel"; + this.defaultOutputPathLabel.Size = new System.Drawing.Size(101, 13); + this.defaultOutputPathLabel.TabIndex = 2; + this.defaultOutputPathLabel.Text = "Default Output Path"; + this.defaultOutputPathLabel.UseWaitCursor = true; + // + // DICPathTextBox + // + this.DICPathTextBox.Anchor = System.Windows.Forms.AnchorStyles.None; + this.DICPathTextBox.Location = new System.Drawing.Point(138, 6); + this.DICPathTextBox.Name = "DICPathTextBox"; + this.DICPathTextBox.Size = new System.Drawing.Size(259, 20); + this.DICPathTextBox.TabIndex = 3; + this.DICPathTextBox.UseWaitCursor = true; + // + // SubDumpPathTextBox + // + this.SubDumpPathTextBox.Anchor = System.Windows.Forms.AnchorStyles.None; + this.SubDumpPathTextBox.Location = new System.Drawing.Point(138, 39); + this.SubDumpPathTextBox.Name = "SubDumpPathTextBox"; + this.SubDumpPathTextBox.Size = new System.Drawing.Size(259, 20); + this.SubDumpPathTextBox.TabIndex = 4; + this.SubDumpPathTextBox.UseWaitCursor = true; + // + // DefaultOutputPathTextBox + // + this.DefaultOutputPathTextBox.Anchor = System.Windows.Forms.AnchorStyles.None; + this.DefaultOutputPathTextBox.Location = new System.Drawing.Point(138, 73); + this.DefaultOutputPathTextBox.Name = "DefaultOutputPathTextBox"; + this.DefaultOutputPathTextBox.Size = new System.Drawing.Size(259, 20); + this.DefaultOutputPathTextBox.TabIndex = 5; + this.DefaultOutputPathTextBox.UseWaitCursor = true; + // + // DICPathButton + // + this.DICPathButton.Location = new System.Drawing.Point(405, 3); + this.DICPathButton.Name = "DICPathButton"; + this.DICPathButton.Size = new System.Drawing.Size(49, 23); + this.DICPathButton.TabIndex = 6; + this.DICPathButton.Text = "..."; + this.DICPathButton.UseVisualStyleBackColor = true; + this.DICPathButton.UseWaitCursor = true; + this.DICPathButton.Click += new System.EventHandler(this.BrowseForPathClick); + // + // preferredSpeedGroupBox + // + this.preferredSpeedGroupBox.Controls.Add(this.tableLayoutPanel3); + this.preferredSpeedGroupBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.preferredSpeedGroupBox.Location = new System.Drawing.Point(3, 130); + this.preferredSpeedGroupBox.Name = "preferredSpeedGroupBox"; + this.preferredSpeedGroupBox.Size = new System.Drawing.Size(469, 144); + this.preferredSpeedGroupBox.TabIndex = 1; + this.preferredSpeedGroupBox.TabStop = false; + this.preferredSpeedGroupBox.Text = "Preferred Dump Speed"; + this.preferredSpeedGroupBox.UseWaitCursor = true; + // + // tableLayoutPanel3 + // + this.tableLayoutPanel3.ColumnCount = 3; + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 80F)); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 40F)); + this.tableLayoutPanel3.Controls.Add(this.DumpSpeedCDLabel, 0, 0); + this.tableLayoutPanel3.Controls.Add(this.DumpSpeedDVDLabel, 0, 1); + this.tableLayoutPanel3.Controls.Add(this.DumpSpeedBDLabel, 0, 2); + this.tableLayoutPanel3.Controls.Add(this.DumpSpeedCDSlider, 1, 0); + this.tableLayoutPanel3.Controls.Add(this.DumpSpeedDVDSlider, 1, 1); + this.tableLayoutPanel3.Controls.Add(this.DumpSpeedBDSlider, 1, 2); + this.tableLayoutPanel3.Controls.Add(this.DumpSpeedCDTextBox, 2, 0); + this.tableLayoutPanel3.Controls.Add(this.DumpSpeedDVDTextBox, 2, 1); + this.tableLayoutPanel3.Controls.Add(this.DumpSpeedBDTextBox, 2, 2); + this.tableLayoutPanel3.Location = new System.Drawing.Point(6, 19); + this.tableLayoutPanel3.Name = "tableLayoutPanel3"; + this.tableLayoutPanel3.RowCount = 3; + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F)); + this.tableLayoutPanel3.Size = new System.Drawing.Size(457, 119); + this.tableLayoutPanel3.TabIndex = 0; + this.tableLayoutPanel3.UseWaitCursor = true; + // + // DumpSpeedCDLabel + // + this.DumpSpeedCDLabel.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.DumpSpeedCDLabel.AutoSize = true; + this.DumpSpeedCDLabel.Location = new System.Drawing.Point(3, 13); + this.DumpSpeedCDLabel.Name = "DumpSpeedCDLabel"; + this.DumpSpeedCDLabel.Size = new System.Drawing.Size(50, 13); + this.DumpSpeedCDLabel.TabIndex = 0; + this.DumpSpeedCDLabel.Text = "CD-ROM"; + this.DumpSpeedCDLabel.UseWaitCursor = true; + // + // DumpSpeedDVDLabel + // + this.DumpSpeedDVDLabel.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.DumpSpeedDVDLabel.AutoSize = true; + this.DumpSpeedDVDLabel.Location = new System.Drawing.Point(3, 52); + this.DumpSpeedDVDLabel.Name = "DumpSpeedDVDLabel"; + this.DumpSpeedDVDLabel.Size = new System.Drawing.Size(58, 13); + this.DumpSpeedDVDLabel.TabIndex = 1; + this.DumpSpeedDVDLabel.Text = "DVD-ROM"; + this.DumpSpeedDVDLabel.UseWaitCursor = true; + // + // DumpSpeedBDLabel + // + this.DumpSpeedBDLabel.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.DumpSpeedBDLabel.AutoSize = true; + this.DumpSpeedBDLabel.Location = new System.Drawing.Point(3, 92); + this.DumpSpeedBDLabel.Name = "DumpSpeedBDLabel"; + this.DumpSpeedBDLabel.Size = new System.Drawing.Size(50, 13); + this.DumpSpeedBDLabel.TabIndex = 2; + this.DumpSpeedBDLabel.Text = "BD-ROM"; + this.DumpSpeedBDLabel.UseWaitCursor = true; + // + // DumpSpeedCDSlider + // + this.DumpSpeedCDSlider.Dock = System.Windows.Forms.DockStyle.Fill; + this.DumpSpeedCDSlider.Location = new System.Drawing.Point(83, 3); + this.DumpSpeedCDSlider.Name = "DumpSpeedCDSlider"; + this.DumpSpeedCDSlider.Size = new System.Drawing.Size(331, 33); + this.DumpSpeedCDSlider.TabIndex = 3; + this.DumpSpeedCDSlider.UseWaitCursor = true; + this.DumpSpeedCDSlider.Value = 1; + this.DumpSpeedCDSlider.Scroll += new System.EventHandler(this.SliderChanged); + // + // DumpSpeedDVDSlider + // + this.DumpSpeedDVDSlider.Dock = System.Windows.Forms.DockStyle.Fill; + this.DumpSpeedDVDSlider.Location = new System.Drawing.Point(83, 42); + this.DumpSpeedDVDSlider.Name = "DumpSpeedDVDSlider"; + this.DumpSpeedDVDSlider.Size = new System.Drawing.Size(331, 33); + this.DumpSpeedDVDSlider.TabIndex = 4; + this.DumpSpeedDVDSlider.UseWaitCursor = true; + this.DumpSpeedDVDSlider.Value = 1; + this.DumpSpeedDVDSlider.Scroll += new System.EventHandler(this.SliderChanged); + // + // DumpSpeedBDSlider + // + this.DumpSpeedBDSlider.Dock = System.Windows.Forms.DockStyle.Fill; + this.DumpSpeedBDSlider.Location = new System.Drawing.Point(83, 81); + this.DumpSpeedBDSlider.Name = "DumpSpeedBDSlider"; + this.DumpSpeedBDSlider.Size = new System.Drawing.Size(331, 35); + this.DumpSpeedBDSlider.TabIndex = 5; + this.DumpSpeedBDSlider.UseWaitCursor = true; + this.DumpSpeedBDSlider.Value = 1; + this.DumpSpeedBDSlider.Scroll += new System.EventHandler(this.SliderChanged); + // + // DumpSpeedCDTextBox + // + this.DumpSpeedCDTextBox.Anchor = System.Windows.Forms.AnchorStyles.None; + this.DumpSpeedCDTextBox.Enabled = false; + this.DumpSpeedCDTextBox.Location = new System.Drawing.Point(420, 9); + this.DumpSpeedCDTextBox.Name = "DumpSpeedCDTextBox"; + this.DumpSpeedCDTextBox.ReadOnly = true; + this.DumpSpeedCDTextBox.Size = new System.Drawing.Size(34, 20); + this.DumpSpeedCDTextBox.TabIndex = 6; + this.DumpSpeedCDTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.DumpSpeedCDTextBox.UseWaitCursor = true; + // + // DumpSpeedDVDTextBox + // + this.DumpSpeedDVDTextBox.Anchor = System.Windows.Forms.AnchorStyles.None; + this.DumpSpeedDVDTextBox.Enabled = false; + this.DumpSpeedDVDTextBox.Location = new System.Drawing.Point(420, 48); + this.DumpSpeedDVDTextBox.Name = "DumpSpeedDVDTextBox"; + this.DumpSpeedDVDTextBox.ReadOnly = true; + this.DumpSpeedDVDTextBox.Size = new System.Drawing.Size(34, 20); + this.DumpSpeedDVDTextBox.TabIndex = 7; + this.DumpSpeedDVDTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.DumpSpeedDVDTextBox.UseWaitCursor = true; + // + // DumpSpeedBDTextBox + // + this.DumpSpeedBDTextBox.Anchor = System.Windows.Forms.AnchorStyles.None; + this.DumpSpeedBDTextBox.Enabled = false; + this.DumpSpeedBDTextBox.Location = new System.Drawing.Point(420, 88); + this.DumpSpeedBDTextBox.Name = "DumpSpeedBDTextBox"; + this.DumpSpeedBDTextBox.ReadOnly = true; + this.DumpSpeedBDTextBox.Size = new System.Drawing.Size(34, 20); + this.DumpSpeedBDTextBox.TabIndex = 8; + this.DumpSpeedBDTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.DumpSpeedBDTextBox.UseWaitCursor = true; + // + // optionsGroupBox + // + this.optionsGroupBox.Controls.Add(this.tableLayoutPanel4); + this.optionsGroupBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.optionsGroupBox.Location = new System.Drawing.Point(3, 280); + this.optionsGroupBox.Name = "optionsGroupBox"; + this.optionsGroupBox.Size = new System.Drawing.Size(469, 94); + this.optionsGroupBox.TabIndex = 2; + this.optionsGroupBox.TabStop = false; + this.optionsGroupBox.Text = "Options"; + // + // tableLayoutPanel4 + // + this.tableLayoutPanel4.ColumnCount = 4; + this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tableLayoutPanel4.Controls.Add(this.QuietModeCheckBox, 0, 0); + this.tableLayoutPanel4.Controls.Add(this.AutoScanCheckBox, 0, 1); + this.tableLayoutPanel4.Controls.Add(this.ParanoidModeCheckBox, 1, 0); + this.tableLayoutPanel4.Controls.Add(this.SkipDetectionCheckBox, 2, 1); + this.tableLayoutPanel4.Controls.Add(this.C2RereadTimesTextBox, 3, 0); + this.tableLayoutPanel4.Controls.Add(this.C2RereadLabel, 2, 0); + this.tableLayoutPanel4.Location = new System.Drawing.Point(6, 19); + this.tableLayoutPanel4.Name = "tableLayoutPanel4"; + this.tableLayoutPanel4.RowCount = 2; + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel4.Size = new System.Drawing.Size(457, 69); + this.tableLayoutPanel4.TabIndex = 0; + // + // QuietModeCheckBox + // + this.QuietModeCheckBox.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.QuietModeCheckBox.AutoSize = true; + this.QuietModeCheckBox.Location = new System.Drawing.Point(3, 8); + this.QuietModeCheckBox.Name = "QuietModeCheckBox"; + this.QuietModeCheckBox.Size = new System.Drawing.Size(81, 17); + this.QuietModeCheckBox.TabIndex = 0; + this.QuietModeCheckBox.Text = "Quiet Mode"; + this.QuietModeCheckBox.UseVisualStyleBackColor = true; + // + // AutoScanCheckBox + // + this.AutoScanCheckBox.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.AutoScanCheckBox.AutoSize = true; + this.tableLayoutPanel4.SetColumnSpan(this.AutoScanCheckBox, 2); + this.AutoScanCheckBox.Location = new System.Drawing.Point(3, 43); + this.AutoScanCheckBox.Name = "AutoScanCheckBox"; + this.AutoScanCheckBox.Size = new System.Drawing.Size(182, 17); + this.AutoScanCheckBox.TabIndex = 1; + this.AutoScanCheckBox.Text = "Automatically Scan for Protection"; + this.AutoScanCheckBox.UseVisualStyleBackColor = true; + // + // ParanoidModeCheckBox + // + this.ParanoidModeCheckBox.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.ParanoidModeCheckBox.AutoSize = true; + this.ParanoidModeCheckBox.Location = new System.Drawing.Point(117, 8); + this.ParanoidModeCheckBox.Name = "ParanoidModeCheckBox"; + this.ParanoidModeCheckBox.Size = new System.Drawing.Size(98, 17); + this.ParanoidModeCheckBox.TabIndex = 2; + this.ParanoidModeCheckBox.Text = "Paranoid Mode"; + this.ParanoidModeCheckBox.UseVisualStyleBackColor = true; + // + // SkipDetectionCheckBox + // + this.SkipDetectionCheckBox.Anchor = System.Windows.Forms.AnchorStyles.Left; + this.SkipDetectionCheckBox.AutoSize = true; + this.tableLayoutPanel4.SetColumnSpan(this.SkipDetectionCheckBox, 2); + this.SkipDetectionCheckBox.Location = new System.Drawing.Point(231, 43); + this.SkipDetectionCheckBox.Name = "SkipDetectionCheckBox"; + this.SkipDetectionCheckBox.Size = new System.Drawing.Size(155, 17); + this.SkipDetectionCheckBox.TabIndex = 3; + this.SkipDetectionCheckBox.Text = "Skip Media Type Detection"; + this.SkipDetectionCheckBox.UseVisualStyleBackColor = true; + // + // C2RereadTimesTextBox + // + this.C2RereadTimesTextBox.Anchor = System.Windows.Forms.AnchorStyles.None; + this.C2RereadTimesTextBox.Location = new System.Drawing.Point(349, 7); + this.C2RereadTimesTextBox.Name = "C2RereadTimesTextBox"; + this.C2RereadTimesTextBox.Size = new System.Drawing.Size(100, 20); + this.C2RereadTimesTextBox.TabIndex = 4; + // + // C2RereadLabel + // + this.C2RereadLabel.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.C2RereadLabel.AutoSize = true; + this.C2RereadLabel.Location = new System.Drawing.Point(250, 10); + this.C2RereadLabel.Name = "C2RereadLabel"; + this.C2RereadLabel.Size = new System.Drawing.Size(89, 13); + this.C2RereadLabel.TabIndex = 5; + this.C2RereadLabel.Text = "C2 Reread Times"; + // + // tableLayoutPanel5 + // + this.tableLayoutPanel5.ColumnCount = 2; + this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel5.Controls.Add(this.AcceptButton, 0, 0); + this.tableLayoutPanel5.Controls.Add(this.CancelButton, 1, 0); + this.tableLayoutPanel5.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel5.Location = new System.Drawing.Point(3, 380); + this.tableLayoutPanel5.Name = "tableLayoutPanel5"; + this.tableLayoutPanel5.RowCount = 1; + this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel5.Size = new System.Drawing.Size(469, 34); + this.tableLayoutPanel5.TabIndex = 3; + // + // AcceptButton + // + this.AcceptButton.Anchor = System.Windows.Forms.AnchorStyles.None; + this.AcceptButton.Location = new System.Drawing.Point(79, 5); + this.AcceptButton.Name = "AcceptButton"; + this.AcceptButton.Size = new System.Drawing.Size(75, 23); + this.AcceptButton.TabIndex = 0; + this.AcceptButton.Text = "Accept"; + this.AcceptButton.UseVisualStyleBackColor = true; + this.AcceptButton.Click += new System.EventHandler(this.OnAcceptClick); + // + // CancelButton + // + this.CancelButton.Anchor = System.Windows.Forms.AnchorStyles.None; + this.CancelButton.Location = new System.Drawing.Point(314, 5); + this.CancelButton.Name = "CancelButton"; + this.CancelButton.Size = new System.Drawing.Size(75, 23); + this.CancelButton.TabIndex = 1; + this.CancelButton.Text = "Cancel"; + this.CancelButton.UseVisualStyleBackColor = true; + this.CancelButton.Click += new System.EventHandler(this.OnCancelClick); + // + // OptionsWindow + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(499, 441); + this.Controls.Add(this.tableLayoutPanel1); + this.Name = "OptionsWindow"; + this.ShowIcon = false; + this.Text = "Options"; + this.UseWaitCursor = true; + this.tableLayoutPanel1.ResumeLayout(false); + this.pathsGroupBox.ResumeLayout(false); + this.tableLayoutPanel2.ResumeLayout(false); + this.tableLayoutPanel2.PerformLayout(); + this.preferredSpeedGroupBox.ResumeLayout(false); + this.tableLayoutPanel3.ResumeLayout(false); + this.tableLayoutPanel3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.DumpSpeedCDSlider)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.DumpSpeedDVDSlider)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.DumpSpeedBDSlider)).EndInit(); + this.optionsGroupBox.ResumeLayout(false); + this.tableLayoutPanel4.ResumeLayout(false); + this.tableLayoutPanel4.PerformLayout(); + this.tableLayoutPanel5.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.GroupBox pathsGroupBox; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; + private System.Windows.Forms.Label discImageCreatorPathLabel; + private System.Windows.Forms.Label subdumpPathLabel; + private System.Windows.Forms.Label defaultOutputPathLabel; + private System.Windows.Forms.TextBox DICPathTextBox; + private System.Windows.Forms.TextBox SubDumpPathTextBox; + private System.Windows.Forms.TextBox DefaultOutputPathTextBox; + private System.Windows.Forms.Button DICPathButton; + private System.Windows.Forms.Button DefaultOutputPathButton; + private System.Windows.Forms.Button SubDumpPathButton; + private System.Windows.Forms.GroupBox preferredSpeedGroupBox; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; + private System.Windows.Forms.Label DumpSpeedCDLabel; + private System.Windows.Forms.Label DumpSpeedDVDLabel; + private System.Windows.Forms.Label DumpSpeedBDLabel; + private System.Windows.Forms.TrackBar DumpSpeedCDSlider; + private System.Windows.Forms.TrackBar DumpSpeedDVDSlider; + private System.Windows.Forms.TrackBar DumpSpeedBDSlider; + private System.Windows.Forms.TextBox DumpSpeedCDTextBox; + private System.Windows.Forms.TextBox DumpSpeedDVDTextBox; + private System.Windows.Forms.TextBox DumpSpeedBDTextBox; + private System.Windows.Forms.GroupBox optionsGroupBox; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; + private System.Windows.Forms.CheckBox QuietModeCheckBox; + private System.Windows.Forms.CheckBox AutoScanCheckBox; + private System.Windows.Forms.CheckBox ParanoidModeCheckBox; + private System.Windows.Forms.CheckBox SkipDetectionCheckBox; + private System.Windows.Forms.TextBox C2RereadTimesTextBox; + private System.Windows.Forms.Label C2RereadLabel; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5; + private System.Windows.Forms.Button AcceptButton; + private System.Windows.Forms.Button CancelButton; + } +} \ No newline at end of file diff --git a/DICUI.Forms/Windows/OptionsWindow.cs b/DICUI.Forms/Windows/OptionsWindow.cs new file mode 100644 index 00000000..5043d417 --- /dev/null +++ b/DICUI.Forms/Windows/OptionsWindow.cs @@ -0,0 +1,179 @@ +using System; +using System.IO; +using System.Linq; +using System.Windows; +using System.Windows.Forms; + +namespace DICUI.Forms.Windows +{ + /// + /// Interaction logic for OptionsWindow + /// + public partial class OptionsWindow : Form + { + private readonly MainWindow _mainWindow; + private readonly Options _options; + + public OptionsWindow(MainWindow mainWindow, Options options) + { + InitializeComponent(); + _mainWindow = mainWindow; + _options = options; + + // Create data sets + DumpSpeedCDSlider.Minimum = (int)Constants.SpeedsForCDAsCollection.First(); + DumpSpeedCDSlider.Maximum = (int)Constants.SpeedsForCDAsCollection.Last(); + DumpSpeedDVDSlider.Minimum = (int)Constants.SpeedsForDVDAsCollection.First(); + DumpSpeedDVDSlider.Maximum = (int)Constants.SpeedsForDVDAsCollection.Last(); + DumpSpeedBDSlider.Minimum = (int)Constants.SpeedsForBDAsCollection.First(); + DumpSpeedBDSlider.Maximum = (int)Constants.SpeedsForBDAsCollection.Last(); + + // Select the current values + DumpSpeedCDSlider.Value = _options.preferredDumpSpeedCD; + DumpSpeedDVDSlider.Value = _options.preferredDumpSpeedDVD; + DumpSpeedBDSlider.Value = _options.preferredDumpSpeedBD; + + // Create textbox outputs + DumpSpeedCDTextBox.Text = DumpSpeedCDSlider.Value.ToString(); + DumpSpeedDVDTextBox.Text = DumpSpeedDVDSlider.Value.ToString(); + DumpSpeedBDTextBox.Text = DumpSpeedBDSlider.Value.ToString(); + + // Set options + QuietModeCheckBox.Checked = _options.QuietMode; + ParanoidModeCheckBox.Checked = _options.ParanoidMode; + C2RereadTimesTextBox.Text = _options.RereadAmountForC2.ToString(); + AutoScanCheckBox.Checked = _options.ScanForProtection; + SkipDetectionCheckBox.Checked = _options.SkipMediaTypeDetection; + } + + private OpenFileDialog CreateOpenFileDialog() + { + OpenFileDialog dialog = new OpenFileDialog(); + + dialog.InitialDirectory = AppDomain.CurrentDomain.BaseDirectory; + dialog.Filter = "Executables (*.exe)|*.exe"; + dialog.FilterIndex = 0; + dialog.RestoreDirectory = true; + + return dialog; + } + + private FolderBrowserDialog CreateFolderBrowserDialog() + { + FolderBrowserDialog dialog = new FolderBrowserDialog(); + return dialog; + } + + private string[] PathSettings() + { + string[] pathSettings = { "DefaultOutputPath", "DICPath", "SubDumpPath" }; + return pathSettings; + } + + private TextBox TextBoxForPathSetting(string name) + { + switch (name) + { + case "DICPath": + return DICPathTextBox; + case "SubDumpPath": + return SubDumpPathTextBox; + case "DefaultOutputPath": + return DefaultOutputPathTextBox; + default: + return null; + } + } + + private void BrowseForPathClick(object sender, EventArgs e) + { + Button button = sender as Button; + // strips button prefix to obtain the setting name + string pathSettingName = button.Name.Substring(0, button.Name.IndexOf("Button")); + + // TODO: hack for now, then we'll see + bool shouldBrowseForPath = pathSettingName == "DefaultOutputPath"; + + CommonDialog dialog = shouldBrowseForPath ? (CommonDialog)CreateFolderBrowserDialog() : CreateOpenFileDialog(); + using (dialog) + { + DialogResult result = dialog.ShowDialog(); + + if (result == System.Windows.Forms.DialogResult.OK) + { + string path; + bool exists; + + if (shouldBrowseForPath) + { + path = (dialog as FolderBrowserDialog).SelectedPath; + exists = Directory.Exists(path); + } + else + { + path = (dialog as OpenFileDialog).FileName; + exists = File.Exists(path); + } + + if (exists) + TextBoxForPathSetting(pathSettingName).Text = path; + else + { + System.Windows.MessageBox.Show( + "Specified path doesn't exists!", + "Error", + MessageBoxButton.OK, + MessageBoxImage.Error + ); + } + } + } + } + + public void RefreshSettings() + { + Array.ForEach(PathSettings(), setting => TextBoxForPathSetting(setting).Text = _options.Get(setting)); + + DumpSpeedCDSlider.Value = _options.preferredDumpSpeedCD; + DumpSpeedDVDSlider.Value = _options.preferredDumpSpeedDVD; + DumpSpeedBDSlider.Value = _options.preferredDumpSpeedBD; + } + + #region Event Handlers + + private void SliderChanged(object sender, EventArgs e) + { + DumpSpeedCDTextBox.Text = DumpSpeedCDSlider.Value.ToString(); + DumpSpeedDVDTextBox.Text = DumpSpeedDVDSlider.Value.ToString(); + DumpSpeedBDTextBox.Text = DumpSpeedBDSlider.Value.ToString(); + } + + private void OnAcceptClick(object sender, EventArgs e) + { + Array.ForEach(PathSettings(), setting => _options.Set(setting, TextBoxForPathSetting(setting).Text)); + + _options.preferredDumpSpeedCD = Convert.ToInt32(DumpSpeedCDSlider.Value); + _options.preferredDumpSpeedDVD = Convert.ToInt32(DumpSpeedDVDSlider.Value); + _options.preferredDumpSpeedBD = Convert.ToInt32(DumpSpeedBDSlider.Value); + + _options.QuietMode = QuietModeCheckBox.Checked; + _options.ParanoidMode = ParanoidModeCheckBox.Checked; + _options.RereadAmountForC2 = Convert.ToInt32(C2RereadTimesTextBox.Text); + _options.ScanForProtection = AutoScanCheckBox.Checked; + _options.SkipMediaTypeDetection = SkipDetectionCheckBox.Checked; + + _options.Save(); + Hide(); + + _mainWindow.OnOptionsUpdated(); + } + + private void OnCancelClick(object sender, EventArgs e) + { + // just hide the window and don't care + Hide(); + } + + #endregion + } +} diff --git a/DICUI.Forms/Windows/OptionsWindow.resx b/DICUI.Forms/Windows/OptionsWindow.resx new file mode 100644 index 00000000..61bc649b --- /dev/null +++ b/DICUI.Forms/Windows/OptionsWindow.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + \ No newline at end of file diff --git a/DICUI.Library/DICUI.Library.csproj b/DICUI.Library/DICUI.Library.csproj new file mode 100644 index 00000000..148c0cd0 --- /dev/null +++ b/DICUI.Library/DICUI.Library.csproj @@ -0,0 +1,101 @@ + + + + + Debug + AnyCPU + {51AB0928-13F9-44BF-A407-B6957A43A056} + Library + Properties + DICUI.Library + DICUI.Library + v4.6.1 + 512 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\BurnOutSharp.1.3.7.1\lib\net461\BurnOutSharp.dll + + + ..\packages\LessIO.0.5.0\lib\net40\LessIO.dll + + + ..\packages\libmspack4n.0.8.0\lib\net40\libmspackn.dll + + + + + + + + + + + + + + ..\packages\UnshieldSharp.1.4.2.2\lib\net461\UnshieldSharp.dll + + + ..\packages\zlib.net.1.0.4.0\lib\zlib.net.dll + + + + + + + + + + + + + + + + Always + + + + + {2735412F-7F64-5B0F-8F00-5D77AFBE261E} + 1 + 0 + 0 + tlbimp + False + True + + + {2C941FD0-975B-59BE-A960-9A2A262853A5} + 1 + 0 + 0 + tlbimp + False + True + + + + + + + \ No newline at end of file diff --git a/DICUI/Data/Constants.cs b/DICUI.Library/Data/Constants.cs similarity index 94% rename from DICUI/Data/Constants.cs rename to DICUI.Library/Data/Constants.cs index ef0afbfb..f0b36f78 100644 --- a/DICUI/Data/Constants.cs +++ b/DICUI.Library/Data/Constants.cs @@ -1,17 +1,5 @@ namespace DICUI.Data { - /// - /// Variables for UI elements - /// - public static class UIElements - { - public const string DiscNotDetected = "Disc Not Detected"; - public const string StartDumping = "Start Dumping"; - public const string StopDumping = "Stop Dumping"; - - public const int LogWindowMarginFromMainWindow = 10; - } - /// /// Top-level commands for DiscImageCreator /// @@ -125,5 +113,6 @@ public const string RequiredIfExistsValue = "(REQUIRED, IF EXISTS)"; public const string OptionalValue = "(OPTIONAL)"; public const string YesNoValue = "Yes/No"; + public const string DiscNotDetected = "Disc Not Detected"; } } diff --git a/DICUI/Data/Enumerations.cs b/DICUI.Library/Data/Enumerations.cs similarity index 100% rename from DICUI/Data/Enumerations.cs rename to DICUI.Library/Data/Enumerations.cs diff --git a/DICUI.Library/Properties/AssemblyInfo.cs b/DICUI.Library/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..331f1859 --- /dev/null +++ b/DICUI.Library/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DICUI.Library")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DICUI.Library")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("51ab0928-13f9-44bf-a407-b6957a43a056")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/DICUI/Utilities/Converters.cs b/DICUI.Library/Utilities/Converters.cs similarity index 96% rename from DICUI/Utilities/Converters.cs rename to DICUI.Library/Utilities/Converters.cs index f404ca52..b7c63d95 100644 --- a/DICUI/Utilities/Converters.cs +++ b/DICUI.Library/Utilities/Converters.cs @@ -1,36 +1,8 @@ -using System; -using System.Globalization; -using System.Windows.Data; -using IMAPI2; +using IMAPI2; using DICUI.Data; namespace DICUI.Utilities { - /// - /// Used to provide a converter to XAML files to render comboboxes with enum values - /// - public class EnumDescriptionConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is DICCommand) - return ((DICCommand)value).Name(); - else if (value is DICFlag) - return ((DICFlag)value).Name(); - else if (value is MediaType?) - return ((MediaType?)value).Name(); - else if (value is KnownSystem?) - return ((KnownSystem?)value).Name(); - else - return ""; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - return string.Empty; - } - } - public static class Converters { /// diff --git a/DICUI/Utilities/DumpEnvironment.cs b/DICUI.Library/Utilities/DumpEnvironment.cs similarity index 97% rename from DICUI/Utilities/DumpEnvironment.cs rename to DICUI.Library/Utilities/DumpEnvironment.cs index 1f206017..3ef6906c 100644 --- a/DICUI/Utilities/DumpEnvironment.cs +++ b/DICUI.Library/Utilities/DumpEnvironment.cs @@ -6,9 +6,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; -using System.Windows; using DICUI.Data; -using DICUI.UI; namespace DICUI.Utilities { @@ -70,8 +68,6 @@ namespace DICUI.Utilities /// public void CancelDumping() { - ViewModels.LoggerViewModel.VerboseLogLn("Canceling dumping process..."); - try { if (dicProcess != null && !dicProcess.HasExited) @@ -86,8 +82,6 @@ namespace DICUI.Utilities /// public async void EjectDisc() { - ViewModels.LoggerViewModel.VerboseLogLn($"Ejecting disc in drive {Drive.Letter}"); - // Validate that the required program exists if (!File.Exists(DICPath)) return; @@ -164,10 +158,7 @@ namespace DICUI.Utilities // If we get the firmware message if (output.Contains("[ERROR] This drive isn't latest firmware. Please update.")) - { - MessageBox.Show($"DiscImageCreator has reported that drive {Drive.Letter} is not updated to the most recent firmware. Please update the firmware for your drive and try again.", "Outdated Firmware", MessageBoxButton.OK, MessageBoxImage.Error); return false; - } // Otherwise, we know the firmware's good return true; @@ -237,12 +228,12 @@ namespace DICUI.Utilities #endregion - #region Internal for Testing Purposes + #region Public for Testing Purposes /// /// Fix output paths to strip out any invalid characters /// - internal void FixOutputPaths() + public void FixOutputPaths() { try { @@ -285,11 +276,73 @@ namespace DICUI.Utilities /// Checks if the parameters are valid /// /// True if the configuration is valid, false otherwise - internal bool ParametersValid() + public bool ParametersValid() { return DICParameters.IsValid() && !(IsFloppy ^ Type == MediaType.FloppyDisk); } + /// + /// Ensures that all required output files have been created + /// + /// + public bool FoundAllFiles() + { + // First, sanitized the output filename to strip off any potential extension + string outputFilename = Path.GetFileNameWithoutExtension(OutputFilename); + + // Now ensure that all required files exist + string combinedBase = Path.Combine(OutputDirectory, outputFilename); + switch (Type) + { + case MediaType.CDROM: + case MediaType.GDROM: // TODO: Verify GD-ROM outputs this + return File.Exists(combinedBase + ".c2") + && File.Exists(combinedBase + ".ccd") + && File.Exists(combinedBase + ".cue") + && File.Exists(combinedBase + ".dat") + && File.Exists(combinedBase + ".img") + && File.Exists(combinedBase + ".img_EdcEcc.txt") + && File.Exists(combinedBase + ".scm") + && File.Exists(combinedBase + ".sub") + && File.Exists(combinedBase + "_c2Error.txt") + && File.Exists(combinedBase + "_cmd.txt") + && File.Exists(combinedBase + "_disc.txt") + && File.Exists(combinedBase + "_drive.txt") + && File.Exists(combinedBase + "_img.cue") + && File.Exists(combinedBase + "_mainError.txt") + && File.Exists(combinedBase + "_mainInfo.txt") + && File.Exists(combinedBase + "_subError.txt") + && File.Exists(combinedBase + "_subInfo.txt") + // && File.Exists(combinedBase + "_subIntention.txt") + && (File.Exists(combinedBase + "_subReadable.txt") || File.Exists(combinedBase + "_sub.txt")) + && File.Exists(combinedBase + "_volDesc.txt"); + case MediaType.DVD: + case MediaType.HDDVD: + case MediaType.BluRay: + case MediaType.NintendoGameCube: + case MediaType.NintendoWiiOpticalDisc: + return File.Exists(combinedBase + ".dat") + && File.Exists(combinedBase + "_cmd.txt") + && File.Exists(combinedBase + "_disc.txt") + && File.Exists(combinedBase + "_drive.txt") + && File.Exists(combinedBase + "_mainError.txt") + && File.Exists(combinedBase + "_mainInfo.txt") + && File.Exists(combinedBase + "_volDesc.txt"); + case MediaType.FloppyDisk: + return File.Exists(combinedBase + ".dat") + && File.Exists(combinedBase + "_cmd.txt") + && File.Exists(combinedBase + "_disc.txt"); + case MediaType.UMD: + return File.Exists(combinedBase + "_disc.txt") + || File.Exists(combinedBase + "_mainError.txt") + || File.Exists(combinedBase + "_mainInfo.txt") + || File.Exists(combinedBase + "_volDesc.txt"); + default: + // Non-dumping commands will usually produce no output, so this is irrelevant + return true; + } + } + #endregion #region Private Helpers @@ -319,8 +372,6 @@ namespace DICUI.Utilities /// private void ExecuteDiskImageCreator() { - ViewModels.LoggerViewModel.VerboseLogLn("Launching DiscImageCreator process."); - dicProcess = new Process() { StartInfo = new ProcessStartInfo() @@ -764,68 +815,6 @@ namespace DICUI.Utilities } } - /// - /// Ensures that all required output files have been created - /// - /// - private bool FoundAllFiles() - { - // First, sanitized the output filename to strip off any potential extension - string outputFilename = Path.GetFileNameWithoutExtension(OutputFilename); - - // Now ensure that all required files exist - string combinedBase = Path.Combine(OutputDirectory, outputFilename); - switch (Type) - { - case MediaType.CDROM: - case MediaType.GDROM: // TODO: Verify GD-ROM outputs this - return File.Exists(combinedBase + ".c2") - && File.Exists(combinedBase + ".ccd") - && File.Exists(combinedBase + ".cue") - && File.Exists(combinedBase + ".dat") - && File.Exists(combinedBase + ".img") - && File.Exists(combinedBase + ".img_EdcEcc.txt") - && File.Exists(combinedBase + ".scm") - && File.Exists(combinedBase + ".sub") - && File.Exists(combinedBase + "_c2Error.txt") - && File.Exists(combinedBase + "_cmd.txt") - && File.Exists(combinedBase + "_disc.txt") - && File.Exists(combinedBase + "_drive.txt") - && File.Exists(combinedBase + "_img.cue") - && File.Exists(combinedBase + "_mainError.txt") - && File.Exists(combinedBase + "_mainInfo.txt") - && File.Exists(combinedBase + "_subError.txt") - && File.Exists(combinedBase + "_subInfo.txt") - // && File.Exists(combinedBase + "_subIntention.txt") - && (File.Exists(combinedBase + "_subReadable.txt") || File.Exists(combinedBase + "_sub.txt")) - && File.Exists(combinedBase + "_volDesc.txt"); - case MediaType.DVD: - case MediaType.HDDVD: - case MediaType.BluRay: - case MediaType.NintendoGameCube: - case MediaType.NintendoWiiOpticalDisc: - return File.Exists(combinedBase + ".dat") - && File.Exists(combinedBase + "_cmd.txt") - && File.Exists(combinedBase + "_disc.txt") - && File.Exists(combinedBase + "_drive.txt") - && File.Exists(combinedBase + "_mainError.txt") - && File.Exists(combinedBase + "_mainInfo.txt") - && File.Exists(combinedBase + "_volDesc.txt"); - case MediaType.FloppyDisk: - return File.Exists(combinedBase + ".dat") - && File.Exists(combinedBase + "_cmd.txt") - && File.Exists(combinedBase + "_disc.txt"); - case MediaType.UMD: - return File.Exists(combinedBase + "_disc.txt") - || File.Exists(combinedBase + "_mainError.txt") - || File.Exists(combinedBase + "_mainInfo.txt") - || File.Exists(combinedBase + "_volDesc.txt"); - default: - // Non-dumping commands will usually produce no output, so this is irrelevant - return true; - } - } - /// /// Get the existance of an anti-modchip string from the input file, if possible /// @@ -1601,26 +1590,6 @@ namespace DICUI.Utilities if (!File.Exists(DICPath)) return Result.Failure("Error! Could not find DiscImageCreator!"); - // Validate that the user explicitly wants an inactive drive to be considered for dumping - if (!Drive.MarkedActive) - { - MessageBoxResult result = MessageBox.Show("The currently selected drive does not appear to contain a disc! Are you sure you want to continue?", "Missing Disc", MessageBoxButton.YesNo, MessageBoxImage.Exclamation); - if (result == MessageBoxResult.No || result == MessageBoxResult.Cancel || result == MessageBoxResult.None) - { - return Result.Failure("Dumping aborted!"); - } - } - - // If a complete dump already exists - if (FoundAllFiles()) - { - MessageBoxResult result = MessageBox.Show("A complete dump already exists! Are you sure you want to overwrite?", "Overwrite?", MessageBoxButton.YesNo, MessageBoxImage.Exclamation); - if (result == MessageBoxResult.No || result == MessageBoxResult.Cancel || result == MessageBoxResult.None) - { - return Result.Failure("Dumping aborted!"); - } - } - return Result.Success(); } diff --git a/DICUI/Utilities/Extensions.cs b/DICUI.Library/Utilities/Extensions.cs similarity index 100% rename from DICUI/Utilities/Extensions.cs rename to DICUI.Library/Utilities/Extensions.cs diff --git a/DICUI/Utilities/Parameters.cs b/DICUI.Library/Utilities/Parameters.cs similarity index 100% rename from DICUI/Utilities/Parameters.cs rename to DICUI.Library/Utilities/Parameters.cs diff --git a/DICUI/Utilities/Result.cs b/DICUI.Library/Utilities/Result.cs similarity index 100% rename from DICUI/Utilities/Result.cs rename to DICUI.Library/Utilities/Result.cs diff --git a/DICUI/Utilities/Validators.cs b/DICUI.Library/Utilities/Validators.cs similarity index 99% rename from DICUI/Utilities/Validators.cs rename to DICUI.Library/Utilities/Validators.cs index e79d92b7..6586dd06 100644 --- a/DICUI/Utilities/Validators.cs +++ b/DICUI.Library/Utilities/Validators.cs @@ -431,7 +431,7 @@ namespace DICUI.Utilities // Get the optical disc drives List discDrives = DriveInfo.GetDrives() .Where(d => d.DriveType == DriveType.CDRom) - .Select(d => Drive.Optical(d.Name[0], (d.IsReady ? d.VolumeLabel : UIElements.DiscNotDetected), d.IsReady)) + .Select(d => Drive.Optical(d.Name[0], (d.IsReady ? d.VolumeLabel : Template.DiscNotDetected), d.IsReady)) .ToList(); // Add the two lists together and order diff --git a/DICUI/mspack.dll b/DICUI.Library/mspack.dll similarity index 100% rename from DICUI/mspack.dll rename to DICUI.Library/mspack.dll diff --git a/DICUI/packages.config b/DICUI.Library/packages.config similarity index 100% rename from DICUI/packages.config rename to DICUI.Library/packages.config diff --git a/DICUI.Test/DICUI.Test.csproj b/DICUI.Test/DICUI.Test.csproj index db2befea..6be8f167 100644 --- a/DICUI.Test/DICUI.Test.csproj +++ b/DICUI.Test/DICUI.Test.csproj @@ -78,14 +78,18 @@ + + + + + {51ab0928-13f9-44bf-a407-b6957a43a056} + DICUI.Library + {7b1b75eb-8940-466f-bd51-76471a57f9be} DICUI - - - diff --git a/DICUI.Test/UI/AllowedSpeedsTest.cs b/DICUI.Test/UI/AllowedSpeedsTest.cs index 6396b1af..386ae01c 100644 --- a/DICUI.Test/UI/AllowedSpeedsTest.cs +++ b/DICUI.Test/UI/AllowedSpeedsTest.cs @@ -1,6 +1,5 @@ using System.Linq; using DICUI.Data; -using DICUI.UI; using Xunit; namespace DICUI.Test.Data @@ -15,7 +14,7 @@ namespace DICUI.Test.Data [InlineData(null, 72)] // TODO: Update when fully determined public void GetAllowedDriveSpeedForMediaTypeTest(MediaType? mediaType, int maxExpected) { - var actual = AllowedSpeeds.GetForMediaType(mediaType); + var actual = Constants.GetSpeedsForMediaType(mediaType); Assert.Equal(maxExpected, actual.Last()); } } diff --git a/DICUI.sln b/DICUI.sln index fcb2872d..8350a403 100644 --- a/DICUI.sln +++ b/DICUI.sln @@ -7,6 +7,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DICUI", "DICUI\DICUI.csproj EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DICUI.Test", "DICUI.Test\DICUI.Test.csproj", "{7CC064D2-38AB-4A05-8519-28660DE4562A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DICUI.Library", "DICUI.Library\DICUI.Library.csproj", "{51AB0928-13F9-44BF-A407-B6957A43A056}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DICUI.Forms", "DICUI.Forms\DICUI.Forms.csproj", "{A6719A99-BF0E-4637-9A8E-CB38B1E16971}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -21,6 +25,14 @@ Global {7CC064D2-38AB-4A05-8519-28660DE4562A}.Debug|Any CPU.Build.0 = Debug|Any CPU {7CC064D2-38AB-4A05-8519-28660DE4562A}.Release|Any CPU.ActiveCfg = Release|Any CPU {7CC064D2-38AB-4A05-8519-28660DE4562A}.Release|Any CPU.Build.0 = Release|Any CPU + {51AB0928-13F9-44BF-A407-B6957A43A056}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51AB0928-13F9-44BF-A407-B6957A43A056}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51AB0928-13F9-44BF-A407-B6957A43A056}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51AB0928-13F9-44BF-A407-B6957A43A056}.Release|Any CPU.Build.0 = Release|Any CPU + {A6719A99-BF0E-4637-9A8E-CB38B1E16971}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6719A99-BF0E-4637-9A8E-CB38B1E16971}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6719A99-BF0E-4637-9A8E-CB38B1E16971}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6719A99-BF0E-4637-9A8E-CB38B1E16971}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/DICUI/App.xaml b/DICUI/App.xaml index bcd42346..b9f57038 100644 --- a/DICUI/App.xaml +++ b/DICUI/App.xaml @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DICUI" - StartupUri="MainWindow.xaml"> + StartupUri="Windows\MainWindow.xaml"> diff --git a/DICUI/App.xaml.cs b/DICUI/App.xaml.cs index 138640a0..4f140534 100644 --- a/DICUI/App.xaml.cs +++ b/DICUI/App.xaml.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Data; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; +using System.Windows; namespace DICUI { diff --git a/DICUI/Constants.cs b/DICUI/Constants.cs new file mode 100644 index 00000000..678aef96 --- /dev/null +++ b/DICUI/Constants.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Media; +using DICUI.Data; + +namespace DICUI +{ + /// + /// Variables for UI elements + /// + public static class Constants + { + public const string StartDumping = "Start Dumping"; + public const string StopDumping = "Stop Dumping"; + + public const int LogWindowMarginFromMainWindow = 10; + + // Private lists of known drive speed ranges + private static IReadOnlyList cd { get; } = new List { 1, 2, 3, 4, 6, 8, 12, 16, 20, 24, 32, 40, 44, 48, 52, 56, 72 }; + private static IReadOnlyList dvd { get; } = cd.Where(s => s <= 24).ToList(); + private static IReadOnlyList bd { get; } = cd.Where(s => s <= 16).ToList(); + private static IReadOnlyList unknown { get; } = cd; // TODO: All or {1}? Maybe null? + + /// + /// Get list of all drive speeds for a given MediaType + /// + /// MediaType? that represents the current item + /// Read-only list of drive speeds + public static IReadOnlyList GetSpeedsForMediaType(MediaType? type) + { + switch (type) + { + case MediaType.CDROM: + case MediaType.GDROM: + return cd; + case MediaType.DVD: + case MediaType.HDDVD: + case MediaType.NintendoGameCube: + case MediaType.NintendoWiiOpticalDisc: + return dvd; + case MediaType.BluRay: + return bd; + default: + return unknown; + } + } + + // Create collections for UI based on known drive speeds + public static DoubleCollection SpeedsForCDAsCollection { get; } = GetDoubleCollectionFromIntList(cd); + public static DoubleCollection SpeedsForDVDAsCollection { get; } = GetDoubleCollectionFromIntList(dvd); + public static DoubleCollection SpeedsForBDAsCollection { get; } = GetDoubleCollectionFromIntList(bd); + private static DoubleCollection GetDoubleCollectionFromIntList(IReadOnlyList list) + => new DoubleCollection(list.Select(i => Convert.ToDouble(i)).ToList()); + } +} diff --git a/DICUI/DICUI.csproj b/DICUI/DICUI.csproj index 2c79be4b..e1708fa4 100644 --- a/DICUI/DICUI.csproj +++ b/DICUI/DICUI.csproj @@ -67,68 +67,42 @@ - - ..\packages\BurnOutSharp.1.3.7.1\lib\net461\BurnOutSharp.dll - - - ..\packages\LessIO.0.5.0\lib\net40\LessIO.dll - - - ..\packages\libmspack4n.0.8.0\lib\net40\libmspackn.dll - - - - - - 4.0 - - ..\packages\UnshieldSharp.1.4.2.2\lib\net461\UnshieldSharp.dll - - - ..\packages\zlib.net.1.0.4.0\lib\zlib.net.dll - MSBuild:Compile Designer - + + + + LogWindow.xaml - - - - - - - - - - - - + OptionsWindow.xaml - + + + Designer MSBuild:Compile - + MSBuild:Compile Designer @@ -136,12 +110,11 @@ App.xaml Code - - + MainWindow.xaml Code - + Designer MSBuild:Compile @@ -153,7 +126,6 @@ - @@ -171,29 +143,10 @@ - - {2735412F-7F64-5B0F-8F00-5D77AFBE261E} - 1 - 0 - 0 - tlbimp - False - True - - - {2C941FD0-975B-59BE-A960-9A2A262853A5} - 1 - 0 - 0 - tlbimp - False - True - - - - - Always - + + {51ab0928-13f9-44bf-a407-b6957a43a056} + DICUI.Library + \ No newline at end of file diff --git a/DICUI/EnumDescriptionConverter.cs b/DICUI/EnumDescriptionConverter.cs new file mode 100644 index 00000000..ffb04c9f --- /dev/null +++ b/DICUI/EnumDescriptionConverter.cs @@ -0,0 +1,33 @@ +using System; +using System.Globalization; +using System.Windows.Data; +using DICUI.Data; +using DICUI.Utilities; + +namespace DICUI +{ + /// + /// Used to provide a converter to XAML files to render comboboxes with enum values + /// + public class EnumDescriptionConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is DICCommand) + return ((DICCommand)value).Name(); + else if (value is DICFlag) + return ((DICFlag)value).Name(); + else if (value is MediaType?) + return ((MediaType?)value).Name(); + else if (value is KnownSystem?) + return ((KnownSystem?)value).Name(); + else + return ""; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return string.Empty; + } + } +} diff --git a/DICUI/UI/KnownSystemComboBoxItem.cs b/DICUI/KnownSystemComboBoxItem.cs similarity index 98% rename from DICUI/UI/KnownSystemComboBoxItem.cs rename to DICUI/KnownSystemComboBoxItem.cs index d9940db2..ef91bd51 100644 --- a/DICUI/UI/KnownSystemComboBoxItem.cs +++ b/DICUI/KnownSystemComboBoxItem.cs @@ -2,7 +2,7 @@ using DICUI.Data; using DICUI.Utilities; -namespace DICUI.UI +namespace DICUI { /// /// Represents a single item in the System combo box diff --git a/DICUI/UI/ViewModels.cs b/DICUI/ViewModels.cs similarity index 98% rename from DICUI/UI/ViewModels.cs rename to DICUI/ViewModels.cs index 574769f1..1c7938d0 100644 --- a/DICUI/UI/ViewModels.cs +++ b/DICUI/ViewModels.cs @@ -1,7 +1,8 @@ using System; using System.Windows.Media; +using DICUI.Windows; -namespace DICUI.UI +namespace DICUI { public class OptionsViewModel { diff --git a/DICUI/LogWindow.xaml b/DICUI/Windows/LogWindow.xaml similarity index 90% rename from DICUI/LogWindow.xaml rename to DICUI/Windows/LogWindow.xaml index b2a74db5..d483079b 100644 --- a/DICUI/LogWindow.xaml +++ b/DICUI/Windows/LogWindow.xaml @@ -1,7 +1,7 @@ - @@ -35,12 +35,12 @@