From b81e396846b395ac5bc889df380f8a56be1d8fbd Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Thu, 25 Jan 2007 17:39:02 +0000 Subject: [PATCH] Fixed SD2-1123. Code coverage vist count list view is now sortable by column. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.1@2324 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../CodeCoverage/Project/CodeCoverage.csproj | 1 + .../Project/Src/CodeCoverageControl.cs | 8 +- .../Src/SequencePointListViewSorter.cs | 140 +++++++++++++++ .../Test/CodeCoverage.Tests.csproj | 1 + .../Test/ListViewSortingTestFixture.cs | 165 ++++++++++++++++++ 5 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 src/AddIns/Misc/CodeCoverage/Project/Src/SequencePointListViewSorter.cs create mode 100644 src/AddIns/Misc/CodeCoverage/Test/ListViewSortingTestFixture.cs diff --git a/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.csproj b/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.csproj index b0d700f89d..197a22139b 100644 --- a/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.csproj +++ b/src/AddIns/Misc/CodeCoverage/Project/CodeCoverage.csproj @@ -52,6 +52,7 @@ + diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageControl.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageControl.cs index b2b1ce9b05..4bd28e2733 100644 --- a/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageControl.cs +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/CodeCoverageControl.cs @@ -31,6 +31,7 @@ namespace ICSharpCode.CodeCoverage ToolStrip toolStrip; bool showSourceCodePanel; bool showVisitCountPanel = true; + SequencePointListViewSorter sequencePointListViewSorter; public CodeCoverageControl() { @@ -338,7 +339,7 @@ namespace ICSharpCode.CodeCoverage listView.FullRowSelect = true; listView.HideSelection = false; listView.ItemActivate += ListViewItemActivate; - + visitCountColumnHeader = new ColumnHeader(); visitCountColumnHeader.Text = StringParser.Parse("${res:ICSharpCode.CodeCoverage.VisitCount}"); visitCountColumnHeader.Width = 80; @@ -364,6 +365,9 @@ namespace ICSharpCode.CodeCoverage startColumnColumnHeader, endLineColumnHeader, endColumnColumnHeader}); + + // Create custom list view sorter. + sequencePointListViewSorter = new SequencePointListViewSorter(listView); } void DisposeListView() @@ -383,6 +387,8 @@ namespace ICSharpCode.CodeCoverage listView.ItemActivate -= ListViewItemActivate; listView.Dispose(); listView = null; + + sequencePointListViewSorter.Dispose(); } void CreateVerticalSplitContainer() diff --git a/src/AddIns/Misc/CodeCoverage/Project/Src/SequencePointListViewSorter.cs b/src/AddIns/Misc/CodeCoverage/Project/Src/SequencePointListViewSorter.cs new file mode 100644 index 0000000000..3ac82d3051 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Project/Src/SequencePointListViewSorter.cs @@ -0,0 +1,140 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections; +using System.Windows.Forms; + +namespace ICSharpCode.CodeCoverage +{ + /// + /// Sorts the list view that contains code coverage sequence + /// points. + /// + public class SequencePointListViewSorter : IComparer, IDisposable + { + ListView listView; + int column = -1; + SortOrder sortOrder = SortOrder.None; + + const int VisitCountColumn = 0; + const int SequencePointLineColumn = 1; + const int SequencePointStartColumnColumn = 2; + const int SequencePointEndLineColumn = 3; + const int SequencePointEndColumnColumn = 4; + + public SequencePointListViewSorter(ListView listView) + { + this.listView = listView; + listView.ListViewItemSorter = this; + listView.ColumnClick += ListViewColumnClick; + } + + public void Dispose() + { + if (listView != null) { + listView.ColumnClick -= ListViewColumnClick; + } + } + + /// + /// Compares two list view items and sorts them according + /// to the currently sorted column. + /// + public int Compare(object x, object y) + { + CodeCoverageSequencePoint lhs = null; + CodeCoverageSequencePoint rhs = null; + + ListViewItem item = x as ListViewItem; + if (item != null) { + lhs = item.Tag as CodeCoverageSequencePoint; + } + + item = y as ListViewItem; + if (item != null) { + rhs = item.Tag as CodeCoverageSequencePoint; + } + + if (lhs != null && rhs != null) { + return Compare(lhs, rhs); + } + return 0; + } + + /// + /// Sorts the list view by the specified column. + /// + public void Sort(int column) + { + if (this.column == column) { + ToggleSortOrder(); + } else { + sortOrder = SortOrder.Ascending; + } + this.column = column; + listView.Sort(); + } + + /// + /// Compares two code coverage sequence points based on the + /// currently sorted column and sort order. + /// + int Compare(CodeCoverageSequencePoint x, CodeCoverageSequencePoint y) + { + int result = 0; + switch (column) { + case VisitCountColumn: + result = x.VisitCount - y.VisitCount; + break; + case SequencePointLineColumn: + result = x.Line - y.Line; + break; + case SequencePointStartColumnColumn: + result = x.Column - y.Column; + break; + case SequencePointEndLineColumn: + result = x.EndLine - y.EndLine; + break; + case SequencePointEndColumnColumn: + result = x.EndColumn - y.EndColumn; + break; + } + + // Sort by secondary sort column? + if (result == 0 && column != SequencePointLineColumn) { + result = x.Line - y.Line; + } + + if (sortOrder == SortOrder.Descending) { + return -result; + } + return result; + } + + /// + /// Switches the sort order from ascending to descending + /// and vice versa. + /// + void ToggleSortOrder() + { + if (sortOrder == SortOrder.Ascending) { + sortOrder = SortOrder.Descending; + } else { + sortOrder = SortOrder.Ascending; + } + } + + /// + /// User clicked a column header so sort that column. + /// + void ListViewColumnClick(object source, ColumnClickEventArgs e) + { + Sort(e.Column); + } + } +} diff --git a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverage.Tests.csproj b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverage.Tests.csproj index ed5cabe9c5..c245627f4d 100644 --- a/src/AddIns/Misc/CodeCoverage/Test/CodeCoverage.Tests.csproj +++ b/src/AddIns/Misc/CodeCoverage/Test/CodeCoverage.Tests.csproj @@ -52,6 +52,7 @@ + diff --git a/src/AddIns/Misc/CodeCoverage/Test/ListViewSortingTestFixture.cs b/src/AddIns/Misc/CodeCoverage/Test/ListViewSortingTestFixture.cs new file mode 100644 index 0000000000..dda4e70eb8 --- /dev/null +++ b/src/AddIns/Misc/CodeCoverage/Test/ListViewSortingTestFixture.cs @@ -0,0 +1,165 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Windows.Forms; +using ICSharpCode.CodeCoverage; +using NUnit.Framework; + +namespace ICSharpCode.CodeCoverage.Tests +{ + /// + /// Tests the sorting of the list view that shows + /// the code coverage sequence points (visit counts, etc). + /// Here we are not actually using the real list view, but + /// just a list view which has the same number of columns. + /// Eventually the sorter class will be replaced in + /// SharpDevelop 3.0 with the generic sorting classes. + /// + [TestFixture] + public class ListViewSortingTestFixture + { + ListView listView; + CodeCoverageSequencePoint firstSequencePoint; + CodeCoverageSequencePoint secondSequencePoint; + SequencePointListViewSorter sorter; + const int VisitCountColumn = 0; + const int SequencePointLineColumn = 1; + const int SequencePointStartColumnColumn = 2; + const int SequencePointEndLineColumn = 3; + const int SequencePointEndColumnColumn = 4; + + [SetUp] + public void SetUp() + { + listView = new ListView(); + sorter = new SequencePointListViewSorter(listView); + + listView.Columns.Add("Visit Count"); + listView.Columns.Add("Line"); + listView.Columns.Add("Column"); + listView.Columns.Add("End Line"); + listView.Columns.Add("End Column"); + + // Add first sequence point. + firstSequencePoint = new CodeCoverageSequencePoint(String.Empty, 1, 5, 1, 5, 10); + ListViewItem item = new ListViewItem("First"); + item.Tag = firstSequencePoint; + listView.Items.Add(item); + + // Add second sequence point. + secondSequencePoint = new CodeCoverageSequencePoint(String.Empty, 0, 10, 2, 10, 8); + item = new ListViewItem("Second"); + item.Tag = secondSequencePoint; + listView.Items.Add(item); + + // Need to create the control's handle otherwise + // the list view will not sort. + listView.CreateControl(); + } + + [TearDown] + public void TearDown() + { + listView.Dispose(); + } + + [Test] + public void InitialOrderSameAsOrderAdded() + { + Assert.AreSame(firstSequencePoint, listView.Items[0].Tag); + Assert.AreSame(secondSequencePoint, listView.Items[1].Tag); + } + + [Test] + public void SortVisitCountColumn() + { + sorter.Sort(VisitCountColumn); + Assert.AreSame(secondSequencePoint, listView.Items[0].Tag); + } + + [Test] + public void SortVisitCountColumnTwice() + { + sorter.Sort(VisitCountColumn); + sorter.Sort(VisitCountColumn); + Assert.AreSame(firstSequencePoint, listView.Items[0].Tag); + } + + [Test] + public void SortLineColumnTwice() + { + sorter.Sort(SequencePointLineColumn); + sorter.Sort(SequencePointLineColumn); + Assert.AreSame(secondSequencePoint, listView.Items[0].Tag); + } + + [Test] + public void SortStartColumnTwice() + { + sorter.Sort(SequencePointStartColumnColumn); + sorter.Sort(SequencePointStartColumnColumn); + Assert.AreSame(secondSequencePoint, listView.Items[0].Tag); + } + + [Test] + public void SortEndLineTwice() + { + sorter.Sort(SequencePointEndLineColumn); + sorter.Sort(SequencePointEndLineColumn); + Assert.AreSame(secondSequencePoint, listView.Items[0].Tag); + } + + [Test] + public void SortEndColumn() + { + sorter.Sort(SequencePointEndColumnColumn); + Assert.AreSame(secondSequencePoint, listView.Items[0].Tag); + } + + [Test] + public void CompareNulls() + { + Assert.AreEqual(0, sorter.Compare(null, null)); + } + + [Test] + public void CompareNullRhs() + { + Assert.AreEqual(0, sorter.Compare(null, new ListViewItem())); + } + + [Test] + public void CompareTwoListViewItemsWithNoTags() + { + sorter.Sort(VisitCountColumn); + Assert.AreEqual(0, sorter.Compare(new ListViewItem(), new ListViewItem())); + } + + [Test] + public void CompareRhsListViewItemWithNoTag() + { + sorter.Sort(VisitCountColumn); + Assert.AreEqual(0, sorter.Compare(listView.Items[0], new ListViewItem())); + } + + [Test] + public void SecondarySortByLineWhenVisitCountSame() + { + sorter.Sort(VisitCountColumn); + CodeCoverageSequencePoint pt1 = new CodeCoverageSequencePoint(String.Empty, 0, 1, 0, 0, 0); + CodeCoverageSequencePoint pt2 = new CodeCoverageSequencePoint(String.Empty, 0, 2, 0, 0, 0); + + ListViewItem item1 = new ListViewItem(); + item1.Tag = pt1; + ListViewItem item2 = new ListViewItem(); + item2.Tag = pt2; + + Assert.AreEqual(-1, sorter.Compare(item1, item2)); + } + } +}