add drag to sort

pull/2148/head
2dust 2022-03-24 19:07:45 +08:00
parent d20791bf73
commit 1493a8b03f
5 changed files with 124 additions and 38 deletions

View File

@ -1,10 +1,13 @@
using System.Drawing;
using System;
using System.Drawing;
using System.Windows.Forms;
namespace v2rayN.Base
{
class ListViewFlickerFree : ListView
{
Action<int, int> _updateFunc;
public ListViewFlickerFree()
{
SetStyle(ControlStyles.OptimizedDoubleBuffer
@ -13,40 +16,82 @@ namespace v2rayN.Base
UpdateStyles();
}
public void AutoResizeColumns()
public void RegisterDragEvent(Action<int, int> _update)
{
try
{
this.SuspendLayout();
Graphics graphics = this.CreateGraphics();
_updateFunc = _update;
this.AllowDrop = true;
// 原生 ColumnHeaderAutoResizeStyle.ColumnContent 将忽略列头宽度
this.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
for (int i = 0; i < this.Columns.Count; i++)
{
ColumnHeader c = this.Columns[i];
int cWidth = c.Width;
string MaxStr = "";
Font font = this.Items[0].SubItems[0].Font;
foreach (ListViewItem item in this.Items)
{
// 整行视作相同字形,不单独计算每个单元格
font = item.SubItems[i].Font;
string str = item.SubItems[i].Text;
if (str.Length > MaxStr.Length) // 未考虑非等宽问题
MaxStr = str;
}
int strWidth = (int)graphics.MeasureString(MaxStr, font).Width;
c.Width = System.Math.Max(cWidth, strWidth);
}
this.ResumeLayout();
}
catch { }
this.ItemDrag += new ItemDragEventHandler(this.lv_ItemDrag);
this.DragDrop += new DragEventHandler(this.lv_DragDrop);
this.DragEnter += new DragEventHandler(this.lv_DragEnter);
this.DragOver += new DragEventHandler(this.lv_DragOver);
this.DragLeave += new EventHandler(this.lv_DragLeave);
}
private void lv_DragDrop(object sender, DragEventArgs e)
{
int targetIndex = this.InsertionMark.Index;
if (targetIndex == -1)
{
return;
}
if (this.InsertionMark.AppearsAfterItem)
{
targetIndex++;
}
if (this.SelectedIndices.Count <= 0)
{
return;
}
_updateFunc(this.SelectedIndices[0], targetIndex);
//ListViewItem draggedItem = (ListViewItem)e.Data.GetData(typeof(ListViewItem));
//this.BeginUpdate();
//this.Items.Insert(targetIndex, (ListViewItem)draggedItem.Clone());
//this.Items.Remove(draggedItem);
//this.EndUpdate();
}
private void lv_DragEnter(object sender, DragEventArgs e)
{
e.Effect = e.AllowedEffect;
}
private void lv_DragLeave(object sender, EventArgs e)
{
this.InsertionMark.Index = -1;
}
private void lv_DragOver(object sender, DragEventArgs e)
{
Point targetPoint = this.PointToClient(new Point(e.X, e.Y));
int targetIndex = this.InsertionMark.NearestIndex(targetPoint);
if (targetIndex > -1)
{
Rectangle itemBounds = this.GetItemRect(targetIndex);
this.EnsureVisible(targetIndex);
if (targetPoint.Y > itemBounds.Top + (itemBounds.Height / 2))
{
this.InsertionMark.AppearsAfterItem = true;
}
else
{
this.InsertionMark.AppearsAfterItem = false;
}
}
this.InsertionMark.Index = targetIndex;
}
private void lv_ItemDrag(object sender, ItemDragEventArgs e)
{
this.DoDragDrop(e.Item, DragDropEffects.Move);
this.InsertionMark.Index = -1;
}
}
}

View File

@ -225,6 +225,7 @@ namespace v2rayN.Forms
lvServers.Scrollable = true;
lvServers.MultiSelect = true;
lvServers.HeaderStyle = ColumnHeaderStyle.Clickable;
lvServers.RegisterDragEvent(UpdateDragEventHandler);
lvServers.Columns.Add("", 30);
lvServers.Columns.Add(UIRes.I18N("LvServiceType"), 80);
@ -247,6 +248,18 @@ namespace v2rayN.Forms
lvServers.EndUpdate();
}
private void UpdateDragEventHandler(int index, int targetIndex)
{
if (index < 0 || targetIndex < 0)
{
return;
}
if (ConfigHandler.MoveServer(ref config, ref lstVmess, index, EMove.Position, targetIndex) == 0)
{
RefreshServers();
}
}
/// <summary>
/// 刷新服务器列表
/// </summary>

