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.

1476 lines
47 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using GeoSigmaDrawLib;
using Microsoft.VisualBasic.Devices;
using UCDraw;
namespace SymbolLibManager
{
/// <summary>
/// 符号管理界面
/// 这个类有两个作用:一是符号及符号组的增删改查,一是供图层/图元修饰时选择符号
/// 基础概念:
/// 最左侧一栏我们称为符号组,对应一个符号文件
/// 中间那栏我们称为符号
/// 右边那栏是符号详情和编辑
/// </summary>
public partial class FrmMarkMain : Form
{
public string LibPath { get; set; }
private const string CurrentFile = "当前文件";
private readonly List<ListViewItem> arrItemsCache = new List<ListViewItem>();
private ImageList lstSymbolImage;
public bool IsDirty { get; set; } = false;
public const string ClipboardFormatSymbol = "ClipboardFormatSymbol";
private string SelectedFile = "";
private bool OnSearchStatus = false;
private GeoSigma.UCDraw.MainView mainView;
private readonly DelayedRefreshHelper refreshHelper;
private const int delay = 100;
public GeoSigmaXY DrawerGeo { get; set; }
/// <summary>
/// 是否显示为符号选择状态
/// </summary>
public bool ShowInSelectMode { get; set; } = false;
public string SelectedSymbolName { get; set; } = null;
public FrmMarkMain(string dataPath) : this(null, dataPath)
{
}
public FrmMarkMain(GeoSigmaXY geo, string dataPath)
{
InitializeComponent();
DrawerGeo = geo;
InitSymbolGroup(dataPath);
InitSymbols();
SelectFirstGroup();
refreshHelper = new DelayedRefreshHelper(delay, ShowSelectedSymbolGroup);
}
private void SelectFirstGroup()
{
if (trvSymbol.Nodes.Count > 0)
{
TreeNode firstChild = trvSymbol.Nodes[0];
if (firstChild != null && firstChild.Nodes.Count > 0)
{
TreeNode firstGrandchild = firstChild.Nodes[0];
trvSymbol.SelectedNode = firstGrandchild;
}
}
}
private void InitSymbolGroup(string dataPath)
{
if (string.IsNullOrEmpty(dataPath))
{
// 符号表默认目录
var symbolFilePath = Directory.GetParent(Application.StartupPath);
LibPath = Path.Combine(symbolFilePath.FullName, "Symbol");
}
else
{
LibPath = dataPath;
}
string symbolData = "";
GeoSigmaXY.InitLibrary(LibPath, ref symbolData);
InitSymbolTree(symbolData);
}
private void InitSymbols()
{
lstSymbolImage = new ImageList();
lstSymbolImage.ColorDepth = ColorDepth.Depth24Bit;
lstSymbolImage.ImageSize = new Size(50, 50);
lsvSymbol.LargeImageList = lstSymbolImage;
lsvSymbol.View = View.LargeIcon;
lsvSymbol.HideSelection = false;
lsvSymbol.VirtualMode = true;
lsvSymbol.MultiSelect = false;
lsvSymbol.LabelEdit = true;
lsvSymbol.ContextMenuStrip = ctmSymbols;
}
private void ApplicationIdle(object sender, EventArgs e)
{
try
{
bool bHasSelected = lsvSymbol.SelectedIndices.Count > 0;
bool bHasClip = false;
var clipData = Clipboard.GetData(ClipboardFormatSymbol);
if (clipData is List<string> lstPxy)
{
if (lstPxy.Count > 0)
{
bHasClip = true;
}
}
// 粘贴、添加
tsbtnSymbolPaste.Enabled = (bHasClip && OnSearchStatus == false);
ctsbtnPasteSymbol.Enabled = tsbtnSymbolPaste.Enabled;
tsbtnListAdd.Enabled = !OnSearchStatus;
if (string.IsNullOrEmpty(SelectedFile))
{
tsbtnListAdd.Enabled = false;
}
// 复制
tsbtnSymbolCopy.Enabled = bHasSelected;
ctsbtnCopySymbol.Enabled = tsbtnSymbolCopy.Enabled;
// 删除、编辑
tsbtnListRemove.Enabled = tsbtnSymbolCopy.Enabled; // (!OnSearchStatus && bHasSelected);
ctsbtnDeleteSymbol.Enabled = tsbtnListRemove.Enabled;
tsbtnEdit.Enabled = tsbtnListRemove.Enabled;
ctsbtnEditName.Enabled = tsbtnEdit.Enabled;
var root = trvSymbol.Nodes[0];
bool bGroupChecked = false;
foreach (TreeNode node in root.Nodes)
{
if (node.Checked)
{
bGroupChecked = true;
break;
}
}
tsbtnDeleteFile.Enabled = bGroupChecked;
tsbtnExportFile.Enabled = bGroupChecked;
}
catch
{
}
}
/// <summary>
/// 初始化最左侧的符号组
/// </summary>
/// <param name="nodeData">以分号分割的字符串,表示符号组列表</param>
private void InitSymbolTree(string nodeData)
{
var root = trvSymbol.Nodes.Add("符号库");
root.ImageIndex = 1;
root.SelectedImageIndex = 1;
root.StateImageIndex = 1;
root.Nodes.AddRange(nodeData.Split(';')
.Where(itemData => !string.IsNullOrEmpty(itemData))
.Select(itemData => new TreeNode
{
Text = Path.GetFileNameWithoutExtension(itemData),
ImageIndex = 0,
Tag = itemData
})
.ToArray());
// 如果当前有选中文件,符号组中添加当前文件
if (DrawerGeo != null)
{
TreeNode currentNode = new TreeNode
{
Text = CurrentFile,
Tag = CurrentFile,
};
root.Nodes.Insert(0, currentNode);
}
root.Expand();
}
private void lsvSymbol_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
if (arrItemsCache == null || arrItemsCache.Count == 0)
{
e.Item = new ListViewItem();
}
e.Item = arrItemsCache[e.ItemIndex];
}
protected override void OnClosed(EventArgs e)
{
mainView.CloseFaultEditor();
base.OnClosed(e);
}
private void FrmMarkMain_Load(object sender, EventArgs e)
{
mainView = new GeoSigma.UCDraw.MainView();
//设置窗体最大化
mainView.Dock = DockStyle.Fill;
//指定当前子窗体显示的容器
mainView.Parent = spMain.Panel2;
mainView.BringToFront();
mainView.Show();
mainView.PropertyVisible = true;
mainView.LayerVisible = false;
mainView.StatisticVisble = false;
mainView.ToolstripView.Visible = false;
mainView.BeforeSaveFileEvent += MainView_SaveFile;
mainView.AutoReleaseView = false;
DrawerEnable(false);
SetUIMode();
Application.Idle += ApplicationIdle;
}
private void SetUIMode()
{
if (ShowInSelectMode)
{
spMain.Panel2Collapsed = true;
tspTree.Visible = false;
tspItems.Visible = false;
tsbtnOK.Visible = true;
tsbtnCancel.Visible = true;
}
}
private ListViewItem CreateSymbolItem(string symbolName, int imageIndex, SymbolItemData itemData)
{
ListViewItem item = new ListViewItem(symbolName);
item.Name = symbolName;
item.ImageIndex = imageIndex;
item.Tag = itemData;
return item;
}
/// <summary>
/// 获取分组的符号列表
/// </summary>
/// <param name="group">分组名称</param>
/// <returns></returns>
private List<string> GetGroupSymbolNames(string group)
{
if (group == null)
{
return new List<string>();
}
SelectedFile = group;
if (string.IsNullOrEmpty(SelectedFile))
{
return new List<string>();
}
return ListSymbols(SelectedFile);
}
/// <summary>
/// 添加符号
/// </summary>
/// <param name="symbol"></param>
private void AddSymbol(SymbolItemData symbol)
{
CreateBitMap(symbol.Group, symbol.Name, out Bitmap bmp, out IntPtr pXy);
SymbolItemData itemData = new SymbolItemData();
itemData.Group = symbol.Group;
itemData.Name = symbol.Name;
itemData.PtrXY = pXy;
ListViewItem item = CreateSymbolItem(symbol.Name, arrItemsCache.Count, itemData);
lstSymbolImage.Images.Add(bmp);
arrItemsCache.Add(item);
lsvSymbol.VirtualListSize = arrItemsCache.Count;
}
/// <summary>
/// 查找符号
/// </summary>
/// <returns></returns>
private List<SymbolItemData> FindSymbol(string text)
{
List<SymbolItemData> result = new List<SymbolItemData>();
foreach (string group in ListAllGroups())
{
List<string> symbols = ListSymbols(group);
foreach (string symbol in symbols)
{
if (!symbol.Contains(text))
{
continue;
}
var item = new SymbolItemData()
{
Name = symbol,
Group = group,
};
result.Add(item);
}
}
return result;
}
/// <summary>
/// 清除当前的符号
/// </summary>
private void ClearSymbols()
{
foreach (Image image in lstSymbolImage.Images)
{
image.Dispose();
}
arrItemsCache.Clear();
lstSymbolImage.Images.Clear();
lsvSymbol.VirtualListSize = arrItemsCache.Count;
}
/// <summary>
/// 查出所有符号组
/// </summary>
/// <returns>返回符号组列表</returns>
private List<string> ListAllGroups()
{
TreeNode rootNode = trvSymbol.Nodes[0];
return rootNode.Nodes.Cast<TreeNode>()
.Select(node => node.Tag.ToString())
.ToList();
}
private void RemoveGroup(string group)
{
GeoSigmaXY.LibraryRemoveGroup(group);
try
{
File.Delete(group);
}
catch
{
}
}
private List<string> ListSymbols(string group)
{
// 获取符号名称列表的逻辑
string strNames = string.Empty;
if (group.Equals(CurrentFile))
{
// 当前文件时
DrawerGeo?.GetDrawerSymbolNames(ref strNames);
}
else
{
GeoSigmaXY.GetLibrarySymbolNames(group, ref strNames);
}
List<string> symbols = strNames.Split(';')
.Where(name => !string.IsNullOrEmpty(name))
.OrderBy(name => name)
.ToList();
return symbols;
}
/// <summary>
/// 构建同一组的符号
/// </summary>
/// <param name="group">符号组</param>
/// <param name="symbols"></param>
private void BuildSymbols(string group, List<string> symbols)
{
foreach (string symbol in symbols)
{
SymbolItemData item = new SymbolItemData()
{
Name = symbol,
Group = group,
};
AddSymbol(item);
}
}
private void BuildSymbols(List<SymbolItemData> symbols)
{
foreach (SymbolItemData item in symbols)
{
AddSymbol(item);
}
}
/// <summary>
/// 显示左侧选中的符号组
/// </summary>
private void ShowSelectedSymbolGroup()
{
TreeNode node = trvSymbol.SelectedNode;
OnSearchStatus = false;
string group = node.Tag?.ToString();
if (group == null)
{
return;
}
ClearSymbols();
List<string> symbolNames = GetGroupSymbolNames(group);
BuildSymbols(group, symbolNames);
if (lsvSymbol.Items.Count > 0)
{
lsvSymbol.Items[0].Selected = true;
}
else
{
// 如果该组没有任何符号,要清理最右侧的显示,不然会显示上次打开的内容
ClearymbolDetials();
}
string strGroupName = Path.GetFileNameWithoutExtension(group);
statusLableGroup.Text = $"所属: {strGroupName}";
}
private void CreateBitMap(string group, string symbolName, out Bitmap bmp, out IntPtr pXy)
{
bmp = new Bitmap(50, 50);
Graphics gBmp = Graphics.FromImage(bmp);
IntPtr pBmpDC = gBmp.GetHdc();
pXy = IntPtr.Zero;
if (group.Equals(CurrentFile))
{
DrawerGeo?.DrawerDrawSymbol(symbolName, pBmpDC, 50, 50, ref pXy);
}
else
{
GeoSigmaXY.LibaryDrawSymbol(group, symbolName, pBmpDC, 50, 50, ref pXy);
}
gBmp.ReleaseHdc();
}
private void CreateBitMap(string symbolName, out Bitmap bmp, out IntPtr pXy)
{
bmp = new Bitmap(50, 50);
Graphics gBmp = Graphics.FromImage(bmp);
IntPtr pBmpDC = gBmp.GetHdc();
pXy = IntPtr.Zero;
if (SelectedFile.Equals(CurrentFile))
{
DrawerGeo?.DrawerDrawSymbol(symbolName, pBmpDC, 50, 50, ref pXy);
}
else
{
GeoSigmaXY.LibaryDrawSymbol(SelectedFile, symbolName, pBmpDC, 50, 50, ref pXy);
}
gBmp.ReleaseHdc();
}
private void trvSymbol_AfterSelect(object sender, TreeViewEventArgs e)
{
//refreshHelper.SelectionChange();
ShowSelectedSymbolGroup();
}
/// <summary>
/// 关闭前
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FrmMarkMain_FormClosing(object sender, FormClosingEventArgs e)
{
if (!SelectedFile.Equals(CurrentFile) && mainView.IsDocumentModified())
{
IsDirty = true;
}
if (IsDirty)
{
DialogResult result = MessageBox.Show(
this,
"是否保存修改?",
"关闭文档",
MessageBoxButtons.YesNoCancel);
switch (result)
{
case DialogResult.Yes:
// 保存文件
MainView_SaveFile(new CancelEventArgs());
break;
case DialogResult.Cancel:
e.Cancel = true;
return;
case DialogResult.No:
break;
}
}
}
private void FrmMarkMain_FormClosed(object sender, FormClosedEventArgs e)
{
Application.Idle -= ApplicationIdle;
DrawerGeo?.ResetSymbol();
ClearSymbols();
}
private void MainView_SaveFile(CancelEventArgs e)
{
if (!SelectedFile.Equals(CurrentFile) && mainView.IsDocumentModified())
{
IsDirty = true;
}
if (!IsDirty)
{
e.Cancel = true;
return;
}
bool bSaved = GeoSigmaXY.LibarySaveAll();
if (bSaved)
{
mainView.SetDocumentModified(!bSaved);
// 重新激活左侧当前符号组,让它刷新缩略图
//TreeNode node = trvSymbol.SelectedNode;
//trvSymbol.SelectedNode = null;
//trvSymbol.SelectedNode = node;
updateCurrentSymbolIcon();
}
IsDirty = !bSaved;
if (e != null)
{
e.Cancel = true;
}
}
/// <summary>
/// 查找符号事件
/// </summary>
/// <param name="sender">查找按钮</param>
/// <param name="e">事件参数</param>
private void tsbtnFindSymbol_Click(object sender, EventArgs e)
{
string strSearchName = txtSearchName.Text.Trim();
if (string.IsNullOrEmpty(strSearchName))
{
return;
}
// 设置查询状态标识
OnSearchStatus = true;
ClearSymbols();
List<SymbolItemData> symbols = FindSymbol(strSearchName);
BuildSymbols(symbols);
}
private void txtSearchName_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
e.Handled = true;
SendKeys.Send("{TAB}");
tsbtnFindSymbol.PerformClick();
}
}
/// <summary>
/// 确定
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void tsbtnOK_Click(object sender, EventArgs e)
{
if (lsvSymbol.SelectedIndices.Count <= 0)
{
MessageBox.Show("没有选中任何符号!");
return;
}
ListViewItem itemLast = lsvSymbol.Items[lsvSymbol.SelectedIndices[0]];
SymbolItemData itemDataLast = itemLast.Tag as SymbolItemData;
string strName = itemDataLast.Name;
// 检查名称重复
ListViewItem lviFind = arrItemsCache.Find(p =>
{
return p.Text.Equals(strName,
StringComparison.CurrentCultureIgnoreCase);
});
if (lviFind != null)
{
IntPtr pxyNew = IntPtr.Zero;
DrawerGeo.DrawerCopySymbol(itemDataLast.PtrXY, strName, ref pxyNew);
}
SelectedSymbolName = strName;
DialogResult = DialogResult.OK;
Close();
}
/// <summary>
/// 取消
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void tsbtnCancel_Click(object sender, EventArgs e)
{
if (IsDirty)
{
DialogResult result = MessageBox.Show(this,
"符号已修改,是否放弃修改并退出符号管理界面?",
"退出",
MessageBoxButtons.YesNo);
if (result == DialogResult.No)
{
return;
}
}
DialogResult = DialogResult.Cancel;
Close();
}
/// <summary>
/// 修改符号名称
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void tsbtnEdit_Click(object sender, EventArgs e)
{
ListView.SelectedIndexCollection selItems = lsvSymbol.SelectedIndices;
if (selItems.Count > 0)
{
lsvSymbol.Items[selItems[0]].BeginEdit();
}
}
/// <summary>
/// 修改符号名称
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lsvSymbol_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
if (e.Label == null)
{
return;
}
string newName = e.Label.Trim();
if (string.IsNullOrEmpty(newName))
{
MessageBox.Show("此名称不能为空!");
e.CancelEdit = true;
return;
}
ListViewItem lvi = lsvSymbol.Items[e.Item];
ListViewItem lviFind = null;
if (arrItemsCache != null)
{
lviFind = arrItemsCache.FirstOrDefault(item =>
item.Text.Equals(newName, StringComparison.CurrentCultureIgnoreCase));
}
else
{
var ie = lsvSymbol.Items.GetEnumerator();
while (ie.MoveNext())
{
ListViewItem lviCur = (ListViewItem)ie.Current;
if (lviCur.Text.Equals(newName, StringComparison.CurrentCultureIgnoreCase))
{
lviFind = lviCur;
break;
}
}
}
if (lviFind != null)
{
MessageBox.Show("此名称已经存在!");
e.CancelEdit = true;
return;
}
lvi.Text = newName;
lvi.Name = newName;
IntPtr ptr = ((SymbolItemData)(lvi.Tag)).PtrXY;
if (!SelectedFile.Equals(CurrentFile))
{
IsDirty = GeoSigmaXY.SetDrawXyName(ptr, ((SymbolItemData)(lvi.Tag)).Group, newName);
((SymbolItemData)(lvi.Tag)).Name = newName;
IsDirty = true;
}
else
{
DrawerGeo.RenameSymble(((SymbolItemData)(lvi.Tag)).Name, newName);
((SymbolItemData)(lvi.Tag)).Name = newName;
}
}
/// <summary>
/// 显示符号预览图大图,最右侧那块儿
/// </summary>
/// <param name="itemData">标识数据</param>
private void ShowSymbolDetials(SymbolItemData itemData)
{
if (!SelectedFile.Equals(CurrentFile) && mainView.IsDocumentModified())
{
IsDirty = true;
}
mainView.Visible = true;
mainView.OpenXy(itemData.PtrXY);
mainView.SetBackColor(192, 192, 192);
mainView.SetSymbolView(true);
RectangleF rect = new RectangleF(-1, -1, 2, 2);
mainView.InitlizePaint(rect);
DrawerEnable(true);
}
/// <summary>
/// 清空符号预览图大图
/// </summary>
private void ClearymbolDetials()
{
if (mainView != null)
{
mainView.Visible = false;
}
}
/// <summary>
/// 选择符号
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void lsvSymbol_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (e.IsSelected == false || e.Item.Tag == null)
{
return;
}
SymbolItemData itemData = e.Item.Tag as SymbolItemData;
// 非选择模式
if (!ShowInSelectMode)
{
ShowSymbolDetials(itemData);
}
statusLableGroup.Text = $"所属: {Path.GetFileNameWithoutExtension(itemData.Group)}";
}
/// <summary>
/// updates the current symbol icon.
/// </summary>
private void updateCurrentSymbolIcon()
{
if (lsvSymbol.SelectedIndices != null && lsvSymbol.SelectedIndices.Count > 0)
{
ListView.SelectedIndexCollection indices = lsvSymbol.SelectedIndices;
int nIndex = indices[0];
ListViewItem item = arrItemsCache[nIndex];// lsvSymbol.Items[nIndex];
//lstSymbolImage.Images.Add(bmp);
//arrItemsCache.Add(item);
SymbolItemData itemData = item.Tag as SymbolItemData;
Bitmap bmp = lstSymbolImage.Images[nIndex] as Bitmap;
Graphics gBmp = Graphics.FromImage(bmp);
gBmp.Clear(Color.White);
IntPtr pBmpDC = gBmp.GetHdc();
IntPtr pXy = itemData.PtrXY;
GeoSigmaXY.XyDrawSymbol(pXy, pBmpDC, 50, 50);
gBmp.ReleaseHdc();
lstSymbolImage.Images[nIndex] = bmp;
lsvSymbol.Invalidate();
}
}
private void lsvSymbol_ItemCheck(object sender, ItemCheckEventArgs e)
{
CheckState status = e.NewValue;
}
private void lsvSymbol_ItemChecked(object sender, ItemCheckedEventArgs e)
{
bool bChecked = e.Item.Checked;
}
private string NewSymbolName()
{
for (int newSymbolIdx = 1; newSymbolIdx < int.MaxValue; newSymbolIdx++)
{
string strSymbolName = "新建符号" + newSymbolIdx;
if (!arrItemsCache.Any(p => p.Text.Equals(strSymbolName, StringComparison.CurrentCultureIgnoreCase)))
{
return strSymbolName;
}
}
return string.Empty;
}
/// <summary>
/// 添加符号
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void tsbtnListAdd_Click(object sender, EventArgs e)
{
string strSymbolName = NewSymbolName();
IntPtr pXy = IntPtr.Zero;
Bitmap bmp = new Bitmap(50, 50);
Graphics gBmp = Graphics.FromImage(bmp);
gBmp.Clear(Color.White);
IntPtr pBmpDC = gBmp.GetHdc();
// 当前文件时
if (SelectedFile.Equals(CurrentFile))
{
DrawerGeo.CreateDrawerSymbol(strSymbolName, ref pXy);
DrawerGeo.DrawerDrawSymbol(strSymbolName, pBmpDC, 50, 50, ref pXy);
}
else
{
GeoSigmaXY.CreateLibrarySymbol(SelectedFile, strSymbolName, ref pXy);
GeoSigmaXY.LibaryDrawSymbol(SelectedFile, strSymbolName, pBmpDC, 50, 50, ref pXy);
}
gBmp.ReleaseHdc();
SymbolItemData itemData = new SymbolItemData()
{
Group = SelectedFile,
Name = strSymbolName,
PtrXY = pXy,
};
ListViewItem item = new ListViewItem(strSymbolName);
item.Name = strSymbolName;
item.ImageIndex = lstSymbolImage.Images.Count;
item.Tag = itemData;
arrItemsCache.Add(item);
lstSymbolImage.Images.Add(bmp);
lsvSymbol.VirtualListSize = arrItemsCache.Count;
SelectSymbol(arrItemsCache.Count - 1);
IsDirty = true;
}
private void SelectSymbol(int nIndex)
{
lsvSymbol.Focus();
if (nIndex >= lsvSymbol.Items.Count)
{
return;
}
lsvSymbol.Items[nIndex].Selected = true;
if (lsvSymbol.SelectedIndices != null && lsvSymbol.SelectedIndices.Count > 0)
{
ListView.SelectedIndexCollection indices = lsvSymbol.SelectedIndices;
lsvSymbol.Items[indices[0]].Selected = false;
}
lsvSymbol.Items[nIndex].Selected = true;
lsvSymbol.EnsureVisible(nIndex);
}
/// <summary>
/// 移除符号
/// </summary>
/// <param name="index">符号下标</param>
private void RemoveSymbol(int index)
{
string strName = lsvSymbol.Items[index].Text;
SymbolItemData itemData = lsvSymbol.Items[index].Tag as SymbolItemData;
IntPtr pXy = itemData.PtrXY;
ListViewItem cachedItem = arrItemsCache.FirstOrDefault(item =>
{
SymbolItemData itemDataFind = (SymbolItemData)item.Tag;
return itemDataFind.PtrXY == pXy;
});
if (cachedItem != null)
{
arrItemsCache.Remove(cachedItem);
}
lsvSymbol.VirtualListSize = arrItemsCache.Count;
if (pXy == IntPtr.Zero)
{
return;
}
if (SelectedFile.Equals(CurrentFile))
{
// 当前文件时
DrawerGeo.RemoveDrawerSymbol(pXy);
}
else
{
IsDirty = GeoSigmaXY.RemoveLibrarySymbol(SelectedFile, pXy);
}
}
/// <summary>
/// 选中下一个符号
/// </summary>
/// <param name="index">被删除的 index 下标</param>
private void SelectNextSymbol(int index)
{
if (index == arrItemsCache.Count)
{
index = arrItemsCache.Count - 1;
}
if (index >= 0 && index < arrItemsCache.Count)
{
lsvSymbol.Items[index].Selected = true;
}
else
{
// 清空画布
DrawerEnable(false);
mainView.ClearGeo();
}
}
/// <summary>
/// 删除符号
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void tsbtnListRemove_Click(object sender, EventArgs e)
{
ListView.SelectedIndexCollection selItems = lsvSymbol.SelectedIndices;
if (arrItemsCache == null || selItems.Count == 0)
{
return;
}
int index = selItems[0];
RemoveSymbol(index);
SelectNextSymbol(index);
}
private void DrawerEnable(bool enable)
{
mainView.ToolDefault();
mainView.ToolstripElements.Enabled = enable;
mainView.ToolstripView.Enabled = enable;
//mainView.ToolAntiAlias(false);
}
/// <summary>
/// 符号拷贝
/// </summary>
/// <param name="sender">拷贝按钮</param>
/// <param name="e">事件参数</param>
private void tsbtnSymbolCopy_Click(object sender, EventArgs e)
{
List<string> lstXyData = new List<string>();
foreach (int indice in lsvSymbol.SelectedIndices)
{
var item = lsvSymbol.Items[indice];
SymbolItemData itemData = (SymbolItemData)item.Tag;
string strXyData = GeoSigmaXY.WriteXy2DFD(itemData.PtrXY);
lstXyData.Add(strXyData);
}
if (lstXyData.Count > 0)
{
Clipboard.Clear();
Clipboard.SetData(ClipboardFormatSymbol, lstXyData);
}
}
/// <summary>
/// 粘贴事件
/// </summary>
/// <param name="sender">粘贴按钮</param>
/// <param name="e">事件参数</param>
private void tsbtnSymbolPaste_Click(object sender, EventArgs e)
{
List<string> lstXyData = (List<string>)Clipboard.GetData(ClipboardFormatSymbol);
if (lstXyData == null)
{
return;
}
foreach (string xyData in lstXyData)
{
IntPtr pXy = GeoSigmaXY.CreateXyFromDFD(xyData);
string strName = GeoSigmaXY.GetDrawXyName(pXy);
// 检查名称重复
int nNameAppend = 0;
string strNameSource = strName;
while (true)
{
if (nNameAppend == 0)
{
strName = strNameSource;
}
else
{
strName = $"{strNameSource}{nNameAppend}";
}
ListViewItem lviFind = arrItemsCache.Find(p =>
{
return p.Text.Equals(strName,
StringComparison.CurrentCultureIgnoreCase);
});
if (lviFind != null)
{
nNameAppend++;
continue;
}
break;
}
Bitmap bmp = new Bitmap(50, 50);
Graphics gBmp = Graphics.FromImage(bmp);
IntPtr pBmpDC = gBmp.GetHdc();
IntPtr pxyNew = IntPtr.Zero;
// 当前文件时
if (SelectedFile.Equals(CurrentFile))
{
DrawerGeo.DrawerCopySymbol(pXy, strName, ref pxyNew);
DrawerGeo.DrawerDrawSymbol(strName, pBmpDC, 50, 50, ref pxyNew);
}
else
{
GeoSigmaXY.LibraryCopySymbol(SelectedFile, pXy, strName, ref pxyNew);
GeoSigmaXY.LibaryDrawSymbol(SelectedFile, strName, pBmpDC, 50, 50, ref pxyNew);
IsDirty = true;
}
gBmp.ReleaseHdc();
lstSymbolImage.Images.Add(bmp);
SymbolItemData itemData = new SymbolItemData();
itemData.Name = strName;
itemData.PtrXY = pxyNew;
itemData.Group = SelectedFile;
ListViewItem item = new ListViewItem(strName);
item.Name = strName;
item.ImageIndex = lstSymbolImage.Images.Count - 1;
item.Tag = itemData;
arrItemsCache.Add(item);
}
lsvSymbol.VirtualListSize = arrItemsCache.Count;
SelectSymbol(arrItemsCache.Count - 1);
}
private void ctmSymbols_Opening(object sender, CancelEventArgs e)
{
//string strMsg = sender.ToString();
}
private string NewGroupName()
{
List<string> fileNames = Directory.EnumerateFiles(LibPath)
.Select(path => Path.GetFileName(path))
.ToList();
for (int newIndex = 1; newIndex < int.MaxValue; newIndex++)
{
string newFileName = $"自定义符号{newIndex}.kev";
if (!fileNames.Any(s => s.Equals(newFileName, StringComparison.OrdinalIgnoreCase)))
{
return newFileName;
}
}
return string.Empty;
}
/// <summary>
/// 新建分组
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void tsbtnNewGroup_Click(object sender, EventArgs e)
{
string newFilename = NewGroupName();
string strNewFile = Path.Combine(LibPath, newFilename);
File.Create(strNewFile).Close();
AddNewGroup(strNewFile);
}
/// <summary>
/// 添加新符号库
/// </summary>
/// <param name="strNewFile">符号文件</param>
private void AddNewGroup(string strNewFile)
{
GeoSigmaXY.LibraryAddNewGroup(strNewFile);
TreeNode tnGroup = new TreeNode();
tnGroup.Text = Path.GetFileNameWithoutExtension(strNewFile);
tnGroup.ImageIndex = 0;
tnGroup.Tag = strNewFile;
var root = trvSymbol.Nodes[0];
root.Nodes.Add(tnGroup);
trvSymbol.SelectedNode = tnGroup;
}
/// <summary>
/// 删除分组
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void tsbtnDeleteFile_Click(object sender, EventArgs e)
{
var root = trvSymbol.Nodes[0];
List<TreeNode> lstCheckedNodes = root.Nodes.Cast<TreeNode>().Where(node => node.Checked).ToList();
if (lstCheckedNodes.Count == 0)
{
return;
}
if (MessageBox.Show("是否删除选中符号库?") != DialogResult.OK)
{
return;
}
trvSymbol.BeginUpdate();
TreeNode tnNext = lstCheckedNodes[lstCheckedNodes.Count - 1].NextNode;
for (int i = 0; i < lstCheckedNodes.Count; i++)
{
string strFileName = lstCheckedNodes[i].Tag as string;
RemoveGroup(strFileName);
lstCheckedNodes[i].Remove();
}
trvSymbol.EndUpdate();
ClearSymbols();
if (tnNext == null && root.Nodes.Count > 0)
{
tnNext = root.Nodes[root.Nodes.Count - 1];
}
if (tnNext != null)
{
trvSymbol.SelectedNode = tnNext;
}
}
/// <summary>
/// 从文件导入符号
/// </summary>
/// <param name="sender">事件按钮</param>
/// <param name="e">事件参数</param>
private void tsbtnImportFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.RestoreDirectory = true;
ofd.Filter = "*.kev|*.kev|*.pcg|*.pcg|*.*|*.*";
if (ofd.ShowDialog() != DialogResult.OK)
{
return;
}
if (!Directory.Exists(LibPath))
{
Directory.CreateDirectory(LibPath);
}
string strFile = ofd.FileName;
string strFileNew = string.Empty;
// string strDir = Path.GetDirectoryName(strFile);
string strOldName = Path.GetFileNameWithoutExtension(strFile);
string[] straOldFiles = Directory.GetFiles(LibPath);
string strFind = straOldFiles.FirstOrDefault(it =>
{
string strName = Path.GetFileNameWithoutExtension(it);
return strName.Equals(strOldName);
});
if (strFind != null)
{
strOldName += "1";
strFileNew = Path.Combine(LibPath, strOldName + Path.GetExtension(strFile));
}
else
{
strFileNew = Path.Combine(LibPath, Path.GetFileName(strFile));
}
Cursor.Current = Cursors.WaitCursor;
trvSymbol.BeginUpdate();
FileInfo fi = new FileInfo(strFile);
fi.CopyTo(strFileNew);
AddNewGroup(strFileNew);
Cursor.Current = Cursors.Default;
trvSymbol.EndUpdate();
}
/// <summary>
/// 符号导出到文件
/// </summary>
/// <param name="sender">符号导出事件</param>
/// <param name="e">事件参数</param>
private void tsbtnExportFile_Click(object sender, EventArgs e)
{
FolderBrowserDialog fldDlg = new FolderBrowserDialog();
fldDlg.Description = @"将选中节点的符号导出到指定文件夹中。
文件名为符号的类别名。";
if (fldDlg.ShowDialog() != DialogResult.OK)
{
return;
}
string strDir = fldDlg.SelectedPath;
if (!Directory.Exists(strDir))
{
Directory.CreateDirectory(strDir);
}
// 保存编辑中的图形
MainView_SaveFile(null);
var root = trvSymbol.Nodes[0];
List<TreeNode> lstCheckedNodes = new List<TreeNode>();
foreach (TreeNode node in root.Nodes)
{
if (!node.Checked)
{
continue;
}
string strFileSource = node.Tag as string;
string strNameDes = Path.GetFileName(strFileSource);
string strFileDes = Path.Combine(strDir, strNameDes);
bool bOverwrite = false;
if (File.Exists(strFileDes))
{
DialogResult result = MessageBox.Show(this, $@"存在同名的文件“{strNameDes}”,覆盖还是跳过?
选择“是”,进行覆盖;
选择“否”,则跳过;
选择“取消”,则终止导入。",
"导出",
MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (result == DialogResult.Cancel)
{
break;
}
else if (result == DialogResult.Yes)
{
bOverwrite = true;
}
else
{
bOverwrite = false;
continue;
}
}
FileInfo fi = new FileInfo(strFileSource);
try
{
fi.CopyTo(strFileDes, bOverwrite);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
MessageBox.Show("导出成功!");
}
/// <summary>
/// 删除选中文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void tmiDeleteFile_Click(object sender, EventArgs e)
{
if (trvSymbol.SelectedNode == null)
{
return;
}
DialogResult result = MessageBox.Show($"要删除选中“{trvSymbol.SelectedNode.Text}”吗?\r\n删除后不可恢复"
, "删除", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result != DialogResult.Yes)
{
return;
}
string strFileName = trvSymbol.SelectedNode.Tag as string;
GeoSigmaXY.LibraryRemoveGroup(strFileName);
trvSymbol.SelectedNode.Remove();
try
{
File.Delete(strFileName);
}
catch
{
}
}
/// <summary>
/// 重命名选中文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void tmiRename_Click(object sender, EventArgs e)
{
trvSymbol.SelectedNode?.BeginEdit();
}
// 重命名符号组
private void trvSymbol_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
{
if (string.IsNullOrEmpty(e.Label))
{
return;
}
string strFileName = trvSymbol.SelectedNode.Tag as string;
string strNewFile = e.Label + Path.GetExtension(strFileName);
string strNewFileFull = Path.Combine(Path.GetDirectoryName(strFileName), strNewFile);
if (GeoSigmaXY.LibraryRenameGroup(strFileName, strNewFileFull) != true)
{
e.CancelEdit = true; // 取消节点的编辑操作
MessageBox.Show("重命名失败!");
return;
}
Computer MyComputer = new Computer();
MyComputer.FileSystem.RenameFile(strFileName, strNewFile);
trvSymbol.SelectedNode.Tag = strNewFileFull;
}
/// <summary>
/// 鼠标点击,右键菜单
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void trvSymbol_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
Point point = new Point(e.X, e.Y);
TreeNode treeNode = trvSymbol.GetNodeAt(point);
if (treeNode == trvSymbol.Nodes[0])
{
return;
}
trvSymbol.SelectedNode = treeNode;
if (e.Button == MouseButtons.Right)
{
if (treeNode.Text == CurrentFile)
{
EnableRenameDeleteItems(false);
}
else
{
EnableRenameDeleteItems(true);
}
//显示上下文菜单
ctmTree.Show(trvSymbol.PointToScreen(point));
}
}
private void EnableRenameDeleteItems(bool enabled)
{
ctmTree.Items.OfType<ToolStripMenuItem>()
.Where(x => x.Text == "重命名" || x.Text == "删除")
.ToList()
.ForEach(x => x.Enabled = enabled);
}
private void tmiMerge_Click(object sender, EventArgs e)
{
if (trvSymbol.SelectedNode == null || string.IsNullOrWhiteSpace(SelectedFile))
{
return;
}
// 选择文件
var dialog = new OpenFileDialog
{
Filter = "*.kev;*.dfd;*.pcg|*kev;*.dfd;*.pcg"
};
if (dialog.ShowDialog(this) != DialogResult.OK)
{
return;
}
// 合并符号
MergeSymbol(dialog.FileName);
// 刷新
ShowSelectedSymbolGroup();
}
private void MergeSymbol(string mergeFile)
{
if (SelectedFile.Equals(CurrentFile))
{
MergeSymbol(DrawerGeo.GetDrawerXy(), mergeFile);
}
else
{
MergeSymbol(SelectedFile, mergeFile);
}
}
private void MergeSymbol(string sourceFile, string mergeFile)
{
var drawerData = new DrawerData();
if (drawerData.OpenFile(SelectedFile))
{
drawerData.MergeSymbol(mergeFile);
drawerData.SaveAs(sourceFile);
drawerData.Dispose();
// FIXME: 符号库里面有缓存,这里需要重新加载一下,
// 也许正确的方法应该是符号库去追踪文件变化,然后自动重新加载
GeoSigmaLib.LibraryReloadGroup(sourceFile);
}
}
private void MergeSymbol(IntPtr sourceXy, string mergeFile)
{
var drawerData = new DrawerData();
drawerData.OpenXy(sourceXy);
drawerData.MergeSymbol(mergeFile);
drawerData.Dispose();
}
}
public class SymbolItemData
{
public string Group { get; set; }
public string Name { get; set; }
public IntPtr PtrXY { get; set; }
}
}