using System.Collections.Generic;
|
using System.Drawing;
|
using System;
|
using System.Drawing.Drawing2D;
|
using System.Text;
|
using System.Windows.Forms;
|
using DPumpHydr.WinFrmUI.WenSkin.Json.Utilities;
|
using System.Linq;
|
using System.IO;
|
|
namespace DPumpHydr.WinFrmUI.WenSkin;
|
|
public class Ini
|
{
|
private IniGroupCollection items;
|
|
public Ini() { }
|
public Ini(string path) : this(path, Encoding.UTF8) { }
|
public Ini(string path, Encoding encoding)
|
{
|
Path = path;
|
Encoding = encoding;
|
Load(path, encoding);
|
}
|
public string? this[string name]
|
{
|
get => GetItem(name);
|
set
|
{
|
var item = Items.SelectMany(t => t.Items)?.ToList().Find(t => t.Name?.ToLower() == name.ToLower());
|
if (item == null)
|
{
|
AddItem(null, name, value);
|
}
|
else
|
{
|
item.Value = value;
|
}
|
}
|
}
|
public string? this[string key, string name]
|
{
|
get => Items[key]?.Items[name]?.Value;
|
set
|
{
|
//获取Group
|
if (Items[key] is not IniGroup group)
|
{
|
group = this.Items.Add(key);
|
}
|
|
if (group.Items[name] is not IniItem iniItem)
|
{
|
iniItem = group.Items.Add(name, value);
|
}
|
iniItem.Value = value;
|
}
|
}
|
|
#region 公有属性
|
|
public string FileName => System.IO.Path.GetFileName(Path);
|
/// <summary>
|
/// 路径
|
/// </summary>
|
public string Path { get; private set; }
|
/// <summary>
|
/// 编码方式
|
/// </summary>
|
public Encoding Encoding { get; private set; }
|
/// <summary>
|
/// 内容
|
/// </summary>
|
public string Text => string.Join("\r\n", Items.Select(g => g.Text));
|
|
#endregion
|
|
/// <summary>
|
/// 加载(默认UTF8编码)
|
/// </summary>
|
/// <param name="path"></param>
|
public void Load(string path) => Load(path, Encoding.UTF8);
|
/// <summary>
|
/// 加载( 指定文件编码)
|
/// </summary>
|
/// <param name="path"></param>
|
/// <param name="encoding"></param>
|
public void Load(string path, Encoding encoding)
|
{
|
Items.Clear();
|
if (!File.Exists(path))
|
return;
|
|
string[] texts = File.ReadAllLines(path, encoding);
|
|
IniGroup? group = null;
|
foreach (var text in texts)
|
{
|
//选项
|
string t = text.Replace(" ", "");
|
var idx = text.IndexOf("=");
|
|
//添加组
|
if (t.StartsWith("[") && t.EndsWith("]"))
|
{
|
group = Items.Add(text.Substring(text.IndexOf("[") + 1, text.IndexOf("]") - 1));
|
continue;
|
}
|
else if (Items.Count == 0)
|
{
|
group = Items.Add(null);
|
}
|
|
//添加选项
|
if (t.StartsWith("!") || t.StartsWith(";") || t.StartsWith("]") || t.StartsWith("//") || string.IsNullOrEmpty(t))
|
{
|
group?.Items.Add(null, text);
|
}
|
else if (idx == -1)
|
{
|
group?.Items.Add(null, text);
|
}
|
else if (idx == 0)
|
{
|
group?.Items.Add("", text);
|
}
|
else if (idx > 0)
|
{
|
group?.Items.Add(text.Substring(0, idx), text.Substring(idx + 1));
|
}
|
}
|
}
|
/// <summary>
|
/// 添加注释
|
/// </summary>
|
/// <param name="groupName"></param>
|
/// <param name="value"></param>
|
public void AddRemark(string groupName, string value) => AddItem(groupName, null, value);
|
/// <summary>
|
/// 添加选项
|
/// </summary>
|
/// <param name="groupName"></param>
|
/// <param name="name"></param>
|
/// <param name="value"></param>
|
public void AddItem(string? groupName, string? name, string? value)
|
{
|
var g = this.Items[groupName];
|
g ??= this.Items.Add(groupName);
|
g.Items.Add(name, value);
|
}
|
/// <summary>
|
/// 获取选项
|
/// </summary>
|
/// <param name="groupName">组名称</param>
|
/// <param name="name">名称</param>
|
/// <returns></returns>
|
public string? GetItem(string groupName, string name) => Items[groupName]?.Items[name]?.Value;
|
/// <summary>
|
/// 获取选项值
|
/// </summary>
|
/// <param name="name">名称</param>
|
/// <returns></returns>
|
public string? GetItem(string name) => Items.SelectMany(t => t.Items)?.ToList().Find(t => t.Name?.ToLower() == name.ToLower())?.Value;
|
/// <summary>
|
/// 保存
|
/// </summary>
|
public void Save()
|
{
|
SaveAs(Path);
|
}
|
/// <summary>
|
/// 另存为
|
/// </summary>
|
/// <param name="path"></param>
|
public void SaveAs(string path)
|
{
|
SaveAs(path, Encoding);
|
}
|
/// <summary>
|
/// 另存为(指定文件编码)
|
/// </summary>
|
/// <param name="path">路径</param>
|
/// <param name="encoding">文件编码</param>
|
public void SaveAs(string path, Encoding encoding)
|
{
|
File.WriteAllText(path, Text, encoding);
|
}
|
/// <summary>
|
/// 选项
|
/// </summary>
|
public IniGroupCollection Items => items ??= new IniGroupCollection(this);
|
|
/// <summary>
|
/// 组
|
/// </summary>
|
public class IniGroup
|
{
|
private readonly IniGroupCollection owner;
|
|
private IniItemCollection? items;
|
|
public IniGroup(IniGroupCollection owner, string? name)
|
{
|
this.owner = owner;
|
Name = name;
|
}
|
public Ini Ini => this.owner.Ini;
|
/// <summary>
|
/// 名称
|
/// </summary>
|
public string? Name { get; private set; }
|
/// <summary>
|
/// 选项合集
|
/// </summary>
|
public IniItemCollection Items => items ??= new IniItemCollection(this);
|
/// <summary>
|
/// 内容
|
/// </summary>
|
public string Text => (string.IsNullOrWhiteSpace(Name) ? "" : $"[{Name}]\r\n") + string.Join("\r\n", Items.Select(x => x.Text));
|
}
|
/// <summary>
|
/// 组合计
|
/// </summary>
|
public class IniGroupCollection : List<IniGroup>
|
{
|
private readonly Ini owner;
|
|
public IniGroupCollection(Ini owner)
|
{
|
this.owner = owner;
|
}
|
/// <summary>
|
/// Ini
|
/// </summary>
|
public Ini Ini => this.owner;
|
/// <summary>
|
/// 获取选项
|
/// </summary>
|
/// <param name="name"></param>
|
/// <returns></returns>
|
public IniGroup? this[string? name] => Find(a => a.Name?.ToUpper() == name?.ToUpper());
|
/// <summary>
|
/// 添加选项
|
/// </summary>
|
/// <param name="name"></param>
|
/// <returns></returns>
|
public IniGroup Add(string? name)
|
{
|
var g = new IniGroup(this, name);
|
if (name is null)
|
{
|
this.Insert(0, g);
|
}
|
else
|
{
|
Add(g);
|
}
|
|
return g;
|
}
|
}
|
/// <summary>
|
/// 选项
|
/// </summary>
|
public class IniItem
|
{
|
private readonly IniItemCollection owner;
|
|
public IniItem(IniItemCollection owner, string? name, string? value)
|
{
|
this.owner = owner;
|
Name = name;
|
Value = value;
|
}
|
public Ini Ini => owner.Ini;
|
|
public IniItemCollection Owner => owner;
|
|
public int Index => owner.IndexOf(this);
|
/// <summary>
|
/// 名称
|
/// </summary>
|
public string? Name { get; set; }
|
/// <summary>
|
/// 值
|
/// </summary>
|
public string? Value { get; set; }
|
/// <summary>
|
/// 文本
|
/// </summary>
|
public string? Text => string.IsNullOrWhiteSpace(Name) ?
|
(string.IsNullOrWhiteSpace(Value) || Value.StartsWith('!') || Value.StartsWith(';') ? Value : (";" + Value)) :
|
$"{Name}={Value}";
|
/// <summary>
|
/// 是否是注释行
|
/// </summary>
|
public bool IsRemarkLine => string.IsNullOrWhiteSpace(this.Name);
|
}
|
/// <summary>
|
/// 选项合集
|
/// </summary>
|
public class IniItemCollection : List<IniItem>
|
{
|
private readonly IniGroup owner;
|
|
public IniItemCollection(IniGroup owner)
|
{
|
this.owner = owner;
|
}
|
public Ini Ini => owner.Ini;
|
public IniItem? this[string name] => Find(a => a.Name?.ToUpper() == name?.ToUpper());
|
|
public IniItem Add(string? name, string? value)
|
{
|
var item = new IniItem(this, name, value);
|
this.Add(item);
|
return item;
|
}
|
}
|
|
/// <summary>
|
/// 弹出编辑窗口
|
/// </summary>
|
public void Show() => IniFormShow();
|
/// <summary>
|
/// 弹出编辑窗口
|
/// </summary>
|
public void IniFormShow()
|
{
|
var fm = new Form()
|
{
|
Width = 925,
|
Height = 571,
|
Text = $"INI可视化编辑器 - 珠海森云科技出品 - {this.FileName} - {this.Encoding.EncodingName}",
|
StartPosition = FormStartPosition.CenterScreen,
|
};
|
fm.Controls.Add(new IniControl(this) { Dock = DockStyle.Fill });
|
fm.ShowDialog();
|
}
|
|
|
public static StringFormat StringConters { get; set; } = new StringFormat(StringFormatFlags.NoClip | StringFormatFlags.NoWrap)
|
{
|
LineAlignment = StringAlignment.Center,
|
Trimming = StringTrimming.EllipsisCharacter
|
};
|
public class IniControl : Control
|
{
|
private Ini Ini;
|
public IniControl(Ini ini)
|
{
|
this.Ini = ini;
|
this.Size = new Size(900, 540);
|
this.BackColor = Color.White;
|
Initcom();
|
if (ini != null)
|
Load();
|
}
|
private FlowLayoutPanel Flow;
|
private void Initcom()
|
{
|
Button button = new Button()
|
{
|
Text = "保存 应用",
|
Dock = DockStyle.Bottom,
|
};
|
button.Click += (s, e) =>
|
{
|
Ini.Save();
|
MessageBox.Show("保存成功!");
|
};
|
Flow = new FlowLayoutPanel()
|
{
|
Dock = DockStyle.Fill,
|
AutoScroll = true,
|
FlowDirection = FlowDirection.TopDown,
|
WrapContents = false,
|
};
|
this.Controls.Add(Flow);
|
this.Controls.Add(button);
|
}
|
|
public IniItem Selected => SelectedControl.IniItem;
|
|
public IniItemControl SelectedControl { get; private set; }
|
private void Load()
|
{
|
foreach (var ini in Ini.Items)
|
{
|
var groupBox = new GroupBox()
|
{
|
Text = ini.Name ?? "Default (Is not group name)",
|
ForeColor = Color.DarkOrchid,
|
AutoSize = true,
|
};
|
var flow = new FlowLayoutPanel()
|
{
|
AutoSize = true,
|
FlowDirection = FlowDirection.TopDown,
|
Dock = DockStyle.Fill,
|
};
|
foreach (var item in ini.Items)
|
{
|
var control = new IniItemControl(this, flow, item);
|
control.Click += (s, e) =>
|
{
|
if (this.SelectedControl != null)
|
this.SelectedControl.SelectColor = Color.White;
|
control.SelectColor = Color.DarkGray;
|
this.SelectedControl = control;
|
};
|
flow.Controls.Add(control);
|
}
|
groupBox.Controls.Add(flow);
|
Flow.Controls.Add(groupBox);
|
}
|
}
|
}
|
public class IniItemControl : Control
|
{
|
private readonly IniControl owner;
|
private readonly FlowLayoutPanel flow;
|
private readonly IniItem iniItem;
|
public IniItemControl(IniControl owner, FlowLayoutPanel flow, IniItem iniItem)
|
{
|
base.SetStyle(
|
ControlStyles.UserPaint |
|
ControlStyles.DoubleBuffer |
|
ControlStyles.OptimizedDoubleBuffer |
|
ControlStyles.AllPaintingInWmPaint |
|
ControlStyles.ResizeRedraw |
|
ControlStyles.SupportsTransparentBackColor, true);
|
base.UpdateStyles();
|
this.BackColor = Color.Transparent;
|
|
this.owner = owner;
|
this.flow = flow;
|
this.iniItem = iniItem;
|
this.Height = 30;
|
this.Width = 870;
|
this.Margin = new Padding(1, 0, 1, 0);
|
this.Name = iniItem.Name;
|
this.Text = iniItem.Text;
|
|
|
menuStrip.Items.Add("注释", null, (s, e) =>
|
{
|
var item = new IniItem(IniItem.Owner, null, ";注释");
|
this.IniItem.Owner.Insert(this.IniItem.Index, item);
|
var control = new IniItemControl(owner, flow, item);
|
this.flow.Controls.Add(control);
|
this.flow.Controls.SetChildIndex(control, this.IniItem.Index - 1);
|
});
|
|
menuStrip.Items.Add("插入", null, (s, e) =>
|
{
|
var item = new IniItem(IniItem.Owner, "Name", "Value");
|
this.IniItem.Owner.Insert(this.IniItem.Index, item);
|
var control = new IniItemControl(owner, flow, item);
|
this.flow.Controls.Add(control);
|
this.flow.Controls.SetChildIndex(control, this.IniItem.Index - 1);
|
});
|
|
menuStrip.Items.Add("添加", null, (s, e) =>
|
{
|
var item = new IniItem(IniItem.Owner, "Name", "Value");
|
this.IniItem.Owner.Add(item);
|
var control = new IniItemControl(owner, flow, item);
|
this.flow.Controls.Add(control);
|
});
|
|
menuStrip.Items.Add("删除", null, (s, e) =>
|
{
|
this.IniItem.Owner.Remove(this.IniItem);
|
this.Dispose();
|
});
|
this.ContextMenuStrip = menuStrip;
|
}
|
|
private readonly ContextMenuStrip menuStrip = new ContextMenuStrip();
|
private Color selectColor = Color.White;
|
|
public IniItem IniItem => iniItem;
|
|
public Color SelectColor { get => selectColor; set { selectColor = value; this.BackColor = value; } }
|
protected override void OnMouseLeave(EventArgs e)
|
{
|
base.OnMouseLeave(e);
|
this.BackColor = SelectColor;
|
}
|
protected override void OnMouseEnter(EventArgs e)
|
{
|
base.OnMouseEnter(e);
|
this.BackColor = Color.LightGray;
|
}
|
|
protected override void OnPaint(PaintEventArgs e)
|
{
|
base.OnPaint(e);
|
var g = e.Graphics;
|
g.SmoothingMode = SmoothingMode.AntiAlias; //使绘图质量最高,即消除锯齿
|
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
g.CompositingQuality = CompositingQuality.HighQuality;
|
|
|
if (IniItem.IsRemarkLine)
|
{
|
var valueRec = new RectangleF(0, 0, Width, Height);
|
g.DrawString(IniItem.Value, Font, Brushes.Green, valueRec, StringConters);
|
}
|
else
|
{
|
var nameRec = new RectangleF(0, 0, 145, Height);
|
var valueRec = new RectangleF(150, 0, Width - 150, Height);
|
g.DrawString(IniItem.Name, Font, Brushes.DodgerBlue, nameRec, StringConters);
|
g.DrawString(IniItem.Value, Font, Brushes.Black, valueRec, StringConters);
|
}
|
}
|
|
protected override void OnMouseClick(MouseEventArgs e)
|
{
|
base.OnMouseClick(e);
|
if (IniItem.IsRemarkLine)
|
{
|
ShowTextBox(Width, 0);
|
}
|
else
|
{
|
if (new RectangleF(0, 0, 145, Height).Contains(e.Location))
|
{
|
ShowTextBox(145, 0, false);
|
}
|
else
|
{
|
ShowTextBox(Width - 150, 150);
|
}
|
}
|
}
|
|
private void ShowTextBox(int width, int x, bool isValue = true)
|
{
|
var tb = new TextBox()
|
{
|
Width = width,
|
Text = isValue ? IniItem.Value : IniItem.Name,
|
ForeColor = IniItem.IsRemarkLine ? Color.Green : Color.Black,
|
};
|
tb.Location = new Point(x, (this.Height - tb.Height) / 2);
|
|
tb.LostFocus += (s, e) =>
|
{
|
tb.Dispose();
|
};
|
tb.TextChanged += (s, e) =>
|
{
|
if (isValue)
|
IniItem.Value = tb.Text;
|
else
|
IniItem.Name = tb.Text;
|
};
|
tb.KeyDown += (s, e) =>
|
{
|
if (e.KeyCode == Keys.Enter)
|
{
|
tb.Dispose();
|
}
|
};
|
this.Controls.Add(tb);
|
tb.Select();
|
}
|
}
|
}
|