优化表格边框绘制逻辑,添加边框缓存。

This commit is contained in:
2026-07-07 10:31:08 +08:00
parent 664c2c841f
commit cbcb85b3e7
4 changed files with 305 additions and 32 deletions
+43
View File
@@ -33,6 +33,11 @@ namespace XericUI.XTable.Core
/// <summary>合并单元格描述列表</summary>
public List<XTableMergeDescriptor> MergeDescriptors;
/// <summary>每个单元格右侧边框的样式命名空间缓存(线性数组,同 Cells[] 布局)</summary>
public string[] BorderRightNs;
/// <summary>每个单元格底部边框的样式命名空间缓存(线性数组,同 Cells[] 布局)</summary>
public string[] BorderBottomNs;
/// <summary>
/// 创建指定尺寸的块
/// </summary>
@@ -42,6 +47,8 @@ namespace XericUI.XTable.Core
BlockSizeY = blockSizeY;
Cells = new XTableCellData[blockSizeX * blockSizeY];
MergeDescriptors = new List<XTableMergeDescriptor>();
BorderRightNs = new string[blockSizeX * blockSizeY];
BorderBottomNs = new string[blockSizeX * blockSizeY];
}
/// <summary>
@@ -74,6 +81,38 @@ namespace XericUI.XTable.Core
Cells[index] = data;
}
/// <summary>通过块内局部坐标获取右侧边框缓存</summary>
public string GetBorderRight(int localRow, int localCol)
{
int index = localRow * BlockSizeX + localCol;
if (index < 0 || index >= (BorderRightNs?.Length ?? 0)) return null;
return BorderRightNs[index];
}
/// <summary>通过块内局部坐标设置右侧边框缓存</summary>
public void SetBorderRight(int localRow, int localCol, string ns)
{
int index = localRow * BlockSizeX + localCol;
if (index < 0 || index >= (BorderRightNs?.Length ?? 0)) return;
BorderRightNs[index] = ns;
}
/// <summary>通过块内局部坐标获取底部边框缓存</summary>
public string GetBorderBottom(int localRow, int localCol)
{
int index = localRow * BlockSizeX + localCol;
if (index < 0 || index >= (BorderBottomNs?.Length ?? 0)) return null;
return BorderBottomNs[index];
}
/// <summary>通过块内局部坐标设置底部边框缓存</summary>
public void SetBorderBottom(int localRow, int localCol, string ns)
{
int index = localRow * BlockSizeX + localCol;
if (index < 0 || index >= (BorderBottomNs?.Length ?? 0)) return;
BorderBottomNs[index] = ns;
}
/// <summary>
/// 检查是否有合并描述重定向此单元格
/// </summary>
@@ -103,6 +142,10 @@ namespace XericUI.XTable.Core
// 确保数组和列表非空
if (Cells == null) Cells = new XTableCellData[BlockSizeX * BlockSizeY];
if (MergeDescriptors == null) MergeDescriptors = new List<XTableMergeDescriptor>();
if (BorderRightNs == null || BorderRightNs.Length != BlockSizeX * BlockSizeY)
BorderRightNs = new string[BlockSizeX * BlockSizeY];
if (BorderBottomNs == null || BorderBottomNs.Length != BlockSizeX * BlockSizeY)
BorderBottomNs = new string[BlockSizeX * BlockSizeY];
}
#endregion
+165
View File
@@ -407,5 +407,170 @@ namespace XericUI.XTable.Core
public int BlockCount => BlockMap.Count;
#endregion
#region 边框缓存
/// <summary>
/// 外边框样式管理器——维护 -1 行 / -1 列的边框样式命名空间。
/// key = (row, col),其中 row / col 可为 -1。
/// (-1, -1) = 表格最外框,
/// (-1, c) = 第 c 列顶部边框,
/// (r, -1) = 第 r 行左侧边框。
/// </summary>
[NonSerialized] public Dictionary<(int row, int col), string> OuterBorderNs;
// OuterBorderNs 序列化代理
[SerializeField] private List<int> m_OuterBorderRows = new List<int>();
[SerializeField] private List<int> m_OuterBorderCols = new List<int>();
[SerializeField] private List<string> m_OuterBorderValues = new List<string>();
/// <summary>
/// 获取右侧边框样式命名空间。
/// col < 0 时退回到 OuterBorderNs。
/// </summary>
public string GetBorderRightNs(int row, int col)
{
if (col < 0 || row < 0)
return GetOuterBorderNs(row, col);
XTableCoordinateUtility.CellToBlockCoordinate(row, col, BlockSizeX, BlockSizeY,
out int blockRow, out int blockCol,
out int localRow, out int localCol);
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
if (!BlockMap.TryGetValue(zIndex, out XTableBlock block))
return null;
return block.GetBorderRight(localRow, localCol);
}
/// <summary>
/// 设置右侧边框样式命名空间。
/// col < 0 时写入 OuterBorderNs。
/// </summary>
public void SetBorderRightNs(int row, int col, string ns)
{
if (col < 0 || row < 0)
{
SetOuterBorderNs(row, col, ns);
return;
}
XTableCoordinateUtility.CellToBlockCoordinate(row, col, BlockSizeX, BlockSizeY,
out int blockRow, out int blockCol,
out int localRow, out int localCol);
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
if (!BlockMap.TryGetValue(zIndex, out XTableBlock block))
{
block = new XTableBlock(BlockSizeX, BlockSizeY, blockRow, blockCol);
BlockMap[zIndex] = block;
}
block.SetBorderRight(localRow, localCol, ns);
}
/// <summary>
/// 获取底部边框样式命名空间。
/// row < 0 时退回到 OuterBorderNs。
/// </summary>
public string GetBorderBottomNs(int row, int col)
{
if (col < 0 || row < 0)
return GetOuterBorderNs(row, col);
XTableCoordinateUtility.CellToBlockCoordinate(row, col, BlockSizeX, BlockSizeY,
out int blockRow, out int blockCol,
out int localRow, out int localCol);
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
if (!BlockMap.TryGetValue(zIndex, out XTableBlock block))
return null;
return block.GetBorderBottom(localRow, localCol);
}
/// <summary>
/// 设置底部边框样式命名空间。
/// row < 0 时写入 OuterBorderNs。
/// </summary>
public void SetBorderBottomNs(int row, int col, string ns)
{
if (col < 0 || row < 0)
{
SetOuterBorderNs(row, col, ns);
return;
}
XTableCoordinateUtility.CellToBlockCoordinate(row, col, BlockSizeX, BlockSizeY,
out int blockRow, out int blockCol,
out int localRow, out int localCol);
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
if (!BlockMap.TryGetValue(zIndex, out XTableBlock block))
{
block = new XTableBlock(BlockSizeX, BlockSizeY, blockRow, blockCol);
BlockMap[zIndex] = block;
}
block.SetBorderBottom(localRow, localCol, ns);
}
/// <summary>获取外边框样式(-1 行 / -1 列)</summary>
public string GetOuterBorderNs(int row, int col)
{
if (OuterBorderNs == null) return null;
OuterBorderNs.TryGetValue((row, col), out string ns);
return ns;
}
/// <summary>设置外边框样式(-1 行 / -1 列)</summary>
public void SetOuterBorderNs(int row, int col, string ns)
{
if (OuterBorderNs == null)
OuterBorderNs = new Dictionary<(int, int), string>();
OuterBorderNs[(row, col)] = ns;
}
/// <summary>清空所有边框缓存</summary>
public void ClearAllBorderCache()
{
OuterBorderNs?.Clear();
foreach (var kv in BlockMap)
{
var b = kv.Value;
if (b.BorderRightNs != null)
System.Array.Clear(b.BorderRightNs, 0, b.BorderRightNs.Length);
if (b.BorderBottomNs != null)
System.Array.Clear(b.BorderBottomNs, 0, b.BorderBottomNs.Length);
}
}
// ── OuterBorderNs 序列化 ──
private void SerializeOuterBorder()
{
m_OuterBorderRows.Clear();
m_OuterBorderCols.Clear();
m_OuterBorderValues.Clear();
if (OuterBorderNs != null)
{
foreach (var kv in OuterBorderNs)
{
m_OuterBorderRows.Add(kv.Key.row);
m_OuterBorderCols.Add(kv.Key.col);
m_OuterBorderValues.Add(kv.Value);
}
}
}
private void DeserializeOuterBorder()
{
OuterBorderNs = new Dictionary<(int, int), string>();
int count = System.Math.Min(m_OuterBorderRows.Count,
System.Math.Min(m_OuterBorderCols.Count, m_OuterBorderValues.Count));
for (int i = 0; i < count; i++)
{
if (m_OuterBorderValues[i] != null)
OuterBorderNs[(m_OuterBorderRows[i], m_OuterBorderCols[i])] = m_OuterBorderValues[i];
}
}
#endregion
}
}