mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-12-17 23:51:10 +00:00
e4cad3e06c
Map Analysis mode: selection color is now used when rendering affected things. Fixed, Map Analysis mode, "Check unused things" check: checker returned false-positive results when used in Doom map format.
779 lines
No EOL
20 KiB
C#
779 lines
No EOL
20 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
|
|
|
|
#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)
|
|
{
|
|
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;
|
|
this.Text = "Map Analysis [" + resultslist.Count + " results"
|
|
+ (hiddencount > 0 ? ", " + hiddencount + " are hidden]" : "]"); //mxd
|
|
}
|
|
|
|
// 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;
|
|
UpdateTitle(); //mxd
|
|
|
|
// When no results found, show "no results" and disable the list
|
|
if(resultslist.Count == 0)
|
|
{
|
|
results.Items.Add(new ResultNoErrors());
|
|
results.Enabled = false;
|
|
}
|
|
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;
|
|
}
|
|
|
|
// 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 ex;
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
// Error!
|
|
General.ErrorLogger.Add(ErrorType.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;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
// 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);
|
|
}
|
|
}
|
|
}
|
|
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
|
|
UpdateTitle();
|
|
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
|
|
foreach (ErrorResult r in tohide) results.Items.Remove(r);
|
|
|
|
// Do the obvious
|
|
UpdateTitle();
|
|
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
|
|
UpdateTitle();
|
|
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
|
|
UpdateTitle();
|
|
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.SetText(sb.ToString());
|
|
|
|
// 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();
|
|
for(int i = 0; i < results.Items.Count; i++) results.SelectedItems.Add(results.Items[i]);
|
|
}
|
|
}
|
|
|
|
private void resultselectcurrenttype_Click(object sender, EventArgs e)
|
|
{
|
|
Dictionary<Type, bool> toselect = GetSelectedTypes();
|
|
results.SelectedItems.Clear();
|
|
|
|
for(int i = 0; i < results.Items.Count; i++)
|
|
{
|
|
if(toselect.ContainsKey(results.Items[i].GetType())) results.SelectedItems.Add(results.Items[i]);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
} |