Browse Source

Improved sorting of TaskList (patch by David Alpert)

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@767 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
7acf63b916
  1. 4
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  2. 306
      src/Main/Base/Project/Src/Gui/Pads/OpenTaskView.cs
  3. 105
      src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskList.cs
  4. 321
      src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskView.cs

4
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -259,7 +259,6 @@ @@ -259,7 +259,6 @@
<Compile Include="Src\Gui\Pads\FileScout.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Src\Gui\Pads\OpenTaskView.cs" />
<Compile Include="Src\Gui\Pads\PropertyPad\PropertyPad.cs" />
<Compile Include="Src\Gui\Pads\SideBarView.cs" />
<Compile Include="Src\Gui\Pads\TreeViewMemento.cs" />
@ -723,6 +722,8 @@ @@ -723,6 +722,8 @@
<Compile Include="Src\Gui\Pads\ProjectBrowser\NodeBuilder\NodeBuilders.cs" />
<Compile Include="Src\TextEditor\Gui\Editor\CompletionWindow\TextCompletionDataProvider.cs" />
<Compile Include="Src\TextEditor\Gui\Editor\CompletionWindow\OverrideCompletionDataProvider.cs" />
<Compile Include="Src\Gui\Pads\TaskList\TaskView.cs" />
<Compile Include="Src\Gui\Pads\TaskList\TaskList.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Libraries\DockPanel_Src\WinFormsUI\WinFormsUI.csproj">
@ -743,6 +744,7 @@ @@ -743,6 +744,7 @@
</ProjectReference>
<Folder Include="Src\Gui\Components\AutoHide" />
<Folder Include="Src\Gui\TreeGrid" />
<Folder Include="Src\Gui\Pads\TaskList" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
</Project>

306
src/Main/Base/Project/Src/Gui/Pads/OpenTaskView.cs

