From 072de642e131b6f31fa8ae8ebfaeecca37353f12 Mon Sep 17 00:00:00 2001 From: Milan Hanajik Date: Mon, 10 Sep 2018 11:19:37 +0200 Subject: [PATCH] ComponentsManagerDlg : Components sorting controlled by click-able column headers. --- Results/Forms/ListViewExtensions.cs | 104 ++++++++++++++++++++++ Results/Forms/LviIntColumnComparer.cs | 31 +++++++ Results/Forms/LviTextColumnComparer.cs | 31 +++++++ Results/Results.csproj | 3 + TBF/ComponentsManagerDlg.Designer.cs | 117 +++++++++++++------------ TBF/ComponentsManagerDlg.cs | 48 ++++++++-- TBF/ComponentsManagerDlg.resx | 4 +- 7 files changed, 271 insertions(+), 67 deletions(-) create mode 100644 Results/Forms/ListViewExtensions.cs create mode 100644 Results/Forms/LviIntColumnComparer.cs create mode 100644 Results/Forms/LviTextColumnComparer.cs diff --git a/Results/Forms/ListViewExtensions.cs b/Results/Forms/ListViewExtensions.cs new file mode 100644 index 000000000..426d3f07f --- /dev/null +++ b/Results/Forms/ListViewExtensions.cs @@ -0,0 +1,104 @@ +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace Results.Forms +{ + [EditorBrowsable(EditorBrowsableState.Never)] + public static class ListViewExtensions + { + [StructLayout(LayoutKind.Sequential)] + public struct HDITEM + { + public Mask mask; + public int cxy; + [MarshalAs(UnmanagedType.LPTStr)] + public string pszText; + public IntPtr hbm; + public int cchTextMax; + public Format fmt; + public IntPtr lParam; + // _WIN32_IE >= 0x0300 + public int iImage; + public int iOrder; + // _WIN32_IE >= 0x0500 + public uint type; + public IntPtr pvFilter; + // _WIN32_WINNT >= 0x0600 + public uint state; + + [Flags] + public enum Mask + { + Format = 0x4, // HDI_FORMAT + }; + + [Flags] + public enum Format + { + SortDown = 0x200, // HDF_SORTDOWN + SortUp = 0x400, // HDF_SORTUP + }; + }; + + public const int LVM_FIRST = 0x1000; + public const int LVM_GETHEADER = LVM_FIRST + 31; + + public const int HDM_FIRST = 0x1200; + public const int HDM_GETITEM = HDM_FIRST + 11; + public const int HDM_SETITEM = HDM_FIRST + 12; + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref HDITEM lParam); + + public static void SetSortIcon(this ListViewEx listViewControl, int columnIndex, SortOrder order) + { + IntPtr columnHeader = SendMessage(listViewControl.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero); + for (int columnNumber = 0; columnNumber <= listViewControl.Columns.Count - 1; columnNumber++) + { + var columnPtr = new IntPtr(columnNumber); + var item = new HDITEM + { + mask = HDITEM.Mask.Format + }; + + if (SendMessage(columnHeader, HDM_GETITEM, columnPtr, ref item) == IntPtr.Zero) + { + throw new Win32Exception(); + } + + if (order != SortOrder.None && columnNumber == columnIndex) + { + switch (order) + { + case SortOrder.Ascending: + item.fmt &= ~HDITEM.Format.SortDown; + item.fmt |= HDITEM.Format.SortUp; + break; + + case SortOrder.Descending: + item.fmt &= ~HDITEM.Format.SortUp; + item.fmt |= HDITEM.Format.SortDown; + break; + + default: + break; + } + } + else + { + item.fmt &= ~HDITEM.Format.SortDown & ~HDITEM.Format.SortUp; + } + + if (SendMessage(columnHeader, HDM_SETITEM, columnPtr, ref item) == IntPtr.Zero) + { + throw new Win32Exception(); + } + } + } + } +} diff --git a/Results/Forms/LviIntColumnComparer.cs b/Results/Forms/LviIntColumnComparer.cs new file mode 100644 index 000000000..d9343e87d --- /dev/null +++ b/Results/Forms/LviIntColumnComparer.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections; +using System.Windows.Forms; + +namespace Results.Forms +{ + public class LviIntColumnComparer : IComparer + { + int column; + SortOrder order; + + public LviIntColumnComparer() + { + column = 0; + order = SortOrder.Ascending; + } + + public LviIntColumnComparer(int column, SortOrder order) + { + this.column = column; + this.order = order; + } + + public int Compare(object x, object y) + { + int valX = int.Parse(((ListViewItem)x).SubItems[column].Text); + int valY = int.Parse(((ListViewItem)y).SubItems[column].Text); + return (order == SortOrder.Descending) ? (valY - valX) : (valX - valY); + } + } +} diff --git a/Results/Forms/LviTextColumnComparer.cs b/Results/Forms/LviTextColumnComparer.cs new file mode 100644 index 000000000..884c0d1b3 --- /dev/null +++ b/Results/Forms/LviTextColumnComparer.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections; +using System.Windows.Forms; + +namespace Results.Forms +{ + public class LviTextColumnComparer : IComparer + { + private int column; + SortOrder order; + + public LviTextColumnComparer() + { + column = 0; + order = SortOrder.Ascending; + } + + public LviTextColumnComparer(int column, SortOrder order) + { + this.column = column; + this.order = order; + } + + public int Compare(object x, object y) + { + string txtX = ((ListViewItem)x).SubItems[column].Text; + string txtY = ((ListViewItem)y).SubItems[column].Text; + return (order == SortOrder.Descending) ? String.Compare(txtY, txtX) : String.Compare(txtX, txtY); + } + } +} diff --git a/Results/Results.csproj b/Results/Results.csproj index eebf00c5a..3d41cba26 100644 --- a/Results/Results.csproj +++ b/Results/Results.csproj @@ -77,6 +77,9 @@ Component + + + UserControl diff --git a/TBF/ComponentsManagerDlg.Designer.cs b/TBF/ComponentsManagerDlg.Designer.cs index 5fa4e9240..c801234f4 100644 --- a/TBF/ComponentsManagerDlg.Designer.cs +++ b/TBF/ComponentsManagerDlg.Designer.cs @@ -31,64 +31,65 @@ namespace TBF /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ComponentsManagerDlg)); - this.splitContainer = new System.Windows.Forms.SplitContainer(); - this.listViewEx = new Results.Forms.ListViewEx(); - this.sharedButtons = new TBF.UiControls.SharedButtons(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); - this.splitContainer.Panel1.SuspendLayout(); - this.splitContainer.Panel2.SuspendLayout(); - this.splitContainer.SuspendLayout(); - this.SuspendLayout(); - // - // splitContainer - // - resources.ApplyResources(this.splitContainer, "splitContainer"); - this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; - this.splitContainer.Name = "splitContainer"; - // - // splitContainer.Panel1 - // - this.splitContainer.Panel1.Controls.Add(this.listViewEx); - // - // splitContainer.Panel2 - // - this.splitContainer.Panel2.Controls.Add(this.sharedButtons); - // - // listViewEx - // - this.listViewEx.AllowColumnReorder = true; - resources.ApplyResources(this.listViewEx, "listViewEx"); - this.listViewEx.DoubleClickActivation = false; - this.listViewEx.FullRowSelect = true; - this.listViewEx.GridLines = true; - this.listViewEx.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; - this.listViewEx.HideSelection = false; - this.listViewEx.MultiSelect = false; - this.listViewEx.Name = "listViewEx"; - this.listViewEx.UseCompatibleStateImageBehavior = false; - this.listViewEx.View = System.Windows.Forms.View.Details; - this.listViewEx.SelectedIndexChanged += new System.EventHandler(this.componentsListView_SelectedIndexChanged); - this.listViewEx.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.listViewEx_MouseDoubleClick); - // - // sharedButtons - // - resources.ApplyResources(this.sharedButtons, "sharedButtons"); - this.sharedButtons.Name = "sharedButtons"; - // - // ComponentsManagerDlg - // - resources.ApplyResources(this, "$this"); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.splitContainer); - this.Name = "ComponentsManagerDlg"; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ComponentsManagerDlg_FormClosing); - this.Load += new System.EventHandler(this.ComponentsManagerDlg_Load); - this.splitContainer.Panel1.ResumeLayout(false); - this.splitContainer.Panel2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); - this.splitContainer.ResumeLayout(false); - this.ResumeLayout(false); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ComponentsManagerDlg)); + this.splitContainer = new System.Windows.Forms.SplitContainer(); + this.listViewEx = new Results.Forms.ListViewEx(); + this.sharedButtons = new TBF.UiControls.SharedButtons(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).BeginInit(); + this.splitContainer.Panel1.SuspendLayout(); + this.splitContainer.Panel2.SuspendLayout(); + this.splitContainer.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer + // + resources.ApplyResources(this.splitContainer, "splitContainer"); + this.splitContainer.FixedPanel = System.Windows.Forms.FixedPanel.Panel2; + this.splitContainer.Name = "splitContainer"; + // + // splitContainer.Panel1 + // + this.splitContainer.Panel1.Controls.Add(this.listViewEx); + // + // splitContainer.Panel2 + // + this.splitContainer.Panel2.Controls.Add(this.sharedButtons); + // + // listViewEx + // + this.listViewEx.AllowColumnReorder = true; + resources.ApplyResources(this.listViewEx, "listViewEx"); + this.listViewEx.DoubleClickActivation = false; + this.listViewEx.FullRowSelect = true; + this.listViewEx.GridLines = true; + this.listViewEx.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listViewEx.HideSelection = false; + this.listViewEx.MultiSelect = false; + this.listViewEx.Name = "listViewEx"; + this.listViewEx.UseCompatibleStateImageBehavior = false; + this.listViewEx.View = System.Windows.Forms.View.Details; + this.listViewEx.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.listViewEx_ColumnClick); + this.listViewEx.SelectedIndexChanged += new System.EventHandler(this.componentsListView_SelectedIndexChanged); + this.listViewEx.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.listViewEx_MouseDoubleClick); + // + // sharedButtons + // + resources.ApplyResources(this.sharedButtons, "sharedButtons"); + this.sharedButtons.Name = "sharedButtons"; + // + // ComponentsManagerDlg + // + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.splitContainer); + this.Name = "ComponentsManagerDlg"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ComponentsManagerDlg_FormClosing); + this.Load += new System.EventHandler(this.ComponentsManagerDlg_Load); + this.splitContainer.Panel1.ResumeLayout(false); + this.splitContainer.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer)).EndInit(); + this.splitContainer.ResumeLayout(false); + this.ResumeLayout(false); } diff --git a/TBF/ComponentsManagerDlg.cs b/TBF/ComponentsManagerDlg.cs index c8aaf68a5..a5ca9bb86 100644 --- a/TBF/ComponentsManagerDlg.cs +++ b/TBF/ComponentsManagerDlg.cs @@ -9,6 +9,7 @@ using System.Windows.Forms; using log4net; using NHibernate; using Config.Entities; +using Results.Forms; using TBF.BenchControl; using TBF.BenchControl.Generic; using TBF.Resources; @@ -38,6 +39,7 @@ namespace TBF /// enum Column { + Number, Name, ClassName, ParentName, @@ -47,6 +49,9 @@ namespace TBF ColumnsCount, } + SortOrder sortOrder = SortOrder.Ascending; + int sortColumn = -1; /// 0-based index of column to be used for sorting + /// Editors used by listViewEx ComboBox debugCB; ComboBox logCB; @@ -96,12 +101,14 @@ namespace TBF Top = (ls.ComponentsDlgTop != 0) ? ls.ComponentsDlgTop : 100; Text = Strings.Test_Bench_Components_Configuration; - listViewEx.Columns.Add(Strings.Name, (ls.ComponentsColumnCount > 0) ? ls.ComponentsColumnWidths[0] : 80); - listViewEx.Columns.Add(Strings.Type, (ls.ComponentsColumnCount > 1) ? ls.ComponentsColumnWidths[1] : 120); - listViewEx.Columns.Add(Strings.Parent, (ls.ComponentsColumnCount > 2) ? ls.ComponentsColumnWidths[2] : 55); - listViewEx.Columns.Add(Strings.Mode, (ls.ComponentsColumnCount > 3) ? ls.ComponentsColumnWidths[3] : 55); - listViewEx.Columns.Add(Strings.Logging, (ls.ComponentsColumnCount > 4) ? ls.ComponentsColumnWidths[4] : 55); - listViewEx.Columns.Add(Strings.Parameters, (ls.ComponentsColumnCount > 5) ? ls.ComponentsColumnWidths[5] : 600); + listViewEx.Columns.Add(Strings.Nr, (ls.ComponentsColumnCount > 0) ? ls.ComponentsColumnWidths[0] : 40); + listViewEx.Columns.Add(Strings.Name, (ls.ComponentsColumnCount > 0) ? ls.ComponentsColumnWidths[1] : 80); + listViewEx.Columns.Add(Strings.Type, (ls.ComponentsColumnCount > 1) ? ls.ComponentsColumnWidths[2] : 120); + listViewEx.Columns.Add(Strings.Parent, (ls.ComponentsColumnCount > 2) ? ls.ComponentsColumnWidths[3] : 55); + listViewEx.Columns.Add(Strings.Mode, (ls.ComponentsColumnCount > 3) ? ls.ComponentsColumnWidths[4] : 55); + listViewEx.Columns.Add(Strings.Logging, (ls.ComponentsColumnCount > 4) ? ls.ComponentsColumnWidths[5] : 55); + listViewEx.Columns.Add(Strings.Parameters, (ls.ComponentsColumnCount > 5) ? ls.ComponentsColumnWidths[6] : 600); + listViewEx.HeaderStyle = ColumnHeaderStyle.Clickable; debugCB = new ComboBox(); for (DebugMode level = 0; level < DebugMode.Count; level++) debugCB.Items.Add(level.ToDescription()); @@ -189,8 +196,9 @@ namespace TBF void DrawOne(Component cmpnt) { - ListViewItem lvi = new ListViewItem(cmpnt.Name); + ListViewItem lvi = new ListViewItem(cmpnt.ItemNr.ToString()); lvi.Tag = cmpnt; + lvi.SubItems.Add(cmpnt.Name); lvi.SubItems.Add(string.IsNullOrEmpty(cmpnt.ClassName) ? string.Empty : cmpnt.ClassName); lvi.SubItems.Add(string.IsNullOrEmpty(cmpnt.ParentName) ? string.Empty : cmpnt.ParentName); @@ -666,5 +674,31 @@ namespace TBF return false; } + + private void listViewEx_ColumnClick(object sender, ColumnClickEventArgs e) + { + if (e.Column == sortColumn) + { + sortOrder = (sortOrder == SortOrder.Ascending) ? SortOrder.Descending : SortOrder.Ascending; + } + else + { + /// Clicked on another column header => set sortOrder to SortOrder.Ascending + sortColumn = e.Column; + sortOrder = SortOrder.Ascending; + } + + if (sortColumn == (int)Column.Number) + { + listViewEx.ListViewItemSorter = new LviIntColumnComparer(sortColumn, sortOrder); + } + else + { + listViewEx.ListViewItemSorter = new LviTextColumnComparer(sortColumn, sortOrder); + } + + listViewEx.SetSortIcon(sortColumn, sortOrder); + listViewEx.Sort(); + } } } diff --git a/TBF/ComponentsManagerDlg.resx b/TBF/ComponentsManagerDlg.resx index 7aeeb31c6..0e4509358 100644 --- a/TBF/ComponentsManagerDlg.resx +++ b/TBF/ComponentsManagerDlg.resx @@ -145,7 +145,7 @@ listViewEx - Results.Forms.ListViewEx, Results, Version=2.12.475.0, Culture=neutral, PublicKeyToken=null + Results.Forms.ListViewEx, Results, Version=2.18.990.0, Culture=neutral, PublicKeyToken=null splitContainer.Panel1 @@ -178,7 +178,7 @@ sharedButtons - TBF.UiControls.SharedButtons, TBF, Version=2.12.481.1, Culture=neutral, PublicKeyToken=null + TBF.UiControls.SharedButtons, TBF, Version=2.18.992.0, Culture=neutral, PublicKeyToken=null splitContainer.Panel2