View File

@ -54,6 +54,7 @@ namespace v2rayN.Forms
lvRoutings.View = View.Details;
lvRoutings.MultiSelect = true;
lvRoutings.HeaderStyle = ColumnHeaderStyle.Clickable;
lvRoutings.RegisterDragEvent(UpdateDragEventHandler);
lvRoutings.Columns.Add("", 30);
lvRoutings.Columns.Add("outboundTag", 80);
@ -61,11 +62,22 @@ namespace v2rayN.Forms
lvRoutings.Columns.Add("protocol", 80);
lvRoutings.Columns.Add("inboundTag", 80);
lvRoutings.Columns.Add("domain", 160);
lvRoutings.Columns.Add("ip", 160);
lvRoutings.Columns.Add("ip", 160);
lvRoutings.Columns.Add("enable", 60);
lvRoutings.EndUpdate();
}
private void UpdateDragEventHandler(int index, int targetIndex)
{
if (index < 0 || targetIndex < 0)
{
return;
}
if (ConfigHandler.MoveRoutingRule(ref routingItem, index, EMove.Position, targetIndex) == 0)
{
RefreshRoutingsView();
}
}
private void RefreshRoutingsView()
{
@ -353,6 +365,6 @@ namespace v2rayN.Forms
#endregion
}
}

View File

@ -15,6 +15,7 @@ namespace v2rayN.Handler
class ConfigHandler
{
private static string configRes = Global.ConfigFileName;
private static object objLock = new object();
#region ConfigHandler
@ -204,7 +205,10 @@ namespace v2rayN.Handler
/// <param name="config"></param>
private static void ToJsonFile(Config config)
{
Utils.ToJsonFile(config, Utils.GetPath(configRes));
lock (objLock)
{
Utils.ToJsonFile(config, Utils.GetPath(configRes));
}
}
#endregion
@ -353,7 +357,7 @@ namespace v2rayN.Handler
/// <param name="index"></param>
/// <param name="eMove"></param>
/// <returns></returns>
public static int MoveServer(ref Config config, ref List<VmessItem> lstVmess, int index, EMove eMove)
public static int MoveServer(ref Config config, ref List<VmessItem> lstVmess, int index, EMove eMove, int pos = -1)
{
int count = lstVmess.Count;
if (index < 0 || index > lstVmess.Count - 1)
@ -409,6 +413,9 @@ namespace v2rayN.Handler
break;
}
case EMove.Position:
lstVmess[index].sort = pos * 10 + 1;
break;
}
ToJsonFile(config);
@ -1258,7 +1265,7 @@ namespace v2rayN.Handler
/// <param name="index"></param>
/// <param name="eMove"></param>
/// <returns></returns>
public static int MoveRoutingRule(ref RoutingItem routingItem, int index, EMove eMove)
public static int MoveRoutingRule(ref RoutingItem routingItem, int index, EMove eMove, int pos = -1)
{
int count = routingItem.rules.Count;
if (index < 0 || index > routingItem.rules.Count - 1)
@ -1316,6 +1323,14 @@ namespace v2rayN.Handler
break;
}
case EMove.Position:
{
var removeItem = routingItem.rules[index];
var item = Utils.DeepCopy(routingItem.rules[index]);
routingItem.rules.Insert(pos, item);
routingItem.rules.Remove(removeItem);
break;
}
}
return 0;

View File

@ -6,6 +6,7 @@ namespace v2rayN.Mode
Top = 1,
Up = 2,
Down = 3,
Bottom = 4
Bottom = 4,
Position = 5
}
}