tbf/TBF/Rig/BridgeComponents/GciBridge/UI/Grid/MeterGridManager.cs

481 lines
15 KiB
C#

using Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using PublicModels = GenesisCordonelInterface.API.PublicModels;
namespace TBF.Rig.BridgeComponents.GciBridge.UI.Grid
{
public class MeterGridManager
{
private readonly DataGridView grid;
public MeterGridManager(DataGridView grid)
{
this.grid = grid ?? throw new ArgumentNullException(nameof(grid));
EnableDoubleBuffering(grid);
}
public void Init(List<string> comPorts)
{
grid.SuspendLayout();
try
{
grid.AutoGenerateColumns = false;
grid.Columns.Clear();
grid.AllowUserToAddRows = false;
grid.AllowUserToDeleteRows = false;
grid.RowHeadersVisible = true;
CreateColumns(comPorts);
ConfigureReadOnlyColumns();
ConfigureSelection();
}
finally
{
grid.ResumeLayout();
}
grid.Focus();
grid.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText;
}
private void CreateColumns(List<string> comPorts)
{
var configs = MeterGridConfigProvider
.GetDefault()
.OrderBy(x => x.DisplayIndex);
foreach (var config in configs)
{
DataGridViewColumn column;
switch (config.ColumnType)
{
case MeterGridConfigProvider.MeterGridColumnType.CheckBox:
column = new DataGridViewCheckBoxColumn();
break;
default:
column = new DataGridViewTextBoxColumn();
break;
}
column.Name = config.Name;
column.HeaderText = config.HeaderText;
column.Width = config.Width;
column.ReadOnly = config.ReadOnly;
column.DisplayIndex = config.DisplayIndex;
grid.Columns.Add(column);
}
grid.Columns.Add(CreateComPortColumn("RequestPort", "RequestPort", comPorts));
grid.Columns.Add(CreateRequestPortTypeColumn());
grid.Columns.Add(CreateComPortColumn("StreamingPort", "StreamingPort", comPorts));
grid.Columns.Add(CreateButtonColumn("DetectRequest", "DetectRequest", "..."));
grid.Columns.Add(CreateButtonColumn("DetectStreaming", "DetectStreaming", "..."));
}
private void ConfigureReadOnlyColumns()
{
foreach (DataGridViewColumn col in grid.Columns)
{
col.ReadOnly =
col.Name != "Selected" &&
col.Name != "RequestPort" &&
col.Name != "RequestPortType" &&
col.Name != "StreamingPort" &&
col.Name != "DetectRequest" &&
col.Name != "DetectStreaming";
}
}
private void ConfigureSelection()
{
grid.MultiSelect = true;
grid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
grid.CellContentClick -= Grid_CellContentClick;
grid.CellContentClick += Grid_CellContentClick;
grid.CurrentCellDirtyStateChanged -= Grid_CurrentCellDirtyStateChanged;
grid.CurrentCellDirtyStateChanged += Grid_CurrentCellDirtyStateChanged;
}
public void UpdateComPortItems(List<string> comPorts)
{
UpdateComPortColumnItems("RequestPort", comPorts);
UpdateComPortColumnItems("StreamingPort", comPorts);
}
public void Update(List<PublicModels.MeterBatchDebugStatus> meters)
{
grid.SuspendLayout();
try
{
foreach (var meter in meters)
{
var row = FindOrCreateRow(meter.Slot);
SetCell(row, "Slot", meter.Slot);
SetCell(row, "Selected", meter.Selected);
SetCell(row, "PcbId", meter.PcbId);
SetCell(row, "IsConnected", meter.IsConnected);
SetCell(row, "IsLoggedOn", meter.IsLoggedOn);
SetCell(row, "RequestPort", meter.RequestPort);
SetCell(row, "RequestPortType", NormalizeRequestPortType(meter.RequestPortType));
SetCell(row, "StreamingPort", meter.StreamingPort);
SetCell(row, "FwVersion", meter.FwVersion);
SetCell(row, "InterfaceVersion", meter.InterfaceVersion);
}
}
finally
{
grid.ResumeLayout();
}
}
public void UpdateSlots(List<PublicModels.GciSlotInfo> slots)
{
grid.SuspendLayout();
try
{
foreach (var slot in slots)
{
var row = FindOrCreateRow(slot.SlotId);
SetCell(row, "Slot", slot.SlotId);
SetCell(row, "PcbId", slot.PcbId);
SetCell(row, "RequestPort", slot.RequestPort == null ? "" : slot.RequestPort.PortName);
SetCell(row, "RequestPortType", MapRequestPortTypeBack(slot.RequestPort == null ? null : slot.RequestPort.Type));
SetCell(row, "StreamingPort", slot.StreamingPort == null ? "" : slot.StreamingPort.PortName);
SetCell(row, "IsConnected", false);
SetCell(row, "IsLoggedOn", false);
SetCell(row, "FwVersion", "");
SetCell(row, "InterfaceVersion", "");
}
}
finally
{
grid.ResumeLayout();
}
}
public void AddEmptySlotRow()
{
AddSlotRow(GetNextSlotId());
}
public void AddSlotRow()
{
AddSlotRow(GetNextSlotId());
}
public void AddSlotRow(int slotId)
{
if (ContainsSlot(slotId))
throw new Exception($"Slot {slotId} already exists.");
int idx = grid.Rows.Add();
var row = grid.Rows[idx];
SetCell(row, "Slot", slotId);
SetCell(row, "Selected", false);
SetCell(row, "RequestPort", "");
SetCell(row, "RequestPortType", "IRDA");
SetCell(row, "StreamingPort", "");
SetCell(row, "PcbId", "");
SetCell(row, "IsConnected", false);
SetCell(row, "IsLoggedOn", false);
SetCell(row, "FwVersion", "");
SetCell(row, "InterfaceVersion", "");
}
public List<PublicModels.MeterBatchDebugStatus> GetGridData()
{
var list = new List<PublicModels.MeterBatchDebugStatus>();
foreach (DataGridViewRow row in grid.Rows)
{
if (row.IsNewRow)
continue;
if (row.Cells["Slot"].Value == null)
continue;
list.Add(new PublicModels.MeterBatchDebugStatus
{
Slot = Convert.ToInt32(row.Cells["Slot"].Value),
Selected = GetBool(row, "Selected"),
PcbId = GetString(row, "PcbId"),
IsConnected = GetBool(row, "IsConnected"),
IsLoggedOn = GetBool(row, "IsLoggedOn"),
RequestPort = GetString(row, "RequestPort"),
RequestPortType = NormalizeRequestPortType(GetString(row, "RequestPortType")),
StreamingPort = GetString(row, "StreamingPort"),
FwVersion = GetString(row, "FwVersion"),
InterfaceVersion = GetString(row, "InterfaceVersion")
});
}
return list;
}
public List<PublicModels.MeterBatchDebugStatus> GetSelectedGridData()
{
return GetGridData()
.Where(x => x.Selected)
.ToList();
}
public int GetSlotFromRow(int rowIndex)
{
if (rowIndex < 0)
throw new ArgumentOutOfRangeException(nameof(rowIndex));
return Convert.ToInt32(grid.Rows[rowIndex].Cells["Slot"].Value);
}
public string GetColumnName(int columnIndex)
{
return grid.Columns[columnIndex].Name;
}
public void ClearSlots()
{
grid.Rows.Clear();
}
public int GetNextSlotId()
{
var existingSlots = grid.Rows
.Cast<DataGridViewRow>()
.Where(r => !r.IsNewRow)
.Where(r => r.Cells["Slot"].Value != null)
.Select(r => Convert.ToInt32(r.Cells["Slot"].Value))
.ToList();
if (existingSlots.Count == 0)
return 1;
return existingSlots.Max() + 1;
}
private bool ContainsSlot(int slotId)
{
return grid.Rows
.Cast<DataGridViewRow>()
.Any(r =>
!r.IsNewRow &&
r.Cells["Slot"].Value != null &&
Convert.ToInt32(r.Cells["Slot"].Value) == slotId);
}
private DataGridViewRow FindOrCreateRow(int slot)
{
foreach (DataGridViewRow row in grid.Rows)
{
if (!row.IsNewRow &&
row.Cells["Slot"].Value != null &&
Convert.ToInt32(row.Cells["Slot"].Value) == slot)
{
return row;
}
}
int idx = grid.Rows.Add();
var newRow = grid.Rows[idx];
newRow.Cells["Slot"].Value = slot;
return newRow;
}
private void SetCell(DataGridViewRow row, string colName, object value)
{
if (!grid.Columns.Contains(colName))
return;
if (value == null)
value = "";
if (colName == "RequestPortType")
value = NormalizeRequestPortType(Convert.ToString(value));
var cell = row.Cells[colName];
if (!Equals(cell.Value, value))
cell.Value = value;
}
private string GetString(DataGridViewRow row, string colName)
{
if (!grid.Columns.Contains(colName))
return "";
return Convert.ToString(row.Cells[colName].Value);
}
private bool GetBool(DataGridViewRow row, string colName)
{
if (!grid.Columns.Contains(colName))
return false;
if (row.Cells[colName].Value == null)
return false;
return Convert.ToBoolean(row.Cells[colName].Value);
}
private DataGridViewComboBoxColumn CreateComPortColumn(
string name,
string headerText,
List<string> comPorts)
{
return new DataGridViewComboBoxColumn
{
Name = name,
HeaderText = headerText,
DataSource = new List<string>(comPorts ?? new List<string>()),
FlatStyle = FlatStyle.Flat,
DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton
};
}
private DataGridViewComboBoxColumn CreateRequestPortTypeColumn()
{
return new DataGridViewComboBoxColumn
{
Name = "RequestPortType",
HeaderText = "RequestPortType",
DataSource = new List<string> { "", "IRDA", "UART", "RFID" },
FlatStyle = FlatStyle.Flat,
DisplayStyle = DataGridViewComboBoxDisplayStyle.DropDownButton
};
}
private DataGridViewButtonColumn CreateButtonColumn(
string name,
string headerText,
string text)
{
return new DataGridViewButtonColumn
{
Name = name,
HeaderText = headerText,
Text = text,
UseColumnTextForButtonValue = true
};
}
private void UpdateComPortColumnItems(string columnName, List<string> comPorts)
{
var col = grid.Columns[columnName] as DataGridViewComboBoxColumn;
if (col == null)
return;
col.DataSource = null;
col.DataSource = new List<string>(comPorts ?? new List<string>());
}
private string NormalizeRequestPortType(string value)
{
if (string.IsNullOrWhiteSpace(value))
return "";
string normalized = value.Trim();
if (normalized.Equals("RFID", StringComparison.OrdinalIgnoreCase) ||
normalized.IndexOf("RfidSerialPort", StringComparison.OrdinalIgnoreCase) >= 0)
return "RFID";
if (normalized.Equals("UART", StringComparison.OrdinalIgnoreCase) ||
normalized.IndexOf("UartSerialPort", StringComparison.OrdinalIgnoreCase) >= 0)
return "UART";
if (normalized.Equals("IRDA", StringComparison.OrdinalIgnoreCase) ||
normalized.Equals("IrDA", StringComparison.OrdinalIgnoreCase) ||
normalized.IndexOf("IrdaSerialPort", StringComparison.OrdinalIgnoreCase) >= 0)
return "IRDA";
return "";
}
public bool RemoveSlot(int slotId)
{
grid.SuspendLayout();
try
{
foreach (DataGridViewRow row in grid.Rows)
{
if (row.IsNewRow)
continue;
if (row.Cells["Slot"].Value == null)
continue;
if (Convert.ToInt32(row.Cells["Slot"].Value) == slotId)
{
grid.Rows.Remove(row);
return true;
}
}
return false;
}
finally
{
grid.ResumeLayout();
}
}
private string MapRequestPortTypeBack(string fullType)
{
return NormalizeRequestPortType(fullType);
}
private void EnableDoubleBuffering(DataGridView dgv)
{
typeof(DataGridView)
.GetProperty(
"DoubleBuffered",
BindingFlags.Instance | BindingFlags.NonPublic)
?.SetValue(dgv, true, null);
}
private void Grid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (grid.IsCurrentCellDirty)
{
grid.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
private void Grid_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex < 0)
return;
if (grid.Columns[e.ColumnIndex].Name != "Selected")
return;
bool clickedValue = Convert.ToBoolean(
grid.Rows[e.RowIndex].Cells["Selected"].Value);
foreach (DataGridViewRow row in grid.SelectedRows)
{
if (row.Index == e.RowIndex)
continue;
row.Cells["Selected"].Value = clickedValue;
}
}
}
}