@deephaven/grid 0.104.1-virtual-webgl.11 → 0.105.1-beta.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.
@@ -68,7 +68,9 @@ export class GridMetricCalculator {
68
68
  /** User set row heights */
69
69
  /** Calculated column widths based on cell contents */
70
70
  /** Calculated row heights based on cell contents */
71
- /** Cache of fonts to estimated width of one char */
71
+ /** Cache of fonts to estimated width of the smallest char */
72
+ /** Cache of fonts to estimated width of the largest char */
73
+ /** Cache of fonts to width of all chars */
72
74
  /** Map from visible index to model index for rows (e.g. reversing movedRows operations) */
73
75
  /** Map from visible index to model index for columns (e.g. reversing movedColumns operations) */
74
76
  /** List of moved row operations. Need to track the previous value so we know if modelRows needs to be cleared. */
@@ -79,7 +81,9 @@ export class GridMetricCalculator {
79
81
  userRowHeights = new Map(),
80
82
  calculatedColumnWidths = new Map(),
81
83
  calculatedRowHeights = new Map(),
82
- fontWidths = new Map(),
84
+ fontWidthsLower = new Map(),
85
+ fontWidthsUpper = new Map(),
86
+ allCharWidths = new Map(),
83
87
  modelRows = new Map(),
84
88
  modelColumns = new Map(),
85
89
  movedRows = [],
@@ -93,7 +97,9 @@ export class GridMetricCalculator {
93
97
  _defineProperty(this, "userRowHeights", void 0);
94
98
  _defineProperty(this, "calculatedColumnWidths", void 0);
95
99
  _defineProperty(this, "calculatedRowHeights", void 0);
96
- _defineProperty(this, "fontWidths", void 0);
100
+ _defineProperty(this, "fontWidthsLower", void 0);
101
+ _defineProperty(this, "fontWidthsUpper", void 0);
102
+ _defineProperty(this, "allCharWidths", void 0);
97
103
  _defineProperty(this, "modelRows", void 0);
98
104
  _defineProperty(this, "modelColumns", void 0);
99
105
  _defineProperty(this, "movedRows", void 0);
@@ -102,7 +108,9 @@ export class GridMetricCalculator {
102
108
  this.userRowHeights = userRowHeights;
103
109
  this.calculatedRowHeights = calculatedRowHeights;
104
110
  this.calculatedColumnWidths = calculatedColumnWidths;
105
- this.fontWidths = fontWidths;
111
+ this.allCharWidths = allCharWidths;
112
+ this.fontWidthsLower = fontWidthsLower;
113
+ this.fontWidthsUpper = fontWidthsUpper;
106
114
 
107
115
  // Need to track the last moved rows/columns array so we know if we need to reset our models cache
108
116
  this.modelRows = modelRows;
@@ -266,7 +274,8 @@ export class GridMetricCalculator {
266
274
  var bottomVisible = lastTop > 0 ? this.getBottomVisible(state, allRowYs, allRowHeights, visibleRows, gridY) : bottom;
267
275
  var rightVisible = lastLeft > 0 ? this.getRightVisible(state, allColumnXs, allColumnWidths, visibleColumns, gridX) : right;
268
276
  var {
269
- fontWidths,
277
+ fontWidthsLower,
278
+ fontWidthsUpper,
270
279
  userColumnWidths,
271
280
  userRowHeights,
272
281
  calculatedRowHeights,
@@ -371,7 +380,8 @@ export class GridMetricCalculator {
371
380
  movedRows,
372
381
  movedColumns,
373
382
  // Map of the width of the fonts
374
- fontWidths,
383
+ fontWidthsLower,
384
+ fontWidthsUpper,
375
385
  // Map of user set column/row width/height
376
386
  userColumnWidths,
377
387
  userRowHeights,
@@ -1292,8 +1302,8 @@ export class GridMetricCalculator {
1292
1302
  } = theme;
1293
1303
  return _columnWidth;
1294
1304
  }
1295
- var headerWidth = this.calculateColumnHeaderWidth(modelColumn, state);
1296
- var dataWidth = this.calculateColumnDataWidth(modelColumn, state);
1305
+ var headerWidth = this.calculateColumnHeaderWidth(modelColumn, state, maxColumnWidth);
1306
+ var dataWidth = this.calculateColumnDataWidth(modelColumn, state, maxColumnWidth);
1297
1307
  var cachedValue = this.calculatedColumnWidths.get(modelColumn);
1298
1308
  var columnWidth = Math.ceil(Math.max(headerWidth, dataWidth));
1299
1309
  columnWidth = Math.max(minColumnWidth, columnWidth);
@@ -1316,21 +1326,24 @@ export class GridMetricCalculator {
1316
1326
  * @param state The grid metric state
1317
1327
  * @returns The calculated width of the column header
1318
1328
  */
1319
- calculateColumnHeaderWidth(modelColumn, state) {
1329
+ calculateColumnHeaderWidth(modelColumn, state, maxColumnWidth) {
1320
1330
  var {
1321
1331
  model,
1322
- theme
1332
+ theme,
1333
+ context
1323
1334
  } = state;
1324
1335
  var {
1325
- headerFont,
1326
- headerHorizontalPadding
1336
+ headerHorizontalPadding,
1337
+ headerFont
1327
1338
  } = theme;
1339
+ this.calculateLowerFontWidth(headerFont, context);
1340
+ this.calculateUpperFontWidth(headerFont, context);
1341
+ var totalPadding = headerHorizontalPadding * 2;
1328
1342
  var headerText = model.textForColumnHeader(modelColumn, 0);
1329
1343
  if (headerText !== undefined && headerText !== '') {
1330
- var headerFontWidth = this.getWidthForFont(headerFont, state);
1331
- return headerText.length * headerFontWidth + headerHorizontalPadding * 2;
1344
+ return this.getTextWidth(context, headerFont, headerText, maxColumnWidth - totalPadding) + totalPadding;
1332
1345
  }
1333
- return headerHorizontalPadding * 2;
1346
+ return totalPadding;
1334
1347
  }
1335
1348
 
1336
1349
  /**
@@ -1339,13 +1352,14 @@ export class GridMetricCalculator {
1339
1352
  * @param state The grid metric state
1340
1353
  * @returns The calculated width of the column data
1341
1354
  */
1342
- calculateColumnDataWidth(modelColumn, state) {
1355
+ calculateColumnDataWidth(modelColumn, state, maxColumnWidth) {
1343
1356
  var {
1344
1357
  top,
1345
1358
  height,
1346
1359
  width,
1347
1360
  model,
1348
- theme
1361
+ theme,
1362
+ context
1349
1363
  } = state;
1350
1364
  var {
1351
1365
  floatingTopRowCount,
@@ -1361,27 +1375,52 @@ export class GridMetricCalculator {
1361
1375
  scrollBarSize,
1362
1376
  dataBarHorizontalPadding
1363
1377
  } = theme;
1378
+ this.calculateLowerFontWidth(font, context);
1379
+ this.calculateUpperFontWidth(font, context);
1364
1380
  var columnWidth = 0;
1365
- var fontWidth = this.getWidthForFont(font, state);
1366
1381
  var rowsPerPage = height / rowHeight;
1367
1382
  var bottom = Math.ceil(top + rowsPerPage);
1383
+ var cellPadding = cellHorizontalPadding * 2;
1368
1384
  GridUtils.iterateAllItems(top, bottom, floatingTopRowCount, floatingBottomRowCount, rowCount, row => {
1369
1385
  var modelRow = this.getModelRow(row, state);
1370
1386
  var text = model.textForCell(modelColumn, modelRow);
1371
1387
  var cellRenderType = model.renderTypeForCell(modelColumn, modelRow);
1372
1388
  var cellWidth = 0;
1373
1389
  if (text) {
1374
- var cellPadding = cellHorizontalPadding * 2;
1375
- cellWidth = text.length * fontWidth + cellPadding;
1390
+ cellWidth = this.getTextWidth(context, font, text, maxColumnWidth - cellPadding) + cellPadding;
1376
1391
  }
1377
1392
  if (cellRenderType === 'dataBar') {
1378
1393
  cellWidth += dataBarHorizontalPadding;
1379
1394
  }
1380
1395
  columnWidth = Math.max(columnWidth, cellWidth);
1381
1396
  });
1382
- columnWidth = Math.max(Math.min(columnWidth, (width - rowHeaderWidth - scrollBarSize - rowFooterWidth) * GridMetricCalculator.MAX_COLUMN_WIDTH), cellHorizontalPadding * 2);
1397
+ columnWidth = Math.max(Math.min(columnWidth, (width - rowHeaderWidth - scrollBarSize - rowFooterWidth) * GridMetricCalculator.MAX_COLUMN_WIDTH), cellPadding);
1383
1398
  return columnWidth;
1384
1399
  }
1400
+ getTextWidth(context, font, text, maxWidth) {
1401
+ if (!this.allCharWidths.has(font)) {
1402
+ this.allCharWidths.set(font, new Map());
1403
+ }
1404
+ var charWidths = getOrThrow(this.allCharWidths, font);
1405
+ var width = 0;
1406
+ for (var i = 0; i < text.length; i += 1) {
1407
+ var char = text[i];
1408
+ if (charWidths.has(char)) {
1409
+ width += getOrThrow(charWidths, char);
1410
+ } else {
1411
+ var textMetrics = context.measureText(char);
1412
+ var {
1413
+ width: charWidth
1414
+ } = textMetrics;
1415
+ charWidths.set(char, charWidth);
1416
+ width += charWidth;
1417
+ }
1418
+ if (maxWidth !== undefined && width > maxWidth) {
1419
+ return maxWidth;
1420
+ }
1421
+ }
1422
+ return width;
1423
+ }
1385
1424
 
1386
1425
  /**
1387
1426
  * The coordinate for where the tree padding should be drawn
@@ -1414,30 +1453,47 @@ export class GridMetricCalculator {
1414
1453
  }
1415
1454
 
1416
1455
  /**
1417
- * Get the width of the provided font. Exploits the fact that we're
1418
- * using tabular figures so every character is same width
1456
+ * Calculates the lower bound width of a character of the provided font.
1419
1457
  * @param font The font to get the width for
1420
1458
  * @param state The grid metric state
1421
- * @returns Width of the char `8` for the specified font
1422
1459
  */
1423
- getWidthForFont(font, state) {
1424
- if (this.fontWidths.has(font)) {
1425
- return getOrThrow(this.fontWidths, font);
1460
+ calculateLowerFontWidth(font, context) {
1461
+ if (this.fontWidthsLower.has(font)) {
1462
+ return;
1426
1463
  }
1464
+ context.font = font;
1465
+ // Assume char `.` is the smallest character
1466
+ var textMetrics = context.measureText('.');
1427
1467
  var {
1428
- context
1429
- } = state;
1468
+ width
1469
+ } = textMetrics;
1470
+
1471
+ // context.font changes the string a little bit, e.g. '10px Arial, sans serif' => '10px Arial, "sans serif"'
1472
+ // Rather than require checking with the correct font def (theme, or context font), just key it to both
1473
+ this.fontWidthsLower.set(font, width);
1474
+ this.fontWidthsLower.set(context.font, width);
1475
+ }
1476
+
1477
+ /**
1478
+ * Calculates the upper bound width of a character of the provided font.
1479
+ * @param font The font to get the width for
1480
+ * @param state The grid metric state
1481
+ */
1482
+ calculateUpperFontWidth(font, context) {
1483
+ if (this.fontWidthsUpper.has(font)) {
1484
+ return;
1485
+ }
1430
1486
  context.font = font;
1431
- var textMetrics = context.measureText('8');
1487
+ // Assume char `m` is the largest character
1488
+ var textMetrics = context.measureText('m');
1432
1489
  var {
1433
1490
  width
1434
1491
  } = textMetrics;
1435
1492
 
1436
1493
  // context.font changes the string a little bit, e.g. '10px Arial, sans serif' => '10px Arial, "sans serif"'
1437
1494
  // Rather than require checking with the correct font def (theme, or context font), just key it to both
1438
- this.fontWidths.set(font, width);
1439
- this.fontWidths.set(context.font, width);
1440
- return width;
1495
+ this.fontWidthsUpper.set(font, width);
1496
+ this.fontWidthsUpper.set(context.font, width);
1441
1497
  }
1442
1498
 
1443
1499
  /**