UltimateZoneBuilder/Source/BuilderModes/Interface/ErrorCheckForm.cs

240 lines
6.2 KiB
C#
Raw Normal View History

2008-10-23 05:53:34 +00:00
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;
using CodeImp.DoomBuilder.Actions;
using CodeImp.DoomBuilder.Data;
using CodeImp.DoomBuilder.Config;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Controls;
using CodeImp.DoomBuilder.Windows;
using System.Reflection;
using System.Globalization;
2008-10-23 11:36:00 +00:00
using System.Threading;
2008-10-23 05:53:34 +00:00
#endregion
namespace CodeImp.DoomBuilder.BuilderModes
{
public partial class ErrorCheckForm : DelayedForm
{
2008-10-23 11:36:00 +00:00
#region ================== Constants
// Constants
private const int RESULTS_WINDOW_HEIGHT = 536;
#endregion
#region ================== Variables
private bool running = false;
private Thread checksthread;
#endregion
2008-10-23 05:53:34 +00:00
#region ================== Constructor / Show
// Constructor
public ErrorCheckForm()
{
2008-10-23 11:36:00 +00:00
// Initialize
2008-10-23 05:53:34 +00:00
InitializeComponent();
2008-10-23 11:36:00 +00:00
// Find all error checkers
Type[] checkertypes = BuilderPlug.Me.FindClasses(typeof(ErrorChecker));
foreach(Type t in checkertypes)
{
object[] attr = t.GetCustomAttributes(typeof(ErrorCheckerAttribute), true);
if(attr.Length > 0)
{
ErrorCheckerAttribute checkerattr = (attr[0] as ErrorCheckerAttribute);
// Add the type to the checkbox list
CheckBox c = checks.Add(checkerattr.DisplayName, t);
c.Checked = checkerattr.DefaultChecked;
}
}
2008-10-23 05:53:34 +00:00
}
2008-10-23 11:36:00 +00:00
2008-10-23 05:53:34 +00:00
// This shows the window
public void Show(Form owner)
{
// First time showing?
//if((this.Location.X == 0) && (this.Location.Y == 0))
{
// Position at left-top of owner
this.Location = new Point(owner.Location.X + 20, owner.Location.Y + 90);
}
2008-10-23 11:36:00 +00:00
2008-10-23 05:53:34 +00:00
// Close results part
2008-10-23 11:36:00 +00:00
resultspanel.Visible = false;
this.Size = new Size(this.Width, this.Height - this.ClientSize.Height + resultspanel.Top);
2008-10-23 05:53:34 +00:00
// Show window
base.Show(owner);
}
#endregion
2008-10-23 11:36:00 +00:00
#region ================== Methods
// This runs in a seperate thread to manage the checking threads
private void RunChecks()
{
List<ErrorChecker> checkers = new List<ErrorChecker>();
int totalprogress = 0;
int nextchecker = 0;
// Initiate all checkers
foreach(CheckBox c in checks.Checkboxes)
{
// Include this one?
if(c.Checked)
{
Type t = (c.Tag as Type);
ErrorChecker checker = null;
try
{
// Create instance
checker = (ErrorChecker)Assembly.GetExecutingAssembly().CreateInstance(t.FullName, false, BindingFlags.Default, null, null, CultureInfo.CurrentCulture, new object[0]);
}
catch(TargetInvocationException ex)
{
// Error!
General.WriteLogLine("ERROR: Failed to create class instance '" + t.Name + "'!");
General.WriteLogLine(ex.InnerException.GetType().Name + ": " + ex.InnerException.Message);
throw ex;
}
catch(Exception ex)
{
// Error!
General.WriteLogLine("ERROR: Failed to create class instance '" + t.Name + "'!");
General.WriteLogLine(ex.GetType().Name + ": " + ex.Message);
throw ex;
}
// Add to list
if(checker != null)
{
checkers.Add(checker);
totalprogress += checker.TotalProgress;
}
}
}
// Setup
progress.Maximum = totalprogress;
const int maxthreads = Environment.ProcessorCount;
List<Thread> threads = new List<Thread>(maxthreads);
// Continue while threads are running or checks are to be done
while((nextchecker < checkers.Count) || (threads.Count > 0))
{
// Start new thread when less than maximum number of
// threads running and there is more work to be done
while((threads.Count < maxthreads) && (checkers.Count > 0))
{
ErrorChecker c = checkers[nextchecker++];
Thread t = new Thread(new ThreadStart(c.Run));
t.Name = "Error Checker '" + c.GetType().Name + "'";
t.Priority = ThreadPriority.BelowNormal;
t.Start();
threads.Add(t);
}
// Remove threads that are done
for(int i = threads.Count; i >= 0; i--)
if(!threads[i].IsAlive) threads.RemoveAt(i);
// Handle thread interruption
try { Thread.Sleep(1); }
catch(ThreadInterruptedException) { break; }
}
// Stop all running threads
foreach(Thread t in threads)
{
t.Interrupt();
t.Join();
}
// Dispose all checkers
checkers = null;
// Done
progress.Value = 0;
}
#endregion
2008-10-23 05:53:34 +00:00
#region ================== Events
2008-10-23 11:36:00 +00:00
2008-10-23 05:53:34 +00:00
// Window closing
private void ErrorCheckForm_FormClosing(object sender, FormClosingEventArgs e)
{
// If the user closes the form, then just cancel the mode
if(e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
General.Map.CancelMode();
}
}
2008-10-23 11:36:00 +00:00
// Start/stop
private void buttoncheck_Click(object sender, EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
// Currently running?
if(running)
{
// Stop checking
checksthread.Interrupt();
checksthread.Join();
checksthread = null;
running = false;
}
else
{
// Open the results panel
this.Size = new Size(this.Width, this.Height - this.ClientSize.Height + resultspanel.Top + resultspanel.Height);
progress.Value = 0;
results.Items.Clear();
resultspanel.Visible = true;
// Start checking
running = true;
checksthread = new Thread(new ThreadStart(RunChecks));
checksthread.Name = "Checking Management";
checksthread.Priority = ThreadPriority.Normal;
checksthread.Start();
}
Cursor.Current = Cursors.Default;
}
2008-10-23 05:53:34 +00:00
#endregion
}
}