371 lines
13 KiB
C#
371 lines
13 KiB
C#
using Newtonsoft.Json;
|
|
using StandardScene.InterLock; // 数据类型采用 TrafficInterlockMission 中的 TrafficArea
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
|
|
namespace LoopViewerApp
|
|
{
|
|
public partial class TrafficInterlockViewer : Form
|
|
{
|
|
/// <summary>-1 表示新增模式;>=0 表示正在编辑对应索引</summary>
|
|
private int _editingIndex = -1;
|
|
|
|
/// <summary>选中行变化时是否允许加载到编辑区(避免在保存/取消时重复刷新)</summary>
|
|
private bool _allowLoadFromSelection = true;
|
|
|
|
public TrafficInterlockViewer()
|
|
{
|
|
InitializeComponent();
|
|
|
|
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
|
|
return;
|
|
|
|
try
|
|
{
|
|
RenderListView();
|
|
ClearPanelInputs();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"TrafficInterlockViewer init error: {ex}");
|
|
}
|
|
}
|
|
|
|
#region 表格绘制(只读展示)
|
|
|
|
private void lstTasks_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
// 与 LoopViewer 一致:深蓝表头 + 白色加粗字体
|
|
using (var backBrush = new SolidBrush(Color.FromArgb(63, 81, 181)))
|
|
using (var textBrush = new SolidBrush(Color.White))
|
|
using (var font = new Font("微软雅黑", 9, FontStyle.Bold))
|
|
{
|
|
e.Graphics.FillRectangle(backBrush, e.Bounds);
|
|
var sf = new StringFormat { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Near };
|
|
var rect = e.Bounds;
|
|
rect.Inflate(-8, 0);
|
|
e.Graphics.DrawString(e.Header.Text, font, textBrush, rect, sf);
|
|
using (var pen = new Pen(Color.FromArgb(200, 200, 200)))
|
|
e.Graphics.DrawLine(pen, e.Bounds.Left, e.Bounds.Bottom - 1, e.Bounds.Right, e.Bounds.Bottom - 1);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
e.DrawBackground();
|
|
e.DrawText();
|
|
}
|
|
}
|
|
|
|
private void lstTasks_DrawItem(object sender, DrawListViewItemEventArgs e)
|
|
{
|
|
// 由 DrawSubItem 统一绘制
|
|
}
|
|
|
|
private void lstTasks_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
bool selected = e.Item.Selected;
|
|
Rectangle bounds = e.Bounds;
|
|
// 与 LoopViewer 一致:选中行蓝色强调,交替行背景,深灰文字
|
|
Color selectedBack = Color.FromArgb(0, 120, 215);
|
|
Color selectedFore = Color.White;
|
|
Color evenBack = Color.White;
|
|
Color oddBack = Color.FromArgb(250, 251, 253);
|
|
Color normalFore = Color.FromArgb(33, 33, 33);
|
|
|
|
if (selected)
|
|
{
|
|
using (var selBrush = new SolidBrush(selectedBack))
|
|
e.Graphics.FillRectangle(selBrush, bounds);
|
|
}
|
|
else
|
|
{
|
|
using (var back = new SolidBrush(e.ItemIndex % 2 == 0 ? evenBack : oddBack))
|
|
e.Graphics.FillRectangle(back, bounds);
|
|
}
|
|
|
|
string text = e.SubItem?.Text ?? string.Empty;
|
|
Color fore = selected ? selectedFore : normalFore;
|
|
var textRect = bounds;
|
|
textRect.Inflate(-6, 0);
|
|
using (var font = new Font("微软雅黑", 9))
|
|
TextRenderer.DrawText(e.Graphics, text, font, textRect, fore, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
|
|
}
|
|
catch
|
|
{
|
|
e.DrawBackground();
|
|
e.DrawText();
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 列表渲染与保存
|
|
|
|
private void RenderListView()
|
|
{
|
|
try
|
|
{
|
|
if (lstTasks == null) return;
|
|
_allowLoadFromSelection = false;
|
|
lstTasks.BeginUpdate();
|
|
lstTasks.Items.Clear();
|
|
foreach (var a in TrafficInterlockMission.TrafficAreaList)
|
|
{
|
|
var stationStr = a.SiteList != null && a.SiteList.Count > 0 ? string.Join(", ", a.SiteList) : "";
|
|
|
|
var lvi = new ListViewItem(new[]
|
|
{
|
|
a.AreaName ?? "",
|
|
stationStr,
|
|
a.ControllerName ?? "",
|
|
a.IsOccupy ? "是" : "否",
|
|
a.IsEnable ? "是" : "否"
|
|
});
|
|
|
|
lstTasks.Items.Add(lvi);
|
|
}
|
|
lstTasks.EndUpdate();
|
|
_allowLoadFromSelection = true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_allowLoadFromSelection = true;
|
|
System.Diagnostics.Debug.WriteLine($"RenderListView failed: {ex}");
|
|
}
|
|
}
|
|
|
|
private void SaveToConfig()
|
|
{
|
|
try
|
|
{
|
|
string configPath = Path.Combine(Application.StartupPath, "Config", "traffic.json");
|
|
string dir = Path.GetDirectoryName(configPath);
|
|
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
|
|
Directory.CreateDirectory(dir);
|
|
File.WriteAllText(configPath, JsonConvert.SerializeObject(TrafficInterlockMission.TrafficAreaList, Formatting.Indented));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show("保存失败:" + ex.Message);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 点击表格行 → 编辑区展示该行数据
|
|
|
|
private void lstTasks_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (!_allowLoadFromSelection || lstTasks == null || lstTasks.SelectedIndices.Count == 0) return;
|
|
int idx = lstTasks.SelectedIndices[0];
|
|
if (idx < 0 || idx >= TrafficInterlockMission.TrafficAreaList.Count) return;
|
|
_editingIndex = idx;
|
|
LoadAreaToPanel(TrafficInterlockMission.TrafficAreaList[idx]);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 编辑区:加载 / 清空
|
|
|
|
private void LoadAreaToPanel(TrafficArea a)
|
|
{
|
|
if (a == null) return;
|
|
try
|
|
{
|
|
if (lblEditingHint != null)
|
|
lblEditingHint.Text = $"编辑:{a.AreaName}";
|
|
if (txtAreaName != null)
|
|
txtAreaName.Text = a.AreaName ?? "";
|
|
if (txtStationIds != null)
|
|
txtStationIds.Text = a.SiteList != null && a.SiteList.Count > 0
|
|
? string.Join(", ", a.SiteList)
|
|
: "";
|
|
if (txtControlRight != null)
|
|
txtControlRight.Text = a.ControllerName ?? "";
|
|
if (chkIsOccupied != null)
|
|
chkIsOccupied.Checked = a.IsOccupy;
|
|
if (chkIsEnabled != null)
|
|
chkIsEnabled.Checked = a.IsEnable;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"LoadAreaToPanel error: {ex}");
|
|
}
|
|
}
|
|
|
|
private void ClearPanelInputs()
|
|
{
|
|
try
|
|
{
|
|
_editingIndex = -1;
|
|
if (lblEditingHint != null)
|
|
lblEditingHint.Text = "新增区域";
|
|
if (txtAreaName != null)
|
|
txtAreaName.Text = "";
|
|
if (txtStationIds != null)
|
|
txtStationIds.Text = "";
|
|
if (txtControlRight != null)
|
|
txtControlRight.Text = "";
|
|
if (chkIsOccupied != null)
|
|
chkIsOccupied.Checked = false;
|
|
if (chkIsEnabled != null)
|
|
chkIsEnabled.Checked = true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"ClearPanelInputs error: {ex}");
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 解析站点集合字符串 "1,2,3" -> List<int>
|
|
|
|
private static List<int> ParseStationIds(string text)
|
|
{
|
|
var list = new List<int>();
|
|
if (string.IsNullOrWhiteSpace(text)) return list;
|
|
foreach (var part in text.Split(new[] { ',', ';', ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries))
|
|
{
|
|
if (int.TryParse(part.Trim(), out int id))
|
|
list.Add(id);
|
|
}
|
|
return list;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 按钮:保存 / 刷新 / 新增 / 删除
|
|
|
|
private void btnSave_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
string areaName = txtAreaName?.Text?.Trim() ?? "";
|
|
if (string.IsNullOrEmpty(areaName))
|
|
{
|
|
MessageBox.Show("请输入区域名称。");
|
|
return;
|
|
}
|
|
|
|
var stationIds = ParseStationIds(txtStationIds?.Text ?? "");
|
|
string controlRight = txtControlRight?.Text?.Trim() ?? "";
|
|
bool isOccupied = chkIsOccupied?.Checked ?? false;
|
|
bool isEnabled = chkIsEnabled?.Checked ?? true;
|
|
|
|
if (_editingIndex >= 0 && _editingIndex < TrafficInterlockMission.TrafficAreaList.Count)
|
|
{
|
|
lock (TrafficInterlockMission.TrafficAreaList)
|
|
{
|
|
var existing = TrafficInterlockMission.TrafficAreaList[_editingIndex];
|
|
existing.AreaName = areaName;
|
|
existing.SiteList = stationIds;
|
|
existing.ControllerName = controlRight;
|
|
existing.IsOccupy = isOccupied;
|
|
existing.IsEnable = isEnabled;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lock (TrafficInterlockMission.TrafficAreaList)
|
|
{
|
|
TrafficInterlockMission.TrafficAreaList.Add(new TrafficArea
|
|
{
|
|
AreaName = areaName,
|
|
SiteList = stationIds,
|
|
ControllerName = controlRight,
|
|
IsOccupy = isOccupied,
|
|
IsEnable = isEnabled
|
|
});
|
|
}
|
|
}
|
|
|
|
SaveToConfig();
|
|
RenderListView();
|
|
ClearPanelInputs();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"btnSave_Click error: {ex}");
|
|
MessageBox.Show("操作失败:" + ex.Message);
|
|
}
|
|
}
|
|
|
|
private void btnRefresh_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
RenderListView();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"btnRefresh_Click error: {ex}");
|
|
}
|
|
}
|
|
|
|
private void btnNew_Click(object sender, EventArgs e)
|
|
{
|
|
if (lstTasks != null)
|
|
lstTasks.SelectedIndices.Clear();
|
|
ClearPanelInputs();
|
|
// 进入新增模式:填写下方编辑区后点击“保存”即可新增一条数据
|
|
}
|
|
|
|
private void btnDelete_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
if (lstTasks == null || lstTasks.SelectedIndices.Count == 0)
|
|
{
|
|
MessageBox.Show("请先在上方列表中选择要删除的区域。");
|
|
return;
|
|
}
|
|
|
|
var dialogResult = MessageBox.Show(
|
|
"确定要删除选中的区域吗?",
|
|
"确认删除",
|
|
MessageBoxButtons.YesNo,
|
|
MessageBoxIcon.Warning);
|
|
|
|
if (dialogResult != DialogResult.Yes)
|
|
return;
|
|
|
|
var indices = lstTasks.SelectedIndices.Cast<int>()
|
|
.OrderByDescending(i => i)
|
|
.ToList();
|
|
|
|
lock (TrafficInterlockMission.TrafficAreaList)
|
|
{
|
|
foreach (var idx in indices)
|
|
{
|
|
if (idx >= 0 && idx < TrafficInterlockMission.TrafficAreaList.Count)
|
|
{
|
|
TrafficInterlockMission.TrafficAreaList.RemoveAt(idx);
|
|
}
|
|
}
|
|
}
|
|
|
|
SaveToConfig();
|
|
RenderListView();
|
|
ClearPanelInputs();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"btnDelete_Click error: {ex}");
|
|
MessageBox.Show("删除失败:" + ex.Message);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|