diff --git a/v2rayN/v2rayN/Base/ListViewSort.cs b/v2rayN/v2rayN/Base/ListViewSort.cs index fded9bed..004985f5 100644 --- a/v2rayN/v2rayN/Base/ListViewSort.cs +++ b/v2rayN/v2rayN/Base/ListViewSort.cs @@ -1,31 +1,50 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Forms; +using System.Windows.Forms; namespace v2rayN.Base { - public class ListViewSort : IComparer + + // ref: https://stackoverflow.com/questions/1214289/how-do-i-sort-integers-in-a-listview + class Sorter : System.Collections.IComparer { - private int col; - private bool descK; - public ListViewSort() + public int Column = 0; + public int Sorting = 0; + public int Compare(object x, object y) // IComparer Member { - col = 0; - } - public ListViewSort(int column, object Desc) - { - descK = (bool)Desc; - col = column; //当前列,0,1,2...,参数由ListView控件的ColumnClick事件传递 - } - public int Compare(object x, object y) - { - int tempInt = String.Compare(((ListViewItem)x).SubItems[col].Text, ((ListViewItem)y).SubItems[col].Text); - if (descK) return -tempInt; - else return tempInt; + if (!(x is ListViewItem) || !(y is ListViewItem)) + return (0); + + ListViewItem l1 = (ListViewItem)x; + ListViewItem l2 = (ListViewItem)y; + + int doIntSort = Sorting; + if (doIntSort > 0) // Tag will be number + { + ulong.TryParse(l1.SubItems[Column].Tag?.ToString(), out ulong fl1); + ulong.TryParse(l2.SubItems[Column].Tag?.ToString(), out ulong fl2); + + if (doIntSort == 1) + { + return fl1.CompareTo(fl2); + } + else + { + return fl2.CompareTo(fl1); + } + } + else + { + string str1 = l1.SubItems[Column].Text; + string str2 = l2.SubItems[Column].Text; + + if (doIntSort == -1) + { + return str1.CompareTo(str2); + } + else + { + return str2.CompareTo(str1); + } + } } } } diff --git a/v2rayN/v2rayN/Forms/MainForm.Designer.cs b/v2rayN/v2rayN/Forms/MainForm.Designer.cs index 86899312..0fae5057 100644 --- a/v2rayN/v2rayN/Forms/MainForm.Designer.cs +++ b/v2rayN/v2rayN/Forms/MainForm.Designer.cs @@ -155,17 +155,18 @@ // // lvServers // + this.lvServers.AllowColumnReorder = true; this.lvServers.ContextMenuStrip = this.cmsLv; resources.ApplyResources(this.lvServers, "lvServers"); this.lvServers.FullRowSelect = true; this.lvServers.GridLines = true; - this.lvServers.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; this.lvServers.HideSelection = false; this.lvServers.Items.AddRange(new System.Windows.Forms.ListViewItem[] { ((System.Windows.Forms.ListViewItem)(resources.GetObject("lvServers.Items")))}); this.lvServers.Name = "lvServers"; this.lvServers.UseCompatibleStateImageBehavior = false; this.lvServers.View = System.Windows.Forms.View.Details; + this.lvServers.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.lvServers_ColumnClick); this.lvServers.SelectedIndexChanged += new System.EventHandler(this.lvServers_SelectedIndexChanged); this.lvServers.DoubleClick += new System.EventHandler(this.lvServers_DoubleClick); this.lvServers.KeyDown += new System.Windows.Forms.KeyEventHandler(this.lvServers_KeyDown); diff --git a/v2rayN/v2rayN/Forms/MainForm.cs b/v2rayN/v2rayN/Forms/MainForm.cs index ef48980e..9980d6b6 100644 --- a/v2rayN/v2rayN/Forms/MainForm.cs +++ b/v2rayN/v2rayN/Forms/MainForm.cs @@ -168,6 +168,8 @@ namespace v2rayN.Forms /// private void InitServersView() { + lvServers.ListViewItemSorter = new Sorter(); + lvServers.BeginUpdate(); lvServers.Items.Clear(); @@ -181,15 +183,18 @@ namespace v2rayN.Forms lvServers.Columns.Add(EServerColName.subRemarks.ToString(), UIRes.I18N("LvSubscription"), 50); lvServers.Columns.Add(EServerColName.testResult.ToString(), UIRes.I18N("LvTestResults"), 70); + lvServers.Columns[EServerColName.port.ToString()].Tag = Global.sortMode.Numeric.ToString(); if (statistics != null && statistics.Enable) - lvServers.HeaderStyle = ColumnHeaderStyle.Clickable; - this.lvServers.AllowColumnReorder = true; - { lvServers.Columns.Add(EServerColName.todayDown.ToString(), UIRes.I18N("LvTodayDownloadDataAmount"), 70); lvServers.Columns.Add(EServerColName.todayUp.ToString(), UIRes.I18N("LvTodayUploadDataAmount"), 70); lvServers.Columns.Add(EServerColName.totalDown.ToString(), UIRes.I18N("LvTotalDownloadDataAmount"), 70); lvServers.Columns.Add(EServerColName.totalUp.ToString(), UIRes.I18N("LvTotalUploadDataAmount"), 70); + + lvServers.Columns[EServerColName.todayDown.ToString()].Tag = Global.sortMode.Numeric.ToString(); + lvServers.Columns[EServerColName.todayUp.ToString()].Tag = Global.sortMode.Numeric.ToString(); + lvServers.Columns[EServerColName.totalDown.ToString()].Tag = Global.sortMode.Numeric.ToString(); + lvServers.Columns[EServerColName.totalUp.ToString()].Tag = Global.sortMode.Numeric.ToString(); } lvServers.EndUpdate(); } @@ -220,11 +225,11 @@ namespace v2rayN.Forms { var n = new ListViewItem.ListViewSubItem() { Text = text }; n.Name = name; // new don't accept it. - n.Tag = tag; + n.Tag = tag; // cell's data store. i.SubItems.Add(n); } ListViewItem lvItem = new ListViewItem(def); - lvItem.Tag = k; // the Tag of items is config's index. + lvItem.Tag = k; // the Tag of line is config's index. _addSubItem(lvItem, EServerColName.type.ToString(), ((EConfigType)item.configType).ToString()); _addSubItem(lvItem, EServerColName.remarks.ToString(), item.remarks); _addSubItem(lvItem, EServerColName.address.ToString(), item.address); @@ -244,10 +249,10 @@ namespace v2rayN.Forms todayUp = Utils.HumanFy(sItem.todayUp); todayDown = Utils.HumanFy(sItem.todayDown); } - _addSubItem(lvItem, EServerColName.todayDown.ToString(), todayDown, sItem.todayDown); - _addSubItem(lvItem, EServerColName.todayUp.ToString(), todayUp, sItem.todayUp); - _addSubItem(lvItem, EServerColName.totalDown.ToString(), totalDown, sItem.totalDown); - _addSubItem(lvItem, EServerColName.totalUp.ToString(), totalUp, sItem.totalUp); + _addSubItem(lvItem, EServerColName.todayDown.ToString(), todayDown, sItem?.todayDown); + _addSubItem(lvItem, EServerColName.todayUp.ToString(), todayUp, sItem?.todayUp); + _addSubItem(lvItem, EServerColName.totalDown.ToString(), totalDown, sItem?.totalDown); + _addSubItem(lvItem, EServerColName.totalUp.ToString(), totalUp, sItem?.totalUp); } if (config.interlaceColoring && k % 2 == 1) // 隔行着色 @@ -1633,15 +1638,31 @@ namespace v2rayN.Forms private void lvServers_ColumnClick(object sender, ColumnClickEventArgs e) { - if (lvServers.Columns[e.Column].Tag == null) - lvServers.Columns[e.Column].Tag = true; - bool flag = (bool)lvServers.Columns[e.Column].Tag; - if (flag) - lvServers.Columns[e.Column].Tag = false; - else - lvServers.Columns[e.Column].Tag = true; - lvServers.ListViewItemSorter = new ListViewSort(e.Column, lvServers.Columns[e.Column].Tag); - lvServers.Sort();//对列表进行自定义排序 + Sorter s = (Sorter)lvServers.ListViewItemSorter; + s.Column = e.Column; + + int doIntSort; + if (lvServers.Columns[e.Column].Tag?.ToString() == Global.sortMode.Numeric.ToString()) // 数字正序 + { + lvServers.Columns[e.Column].Tag = Global.sortMode.NumericB.ToString(); + doIntSort = 1; + } + else if (lvServers.Columns[e.Column].Tag?.ToString() == Global.sortMode.NumericB.ToString()) // 数字倒序 + { + lvServers.Columns[e.Column].Tag = Global.sortMode.Numeric.ToString(); + doIntSort = 2; + } + else // 非数字 + { + bool bGo = bool.TryParse(lvServers.Columns[e.Column].Tag?.ToString(), out bool bOk); + // 首个转换将失败,如果Tag是null或其他。 + bool flag = bOk ? bGo : false; + lvServers.Columns[e.Column].Tag = !flag; // 首次则赋值true。 + doIntSort = flag ? -1 : -2; // -1正序 -2倒序 + } + s.Sorting = doIntSort; + + lvServers.Sort(); } } } diff --git a/v2rayN/v2rayN/Global.cs b/v2rayN/v2rayN/Global.cs index 3d1e6137..5fc9a175 100644 --- a/v2rayN/v2rayN/Global.cs +++ b/v2rayN/v2rayN/Global.cs @@ -156,6 +156,16 @@ namespace v2rayN /// public const string CustomIconName = "v2rayN.ico"; + /// + /// 表格列的排序方式 + /// + public enum sortMode + { + Numeric, + NumericB, + // More, like natural numbers, string length, visual length, etc. + } + public enum StatisticsFreshRate { quick = 1000,