添加合并单元格的用法。
This commit is contained in:
@@ -3,6 +3,7 @@ using UnityEditor;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
using XericLibrary.Runtime.SuperStyleSheet;
|
using XericLibrary.Runtime.SuperStyleSheet;
|
||||||
|
using XericUI.XTable.Core;
|
||||||
using XericUI.XTable.Mapping;
|
using XericUI.XTable.Mapping;
|
||||||
using XericUI.XTable.Rendering.Component;
|
using XericUI.XTable.Rendering.Component;
|
||||||
|
|
||||||
@@ -445,18 +446,42 @@ namespace XericUIEditor.XTable
|
|||||||
{
|
{
|
||||||
Color lineColor = new Color(0.5f, 0.5f, 0.55f, 0.18f);
|
Color lineColor = new Color(0.5f, 0.5f, 0.55f, 0.18f);
|
||||||
|
|
||||||
|
// 水平网格线(跳过合并区域内的线)
|
||||||
float y = tr.y;
|
float y = tr.y;
|
||||||
for (int r = 0; r < rh.Length; r++)
|
for (int r = 0; r < rh.Length; r++)
|
||||||
{
|
{
|
||||||
y += rh[r] * yScale;
|
y += rh[r] * yScale;
|
||||||
EditorGUI.DrawRect(new Rect(tr.x, y, tr.width, 1), lineColor);
|
|
||||||
|
// 检查此行是否在合并区域内(非底部边界的行)
|
||||||
|
bool skipLine = false;
|
||||||
|
if (s_ActiveTable != null && r + 1 < rh.Length)
|
||||||
|
{
|
||||||
|
var data = s_ActiveTable.TableData;
|
||||||
|
if (data != null && data.IsCellMerged(r + 1, 0))
|
||||||
|
skipLine = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipLine)
|
||||||
|
EditorGUI.DrawRect(new Rect(tr.x, y, tr.width, 1), lineColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 垂直网格线(跳过合并区域内的线)
|
||||||
float x = tr.x;
|
float x = tr.x;
|
||||||
for (int c = 0; c < cw.Length; c++)
|
for (int c = 0; c < cw.Length; c++)
|
||||||
{
|
{
|
||||||
x += cw[c] * xScale;
|
x += cw[c] * xScale;
|
||||||
EditorGUI.DrawRect(new Rect(x, tr.y, 1, tr.height), lineColor);
|
|
||||||
|
// 检查此列是否在合并区域内(非右侧边界的列)
|
||||||
|
bool skipLine = false;
|
||||||
|
if (s_ActiveTable != null && c + 1 < cw.Length)
|
||||||
|
{
|
||||||
|
var data = s_ActiveTable.TableData;
|
||||||
|
if (data != null && data.IsCellMerged(0, c + 1))
|
||||||
|
skipLine = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipLine)
|
||||||
|
EditorGUI.DrawRect(new Rect(x, tr.y, 1, tr.height), lineColor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,6 +496,10 @@ namespace XericUIEditor.XTable
|
|||||||
int sc = table.SelectedCol;
|
int sc = table.SelectedCol;
|
||||||
if (sr < 0 || sc < 0 || sr >= rh.Length || sc >= cw.Length) return;
|
if (sr < 0 || sc < 0 || sr >= rh.Length || sc >= cw.Length) return;
|
||||||
|
|
||||||
|
// 获取选中单元格的实际显示范围(合并源需要扩展)
|
||||||
|
int hlRowSpan = 1, hlColSpan = 1;
|
||||||
|
table.IsMergeSource(sr, sc, out hlRowSpan, out hlColSpan);
|
||||||
|
|
||||||
if (table.HasMultiSelection)
|
if (table.HasMultiSelection)
|
||||||
{
|
{
|
||||||
int minR = Mathf.Min(table.SelectStartRow, table.SelectEndRow);
|
int minR = Mathf.Min(table.SelectStartRow, table.SelectEndRow);
|
||||||
@@ -478,6 +507,13 @@ namespace XericUIEditor.XTable
|
|||||||
int minC = Mathf.Min(table.SelectStartCol, table.SelectEndCol);
|
int minC = Mathf.Min(table.SelectStartCol, table.SelectEndCol);
|
||||||
int maxC = Mathf.Max(table.SelectStartCol, table.SelectEndCol);
|
int maxC = Mathf.Max(table.SelectStartCol, table.SelectEndCol);
|
||||||
|
|
||||||
|
// 扩展多选区域以包含合并源的全部跨度
|
||||||
|
if (table.IsMergeSource(minR, minC, out int msRS, out int msCS))
|
||||||
|
{
|
||||||
|
maxR = Mathf.Max(maxR, minR + msRS - 1);
|
||||||
|
maxC = Mathf.Max(maxC, minC + msCS - 1);
|
||||||
|
}
|
||||||
|
|
||||||
minR = Mathf.Clamp(minR, 0, rh.Length - 1);
|
minR = Mathf.Clamp(minR, 0, rh.Length - 1);
|
||||||
maxR = Mathf.Clamp(maxR, 0, rh.Length - 1);
|
maxR = Mathf.Clamp(maxR, 0, rh.Length - 1);
|
||||||
minC = Mathf.Clamp(minC, 0, cw.Length - 1);
|
minC = Mathf.Clamp(minC, 0, cw.Length - 1);
|
||||||
@@ -492,10 +528,11 @@ namespace XericUIEditor.XTable
|
|||||||
s_MultiSelectRangeColor);
|
s_MultiSelectRangeColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 单选高亮(合并源用完整跨度)
|
||||||
float sx = tr.x + SumBefore(cw, sc) * xScale;
|
float sx = tr.x + SumBefore(cw, sc) * xScale;
|
||||||
float sy = tr.y + SumBefore(rh, sr) * yScale;
|
float sy = tr.y + SumBefore(rh, sr) * yScale;
|
||||||
float sw = cw[sc] * xScale;
|
float sw = SumRange(cw, sc, sc + hlColSpan) * xScale;
|
||||||
float sh = rh[sr] * yScale;
|
float sh = SumRange(rh, sr, sr + hlRowSpan) * yScale;
|
||||||
|
|
||||||
EditorGUI.DrawRect(new Rect(sx + 1, sy + 1, sw - 2, sh - 2),
|
EditorGUI.DrawRect(new Rect(sx + 1, sy + 1, sw - 2, sh - 2),
|
||||||
s_SelectionColor);
|
s_SelectionColor);
|
||||||
@@ -763,16 +800,31 @@ namespace XericUIEditor.XTable
|
|||||||
padding = new RectOffset(4, 4, 2, 2)
|
padding = new RectOffset(4, 4, 2, 2)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Row 1: 坐标标签 | 输入框 | 应用按钮
|
// Row 1: 坐标标签 | 输入框 | 应用按钮 + 合并/拆分按钮
|
||||||
float btnW = 44;
|
float actionBtnW = 50;
|
||||||
float row1Y = barRect.y + pad;
|
float row1Y = barRect.y + pad;
|
||||||
float row2Y = barRect.y + rowH + pad + 4;
|
float row2Y = barRect.y + rowH + pad + 4;
|
||||||
string cellLabel = table.GetSelectionText();
|
string cellLabel = table.GetSelectionText();
|
||||||
|
|
||||||
|
// 合并按钮(多选时显示)
|
||||||
|
bool showMerge = table.HasMultiSelection &&
|
||||||
|
(table.SelectStartRow != table.SelectEndRow ||
|
||||||
|
table.SelectStartCol != table.SelectEndCol);
|
||||||
|
|
||||||
|
// 拆分按钮(选中单元格是合并源时显示)
|
||||||
|
bool isMergeSource = table.IsMergeSource(table.SelectedRow,
|
||||||
|
table.SelectedCol, out _, out _);
|
||||||
|
|
||||||
|
float mergeBtnW = showMerge || isMergeSource ? actionBtnW : 0;
|
||||||
|
float unmergeBtnW = isMergeSource ? actionBtnW : 0;
|
||||||
|
|
||||||
|
// 坐标标签
|
||||||
GUI.Label(new Rect(barRect.x + 4, row1Y, 60, rowH), cellLabel, labelStyle);
|
GUI.Label(new Rect(barRect.x + 4, row1Y, 60, rowH), cellLabel, labelStyle);
|
||||||
Rect inputRect = new Rect(barRect.x + 68, row1Y, barW - 68 - btnW - pad * 2, rowH);
|
|
||||||
|
// 输入框
|
||||||
|
float inputW = barW - 68 - 44 - 2 - mergeBtnW - unmergeBtnW - pad * 2 - 4;
|
||||||
|
Rect inputRect = new Rect(barRect.x + 68, row1Y, inputW, rowH);
|
||||||
|
|
||||||
// 回车提交(仅在 CellEditing 状态下)
|
|
||||||
if (s_State == EditorState.CellEditing &&
|
if (s_State == EditorState.CellEditing &&
|
||||||
Event.current.type == EventType.KeyDown &&
|
Event.current.type == EventType.KeyDown &&
|
||||||
Event.current.keyCode == KeyCode.Return)
|
Event.current.keyCode == KeyCode.Return)
|
||||||
@@ -784,13 +836,51 @@ namespace XericUIEditor.XTable
|
|||||||
GUI.SetNextControlName("XTableSceneEditInput");
|
GUI.SetNextControlName("XTableSceneEditInput");
|
||||||
s_EditText = GUI.TextField(inputRect, s_EditText, inputStyle);
|
s_EditText = GUI.TextField(inputRect, s_EditText, inputStyle);
|
||||||
|
|
||||||
if (GUI.Button(new Rect(barRect.x + barW - btnW - pad, row1Y, btnW, rowH),
|
// 应用按钮
|
||||||
"应用", btnStyle))
|
float rightX = barRect.x + barW - pad - 44;
|
||||||
|
if (GUI.Button(new Rect(rightX, row1Y, 44, rowH), "应用", btnStyle))
|
||||||
{
|
{
|
||||||
GUI.FocusControl(null);
|
GUI.FocusControl(null);
|
||||||
ApplyCellEdit(table);
|
ApplyCellEdit(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 合并按钮
|
||||||
|
if (showMerge)
|
||||||
|
{
|
||||||
|
var mergeStyle = new GUIStyle(btnStyle)
|
||||||
|
{
|
||||||
|
normal = { background = MakeTex(1, 1, new Color(0.15f, 0.3f, 0.65f, 0.8f)), textColor = Color.white },
|
||||||
|
hover = { background = MakeTex(1, 1, new Color(0.2f, 0.4f, 0.85f, 0.9f)), textColor = Color.white }
|
||||||
|
};
|
||||||
|
if (GUI.Button(new Rect(rightX - mergeBtnW - 2, row1Y, mergeBtnW, rowH), "合并", mergeStyle))
|
||||||
|
{
|
||||||
|
int minR = Mathf.Min(table.SelectStartRow, table.SelectEndRow);
|
||||||
|
int maxR = Mathf.Max(table.SelectStartRow, table.SelectEndRow);
|
||||||
|
int minC = Mathf.Min(table.SelectStartCol, table.SelectEndCol);
|
||||||
|
int maxC = Mathf.Max(table.SelectStartCol, table.SelectEndCol);
|
||||||
|
table.MergeCells(minR, minC, maxR - minR + 1, maxC - minC + 1);
|
||||||
|
table.RefreshView();
|
||||||
|
SceneView.RepaintAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拆分按钮
|
||||||
|
if (isMergeSource)
|
||||||
|
{
|
||||||
|
var unmergeStyle = new GUIStyle(btnStyle)
|
||||||
|
{
|
||||||
|
normal = { background = MakeTex(1, 1, new Color(0.65f, 0.25f, 0.15f, 0.8f)), textColor = Color.white },
|
||||||
|
hover = { background = MakeTex(1, 1, new Color(0.85f, 0.35f, 0.2f, 0.9f)), textColor = Color.white }
|
||||||
|
};
|
||||||
|
float unmergeX = showMerge ? rightX - mergeBtnW - unmergeBtnW - 4 : rightX - unmergeBtnW - 2;
|
||||||
|
if (GUI.Button(new Rect(unmergeX, row1Y, unmergeBtnW, rowH), "拆分", unmergeStyle))
|
||||||
|
{
|
||||||
|
table.UnmergeCells(table.SelectedRow, table.SelectedCol);
|
||||||
|
table.RefreshView();
|
||||||
|
SceneView.RepaintAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Row 2: 样式命名空间下拉框
|
// Row 2: 样式命名空间下拉框
|
||||||
var nsLabelStyle = new GUIStyle(GUI.skin.label)
|
var nsLabelStyle = new GUIStyle(GUI.skin.label)
|
||||||
{
|
{
|
||||||
@@ -800,11 +890,9 @@ namespace XericUIEditor.XTable
|
|||||||
};
|
};
|
||||||
GUI.Label(new Rect(barRect.x + 4, row2Y, 36, rowH), "样式:", nsLabelStyle);
|
GUI.Label(new Rect(barRect.x + 4, row2Y, 36, rowH), "样式:", nsLabelStyle);
|
||||||
|
|
||||||
// 获取当前命名空间
|
|
||||||
string currentNS = table.GetCellStyleNamespace(
|
string currentNS = table.GetCellStyleNamespace(
|
||||||
table.SelectedRow, table.SelectedCol) ?? "";
|
table.SelectedRow, table.SelectedCol) ?? "";
|
||||||
|
|
||||||
// 构建下拉选项(StyleManager.GetAvailableNamespaces 已保证 "default" 在首位)
|
|
||||||
var namespaces = StyleManager.GetAvailableNamespaces();
|
var namespaces = StyleManager.GetAvailableNamespaces();
|
||||||
int currentIdx = namespaces.IndexOf(currentNS);
|
int currentIdx = namespaces.IndexOf(currentNS);
|
||||||
if (currentIdx < 0) currentIdx = 0;
|
if (currentIdx < 0) currentIdx = 0;
|
||||||
@@ -908,6 +996,46 @@ namespace XericUIEditor.XTable
|
|||||||
float ry = (Event.current.mousePosition.y - tr.y) / yScale;
|
float ry = (Event.current.mousePosition.y - tr.y) / yScale;
|
||||||
col = IndexFromCoord(rx, s_ColWidths);
|
col = IndexFromCoord(rx, s_ColWidths);
|
||||||
row = IndexFromCoord(ry, s_RowHeights);
|
row = IndexFromCoord(ry, s_RowHeights);
|
||||||
|
|
||||||
|
// 点击合并覆盖的单元格时,重定向到合并源
|
||||||
|
if (row >= 0 && col >= 0 && s_ActiveTable != null)
|
||||||
|
RedirectToMergeSource(ref row, ref col);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>如果指定单元格被合并覆盖,重定向到合并源(锚点)</summary>
|
||||||
|
private static void RedirectToMergeSource(ref int row, ref int col)
|
||||||
|
{
|
||||||
|
var data = s_ActiveTable.TableData;
|
||||||
|
if (data == null) return;
|
||||||
|
|
||||||
|
XTableCoordinateUtility.CellToBlockCoordinate(
|
||||||
|
row, col, data.BlockSizeX, data.BlockSizeY,
|
||||||
|
out int blockRow, out int blockCol,
|
||||||
|
out int localRow, out int localCol);
|
||||||
|
|
||||||
|
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
|
||||||
|
if (!data.BlockMap.TryGetValue(zIndex, out XTableBlock block))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var merge = block.GetMergeRedirect(localRow, localCol);
|
||||||
|
if (merge == null) return;
|
||||||
|
|
||||||
|
merge.GetRedirectTarget(out ulong targetBlockIndex, out int targetLocalRow, out int targetLocalCol);
|
||||||
|
|
||||||
|
if (merge.IsCrossBlock && data.BlockMap.TryGetValue(targetBlockIndex, out XTableBlock targetBlock))
|
||||||
|
{
|
||||||
|
// 跨块合并:从目标块的块坐标反算全局坐标
|
||||||
|
XTableBlockMapping.ZIndexToBlockCoord(targetBlockIndex,
|
||||||
|
out int targetBlockRow, out int targetBlockCol);
|
||||||
|
row = targetBlockRow * data.BlockSizeY + targetLocalRow;
|
||||||
|
col = targetBlockCol * data.BlockSizeX + targetLocalCol;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 本地合并:源在同一块内,反算全局坐标
|
||||||
|
row = blockRow * data.BlockSizeY + targetLocalRow;
|
||||||
|
col = blockCol * data.BlockSizeX + targetLocalCol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -987,6 +1115,7 @@ namespace XericUIEditor.XTable
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
RedirectToMergeSource(ref row, ref col);
|
||||||
table.SelectCell(row, col);
|
table.SelectCell(row, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -229,12 +229,19 @@ namespace XericUI.XTable.Core
|
|||||||
BlockMap[zIndex] = block;
|
BlockMap[zIndex] = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找或创建此块的合并描述(相同源)
|
// 计算本块内合并区域的局部起始和跨度
|
||||||
|
int localStartRow = Math.Max(0, startRow - blockRow * BlockSizeY);
|
||||||
|
int localStartCol = Math.Max(0, startCol - blockCol * BlockSizeX);
|
||||||
|
int blockEndRow = Math.Min((blockRow + 1) * BlockSizeY, startRow + rowSpan) - blockRow * BlockSizeY;
|
||||||
|
int blockEndCol = Math.Min((blockCol + 1) * BlockSizeX, startCol + colSpan) - blockCol * BlockSizeX;
|
||||||
|
|
||||||
|
// 查找或创建此块的合并描述
|
||||||
XTableMergeDescriptor descriptor = FindOrCreateMergeDescriptor(block,
|
XTableMergeDescriptor descriptor = FindOrCreateMergeDescriptor(block,
|
||||||
zIndex == srcZIndex ? srcLocalRow : -1,
|
|
||||||
zIndex == srcZIndex ? srcLocalCol : -1,
|
|
||||||
srcZIndex, srcLocalRow, srcLocalCol,
|
srcZIndex, srcLocalRow, srcLocalCol,
|
||||||
zIndex != srcZIndex);
|
zIndex != srcZIndex,
|
||||||
|
localStartRow, localStartCol,
|
||||||
|
blockEndRow - localStartRow, blockEndCol - localStartCol,
|
||||||
|
rowSpan, colSpan);
|
||||||
|
|
||||||
descriptor.MergedCellSet.Add((localRow, localCol));
|
descriptor.MergedCellSet.Add((localRow, localCol));
|
||||||
}
|
}
|
||||||
@@ -245,35 +252,41 @@ namespace XericUI.XTable.Core
|
|||||||
/// 查找或创建合并描述
|
/// 查找或创建合并描述
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private XTableMergeDescriptor FindOrCreateMergeDescriptor(
|
private XTableMergeDescriptor FindOrCreateMergeDescriptor(
|
||||||
XTableBlock block, int checkLocalRow, int checkLocalCol,
|
XTableBlock block,
|
||||||
ulong srcZIndex, int srcLocalRow, int srcLocalCol, bool isCrossBlock)
|
ulong srcZIndex, int srcLocalRow, int srcLocalCol, bool isCrossBlock,
|
||||||
|
int localStartRow, int localStartCol, int blockRowSpan, int blockColSpan,
|
||||||
|
int totalRowSpan, int totalColSpan)
|
||||||
{
|
{
|
||||||
// 查找已有描述
|
// 查找已有描述:匹配源坐标和跨块标记
|
||||||
for (int i = 0; i < block.MergeDescriptors.Count; i++)
|
for (int i = 0; i < block.MergeDescriptors.Count; i++)
|
||||||
{
|
{
|
||||||
var desc = block.MergeDescriptors[i];
|
var desc = block.MergeDescriptors[i];
|
||||||
if (desc.MergeRowSpan > 0 && desc.MergeColSpan > 0)
|
if (desc.IsCrossBlock == isCrossBlock &&
|
||||||
{
|
desc.SourceBlockIndex == srcZIndex &&
|
||||||
// 简化的同源判断:跨块引用共享 sourceBlockIndex
|
desc.SourceLocalRow == srcLocalRow &&
|
||||||
if (isCrossBlock && desc.IsCrossBlock && desc.SourceBlockIndex == srcZIndex)
|
desc.SourceLocalCol == srcLocalCol)
|
||||||
return desc;
|
return desc;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建新描述
|
// 创建新描述,设置完整跨度信息
|
||||||
var newDesc = new XTableMergeDescriptor
|
var newDesc = new XTableMergeDescriptor
|
||||||
{
|
{
|
||||||
IsCrossBlock = isCrossBlock,
|
IsCrossBlock = isCrossBlock,
|
||||||
SourceBlockIndex = srcZIndex,
|
SourceBlockIndex = srcZIndex,
|
||||||
SourceLocalRow = srcLocalRow,
|
SourceLocalRow = srcLocalRow,
|
||||||
SourceLocalCol = srcLocalCol
|
SourceLocalCol = srcLocalCol,
|
||||||
|
LocalStartRow = localStartRow,
|
||||||
|
LocalStartCol = localStartCol,
|
||||||
|
MergeRowSpan = totalRowSpan,
|
||||||
|
MergeColSpan = totalColSpan
|
||||||
};
|
};
|
||||||
block.MergeDescriptors.Add(newDesc);
|
block.MergeDescriptors.Add(newDesc);
|
||||||
return newDesc;
|
return newDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 取消指定区域的合并
|
/// 取消指定坐标所在合并——同时处理"点击源坐标"和"点击被合并坐标"两种情况。
|
||||||
|
/// 遍历所有块,移除所有指向该源的合并描述。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void UnmergeCells(int startRow, int startCol)
|
public void UnmergeCells(int startRow, int startCol)
|
||||||
{
|
{
|
||||||
@@ -284,15 +297,43 @@ namespace XericUI.XTable.Core
|
|||||||
|
|
||||||
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
|
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
|
||||||
|
|
||||||
if (!BlockMap.TryGetValue(zIndex, out XTableBlock block))
|
// 1) 从这个单元格所在的块开始:移除包含此坐标的合并描述(被合并格)
|
||||||
return;
|
if (BlockMap.TryGetValue(zIndex, out XTableBlock block))
|
||||||
|
|
||||||
// 移除包含此单元格的所有合并描述
|
|
||||||
for (int i = block.MergeDescriptors.Count - 1; i >= 0; i--)
|
|
||||||
{
|
{
|
||||||
if (block.MergeDescriptors[i].Contains(localRow, localCol))
|
for (int i = block.MergeDescriptors.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
block.MergeDescriptors.RemoveAt(i);
|
if (block.MergeDescriptors[i].Contains(localRow, localCol))
|
||||||
|
block.MergeDescriptors.RemoveAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) 遍历所有块:移除源坐标为此单元格的合并描述(合并源 / 锚点)
|
||||||
|
// 处理非跨块和跨块两种情况
|
||||||
|
foreach (var kv in BlockMap)
|
||||||
|
{
|
||||||
|
var b = kv.Value;
|
||||||
|
if (b.MergeDescriptors.Count == 0) continue;
|
||||||
|
|
||||||
|
for (int i = b.MergeDescriptors.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var desc = b.MergeDescriptors[i];
|
||||||
|
|
||||||
|
// 非跨块:源在同一个块内 → 直接比较本地坐标
|
||||||
|
if (!desc.IsCrossBlock &&
|
||||||
|
desc.SourceLocalRow == localRow &&
|
||||||
|
desc.SourceLocalCol == localCol &&
|
||||||
|
kv.Key == zIndex)
|
||||||
|
{
|
||||||
|
b.MergeDescriptors.RemoveAt(i);
|
||||||
|
}
|
||||||
|
// 跨块:源在另一个块 → 比较 SourceBlockIndex + 源本地坐标
|
||||||
|
else if (desc.IsCrossBlock &&
|
||||||
|
desc.SourceBlockIndex == zIndex &&
|
||||||
|
desc.SourceLocalRow == localRow &&
|
||||||
|
desc.SourceLocalCol == localCol)
|
||||||
|
{
|
||||||
|
b.MergeDescriptors.RemoveAt(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,9 +342,47 @@ namespace XericUI.XTable.Core
|
|||||||
|
|
||||||
#region 查询方法
|
#region 查询方法
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>判断指定单元格是否被合并覆盖(非源,会被重定向)</summary>
|
||||||
/// 判断指定块是否存在
|
public bool IsCellMerged(int row, int col)
|
||||||
/// </summary>
|
{
|
||||||
|
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 false;
|
||||||
|
return block.GetMergeRedirect(localRow, localCol) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>判断指定单元格是否为合并源(锚点),并返回合并跨度</summary>
|
||||||
|
public bool IsMergeSource(int row, int col, out int rowSpan, out int colSpan)
|
||||||
|
{
|
||||||
|
rowSpan = 1; colSpan = 1;
|
||||||
|
XTableCoordinateUtility.CellToBlockCoordinate(
|
||||||
|
row, col, BlockSizeX, BlockSizeY,
|
||||||
|
out int blockRow, out int blockCol,
|
||||||
|
out int localRow, out int localCol);
|
||||||
|
ulong thisZIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
|
||||||
|
|
||||||
|
foreach (var kv in BlockMap)
|
||||||
|
{
|
||||||
|
foreach (var desc in kv.Value.MergeDescriptors)
|
||||||
|
{
|
||||||
|
ulong srcBlockIdx = desc.IsCrossBlock ? desc.SourceBlockIndex : kv.Key;
|
||||||
|
if (srcBlockIdx == thisZIndex &&
|
||||||
|
desc.SourceLocalRow == localRow &&
|
||||||
|
desc.SourceLocalCol == localCol)
|
||||||
|
{
|
||||||
|
rowSpan = desc.MergeRowSpan;
|
||||||
|
colSpan = desc.MergeColSpan;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>判断指定块是否存在</summary>
|
||||||
public bool HasBlock(int blockRow, int blockCol)
|
public bool HasBlock(int blockRow, int blockCol)
|
||||||
{
|
{
|
||||||
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
|
ulong zIndex = XTableBlockMapping.BlockCoordToZIndex(blockRow, blockCol);
|
||||||
|
|||||||
@@ -310,6 +310,13 @@ namespace XericUI.XTable.Rendering.Component
|
|||||||
MarkDirty(TableDirtyType.DataChanged);
|
MarkDirty(TableDirtyType.DataChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>判断指定单元格是否被合并覆盖(非源,会被重定向)</summary>
|
||||||
|
public bool IsCellMerged(int row, int col) => TableData.IsCellMerged(row, col);
|
||||||
|
|
||||||
|
/// <summary>判断指定单元格是否为合并源(锚点),并返回合并跨度</summary>
|
||||||
|
public bool IsMergeSource(int row, int col, out int rowSpan, out int colSpan)
|
||||||
|
=> TableData.IsMergeSource(row, col, out rowSpan, out colSpan);
|
||||||
|
|
||||||
/// <summary>在末尾追加一行,默认行高 40</summary>
|
/// <summary>在末尾追加一行,默认行高 40</summary>
|
||||||
public void AddRow(float height = 40f)
|
public void AddRow(float height = 40f)
|
||||||
{
|
{
|
||||||
@@ -738,15 +745,28 @@ namespace XericUI.XTable.Rendering.Component
|
|||||||
{
|
{
|
||||||
for (int c = sc; c < ec && c < m_ColWidths.Length; c++)
|
for (int c = sc; c < ec && c < m_ColWidths.Length; c++)
|
||||||
{
|
{
|
||||||
|
// 跳过被合并覆盖的单元格
|
||||||
|
if (TableData.IsCellMerged(r, c)) continue;
|
||||||
|
|
||||||
float cellX = GetColLeftX(c);
|
float cellX = GetColLeftX(c);
|
||||||
float cellY = -GetRowTopY(r);
|
float cellY = -GetRowTopY(r);
|
||||||
float cellW = m_ColWidths[c];
|
float cellW = m_ColWidths[c];
|
||||||
float cellH = m_RowHeights[r];
|
float cellH = m_RowHeights[r];
|
||||||
|
|
||||||
|
// 合并源:扩展尺寸
|
||||||
|
if (TableData.IsMergeSource(r, c, out int mergeRS, out int mergeCS))
|
||||||
|
{
|
||||||
|
for (int i = 1; i < mergeCS && c + i < m_ColWidths.Length; i++)
|
||||||
|
cellW += m_ColWidths[c + i];
|
||||||
|
for (int i = 1; i < mergeRS && r + i < m_RowHeights.Length; i++)
|
||||||
|
cellH += m_RowHeights[r + i];
|
||||||
|
}
|
||||||
|
|
||||||
XTableCellData data = TableData.GetCell(r, c);
|
XTableCellData data = TableData.GetCell(r, c);
|
||||||
string cellNS = (data != null && !string.IsNullOrEmpty(data.StyleNamespace))
|
string cellNS = (data != null && !string.IsNullOrEmpty(data.StyleNamespace))
|
||||||
? data.StyleNamespace : ns;
|
? data.StyleNamespace : ns;
|
||||||
|
|
||||||
// 多选高亮
|
// 多选 / 单选高亮
|
||||||
if (IsInSelectionRange(r, c))
|
if (IsInSelectionRange(r, c))
|
||||||
{
|
{
|
||||||
var selImg = m_Assembler.GetImage("cell_multiselect");
|
var selImg = m_Assembler.GetImage("cell_multiselect");
|
||||||
@@ -763,13 +783,13 @@ namespace XericUI.XTable.Rendering.Component
|
|||||||
selImg.Image.color = selectionColor;
|
selImg.Image.color = selectionColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 水平网格线(单元格底部)
|
// 水平网格线(合并区域底部)
|
||||||
var hLine = m_Assembler.GetImage("cell_hline");
|
var hLine = m_Assembler.GetImage("cell_hline");
|
||||||
hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH);
|
hLine.Rect.anchoredPosition = new Vector2(cellX, cellY - cellH);
|
||||||
hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth);
|
hLine.Rect.sizeDelta = new Vector2(cellW, borderWidth);
|
||||||
hLine.Image.color = borderColor;
|
hLine.Image.color = borderColor;
|
||||||
|
|
||||||
// 垂直网格线(单元格右侧)
|
// 垂直网格线(合并区域右侧)
|
||||||
var vLine = m_Assembler.GetImage("cell_vline");
|
var vLine = m_Assembler.GetImage("cell_vline");
|
||||||
vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY);
|
vLine.Rect.anchoredPosition = new Vector2(cellX + cellW - borderWidth, cellY);
|
||||||
vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH);
|
vLine.Rect.sizeDelta = new Vector2(borderWidth, cellH);
|
||||||
@@ -802,10 +822,23 @@ namespace XericUI.XTable.Rendering.Component
|
|||||||
{
|
{
|
||||||
for (int c = sc; c < ec && c < m_ColWidths.Length; c++)
|
for (int c = sc; c < ec && c < m_ColWidths.Length; c++)
|
||||||
{
|
{
|
||||||
|
// 跳过被合并覆盖的单元格
|
||||||
|
if (TableData.IsCellMerged(r, c)) continue;
|
||||||
|
|
||||||
float cellX = GetColLeftX(c);
|
float cellX = GetColLeftX(c);
|
||||||
float cellY = -GetRowTopY(r);
|
float cellY = -GetRowTopY(r);
|
||||||
float cellW = m_ColWidths[c];
|
float cellW = m_ColWidths[c];
|
||||||
float cellH = m_RowHeights[r];
|
float cellH = m_RowHeights[r];
|
||||||
|
|
||||||
|
// 合并源:扩展尺寸
|
||||||
|
if (TableData.IsMergeSource(r, c, out int mergeRS, out int mergeCS))
|
||||||
|
{
|
||||||
|
for (int i = 1; i < mergeCS && c + i < m_ColWidths.Length; i++)
|
||||||
|
cellW += m_ColWidths[c + i];
|
||||||
|
for (int i = 1; i < mergeRS && r + i < m_RowHeights.Length; i++)
|
||||||
|
cellH += m_RowHeights[r + i];
|
||||||
|
}
|
||||||
|
|
||||||
XTableCellData data = TableData.GetCell(r, c);
|
XTableCellData data = TableData.GetCell(r, c);
|
||||||
string cellNS = (data != null && !string.IsNullOrEmpty(data.StyleNamespace))
|
string cellNS = (data != null && !string.IsNullOrEmpty(data.StyleNamespace))
|
||||||
? data.StyleNamespace : ns;
|
? data.StyleNamespace : ns;
|
||||||
|
|||||||
Reference in New Issue
Block a user