@ -1,306 +0,0 @@ @@ -1,306 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows.Forms;
using System.Drawing;
using System.CodeDom.Compiler;
using System.Collections;
using System.IO;
using System.Diagnostics;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Gui
{
public class OpenTaskView : AbstractPadContent
{
ListView listView = new ListView();
ColumnHeader type = new ColumnHeader();
ColumnHeader line = new ColumnHeader();
ColumnHeader description = new ColumnHeader();
ColumnHeader file = new ColumnHeader();
ColumnHeader path = new ColumnHeader();
ToolTip taskToolTip = new ToolTip();
public override Control Control {
get {
return listView;
}
}
public OpenTaskView()
{
type.Text = "!";
RedrawContent();
listView.Columns.Add(type);
listView.Columns.Add(line);
listView.Columns.Add(description);
listView.Columns.Add(file);
listView.Columns.Add(path);
listView.FullRowSelect = true;
listView.AutoArrange = true;
listView.Alignment = ListViewAlignment.Left;
listView.View = View.Details;
listView.Dock = DockStyle.Fill;
listView.GridLines = true;
listView.Activation = ItemActivation.OneClick;
ListViewResize(this, EventArgs.Empty);
TaskService.Cleared += new EventHandler(TaskServiceCleared);
TaskService.Added += new TaskEventHandler(TaskServiceAdded);
TaskService.Removed += new TaskEventHandler(TaskServiceRemoved);
ProjectService.SolutionLoaded += OnCombineOpen;
ProjectService.SolutionClosed += OnCombineClosed;
ImageList imglist = new ImageList();
imglist.ColorDepth = ColorDepth.Depth32Bit;
imglist.Images.Add(ResourceService.GetBitmap("Icons.16x16.Error"));
imglist.Images.Add(ResourceService.GetBitmap("Icons.16x16.Warning"));
imglist.Images.Add(ResourceService.GetBitmap("Icons.16x16.Information"));
imglist.Images.Add(ResourceService.GetBitmap("Icons.16x16.Question"));
listView.SmallImageList = listView.LargeImageList = imglist;
// Set up the delays for the ToolTip.
taskToolTip.InitialDelay = 500;
taskToolTip.ReshowDelay = 100;
taskToolTip.AutoPopDelay = 5000;
//
// // Force the ToolTip text to be displayed whether or not the form is active.
// taskToolTip.ShowAlways = false;
listView.ItemActivate += new EventHandler(ListViewItemActivate);
listView.MouseMove += new MouseEventHandler(ListViewMouseMove);
listView.Resize += new EventHandler(ListViewResize);
listView.ColumnClick += new ColumnClickEventHandler(ListViewColumnClick);
ShowResults2(null, null);
}
public void ListViewColumnClick(object sender, ColumnClickEventArgs e)
{
listView.ListViewItemSorter = new OpenTaskViewSorter(e.Column);
}
public override void RedrawContent()
{
line.Text = ResourceService.GetString("CompilerResultView.LineText");
description.Text = ResourceService.GetString("CompilerResultView.DescriptionText");
file.Text = ResourceService.GetString("CompilerResultView.FileText");
path.Text = ResourceService.GetString("CompilerResultView.PathText");
}
void OnCombineOpen(object sender, SolutionEventArgs e)
{
listView.Items.Clear();
}
void OnCombineClosed(object sender, EventArgs e)
{
listView.Items.Clear();
}
void ListViewItemActivate(object sender, EventArgs e)
{
if (listView.FocusedItem != null) {
Task task = (Task)listView.FocusedItem.Tag;
System.Diagnostics.Debug.Assert(task != null);
task.JumpToPosition();
}
}
ListViewItem currentListViewItem = null;
void ListViewMouseMove(object sender, MouseEventArgs e)
{
ListViewItem item = listView.GetItemAt(e.X, e.Y);
if (item != currentListViewItem) {
if (item != null) {
Task task = (Task)item.Tag;
string description = task.Description;
if (description != null) {
description = description.Replace("\t", " ");
}
taskToolTip.SetToolTip(listView, description);
taskToolTip.Active = true;
} else {
taskToolTip.RemoveAll();
taskToolTip.Active = false;
}
currentListViewItem = item;
}
}
void ListViewResize(object sender, EventArgs e)
{
type.Width = 24;
line.Width = 50;
int w = listView.Width - type.Width - line.Width;
file.Width = w * 15 / 100;
path.Width = w * 15 / 100;
description.Width = w - file.Width - path.Width - 5;
}
public CompilerResults CompilerResults = null;
void AddTask(Task task)
{
int imageIndex = 3;
string tmpPath;
if (task.Project != null && task.FileName != null) {
tmpPath = FileUtility.GetRelativePath(task.Project.Directory, task.FileName);
} else {
tmpPath = task.FileName;
}
string fileName = tmpPath;
string path = tmpPath;
try {
fileName = Path.GetFileName(tmpPath);
} catch (Exception) {}
try {
path = Path.GetDirectoryName(tmpPath);
} catch (Exception) {}
ListViewItem item = new ListViewItem(new string[] {
String.Empty,
(task.Line + 1).ToString(),
FormatDescription(task.Description),
fileName,
path
});
item.ImageIndex = item.StateImageIndex = imageIndex;
item.Tag = task;
// insert new item into sorted list (binary search)
int left = 0;
int right = listView.Items.Count - 1;
while (left <= right) {
int m = left + (right - left) / 2;
if (CompareItems(item, listView.Items[m])) {
left = m + 1;
} else {
right = m - 1;
}
}
listView.Items.Insert(left, item);
}
/// <summary>Returns true when a &gt; b</summary>
bool CompareItems(ListViewItem a, ListViewItem b)
{
// insert sorted by: Directory, FileName, Line
int res = string.Compare(a.SubItems[4].Text, b.SubItems[4].Text, StringComparison.InvariantCultureIgnoreCase);
if (res > 0) return true;
if (res < 0) return false;
res = string.Compare(a.SubItems[3].Text, b.SubItems[3].Text, StringComparison.InvariantCultureIgnoreCase);
if (res > 0) return true;
if (res < 0) return false;
Task x = (Task)a.Tag;
Task y = (Task)b.Tag;
return x.Line > y.Line;
}
void TaskServiceCleared(object sender, EventArgs e)
{
listView.Items.Clear();
}
void TaskServiceAdded(object sender, TaskEventArgs e)
{
if (e.Task.TaskType == TaskType.Comment) {
AddTask(e.Task);
}
}
void TaskServiceRemoved(object sender, TaskEventArgs e)
{
Task task = e.Task;
if (task.TaskType == TaskType.Comment) {
for (int i = 0; i < listView.Items.Count; ++i) {
if ((Task)listView.Items[i].Tag == task) {
listView.Items.RemoveAt(i);
break;
}
}
}
}
/// <summary>
/// Removes new lines, carriage returns and tab characters from
/// the list view task description and replaces them with a space.
/// </summary>
/// <param name="description">The task list description.</param>
/// <returns>A formatted task list description.</returns>
string FormatDescription(string description)
{
string FormattedDescription = description.Replace("\r", " ");
FormattedDescription = FormattedDescription.Replace("\t", " ");
return FormattedDescription.Replace("\n", " ");
}
void ShowResults2(object sender, EventArgs e)
{
listView.BeginUpdate();
listView.Items.Clear();
foreach (Task task in TaskService.CommentTasks) {
AddTask(task);
}
listView.EndUpdate();
}
public void ShowResults(object sender, EventArgs e)
{
listView.Invoke(new EventHandler(ShowResults2));
// SelectTaskView(null, null);
}
private class OpenTaskViewSorter : IComparer
{
static int lastSortColumn = -1;
static SortOrder lastSortOrder = SortOrder.Ascending;
public OpenTaskViewSorter(int col)
{
if (col==lastSortColumn) {
if (lastSortOrder == SortOrder.Ascending) {
lastSortOrder = SortOrder.Descending;
} else {
lastSortOrder = SortOrder.Ascending;
}
} else {
lastSortColumn = col;
lastSortOrder = SortOrder.Ascending;
}
}
#region System.Collections.IComparer interface implementation
public int Compare(object x, object y) {
ListViewItem a = (ListViewItem)x;
ListViewItem b = (ListViewItem)y;
if (lastSortOrder == SortOrder.Ascending) {
return a.SubItems[lastSortColumn].Text.CompareTo(b.SubItems[lastSortColumn].Text);
} else {
return b.SubItems[lastSortColumn].Text.CompareTo(a.SubItems[lastSortColumn].Text);
}
}
#endregion
}
}
}

