diff --git a/CUERipper/CUERipper.csproj b/CUERipper/CUERipper.csproj index 1676c3b..3a3880f 100644 --- a/CUERipper/CUERipper.csproj +++ b/CUERipper/CUERipper.csproj @@ -14,15 +14,17 @@ 2.0 + cue2.ico true full false - bin\Debug\ + ..\bin\Debug\ DEBUG;TRACE prompt 4 + true pdbonly @@ -103,15 +105,14 @@ {6458A13A-30EF-45A9-9D58-E5031B17BEE2} CUETools.Codecs + + {AA2A9A7E-45FB-4632-AD85-85B0E556F818} + CUETools.CTDB + {4911BD82-49EF-4858-8B51-5394F86739A4} CUETools.Processor - - {8CF07381-BEA2-4AFC-B3DD-9B2F21C65A3A} - CUETools.Ripper.SCSI - False - {D2700165-3E77-4B28-928D-551F5FC11954} CUETools.Ripper @@ -124,6 +125,10 @@ {74C2036B-2C9B-4FC8-B7BD-AE81A8DCE533} MusicBrainz + + {8DD1E84B-0B03-4C0B-9B42-1E49F75E7CB1} + ProgressODoom + @@ -136,6 +141,8 @@ + + diff --git a/CUERipper/Properties/Resources.Designer.cs b/CUERipper/Properties/Resources.Designer.cs index 6e45489..d61d387 100644 --- a/CUERipper/Properties/Resources.Designer.cs +++ b/CUERipper/Properties/Resources.Designer.cs @@ -81,6 +81,13 @@ namespace CUERipper.Properties { } } + internal static System.Drawing.Bitmap cdrepair { + get { + object obj = ResourceManager.GetObject("cdrepair", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + internal static System.Drawing.Bitmap freedb { get { object obj = ResourceManager.GetObject("freedb", resourceCulture); diff --git a/CUERipper/Properties/Resources.resx b/CUERipper/Properties/Resources.resx index 177c1cc..eca370c 100644 --- a/CUERipper/Properties/Resources.resx +++ b/CUERipper/Properties/Resources.resx @@ -133,4 +133,7 @@ ..\Resources\accuraterip_16.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\cdrepair.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/CUERipper/frmCUERipper.Designer.cs b/CUERipper/frmCUERipper.Designer.cs index 0713c86..e080a8b 100644 --- a/CUERipper/frmCUERipper.Designer.cs +++ b/CUERipper/frmCUERipper.Designer.cs @@ -33,9 +33,9 @@ namespace CUERipper this.comboDrives = new System.Windows.Forms.ComboBox(); this.statusStrip1 = new System.Windows.Forms.StatusStrip(); this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); + this.toolStripStatusCTDB = new System.Windows.Forms.ToolStripStatusLabel(); this.toolStripStatusAr = new System.Windows.Forms.ToolStripStatusLabel(); this.toolStripProgressBar1 = new System.Windows.Forms.ToolStripProgressBar(); - this.toolStripProgressBar2 = new System.Windows.Forms.ToolStripProgressBar(); this.toolStripStatusLabel2 = new System.Windows.Forms.ToolStripStatusLabel(); this.listTracks = new System.Windows.Forms.ListView(); this.Title = new System.Windows.Forms.ColumnHeader(); @@ -50,8 +50,6 @@ namespace CUERipper this.comboRelease = new System.Windows.Forms.ComboBox(); this.contextMenuStripRelease = new System.Windows.Forms.ContextMenuStrip(this.components); this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); - this.releaseBindingSource = new System.Windows.Forms.BindingSource(this.components); this.numericWriteOffset = new System.Windows.Forms.NumericUpDown(); this.lblWriteOffset = new System.Windows.Forms.Label(); this.comboBoxEncoder = new System.Windows.Forms.ComboBox(); @@ -60,11 +58,28 @@ namespace CUERipper this.radioButtonAudioLossless = new System.Windows.Forms.RadioButton(); this.checkBoxEACMode = new System.Windows.Forms.CheckBox(); this.groupBoxSettings = new System.Windows.Forms.GroupBox(); + this.labelSecureMode = new System.Windows.Forms.Label(); + this.labelEncoderMinMode = new System.Windows.Forms.Label(); + this.labelEncoderMaxMode = new System.Windows.Forms.Label(); + this.labelEncoderMode = new System.Windows.Forms.Label(); + this.trackBarEncoderMode = new System.Windows.Forms.TrackBar(); + this.trackBarSecureMode = new System.Windows.Forms.TrackBar(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); + this.releaseBindingSource = new System.Windows.Forms.BindingSource(this.components); + this.progressBarErrors = new ProgressODoom.ProgressBarEx(); + this.plainBackgroundPainter1 = new ProgressODoom.PlainBackgroundPainter(); + this.styledBorderPainter1 = new ProgressODoom.StyledBorderPainter(); + this.plainProgressPainter1 = new ProgressODoom.PlainProgressPainter(); + this.gradientGlossPainter1 = new ProgressODoom.GradientGlossPainter(); + this.progressBarCD = new ProgressODoom.ProgressBarEx(); + this.plainProgressPainter2 = new ProgressODoom.PlainProgressPainter(); this.statusStrip1.SuspendLayout(); this.contextMenuStripRelease.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.releaseBindingSource)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.numericWriteOffset)).BeginInit(); this.groupBoxSettings.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarEncoderMode)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarSecureMode)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.releaseBindingSource)).BeginInit(); this.SuspendLayout(); // // comboDrives @@ -81,9 +96,9 @@ namespace CUERipper // this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripStatusLabel1, + this.toolStripStatusCTDB, this.toolStripStatusAr, this.toolStripProgressBar1, - this.toolStripProgressBar2, this.toolStripStatusLabel2}); resources.ApplyResources(this.statusStrip1, "statusStrip1"); this.statusStrip1.Name = "statusStrip1"; @@ -96,8 +111,22 @@ namespace CUERipper resources.ApplyResources(this.toolStripStatusLabel1, "toolStripStatusLabel1"); this.toolStripStatusLabel1.Spring = true; // + // toolStripStatusCTDB + // + this.toolStripStatusCTDB.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom))); + this.toolStripStatusCTDB.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; + this.toolStripStatusCTDB.Image = global::CUERipper.Properties.Resources.cdrepair; + this.toolStripStatusCTDB.Name = "toolStripStatusCTDB"; + resources.ApplyResources(this.toolStripStatusCTDB, "toolStripStatusCTDB"); + // // toolStripStatusAr // + this.toolStripStatusAr.BorderSides = ((System.Windows.Forms.ToolStripStatusLabelBorderSides)((((System.Windows.Forms.ToolStripStatusLabelBorderSides.Left | System.Windows.Forms.ToolStripStatusLabelBorderSides.Top) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Right) + | System.Windows.Forms.ToolStripStatusLabelBorderSides.Bottom))); + this.toolStripStatusAr.BorderStyle = System.Windows.Forms.Border3DStyle.SunkenInner; resources.ApplyResources(this.toolStripStatusAr, "toolStripStatusAr"); this.toolStripStatusAr.Name = "toolStripStatusAr"; // @@ -109,13 +138,6 @@ namespace CUERipper resources.ApplyResources(this.toolStripProgressBar1, "toolStripProgressBar1"); this.toolStripProgressBar1.Style = System.Windows.Forms.ProgressBarStyle.Continuous; // - // toolStripProgressBar2 - // - this.toolStripProgressBar2.AutoToolTip = true; - this.toolStripProgressBar2.Name = "toolStripProgressBar2"; - resources.ApplyResources(this.toolStripProgressBar2, "toolStripProgressBar2"); - this.toolStripProgressBar2.Style = System.Windows.Forms.ProgressBarStyle.Continuous; - // // toolStripStatusLabel2 // this.toolStripStatusLabel2.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; @@ -229,16 +251,6 @@ namespace CUERipper resources.ApplyResources(this.editToolStripMenuItem, "editToolStripMenuItem"); this.editToolStripMenuItem.Click += new System.EventHandler(this.editToolStripMenuItem_Click); // - // toolStripMenuItem1 - // - this.toolStripMenuItem1.Image = global::CUERipper.Properties.Resources.cddb; - this.toolStripMenuItem1.Name = "toolStripMenuItem1"; - resources.ApplyResources(this.toolStripMenuItem1, "toolStripMenuItem1"); - // - // releaseBindingSource - // - this.releaseBindingSource.DataSource = typeof(MusicBrainz.Release); - // // numericWriteOffset // resources.ApplyResources(this.numericWriteOffset, "numericWriteOffset"); @@ -300,31 +312,151 @@ namespace CUERipper // // groupBoxSettings // + this.groupBoxSettings.Controls.Add(this.labelSecureMode); + this.groupBoxSettings.Controls.Add(this.labelEncoderMinMode); + this.groupBoxSettings.Controls.Add(this.labelEncoderMaxMode); + this.groupBoxSettings.Controls.Add(this.labelEncoderMode); + this.groupBoxSettings.Controls.Add(this.trackBarEncoderMode); + this.groupBoxSettings.Controls.Add(this.trackBarSecureMode); this.groupBoxSettings.Controls.Add(this.radioButtonAudioLossless); this.groupBoxSettings.Controls.Add(this.comboBoxAudioFormat); - this.groupBoxSettings.Controls.Add(this.checkBoxEACMode); this.groupBoxSettings.Controls.Add(this.lblWriteOffset); - this.groupBoxSettings.Controls.Add(this.numericWriteOffset); + this.groupBoxSettings.Controls.Add(this.checkBoxEACMode); this.groupBoxSettings.Controls.Add(this.comboImage); this.groupBoxSettings.Controls.Add(this.radioButtonAudioLossy); this.groupBoxSettings.Controls.Add(this.comboBoxEncoder); this.groupBoxSettings.Controls.Add(this.radioButtonAudioHybrid); + this.groupBoxSettings.Controls.Add(this.numericWriteOffset); resources.ApplyResources(this.groupBoxSettings, "groupBoxSettings"); this.groupBoxSettings.Name = "groupBoxSettings"; this.groupBoxSettings.TabStop = false; // + // labelSecureMode + // + resources.ApplyResources(this.labelSecureMode, "labelSecureMode"); + this.labelSecureMode.Name = "labelSecureMode"; + // + // labelEncoderMinMode + // + resources.ApplyResources(this.labelEncoderMinMode, "labelEncoderMinMode"); + this.labelEncoderMinMode.Name = "labelEncoderMinMode"; + // + // labelEncoderMaxMode + // + resources.ApplyResources(this.labelEncoderMaxMode, "labelEncoderMaxMode"); + this.labelEncoderMaxMode.Name = "labelEncoderMaxMode"; + // + // labelEncoderMode + // + resources.ApplyResources(this.labelEncoderMode, "labelEncoderMode"); + this.labelEncoderMode.Name = "labelEncoderMode"; + // + // trackBarEncoderMode + // + resources.ApplyResources(this.trackBarEncoderMode, "trackBarEncoderMode"); + this.trackBarEncoderMode.LargeChange = 1; + this.trackBarEncoderMode.Name = "trackBarEncoderMode"; + this.trackBarEncoderMode.Scroll += new System.EventHandler(this.trackBarEncoderMode_Scroll); + // + // trackBarSecureMode + // + this.trackBarSecureMode.LargeChange = 3; + resources.ApplyResources(this.trackBarSecureMode, "trackBarSecureMode"); + this.trackBarSecureMode.Maximum = 2; + this.trackBarSecureMode.Name = "trackBarSecureMode"; + this.trackBarSecureMode.Scroll += new System.EventHandler(this.trackBarSecureMode_Scroll); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.Image = global::CUERipper.Properties.Resources.cddb; + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + resources.ApplyResources(this.toolStripMenuItem1, "toolStripMenuItem1"); + // + // releaseBindingSource + // + this.releaseBindingSource.DataSource = typeof(MusicBrainz.Release); + // + // progressBarErrors + // + this.progressBarErrors.BackgroundPainter = this.plainBackgroundPainter1; + this.progressBarErrors.BorderPainter = this.styledBorderPainter1; + resources.ApplyResources(this.progressBarErrors, "progressBarErrors"); + this.progressBarErrors.MarqueePercentage = 25; + this.progressBarErrors.MarqueeSpeed = 30; + this.progressBarErrors.MarqueeStep = 1; + this.progressBarErrors.Maximum = 100; + this.progressBarErrors.Minimum = 0; + this.progressBarErrors.Name = "progressBarErrors"; + this.progressBarErrors.ProgressPadding = 0; + this.progressBarErrors.ProgressPainter = this.plainProgressPainter1; + this.progressBarErrors.ProgressType = ProgressODoom.ProgressType.Smooth; + this.progressBarErrors.ShowPercentage = false; + this.progressBarErrors.Value = 10; + // + // plainBackgroundPainter1 + // + this.plainBackgroundPainter1.Color = System.Drawing.SystemColors.Control; + this.plainBackgroundPainter1.GlossPainter = null; + // + // styledBorderPainter1 + // + this.styledBorderPainter1.Border3D = System.Windows.Forms.Border3DStyle.Etched; + // + // plainProgressPainter1 + // + this.plainProgressPainter1.Color = System.Drawing.Color.Red; + this.plainProgressPainter1.GlossPainter = this.gradientGlossPainter1; + this.plainProgressPainter1.LeadingEdge = System.Drawing.Color.Transparent; + this.plainProgressPainter1.ProgressBorderPainter = null; + // + // gradientGlossPainter1 + // + this.gradientGlossPainter1.AlphaHigh = 235; + this.gradientGlossPainter1.AlphaLow = 0; + this.gradientGlossPainter1.Angle = 90F; + this.gradientGlossPainter1.Color = System.Drawing.SystemColors.Control; + this.gradientGlossPainter1.PercentageCovered = 100; + this.gradientGlossPainter1.Style = ProgressODoom.GlossStyle.Top; + this.gradientGlossPainter1.Successor = null; + // + // progressBarCD + // + this.progressBarCD.BackgroundPainter = this.plainBackgroundPainter1; + this.progressBarCD.BorderPainter = this.styledBorderPainter1; + resources.ApplyResources(this.progressBarCD, "progressBarCD"); + this.progressBarCD.MarqueePercentage = 25; + this.progressBarCD.MarqueeSpeed = 30; + this.progressBarCD.MarqueeStep = 1; + this.progressBarCD.Maximum = 100; + this.progressBarCD.Minimum = 0; + this.progressBarCD.Name = "progressBarCD"; + this.progressBarCD.ProgressPadding = 0; + this.progressBarCD.ProgressPainter = this.plainProgressPainter2; + this.progressBarCD.ProgressType = ProgressODoom.ProgressType.Smooth; + this.progressBarCD.ShowPercentage = true; + this.progressBarCD.Value = 10; + // + // plainProgressPainter2 + // + this.plainProgressPainter2.Color = System.Drawing.Color.Lime; + this.plainProgressPainter2.GlossPainter = this.gradientGlossPainter1; + this.plainProgressPainter2.LeadingEdge = System.Drawing.Color.Transparent; + this.plainProgressPainter2.ProgressBorderPainter = null; + // // frmCUERipper // resources.ApplyResources(this, "$this"); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.progressBarErrors); + this.Controls.Add(this.progressBarCD); this.Controls.Add(this.groupBoxSettings); this.Controls.Add(this.comboRelease); - this.Controls.Add(this.buttonPause); this.Controls.Add(this.listTracks); - this.Controls.Add(this.buttonAbort); this.Controls.Add(this.buttonGo); this.Controls.Add(this.statusStrip1); + this.Controls.Add(this.buttonAbort); this.Controls.Add(this.comboDrives); + this.Controls.Add(this.buttonPause); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.MaximizeBox = false; this.Name = "frmCUERipper"; @@ -334,10 +466,12 @@ namespace CUERipper this.statusStrip1.ResumeLayout(false); this.statusStrip1.PerformLayout(); this.contextMenuStripRelease.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.releaseBindingSource)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.numericWriteOffset)).EndInit(); this.groupBoxSettings.ResumeLayout(false); this.groupBoxSettings.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarEncoderMode)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.trackBarSecureMode)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.releaseBindingSource)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -349,7 +483,6 @@ namespace CUERipper private System.Windows.Forms.StatusStrip statusStrip1; private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; private System.Windows.Forms.ToolStripProgressBar toolStripProgressBar1; - private System.Windows.Forms.ToolStripProgressBar toolStripProgressBar2; private System.Windows.Forms.ListView listTracks; private System.Windows.Forms.ColumnHeader TrackNo; private System.Windows.Forms.ColumnHeader Title; @@ -375,6 +508,20 @@ namespace CUERipper private System.Windows.Forms.RadioButton radioButtonAudioLossless; private System.Windows.Forms.CheckBox checkBoxEACMode; private System.Windows.Forms.GroupBox groupBoxSettings; + private System.Windows.Forms.ToolStripStatusLabel toolStripStatusCTDB; + private System.Windows.Forms.TrackBar trackBarEncoderMode; + private System.Windows.Forms.Label labelEncoderMode; + private System.Windows.Forms.Label labelEncoderMaxMode; + private System.Windows.Forms.Label labelEncoderMinMode; + private System.Windows.Forms.TrackBar trackBarSecureMode; + private System.Windows.Forms.Label labelSecureMode; + private ProgressODoom.ProgressBarEx progressBarErrors; + private ProgressODoom.StyledBorderPainter styledBorderPainter1; + private ProgressODoom.PlainProgressPainter plainProgressPainter1; + private ProgressODoom.PlainBackgroundPainter plainBackgroundPainter1; + private ProgressODoom.GradientGlossPainter gradientGlossPainter1; + private ProgressODoom.ProgressBarEx progressBarCD; + private ProgressODoom.PlainProgressPainter plainProgressPainter2; } } diff --git a/CUERipper/frmCUERipper.cs b/CUERipper/frmCUERipper.cs index c5bbcd8..5c2f82e 100644 --- a/CUERipper/frmCUERipper.cs +++ b/CUERipper/frmCUERipper.cs @@ -5,16 +5,17 @@ using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; +using System.Net; using System.Text; using System.Threading; using System.Windows.Forms; using System.Configuration; using CUETools.AccurateRip; +using CUETools.CTDB; using CUETools.CDImage; using CUETools.Codecs; using CUETools.Processor; using CUETools.Ripper; -using CUETools.Ripper.SCSI; using MusicBrainz; using Freedb; @@ -23,11 +24,11 @@ namespace CUERipper public partial class frmCUERipper : Form { private Thread _workThread = null; - private CDDriveReader _reader = null; + private ICDRipper _reader = null; private StartStop _startStop; private CUEConfig _config; private string _format; - private CUESheet _cueSheet; + private CUESheet metadata, cueSheet; private string _pathOut; private string _pathFormat; string _defaultLosslessFormat, _defaultLossyFormat, _defaultHybridFormat; @@ -69,19 +70,31 @@ namespace CUERipper //if (crc0a != crc0b) // || crc1a != crc1b || crc2a != crc2b) //{ //} - + SetupControls(); SettingsReader sr = new SettingsReader("CUERipper", "settings.txt", Application.ExecutablePath); + _config.Load(sr); _defaultLosslessFormat = sr.Load("DefaultLosslessFormat") ?? "flac"; _defaultLossyFormat = sr.Load("DefaultLossyFormat") ?? "mp3"; _defaultHybridFormat = sr.Load("DefaultHybridFormat") ?? "lossy.flac"; - _config.createEACLOG = sr.LoadBoolean("CreateEACLOG") ?? false; - _config.preserveHTOA = sr.LoadBoolean("PreserveHTOA") ?? false; - _config.createM3U = sr.LoadBoolean("CreateM3U") ?? true; + //_config.createEACLOG = sr.LoadBoolean("CreateEACLOG") ?? true; + //_config.preserveHTOA = sr.LoadBoolean("PreserveHTOA") ?? false; + //_config.createM3U = sr.LoadBoolean("CreateM3U") ?? true; _pathFormat = sr.Load("PathFormat") ?? "%music%\\%artist%\\[%year% - ]%album%\\%artist% - %album%.cue"; checkBoxEACMode.Checked = _config.createEACLOG; SelectedOutputAudioType = (AudioEncoderType?)sr.LoadInt32("OutputAudioType", null, null) ?? AudioEncoderType.Lossless; comboBoxAudioFormat.SelectedIndex = sr.LoadInt32("ComboCodec", 0, comboBoxAudioFormat.Items.Count - 1) ?? 0; comboImage.SelectedIndex = sr.LoadInt32("ComboImage", 0, comboImage.Items.Count - 1) ?? 0; + trackBarSecureMode.Value = sr.LoadInt32("SecureMode", 0, trackBarSecureMode.Maximum - 1) ?? 1; + trackBarSecureMode_Scroll(this, new EventArgs()); + //string encoderName = sr.Load("EncoderName"); + //if (encoderName != null) + // foreach (object item in comboBoxEncoder.Items) + // { + // CUEToolsUDC encoder = item as CUEToolsUDC; + // if (encoder.Name != encoderName) continue; + // comboBoxEncoder.SelectedItem = encoder; + // break; + // } UpdateDrives(); } @@ -119,18 +132,25 @@ namespace CUERipper private void UpdateDrives() { buttonGo.Enabled = false; + foreach (object item in comboDrives.Items) + { + ICDRipper drive = item as ICDRipper; + if (drive != null) + drive.Close(); + } comboDrives.Items.Clear(); comboRelease.Items.Clear(); listTracks.Items.Clear(); - foreach (char drive in CDDriveReader.DrivesAvailable()) + foreach (char drive in CDDrivesList.DrivesAvailable()) { - CDDriveReader reader = new CDDriveReader(); + ICDRipper reader = Activator.CreateInstance(CUEProcessorPlugins.ripper) as ICDRipper; string arName = null; int driveOffset; try { reader.Open(drive); arName = reader.ARName; + reader.Close(); } catch (Exception ex) { @@ -165,12 +185,12 @@ namespace CUERipper buttonGo.Visible = buttonGo.Enabled = !running; toolStripStatusLabel1.Text = String.Empty; toolStripProgressBar1.Value = 0; - toolStripProgressBar2.Value = 0; + progressBarErrors.Value = 0; + progressBarCD.Value = 0; } - private void CDReadProgress(object sender, ReadProgressArgs e) + private void CheckStop() { - CDDriveReader audioSource = (CDDriveReader)sender; lock (_startStop) { if (_startStop._stop) @@ -188,37 +208,81 @@ namespace CUERipper Monitor.Wait(_startStop); } } + } + + private void UploadProgress(object sender, Krystalware.UploadHelper.UploadProgressEventArgs e) + { + CheckStop(); + this.BeginInvoke((MethodInvoker)delegate() + { + toolStripStatusLabel1.Text = e.uri; + toolStripProgressBar1.Value = Math.Max(0, Math.Min(100, (int)(e.percent * 100))); + }); + } + + private void CDReadProgress(object sender, ReadProgressArgs e) + { + CheckStop(); + + ICDRipper audioSource = sender as ICDRipper; int processed = e.Position - e.PassStart; TimeSpan elapsed = DateTime.Now - e.PassTime; double speed = elapsed.TotalSeconds > 0 ? processed / elapsed.TotalSeconds / 75 : 1.0; - double percentDisk = (double)(e.PassStart + (processed + e.Pass * (e.PassEnd - e.PassStart)) / (audioSource.CorrectionQuality + 1)) / audioSource.TOC.AudioLength; double percentTrck = (double)(e.Position - e.PassStart) / (e.PassEnd - e.PassStart); string status = string.Format("Ripping @{0:00.00}x {1}", speed, e.Pass > 0 ? " (Retry " + e.Pass.ToString() + ")" : ""); - this.BeginInvoke((MethodInvoker)delegate() { - //Color color = ColorTranslator.FromWin32(e.ErrorsCount == 0 || e.Position == 0 ? (byte)0 : (byte)(Math.Log(1 + e.ErrorsCount / e.Position, 2) * 255)); toolStripStatusLabel1.Text = status; toolStripProgressBar1.Value = Math.Max(0, Math.Min(100, (int)(percentTrck * 100))); - //toolStripProgressBar1.ProgressBar.Style = ProgressBarStyle.Blocks; - toolStripProgressBar2.Value = Math.Max(0, Math.Min(100, (int)(percentDisk * 100))); - //if (e.ErrorsCount == 0 || e.Position == 0) - //toolStripProgressBar3.Value = 0; - //else - //toolStripProgressBar3.Value = Math.Min(100, (int)(100 + Math.Log10(e.ErrorsCount / e.Position / 4 / 588) * 100)); + + progressBarErrors.Maximum = (int)(Math.Log(e.PassEnd - e.PassStart + 1) * 10); + progressBarErrors.Value = Math.Min(progressBarErrors.Maximum, (int)(Math.Log(e.ErrorsCount + 1) * 10)); + progressBarErrors.Enabled = e.Pass >= audioSource.CorrectionQuality; + + progressBarCD.Maximum = (int) audioSource.TOC.AudioLength; + progressBarCD.Value = Math.Max(0, Math.Min(progressBarCD.Maximum, (int)e.PassStart + (e.PassEnd - e.PassStart) * (Math.Min(e.Pass, audioSource.CorrectionQuality) + 1) / (audioSource.CorrectionQuality + 1))); }); } private void Rip(object o) { - CDDriveReader audioSource = (CDDriveReader)o; + ICDRipper audioSource = o as ICDRipper; audioSource.ReadProgress += new EventHandler(CDReadProgress); audioSource.DriveOffset = (int)numericWriteOffset.Value; try { - _cueSheet.Go(); + cueSheet.Go(); + + bool submit = cueSheet.CTDB.AccResult == HttpStatusCode.NotFound || + cueSheet.CTDB.AccResult == HttpStatusCode.OK; + //_cueSheet.CTDB.AccResult == HttpStatusCode.NoContent; + DBEntry confirm = null; + + submit &= audioSource.CorrectionQuality > 0; + + foreach (DBEntry entry in cueSheet.CTDB.Entries) + if (!entry.hasErrors) + confirm = entry; + + int start = (int)cueSheet.TOC[cueSheet.TOC.FirstAudio][0].Start; + for (int iSector = 0; iSector < (int)cueSheet.TOC.AudioLength; iSector++) + if (audioSource.Errors[start + iSector]) + submit = false; + + if (submit) + { + if (confirm != null) + cueSheet.CTDB.Confirm(confirm); + else + cueSheet.CTDB.Submit( + (int)cueSheet.ArVerify.WorstConfidence() + 1, + (int)cueSheet.ArVerify.WorstTotal() + 1, + cueSheet.Artist, + cueSheet.Title); + } + //CUESheet.WriteText(_pathOut, _cueSheet.CUESheetContents(_style)); //CUESheet.WriteText(Path.ChangeExtension(_pathOut, ".log"), _cueSheet.LOGContents()); } @@ -238,6 +302,8 @@ namespace CUERipper } #endif audioSource.ReadProgress -= new EventHandler(CDReadProgress); + audioSource.Close(); + audioSource.Open(audioSource.Path[0]); _workThread = null; this.BeginInvoke((MethodInvoker)delegate() { @@ -250,18 +316,20 @@ namespace CUERipper if (_reader == null) return; + cueSheet.CopyMetadata(metadata); _format = (string)comboBoxAudioFormat.SelectedItem; - _cueSheet.OutputStyle = comboImage.SelectedIndex == 0 ? CUEStyle.SingleFileWithCUE : + cueSheet.OutputStyle = comboImage.SelectedIndex == 0 ? CUEStyle.SingleFileWithCUE : CUEStyle.GapsAppended; - _pathOut = _cueSheet.GenerateUniqueOutputPath(_pathFormat, - _cueSheet.OutputStyle == CUEStyle.SingleFileWithCUE ? "." + _format : ".cue", + _pathOut = cueSheet.GenerateUniqueOutputPath(_pathFormat, + cueSheet.OutputStyle == CUEStyle.SingleFileWithCUE ? "." + _format : ".cue", CUEAction.Encode, null); if (_pathOut == "") { MessageBox.Show(this, "Output path generation failed", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } - _cueSheet.GenerateFilenames(SelectedOutputAudioType, _format, _pathOut); + cueSheet.GenerateFilenames(SelectedOutputAudioType, _format, _pathOut); + _reader.CorrectionQuality = trackBarSecureMode.Value; _workThread = new Thread(Rip); _workThread.Priority = ThreadPriority.BelowNormal; @@ -285,7 +353,7 @@ namespace CUERipper if (e.ListItem is string) return; ReleaseInfo r = (ReleaseInfo)(e.ListItem); - e.Value = string.Format("{0}{1} - {2}", r.cueSheet.Year != "" ? r.cueSheet.Year + ": " : "", r.cueSheet.Artist, r.cueSheet.Title); + e.Value = string.Format("{0}{1} - {2}", r.metadata.Year != "" ? r.metadata.Year + ": " : "", r.metadata.Artist, r.metadata.Title); } private void UpdateRelease() @@ -293,11 +361,11 @@ namespace CUERipper listTracks.Items.Clear(); if (comboRelease.SelectedItem == null || comboRelease.SelectedItem is string) return; - _cueSheet = ((ReleaseInfo)comboRelease.SelectedItem).cueSheet; + metadata = ((ReleaseInfo)comboRelease.SelectedItem).metadata; for (int i = 1; i <= _reader.TOC.TrackCount; i++) { listTracks.Items.Add(new ListViewItem(new string[] { - _reader.TOC[i].IsAudio ? _cueSheet.Tracks[i - _reader.TOC.FirstAudio].Title : "Data track", + _reader.TOC[i].IsAudio ? metadata.Tracks[i - _reader.TOC.FirstAudio].Title : "Data track", _reader.TOC[i].Number.ToString(), _reader.TOC[i].StartMSF, _reader.TOC[i].LengthMSF })); @@ -311,71 +379,60 @@ namespace CUERipper private void MusicBrainz_LookupProgress(object sender, XmlRequestEventArgs e) { + CheckStop(); //_progress.percentDisk = (1.0 + _progress.percentDisk) / 2; //_progress.input = e.Uri.ToString(); - lock (_startStop) - { - if (_startStop._stop) - { - _startStop._stop = false; - _startStop._pause = false; - throw new StopException(); - } - if (_startStop._pause) - { - this.BeginInvoke((MethodInvoker)delegate() - { - toolStripStatusLabel1.Text = "Paused..."; - }); - Monitor.Wait(_startStop); - } - } this.BeginInvoke((MethodInvoker)delegate() { toolStripStatusLabel1.Text = "Looking up album via " + (e == null ? "FreeDB" : "MusicBrainz"); - toolStripProgressBar1.Value = 0; - toolStripProgressBar2.Value = (100 + 2 * toolStripProgressBar2.Value) / 3; + toolStripProgressBar1.Value = (100 + 2 * toolStripProgressBar1.Value) / 3; }); } - private ReleaseInfo CreateCUESheet(CDDriveReader audioSource, Release release, CDEntry cdEntry) + private ReleaseInfo CreateCUESheet(ICDRipper audioSource, Release release, CDEntry cdEntry) { - ReleaseInfo r = new ReleaseInfo(); - r.cueSheet = new CUESheet(_config); - r.cueSheet.OpenCD(audioSource); - //r.cueSheet.WriteOffset = - General.SetCUELine(r.cueSheet.Attributes, "REM", "GENRE", "", true); - General.SetCUELine(r.cueSheet.Attributes, "REM", "DATE", "", false); - General.SetCUELine(r.cueSheet.Attributes, "REM", "DISCID", AccurateRipVerify.CalculateCDDBId(audioSource.TOC), false); - General.SetCUELine(r.cueSheet.Attributes, "REM", "COMMENT", _config.createEACLOG ? "ExactAudioCopy v0.99pb4" : audioSource.RipperVersion, true); + ReleaseInfo r = new ReleaseInfo(cueSheet); + General.SetCUELine(r.metadata.Attributes, "REM", "GENRE", "", true); + General.SetCUELine(r.metadata.Attributes, "REM", "DATE", "", false); if (release != null) { - r.cueSheet.FillFromMusicBrainz(release); + r.metadata.FillFromMusicBrainz(release); r.bitmap = Properties.Resources.musicbrainz; } else if (cdEntry != null) { - r.cueSheet.FillFromFreedb(cdEntry); + r.metadata.FillFromFreedb(cdEntry); r.bitmap = Properties.Resources.freedb; } else { - r.cueSheet.Artist = "Unknown Artist"; - r.cueSheet.Title = "Unknown Title"; + r.metadata.Artist = "Unknown Artist"; + r.metadata.Title = "Unknown Title"; for (int i = 0; i < audioSource.TOC.AudioTracks; i++) - r.cueSheet.Tracks[i].Title = string.Format("Track {0:00}", i + 1); + r.metadata.Tracks[i].Title = string.Format("Track {0:00}", i + 1); } - if (r.cueSheet.Genre == "") r.cueSheet.Genre = ""; - if (r.cueSheet.Year == "") r.cueSheet.Year = ""; - r.cueSheet.Action = CUEAction.Encode; - r.cueSheet.UseAccurateRip(); - //r.cueSheet.ArVerify.ContactAccurateRip(AccurateRipVerify.CalculateAccurateRipId(audioSource.TOC)); + if (r.metadata.Genre == "") r.metadata.Genre = ""; + if (r.metadata.Year == "") r.metadata.Year = ""; return r; } private void Lookup(object o) { - CDDriveReader audioSource = (CDDriveReader)o; + ICDRipper audioSource = o as ICDRipper; + + cueSheet = new CUESheet(_config); + cueSheet.OpenCD(audioSource); + cueSheet.CTDB.UploadHelper.onProgress += new EventHandler(UploadProgress); + cueSheet.Action = CUEAction.Encode; + + this.BeginInvoke((MethodInvoker)delegate() { toolStripStatusLabel1.Text = "Contacting AccurateRip database..."; }); + cueSheet.UseAccurateRip(); + this.BeginInvoke((MethodInvoker)delegate() { toolStripStatusLabel1.Text = "Contacting CTDB database..."; }); + cueSheet.UseCUEToolsDB(true, "CUERipper 205: " + _reader.ARName); + this.BeginInvoke((MethodInvoker)delegate() { toolStripStatusLabel1.Text = "Looking album info..."; }); + + General.SetCUELine(cueSheet.Attributes, "REM", "DISCID", AccurateRipVerify.CalculateCDDBId(audioSource.TOC), false); + General.SetCUELine(cueSheet.Attributes, "REM", "COMMENT", _config.createEACLOG ? "ExactAudioCopy v0.99pb4" : audioSource.RipperVersion, true); ReleaseQueryParameters p = new ReleaseQueryParameters(); p.DiscId = audioSource.TOC.MusicBrainzId; @@ -479,16 +536,19 @@ namespace CUERipper { SetupControls(); comboRelease.SelectedIndex = 0; - CUESheet cueSheet = ((ReleaseInfo)comboRelease.SelectedItem).cueSheet; toolStripStatusAr.Visible = cueSheet.ArVerify.ARStatus == null; toolStripStatusAr.Text = cueSheet.ArVerify.ARStatus == null ? cueSheet.ArVerify.Total(0).ToString() : "?"; toolStripStatusAr.ToolTipText = "AccurateRip: " + (cueSheet.ArVerify.ARStatus ?? "found") + "."; + toolStripStatusCTDB.Visible = cueSheet.CTDB.DBStatus == null; + toolStripStatusCTDB.Text = cueSheet.CTDB.DBStatus == null ? cueSheet.CTDB.Total.ToString() : ""; + toolStripStatusCTDB.ToolTipText = "CUETools DB: " + (cueSheet.CTDB.DBStatus ?? "found") + "."; }); } private void UpdateDrive() { toolStripStatusAr.Visible = false; + toolStripStatusCTDB.Visible = false; buttonGo.Enabled = false; comboRelease.Items.Clear(); listTracks.Items.Clear(); @@ -497,16 +557,17 @@ namespace CUERipper _reader = null; return; } - _reader = (CDDriveReader)comboDrives.SelectedItem; + _reader = comboDrives.SelectedItem as ICDRipper; try { + _reader.Close(); _reader.Open(_reader.Path[0]); numericWriteOffset.Value = _reader.DriveOffset; } catch (Exception ex) { numericWriteOffset.Value = _reader.DriveOffset; - _reader.Close(); + //_reader.Close(); comboRelease.Items.Add(ex.Message); comboRelease.SelectedIndex = 0; return; @@ -559,18 +620,19 @@ namespace CUERipper private void listTracks_AfterLabelEdit(object sender, LabelEditEventArgs e) { - CUESheet cueSheet = ((ReleaseInfo)comboRelease.SelectedItem).cueSheet; + CUESheet metadata = ((ReleaseInfo)comboRelease.SelectedItem).metadata; if (e.Label != null && _reader.TOC[e.Item + 1].IsAudio) - cueSheet.Tracks[e.Item].Title = e.Label; + metadata.Tracks[e.Item].Title = e.Label; else e.CancelEdit = true; } private void editToolStripMenuItem_Click(object sender, EventArgs e) { - CUESheet cueSheet = ((ReleaseInfo)comboRelease.SelectedItem).cueSheet; + ReleaseInfo ri = comboRelease.SelectedItem as ReleaseInfo; + if (ri == null) return; frmProperties frm = new frmProperties(); - frm.CUE = cueSheet; + frm.CUE = ri.metadata; frm.ShowDialog(); } @@ -598,16 +660,21 @@ namespace CUERipper private void frmCUERipper_FormClosed(object sender, FormClosedEventArgs e) { SettingsWriter sw = new SettingsWriter("CUERipper", "settings.txt", Application.ExecutablePath); + //CUEToolsUDC encoder = comboBoxEncoder.SelectedItem as CUEToolsUDC; + //if (encoder != null) + // sw.Save("EncoderName", encoder.Name); + _config.Save(sw); sw.Save("DefaultLosslessFormat", _defaultLosslessFormat); sw.Save("DefaultLossyFormat", _defaultLossyFormat); sw.Save("DefaultHybridFormat", _defaultHybridFormat); - sw.Save("CreateEACLOG", _config.createEACLOG); - sw.Save("PreserveHTOA", _config.preserveHTOA); - sw.Save("CreateM3U", _config.createM3U); + //sw.Save("CreateEACLOG", _config.createEACLOG); + //sw.Save("PreserveHTOA", _config.preserveHTOA); + //sw.Save("CreateM3U", _config.createM3U); sw.Save("OutputAudioType", (int)SelectedOutputAudioType); sw.Save("ComboCodec", comboBoxAudioFormat.SelectedIndex); sw.Save("ComboImage", comboImage.SelectedIndex); sw.Save("PathFormat", _pathFormat); + sw.Save("SecureMode", trackBarSecureMode.Value); sw.Close(); } @@ -749,6 +816,41 @@ namespace CUERipper SelectedOutputAudioFmt.encoderLossless = encoder; else SelectedOutputAudioFmt.encoderLossy = encoder; + + string[] modes = encoder.SupportedModes; + if (modes == null || modes.Length < 2) + { + trackBarEncoderMode.Visible = false; + labelEncoderMode.Visible = false; + labelEncoderMinMode.Visible = false; + labelEncoderMaxMode.Visible = false; + } + else + { + trackBarEncoderMode.Maximum = modes.Length - 1; + trackBarEncoderMode.Value = encoder.DefaultModeIndex == -1 ? modes.Length - 1 : encoder.DefaultModeIndex; + labelEncoderMode.Text = encoder.default_mode; + labelEncoderMinMode.Text = modes[0]; + labelEncoderMaxMode.Text = modes[modes.Length - 1]; + trackBarEncoderMode.Visible = true; + labelEncoderMode.Visible = true; + labelEncoderMinMode.Visible = true; + labelEncoderMaxMode.Visible = true; + } + } + + private void trackBarEncoderMode_Scroll(object sender, EventArgs e) + { + CUEToolsUDC encoder = comboBoxEncoder.SelectedItem as CUEToolsUDC; + string[] modes = encoder.SupportedModes; + encoder.default_mode = modes[trackBarEncoderMode.Value]; + labelEncoderMode.Text = encoder.default_mode; + } + + private void trackBarSecureMode_Scroll(object sender, EventArgs e) + { + string[] modes = new string[] { "Burst", "Secure", "Paranoid" }; + labelSecureMode.Text = modes[trackBarSecureMode.Value]; } } @@ -793,7 +895,13 @@ namespace CUERipper class ReleaseInfo { - public CUESheet cueSheet; + public CUESheet metadata; public Bitmap bitmap; + + public ReleaseInfo(CUESheet cue) + { + metadata = new CUESheet(cue.Config); + metadata.TOC = cue.TOC; + } } } diff --git a/CUERipper/frmCUERipper.resx b/CUERipper/frmCUERipper.resx index 11161c1..c6ea559 100644 --- a/CUERipper/frmCUERipper.resx +++ b/CUERipper/frmCUERipper.resx @@ -126,11 +126,11 @@ 6, 6 - 487, 21 + 553, 21 - 1 + 0 comboDrives @@ -142,17 +142,20 @@ $this - 8 + 9 - 0, 443 + 376, 17 - 260, 17 + 414, 20 MiddleLeft + + 20, 20 + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 @@ -177,37 +180,28 @@ White - 16, 17 - - - Overlay + 20, 20 Album found in AccurateRip database. - 70, 16 + 100, 19 - Track progress - - - 140, 16 - - - Disk progress + Read progress - 0, 17 + 0, 20 toolStripStatusAr - 0, 443 + 0, 456 - 505, 22 + 571, 25 12 @@ -237,7 +231,7 @@ Title - 292 + 355 0 @@ -264,10 +258,10 @@ 6, 60 - 487, 272 + 553, 272 - 0 + 2 listTracks @@ -279,7 +273,7 @@ $this - 4 + 5 Top, Left, Right @@ -288,10 +282,10 @@ NoControl - 382, 406 + 382, 343 - 111, 33 + 177, 33 13 @@ -327,13 +321,13 @@ tta - 103, 20 + 113, 15 - 89, 21 + 114, 21 - 17 + 4 comboBoxAudioFormat @@ -345,7 +339,7 @@ groupBoxSettings - 1 + 7 image @@ -354,13 +348,13 @@ tracks - 103, 49 + 6, 78 89, 21 - 18 + 5 comboImage @@ -372,7 +366,7 @@ groupBoxSettings - 5 + 10 Top, Left, Right @@ -381,10 +375,10 @@ NoControl - 382, 406 + 474, 343 - 111, 33 + 85, 33 19 @@ -405,7 +399,7 @@ $this - 5 + 8 Top, Left, Right @@ -414,10 +408,10 @@ NoControl - 382, 367 + 383, 343 - 111, 33 + 85, 33 20 @@ -438,13 +432,13 @@ $this - 3 + 10 Top, Left, Right - 285, 58 + 17, 17 94, 22 @@ -465,10 +459,10 @@ 6, 33 - 487, 21 + 553, 21 - 21 + 1 comboRelease @@ -480,25 +474,16 @@ $this - 2 + 4 - - 181, 22 - - - toolStripMenuItem1 - - - 116, 371 - - 305, 19 + 310, 15 54, 20 - 22 + 7 Right @@ -513,7 +498,7 @@ groupBoxSettings - 4 + 14 True @@ -522,7 +507,7 @@ NoControl - 237, 21 + 242, 19 62, 13 @@ -543,16 +528,16 @@ groupBoxSettings - 3 + 8 - 103, 78 + 113, 42 - 89, 21 + 114, 21 - 24 + 6 comboBoxEncoder @@ -564,7 +549,7 @@ groupBoxSettings - 7 + 12 True @@ -579,7 +564,7 @@ 52, 17 - 27 + 1 Lossy @@ -594,7 +579,7 @@ groupBoxSettings - 6 + 11 True @@ -609,7 +594,7 @@ 55, 17 - 26 + 2 Hybrid @@ -624,7 +609,7 @@ groupBoxSettings - 8 + 13 True @@ -639,7 +624,7 @@ 65, 17 - 25 + 0 Lossless @@ -654,19 +639,25 @@ groupBoxSettings - 0 + 6 True + + MiddleRight + + + NoControl + - 6, 77 + 288, 44 76, 17 - 28 + 3 EAC mode @@ -681,13 +672,199 @@ groupBoxSettings + 9 + + + 248, 98 + + + 109, 18 + + + 33 + + + TopCenter + + + labelSecureMode + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxSettings + + + 0 + + + True + + + False + + + Tahoma, 8.25pt + + + NoControl + + + 116, 103 + + + 0, 0, 0, 0 + + + 25, 13 + + + 30 + + + 128 + + + labelEncoderMinMode + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxSettings + + + 1 + + + False + + + Tahoma, 8.25pt + + + NoControl + + + 198, 103 + + + 0, 0, 0, 0 + + + 29, 13 + + + 32 + + + 320 + + + TopRight + + + labelEncoderMaxMode + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxSettings + + 2 + + Tahoma, 8.25pt + + + NoControl + + + 116, 103 + + + 0, 0, 0, 0 + + + 111, 15 + + + 31 + + + 256 + + + TopCenter + + + labelEncoderMode + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxSettings + + + 3 + + + NoControl + + + 113, 73 + + + 0, 0, 0, 0 + + + 114, 45 + + + 8 + + + trackBarEncoderMode + + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxSettings + + + 4 + + + 237, 71 + + + 127, 45 + + + 30 + + + trackBarSecureMode + + + System.Windows.Forms.TrackBar, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxSettings + + + 5 + 6, 332 - 370, 108 + 370, 121 29 @@ -702,50 +879,491 @@ $this + 3 + + + 181, 22 + + + toolStripMenuItem1 + + + 207, 17 + + + 998, 17 + + + 662, 17 + + + 382, 421 + + + 492, 17 + + + 827, 17 + + + 177, 23 + + + 30 + + + progressBarErrors + + + ProgressODoom.ProgressBarEx, ProgressODoom, Version=1.0.3711.31206, Culture=neutral, PublicKeyToken=null + + + $this + + 1 + + 382, 392 + + + 17, 56 + + + 176, 23 + + + 31 + + + 10% + + + progressBarCD + + + ProgressODoom.ProgressBarEx, ProgressODoom, Version=1.0.3711.31206, Culture=neutral, PublicKeyToken=null + + + $this + + + 2 + True + + 50 + 6, 13 - 505, 465 + 571, 481 - AAABAAEAEBAAAAAACABoBQAAFgAAACgAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAAB - AAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAwMDAAMDcwADwyqYABAQEAAgICAAMDAwAERERABYW - FgAcHBwAIiIiACkpKQBVVVUATU1NAEJCQgA5OTkAgHz/AFBQ/wCTANYA/+zMAMbW7wDW5+cAkKmtAAAA - MwAAAGYAAACZAAAAzAAAMwAAADMzAAAzZgAAM5kAADPMAAAz/wAAZgAAAGYzAABmZgAAZpkAAGbMAABm - /wAAmQAAAJkzAACZZgAAmZkAAJnMAACZ/wAAzAAAAMwzAADMZgAAzJkAAMzMAADM/wAA/2YAAP+ZAAD/ - zAAzAAAAMwAzADMAZgAzAJkAMwDMADMA/wAzMwAAMzMzADMzZgAzM5kAMzPMADMz/wAzZgAAM2YzADNm - ZgAzZpkAM2bMADNm/wAzmQAAM5kzADOZZgAzmZkAM5nMADOZ/wAzzAAAM8wzADPMZgAzzJkAM8zMADPM - /wAz/zMAM/9mADP/mQAz/8wAM///AGYAAABmADMAZgBmAGYAmQBmAMwAZgD/AGYzAABmMzMAZjNmAGYz - mQBmM8wAZjP/AGZmAABmZjMAZmZmAGZmmQBmZswAZpkAAGaZMwBmmWYAZpmZAGaZzABmmf8AZswAAGbM - MwBmzJkAZszMAGbM/wBm/wAAZv8zAGb/mQBm/8wAzAD/AP8AzACZmQAAmTOZAJkAmQCZAMwAmQAAAJkz - MwCZAGYAmTPMAJkA/wCZZgAAmWYzAJkzZgCZZpkAmWbMAJkz/wCZmTMAmZlmAJmZmQCZmcwAmZn/AJnM - AACZzDMAZsxmAJnMmQCZzMwAmcz/AJn/AACZ/zMAmcxmAJn/mQCZ/8wAmf//AMwAAACZADMAzABmAMwA - mQDMAMwAmTMAAMwzMwDMM2YAzDOZAMwzzADMM/8AzGYAAMxmMwCZZmYAzGaZAMxmzACZZv8AzJkAAMyZ - MwDMmWYAzJmZAMyZzADMmf8AzMwAAMzMMwDMzGYAzMyZAMzMzADMzP8AzP8AAMz/MwCZ/2YAzP+ZAMz/ - zADM//8AzAAzAP8AZgD/AJkAzDMAAP8zMwD/M2YA/zOZAP8zzAD/M/8A/2YAAP9mMwDMZmYA/2aZAP9m - zADMZv8A/5kAAP+ZMwD/mWYA/5mZAP+ZzAD/mf8A/8wAAP/MMwD/zGYA/8yZAP/MzAD/zP8A//8zAMz/ - ZgD//5kA///MAGZm/wBm/2YAZv//AP9mZgD/Zv8A//9mACEApQBfX18Ad3d3AIaGhgCWlpYAy8vLALKy - sgDX19cA3d3dAOPj4wDq6uoA8fHxAPj4+ADw+/8ApKCgAICAgAAAAP8AAP8AAAD//wD/AAAA/wD/AP// - AAD///8ACgoKCgrr6+vr6+sKCgoKCgoKCu/r7/Pz8/Pv6+8KCgoKCuvr7/Pz8/Pz8+/r6woKCu/r8/Pz - 8/Pz8/Pz8+vvCu/r8/Pz8/Pz8/Pz8/Pz6+/r7/Pz8/Pz8/Pz8/Pz8+/r6/PrCgrz6woK6/MKCgrz6+vz - CvPz8wrz8wrzCvPz8+vr8wrz8/MK8/MK8woK8/Pr6/MK8/PzCvPzCvMK8/Pz6+vv6woK8wrz8wrzCgoK - 7+vv6/Pz8/Pz8/Pz8/Pz8+vvCu/r8/Pz8/Pz8/Pz8+vvCgoK6+vv8/Pz8/Pz7+vrCgoKCgrv6+/z8/Pz - 7+vvCgoKCgoKCu/r6+vr6+vvCgoKCvgfAADgBwAAwAMAAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAIABAADAAwAA4AcAAPAPAAA= + AAABAAgAICAQAAEABADoAgAAhgAAABAQEAABAAQAKAEAAG4DAAAwMAAAAQAIAKgOAACWBAAAICAAAAEA + CACoCAAAPhMAABAQAAABAAgAaAUAAOYbAAAwMAAAAQAgAKglAABOIQAAICAAAAEAIACoEAAA9kYAABAQ + AAABACAAaAQAAJ5XAAAoAAAAIAAAAEAAAAABAAQAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA + AAAAgAAAgIAAAAAAgACAAIAAAICAAMDAwACAgIAA/wAAAAD/AAD//wAAAAD/AP8A/wAA//8A////AAAA + AAAAAAAAAAAAAAAAAAAAAAAAAIiHfu6gAAAAAAAAAAAAAIh3d3fuqngAAAAAAAAAAAh3d3d+7qp7uwAA + AAAAAACPd3d3d+qnu7twAAAAAAAI9/d3d37qp7u3dwAAAAAACI9/d3d36nu7d3cAAAAAAIh49/d3fup7 + t3d3cAAAAACHh49/d3fnu3d3d3AAAAAIeHh49/eIiLd3d3d3AAAACIeHh494AACHd3d3dwAAAAh4eHh4 + gAAACHd3d3cAAAAIh4eHh4AAAAh3d3d3AAAACHd3d3eAAAAId3d3dwAAAAh3d3d7gAAACIeHh4cAAAAI + d3d3t3gAAI/4eHh4AAAACHd3e3eqiIh/f4eHhwAAAACHe7d6q+53d/f4eHAAAAAAi7t3qrvud3d/f4eA + AAAAAAi3eqq77nd3d/f4AAAAAAAId6qru+53d3d/fwAAAAAAAIqqq7vud3d3d/AAAAAAAAAIqru+7nd3 + d3cAAAAAAAAAAIiLvu53d3cAAAAAAAAAAAAAiI7ud3AAAAAAAAAAAAAAAAAIiIiAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//Af///AA///AAD//gAAf/wAAD/4AAAf+AAAH/AA + AA/wAAAP4AAAB+AAAAfgA8AH4APAB+ADwAfgA8AH4AAAB+AAAAfwAAAP8AAAD/gAAB/4AAAf/AAAP/4A + AH//AAD//8AD///4H/////////////////////////////////8oAAAAEAAAACAAAAABAAQAAAAAAIAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAgAAAgIAAAAAAgACAAIAAAICAAMDAwACAgIAA/wAAAAD/ + AAD//wAAAAD/AP8A/wAA//8A////AAAAAAAAAAAAAAAAiAAAAAAAAIh3eqAAAAAId3d6ruAAAI93d3ru + uwAAh/d3euu3AAh3f3f663dwCHd3+Ai3d3AId3eg8Hd3cAh3ergId3dwCHeqvnf3d3AAiqvud393AACK + u+53d/cAAAi+7nd3cAAAAIjud3AAAAAAAIiIgAAA//8AAPwfAADwBwAA4AMAAMABAADAAQAAgAAAAIAA + AACAAAAAgAAAAIAAAADAAQAAwAEAAOADAADwBwAA/B8AACgAAAAwAAAAYAAAAAEACAAAAAAAAAkAAAAA + AAAAAAAAAAAAAAAAAAAAAAAASkpKAE1NTQBOTk4AUVFRAFNTUwBUVFQAVlZWAFlZWQBbW1sAXV1dAF5e + XgBhYWEAY2NjAGVlZQBmZmYAaGhoAGtrawBtbW0Ab29vAHBtbQBwbm4AcHBwAHNzcwB0dHQAd3d3AHlz + cwB5dXUAeXd3AHl5eQB8fHwAf39/AIN5eQCDf38AgICAAIOBgQCDg4MAhISEAIeHhwCMgIAAjIKCAIyE + hACIiIgAjIiIAIyMjACOjo4AloeHAJaJiQCWjIwAlo6OAJ+NjQCfj48AlpaWAJ+UlACfnJwAn5+fAKmT + kwCplpYAqZiYALOZmQCznZ0AqaOjAKmlpQCpqKgAs6GhALOjowCzpqYAvKGhALylpQC8qKgAvKurALyt + rQC8r68As7OzALy8vADGp6cAxqioAMaqqgDGrKwAxq+vAM+srADGsLAAxrS0AMa5uQDGu7sAxr+/ANmz + swDZtbUA2be3AOy/vwDGwsIAxsbGAM/CwgDPyckA2cjIANnZ2QDd3d0A4s7OAOzKygD1xsYA9c3NAP/M + zAD/zs4A7NLSAOzW1gDs2dkA7NzcAPXR0QD11dUA9dfXAP/Q0AD/0NMA/9PTAP/T1QD/1dUA/9XXAP/W + 1gD/0NoA/9PaAP/X2AD/19sA9draAP/Z2QD/2toA/9ndAP/a3gD/3d0A/9/fAP/W4QD/3eMA/97iAP/c + 5QD/1eoA/9bvAP/Z6QD/2+0A/9ztAP/f7QD/z/QA/87/AP/Q8gD/1PAA/9XzAP/Q9QD/0fYA/9nyAP/e + 8wD/3vcA/9X/AP/b/wD/3f8A4uLiAOzi4gDs5+cA/+HhAP/i4gD/5eUA/+fnAP/k6AD/4O8A9e7uAP/p + 6QD/6+sA/+ntAP/t7QD/7+8A/+TxAP/l9AD/6PUA/+/0AP/h/wD/5P8A/+75AP/p/AD/6/wA/+j/AP/r + /wD/7f8A/+7/APX19QD/8PAA//LyAP/09AD/9/cA//H8AP/x/wD/8v8A//T/AP/5+QD/+/sA//v/AP/8 + /AD//f8A////AElJSQBwoVQDdQz/dQO18T0gN+/G/3UQ//////9xx//FyeA4ALl5N57yma+ama+a8pry + ma8gAAAAr5rymcngOAAkCqgAHIM7AAwKqACx4DgAGAAAAAEAAADyma+ama+a8q+a8pma8pmv8pmvmpmv + mvKa8pmvr5rymYYAAACGAAAADAuoAIgKqACH4TgAwGs+AIYAAAAMC6gAhgAAAAAANgAAADYAAAA2AET/ + YQFE/2EBRP9hAUT/YQEw/2EBzP5hAcz+YQEw/2EBqGI+ACAjOACoYD4AAQAAAK+a8pmsCqgAvD1NACQG + AABwoVQDhgAAALgKqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4eHh4eHh4eHh4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAkCwoLCwsLCwsKBwYECRkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAsP + Dw8PISsrKyEPDw8PCwUEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIODxU1UmidoaKkpLS1mFU2 + Ew8NBQMRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiDg8bUW1/mpycnaGipKS0tba2oFosDw0EBSYAAAAA + AAAAAAAAAAAAAAAAAAAAABIPGk56e35+f5qcnJ2hoqSktLW2trzBXyQPCgEWAAAAAAAAAAAAAAAAAAAA + AAAAEA8yZHJ3ent+fn+anJydoaKkpLS1tsDBwcFJDw3CEgAAAAAAAAAAAAAAAAAAAAAPD0tubnByd3p7 + fn5/mpycnaGipKS0tsHBwcHBXxYNwhIAAAAAAAAAAAAAAAAAABAUVmVmbm5wcnd6e35+f5qcnJ2hoqSk + vcHBwcHBwZcWDcIWAAAAAAAAAAAAAAAAEw9XZmVlZm5ucHJ3ent+fn+anJydoaKlwcHBwcHBwcGXFg0B + JgAAAAAAAAAAAAAlD01wbmZlZWZubnByd3p7fn5/mpycnaG3wcHBwcHBwcHBXw8KBQAAAAAAAAAAAAAP + L3JwcG5mZWVmbm5wcnd6e35+f5qcnKHAwcHBwcHBwcHBwUkPBBEAAAAAAAAAABYUa3RycHBuZmVlZm5u + cHJ3ent+fn+anLXBwcHBwcHBwcHBwcEkDQMAAAAAAAAAAA9Pe3d0cnBwbmZlZWZubnByd3p7fn5/mr/B + wcHBwcHBwcHBwcFfDwUQAAAAAAAAFht+e3t3dHJwcG5mZWVmbm5wcnd6e35+osHBwcHBwcHBwcHBwcHB + LA0EAAAAAAAAD0Z/fnt7d3RycHBuZmVlZm52hIyPjoeBt8HBwcHBwcHBwcHBwcG/XA8FHwAAAAAAD3ma + f357e3d0cnBwbmZlb5KWlIuLlJWqscDBwcHBwcHBwcHBtn9mZRoKCgAAAAASMZubmn9+e3t3dHJwcG5z + rauWlIuKlJWqr7LAwcHBwcHBv6J0ZWVlZTgPBQAAAAAPSJybm5p/fnt7d3RycHe4sKuRdW5ucIOvr7K7 + wMHBwbV/ZmVlZWVlZVAPBQAAAAAPXp2cm5uaf357e3d0cqm6sIhlUC4nJ1TBubK7vr+hcGVlZWVlZWVl + ZWMPCC0AAAAPoZ2dnJubmn9+e3t3e766p24yDxAiEw83wbq7vnBlZWVlZWVlZWVlZWUUCR8AACYPoqGd + nZybm5p/fnt7or66fVgPDAAAACwPU4K7vptlZWVlZWVlZWVlZWUnCx4AACYcpKKhnZ2cm5uaf357tb66 + cjMPCAAAAAAPLmW7vqJlZWVlZWVlZWVlZWUnCx4AACYocnFxcHBwcHBubm5utb6sZjgPBQAAAAAiJ2a7 + vrZwcHFydHR3enp7e34pCx4AACoUZWVlZWVlZWVlZWVlor66ZTsPARkAAAAPMm67vrR3ent+fn+anJyd + oaIrCyIAACoPZWVlZWVlZWVlZWVlm766gWoWCwIFCQ0PVny7vp1yd3p7fn5/mpycnaEVCyIAACoPY2Vl + ZWVlZWVlZWVldL66ssFbFg8PDw9LZai7vndwcnd6e35+f5qcnJ0PCSIAACoPVmVlZWVlZWVlZXqiwb66 + sLLBmTooOVhuibK7o25ucHJ3ent+fn+anGEPCQAAAAAPO2VlZWVlZWabvMHBwcG6sKurpnd0coCTr7K4 + ZmZubnByd3p7fn5/mkcPDAAAAAATIGVlZWV6osHBwcHBwcG+sKuWlIuLlJWqr65zZWVmbm5wcnd6e35+ + fzAPIgAAAAAqD1lmm7zBwcHBwcHBwcHBwLKWlIuLlJWqn3FuZmVlZm5ucHJ3ent+bQ8MAAAAAAAADz3B + wcHBwcHBwcHBwcHBwcGeh42QhYZ4cnBwbmZlZWZubnByd3p7RQ8TAAAAAAAAHRazwcHBwcHBwcHBwcHB + wbebmn9+e3t3dHJwcG5mZWVmbm5wcnd6Gw0AAAAAAAAAKg9JwcHBwcHBwcHBwcHBwaSbm5p/fnt7d3Ry + cHBuZmVlZm5ucHJEDxYAAAAAAAAAAB0Pl8HBwcHBwcHBwcHBv52cm5uaf357e3d0cnBwbmZlZWZubmQU + DwAAAAAAAAAAAAAPJMHBwcHBwcHBwcHBtZ2dnJubmn9+e3t3dHJwcG5mZWVmbi4PLQAAAAAAAAAAAAAq + DzfBwcHBwcHBwcHAoqGdnZybm5p/fnt7d3RycHBuZmVlQw8WAAAAAAAAAAAAAAAAJA9KwcHBwcHBwcG8 + pKKhnZ2cm5uaf357e3d0cnBwbmZLDxEAAAAAAAAAAAAAAAAAACMPSsHBwcHBwcG1paSioZ2dnJubmn9+ + e3t3dHJwcEwPEQAAAAAAAAAAAAAAAAAAAAAjDzfBwcHBwb+1tKWkoqGdnZybm5p/fnt7d3RyPA8RAAAA + AAAAAAAAAAAAAAAAAAAAJA8kl8HBwby2tbSlpKKhnZ2cm5uaf357e2IoDxYAAAAAAAAAAAAAAAAAAAAA + AAAAACoPD0mzwLe3trW0paSioZ2dnJubmn9sQBQPLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHQ8WP5m3 + t7a1tKWkoqGdnZybZ0EVDxgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdDw8jPl2YtbSlpKJpXkIh + Dw8WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYZDw8PDw8PDw8PDw8XNAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYmJiomJiYmJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////AAD//+AH//8AAP// + gAD//wAA//4AAD//AAD/+AAAD/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAP8AAP8AAAAAfwAA/gAAAAA/ + AAD8AAAAAB8AAPgAAAAAHwAA+AAAAAAPAADwAAAAAA8AAPAAAAAABwAA4AAAAAAHAADgAAAAAAMAAOAA + AAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAAAQAAwAAAAAABAACAAAOAAAEAAIAAA8AAAQAAgAADwAAB + AACAAAHAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAcAAOAA + AAAABwAA4AAAAAAPAADgAAAAAA8AAPAAAAAAHwAA+AAAAAAfAAD4AAAAAD8AAPwAAAAAfwAA/gAAAAD/ + AAD/AAAAAf8AAP+AAAAD/wAA/8AAAAf/AAD/8AAAH/8AAP/8AAB//wAA//8AAf//AAD//+AP//8AAP// + /////wAAKAAAACAAAABAAAAAAQAIAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOTk4AUFBQAFFR + UQBTU1MAVFRUAFVVVQBWVlYAV1dXAFhYWABbW1sAXV1dAF5eXgBfX18AYWFhAGJiYgBjY2MAZGRkAGVl + ZQBmZmYAampqAGtrawBvb28AcGxsAHBtbQBwbm4AcG9vAHBwcABzc3MAdHR0AHV1dQB5c3MAeXR0AHl1 + dQB5eXkAenp6AH5+fgCDenoAgICAAIGBgQCCgoIAg4ODAIeHhwCMgIAAjIGBAIyCggCMhoYAiIiIAIqK + igCMiooAjIyMAJaNjQCWjo4AkZGRAJ+VlQCfnJwAqZOTALOZmQCznJwAs5+fALyfnwCpqakAs6enALyj + owC8pqYAs6ysALOtrQC8rq4As7CwALOysgC8tbUAxqamAMapqQDGr68Az6ysAMaysgDPsLAA2bOzAOK6 + ugDiu7sA4r+/AM/CwgDPxsYAz8fHAM/MzADPz88A2cbGANnIyADZysoA2czMANnOzgDZz88A3d3dAPXG + xgD/zMwA/87OAP/PzwD/0NAA/9HRAP/R0wD/0tIA/9PTAP/V1QD/1tYA/9DfAP/W3AD/19wA9draAP/Z + 2QD/29sA/9jcAP/Y3QD/2twA/9vfAP/c3AD/3d0A/97eAP/f3wD/0+AA/9ThAP/W4QD/1OUA/9TnAP/Y + 4QD/3OAA/9rlAP/b5gD/0usA/9TsAP/W7AD/1+0A/9buAP/d6gD/zv8A/9rxAP/f9AD/0v8A/9f/AP/f + /AD/3P8A4uLiAOzs7AD/4OAA/+HhAP/i4gD/4+MA/+TkAP/l5QD/5uYA/+fnAP/k7AD/5O4A9e/vAP/o + 6AD/6ekA/+vrAP/s7AD/7e0A/+7uAP/v7wD/6PIA/+nyAP/v8QD/4voA/+P6AP/g/wD/5P8A/+b/AP/n + /wD/7f8A/+//APX19QD/8PAA//HxAP/y8gD/8/MA//X1AP/29gD/9/cA//X5AP/0/AD/9P8A//b/AP/3 + /wD/+PgA//r6AP/7+wD/+f8A//v/AP/8/AD//f8A//7+AP///wBGRkYASUlJAHChVAN1DP91A7XxPSA3 + 78b/dRD//////3HH/8XJ4DgAuXk3nvKZr5qZr5rymvKZryAAAACvmvKZyeA4ACQKqAAcgzsADAqoALHg + OAAYAAAAAQAAAPKZr5qZr5ryr5rymZryma/yma+ama+a8pryma+vmvKZhgAAAIYAAAAMC6gAiAqoAIfh + OADAaz4AhgAAAAwLqACGAAAAAAA2AAAANgAAADYARP9hAUT/YQFE/2EBRP9hATD/YQHM/mEBzP5hATD/ + YQGoYj4AICM4AKhgPgABAAAAr5rymawKqAC8PU0AJAYAAHChVAOGAAAAuAqoAAAAAAAAAAAAAAAAAAAA + AAAAKBsRwcERGygAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGw0NDBMTCwwHBAYbAAAAAAAAAAAAAAAAAAAA + AAAAGxAZNkNXWFlaRjcaDgUCHAAAAAAAAAAAAAAAAAAAKBMgSXSOkZSZnJ6tr7FUMg4BCgAAAAAAAAAA + AAAAACYYP2dsbXSOkZSZnJ6tr7/AVRsGBCgAAAAAAAAAAAAkF05hZWdsbXSOkZSZnJ6wwMDAjSkIBCgA + AAAAAAAAKBhPXl9hZWdsbXSOkZSZnLrAwMDAqykGCgAAAAAAAAATUGJfXl9hZWdsbXSOkZSdwMDAwMDA + jRsBHAAAAAAAG0BmZWJfXl9hZWdsbXSOkbDAwMDAwMDAVQ4CKAAAAAAhbWxmZWJfXl9hZWdsbXSSwMDA + wMDAwMDAMgUbAAAAIktzbWxmZWJfXl9jd3+BfqLAwMDAwMDAwMBbDgcAAAAZa45zbWxmZWJfaYqJhYiL + qLvAwMDAwL2aZF4fAygAADSTkI5zbWxmZXyppYBodoenqr7AwJ91Xl5eXjgHGwAoPpWTkI5zbWxmtKl4 + OR8lRLeqvJRkXl5eXl5eRwwUACpYmpWTkI5zbZO2l0gSNQAWQaG8cl5eXl5eXl5NDBQAKlaRkI50c21s + m7Z8LAkAAAArbryUXl5eXl5eXk0MFAAqTV5eXl5eXl6UtmorAhEANStxvJtsbXSOkZSZWAwVAC9KXl5e + Xl5eXnK2oFIQAgkSPJa8j2dsbXSOkZRXDCIAKjleXl5eXl5kmreptVUtLUx7qrNhZWdsbXSOkUMMKAAq + K15eXmB1rsDAvKmlo3p5hqeqcF9hZWdsbXSOMwwAAAATXWecvcDAwMDAu6aJhYiLpG9fXl9hZWdsbXQZ + HgAAACdBwMDAwMDAwMDAuISDgn1mZWJfXl9hZWdsSQ8AAAAAABurwMDAwMDAwMCekI5zbWxmZWJfXl9h + ZWcgHQAAAAAAKD3AwMDAwMDAvZWTkI5zbWxmZWJfXl9hOhIAAAAAAAAAE1XAwMDAwMCwmpWTkI5zbWxm + ZWJfXk4TKAAAAAAAAAAAG4zAwMDAwKybmpWTkI5zbWxmZWJPFzAAAAAAAAAAAAAoG1XAwMC5rZ+bmpWT + kI5zbWxmUBgvAAAAAAAAAAAAAAAAEz2rwLKvrZ+bmpWTkI5zbTsTKAAAAAAAAAAAAAAAAAAAKBtFmLGv + rZ+bmpWTa0shHQAAAAAAAAAAAAAAAAAAAAAAACcTMUJTWllRPi4TIwAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAKC8qKioqKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//gH///g + Af//gAB//gAAP/wAAA/4AAAH8AAAB/AAAAPgAAAB4AAAAcAAAAHAAAAAwAAAAIAAAACAAIAAgAHAAIAA + gACAAAAAgAAAAIAAAAHAAAABwAAAA+AAAAPgAAAH8AAAB/gAAA/4AAAf/gAAP/8AAP//wAP///gP//// + //8oAAAAEAAAACAAAAABAAgAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJSUgBTU1MAW1tbAF5e + XgBlZWUAaWFhAGlpaQBraWkAa2trAG1sbABtbW0AcGtrAHNvbwB2dnYAfHV1AHx2dgB5eXkAe3t7AH19 + fQCAcXEAgnd3AIV7ewCGhoYAiIODAIiIiACMiYkAjoqKAI2NjQCUjIwAlI+PAJ6MjACcj48AlpaWAJ2X + lwCYmJgAm5iYAJ2dnQCmlJQApJ+fALOeowCioaEApqSkAKampgCvqKwAs6CjALOpqQDMmZkAxq2tANWi + ogDWrKwA26ioAMaxsQDPtLQAw7+/ANy5uQDjsLAA6re3AOa6ugDmvb0A6b6+AMW8wgDGxsYAz8/PANLM + zADd3d0A5sDAAOfExADvwsIA7MrKAPPFxQD1x8cA883NAPXNzQD/zc0A/8/PAO/f3wD/0tIA+dbWAP/U + 1AD/1NsA/9jYAP/Z2QD/2d4A/93dAP/e3gD/1+IA/9vnAP/e5wD/0fMA/9L1AP/a/AD/3v8A9+fnAP/g + 4AD/4uIA/+PjAP/g5wD/5+cA/+TqAP/o6AD56OwA/+zsAP/u7gD/6fMA/+zxAP/i/AD/7vwA/+/8APX1 + 9QD/8vIA//PzAP/09AD/9/cA/PD5AP/0/AD/9v8A//j4AP/6+gD/+P8A//7+AP///wBMTEwA/9jhAP/c + 4AD/2uUA/9vmAP/S6wD/1OwA/9bsAP/X7QD/1u4A/93qAP/O/wD/2vEA/9/0AP/S/wD/1/8A/9/8AP/c + /wDi4uIA7OzsAP/g4AD/4eEA/+LiAP/j4wD/5OQA/+XlAP/m5gD/5+cA/+TsAP/k7gD17+8A/+joAP/p + 6QD/6+sA/+zsAP/t7QD/7u4A/+/vAP/o8gD/6fIA/+/xAP/i+gD/4/oA/+D/AP/k/wD/5v8A/+f/AP/t + /wD/7/8A9fX1AP/w8AD/8fEA//LyAP/z8wD/9fUA//b2AP/39wD/9fkA//T8AP/0/wD/9v8A//f/AP/4 + +AD/+voA//v7AP/5/wD/+/8A//z8AP/9/wD//v4A////AEZGRgBJSUkAcKFUA3UM/3UDtfE9IDfvxv91 + EP//////ccf/xcngOAC5eTee8pmvmpmvmvKa8pmvIAAAAK+a8pnJ4DgAJAqoAByDOwAMCqgAseA4ABgA + AAABAAAA8pmvmpmvmvKvmvKZmvKZr/KZr5qZr5rymvKZr6+a8pmGAAAAhgAAAAwLqACICqgAh+E4AMBr + PgCGAAAADAuoAIYAAAAAADYAAAA2AAAANgBE/2EBRP9hAUT/YQFE/2EBMP9hAcz+YQHM/mEBMP9hAahi + PgAgIzgAqGA+AAEAAACvmvKZrAqoALw9TQAkBgAAcKFUA4YAAAC4CqgAAAAAAAAAAAAAFxcFAwUTEwAA + AAAAAAAADg0dLh4KAQITAAAAAAAADzVUX2Rnbz8SegsAAAAAFkdNUVRfZHB5bSV6EwAAGElLSk1RVF92 + eXltEgIAIzRST0tKUFZjeXl5eUABGSNgVVJPWFtZand5TDcvBgkiYmBVXmwoByxyMi8vLxQEHzxERk5o + FXoHZUU6O0ImCSAzODlIaz0MLXNRUVRfGBkkMUNdeXRcWmphSk1RVAgZADZ5eXl5aVdTT0tKTTARAAAh + bXl5eGJgVVJPS0cQAAAAABxteXVmYmBVUkkWAAAAAAAAIT5xbmZiYDQbAAAAAAAAAAAAKyoaJykAAAAA + AAD4DwAA8AcAAOADAADAAQAAgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIABAACAAwAAwAcAAOAP + AAD4PwAAKAAAADAAAABgAAAAAQAgAAAAAACAJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAEAAAAGAAAADAAAABAAAAASAAAAEgAAABIAAAASAAAAEgAAABAAAAAMAAAABwAAAAEAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAJAAAAEgAAACQAAAA9AAAAXgAAAHcAAACCAAAAgwAAAIMAAACDAAAAggAAAHcAAABgAAAAQwAA + ACUAAAAVAAAACgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAABAAAADAAAAB8AAABMDAwMgiMjI7k9PT3WTU1N51JSUu1SUlLtUlJS7VJSUu1SUlLtTU1N6Ts7 + O9woKCjLCQkJtAAAAKQAAACIAAAAVwAAACcAAAANAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAkAAAAnAAAAYDQ0NL1OTk7mZmZm/2ZmZv9mZmb/ZmZm/4N/f/+MiIj/jIiI/4yJ + if+DgID/ZmZm/2ZmZv9mZmb/ZmZm/1dXV/M1NTXZCQkJtQAAAJcAAABgAAAAKAAAAAwAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAABAAAAGBMTE1ZCQkLGYmJi+mZmZv9wbm7/n5SU/8a0tP/s1tb//+fn///p + 6f//6+v//+3t///u7v//8PD///Ly/+zi4v/Gv7//n5yc/3Bvb/9mZmb/YWFh+zo6Ot8JCQm3AAAAlQAA + AFgAAAAcAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAqMzMzn11dXfRmZmb/eXV1/8awsP/119f//+Dg///h + 4f//5OT//+bm///n5///6en//+vr///t7f//7u7///Dw///y8v//9PT///X1//Xu7v/GwsL/jIyM/2Zm + Zv9hYWH7NDQ02wAAAKwAAAB5AAAALgAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxgYGENTU1PYZmZm/3l0dP/GrKz//9nZ///a + 2v//3Nz//97e///g4P//4eH//+Tk///m5v//5+f//+np///r6///7e3//+7u///w8P//8vL///T0///1 + 9f//+vr//////9nZ2f+Dg4P/ZmZm/1JSUu8JCQm8AAAAjwAAAD8AAAAJAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGJiYmV1paWupmZmb/n46O//XN + zf//1dX//9fX///Z2f//2tr//9zc///e3v//4OD//+Hh///k5P//5ub//+fn///p6f//6+v//+3t///u + 7v//8PD///Ly///09P///v7/////////////////s7Oz/2ZmZv9hYWH7GBgYyQAAAJIAAAA/AAAACQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM4ODhXYmJi+GZm + Zv/Gp6f//9DQ///R0f//09P//9XV///X1///2dn//9ra///c3P//3t7//+Dg///h4f//5OT//+bm///n + 5///6en//+vr///t7f//7u7///Dw///19f///////////////////////////9nZ2f9wcHD/YWFh+xgY + GMkAAACSAAAAPwAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAR8f + HzVjY2P3cG1t/9mzs///zMz//87O///Q0P//0dH//9PT///V1f//19f//9nZ///a2v//3Nz//97e///g + 4P//4eH//+Tk///m5v//5+f//+np///r6///7e3//+7u///7+/////////////////////////////// + ///i4uL/cHBw/2FhYfsYGBjJAAAAjwAAAC4AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAALCwsJV1dXeRmZmb/2bW1///Ozv//zMz//8zM///Ozv//0ND//9HR///T0///1dX//9fX///Z + 2f//2tr//9zc///e3v//4OD//+Hh///k5P//5ub//+fn///p6f//6+v//+/v//////////////////// + ////////////////////////4uLi/3BwcP9hYWH7CQkJvAAAAHkAAAAcAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAHV1dXu2ZmZv/Gqqr//9LS///Q0P//zs7//8zM///MzP//zs7//9DQ///R + 0f//09P//9XV///X1///2dn//9ra///c3P//3t7//+Dg///h4f//5OT//+bm///n5///6en///f3//// + /////////////////////////////////////////////9nZ2f9mZmb/UlJS7wAAAKwAAABYAAAADAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRUVFlZmZm/5aJif//1dX//9PT///S0v//0ND//87O///M + zP//zMz//87O///Q0P//0dH//9PT///V1f//19f//9nZ///a2v//3Nz//97e///g4P//4eH//+Tk///m + 5v//6en///7+//////////////////////////////////////////////////////+zs7P/ZmZm/zQ0 + NNsAAACVAAAAKAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAliYmLpcG1t//XR0f//1tb//9XV///T + 0///0tL//9DQ///Ozv//zMz//8zM///Ozv//0ND//9HR///T0///1dX//9fX///Z2f//2tr//9zc///e + 3v//4OD//+Hh///k5P//8vL///////////////////////////////////////////////////////// + ////////g4OD/2FhYfsJCQm3AAAAYAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAAAFdXV3FmZmb/xq+v///a + 2v//2Nj//9bW///V1f//09P//9LS///Q0P//zs7//8zM///MzP//zs7//9DQ///R0f//09P//9XV///X + 1///2dn//9ra///c3P//3t7//+Dg///h4f///Pz///////////////////////////////////////// + ////////////////////////2dnZ/2ZmZv86OjrfAAAAlwAAACUAAAABAAAAAAAAAAAAAAAAAAAAB2Ji + Yuh5dXX//93d///b2///2tr//9jY///W1v//1dX//9PT///S0v//0ND//87O///MzP//zMz//87O///Q + 0P//0dH//9PT///V1f//19f//9nZ///a2v//3Nz//97e///r6/////////////////////////////// + /////////////////////////////////////////////4yMjP9hYWH7CQkJtAAAAE8AAAAJAAAAAAAA + AAAAAAAAW1tbWmZmZv+8q6v//9/f///d3f//29v//9ra///Y2P//1tb//9XV///T0///0tL//9DQ///O + zv//zMz//8zM///Ozv//0ND//9Pa///V6v//0PL//9D1///V8///2+3//93j///39/////////////// + //////////////////////////////////////////////////////////z8/8/Cwv9mZmb/Li4u0wAA + AIAAAAATAAAAAAAAAAAAAAAAYGBgqWZmZv/12tr//+Hh///f3///3d3//9vb///a2v//2Nj//9bW///V + 1f//09P//9LS///Q0P//zs7//8zM///Q0///3vP//93////V////zv///87////U////2////+H////t + /////f/////////////////////////////////////////////////////////19f//39///8/P///M + zP95c3P/UlJS7wAAAKMAAAAkAAAAAQAAAAAAAAAEZWVl8paOjv//4+P//+Li///h4f//39///93d///b + 2///2tr//9jY///W1v//1dX//9PT///S0v//0ND//9TX///p/P//5P///93////V////zv///8/0///U + ////2////+H////o////7v////3////////////////////////////////////8/P//7Oz//9bW///M + zP//zMz//8zM///MzP+pk5P/ZmZm/wkJCbIAAAA9AAAABgAAAABYWFg4ZmZm/7yvr///5eX//+Pj///i + 4v//4eH//9/f///d3f//29v//9ra///Y2P//1tb//9XV///T0///19j///D8///r////5P///9ny///Q + 2v//0ND//9HR///T0///3OX//+n////o////7v////T////+////////////////////8vL//9/f///P + z///zMz//8zM///MzP//zMz//8zM///MzP/PrKz/ZmZm/yEhIcYAAABdAAAADAAAAABgYGB3ZmZm/9nI + yP//5+f//+Xl///j4///4uL//+Hh///f3///3d3//9vb///a2v//2Nj//9bW///V1f//7/T///L////r + ////3O3//8zM/8+srP+Wh4f/jIGB/4yBgf/Gu7v////////x////7v////T////7/////Pz//+np///S + 0v//zMz//8zM///MzP//zMz//8zM///MzP//zMz//8zM///MzP/1xsb/ZmZm/zw8PNsAAABxAAAADwAA + AABfX1+JZmZm///q6v//6Oj//+fn///l5f//4+P//+Li///h4f//39///93d///b2///2tr//9jY///b + 2///+v////L////l9P//0ND/n42N/2ZmZv9jY2P2YGBgymZmZvBmZmb/n5+f////////8v////T////7 + ////0tL//8zM///MzP//zMz//8zM///MzP//zMz//8zM///MzP//zMz//8zM///MzP//zMz/cGxs/0dH + R+UAAACAAAAAEgAAAABjY2PEZmZm///r6///6ur//+jo///n5///5eX//+Pj///i4v//4eH//9/f///d + 3f//29v//9ra///s7P//+v////L////a3v/Zt7f/ZmZm/05OTuQcHBw7AAAAA2ZmZhBmZmbAZmZm/8a5 + uf//3uL///T////7////4uL//8zM///MzP//zMz//8zM///MzP//zMz//8zM///MzP//zMz//8zM///M + zP//zMz/jICA/1JSUu0AAACDAAAAEgAAAABjY2PEeXd3///t7f//6+v//+rq///o6P//5+f//+Xl///j + 4///4uL//+Hh///f3///3d3//9vb///z8///+v////L////V1f+fj4//ZmZm/woKCq0AAAAeAAAAAAAA + AABmZmYQZmZm/5aGhv//zMz///T////7////7Oz//8zM///MzP//zMz//8zM///MzP//zMz//8zM///M + zP//zMz//8zM///MzP//zMz/jICA/1JSUu0AAACDAAAAEgAAAABjY2PEjIKC///V1f//1NT//9TU///T + 0///09P//9PT///S0v//0tL//9HR///R0f//0dH//9DQ///z8///+v///+75///Ozv+pk5P/ZmZm/wAA + AKwAAAA9AAAACgAAAAAAAAAEYGBgy4yAgP//z8////T////7////9PT//9LS///T0///1NT//9XV///W + 1v//1tb//9jY///Z2f//2dn//9ra///b2///3Nz/jISE/1JSUu0AAACDAAAAEgAAAABkZGTDcGxs///M + zP//zMz//8zM///MzP//zMz//8zM///MzP//zMz//8zM///MzP//zMz//8zM///s7P//+v////L////M + zP+zmZn/ZmZm/xgYGMgAAACIAAAAQwAAACEYGBhEZmZm/5+Njf//0ND///T////7////8PD//9fX///Z + 2f//2tr//9zc///e3v//4OD//+Hh///k5P//5ub//+fn///p6f//6+v/jIiI/1JSUu0AAAB/AAAAEgAA + AABkZGSzZmZm///MzP//zMz//8zM///MzP//zMz//8zM///MzP//zMz//8zM///MzP//zMz//8zM///i + 4v//+v////L////d4v/s3Nz/cHBw/1dXV/MgICDMAAAArRISErJYWFjvZmZm/9mzs///2d3///T////7 + ////5+f//9XV///X1///2dn//9ra///c3P//3t7//+Dg///h4f//5OT//+bm///n5///6en/cG5u/1JS + UuwAAABqAAAADQAAAABjY2OEZmZm//XGxv//zMz//8zM///MzP//zMz//8zM///MzP//zMz//8zM///M + zP//zMz//8zM///W1v//+v////L////v////////xsbG/3BwcP9mZmb/ZmZm/2ZmZv9mZmb/xqen///M + zP//6PX///T////7////19f//9PT///V1f//19f//9nZ///a2v//3Nz//97e///g4P//4eH//+Tk///m + 5v//5+f/ZmZm/0JCQt0AAABVAAAACgAAAABkZGRiZmZm/9mzs///zMz//8zM///MzP//zMz//8zM///M + zP//zMz//8zM///MzP//2dn//+zs////////+/////L////r////7////////+zn5/+pmJj/jIKC/6mW + lv/Zt7f//9DQ///f7f//7v////T////p7f//0ND//9HR///T0///1dX//9fX///Z2f//2tr//9zc///e + 3v//4OD//+Hh///k5P/izs7/ZmZm/zc3N9EAAAA6AAAABgAAAABmZmYwZmZm/7OZmf//zMz//8zM///M + zP//zMz//8zM///MzP//z8///+Li///5+f////////////////////////L////r////5P///+T////k + 8f//2Nj//9bW///V1f//1uH//973///o////7v////H8///Pz///zs7//9DQ///R0f//09P//9XV///X + 1///2dn//9ra///c3P//3t7//+Dg///h4f+8ra3/ZmZm/yQkJLgAAAAeAAAAAAAAAAAAAAAAZmZm8IN5 + ef//zMz//8zM///MzP//zMz//9nZ///s7P////////////////////////////////////////z////s + ////5P///93////V////zv///87////U////2////+H////o////6/z//9XX///MzP//zMz//87O///Q + 0P//0dH//9PT///V1f//19f//9nZ///a2v//3Nz//97e///g4P+WjIz/ZmZm/wAAAHkAAAAQAAAAAAAA + AAAAAAAAZGRkomZmZv/sv7///8/P///i4v//+fn///////////////////////////////////////// + ///////////////+////7v///93////V////zv///87////U////2////+H////g7///09X//9DQ///O + zv//zMz//8zM///Ozv//0ND//9HR///T0///1dX//9fX///Z2f//2tr//9zc//XX1/9mZmb/Tk5O5QAA + AEYAAAAHAAAAAAAAAAAAAAAAZmZmUGZmZv+po6P///////////////////////////////////////// + /////////////////////////////////////////+To///a7f//1PD//9H2///W7///2en//9fb///V + 1f//09P//9LS///Q0P//zs7//8zM///MzP//zs7//9DQ///R0f//09P//9XV///X1///2dn//9ra/7yo + qP9mZmb/Li4usAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAGZmZuBwcHD/9fX1//////////////////// + ////////////////////////b4eF/wArKP8AKyj/ACso/5mqqf//+Pj//+Li/296eP8AKyj/ACso/yRD + Qf//2tr//9jY/yRDQP8AKyj/ACso/wArKP8AKyj/JEI////MzP//zMz//87O///Q0P//0dH//9PT///V + 1f//19f//9nZ/3l1df9dXV31AAAAUQAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAGZmZmBmZmb/s7Oz//// + //////////////////////////////////+Zqqn/JEhG/////////////////wArKP/FwMD//+Pj/yRE + Qv//4eH//9/f/294dv9vd3X//9ra///Y2P9JW1n//9XV///T0///0tL/JEI////Ozv//zMz//8zM///O + zv//0ND//9HR///T0///1dX/vKWl/2ZmZv82Nja1AAAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABmZmbgZmZm/+Li4v////////////////////////////////9JZ2X/xc7O///////////////////8 + /P//5+f/mZqZ/297ef//4uL//+Hh///f3/9JXVv//9vb///a2v9JXFr//9bW/yRDQP//09P//9LS///Q + 0P//zs7//8zM///MzP//zs7//9DQ///R0f/1zc3/cG1t/15eXvMAAABFAAAABgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABmZmZAZmZm/4ODg/////////////////////////////////8kSEb/xc7O//// + ///////////////z8///6Oj/mZua/297ev//4+P//+Li///h4f9JXlz//93d///b2/8kQ0H/ACso/wAr + KP//1dX//9PT///S0v//0ND//87O///MzP//zMz//87O///Q0P+Wh4f/ZmZm/y8vL4wAAAATAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZmZmj2ZmZv+fn5////////////////////////// + //9JZ2X/xc7O//////////////7+///s7P//6ur/mZyb/298e///5eX//+Pj///i4v9JX1z//9/f///d + 3f9JXVv//9ra/yRDQP//1tb//9XV///T0///0tL//9DQ///Ozv//zMz//8zM/7yhof9mZmb/SUlJxwAA + ACEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGZmZs9mZmb/vLy8//// + //////////////////+Zqqn/JEhG////////////b4SC/wArKP/Fv77/mZ2c/299e///5+f//+Xl///j + 4/9JX13//+Hh///f3/9JXVv//9vb///a2v//2Nj/SVtZ///V1f//09P//9LS///Q0P//zs7/xqam/2Zm + Zv9cXFznAAAALQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGZm + ZhBmZmbQZmZm/7y8vP//////////////////////b4eF/wArKP8AKyj/JEdE/0ljYP/FwMD/ACso/wAr + KP8kRUP/mZua/wArKP8AKyj/b3p4/yREQv8AKyj/ACso/wArKP8AKyj/SVxa///W1v//1dX//9PT///S + 0v/GqKj/ZmZm/1xcXOccHBw6AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABmZmYQZmZm0GZmZv+fn5///////////////////////////////Pz///Ly///x + 8f//7+///+3t///r6///6ur//+jo///n5///5eX//+Pj///i4v//4eH//9/f///d3f//29v//9ra///Y + 2P//1tb//9XV/7Odnf9mZmb/XFxc5xwcHDoAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZmZmEGZmZs9mZmb/g4OD/+Li4v////////////// + ////+fn///T0///y8v//8fH//+/v///t7f//6+v//+rq///o6P//5+f//+Xl///j4///4uL//+Hh///f + 3///3d3//9vb///a2v/sysr/jIKC/2ZmZv9eXl7iIyMjLwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmZmaPZmZm/2Zm + Zv+zs7P/9fX1///+/v//9/f///b2///09P//8vL///Hx///v7///7e3//+vr///q6v//6Oj//+fn///l + 5f//4+P//+Li///h4f//39//9dXV/7Ohof9wbW3/ZmZm/1VVVawAAAATAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAZmZmQGZmZuBmZmb/cHBw/6moqP/s5ub///f3///29v//9PT///Ly///x8f//7+///+3t///r + 6///6ur//+jo///n5///5eX//+Pj/+zS0v+zo6P/cG5u/2ZmZv9fX1/eTU1NVQAAAAYAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmZmZgZmZm4GZmZv9mZmb/g4GB/6mlpf/Pycn/7OLi///y + 8v//8fH//+/v///t7f//6+v/7NnZ/9nIyP+zpqb/g35+/2ZmZv9mZmb/YmJi51dXV3EAAAAJAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGZmZkBlZWWhZWVl4WZm + Zv9mZmb/ZmZm/2ZmZv9mZmb/ZmZm/2ZmZv9mZmb/ZmZm/2ZmZv9mZmb/Y2Nj5WBgYKhXV1dLAAAABgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAGZmZjBkZGRiY2NjhGNjY6RkZGTDY2NjxGNjY8RiYmKmYWFhh19fX2dZWVk3AAAABAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//wAH//wAA//8AAD//AAD/+AAAD/8AAP/wAAAH/wAA/8AAAAH/ + AAD/gAAAAP8AAP8AAAAAfwAA/gAAAAA/AAD8AAAAAB8AAPgAAAAADwAA+AAAAAAPAADwAAAAAAcAAPAA + AAAAAwAA4AAAAAADAADgAAAAAAEAAMAAAAAAAQAAwAAAAAABAADAAAAAAAAAAIAAAAAAAAAAgAAAAAAA + AACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAGAAAAAAIAAAIAAAAAAgAAAAAAAAACAAAAAAAAAAIAA + AAAAAAAAgAAAAAAAAACAAAAAAAEAAMAAAAAAAQAAwAAAAAABAADAAAAAAAMAAOAAAAAAAwAA4AAAAAAH + AADwAAAAAAcAAPAAAAAADwAA+AAAAAAfAAD8AAAAAB8AAPwAAAAAPwAA/gAAAAB/AAD/AAAAAP8AAP/A + AAAD/wAA/+AAAAf/AAD/+AAAH/8AAP/+AAB//wAA///AA///AAD///////8AACgAAAAgAAAAQAAAAAEA + IAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAACQAAABkAAAA6AAAAagAAAI8AAACbAAAAuQAAALkAAACbAAAAjwAAAGwAAABCAAAAGwAA + AAwAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAABgAAAB4AAABRHh4eoj4+PtRSUlLsUlJS7WZmZv9mZmb/UlJS71JSUu07OzvcISEhxgAA + AKoAAACPAAAAXgAAACcAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAABAAAABFNjY2tV1dXfVwbm7/n5WV/7yurv/ZyMj/2crK/9nMzP/Zzs7/vLW1/5+c + nP9wb2//XFxc9zs7O94JCQm1AAAAjAAAAEsAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAZMjIyg15eXvN5dHT/xq+v///e3v//4OD//+Pj///m5v//6Oj//+zs///u + 7v//8fH///Pz///29v/PzMz/jIyM/1xcXPcnJyfRAAAApAAAAGUAAAAcAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAGUJCQqxwbW3/vKOj///W1v//2dn//9vb///e3v//4OD//+Pj///m + 5v//6Oj//+zs///u7v//8fH///Pz///+/v//////z8/P/3BwcP9AQEDjAAAArAAAAGsAAAAcAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBUVFTBcGxs/+K6uv//0ND//9PT///W1v//2dn//9vb///e + 3v//4OD//+Pj///m5v//6Oj//+zs///u7v//9fX/////////////////7Ozs/4ODg/9GRkbnAAAArAAA + AGUAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGTExMl3Btbf/iu7v//8zM///Ozv//0ND//9PT///W + 1v//2dn//9vb///e3v//4OD//+Pj///m5v//6Oj//+zs///7+///////////////////////9fX1/4OD + g/9AQEDjAAAApAAAAEsAAAAJAAAAAAAAAAAAAAAAAAAAAExMTFZmZmb/4r+////R0f//zs7//8zM///O + zv//0ND//9PT///W1v//2dn//9vb///e3v//4OD//+Pj///m5v//7e3///////////////////////// + ////////7Ozs/3BwcP8nJyfRAAAAjAAAACcAAAABAAAAAAAAAAAAAAAJYmJi6bympv//1dX//9PT///R + 0f//zs7//8zM///Ozv//0ND//9PT///W1v//2dn//9vb///e3v//4OD//+Pj///19f////////////// + ////////////////////////z8/P/1xcXPcJCQm1AAAAXgAAAAwAAAAAAAAAAFhYWG95dXX//9vb///Z + 2f//1dX//9PT///R0f//zs7//8zM///Ozv//0ND//9PT///W1v//2dn//9vb///e3v//5OT///////// + ////////////////////////////////////////jIyM/zs7O94AAACPAAAAGQAAAAAAAAAEYWFh2cay + sv//3d3//9vb///Z2f//1dX//9PT///R0f//zs7//8zM///Ozv//0dP//9Th///S6///1uz//9vm///v + 8f/////////////////////////////////////////////////Zz8//XFxc9wAAAKkAAAA6AAAAAFhY + WDhwbm7/9dra///g4P//3d3//9vb///Z2f//1dX//9PT///R0f//zs7//9bc///f/P//1////87////S + ////3P///+f////5///////////////////////////////8/P//6en//9LS///MzP95c3P/GRkZwQAA + AGoAAAAAX19feJaOjv//5eX//+Li///g4P//3d3//9vb///Z2f//1dX//9PT///c4P//7f///+D////U + 7P//0N///9Pg///f9P//5v///+/////9///////////////v7///39///8zM///MzP//zMz//8zM/6mT + k/87OzvcAAAAjwAAAABiYmKms6en///n5///5eX//+Li///g4P//3d3//9vb///Z2f//1dX///T8///t + ////1uH/s5mZ/3lzc/+Denr/s7Cw///3////7/////v////m5v//0tL//8zM///MzP//zMz//8zM///M + zP//zMz/xqam/1JSUu0AAACVAAAAAGNjY8TZysr//+np///n5///5eX//+Li///g4P//3d3//9vb///l + 5f//9v///+Tu/8apqf9iYmL6Ojo6jlpaWltmZmbws6ys///p8v//+////9zc///MzP//zMz//8zM///M + zP//zMz//8zM///MzP/Zs7P/UlJS7QAAAJUAAAAAY2NjxNnGxv//4+P//+Li///g4P//3t7//93d///b + 2///2dn//+vr///2////3OD/jIGB/zAwMM4AAABbAAAAElpaWluMgID//9jc///7////5ub//8zM///M + zP//zMz//8zM///MzP//zMz//8zM/9mzs/9SUlLtAAAAlQAAAABjY2PE2bOz///MzP//zMz//8zM///M + zP//zMz//8zM///MzP//5ub///b////X3P+MgID/Li4u1gAAAJsAAABbOjo6joyAgP//29////v////r + 6///2dn//9vb///e3v//4OD//+Pj///m5v//6Oj/2crK/1JSUu0AAACUAAAAAGRkZMPPrKz//8zM///M + zP//zMz//8zM///MzP//zMz//8zM///c3P//9v///+jy/8/Gxv9hYWH7Li4u1jAwMM5iYmL6vJ+f///k + 7P//+////+Hh///W1v//2dn//9vb///e3v//4OD//+Pj///m5v/ZyMj/UlJS7QAAAIYAAAAAZGRko7OZ + mf//zMz//8zM///MzP//zMz/b3Fv/wArKP8AKyj/ACso/5mlqf//7f////T//8/Pz/+MgoL/jIKC/8+w + sP//2OH//+///yRHRf8AKyj/ACso/wArKP8AKyj/JENB///e3v//4OD//+Pj/7yurv9NTU3nAAAAYQAA + AABkZGRyjICA///MzP//zMz//8zM/5mNjP8kREH///Ly////////////ACso/8XAzv//4P///+L6///U + 5///1OX//9rx///m////7////9rc/0lZV///0ND//9PT///W1v8kQ0D//9vb///e3v//4OD/lo2N/zg4 + OM4AAAA5AAAAAGZmZiBmZmb/9cbG///W1v//7Oz/SWZk/8XOzv////////////////////////n////k + //9vdYX/ACso/wArKP8kQ0b//+P6///Y3f//zs7/SVlW///Ozv8kQj///9PT///W1v//2dn//9vb///e + 3v9wbm7/Hx8fnQAAABgAAAAAAAAAAGVlZdGzrKz///////////8kSEb/xc7O//////////////////// + //////////j4/yREQ///1u7//9ft/293ev9vdXP//9PT///R0f8kQj//ACso/wArKP//0ND//9PT///W + 1v//2dn/xq+v/1hYWO8AAABPAAAACQAAAAAAAAAAZmZmYHBwcP/19fX//////0lnZf/Fzs7///////// + //////////////////+ZoJ7/b3p4///g4P//3d3//9vb/0lcWv//1dX//9PT/0laWP//zs7/JEE////O + zv//0ND//9PT///W1v95dHT/Nzc3sQAAABwAAAAAAAAAAAAAAAAAAAAAZmZm0Kmpqf//////maqp/yRI + Rv///////////2+Hhf8AKyj/xczL/5mbmv9ve3r//+Li///g4P//3d3/SV1b///Z2f//1dX/SVtY///R + 0f//zs7//8zM/0lZV///0ND/s5yc/1lZWe0AAAA9AAAABAAAAAAAAAAAAAAAAAAAAABmZmYwZmZm/8/P + z///////b4eF/wArKP8AKyj/JEhG/0lnZf/Fx8b/mZ2b/298e///5eX//+Li///g4P9JXVv//9vb/yRD + QP8AKyj/ACso/wArKP8AKyj/SVlW/+K6uv9mZmb/KioqdAAAAA0AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AABmZmZgcHBw/+Li4v/////////////////////////////w8P+Znp3/b318///n5///5eX//+Li/0le + XP//3d3//9vb///Z2f//1dX//9PT///R0f/iu7v/cGxs/z8/P5wAAAAVAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAABmZmafcHBw/8/Pz///////////////////+vr///Hx/wArKP8AKyj/JEVD/5mb + mv8AKyj/ACso/295eP//3d3//9vb///Z2f//1dX/4r+//3Btbf9NTU2qAAAAFQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmZmZgZmZm/6mpqf/19fX////////39///8/P///Hx///v + 7///6+v//+np///n5///5eX//+Li///g4P//3d3//9vb/7Ofn/9mZmb/SUlJhgAAAA0AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABmZmYwZmZm0HBwcP+zsrL/9e/v///2 + 9v//8/P///Hx///v7///6+v//+np///n5///5eX/9dra/8aysv95dXX/X19f3kVFRUcAAAAEAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZmZmYGVl + ZdFmZmb/jIqK/7Otrf/Px8f/2c7O/9nMzP/PwsL/s6en/4yGhv9mZmb/YmJi2FlZWW4AAAAJAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAGZmZiBkZGRyZGRko2RkZMNjY2PEY2NjxGNjY8RiYmKmX19feFBQUCkAAAADAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8AAf/8AAD/+AAAf/AAAD/gA + AAfwAAAD4AAAAeAAAADAAAAAwAAAAIAAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAA + AACAAAAAwAAAAMAAAAHgAAAB4AAAA/AAAAf4AAAP/AAAH/4AAD//gAD//+AD//////8oAAAAEAAAACAA + AAABACAAAAAAAEAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAABwAAABMAAAAeQAA + AJoAAACkAAAAmgAAAHkAAABMAAAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABgAAADY4ODiwY19f5ZKK + ivuzqan/ko2N+2FfX+suLi7TAAAArAAAAIIAAAA8AAAACQAAAAAAAAAAAAAAAykpKU9waWnqz7S0///d + 3f//4uL//+jo///u7v//8/P/z8/P/3V1dfMZGRnGAAAAkgAAADwAAAAEAAAAADo6OjiBd3f39cfH///S + 0v//2Nj//93d///i4v//6Oj///T0///////19fX/m5ub+xkZGcYAAACCAAAAHAAAAAl2cHDd9c3N///P + z///zc3//9LS///Y2P//3d3//+Li///6+v////////////X19f91dXXzAAAArAAAAExcXFxqxrGx///Z + 2f//1NT//8/P///Nzf//1Nv//9fi///k6v//////////////////////0szM/y4uLtMAAAB3b25utv/j + 4/9udHT/AS4v/250dP//3uf/bnR0/wEuL/9udHT///j//wEuL/8BLi//AS4v/8yZmf9bU1PqAAAAlJCK + iuL/5+f/AS4v///e3v8BLi///+/8/wEuL///4vz/AS4v//zw+f8BLi//zJmZ/8yZmf/MmZn/fGxs9wAA + AKGejIz/6b6+/wEuL//zxcX/+dbW///p8/8BLi///+nz/wEuL//56Oz/AS4v/wEuL//mvb3/5sDA/6aU + lP8AAACUh3d30tuoqP8BLi//6re3/wEuL///7vz/AS4v///S9f8BLi////T8/wEuL///2Nj//93d///i + 4v+Efn72AAAAd29qarHVoqL/bnR0/wEuL/9udHT///b//wEuL///0vX/AS4v///g5/8BLi//AS4v/wEu + L///3d3/WVdX5AAAAExmZmZQw7+/////////////////////////7PH//9vn///Z3v//1NT//8/P///N + zf//0tL/xq2t/zk5OawAAAAbAAAAAHNzc8D19fX//////////////v7//+fn///j4///3t7//9nZ///U + 1P//z8//9cfH/2xlZeMAAAA0AAAAAwAAAABmZmYghYWF7/X19f////////j4///s7P//5+f//+Pj///e + 3v//2dn/9c3N/4F3d/cqKipNAAAABgAAAAAAAAAAAAAAAGZmZiBzc3PAxsbG///39///8vL//+zs///n + 5///4+P/xrGx/3Vvb9A8PDw2AAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGZmZlBzc3Oik5CQ0oyJ + if+RjIzUcG5upltbW1oAAAAHAAAAAAAAAAAAAAAAAAAAAOADAADAAQAAgAAAAIAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAACAAQAAwAMAAPAPAAA= CenterScreen - CUERipper 2.0.4a + CUERipper 2.0.5 toolStripStatusLabel1 @@ -753,6 +1371,12 @@ System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + toolStripStatusCTDB + + + System.Windows.Forms.ToolStripStatusLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + toolStripStatusAr @@ -765,12 +1389,6 @@ System.Windows.Forms.ToolStripProgressBar, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - toolStripProgressBar2 - - - System.Windows.Forms.ToolStripProgressBar, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - toolStripStatusLabel2 @@ -819,6 +1437,36 @@ System.Windows.Forms.BindingSource, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + plainBackgroundPainter1 + + + ProgressODoom.PlainBackgroundPainter, ProgressODoom, Version=1.0.3711.31206, Culture=neutral, PublicKeyToken=null + + + styledBorderPainter1 + + + ProgressODoom.StyledBorderPainter, ProgressODoom, Version=1.0.3711.31206, Culture=neutral, PublicKeyToken=null + + + plainProgressPainter1 + + + ProgressODoom.PlainProgressPainter, ProgressODoom, Version=1.0.3711.31206, Culture=neutral, PublicKeyToken=null + + + gradientGlossPainter1 + + + ProgressODoom.GradientGlossPainter, ProgressODoom, Version=1.0.3711.31206, Culture=neutral, PublicKeyToken=null + + + plainProgressPainter2 + + + ProgressODoom.PlainProgressPainter, ProgressODoom, Version=1.0.3711.31206, Culture=neutral, PublicKeyToken=null + frmCUERipper diff --git a/CUETools.CTDB/CUEToolsDB.cs b/CUETools.CTDB/CUEToolsDB.cs index f98be24..ccbb0fb 100644 --- a/CUETools.CTDB/CUEToolsDB.cs +++ b/CUETools.CTDB/CUEToolsDB.cs @@ -15,7 +15,7 @@ namespace CUETools.CTDB public class CUEToolsDB { const string urlbase = "http://db.cuetools.net"; - const string userAgent = "CUETools 205"; + string userAgent; private CDRepairEncode verify; private CDImageLayout toc; @@ -40,8 +40,9 @@ namespace CUETools.CTDB this.uploadHelper = new HttpUploadHelper(); } - public void ContactDB(string id) + public void ContactDB(string id, string userAgent) { + this.userAgent = userAgent; this.id = id; // Calculate the three disc ids used by AR @@ -126,6 +127,23 @@ namespace CUETools.CTDB return cpuInfo ?? "unknown"; } + public string Confirm(DBEntry entry) + { + if (fullid == null) + throw new Exception("no id"); + HttpWebRequest req = (HttpWebRequest)WebRequest.Create(urlbase + "/confirm.php"); + req.Proxy = proxy; + req.UserAgent = userAgent; + NameValueCollection form = new NameValueCollection(); + form.Add("id", fullid); + form.Add("ctdbid", string.Format("{0:x8}", entry.crc)); + HttpWebResponse resp = uploadHelper.Upload(req, new UploadFile[0], form); + using (Stream s = resp.GetResponseStream()) + using (StreamReader sr = new StreamReader(s)) + subResult = sr.ReadToEnd(); + return subResult; + } + public string Submit(int confidence, int total, string artist, string title) { if (fullid == null) @@ -162,7 +180,7 @@ namespace CUETools.CTDB if (artist != null && artist != "") using (DBHDR TAG = DISC.HDR("ART ")) TAG.Write(artist); if (title != null && title != "") using (DBHDR TAG = DISC.HDR("nam ")) TAG.Write(title); using (DBHDR USER = DISC.HDR("USER")) USER.Write(GetCPUID()); - using (DBHDR TOOL = DISC.HDR("TOOL")) TOOL.Write("CUETools 205"); + using (DBHDR TOOL = DISC.HDR("TOOL")) TOOL.Write(userAgent); using (DBHDR TOOL = DISC.HDR("MBID")) TOOL.Write(toc.MusicBrainzId); using (DBHDR DATE = DISC.HDR("DATE")) DATE.Write(DateTime.Now); using (DBHDR CONF = DISC.HDR("CONF")) CONF.Write(confidence); diff --git a/CUETools.CTDB/Web/404.html b/CUETools.CTDB/Web/404.html new file mode 100644 index 0000000..3d18775 --- /dev/null +++ b/CUETools.CTDB/Web/404.html @@ -0,0 +1,8 @@ + + + + + +disc not present in database + + \ No newline at end of file diff --git a/CUETools.CTDB/Web/ctdb.png b/CUETools.CTDB/Web/ctdb.png new file mode 100644 index 0000000..b5226ea Binary files /dev/null and b/CUETools.CTDB/Web/ctdb.png differ diff --git a/CUETools.CTDB/Web/index.php b/CUETools.CTDB/Web/index.php index 1d603f7..054632d 100644 --- a/CUETools.CTDB/Web/index.php +++ b/CUETools.CTDB/Web/index.php @@ -1,65 +1,77 @@ - - - -CUETools DB - - - -

