@veltra/sheet 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -19
- package/dist/index.js +2 -15
- package/dist/types/index.d.ts +1 -3
- package/package.json +2 -3
- package/src/index.ts +1 -27
- package/src/types/index.ts +0 -2
- package/dist/components/report/binding-badge.js +0 -118
- package/dist/components/report/designer/cell-coords.js +0 -46
- package/dist/components/report/designer/col-widths.js +0 -29
- package/dist/components/report/designer/conditional-rules/helpers.js +0 -139
- package/dist/components/report/designer/drill-dialog.js +0 -258
- package/dist/components/report/designer/drop-highlight-overlay.js +0 -76
- package/dist/components/report/designer/float-panel.js +0 -434
- package/dist/components/report/designer/role.js +0 -17
- package/dist/components/report/designer/rule-preview.js +0 -33
- package/dist/components/report/designer/rule-row.js +0 -253
- package/dist/components/report/designer/rules-dialog.js +0 -118
- package/dist/components/report/designer/topology-overlay.js +0 -122
- package/dist/components/report/designer/topology.js +0 -64
- package/dist/components/report/designer/use-grid-overlay.js +0 -75
- package/dist/components/report/designer-hub.js +0 -177
- package/dist/components/report/field-panel-helpers.js +0 -33
- package/dist/components/report/field-panel.js +0 -132
- package/dist/components/report/filter-bar.js +0 -74
- package/dist/components/report/hub-connection-form.js +0 -145
- package/dist/components/report/hub-dataset-editor.js +0 -409
- package/dist/components/report/preview-grid-size.js +0 -32
- package/dist/components/report/print.js +0 -39
- package/dist/components/report/report-designer.js +0 -428
- package/dist/components/report/report-viewer.js +0 -253
- package/dist/components/report/style.d.ts +0 -17
- package/dist/components/report/style.js +0 -18
- package/dist/components/report/style2.css +0 -965
- package/dist/components/report/use-report-designer.js +0 -387
- package/dist/components/report/use-report-viewer.js +0 -140
- package/dist/report/binding.d.ts +0 -83
- package/dist/report/binding.js +0 -334
- package/dist/report/connector.d.ts +0 -66
- package/dist/report/connector.js +0 -159
- package/dist/report/drill.d.ts +0 -48
- package/dist/report/drill.js +0 -78
- package/dist/report/export-xlsx.d.ts +0 -13
- package/dist/report/export-xlsx.js +0 -13
- package/dist/report/filter-bar.d.ts +0 -10
- package/dist/report/filter-bar.js +0 -31
- package/dist/report/index.d.ts +0 -14
- package/dist/report/params.d.ts +0 -13
- package/dist/report/params.js +0 -61
- package/dist/report/print.d.ts +0 -23
- package/dist/report/print.js +0 -197
- package/dist/report/render/aggregate.js +0 -193
- package/dist/report/render/builder.d.ts +0 -12
- package/dist/report/render/builder.js +0 -139
- package/dist/report/render/coordinate.d.ts +0 -25
- package/dist/report/render/coordinate.js +0 -733
- package/dist/report/render/index.d.ts +0 -14
- package/dist/report/render/index.js +0 -21
- package/dist/report/render/style-resolver.js +0 -50
- package/dist/report/render/template-index.d.ts +0 -24
- package/dist/report/render/template-index.js +0 -137
- package/dist/report/rules/evaluate.d.ts +0 -25
- package/dist/report/rules/evaluate.js +0 -82
- package/dist/report/rules/index.d.ts +0 -2
- package/dist/report/template.d.ts +0 -63
- package/dist/report/template.js +0 -83
- package/dist/report/types.d.ts +0 -103
- package/dist/types/report-designer.d.ts +0 -51
- package/dist/types/report-viewer.d.ts +0 -57
- package/src/components/report/__test__/binding-badge.test.ts +0 -92
- package/src/components/report/__test__/conditional-rules-helpers.test.ts +0 -88
- package/src/components/report/__test__/field-panel-helpers.test.ts +0 -65
- package/src/components/report/__test__/float-panel-position.test.ts +0 -45
- package/src/components/report/__test__/preview-grid-size.test.ts +0 -63
- package/src/components/report/__test__/report-designer.test.ts +0 -559
- package/src/components/report/__test__/report-drill.test.ts +0 -692
- package/src/components/report/__test__/report-viewer.test.ts +0 -400
- package/src/components/report/__test__/topology.test.ts +0 -143
- package/src/components/report/__test__/use-report-designer.test.ts +0 -804
- package/src/components/report/binding-badge.ts +0 -122
- package/src/components/report/designer/cell-coords.ts +0 -95
- package/src/components/report/designer/col-widths.ts +0 -56
- package/src/components/report/designer/conditional-rules/helpers.ts +0 -189
- package/src/components/report/designer/drill-dialog.vue +0 -245
- package/src/components/report/designer/drop-highlight-overlay.vue +0 -75
- package/src/components/report/designer/float-panel.vue +0 -444
- package/src/components/report/designer/role.ts +0 -32
- package/src/components/report/designer/rule-preview.vue +0 -40
- package/src/components/report/designer/rule-row.vue +0 -252
- package/src/components/report/designer/rules-dialog.vue +0 -110
- package/src/components/report/designer/topology-overlay.vue +0 -128
- package/src/components/report/designer/topology.ts +0 -124
- package/src/components/report/designer/use-grid-overlay.ts +0 -114
- package/src/components/report/designer-hub.vue +0 -198
- package/src/components/report/field-panel-helpers.ts +0 -44
- package/src/components/report/field-panel.vue +0 -136
- package/src/components/report/filter-bar.vue +0 -77
- package/src/components/report/hub-connection-form.vue +0 -124
- package/src/components/report/hub-dataset-editor.vue +0 -387
- package/src/components/report/index.ts +0 -2
- package/src/components/report/preview-grid-size.ts +0 -33
- package/src/components/report/print.ts +0 -44
- package/src/components/report/report-designer.vue +0 -454
- package/src/components/report/report-viewer.vue +0 -289
- package/src/components/report/style-designer.scss +0 -653
- package/src/components/report/style-hub.scss +0 -292
- package/src/components/report/style-viewer.scss +0 -144
- package/src/components/report/style.scss +0 -3
- package/src/components/report/style.ts +0 -20
- package/src/components/report/use-report-designer.ts +0 -603
- package/src/components/report/use-report-viewer.ts +0 -227
- package/src/report/__test__/binding.test.ts +0 -320
- package/src/report/__test__/connector.test.ts +0 -239
- package/src/report/__test__/drill.test.ts +0 -194
- package/src/report/__test__/export-xlsx.test.ts +0 -96
- package/src/report/__test__/filter-bar.test.ts +0 -58
- package/src/report/__test__/params.test.ts +0 -156
- package/src/report/__test__/print.test.ts +0 -170
- package/src/report/__test__/render.test.ts +0 -856
- package/src/report/__test__/rules.test.ts +0 -131
- package/src/report/__test__/template.test.ts +0 -366
- package/src/report/binding.ts +0 -474
- package/src/report/connector.ts +0 -206
- package/src/report/drill.ts +0 -112
- package/src/report/export-xlsx.ts +0 -15
- package/src/report/filter-bar.ts +0 -36
- package/src/report/index.ts +0 -16
- package/src/report/params.ts +0 -96
- package/src/report/print.ts +0 -234
- package/src/report/render/__test__/aggregate.test.ts +0 -16
- package/src/report/render/__test__/coordinate.test.ts +0 -405
- package/src/report/render/aggregate.ts +0 -289
- package/src/report/render/builder.ts +0 -211
- package/src/report/render/coordinate.ts +0 -1239
- package/src/report/render/index.ts +0 -30
- package/src/report/render/style-resolver.ts +0 -68
- package/src/report/render/template-index.ts +0 -200
- package/src/report/rules/evaluate.ts +0 -113
- package/src/report/rules/index.ts +0 -7
- package/src/report/template.ts +0 -145
- package/src/report/types.ts +0 -116
- package/src/types/report-designer.ts +0 -55
- package/src/types/report-viewer.ts +0 -54
|
@@ -1,733 +0,0 @@
|
|
|
1
|
-
import { sameAddress } from "./template-index.js";
|
|
2
|
-
import { cellKey, createRange } from "@veltra/sheet-core";
|
|
3
|
-
//#region src/report/render/coordinate.ts
|
|
4
|
-
function isRowExpanding(binding) {
|
|
5
|
-
return binding.expand === "down" && (binding.aggregate === "group" || binding.aggregate === "list");
|
|
6
|
-
}
|
|
7
|
-
function isColExpanding(binding) {
|
|
8
|
-
return binding.expand === "right" && (binding.aggregate === "group" || binding.aggregate === "list");
|
|
9
|
-
}
|
|
10
|
-
function mergeSpanEnabled(binding) {
|
|
11
|
-
return binding?.mergeSpan !== false;
|
|
12
|
-
}
|
|
13
|
-
function filterRows(rows, filter) {
|
|
14
|
-
if (Object.keys(filter).length === 0) return rows;
|
|
15
|
-
return rows.filter((row) => Object.entries(filter).every(([field, value]) => row[field] === value));
|
|
16
|
-
}
|
|
17
|
-
function distinctFieldValues(rows, field) {
|
|
18
|
-
const seen = /* @__PURE__ */ new Set();
|
|
19
|
-
const values = [];
|
|
20
|
-
for (const row of rows) {
|
|
21
|
-
const key = JSON.stringify(row[field]);
|
|
22
|
-
if (seen.has(key)) continue;
|
|
23
|
-
seen.add(key);
|
|
24
|
-
values.push(row[field]);
|
|
25
|
-
}
|
|
26
|
-
return values;
|
|
27
|
-
}
|
|
28
|
-
function sortValues(values, sort) {
|
|
29
|
-
if (sort === "asc") return [...values].sort((a, b) => String(a).localeCompare(String(b), "zh-CN"));
|
|
30
|
-
if (sort === "desc") return [...values].sort((a, b) => String(b).localeCompare(String(a), "zh-CN"));
|
|
31
|
-
return values;
|
|
32
|
-
}
|
|
33
|
-
function singleCellRange(row, col) {
|
|
34
|
-
return {
|
|
35
|
-
start: {
|
|
36
|
-
row,
|
|
37
|
-
col
|
|
38
|
-
},
|
|
39
|
-
end: {
|
|
40
|
-
row,
|
|
41
|
-
col
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
function rangeRows(range) {
|
|
46
|
-
return range.end.row - range.start.row + 1;
|
|
47
|
-
}
|
|
48
|
-
function rangeCols(range) {
|
|
49
|
-
return range.end.col - range.start.col + 1;
|
|
50
|
-
}
|
|
51
|
-
function mergeFilters(rowFilter, colFilter) {
|
|
52
|
-
return {
|
|
53
|
-
...rowFilter,
|
|
54
|
-
...colFilter
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
function parentFilterForBinding(binding, index, rowFilter, colFilter) {
|
|
58
|
-
const filter = {};
|
|
59
|
-
if (binding.rowParent) {
|
|
60
|
-
const parent = index.bindingAt(binding.rowParent);
|
|
61
|
-
if (parent && parent.dataset === binding.dataset) Object.assign(filter, rowFilter);
|
|
62
|
-
}
|
|
63
|
-
if (binding.colParent) {
|
|
64
|
-
const parent = index.bindingAt(binding.colParent);
|
|
65
|
-
if (parent && parent.dataset === binding.dataset) Object.assign(filter, colFilter);
|
|
66
|
-
}
|
|
67
|
-
return filter;
|
|
68
|
-
}
|
|
69
|
-
/** 枚举扩展格实例 */
|
|
70
|
-
function enumerateExpansionInstances(binding, data, filter) {
|
|
71
|
-
const rows = filterRows(data[binding.dataset] ?? [], filter);
|
|
72
|
-
if (!isRowExpanding(binding) && !isColExpanding(binding)) return [{
|
|
73
|
-
index: 0,
|
|
74
|
-
filter
|
|
75
|
-
}];
|
|
76
|
-
if (binding.aggregate === "group") return sortValues(distinctFieldValues(rows, binding.field), binding.sort).map((value, index) => ({
|
|
77
|
-
index,
|
|
78
|
-
value,
|
|
79
|
-
filter: {
|
|
80
|
-
...filter,
|
|
81
|
-
[binding.field]: value
|
|
82
|
-
}
|
|
83
|
-
}));
|
|
84
|
-
if (binding.aggregate === "list") return rows.map((_, index) => ({
|
|
85
|
-
index,
|
|
86
|
-
filter
|
|
87
|
-
}));
|
|
88
|
-
return [{
|
|
89
|
-
index: 0,
|
|
90
|
-
filter
|
|
91
|
-
}];
|
|
92
|
-
}
|
|
93
|
-
function isRowSubtreeRoot(binding, index) {
|
|
94
|
-
if (!isRowExpanding(binding)) return false;
|
|
95
|
-
if (!binding.rowParent) return true;
|
|
96
|
-
const parent = index.bindingAt(binding.rowParent);
|
|
97
|
-
return !parent || !isRowExpanding(parent);
|
|
98
|
-
}
|
|
99
|
-
function isColSubtreeRoot(binding, index) {
|
|
100
|
-
if (!isColExpanding(binding)) return false;
|
|
101
|
-
if (!binding.colParent) return true;
|
|
102
|
-
const parent = index.bindingAt(binding.colParent);
|
|
103
|
-
return !parent || !isColExpanding(parent);
|
|
104
|
-
}
|
|
105
|
-
function isNestedRowExpander(binding, index) {
|
|
106
|
-
return isRowExpanding(binding) && binding.aggregate === "group" && !!binding.rowParent && !isRowSubtreeRoot(binding, index);
|
|
107
|
-
}
|
|
108
|
-
function isNestedColExpander(binding, index) {
|
|
109
|
-
return isColExpanding(binding) && binding.aggregate === "group" && !!binding.colParent && !isColSubtreeRoot(binding, index);
|
|
110
|
-
}
|
|
111
|
-
function rowSubtreeRows(rootAddr, index) {
|
|
112
|
-
let maxRow = rootAddr.row;
|
|
113
|
-
const walk = (addr) => {
|
|
114
|
-
maxRow = Math.max(maxRow, addr.row);
|
|
115
|
-
for (const child of index.rowChildren.get(cellKey(addr)) ?? []) walk(child);
|
|
116
|
-
};
|
|
117
|
-
walk(rootAddr);
|
|
118
|
-
return index.logicalRows.filter((row) => row >= rootAddr.row && row <= maxRow);
|
|
119
|
-
}
|
|
120
|
-
function colSubtreeCols(rootAddr, index) {
|
|
121
|
-
let maxCol = rootAddr.col;
|
|
122
|
-
const walk = (addr) => {
|
|
123
|
-
maxCol = Math.max(maxCol, addr.col);
|
|
124
|
-
for (const child of index.colChildren.get(cellKey(addr)) ?? []) walk(child);
|
|
125
|
-
};
|
|
126
|
-
walk(rootAddr);
|
|
127
|
-
return index.logicalCols.filter((col) => col >= rootAddr.col && col <= maxCol);
|
|
128
|
-
}
|
|
129
|
-
function columnsOnRow(index, row) {
|
|
130
|
-
const cols = /* @__PURE__ */ new Set();
|
|
131
|
-
for (const entry of index.bindingsOnRow(row)) cols.add(entry.addr.col);
|
|
132
|
-
for (const cell of index.staticCells.values()) if (cell.row === row) cols.add(cell.col);
|
|
133
|
-
return [...cols].sort((a, b) => a - b);
|
|
134
|
-
}
|
|
135
|
-
function findRowSubtreeRootOnRow(index, row) {
|
|
136
|
-
for (const entry of index.bindingsOnRow(row)) if (isRowSubtreeRoot(entry.binding, index)) return entry.addr;
|
|
137
|
-
return null;
|
|
138
|
-
}
|
|
139
|
-
/** 扩展带终止行:新的纵向子树根,或无父格的汇总行(如总计) */
|
|
140
|
-
function isExpansionBandTerminatorRow(index, row, rootRow) {
|
|
141
|
-
if (row <= rootRow) return false;
|
|
142
|
-
const rowRoot = findRowSubtreeRootOnRow(index, row);
|
|
143
|
-
if (rowRoot && rowRoot.row !== rootRow) return true;
|
|
144
|
-
return !isCompanionRow(index, row);
|
|
145
|
-
}
|
|
146
|
-
/** 扩展带内随行:全部绑定均带 rowParent(纯静态行不算带内行) */
|
|
147
|
-
function isCompanionRow(index, row) {
|
|
148
|
-
const bindings = index.bindingsOnRow(row);
|
|
149
|
-
if (bindings.length === 0) return false;
|
|
150
|
-
return bindings.every(({ binding }) => binding.rowParent !== void 0);
|
|
151
|
-
}
|
|
152
|
-
/** 纵向扩展带覆盖的模板行:子树行 + 紧随其后的带内汇总行 */
|
|
153
|
-
function expansionBandRows(rootAddr, index) {
|
|
154
|
-
const subtreeRows = rowSubtreeRows(rootAddr, index);
|
|
155
|
-
const maxSubtreeRow = Math.max(...subtreeRows);
|
|
156
|
-
const rows = new Set(subtreeRows);
|
|
157
|
-
for (const row of index.logicalRows) {
|
|
158
|
-
if (row <= maxSubtreeRow) continue;
|
|
159
|
-
if (isExpansionBandTerminatorRow(index, row, rootAddr.row)) break;
|
|
160
|
-
if (!isCompanionRow(index, row)) break;
|
|
161
|
-
rows.add(row);
|
|
162
|
-
}
|
|
163
|
-
return index.logicalRows.filter((row) => rows.has(row));
|
|
164
|
-
}
|
|
165
|
-
function findNestedColChild(rootAddr, index) {
|
|
166
|
-
for (const child of index.colChildren.get(cellKey(rootAddr)) ?? []) {
|
|
167
|
-
const binding = index.bindingAt(child);
|
|
168
|
-
if (binding && isColExpanding(binding) && child.row > rootAddr.row) return child;
|
|
169
|
-
}
|
|
170
|
-
return null;
|
|
171
|
-
}
|
|
172
|
-
var CoordinateEngine = class {
|
|
173
|
-
index;
|
|
174
|
-
data;
|
|
175
|
-
constructor(index, data) {
|
|
176
|
-
this.index = index;
|
|
177
|
-
this.data = data;
|
|
178
|
-
}
|
|
179
|
-
compute() {
|
|
180
|
-
const placements = [];
|
|
181
|
-
const consumedRows = /* @__PURE__ */ new Set();
|
|
182
|
-
let physRow = 0;
|
|
183
|
-
let maxCol = 0;
|
|
184
|
-
for (const logicalRow of this.index.logicalRows) {
|
|
185
|
-
if (consumedRows.has(logicalRow)) continue;
|
|
186
|
-
const rowRoot = findRowSubtreeRootOnRow(this.index, logicalRow);
|
|
187
|
-
if (rowRoot) {
|
|
188
|
-
const result = this.layoutRowSubtree(rowRoot, emptyCtx(), physRow, 0);
|
|
189
|
-
placements.push(...result.placements);
|
|
190
|
-
physRow += result.rowSpan;
|
|
191
|
-
maxCol = Math.max(maxCol, result.colSpan);
|
|
192
|
-
for (const row of expansionBandRows(rowRoot, this.index)) consumedRows.add(row);
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
const result = this.layoutStandaloneRow(logicalRow, emptyCtx(), physRow, 0);
|
|
196
|
-
placements.push(...result.placements);
|
|
197
|
-
physRow += result.rowSpan;
|
|
198
|
-
maxCol = Math.max(maxCol, result.colSpan);
|
|
199
|
-
}
|
|
200
|
-
return {
|
|
201
|
-
rowCount: physRow,
|
|
202
|
-
colCount: Math.max(maxCol, this.baseColCount()),
|
|
203
|
-
placements,
|
|
204
|
-
mappedMerges: mapTemplateMerges(this.index, placements)
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
baseColCount() {
|
|
208
|
-
if (this.index.logicalCols.length === 0) return 0;
|
|
209
|
-
return Math.max(...this.index.logicalCols) + 1;
|
|
210
|
-
}
|
|
211
|
-
layoutRowSubtree(rootAddr, ctx, physRowStart, physColStart) {
|
|
212
|
-
const rootBinding = this.index.bindingAt(rootAddr);
|
|
213
|
-
const parentFilter = parentFilterForBinding(rootBinding, this.index, ctx.rowFilter, ctx.colFilter);
|
|
214
|
-
const instances = enumerateExpansionInstances(rootBinding, this.data, mergeFilters(parentFilter, ctx.rowFilter));
|
|
215
|
-
const bandRows = expansionBandRows(rootAddr, this.index);
|
|
216
|
-
if (instances.length === 0) return {
|
|
217
|
-
rowSpan: 0,
|
|
218
|
-
colSpan: 0,
|
|
219
|
-
placements: []
|
|
220
|
-
};
|
|
221
|
-
if (rootBinding.aggregate === "list") {
|
|
222
|
-
const listCtx = {
|
|
223
|
-
rowFilter: mergeFilters(parentFilter, ctx.rowFilter),
|
|
224
|
-
colFilter: ctx.colFilter,
|
|
225
|
-
rowPath: ctx.rowPath,
|
|
226
|
-
colPath: ctx.colPath
|
|
227
|
-
};
|
|
228
|
-
const rowResult = this.layoutTemplateRow(rootAddr.row, listCtx, physRowStart, physColStart, rootAddr, instances.length);
|
|
229
|
-
const placements = [...rowResult.placements];
|
|
230
|
-
let totalRowSpan = instances.length;
|
|
231
|
-
for (const templateRow of bandRows) {
|
|
232
|
-
if (templateRow === rootAddr.row) continue;
|
|
233
|
-
const companionResult = this.layoutTemplateRow(templateRow, listCtx, physRowStart + totalRowSpan, physColStart, null, 1);
|
|
234
|
-
placements.push(...companionResult.placements);
|
|
235
|
-
totalRowSpan += companionResult.rowSpan;
|
|
236
|
-
}
|
|
237
|
-
return {
|
|
238
|
-
rowSpan: totalRowSpan,
|
|
239
|
-
colSpan: rowResult.colSpan,
|
|
240
|
-
placements
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
const placements = [];
|
|
244
|
-
let totalRowSpan = 0;
|
|
245
|
-
let maxColSpan = 0;
|
|
246
|
-
for (const instance of instances) {
|
|
247
|
-
const instanceCtx = {
|
|
248
|
-
rowFilter: instance.filter,
|
|
249
|
-
colFilter: ctx.colFilter,
|
|
250
|
-
rowPath: [...ctx.rowPath, instance.index],
|
|
251
|
-
colPath: ctx.colPath
|
|
252
|
-
};
|
|
253
|
-
const instanceHeight = this.measureSubtreeInstanceHeight(bandRows, rootAddr, instanceCtx);
|
|
254
|
-
const groupMergeHeight = this.measureTemplateRowHeight(rootAddr.row, instanceCtx, null);
|
|
255
|
-
if (this.bandHasMultiRowList(bandRows, instanceCtx)) {
|
|
256
|
-
const bandResult = this.layoutMultiRowListBand(bandRows, rootAddr, instanceCtx, physRowStart + totalRowSpan, physColStart, groupMergeHeight);
|
|
257
|
-
placements.push(...bandResult.placements);
|
|
258
|
-
maxColSpan = Math.max(maxColSpan, bandResult.colSpan);
|
|
259
|
-
totalRowSpan += instanceHeight;
|
|
260
|
-
continue;
|
|
261
|
-
}
|
|
262
|
-
let rowOffset = 0;
|
|
263
|
-
for (const templateRow of bandRows) {
|
|
264
|
-
const rowHeight = this.measureTemplateRowHeight(templateRow, instanceCtx, rootAddr);
|
|
265
|
-
const mergeHeight = templateRow === rootAddr.row ? groupMergeHeight : instanceHeight - rowOffset;
|
|
266
|
-
const rowResult = this.layoutTemplateRow(templateRow, instanceCtx, physRowStart + totalRowSpan + rowOffset, physColStart, rootAddr, mergeHeight);
|
|
267
|
-
placements.push(...rowResult.placements);
|
|
268
|
-
rowOffset += rowHeight;
|
|
269
|
-
maxColSpan = Math.max(maxColSpan, rowResult.colSpan);
|
|
270
|
-
}
|
|
271
|
-
totalRowSpan += instanceHeight;
|
|
272
|
-
}
|
|
273
|
-
return {
|
|
274
|
-
rowSpan: totalRowSpan,
|
|
275
|
-
colSpan: maxColSpan,
|
|
276
|
-
placements
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
measureSubtreeInstanceHeight(bandRows, rootAddr, ctx) {
|
|
280
|
-
let listDrivenHeight = 0;
|
|
281
|
-
let companionHeight = 0;
|
|
282
|
-
for (const row of bandRows) {
|
|
283
|
-
const listCount = this.listInstanceCountOnRow(row, ctx);
|
|
284
|
-
if (listCount > 0) {
|
|
285
|
-
listDrivenHeight = Math.max(listDrivenHeight, listCount);
|
|
286
|
-
continue;
|
|
287
|
-
}
|
|
288
|
-
if (row === rootAddr.row) continue;
|
|
289
|
-
companionHeight += this.measureTemplateRowHeight(row, ctx, rootAddr);
|
|
290
|
-
}
|
|
291
|
-
if (listDrivenHeight === 0) return this.measureTemplateRowHeight(rootAddr.row, ctx, null);
|
|
292
|
-
return listDrivenHeight + companionHeight;
|
|
293
|
-
}
|
|
294
|
-
bandHasMultiRowList(bandRows, ctx) {
|
|
295
|
-
let count = 0;
|
|
296
|
-
for (const row of bandRows) {
|
|
297
|
-
if (this.listInstanceCountOnRow(row, ctx) > 0) count++;
|
|
298
|
-
if (count > 1) return true;
|
|
299
|
-
}
|
|
300
|
-
return false;
|
|
301
|
-
}
|
|
302
|
-
layoutMultiRowListBand(bandRows, rootAddr, ctx, physRowStart, physColStart, groupMergeHeight) {
|
|
303
|
-
const listRows = bandRows.filter((row) => this.listInstanceCountOnRow(row, ctx) > 0);
|
|
304
|
-
const companionRows = bandRows.filter((row) => !listRows.includes(row));
|
|
305
|
-
const listCount = Math.max(...listRows.map((row) => this.listInstanceCountOnRow(row, ctx)), 1);
|
|
306
|
-
const placements = [];
|
|
307
|
-
let maxColSpan = 0;
|
|
308
|
-
for (let listIndex = 0; listIndex < listCount; listIndex++) for (const templateRow of listRows) {
|
|
309
|
-
const rowResult = this.layoutTemplateRow(templateRow, ctx, physRowStart + listIndex, physColStart, templateRow === rootAddr.row ? rootAddr : null, groupMergeHeight, false, listIndex, listCount);
|
|
310
|
-
placements.push(...rowResult.placements);
|
|
311
|
-
maxColSpan = Math.max(maxColSpan, rowResult.colSpan);
|
|
312
|
-
}
|
|
313
|
-
let rowOffset = listCount;
|
|
314
|
-
for (const templateRow of companionRows) {
|
|
315
|
-
const rowResult = this.layoutTemplateRow(templateRow, ctx, physRowStart + rowOffset, physColStart, null, 1);
|
|
316
|
-
placements.push(...rowResult.placements);
|
|
317
|
-
maxColSpan = Math.max(maxColSpan, rowResult.colSpan);
|
|
318
|
-
rowOffset += rowResult.rowSpan;
|
|
319
|
-
}
|
|
320
|
-
return {
|
|
321
|
-
rowSpan: rowOffset,
|
|
322
|
-
colSpan: maxColSpan,
|
|
323
|
-
placements
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
measureTemplateRowHeight(templateRow, ctx, rootAddr) {
|
|
327
|
-
for (const entry of this.index.bindingsOnRow(templateRow)) if (isNestedRowExpander(entry.binding, this.index)) return this.measureNestedRowBandHeight(entry.addr, entry.binding, templateRow, ctx);
|
|
328
|
-
const listCount = this.listInstanceCountOnRow(templateRow, ctx);
|
|
329
|
-
if (listCount > 0) return listCount;
|
|
330
|
-
if (rootAddr && templateRow === rootAddr.row) return 0;
|
|
331
|
-
return 1;
|
|
332
|
-
}
|
|
333
|
-
measureNestedRowBandHeight(groupAddr, groupBinding, templateRow, ctx) {
|
|
334
|
-
const parentFilter = parentFilterForBinding(groupBinding, this.index, ctx.rowFilter, ctx.colFilter);
|
|
335
|
-
const instances = enumerateExpansionInstances(groupBinding, this.data, mergeFilters(parentFilter, ctx.rowFilter));
|
|
336
|
-
if (instances.length === 0) return 0;
|
|
337
|
-
let total = 0;
|
|
338
|
-
for (const instance of instances) {
|
|
339
|
-
const instanceCtx = {
|
|
340
|
-
...ctx,
|
|
341
|
-
rowFilter: instance.filter,
|
|
342
|
-
rowPath: [...ctx.rowPath, instance.index]
|
|
343
|
-
};
|
|
344
|
-
total += this.listInstanceCountOnRow(templateRow, instanceCtx) || 1;
|
|
345
|
-
}
|
|
346
|
-
return total;
|
|
347
|
-
}
|
|
348
|
-
layoutStandaloneRow(templateRow, ctx, physRowStart, physColStart) {
|
|
349
|
-
return this.layoutTemplateRow(templateRow, ctx, physRowStart, physColStart, null, 1, !this.rowUsesPackedColumns(templateRow));
|
|
350
|
-
}
|
|
351
|
-
rowUsesPackedColumns(templateRow) {
|
|
352
|
-
for (const entry of this.index.bindingsOnRow(templateRow)) {
|
|
353
|
-
if (isColSubtreeRoot(entry.binding, this.index)) return true;
|
|
354
|
-
if (isNestedColExpander(entry.binding, this.index)) return true;
|
|
355
|
-
if (entry.binding.colParent) {
|
|
356
|
-
const parent = this.index.bindingAt(entry.binding.colParent);
|
|
357
|
-
if (parent && isColExpanding(parent)) return true;
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
return false;
|
|
361
|
-
}
|
|
362
|
-
layoutTemplateRow(templateRow, ctx, physRowStart, physColStart, rowSubtreeRoot, groupMergeHeight, preserveLogicalCols = false, fixedListIndex, mergeListCount) {
|
|
363
|
-
for (const entry of this.index.bindingsOnRow(templateRow)) if (isNestedRowExpander(entry.binding, this.index)) return this.layoutNestedRowBand(templateRow, entry.addr, entry.binding, ctx, physRowStart, physColStart);
|
|
364
|
-
const cols = columnsOnRow(this.index, templateRow);
|
|
365
|
-
const placements = [];
|
|
366
|
-
let physCol = physColStart;
|
|
367
|
-
const packedCols = !preserveLogicalCols && this.rowUsesPackedColumns(templateRow);
|
|
368
|
-
const listCount = this.listInstanceCountOnRow(templateRow, ctx);
|
|
369
|
-
const rowSpan = fixedListIndex !== void 0 ? 1 : Math.max(listCount, 1);
|
|
370
|
-
const leadingGap = cols.length > 0 && cols[0] > physColStart;
|
|
371
|
-
for (const col of cols) {
|
|
372
|
-
const addr = {
|
|
373
|
-
row: templateRow,
|
|
374
|
-
col
|
|
375
|
-
};
|
|
376
|
-
const binding = this.index.bindingAt(addr);
|
|
377
|
-
const targetCol = packedCols && !leadingGap ? physCol : col;
|
|
378
|
-
if (binding && isColSubtreeRoot(binding, this.index)) {
|
|
379
|
-
const colResult = this.layoutColSubtree(addr, ctx, physRowStart, targetCol);
|
|
380
|
-
placements.push(...colResult.placements);
|
|
381
|
-
if (packedCols) physCol = leadingGap ? targetCol + colResult.colSpan : physCol + colResult.colSpan;
|
|
382
|
-
continue;
|
|
383
|
-
}
|
|
384
|
-
if (binding && isNestedColExpander(binding, this.index)) {
|
|
385
|
-
const colResult = this.layoutNestedColBand(addr, binding, ctx, physRowStart, targetCol);
|
|
386
|
-
placements.push(...colResult.placements);
|
|
387
|
-
if (packedCols) physCol = leadingGap ? targetCol + colResult.colSpan : physCol + colResult.colSpan;
|
|
388
|
-
continue;
|
|
389
|
-
}
|
|
390
|
-
if (binding && this.isInlineColChild(templateRow, col)) continue;
|
|
391
|
-
if (binding && binding.colParent && !isColExpanding(binding)) {
|
|
392
|
-
const colResult = this.layoutColParentAlignedCell(addr, binding, ctx, physRowStart, targetCol, rowSpan);
|
|
393
|
-
placements.push(...colResult.placements);
|
|
394
|
-
if (packedCols) physCol = leadingGap ? targetCol + colResult.colSpan : physCol + colResult.colSpan;
|
|
395
|
-
continue;
|
|
396
|
-
}
|
|
397
|
-
if (binding) {
|
|
398
|
-
const cellResult = this.layoutBindingCell(addr, binding, ctx, physRowStart, targetCol, rowSpan, rowSubtreeRoot, groupMergeHeight, fixedListIndex, mergeListCount);
|
|
399
|
-
placements.push(...cellResult.placements);
|
|
400
|
-
if (packedCols) physCol = leadingGap ? targetCol + cellResult.colSpan : physCol + cellResult.colSpan;
|
|
401
|
-
continue;
|
|
402
|
-
}
|
|
403
|
-
if (this.index.cellAt(addr)) {
|
|
404
|
-
if (rowSpan > 1) for (let i = 0; i < rowSpan; i++) placements.push(this.makePlacement(addr, singleCellRange(physRowStart + i, targetCol), ctx, void 0, i, false));
|
|
405
|
-
else placements.push(this.makePlacement(addr, singleCellRange(physRowStart, targetCol), ctx, void 0, 0, false));
|
|
406
|
-
if (packedCols) physCol = leadingGap ? targetCol + 1 : physCol + 1;
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
const effectiveColSpan = packedCols ? leadingGap && cols.length > 0 ? Math.max(...cols) + 1 - physColStart : physCol - physColStart : cols.length > 0 ? Math.max(...cols) + 1 - physColStart : 0;
|
|
410
|
-
return {
|
|
411
|
-
rowSpan: rowSubtreeRoot && templateRow === rowSubtreeRoot.row && listCount === 0 ? 0 : rowSpan,
|
|
412
|
-
colSpan: effectiveColSpan,
|
|
413
|
-
placements
|
|
414
|
-
};
|
|
415
|
-
}
|
|
416
|
-
layoutNestedRowBand(templateRow, groupAddr, groupBinding, ctx, physRowStart, physColStart) {
|
|
417
|
-
const parentFilter = parentFilterForBinding(groupBinding, this.index, ctx.rowFilter, ctx.colFilter);
|
|
418
|
-
const instances = enumerateExpansionInstances(groupBinding, this.data, mergeFilters(parentFilter, ctx.rowFilter));
|
|
419
|
-
if (instances.length === 0) return {
|
|
420
|
-
rowSpan: 0,
|
|
421
|
-
colSpan: 0,
|
|
422
|
-
placements: []
|
|
423
|
-
};
|
|
424
|
-
const placements = [];
|
|
425
|
-
let rowOffset = 0;
|
|
426
|
-
let maxColSpan = 0;
|
|
427
|
-
const colOffsets = this.rowLogicalColOffsets(templateRow, physColStart);
|
|
428
|
-
for (const instance of instances) {
|
|
429
|
-
const instanceCtx = {
|
|
430
|
-
...ctx,
|
|
431
|
-
rowFilter: instance.filter,
|
|
432
|
-
rowPath: [...ctx.rowPath, instance.index]
|
|
433
|
-
};
|
|
434
|
-
const detailCount = this.listInstanceCountOnRow(templateRow, instanceCtx) || 1;
|
|
435
|
-
if (mergeSpanEnabled(groupBinding)) placements.push(this.makePlacement(groupAddr, createRange({
|
|
436
|
-
row: physRowStart + rowOffset,
|
|
437
|
-
col: physColStart
|
|
438
|
-
}, {
|
|
439
|
-
row: physRowStart + rowOffset + detailCount - 1,
|
|
440
|
-
col: physColStart
|
|
441
|
-
}), instanceCtx, groupBinding, 0, true));
|
|
442
|
-
else for (let i = 0; i < detailCount; i++) placements.push(this.makePlacement(groupAddr, singleCellRange(physRowStart + rowOffset + i, physColStart), instanceCtx, groupBinding, i, false));
|
|
443
|
-
for (const entry of this.index.bindingsOnRow(templateRow)) {
|
|
444
|
-
if (sameAddress(entry.addr, groupAddr)) continue;
|
|
445
|
-
if (!isRowExpanding(entry.binding) || entry.binding.aggregate !== "list") continue;
|
|
446
|
-
for (let i = 0; i < detailCount; i++) placements.push(this.makePlacement(entry.addr, singleCellRange(physRowStart + rowOffset + i, colOffsets.get(entry.addr.col)), instanceCtx, entry.binding, i, false));
|
|
447
|
-
}
|
|
448
|
-
for (const col of columnsOnRow(this.index, templateRow)) {
|
|
449
|
-
if (this.index.bindingAt({
|
|
450
|
-
row: templateRow,
|
|
451
|
-
col
|
|
452
|
-
})) continue;
|
|
453
|
-
if (!this.index.cellAt({
|
|
454
|
-
row: templateRow,
|
|
455
|
-
col
|
|
456
|
-
})) continue;
|
|
457
|
-
for (let i = 0; i < detailCount; i++) placements.push(this.makePlacement({
|
|
458
|
-
row: templateRow,
|
|
459
|
-
col
|
|
460
|
-
}, singleCellRange(physRowStart + rowOffset + i, colOffsets.get(col)), instanceCtx, void 0, i, false));
|
|
461
|
-
}
|
|
462
|
-
maxColSpan = Math.max(maxColSpan, colOffsets.size);
|
|
463
|
-
rowOffset += detailCount;
|
|
464
|
-
}
|
|
465
|
-
return {
|
|
466
|
-
rowSpan: rowOffset,
|
|
467
|
-
colSpan: maxColSpan,
|
|
468
|
-
placements
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
layoutBindingCell(addr, binding, ctx, physRowStart, physColStart, rowSpan, rowSubtreeRoot, groupMergeHeight, fixedListIndex, mergeListCount) {
|
|
472
|
-
if (rowSubtreeRoot && isRowExpanding(binding) && binding.aggregate === "group" && sameAddress(addr, rowSubtreeRoot)) {
|
|
473
|
-
if (fixedListIndex !== void 0 && fixedListIndex > 0) return {
|
|
474
|
-
rowSpan: 0,
|
|
475
|
-
colSpan: 1,
|
|
476
|
-
placements: []
|
|
477
|
-
};
|
|
478
|
-
const mergeRows = Math.max(fixedListIndex !== void 0 ? mergeListCount ?? groupMergeHeight : groupMergeHeight, 1);
|
|
479
|
-
if (!mergeSpanEnabled(binding)) return {
|
|
480
|
-
rowSpan: 0,
|
|
481
|
-
colSpan: 1,
|
|
482
|
-
placements: Array.from({ length: mergeRows }, (_, listIndex) => this.makePlacement(addr, singleCellRange(physRowStart + listIndex, physColStart), ctx, binding, listIndex, false))
|
|
483
|
-
};
|
|
484
|
-
const range = createRange({
|
|
485
|
-
row: physRowStart,
|
|
486
|
-
col: physColStart
|
|
487
|
-
}, {
|
|
488
|
-
row: physRowStart + mergeRows - 1,
|
|
489
|
-
col: physColStart
|
|
490
|
-
});
|
|
491
|
-
return {
|
|
492
|
-
rowSpan: 0,
|
|
493
|
-
colSpan: 1,
|
|
494
|
-
placements: [this.makePlacement(addr, range, ctx, binding, 0, true)]
|
|
495
|
-
};
|
|
496
|
-
}
|
|
497
|
-
if (isRowExpanding(binding) && binding.aggregate === "list") {
|
|
498
|
-
if (fixedListIndex !== void 0) return {
|
|
499
|
-
rowSpan: 0,
|
|
500
|
-
colSpan: 1,
|
|
501
|
-
placements: [this.makePlacement(addr, singleCellRange(physRowStart, physColStart), ctx, binding, fixedListIndex, false)]
|
|
502
|
-
};
|
|
503
|
-
return {
|
|
504
|
-
rowSpan: 0,
|
|
505
|
-
colSpan: 1,
|
|
506
|
-
placements: Array.from({ length: rowSpan }, (_, listIndex) => this.makePlacement(addr, singleCellRange(physRowStart + listIndex, physColStart), ctx, binding, listIndex, false))
|
|
507
|
-
};
|
|
508
|
-
}
|
|
509
|
-
return {
|
|
510
|
-
rowSpan: 0,
|
|
511
|
-
colSpan: 1,
|
|
512
|
-
placements: [this.makePlacement(addr, expandRows(singleCellRange(physRowStart, physColStart), rowSpan), ctx, binding, 0, mergeSpanEnabled(binding) && rowSpan > 1)]
|
|
513
|
-
};
|
|
514
|
-
}
|
|
515
|
-
layoutColSubtree(rootAddr, ctx, physRowStart, physColStart) {
|
|
516
|
-
const rootBinding = this.index.bindingAt(rootAddr);
|
|
517
|
-
const parentFilter = parentFilterForBinding(rootBinding, this.index, ctx.rowFilter, ctx.colFilter);
|
|
518
|
-
const instances = enumerateExpansionInstances(rootBinding, this.data, mergeFilters(parentFilter, ctx.colFilter));
|
|
519
|
-
if (instances.length === 0) return {
|
|
520
|
-
rowSpan: 0,
|
|
521
|
-
colSpan: 0,
|
|
522
|
-
placements: []
|
|
523
|
-
};
|
|
524
|
-
const placements = [];
|
|
525
|
-
let totalColSpan = 0;
|
|
526
|
-
for (const instance of instances) {
|
|
527
|
-
const instanceCtx = {
|
|
528
|
-
rowFilter: ctx.rowFilter,
|
|
529
|
-
colFilter: instance.filter,
|
|
530
|
-
rowPath: ctx.rowPath,
|
|
531
|
-
colPath: [...ctx.colPath, instance.index]
|
|
532
|
-
};
|
|
533
|
-
const width = this.colInstanceWidth(rootAddr, instanceCtx);
|
|
534
|
-
const range = createRange({
|
|
535
|
-
row: physRowStart,
|
|
536
|
-
col: physColStart + totalColSpan
|
|
537
|
-
}, {
|
|
538
|
-
row: physRowStart,
|
|
539
|
-
col: physColStart + totalColSpan + width - 1
|
|
540
|
-
});
|
|
541
|
-
placements.push(this.makePlacement(rootAddr, range, instanceCtx, rootBinding, rootBinding.aggregate === "list" ? instance.index : 0, mergeSpanEnabled(rootBinding)));
|
|
542
|
-
totalColSpan += width;
|
|
543
|
-
}
|
|
544
|
-
return {
|
|
545
|
-
rowSpan: 1,
|
|
546
|
-
colSpan: totalColSpan,
|
|
547
|
-
placements
|
|
548
|
-
};
|
|
549
|
-
}
|
|
550
|
-
layoutNestedColBand(addr, binding, ctx, physRowStart, physColStart) {
|
|
551
|
-
const parentAddr = binding.colParent;
|
|
552
|
-
const parentBinding = this.index.bindingAt(parentAddr);
|
|
553
|
-
const parentFilter = parentFilterForBinding(parentBinding, this.index, ctx.rowFilter, ctx.colFilter);
|
|
554
|
-
const parentInstances = enumerateExpansionInstances(parentBinding, this.data, mergeFilters(parentFilter, ctx.colFilter));
|
|
555
|
-
const placements = [];
|
|
556
|
-
let colOffset = 0;
|
|
557
|
-
for (const parentInstance of parentInstances) {
|
|
558
|
-
const bandCtx = {
|
|
559
|
-
...ctx,
|
|
560
|
-
colFilter: parentInstance.filter,
|
|
561
|
-
colPath: [...ctx.colPath, parentInstance.index]
|
|
562
|
-
};
|
|
563
|
-
const childFilter = parentFilterForBinding(binding, this.index, bandCtx.rowFilter, bandCtx.colFilter);
|
|
564
|
-
const childInstances = enumerateExpansionInstances(binding, this.data, mergeFilters(childFilter, bandCtx.colFilter));
|
|
565
|
-
for (const childInstance of childInstances) {
|
|
566
|
-
const childCtx = {
|
|
567
|
-
...bandCtx,
|
|
568
|
-
colFilter: childInstance.filter,
|
|
569
|
-
colPath: [...bandCtx.colPath, childInstance.index]
|
|
570
|
-
};
|
|
571
|
-
placements.push(this.makePlacement(addr, singleCellRange(physRowStart, physColStart + colOffset), childCtx, binding, 0, false));
|
|
572
|
-
colOffset++;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
return {
|
|
576
|
-
rowSpan: 1,
|
|
577
|
-
colSpan: colOffset,
|
|
578
|
-
placements
|
|
579
|
-
};
|
|
580
|
-
}
|
|
581
|
-
colInstanceWidth(rootAddr, ctx) {
|
|
582
|
-
const nestedChild = findNestedColChild(rootAddr, this.index);
|
|
583
|
-
if (nestedChild) {
|
|
584
|
-
const binding = this.index.bindingAt(nestedChild);
|
|
585
|
-
const parentFilter = parentFilterForBinding(binding, this.index, ctx.rowFilter, ctx.colFilter);
|
|
586
|
-
const instances = enumerateExpansionInstances(binding, this.data, mergeFilters(parentFilter, ctx.colFilter));
|
|
587
|
-
return Math.max(instances.length, 1);
|
|
588
|
-
}
|
|
589
|
-
if (!mergeSpanEnabled(this.index.bindingAt(rootAddr))) return 1;
|
|
590
|
-
let width = 0;
|
|
591
|
-
for (const col of colSubtreeCols(rootAddr, this.index)) {
|
|
592
|
-
if (col <= rootAddr.col) continue;
|
|
593
|
-
if (this.index.bindingAt({
|
|
594
|
-
row: rootAddr.row,
|
|
595
|
-
col
|
|
596
|
-
}) || this.index.cellAt({
|
|
597
|
-
row: rootAddr.row,
|
|
598
|
-
col
|
|
599
|
-
})) width++;
|
|
600
|
-
}
|
|
601
|
-
return Math.max(width, 1);
|
|
602
|
-
}
|
|
603
|
-
layoutColParentAlignedCell(addr, binding, ctx, physRowStart, physColStart, rowSpan) {
|
|
604
|
-
const colParent = binding.colParent;
|
|
605
|
-
const parentBinding = this.index.bindingAt(colParent);
|
|
606
|
-
const parentFilter = parentFilterForBinding(parentBinding, this.index, ctx.rowFilter, ctx.colFilter);
|
|
607
|
-
const instances = enumerateExpansionInstances(parentBinding, this.data, mergeFilters(parentFilter, ctx.colFilter));
|
|
608
|
-
if (instances.length === 0) return {
|
|
609
|
-
rowSpan: 0,
|
|
610
|
-
colSpan: 0,
|
|
611
|
-
placements: []
|
|
612
|
-
};
|
|
613
|
-
const placements = [];
|
|
614
|
-
let colOffset = 0;
|
|
615
|
-
for (const instance of instances) {
|
|
616
|
-
const instanceCtx = {
|
|
617
|
-
rowFilter: ctx.rowFilter,
|
|
618
|
-
colFilter: instance.filter,
|
|
619
|
-
rowPath: ctx.rowPath,
|
|
620
|
-
colPath: [...ctx.colPath, instance.index]
|
|
621
|
-
};
|
|
622
|
-
const width = this.colInstanceWidth(colParent, instanceCtx);
|
|
623
|
-
placements.push(this.makePlacement(addr, expandRows(singleCellRange(physRowStart, physColStart + colOffset), rowSpan), instanceCtx, binding, 0, mergeSpanEnabled(binding) && rowSpan > 1));
|
|
624
|
-
colOffset += width;
|
|
625
|
-
}
|
|
626
|
-
return {
|
|
627
|
-
rowSpan: 0,
|
|
628
|
-
colSpan: colOffset,
|
|
629
|
-
placements
|
|
630
|
-
};
|
|
631
|
-
}
|
|
632
|
-
isInlineColChild(row, col) {
|
|
633
|
-
const binding = this.index.bindingAt({
|
|
634
|
-
row,
|
|
635
|
-
col
|
|
636
|
-
});
|
|
637
|
-
if (!binding?.colParent) return false;
|
|
638
|
-
const parent = this.index.bindingAt(binding.colParent);
|
|
639
|
-
if (!parent || !isColExpanding(parent)) return false;
|
|
640
|
-
return binding.colParent.row === row;
|
|
641
|
-
}
|
|
642
|
-
listInstanceCountOnRow(templateRow, ctx) {
|
|
643
|
-
let count = 0;
|
|
644
|
-
for (const entry of this.index.bindingsOnRow(templateRow)) {
|
|
645
|
-
if (!isRowExpanding(entry.binding) || entry.binding.aggregate !== "list") continue;
|
|
646
|
-
const parentFilter = parentFilterForBinding(entry.binding, this.index, ctx.rowFilter, ctx.colFilter);
|
|
647
|
-
const instances = enumerateExpansionInstances(entry.binding, this.data, mergeFilters(parentFilter, ctx.rowFilter));
|
|
648
|
-
count = Math.max(count, instances.length);
|
|
649
|
-
}
|
|
650
|
-
return count;
|
|
651
|
-
}
|
|
652
|
-
rowLogicalColOffsets(templateRow, physColStart) {
|
|
653
|
-
const offsets = /* @__PURE__ */ new Map();
|
|
654
|
-
let physCol = physColStart;
|
|
655
|
-
for (const col of columnsOnRow(this.index, templateRow)) {
|
|
656
|
-
offsets.set(col, physCol);
|
|
657
|
-
physCol++;
|
|
658
|
-
}
|
|
659
|
-
return offsets;
|
|
660
|
-
}
|
|
661
|
-
makePlacement(logical, physical, ctx, binding, listIndex, mergeSpan) {
|
|
662
|
-
return {
|
|
663
|
-
logical,
|
|
664
|
-
physical,
|
|
665
|
-
rowPath: ctx.rowPath,
|
|
666
|
-
colPath: ctx.colPath,
|
|
667
|
-
mergeSpan,
|
|
668
|
-
binding,
|
|
669
|
-
listIndex
|
|
670
|
-
};
|
|
671
|
-
}
|
|
672
|
-
};
|
|
673
|
-
function emptyCtx() {
|
|
674
|
-
return {
|
|
675
|
-
rowFilter: {},
|
|
676
|
-
colFilter: {},
|
|
677
|
-
rowPath: [],
|
|
678
|
-
colPath: []
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
function expandRows(range, rowSpan) {
|
|
682
|
-
if (rowSpan <= 1) return range;
|
|
683
|
-
return createRange(range.start, {
|
|
684
|
-
row: range.start.row + rowSpan - 1,
|
|
685
|
-
col: range.end.col
|
|
686
|
-
});
|
|
687
|
-
}
|
|
688
|
-
/** 将模板合并区域映射到物理网格(基于锚点格的物理落点) */
|
|
689
|
-
function mapTemplateMerges(index, placements) {
|
|
690
|
-
const layout = {
|
|
691
|
-
rowCount: 0,
|
|
692
|
-
colCount: 0,
|
|
693
|
-
placements,
|
|
694
|
-
mappedMerges: []
|
|
695
|
-
};
|
|
696
|
-
const mapped = [];
|
|
697
|
-
for (const merge of index.merges) {
|
|
698
|
-
const mappedRange = mapLogicalMerge(merge, layout);
|
|
699
|
-
if (mappedRange) mapped.push(mappedRange);
|
|
700
|
-
}
|
|
701
|
-
return mapped;
|
|
702
|
-
}
|
|
703
|
-
function mapLogicalMerge(merge, layout) {
|
|
704
|
-
const startHits = placementsAt(layout, merge.start);
|
|
705
|
-
if (startHits.length === 0) return null;
|
|
706
|
-
const startPlacement = startHits[0];
|
|
707
|
-
const endHits = placementsAt(layout, merge.end);
|
|
708
|
-
if (endHits.length > 0) return createRange(startPlacement.physical.start, endHits[endHits.length - 1].physical.end);
|
|
709
|
-
const logicalRowSpan = merge.end.row - merge.start.row;
|
|
710
|
-
const logicalColSpan = merge.end.col - merge.start.col;
|
|
711
|
-
return createRange(startPlacement.physical.start, {
|
|
712
|
-
row: startPlacement.physical.start.row + logicalRowSpan,
|
|
713
|
-
col: startPlacement.physical.start.col + logicalColSpan
|
|
714
|
-
});
|
|
715
|
-
}
|
|
716
|
-
/** 计算扩展坐标系:逻辑格 → 物理区间映射(纯计算、无快照输出) */
|
|
717
|
-
function computeExpansionLayout(index, data) {
|
|
718
|
-
return new CoordinateEngine(index, data).compute();
|
|
719
|
-
}
|
|
720
|
-
/** 按逻辑地址查找全部物理落点 */
|
|
721
|
-
function placementsAt(layout, addr) {
|
|
722
|
-
return layout.placements.filter((p) => sameAddress(p.logical, addr));
|
|
723
|
-
}
|
|
724
|
-
/** 物理区间行高(含合并) */
|
|
725
|
-
function physicalRowSpan(placement) {
|
|
726
|
-
return rangeRows(placement.physical);
|
|
727
|
-
}
|
|
728
|
-
/** 物理区间列宽(含合并) */
|
|
729
|
-
function physicalColSpan(placement) {
|
|
730
|
-
return rangeCols(placement.physical);
|
|
731
|
-
}
|
|
732
|
-
//#endregion
|
|
733
|
-
export { computeExpansionLayout, enumerateExpansionInstances, mapTemplateMerges, physicalColSpan, physicalRowSpan, placementsAt };
|