105
src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskList.cs

@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
// <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows.Forms;
using System.Drawing;
using System.CodeDom.Compiler;
using System.Collections;
using System.IO;
using System.Diagnostics;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Gui
{
public class OpenTaskView : AbstractPadContent
{
TaskView taskView = new TaskView();
public override Control Control {
get {
return taskView;
}
}
public OpenTaskView()
{
RedrawContent();
TaskService.Cleared += new EventHandler(TaskServiceCleared);
TaskService.Added += new TaskEventHandler(TaskServiceAdded);
TaskService.Removed += new TaskEventHandler(TaskServiceRemoved);
ProjectService.SolutionLoaded += OnCombineOpen;
ProjectService.SolutionClosed += OnCombineClosed;
ShowResults2(null, null);
}
public override void RedrawContent()
{
taskView.RefreshColumnNames();
}
void OnCombineOpen(object sender, SolutionEventArgs e)
{
taskView.Items.Clear();
}
void OnCombineClosed(object sender, EventArgs e)
{
taskView.Items.Clear();
}
public CompilerResults CompilerResults = null;
void TaskServiceCleared(object sender, EventArgs e)
{
taskView.Items.Clear();
}
void TaskServiceAdded(object sender, TaskEventArgs e)
{
if (e.Task.TaskType == TaskType.Comment) {
taskView.AddTask(e.Task);
}
}
void TaskServiceRemoved(object sender, TaskEventArgs e)
{
Task task = e.Task;
if (task.TaskType == TaskType.Comment) {
for (int i = 0; i < taskView.Items.Count; ++i) {
if ((Task)taskView.Items[i].Tag == task) {
taskView.Items.RemoveAt(i);
break;
}
}
}
}
void ShowResults2(object sender, EventArgs e)
{
taskView.BeginUpdate();
taskView.Items.Clear();
foreach (Task task in TaskService.CommentTasks) {
taskView.AddTask(task);
}
taskView.EndUpdate();
}
public void ShowResults(object sender, EventArgs e)
{
taskView.Invoke(new EventHandler(ShowResults2));
// SelectTaskView(null, null);
}
}
}

321
src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskView.cs