CUETools Database

$totaldiscs || $start < 0) $start = $totaldiscs - $count; +fseek($fp, 57 * $start, SEEK_SET); +$n = $count; while($line=fgets($fp)) { $name = trim($line); if (file_exists($name)) $lines[]=$name; - if (--$count <= 0) + if (--$n <= 0) break; } fclose($fp); -printf("

Recent additions:

"); -printf(""); +printf("

Recent additions:

"); +include 'table_start.php'; +?> +
ArtistAlbumDisc IdCTDB Id
+ +$imgs = ''; if ($lines) foreach(array_reverse($lines) as $line) { $ctdb = new phpCTDB($line); $disc = $ctdb->db['discs'][0]; - $id = @$disc['MBID']['value']; + $ctdb->ParseToc(); + //$id = @$disc['MBID']['value']; $artist = @$disc['ART ']['value']; $title = @$disc['nam ']['value']; - $link = $id == "" ? "" : ''; - //echo $line . ':' . $id . '
'; - if ($artist == "" && $title == "" && $id != "") { + $discid = substr($line,13,30); + $ctdbid = $ctdb->db['discs'][0]['CRC ']['int']; + if ($artist == "" && $title == "") + { //$q = new MusicBrainzQuery(new WebService('db4.cuetools.net')); $q = new MusicBrainzQuery(); $rf = new ReleaseFilter(); try { - $rresults = $q->getReleases( $rf->discId($id) ); + $rresults = $q->getReleases( $rf->discId($ctdb->mbid) ); foreach ( $rresults as $key => $rr ) { $rr = $rr->getRelease(); $artist = $rr->getArtist()->getName(); $title = $rr->getTitle(); + $imgs = $imgs . ''; } } catch ( ResponseError $e ) { // echo $e->getMessage() . " "; } } - printf("
", $artist, $title, $link, substr($line,13,30), $ctdb->db['discs'][0]['CRC ']['int']); + printf('', htmlspecialchars($artist), htmlspecialchars($title), $ctdb->mbid, $discid, $discid, $ctdbid, $ctdbid); } +printf('', $count * floor(($start - 1) / $count)); printf("
ArtistAlbumDisc IdCTDB Id
%s%s%s%s%x
%s%s%s%08x
More
"); -printf("
Status: %d unique discs.
", filesize("parity/list.txt")/57); +include 'table_end.php' ; +//printf('%s', $imgs); +printf(""); ?> + diff --git a/CUETools.CTDB/Web/logo_start.php b/CUETools.CTDB/Web/logo_start.php new file mode 100644 index 0000000..525bc13 --- /dev/null +++ b/CUETools.CTDB/Web/logo_start.php @@ -0,0 +1,62 @@ + + + +CUETools DB + + + + + + + + + + + + + + + +
+ +
AboutCUETools
+
diff --git a/CUETools.CTDB/Web/phpctdb/ctdb.php b/CUETools.CTDB/Web/phpctdb/ctdb.php index 6e35c46..135c7c7 100644 --- a/CUETools.CTDB/Web/phpctdb/ctdb.php +++ b/CUETools.CTDB/Web/phpctdb/ctdb.php @@ -6,6 +6,8 @@ class phpCTDB{ private $fpstats; private $atoms; public $db; + public $fulltoc; + public $mbid; function __construct($target_file) { $this->fp = fopen($target_file, 'rb'); @@ -19,6 +21,32 @@ class phpCTDB{ fclose($this->fp); } + function ParseTOC() + { + $disc = $this->db['discs'][0]; + $this->fulltoc = ''; + $mbtoc = ''; + foreach ($disc['TOC ']['subatoms'] as $track) + { + if ($track['name']=='INFO') { + $trackcount = phpCTDB::BigEndian2Int(substr($track['value'],0,4)); + $pregap = phpCTDB::BigEndian2Int(substr($track['value'],4,4)); + $pos = $pregap + 150; + } + if ($track['name']=='TRAK') { + $isaudio = phpCTDB::BigEndian2Int(substr($track['value'],0,4)); + $length = phpCTDB::BigEndian2Int(substr($track['value'],4,4)); + $this->fulltoc = sprintf('%s %d', $this->fulltoc, $pos); + $mbtoc = sprintf('%s%08X', $mbtoc, $pos); + $pos += $length; + } + } + $this->fulltoc = sprintf('1 %d %d%s', $trackcount, $pos, $this->fulltoc); + $mbtoc = sprintf('01%02X%08X%s', $trackcount, $pos, $mbtoc); + $mbtoc = str_pad($mbtoc,804,'0'); + $this->mbid = str_replace('+', '.', str_replace('/', '_', str_replace('=', '-', base64_encode(pack("H*" , sha1($mbtoc)))))); + } + static function BigEndian2Int($byte_word, $signed = false) { $int_value = 0; @@ -56,6 +84,25 @@ class phpCTDB{ return strrev(phpCTDB::LittleEndian2String($number, $minbytes, $synchsafe)); } + static function discid2path($id) + { + $err = sscanf($id, "%03d-%04x%04x-%04x%04x-%04x%04x", $tracks, $id1a, $id1b, $id2a, $id2b, $cddbida, $cddbidb); + $parsedid = sprintf("%03d-%04x%04x-%04x%04x-%04x%04x", $tracks, $id1a, $id1b, $id2a, $id2b, $cddbida, $cddbidb); + if ($id != $parsedid) + die("bad id ". $id); + return sprintf("parity/%x/%x/%x/%s", $id1b & 15, ($id1b >> 4) & 15, ($id1b >> 8) & 15, $parsedid); + } + + static function ctdbid2path($discid, $ctdbid) + { + $path = phpCTDB::discid2path($discid); + sscanf($ctdbid, "%04x%04x", $ctdbida, $ctdbidb); + $parsedctdbid = sprintf("%04x%04x", $ctdbida, $ctdbidb); + if ($ctdbid != $parsedctdbid) + die("bad id ". $ctdbid); + return sprintf("%s/%s.bin", $path, $ctdbid); + } + static function unparse_atom($fp, $atom) { // printf('unparse_atom(%s)
', $atom['name']); @@ -105,6 +152,7 @@ class phpCTDB{ foreach ($atom['subatoms'] as $param) switch ($param['name']) { case 'HEAD': + case 'TOC ': case 'CRC ': case 'MBID': case 'ART ': diff --git a/CUETools.CTDB/Web/show.php b/CUETools.CTDB/Web/show.php new file mode 100644 index 0000000..8eb0cfc --- /dev/null +++ b/CUETools.CTDB/Web/show.php @@ -0,0 +1,55 @@ +db['discs'][0]; +//$id = @$disc['MBID']['value']; +$ctdb->ParseTOC(); +$artist = @$disc['ART ']['value']; +$title = @$disc['nam ']['value']; +$link = '
'; +$q = new MusicBrainzQuery(); +$rf = new ReleaseFilter(); +$mbrr = false; +try { + $rresults = $q->getReleases( $rf->discId($ctdb->mbid) ); + foreach ( $rresults as $key => $rr ) { + $mbrr = $rr->getRelease(); + } +} +catch ( ResponseError $e ) { + // echo $e->getMessage() . " "; +} +printf('
'); +if ($mbrr && $mbrr->getAsin()) +{ + include 'table_start.php'; + $imgurl = 'http://ec1.images-amazon.com/images/P/' . $mbrr->getAsin() . '.01.MZZZZZZZ.jpg'; + #$imgurl = 'http://images.amazon.com/images/P/' . $mbrr->getAsin() . '.01._SCLZZZZZZZ_PU_PU-5_.jpg'; + printf('', $imgurl); + include 'table_end.php'; + printf('

'); +} +include 'table_start.php'; +?> + +', $ctdb->fulltoc); +printf('', $artist); +if ($mbrr && $mbrr->getArtist()->getName() != $artist) +printf('', $mbrr->getArtist()->getName()); +printf('', $title); +if ($mbrr && $mbrr->getTitle() != $title) +printf('', $mbrr->getTitle()); +printf('', $link, $ctdb->mbid); +?> +
Full TOC%s
Artist%s
Artist (MB)%s
Title%s
Title (MB)%s
MusicbrainzId%s%s
+ +
+ + diff --git a/CUETools.CTDB/Web/submit.php b/CUETools.CTDB/Web/submit.php index a546d57..1320a14 100644 --- a/CUETools.CTDB/Web/submit.php +++ b/CUETools.CTDB/Web/submit.php @@ -75,15 +75,9 @@ if ($size == 0) { } $id = $_POST['id']; -$err = sscanf($id, "%03d-%04x%04x-%04x%04x-%04x%04x", $tracks, $id1a, $id1b, $id2a, $id2b, $cddbida, $cddbidb); -$parsedid = sprintf("%03d-%04x%04x-%04x%04x-%04x%04x", $tracks, $id1a, $id1b, $id2a, $id2b, $cddbida, $cddbidb); -if ($id != $parsedid) - die("bad id ". $id); - -$target_path = sprintf("parity/%x/%x/%x/%s", $id1b & 15, ($id1b >> 4) & 15, ($id1b >> 8) & 15, $parsedid); -$target_file = sprintf("%s/ctdb.bin", $target_path, $parsedid); - +$target_path = phpCTDB::discid2path($id); @mkdir($target_path, 0777, true); +$target_file = sprintf("%s/ctdb.bin", $target_path); $ctdb = new phpCTDB($tmpname); $ctdb1 = @file_exists($target_file) ? new phpCTDB($target_file) : false; @@ -162,7 +156,7 @@ fwrite($listfp, "\n"); fclose($listfp); if ($merging) - printf("%s has been updated", $parsedid); + printf("%s has been updated", $id); else - printf("%s has been uploaded", $parsedid); + printf("%s has been uploaded", $id); ?> diff --git a/CUETools.CTDB/Web/table_end.php b/CUETools.CTDB/Web/table_end.php new file mode 100644 index 0000000..520a0e5 --- /dev/null +++ b/CUETools.CTDB/Web/table_end.php @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/CUETools.CTDB/Web/table_start.php b/CUETools.CTDB/Web/table_start.php new file mode 100644 index 0000000..0a32d34 --- /dev/null +++ b/CUETools.CTDB/Web/table_start.php @@ -0,0 +1,10 @@ + + + + + + + + +
+ diff --git a/CUETools.Codecs/Codecs.cs b/CUETools.Codecs/Codecs.cs index f696a77..00d5ee8 100644 --- a/CUETools.Codecs/Codecs.cs +++ b/CUETools.Codecs/Codecs.cs @@ -1642,9 +1642,11 @@ namespace CUETools.Codecs bool _haveData = false; int _bufferPos = 0; Exception _ex = null; + bool own; - public AudioPipe(IAudioSource source, int size) + public AudioPipe(IAudioSource source, int size, bool own) { + this.own = own; _source = source; _readBuffer = new AudioBuffer(source, size); _writeBuffer = new AudioBuffer(source, size); @@ -1655,7 +1657,9 @@ namespace CUETools.Codecs private void Decompress(object o) { +#if !DEBUG try +#endif { bool done = false; do @@ -1674,8 +1678,8 @@ namespace CUETools.Codecs Monitor.Pulse(this); } } while (!done); - _source.Close(); } +#if !DEBUG catch (Exception ex) { lock (this) @@ -1684,6 +1688,7 @@ namespace CUETools.Codecs Monitor.Pulse(this); } } +#endif } private void Go() @@ -1712,6 +1717,11 @@ namespace CUETools.Codecs _workThread.Join(); _workThread = null; } + if (_source != null) + { + if (own) _source.Close(); + _source = null; + } if (_readBuffer != null) { //_readBuffer.Clear(); diff --git a/CUETools.Processor/Processor.cs b/CUETools.Processor/Processor.cs index 57c09ab..400dbd2 100644 --- a/CUETools.Processor/Processor.cs +++ b/CUETools.Processor/Processor.cs @@ -978,7 +978,7 @@ namespace CUETools.Processor overwriteCUEData = false; filenamesANSISafe = true; bruteForceDTL = false; - createEACLOG = false; + createEACLOG = true; detectHDCD = true; wait750FramesForHDCD = true; decodeHDCD = false; @@ -1030,7 +1030,7 @@ namespace CUETools.Processor } if (Type.GetType("Mono.Runtime", false) == null) { - encoders.Add(new CUEToolsUDC("flake", "flac", true, "0 1 2 3 4 5 6 7 8 9 10 11", "10", "flake.exe", "-%M - -o %O -p %P")); + encoders.Add(new CUEToolsUDC("flake", "flac", true, "0 1 2 3 4 5 6 7 8 9 10 11 12", "8", "flake.exe", "-%M - -o %O -p %P")); encoders.Add(new CUEToolsUDC("takc", "tak", true, "0 1 2 2e 2m 3 3e 3m 4 4e 4m", "2", "takc.exe", "-e -p%M -overwrite - %O")); encoders.Add(new CUEToolsUDC("ffmpeg alac", "m4a", true, "", "", "ffmpeg.exe", "-i - -f ipod -acodec alac -y %O")); encoders.Add(new CUEToolsUDC("lame vbr", "mp3", false, "V9 V8 V7 V6 V5 V4 V3 V2 V1 V0", "V2", "lame.exe", "--vbr-new -%M - %O")); @@ -1159,7 +1159,7 @@ string status = processor.Go(); sw.Save("OverwriteCUEData", overwriteCUEData); sw.Save("FilenamesANSISafe", filenamesANSISafe); if (bruteForceDTL) sw.Save("BruteForceDTL", bruteForceDTL); - if (createEACLOG) sw.Save("CreateEACLOG", createEACLOG); + sw.Save("CreateEACLOG", createEACLOG); sw.Save("DetectHDCD", detectHDCD); sw.Save("Wait750FramesForHDCD", wait750FramesForHDCD); sw.Save("DecodeHDCD", decodeHDCD); @@ -1292,7 +1292,7 @@ string status = processor.Go(); overwriteCUEData = sr.LoadBoolean("OverwriteCUEData") ?? false; filenamesANSISafe = sr.LoadBoolean("FilenamesANSISafe") ?? true; bruteForceDTL = sr.LoadBoolean("BruteForceDTL") ?? false; - createEACLOG = sr.LoadBoolean("createEACLOG") ?? false; + createEACLOG = sr.LoadBoolean("CreateEACLOG") ?? createEACLOG; detectHDCD = sr.LoadBoolean("DetectHDCD") ?? true; wait750FramesForHDCD = sr.LoadBoolean("Wait750FramesForHDCD") ?? true; decodeHDCD = sr.LoadBoolean("DecodeHDCD") ?? false; @@ -2635,14 +2635,15 @@ string status = processor.Go(); _padding += _eacLog.Length; } - public void UseCUEToolsDB() + public void UseCUEToolsDB(bool submit, string userAgent) { ShowProgress((string)"Contacting CUETools database...", 0, 0, null, null); - _CUEToolsDB.ContactDB(_accurateRipId ?? AccurateRipVerify.CalculateAccurateRipId(_toc)); + _CUEToolsDB.ContactDB(_accurateRipId ?? AccurateRipVerify.CalculateAccurateRipId(_toc), userAgent); ShowProgress("", 0.0, 0.0, null, null); _useCUEToolsDB = true; + _useCUEToolsDBSibmit = submit; } public void UseAccurateRip() @@ -3141,6 +3142,50 @@ string status = processor.Go(); } } + public bool PrintErrors(StringWriter logWriter, uint tr_start, uint len) + { + uint tr_end = (len + 74) / 75; + int errCount = 0; + for (uint iSecond = 0; iSecond < tr_end; iSecond++) + { + uint sec_start = tr_start + iSecond * 75; + uint sec_end = Math.Min(sec_start + 74, tr_start + len - 1); + bool fError = false; + for (uint iSector = sec_start; iSector <= sec_end; iSector++) + if (_ripper.Errors[(int)iSector]) + fError = true; + if (fError) + { + uint end = iSecond; + for (uint jSecond = iSecond + 1; jSecond < tr_end; jSecond++) + { + uint jsec_start = tr_start + jSecond * 75; + uint jsec_end = Math.Min(jsec_start + 74, tr_start + len - 1); + bool jfError = false; + for (uint jSector = jsec_start; jSector <= jsec_end; jSector++) + if (_ripper.Errors[(int)jSector]) + jfError = true; + if (jfError) + end = jSecond; + } + if (errCount == 0) + logWriter.WriteLine(); + if (errCount++ > 20) + break; + //"Suspicious position 0:02:20" + //" Suspicious position 0:02:23 - 0:02:24" + string s1 = CDImageLayout.TimeToString("0:{0:00}:{1:00}", iSecond * 75); + string s2 = CDImageLayout.TimeToString("0:{0:00}:{1:00}", end * 75); + if (iSecond == end) + logWriter.WriteLine(" Suspicious position {0}", s1); + else + logWriter.WriteLine(" Suspicious position {0} - {1}", s1, s2); + iSecond = end; + } + } + return errCount > 0; + } + public void CreateExactAudioCopyLOG() { StringWriter logWriter = new StringWriter(CultureInfo.InvariantCulture); @@ -3163,7 +3208,7 @@ string status = processor.Go(); "Delete leading and trailing silent blocks : No\r\n" + "Null samples used in CRC calculations : Yes\r\n" + "Used interface : Native Win32 interface for Win NT & 2000\r\n" + - "Gap handling : Appended to previous track\r\n" + + "{6}" + "\r\n" + "Used output format : Internal WAV Routines\r\n" + "Sample format : 44.100 Hz; 16 Bit; Stereo\r\n"; @@ -3173,7 +3218,8 @@ string status = processor.Go(); Artist, Title, _ripper.EACName, _ripper.CorrectionQuality > 0 ? "Secure" : "Burst", - _ripper.DriveOffset); + _ripper.DriveOffset, + (OutputStyle != CUEStyle.SingleFile && OutputStyle != CUEStyle.SingleFileWithCUE) ? "Gap handling : Appended to previous track\r\n" : "" ); logWriter.WriteLine(); logWriter.WriteLine("TOC of the extracted CD"); @@ -3192,6 +3238,7 @@ string status = processor.Go(); bool htoaToFile = ((OutputStyle == CUEStyle.GapsAppended) && _config.preserveHTOA && (_toc.Pregap != 0)); int accurateTracks = 0, knownTracks = 0; + bool wereErrors = false; if (OutputStyle != CUEStyle.SingleFile && OutputStyle != CUEStyle.SingleFileWithCUE) { logWriter.WriteLine(); @@ -3206,46 +3253,7 @@ string status = processor.Go(); logWriter.WriteLine(" Pre-gap length 0:{0}.{1:00}", CDImageLayout.TimeToString("{0:00}:{1:00}", _toc[track + _toc.FirstAudio].Pregap + (track + _toc.FirstAudio == 1 ? 150U : 0U)), (_toc[track + _toc.FirstAudio].Pregap % 75) * 100 / 75); } - int errCount = 0; - uint tr_start = _toc[track + _toc.FirstAudio].Start; - uint tr_end = (_toc[track + _toc.FirstAudio].Length + 74) / 75; - for (uint iSecond = 0; iSecond < tr_end; iSecond ++) - { - uint sec_start = tr_start + iSecond * 75; - uint sec_end = Math.Min(sec_start + 74, _toc[track + _toc.FirstAudio].End); - bool fError = false; - for (uint iSector = sec_start; iSector <= sec_end; iSector++) - if (_ripper.Errors[(int)iSector]) - fError = true; - if (fError) - { - uint end = iSecond; - for (uint jSecond = iSecond + 1; jSecond < tr_end; jSecond++) - { - uint jsec_start = tr_start + jSecond * 75; - uint jsec_end = Math.Min(jsec_start + 74, _toc[track + _toc.FirstAudio].End); - bool jfError = false; - for (uint jSector = jsec_start; jSector <= jsec_end; jSector++) - if (_ripper.Errors[(int)jSector]) - jfError = true; - if (jfError) - end = jSecond; - } - if (errCount == 0) - logWriter.WriteLine(); - if (errCount++ > 20) - break; - //"Suspicious position 0:02:20" - //" Suspicious position 0:02:23 - 0:02:24" - string s1 = CDImageLayout.TimeToString("0:{0:00}:{1:00}", iSecond * 75); - string s2 = CDImageLayout.TimeToString("0:{0:00}:{1:00}", end * 75); - if (iSecond == end) - logWriter.WriteLine(" Suspicious position {0}", s1); - else - logWriter.WriteLine(" Suspicious position {0} - {1}", s1, s2); - iSecond = end; - } - } + wereErrors |= PrintErrors(logWriter, _toc[track + _toc.FirstAudio].Start, _toc[track + _toc.FirstAudio].Length); logWriter.WriteLine(); logWriter.WriteLine(" Peak level {0:F1} %", (Tracks[track].PeakLevel * 1000 / 32768) * 0.1); @@ -3277,6 +3285,7 @@ string status = processor.Go(); logWriter.WriteLine("Selected range"); logWriter.WriteLine(); logWriter.WriteLine(" Filename {0}", Path.ChangeExtension(Path.GetFullPath(_destPaths[0]), ".wav")); + wereErrors = PrintErrors(logWriter, _toc[_toc.FirstAudio][0].Start, _toc.AudioLength); logWriter.WriteLine(); int PeakLevel = 0; for (int track = 0; track < TrackCount; track++) @@ -3288,7 +3297,10 @@ string status = processor.Go(); logWriter.WriteLine(" Copy CRC {0:X8}", _arVerify.CRC32(0)); logWriter.WriteLine(" Copy OK"); logWriter.WriteLine(); - logWriter.WriteLine("No errors occurred"); + if (wereErrors) + logWriter.WriteLine("There were errors"); + else + logWriter.WriteLine("No errors occurred"); logWriter.WriteLine(); logWriter.WriteLine(); logWriter.WriteLine("AccurateRip summary"); @@ -3331,7 +3343,10 @@ string status = processor.Go(); logWriter.WriteLine(); if (OutputStyle != CUEStyle.SingleFile && OutputStyle != CUEStyle.SingleFileWithCUE) { - logWriter.WriteLine("No errors occurred"); + if (wereErrors) + logWriter.WriteLine("There were errors"); + else + logWriter.WriteLine("No errors occurred"); logWriter.WriteLine(); } logWriter.WriteLine("End of status report"); @@ -3383,24 +3398,19 @@ string status = processor.Go(); logWriter.WriteLine("Destination files"); foreach (string path in _destPaths) logWriter.WriteLine(" {0}", path); - bool wereErrors = false; - for (int iTrack = 0; iTrack < _toc.AudioTracks; iTrack++) + bool wereErrors = PrintErrors(logWriter, _toc[_toc.FirstAudio][0].Start, _toc.AudioLength); + if (wereErrors) { - int cdErrors = 0; - for (uint iSector = _toc[iTrack + 1].Start; iSector <= _toc[iTrack + 1].End; iSector++) - if (_ripper.Errors[(int)iSector]) - cdErrors++; - if (cdErrors != 0) - { - if (!wereErrors) - { - logWriter.WriteLine(); - logWriter.WriteLine("Errors detected"); - logWriter.WriteLine(); - } - wereErrors = true; - logWriter.WriteLine("Track {0} contains {1} errors", iTrack + 1, cdErrors); - } + logWriter.WriteLine(); + if (wereErrors) + logWriter.WriteLine("There were errors"); + else + logWriter.WriteLine("No errors occurred"); + } + if (_useCUEToolsDB) + { + logWriter.WriteLine(); + GenerateCTDBLog(logWriter); } if (_useAccurateRip) { @@ -3408,7 +3418,6 @@ string status = processor.Go(); logWriter.WriteLine("AccurateRip summary"); logWriter.WriteLine(); _arVerify.GenerateFullLog(logWriter, true); - logWriter.WriteLine(); } logWriter.WriteLine(); logWriter.WriteLine("End of status report"); @@ -3514,6 +3523,28 @@ string status = processor.Go(); return sw.ToString(); } + public void GenerateCTDBLog(TextWriter sw) + { + if (_CUEToolsDB.DBStatus != null) + sw.WriteLine("CUETools DB: {0}.", _CUEToolsDB.DBStatus); + if (_CUEToolsDB.SubStatus != null) + sw.WriteLine("CUETools DB: {0}.", _CUEToolsDB.SubStatus); + if (_CUEToolsDB.DBStatus == null) + sw.WriteLine(" [ CTDBID ] Status"); + foreach (DBEntry entry in _CUEToolsDB.Entries) + { + string confFormat = (_CUEToolsDB.Total < 10) ? "{0:0}/{1:0}" : + (_CUEToolsDB.Total < 100) ? "{0:00}/{1:00}" : "{0:000}/{1:000}"; + string conf = string.Format(confFormat, entry.conf, _CUEToolsDB.Total); + string status = + (!entry.hasErrors) ? "Accurately ripped" : + entry.canRecover ? string.Format("Contains {0} correctable errors", entry.repair.CorrectableErrors) : + (entry.httpStatus == 0 || entry.httpStatus == HttpStatusCode.OK) ? "No match" : + entry.httpStatus.ToString(); + sw.WriteLine(" [{0:x8}] ({1}) {2}", entry.crc, conf, status); + } + } + public void GenerateAccurateRipLog(TextWriter sw) { if (!_processed) @@ -3544,26 +3575,7 @@ string status = processor.Go(); if (_useCUEToolsDBFix)// && _CUEToolsDB.SelectedEntry != null) sw.WriteLine("CUETools DB: corrected {0} errors.", _CUEToolsDB.SelectedEntry.repair.CorrectableErrors); else if (_useCUEToolsDB) - { - if (_CUEToolsDB.DBStatus != null) - sw.WriteLine("CUETools DB: {0}.", _CUEToolsDB.DBStatus); - if (_CUEToolsDB.SubStatus != null) - sw.WriteLine("CUETools DB: {0}.", _CUEToolsDB.SubStatus); - if (_CUEToolsDB.DBStatus == null) - sw.WriteLine(" [ CTDBID ] Status"); - foreach (DBEntry entry in _CUEToolsDB.Entries) - { - string confFormat = (_CUEToolsDB.Total < 10) ? "{0:0}/{1:0}" : - (_CUEToolsDB.Total < 100) ? "{0:00}/{1:00}" : "{0:000}/{1:000}"; - string conf = string.Format(confFormat, entry.conf, _CUEToolsDB.Total); - string status = - (!entry.hasErrors) ? "Accurately ripped" : - entry.canRecover ? string.Format("Contains {0} correctable errors", entry.repair.CorrectableErrors) : - (entry.httpStatus == 0 || entry.httpStatus == HttpStatusCode.OK) ? "No match" : - entry.httpStatus.ToString(); - sw.WriteLine(" [{0:x8}] ({1}) {2}", entry.crc, conf, status); - } - } + GenerateCTDBLog(sw); _arVerify.GenerateFullLog(sw, _config.arLogVerbose); } @@ -4706,7 +4718,7 @@ string status = processor.Go(); { _ripper.Position = 0; //audioSource = _ripper; - audioSource = new AudioPipe(_ripper, 0x100000); + audioSource = new AudioPipe(_ripper, 0x100000, false); } else if (_isArchive) audioSource = AudioReadWrite.GetAudioSource(sourceInfo.Path, OpenArchive(sourceInfo.Path, false), _config); @@ -4719,7 +4731,7 @@ string status = processor.Go(); //if (!(audioSource is AudioPipe) && !(audioSource is UserDefinedReader) && _config.separateDecodingThread) if (!(audioSource is AudioPipe) && _config.separateDecodingThread) - audioSource = new AudioPipe(audioSource, 0x10000); + audioSource = new AudioPipe(audioSource, 0x10000, true); return audioSource; } @@ -5226,7 +5238,7 @@ string status = processor.Go(); return "AccurateRip: confidence too low"; //if (CTDB.AccResult == HttpStatusCode.OK) //return "CUEToolsDB: disc already present in database"; - if (CTDB.AccResult != HttpStatusCode.NotFound && CTDB.AccResult != HttpStatusCode.OK) + if (CTDB.AccResult != HttpStatusCode.NotFound && CTDB.AccResult != HttpStatusCode.OK)// && CTDB.AccResult != HttpStatusCode.NoContent) return "CUEToolsDB: " + CTDB.DBStatus; _useCUEToolsDBSibmit = true; string status = Go(); @@ -5240,7 +5252,7 @@ string status = processor.Go(); } case "repair": { - UseCUEToolsDB(); + UseCUEToolsDB(false, "CUETools 205"); Action = CUEAction.Verify; if (CTDB.DBStatus != null) return CTDB.DBStatus; diff --git a/CUETools.Ripper.SCSI/CUETools.Ripper.SCSI.csproj b/CUETools.Ripper.SCSI/CUETools.Ripper.SCSI.csproj index e7aa6fb..888ddfe 100644 --- a/CUETools.Ripper.SCSI/CUETools.Ripper.SCSI.csproj +++ b/CUETools.Ripper.SCSI/CUETools.Ripper.SCSI.csproj @@ -19,10 +19,11 @@ true full false - bin\Debug\ + ..\bin\Debug\plugins\ DEBUG;TRACE prompt 4 + true pdbonly diff --git a/CUETools.Ripper.SCSI/SCSIDrive.cs b/CUETools.Ripper.SCSI/SCSIDrive.cs index 75e979f..ad66e08 100644 --- a/CUETools.Ripper.SCSI/SCSIDrive.cs +++ b/CUETools.Ripper.SCSI/SCSIDrive.cs @@ -57,14 +57,14 @@ namespace CUETools.Ripper.SCSI int m_max_sectors; int _timeout = 10; Crc16Ccitt _crc; - public long[,] UserData; - public long[,] C2Data; + public long[,,] UserData; + public byte[,] C2Count; public byte[,] QData; public long[] byte2long; BitArray _errors; int _errorsCount; int _crcErrorsCount = 0; - byte[] _currentData = new byte[MSECTORS * 4 * 588]; + AudioBuffer currentData = new AudioBuffer(AudioPCMConfig.RedBook, MSECTORS * 588); short[] _valueScore = new short[256]; bool _debugMessages = false; ReadCDCommand _readCDCommand = ReadCDCommand.Unknown; @@ -183,8 +183,8 @@ namespace CUETools.Ripper.SCSI { m_logger = new Logger(); _crc = new Crc16Ccitt(InitialCrcValue.Zeros); - UserData = new long[MSECTORS, 4 * 588]; - C2Data = new long[MSECTORS, 588 / 2]; + UserData = new long[MSECTORS, 2, 4 * 588]; + C2Count = new byte[MSECTORS, 294]; QData = new byte[MSECTORS, 16]; byte2long = new long[256]; for (long i = 0; i < 256; i++) @@ -287,6 +287,8 @@ namespace CUETools.Ripper.SCSI m_device.Close(); m_device = null; _toc = null; + _currentStart = -1; + _currentEnd = -1; } public void Dispose() @@ -511,33 +513,73 @@ namespace CUETools.Ripper.SCSI return found; } + //int dbg_pass; + //FileStream fs_d, fs_c; + private unsafe void ReorganiseSectors(int sector, int Sectors2Read) { int c2Size = _c2ErrorMode == Device.C2ErrorMode.None ? 0 : _c2ErrorMode == Device.C2ErrorMode.Mode294 ? 294 : 296; int oldSize = 4 * 588 + c2Size + (_subChannelMode == Device.SubChannelMode.None ? 0 : 16); - fixed (byte* readBuf = _readBuffer, qBuf = _subchannelBuffer, qData = QData) - fixed (long* userData = UserData, c2Data = C2Data) + fixed (byte* readBuf = _readBuffer, qBuf = _subchannelBuffer, qData = QData, c2Count = C2Count) + fixed (long* userData = UserData) { for (int iSector = 0; iSector < Sectors2Read; iSector++) { byte* sectorPtr = readBuf + iSector * oldSize; - long* userDataPtr = userData + (sector - _currentStart + iSector) * 4 * 588; - long* c2DataPtr = c2Data + (sector - _currentStart + iSector) * 294; + long* userDataPtr = userData + (sector - _currentStart + iSector) * 8 * 588; + byte* c2CountPtr = c2Count + (sector - _currentStart + iSector) * 294; byte* qDataPtr = qData + (sector - _currentStart + iSector) * 16; - for (int sample = 0; sample < 4 * 588; sample++) - userDataPtr[sample] += byte2long[sectorPtr[sample]] * 3; + //if (_currentStart > 0) + //{ + // string nm_d = string.Format("Y:\\Temp\\dbg\\{0:x}-{1:00}.bin", _currentStart, dbg_pass); + // string nm_c = string.Format("Y:\\Temp\\dbg\\{0:x}-{1:00}.c2", _currentStart, dbg_pass); + // if (fs_d != null && fs_d.Name != nm_d) { fs_d.Close(); fs_d = null; } + // if (fs_c != null && fs_c.Name != nm_c) { fs_c.Close(); fs_c = null; } + // if (fs_d == null) fs_d = new FileStream(nm_d, FileMode.Create); + // if (fs_c == null) fs_c = new FileStream(nm_c, FileMode.Create); + // fs_d.Seek((sector - _currentStart + iSector) * 4 * 588, SeekOrigin.Begin); + // fs_d.Write(_readBuffer, iSector * oldSize, 4 * 588); + // fs_c.Seek((sector - _currentStart + iSector) * 296, SeekOrigin.Begin); + // fs_c.Write(_readBuffer, iSector * oldSize + 4 * 588, 296); + //} + if (_c2ErrorMode != Device.C2ErrorMode.None) { - for (int c2 = 0; c2 < 294; c2++) + int offs = 0; + if (c2Size == 296) { - byte c2val = sectorPtr[4 * 588 + c2Size - 294 + c2]; - c2DataPtr[c2] += byte2long[c2val]; - if (c2val != 0) - for (int b = 0; b < 8; b++) - if (((c2val >> b) & 1) != 0) - userDataPtr[c2 * 8 + b] += 0x0101010101010101 - byte2long[sectorPtr[c2 * 8 + b]] * 2; + // sometimes sector C2 byte is placed after C2 info, not before!! + int c2 = 0; + for (int pos = 2; pos < 294; pos++) + c2 |= sectorPtr[4 * 588 + pos]; + if (sectorPtr[4 * 588 + 294] == (c2 | sectorPtr[4 * 588 + 0] | sectorPtr[4 * 588 + 1])) + offs = 0; + else if (sectorPtr[4 * 588] == (c2 | sectorPtr[4 * 588 + 294] | sectorPtr[4 * 588 + 295])) + offs = 2; + else + throw new Exception("invalid C2 pointers"); } + for (int pos = 0; pos < 294; pos++) + { + int c2d = sectorPtr[4 * 588 + pos + offs]; + int c2 = ((-c2d) >> 31) & 1; + c2CountPtr[pos] += (byte)c2; + int sample = pos << 3; + userDataPtr[sample + c2 * 4 * 588] += byte2long[sectorPtr[sample]]; sample++; + userDataPtr[sample + c2 * 4 * 588] += byte2long[sectorPtr[sample]]; sample++; + userDataPtr[sample + c2 * 4 * 588] += byte2long[sectorPtr[sample]]; sample++; + userDataPtr[sample + c2 * 4 * 588] += byte2long[sectorPtr[sample]]; sample++; + userDataPtr[sample + c2 * 4 * 588] += byte2long[sectorPtr[sample]]; sample++; + userDataPtr[sample + c2 * 4 * 588] += byte2long[sectorPtr[sample]]; sample++; + userDataPtr[sample + c2 * 4 * 588] += byte2long[sectorPtr[sample]]; sample++; + userDataPtr[sample + c2 * 4 * 588] += byte2long[sectorPtr[sample]]; + } + } + else + { + for (int sample = 0; sample < 4 * 588; sample++) + userDataPtr[sample] += byte2long[sectorPtr[sample]] * 3; } if (_subChannelMode != Device.SubChannelMode.None) for (int qi = 0; qi < 16; qi++) @@ -551,10 +593,11 @@ namespace CUETools.Ripper.SCSI private unsafe void ClearSectors(int sector, int Sectors2Read) { - fixed (long* userData = &UserData[sector - _currentStart, 0], c2Data = &C2Data[sector - _currentStart, 0]) + fixed (long* userData = &UserData[sector - _currentStart, 0, 0]) + fixed (byte* c2Count = &C2Count[sector - _currentStart, 0]) { - ZeroMemory((byte*)userData, 8 * 4 * 588 * Sectors2Read); - ZeroMemory((byte*)c2Data, 4 * 588 * Sectors2Read); + ZeroMemory((byte*)userData, 8 * 2 * 4 * 588 * Sectors2Read); + ZeroMemory(c2Count, 294 * Sectors2Read); } } @@ -598,10 +641,8 @@ namespace CUETools.Ripper.SCSI if (FetchSectors(sector + iSector, 1, false, subchannel) != Device.CommandStatus.Success) { iErrors ++; - for (int i = 0; i < 4 * 588; i++) - UserData[sector + iSector - _currentStart, i] += 0x0101010101010101; for (int i = 0; i < 294; i++) - C2Data[sector + iSector - _currentStart, i] += 0x0101010101010101; + C2Count[sector + iSector - _currentStart, i] ++; for (int i = 0; i < 16; i++) QData[ sector + iSector - _currentStart, i] = 0; if (_debugMessages) @@ -745,8 +786,6 @@ namespace CUETools.Ripper.SCSI for (int iSector = 0; iSector < Sectors2Read; iSector++) { int pos = sector - _currentStart + iSector; - int avg = (pass + 1) * 3 / 2; - int er_limit = 2 + pass / 2; // allow 25% minority // avg - pass + 1 // p a l o // 0 1 1 2 @@ -755,23 +794,30 @@ namespace CUETools.Ripper.SCSI // 6 10 5 //16 25 10 bool fError = false; + const byte c2div = 128; + int er_limit = c2div * (1 + _correctionQuality) - 1; + // need at least 1 + _correctionQuality good passes for (int iPar = 0; iPar < 4 * 588; iPar++) { - long val = UserData[pos, iPar]; - byte c2 = (byte)(C2Data[pos, iPar >> 3] >> ((iPar & 7) * 8)); + long val = UserData[pos, 0, iPar]; + long val1 = UserData[pos, 1, iPar]; + byte c2 = C2Count[pos, iPar >> 3]; + int ave = (pass + 1 - c2) * c2div + c2; int bestValue = 0; for (int i = 0; i < 8; i++) { - int sum = avg - ((int)(val & 0xff)); + int sum = ave - 2 * (int)((val & 0xff) * c2div + (val1 & 0xff)); int sig = sum >> 31; // bit value fError |= (sum ^ sig) < er_limit; bestValue += sig & (1 << i); val >>= 8; } - _currentData[pos * 4 * 588 + iPar] = (byte)bestValue; + currentData.Bytes[pos * 4 * 588 + iPar] = (byte)bestValue; } - if (fError) - _currentErrorsCount++; + int newerr = (fError ? 1 : 0); + //_currentErrorsCount += newerr; + _currentErrorsCount += newerr - errtmp[pos]; + errtmp[pos] = newerr; if (markErrors) { _errors[sector + iSector] |= fError; @@ -781,6 +827,8 @@ namespace CUETools.Ripper.SCSI } + int[] errtmp = new int[MSECTORS]; + //private unsafe int CorrectSectorsTest(int start, int end, int c2Score, byte[] realData, int worstScan) //{ // int[] valueScore = new int[256]; @@ -837,14 +885,24 @@ namespace CUETools.Ripper.SCSI public unsafe void PrefetchSector(int iSector) { - if (_currentStart == MSECTORS * (iSector / MSECTORS)) + if (iSector >= _currentStart && iSector < _currentEnd) return; if (_readCDCommand == ReadCDCommand.Unknown && !TestReadCommand()) throw new Exception("failed to autodetect read command: " + _autodetectResult); _currentStart = MSECTORS * (iSector / MSECTORS); - _currentEnd = Math.Min(_currentStart + MSECTORS, (int)_toc.AudioLength); + _currentEnd = _currentStart + MSECTORS; + if (_currentEnd > (int)_toc.AudioLength) + { + _currentEnd = (int)_toc.AudioLength; + _currentStart = Math.Max(0, _currentEnd - MSECTORS); + } + + int neededSize = (_currentEnd - _currentStart) * 588; + if (currentData.Size < neededSize) + currentData.Prepare(new byte[neededSize * 4], neededSize); + currentData.Length = neededSize; //FileStream correctFile = new FileStream("correct.wav", FileMode.Open); //byte[] realData = new byte[MSECTORS * 4 * 588]; @@ -853,11 +911,15 @@ namespace CUETools.Ripper.SCSI // throw new Exception("read"); //correctFile.Close(); - int max_scans = 64; - for (int pass = 0; pass <= max_scans; pass++) + _currentErrorsCount = 0; + for (int i = 0; i < MSECTORS; i++) + errtmp[i] = 0; + + int max_scans = 16 << _correctionQuality; + for (int pass = 0; pass < max_scans; pass++) { +// dbg_pass = pass; DateTime PassTime = DateTime.Now, LastFetch = DateTime.Now; - _currentErrorsCount = 0; for (int sector = _currentStart; sector < _currentEnd; sector += m_max_sectors) { @@ -875,9 +937,9 @@ namespace CUETools.Ripper.SCSI if (pass == 0) ProcessSubchannel(sector, Sectors2Read, true); //DateTime LastFetched = DateTime.Now; - if ((pass & 1) == 0) + if (pass >= _correctionQuality) { - CorrectSectors(pass, sector, Sectors2Read, pass >= max_scans); + CorrectSectors(pass, sector, Sectors2Read, pass == max_scans - 1); PrintErrors(pass, sector, Sectors2Read, /*realData*/null); } //TimeSpan delay2 = DateTime.Now - LastFetched; @@ -889,7 +951,7 @@ namespace CUETools.Ripper.SCSI //System.Console.WriteLine(); //if (CorrectSectorsTest(start, _currentEnd, 10, realData) == 0) // break; - if ((pass & 1) == 0 && pass >= _correctionQuality && _currentErrorsCount == 0) + if (pass >= _correctionQuality && _currentErrorsCount == 0) break; } } @@ -917,8 +979,15 @@ namespace CUETools.Ripper.SCSI PrefetchSector(_sampleOffset / 588); buff.Length = Math.Min(buff.Length, (int)Length - _sampleOffset); buff.Length = Math.Min(buff.Length, _currentEnd * 588 - _sampleOffset); - fixed (byte* dest = buff.Bytes, src = &_currentData[(_sampleOffset - _currentStart * 588) * 4]) - AudioSamples.MemCpy(dest, src, buff.ByteLength); + if ((_sampleOffset - _currentStart * 588) == 0 && (maxLength < 0 || (_currentEnd - _currentStart) * 588 <= buff.Length)) + { + buff.Swap(currentData); + _currentStart = -1; + _currentEnd = -1; + } + else + fixed (byte* dest = buff.Bytes, src = ¤tData.Bytes[(_sampleOffset - _currentStart * 588) * 4]) + AudioSamples.MemCpy(dest, src, buff.ByteLength); _sampleOffset += buff.Length; return buff.Length; } @@ -982,7 +1051,9 @@ namespace CUETools.Ripper.SCSI _currentTrack = -1; _currentIndex = -1; _crcErrorsCount = 0; - _errorsCount = 0; + _errorsCount = 0; + _currentStart = -1; + _currentEnd = -1; _errors = new BitArray((int)_toc.AudioLength); // !!! _sampleOffset = (int)value + _driveOffset; } @@ -1017,6 +1088,8 @@ namespace CUETools.Ripper.SCSI } set { + if (value < 0 || value > 3) + throw new Exception("invalid CorrectionQuality"); _correctionQuality = value; } } @@ -1046,15 +1119,6 @@ namespace CUETools.Ripper.SCSI bcd &= 0x3f; return bcd >= ISRC6.Length ? '#' : ISRC6[bcd]; } - - public static char[] DrivesAvailable() - { - List result = new List(); - foreach (DriveInfo info in DriveInfo.GetDrives()) - if (info.DriveType == DriveType.CDRom) - result.Add(info.Name[0]); - return result.ToArray(); - } } enum ReadCDCommand diff --git a/CUETools.Ripper/CUETools.Ripper.csproj b/CUETools.Ripper/CUETools.Ripper.csproj index 3cc381a..6189b27 100644 --- a/CUETools.Ripper/CUETools.Ripper.csproj +++ b/CUETools.Ripper/CUETools.Ripper.csproj @@ -23,6 +23,7 @@ DEBUG;TRACE prompt 4 + true pdbonly diff --git a/CUETools.Ripper/Ripper.cs b/CUETools.Ripper/Ripper.cs index d90c41a..7356e13 100644 --- a/CUETools.Ripper/Ripper.cs +++ b/CUETools.Ripper/Ripper.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Collections; using System.Collections.Generic; using CUETools.CDImage; @@ -22,6 +23,18 @@ namespace CUETools.Ripper event EventHandler ReadProgress; } + public class CDDrivesList + { + public static char[] DrivesAvailable() + { + List result = new List(); + foreach (DriveInfo info in DriveInfo.GetDrives()) + if (info.DriveType == DriveType.CDRom) + result.Add(info.Name[0]); + return result.ToArray(); + } + } + public sealed class ReadProgressArgs : EventArgs { public int Position; diff --git a/CUETools/CUETools.sln b/CUETools/CUETools.sln index eb1e14b..69035cc 100644 --- a/CUETools/CUETools.sln +++ b/CUETools/CUETools.sln @@ -153,6 +153,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.CDRepair", "..\CUE EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CUETools.CTDB", "..\CUETools.CTDB\CUETools.CTDB.csproj", "{AA2A9A7E-45FB-4632-AD85-85B0E556F818}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProgressODoom", "..\ProgressODoom\ProgressODoom.csproj", "{8DD1E84B-0B03-4C0B-9B42-1E49F75E7CB1}" +EndProject Global GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = CUETools1.vsmdi @@ -560,6 +562,14 @@ Global {AA2A9A7E-45FB-4632-AD85-85B0E556F818}.Release|Any CPU.Build.0 = Release|Any CPU {AA2A9A7E-45FB-4632-AD85-85B0E556F818}.Release|Win32.ActiveCfg = Release|Any CPU {AA2A9A7E-45FB-4632-AD85-85B0E556F818}.Release|x64.ActiveCfg = Release|Any CPU + {8DD1E84B-0B03-4C0B-9B42-1E49F75E7CB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8DD1E84B-0B03-4C0B-9B42-1E49F75E7CB1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8DD1E84B-0B03-4C0B-9B42-1E49F75E7CB1}.Debug|Win32.ActiveCfg = Debug|Any CPU + {8DD1E84B-0B03-4C0B-9B42-1E49F75E7CB1}.Debug|x64.ActiveCfg = Debug|Any CPU + {8DD1E84B-0B03-4C0B-9B42-1E49F75E7CB1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8DD1E84B-0B03-4C0B-9B42-1E49F75E7CB1}.Release|Any CPU.Build.0 = Release|Any CPU + {8DD1E84B-0B03-4C0B-9B42-1E49F75E7CB1}.Release|Win32.ActiveCfg = Release|Any CPU + {8DD1E84B-0B03-4C0B-9B42-1E49F75E7CB1}.Release|x64.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/CUETools/TestRipper/CDDriveReaderTest.cs b/CUETools/TestRipper/CDDriveReaderTest.cs index 584fc6c..da7dc22 100644 --- a/CUETools/TestRipper/CDDriveReaderTest.cs +++ b/CUETools/TestRipper/CDDriveReaderTest.cs @@ -1,5 +1,6 @@ using System; using System.Text; +using System.IO; using System.Collections.Generic; using CUETools.Codecs; using CUETools.Ripper; @@ -36,19 +37,17 @@ namespace TestRipper } } - const int pass = 16; - const int Sectors2Read = 10000; - const int bit_weight = 3; - const int c2_weight = 1; + const int max_pass = 64; + const int Sectors2Read = 2400; bool markErrors = true; int _currentStart = 0, _realErrors = 0; byte[] _currentData = new byte[Sectors2Read * 4 * 588]; - static long[,] UserData = new long[Sectors2Read, 4 * 588]; - static long[,] C2Data = new long[Sectors2Read, 4 * 588 / 8]; + static ulong[,,] UserData = new ulong[Sectors2Read, 2, 4 * 588]; + static byte[,] C2Count = new byte[Sectors2Read, 4 * 588]; static byte[] _realData = new byte[Sectors2Read * 4 * 588]; - static long[] byte2long = new long[256]; + static ulong[] byte2long = new ulong[256]; #region Additional test attributes // @@ -58,30 +57,58 @@ namespace TestRipper [ClassInitialize()] public static void MyClassInitialize(TestContext testContext) { - for (long i = 0; i < 256; i++) + for (ulong i = 0; i < 256; i++) { - long bl = 0; + ulong bl = 0; for (int b = 0; b < 8; b++) bl += ((i >> b) & 1) << (b << 3); byte2long[i] = bl; } - Random rnd = new Random(2314); - rnd.NextBytes(_realData); + //Random rnd = new Random(2314); + //rnd.NextBytes(_realData); - for (int p = 0; p <= pass; p++) - for (int iSector = 0; iSector < Sectors2Read; iSector++) - for (int iPar = 0; iPar < 4 * 588; iPar++) + byte [] c2data = new byte[Sectors2Read * 296]; + for (int p = 0; p < max_pass; p++) + { + // string nm_d = string.Format("Y:\\Temp\\dbg\\{0:x}-{1:00}.bin", _currentStart, dbg_pass); + using (FileStream fs = new FileStream(string.Format("Y:\\Temp\\dbg\\960\\960-{0:00}.bin", p), FileMode.Open)) + using (FileStream fs2 = new FileStream(string.Format("Y:\\Temp\\dbg\\960\\960-{0:00}.c2", p), FileMode.Open)) + { + fs.Read(_realData, 0, Sectors2Read * 4 * 588); + fs2.Read(c2data, 0, Sectors2Read * 296); + for (int iSector = 0; iSector < Sectors2Read; iSector++) { - bool error = rnd.NextDouble() < 0.2; - byte val = error ? (byte)rnd.Next(255) : _realData[iSector * 4 * 588 + iPar]; - UserData[iSector, iPar] += byte2long[val] * bit_weight; - if (error && rnd.NextDouble() < 0.5) + for (int pos = 0; pos < 294; pos++) { - C2Data[iSector, iPar >> 3] += (iPar & 7) * 8; - UserData[iSector, iPar] += 0x0101010101010101 * (bit_weight / 2) + byte2long[val] * (c2_weight - bit_weight); + int c2d = c2data[iSector * 296 + pos]; + for (int sample = (pos << 3); sample < (pos << 3) + 8; sample++) + { + //int c2 = (c2d >> (7 - (sample & 7))) & 1; + //int c2 = (c2d >> ((sample & 7))) & 1; + //int c2 = ((c2d >> ((sample & 7))) | (c2d >> (7 - (sample & 7)))) & 1; + int c2 = ((-c2d) >> 31) & 1; + C2Count[iSector, sample] += (byte)c2; + UserData[iSector, c2, sample] += byte2long[_realData[iSector * 4 * 588 + sample]]; + } } } + } + //for (int iSector = 0; iSector < Sectors2Read; iSector++) + // for (int iPar = 0; iPar < 4 * 588; iPar++) + // { + // bool error = rnd.NextDouble() < 0.2; + // byte val = error ? (byte)rnd.Next(255) : _realData[iSector * 4 * 588 + iPar]; + // UserData[iSector, iPar] += byte2long[val] * bit_weight; + // if (error && rnd.NextDouble() < 0.5) + // { + // C2Data[iSector, iPar >> 3] += (iPar & 7) * 8; + // UserData[iSector, iPar] += 0x0101010101010101 * (bit_weight / 2) + byte2long[val] * (c2_weight - bit_weight); + // } + // } + } + using (FileStream fs = new FileStream(string.Format("Y:\\Temp\\dbg\\960\\960.bin", 0), FileMode.Open)) + fs.Read(_realData, 0, Sectors2Read * 4 * 588); } // //Use ClassCleanup to run code after all tests in a class have run @@ -114,36 +141,39 @@ namespace TestRipper { int _currentErrorsCount = 0; int sector = 0; - + _realErrors = 0; + const byte c2div = 128; + const int er_limit = c2div * 3; + int fErrCnt = 0; for (int iSector = 0; iSector < Sectors2Read; iSector++) { int pos = sector - _currentStart + iSector; - int avg = (pass + 1) * bit_weight / 2; - int c2_limit = pass / 3; // - int er_limit = avg - pass; // allow 33% minority for (int iPar = 0; iPar < 4 * 588; iPar++) { - long val = UserData[pos, iPar]; - byte c2 = (byte)(C2Data[pos, iPar >> 3] >> ((iPar & 7) * 8)); + ulong val = UserData[pos, 0, iPar]; + ulong val1 = 0;// UserData[pos, 1, iPar]; + byte c2 = C2Count[pos, iPar]; + int ave = (max_pass - c2) * c2div + c2; int bestValue = 0; + bool fError = false; for (int i = 0; i < 8; i++) { - int sum = avg - ((int)(val & 0xff)); - int sig = sum >> 31; // bit value - if ((sum ^ sig) < er_limit) _currentErrorsCount++; + int sum = ave - 2 * (int)((val & 0xff) * c2div + (val1 & 0xff)); + int sig = sum >> 31; + fError |= (sum ^ sig) < er_limit; bestValue += sig & (1 << i); val >>= 8; } + if (fError) + fErrCnt++; //if (c2 > c2_limit) //_currentErrorsCount++; _currentData[pos * 4 * 588 + iPar] = (byte)bestValue; + if (_realData[iSector * 4 * 588 + iPar] != bestValue) + _realErrors++; } } - for (int p = 0; p <= pass; p++) - for (int iSector = 0; iSector < Sectors2Read; iSector++) - for (int iPar = 0; iPar < 4 * 588; iPar++) - if (_realData[iSector * 4 * 588 + iPar] != _currentData[iSector * 4 * 588 + iPar]) - _realErrors++; + //Assert.AreEqual(0, fErrCnt); Assert.AreEqual(0, _realErrors, "0 != _realErrors; _currentErrorsCount == " + _currentErrorsCount.ToString()); //CollectionAssert.AreEqual(_realData, _currentData, "_realData != _currentData"); Assert.AreEqual(0, _currentErrorsCount, "_currentErrorsCount != 0"); diff --git a/CUETools/frmCUETools.cs b/CUETools/frmCUETools.cs index aa69769..fcbabe6 100644 --- a/CUETools/frmCUETools.cs +++ b/CUETools/frmCUETools.cs @@ -745,7 +745,7 @@ namespace JDP { } if (useCUEToolsDB) { - cueSheet.UseCUEToolsDB(); + cueSheet.UseCUEToolsDB(false, "CUETools 205"); } if (_batchPaths.Count == 0 && action == CUEAction.Encode) diff --git a/CUETools/frmCUETools.resx b/CUETools/frmCUETools.resx index 5924055..4a4a385 100644 --- a/CUETools/frmCUETools.resx +++ b/CUETools/frmCUETools.resx @@ -669,6 +669,9 @@ Fill + + NoControl + 3, 3 diff --git a/ProgressODoom/AbstractProgressBar.cs b/ProgressODoom/AbstractProgressBar.cs new file mode 100644 index 0000000..81af890 --- /dev/null +++ b/ProgressODoom/AbstractProgressBar.cs @@ -0,0 +1,223 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + public enum ProgressType { + Smooth, MarqueeWrap, MarqueeBounce, MarqueeBounceDeep, Animated + } + + /// + public abstract class AbstractProgressBar : Control { + protected int minimum = 0; + protected int maximum = 100; + protected int value = 0; + protected Rectangle borderbox; + protected Rectangle progressbox; + protected Rectangle backbox; + private bool showPercent = false; + private int padding = 0; + #region Marquee + protected ProgressType type = ProgressType.Smooth; + protected int marqueeSpeed = 30; + protected int marqueePercentage = 25; + protected int marqueeStep = 1; + #endregion + + protected EventHandler OnValueChanged; + /// + public event EventHandler ValueChanged { + add { + if (OnValueChanged != null) { + foreach (Delegate d in OnValueChanged.GetInvocationList()) { + if (object.ReferenceEquals(d, value)) { return; } + } + } + OnValueChanged = (EventHandler)Delegate.Combine(OnValueChanged, value); + } + remove { OnValueChanged = (EventHandler)Delegate.Remove(OnValueChanged, value); } + } + + public AbstractProgressBar() { + this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true); + } + + /// + [Category("Progress"), Description("Gets or sets whether or not to draw the percentage text"), Browsable(true)] + public bool ShowPercentage { + get { return showPercent; } + set { + showPercent = value; + Invalidate(); + if (!showPercent) { + this.Text = ""; + } + } + } + + /// + [Category("Progress"), Description("Gets or sets the minimum value"), Browsable(true)] + public virtual int Minimum { + get { return this.minimum; } + set { + if (value > maximum) { throw new ArgumentException("Minimum must be smaller than maximum."); } + this.minimum = value; + this.Invalidate(); + } + } + + /// + [Category("Progress"), Description("Gets or sets the maximum value"), Browsable(true)] + public virtual int Maximum { + get { return this.maximum; } + set { + if (value < minimum) { throw new ArgumentException("Maximum must be larger than minimum."); } + this.maximum = value; + this.Invalidate(); + } + } + + /// + [Category("Progress"), Description("Gets or sets the current value"), Browsable(true)] + public int Value { + get { return this.value; } + set { + if (value < minimum) { throw new ArgumentException("Value must be greater than or equal to minimum."); } + if (value > maximum) { throw new ArgumentException("Value must be less than or equal to maximum."); } + this.value = value; + if (showPercent) { + int percent = (int)(((float)this.value / (float)(this.maximum - 1f)) * 100f); + if (percent > 0) { + if (percent > 100) { percent = 100; } + this.Text = string.Format("{0}%", percent.ToString()); + } else { this.Text = ""; } + } + if (OnValueChanged != null) { + OnValueChanged(this, EventArgs.Empty); + } + ResizeProgress(); + this.Invalidate(); + } + } + + /// + [Category("Progress"), Description("Gets or sets the number of pixels to pad between the border and progress"), Browsable(true)] + public int ProgressPadding { + get { return this.padding; } + set { + this.padding = value; + if (OnValueChanged != null) { + OnValueChanged(this, EventArgs.Empty); + } + //ResizeProgress(); + OnResize(EventArgs.Empty); + this.Invalidate(); + } + } + + /// + [Category("Progress"), Description("Gets or sets the type of progress"), Browsable(true)] + public virtual ProgressType ProgressType { + get { return this.type; } + set { this.type = value; } + } + + #region Marquee + /// + [Category("Marquee"), Description("Gets or sets the number of milliseconds between marquee steps"), Browsable(true)] + public int MarqueeSpeed { + get { return this.marqueeSpeed; } + set { + this.marqueeSpeed = value; + if (this.marqueeSpeed < 10) { this.marqueeSpeed = 10; } + } + } + + /// + [Category("Marquee"), Description("Gets or sets the number of pixels to progress the marquee bar"), Browsable(true)] + public int MarqueeStep { + get { return this.marqueeStep; } + set { this.marqueeStep = value; } + } + + /// + [Category("Marquee"), Description("Gets or sets the percentage of the width that the marquee progress fills"), Browsable(true)] + public int MarqueePercentage { + get { return this.marqueePercentage; } + set { + if (value < 5 || value > 95) { + throw new ArgumentException("Marquee percentage width must be between 5% and 95%."); + } + this.marqueePercentage = value; + } + } + #endregion + + /// + [Browsable(false)] + public Rectangle BorderBox { + get { return this.borderbox; } + } + + /// + [Browsable(false)] + public Rectangle BackBox { + get { return this.backbox; } + } + + /// + [Browsable(false)] + public Rectangle ProgressBox { + get { return this.progressbox; } + } + + /// + /// + protected abstract void PaintBackground(Graphics gr); + + /// + /// + protected abstract void PaintProgress(Graphics gr); + + /// + /// + protected abstract void PaintText(Graphics gr); + + /// + /// + protected abstract void PaintBorder(Graphics gr); + + /// + protected abstract void ResizeProgress(); + + /// + /// + protected override void OnResize(EventArgs e) { + base.OnResize(e); + borderbox = new Rectangle(0, 0, this.Width - 1, this.Height - 1); + backbox = new Rectangle(0, 0, this.Width - 1, this.Height - 1); + ResizeProgress(); + } + + /// + /// + protected override void OnPaint(PaintEventArgs e) { + base.OnPaint(e); + PaintBackground(e.Graphics); + PaintProgress(e.Graphics); + e.Graphics.Clip = new Region(new Rectangle(0, 0, this.Width, this.Height)); + PaintText(e.Graphics); + PaintBorder(e.Graphics); + } + + /// + public abstract void MarqueeStart(); + /// + public abstract void MarqueePause(); + /// + public abstract void MarqueeStop(); + } +} \ No newline at end of file diff --git a/ProgressODoom/AbstractProgressPainter.cs b/ProgressODoom/AbstractProgressPainter.cs new file mode 100644 index 0000000..9b8ffb8 --- /dev/null +++ b/ProgressODoom/AbstractProgressPainter.cs @@ -0,0 +1,108 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + public abstract class AbstractProgressPainter : Component, IProgressPainter { + protected IGlossPainter gloss; + protected IProgressBorderPainter border; + internal int padding = 0; + + /// + [Category("Painters"), Description("Gets or sets the gloss painter chain"), Browsable(true)] + public IGlossPainter GlossPainter { + get { return this.gloss; } + set { + this.gloss = value; + if (this.gloss != null) { this.gloss.PropertiesChanged += new EventHandler(component_PropertiesChanged); } + FireChange(); + } + } + + /// + [Category("Painters"), Description("Gets or sets the border painter for this progress painter"), Browsable(true)] + public IProgressBorderPainter ProgressBorderPainter { + get { return this.border; } + set { + this.border = value; + if (this.gloss != null) { this.gloss.PropertiesChanged += new EventHandler(component_PropertiesChanged); } + FireChange(); + } + } + + /// + /// + /// + protected virtual void component_PropertiesChanged(object sender, EventArgs e) { + FireChange(); + } + + /// + /// + /// + public void PaintProgress(Rectangle box, Graphics gr) { + PaintThisProgress(box, gr); + //if (this.gloss != null && box.Width > 1) { + // Rectangle b = new Rectangle(box.X, box.Y, box.Width - 1, box.Height - 1); + // //gr.DrawRectangle(Pens.Red, b); + // this.gloss.PaintGloss(box, gr); + //} + if (this.border != null && box.Width > 1) { + int w = box.Width; + //if (padding > 0) { w += 3; } else { w += 1; } + //Rectangle b = new Rectangle(box.X - 1, box.Y - 1, w, box.Height + 3); + Rectangle b = new Rectangle(box.X, box.Y, box.Width - 1, box.Height - 1); + b.Inflate(1, 1); + this.border.PaintBorder(b, gr); + } + } + /// + /// + /// + protected abstract void PaintThisProgress(Rectangle box, Graphics gr); + + /// + /// + public virtual void Resize(Rectangle box) { + if (gloss != null) { gloss.Resize(box); } + if (border != null) { border.Resize(box); } + ResizeThis(box); + } + /// + /// + protected virtual void ResizeThis(Rectangle box) {} + + private EventHandler onPropertiesChanged; + /// + public event EventHandler PropertiesChanged { + add { + if (onPropertiesChanged != null) { + foreach (Delegate d in onPropertiesChanged.GetInvocationList()) { + if (object.ReferenceEquals(d, value)) { return; } + } + } + onPropertiesChanged = (EventHandler)Delegate.Combine(onPropertiesChanged, value); + } + remove { onPropertiesChanged = (EventHandler)Delegate.Remove(onPropertiesChanged, value); } + } + + /// + protected void FireChange() { + if (onPropertiesChanged != null) { onPropertiesChanged(this, EventArgs.Empty); } + } + + /// + /// + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + DisposeThis(disposing); + } + + /// + /// + protected virtual void DisposeThis(bool disposing) { + } + } +} \ No newline at end of file diff --git a/ProgressODoom/BarberPoleProgressPainter.cs b/ProgressODoom/BarberPoleProgressPainter.cs new file mode 100644 index 0000000..c99be80 --- /dev/null +++ b/ProgressODoom/BarberPoleProgressPainter.cs @@ -0,0 +1,139 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.BarberPoleProgressPainter), "Icons.BarberPoleProgressPainter.ico")] + public class BarberPoleProgressPainter : AbstractProgressPainter, IProgressPainter, IDisposable { + private Color baseColor; + private Color highlightColor; + private Color stripeColor; + private Color baseShadeColor; + private Color highlightShadeColor; + private Color stripeShadeColor; + private int shadeHeight; + private int stripeWidth; + private Image img; + private Rectangle box; + + /// + public BarberPoleProgressPainter() { + baseColor = Color.FromArgb(226, 138, 078); + highlightColor = Color.FromArgb(225, 132, 068); + stripeColor = Color.FromArgb(222, 123, 055); + baseShadeColor = Color.FromArgb(215, 097, 020); + highlightShadeColor = Color.FromArgb(213, 087, 007); + stripeShadeColor = Color.FromArgb(210, 078, 000); + } + + /// + [Category("Appearance"), Description("Gets or sets the base progress color"), Browsable(true)] + public Color Color { + get { return baseColor; } + set { + baseColor = value; + HSV baseHsv = new HSV(baseColor); + + bool change = false; + if (baseHsv.Saturation > 166) { baseHsv.Saturation = 166; change = true; } + if (baseHsv.Value > 239) { baseHsv.Value = 239; change = true; } + if (change) { baseColor = baseHsv.Color; } + + highlightColor = HSV.FromHsv(baseHsv.Hue, baseHsv.Saturation + 11, baseHsv.Value); + stripeColor = HSV.FromHsv(baseHsv.Hue, baseHsv.Saturation + 25, baseHsv.Value - 4); + + HSV shade = new HSV(baseHsv.Hue, baseHsv.Saturation + 65, baseHsv.Value - 11); + baseShadeColor = shade.Color; + highlightShadeColor = HSV.FromHsv(shade.Hue, shade.Saturation + 15, shade.Value - 2); + stripeShadeColor = HSV.FromHsv(shade.Hue, shade.Saturation + 24, shade.Value - 5); + + try { if (box != null) { RepaintImage(box); } } catch { } + FireChange(); + } + } + + private void RepaintImage(Rectangle box) { + if (box.Width == 0 || box.Height == 0) { img = null; return; } + img = new Bitmap(box.Width - (box.X * 2), box.Height - (box.Y * 2)); + Bitmap tile = new Bitmap(img.Height * 2, img.Height); + + shadeHeight = (int)((double)box.Height * 0.4D); + stripeWidth = box.Height; + + using (Graphics g = Graphics.FromImage(tile)) { + g.FillRectangle(new SolidBrush(baseColor), 0, 0, tile.Width, tile.Height); + g.FillRectangle(new SolidBrush(baseShadeColor), 0, tile.Height - shadeHeight, tile.Width, tile.Height); + + Pen highlightPen = new Pen(new SolidBrush(highlightColor), 1f); + Pen highlightShadePen = new Pen(new SolidBrush(highlightShadeColor), 1f); + Pen stripePen = new Pen(new SolidBrush(stripeColor), 1f); + Pen stripeShadePen = new Pen(new SolidBrush(stripeShadeColor), 1f); + + for (int y = 0; y < stripeWidth; y++) { + if (y < tile.Height - shadeHeight) { + g.DrawLine(highlightPen, stripeWidth - y - 1, y, (stripeWidth * 2) - y + 1, y); + g.DrawLine(stripePen, stripeWidth - y, y, (stripeWidth * 2) - y, y); + } else { + g.DrawLine(highlightShadePen, stripeWidth - y - 1, y, (stripeWidth * 2) - y + 1, y); + g.DrawLine(stripeShadePen, stripeWidth - y, y, (stripeWidth * 2) - y, y); + } + } + } + + int x = box.X; + using (Graphics i = Graphics.FromImage(img)) { + while (true) { + if (x > img.Width) { break; } + i.DrawImageUnscaled(tile, x, box.Y); + x += tile.Width; + } + } + + tile.Dispose(); + } + private Point Offset(Point p, int x, int y) { + return new Point(p.X + x, p.Y + y); + } + + /// + /// + /// + protected override void PaintThisProgress(Rectangle box, Graphics g) { + try { + box.Width -= 1; + box.Height -= 1; + } catch { } + if (box.Width <= 1) { return; } + + if (img == null) { RepaintImage(box); } + Rectangle off = new Rectangle(box.Location, box.Size); + off.Offset(box.Right - img.Width, 0); + g.DrawImageUnscaled(img, off); + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + + /// + /// + protected override void ResizeThis(Rectangle box) { + this.box = box; + try { + box.Width -= 1; + box.Height -= 1; + } catch {} + shadeHeight = (int)((double)box.Height * 0.4D); + stripeWidth = box.Height; + RepaintImage(box); + } + + /// + protected override void DisposeThis(bool disposing) { + if (img != null) { img.Dispose(); } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/BevelledGradientProgressPainter.cs b/ProgressODoom/BevelledGradientProgressPainter.cs new file mode 100644 index 0000000..33dbc66 --- /dev/null +++ b/ProgressODoom/BevelledGradientProgressPainter.cs @@ -0,0 +1,118 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.BevelledGradientProgressPainter), "Icons.BevelledGradientProgressPainter.ico")] + public class BevelledGradientProgressPainter : AbstractProgressPainter, IProgressPainter, IDisposable { + private ColorRange min; + private ColorRange max; + + /// + public BevelledGradientProgressPainter() { + this.MinColor = Color.Cornsilk; + this.MaxColor = Color.Gold; + } + + /// + /// + /// + public BevelledGradientProgressPainter(Color min, Color max) { + this.MinColor = min; + this.MaxColor = max; + } + + /// + [Category("Appearance"), Description("Gets or sets the left progress color"), Browsable(true)] + public Color MinColor { + get { return min.BaseColor; } + set { + min = new ColorRange(value); + FireChange(); + } + } + + /// + [Category("Appearance"), Description("Gets or sets the right progress color"), Browsable(true)] + public Color MaxColor { + get { return max.BaseColor; } + set { + max = new ColorRange(value); + FireChange(); + } + } + + /// + /// + /// + protected override void PaintThisProgress(Rectangle box, Graphics g) { + try { + box.Height -= 1; + box.Width -= 1; + } catch { } + + if (box.Width < 2) { return; } + + Point left = new Point(box.X, box.Y); + Point right = new Point(box.Right, box.Y); + Brush bottomOuter = new System.Drawing.Drawing2D.LinearGradientBrush(left, right, min.Darker, max.Darker); + Brush bottomInner = new System.Drawing.Drawing2D.LinearGradientBrush(left, right, min.Dark, max.Dark); + Brush topInner = new System.Drawing.Drawing2D.LinearGradientBrush(left, right, min.Light, max.Light); + Brush topOuter = new System.Drawing.Drawing2D.LinearGradientBrush(left, right, min.Lighter, max.Lighter); + Brush fill = new System.Drawing.Drawing2D.LinearGradientBrush(left, right, min.BaseColor, max.BaseColor); + + // fill box + g.FillRectangle(fill, box); + + using (Pen p = new Pen(topInner, 1)) { + // inner top + g.DrawLine(p, box.X + 1, box.Y + 1, box.Right - 1, box.Y + 1); + } + using (Pen p = new Pen(min.Light, 1)) { + // inner left + g.DrawLine(p, box.X + 1, box.Y + 1, box.X + 1, box.Bottom - 1); + } + + using (Pen p = new Pen(topOuter, 1)) { + // outer top + g.DrawLine(p, box.X, box.Y, box.Right, box.Y); + } + using (Pen p = new Pen(min.Lighter, 1)) { + // outer left + g.DrawLine(p, box.X, box.Y, box.X, box.Bottom); + } + + // draw border + using (Pen p = new Pen(bottomInner, 1)) { + // inner bottom + g.DrawLine(p, box.X + 1, box.Bottom - 1, box.Right - 1, box.Bottom - 1); + } + using (Pen p = new Pen(max.Dark, 1)) { + // inner right + g.DrawLine(p, box.Right - 1, box.Y + 1, box.Right - 1, box.Bottom - 1); + } + + using (Pen p = new Pen(bottomOuter, 1)) { + // outer bottom + g.DrawLine(p, box.X, box.Bottom, box.Right, box.Bottom); + } + using (Pen p = new Pen(max.Darker, 1)) { + // outer right + g.DrawLine(p, box.Right, box.Y, box.Right, box.Bottom); + } + + bottomOuter.Dispose(); + bottomInner.Dispose(); + topInner.Dispose(); + topOuter.Dispose(); + fill.Dispose(); + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/BevelledProgressPainter.cs b/ProgressODoom/BevelledProgressPainter.cs new file mode 100644 index 0000000..a66389f --- /dev/null +++ b/ProgressODoom/BevelledProgressPainter.cs @@ -0,0 +1,91 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.BevelledProgressPainter), "Icons.BevelledProgressPainter.ico")] + public class BevelledProgressPainter : AbstractProgressPainter, IProgressPainter, IDisposable { + private ColorRange bender; + + /// + public BevelledProgressPainter() { + this.Color = Color.FromArgb(151, 151, 234); + } + + /// + /// + public BevelledProgressPainter(Color color) { + this.Color = color; + } + + /// + [Category("Appearance"), Description("Gets or sets the base progress color"), Browsable(true)] + public Color Color { + get { return bender.BaseColor; } + set { + bender = new ColorRange(value); + FireChange(); + } + } + + /// + /// + /// + protected override void PaintThisProgress(Rectangle box, Graphics g) { + if (box.Width < 2) { return; } + g.PageUnit = GraphicsUnit.Pixel; + + // fill box + Rectangle back = new Rectangle(box.X, box.Y, box.Width, box.Height); + try { + back.Height -= 1; + back.Width -= 1; + } catch { } + using (SolidBrush b = new SolidBrush(bender.BaseColor)) { + g.FillRectangle(b, back); + } + + box = new Rectangle(box.X, box.Y, box.Width - 1, box.Height - 1); + + using (Pen p = new Pen(bender.Light, 1)) { + // inner top + g.DrawLine(p, box.X + 1, box.Y + 1, box.Right - 1, box.Y + 1); + // inner left + g.DrawLine(p, box.X + 1, box.Y + 1, box.X + 1, box.Bottom - 1); + } + + using (Pen p = new Pen(bender.Lighter, 1)) { + // outer top + g.DrawLine(p, box.X, box.Y, box.Right, box.Y); + // outer left + g.DrawLine(p, box.X, box.Y, box.X, box.Bottom); + } + + // draw border + using (Pen p = new Pen(bender.Dark, 1)) { + // inner bottom + g.DrawLine(p, box.X + 1, box.Bottom - 1, box.Right - 1, box.Bottom - 1); + // inner right + g.DrawLine(p, box.Right - 1, box.Y + 1, box.Right - 1, box.Bottom - 1); + + //g.DrawRectangle(p, box.X + 1, box.Y + 1, box.Width - 3, box.Height - 3); + } + + using (Pen p = new Pen(bender.Darker, 1)) { + // outer bottom + g.DrawLine(p, box.X, box.Bottom, box.Right, box.Bottom); + // outer right + g.DrawLine(p, box.Right, box.Y, box.Right, box.Bottom); + + //g.DrawRectangle(p, box.X, box.Y, box.Width - 1, box.Height - 1); + } + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/CandyCane.png b/ProgressODoom/CandyCane.png new file mode 100644 index 0000000..8b48247 Binary files /dev/null and b/ProgressODoom/CandyCane.png differ diff --git a/ProgressODoom/CandyCaneBackgroundPainter.cs b/ProgressODoom/CandyCaneBackgroundPainter.cs new file mode 100644 index 0000000..bee5250 --- /dev/null +++ b/ProgressODoom/CandyCaneBackgroundPainter.cs @@ -0,0 +1,123 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.CandyCaneBackgroundPainter), "Icons.CandyCaneBackgroundPainter.ico")] + public class CandyCaneBackgroundPainter : Component, IProgressBackgroundPainter, IDisposable { + private Image img; + private Rectangle box; + private IGlossPainter gloss; + + private EventHandler onPropertiesChanged; + /// + public event EventHandler PropertiesChanged { + add { + if (onPropertiesChanged != null) { + foreach (Delegate d in onPropertiesChanged.GetInvocationList()) { + if (object.ReferenceEquals(d, value)) { return; } + } + } + onPropertiesChanged = (EventHandler)Delegate.Combine(onPropertiesChanged, value); + } + remove { onPropertiesChanged = (EventHandler)Delegate.Remove(onPropertiesChanged, value); } + } + + private void FireChange() { + if (onPropertiesChanged != null) { onPropertiesChanged(this, EventArgs.Empty); } + } + + /// + /// + /// + protected virtual void component_PropertiesChanged(object sender, EventArgs e) { + FireChange(); + } + + /// + [Category("Painters"), Description("Gets or sets the chain of gloss painters"), Browsable(true)] + public IGlossPainter GlossPainter { + get { return this.gloss; } + set { + this.gloss = value; + if (this.gloss != null) { this.gloss.PropertiesChanged += new EventHandler(component_PropertiesChanged); } + FireChange(); + } + } + + /// + /// + /// + public void PaintBackground(Rectangle box, Graphics g) { + if (img == null) { + Resize(box); + } + g.DrawImageUnscaled(img, box.X, box.Y); + //g.FillRectangle(brush, box); + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + + /// + public void Resize(Rectangle box) { + this.box = box; + RepaintImage(box); + } + + /// + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + if (img != null) { + img.Dispose(); + } + } + + private void RepaintImage(Rectangle box) { + Bitmap source = BuildTile(box.Width); + img = new Bitmap(box.Width, box.Height); + using (Graphics g = Graphics.FromImage(img)) { + g.DrawImage(source, 0, 0, box.Width, box.Height + 1); // box + } + source.Dispose(); + + //Bitmap source = BuildTile(); + //Bitmap tile = new Bitmap((int)(((float)box.Height * (float)source.Width) / (float)source.Height), box.Height); + //using (Graphics g = Graphics.FromImage(tile)) { + // g.DrawImage(source, 0, 0, tile.Width, tile.Height); + //} + //source.Dispose(); + + //img = new Bitmap(box.Width, box.Height); + //using (Graphics g = Graphics.FromImage(img)) { + // int i = 0; + // while (i < box.Width) { + // g.DrawImageUnscaled(tile, i, 0); + // i += tile.Width; + // } + //} + } + + private Bitmap BuildTile(int width) { + Bitmap bmp = new Bitmap(width, 9); + Graphics g = Graphics.FromImage(bmp); + + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(245, 245, 245))), new Point(0, 0), new Point(width - 1, 0)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(236, 236, 236))), new Point(0, 1), new Point(width - 1, 1)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(234, 234, 235))), new Point(0, 2), new Point(width - 1, 2)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(234, 234, 235))), new Point(0, 3), new Point(width - 1, 3)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(222, 222, 222))), new Point(0, 4), new Point(width - 1, 4)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(229, 229, 230))), new Point(0, 5), new Point(width - 1, 5)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(239, 239, 239))), new Point(0, 6), new Point(width - 1, 6)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(247, 247, 247))), new Point(0, 7), new Point(width - 1, 7)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(254, 254, 255))), new Point(0, 8), new Point(width - 1, 8)); + + g.Dispose(); + return bmp; + } + } +} \ No newline at end of file diff --git a/ProgressODoom/CandyCaneProgressPainter.cs b/ProgressODoom/CandyCaneProgressPainter.cs new file mode 100644 index 0000000..389fe2f --- /dev/null +++ b/ProgressODoom/CandyCaneProgressPainter.cs @@ -0,0 +1,164 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.CandyCaneProgressPainter), "Icons.CandyCaneProgressPainter.ico")] + public class CandyCaneProgressPainter : AbstractProgressPainter, IProgressPainter, IDisposable { + private Color baseColor; + private Image img; + private Rectangle box; + + /// + public CandyCaneProgressPainter() { + baseColor = Color.FromArgb(049, 129, 222); + } + + /// + [Category("Appearance"), Description("Gets or sets the base progress color"), Browsable(true)] + public Color Color { + get { return baseColor; } + set { + baseColor = value; + try { if (box != null) { RepaintImage(box); } } catch { } + FireChange(); + } + } + + private void RepaintImage(Rectangle box) { + this.box = box; + this.img = new Bitmap(box.Width, box.Height); + // BuildTile() then resize it to fix the box.Height, then tile it. + Bitmap source = BuildTile(this.baseColor); + img = new Bitmap((int)(((float)box.Height * (float)source.Width) / (float)source.Height), box.Height + 1); + using (Graphics g = Graphics.FromImage(img)) { + g.DrawImage(source, 0, 0, img.Width, img.Height + 1); + } + + source.Dispose(); + } + private Point Offset(Point p, int x, int y) { + return new Point(p.X + x, p.Y + y); + } + + /// + /// + /// + protected override void PaintThisProgress(Rectangle box, Graphics g) { + if (img == null) { RepaintImage(box); } + if (box.Width <= 1) { return; } + + int x = box.Width - img.Width; + while (x > (0 - img.Width)) { + g.DrawImageUnscaled(img, x, 0); + x -= img.Width; + } + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + + /// + /// + protected override void ResizeThis(Rectangle box) { + this.box = box; + RepaintImage(box); + } + + /// + protected override void DisposeThis(bool disposing) { + if (img != null) { + img.Dispose(); + } + } + + public Bitmap BuildTile(Color color) { + HSV clr = new HSV(color); + Bitmap src = GetSource(); + Bitmap bmp = new Bitmap(src.Width, src.Height); + for (int x = 0; x < bmp.Width; x++) { + for (int y = 0; y < bmp.Height; y++) { + Color original = src.GetPixel(x, y); + Color altered = Color.FromArgb(0, 255, 255, 255); + HSV orighsv = new HSV(original); + Color origrgb = orighsv.Color; + origrgb = Color.FromArgb(original.A, origrgb.R, origrgb.G, origrgb.B); + if (!origrgb.Equals(altered)) { + orighsv.Hue = clr.Hue; + //orighsv.Saturation = clr.Saturation; + //orighsv.Value = clr.Value; + altered = orighsv.Color; + altered = Color.FromArgb(original.A, altered.R, altered.G, altered.B); + } + bmp.SetPixel(x, y, altered); + } + } + src.Dispose(); + return bmp; + } + private Bitmap GetSource() { + Bitmap bmp = new Bitmap(16, 9); + Graphics g = Graphics.FromImage(bmp); + g.Clear(Color.FromArgb(0, 255, 255, 255)); + + bmp.SetPixel(0, 0, Color.FromArgb(77, 140, 177, 225)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(140, 177, 225))), new Point(1, 0), new Point(7, 0)); + bmp.SetPixel(8, 0, Color.FromArgb(77, 140, 177, 225)); + + bmp.SetPixel(0, 1, Color.FromArgb(38, 99, 158, 222)); + bmp.SetPixel(1, 1, Color.FromArgb(128, 99, 158, 222)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(99, 158, 222))), new Point(2, 1), new Point(8, 1)); + bmp.SetPixel(9, 1, Color.FromArgb(64, 99, 158, 222)); + + bmp.SetPixel(1, 2, Color.FromArgb(38, 94, 156, 222)); + bmp.SetPixel(2, 2, Color.FromArgb(205, 94, 156, 222)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(94, 156, 222))), new Point(3, 2), new Point(8, 2)); + bmp.SetPixel(9, 2, Color.FromArgb(192, 94, 156, 222)); + bmp.SetPixel(10, 2, Color.FromArgb(38, 94, 156, 222)); + + bmp.SetPixel(2, 3, Color.FromArgb(77, 93, 158, 228)); + bmp.SetPixel(3, 3, Color.FromArgb(251, 93, 158, 228)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(93, 158, 228))), new Point(4, 3), new Point(9, 3)); + bmp.SetPixel(10, 3, Color.FromArgb(154, 93, 158, 228)); + bmp.SetPixel(11, 3, Color.FromArgb(26, 93, 158, 228)); + + bmp.SetPixel(2, 4, Color.FromArgb(13, 49, 129, 222)); + bmp.SetPixel(3, 4, Color.FromArgb(51, 49, 129, 222)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(49, 129, 222))), new Point(4, 4), new Point(9, 4)); + bmp.SetPixel(10, 4, Color.FromArgb(251, 49, 129, 222)); + bmp.SetPixel(11, 4, Color.FromArgb(90, 49, 129, 222)); + + bmp.SetPixel(3, 5, Color.FromArgb(64, 81, 159, 247)); + bmp.SetPixel(4, 5, Color.FromArgb(205, 81, 159, 247)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(81, 159, 247))), new Point(5, 5), new Point(10, 5)); + bmp.SetPixel(11, 5, Color.FromArgb(218, 81, 159, 247)); + bmp.SetPixel(12, 5, Color.FromArgb(77, 81, 159, 247)); + + bmp.SetPixel(4, 6, Color.FromArgb(77, 110, 186, 255)); + bmp.SetPixel(5, 6, Color.FromArgb(243, 110, 186, 255)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(110, 186, 255))), new Point(6, 6), new Point(11, 6)); + bmp.SetPixel(12, 6, Color.FromArgb(154, 110, 186, 255)); + bmp.SetPixel(13, 6, Color.FromArgb(38, 110, 186, 255)); + + bmp.SetPixel(4, 7, Color.FromArgb(26, 121, 201, 255)); + bmp.SetPixel(5, 7, Color.FromArgb(141, 121, 201, 255)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(121, 201, 255))), new Point(6, 7), new Point(12, 7)); + bmp.SetPixel(13, 7, Color.FromArgb(102, 121, 201, 255)); + bmp.SetPixel(14, 7, Color.FromArgb(26, 121, 201, 255)); + + bmp.SetPixel(5, 8, Color.FromArgb(26, 135, 227, 255)); + bmp.SetPixel(6, 8, Color.FromArgb(192, 135, 227, 255)); + g.DrawLine(new Pen(new SolidBrush(Color.FromArgb(135, 227, 255))), new Point(7, 8), new Point(12, 8)); + bmp.SetPixel(13, 8, Color.FromArgb(243, 135, 227, 255)); + bmp.SetPixel(14, 8, Color.FromArgb(64, 135, 227, 255)); + bmp.SetPixel(15, 8, Color.FromArgb(13, 135, 227, 255)); + + g.Dispose(); + return bmp; + } + } +} \ No newline at end of file diff --git a/ProgressODoom/ChainedGlossPainter.cs b/ProgressODoom/ChainedGlossPainter.cs new file mode 100644 index 0000000..b6c66d8 --- /dev/null +++ b/ProgressODoom/ChainedGlossPainter.cs @@ -0,0 +1,84 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// Extending this class allows you to chain multiple IGlossPainters together. + public abstract class ChainedGlossPainter : Component, IGlossPainter, IDisposable { + private IGlossPainter successor = null; + + /// + [Category("Painters"), Description("Gets or sets the next gloss in the chain"), Browsable(true)] + public IGlossPainter Successor { + get { return successor; } + set { + IGlossPainter nextPainter = value; + while (nextPainter != null && nextPainter is ChainedGlossPainter) { + if (object.ReferenceEquals(this, nextPainter)) { + throw new ArgumentException("Gloss cannot eventually be it's own successor, an infinite loop will result"); + } + nextPainter = ((ChainedGlossPainter)nextPainter).Successor; + } + + successor = value; + if (successor != null) { + successor.PropertiesChanged += new EventHandler(successor_PropertiesChanged); + } + FireChange(); + } + } + private void successor_PropertiesChanged(object sender, EventArgs e) { + FireChange(); + } + + private EventHandler onPropertiesChanged; + /// + public event EventHandler PropertiesChanged { + add { + if (onPropertiesChanged != null) { + foreach (Delegate d in onPropertiesChanged.GetInvocationList()) { + if (object.ReferenceEquals(d, value)) { return; } + } + } + onPropertiesChanged = (EventHandler)Delegate.Combine(onPropertiesChanged, value); + } + remove { onPropertiesChanged = (EventHandler)Delegate.Remove(onPropertiesChanged, value); } + } + + /// + protected void FireChange() { + if (onPropertiesChanged != null) { onPropertiesChanged(this, EventArgs.Empty); } + } + + /// + /// + /// + public void PaintGloss(Rectangle box, Graphics g) { + if (box.Width < 1) { return; } + PaintThisGloss(box, g); + if (successor != null) { successor.PaintGloss(box, g); } + } + + /// + /// + /// + protected abstract void PaintThisGloss(Rectangle box, Graphics g); + + /// + /// + public void Resize(Rectangle box) { + ResizeThis(box); + if (successor != null) { successor.Resize(box); } + } + + protected abstract void ResizeThis(Rectangle box); + + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + if (successor != null) { successor.Dispose(); } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/ColorTools.cs b/ProgressODoom/ColorTools.cs new file mode 100644 index 0000000..6b577ee --- /dev/null +++ b/ProgressODoom/ColorTools.cs @@ -0,0 +1,285 @@ +using System; +using System.ComponentModel; +using System.Drawing; + +namespace ProgressODoom { + /// + public class ColorUtility { + static ColorUtility() { + } + + /// + /// + /// + public static Color ReverseColor(Color c) { + return Color.FromArgb(ReverseInt(c.R), ReverseInt(c.G), ReverseInt(c.B)); + } + + private static int ReverseInt(int x) { + int val = x - 255; + if (val < 0) { val = val * -1; } + return val; + } + + /// + /// + /// + public static string ToHexString(Color c) { + string hex = string.Empty; + hex += DoHex(c.R); + hex += DoHex(c.G); + hex += DoHex(c.B); + return "#" + hex; + } + + private static string DoHex(int xor) { + string hex = xor.ToString("x"); + if (xor < 16) { + hex = "0" + hex; + } + if (xor == 0) { + hex = "00"; + } + return hex.ToUpper(); + } + + private static int DeHex(string input) { + int val; + int result = 0; + for (int i = 0; i < input.Length; i++) { + string chunk = input.Substring(i, 1).ToUpper(); + switch (chunk) { + case "A": + val = 10; break; + case "B": + val = 11; break; + case "C": + val = 12; break; + case "D": + val = 13; break; + case "E": + val = 14; break; + case "F": + val = 15; break; + default: + val = int.Parse(chunk); break; + } + if (i == 0) { + result += val * 16; + } else { + result += val; + } + } + return result; + } + } + + // System.Drawing.Drawing2D.ColorBlend + /// + public class ColorBlender { + private Color colorleft; + private Color colorright; + private int steps; + + private float step; + private float stepsize; + + /// + /// + /// + /// + public ColorBlender(int numberofsteps, Color one, Color two) { + steps = numberofsteps; + colorleft = one; + colorright = two; + stepsize = 1.0f / Convert.ToSingle(steps); + step = 0; + } + + /// + /// + public bool HasNext() { + return step < 1; + } + + /// + /// + public Color Next() { + if (!HasNext()) { throw new Exception("Past threshold."); } + step += stepsize; + return Morph(step, colorleft, colorright); + } + + /// + /// + /// + /// + /// + public Color Morph(float ratio, Color c1, Color c2) { + int r = (int)(c1.R + ratio * (c2.R - c1.R)); + int g = (int)(c1.G + ratio * (c2.G - c1.G)); + int b = (int)(c1.B + ratio * (c2.B - c1.B)); + return Color.FromArgb(r, g, b); + } + } + + /// + public struct ColorRange { + /// + public Color Light; + /// + public Color Lighter; + /// + public Color BaseColor; + /// + public Color Dark; + /// + public Color Darker; + + /// + /// + public ColorRange(Color color) { + BaseColor = color; + Light = ColorRange.Tint(0.6f, color); + Lighter = ColorRange.Tint(0.3f, color); + Dark = ColorRange.Shade(0.8f, color); + Darker = ColorRange.Shade(0.6f, color); + } + + /// + /// + /// + /// + public ColorRange(Color color, float lightratio, float lighterratio) { + BaseColor = color; + Light = ColorRange.Tint(lightratio, color); + Lighter = ColorRange.Tint(lighterratio, color); + Dark = ColorRange.Shade(lightratio, color); + Darker = ColorRange.Shade(lighterratio, color); + } + + /// + /// + /// + /// + /// + /// + public ColorRange(Color color, float lightratio, float lighterratio, float darkratio, float darkerratio) { + BaseColor = color; + Light = ColorRange.Tint(lightratio, color); + Lighter = ColorRange.Tint(lighterratio, color); + Dark = ColorRange.Shade(darkratio, color); + Darker = ColorRange.Shade(darkerratio, color); + } + + /// + /// + /// + /// + public static Color Tint(float ratio, Color c1) { + return Morph(ratio, Color.White, c1); + } + + /// + /// + /// + /// + public static Color Shade(float ratio, Color c1) { + return Morph(ratio, Color.Black, c1); + } + + /// + /// + /// + /// + /// + public static Color Morph(float ratio, Color c1, Color c2) { + int r = (int)(c1.R + ratio * (c2.R - c1.R)); + int g = (int)(c1.G + ratio * (c2.G - c1.G)); + int b = (int)(c1.B + ratio * (c2.B - c1.B)); + return Color.FromArgb(r, g, b); + } + } + + /// + public class ColorSet { + private bool shade; + private Color color; + private float factor; + private int colors; + private Color[] range; + + /// + /// + /// + /// + /// + public ColorSet(bool shade, Color color, float factor, int colors) { + if (colors < 1) { throw new ArgumentException("Number of colors must be greater than 0."); } + if (factor < 0 || factor > 1) { throw new ArgumentException("Factor must be between 0 and 1."); } + this.shade = shade; + this.color = color; + this.factor = factor; + this.colors = colors; + Build(); + } + + private void Build() { + this.range = new Color[colors]; + Color current = color; + range[0] = current; + for (int i = 1; i < colors; i++) { + if (shade) { + range[i] = ColorRange.Shade(factor, current); + } else { + range[i] = ColorRange.Tint(factor, current); + } + current = range[i]; + } + } + + /// + public Color[] Colors { + get { return range; } + } + } + + /// + public class BlendSet { + private Color color1; + private Color color2; + private float factor; + private int colors; + private Color[] range; + + /// + /// + /// + /// + /// + public BlendSet(Color one, Color two, float factor, int colors) { + if (colors < 1) { throw new ArgumentException("Number of colors must be greater than 0."); } + if (factor < 0 || factor > 1) { throw new ArgumentException("Factor must be between 0 and 1."); } + this.color1 = one; + this.color2 = two; + this.factor = factor; + this.colors = colors; + Build(); + } + + private void Build() { + this.range = new Color[colors]; + Color current = color1; + range[0] = current; + for (int i = 1; i < colors; i++) { + range[i] = ColorRange.Morph(factor, current, color2); + current = range[i]; + } + } + + /// + public Color[] Colors { + get { return range; } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/DualProgressBar.cs b/ProgressODoom/DualProgressBar.cs new file mode 100644 index 0000000..3f1b10c --- /dev/null +++ b/ProgressODoom/DualProgressBar.cs @@ -0,0 +1,159 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.DualProgressBar), "Icons.DualProgressBar.ico")] + public class DualProgressBar : ProgressBarEx { + private int masterval = 0; + private int mastermax = 100; + private IProgressPainter masterpainter; + private bool masterBottom = false; + private Rectangle masterbox; + private int padding = 0; + + protected EventHandler OnMasterValueChanged; + /// + public event EventHandler MasterValueChanged { + add { + if (OnMasterValueChanged != null) { + foreach (Delegate d in OnMasterValueChanged.GetInvocationList()) { + if (object.ReferenceEquals(d, value)) { return; } + } + } + OnMasterValueChanged = (EventHandler)Delegate.Combine(OnMasterValueChanged, value); + } + remove { OnMasterValueChanged = (EventHandler)Delegate.Remove(OnMasterValueChanged, value); } + } + + /// + [Category("Progress"), Description("Gets or sets the maximum value"), Browsable(true)] + public override int Maximum { + get { return base.maximum; } + set { + base.Maximum = value; + mastermax = value; + } + } + + /// + [Category("Progress"), Description("Gets or sets the value of the master progress"), Browsable(true)] + public int MasterValue { + get { return this.masterval; } + set { + this.masterval = value; + if (OnMasterValueChanged != null) { + OnMasterValueChanged(this, EventArgs.Empty); + } + ResizeMasterProgress(); + this.Invalidate(); + } + } + + /// + [Category("Progress"), Description("Gets or sets the maximum value for the master progress"), Browsable(true)] + public int MasterMaximum { + get { return mastermax; } + set { + this.mastermax = value; + ResizeMasterProgress(); + this.Invalidate(); + } + } + + /// + [Category("Progress"), Description("Gets or sets the padding for the master progress"), Browsable(true)] + public int MasterProgressPadding { + get { return this.padding; } + set { + this.padding = value; + if (OnValueChanged != null) { + OnValueChanged(this, EventArgs.Empty); + } + ResizeMasterProgress(); + this.Invalidate(); + } + } + + /// + [Category("Painters"), Description("Paints this progress bar's master progress"), Browsable(true)] + public IProgressPainter MasterPainter { + get { return this.masterpainter; } + set { + this.masterpainter = value; + if (this.masterpainter is AbstractProgressPainter) { + ((AbstractProgressPainter)this.masterpainter).padding = base.ProgressPadding; + } + this.masterpainter.PropertiesChanged += new EventHandler(component_PropertiesChanged); + this.Invalidate(); + } + } + + /// + [Category("Progress"), Description("Determines whether or not the master progress is painted under the main progress"), Browsable(true)] + public bool PaintMasterFirst { + get { return this.masterBottom; } + set { + this.masterBottom = value; + this.Invalidate(); + } + } + + protected override void OnResize(EventArgs e) { + base.OnResize(e); + ResizeProgress(); + ResizeMasterProgress(); + if (this.backgroundpainter != null) { this.backgroundpainter.Resize(borderbox); } + if (masterBottom && this.masterpainter != null) { this.masterpainter.Resize(masterbox); } + if (this.progresspainter != null) { this.progresspainter.Resize(borderbox); } + if (!masterBottom && this.masterpainter != null) { this.masterpainter.Resize(masterbox); } + if (this.borderpainter != null) { this.borderpainter.Resize(borderbox); } + } + + private void ResizeMasterProgress() { + Rectangle newprog = base.borderbox; + newprog.Offset(this.borderpainter.BorderWidth, this.borderpainter.BorderWidth); + newprog.Size = new Size(newprog.Size.Width - this.borderpainter.BorderWidth, newprog.Size.Height - this.borderpainter.BorderWidth); + base.backbox = newprog; + + int val = masterval; if (val > 0) { val++; } + int progWidth = mastermax > 0 ? (backbox.Width * val / mastermax) : 1; + if (value >= mastermax && mastermax > 0) { + progWidth = backbox.Width; + } /*else if (value > 0) { + progWidth++; + }*/ + //newprog = new Rectangle(backbox.X + base.ProgressPadding, backbox.Y + base.ProgressPadding, progWidth - (base.ProgressPadding * 2), backbox.Height - (base.ProgressPadding * 2)); + //newprog = new Rectangle(backbox.X, backbox.Y, progWidth, backbox.Height); + newprog = new Rectangle(backbox.X + this.padding, backbox.Y + this.padding, progWidth - (this.padding * 2), backbox.Height - (this.padding * 2)); + masterbox = newprog; + } + + ///// + //protected override void MarqueeStart() { + //} + ///// + //protected override void MarqueePause() { + //} + ///// + //protected override void MarqueeStop() { + //} + + /// + /// + protected override void PaintProgress(Graphics g) { + if (this.progresspainter != null) { + if (masterBottom && this.masterpainter != null) { + this.masterpainter.PaintProgress(masterbox, g); + } + this.progresspainter.PaintProgress(progressbox, g); + if (!masterBottom && this.masterpainter != null) { + this.masterpainter.PaintProgress(masterbox, g); + } + } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/FlatGlossPainter.cs b/ProgressODoom/FlatGlossPainter.cs new file mode 100644 index 0000000..a173948 --- /dev/null +++ b/ProgressODoom/FlatGlossPainter.cs @@ -0,0 +1,107 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.FlatGlossPainter), "Icons.FlatGlossPainter.ico")] + public class FlatGlossPainter : ChainedGlossPainter { + private GlossStyle style = GlossStyle.Bottom; + private int percent = 50; + private Rectangle box; + private Color color = Color.White; + private int alpha = 128; + private Brush brush; + + /// + [Category("Appearance"), Description("Gets or sets the style for this progress gloss"), Browsable(true)] + public GlossStyle Style { + get { return this.style; } + set { + this.style = value; + this.box = new Rectangle(0, 0, 1, 1); + FireChange(); + } + } + + /// + [Category("Appearance"), Description("Gets or sets the percentage of surface this gloss should cover"), Browsable(true)] + public int PercentageCovered { + get { return this.percent; } + set { + if (value < 0 || value > 100) { + throw new ArgumentException("Percentage value must be between 0 and 100."); + } + this.percent = value; + this.box = new Rectangle(0, 0, 1, 1); + FireChange(); + } + } + + /// + [Category("Appearance"), Description("Gets or sets color to gloss"), Browsable(true)] + public Color Color { + get { return this.color; } + set { + this.color = value; + box = new Rectangle(0, 0, 1, 1); + FireChange(); + } + } + + /// + [Category("Blending"), Description("Gets or sets the alpha value"), Browsable(true)] + public int Alpha { + get { return this.alpha; } + set { + if (value < 0 || value > 255) { + throw new ArgumentException("Alpha values must be between 0 and 255."); + } + this.alpha = value; + box = new Rectangle(0, 0, 1, 1); + FireChange(); + } + } + + protected override void PaintThisGloss(Rectangle box, Graphics g) { + if (!this.box.Equals(box)) { + this.box = box; + } + + int y = (int)(((float)box.Height * (float)percent) / 100f); + if (box.Y + y > box.Height) { y = box.Height; } + + Rectangle cover = box; + switch (style) { + case GlossStyle.Bottom: + int start = box.Height + box.Y - y; + cover = new Rectangle(box.X, start, box.Width, box.Bottom - start); + break; + case GlossStyle.Top: + cover = new Rectangle(box.X, box.Y, box.Width, y + 1); + break; + case GlossStyle.Both: + cover = box; + break; + } + + Color ccv = Color.FromArgb(alpha, color.R, color.G, color.B); + brush = new SolidBrush(ccv); + g.FillRectangle(brush, cover); + } + + protected override void ResizeThis(Rectangle box) { + if (!this.box.Equals(box)) { + this.box = box; + } + } + + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + if (brush != null) { brush.Dispose(); } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/FruityLoopsBackgroundPainter.cs b/ProgressODoom/FruityLoopsBackgroundPainter.cs new file mode 100644 index 0000000..50338f6 --- /dev/null +++ b/ProgressODoom/FruityLoopsBackgroundPainter.cs @@ -0,0 +1,209 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.FruityLoopsBackgroundPainter), "Icons.FruityLoopsBackgroundPainter.ico")] + public class FruityLoopsBackgroundPainter : Component, IProgressBackgroundPainter, IDisposable { + private IGlossPainter gloss; + private FruityLoopsProgressPainter.FruityLoopsProgressType type; + private Image img; + + private Color OffLit = Color.FromArgb(49, 69, 74); + private Pen pOffLit; // = new Pen(new SolidBrush(OffLit),1f); + private Color OffLitTop = Color.FromArgb(66, 85, 90); + private Pen pOffLitTop; // = new Pen(new SolidBrush(OffLitTop),1f); + private Color OffLitBot = Color.FromArgb(24, 48, 49); + private Pen pOffLitBot; // = new Pen(new SolidBrush(OffLitBot),1f); + + private Color OffMid = Color.FromArgb(24, 48, 49); + private Pen pOffMid; // = new Pen(new SolidBrush(OffMid),1f); + private Color OffMidTop = Color.FromArgb(24, 48, 49); + private Pen pOffMidTop; // = new Pen(new SolidBrush(OffMidTop),1f); + private Color OffMidBot = Color.FromArgb(8, 28, 24); + private Pen pOffMidBot; // = new Pen(new SolidBrush(OffMidBot),1f); + + private Color OffDrk = Color.FromArgb(0, 24, 24); + private Pen pOffDrk; // = new Pen(new SolidBrush(OffDrk),1f); + private Color OffDrkTop = Color.FromArgb(8, 28, 24); + private Pen pOffDrkTop; // = new Pen(new SolidBrush(OffDrkTop),1f); + private Color OffDrkBot = Color.FromArgb(0, 16, 16); + private Pen pOffDrkBot; // = new Pen(new SolidBrush(OffDrkBot),1f); + + private EventHandler onPropertiesChanged; + /// + public event EventHandler PropertiesChanged { + add { + if (onPropertiesChanged != null) { + foreach (Delegate d in onPropertiesChanged.GetInvocationList()) { + if (object.ReferenceEquals(d, value)) { return; } + } + } + onPropertiesChanged = (EventHandler)Delegate.Combine(onPropertiesChanged, value); + } + remove { onPropertiesChanged = (EventHandler)Delegate.Remove(onPropertiesChanged, value); } + } + + private void FireChange() { + if (onPropertiesChanged != null) { onPropertiesChanged(this, EventArgs.Empty); } + } + + /// + /// + /// + protected virtual void component_PropertiesChanged(object sender, EventArgs e) { + FireChange(); + } + + /// + [Category("Painters"), Description("Gets or sets the chain of gloss painters"), Browsable(true)] + public IGlossPainter GlossPainter { + get { return this.gloss; } + set { + this.gloss = value; + if (this.gloss != null) { this.gloss.PropertiesChanged += new EventHandler(component_PropertiesChanged); } + FireChange(); + } + } + + /// + [Category("Appearance"), Description("Gets or sets the type of FruityLoops progress style"), Browsable(true)] + public FruityLoopsProgressPainter.FruityLoopsProgressType FruityType { + get { return type; } + set { + type = value; + if (type == FruityLoopsProgressPainter.FruityLoopsProgressType.DoubleLayer) { + OffLit = Color.FromArgb(49, 69, 74); + pOffLit = new Pen(new SolidBrush(OffLit), 1f); + OffLitTop = Color.FromArgb(57, 77, 82); + pOffLitTop = new Pen(new SolidBrush(OffLitTop), 1f); + OffLitBot = Color.FromArgb(24, 48, 49); + pOffLitBot = new Pen(new SolidBrush(OffLitBot), 1f); + + OffDrk = Color.FromArgb(24, 48, 49); + pOffDrk = new Pen(new SolidBrush(OffDrk), 1f); + OffDrkTop = Color.FromArgb(16, 40, 41); + pOffDrkTop = new Pen(new SolidBrush(OffDrkTop), 1f); + OffDrkBot = Color.FromArgb(8, 18, 24); + pOffDrkBot = new Pen(new SolidBrush(OffDrkBot), 1f); + } else if (type == FruityLoopsProgressPainter.FruityLoopsProgressType.TripleLayer) { + OffLit = Color.FromArgb(49, 69, 74); + pOffLit = new Pen(new SolidBrush(OffLit), 1f); + OffLitTop = Color.FromArgb(66, 85, 90); + pOffLitTop = new Pen(new SolidBrush(OffLitTop), 1f); + OffLitBot = Color.FromArgb(24, 48, 49); + pOffLitBot = new Pen(new SolidBrush(OffLitBot), 1f); + + OffMid = Color.FromArgb(24, 48, 49); + pOffMid = new Pen(new SolidBrush(OffMid), 1f); + OffMidTop = Color.FromArgb(24, 48, 49); + pOffMidTop = new Pen(new SolidBrush(OffMidTop), 1f); + OffMidBot = Color.FromArgb(8, 28, 24); + pOffMidBot = new Pen(new SolidBrush(OffMidBot), 1f); + + OffDrk = Color.FromArgb(0, 24, 24); + pOffDrk = new Pen(new SolidBrush(OffDrk), 1f); + OffDrkTop = Color.FromArgb(8, 28, 24); + pOffDrkTop = new Pen(new SolidBrush(OffDrkTop), 1f); + OffDrkBot = Color.FromArgb(0, 16, 16); + pOffDrkBot = new Pen(new SolidBrush(OffDrkBot), 1f); + } + FireChange(); + } + } + + /// + /// + /// + public void PaintBackground(Rectangle box, Graphics g) { + if (img == null) { + if (type == FruityLoopsProgressPainter.FruityLoopsProgressType.DoubleLayer) { + PaintDouble(box, g); + } else if (type == FruityLoopsProgressPainter.FruityLoopsProgressType.TripleLayer) { + PaintTriple(box, g); + } + } + g.DrawImageUnscaled(img, 0, 0); + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + + /// + /// + /// + protected virtual void PaintDouble(Rectangle r, Graphics g) { + bool lite = true; + img = new Bitmap(r.Width + 1, r.Height + 1); + Graphics gi = Graphics.FromImage(img); + + for (int i = 1; i < r.Width + 1; i++) { + if (lite) { + gi.DrawLine(pOffLitTop, i, r.Y, i, r.Y + 1); + gi.DrawLine(pOffLitBot, i, r.Height, i, r.Height - 1); + gi.DrawLine(pOffLit, i, r.Y + 1, i, r.Height - 1); + } else { + gi.DrawLine(pOffDrkTop, i, r.Y, i, r.Y + 1); + gi.DrawLine(pOffDrkBot, i, r.Height, i, r.Height - 1); + gi.DrawLine(pOffDrk, i, r.Y + 1, i, r.Height - 1); + } + lite = !lite; + } + gi.Dispose(); + } + + /// + /// + /// + protected virtual void PaintTriple(Rectangle r, Graphics g) { + int lite = 1; + img = new Bitmap(r.Width + 1, r.Height + 1); + Graphics gi = Graphics.FromImage(img); + + for (int i = 1; i < r.Width + 1; i++) { + if (lite == 2) { + gi.DrawLine(pOffLitTop, i, r.Y, i, r.Y + 1); + gi.DrawLine(pOffLitBot, i, r.Height, i, r.Height - 1); + gi.DrawLine(pOffLit, i, r.Y + 1, i, r.Height - 1); + lite = 0; + } else if (lite == 1) { + gi.DrawLine(pOffMidTop, i, r.Y, i, r.Y + 1); + gi.DrawLine(pOffMidBot, i, r.Height, i, r.Height - 1); + gi.DrawLine(pOffMid, i, r.Y + 1, i, r.Height - 1); + lite = 2; + } else if (lite == 0) { + gi.DrawLine(pOffDrkTop, i, r.Y, i, r.Y + 1); + gi.DrawLine(pOffDrkBot, i, r.Height, i, r.Height - 1); + gi.DrawLine(pOffDrk, i, r.Y + 1, i, r.Height - 1); + lite = 1; + } + } + gi.Dispose(); + } + + /// + public void Resize(Rectangle box) { + img = null; + } + + /// + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + if (img != null) { img.Dispose(); } + + if (pOffLit != null) { pOffLit.Dispose(); } + if (pOffLitTop != null) { pOffLitTop.Dispose(); } + if (pOffLitBot != null) { pOffLitBot.Dispose(); } + if (pOffMid != null) { pOffMid.Dispose(); } + if (pOffMidTop != null) { pOffMidTop.Dispose(); } + if (pOffMidBot != null) { pOffMidBot.Dispose(); } + if (pOffDrk != null) { pOffDrk.Dispose(); } + if (pOffDrkTop != null) { pOffDrkTop.Dispose(); } + if (pOffDrkBot != null) { pOffDrkBot.Dispose(); } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/FruityLoopsProgressPainter.cs b/ProgressODoom/FruityLoopsProgressPainter.cs new file mode 100644 index 0000000..50a7f19 --- /dev/null +++ b/ProgressODoom/FruityLoopsProgressPainter.cs @@ -0,0 +1,169 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.FruityLoopsProgressPainter), "Icons.FruityLoopsProgressPainter.ico")] + public class FruityLoopsProgressPainter : AbstractProgressPainter, IProgressPainter, IDisposable { + private FruityLoopsProgressType type; + + private Color OnLit = Color.FromArgb(148, 170, 173); + private Pen pOnLit; // = new Pen(new SolidBrush(OnLit),1f); + private Color OnLitTop = Color.FromArgb(206, 227, 231); + private Pen pOnLitTop; // = new Pen(new SolidBrush(OnLitTop),1f); + private Color OnLitBot = Color.FromArgb(90, 117, 123); + private Pen pOnLitBot; // = new Pen(new SolidBrush(OnLitBot),1f); + + private Color OnMid = Color.FromArgb(107, 130, 132); + private Pen pOnMid; // = new Pen(new SolidBrush(OnMid),1f); + private Color OnMidTop = Color.FromArgb(140, 154, 156); + private Pen pOnMidTop; // = new Pen(new SolidBrush(OnMidTop),1f); + private Color OnMidBot = Color.FromArgb(57, 85, 82); + private Pen pOnMidBot; // = new Pen(new SolidBrush(OnMidBot),1f); + + private Color OnDrk = Color.FromArgb(57, 85, 82); + private Pen pOnDrk; // = new Pen(new SolidBrush(OnDrk),1f); + private Color OnDrkTop = Color.FromArgb(107, 125, 123); + private Pen pOnDrkTop; // = new Pen(new SolidBrush(OnDrkTop),1f); + private Color OnDrkBot = Color.FromArgb(33, 60, 66); + private Pen pOnDrkBot; // = new Pen(new SolidBrush(OnDrkBot),1f); + + /// + [Category("Appearance"), Description("Gets or sets the type of FruityLoops progress style"), Browsable(true)] + public FruityLoopsProgressType FruityType { + get { return type; } + set { + type = value; + if (type == FruityLoopsProgressType.DoubleLayer) { + OnLit = Color.FromArgb(148, 170, 173); + pOnLit = new Pen(new SolidBrush(OnLit), 1f); + OnLitTop = Color.FromArgb(206, 227, 231); + pOnLitTop = new Pen(new SolidBrush(OnLitTop), 1f); + OnLitBot = Color.FromArgb(90, 113, 115); + pOnLitBot = new Pen(new SolidBrush(OnLitBot), 1f); + + OnDrk = Color.FromArgb(115, 142, 148); + pOnDrk = new Pen(new SolidBrush(OnDrk), 1f); + OnDrkTop = Color.FromArgb(181, 199, 198); + pOnDrkTop = new Pen(new SolidBrush(OnDrkTop), 1f); + OnDrkBot = Color.FromArgb(66, 89, 90); + pOnDrkBot = new Pen(new SolidBrush(OnDrkBot), 1f); + } else if (type == FruityLoopsProgressType.TripleLayer) { + OnLit = Color.FromArgb(148, 170, 173); + pOnLit = new Pen(new SolidBrush(OnLit), 1f); + OnLitTop = Color.FromArgb(206, 227, 231); + pOnLitTop = new Pen(new SolidBrush(OnLitTop), 1f); + OnLitBot = Color.FromArgb(90, 117, 123); + pOnLitBot = new Pen(new SolidBrush(OnLitBot), 1f); + + OnMid = Color.FromArgb(107, 130, 132); + pOnMid = new Pen(new SolidBrush(OnMid), 1f); + OnMidTop = Color.FromArgb(140, 154, 156); + pOnMidTop = new Pen(new SolidBrush(OnMidTop), 1f); + OnMidBot = Color.FromArgb(57, 85, 82); + pOnMidBot = new Pen(new SolidBrush(OnMidBot), 1f); + + OnDrk = Color.FromArgb(57, 85, 82); + pOnDrk = new Pen(new SolidBrush(OnDrk), 1f); + OnDrkTop = Color.FromArgb(107, 125, 123); + pOnDrkTop = new Pen(new SolidBrush(OnDrkTop), 1f); + OnDrkBot = Color.FromArgb(33, 60, 66); + pOnDrkBot = new Pen(new SolidBrush(OnDrkBot), 1f); + } + FireChange(); + } + } + + /// + /// + /// + protected override void PaintThisProgress(Rectangle box, Graphics g) { + try { + box.Height -= 1; + } catch { } + + if (box.Width <= 1) { return; } + if (type == FruityLoopsProgressType.DoubleLayer) { + PaintDouble(box, g); + } else if (type == FruityLoopsProgressType.TripleLayer) { + PaintTriple(box, g); + } + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + + private void PaintDouble(Rectangle r, Graphics g) { + bool lite = true; + + Brush b = new SolidBrush(pOnLit.Color); + g.FillRectangle(b, r); + g.DrawLine(pOnLitTop, r.X, r.Y, r.Right - 1, r.Y); + g.DrawLine(pOnLitBot, r.X, r.Bottom, r.Right - 1, r.Bottom); + for (int i = r.X; i < r.Right; i++) { + if (lite) { + //g.DrawLine(off ? pOffLitTop : pOnLitTop, i, r.Y, i, r.Y + 1); + //g.DrawLine(off ? pOffLitBot : pOnLitBot, i, r.Height, i, r.Height - 1); + //g.DrawLine(off ? pOffLit : pOnLit, i, r.Y + 1, i, r.Height - 1); + } else { + g.DrawLine(pOnDrkTop, i, r.Y, i, r.Y + 1); + g.DrawLine(pOnDrkBot, i, r.Bottom, i, r.Bottom - 1); + g.DrawLine(pOnDrk, i, r.Y + 1, i, r.Bottom - 1); + } + lite = !lite; + } + } + + private void PaintTriple(Rectangle r, Graphics g) { + int lite = 1; + + Brush b = new SolidBrush(pOnMid.Color); + g.FillRectangle(b, r); + g.DrawLine(pOnMidTop, r.X, r.Y, r.Right - 1, r.Y); + g.DrawLine(pOnMidBot, r.X, r.Bottom, r.Right - 1, r.Bottom); + for (int i = r.X; i < r.Right; i++) { + if (lite == 2) { + g.DrawLine(pOnLitTop, i, r.Y, i, r.Y + 1); + g.DrawLine(pOnLitBot, i, r.Bottom, i, r.Bottom - 1); + g.DrawLine(pOnLit, i, r.Y + 1, i, r.Bottom - 1); + lite = 0; + } else if (lite == 1) { + //g.DrawLine(pOnMidTop, i, r.Y, i, r.Y + 1); + //g.DrawLine(pOnMidBot, i, r.Height, i, r.Height - 1); + //g.DrawLine(pOnMid, i, r.Y + 1, i, r.Height - 1); + lite = 2; + } else if (lite == 0) { + g.DrawLine(pOnDrkTop, i, r.Y, i, r.Y + 1); + g.DrawLine(pOnDrkBot, i, r.Bottom, i, r.Bottom - 1); + g.DrawLine(pOnDrk, i, r.Y + 1, i, r.Bottom - 1); + lite = 1; + } + } + } + + /// + protected override void DisposeThis(bool disposing) { + if (pOnLit != null) { pOnLit.Dispose(); } + if (pOnLitTop != null) { pOnLitTop.Dispose(); } + if (pOnLitBot != null) { pOnLitBot.Dispose(); } + if (pOnMid != null) { pOnMid.Dispose(); } + if (pOnMidTop != null) { pOnMidTop.Dispose(); } + if (pOnMidBot != null) { pOnMidBot.Dispose(); } + if (pOnDrk != null) { pOnDrk.Dispose(); } + if (pOnDrkTop != null) { pOnDrkTop.Dispose(); } + if (pOnDrkBot != null) { pOnDrkBot.Dispose(); } + } + + /// + public enum FruityLoopsProgressType { + /// + DoubleLayer, + /// + TripleLayer + } + } +} \ No newline at end of file diff --git a/ProgressODoom/GradientBackgroundPainter.cs b/ProgressODoom/GradientBackgroundPainter.cs new file mode 100644 index 0000000..19f9bc2 --- /dev/null +++ b/ProgressODoom/GradientBackgroundPainter.cs @@ -0,0 +1,102 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.GradientBackgroundPainter), "Icons.GradientBackgroundPainter.ico")] + public class GradientBackgroundPainter : Component, IProgressBackgroundPainter, IDisposable { + private Color top; + private Color bottom; + private Brush brush; + private IGlossPainter gloss; + + private EventHandler onPropertiesChanged; + /// + public event EventHandler PropertiesChanged { + add { + if (onPropertiesChanged != null) { + foreach (Delegate d in onPropertiesChanged.GetInvocationList()) { + if (object.ReferenceEquals(d, value)) { return; } + } + } + onPropertiesChanged = (EventHandler)Delegate.Combine(onPropertiesChanged, value); + } + remove { onPropertiesChanged = (EventHandler)Delegate.Remove(onPropertiesChanged, value); } + } + + private void FireChange() { + if (onPropertiesChanged != null) { onPropertiesChanged(this, EventArgs.Empty); } + } + + /// + /// + /// + protected virtual void component_PropertiesChanged(object sender, EventArgs e) { + FireChange(); + } + + /// + public GradientBackgroundPainter() { + this.top = Color.FromArgb(240, 240, 240); + this.bottom = Color.FromArgb(224, 224, 224); + } + + /// + /// + public GradientBackgroundPainter(Color top, Color bottom) { + this.top = top; + this.bottom = bottom; + } + + /// + [Category("Painters"), Description("Gets or sets the chain of gloss painters"), Browsable(true)] + public IGlossPainter GlossPainter { + get { return this.gloss; } + set { + this.gloss = value; + if (this.gloss != null) { this.gloss.PropertiesChanged += new EventHandler(component_PropertiesChanged); } + FireChange(); + } + } + + /// + [Category("Appearance"), Description("Gets or sets the top gradient color"), Browsable(true)] + public Color TopColor { + get { return top; } + set { top = value; FireChange(); } + } + + /// + [Category("Appearance"), Description("Gets or sets the bottom gradient color"), Browsable(true)] + public Color BottomColor { + get { return bottom; } + set { bottom = value; FireChange(); } + } + + /// + /// + /// + public void PaintBackground(Rectangle box, Graphics g) { + Resize(box); + g.FillRectangle(brush, box); + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + + /// + public void Resize(Rectangle box) { + brush = new System.Drawing.Drawing2D.LinearGradientBrush(new Point(0, 0), new Point(0, box.Height), bottom, top); + } + + /// + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + if (brush != null) { brush.Dispose(); } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/GradientGlossPainter.cs b/ProgressODoom/GradientGlossPainter.cs new file mode 100644 index 0000000..199d94b --- /dev/null +++ b/ProgressODoom/GradientGlossPainter.cs @@ -0,0 +1,119 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.GradientGlossPainter), "Icons.GradientGlossPainter.ico")] + public class GradientGlossPainter : ChainedGlossPainter { + private GlossStyle style = GlossStyle.Bottom; + private int percent = 50; + private Color color = Color.White; + private int highAlpha = 240; + private int lowAlpha = 0; + private float angle = 90f; + private Brush brush; + + /// + [Category("Appearance"), Description("Gets or sets the style for this progress gloss"), Browsable(true)] + public GlossStyle Style { + get { return this.style; } + set { + this.style = value; + FireChange(); + } + } + + /// + [Category("Appearance"), Description("Gets or sets the percentage of surface this gloss should cover"), Browsable(true)] + public int PercentageCovered { + get { return this.percent; } + set { + this.percent = value; + FireChange(); + } + } + + /// + [Category("Appearance"), Description("Gets or sets color to gloss"), Browsable(true)] + public Color Color { + get { return this.color; } + set { + this.color = value; + FireChange(); + } + } + + /// + [Category("Blending"), Description("Gets or sets the high alpha value"), Browsable(true)] + public int AlphaHigh { + get { return this.highAlpha; } + set { + if (value < 0 || value > 255) { + throw new ArgumentException("Alpha values must be between 0 and 255."); + } + this.highAlpha = value; + FireChange(); + } + } + + /// + [Category("Blending"), Description("Gets or sets the low alpha value"), Browsable(true)] + public int AlphaLow { + get { return this.lowAlpha; } + set { + if (value < 0 || value > 255) { + throw new ArgumentException("Alpha values must be between 0 and 255."); + } + this.lowAlpha = value; + FireChange(); + } + } + + /// + [Category("Blending"), Description("Gets or sets angle for the gradient"), Browsable(true)] + public float Angle { + get { return this.angle; } + set { + this.angle = value; + FireChange(); + } + } + + protected override void PaintThisGloss(Rectangle box, Graphics g) { + int y = (int)(((float)box.Height * (float)percent) / 100f); + if (box.Y + y > box.Height) { y = box.Height; } + + Rectangle cover = box; + switch (style) { + case GlossStyle.Bottom: + int start = box.Height + box.Y - y; + cover = new Rectangle(box.X, start - 1, box.Width /*- 1*/, box.Bottom - start); + break; + case GlossStyle.Top: + cover = new Rectangle(box.X, box.Y - 1, box.Width /*- 1*/, y + 2); + break; + case GlossStyle.Both: + cover = box; + break; + } + + Color hcolor = Color.FromArgb(highAlpha, color.R, color.G, color.B); + Color lcolor = Color.FromArgb(lowAlpha, color.R, color.G, color.B); + brush = new LinearGradientBrush(cover, hcolor, lcolor, angle, true); + g.FillRectangle(brush, cover); + //g.DrawRectangle(Pens.Red, cover); + } + + protected override void ResizeThis(Rectangle box) { + } + + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + if (brush != null) { brush.Dispose(); } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/HSV.cs b/ProgressODoom/HSV.cs new file mode 100644 index 0000000..5091da0 --- /dev/null +++ b/ProgressODoom/HSV.cs @@ -0,0 +1,188 @@ +using System; +using System.Drawing; + +namespace ProgressODoom { + public struct HSV { + private int hue; + private int sat; + private int val; + + public HSV(int h, int s, int v) { + hue = h; + sat = s; + val = v; + } + + public HSV(Color color) { + hue = 0; + sat = 0; + val = 0; + FromRGB(color); + } + + public static Color FromHsv(int h, int s, int v) { + HSV hsv = new HSV(h, s, v); + return hsv.Color; + } + + public int Hue { + get { return hue; } + set { hue = value; } + } + + public int Saturation { + get { return sat; } + set { sat = value; } + } + + public int Value { + get { return val; } + set { val = value; } + } + + public Color Color { + get { return ToRGB(); } + set { FromRGB(value); } + } + + private void FromRGB(Color color) { + /* + if (max = min) + h = 0 + if (max = r) + h = (60deg * (g-b)/(max-min) + 0deg) % 360deg + if (max = g) + h = (60deg * (b-r)/(max-min) + 120deg) + if (max = b) + h = (60deg * (r-g)/(max-min) + 240deg) + + if (max = 0) + s = 0 + else + s = 1 - min/max + + v = max + */ + + double min; + double max; + double delta; + + double r = (double)color.R / 255D; + double g = (double)color.G / 255D; + double b = (double)color.B / 255D; + + double h; + double s; + double v; + + min = Math.Min(Math.Min(r, g), b); + max = Math.Max(Math.Max(r, g), b); + v = max; + delta = max - min; + if (max == 0 || delta == 0) { + s = 0; + h = 0; + } else { + s = delta / max; + if (r == max) { + h = (60D * ((g - b) / delta)) % 360D; + } else if (g == max) { + h = 60D * ((b - r) / delta) + 120D; + } else { + h = 60D * ((r - g) / delta) + 240D; + } + } + if (h < 0) { + h += 360D; + } + + Hue = (int)(h / 360D * 255D); + Saturation = (int)(s * 255D); + Value = (int)(v * 255D); + } + private Color ToRGB() { + double h; + double s; + double v; + + double r = 0; + double g = 0; + double b = 0; + + // Scale Hue to be between 0 and 360. Saturation + // and value scale to be between 0 and 1. + h = ((double)Hue / 255D * 360D) % 360D; + s = (double)Saturation / 255D; + v = (double)Value / 255D; + + if (s == 0) { + r = v; + g = v; + b = v; + } else { + double p; + double q; + double t; + + double fractionalSector; + int sectorNumber; + double sectorPos; + + sectorPos = h / 60D; + sectorNumber = (int)(Math.Floor(sectorPos)); + + fractionalSector = sectorPos - sectorNumber; + + p = v * (1D - s); + q = v * (1D - (s * fractionalSector)); + t = v * (1D - (s * (1D - fractionalSector))); + + switch (sectorNumber) { + case 0: + r = v; + g = t; + b = p; + break; + case 1: + r = q; + g = v; + b = p; + break; + case 2: + r = p; + g = v; + b = t; + break; + case 3: + r = p; + g = q; + b = v; + break; + case 4: + r = t; + g = p; + b = v; + break; + case 5: + r = v; + g = p; + b = q; + break; + } + } + return Color.FromArgb((int)(r * 255D), (int)(g * 255D), (int)(b * 255D)); + } + + public static bool operator !=(HSV left, HSV right) { + return !(left == right); + } + public static bool operator ==(HSV left, HSV right) { + return (left.Hue == right.Hue && left.Value == right.Value && left.Saturation == right.Saturation); + } + public override string ToString() { + string s = string.Format("HSV({0:f2}, {1:f2}, {2:f2})", Hue, Saturation, Value); + return s; + } + } +} \ No newline at end of file diff --git a/ProgressODoom/IAnimatedProgressPainter.cs b/ProgressODoom/IAnimatedProgressPainter.cs new file mode 100644 index 0000000..3de39df --- /dev/null +++ b/ProgressODoom/IAnimatedProgressPainter.cs @@ -0,0 +1,19 @@ +using System; +using System.Drawing; + +namespace ProgressODoom { + /// + public interface IAnimatedProgressPainter : IProgressPainter { + ///// + ///// + ///// + ///// + //void AnimateFrame(Rectangle box, Graphics g, ref int marqueeX); + + /// + int AnimationSpeed { get; set; } + + /// + bool Animating { get; set; } + } +} \ No newline at end of file diff --git a/ProgressODoom/IGlossPainter.cs b/ProgressODoom/IGlossPainter.cs new file mode 100644 index 0000000..adf1ea1 --- /dev/null +++ b/ProgressODoom/IGlossPainter.cs @@ -0,0 +1,17 @@ +using System; +using System.Drawing; + +namespace ProgressODoom { + public interface IGlossPainter : IDisposable { + /// + /// + /// + void PaintGloss(Rectangle box, Graphics g); + + /// + void Resize(Rectangle box); + + /// + event EventHandler PropertiesChanged; + } +} \ No newline at end of file diff --git a/ProgressODoom/IProgressBackgroundPainter.cs b/ProgressODoom/IProgressBackgroundPainter.cs new file mode 100644 index 0000000..ae36176 --- /dev/null +++ b/ProgressODoom/IProgressBackgroundPainter.cs @@ -0,0 +1,21 @@ +using System; +using System.Drawing; + +namespace ProgressODoom { + /// + public interface IProgressBackgroundPainter : IDisposable { + /// + IGlossPainter GlossPainter { get; set; } + + /// + /// + /// + void PaintBackground(Rectangle box, Graphics gr); + + /// + void Resize(Rectangle box); + + /// + event EventHandler PropertiesChanged; + } +} \ No newline at end of file diff --git a/ProgressODoom/IProgressBorderPainter.cs b/ProgressODoom/IProgressBorderPainter.cs new file mode 100644 index 0000000..21c69d5 --- /dev/null +++ b/ProgressODoom/IProgressBorderPainter.cs @@ -0,0 +1,21 @@ +using System; +using System.Drawing; + +namespace ProgressODoom { + /// + public interface IProgressBorderPainter : IDisposable { + /// + /// + /// + void PaintBorder(Rectangle box, Graphics gr); + + /// + void Resize(Rectangle box); + + /// + int BorderWidth { get; } + + /// + event EventHandler PropertiesChanged; + } +} \ No newline at end of file diff --git a/ProgressODoom/IProgressPainter.cs b/ProgressODoom/IProgressPainter.cs new file mode 100644 index 0000000..93a0327 --- /dev/null +++ b/ProgressODoom/IProgressPainter.cs @@ -0,0 +1,24 @@ +using System; +using System.Drawing; + +namespace ProgressODoom { + /// + public interface IProgressPainter : IDisposable { + /// + IGlossPainter GlossPainter { get; set; } + + /// + IProgressBorderPainter ProgressBorderPainter { get; set; } + + /// + /// + /// + void PaintProgress(Rectangle box, Graphics gr); + + /// + void Resize(Rectangle box); + + /// + event EventHandler PropertiesChanged; + } +} \ No newline at end of file diff --git a/ProgressODoom/Icons/BarberPoleProgressPainter.ico b/ProgressODoom/Icons/BarberPoleProgressPainter.ico new file mode 100644 index 0000000..c2ce723 Binary files /dev/null and b/ProgressODoom/Icons/BarberPoleProgressPainter.ico differ diff --git a/ProgressODoom/Icons/BevelledGradientProgressPainter.ico b/ProgressODoom/Icons/BevelledGradientProgressPainter.ico new file mode 100644 index 0000000..036f249 Binary files /dev/null and b/ProgressODoom/Icons/BevelledGradientProgressPainter.ico differ diff --git a/ProgressODoom/Icons/BevelledProgressPainter.ico b/ProgressODoom/Icons/BevelledProgressPainter.ico new file mode 100644 index 0000000..230af6a Binary files /dev/null and b/ProgressODoom/Icons/BevelledProgressPainter.ico differ diff --git a/ProgressODoom/Icons/CandyCaneBackgroundPainter.ico b/ProgressODoom/Icons/CandyCaneBackgroundPainter.ico new file mode 100644 index 0000000..1203da7 Binary files /dev/null and b/ProgressODoom/Icons/CandyCaneBackgroundPainter.ico differ diff --git a/ProgressODoom/Icons/CandyCaneProgressPainter.ico b/ProgressODoom/Icons/CandyCaneProgressPainter.ico new file mode 100644 index 0000000..ff646f2 Binary files /dev/null and b/ProgressODoom/Icons/CandyCaneProgressPainter.ico differ diff --git a/ProgressODoom/Icons/DualProgressBar.ico b/ProgressODoom/Icons/DualProgressBar.ico new file mode 100644 index 0000000..c08d8db Binary files /dev/null and b/ProgressODoom/Icons/DualProgressBar.ico differ diff --git a/ProgressODoom/Icons/FlatGlossPainter.ico b/ProgressODoom/Icons/FlatGlossPainter.ico new file mode 100644 index 0000000..f0b4043 Binary files /dev/null and b/ProgressODoom/Icons/FlatGlossPainter.ico differ diff --git a/ProgressODoom/Icons/FruityLoopsBackgroundPainter.ico b/ProgressODoom/Icons/FruityLoopsBackgroundPainter.ico new file mode 100644 index 0000000..782c424 Binary files /dev/null and b/ProgressODoom/Icons/FruityLoopsBackgroundPainter.ico differ diff --git a/ProgressODoom/Icons/FruityLoopsProgressPainter.ico b/ProgressODoom/Icons/FruityLoopsProgressPainter.ico new file mode 100644 index 0000000..ac28ea9 Binary files /dev/null and b/ProgressODoom/Icons/FruityLoopsProgressPainter.ico differ diff --git a/ProgressODoom/Icons/GradientBackgroundPainter.ico b/ProgressODoom/Icons/GradientBackgroundPainter.ico new file mode 100644 index 0000000..9f22c63 Binary files /dev/null and b/ProgressODoom/Icons/GradientBackgroundPainter.ico differ diff --git a/ProgressODoom/Icons/GradientGlossPainter.ico b/ProgressODoom/Icons/GradientGlossPainter.ico new file mode 100644 index 0000000..3134324 Binary files /dev/null and b/ProgressODoom/Icons/GradientGlossPainter.ico differ diff --git a/ProgressODoom/Icons/JavaProgressPainter.ico b/ProgressODoom/Icons/JavaProgressPainter.ico new file mode 100644 index 0000000..6f227ad Binary files /dev/null and b/ProgressODoom/Icons/JavaProgressPainter.ico differ diff --git a/ProgressODoom/Icons/MetalProgressPainter.ico b/ProgressODoom/Icons/MetalProgressPainter.ico new file mode 100644 index 0000000..6ebc362 Binary files /dev/null and b/ProgressODoom/Icons/MetalProgressPainter.ico differ diff --git a/ProgressODoom/Icons/MiddleGlossPainter.ico b/ProgressODoom/Icons/MiddleGlossPainter.ico new file mode 100644 index 0000000..32f09af Binary files /dev/null and b/ProgressODoom/Icons/MiddleGlossPainter.ico differ diff --git a/ProgressODoom/Icons/PlainBackgroundPainter.ico b/ProgressODoom/Icons/PlainBackgroundPainter.ico new file mode 100644 index 0000000..e51e78f Binary files /dev/null and b/ProgressODoom/Icons/PlainBackgroundPainter.ico differ diff --git a/ProgressODoom/Icons/PlainBorderPainter.ico b/ProgressODoom/Icons/PlainBorderPainter.ico new file mode 100644 index 0000000..de5fcaa Binary files /dev/null and b/ProgressODoom/Icons/PlainBorderPainter.ico differ diff --git a/ProgressODoom/Icons/PlainProgressPainter.ico b/ProgressODoom/Icons/PlainProgressPainter.ico new file mode 100644 index 0000000..bb40f35 Binary files /dev/null and b/ProgressODoom/Icons/PlainProgressPainter.ico differ diff --git a/ProgressODoom/Icons/ProgressBarEx.ico b/ProgressODoom/Icons/ProgressBarEx.ico new file mode 100644 index 0000000..d60e0b9 Binary files /dev/null and b/ProgressODoom/Icons/ProgressBarEx.ico differ diff --git a/ProgressODoom/Icons/RarBackgroundPainter.ico b/ProgressODoom/Icons/RarBackgroundPainter.ico new file mode 100644 index 0000000..2fb5b1e Binary files /dev/null and b/ProgressODoom/Icons/RarBackgroundPainter.ico differ diff --git a/ProgressODoom/Icons/RarBorderPainter.ico b/ProgressODoom/Icons/RarBorderPainter.ico new file mode 100644 index 0000000..8465005 Binary files /dev/null and b/ProgressODoom/Icons/RarBorderPainter.ico differ diff --git a/ProgressODoom/Icons/RarProgressBar.ico b/ProgressODoom/Icons/RarProgressBar.ico new file mode 100644 index 0000000..551130f Binary files /dev/null and b/ProgressODoom/Icons/RarProgressBar.ico differ diff --git a/ProgressODoom/Icons/RarProgressPainter.ico b/ProgressODoom/Icons/RarProgressPainter.ico new file mode 100644 index 0000000..7a78c9e Binary files /dev/null and b/ProgressODoom/Icons/RarProgressPainter.ico differ diff --git a/ProgressODoom/Icons/RoundGlossPainter.ico b/ProgressODoom/Icons/RoundGlossPainter.ico new file mode 100644 index 0000000..fba36f4 Binary files /dev/null and b/ProgressODoom/Icons/RoundGlossPainter.ico differ diff --git a/ProgressODoom/Icons/StripedProgressPainter.ico b/ProgressODoom/Icons/StripedProgressPainter.ico new file mode 100644 index 0000000..d91316e Binary files /dev/null and b/ProgressODoom/Icons/StripedProgressPainter.ico differ diff --git a/ProgressODoom/Icons/StyledBorderPainter.ico b/ProgressODoom/Icons/StyledBorderPainter.ico new file mode 100644 index 0000000..e63db19 Binary files /dev/null and b/ProgressODoom/Icons/StyledBorderPainter.ico differ diff --git a/ProgressODoom/Icons/WaveProgressPainter.ico b/ProgressODoom/Icons/WaveProgressPainter.ico new file mode 100644 index 0000000..10934d2 Binary files /dev/null and b/ProgressODoom/Icons/WaveProgressPainter.ico differ diff --git a/ProgressODoom/JavaProgressPainter.cs b/ProgressODoom/JavaProgressPainter.cs new file mode 100644 index 0000000..fdf2cf6 --- /dev/null +++ b/ProgressODoom/JavaProgressPainter.cs @@ -0,0 +1,138 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.JavaProgressPainter), "Icons.JavaProgressPainter.ico")] + public class JavaProgressPainter : AbstractProgressPainter, IProgressPainter, IDisposable { + private Color color; + private ColorSet colors; + + /// + public JavaProgressPainter() { + color = Color.SkyBlue; + colors = new ColorSet(false, color, 0.95f, 8); + } + + /// + /// + public JavaProgressPainter(Color color) { + this.color = color; + colors = new ColorSet(false, color, 0.95f, 8); + } + + /// + [Category("Appearance"), Description("Gets or sets the base progress color."), Browsable(true)] + public Color Color { + get { return color; } + set { + color = value; + colors = new ColorSet(false, color, 0.95f, 8); + FireChange(); + } + } + + /// + /// + /// + protected override void PaintThisProgress(Rectangle box, Graphics g) { + try { + box.Width -= 1; + box.Height -= 1; + } catch {} + if (box.Width <= 1) { return; } + + float x = (float)box.X; + float y = (float)box.Y; + float w = (float)box.Right; + float h = (float)box.Bottom; + + //Color corner + Pen p; + x += 2f; //x += 3f; //x += 2f; //x = x + 3f; + y += 4f; //y += 5f; //y += 4f; //y = y + 5f; + w -= 2f; //w -= 3f; //w -= 1f; //w = w - 2f; + h -= 4f; //h -= 6f; //h -= 4f; //h = h - 6f; + + // Progress + colors = new ColorSet(true, this.color, 0.95f, (int)h); + float z = 2; + float ni; + float th = box.Height - 4; + for (int i = -2; i < th; i++) { + //for (int i = -2; i < th; i++) { + z = (i < 0 ? i * -1 : i); + Color c = colors.Colors[colors.Colors.Length - 1]; + try { + c = colors.Colors[(int)z]; + } catch {} + p = new Pen(c); + ni = y + i; + g.DrawLine(p, x, ni, w, ni); + } + + Color progborder = ColorRange.Morph(0.2f, Color.FromArgb(98, 98, 89), this.color); + + Color fade = Color.FromArgb(64, progborder.R, progborder.G, progborder.B); + p = new Pen(new SolidBrush(fade), 1); + //g.DrawRectangle(p, x - 1f, y - 3f, w - 1f, h + 1f); + Rectangle bbox = box; + bbox.Inflate(-1, -1); + g.DrawRectangle(p, bbox); + + // Border + p = new Pen(progborder, 1); + ////g.DrawRectangle(p, x - 1f, y - 3f, w - 1f, h + 1f); + //g.DrawLine(p, x, y - 3f, w, y - 3f); + //g.DrawLine(p, x, h + 3f, w, h + 3f); + //g.DrawLine(p, x - 1f, y - 2f, x - 1f, h + 2f); + //g.DrawLine(p, w + 1f, y - 2f, w + 1f, h + 2f); + g.DrawLine(p, x + 1f, y - 3f, w - 1f, y - 3f); + g.DrawLine(p, x + 1f, h + 3f, w - 1f, h + 3f); + g.DrawLine(p, x - 1f, y - 1f, x - 1f, h + 1f); + g.DrawLine(p, w + 1f, y - 1f, w + 1f, h + 1f); + + // Border corner skirt + //Color skirt = ColorRange.Morph(0.8f, this.color, progborder); + Color skirt = Color.FromArgb(210, progborder.R, progborder.G, progborder.B); + p = new Pen(skirt, 1); + //// Upper Left + //g.DrawLine(p, x - 1f, y - 3f, x, y - 3f); + //g.DrawLine(p, x - 1f, y - 3f, x - 1f, y - 2f); + g.DrawLine(p, x, y - 3f, x - 1f, y - 2f); + //// Lower Left + //g.DrawLine(p, x - 1f, h + 3f, x - 1f, h + 2f); + //g.DrawLine(p, x - 1f, h + 3f, x, h + 3f); + g.DrawLine(p, x, h + 3f, x - 1f, h + 2f); + //// Upper Right + //g.DrawLine(p, w + 1f, y - 3f, w + 1f, y - 2f); + //g.DrawLine(p, w + 1f, y - 3f, w, y - 3f); + g.DrawLine(p, w, y - 3f, w + 1f, y - 2f); + //// Lower Right + //g.DrawLine(p, w + 1f, h + 3f, w, h + 3f); + //g.DrawLine(p, w + 1f, h + 3f, w + 1f, h + 2f); + g.DrawLine(p, w, h + 3f, w + 1f, h + 2f); + + //// Border corner x-1f, y-3f, w-2f, h+1f + //Color corners = ColorRange.Morph(0.5f, this.color, progborder); //Color.FromArgb(229, 229, 222) + //p = new Pen(corners, 1); + //g.DrawLine(p, x - 1f, y - 3f, x, y - 2f); // ul + //g.DrawLine(p, x - 1f, h + 3f, x, h + 2f); // ll + //g.DrawLine(p, w + 1f, y - 3f, w, y - 2f); // ur + //g.DrawLine(p, w + 1f, h + 3f, w, h + 2f); // lr + + ////// Outer corner (Left side only) + ////Color outcorner = ColorRange.Morph(0.5f, progborder, Color.FromArgb(229, 229, 222)); + ////p = new Pen(outcorner, 1); + ////g.DrawLine(p, x - 2f, y - 4f, x - 1f, y - 3f); + ////g.DrawLine(p, x - 2f, h + 4f, x - 1f, h + 3f); + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/MetalProgressPainter.cs b/ProgressODoom/MetalProgressPainter.cs new file mode 100644 index 0000000..99672a2 --- /dev/null +++ b/ProgressODoom/MetalProgressPainter.cs @@ -0,0 +1,153 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.MetalProgressPainter), "Icons.MetalProgressPainter.ico")] + public class MetalProgressPainter : AbstractProgressPainter, IProgressPainter, IDisposable { + private Color progColor = Color.FromArgb(201, 202, 201); + private Color bkColor = Color.FromArgb(240, 240, 240); + + #region Default Colors + private Color backColor = Color.FromArgb(176, 177, 176); + private Color borderColor = Color.FromArgb(69, 68, 69); + private Color backtopColor = Color.FromArgb(160, 157, 160); + private Color barColor12 = Color.FromArgb(193, 194, 193); + private Color barColor3 = Color.FromArgb(201, 202, 201); + private Color barColor8 = Color.FromArgb(226, 226, 226); + private Color barBorderTopColor = Color.FromArgb(250, 250, 250); + private Color barBorderBottomColor = Color.FromArgb(176, 173, 176); + #endregion + + #region Pens & Brushes + private Pen border; + private Pen backtop; + private Brush back; + + private Pen bar12; + private Pen bar8; + + private Pen barBorderTop; + private Pen barBorderBottom; + + private Brush prog; + #endregion + + /// + public MetalProgressPainter() { + progColor = barColor3; + back = new SolidBrush(bkColor); //backColor); + + border = new Pen(new SolidBrush(borderColor), 1f); + backtop = new Pen(new SolidBrush(backtopColor), 1f); + + bar12 = new Pen(new SolidBrush(barColor12), 1f); + bar8 = new Pen(new SolidBrush(barColor8), 1f); + + barBorderTop = new Pen(new SolidBrush(barBorderTopColor), 1f); + barBorderBottom = new Pen(new SolidBrush(barBorderBottomColor), 1f); + + prog = new System.Drawing.Drawing2D.LinearGradientBrush(new Point(0, 0), new Point(0, 20), barColor12, barColor8); + } + + /// + [Category("Appearance"), Description("Gets or sets the base progress color"), Browsable(true)] + public Color Color { + get { return progColor; } + set { + progColor = value; + FireChange(); + } + } + + [Category("Appearance"), Description("Gets or sets the color that the highlights are blended with"), Browsable(true)] + public Color Highlight { + get { return backColor; } + set { + backColor = value; + FireChange(); + } + } + + /// + /// + /// + protected override void PaintThisProgress(Rectangle box, Graphics g) { + try { + box.Width -= 1; + box.Height -= 1; + } catch {} + float x = box.X; + float y = box.Y; + float w = box.Right; + float h = box.Bottom; + if (w < 2) { return; } + + RebuildBrushes(box.Bottom - 1); + + //g.FillRectangle(prog, x + 1, y + 1, w - 2, h - 1); + // + //g.DrawRectangle(barBorderBottom, box.X, box.Y, box.Right, box.Height - 1); + //g.DrawLine(barBorderTop, box.X, box.Y, box.Width + 2, box.Y); + //g.DrawLine(barBorderTop, box.X, box.Y, box.X, box.Height + 2); + + g.FillRectangle(prog, box); + + g.DrawLine(barBorderTop, x, y, w, y); // top + g.DrawLine(barBorderTop, x, y, x, h); // left + g.DrawLine(barBorderBottom, x, h, w, h); // bottom + g.DrawLine(barBorderBottom, w, h, w, y); // right + + //g.DrawRectangle(border, x + 2, y + 2, w - 3, h - 4); + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + + /// + protected override void ResizeThis(Rectangle box) { + //RebuildBrushes(); + } + + private void RebuildBrushes(int height) { + Color top = Cross(barColor3, progColor, barColor12); + Color bottom = Cross(barColor3, progColor, barColor8); + bar12 = new Pen(new SolidBrush(top), 1f); + bar8 = new Pen(new SolidBrush(bottom), 1f); + barBorderTop = new Pen(new SolidBrush(Cross(barColor3, progColor, barBorderTopColor)), 1f); + barBorderBottom = new Pen(new SolidBrush(Cross(barColor3, progColor, barBorderBottomColor)), 1f); + int h = height; + //if (h == 0) { h = 20; } + prog = new System.Drawing.Drawing2D.LinearGradientBrush(new Point(0, 1), new Point(0, h + 2), top, bottom); + + backtop = new Pen(new SolidBrush(Cross(backColor, bkColor, backtopColor)), 1f); + back = new SolidBrush(bkColor); + } + + private Color Cross(Color colorX, Color colorY, Color colorX2) { + int r = (int)(((float)colorY.R * (float)colorX2.R) / (float)colorX.R); + int g = (int)(((float)colorY.G * (float)colorX2.G) / (float)colorX.G); + int b = (int)(((float)colorY.B * (float)colorX2.B) / (float)colorX.B); + if (r > 255) { r = 255; } else if (r < 0) { r = 0; } + if (g > 255) { g = 255; } else if (g < 0) { g = 0; } + if (b > 255) { b = 255; } else if (b < 0) { b = 0; } + return Color.FromArgb(r, g, b); + } + + /// + protected override void DisposeThis(bool disposing) { + if (border != null) { border.Dispose(); } + if (backtop != null) { backtop.Dispose(); } + if (back != null) { back.Dispose(); } + if (bar12 != null) { bar12.Dispose(); } + if (bar8 != null) { bar8.Dispose(); } + if (barBorderTop != null) { barBorderTop.Dispose(); } + if (barBorderBottom != null) { barBorderBottom.Dispose(); } + if (prog != null) { prog.Dispose(); } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/MiddleGlossPainter.cs b/ProgressODoom/MiddleGlossPainter.cs new file mode 100644 index 0000000..4cf5467 --- /dev/null +++ b/ProgressODoom/MiddleGlossPainter.cs @@ -0,0 +1,162 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.MiddleGlossPainter), "Icons.MiddleGlossPainter.ico")] + public class MiddleGlossPainter : ChainedGlossPainter { + private GlossStyle style = GlossStyle.Both; + private int highAlpha = 240; + private int lowAlpha = 0; + private int fadewidth = 4; + private Brush highBrush; + private Brush lowBrush; + private Brush bothBrush; + private Rectangle box; + private Color color = Color.White; + private Color topColor; + private Color botColor; + + /// + [Category("Appearance"), Description("Gets or sets the style for this progress gloss"), Browsable(true)] + public GlossStyle Style { + get { return this.style; } + set { + this.style = value; + this.box = new Rectangle(0, 0, 1, 1); + FireChange(); + } + } + + /// + [Category("Blending"), Description("Gets or sets the high alpha value"), Browsable(true)] + public int AlphaHigh { + get { return this.highAlpha; } + set { + if (value < 0 || value > 255) { + throw new ArgumentException("Alpha values must be between 0 and 255."); + } + this.highAlpha = value; + this.box = new Rectangle(0, 0, 1, 1); + FireChange(); + } + } + + /// + [Category("Blending"), Description("Gets or sets the low alpha value"), Browsable(true)] + public int AlphaLow { + get { return this.lowAlpha; } + set { + if (value < 0 || value > 255) { + throw new ArgumentException("Alpha values must be between 0 and 255."); + } + this.lowAlpha = value; + this.box = new Rectangle(0, 0, 1, 1); + FireChange(); + } + } + /// + [Category("Blending"), Description("Gets or sets the number of pixels to blend over"), Browsable(true)] + public int TaperHeight { + get { return this.fadewidth; } + set { + this.fadewidth = value; + this.box = new Rectangle(0, 0, 1, 1); + FireChange(); + } + } + + /// + [Category("Appearance"), Description("Gets or sets color to gloss"), Browsable(true)] + public Color Color { + get { return this.color; } + set { + this.color = value; + this.topColor = Color.FromArgb(highAlpha, this.color.R, this.color.G, this.color.B); + this.botColor = Color.FromArgb(lowAlpha, this.color.R, this.color.G, this.color.B); + box = new Rectangle(0, 0, 1, 1); + FireChange(); + } + } + + protected override void PaintThisGloss(Rectangle box, Graphics g) { + if (!this.box.Equals(box)) { + this.box = box; + ResetBrushes(box); + } + + int midpoint = box.X + (int)((float)box.Height / 2f); + Rectangle topBox = new Rectangle(box.X, midpoint - fadewidth, box.Width - 1, fadewidth); + Rectangle botBox = new Rectangle(box.X, midpoint, box.Width - 1, fadewidth); + Rectangle fullBox = new Rectangle(box.X, midpoint - fadewidth, box.Width - 1, fadewidth * 2); + + switch (style) { + case GlossStyle.Bottom: + g.FillRectangle(lowBrush, botBox); + //g.DrawRectangle(Pens.Fuchsia, botBox); + break; + case GlossStyle.Top: + g.FillRectangle(highBrush, topBox); + //g.DrawRectangle(Pens.Fuchsia, topBox); + break; + case GlossStyle.Both: + //g.FillRectangle(highBrush, topBox); + //g.FillRectangle(lowBrush, botBox); + g.FillRectangle(bothBrush, fullBox); + break; + } + //g.DrawRectangle(Pens.Purple, fullBox); + //g.DrawRectangle(new Pen(new SolidBrush(Color.FromArgb(64, 255, 255, 0))), topBox); + //g.DrawRectangle(new Pen(new SolidBrush(Color.FromArgb(64, 0, 255, 0))), botBox); + } + + protected override void ResizeThis(Rectangle box) { + if (!this.box.Equals(box)) { + this.box = box; + ResetBrushes(box); + } + } + + private void ResetBrushes(Rectangle box) { + int midpoint = box.X + (int)((float)box.Height / 2f); + Rectangle topBox = new Rectangle(box.X, midpoint - fadewidth, box.Width - 1, fadewidth); + Rectangle botBox = new Rectangle(box.X, midpoint, box.Width - 1, fadewidth); + Rectangle fullBox = new Rectangle(box.X, midpoint - fadewidth, box.Width - 1, fadewidth * 2); + + //int midpoint = box.X + (int)((float)box.Height / 2f); + Point top = new Point(box.X, fullBox.Top); + Point topmid = new Point(box.X, topBox.Bottom); + Point botmid = new Point(box.X, botBox.Top); + Point bot = new Point(box.X, botBox.Bottom); + Color high = topColor; + Color low = botColor; + //Rectangle fullBox = new Rectangle(box.X, midpoint - fadewidth, box.Width - 1, fadewidth * 2); + switch (style) { + case GlossStyle.Top: + highBrush = new LinearGradientBrush(top, topmid, low, high); + break; + case GlossStyle.Bottom: + lowBrush = new LinearGradientBrush(botmid, bot, high, low); + break; + case GlossStyle.Both: + //highBrush = new LinearGradientBrush(top, topmid, low, high); + //lowBrush = new LinearGradientBrush(botmid, bot, high, low); + bothBrush = new LinearGradientBrush(fullBox, low, high, LinearGradientMode.Vertical); + //((LinearGradientBrush)bothBrush).SetSigmaBellShape(0.5f, 0.5f); + ((LinearGradientBrush)bothBrush).SetBlendTriangularShape(0.5f); + break; + } + } + + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + if (highBrush != null) { highBrush.Dispose(); } + if (lowBrush != null) { lowBrush.Dispose(); } + if (bothBrush != null) { bothBrush.Dispose(); } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/PlainBackgroundPainter.cs b/ProgressODoom/PlainBackgroundPainter.cs new file mode 100644 index 0000000..f00284f --- /dev/null +++ b/ProgressODoom/PlainBackgroundPainter.cs @@ -0,0 +1,95 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.PlainBackgroundPainter), "Icons.PlainBackgroundPainter.ico")] + public class PlainBackgroundPainter : Component, IProgressBackgroundPainter, IDisposable { + private Color color; + private Brush brush; + private IGlossPainter gloss; + + private EventHandler onPropertiesChanged; + /// + public event EventHandler PropertiesChanged { + add { + if (onPropertiesChanged != null) { + foreach (Delegate d in onPropertiesChanged.GetInvocationList()) { + if (object.ReferenceEquals(d, value)) { return; } + } + } + onPropertiesChanged = (EventHandler)Delegate.Combine(onPropertiesChanged, value); + } + remove { onPropertiesChanged = (EventHandler)Delegate.Remove(onPropertiesChanged, value); } + } + + private void FireChange() { + if (onPropertiesChanged != null) { onPropertiesChanged(this, EventArgs.Empty); } + } + + /// + /// + /// + protected virtual void component_PropertiesChanged(object sender, EventArgs e) { + FireChange(); + } + + /// + public PlainBackgroundPainter() { + this.Color = Color.FromArgb(240, 240, 240); + } + + /// + /// + public PlainBackgroundPainter(Color color) { + this.Color = color; + } + + /// + /// + [Category("Painters"), Description("Gets or sets the chain of gloss painters"), Browsable(true)] + public IGlossPainter GlossPainter { + get { return this.gloss; } + set { + this.gloss = value; + if (this.gloss != null) { this.gloss.PropertiesChanged += new EventHandler(component_PropertiesChanged); } + FireChange(); + } + } + + /// + [Category("Appearance"), Description("Gets or sets the background color"), Browsable(true)] + public Color Color { + get { return color; } + set { + color = value; + brush = new SolidBrush(color); + FireChange(); + } + } + + /// + /// + /// + public void PaintBackground(Rectangle box, Graphics g) { + g.FillRectangle(brush, box); + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + + /// + public void Resize(Rectangle box) { + } + + /// + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + brush.Dispose(); + } + } +} \ No newline at end of file diff --git a/ProgressODoom/PlainBorderPainter.cs b/ProgressODoom/PlainBorderPainter.cs new file mode 100644 index 0000000..f2e6c82 --- /dev/null +++ b/ProgressODoom/PlainBorderPainter.cs @@ -0,0 +1,158 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.PlainBorderPainter), "Icons.PlainBorderPainter.ico")] + public class PlainBorderPainter : Component, IProgressBorderPainter, IDisposable { + private Color color; + private Pen pent; + private Pen penb; + private Pen cleart; + private Pen clearb; + private bool rounded = false; + private PlainBorderStyle style = PlainBorderStyle.Flat; + + private EventHandler onPropertiesChanged; + /// + public event EventHandler PropertiesChanged { + add { + if (onPropertiesChanged != null) { + foreach (Delegate d in onPropertiesChanged.GetInvocationList()) { + if (object.ReferenceEquals(d, value)) { return; } + } + } + onPropertiesChanged = (EventHandler)Delegate.Combine(onPropertiesChanged, value); + } + remove { onPropertiesChanged = (EventHandler)Delegate.Remove(onPropertiesChanged, value); } + } + + private void FireChange() { + if (onPropertiesChanged != null) { onPropertiesChanged(this, EventArgs.Empty); } + } + + /// + public PlainBorderPainter() { + this.Color = Color.Black; + //this.clear = new Pen(new SolidBrush(SystemColors.Control)); + } + + /// + /// + public PlainBorderPainter(Color color) { + this.Color = color; + //this.clear = new Pen(new SolidBrush(SystemColors.Control)); + } + + /// + [Category("Appearance"), Description("Gets or sets the border color"), Browsable(true)] + public Color Color { + get { return color; } + set { + color = value; + if (style == PlainBorderStyle.Flat) { + pent = new Pen(new SolidBrush(color), 1f); + penb = pent; + this.cleart = new Pen(new SolidBrush(Color.FromArgb(64, color.R, color.G, color.B))); + this.clearb = cleart; + FireChange(); + } + } + } + + /// + [Category("Appearance"), Description("Determines wether or not to make the border a flat sqaure"), Browsable(true)] + public bool RoundedCorners { + get { return rounded; } + set { rounded = value; FireChange(); } + } + + [Category("Appearance"), Description("Gets or sets the border style"), Browsable(true)] + public PlainBorderStyle Style { + get { return style; } + set { + style = value; + switch (style) { + case PlainBorderStyle.Flat: + pent = new Pen(new SolidBrush(color), 1f); + penb = pent; + this.cleart = new Pen(new SolidBrush(Color.FromArgb(64, color.R, color.G, color.B))); + this.clearb = cleart; + break; + case PlainBorderStyle.Raised: + pent = new Pen(new SolidBrush(SystemColors.ControlLightLight), 1f); + penb = new Pen(new SolidBrush(SystemColors.ControlDark), 1f); + this.cleart = new Pen(new SolidBrush(Color.FromArgb(64, SystemColors.ControlLightLight.R, SystemColors.ControlLightLight.G, SystemColors.ControlLightLight.B))); + this.clearb = new Pen(new SolidBrush(Color.FromArgb(64, SystemColors.ControlDark.R, SystemColors.ControlDark.G, SystemColors.ControlDark.B))); + break; + case PlainBorderStyle.Sunken: + pent = new Pen(new SolidBrush(SystemColors.ControlDark), 1f); + penb = new Pen(new SolidBrush(SystemColors.ControlLightLight), 1f); + this.cleart = new Pen(new SolidBrush(Color.FromArgb(64, SystemColors.ControlDark.R, SystemColors.ControlDark.G, SystemColors.ControlDark.B))); + this.clearb = new Pen(new SolidBrush(Color.FromArgb(64, SystemColors.ControlLightLight.R, SystemColors.ControlLightLight.G, SystemColors.ControlLightLight.B))); + break; + } + FireChange(); + } + } + + /// + [Browsable(false)] + public int BorderWidth { + get { return 1; } + } + + /// + /// + /// + public void PaintBorder(Rectangle box, Graphics g) { + //try { + // box.Width -= 1; + // box.Height -= 1; + //} catch {} + if (rounded) { + //// draws the left and right side (because they're shorter) to cover the corner pixels. + //g.DrawLine(clear, box.X, 0, box.X, box.Height); + //g.DrawLine(clear, box.Width, 0, box.Width, box.Height); + + g.DrawLine(cleart, box.X, box.Y, box.Right - 1, box.Y); // top + g.DrawLine(cleart, box.X, box.Y, box.X, box.Bottom - 1); // left + g.DrawLine(clearb, box.X, box.Bottom, box.Right, box.Bottom); // bottom + g.DrawLine(clearb, box.Right, box.Y, box.Right, box.Bottom); // right + + //g.DrawRectangle(clear, box); + g.DrawLine(pent, box.X + 1, box.Y, box.Right - 1, box.Y); // top + g.DrawLine(penb, box.X + 1, box.Bottom, box.Right - 1, box.Bottom); // bottom + g.DrawLine(pent, box.X, box.Y + 1, box.X, box.Bottom - 1); // left + g.DrawLine(penb, box.Right, box.Y + 1, box.Right, box.Bottom - 1); // right + } else { + //g.DrawRectangle(pen, box); + g.DrawLine(pent, box.X, box.Y, box.Right, box.Y); // top + g.DrawLine(pent, box.X, box.Y, box.X, box.Bottom); // left + g.DrawLine(penb, box.X, box.Bottom, box.Right, box.Bottom); // bottom + g.DrawLine(penb, box.Right, box.Y, box.Right, box.Bottom); // right + } + } + + /// + public void Resize(Rectangle box) { + } + + /// + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + pent.Dispose(); + penb.Dispose(); + cleart.Dispose(); + clearb.Dispose(); + } + + /// + public enum PlainBorderStyle { + Flat, Sunken, Raised + } + } +} \ No newline at end of file diff --git a/ProgressODoom/PlainProgressPainter.cs b/ProgressODoom/PlainProgressPainter.cs new file mode 100644 index 0000000..fde2806 --- /dev/null +++ b/ProgressODoom/PlainProgressPainter.cs @@ -0,0 +1,66 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.PlainProgressPainter), "Icons.PlainProgressPainter.ico")] + public class PlainProgressPainter : AbstractProgressPainter, IProgressPainter, IDisposable { + private Color color; + private Brush brush; + private Color edge = Color.Transparent; + + /// + public PlainProgressPainter() { + this.Color = Color.FromArgb(151, 151, 234); + } + + /// + /// + public PlainProgressPainter(Color color) { + this.Color = color; + } + + /// + [Category("Appearance"), Description("Gets or sets the color to draw the leading edge of the progress with"), Browsable(true)] + public Color LeadingEdge { + get { return this.edge; } + set { this.edge = value; FireChange(); } + } + + /// + [Category("Appearance"), Description("Gets or sets the base progress color"), Browsable(true)] + public Color Color { + get { return color; } + set { + color = value; + brush = new SolidBrush(color); + FireChange(); + } + } + + /// + /// + /// + protected override void PaintThisProgress(Rectangle box, Graphics g) { + if (box.Width <= 1) { + return; + } + + g.FillRectangle(brush, box); + if (gloss != null) { + gloss.PaintGloss(box, g); + } + if (!edge.Equals(Color.Transparent)) { + g.DrawLine(new Pen(new SolidBrush(edge), 1f), box.Right, box.Y, box.Right, box.Bottom - 1); + } + } + + /// + protected override void DisposeThis(bool disposing) { + brush.Dispose(); + } + } +} \ No newline at end of file diff --git a/ProgressODoom/ProgressBarEx.cs b/ProgressODoom/ProgressBarEx.cs new file mode 100644 index 0000000..ac86d9b --- /dev/null +++ b/ProgressODoom/ProgressBarEx.cs @@ -0,0 +1,340 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.ProgressBarEx), "Icons.ProgressBarEx.ico")] + public class ProgressBarEx : AbstractProgressBar { + protected IProgressBackgroundPainter backgroundpainter; + protected IProgressPainter progresspainter; + protected IProgressBorderPainter borderpainter; + + public ProgressBarEx() { + backgroundpainter = new PlainBackgroundPainter(); + progresspainter = new PlainProgressPainter(Color.Gold); + borderpainter = new PlainBorderPainter(); + } + + /// + [Category("Painters"), Description("Paints this progress bar's background"), Browsable(true)] + public IProgressBackgroundPainter BackgroundPainter { + get { return this.backgroundpainter; } + set { + this.backgroundpainter = value; + this.backgroundpainter.PropertiesChanged += new EventHandler(component_PropertiesChanged); + this.Invalidate(); + } + } + + /// + /// + /// + protected virtual void component_PropertiesChanged(object sender, EventArgs e) { + this.Invalidate(); + } + + /// + [Category("Painters"), Description("Paints this progress bar's progress"), Browsable(true)] + public IProgressPainter ProgressPainter { + get { return this.progresspainter; } + set { + if (!(value is IAnimatedProgressPainter) && base.ProgressType == ProgressType.Animated) { + base.ProgressType = ProgressType.Smooth; + } + this.progresspainter = value; + if (this.progresspainter is AbstractProgressPainter) { + ((AbstractProgressPainter)this.progresspainter).padding = base.ProgressPadding; + } + this.progresspainter.PropertiesChanged += new EventHandler(component_PropertiesChanged); + this.Invalidate(); + } + } + + /// + [Category("Progress"), Description("Gets or sets the type of progress"), Browsable(true)] + public override ProgressType ProgressType { + get { return base.type; } + set { + if (value == ProgressType.Animated && !(progresspainter is IAnimatedProgressPainter)) { + throw new ArgumentException("Animated is not available with the current Progress Painter"); + } + this.type = value; + } + } + + /// + [Category("Painters"), Description("Paints this progress bar's border"), Browsable(true)] + public IProgressBorderPainter BorderPainter { + get { return this.borderpainter; } + set { + this.borderpainter = value; + this.borderpainter.PropertiesChanged += new EventHandler(component_PropertiesChanged); + ResizeProgress(); + this.Invalidate(); + } + } + + protected override void ResizeProgress() { + if (base.ProgressType != ProgressType.Smooth) { return; } + Rectangle newprog = base.borderbox; + //newprog.Inflate(this.borderpainter.BorderWidth, this.borderpainter.BorderWidth); + newprog.Offset(this.borderpainter.BorderWidth, this.borderpainter.BorderWidth); + newprog.Size = new Size(newprog.Size.Width - this.borderpainter.BorderWidth, newprog.Size.Height - this.borderpainter.BorderWidth); + base.backbox = newprog; + + int val = value; if (val > 0) { val++; } + int progWidth = maximum > 0 ? (backbox.Width * val / maximum) : 1; + if (value >= maximum && maximum > 0) { + progWidth = backbox.Width; + } /*else if (value > 0) { + progWidth++; + }*/ + newprog.Inflate(-base.ProgressPadding, -base.ProgressPadding); + newprog.Width = progWidth - (base.ProgressPadding * 2); + //newprog.Offset(base.ProgressPadding, base.ProgressPadding); + //newprog = new Rectangle(backbox.X + base.ProgressPadding, backbox.Y + base.ProgressPadding, progWidth - (base.ProgressPadding * 2), backbox.Height - (base.ProgressPadding * 2)); + base.progressbox = newprog; + } + + #region Animation + public void StartAnimation() { + if (running) { return; } + IAnimatedProgressPainter iapp = this.progresspainter as IAnimatedProgressPainter; + if (iapp == null) { return; } + iapp.Animating = true; + running = true; + timerMethod = new EventHandler(DoAnimation); + timer.Interval = iapp.AnimationSpeed; + timer.Tick += timerMethod; + timer.Enabled = true; + } + public void StopAnimation() { + timer.Enabled = false; + timer.Tick -= timerMethod; + running = false; + IAnimatedProgressPainter iapp = this.progresspainter as IAnimatedProgressPainter; + if (iapp == null) { return; } + iapp.Animating = false; + } + private void DoAnimation(object sender, EventArgs e) { + IAnimatedProgressPainter iapp = this.progresspainter as IAnimatedProgressPainter; + if (iapp == null) { return; } + + //Rectangle newprog = base.borderbox; + //newprog.Offset(this.borderpainter.BorderWidth, this.borderpainter.BorderWidth); + //newprog.Size = new Size(newprog.Size.Width - this.borderpainter.BorderWidth, newprog.Size.Height - this.borderpainter.BorderWidth); + ////int progWidth = (int)(((float)marqueePercentage * (float)backbox.Width) / 100f); + //int progWidth = (int)(((float)marqueePercentage * (float)backbox.Width) / 100f); + //newprog.Inflate(-base.ProgressPadding, -base.ProgressPadding); + //newprog.Width = progWidth - (base.ProgressPadding * 2); + + //base.progressbox = newprog; + + ////iapp.AnimateFrame(newprog, g, ref marqueeX); + + this.Invalidate(); + this.Refresh(); + } + #endregion + + #region Marquee + private bool running = false; + private Timer timer = new Timer(); + private EventHandler timerMethod; + /// + public override void MarqueeStart() { + if (running) { return; } + running = true; + switch (base.ProgressType) { + case ProgressType.MarqueeWrap: timerMethod = new EventHandler(DoMarqueeWrap); break; + case ProgressType.MarqueeBounce: timerMethod = new EventHandler(DoMarqueeBounce); break; + case ProgressType.MarqueeBounceDeep: timerMethod = new EventHandler(DoMarqueeDeep); break; + } + timer.Interval = base.marqueeSpeed; + timer.Tick += timerMethod; + timer.Enabled = true; + } + + private int marqueeX = 0; + private void DoMarqueeWrap(object sender, EventArgs e) { + Rectangle newprog = base.borderbox; + newprog.Offset(this.borderpainter.BorderWidth, this.borderpainter.BorderWidth); + newprog.Size = new Size(newprog.Size.Width - this.borderpainter.BorderWidth, newprog.Size.Height - this.borderpainter.BorderWidth); + + int progWidth = (int)(((float)marqueePercentage * (float)backbox.Width) / 100f); + + marqueeX += marqueeStep; + if (marqueeX > backbox.Width) { + marqueeX = 0 - progWidth; + } + + newprog.Inflate(-base.ProgressPadding, -base.ProgressPadding); + newprog.Width = progWidth - (base.ProgressPadding * 2); + newprog.X += marqueeX; + + int leftBoundry = backbox.X + this.borderpainter.BorderWidth + base.ProgressPadding; + int rightBoundry = backbox.X + backbox.Width - (this.borderpainter.BorderWidth + base.ProgressPadding); + if (marqueeX <= leftBoundry) { + newprog.Width -= leftBoundry - marqueeX; + newprog.X = leftBoundry; + } else if (marqueeX + newprog.Width >= rightBoundry) { + newprog.Width -= (marqueeX + newprog.Width + base.ProgressPadding) - rightBoundry; + } + + base.progressbox = newprog; + + this.Invalidate(); + this.Refresh(); + } + private bool marqueeForward = true; + private void DoMarqueeBounce(object sender, EventArgs e) { + Rectangle newprog = base.borderbox; + newprog.Offset(this.borderpainter.BorderWidth, this.borderpainter.BorderWidth); + newprog.Size = new Size(newprog.Size.Width - this.borderpainter.BorderWidth, newprog.Size.Height - this.borderpainter.BorderWidth); + + int progWidth = (int)(((float)marqueePercentage * (float)backbox.Width) / 100f); + + if (marqueeForward) { + marqueeX += marqueeStep; + } else { + marqueeX -= marqueeStep; + } + + newprog.Inflate(-base.ProgressPadding, -base.ProgressPadding); + newprog.Width = progWidth - (base.ProgressPadding * 2); + newprog.X += marqueeX; + + int leftBoundry = backbox.X + this.borderpainter.BorderWidth + base.ProgressPadding; + int rightBoundry = backbox.X + backbox.Width - (this.borderpainter.BorderWidth + base.ProgressPadding); + if (marqueeX + progWidth >= rightBoundry) { + marqueeForward = false; + } else if (marqueeX <= leftBoundry) { + marqueeForward = true; + } + + base.progressbox = newprog; + + this.Invalidate(); + this.Refresh(); + } + private void DoMarqueeDeep(object sender, EventArgs e) { + Rectangle newprog = base.borderbox; + newprog.Offset(this.borderpainter.BorderWidth, this.borderpainter.BorderWidth); + newprog.Size = new Size(newprog.Size.Width - this.borderpainter.BorderWidth, newprog.Size.Height - this.borderpainter.BorderWidth); + + int progWidth = (int)(((float)marqueePercentage * (float)backbox.Width) / 100f); + + if (marqueeForward) { + marqueeX += marqueeStep; + } else { + marqueeX -= marqueeStep; + } + if (marqueeX > backbox.Width) { + marqueeForward = false; + } else if (marqueeX < backbox.X - progWidth) { + marqueeForward = true; + } + + newprog.Inflate(-base.ProgressPadding, -base.ProgressPadding); + newprog.Width = progWidth - (base.ProgressPadding * 2); + newprog.X += marqueeX; + + int leftBoundry = backbox.X + this.borderpainter.BorderWidth + base.ProgressPadding; + int rightBoundry = backbox.X + backbox.Width - (this.borderpainter.BorderWidth + base.ProgressPadding); + if (marqueeX <= leftBoundry) { + newprog.Width -= leftBoundry - marqueeX; + newprog.X = leftBoundry; + } else if (marqueeX + newprog.Width >= rightBoundry) { + newprog.Width -= (marqueeX + newprog.Width + base.ProgressPadding) - rightBoundry; + } + + base.progressbox = newprog; + + this.Invalidate(); + this.Refresh(); + } + + /// + public override void MarqueePause() { + running = false; + timer.Enabled = false; + timer.Tick -= timerMethod; + } + /// + public override void MarqueeStop() { + Rectangle newprog = base.borderbox; + newprog.Offset(this.borderpainter.BorderWidth, this.borderpainter.BorderWidth); + newprog.Size = new Size(newprog.Size.Width - this.borderpainter.BorderWidth, newprog.Size.Height - this.borderpainter.BorderWidth); + + newprog.Inflate(-base.ProgressPadding, -base.ProgressPadding); + newprog.Width = 1; + base.progressbox = newprog; + + running = false; + timer.Enabled = false; + timer.Tick -= timerMethod; + + marqueeX = 0; + this.Invalidate(); + } + #endregion + + /// + /// + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + if (running) { running = false; } + } + + /// + /// + protected override void OnResize(EventArgs e) { + base.OnResize(e); + ResizeProgress(); + if (this.backgroundpainter != null) { this.backgroundpainter.Resize(borderbox); } + if (this.progresspainter != null) { this.progresspainter.Resize(borderbox); } + if (this.borderpainter != null) { this.borderpainter.Resize(borderbox); } + } + + /// + /// + protected override void PaintBackground(Graphics g) { + if (this.backgroundpainter != null) { + this.backgroundpainter.PaintBackground(backbox, g); + } + } + + /// + /// + protected override void PaintProgress(Graphics g) { + if (this.progresspainter != null) { + this.progresspainter.PaintProgress(progressbox, g); + } + } + + /// + /// + protected override void PaintText(Graphics g) { + if (base.ProgressType != ProgressType.Smooth) { return; } + Brush b = new SolidBrush(ForeColor); + SizeF sf = g.MeasureString(Text, Font, Convert.ToInt32(Width), StringFormat.GenericDefault); + float m = sf.Width; + float x = (Width / 2) - (m / 2); + float w = (Width / 2) + (m / 2); + float h = (float)borderbox.Height - (2f * (float)this.borderpainter.BorderWidth); + float y = (float)this.borderpainter.BorderWidth + ((h - sf.Height) / 2f); + g.DrawString(Text, Font, b, RectangleF.FromLTRB(x, y, w, Height - 1), StringFormat.GenericDefault); + } + + /// + /// + protected override void PaintBorder(Graphics g) { + if (this.borderpainter != null) { + this.borderpainter.PaintBorder(borderbox, g); + } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/ProgressODoom.csproj b/ProgressODoom/ProgressODoom.csproj new file mode 100644 index 0000000..32f98f1 --- /dev/null +++ b/ProgressODoom/ProgressODoom.csproj @@ -0,0 +1,224 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {8DD1E84B-0B03-4C0B-9B42-1E49F75E7CB1} + Library + Properties + ProgressODoom + ProgressODoom + + + 2.0 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + Component + + + Component + + + Component + + + Component + + + Component + + + Component + + + Component + + + Component + + + + Component + + + Component + + + Component + + + Component + + + Component + + + Component + + + + + + + + + Component + + + Component + + + Component + + + Component + + + Component + + + Component + + + Component + + + + Component + + + Component + + + Component + + + Component + + + Component + + + Component + + + Component + + + Component + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + .NET Framework Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + + + + + \ No newline at end of file diff --git a/ProgressODoom/ProgressODoom.csproj.user b/ProgressODoom/ProgressODoom.csproj.user new file mode 100644 index 0000000..ce4e607 --- /dev/null +++ b/ProgressODoom/ProgressODoom.csproj.user @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + en-US + false + + \ No newline at end of file diff --git a/ProgressODoom/Properties/AssemblyInfo.cs b/ProgressODoom/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..9ed59a3 --- /dev/null +++ b/ProgressODoom/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +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("ProgressODoom")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ProgressODoom")] +[assembly: AssemblyCopyright("Copyright © 2008")] +[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("375b7734-9e29-4ae9-8c57-d1bf00450128")] + +// 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 Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ProgressODoom/RarBackgroundPainter.cs b/ProgressODoom/RarBackgroundPainter.cs new file mode 100644 index 0000000..882d04f --- /dev/null +++ b/ProgressODoom/RarBackgroundPainter.cs @@ -0,0 +1,83 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + [ToolboxBitmapAttribute(typeof(ProgressODoom.RarBackgroundPainter), "Icons.RarBackgroundPainter.ico")] + public class RarBackgroundPainter : Component, IProgressBackgroundPainter, IDisposable { + private Brush brush; + private IGlossPainter gloss; + private Pen outer, inner, border; + + private EventHandler onPropertiesChanged; + /// + public event EventHandler PropertiesChanged { + add { + if (onPropertiesChanged != null) { + foreach (Delegate d in onPropertiesChanged.GetInvocationList()) { + if (object.ReferenceEquals(d, value)) { return; } + } + } + onPropertiesChanged = (EventHandler)Delegate.Combine(onPropertiesChanged, value); + } + remove { onPropertiesChanged = (EventHandler)Delegate.Remove(onPropertiesChanged, value); } + } + + private void FireChange() { + if (onPropertiesChanged != null) { onPropertiesChanged(this, EventArgs.Empty); } + } + + /// + /// + /// + protected virtual void component_PropertiesChanged(object sender, EventArgs e) { + FireChange(); + } + + public RarBackgroundPainter() { + brush = new SolidBrush(Color.FromArgb(148, 110, 110)); + inner = new Pen(new SolidBrush(Color.FromArgb(158, 128, 128)), 1f); + outer = new Pen(new SolidBrush(Color.FromArgb(180, 148, 148)), 1f); + border = new Pen(new SolidBrush(Color.FromArgb(096, 096, 096)), 1f); + } + + /// + public IGlossPainter GlossPainter { + get { return this.gloss; } + set { + this.gloss = value; + if (this.gloss != null) { this.gloss.PropertiesChanged += new EventHandler(component_PropertiesChanged); } + FireChange(); + } + } + + /// + /// + /// + public void PaintBackground(Rectangle box, Graphics g) { + g.FillRectangle(brush, box); + g.DrawRectangle(inner, 2, 2, box.Width - 3, box.Height - 4); + g.DrawRectangle(outer, 1, 1, box.Width - 1, box.Height - 2); + g.DrawLine(border, 1, box.Height, box.Width, box.Height); + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + + /// + public void Resize(Rectangle box) { + } + + /// + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + brush.Dispose(); + inner.Dispose(); + outer.Dispose(); + border.Dispose(); + } + } +} \ No newline at end of file diff --git a/ProgressODoom/RarBorderPainter.cs b/ProgressODoom/RarBorderPainter.cs new file mode 100644 index 0000000..ffd6ba0 --- /dev/null +++ b/ProgressODoom/RarBorderPainter.cs @@ -0,0 +1,61 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.RarBorderPainter), "Icons.RarBorderPainter.ico")] + public class RarBorderPainter : Component, IProgressBorderPainter, IDisposable { + private Pen border; + + private EventHandler onPropertiesChanged; + /// + public event EventHandler PropertiesChanged { + add { + if (onPropertiesChanged != null) { + foreach (Delegate d in onPropertiesChanged.GetInvocationList()) { + if (object.ReferenceEquals(d, value)) { return; } + } + } + onPropertiesChanged = (EventHandler)Delegate.Combine(onPropertiesChanged, value); + } + remove { onPropertiesChanged = (EventHandler)Delegate.Remove(onPropertiesChanged, value); } + } + + private void FireChange() { + if (onPropertiesChanged != null) { onPropertiesChanged(this, EventArgs.Empty); } + } + + /// + public RarBorderPainter() { + border = new Pen(new SolidBrush(Color.FromArgb(064, 064, 070)), 1f); + } + + /// + [Browsable(false)] + public int BorderWidth { + get { return 1; } + } + + /// + /// + /// + public void PaintBorder(Rectangle box, Graphics g) { + g.DrawRectangle(new Pen(new SolidBrush(SystemColors.Control), 1f), 0, 0, box.Width, box.Height); + g.DrawLine(border, 2, box.Height, box.Width, box.Height); + g.DrawLine(border, box.Width, 3, box.Width, box.Height); + } + + /// + public void Resize(Rectangle box) { + } + + /// + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + border.Dispose(); + } + } +} \ No newline at end of file diff --git a/ProgressODoom/RarProgressBar.cs b/ProgressODoom/RarProgressBar.cs new file mode 100644 index 0000000..f16bcf8 --- /dev/null +++ b/ProgressODoom/RarProgressBar.cs @@ -0,0 +1,31 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + [ToolboxBitmapAttribute(typeof(ProgressODoom.RarProgressBar), "Icons.RarProgressBar.ico")] + public class RarProgressBar : DualProgressBar { + public RarProgressBar() { + this.MasterPainter = new RarProgressPainter(RarProgressPainter.RarProgressType.Silver); + ((RarProgressPainter)this.MasterPainter).ShowEdge = false; + this.ProgressPainter = new RarProgressPainter(RarProgressPainter.RarProgressType.Gold); + ((RarProgressPainter)this.ProgressPainter).ShowEdge = true; + this.BorderPainter = new RarBorderPainter(); + this.BackgroundPainter = new RarBackgroundPainter(); + this.PaintMasterFirst = true; + this.OnValueChanged += new EventHandler(onValueChanged); + this.OnMasterValueChanged += new EventHandler(onValueChanged); + } + + private void onValueChanged(object sender, EventArgs e) { + bool masterAhead = false; + if (this.MasterValue > this.Value) { + masterAhead = true; + } + ((RarProgressPainter)this.MasterPainter).ShowEdge = masterAhead; + ((RarProgressPainter)this.ProgressPainter).ShowEdge = !masterAhead; + } + } +} \ No newline at end of file diff --git a/ProgressODoom/RarProgressPainter.cs b/ProgressODoom/RarProgressPainter.cs new file mode 100644 index 0000000..e547201 --- /dev/null +++ b/ProgressODoom/RarProgressPainter.cs @@ -0,0 +1,103 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.RarProgressPainter), "Icons.RarProgressPainter.ico")] + public class RarProgressPainter : AbstractProgressPainter, IProgressPainter, IDisposable { + private Brush brush; + private Pen inner, outer, edge; + private bool showEdge = false; + private RarProgressType type; + + /// + public RarProgressPainter() { + this.ProgressType = RarProgressType.Silver; + } + + /// + /// + public RarProgressPainter(RarProgressType type) { + this.ProgressType = type; + } + + /// + [Category("Appearance"), Description("Gets or sets the type of rar progress color"), Browsable(true)] + public RarProgressType ProgressType { + get { return type; } + set { + this.type = value; + switch (type) { + case RarProgressType.Silver: + brush = new SolidBrush(Color.FromArgb(214, 214, 220)); + inner = new Pen(new SolidBrush(Color.FromArgb(232, 232, 238)), 1f); + outer = new Pen(new SolidBrush(Color.FromArgb(255, 255, 255)), 1f); + edge = new Pen(new SolidBrush(Color.FromArgb(096, 096, 096)), 1f); + break; + case RarProgressType.Gold: + brush = new SolidBrush(Color.FromArgb(208, 192, 160)); + inner = new Pen(new SolidBrush(Color.FromArgb(228, 212, 180)), 1f); + outer = new Pen(new SolidBrush(Color.FromArgb(255, 255, 192)), 1f); + edge = new Pen(new SolidBrush(Color.FromArgb(096, 096, 096)), 1f); + break; + } + FireChange(); + } + } + + /// + [Category("Appearance"), Description("Gets or sets whether or not this progress has a leading edge"), Browsable(true)] + public bool ShowEdge { + get { return showEdge; } + set { + showEdge = value; + FireChange(); + } + } + + /// + /// + /// + protected override void PaintThisProgress(Rectangle box, Graphics g) { + try { + box.Width -= 1; + box.Height -= 1; + } catch {} + if (box.Width <= 1) { + return; + } + + g.FillRectangle(brush, box); + Rectangle innerBox = box; + innerBox.Inflate(-1, -1); + g.DrawRectangle(inner, innerBox); + g.DrawLine(outer, box.X, box.Y, box.Right, box.Y); + g.DrawLine(outer, box.X, box.Y, box.X, box.Bottom); + g.DrawLine(edge, box.X, box.Bottom, box.Right, box.Bottom); + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + + if (showEdge) { + g.DrawLine(edge, box.Right, box.Y, box.Right, box.Bottom); + } + } + + /// + protected override void DisposeThis(bool disposing) { + brush.Dispose(); + inner.Dispose(); + outer.Dispose(); + edge.Dispose(); + } + + /// + public enum RarProgressType { + Gold, Silver + } + } +} \ No newline at end of file diff --git a/ProgressODoom/RoundGlossPainter.cs b/ProgressODoom/RoundGlossPainter.cs new file mode 100644 index 0000000..9b27e06 --- /dev/null +++ b/ProgressODoom/RoundGlossPainter.cs @@ -0,0 +1,172 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + public enum GlossStyle { + Top, Bottom, Both + } + + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.RoundGlossPainter), "Icons.RoundGlossPainter.ico")] + public class RoundGlossPainter : ChainedGlossPainter { + private GlossStyle style = GlossStyle.Both; + private int highAlpha = 240; + private int lowAlpha = 0; + private int fadewidth = 4; + private Brush highBrush; + private Brush lowBrush; + private Rectangle box; + private Color color = Color.White; + private Color topColor; + private Color botColor; + + /// + [Category("Appearance"), Description("Gets or sets the style for this progress gloss"), Browsable(true)] + public GlossStyle Style { + get { return this.style; } + set { + this.style = value; + FireChange(); + } + } + + /// + [Category("Blending"), Description("Gets or sets the high alpha value"), Browsable(true)] + public int AlphaHigh { + get { return this.highAlpha; } + set { + if (value < 0 || value > 255) { + throw new ArgumentException("Alpha values must be between 0 and 255."); + } + this.highAlpha = value; + FireChange(); + } + } + + /// + [Category("Blending"), Description("Gets or sets the low alpha value"), Browsable(true)] + public int AlphaLow { + get { return this.lowAlpha; } + set { + if (value < 0 || value > 255) { + throw new ArgumentException("Alpha values must be between 0 and 255."); + } + this.lowAlpha = value; + FireChange(); + } + } + + /// + [Category("Blending"), Description("Gets or sets the number of pixels to blend over"), Browsable(true)] + public int TaperHeight { + get { return this.fadewidth; } + set { + this.fadewidth = value; + FireChange(); + } + } + + /// + [Category("Appearance"), Description("Gets or sets color to gloss"), Browsable(true)] + public Color Color { + get { return this.color; } + set { + this.color = value; + this.topColor = Color.FromArgb(highAlpha, this.color.R, this.color.G, this.color.B); + this.botColor = Color.FromArgb(lowAlpha, this.color.R, this.color.G, this.color.B); + box = new Rectangle(0, 0, 1, 1); + FireChange(); + } + } + + protected override void PaintThisGloss(Rectangle box, Graphics g) { + if (!this.box.Equals(box)) { + this.box = box; + ResetBrushes(box); + } + + //int midpoint = (int)((float)box.Height / 2f); + //int toppoint = midpoint > (fadewidth + 2) ? midpoint - (fadewidth / 2) : midpoint; + //int botpoint = midpoint > (fadewidth + 2) ? midpoint + (fadewidth / 2) : midpoint; + + //Rectangle topBox = new Rectangle(box.X, box.Y, box.Width - 1, box.Y + fadewidth); + //Rectangle botBox = new Rectangle(box.X, box.Bottom - fadewidth - 2, box.Width - 1, fadewidth + 1); + Rectangle topBox = new Rectangle(box.X, box.Y, box.Width, fadewidth); + Rectangle botBox = new Rectangle(box.X, box.Bottom - fadewidth, box.Width, fadewidth); + + //if (midpoint - fadewidth > 2) { midpoint -= fadewidth; } + + switch (style) { + case GlossStyle.Bottom: + g.FillRectangle(lowBrush, botBox); + break; + case GlossStyle.Top: + g.FillRectangle(highBrush, topBox); + break; + case GlossStyle.Both: + g.FillRectangle(highBrush, topBox); + g.FillRectangle(lowBrush, botBox); + //g.DrawRectangle(Pens.Red, topBox); + //g.DrawRectangle(Pens.Blue, botBox); + break; + } + //g.DrawRectangle(new Pen(new SolidBrush(Color.FromArgb(64, 255, 0, 0))), topBox); + //g.FillRectangle(new SolidBrush(Color.FromArgb(32, 255, 0, 0)), topBox); + //g.DrawRectangle(new Pen(new SolidBrush(Color.FromArgb(64, 0, 0, 255))), botBox); + //g.FillRectangle(new SolidBrush(Color.FromArgb(32, 0, 0, 255)), botBox); + } + + protected override void ResizeThis(Rectangle box) { + if (!this.box.Equals(box)) { + this.box = box; + ResetBrushes(box); + } + } + + private void ResetBrushes(Rectangle box) { + //int midpoint = (int)((float)box.Height / 2f); + //int toppoint = midpoint - (fadewidth / 2); + //if (toppoint < box.Y + 2) { toppoint = box.Y + 2; } + //int botpoint = midpoint + (fadewidth / 2); + //if (botpoint > box.Height - 2) { botpoint = box.Height - 2; } + + //Point top = new Point(box.X, box.Y); + //Point topmid = new Point(box.X, box.Y + fadewidth + 1); + //Point botmid = new Point(box.X, box.Height - fadewidth - 1); + //Point bot = new Point(box.X, box.Bottom); + + Rectangle topBox = new Rectangle(box.X, box.Y, box.Width, fadewidth); + Rectangle botBox = new Rectangle(box.X, box.Bottom - fadewidth, box.Width, fadewidth); + Point top = new Point(box.X, topBox.Top); + Point topmid = new Point(box.X, topBox.Bottom); + Point botmid = new Point(box.X, botBox.Top - 1); + Point bot = new Point(box.X, botBox.Bottom); + + Color high = topColor; + Color low = botColor; + switch (style) { + case GlossStyle.Top: + highBrush = new LinearGradientBrush(top, topmid, high, low); + break; + case GlossStyle.Bottom: + lowBrush = new LinearGradientBrush(botmid, bot, low, high); + break; + case GlossStyle.Both: + highBrush = new LinearGradientBrush(top, topmid, high, low); + lowBrush = new LinearGradientBrush(botmid, bot, low, high); + break; + } + } + + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + if (highBrush != null) { highBrush.Dispose(); } + if (lowBrush != null) { lowBrush.Dispose(); } + } + } +} \ No newline at end of file diff --git a/ProgressODoom/StripedProgressPainter.cs b/ProgressODoom/StripedProgressPainter.cs new file mode 100644 index 0000000..fc87d7a --- /dev/null +++ b/ProgressODoom/StripedProgressPainter.cs @@ -0,0 +1,183 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.StripedProgressPainter), "Icons.StripedProgressPainter.ico")] + public class StripedProgressPainter : AbstractProgressPainter, IProgressPainter, IAnimatedProgressPainter, IDisposable { + private Color color1 = Color.FromArgb(110, 195, 248); + private Color color2 = Color.FromArgb(056, 150, 230); + private Color blend = Color.FromArgb(097, 184, 244); + private int spacing = 6; + private int marqueeSpeed = 10; + + private int marqueeX = 0; + + private bool isAnimated = false; + + /// + public StripedProgressPainter() { + } + + /// + public Color BaseColor { + get { return color1; } + set { + color1 = value; + blend = ColorRange.Morph(0.25f, color1, color2); + FireChange(); + } + } + + /// + public Color StripeColor { + get { return color2; } + set { + color2 = value; + blend = ColorRange.Morph(0.25f, color1, color2); + FireChange(); + } + } + + /// + public int StripeSpacing { + get { return spacing; } + set { spacing = value; FireChange(); } + } + + /// + public int AnimationSpeed { + get { return marqueeSpeed; } + set { marqueeSpeed = value; FireChange(); } + } + + /// + public bool Animating { + get { return isAnimated; } + set { isAnimated = value; } + } + + private void AnimateFrame(Rectangle box, Graphics g, ref int marqueeX) { + if (box == null || g == null || box.Width <= 1) { return; } + + Pen penb = new Pen(new SolidBrush(blend)); + g.FillRectangle(new SolidBrush(color1), box); + for (int i = box.Right + marqueeX; i > box.Left; i -= ((box.Height * 2) + StripeSpacing - 1)) { + Point theoreticalRightTop = new Point(i, box.Top); + Point theoreticalRightBottom = new Point(i - box.Height, box.Bottom); + Point theoreticalLeftTop = new Point(i - box.Height, box.Top); + Point theoreticalLeftBottom = new Point(i - (box.Height * 2), box.Bottom); + + Point leftTop, leftBottom, rightTop, rightBottom; + using (GraphicsPath gp = new GraphicsPath()) { + if (theoreticalLeftTop.X <= box.Left) { + // left triangle + int diff = i - box.Height; + rightTop = new Point(i, box.Top); + rightBottom = new Point(box.Left, box.Bottom + diff); + leftTop = new Point(box.Left, box.Top); + leftBottom = leftTop; + + if (rightBottom.Equals(rightTop)) { continue; } + + gp.AddLine(rightTop, rightBottom); + gp.AddLine(rightBottom, leftTop); + gp.AddLine(leftTop, new Point(i, box.Top)); + } else if (theoreticalLeftBottom.X <= box.Left) { + // left pentagon + int diff = i - (box.Height * 2); + rightTop = new Point(i, box.Top); + rightBottom = new Point(i - box.Height, box.Bottom); + leftTop = new Point(i - box.Height, box.Top); + leftBottom = new Point(box.Left, box.Bottom + diff); + + gp.AddLine(rightTop, rightBottom); + gp.AddLine(rightBottom, new Point(box.Left, box.Bottom)); + gp.AddLine(new Point(box.Left, box.Bottom), leftBottom); + gp.AddLine(leftBottom, leftTop); + gp.AddLine(leftTop, rightTop); + } else if (theoreticalRightBottom.X >= box.Right) { + // right triangle + int diff = marqueeX - box.Height; + leftTop = new Point(box.Right, box.Top + diff); //= something funky + leftBottom = theoreticalLeftBottom; + rightBottom = new Point(box.Right, box.Bottom); + rightTop = rightBottom; + + if (leftBottom.Equals(leftTop)) { continue; } + + gp.AddLine(leftTop, rightBottom); + gp.AddLine(rightBottom, leftBottom); + gp.AddLine(leftBottom, leftTop); + } else if (theoreticalRightTop.X >= box.Right) { + // right pentagon + int diff = i - box.Right; + Point topRight = new Point(box.Right, box.Top); + rightTop = new Point(box.Right, box.Top + diff); + rightBottom = new Point(i - box.Height, box.Bottom); + leftTop = new Point(i - box.Height, box.Top); + leftBottom = new Point(i - (box.Height * 2), box.Bottom); + + gp.AddLine(leftTop, topRight); + gp.AddLine(topRight, rightTop); + gp.AddLine(rightTop, rightBottom); + gp.AddLine(rightBottom, leftBottom); + gp.AddLine(leftBottom, leftTop); + } else { + // mid-range rectangle + rightTop = new Point(i, box.Top); + rightBottom = new Point(i - box.Height, box.Bottom); + leftTop = new Point(i - box.Height, box.Top); + leftBottom = new Point(i - (box.Height * 2), box.Bottom); + + gp.AddLine(rightTop, rightBottom); + gp.AddLine(rightBottom, leftBottom); + gp.AddLine(leftBottom, leftTop); + gp.AddLine(leftTop, rightTop); + } + g.FillPath(new SolidBrush(color2), gp); + } + + if (!leftTop.Equals(leftBottom)) { + g.DrawLine(penb, leftTop, leftBottom); + } + if (!rightTop.Equals(rightBottom)) { + g.DrawLine(penb, rightTop, rightBottom); + } + } + g.DrawLine(penb, new Point(box.Left, box.Bottom), new Point(box.Right, box.Bottom)); + + if (++marqueeX > (box.Height * 2) + StripeSpacing) { + marqueeX = 1; + } + } + + /// + /// + /// + protected override void PaintThisProgress(Rectangle box, Graphics g) { + if (box.Width <= 1) { + return; + } + + if (isAnimated) { + AnimateFrame(box, g, ref marqueeX); + } else { + int x = 0; + AnimateFrame(box, g, ref x); + } + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + + /// + protected override void DisposeThis(bool disposing) { + } + } +} \ No newline at end of file diff --git a/ProgressODoom/StyledBorderPainter.cs b/ProgressODoom/StyledBorderPainter.cs new file mode 100644 index 0000000..a7b08bb --- /dev/null +++ b/ProgressODoom/StyledBorderPainter.cs @@ -0,0 +1,66 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + /// + [ToolboxBitmapAttribute(typeof(ProgressODoom.StyledBorderPainter), "Icons.StyledBorderPainter.ico")] + public class StyledBorderPainter : Component, IProgressBorderPainter, IDisposable { + private Border3DStyle border; + + private EventHandler onPropertiesChanged; + /// + public event EventHandler PropertiesChanged { + add { + if (onPropertiesChanged != null) { + foreach (Delegate d in onPropertiesChanged.GetInvocationList()) { + if (object.ReferenceEquals(d, value)) { return; } + } + } + onPropertiesChanged = (EventHandler)Delegate.Combine(onPropertiesChanged, value); + } + remove { onPropertiesChanged = (EventHandler)Delegate.Remove(onPropertiesChanged, value); } + } + + private void FireChange() { + if (onPropertiesChanged != null) { onPropertiesChanged(this, EventArgs.Empty); } + } + + /// + public StyledBorderPainter() { + border = Border3DStyle.Raised; + } + + /// + [Category("Appearance"), Description("Gets or sets the border style"), Browsable(true)] + public Border3DStyle Border3D { + get { return border; } + set { border = value; FireChange(); } + } + + /// + [Browsable(false)] + public int BorderWidth { + get { return 2; } + } + + /// + /// + /// + public void PaintBorder(Rectangle box, Graphics g) { + Rectangle brd = new Rectangle(box.X, box.Y, box.Width, box.Height + 1); + ControlPaint.DrawBorder3D(g, brd, border); + } + + /// + public void Resize(Rectangle box) { + } + + /// + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + } + } +} \ No newline at end of file diff --git a/ProgressODoom/WaveProgressPainter.cs b/ProgressODoom/WaveProgressPainter.cs new file mode 100644 index 0000000..69504a0 --- /dev/null +++ b/ProgressODoom/WaveProgressPainter.cs @@ -0,0 +1,112 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; +using System.Collections.Generic; + +namespace ProgressODoom { + [ToolboxBitmapAttribute(typeof(ProgressODoom.WaveProgressPainter), "Icons.WaveProgressPainter.ico")] + public class WaveProgressPainter : AbstractProgressPainter, IProgressPainter, IAnimatedProgressPainter, IDisposable { + private Color color1 = Color.FromArgb(110, 195, 248); + private Color color2 = Color.FromArgb(056, 150, 230); + private int marqueeSpeed = 10; + private int marqueeX = 0; + private int animateX = 0; + private bool isAnimated = false; + + /// + public Color BaseColor { + get { return color1; } + set { + color1 = value; + FireChange(); + } + } + + /// + public Color WaveColor { + get { return color2; } + set { + color2 = value; + FireChange(); + } + } + + /// + public int AnimationSpeed { + get { return marqueeSpeed; } + set { marqueeSpeed = value; FireChange(); } + } + + /// + public bool Animating { + get { return isAnimated; } + set { isAnimated = value; } + } + + private void AnimateFrame(Rectangle box, Graphics g, ref int marqueeX) { + if (box == null || g == null || box.Width <= 1) { return; } + + g.SmoothingMode = SmoothingMode.AntiAlias; + //g.Clip = new Region(box); + + g.FillRectangle(new SolidBrush(color1), box); + int h = box.Height; + int hm = (int)((float)h / 2f); + + using (GraphicsPath gp = new GraphicsPath()) { + Point MidLeft = new Point(0, hm); + Point MidRight = new Point(h * 2, hm); + + int currentX = box.Right + animateX; // Increment currentX to animate + int left = currentX - (h * 2); + if (left < box.Left) { left = box.Left; } + while (currentX > box.Left) { + left = currentX - (h * 2); + + MidLeft = new Point(left, hm); + MidRight = new Point(currentX, hm); + + int crestX = currentX - h; + gp.AddBezier(MidRight, new Point(crestX, 0), new Point(crestX, h), MidLeft); + currentX -= h * 2; + } + gp.AddLine(MidLeft, new Point(box.Left, box.Bottom)); // left side + gp.AddLine(new Point(box.Left, box.Bottom), new Point(box.Right, box.Bottom)); // bottom + gp.AddLine(new Point(box.Right, box.Bottom), new Point(box.Right, hm)); // right side + + g.FillPath(new SolidBrush(color2), gp); + } + g.SmoothingMode = SmoothingMode.Default; + + if (isAnimated && ++animateX > (box.Height * 2)) { + animateX = 1; + } + } + + /// + /// + /// + protected override void PaintThisProgress(Rectangle box, Graphics g) { + if (box.Width <= 1) { + return; + } + + if (isAnimated) { + AnimateFrame(box, g, ref marqueeX); + } else { + int x = 0; + AnimateFrame(box, g, ref x); + } + + if (gloss != null) { + gloss.PaintGloss(box, g); + } + } + + /// + protected override void DisposeThis(bool disposing) { + } + } +} \ No newline at end of file