mirror of
https://git.do.srb2.org/STJr/ZoneBuilder.git
synced 2024-11-15 00:51:39 +00:00
154ceb0eb7
Changed, Map Analysis mode: some checks are now available only under certain conditions (for example, "Check polyobjects" is now available only when the map is in Hexen or UDMF map format). Updated documentation ("Game Configuration - Basic Settings" page).
827 lines
No EOL
21 KiB
C#
827 lines
No EOL
21 KiB
C#
|
|
#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.Drawing;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using CodeImp.DoomBuilder.Editing;
|
|
using CodeImp.DoomBuilder.Map;
|
|
using CodeImp.DoomBuilder.Windows;
|
|
using System.Reflection;
|
|
using System.Globalization;
|
|
using System.Threading;
|
|
|
|
#endregion
|
|
|
|
namespace CodeImp.DoomBuilder.BuilderModes
|
|
{
|
|
public partial class ErrorCheckForm : DelayedForm
|
|
{
|
|
#region ================== Constants
|
|
|
|
#endregion
|
|
|
|
#region ================== Delegates
|
|
|
|
private delegate void CallVoidMethodDeletage();
|
|
private delegate void CallIntMethodDelegate(int i);
|
|
private delegate void CallResultMethodDelegate(ErrorResult r);
|
|
|
|
#endregion
|
|
|
|
#region ================== Variables
|
|
|
|
private volatile bool running;
|
|
private Thread checksthread;
|
|
private BlockMap<BlockEntry> blockmap;
|
|
private Size initialsize; //mxd
|
|
private List<ErrorResult> resultslist; //mxd
|
|
private List<Type> hiddentresulttypes; //mxd
|
|
private bool bathselectioninprogress; //mxd
|
|
|
|
#endregion
|
|
|
|
#region ================== Properties
|
|
|
|
public List<ErrorResult> SelectedResults {
|
|
get
|
|
{
|
|
List<ErrorResult> selection = new List<ErrorResult>();
|
|
foreach(Object ro in results.SelectedItems)
|
|
{
|
|
ErrorResult result = ro as ErrorResult;
|
|
if(result == null) continue;
|
|
selection.Add(result);
|
|
}
|
|
return selection;
|
|
}
|
|
}
|
|
public BlockMap<BlockEntry> BlockMap { get { return blockmap; } }
|
|
|
|
#endregion
|
|
|
|
#region ================== Constructor / Show
|
|
|
|
// Constructor
|
|
public ErrorCheckForm()
|
|
{
|
|
// Initialize
|
|
InitializeComponent();
|
|
|
|
// 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)
|
|
{
|
|
//mxd. Skip this check?..
|
|
ErrorChecker checker;
|
|
|
|
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.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance \"" + t.Name + "\"");
|
|
General.WriteLogLine(ex.InnerException.GetType().Name + ": " + ex.InnerException.Message);
|
|
throw;
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
// Error!
|
|
General.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance \"" + t.Name + "\"");
|
|
General.WriteLogLine(ex.GetType().Name + ": " + ex.Message);
|
|
throw;
|
|
}
|
|
|
|
if(checker.SkipCheck) continue;
|
|
|
|
ErrorCheckerAttribute checkerattr = (attr[0] as ErrorCheckerAttribute);
|
|
|
|
// Add the type to the checkbox list
|
|
CheckBox c = checks.Add(checkerattr.DisplayName, t);
|
|
c.Checked = checkerattr.DefaultChecked;
|
|
}
|
|
}
|
|
checks.Sort(); //mxd
|
|
|
|
//mxd. Store initial height
|
|
initialsize = this.Size;
|
|
resultslist = new List<ErrorResult>();
|
|
hiddentresulttypes = new List<Type>();
|
|
}
|
|
|
|
// This shows the window
|
|
public void Show(Form owner)
|
|
{
|
|
// Move controls according to the height of the checkers box
|
|
checks.PerformLayout();
|
|
buttoncheck.Top = checks.Bottom + 14;
|
|
resultspanel.Top = buttoncheck.Bottom + 14;
|
|
this.Text = "Map Analysis"; //mxd
|
|
|
|
// Position at left-top of owner
|
|
this.Location = new Point(owner.Location.X + 20, owner.Location.Y + 90);
|
|
|
|
// Close results part
|
|
resultspanel.Visible = false;
|
|
this.Size = new Size(initialsize.Width, this.Height - this.ClientSize.Height + resultspanel.Top);
|
|
this.MinimumSize = this.Size; //mxd
|
|
this.MaximumSize = this.Size; //mxd
|
|
|
|
// Show window
|
|
base.Show(owner);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Thread Calls
|
|
|
|
public void SubmitResult(ErrorResult result)
|
|
{
|
|
if(results.InvokeRequired)
|
|
{
|
|
CallResultMethodDelegate d = SubmitResult;
|
|
try { progress.Invoke(d, result); }
|
|
catch(ThreadInterruptedException) { }
|
|
}
|
|
else
|
|
{
|
|
if(!result.IsHidden && !hiddentresulttypes.Contains(result.GetType())) //mxd
|
|
{
|
|
results.Items.Add(result);
|
|
}
|
|
resultslist.Add(result); //mxd
|
|
UpdateTitle();
|
|
}
|
|
}
|
|
|
|
private void SetProgressMaximum(int maximum)
|
|
{
|
|
if(progress.InvokeRequired)
|
|
{
|
|
CallIntMethodDelegate d = SetProgressMaximum;
|
|
try { progress.Invoke(d, maximum); }
|
|
catch(ThreadInterruptedException) { }
|
|
}
|
|
else
|
|
{
|
|
progress.Maximum = maximum;
|
|
}
|
|
}
|
|
|
|
public void AddProgressValue(int value)
|
|
{
|
|
if(progress.InvokeRequired)
|
|
{
|
|
CallIntMethodDelegate d = AddProgressValue;
|
|
try { progress.Invoke(d, value); }
|
|
catch(ThreadInterruptedException) { }
|
|
}
|
|
else
|
|
{
|
|
progress.Value += value;
|
|
}
|
|
}
|
|
|
|
//mxd
|
|
private void UpdateTitle()
|
|
{
|
|
int hiddencount = resultslist.Count - results.Items.Count;
|
|
string title = "Map Analysis [" + resultslist.Count + " results";
|
|
if(hiddencount > 0) title += hiddencount + " hidden";
|
|
title += ", " + results.SelectedItems.Count + " selected";
|
|
this.Text = title + @"]";
|
|
}
|
|
|
|
// This stops checking (only called from the checking management thread)
|
|
private void StopChecking()
|
|
{
|
|
if(this.InvokeRequired)
|
|
{
|
|
CallVoidMethodDeletage d = StopChecking;
|
|
this.Invoke(d);
|
|
}
|
|
else
|
|
{
|
|
checksthread = null;
|
|
progress.Value = 0;
|
|
buttoncheck.Text = "Start Analysis";
|
|
Cursor.Current = Cursors.Default;
|
|
running = false;
|
|
blockmap.Dispose();
|
|
blockmap = null;
|
|
|
|
// When no results found, show "no results" and disable the list
|
|
if(resultslist.Count == 0)
|
|
{
|
|
results.Items.Add(new ResultNoErrors());
|
|
results.Enabled = false;
|
|
UpdateTitle(); //mxd
|
|
}
|
|
else
|
|
{
|
|
ClearSelectedResult(); //mxd
|
|
}
|
|
}
|
|
}
|
|
|
|
// This starts checking
|
|
private void StartChecking()
|
|
{
|
|
if(running) return;
|
|
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
|
|
// Make blockmap
|
|
RectangleF area = MapSet.CreateArea(General.Map.Map.Vertices);
|
|
area = MapSet.IncreaseArea(area, General.Map.Map.Things);
|
|
blockmap = new BlockMap<BlockEntry>(area);
|
|
blockmap.AddLinedefsSet(General.Map.Map.Linedefs);
|
|
blockmap.AddSectorsSet(General.Map.Map.Sectors);
|
|
blockmap.AddThingsSet(General.Map.Map.Things);
|
|
blockmap.AddVerticesSet(General.Map.Map.Vertices); //mxd
|
|
|
|
//mxd. Open the results panel
|
|
if(!resultspanel.Visible)
|
|
{
|
|
this.MinimumSize = new Size();
|
|
this.MaximumSize = new Size();
|
|
this.Size = initialsize;
|
|
resultspanel.Size = new Size(resultspanel.Width, this.ClientSize.Height - resultspanel.Top);
|
|
resultspanel.Visible = true;
|
|
}
|
|
progress.Value = 0;
|
|
results.Items.Clear();
|
|
results.Enabled = true;
|
|
resultslist = new List<ErrorResult>(); //mxd
|
|
ClearSelectedResult();
|
|
buttoncheck.Text = "Abort Analysis";
|
|
General.Interface.RedrawDisplay();
|
|
|
|
// Start checking
|
|
running = true;
|
|
checksthread = new Thread(RunChecks);
|
|
checksthread.Name = "Error Checking Management";
|
|
checksthread.Priority = ThreadPriority.Normal;
|
|
checksthread.Start();
|
|
|
|
Cursor.Current = Cursors.Default;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Methods
|
|
|
|
// This stops the checking
|
|
public void CloseWindow()
|
|
{
|
|
// Currently running?
|
|
if(running)
|
|
{
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
checksthread.Interrupt();
|
|
}
|
|
|
|
ClearSelectedResult();
|
|
|
|
//mxd. Clear results
|
|
resultslist.Clear();
|
|
results.Items.Clear();
|
|
|
|
this.Hide();
|
|
}
|
|
|
|
// This clears the selected result
|
|
private void ClearSelectedResult()
|
|
{
|
|
results.SelectedItems.Clear(); //mxd
|
|
if(results.Items.Count == 0 && resultslist.Count > 0) //mxd
|
|
resultinfo.Text = "All results are hidden. Use context menu to show them.";
|
|
else
|
|
resultinfo.Text = "Select a result from the list to see more information.\r\nHold 'Ctrl' to select several results.\r\nHold 'Shift' to select a range of results.\r\nRight-click on a result to show context menu.";
|
|
resultinfo.Enabled = false;
|
|
fix1.Visible = false;
|
|
fix2.Visible = false;
|
|
fix3.Visible = false;
|
|
|
|
UpdateTitle(); //mxd
|
|
}
|
|
|
|
// This runs in a seperate thread to manage the checking threads
|
|
private void RunChecks()
|
|
{
|
|
List<ErrorChecker> checkers = new List<ErrorChecker>();
|
|
List<Thread> threads = new List<Thread>();
|
|
int maxthreads = Environment.ProcessorCount;
|
|
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;
|
|
|
|
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.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance \"" + t.Name + "\"");
|
|
General.WriteLogLine(ex.InnerException.GetType().Name + ": " + ex.InnerException.Message);
|
|
throw;
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
// Error!
|
|
General.ErrorLogger.Add(ErrorType.Error, "Failed to create class instance \"" + t.Name + "\"");
|
|
General.WriteLogLine(ex.GetType().Name + ": " + ex.Message);
|
|
throw;
|
|
}
|
|
|
|
// Add to list
|
|
if(checker != null)
|
|
{
|
|
checkers.Add(checker);
|
|
totalprogress += checker.TotalProgress;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sort the checkers with highest cost first
|
|
// See CompareTo method in ErrorChecker for sorting comparison
|
|
checkers.Sort();
|
|
|
|
// Setup
|
|
SetProgressMaximum(totalprogress);
|
|
|
|
// 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) && (nextchecker < checkers.Count))
|
|
{
|
|
ErrorChecker c = checkers[nextchecker++];
|
|
Thread t = new Thread(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 - 1; 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)
|
|
{
|
|
while(t.IsAlive)
|
|
{
|
|
try
|
|
{
|
|
t.Interrupt();
|
|
t.Join(1);
|
|
}
|
|
catch(ThreadInterruptedException)
|
|
{
|
|
// We have to continue, we can't just leave the other threads running!
|
|
}
|
|
}
|
|
}
|
|
|
|
// Done
|
|
StopChecking();
|
|
}
|
|
|
|
//mxd
|
|
private Dictionary<Type, bool> GetSelectedTypes()
|
|
{
|
|
Dictionary<Type, bool> selectedtypes = new Dictionary<Type, bool>();
|
|
foreach(var ro in results.SelectedItems)
|
|
{
|
|
ErrorResult r = ro as ErrorResult;
|
|
if(r == null) continue;
|
|
Type t = r.GetType();
|
|
if(!selectedtypes.ContainsKey(t)) selectedtypes.Add(t, false);
|
|
}
|
|
|
|
return selectedtypes;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Events
|
|
|
|
// Window closing
|
|
private void ErrorCheckForm_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
//mxd. Clear results
|
|
resultslist.Clear();
|
|
results.Items.Clear();
|
|
|
|
// If the user closes the form, then just cancel the mode
|
|
if(e.CloseReason == CloseReason.UserClosing)
|
|
{
|
|
e.Cancel = true;
|
|
General.Interface.Focus();
|
|
General.Editing.CancelMode();
|
|
}
|
|
}
|
|
|
|
// Start/stop
|
|
private void buttoncheck_Click(object sender, EventArgs e)
|
|
{
|
|
// Currently running?
|
|
if(running)
|
|
{
|
|
Cursor.Current = Cursors.WaitCursor;
|
|
checksthread.Interrupt();
|
|
}
|
|
else
|
|
{
|
|
StartChecking();
|
|
}
|
|
}
|
|
|
|
// Close
|
|
private void closebutton_Click(object sender, EventArgs e)
|
|
{
|
|
General.Interface.Focus();
|
|
General.Editing.CancelMode();
|
|
}
|
|
|
|
// Results selection changed
|
|
private void results_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
//mxd
|
|
if(bathselectioninprogress) return;
|
|
|
|
// Anything selected?
|
|
if(results.SelectedItems.Count > 0)
|
|
{
|
|
ErrorResult firstresult = (results.SelectedItems[0] as ErrorResult);
|
|
if(firstresult == null)
|
|
{
|
|
ClearSelectedResult();
|
|
}
|
|
else
|
|
{
|
|
bool sametype = true;
|
|
List<ErrorResult> validresults = new List<ErrorResult>();
|
|
|
|
// Selected results have the same fixes?
|
|
foreach(var ri in results.SelectedItems)
|
|
{
|
|
ErrorResult result = ri as ErrorResult;
|
|
if(result == null) continue;
|
|
validresults.Add(result);
|
|
|
|
if(result.Buttons != firstresult.Buttons || result.Button1Text != firstresult.Button1Text
|
|
|| result.Button2Text != firstresult.Button2Text || result.Button3Text != firstresult.Button3Text)
|
|
{
|
|
sametype = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
resultinfo.Enabled = true;
|
|
|
|
if(sametype)
|
|
{
|
|
resultinfo.Text = firstresult.Description;
|
|
fix1.Text = firstresult.Button1Text;
|
|
fix2.Text = firstresult.Button2Text;
|
|
fix3.Text = firstresult.Button3Text;
|
|
fix1.Visible = (firstresult.Buttons > 0);
|
|
fix2.Visible = (firstresult.Buttons > 1);
|
|
fix3.Visible = (firstresult.Buttons > 2);
|
|
}
|
|
else
|
|
{
|
|
resultinfo.Text = "Several types of map analysis results are selected. To display fixes, make sure that only a single result type is selected.";
|
|
fix1.Visible = false;
|
|
fix2.Visible = false;
|
|
fix3.Visible = false;
|
|
}
|
|
|
|
// Zoom to area
|
|
if(validresults.Count > 0)
|
|
{
|
|
RectangleF zoomarea = validresults[0].GetZoomArea();
|
|
foreach(ErrorResult result in validresults)
|
|
{
|
|
zoomarea = RectangleF.Union(zoomarea, result.GetZoomArea());
|
|
}
|
|
|
|
ClassicMode editmode = (General.Editing.Mode as ClassicMode);
|
|
editmode.CenterOnArea(zoomarea, 0.6f);
|
|
}
|
|
}
|
|
|
|
UpdateTitle(); //mxd
|
|
}
|
|
else
|
|
{
|
|
ClearSelectedResult();
|
|
}
|
|
|
|
General.Interface.RedrawDisplay();
|
|
}
|
|
|
|
// First button
|
|
private void fix1_Click(object sender, EventArgs e)
|
|
{
|
|
// Anything selected?
|
|
if(results.SelectedItems.Count > 0)
|
|
{
|
|
if(running)
|
|
{
|
|
General.ShowWarningMessage("You must stop the analysis before you can make changes to your map!", MessageBoxButtons.OK);
|
|
}
|
|
else
|
|
{
|
|
ErrorResult r = (results.SelectedItem as ErrorResult);
|
|
if(r.Button1Click(false))
|
|
{
|
|
if(results.SelectedItems.Count > 1) FixSimilarErrors(r.GetType(), 1); //mxd
|
|
StartChecking();
|
|
}
|
|
else
|
|
{
|
|
General.Interface.RedrawDisplay();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Second button
|
|
private void fix2_Click(object sender, EventArgs e)
|
|
{
|
|
// Anything selected?
|
|
if(results.SelectedIndex >= 0)
|
|
{
|
|
if(running)
|
|
{
|
|
General.ShowWarningMessage("You must stop the analysis before you can make changes to your map!", MessageBoxButtons.OK);
|
|
}
|
|
else
|
|
{
|
|
ErrorResult r = (results.SelectedItem as ErrorResult);
|
|
if(r.Button2Click(false))
|
|
{
|
|
if(results.SelectedItems.Count > 1) FixSimilarErrors(r.GetType(), 2); //mxd
|
|
StartChecking();
|
|
}
|
|
else
|
|
{
|
|
General.Interface.RedrawDisplay();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Third button
|
|
private void fix3_Click(object sender, EventArgs e)
|
|
{
|
|
// Anything selected?
|
|
if(results.SelectedIndex >= 0)
|
|
{
|
|
if(running)
|
|
{
|
|
General.ShowWarningMessage("You must stop the analysis before you can make changes to your map!", MessageBoxButtons.OK);
|
|
}
|
|
else
|
|
{
|
|
ErrorResult r = (results.SelectedItem as ErrorResult);
|
|
if(r.Button3Click(false))
|
|
{
|
|
if(results.SelectedItems.Count > 1) FixSimilarErrors(r.GetType(), 3); //mxd
|
|
StartChecking();
|
|
}
|
|
else
|
|
{
|
|
General.Interface.RedrawDisplay();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//mxd
|
|
private void FixSimilarErrors(Type type, int fixIndex)
|
|
{
|
|
foreach(Object item in results.SelectedItems)
|
|
{
|
|
if(item == results.SelectedItem) continue;
|
|
if(item.GetType() != type) continue;
|
|
|
|
ErrorResult r = item as ErrorResult;
|
|
|
|
if(fixIndex == 1 && !r.Button1Click(true)) break;
|
|
if(fixIndex == 2 && !r.Button2Click(true)) break;
|
|
if(fixIndex == 3 && !r.Button3Click(true)) break;
|
|
}
|
|
}
|
|
|
|
//mxd
|
|
private void toggleall_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
foreach(CheckBox cb in checks.Checkboxes) cb.Checked = toggleall.Checked;
|
|
}
|
|
|
|
private void ErrorCheckForm_HelpRequested(object sender, HelpEventArgs hlpevent)
|
|
{
|
|
General.ShowHelp("e_mapanalysis.html");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ================== Results Context Menu (mxd)
|
|
|
|
private void resultcontextmenustrip_Opening(object sender, System.ComponentModel.CancelEventArgs e)
|
|
{
|
|
//disable or enable stuff
|
|
bool haveresult = resultslist.Count > 0 && results.SelectedItems.Count > 0;
|
|
resultshowall.Enabled = (resultslist.Count > 0 && resultslist.Count > results.Items.Count);
|
|
resultselectcurrenttype.Enabled = haveresult;
|
|
resultcopytoclipboard.Enabled = haveresult;
|
|
resulthidecurrent.Enabled = haveresult;
|
|
resulthidecurrenttype.Enabled = haveresult;
|
|
resultshowonlycurrent.Enabled = haveresult;
|
|
}
|
|
|
|
private void resultshowall_Click(object sender, EventArgs e)
|
|
{
|
|
// Reset ignored items
|
|
foreach(ErrorResult result in resultslist) result.Hide(false);
|
|
|
|
// Restore items
|
|
results.Items.Clear();
|
|
results.Items.AddRange(resultslist.ToArray());
|
|
hiddentresulttypes.Clear();
|
|
|
|
// Do the obvious
|
|
ClearSelectedResult();
|
|
}
|
|
|
|
private void resulthidecurrent_Click(object sender, EventArgs e)
|
|
{
|
|
// Collect results to hide
|
|
List<ErrorResult> tohide = new List<ErrorResult>();
|
|
foreach(var ro in results.SelectedItems)
|
|
{
|
|
ErrorResult r = ro as ErrorResult;
|
|
if(r == null) return;
|
|
r.Hide(true);
|
|
tohide.Add(r);
|
|
}
|
|
|
|
// Remove from the list
|
|
results.BeginUpdate();
|
|
foreach(ErrorResult r in tohide) results.Items.Remove(r);
|
|
results.EndUpdate();
|
|
|
|
// Do the obvious
|
|
ClearSelectedResult();
|
|
}
|
|
|
|
private void resulthidecurrenttype_Click(object sender, EventArgs e)
|
|
{
|
|
Dictionary<Type, bool> tohide = GetSelectedTypes();
|
|
List<ErrorResult> filtered = new List<ErrorResult>();
|
|
hiddentresulttypes.AddRange(tohide.Keys);
|
|
|
|
// Apply filtering
|
|
foreach(ErrorResult result in results.Items)
|
|
{
|
|
if(!tohide.ContainsKey(result.GetType())) filtered.Add(result);
|
|
}
|
|
|
|
// Replace items
|
|
results.Items.Clear();
|
|
results.Items.AddRange(filtered.ToArray());
|
|
|
|
// Do the obvious
|
|
ClearSelectedResult();
|
|
}
|
|
|
|
private void resultshowonlycurrent_Click(object sender, EventArgs e)
|
|
{
|
|
Dictionary<Type, bool> toshow = GetSelectedTypes();
|
|
List<ErrorResult> filtered = new List<ErrorResult>();
|
|
hiddentresulttypes.Clear();
|
|
|
|
// Apply filtering
|
|
foreach(ErrorResult result in results.Items)
|
|
{
|
|
Type curresulttype = result.GetType();
|
|
if(!toshow.ContainsKey(curresulttype))
|
|
{
|
|
hiddentresulttypes.Add(curresulttype);
|
|
}
|
|
else
|
|
{
|
|
filtered.Add(result);
|
|
}
|
|
}
|
|
|
|
// Replace items
|
|
results.Items.Clear();
|
|
results.Items.AddRange(filtered.ToArray());
|
|
|
|
// Do the obvious
|
|
ClearSelectedResult();
|
|
}
|
|
|
|
private void resultcopytoclipboard_Click(object sender, EventArgs e)
|
|
{
|
|
// Get results
|
|
StringBuilder sb = new StringBuilder();
|
|
foreach(ErrorResult result in results.SelectedItems) sb.AppendLine(result.ToString());
|
|
|
|
// Set on clipboard
|
|
Clipboard.SetDataObject(sb.ToString(), true, 5, 200); //mxd
|
|
|
|
// Inform the user
|
|
General.Interface.DisplayStatus(StatusType.Info, "Analysis results copied to clipboard.");
|
|
}
|
|
|
|
private void results_KeyUp(object sender, KeyEventArgs e)
|
|
{
|
|
// Copy descriptions to clipboard?
|
|
if(e.Control && e.KeyCode == Keys.C)
|
|
{
|
|
resultcopytoclipboard_Click(sender, EventArgs.Empty);
|
|
}
|
|
// Select all?
|
|
else if(e.Control && e.KeyCode == Keys.A)
|
|
{
|
|
results.SelectedItems.Clear();
|
|
|
|
bathselectioninprogress = true; //mxd
|
|
results.BeginUpdate(); //mxd
|
|
for(int i = 0; i < results.Items.Count; i++) results.SelectedItems.Add(results.Items[i]);
|
|
results.EndUpdate(); //mxd
|
|
bathselectioninprogress = false; //mxd
|
|
|
|
results_SelectedIndexChanged(this, EventArgs.Empty); //trigger update manually
|
|
}
|
|
}
|
|
|
|
private void resultselectcurrenttype_Click(object sender, EventArgs e)
|
|
{
|
|
Dictionary<Type, bool> toselect = GetSelectedTypes();
|
|
results.SelectedItems.Clear();
|
|
|
|
bathselectioninprogress = true; //mxd
|
|
results.BeginUpdate(); //mxd
|
|
|
|
for(int i = 0; i < results.Items.Count; i++)
|
|
{
|
|
if(toselect.ContainsKey(results.Items[i].GetType())) results.SelectedItems.Add(results.Items[i]);
|
|
}
|
|
|
|
results.EndUpdate(); //mxd
|
|
bathselectioninprogress = false; //mxd
|
|
|
|
results_SelectedIndexChanged(this, EventArgs.Empty); //trigger update manually
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
} |