You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

707 lines
19 KiB
C#

1 month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Design;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using BrightIdeasSoftware;
using static UCDraw.GeoSigma;
namespace UCDraw.Editor
{
//public delegate void DrawSymbol();
public partial class frmMarkEditor : DialogUIEditorFrom<string>
{
//public DrawSymbol drawSymbolEvent;
private MarkLibrary _library = new MarkLibrary();
public frmMarkEditor()
{
InitializeComponent();
toolStrip1.Renderer = MyToolStripRenderer.Instance;
treeSymbol.CanExpandGetter = delegate (object o)
{
if (o is MarkBaseNode mln)
{
if (_library.GetChildren(mln).Any())
return true;
}
return false;
};
treeSymbol.ChildrenGetter = delegate (object o)
{
var list = new ArrayList();
if (o is MarkBaseNode mlr)
{
list.AddRange(_library.GetChildren(mlr).ToList());
}
return list;
};
treeSymbol.ParentGetter = delegate (object o)
{
if (o is MarkBaseNode mln)
{
return _library.GetParent(mln);
}
return null;
};
treeSymbol.AllColumns.Add(new OLVColumn()
{
Text = "名称",
Width = 260,
Sortable = false,
AspectGetter = delegate (object o)
{
//if (o is MarkBaseItem mli)
// return mli.PathEx.Last();
if (o is MarkBaseNode mln)
return mln.PathEx.Last();
return "";
},
ImageGetter = delegate (object o)
{
if (treeSymbol.CanExpandGetter(o))
{
return "folder";
}
return "item";
},
});
treeSymbol.RebuildColumns();
treeSymbol.RowHeight = 20;
olvSymbol.ItemRenderer = new MarkItemRenderer();
//olvColumnText.ImageGetter += delegate (object o) {
// if (o is MarkItem mi)
// return mi.Image;
// return null;
//};
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_library = MarkLibrary.GetMarkLibrary();
_library.GenerateNodes();
var roots = _library.GetRoots().ToList();
treeSymbol.Objects = roots;
if (roots.Count > 0)
treeSymbol.SelectedObject = roots[0];
if (olvSymbol.Objects is List<MarkItem> list)
{
foreach (var mi in list)
{
if (this.Value != null)
{
if (mi.Name == this.Value)
{
olvSymbol.SelectedObject = mi;
break;
}
}
}
}
}
private void btnOk_Click(object sender, EventArgs e)
{
if (olvSymbol.SelectedObject is MarkItem mi)
{
if (mi is LibraryMarkItem lmi && DrawViewer.Current?.GetGeoSigma() is GeoSigma gs)
{
gs.MarkCopyLibraryToDocument(lmi.Id);
}
this.Value = mi.Name;
}
DialogResult = DialogResult.OK;
}
private void btnCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
this.Close();
}
private void treeSymbol_SelectedIndexChanged(object sender, EventArgs e)
{
if (treeSymbol.SelectedObject is MarkDocumentNode dnode)
{
MarkLibrary.GenerateDocumentImage(dnode.Marks);
olvSymbol.Objects = dnode.Marks;
if (dnode.Marks.Count > 0)
olvSymbol.EnsureModelVisible(dnode.Marks[0]);
}
else if (treeSymbol.SelectedObject is MarkLibraryNode lnode)
{
MarkLibrary.GenerateLibraryImage(lnode.Marks);
olvSymbol.Objects = lnode.Marks;
if (lnode.Marks.Count > 0)
olvSymbol.EnsureModelVisible(lnode.Marks[0]);
}
}
private void tsbtnSearch_Click(object sender, EventArgs e)
{
var text = tstbSearch.Text;
var list = new List<MarkItem>();
foreach (var node in _library.Nodes.OfType<MarkItemNode>())
{
var tmp = node.Marks.Where(r => r.Name.Contains(text)).ToList();
if (node is MarkDocumentNode dnode)
{
MarkLibrary.GenerateDocumentImage(tmp);
}
else if (node is MarkLibraryNode lnode)
{
MarkLibrary.GenerateLibraryImage(tmp);
}
list.AddRange(tmp);
}
olvSymbol.Objects = list;
if (list.Count > 0)
olvSymbol.EnsureModelVisible(list[0]);
}
private void btnNew_Click(object sender, EventArgs e)
{
var mdNode = new MarkDocumentNode();
string aa = mdNode.Name;
olvSymbol.AddObject(mdNode);
this.olvSymbol.SelectObject(mdNode, true);
}
private void btnEdit_Click(object sender, EventArgs e)
{
if (treeSymbol.SelectedObject is MarkDocumentNode dnode)
{
olvSymbol.Objects = dnode.Marks;
}
}
private void olvSymbol_SelectedIndexChanged(object sender, EventArgs e)
{
var symbol = olvSymbol.SelectedItem;
if (symbol != null)
{
var dataSymbol = symbol.RowObject;
DrawViewer.Current.GetGeoSigma().DrawImg();
//drawer1.InvokePaintEvent();
//this.Paint += new System.Windows.Forms.PaintEventHandler(DrawViewer.Current.Drawer_Paint);
//drawSymbolEvent?.Invoke();
}
}
}
public class MarkEditor : DialogUIEditor<string, frmMarkEditor>
{
private List<MarkItem> _items = new List<MarkItem>();
public override bool GetPaintValueSupported(ITypeDescriptorContext context)
{
return true;
}
public override void PaintValue(PaintValueEventArgs e)
{
if (e.Value is string s)
{
MarkItem mi = _items.FirstOrDefault(r => r.Name == s);
if (mi == null)
{
foreach (var dm in MarkLibrary.GetDocumentMarks())
{
var tmp = _items.FirstOrDefault(r => r.Id == dm.Id);
if (tmp == null)
{
_items.Add(dm);
}
else
{
tmp.Name = dm.Name;
tmp.Image = dm.Image;
}
}
mi = _items.FirstOrDefault(r => r.Name == s);
}
if (mi != null)
{
if (mi.Image == null)
MarkLibrary.GenerateDocumentImage(new[] { mi });
e.Graphics.DrawImage(mi.Image, e.Bounds);
}
}
base.PaintValue(e);
}
}
#region 符号
public abstract class MarkItem
{
public string Name { get; set; }
public string Id { get; set; }
public Image Image { get; set; }
}
public class DocumentMarkItem : MarkItem { }
public class LibraryMarkItem : MarkItem { }
public abstract class MarkBaseNode
{
private string _path;
public string Path
{
get => _path;//string.Join("\\", PathEx);
set
{
_path = value;
PathEx.Clear();
PathEx.AddRange(value.Split(new[] { "\\" }, StringSplitOptions.RemoveEmptyEntries));
}
}
public List<string> PathEx { get; set; } = new List<string>();
public string Name
{
get
{
if (PathEx.Count > 0)
return PathEx.Last();
return string.Empty;
}
}
public int Level => PathEx.Count;
public string GetPathByLevel(int level)
{
return string.Join("\\", PathEx.Take(level));
}
public bool IsParentOf(MarkBaseNode rhs)
{
if (this.PathEx.Count == rhs.PathEx.Count - 1)
{
int count = 0;
for (int i = 0; i < this.PathEx.Count; i++)
{
if (this.PathEx[i] == rhs.PathEx[i])
count++;
}
return count == this.PathEx.Count;
}
return false;
}
public bool IsChildOf(MarkBaseNode rhs)
{
return rhs.IsParentOf(this);
}
public bool IsAncestorOf(MarkBaseNode rhs)
{
if (this.PathEx.Count < rhs.PathEx.Count)
{
int count = 0;
for (int i = 0; i < this.PathEx.Count; i++)
{
if (this.PathEx[i] == rhs.PathEx[i])
count++;
}
return count == this.PathEx.Count;
}
return false;
}
public bool IsPosterityOf(MarkBaseNode rhs)
{
return rhs.IsAncestorOf(this);
}
}
public class MarkVirtualNode : MarkBaseNode
{
}
public class MarkItemNode : MarkBaseNode
{
public List<MarkItem> Marks { get; set; } = new List<MarkItem>();
public override string ToString()
{
return $"{Path}: {Marks.Count}";
}
}
public class MarkLibraryNode : MarkItemNode { }
public class MarkDocumentNode : MarkItemNode { }
public class MarkLibrary
{
public List<MarkItemNode> Items { get; set; } = new List<MarkItemNode>();
public bool Empty => Items.Count == 0;
public List<MarkBaseNode> Nodes { get; set; } = new List<MarkBaseNode>();
public void GenerateNodes()
{
List<MarkBaseNode> GetRoots()
{
var list = new List<MarkBaseNode>();
list.AddRange(this.Items.OfType<MarkDocumentNode>());
var parents = this.Items.Where(r => !(r is MarkDocumentNode))
.Where(r => !this.Items.Any(k => k.IsParentOf(r)));
list.AddRange(parents.Where(r => r.PathEx.Count != 1)
.Select(r => r.PathEx[0])
.Distinct()
.Select(r => new MarkVirtualNode() { Path = r })
);
list.AddRange(parents.Where(r => r.PathEx.Count == 1));
return list;
}
List<MarkBaseNode> GetChildren(MarkBaseNode node)
{
var list = new List<MarkBaseNode>();
var tmp = this.Items.Where(r => r.IsPosterityOf(node));
list.AddRange(tmp.Where(r => !r.IsChildOf(node))
.Select(r => r.GetPathByLevel(node.Level + 1))
.Distinct()
.Select(r => new MarkVirtualNode() { Path = r })
.ToList()
);
list.AddRange(tmp.Where(r => r.IsChildOf(node)).ToList());
var children = list.SelectMany(r => GetChildren(r)).ToList();
list.AddRange(children);
return list;
}
Nodes.Clear();
var roots = GetRoots();
Nodes.AddRange(roots);
var nodes = roots.SelectMany(r => GetChildren(r));
Nodes.AddRange(nodes);
}
public IEnumerable<MarkBaseNode> GetRoots()
{
var list = new List<MarkBaseNode>();
list.AddRange(Nodes.OfType<MarkDocumentNode>());
list.AddRange(Nodes.OfType<MarkVirtualNode>().Where(r => r.Level == 1));
list.AddRange(Nodes.OfType<MarkLibraryNode>().Where(r => r.Level == 1));
return list;
}
public IEnumerable<MarkBaseNode> GetChildren(MarkBaseNode parent)
{
foreach (var mln in Nodes)
{
if (mln.IsChildOf(parent))
yield return mln;
}
}
public MarkBaseNode GetParent(MarkBaseNode child)
{
foreach (var mln in Nodes)
{
if (mln.IsParentOf(child))
return mln;
}
return null;
}
#region 接口
public static List<MarkItem> GetDocumentMarks()
{
var list = new List<MarkItem>();
if (DrawViewer.Current?.GetGeoSigma() is GeoSigma gs)
{
var idList = new StringBuilder(65535);
var nameList = new StringBuilder(65535);
if (gs.MarkLoopName(idList, nameList))
{
var arrId = idList.ToString().Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
var arrName = nameList.ToString().Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
if (arrId.Length == arrName.Length)
{
for (int i = 0; i < arrId.Length; i++)
{
list.Add(new DocumentMarkItem()
{
Name = arrName[i],
Id = arrId[i],
});
}
}
}
}
return list;
}
public static MarkLibrary GetMarkLibrary()
{
var library = new MarkLibrary();
library.Items.Add(new MarkDocumentNode()
{
Path = "当前文件符号",
Marks = GetDocumentMarks(),
});
library.Items.AddRange(GetDefaultLibrary().Items);
return library;
}
private static MarkLibrary _defaultMarkLibrary = new MarkLibrary();
public static MarkLibrary GetDefaultLibrary()
{
if (_defaultMarkLibrary.Empty)
{
var pathList = new StringBuilder(65535);
if (GeoSigma.MarkLibraryLoopName(pathList))
{
var arrPath = pathList.ToString().Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
foreach (var path in arrPath)
{
var item = new MarkLibraryNode()
{
Path = path
};
var idList = new StringBuilder(65535);
var nameList = new StringBuilder(65535);
if (GeoSigma.MarkLibraryLoopMark(path, idList, nameList))
{
var arrId = idList.ToString().Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
var arrName = nameList.ToString().Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
if (arrId.Length == arrName.Length)
{
for (int i = 0; i < arrId.Length; i++)
{
item.Marks.Add(new DocumentMarkItem()
{
Name = arrName[i],
Id = arrId[i],
});
}
}
}
_defaultMarkLibrary.Items.Add(item);
}
}
}
return _defaultMarkLibrary;
}
public static void GenerateDocumentImage(IEnumerable<MarkItem> marks)
{
if (DrawViewer.Current?.GetGeoSigma() is GeoSigma gs)
{
foreach (var nm in marks)
{
int cx = 50, cy = 50;
var img = new Bitmap(cx, cy);
Graphics g = Graphics.FromImage(img);
if (gs.MarkDrawByName(nm.Id, g.GetHdc(), cx, cy))
{
//加上这句才能回写到bitmap中
g.ReleaseHdc();
nm.Image = img;
//nm.Image.Save($"d:\\{nm.Name}.bmp");
}
}
}
}
public static void GenerateLibraryImage(IEnumerable<MarkItem> marks)
{
foreach (var nm in marks)
{
int cx = 50, cy = 50;
var img = new Bitmap(cx, cy);
Graphics g = Graphics.FromImage(img);
if (GeoSigma.MarkLibraryDrawByName(nm.Id, g.GetHdc(), cx, cy))
{
//加上这句才能回写到bitmap中
g.ReleaseHdc();
nm.Image = img;
//nm.Image.Save($"d:\\{nm.Name}.bmp");
}
}
}
#endregion
}
#endregion
#region MarkItemRenderer
internal class MarkItemRenderer : BrightIdeasSoftware.BaseRenderer
{
public override bool RenderItem(DrawListViewItemEventArgs e, Graphics g, Rectangle r, object x)
{
var ret = base.RenderItem(e, g, r, x);
if (x is MarkItem mi)
{
if (e.Item.Selected)
{
g.FillRectangle(Brushes.LightGray, r);
}
int cx = 30;
int cy = 30;
int size = Math.Min(r.Width - cx, r.Height - cy);
var rcImageBorder = new Rectangle(r.Left + (r.Width-size) / 2, r.Top, size, size);
rcImageBorder.Inflate(-2, -2);
var rcImage = rcImageBorder;
rcImage.Inflate(-2, -2);
g.DrawImage(mi.Image, rcImage);
g.DrawRectangle(Pens.Black, rcImageBorder);
StringFormat fmt = new StringFormat();
fmt.LineAlignment = StringAlignment.Near;
fmt.Alignment = StringAlignment.Center;
g.DrawString(mi.Name, this.Font, Brushes.Black,
new Rectangle(r.Left, r.Top+size, r.Width, r.Height-size)
, fmt);
return true;
}
return ret;
}
}
#endregion
}