canvas-datagrid 0.25.3 → 0.26.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/CHANGELOG.md +328 -1
- package/README.md +85 -67
- package/dist/canvas-datagrid.debug.js +7606 -3099
- package/dist/canvas-datagrid.debug.map +1 -1
- package/dist/canvas-datagrid.js +1 -1
- package/dist/canvas-datagrid.module.js +1 -1
- package/dist/canvas-datagrid.module.js.map +1 -1
- package/dist/types.d.ts +2508 -0
- package/lib/button.js +326 -0
- package/lib/component.js +51 -13
- package/lib/contextMenu.js +408 -30
- package/lib/defaults.js +100 -7
- package/lib/docs.js +121 -11
- package/lib/dom.js +239 -18
- package/lib/draw.js +1446 -206
- package/lib/events/index.js +2640 -0
- package/lib/events/util.js +165 -0
- package/lib/groups/util.js +42 -0
- package/lib/intf.js +908 -87
- package/lib/main.js +8 -1
- package/lib/publicMethods.js +773 -377
- package/lib/selections/index.js +989 -0
- package/lib/selections/type.d.ts +38 -0
- package/lib/selections/util.js +1320 -0
- package/lib/touch.js +20 -47
- package/package.json +32 -21
- package/lib/events.js +0 -1741
package/lib/draw.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
/*globals XMLSerializer: false, define: true, Blob: false, MutationObserver: false, requestAnimationFrame: false, performance: false, btoa: false*/
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
+
import { isCellSelected } from './selections/util';
|
|
6
|
+
|
|
5
7
|
export default function (self) {
|
|
6
8
|
var perfCounters = [],
|
|
7
9
|
cachedImagesDrawn = false,
|
|
@@ -108,6 +110,98 @@ export default function (self) {
|
|
|
108
110
|
'</svg>\n',
|
|
109
111
|
);
|
|
110
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* @param {number[]} coords [x0,y0, x1,y1, x2,y2, ...]
|
|
115
|
+
* @param {boolean} [fill] fill the area that construct by these lines but not stroke
|
|
116
|
+
*/
|
|
117
|
+
function drawLines(coords, fill) {
|
|
118
|
+
if (coords.length < 4) return;
|
|
119
|
+
self.ctx.beginPath();
|
|
120
|
+
self.ctx.moveTo(
|
|
121
|
+
coords[0] + self.canvasOffsetLeft,
|
|
122
|
+
coords[1] + self.canvasOffsetTop,
|
|
123
|
+
);
|
|
124
|
+
for (let i = 2; i < coords.length; i += 2) {
|
|
125
|
+
const x = coords[i] + self.canvasOffsetLeft;
|
|
126
|
+
const y = coords[i + 1] + self.canvasOffsetTop;
|
|
127
|
+
self.ctx.lineTo(x, y);
|
|
128
|
+
}
|
|
129
|
+
if (fill) self.ctx.fill();
|
|
130
|
+
else self.ctx.stroke();
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* @param {number} x based-X (left-top)
|
|
134
|
+
* @param {number} y based-Y (left-top)
|
|
135
|
+
* @param {number} width
|
|
136
|
+
* @param {boolean} collapsed true: '+'; false: '-'
|
|
137
|
+
*/
|
|
138
|
+
function drawGroupHandle(x, y, width, collapsed) {
|
|
139
|
+
fillRect(x, y, width, width);
|
|
140
|
+
strokeRect(x, y, width, width);
|
|
141
|
+
const cx = x + width * 0.5;
|
|
142
|
+
const cy = y + width * 0.5;
|
|
143
|
+
drawLines([x + width * 0.2, cy, x + width * 0.78, cy]);
|
|
144
|
+
if (collapsed) drawLines([cx, y + width * 0.22, cx, y + width * 0.8]);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* @param {number} x
|
|
148
|
+
* @param {number} y
|
|
149
|
+
* @param {number} size
|
|
150
|
+
* @param {string} dir Direction of the triangle, one of the 't','b','l' and 'r'
|
|
151
|
+
* @param {boolean} [active]
|
|
152
|
+
*/
|
|
153
|
+
function drawUnhideIndicator(x, y, size, dir, active) {
|
|
154
|
+
const minPadding = size * 0.2;
|
|
155
|
+
const maxPadding = size * 0.3;
|
|
156
|
+
/** The long edge width of the triangle */
|
|
157
|
+
const longEdge = size - 2 * minPadding;
|
|
158
|
+
/** The median width of the triangle */
|
|
159
|
+
const median = size - 2 * maxPadding;
|
|
160
|
+
const halfLongEdge = longEdge * 0.5;
|
|
161
|
+
let x0, y0;
|
|
162
|
+
let coords, borderCoords;
|
|
163
|
+
switch (dir) {
|
|
164
|
+
case 'r':
|
|
165
|
+
x0 = x + maxPadding;
|
|
166
|
+
y0 = y + minPadding;
|
|
167
|
+
borderCoords = [x, y, x + size, y, x + size, y + size, x, y + size];
|
|
168
|
+
coords = [x0, y0, x0, y0 + longEdge, x0 + median, y0 + halfLongEdge];
|
|
169
|
+
break;
|
|
170
|
+
case 'l':
|
|
171
|
+
x0 = x + size - maxPadding;
|
|
172
|
+
y0 = y + minPadding;
|
|
173
|
+
borderCoords = [x + size, y, x, y, x, y + size, x + size, y + size];
|
|
174
|
+
coords = [x0, y0, x0, y0 + longEdge, x0 - median, y0 + halfLongEdge];
|
|
175
|
+
break;
|
|
176
|
+
case 't':
|
|
177
|
+
x0 = x + minPadding;
|
|
178
|
+
y0 = y + size - maxPadding;
|
|
179
|
+
borderCoords = [x, y + size, x, y, x + size, y, x + size, y + size];
|
|
180
|
+
coords = [x0, y0, x0 + longEdge, y0, x0 + halfLongEdge, y0 - median];
|
|
181
|
+
break;
|
|
182
|
+
case 'b':
|
|
183
|
+
x0 = x + minPadding;
|
|
184
|
+
y0 = y + maxPadding;
|
|
185
|
+
borderCoords = [x, y, x, y + size, x + size, y + size, x + size, y];
|
|
186
|
+
coords = [x0, y0, x0 + longEdge, y0, x0 + halfLongEdge, y0 + median];
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (active) {
|
|
191
|
+
self.ctx.strokeStyle = self.style.unhideIndicatorBorderColor;
|
|
192
|
+
self.ctx.lineWidth = 2;
|
|
193
|
+
drawLines(borderCoords);
|
|
194
|
+
|
|
195
|
+
self.ctx.fillStyle = self.style.unhideIndicatorBackgroundColor;
|
|
196
|
+
let offset = dir === 'r' || dir === 'b' ? 1 : 0;
|
|
197
|
+
if (dir === 'l' || dir === 'r')
|
|
198
|
+
fillRect(x - offset, y, size + offset, size);
|
|
199
|
+
else fillRect(x, y - offset, size, size + offset);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
self.ctx.fillStyle = self.style.unhideIndicatorColor;
|
|
203
|
+
drawLines(coords, true);
|
|
204
|
+
}
|
|
111
205
|
function drawOrderByArrow(x, y) {
|
|
112
206
|
var mt = self.style.columnHeaderOrderByArrowMarginTop * self.scale,
|
|
113
207
|
ml = self.style.columnHeaderOrderByArrowMarginLeft * self.scale,
|
|
@@ -122,15 +216,15 @@ export default function (self) {
|
|
|
122
216
|
x = x + ml;
|
|
123
217
|
y = y + mt;
|
|
124
218
|
if (self.orderDirection === 'asc') {
|
|
125
|
-
self.ctx.moveTo(x, y);
|
|
126
|
-
self.ctx.lineTo(x + aw, y);
|
|
127
|
-
self.ctx.lineTo(x + aw * 0.5, y + ah);
|
|
128
|
-
self.ctx.moveTo(x, y);
|
|
129
|
-
} else {
|
|
130
219
|
self.ctx.lineTo(x, y + ah);
|
|
131
220
|
self.ctx.lineTo(x + aw, y + ah);
|
|
132
221
|
self.ctx.lineTo(x + aw * 0.5, y);
|
|
133
222
|
self.ctx.lineTo(x, y + ah);
|
|
223
|
+
} else {
|
|
224
|
+
self.ctx.moveTo(x, y);
|
|
225
|
+
self.ctx.lineTo(x + aw, y);
|
|
226
|
+
self.ctx.lineTo(x + aw * 0.5, y + ah);
|
|
227
|
+
self.ctx.moveTo(x, y);
|
|
134
228
|
}
|
|
135
229
|
self.ctx.stroke();
|
|
136
230
|
self.ctx.fill();
|
|
@@ -164,6 +258,82 @@ export default function (self) {
|
|
|
164
258
|
self.ctx.fill();
|
|
165
259
|
return ml + aw + mr;
|
|
166
260
|
}
|
|
261
|
+
function drawCellTreeIcon(cell, tree, rowTree) {
|
|
262
|
+
const parentCount = rowTree ? tree.parentCount : 0;
|
|
263
|
+
const iconSize = self.style.cellTreeIconWidth * self.scale,
|
|
264
|
+
marginTop = self.style.cellTreeIconMarginTop * self.scale,
|
|
265
|
+
marginRight = self.style.cellTreeIconMarginRight * self.scale,
|
|
266
|
+
marginLeft =
|
|
267
|
+
self.style.cellTreeIconMarginLeft * self.scale +
|
|
268
|
+
parentCount * (iconSize + cell.paddingLeft);
|
|
269
|
+
|
|
270
|
+
let x = cell.x + cell.paddingLeft + self.canvasOffsetLeft + marginLeft,
|
|
271
|
+
y = cell.y + self.canvasOffsetTop + marginTop;
|
|
272
|
+
|
|
273
|
+
if (tree.icon) {
|
|
274
|
+
self.ctx.beginPath();
|
|
275
|
+
const oldFillStyle = self.ctx.fillStyle;
|
|
276
|
+
const oldStrokeStyle = self.ctx.strokeStyle;
|
|
277
|
+
|
|
278
|
+
if (cell.hovered && self.hovers.onCellTreeIcon) {
|
|
279
|
+
self.ctx.fillStyle = self.style.cellTreeIconHoverFillColor;
|
|
280
|
+
} else {
|
|
281
|
+
self.ctx.fillStyle = self.style.cellTreeIconFillColor;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
self.ctx.fillRect(x, y, iconSize, iconSize);
|
|
285
|
+
self.ctx.strokeStyle = self.style.cellTreeIconBorderColor;
|
|
286
|
+
self.ctx.rect(x, y, iconSize, iconSize);
|
|
287
|
+
self.ctx.stroke();
|
|
288
|
+
|
|
289
|
+
self.ctx.beginPath();
|
|
290
|
+
if (tree.expand) {
|
|
291
|
+
self.ctx.moveTo(x + 3, y + iconSize * 0.5);
|
|
292
|
+
self.ctx.lineTo(x + iconSize - 3, y + iconSize * 0.5);
|
|
293
|
+
} else {
|
|
294
|
+
self.ctx.moveTo(x + 2, y + iconSize * 0.5);
|
|
295
|
+
self.ctx.lineTo(x + iconSize - 2, y + iconSize * 0.5);
|
|
296
|
+
self.ctx.moveTo(x + iconSize * 0.5, y + 2);
|
|
297
|
+
self.ctx.lineTo(x + iconSize * 0.5, y + iconSize - 2);
|
|
298
|
+
}
|
|
299
|
+
self.ctx.lineWidth = self.style.cellTreeIconLineWidth;
|
|
300
|
+
self.ctx.strokeStyle = self.style.cellTreeIconLineColor;
|
|
301
|
+
self.ctx.stroke();
|
|
302
|
+
|
|
303
|
+
self.ctx.strokeStyle = oldStrokeStyle;
|
|
304
|
+
self.ctx.fillStyle = oldFillStyle;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return marginLeft + iconSize + marginRight;
|
|
308
|
+
}
|
|
309
|
+
function drawFilterButtonArrow(x, y) {
|
|
310
|
+
var mt =
|
|
311
|
+
((self.style.filterButtonHeight - self.style.filterButtonArrowHeight) /
|
|
312
|
+
2) *
|
|
313
|
+
self.scale,
|
|
314
|
+
ml =
|
|
315
|
+
((self.style.filterButtonWidth - self.style.filterButtonArrowWidth) /
|
|
316
|
+
2) *
|
|
317
|
+
self.scale,
|
|
318
|
+
aw = self.style.filterButtonArrowWidth * self.scale,
|
|
319
|
+
ah = self.style.filterButtonArrowHeight * self.scale;
|
|
320
|
+
x += self.canvasOffsetLeft;
|
|
321
|
+
y += self.canvasOffsetTop;
|
|
322
|
+
self.ctx.fillStyle = self.style.filterButtonArrowColor;
|
|
323
|
+
self.ctx.strokeStyle = self.style.filterButtonArrowBorderColor;
|
|
324
|
+
self.ctx.beginPath();
|
|
325
|
+
x = x + ml;
|
|
326
|
+
y = y + mt;
|
|
327
|
+
|
|
328
|
+
self.ctx.moveTo(x, y);
|
|
329
|
+
self.ctx.lineTo(x + aw, y);
|
|
330
|
+
self.ctx.lineTo(x + aw * 0.5, y + ah);
|
|
331
|
+
self.ctx.moveTo(x, y);
|
|
332
|
+
|
|
333
|
+
self.ctx.stroke();
|
|
334
|
+
self.ctx.fill();
|
|
335
|
+
return ml + aw;
|
|
336
|
+
}
|
|
167
337
|
function radiusRect(x, y, w, h, radius) {
|
|
168
338
|
x += self.canvasOffsetLeft;
|
|
169
339
|
y += self.canvasOffsetTop;
|
|
@@ -362,9 +532,10 @@ export default function (self) {
|
|
|
362
532
|
elWidth = self.ctx.measureText(' ' + et).width;
|
|
363
533
|
for (x = 0; x < words.length; x += 1) {
|
|
364
534
|
word = words[x];
|
|
365
|
-
var
|
|
535
|
+
var curSplitChar = word[word.length - 1] === '-' ? '' : splitChar;
|
|
536
|
+
var measure = self.ctx.measureText(word + curSplitChar);
|
|
366
537
|
if (line.width + measure.width + elWidth < cell.paddedWidth) {
|
|
367
|
-
line.value += word +
|
|
538
|
+
line.value += word + curSplitChar;
|
|
368
539
|
line.width += measure.width;
|
|
369
540
|
continue;
|
|
370
541
|
}
|
|
@@ -373,13 +544,17 @@ export default function (self) {
|
|
|
373
544
|
// then back up and re-read new split set
|
|
374
545
|
// this behavior seems right, it might not be
|
|
375
546
|
if (/\w-\w/.test(word) && cell.paddedWidth < measure.width) {
|
|
376
|
-
|
|
547
|
+
var arr = word.split('-');
|
|
548
|
+
arr = arr.map((item, index) => {
|
|
549
|
+
return index === arr.length - 1 ? item : item + '-';
|
|
550
|
+
});
|
|
551
|
+
words.splice(x, 1, ...arr);
|
|
377
552
|
x -= 1;
|
|
378
553
|
continue;
|
|
379
554
|
}
|
|
380
555
|
line = {
|
|
381
556
|
width: measure.width,
|
|
382
|
-
value: word +
|
|
557
|
+
value: word + curSplitChar,
|
|
383
558
|
};
|
|
384
559
|
if (x === 0) {
|
|
385
560
|
lines = [];
|
|
@@ -427,35 +602,58 @@ export default function (self) {
|
|
|
427
602
|
height: cell.calculatedLineHeight * lines.length,
|
|
428
603
|
};
|
|
429
604
|
}
|
|
430
|
-
function drawText(cell) {
|
|
605
|
+
function drawText(cell, treeCellPadding = 0) {
|
|
431
606
|
var ll = cell.text.lines.length,
|
|
432
607
|
h = cell.fontHeight * cell.lineHeight,
|
|
433
608
|
x,
|
|
434
609
|
line,
|
|
435
610
|
wrap = self.style.cellWhiteSpace !== 'nowrap',
|
|
436
611
|
textHeight = 0;
|
|
612
|
+
// text supplied by a rendertext handler may omit width/height (#460)
|
|
613
|
+
var textBlockHeight =
|
|
614
|
+
cell.text.height === undefined
|
|
615
|
+
? cell.calculatedLineHeight * ll
|
|
616
|
+
: cell.text.height;
|
|
437
617
|
for (x = 0; x < cell.text.lines.length; x += 1) {
|
|
438
618
|
line = cell.text.lines[x];
|
|
619
|
+
if (line.width === undefined) {
|
|
620
|
+
line.width = self.ctx.measureText(
|
|
621
|
+
line.value === undefined || line.value === null
|
|
622
|
+
? ''
|
|
623
|
+
: String(line.value),
|
|
624
|
+
).width;
|
|
625
|
+
}
|
|
439
626
|
var vPos =
|
|
440
627
|
Math.max(
|
|
441
628
|
(cell.height -
|
|
442
|
-
(wrap ?
|
|
629
|
+
(wrap ? textBlockHeight : cell.calculatedLineHeight)) *
|
|
443
630
|
0.5,
|
|
444
631
|
0,
|
|
445
632
|
) + h,
|
|
446
|
-
hPos =
|
|
633
|
+
hPos =
|
|
634
|
+
cell.paddingLeft +
|
|
635
|
+
treeCellPadding +
|
|
636
|
+
cell.treeArrowWidth +
|
|
637
|
+
cell.orderByArrowWidth;
|
|
447
638
|
if (cell.horizontalAlignment === 'right') {
|
|
448
|
-
hPos =
|
|
639
|
+
hPos =
|
|
640
|
+
cell.paddingLeft + treeCellPadding + cell.paddedWidth - line.width;
|
|
449
641
|
} else if (cell.horizontalAlignment === 'center') {
|
|
450
642
|
hPos =
|
|
451
643
|
cell.paddingLeft +
|
|
644
|
+
treeCellPadding +
|
|
452
645
|
(cell.paddedWidth + cell.paddingRight) / 2 -
|
|
453
646
|
line.width / 2;
|
|
454
647
|
}
|
|
455
648
|
if (cell.verticalAlignment === 'top') {
|
|
456
649
|
vPos = cell.calculatedLineHeight;
|
|
457
650
|
} else if (cell.verticalAlignment === 'bottom') {
|
|
458
|
-
|
|
651
|
+
// baseline of the last line sits on the bottom padding (#530)
|
|
652
|
+
vPos =
|
|
653
|
+
cell.height -
|
|
654
|
+
cell.paddingBottom -
|
|
655
|
+
textBlockHeight +
|
|
656
|
+
cell.calculatedLineHeight;
|
|
459
657
|
}
|
|
460
658
|
line.height = h + cell.lineSpacing;
|
|
461
659
|
line.offsetLeft = hPos;
|
|
@@ -505,6 +703,7 @@ export default function (self) {
|
|
|
505
703
|
s = self.getSchema(),
|
|
506
704
|
x = 0,
|
|
507
705
|
n = Math.min(self.frozenColumn, s.length),
|
|
706
|
+
collapsedGroups = self.getCollapsedColumnGroups(),
|
|
508
707
|
column;
|
|
509
708
|
hiddenFrozenColumnCount = 0;
|
|
510
709
|
while (x < n) {
|
|
@@ -512,7 +711,15 @@ export default function (self) {
|
|
|
512
711
|
if (column.hidden) {
|
|
513
712
|
hiddenFrozenColumnCount += 1;
|
|
514
713
|
} else {
|
|
515
|
-
|
|
714
|
+
const isCollapsed =
|
|
715
|
+
collapsedGroups.findIndex(
|
|
716
|
+
(group) => x >= group.from && x <= group.to,
|
|
717
|
+
) >= 0;
|
|
718
|
+
if (isCollapsed) {
|
|
719
|
+
hiddenFrozenColumnCount += 1;
|
|
720
|
+
} else {
|
|
721
|
+
w += self.getColumnWidth(x);
|
|
722
|
+
}
|
|
516
723
|
}
|
|
517
724
|
x += 1;
|
|
518
725
|
}
|
|
@@ -568,43 +775,100 @@ export default function (self) {
|
|
|
568
775
|
c,
|
|
569
776
|
h,
|
|
570
777
|
w,
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
778
|
+
schema,
|
|
779
|
+
rowIndex,
|
|
780
|
+
rowData,
|
|
574
781
|
aCell,
|
|
575
|
-
|
|
782
|
+
viewData = self.viewData || [],
|
|
576
783
|
bc = self.style.gridBorderCollapse === 'collapse',
|
|
577
784
|
selectionBorders = [],
|
|
578
785
|
moveBorders = [],
|
|
579
786
|
selectionHandles = [],
|
|
580
787
|
rowHeaders = [],
|
|
581
|
-
l =
|
|
788
|
+
l = viewData.length,
|
|
582
789
|
u = self.currentCell || {},
|
|
583
790
|
columnHeaderCellHeight = self.getColumnHeaderCellHeight(),
|
|
584
791
|
rowHeaderCellWidth = self.getRowHeaderCellWidth(),
|
|
585
|
-
|
|
792
|
+
rowGroupsAreaWidth = self.getRowGroupAreaWidth(),
|
|
793
|
+
columnGroupsAreaHeight = self.getColumnGroupAreaHeight(),
|
|
794
|
+
/** key: boundRowIndex, value: `{y,h}` */
|
|
795
|
+
rowGroupsRectInfo = {},
|
|
796
|
+
/** value: `{y,h}` */
|
|
797
|
+
rowGroupsFrozenInfo = {},
|
|
798
|
+
/** key: columnIndex, value: `{x,w}` */
|
|
799
|
+
columnGroupsRectInfo = {},
|
|
800
|
+
collapsedColumnGroups = self.getCollapsedColumnGroups(),
|
|
801
|
+
collapsedRowGroups = self.getCollapsedRowGroups(),
|
|
802
|
+
cellHeight = self.style.cellHeight,
|
|
803
|
+
currentRowIndexOffset = 0,
|
|
804
|
+
/** @type {Array<{from:number,plus:number}>} */
|
|
805
|
+
rowIndexOffsetByHiddenRows = self.hiddenRowRanges
|
|
806
|
+
.map((range) => ({
|
|
807
|
+
from: range[0],
|
|
808
|
+
plus: range[1] - range[0] + 1,
|
|
809
|
+
}))
|
|
810
|
+
.sort((a, b) => a.from - b.from);
|
|
586
811
|
drawCount += 1;
|
|
587
812
|
p = performance.now();
|
|
588
813
|
self.visibleRowHeights = [];
|
|
589
814
|
// if data length has changed, there is no way to know
|
|
590
|
-
if (
|
|
815
|
+
if (viewData.length > self.orders.rows.length) {
|
|
591
816
|
self.createRowOrders();
|
|
592
817
|
}
|
|
818
|
+
function saveRowGroupsRectInfo(cell) {
|
|
819
|
+
let index = cell.boundRowIndex;
|
|
820
|
+
if (index >= -1 === false)
|
|
821
|
+
if (cell.rowIndex === -1) index = -1;
|
|
822
|
+
else return;
|
|
823
|
+
if (rowGroupsRectInfo[index]) return;
|
|
824
|
+
rowGroupsRectInfo[index] = { y: cell.y, h: cell.height };
|
|
825
|
+
}
|
|
826
|
+
function saveColumnGroupsRectInfo(cell) {
|
|
827
|
+
const index = cell.columnIndex;
|
|
828
|
+
if (columnGroupsRectInfo[index]) return;
|
|
829
|
+
columnGroupsRectInfo[index] = { x: cell.x, w: cell.width };
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* @param {number} columnIndex
|
|
833
|
+
* @returns {boolean}
|
|
834
|
+
*/
|
|
835
|
+
function isColumnCollapsedByGroup(columnIndex) {
|
|
836
|
+
return (
|
|
837
|
+
collapsedColumnGroups.findIndex(
|
|
838
|
+
(group) => columnIndex >= group.from && columnIndex <= group.to,
|
|
839
|
+
) >= 0
|
|
840
|
+
);
|
|
841
|
+
}
|
|
842
|
+
|
|
593
843
|
function drawScrollBars() {
|
|
594
844
|
var drawCorner,
|
|
595
845
|
en = self.scrollBox.entities,
|
|
596
846
|
m = self.style.scrollBarBoxMargin * 2;
|
|
597
847
|
self.ctx.strokeStyle = self.style.scrollBarBorderColor;
|
|
598
848
|
self.ctx.lineWidth = self.style.scrollBarBorderWidth;
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
849
|
+
if (self.frozenColumn > 0) {
|
|
850
|
+
en.horizontalBox.x =
|
|
851
|
+
rowHeaderCellWidth +
|
|
852
|
+
self.style.scrollBarBoxMargin +
|
|
853
|
+
self.scrollCache.x[self.frozenColumn - 1] +
|
|
854
|
+
(en.horizontalBar.width -
|
|
855
|
+
self.scrollCache.x[self.frozenColumn - 1] -
|
|
856
|
+
self.scrollBox.scrollBoxWidth) *
|
|
857
|
+
(self.scrollBox.scrollLeft / self.scrollBox.scrollWidth);
|
|
858
|
+
} else {
|
|
859
|
+
en.horizontalBox.x =
|
|
860
|
+
rowHeaderCellWidth +
|
|
861
|
+
self.style.scrollBarBoxMargin +
|
|
862
|
+
(en.horizontalBar.width - self.scrollBox.scrollBoxWidth) *
|
|
863
|
+
(self.scrollBox.scrollLeft / self.scrollBox.scrollWidth);
|
|
864
|
+
}
|
|
604
865
|
en.verticalBox.y =
|
|
605
866
|
columnHeaderCellHeight +
|
|
606
867
|
self.style.scrollBarBoxMargin +
|
|
607
|
-
|
|
868
|
+
self.scrollCache.y[self.frozenRow] +
|
|
869
|
+
(en.verticalBar.height -
|
|
870
|
+
self.scrollBox.scrollBoxHeight -
|
|
871
|
+
self.scrollCache.y[self.frozenRow]) *
|
|
608
872
|
(self.scrollBox.scrollTop / self.scrollBox.scrollHeight);
|
|
609
873
|
if (self.scrollBox.horizontalBarVisible) {
|
|
610
874
|
self.ctx.fillStyle = self.style.scrollBarBackgroundColor;
|
|
@@ -698,13 +962,17 @@ export default function (self) {
|
|
|
698
962
|
selectionHandles.push([cell, 'tr']);
|
|
699
963
|
cell.selectionHandle = 'tr';
|
|
700
964
|
}
|
|
701
|
-
if (
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
965
|
+
if (cell.selectionBorderTop && cell.selectionBorderLeft) {
|
|
966
|
+
if (self.mobile) {
|
|
967
|
+
selectionHandles.push([cell, 'tl']);
|
|
968
|
+
cell.selectionHandle = 'tl';
|
|
969
|
+
}
|
|
970
|
+
if (self.fillOverlay.handle) {
|
|
971
|
+
self.fillOverlay.snapTo = {
|
|
972
|
+
x: cell.x,
|
|
973
|
+
y: cell.y,
|
|
974
|
+
};
|
|
975
|
+
}
|
|
708
976
|
}
|
|
709
977
|
if (
|
|
710
978
|
cell.selectionBorderBottom &&
|
|
@@ -721,6 +989,22 @@ export default function (self) {
|
|
|
721
989
|
) {
|
|
722
990
|
selectionHandles.push([cell, 'br']);
|
|
723
991
|
cell.selectionHandle = 'br';
|
|
992
|
+
|
|
993
|
+
if (self.fillOverlay.handle) {
|
|
994
|
+
self.fillOverlay.handle.x = cell.x + cell.width;
|
|
995
|
+
self.fillOverlay.handle.y = cell.y + cell.height;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
if (self.fillOverlay.handle) {
|
|
1000
|
+
// Some corners may not be displaying, so we get at least
|
|
1001
|
+
// one correct axis in order to display a fill overlay.
|
|
1002
|
+
if (self.fillOverlay.snapTo.x === -1 && cell.selectionBorderLeft) {
|
|
1003
|
+
self.fillOverlay.snapTo.x = cell.x;
|
|
1004
|
+
}
|
|
1005
|
+
if (self.fillOverlay.snapTo.y === -1 && cell.selectionBorderTop) {
|
|
1006
|
+
self.fillOverlay.snapTo.y = cell.y;
|
|
1007
|
+
}
|
|
724
1008
|
}
|
|
725
1009
|
}
|
|
726
1010
|
}
|
|
@@ -730,21 +1014,23 @@ export default function (self) {
|
|
|
730
1014
|
propPrefix,
|
|
731
1015
|
offsetPoint,
|
|
732
1016
|
) {
|
|
733
|
-
offsetPoint = offsetPoint || { x: 0, y: 0 };
|
|
734
1017
|
cell.selectionBorder = '';
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
1018
|
+
// TODO: optimize it by `getSelectionStateFromCells`
|
|
1019
|
+
const isSelected = offsetPoint
|
|
1020
|
+
? (row, col) =>
|
|
1021
|
+
isCellSelected(
|
|
1022
|
+
self.selections,
|
|
1023
|
+
row - offsetPoint.y,
|
|
1024
|
+
col - offsetPoint.x,
|
|
1025
|
+
)
|
|
1026
|
+
: (row, col) => isCellSelected(self.selections, row, col);
|
|
1027
|
+
const lastColumnIndex = Math.max(schema.length - 1, 0);
|
|
1028
|
+
const lastRowIndex = Math.max(viewData.length - 1, 0);
|
|
1029
|
+
const { isRowHeader, rowIndex, columnIndex } = cell;
|
|
1030
|
+
|
|
1031
|
+
if (!isRowHeader && isSelected(rowIndex, columnIndex)) {
|
|
742
1032
|
if (
|
|
743
|
-
(!
|
|
744
|
-
self.selections[cell.rowIndex - 1 + -offsetPoint.y].indexOf(
|
|
745
|
-
cell.columnIndex + -offsetPoint.x,
|
|
746
|
-
) === -1 ||
|
|
747
|
-
cell.rowIndex === 0) &&
|
|
1033
|
+
(!isSelected(rowIndex - 1, columnIndex) || rowIndex === 0) &&
|
|
748
1034
|
!cell.isHeader
|
|
749
1035
|
) {
|
|
750
1036
|
drawArray.push([cell, 't']);
|
|
@@ -752,32 +1038,21 @@ export default function (self) {
|
|
|
752
1038
|
cell[propPrefix + 'Border'] += 't';
|
|
753
1039
|
}
|
|
754
1040
|
if (
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
cell.columnIndex + -offsetPoint.x,
|
|
758
|
-
) === -1
|
|
1041
|
+
rowIndex >= lastRowIndex ||
|
|
1042
|
+
!isSelected(rowIndex + 1, columnIndex)
|
|
759
1043
|
) {
|
|
760
1044
|
drawArray.push([cell, 'b']);
|
|
761
1045
|
cell[propPrefix + 'BorderBottom'] = true;
|
|
762
1046
|
cell[propPrefix + 'Border'] += 'b';
|
|
763
1047
|
}
|
|
764
|
-
if (
|
|
765
|
-
!self.selections[cell.rowIndex + -offsetPoint.y] ||
|
|
766
|
-
cell.columnIndex === 0 ||
|
|
767
|
-
self.selections[cell.rowIndex + -offsetPoint.y].indexOf(
|
|
768
|
-
cell.columnIndex - 1 + -offsetPoint.x,
|
|
769
|
-
) === -1
|
|
770
|
-
) {
|
|
1048
|
+
if (columnIndex === 0 || !isSelected(rowIndex, columnIndex - 1)) {
|
|
771
1049
|
drawArray.push([cell, 'l']);
|
|
772
1050
|
cell[propPrefix + 'BorderLeft'] = true;
|
|
773
1051
|
cell[propPrefix + 'Border'] += 'l';
|
|
774
1052
|
}
|
|
775
1053
|
if (
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
self.selections[cell.rowIndex + -offsetPoint.y].indexOf(
|
|
779
|
-
cell.columnIndex + 1 + -offsetPoint.x,
|
|
780
|
-
) === -1
|
|
1054
|
+
columnIndex >= lastColumnIndex ||
|
|
1055
|
+
!isSelected(rowIndex, columnIndex + 1)
|
|
781
1056
|
) {
|
|
782
1057
|
drawArray.push([cell, 'r']);
|
|
783
1058
|
cell[propPrefix + 'BorderRight'] = true;
|
|
@@ -785,7 +1060,11 @@ export default function (self) {
|
|
|
785
1060
|
}
|
|
786
1061
|
}
|
|
787
1062
|
}
|
|
788
|
-
function drawCell(
|
|
1063
|
+
function drawCell(rowData, rowOrderIndex, rowIndex) {
|
|
1064
|
+
const isActiveRowHeader =
|
|
1065
|
+
self.orders.rows[self.activeCell.rowIndex] === rowOrderIndex ||
|
|
1066
|
+
self.isRowSelected(rowOrderIndex);
|
|
1067
|
+
|
|
789
1068
|
return function drawEach(header, headerIndex, columnOrderIndex) {
|
|
790
1069
|
if (header.hidden) {
|
|
791
1070
|
return 0;
|
|
@@ -797,38 +1076,55 @@ export default function (self) {
|
|
|
797
1076
|
isCorner = /cornerCell/.test(cellStyle),
|
|
798
1077
|
isRowHeader = 'rowHeaderCell' === cellStyle,
|
|
799
1078
|
isColumnHeader = 'columnHeaderCell' === cellStyle,
|
|
1079
|
+
isFilterable =
|
|
1080
|
+
self.filterable.rows.includes(rowIndex) &&
|
|
1081
|
+
self.filterable.columns.includes(headerIndex),
|
|
800
1082
|
wrap = self.style.cellWhiteSpace !== 'nowrap',
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
self.selections
|
|
1083
|
+
// TODO: optimize it by `getSelectionStateFromCells`
|
|
1084
|
+
selected = isCellSelected(
|
|
1085
|
+
self.selections,
|
|
1086
|
+
rowOrderIndex,
|
|
1087
|
+
columnOrderIndex,
|
|
1088
|
+
),
|
|
804
1089
|
hovered =
|
|
805
1090
|
self.hovers.rowIndex === rowOrderIndex &&
|
|
806
|
-
self.
|
|
1091
|
+
(self.attributes.hoverMode === 'row' ||
|
|
1092
|
+
self.hovers.columnIndex === columnOrderIndex),
|
|
1093
|
+
openedFilter =
|
|
1094
|
+
self.selectedFilterButton.rowIndex == rowIndex &&
|
|
1095
|
+
self.selectedFilterButton.columnIndex == headerIndex,
|
|
807
1096
|
active =
|
|
808
1097
|
self.activeCell.rowIndex === rowOrderIndex &&
|
|
809
1098
|
self.activeCell.columnIndex === columnOrderIndex,
|
|
810
1099
|
isColumnHeaderCellCap = cellStyle === 'columnHeaderCellCap',
|
|
811
|
-
rawValue =
|
|
1100
|
+
rawValue = rowData ? rowData[header.name] : undefined,
|
|
812
1101
|
isGrid = header.type === 'canvas-datagrid',
|
|
813
|
-
activeHeader =
|
|
814
|
-
(self.orders.rows[self.activeCell.rowIndex] === rowOrderIndex ||
|
|
815
|
-
self.orders.columns[self.activeCell.columnIndex] ===
|
|
816
|
-
headerIndex) &&
|
|
817
|
-
(columnOrderIndex === -1 || rowOrderIndex === -1)
|
|
818
|
-
? isRowHeader
|
|
819
|
-
? 'activeRowHeaderCell'
|
|
820
|
-
: 'activeColumnHeaderCell'
|
|
821
|
-
: false,
|
|
822
1102
|
val,
|
|
823
1103
|
f = self.formatters[header.type || 'string'],
|
|
824
1104
|
orderByArrowSize = 0,
|
|
825
1105
|
treeArrowSize = 0,
|
|
826
|
-
cellWidth =
|
|
1106
|
+
cellWidth =
|
|
1107
|
+
headerIndex >= 0
|
|
1108
|
+
? self.getColumnWidth(headerIndex)
|
|
1109
|
+
: self.sizes.columns[headerIndex] || header.width,
|
|
827
1110
|
ev = {
|
|
828
1111
|
value: rawValue,
|
|
829
|
-
row:
|
|
1112
|
+
row: rowData,
|
|
830
1113
|
header: header,
|
|
831
1114
|
};
|
|
1115
|
+
|
|
1116
|
+
const isActiveColumnHeader =
|
|
1117
|
+
self.orders.columns[self.activeCell.columnIndex] === headerIndex ||
|
|
1118
|
+
self.isColumnSelected(self.activeCell.viewColumnIndex);
|
|
1119
|
+
let activeHeader = false;
|
|
1120
|
+
if (
|
|
1121
|
+
(isActiveColumnHeader || isActiveRowHeader) &&
|
|
1122
|
+
(columnOrderIndex === -1 || rowOrderIndex === -1)
|
|
1123
|
+
)
|
|
1124
|
+
activeHeader = isRowHeader
|
|
1125
|
+
? 'activeRowHeaderCell'
|
|
1126
|
+
: 'activeColumnHeaderCell';
|
|
1127
|
+
|
|
832
1128
|
if (isColumnHeaderCellCap) {
|
|
833
1129
|
cellWidth = w - x;
|
|
834
1130
|
}
|
|
@@ -836,7 +1132,9 @@ export default function (self) {
|
|
|
836
1132
|
if (cellWidth === undefined) {
|
|
837
1133
|
cellWidth = self.style.cellWidth;
|
|
838
1134
|
}
|
|
839
|
-
|
|
1135
|
+
if (headerIndex < 0) {
|
|
1136
|
+
cellWidth = cellWidth * self.scale;
|
|
1137
|
+
}
|
|
840
1138
|
if (x + cellWidth + self.style.cellBorderWidth < 0) {
|
|
841
1139
|
x += cellWidth + self.style.cellBorderWidth;
|
|
842
1140
|
}
|
|
@@ -889,18 +1187,30 @@ export default function (self) {
|
|
|
889
1187
|
offsetHeight: cellHeight,
|
|
890
1188
|
parentNode: self.intf.parentNode,
|
|
891
1189
|
offsetParent: self.intf.parentNode,
|
|
892
|
-
data:
|
|
1190
|
+
data: rowData,
|
|
893
1191
|
isCorner: isCorner,
|
|
894
1192
|
isHeader: isHeader,
|
|
895
1193
|
isColumnHeader: isColumnHeader,
|
|
896
1194
|
isColumnHeaderCellCap: isColumnHeaderCellCap,
|
|
897
1195
|
isRowHeader: isRowHeader,
|
|
1196
|
+
isFilterable: isFilterable,
|
|
1197
|
+
openedFilter: openedFilter,
|
|
898
1198
|
rowOpen: rowOpen,
|
|
899
1199
|
header: header,
|
|
1200
|
+
|
|
900
1201
|
columnIndex: columnOrderIndex,
|
|
901
1202
|
rowIndex: rowOrderIndex,
|
|
1203
|
+
|
|
1204
|
+
viewRowIndex: rowOrderIndex,
|
|
1205
|
+
viewColumnIndex: columnOrderIndex,
|
|
1206
|
+
|
|
1207
|
+
boundRowIndex: self.getBoundRowIndexFromViewRowIndex(rowOrderIndex),
|
|
1208
|
+
boundColumnIndex:
|
|
1209
|
+
self.getBoundColumnIndexFromViewColumnIndex(columnOrderIndex),
|
|
1210
|
+
|
|
902
1211
|
sortColumnIndex: headerIndex,
|
|
903
1212
|
sortRowIndex: rowIndex,
|
|
1213
|
+
|
|
904
1214
|
isGrid: isGrid,
|
|
905
1215
|
isNormal: !isGrid && !isCorner && !isHeader,
|
|
906
1216
|
gridId: (self.attributes.name || '') + rowIndex + ':' + headerIndex,
|
|
@@ -909,6 +1219,15 @@ export default function (self) {
|
|
|
909
1219
|
activeHeader: activeHeader,
|
|
910
1220
|
value:
|
|
911
1221
|
isHeader && !isRowHeader ? header.title || header.name : rawValue,
|
|
1222
|
+
isRowTree:
|
|
1223
|
+
rowOrderIndex >= 0 &&
|
|
1224
|
+
columnOrderIndex == self.cellTree.rowTreeColIndex &&
|
|
1225
|
+
self.cellTree.rows.length > 0 &&
|
|
1226
|
+
self.cellTree.rows[rowOrderIndex].icon,
|
|
1227
|
+
isColumnTree:
|
|
1228
|
+
columnOrderIndex >= 0 &&
|
|
1229
|
+
self.cellTree.columns[rowOrderIndex] &&
|
|
1230
|
+
self.cellTree.columns[rowOrderIndex][columnOrderIndex].icon,
|
|
912
1231
|
};
|
|
913
1232
|
cell.calculatedLineHeight =
|
|
914
1233
|
cell.fontHeight * cell.lineHeight + cell.lineSpacing;
|
|
@@ -920,6 +1239,8 @@ export default function (self) {
|
|
|
920
1239
|
? self.sizes.columns.cornerCell
|
|
921
1240
|
: self.sizes.columns[headerIndex];
|
|
922
1241
|
self.visibleCells.unshift(cell);
|
|
1242
|
+
saveRowGroupsRectInfo(cell);
|
|
1243
|
+
saveColumnGroupsRectInfo(cell);
|
|
923
1244
|
if (self.dispatchEvent('beforerendercell', ev)) {
|
|
924
1245
|
return;
|
|
925
1246
|
}
|
|
@@ -994,9 +1315,8 @@ export default function (self) {
|
|
|
994
1315
|
if (self.dispatchEvent('beforecreatecellgrid', ev)) {
|
|
995
1316
|
return;
|
|
996
1317
|
}
|
|
997
|
-
self.childGrids[cell.gridId] =
|
|
998
|
-
cellGridAttributes
|
|
999
|
-
);
|
|
1318
|
+
self.childGrids[cell.gridId] =
|
|
1319
|
+
self.createGrid(cellGridAttributes);
|
|
1000
1320
|
self.sizes.rows[rowIndex] =
|
|
1001
1321
|
self.sizes.rows[rowIndex] || self.style.cellGridHeight;
|
|
1002
1322
|
checkScrollHeight = true;
|
|
@@ -1040,9 +1360,8 @@ export default function (self) {
|
|
|
1040
1360
|
' add a cellFormater',
|
|
1041
1361
|
);
|
|
1042
1362
|
}
|
|
1043
|
-
cell.formattedValue = (
|
|
1044
|
-
? val
|
|
1045
|
-
: ''
|
|
1363
|
+
cell.formattedValue = (
|
|
1364
|
+
val !== undefined && val !== null ? val : ''
|
|
1046
1365
|
).toString();
|
|
1047
1366
|
if (
|
|
1048
1367
|
self.columnFilters &&
|
|
@@ -1051,10 +1370,7 @@ export default function (self) {
|
|
|
1051
1370
|
) {
|
|
1052
1371
|
cell.formattedValue = self.attributes.filterTextPrefix + val;
|
|
1053
1372
|
}
|
|
1054
|
-
self.ctx.font =
|
|
1055
|
-
self.style[cellStyle + 'FontHeight'] * self.scale +
|
|
1056
|
-
'px ' +
|
|
1057
|
-
self.style[cellStyle + 'FontName'];
|
|
1373
|
+
self.ctx.font = self.getScaledFont(cellStyle + 'Font');
|
|
1058
1374
|
if (!self.dispatchEvent('formattext', ev)) {
|
|
1059
1375
|
cell.text = wrapText(cell, ' ');
|
|
1060
1376
|
}
|
|
@@ -1062,7 +1378,53 @@ export default function (self) {
|
|
|
1062
1378
|
if (cell.innerHTML || header.type === 'html') {
|
|
1063
1379
|
drawHtml(cell);
|
|
1064
1380
|
} else {
|
|
1065
|
-
|
|
1381
|
+
let treeCellPadding = 0,
|
|
1382
|
+
isDrawText = true;
|
|
1383
|
+
if (
|
|
1384
|
+
cell.columnIndex == self.cellTree.rowTreeColIndex &&
|
|
1385
|
+
!cell.isColumnHeader &&
|
|
1386
|
+
self.cellTree.rows.length > 0 &&
|
|
1387
|
+
Object.keys(self.cellTree.rows[cell.rowIndex]).length > 1
|
|
1388
|
+
)
|
|
1389
|
+
treeCellPadding = drawCellTreeIcon(
|
|
1390
|
+
cell,
|
|
1391
|
+
self.cellTree.rows[cell.rowIndex],
|
|
1392
|
+
true,
|
|
1393
|
+
);
|
|
1394
|
+
|
|
1395
|
+
if (
|
|
1396
|
+
!cell.isRowHeader &&
|
|
1397
|
+
cell.rowIndex > 0 &&
|
|
1398
|
+
self.cellTree.columns[cell.rowIndex - 1] &&
|
|
1399
|
+
self.cellTree.columns[cell.rowIndex - 1][cell.columnIndex]
|
|
1400
|
+
.icon
|
|
1401
|
+
) {
|
|
1402
|
+
for (let r = cell.rowIndex - 1; r >= 0; r--) {
|
|
1403
|
+
if (!self.cellTree.columns[r]) break;
|
|
1404
|
+
if (!self.cellTree.columns[r][cell.columnIndex].icon) break;
|
|
1405
|
+
if (!self.cellTree.columns[r][cell.columnIndex].expand) {
|
|
1406
|
+
isDrawText = false;
|
|
1407
|
+
break;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
if (
|
|
1412
|
+
isDrawText &&
|
|
1413
|
+
!cell.isRowHeader &&
|
|
1414
|
+
self.cellTree.columns[cell.rowIndex] &&
|
|
1415
|
+
self.cellTree.columns[cell.rowIndex][cell.columnIndex].icon
|
|
1416
|
+
) {
|
|
1417
|
+
if (
|
|
1418
|
+
self.viewData.length > 0 &&
|
|
1419
|
+
self.viewData[cell.rowIndex][cell.columnIndex].length > 0
|
|
1420
|
+
)
|
|
1421
|
+
treeCellPadding = drawCellTreeIcon(
|
|
1422
|
+
cell,
|
|
1423
|
+
self.cellTree.columns[cell.rowIndex][cell.columnIndex],
|
|
1424
|
+
false,
|
|
1425
|
+
);
|
|
1426
|
+
}
|
|
1427
|
+
if (isDrawText) drawText(cell, treeCellPadding);
|
|
1066
1428
|
}
|
|
1067
1429
|
|
|
1068
1430
|
if (wrap && cell.text && cell.text.height > rowHeight) {
|
|
@@ -1082,31 +1444,283 @@ export default function (self) {
|
|
|
1082
1444
|
createBorderOverlayArray(cell, moveBorders, 'move', self.moveOffset);
|
|
1083
1445
|
}
|
|
1084
1446
|
self.ctx.restore();
|
|
1447
|
+
|
|
1448
|
+
if (isFilterable) {
|
|
1449
|
+
drawFilterButton(cell);
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
// Gaps may occur in row numbers between consecutively rendered rows
|
|
1453
|
+
// when we are filtering. We draw attention to this by drawing a thick
|
|
1454
|
+
// border overlapping the two consecutive row headers. If sorting, visible
|
|
1455
|
+
// row numbers stay the same (i.e. they don't correspond to the underlying
|
|
1456
|
+
// data's row number), so we do not show row gaps in that case.
|
|
1457
|
+
const isSorting =
|
|
1458
|
+
self.orderings.columns && self.orderings.columns.length > 0;
|
|
1459
|
+
|
|
1460
|
+
if (
|
|
1461
|
+
isRowHeader &&
|
|
1462
|
+
self.attributes.showRowNumbers &&
|
|
1463
|
+
self.attributes.showRowNumberGaps &&
|
|
1464
|
+
isSorting === false
|
|
1465
|
+
) {
|
|
1466
|
+
const previousRowNumber = self.getBoundRowIndexFromViewRowIndex(
|
|
1467
|
+
rowOrderIndex - 1,
|
|
1468
|
+
);
|
|
1469
|
+
let hasRowGap =
|
|
1470
|
+
previousRowNumber !== undefined &&
|
|
1471
|
+
cell.boundRowIndex > 0 &&
|
|
1472
|
+
cell.boundRowIndex - previousRowNumber > 1;
|
|
1473
|
+
if (hasRowGap && collapsedRowGroups.length > 0) {
|
|
1474
|
+
hasRowGap =
|
|
1475
|
+
collapsedRowGroups.find(
|
|
1476
|
+
(group) =>
|
|
1477
|
+
group.from === previousRowNumber &&
|
|
1478
|
+
group.to === cell.boundRowIndex,
|
|
1479
|
+
) >= 0;
|
|
1480
|
+
}
|
|
1481
|
+
// We don't treat the row index difference from hidden rows as the row gap.
|
|
1482
|
+
if (hasRowGap && self.hiddenRowRanges.length > 0) {
|
|
1483
|
+
for (let i = 0; i < self.hiddenRowRanges.length; i++) {
|
|
1484
|
+
const [beginRowIndex, endRowIndex] = self.hiddenRowRanges[i];
|
|
1485
|
+
if (
|
|
1486
|
+
cell.boundRowIndex === endRowIndex + 1 &&
|
|
1487
|
+
previousRowNumber === beginRowIndex - 1
|
|
1488
|
+
) {
|
|
1489
|
+
hasRowGap = false;
|
|
1490
|
+
break;
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
if (hasRowGap) {
|
|
1496
|
+
const barHeight = self.style.rowHeaderCellRowNumberGapHeight;
|
|
1497
|
+
const barColor = self.style.rowHeaderCellRowNumberGapColor;
|
|
1498
|
+
|
|
1499
|
+
self.ctx.save();
|
|
1500
|
+
|
|
1501
|
+
self.ctx.fillStyle = barColor;
|
|
1502
|
+
|
|
1503
|
+
fillRect(cell.x, cell.y - barHeight / 2, cell.width, barHeight);
|
|
1504
|
+
|
|
1505
|
+
self.ctx.restore();
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
//#region draw unhide indicator for column headers
|
|
1510
|
+
if (isColumnHeader && self.attributes.showUnhideColumnsIndicator) {
|
|
1511
|
+
const hovered = self.hovers.unhideIndicator;
|
|
1512
|
+
const size = self.style.unhideIndicatorSize;
|
|
1513
|
+
const cellX = x;
|
|
1514
|
+
const topY = cell.y + Math.max(0.5 * (cell.height - size), 0);
|
|
1515
|
+
|
|
1516
|
+
const isActive = (orderIndex) =>
|
|
1517
|
+
hovered &&
|
|
1518
|
+
(hovered.dir === 'l' || hovered.dir === 'r') &&
|
|
1519
|
+
orderIndex >= hovered.orderIndex0 &&
|
|
1520
|
+
orderIndex <= hovered.orderIndex1;
|
|
1521
|
+
const isHiddenColumn = (columnIndex) =>
|
|
1522
|
+
columnIndex >= 0 &&
|
|
1523
|
+
schema[columnIndex] &&
|
|
1524
|
+
schema[columnIndex].hidden;
|
|
1525
|
+
|
|
1526
|
+
let orderIndex0, orderIndex1;
|
|
1527
|
+
const drawIndicator = (leftX, dir, active) => {
|
|
1528
|
+
self.visibleUnhideIndicators.push({
|
|
1529
|
+
x: leftX - 1,
|
|
1530
|
+
y: topY - 1,
|
|
1531
|
+
x2: leftX + size + 2,
|
|
1532
|
+
y2: topY + size + 2,
|
|
1533
|
+
orderIndex0,
|
|
1534
|
+
orderIndex1,
|
|
1535
|
+
dir,
|
|
1536
|
+
});
|
|
1537
|
+
if (!active) {
|
|
1538
|
+
const line = cell.text && cell.text.lines && cell.text.lines[0];
|
|
1539
|
+
if (line) {
|
|
1540
|
+
const iconsWidth = orderByArrowSize + treeArrowSize;
|
|
1541
|
+
const lineX0 = iconsWidth > 0 ? iconsWidth : line.x;
|
|
1542
|
+
const lineX1 = line.x + line.width;
|
|
1543
|
+
if (leftX + size >= lineX0 && leftX <= lineX1) return;
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
drawUnhideIndicator(leftX, topY, size, dir, active);
|
|
1547
|
+
}; // end of drawIndicator
|
|
1548
|
+
|
|
1549
|
+
let orderIndexPtr = columnOrderIndex - 1;
|
|
1550
|
+
const prevColumnIndex = self.orders.columns[orderIndexPtr];
|
|
1551
|
+
if (isHiddenColumn(prevColumnIndex)) {
|
|
1552
|
+
const active = isActive(prevColumnIndex);
|
|
1553
|
+
orderIndex0 = orderIndexPtr;
|
|
1554
|
+
orderIndex1 = orderIndexPtr;
|
|
1555
|
+
while (--orderIndexPtr >= 0) {
|
|
1556
|
+
if (isHiddenColumn(self.orders.columns[orderIndexPtr]))
|
|
1557
|
+
orderIndex0 = orderIndexPtr;
|
|
1558
|
+
else break;
|
|
1559
|
+
}
|
|
1560
|
+
drawIndicator(cellX, 'r', active);
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
orderIndexPtr = columnOrderIndex + 1;
|
|
1564
|
+
const nextColumnIndex = self.orders.columns[orderIndexPtr];
|
|
1565
|
+
if (isHiddenColumn(nextColumnIndex)) {
|
|
1566
|
+
const active = isActive(nextColumnIndex);
|
|
1567
|
+
orderIndex0 = orderIndexPtr;
|
|
1568
|
+
orderIndex1 = orderIndexPtr;
|
|
1569
|
+
while (++orderIndexPtr < self.orders.columns.length) {
|
|
1570
|
+
if (isHiddenColumn(self.orders.columns[orderIndexPtr]))
|
|
1571
|
+
orderIndex1 = orderIndexPtr;
|
|
1572
|
+
else break;
|
|
1573
|
+
}
|
|
1574
|
+
const indicatorX = x + cell.width - size;
|
|
1575
|
+
drawIndicator(indicatorX, 'l', active);
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
//#endregion draw unhide indicator for column headers
|
|
1579
|
+
|
|
1580
|
+
//#region draw unhide indicator for row headers
|
|
1581
|
+
if (
|
|
1582
|
+
isRowHeader &&
|
|
1583
|
+
self.attributes.showUnhideRowsIndicator &&
|
|
1584
|
+
self.hiddenRowRanges.length > 0
|
|
1585
|
+
) {
|
|
1586
|
+
// Leo's comment:
|
|
1587
|
+
// from the first row to the last row, `rowIndex` is from 0 to the count of rows
|
|
1588
|
+
// but `boundRowIndex` can be disordered if there are any ordered columns or filtered columns
|
|
1589
|
+
// Like this statement:
|
|
1590
|
+
// console.log(rowIndex, cell.boundRowIndex, cell.formattedValue);
|
|
1591
|
+
// can output the result like this:
|
|
1592
|
+
// 0 1 '2'
|
|
1593
|
+
// 1 3 '4'
|
|
1594
|
+
const hovered = self.hovers.unhideIndicator;
|
|
1595
|
+
const size = self.style.unhideIndicatorSize;
|
|
1596
|
+
const leftX = cell.x + cell.width - size - 2;
|
|
1597
|
+
const cellY = y;
|
|
1598
|
+
const topIndicators = {};
|
|
1599
|
+
const bottomIndicators = {};
|
|
1600
|
+
self.hiddenRowRanges.forEach((it) => {
|
|
1601
|
+
topIndicators[it[0] - 1] = it;
|
|
1602
|
+
bottomIndicators[it[1] + 1] = it;
|
|
1603
|
+
});
|
|
1604
|
+
|
|
1605
|
+
const rowIndex = cell.rowIndex + currentRowIndexOffset;
|
|
1606
|
+
const isActive = () =>
|
|
1607
|
+
hovered &&
|
|
1608
|
+
(hovered.dir === 't' || hovered.dir === 'b') &&
|
|
1609
|
+
rowIndex >= hovered.orderIndex0 - 1 &&
|
|
1610
|
+
rowIndex <= hovered.orderIndex1 + 1;
|
|
1611
|
+
|
|
1612
|
+
let orderIndex0, orderIndex1;
|
|
1613
|
+
const drawIndicator = (topY, dir, active) => {
|
|
1614
|
+
self.visibleUnhideIndicators.push({
|
|
1615
|
+
x: leftX - 1,
|
|
1616
|
+
y: topY - 1,
|
|
1617
|
+
x2: leftX + size + 2,
|
|
1618
|
+
y2: topY + size + 2,
|
|
1619
|
+
orderIndex0,
|
|
1620
|
+
orderIndex1,
|
|
1621
|
+
dir,
|
|
1622
|
+
});
|
|
1623
|
+
drawUnhideIndicator(leftX, topY, size, dir, active);
|
|
1624
|
+
}; // end of drawIndicator
|
|
1625
|
+
|
|
1626
|
+
let matched = topIndicators[rowIndex];
|
|
1627
|
+
if (matched) {
|
|
1628
|
+
const indicatorY = cellY + cell.height - size;
|
|
1629
|
+
[orderIndex0, orderIndex1] = matched;
|
|
1630
|
+
drawIndicator(indicatorY, 't', isActive());
|
|
1631
|
+
}
|
|
1632
|
+
matched = bottomIndicators[rowIndex];
|
|
1633
|
+
if (matched) {
|
|
1634
|
+
const indicatorY = cellY;
|
|
1635
|
+
[orderIndex0, orderIndex1] = matched;
|
|
1636
|
+
drawIndicator(indicatorY, 'b', isActive());
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
//#endregion draw unhide indicator for row headers
|
|
1640
|
+
|
|
1085
1641
|
x += cell.width + (bc ? 0 : self.style.cellBorderWidth);
|
|
1086
1642
|
return cell.width;
|
|
1087
|
-
};
|
|
1643
|
+
}; // end of drawEach
|
|
1644
|
+
}
|
|
1645
|
+
function drawFilterButton(cell, ev) {
|
|
1646
|
+
var posX = cell.x + cell.width - self.style.filterButtonWidth - 1;
|
|
1647
|
+
var posY = cell.y + cell.height - self.style.filterButtonHeight - 2;
|
|
1648
|
+
if (self.dispatchEvent('beforerenderfilterbutton', ev)) {
|
|
1649
|
+
return;
|
|
1650
|
+
}
|
|
1651
|
+
self.ctx.save();
|
|
1652
|
+
self.ctx.strokeStyle = self.style.filterButtonBorderColor;
|
|
1653
|
+
self.ctx.fillStyle = self.style.filterButtonBackgroundColor;
|
|
1654
|
+
if (cell.openedFilter) {
|
|
1655
|
+
self.ctx.fillStyle = self.style.filterButtonActiveBackgroundColor;
|
|
1656
|
+
} else if (cell.hovered && self.hovers.onFilterButton) {
|
|
1657
|
+
self.ctx.fillStyle = self.style.filterButtonHoverBackgroundColor;
|
|
1658
|
+
}
|
|
1659
|
+
radiusRect(
|
|
1660
|
+
posX,
|
|
1661
|
+
posY,
|
|
1662
|
+
self.style.filterButtonWidth,
|
|
1663
|
+
self.style.filterButtonHeight,
|
|
1664
|
+
self.style.filterButtonBorderRadius,
|
|
1665
|
+
);
|
|
1666
|
+
self.ctx.stroke();
|
|
1667
|
+
self.ctx.fill();
|
|
1668
|
+
drawFilterButtonArrow(posX, posY);
|
|
1669
|
+
self.ctx.clip();
|
|
1670
|
+
self.dispatchEvent('afterrenderfilterbutton', ev);
|
|
1671
|
+
self.ctx.restore();
|
|
1088
1672
|
}
|
|
1089
|
-
function drawRowHeader(rowData,
|
|
1090
|
-
var a, i;
|
|
1673
|
+
function drawRowHeader(rowData, rowIndex, rowOrderIndex) {
|
|
1091
1674
|
if (self.attributes.showRowHeaders) {
|
|
1092
1675
|
x = 0;
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1676
|
+
|
|
1677
|
+
// When filtering we'd like to display the actual row numbers,
|
|
1678
|
+
// as it is in the unfiltered data, instead of simply the viewed
|
|
1679
|
+
// row index + 1. If rowIndex > viewData.length, it's a new row
|
|
1680
|
+
// added to the end, and we want to render that new row's number
|
|
1681
|
+
let filteredRowNumber;
|
|
1682
|
+
if (self.viewData && rowIndex < self.viewData.length)
|
|
1683
|
+
filteredRowNumber =
|
|
1684
|
+
self.getBoundRowIndexFromViewRowIndex(rowIndex) + 1;
|
|
1685
|
+
else
|
|
1686
|
+
filteredRowNumber = self.originalData
|
|
1687
|
+
? self.originalData.length + 1
|
|
1688
|
+
: rowOrderIndex + 1;
|
|
1689
|
+
|
|
1690
|
+
let rowHeaderValue =
|
|
1691
|
+
self.hasActiveFilters() || self.hasCollapsedRowGroup()
|
|
1692
|
+
? filteredRowNumber
|
|
1693
|
+
: rowIndex + 1;
|
|
1694
|
+
rowHeaderValue += currentRowIndexOffset;
|
|
1695
|
+
|
|
1696
|
+
const rowHeaderCell = { rowHeaderCell: rowHeaderValue };
|
|
1697
|
+
const headerDescription = {
|
|
1096
1698
|
name: 'rowHeaderCell',
|
|
1097
1699
|
width: self.sizes.columns[-1] || self.style.rowHeaderCellWidth,
|
|
1098
1700
|
style: 'rowHeaderCell',
|
|
1099
1701
|
type: 'string',
|
|
1100
|
-
data:
|
|
1702
|
+
data: rowHeaderValue,
|
|
1101
1703
|
index: -1,
|
|
1102
1704
|
};
|
|
1103
|
-
rowOpen = self.openChildren[
|
|
1104
|
-
drawCell(rowHeaderCell,
|
|
1705
|
+
rowOpen = self.openChildren[rowIndex];
|
|
1706
|
+
drawCell(rowHeaderCell, rowOrderIndex, rowIndex)(
|
|
1707
|
+
headerDescription,
|
|
1708
|
+
-1,
|
|
1709
|
+
-1,
|
|
1710
|
+
);
|
|
1711
|
+
|
|
1712
|
+
if (
|
|
1713
|
+
rowIndexOffsetByHiddenRows[0] &&
|
|
1714
|
+
rowHeaderValue >= rowIndexOffsetByHiddenRows[0].from
|
|
1715
|
+
) {
|
|
1716
|
+
const { plus } = rowIndexOffsetByHiddenRows.shift();
|
|
1717
|
+
currentRowIndexOffset += plus;
|
|
1718
|
+
}
|
|
1105
1719
|
}
|
|
1106
1720
|
}
|
|
1107
1721
|
function drawHeaders() {
|
|
1108
1722
|
var d,
|
|
1109
|
-
g =
|
|
1723
|
+
g = schema.length,
|
|
1110
1724
|
i,
|
|
1111
1725
|
o,
|
|
1112
1726
|
columnHeaderCell,
|
|
@@ -1116,8 +1730,8 @@ export default function (self) {
|
|
|
1116
1730
|
end = Math.min(end, g);
|
|
1117
1731
|
for (o = start; o < end; o += 1) {
|
|
1118
1732
|
i = self.orders.columns[o];
|
|
1119
|
-
header =
|
|
1120
|
-
if (!header.hidden) {
|
|
1733
|
+
header = schema[i];
|
|
1734
|
+
if (!header.hidden && !isColumnCollapsedByGroup(o)) {
|
|
1121
1735
|
d = {
|
|
1122
1736
|
title: header.title,
|
|
1123
1737
|
name: header.name,
|
|
@@ -1182,7 +1796,7 @@ export default function (self) {
|
|
|
1182
1796
|
isColumnHeaderCell: true,
|
|
1183
1797
|
isColumnHeaderCellCap: true,
|
|
1184
1798
|
type: 'string',
|
|
1185
|
-
index:
|
|
1799
|
+
index: schema.length,
|
|
1186
1800
|
};
|
|
1187
1801
|
drawCell({ endCap: '' }, -1, -1)(c, -1, -1);
|
|
1188
1802
|
}
|
|
@@ -1201,20 +1815,20 @@ export default function (self) {
|
|
|
1201
1815
|
}
|
|
1202
1816
|
}
|
|
1203
1817
|
}
|
|
1204
|
-
function drawRow(
|
|
1205
|
-
var
|
|
1818
|
+
function drawRow(rowOrderIndex, rowIndex) {
|
|
1819
|
+
var headerIndex,
|
|
1206
1820
|
treeHeight,
|
|
1207
1821
|
rowSansTreeHeight,
|
|
1208
|
-
|
|
1209
|
-
g =
|
|
1822
|
+
columnOrderIndex,
|
|
1823
|
+
g = schema.length;
|
|
1210
1824
|
if (y - cellHeight * 2 > h) {
|
|
1211
1825
|
return false;
|
|
1212
1826
|
}
|
|
1213
|
-
|
|
1214
|
-
rowOpen = self.openChildren[
|
|
1827
|
+
rowData = viewData[rowOrderIndex];
|
|
1828
|
+
rowOpen = self.openChildren[rowOrderIndex];
|
|
1215
1829
|
rowSansTreeHeight =
|
|
1216
|
-
(self.sizes.rows[
|
|
1217
|
-
treeHeight = (rowOpen ? self.sizes.trees[
|
|
1830
|
+
(self.sizes.rows[rowOrderIndex] || self.style.cellHeight) * self.scale;
|
|
1831
|
+
treeHeight = (rowOpen ? self.sizes.trees[rowOrderIndex] : 0) * self.scale;
|
|
1218
1832
|
rowHeight = rowSansTreeHeight + treeHeight;
|
|
1219
1833
|
if (y < -rowHeight) {
|
|
1220
1834
|
return false;
|
|
@@ -1224,23 +1838,43 @@ export default function (self) {
|
|
|
1224
1838
|
}
|
|
1225
1839
|
cellHeight = rowHeight;
|
|
1226
1840
|
//draw normal columns
|
|
1227
|
-
for (
|
|
1228
|
-
|
|
1229
|
-
|
|
1841
|
+
for (
|
|
1842
|
+
columnOrderIndex = self.scrollIndexLeft;
|
|
1843
|
+
columnOrderIndex < g;
|
|
1844
|
+
columnOrderIndex += 1
|
|
1845
|
+
) {
|
|
1846
|
+
if (!isColumnCollapsedByGroup(columnOrderIndex)) {
|
|
1847
|
+
headerIndex = self.orders.columns[columnOrderIndex];
|
|
1848
|
+
x += drawCell(rowData, rowOrderIndex, rowIndex)(
|
|
1849
|
+
schema[headerIndex],
|
|
1850
|
+
headerIndex,
|
|
1851
|
+
columnOrderIndex,
|
|
1852
|
+
);
|
|
1853
|
+
}
|
|
1230
1854
|
if (x > self.width) {
|
|
1231
|
-
self.scrollIndexRight =
|
|
1855
|
+
self.scrollIndexRight = columnOrderIndex;
|
|
1232
1856
|
self.scrollPixelRight = x;
|
|
1233
1857
|
break;
|
|
1234
1858
|
}
|
|
1235
1859
|
}
|
|
1236
1860
|
//draw frozen columns
|
|
1237
|
-
x =
|
|
1861
|
+
x = 1;
|
|
1238
1862
|
if (self.attributes.showRowHeaders) {
|
|
1239
1863
|
x += rowHeaderCellWidth;
|
|
1240
1864
|
}
|
|
1241
|
-
for (
|
|
1242
|
-
|
|
1243
|
-
|
|
1865
|
+
for (
|
|
1866
|
+
columnOrderIndex = 0;
|
|
1867
|
+
columnOrderIndex < self.frozenColumn;
|
|
1868
|
+
columnOrderIndex += 1
|
|
1869
|
+
) {
|
|
1870
|
+
if (!isColumnCollapsedByGroup(columnOrderIndex)) {
|
|
1871
|
+
headerIndex = self.orders.columns[columnOrderIndex];
|
|
1872
|
+
x += drawCell(rowData, rowOrderIndex, rowIndex)(
|
|
1873
|
+
schema[headerIndex],
|
|
1874
|
+
headerIndex,
|
|
1875
|
+
columnOrderIndex,
|
|
1876
|
+
);
|
|
1877
|
+
}
|
|
1244
1878
|
if (x > self.width) {
|
|
1245
1879
|
break;
|
|
1246
1880
|
}
|
|
@@ -1253,8 +1887,8 @@ export default function (self) {
|
|
|
1253
1887
|
self.scrollPixelLeft +
|
|
1254
1888
|
self.style.cellBorderWidth;
|
|
1255
1889
|
// don't draw a tree for the new row
|
|
1256
|
-
treeGrid = self.childGrids[
|
|
1257
|
-
if (
|
|
1890
|
+
treeGrid = self.childGrids[rowOrderIndex];
|
|
1891
|
+
if (rowOrderIndex !== viewData.length && rowOpen) {
|
|
1258
1892
|
treeGrid.visible = true;
|
|
1259
1893
|
treeGrid.parentNode = {
|
|
1260
1894
|
offsetTop: y + rowSansTreeHeight + self.canvasOffsetTop,
|
|
@@ -1268,10 +1902,19 @@ export default function (self) {
|
|
|
1268
1902
|
nodeType: 'canvas-datagrid-tree',
|
|
1269
1903
|
scrollTop: self.scrollBox.scrollTop,
|
|
1270
1904
|
scrollLeft: self.scrollBox.scrollLeft,
|
|
1271
|
-
rowIndex:
|
|
1905
|
+
rowIndex: rowOrderIndex,
|
|
1906
|
+
columnGroupsAreaHeight: columnGroupsAreaHeight,
|
|
1907
|
+
rowGroupsAreaWidth: rowGroupsAreaWidth,
|
|
1272
1908
|
};
|
|
1909
|
+
if (self.intf.parentNode) {
|
|
1910
|
+
const { columnGroupsAreaHeight, rowGroupsAreaWidth } =
|
|
1911
|
+
self.intf.parentNode;
|
|
1912
|
+
treeGrid.parentNode.columnGroupsAreaHeight +=
|
|
1913
|
+
columnGroupsAreaHeight || 0;
|
|
1914
|
+
treeGrid.parentNode.rowGroupsAreaWidth += rowGroupsAreaWidth || 0;
|
|
1915
|
+
}
|
|
1273
1916
|
self.visibleCells.unshift({
|
|
1274
|
-
rowIndex:
|
|
1917
|
+
rowIndex: rowOrderIndex,
|
|
1275
1918
|
columnIndex: 0,
|
|
1276
1919
|
y: treeGrid.parentNode.offsetTop,
|
|
1277
1920
|
x: treeGrid.parentNode.offsetLeft,
|
|
@@ -1283,51 +1926,432 @@ export default function (self) {
|
|
|
1283
1926
|
treeGrid.draw();
|
|
1284
1927
|
} else if (treeGrid) {
|
|
1285
1928
|
treeGrid.parentNode.offsetHeight = 0;
|
|
1286
|
-
delete self.sizes.trees[
|
|
1929
|
+
delete self.sizes.trees[rowOrderIndex];
|
|
1287
1930
|
}
|
|
1288
|
-
rowHeaders.push([
|
|
1289
|
-
self.visibleRowHeights[
|
|
1931
|
+
rowHeaders.push([rowData, rowOrderIndex, rowIndex, y, rowHeight]);
|
|
1932
|
+
self.visibleRowHeights[rowOrderIndex] = rowHeight;
|
|
1290
1933
|
y += cellHeight + (bc ? 0 : self.style.cellBorderWidth);
|
|
1291
1934
|
return true;
|
|
1292
1935
|
}
|
|
1293
1936
|
function initDraw() {
|
|
1294
1937
|
self.visibleRows = [];
|
|
1295
|
-
|
|
1938
|
+
schema = self.getSchema();
|
|
1296
1939
|
self.visibleCells = [];
|
|
1940
|
+
self.visibleGroups = [];
|
|
1941
|
+
self.visibleUnhideIndicators = [];
|
|
1297
1942
|
self.canvasOffsetTop = self.isChildGrid ? self.parentNode.offsetTop : 0.5;
|
|
1298
1943
|
self.canvasOffsetLeft = self.isChildGrid
|
|
1299
1944
|
? self.parentNode.offsetLeft
|
|
1300
1945
|
: -0.5;
|
|
1301
1946
|
h = self.height;
|
|
1302
1947
|
w = self.width;
|
|
1948
|
+
|
|
1949
|
+
// patch for first row being hidden
|
|
1950
|
+
const firstRowIndexOffset = rowIndexOffsetByHiddenRows[0];
|
|
1951
|
+
if (firstRowIndexOffset && firstRowIndexOffset.from === 0) {
|
|
1952
|
+
currentRowIndexOffset = firstRowIndexOffset.plus;
|
|
1953
|
+
rowIndexOffsetByHiddenRows.shift();
|
|
1954
|
+
}
|
|
1303
1955
|
}
|
|
1304
1956
|
function drawBackground() {
|
|
1305
1957
|
radiusRect(0, 0, w, h, 0);
|
|
1306
1958
|
self.ctx.clip();
|
|
1959
|
+
self.ctx.clearRect(0, 0, w, h);
|
|
1307
1960
|
self.ctx.fillStyle = self.style.gridBackgroundColor;
|
|
1308
1961
|
fillRect(0, 0, w, h);
|
|
1309
1962
|
}
|
|
1963
|
+
function initGroupArea() {
|
|
1964
|
+
self.ctx.translate(rowGroupsAreaWidth, columnGroupsAreaHeight);
|
|
1965
|
+
}
|
|
1966
|
+
function drawGroupArea() {
|
|
1967
|
+
const mx = rowGroupsAreaWidth;
|
|
1968
|
+
const my = columnGroupsAreaHeight;
|
|
1969
|
+
const frozenColumnsWidth = getFrozenColumnsWidth();
|
|
1970
|
+
const frozenRowsHeight =
|
|
1971
|
+
rowGroupsFrozenInfo.y + rowGroupsFrozenInfo.h - columnHeaderCellHeight;
|
|
1972
|
+
const onTheLeft = self.attributes.columnGroupIndicatorPosition === 'left';
|
|
1973
|
+
const onTheTop = self.attributes.rowGroupIndicatorPosition === 'top';
|
|
1974
|
+
|
|
1975
|
+
/** @type {CanvasRenderingContext2D} */
|
|
1976
|
+
const ctx = self.ctx;
|
|
1977
|
+
ctx.save();
|
|
1978
|
+
ctx.fillStyle = self.style.groupingAreaBackgroundColor;
|
|
1979
|
+
fillRect(0, -my, w, my);
|
|
1980
|
+
fillRect(-mx, -my, mx, h);
|
|
1981
|
+
ctx.restore();
|
|
1982
|
+
|
|
1983
|
+
//#region Columns Grouping
|
|
1984
|
+
/** it extends `self.groupedRows` */
|
|
1985
|
+
const groupedColumns = [];
|
|
1986
|
+
for (let row = 0; row < self.groupedColumns.length; row++) {
|
|
1987
|
+
const groups = self.groupedColumns[row];
|
|
1988
|
+
for (let j = 0; j < groups.length; j++) {
|
|
1989
|
+
groupedColumns.push(Object.assign({ row }, groups[j]));
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
if (groupedColumns.length > 0) {
|
|
1993
|
+
const rowHeight = self.style.columnGroupRowHeight;
|
|
1994
|
+
const toggleHandleSize = rowHeight * 0.5;
|
|
1995
|
+
const toggleHandlePadding = (rowHeight - toggleHandleSize) * 0.5;
|
|
1996
|
+
|
|
1997
|
+
for (let i = 0; i < groupedColumns.length; i++) {
|
|
1998
|
+
const group = groupedColumns[i];
|
|
1999
|
+
const { row, collapsed } = group;
|
|
2000
|
+
|
|
2001
|
+
const topY = -my + row * rowHeight;
|
|
2002
|
+
const centerY = topY + rowHeight * 0.5;
|
|
2003
|
+
const bottomY = topY + rowHeight - toggleHandlePadding;
|
|
2004
|
+
const leftmostX =
|
|
2005
|
+
rowHeaderCellWidth - toggleHandleSize - toggleHandlePadding;
|
|
2006
|
+
|
|
2007
|
+
const drawGroupHandleAtX = (x) =>
|
|
2008
|
+
drawGroupHandle(
|
|
2009
|
+
x,
|
|
2010
|
+
topY + toggleHandlePadding,
|
|
2011
|
+
toggleHandleSize,
|
|
2012
|
+
group.collapsed,
|
|
2013
|
+
);
|
|
2014
|
+
const pushToVisibleGroups = (leftX, rightX) =>
|
|
2015
|
+
self.visibleGroups.push({
|
|
2016
|
+
type: 'c',
|
|
2017
|
+
collapsed,
|
|
2018
|
+
from: group.from,
|
|
2019
|
+
to: group.to,
|
|
2020
|
+
row,
|
|
2021
|
+
x: leftX + mx,
|
|
2022
|
+
y: topY + my,
|
|
2023
|
+
x2: rightX + mx,
|
|
2024
|
+
y2: bottomY + my,
|
|
2025
|
+
});
|
|
2026
|
+
|
|
2027
|
+
//#region check the relationship between this group and frozen columns
|
|
2028
|
+
const crossTheFrozen =
|
|
2029
|
+
group.from < self.frozenColumn && group.to >= self.frozenColumn;
|
|
2030
|
+
const notInFrozen = group.from >= self.frozenColumn;
|
|
2031
|
+
//#endregion
|
|
2032
|
+
|
|
2033
|
+
if (collapsed) {
|
|
2034
|
+
let leftX = leftmostX + toggleHandleSize;
|
|
2035
|
+
// This group is not sticking on the first column
|
|
2036
|
+
if (group.from > 0) {
|
|
2037
|
+
let colIndex = group.to + 1;
|
|
2038
|
+
let col = columnGroupsRectInfo[colIndex];
|
|
2039
|
+
if (!col) {
|
|
2040
|
+
colIndex = group.from - 1;
|
|
2041
|
+
col = columnGroupsRectInfo[colIndex];
|
|
2042
|
+
if (!col) continue; // don't draw this group indicator because it is invisible
|
|
2043
|
+
leftX = col.x + col.w - toggleHandleSize * 0.5;
|
|
2044
|
+
} else {
|
|
2045
|
+
leftX = col.x + toggleHandlePadding;
|
|
2046
|
+
}
|
|
2047
|
+
if (colIndex >= self.frozenColumn) {
|
|
2048
|
+
const compare =
|
|
2049
|
+
frozenColumnsWidth + rowHeaderCellWidth - toggleHandlePadding;
|
|
2050
|
+
// don't draw this group indicator because it is hidden by frozen columns
|
|
2051
|
+
if (leftX < compare) continue;
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
const rightX = leftX + toggleHandleSize;
|
|
2055
|
+
ctx.save();
|
|
2056
|
+
ctx.strokeStyle = self.style.groupIndicatorColor;
|
|
2057
|
+
ctx.fillStyle = self.style.groupIndicatorBackgroundColor;
|
|
2058
|
+
drawGroupHandleAtX(leftX);
|
|
2059
|
+
ctx.restore();
|
|
2060
|
+
pushToVisibleGroups(leftX, rightX);
|
|
2061
|
+
} // end of collapsed group
|
|
2062
|
+
|
|
2063
|
+
/** @type {number} pointer for loop */
|
|
2064
|
+
let ptr;
|
|
2065
|
+
let left = columnGroupsRectInfo[group.from];
|
|
2066
|
+
let right = columnGroupsRectInfo[group.to];
|
|
2067
|
+
|
|
2068
|
+
let containsBegining = true;
|
|
2069
|
+
let containsEnd = true;
|
|
2070
|
+
ptr = group.from;
|
|
2071
|
+
while (!left && ptr < group.to) {
|
|
2072
|
+
left = columnGroupsRectInfo[++ptr];
|
|
2073
|
+
containsBegining = false;
|
|
2074
|
+
}
|
|
2075
|
+
ptr = group.to;
|
|
2076
|
+
while (!right && ptr > group.from) {
|
|
2077
|
+
right = columnGroupsRectInfo[--ptr];
|
|
2078
|
+
containsEnd = false;
|
|
2079
|
+
}
|
|
2080
|
+
if (!left || !right) continue;
|
|
2081
|
+
let rightX = right.x + right.w;
|
|
2082
|
+
let leftX = left.x;
|
|
2083
|
+
if (crossTheFrozen) {
|
|
2084
|
+
const rightCompare = columnGroupsRectInfo[self.frozenColumn - 1];
|
|
2085
|
+
if (rightCompare) {
|
|
2086
|
+
let compareX = rightCompare.x + rightCompare.w;
|
|
2087
|
+
if (!onTheLeft) compareX += toggleHandleSize;
|
|
2088
|
+
if (compareX >= rightX) {
|
|
2089
|
+
right = rightCompare;
|
|
2090
|
+
rightX = right.x + right.w;
|
|
2091
|
+
containsEnd = false;
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
let minLeftX =
|
|
2097
|
+
rowHeaderCellWidth + (notInFrozen ? frozenColumnsWidth : 0);
|
|
2098
|
+
if (rightX + (onTheLeft ? 0 : toggleHandleSize) < minLeftX) continue;
|
|
2099
|
+
|
|
2100
|
+
rightX -= toggleHandlePadding;
|
|
2101
|
+
leftX += toggleHandlePadding;
|
|
2102
|
+
|
|
2103
|
+
ctx.save();
|
|
2104
|
+
ctx.strokeStyle = self.style.groupIndicatorColor;
|
|
2105
|
+
ctx.fillStyle = self.style.groupIndicatorBackgroundColor;
|
|
2106
|
+
const lineCoords = [];
|
|
2107
|
+
|
|
2108
|
+
if (onTheLeft) {
|
|
2109
|
+
// avoid lines from two groups be overlapping
|
|
2110
|
+
minLeftX += toggleHandlePadding * 2;
|
|
2111
|
+
if (leftX < minLeftX) leftX = minLeftX;
|
|
2112
|
+
if (group.from === 0) leftX -= toggleHandlePadding * 2;
|
|
2113
|
+
if (rightX >= leftX) {
|
|
2114
|
+
lineCoords.push(leftX, centerY, rightX, centerY);
|
|
2115
|
+
if (containsEnd) lineCoords.push(rightX, bottomY);
|
|
2116
|
+
} else {
|
|
2117
|
+
rightX = leftX;
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
leftX -= toggleHandleSize;
|
|
2121
|
+
drawGroupHandleAtX(leftX);
|
|
2122
|
+
// add more clickable area into `visibleGroups`
|
|
2123
|
+
rightX += toggleHandlePadding - 1;
|
|
2124
|
+
} else {
|
|
2125
|
+
// handle on the right
|
|
2126
|
+
if (leftX < minLeftX) leftX = minLeftX;
|
|
2127
|
+
if (group.from === 0) leftX -= toggleHandlePadding * 2;
|
|
2128
|
+
if (containsEnd) {
|
|
2129
|
+
if (group.to === self.frozenColumn - 1) {
|
|
2130
|
+
rightX -= toggleHandleSize;
|
|
2131
|
+
} else {
|
|
2132
|
+
rightX += toggleHandlePadding * 2;
|
|
2133
|
+
}
|
|
2134
|
+
drawGroupHandleAtX(rightX);
|
|
2135
|
+
}
|
|
2136
|
+
if (leftX > rightX) {
|
|
2137
|
+
leftX = rightX;
|
|
2138
|
+
} else {
|
|
2139
|
+
if (group.from === 0) {
|
|
2140
|
+
containsBegining = true;
|
|
2141
|
+
leftX = leftmostX + toggleHandleSize;
|
|
2142
|
+
}
|
|
2143
|
+
if (containsBegining) lineCoords.push(leftX, bottomY);
|
|
2144
|
+
lineCoords.push(leftX, centerY, rightX, centerY);
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
// add more clickable area into `visibleGroups`
|
|
2148
|
+
leftX -= toggleHandlePadding + 1;
|
|
2149
|
+
if (containsEnd) rightX += toggleHandleSize;
|
|
2150
|
+
}
|
|
2151
|
+
drawLines(lineCoords);
|
|
2152
|
+
ctx.restore();
|
|
2153
|
+
pushToVisibleGroups(leftX, rightX);
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
//#endregion Columns Grouping
|
|
2157
|
+
|
|
2158
|
+
//#region Rows Grouping
|
|
2159
|
+
/** it extends `self.groupedRows` */
|
|
2160
|
+
const groupedRows = [];
|
|
2161
|
+
for (let col = 0; col < self.groupedRows.length; col++) {
|
|
2162
|
+
const groups = self.groupedRows[col];
|
|
2163
|
+
for (let j = 0; j < groups.length; j++) {
|
|
2164
|
+
groupedRows.push(Object.assign({ col }, groups[j]));
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
if (groupedRows.length > 0) {
|
|
2168
|
+
const colWidth = self.style.rowGroupColumnWidth;
|
|
2169
|
+
const toggleHandleSize = colWidth * 0.5;
|
|
2170
|
+
const toggleHandlePadding = (colWidth - toggleHandleSize) * 0.5;
|
|
2171
|
+
|
|
2172
|
+
for (let i = 0; i < groupedRows.length; i++) {
|
|
2173
|
+
const group = groupedRows[i];
|
|
2174
|
+
const { col, collapsed } = group;
|
|
2175
|
+
|
|
2176
|
+
const leftX = -mx + col * colWidth;
|
|
2177
|
+
const centerX = leftX + colWidth * 0.5;
|
|
2178
|
+
const rightX = leftX + colWidth - toggleHandlePadding;
|
|
2179
|
+
const topmostY =
|
|
2180
|
+
columnHeaderCellHeight - toggleHandleSize - toggleHandlePadding;
|
|
2181
|
+
|
|
2182
|
+
const drawGroupHandleAtY = (y) =>
|
|
2183
|
+
drawGroupHandle(
|
|
2184
|
+
leftX + toggleHandlePadding,
|
|
2185
|
+
y,
|
|
2186
|
+
toggleHandleSize,
|
|
2187
|
+
group.collapsed,
|
|
2188
|
+
);
|
|
2189
|
+
const pushToVisibleGroups = (topY, bottomY) =>
|
|
2190
|
+
self.visibleGroups.push({
|
|
2191
|
+
type: 'r',
|
|
2192
|
+
collapsed,
|
|
2193
|
+
from: group.from,
|
|
2194
|
+
to: group.to,
|
|
2195
|
+
col,
|
|
2196
|
+
x: leftX + mx,
|
|
2197
|
+
y: topY + my,
|
|
2198
|
+
x2: rightX + mx,
|
|
2199
|
+
y2: bottomY + my,
|
|
2200
|
+
});
|
|
2201
|
+
|
|
2202
|
+
//#region check the relationship between this group and frozen columns
|
|
2203
|
+
const crossTheFrozen =
|
|
2204
|
+
group.from < self.frozenRow && group.to >= self.frozenRow;
|
|
2205
|
+
const notInFrozen = group.from >= self.frozenRow;
|
|
2206
|
+
//#endregion
|
|
2207
|
+
|
|
2208
|
+
if (collapsed) {
|
|
2209
|
+
let topY = topmostY + toggleHandleSize;
|
|
2210
|
+
// This group is not sticking on the first column
|
|
2211
|
+
if (group.from > 0) {
|
|
2212
|
+
let rowIndex = group.to + 1;
|
|
2213
|
+
let row = rowGroupsRectInfo[rowIndex];
|
|
2214
|
+
if (!row) {
|
|
2215
|
+
rowIndex = group.from - 1;
|
|
2216
|
+
row = rowGroupsRectInfo[rowIndex];
|
|
2217
|
+
if (!row) continue; // don't draw this group indicator because it is invisible
|
|
2218
|
+
topY = row.y + row.h - toggleHandleSize * 0.5;
|
|
2219
|
+
} else {
|
|
2220
|
+
topY = row.y;
|
|
2221
|
+
}
|
|
2222
|
+
if (rowIndex >= self.frozenRow) {
|
|
2223
|
+
const compare =
|
|
2224
|
+
frozenRowsHeight +
|
|
2225
|
+
columnHeaderCellHeight -
|
|
2226
|
+
toggleHandlePadding;
|
|
2227
|
+
// don't draw this group indicator because it is hidden by frozen columns
|
|
2228
|
+
if (topY < compare) continue;
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
const bottomY = topY + toggleHandleSize;
|
|
2232
|
+
ctx.save();
|
|
2233
|
+
ctx.strokeStyle = self.style.groupIndicatorColor;
|
|
2234
|
+
ctx.fillStyle = self.style.groupIndicatorBackgroundColor;
|
|
2235
|
+
drawGroupHandleAtY(topY);
|
|
2236
|
+
ctx.restore();
|
|
2237
|
+
pushToVisibleGroups(topY, bottomY);
|
|
2238
|
+
} // end of collapsed group
|
|
2239
|
+
|
|
2240
|
+
/** @type {number} pointer for loop */
|
|
2241
|
+
let ptr;
|
|
2242
|
+
let top = rowGroupsRectInfo[group.from];
|
|
2243
|
+
let bottom = rowGroupsRectInfo[group.to];
|
|
2244
|
+
|
|
2245
|
+
let containsBegining = true;
|
|
2246
|
+
let containsEnd = true;
|
|
2247
|
+
ptr = group.from;
|
|
2248
|
+
while (!top && ptr < group.to) {
|
|
2249
|
+
top = rowGroupsRectInfo[++ptr];
|
|
2250
|
+
containsBegining = false;
|
|
2251
|
+
}
|
|
2252
|
+
ptr = group.to;
|
|
2253
|
+
while (!bottom && ptr > group.from) {
|
|
2254
|
+
bottom = rowGroupsRectInfo[--ptr];
|
|
2255
|
+
containsEnd = false;
|
|
2256
|
+
}
|
|
2257
|
+
if (!top || !bottom) continue;
|
|
2258
|
+
let bottomY = bottom.y + bottom.h;
|
|
2259
|
+
let topY = top.y;
|
|
2260
|
+
if (crossTheFrozen) {
|
|
2261
|
+
const bottomCompare = rowGroupsRectInfo[self.frozenRow - 1];
|
|
2262
|
+
if (bottomCompare) {
|
|
2263
|
+
let compareY = bottomCompare.y + bottomCompare.h;
|
|
2264
|
+
if (!onTheTop) compareY += toggleHandleSize;
|
|
2265
|
+
if (compareY >= bottomY) {
|
|
2266
|
+
bottom = bottomCompare;
|
|
2267
|
+
bottomY = bottom.y + bottom.h;
|
|
2268
|
+
containsEnd = false;
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
let minTopY =
|
|
2274
|
+
columnHeaderCellHeight + (notInFrozen ? frozenRowsHeight : 0);
|
|
2275
|
+
if (bottomY + (onTheTop ? 0 : toggleHandleSize) < minTopY) continue;
|
|
2276
|
+
|
|
2277
|
+
bottomY -= toggleHandlePadding;
|
|
2278
|
+
topY += toggleHandlePadding;
|
|
2279
|
+
|
|
2280
|
+
ctx.save();
|
|
2281
|
+
ctx.strokeStyle = self.style.groupIndicatorColor;
|
|
2282
|
+
ctx.fillStyle = self.style.groupIndicatorBackgroundColor;
|
|
2283
|
+
const lineCoords = [];
|
|
2284
|
+
|
|
2285
|
+
if (onTheTop) {
|
|
2286
|
+
// avoid lines from two groups be overlapping
|
|
2287
|
+
minTopY += toggleHandlePadding * 2;
|
|
2288
|
+
if (topY < minTopY) topY = minTopY;
|
|
2289
|
+
if (group.from === 0) topY -= toggleHandlePadding * 2;
|
|
2290
|
+
if (bottomY >= topY) {
|
|
2291
|
+
lineCoords.push(centerX, topY, centerX, bottomY);
|
|
2292
|
+
if (containsEnd) lineCoords.push(rightX, bottomY);
|
|
2293
|
+
} else {
|
|
2294
|
+
bottomY = topY;
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
topY -= toggleHandleSize;
|
|
2298
|
+
drawGroupHandleAtY(topY);
|
|
2299
|
+
|
|
2300
|
+
// add more clickable area into `visibleGroups`
|
|
2301
|
+
bottomY += toggleHandlePadding - 1;
|
|
2302
|
+
} else {
|
|
2303
|
+
// handle on the bottom
|
|
2304
|
+
if (topY < minTopY) topY = minTopY;
|
|
2305
|
+
if (group.from === 0) topY -= toggleHandlePadding * 2;
|
|
2306
|
+
if (containsEnd) {
|
|
2307
|
+
if (group.to === self.frozenRow - 1) {
|
|
2308
|
+
bottomY -= toggleHandleSize;
|
|
2309
|
+
} else {
|
|
2310
|
+
// bottomY += toggleHandlePadding * 2;
|
|
2311
|
+
}
|
|
2312
|
+
drawGroupHandleAtY(bottomY);
|
|
2313
|
+
}
|
|
2314
|
+
if (topY > bottomY) {
|
|
2315
|
+
topY = bottomY;
|
|
2316
|
+
} else {
|
|
2317
|
+
if (group.from === 0) {
|
|
2318
|
+
containsBegining = true;
|
|
2319
|
+
topY = topmostY + toggleHandleSize;
|
|
2320
|
+
}
|
|
2321
|
+
if (containsBegining) lineCoords.push(rightX, topY);
|
|
2322
|
+
lineCoords.push(centerX, topY, centerX, bottomY);
|
|
2323
|
+
// add more clickable area into `visibleGroups`
|
|
2324
|
+
topY -= toggleHandlePadding + 1;
|
|
2325
|
+
}
|
|
2326
|
+
// add more clickable area into `visibleGroups`
|
|
2327
|
+
if (containsEnd) bottomY += toggleHandleSize;
|
|
2328
|
+
}
|
|
2329
|
+
drawLines(lineCoords);
|
|
2330
|
+
ctx.restore();
|
|
2331
|
+
pushToVisibleGroups(topY, bottomY);
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
//#endregion Rows Grouping
|
|
2335
|
+
}
|
|
1310
2336
|
function drawFrozenRows() {
|
|
1311
|
-
var
|
|
1312
|
-
ln = Math.min(
|
|
2337
|
+
var rowOrderIndex,
|
|
2338
|
+
ln = Math.min(viewData.length, self.frozenRow);
|
|
1313
2339
|
x =
|
|
1314
2340
|
-self.scrollBox.scrollLeft +
|
|
1315
2341
|
self.scrollPixelLeft +
|
|
1316
2342
|
self.style.cellBorderWidth;
|
|
1317
2343
|
y = columnHeaderCellHeight;
|
|
1318
|
-
for (
|
|
1319
|
-
|
|
1320
|
-
if (!drawRow(
|
|
2344
|
+
for (rowIndex = 0; rowIndex < ln; rowIndex += 1) {
|
|
2345
|
+
rowOrderIndex = self.orders.rows[rowIndex];
|
|
2346
|
+
if (!drawRow(rowOrderIndex, rowIndex)) {
|
|
1321
2347
|
break;
|
|
1322
2348
|
}
|
|
1323
2349
|
}
|
|
1324
2350
|
if (self.attributes.allowFreezingRows) {
|
|
1325
2351
|
// HACK great, another stupid magic number.
|
|
1326
2352
|
// Background will appear as a 0.5px artifact behind the row freeze bar without this hack
|
|
1327
|
-
y +=
|
|
1328
|
-
|
|
1329
|
-
self.style.frozenMarkerWidth -
|
|
1330
|
-
0.4999999999;
|
|
2353
|
+
if (y > columnHeaderCellHeight) y += self.style.frozenMarkerWidth;
|
|
2354
|
+
y += self.style.frozenMarkerBorderWidth - 0.4999999999;
|
|
1331
2355
|
}
|
|
1332
2356
|
self.lastFrozenRowPixel = y;
|
|
1333
2357
|
}
|
|
@@ -1343,10 +2367,10 @@ export default function (self) {
|
|
|
1343
2367
|
);
|
|
1344
2368
|
self.ctx.clip();
|
|
1345
2369
|
}
|
|
1346
|
-
var
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
g =
|
|
2370
|
+
var columnOrderIndex,
|
|
2371
|
+
rowOrderIndex,
|
|
2372
|
+
headerIndex,
|
|
2373
|
+
g = schema.length;
|
|
1350
2374
|
x =
|
|
1351
2375
|
-self.scrollBox.scrollLeft +
|
|
1352
2376
|
self.scrollPixelLeft +
|
|
@@ -1357,11 +2381,21 @@ export default function (self) {
|
|
|
1357
2381
|
self.scrollPixelTop +
|
|
1358
2382
|
self.style.cellBorderWidth;
|
|
1359
2383
|
}
|
|
1360
|
-
for (
|
|
1361
|
-
|
|
1362
|
-
|
|
2384
|
+
for (
|
|
2385
|
+
rowIndex = self.frozenRow + self.scrollIndexTop;
|
|
2386
|
+
rowIndex < l;
|
|
2387
|
+
rowIndex += 1
|
|
2388
|
+
) {
|
|
2389
|
+
rowOrderIndex = self.orders.rows[rowIndex];
|
|
2390
|
+
self.scrollIndexBottom = rowIndex;
|
|
1363
2391
|
self.scrollPixelBottom = y;
|
|
1364
|
-
if (
|
|
2392
|
+
if (
|
|
2393
|
+
self.cellTree.rows.length > 0 &&
|
|
2394
|
+
Object.keys(self.cellTree.rows[rowOrderIndex]).length > 0 &&
|
|
2395
|
+
self.cellTree.rows[rowOrderIndex].hide
|
|
2396
|
+
)
|
|
2397
|
+
continue;
|
|
2398
|
+
if (!drawRow(rowOrderIndex, rowIndex)) {
|
|
1365
2399
|
break;
|
|
1366
2400
|
}
|
|
1367
2401
|
}
|
|
@@ -1371,14 +2405,30 @@ export default function (self) {
|
|
|
1371
2405
|
}
|
|
1372
2406
|
rowHeight = cellHeight = self.style.cellHeight;
|
|
1373
2407
|
rowOpen = false;
|
|
1374
|
-
for (
|
|
1375
|
-
|
|
1376
|
-
|
|
2408
|
+
for (
|
|
2409
|
+
columnOrderIndex = self.scrollIndexLeft;
|
|
2410
|
+
columnOrderIndex < g;
|
|
2411
|
+
columnOrderIndex += 1
|
|
2412
|
+
) {
|
|
2413
|
+
if (!isColumnCollapsedByGroup(columnOrderIndex)) {
|
|
2414
|
+
headerIndex = self.orders.columns[columnOrderIndex];
|
|
2415
|
+
x += drawCell(self.newRow, viewData.length, viewData.length)(
|
|
2416
|
+
schema[headerIndex],
|
|
2417
|
+
headerIndex,
|
|
2418
|
+
columnOrderIndex,
|
|
2419
|
+
);
|
|
2420
|
+
}
|
|
1377
2421
|
if (x > self.width + self.scrollBox.scrollLeft) {
|
|
1378
2422
|
break;
|
|
1379
2423
|
}
|
|
1380
2424
|
}
|
|
1381
|
-
rowHeaders.push([
|
|
2425
|
+
rowHeaders.push([
|
|
2426
|
+
self.newRow,
|
|
2427
|
+
viewData.length,
|
|
2428
|
+
viewData.length,
|
|
2429
|
+
y,
|
|
2430
|
+
rowHeight,
|
|
2431
|
+
]);
|
|
1382
2432
|
}
|
|
1383
2433
|
self.ctx.restore();
|
|
1384
2434
|
}
|
|
@@ -1414,6 +2464,7 @@ export default function (self) {
|
|
|
1414
2464
|
self.ctx.lineWidth = self.style.reorderMarkerBorderWidth;
|
|
1415
2465
|
self.ctx.strokeStyle = self.style.reorderMarkerBorderColor;
|
|
1416
2466
|
if (self.dragMode === 'row-reorder') {
|
|
2467
|
+
b.height = self.getSelectedRowsHeight();
|
|
1417
2468
|
b.width = w;
|
|
1418
2469
|
b.x = 0;
|
|
1419
2470
|
m.width = w;
|
|
@@ -1424,6 +2475,7 @@ export default function (self) {
|
|
|
1424
2475
|
self.ctx.lineWidth = self.style.reorderMarkerIndexBorderWidth;
|
|
1425
2476
|
self.ctx.strokeStyle = self.style.reorderMarkerIndexBorderColor;
|
|
1426
2477
|
if (
|
|
2478
|
+
!self.isRowSelected(self.reorderTarget.sortRowIndex) &&
|
|
1427
2479
|
self.currentCell.rowIndex !== self.reorderObject.rowIndex &&
|
|
1428
2480
|
self.currentCell.rowIndex > -1 &&
|
|
1429
2481
|
self.currentCell.rowIndex < l
|
|
@@ -1436,6 +2488,7 @@ export default function (self) {
|
|
|
1436
2488
|
);
|
|
1437
2489
|
}
|
|
1438
2490
|
} else if (self.dragMode === 'column-reorder' && self.reorderObject) {
|
|
2491
|
+
b.width = self.getSelectedColumnsWidth();
|
|
1439
2492
|
b.height = h;
|
|
1440
2493
|
b.y = 0;
|
|
1441
2494
|
m.height = h;
|
|
@@ -1447,10 +2500,12 @@ export default function (self) {
|
|
|
1447
2500
|
self.ctx.lineWidth = self.style.reorderMarkerIndexBorderWidth;
|
|
1448
2501
|
self.ctx.strokeStyle = self.style.reorderMarkerIndexBorderColor;
|
|
1449
2502
|
if (
|
|
2503
|
+
!self.isColumnSelected(self.reorderTarget.sortColumnIndex) &&
|
|
1450
2504
|
self.currentCell.sortColumnIndex !==
|
|
1451
2505
|
self.reorderObject.sortColumnIndex &&
|
|
2506
|
+
self.reorderTarget.columnIndex !== self.reorderObject.columnIndex &&
|
|
1452
2507
|
self.currentCell.sortColumnIndex > -1 &&
|
|
1453
|
-
self.currentCell.sortColumnIndex <
|
|
2508
|
+
self.currentCell.sortColumnIndex < schema.length
|
|
1454
2509
|
) {
|
|
1455
2510
|
addBorderLine(
|
|
1456
2511
|
m,
|
|
@@ -1461,16 +2516,43 @@ export default function (self) {
|
|
|
1461
2516
|
}
|
|
1462
2517
|
}
|
|
1463
2518
|
}
|
|
2519
|
+
function drawResizeMarkers() {
|
|
2520
|
+
if (
|
|
2521
|
+
!self.attributes.resizeAfterDragged ||
|
|
2522
|
+
!self.draggingItem ||
|
|
2523
|
+
!self.pendingDragResize ||
|
|
2524
|
+
(self.dragMode != 'ew-resize' && self.dragMode != 'ns-resize')
|
|
2525
|
+
) {
|
|
2526
|
+
return;
|
|
2527
|
+
}
|
|
2528
|
+
|
|
2529
|
+
const resizingRow = self.dragMode == 'ns-resize';
|
|
2530
|
+
const height = resizingRow ? self.style.resizeMarkerSize : self.height;
|
|
2531
|
+
const width = resizingRow ? self.width : self.style.resizeMarkerSize;
|
|
2532
|
+
const minX =
|
|
2533
|
+
self.dragStart.x -
|
|
2534
|
+
(self.resizingStartingWidth - self.style.minColumnWidth);
|
|
2535
|
+
const minY =
|
|
2536
|
+
self.dragStart.y -
|
|
2537
|
+
(self.resizingStartingHeight - self.style.minRowHeight);
|
|
2538
|
+
const x = resizingRow ? 0 : Math.max(self.pendingDragResize.x, minX);
|
|
2539
|
+
const y = !resizingRow ? 0 : Math.max(self.pendingDragResize.y, minY);
|
|
2540
|
+
|
|
2541
|
+
self.ctx.fillStyle = self.style.resizeMarkerColor;
|
|
2542
|
+
fillRect(x, y, width, height);
|
|
2543
|
+
}
|
|
1464
2544
|
function drawBorder() {
|
|
1465
2545
|
self.ctx.lineWidth = self.style.gridBorderWidth;
|
|
1466
2546
|
self.ctx.strokeStyle = self.style.gridBorderColor;
|
|
1467
2547
|
strokeRect(0, 0, self.width, self.height);
|
|
1468
2548
|
}
|
|
1469
2549
|
function drawSelectionBorders() {
|
|
1470
|
-
self.ctx.lineWidth = self.style.selectionOverlayBorderWidth;
|
|
1471
|
-
self.ctx.strokeStyle = self.style.selectionOverlayBorderColor;
|
|
1472
2550
|
function dsb(c) {
|
|
1473
|
-
|
|
2551
|
+
if (!self.fillOverlay.handle) {
|
|
2552
|
+
self.ctx.lineWidth = self.style.selectionOverlayBorderWidth;
|
|
2553
|
+
self.ctx.strokeStyle = self.style.selectionOverlayBorderColor;
|
|
2554
|
+
addBorderLine(c[0], c[1]);
|
|
2555
|
+
}
|
|
1474
2556
|
}
|
|
1475
2557
|
selectionBorders
|
|
1476
2558
|
.filter(function (c) {
|
|
@@ -1513,9 +2595,14 @@ export default function (self) {
|
|
|
1513
2595
|
})
|
|
1514
2596
|
.forEach(dsb);
|
|
1515
2597
|
self.ctx.restore();
|
|
2598
|
+
|
|
2599
|
+
drawFillOverlay();
|
|
1516
2600
|
}
|
|
1517
2601
|
function drawSelectionHandles() {
|
|
1518
|
-
if (
|
|
2602
|
+
if (
|
|
2603
|
+
(self.mobile || self.attributes.allowMovingSelection) &&
|
|
2604
|
+
self.attributes.editable
|
|
2605
|
+
) {
|
|
1519
2606
|
self.ctx.lineWidth = self.style.selectionHandleBorderWidth;
|
|
1520
2607
|
self.ctx.strokeStyle = self.style.selectionHandleBorderColor;
|
|
1521
2608
|
self.ctx.fillStyle = self.style.selectionHandleColor;
|
|
@@ -1536,6 +2623,62 @@ export default function (self) {
|
|
|
1536
2623
|
});
|
|
1537
2624
|
}
|
|
1538
2625
|
}
|
|
2626
|
+
function drawFillOverlay() {
|
|
2627
|
+
if (!self.fillOverlay.handle || !self.fillOverlay.snapTo) {
|
|
2628
|
+
return;
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
self.ctx.save();
|
|
2632
|
+
|
|
2633
|
+
const overlay = self.fillOverlay;
|
|
2634
|
+
const handle = overlay.handle;
|
|
2635
|
+
const toX = overlay.snapTo.x;
|
|
2636
|
+
const toY = overlay.snapTo.y;
|
|
2637
|
+
|
|
2638
|
+
// The cell that the cursor is moving over. This may be unavailable
|
|
2639
|
+
// when the cursor is outside the grid or is pointing to something else.
|
|
2640
|
+
//
|
|
2641
|
+
// When unavailable, we use the actual position of the cursor to draw
|
|
2642
|
+
// the overlay.
|
|
2643
|
+
const snap = overlay.snap;
|
|
2644
|
+
|
|
2645
|
+
// Calculate the X, Y coordinates of the cursor with snap positions and
|
|
2646
|
+
// the direction of the movement in mind.
|
|
2647
|
+
//
|
|
2648
|
+
// When the movement is horizontal, we get the Y coordinate from the handle,
|
|
2649
|
+
// and vice-versa.
|
|
2650
|
+
const cursorX =
|
|
2651
|
+
overlay.direction === 'x'
|
|
2652
|
+
? snap
|
|
2653
|
+
? snap.x + (overlay.x < toX ? 0 : snap.width)
|
|
2654
|
+
: overlay.x
|
|
2655
|
+
: handle.x;
|
|
2656
|
+
const cursorY =
|
|
2657
|
+
overlay.direction === undefined || overlay.direction === 'y'
|
|
2658
|
+
? snap
|
|
2659
|
+
? snap.y + (overlay.y < toY ? 0 : snap.height)
|
|
2660
|
+
: overlay.y
|
|
2661
|
+
: handle.y;
|
|
2662
|
+
|
|
2663
|
+
// The final coordinates of the rect. We use 'minX' and 'minY' to avoid
|
|
2664
|
+
// drawing on the frozen area.
|
|
2665
|
+
const x = Math.max(Math.min(toX, cursorX), overlay.minX);
|
|
2666
|
+
const y = Math.max(Math.min(toY, cursorY), overlay.minY);
|
|
2667
|
+
|
|
2668
|
+
// Width and height of the rect are the difference between the
|
|
2669
|
+
// coordinates of both the rect and the cursor. The user may be pointing
|
|
2670
|
+
// behind and/or upwards of the rect, so we need to take that into
|
|
2671
|
+
// account.
|
|
2672
|
+
const width = Math.max(toX, cursorX) - x;
|
|
2673
|
+
const height = Math.max(toY, cursorY) - y;
|
|
2674
|
+
|
|
2675
|
+
self.ctx.strokeStyle = self.style.fillOverlayBorderColor;
|
|
2676
|
+
self.ctx.lineWidth = self.style.fillOverlayBorderWidth;
|
|
2677
|
+
self.ctx.setLineDash([3, 3]);
|
|
2678
|
+
strokeRect(x, y, width, height);
|
|
2679
|
+
self.ctx.setLineDash([]);
|
|
2680
|
+
self.ctx.restore();
|
|
2681
|
+
}
|
|
1539
2682
|
function drawActiveCell() {
|
|
1540
2683
|
if (!aCell) {
|
|
1541
2684
|
return;
|
|
@@ -1570,77 +2713,171 @@ export default function (self) {
|
|
|
1570
2713
|
}
|
|
1571
2714
|
function drawFrozenMarkers() {
|
|
1572
2715
|
var my = self.lastFrozenRowPixel - self.style.frozenMarkerWidth,
|
|
1573
|
-
mx = self.lastFrozenColumnPixel - self.style.
|
|
2716
|
+
mx = self.lastFrozenColumnPixel - self.style.frozenMarkerWidth,
|
|
1574
2717
|
xHover =
|
|
1575
2718
|
self.currentCell && self.currentCell.style === 'frozen-row-marker',
|
|
1576
2719
|
yHover =
|
|
1577
2720
|
self.currentCell && self.currentCell.style === 'frozen-column-marker';
|
|
2721
|
+
let rowHeaderCellWidth = self.getRowHeaderCellWidth();
|
|
1578
2722
|
self.ctx.lineWidth = self.style.frozenMarkerBorderWidth;
|
|
1579
2723
|
if (self.attributes.allowFreezingColumns) {
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
}
|
|
1597
|
-
if (self.attributes.allowFreezingRows) {
|
|
1598
|
-
self.ctx.fillStyle = xHover
|
|
1599
|
-
? self.style.frozenMarkerHoverColor
|
|
1600
|
-
: self.style.frozenMarkerColor;
|
|
1601
|
-
self.ctx.strokeStyle = xHover
|
|
1602
|
-
? self.style.frozenMarkerHoverBorderColor
|
|
1603
|
-
: self.style.frozenMarkerBorderColor;
|
|
1604
|
-
fillRect(0, my, self.width, self.style.frozenMarkerWidth);
|
|
1605
|
-
strokeRect(0, my, self.width, self.style.frozenMarkerWidth);
|
|
1606
|
-
self.visibleCells.unshift({
|
|
1607
|
-
x: 0,
|
|
1608
|
-
y: my,
|
|
1609
|
-
height:
|
|
1610
|
-
self.style.frozenMarkerWidth + self.style.frozenMarkerBorderWidth,
|
|
1611
|
-
width: self.width,
|
|
1612
|
-
style: 'frozen-row-marker',
|
|
1613
|
-
});
|
|
1614
|
-
}
|
|
1615
|
-
if (self.freezeMarkerPosition) {
|
|
1616
|
-
self.ctx.fillStyle = self.style.frozenMarkerActiveColor;
|
|
1617
|
-
self.ctx.strokeStyle = self.style.frozenMarkerActiveBorderColor;
|
|
1618
|
-
if (self.dragMode === 'frozen-column-marker') {
|
|
2724
|
+
if (
|
|
2725
|
+
!self.freezeMarkerPosition ||
|
|
2726
|
+
(self.freezeMarkerPosition && self.dragMode === 'frozen-row-marker')
|
|
2727
|
+
) {
|
|
2728
|
+
if (mx > self.style.rowHeaderCellWidth) {
|
|
2729
|
+
self.ctx.fillStyle = self.style.frozenMarkerColor;
|
|
2730
|
+
self.ctx.strokeStyle = self.style.frozenMarkerBorderColor;
|
|
2731
|
+
fillRect(mx, 0, self.style.frozenMarkerWidth, self.height);
|
|
2732
|
+
strokeRect(mx, 0, self.style.frozenMarkerWidth, self.height);
|
|
2733
|
+
}
|
|
2734
|
+
self.ctx.fillStyle = yHover
|
|
2735
|
+
? self.style.frozenMarkerHoverColor
|
|
2736
|
+
: self.style.frozenMarkerHeaderColor;
|
|
2737
|
+
self.ctx.strokeStyle = yHover
|
|
2738
|
+
? self.style.frozenMarkerHoverBorderColor
|
|
2739
|
+
: self.style.frozenMarkerHeaderColor;
|
|
1619
2740
|
fillRect(
|
|
1620
|
-
|
|
2741
|
+
mx,
|
|
1621
2742
|
0,
|
|
1622
2743
|
self.style.frozenMarkerWidth,
|
|
1623
|
-
self.
|
|
2744
|
+
self.style.columnHeaderCellHeight,
|
|
1624
2745
|
);
|
|
1625
2746
|
strokeRect(
|
|
1626
|
-
|
|
2747
|
+
mx,
|
|
1627
2748
|
0,
|
|
1628
2749
|
self.style.frozenMarkerWidth,
|
|
1629
|
-
self.
|
|
2750
|
+
self.style.columnHeaderCellHeight,
|
|
1630
2751
|
);
|
|
1631
|
-
}
|
|
2752
|
+
}
|
|
2753
|
+
|
|
2754
|
+
if (
|
|
2755
|
+
!self.dragStartObject ||
|
|
2756
|
+
(self.dragStartObject &&
|
|
2757
|
+
self.dragStartObject.style !== 'rowHeaderCell')
|
|
2758
|
+
) {
|
|
2759
|
+
self.visibleCells.unshift({
|
|
2760
|
+
x: mx,
|
|
2761
|
+
y: 0,
|
|
2762
|
+
height: self.height,
|
|
2763
|
+
width: self.style.frozenMarkerWidth, // + self.style.frozenMarkerBorderWidth,
|
|
2764
|
+
style: 'frozen-column-marker',
|
|
2765
|
+
});
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
if (self.attributes.allowFreezingRows) {
|
|
2769
|
+
if (
|
|
2770
|
+
!self.freezeMarkerPosition ||
|
|
2771
|
+
(self.freezeMarkerPosition &&
|
|
2772
|
+
self.dragMode === 'frozen-column-marker')
|
|
2773
|
+
) {
|
|
2774
|
+
if (my > rowHeaderCellWidth) {
|
|
2775
|
+
self.ctx.fillStyle = self.style.frozenMarkerColor;
|
|
2776
|
+
self.ctx.strokeStyle = self.style.frozenMarkerBorderColor;
|
|
2777
|
+
fillRect(0, my, self.width, self.style.frozenMarkerWidth);
|
|
2778
|
+
strokeRect(0, my, self.width, self.style.frozenMarkerWidth);
|
|
2779
|
+
}
|
|
2780
|
+
self.ctx.fillStyle = xHover
|
|
2781
|
+
? self.style.frozenMarkerHoverColor
|
|
2782
|
+
: self.style.frozenMarkerHeaderColor;
|
|
2783
|
+
self.ctx.strokeStyle = xHover
|
|
2784
|
+
? self.style.frozenMarkerHoverBorderColor
|
|
2785
|
+
: self.style.frozenMarkerHeaderColor;
|
|
2786
|
+
fillRect(0, my, rowHeaderCellWidth, self.style.frozenMarkerWidth);
|
|
2787
|
+
strokeRect(0, my, rowHeaderCellWidth, self.style.frozenMarkerWidth);
|
|
2788
|
+
}
|
|
2789
|
+
var height =
|
|
2790
|
+
self.style.frozenMarkerWidth + self.style.frozenMarkerBorderWidth;
|
|
2791
|
+
if (
|
|
2792
|
+
!self.dragStartObject ||
|
|
2793
|
+
(self.dragStartObject &&
|
|
2794
|
+
self.dragStartObject.style !== 'columnHeaderCell')
|
|
2795
|
+
) {
|
|
2796
|
+
self.visibleCells.unshift({
|
|
2797
|
+
x: 0,
|
|
2798
|
+
y: my,
|
|
2799
|
+
height: height,
|
|
2800
|
+
width: self.width,
|
|
2801
|
+
style: 'frozen-row-marker',
|
|
2802
|
+
});
|
|
2803
|
+
}
|
|
2804
|
+
rowGroupsFrozenInfo = { y: my, h: height };
|
|
2805
|
+
}
|
|
2806
|
+
if (self.freezeMarkerPosition) {
|
|
2807
|
+
self.ctx.fillStyle = self.style.frozenMarkerActiveColor;
|
|
2808
|
+
self.ctx.strokeStyle = self.style.frozenMarkerActiveBorderColor;
|
|
2809
|
+
if (self.dragMode === 'frozen-column-marker') {
|
|
2810
|
+
let posX = self.freezeMarkerPosition.x;
|
|
2811
|
+
let nearCell = self.getCellAt(posX, 0);
|
|
2812
|
+
if (self.freezeMarkerPosition.isGrab) posX = mx;
|
|
2813
|
+
if (posX > rowHeaderCellWidth) {
|
|
2814
|
+
let x =
|
|
2815
|
+
nearCell.x -
|
|
2816
|
+
self.style.frozenMarkerWidth -
|
|
2817
|
+
self.style.frozenMarkerBorderWidth;
|
|
2818
|
+
if (posX > x + nearCell.width / 2) x = x + nearCell.width;
|
|
2819
|
+
self.ctx.fillStyle = self.style.frozenMarkerColor;
|
|
2820
|
+
self.ctx.strokeStyle = self.style.frozenMarkerBorderColor;
|
|
2821
|
+
fillRect(x, 0, self.style.frozenMarkerWidth, self.height);
|
|
2822
|
+
strokeRect(x, 0, self.style.frozenMarkerWidth, self.height);
|
|
2823
|
+
self.ctx.fillStyle = self.style.frozenMarkerHeaderColor;
|
|
2824
|
+
self.ctx.strokeStyle = self.style.frozenMarkerHeaderColor;
|
|
2825
|
+
fillRect(
|
|
2826
|
+
x,
|
|
2827
|
+
0,
|
|
2828
|
+
self.style.frozenMarkerWidth,
|
|
2829
|
+
self.style.columnHeaderCellHeight,
|
|
2830
|
+
);
|
|
2831
|
+
strokeRect(
|
|
2832
|
+
x,
|
|
2833
|
+
0,
|
|
2834
|
+
self.style.frozenMarkerWidth,
|
|
2835
|
+
self.style.columnHeaderCellHeight,
|
|
2836
|
+
);
|
|
2837
|
+
}
|
|
2838
|
+
self.ctx.fillStyle = self.style.frozenMarkerActiveHeaderColor;
|
|
2839
|
+
self.ctx.strokeStyle = self.style.frozenMarkerActiveBorderColor;
|
|
1632
2840
|
fillRect(
|
|
2841
|
+
posX,
|
|
1633
2842
|
0,
|
|
1634
|
-
self.freezeMarkerPosition.y,
|
|
1635
|
-
self.width,
|
|
1636
2843
|
self.style.frozenMarkerWidth,
|
|
2844
|
+
self.style.columnHeaderCellHeight,
|
|
1637
2845
|
);
|
|
1638
2846
|
strokeRect(
|
|
2847
|
+
posX,
|
|
1639
2848
|
0,
|
|
1640
|
-
self.freezeMarkerPosition.y,
|
|
1641
|
-
self.width,
|
|
1642
2849
|
self.style.frozenMarkerWidth,
|
|
2850
|
+
self.style.columnHeaderCellHeight,
|
|
1643
2851
|
);
|
|
2852
|
+
self.ctx.fillStyle = self.style.frozenMarkerActiveColor;
|
|
2853
|
+
fillRect(posX, 0, self.style.frozenMarkerWidth, self.height);
|
|
2854
|
+
strokeRect(posX, 0, self.style.frozenMarkerWidth, self.height);
|
|
2855
|
+
} else {
|
|
2856
|
+
let posY = self.freezeMarkerPosition.y;
|
|
2857
|
+
let nearCell = self.getCellAt(0, posY);
|
|
2858
|
+
if (self.freezeMarkerPosition.isGrab) posY = my;
|
|
2859
|
+
if (posY > self.style.columnHeaderCellHeight) {
|
|
2860
|
+
let y =
|
|
2861
|
+
nearCell.y -
|
|
2862
|
+
self.style.frozenMarkerWidth -
|
|
2863
|
+
self.style.frozenMarkerBorderWidth;
|
|
2864
|
+
if (posY > y + nearCell.height / 2) y = y + nearCell.height;
|
|
2865
|
+
self.ctx.fillStyle = self.style.frozenMarkerColor;
|
|
2866
|
+
self.ctx.strokeStyle = self.style.frozenMarkerBorderColor;
|
|
2867
|
+
fillRect(0, y, self.width, self.style.frozenMarkerWidth);
|
|
2868
|
+
strokeRect(0, y, self.width, self.style.frozenMarkerWidth);
|
|
2869
|
+
self.ctx.fillStyle = self.style.frozenMarkerHeaderColor;
|
|
2870
|
+
self.ctx.strokeStyle = self.style.frozenMarkerHeaderColor;
|
|
2871
|
+
fillRect(0, y, rowHeaderCellWidth, self.style.frozenMarkerWidth);
|
|
2872
|
+
strokeRect(0, y, rowHeaderCellWidth, self.style.frozenMarkerWidth);
|
|
2873
|
+
}
|
|
2874
|
+
self.ctx.fillStyle = self.style.frozenMarkerActiveHeaderColor;
|
|
2875
|
+
self.ctx.strokeStyle = self.style.frozenMarkerActiveBorderColor;
|
|
2876
|
+
fillRect(0, posY, rowHeaderCellWidth, self.style.frozenMarkerWidth);
|
|
2877
|
+
strokeRect(0, posY, rowHeaderCellWidth, self.style.frozenMarkerWidth);
|
|
2878
|
+
self.ctx.fillStyle = self.style.frozenMarkerActiveColor;
|
|
2879
|
+
fillRect(0, posY, self.width, self.style.frozenMarkerWidth);
|
|
2880
|
+
strokeRect(0, posY, self.width, self.style.frozenMarkerWidth);
|
|
1644
2881
|
}
|
|
1645
2882
|
}
|
|
1646
2883
|
}
|
|
@@ -1849,6 +3086,7 @@ export default function (self) {
|
|
|
1849
3086
|
self.ctx.save();
|
|
1850
3087
|
initDraw();
|
|
1851
3088
|
drawBackground();
|
|
3089
|
+
initGroupArea();
|
|
1852
3090
|
drawFrozenRows();
|
|
1853
3091
|
drawRows();
|
|
1854
3092
|
drawActiveCell();
|
|
@@ -1857,12 +3095,14 @@ export default function (self) {
|
|
|
1857
3095
|
drawSelectionHandles();
|
|
1858
3096
|
drawReorderMarkers();
|
|
1859
3097
|
drawMoveMarkers();
|
|
3098
|
+
drawResizeMarkers();
|
|
1860
3099
|
drawBorder();
|
|
1861
3100
|
drawSelectionBorders();
|
|
1862
3101
|
drawScrollBars();
|
|
1863
3102
|
if (checkScrollHeight) {
|
|
1864
3103
|
self.resize(true);
|
|
1865
3104
|
}
|
|
3105
|
+
drawGroupArea();
|
|
1866
3106
|
drawDebug();
|
|
1867
3107
|
drawPerfLines();
|
|
1868
3108
|
if (self.dispatchEvent('afterdraw', {})) {
|