@ -0,0 +1,321 @@ @@ -0,0 +1,321 @@
// <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="David Alpert" email="david@spinthemoose.com"/>
// <version>$Revision$</version>
// </file>
// much of TaskView's code has been refactored from OpenTaskView.cs & ErrorList.cs
using System;
using System.Collections;
using System.IO;
using System.Windows.Forms;
namespace ICSharpCode.Core
{
public enum TaskViewCols : int {
Icon = 0,
Line = 1,
Description = 2,
File = 3,
Path = 4
}
/// <summary>
/// Description of TaskView.
/// </summary>
public class TaskView : ListView
{
public TaskView() : base()
{
RefreshColumnNames();
this.Columns.Add(type);
this.Columns.Add(line);
this.Columns.Add(description);
this.Columns.Add(file);
this.Columns.Add(path);
this.FullRowSelect = true;
this.AutoArrange = true;
this.Alignment = ListViewAlignment.Left;
this.View = View.Details;
this.Dock = DockStyle.Fill;
this.GridLines = true;
this.Activation = ItemActivation.OneClick;
OnResize(EventArgs.Empty);
// ...
ImageList imglist = new ImageList();
imglist.ColorDepth = ColorDepth.Depth32Bit;
imglist.Images.Add(ResourceService.GetBitmap("Icons.16x16.Error"));
imglist.Images.Add(ResourceService.GetBitmap("Icons.16x16.Warning"));
imglist.Images.Add(ResourceService.GetBitmap("Icons.16x16.Information"));
imglist.Images.Add(ResourceService.GetBitmap("Icons.16x16.Question"));
this.SmallImageList = this.LargeImageList = imglist;
// Set up the delays for the ToolTip.
taskToolTip.InitialDelay = 500;
taskToolTip.ReshowDelay = 100;
taskToolTip.AutoPopDelay = 5000;
//
// // Force the ToolTip text to be displayed whether or not the form is active.
// taskToolTip.ShowAlways = false;
}
ColumnHeader type = new ColumnHeader();
ColumnHeader line = new ColumnHeader();
ColumnHeader description = new ColumnHeader();
ColumnHeader file = new ColumnHeader();
ColumnHeader path = new ColumnHeader();
ToolTip taskToolTip = new ToolTip();
public void RefreshColumnNames()
{
type.Text = "!";
line.Text = ResourceService.GetString("CompilerResultView.LineText");
description.Text = ResourceService.GetString("CompilerResultView.DescriptionText");
file.Text = ResourceService.GetString("CompilerResultView.FileText");
path.Text = ResourceService.GetString("CompilerResultView.PathText");
}
protected override void OnResize(EventArgs e) {
base.OnResize(e);
// recalculate column widths
type.Width = 24;
line.Width = 50;
int w = this.Width - type.Width - line.Width;
file.Width = w * 15 / 100;
path.Width = w * 15 / 100;
description.Width = w - file.Width - path.Width - 5;
}
protected override void OnColumnClick(ColumnClickEventArgs e)
{
base.OnColumnClick(e);
this.ListViewItemSorter = new TaskViewSorter(e.Column);
}
protected override void OnItemActivate(EventArgs e) {
base.OnItemActivate(e);
if (this.FocusedItem != null) {
Task task = (Task)this.FocusedItem.Tag;
System.Diagnostics.Debug.Assert(task != null);
task.JumpToPosition();
}
}
ListViewItem currentListViewItem = null;
protected override void OnMouseMove(MouseEventArgs e) {
base.OnMouseMove(e);
ListViewItem item = GetItemAt(e.X, e.Y);
if (item != currentListViewItem) {
if (item != null) {
Task task = (Task)item.Tag;
string description = task.Description;
if (description != null) {
description = description.Replace("\t", " ");
}
taskToolTip.SetToolTip(this, description);
taskToolTip.Active = true;
} else {
taskToolTip.RemoveAll();
taskToolTip.Active = false;
}
currentListViewItem = item;
}
}
public void AddTask(Task task)
{
int imageIndex = 3;
string tmpPath;
if (task.Project != null && task.FileName != null) {
tmpPath = FileUtility.GetRelativePath(task.Project.Directory, task.FileName);
} else {
tmpPath = task.FileName;
}
string fileName = tmpPath;
string path = tmpPath;
try {
fileName = Path.GetFileName(tmpPath);
} catch (Exception) {}
try {
path = Path.GetDirectoryName(tmpPath);
} catch (Exception) {}
ListViewItem item = new ListViewItem(new string[] {
String.Empty,
(task.Line + 1).ToString(),
FormatDescription(task.Description),
fileName,
path
});
item.ImageIndex = item.StateImageIndex = imageIndex;
item.Tag = task;
// insert new item into sorted list (binary search)
int left = 0;
int right = this.Items.Count - 1;
while (left <= right) {
int m = left + (right - left) / 2;
if (CompareItems(item, this.Items[m])) {
left = m + 1;
} else {
right = m - 1;
}
}
this.Items.Insert(left, item);
}
// TODO: DavidAlpert - convert CompareItems into an IComparer implementation and
// install it as the default ListViewItemSorter; then modify
// AddTask to use the current ListViewItemSorter when adding
// new items.
/// <summary>Returns true when a &gt; b</summary>
bool CompareItems(ListViewItem a, ListViewItem b)
{
// TODO: DavidAlpert - convert ListViewItem.SubItem index references into TaskViewCol enum.
// insert sorted by: Directory, FileName, Line
int res = string.Compare(a.SubItems[3].Text, b.SubItems[4].Text, StringComparison.InvariantCultureIgnoreCase);
if (res > 0) return true;
if (res < 0) return false;
res = string.Compare(a.SubItems[3].Text, b.SubItems[3].Text, StringComparison.InvariantCultureIgnoreCase);
if (res > 0) return true;
if (res < 0) return false;
Task x = (Task)a.Tag;
Task y = (Task)b.Tag;
return x.Line > y.Line;
}
/// <summary>
/// Removes new lines, carriage returns and tab characters from
/// the list view task description and replaces them with a space.
/// </summary>
/// <param name="description">The task list description.</param>
/// <returns>A formatted task list description.</returns>
string FormatDescription(string description)
{
string FormattedDescription = description.Replace("\r", " ");
FormattedDescription = FormattedDescription.Replace("\t", " ");
return FormattedDescription.Replace("\n", " ");
}
#region Custom IComparer for sorting TaskView.
/// <summary>
/// Custom <see cref="IComparer"/> for TaskView.
/// </summary>
private class TaskViewSorter : IComparer
{
static int currentSortColumn = -1;
static SortOrder currentSortOrder = SortOrder.Ascending;
public TaskViewSorter(int col)
{
if (col==currentSortColumn) {
if (currentSortOrder == SortOrder.Ascending) {
currentSortOrder = SortOrder.Descending;
} else {
currentSortOrder = SortOrder.Ascending;
}
} else {
currentSortColumn = col;
currentSortOrder = SortOrder.Ascending;
}
}
/// <summary>
/// Compares 2 Int32 objects using <see cref="Int32.CompareTo"/>.
/// </summary>
/// <returns>
/// A signed number indicating the relative values of two Int32
/// objects; less than zero if b is less than a.
/// </returns>
protected int CompareAsInt32(object a, object b)
{
return Convert.ToInt32(a).CompareTo(Convert.ToInt32(b));
}
protected int CompareAsText(ListViewItem a, ListViewItem b, TaskViewCols c)
{
return CompareAsText(a, b, (int)c);
}
protected int CompareAsText(ListViewItem a, ListViewItem b, int c)
{
return a.SubItems[(int)c].Text.CompareTo(b.SubItems[(int)c].Text);;
}
#region System.Collections.IComparer interface implementation
/// <summary>
/// The meat of this IComparer class; intelligently compares
/// two FileReportResults items.
/// </summary>
/// <returns>
/// A signed integer indicating the relative sort ranking
/// of item <paramref name="x"/> relative to item
/// <paramref name="y"/>.
/// </returns>
public int Compare(object x, object y) {
ListViewItem a = (ListViewItem)x; // List item a
ListViewItem b = (ListViewItem)y; // List item b
int r = 0; // the result
if (currentSortColumn==(int)TaskViewCols.Line) {
r = CompareAsInt32(a.SubItems[currentSortColumn].Text,
b.SubItems[currentSortColumn].Text);
} else { // all others
r = CompareAsText(a, b, currentSortColumn);
// doing this test first is an optimization; we only
// need to check for secondary sort conditions if
// the primary test is a tie.
if (r == 0) {
if (currentSortColumn==(int)TaskViewCols.Path) {
// Sorts as Path -> File
r = CompareAsText(a, b, TaskViewCols.File);
if (r == 0) {
// Sorts as Path -> File -> Line
r = CompareAsText(a, b, TaskViewCols.Line);
}
} else if (currentSortColumn==(int)TaskViewCols.File) {
// Sorts as File -> Line
r = CompareAsInt32(a.SubItems[(int)TaskViewCols.Line].Text,
b.SubItems[(int)TaskViewCols.Line].Text);
}
}
}
if (currentSortOrder == SortOrder.Descending) {
// Return the opposite ranking
return -r;
}
return r;
}
#endregion
}
#endregion
}
}
Loading…
Cancel
Save