@@ -20765,6 +20765,7 @@ var DataGrid = (function (_super) {
20765
20765
_this._inPaint = false;
20766
20766
_this._paintPending = false; // TODO: would like to get rid of this flag
20767
20767
_this._pressData = null;
20768
+ _this._dpiRatio = Math.ceil(window.devicePixelRatio);
20768
20769
_this._scrollX = 0;
20769
20770
_this._scrollY = 0;
20770
20771
_this._viewportWidth = 0;
@@ -21510,7 +21511,7 @@ var DataGrid = (function (_super) {
21510
21511
var y_1 = dy < 0 ? contentY : contentY + dy;
21511
21512
var w = width;
21512
21513
var h = contentHeight - Math.abs(dy);
21513
- this._canvasGC.drawImage (this._canvas, x_1, y_1, w, h, x_1, y_1 - dy, w, h );
21514
+ this._blit (this._canvas, x_1, y_1, w, h, x_1, y_1 - dy);
21514
21515
this._paint(0, dy < 0 ? contentY : height - dy, width, Math.abs(dy));
21515
21516
}
21516
21517
}
@@ -21528,7 +21529,7 @@ var DataGrid = (function (_super) {
21528
21529
var y_2 = 0;
21529
21530
var w = contentWidth - Math.abs(dx);
21530
21531
var h = height;
21531
- this._canvasGC.drawImage (this._canvas, x_2, y_2, w, h, x_2 - dx, y_2, w, h );
21532
+ this._blit (this._canvas, x_2, y_2, w, h, x_2 - dx, y_2);
21532
21533
this._paint(dx < 0 ? contentX : width - dx, 0, Math.abs(dx), height);
21533
21534
}
21534
21535
}
@@ -21635,12 +21636,16 @@ var DataGrid = (function (_super) {
21635
21636
event.preventDefault();
21636
21637
event.stopPropagation();
21637
21638
break;
21639
+ case 'resize':
21640
+ this._refreshDPI();
21641
+ break;
21638
21642
}
21639
21643
};
21640
21644
/**
21641
21645
* A message handler invoked on a `'before-attach'` message.
21642
21646
*/
21643
21647
DataGrid.prototype.onBeforeAttach = function (msg) {
21648
+ window.addEventListener('resize', this);
21644
21649
this.node.addEventListener('wheel', this);
21645
21650
this.node.addEventListener('mousedown', this);
21646
21651
this._viewport.node.addEventListener('mousemove', this);
@@ -21650,6 +21655,7 @@ var DataGrid = (function (_super) {
21650
21655
* A message handler invoked on an `'after-detach'` message.
21651
21656
*/
21652
21657
DataGrid.prototype.onAfterDetach = function (msg) {
21658
+ window.removeEventListener('resize', this);
21653
21659
this.node.removeEventListener('wheel', this);
21654
21660
this.node.removeEventListener('mousedown', this);
21655
21661
this._viewport.node.removeEventListener('mousemove', this);
@@ -21667,47 +21673,93 @@ var DataGrid = (function (_super) {
21667
21673
DataGrid.prototype.onResize = function (msg) {
21668
21674
this._syncScrollState();
21669
21675
};
21676
+ /**
21677
+ * Refresh the internal dpi ratio.
21678
+ *
21679
+ * This will update the canvas size and schedule a repaint if needed.
21680
+ */
21681
+ DataGrid.prototype._refreshDPI = function () {
21682
+ // Get the best integral value for the dpi ratio.
21683
+ var dpiRatio = Math.ceil(window.devicePixelRatio);
21684
+ // Bail early if the computed dpi ratio has not changed.
21685
+ if (this._dpiRatio === dpiRatio) {
21686
+ return;
21687
+ }
21688
+ // Update the internal dpi ratio.
21689
+ this._dpiRatio = dpiRatio;
21690
+ // Schedule a full repaint of the grid.
21691
+ this.repaint();
21692
+ // Update the canvas size for the new dpi ratio.
21693
+ this._resizeCanvasIfNeeded(this._viewportWidth, this._viewportHeight);
21694
+ // Ensure the canvas style is scaled for the new ratio.
21695
+ this._canvas.style.width = this._canvas.width / this._dpiRatio + "px";
21696
+ this._canvas.style.height = this._canvas.height / this._dpiRatio + "px";
21697
+ };
21670
21698
/**
21671
21699
* Ensure the canvas is at least the specified size.
21672
21700
*
21673
21701
* This method will retain the valid canvas content.
21674
21702
*/
21675
- DataGrid.prototype._expandCanvasIfNeeded = function (width, height) {
21676
- // Bail if the canvas is larger than the specified size.
21677
- if (this._canvas.width > width && this._canvas.height > height) {
21703
+ DataGrid.prototype._resizeCanvasIfNeeded = function (width, height) {
21704
+ // Scale the size by the dpi ratio.
21705
+ width = width * this._dpiRatio;
21706
+ height = height * this._dpiRatio;
21707
+ // Compute the maximum canvas size for the given width.
21708
+ var maxW = (Math.ceil((width + 1) / 512) + 1) * 512;
21709
+ var maxH = (Math.ceil((height + 1) / 512) + 1) * 512;
21710
+ // Get the current size of the canvas.
21711
+ var curW = this._canvas.width;
21712
+ var curH = this._canvas.height;
21713
+ // Bail early if the canvas size is within bounds.
21714
+ if (curW >= width && curH >= height && curW <= maxW && curH <= maxH) {
21678
21715
return;
21679
21716
}
21680
21717
// Compute the expanded canvas size.
21681
- var exWidth = Math.ceil((width + 1) / 512) * 512;
21682
- var exHeight = Math.ceil((height + 1) / 512) * 512;
21683
- // Expand the buffer width if needed.
21684
- if (this._buffer.width < width) {
21685
- this._buffer.width = exWidth;
21686
- }
21687
- // Expand the buffer height if needed.
21688
- if (this._buffer.height < height) {
21689
- this._buffer.height = exHeight;
21690
- }
21691
- // Test whether there is valid content to blit.
21692
- var needBlit = this._canvas.width > 0 && this._canvas.height > 0;
21718
+ var expW = maxW - 512;
21719
+ var expH = maxH - 512;
21720
+ // Set the transforms to the identity matrix.
21721
+ this._canvasGC.setTransform(1, 0, 0, 1, 0, 0);
21722
+ this._bufferGC.setTransform(1, 0, 0, 1, 0, 0);
21723
+ // Resize the buffer width if needed.
21724
+ if (curW < width) {
21725
+ this._buffer.width = expW;
21726
+ }
21727
+ else if (curW > maxW) {
21728
+ this._buffer.width = maxW;
21729
+ }
21730
+ // Resize the buffer height if needed.
21731
+ if (curH < height) {
21732
+ this._buffer.height = expH;
21733
+ }
21734
+ else if (curH > maxH) {
21735
+ this._buffer.height = maxH;
21736
+ }
21737
+ // Test whether there is content to blit.
21738
+ var needBlit = curH > 0 && curH > 0 && width > 0 && height > 0;
21693
21739
// Copy the valid content into the buffer if needed.
21694
21740
if (needBlit) {
21695
- this._bufferGC.clearRect(0, 0, width, height);
21696
21741
this._bufferGC.drawImage(this._canvas, 0, 0);
21697
21742
}
21698
- // Expand the canvas width if needed.
21699
- if (this._canvas.width < width) {
21700
- this._canvas.width = exWidth;
21701
- this._canvas.style.width = exWidth + "px";
21743
+ // Resize the canvas width if needed.
21744
+ if (curW < width) {
21745
+ this._canvas.width = expW;
21746
+ this._canvas.style.width = expW / this._dpiRatio + "px";
21747
+ }
21748
+ else if (curW > maxW) {
21749
+ this._canvas.width = maxW;
21750
+ this._canvas.style.width = maxW / this._dpiRatio + "px";
21702
21751
}
21703
- // Expand the canvas height of needed.
21704
- if (this._canvas.height < height) {
21705
- this._canvas.height = exHeight;
21706
- this._canvas.style.height = exHeight + "px";
21752
+ // Resize the canvas height if needed.
21753
+ if (curH < height) {
21754
+ this._canvas.height = expH;
21755
+ this._canvas.style.height = expH / this._dpiRatio + "px";
21756
+ }
21757
+ else if (curH > maxH) {
21758
+ this._canvas.height = maxH;
21759
+ this._canvas.style.height = maxH / this._dpiRatio + "px";
21707
21760
}
21708
21761
// Copy the valid content from the buffer if needed.
21709
21762
if (needBlit) {
21710
- this._canvasGC.clearRect(0, 0, width, height);
21711
21763
this._canvasGC.drawImage(this._buffer, 0, 0);
21712
21764
}
21713
21765
};
@@ -21892,7 +21944,7 @@ var DataGrid = (function (_super) {
21892
21944
dy = sy + delta;
21893
21945
}
21894
21946
// Blit the valid content to the destination.
21895
- this._canvasGC.drawImage (this._canvas, sx, sy, sw, sh, dx, dy, sw, sh );
21947
+ this._blit (this._canvas, sx, sy, sw, sh, dx, dy);
21896
21948
// Repaint the section if needed.
21897
21949
if (newSize > 0 && offset + newSize > hh) {
21898
21950
this._paint(0, pos, vpWidth, offset + newSize - pos);
@@ -21945,7 +21997,7 @@ var DataGrid = (function (_super) {
21945
21997
dx = sx + delta;
21946
21998
}
21947
21999
// Blit the valid content to the destination.
21948
- this._canvasGC.drawImage (this._canvas, sx, sy, sw, sh, dx, dy, sw, sh );
22000
+ this._blit (this._canvas, sx, sy, sw, sh, dx, dy);
21949
22001
// Repaint the section if needed.
21950
22002
if (newSize > 0 && offset + newSize > hw) {
21951
22003
this._paint(pos, 0, offset + newSize - pos, vpHeight);
@@ -21978,7 +22030,7 @@ var DataGrid = (function (_super) {
21978
22030
var dx = sx + delta;
21979
22031
var dy = 0;
21980
22032
// Blit the valid contents to the destination.
21981
- this._canvasGC.drawImage (this._canvas, sx, sy, sw, sh, dx, dy, sw, sh );
22033
+ this._blit (this._canvas, sx, sy, sw, sh, dx, dy);
21982
22034
// Repaint the header section if needed.
21983
22035
if (newSize > 0) {
21984
22036
this._paint(offset, 0, newSize, vpHeight);
@@ -22011,7 +22063,7 @@ var DataGrid = (function (_super) {
22011
22063
var dx = 0;
22012
22064
var dy = sy + delta;
22013
22065
// Blit the valid contents to the destination.
22014
- this._canvasGC.drawImage (this._canvas, sx, sy, sw, sh, dx, dy, sw, sh );
22066
+ this._blit (this._canvas, sx, sy, sw, sh, dx, dy);
22015
22067
// Repaint the header section if needed.
22016
22068
if (newSize > 0) {
22017
22069
this._paint(0, offset, vpWidth, newSize);
@@ -22184,6 +22236,10 @@ var DataGrid = (function (_super) {
22184
22236
if (this._pressData) {
22185
22237
return;
22186
22238
}
22239
+ // Do nothing if the `Ctrl` key is held.
22240
+ if (event.ctrlKey) {
22241
+ return;
22242
+ }
22187
22243
// Extract the delta X and Y movement.
22188
22244
var dx = event.deltaX;
22189
22245
var dy = event.deltaY;
@@ -22342,8 +22398,8 @@ var DataGrid = (function (_super) {
22342
22398
// Updated internal viewport size.
22343
22399
this._viewportWidth = width;
22344
22400
this._viewportHeight = height;
22345
- // Expand the canvas if needed.
22346
- this._expandCanvasIfNeeded (width, height);
22401
+ // Resize the canvas if needed.
22402
+ this._resizeCanvasIfNeeded (width, height);
22347
22403
// Compute the sizes of the dirty regions.
22348
22404
var right = width - oldWidth;
22349
22405
var bottom = height - oldHeight;
@@ -22848,6 +22904,30 @@ var DataGrid = (function (_super) {
22848
22904
DataGrid.prototype._onRenderersChanged = function () {
22849
22905
this.repaint();
22850
22906
};
22907
+ /**
22908
+ * Blit content into the on-screen canvas.
22909
+ *
22910
+ * The rect should be expressed in viewport coordinates.
22911
+ *
22912
+ * This automatically accounts for the dpi ratio.
22913
+ */
22914
+ DataGrid.prototype._blit = function (source, x, y, w, h, dx, dy) {
22915
+ // Scale the blit coordinates by the dpi ratio.
22916
+ x *= this._dpiRatio;
22917
+ y *= this._dpiRatio;
22918
+ w *= this._dpiRatio;
22919
+ h *= this._dpiRatio;
22920
+ dx *= this._dpiRatio;
22921
+ dy *= this._dpiRatio;
22922
+ // Save the current gc state.
22923
+ this._canvasGC.save();
22924
+ // Set the transform to the identity matrix.
22925
+ this._canvasGC.setTransform(1, 0, 0, 1, 0, 0);
22926
+ // Draw the specified content.
22927
+ this._canvasGC.drawImage(source, x, y, w, h, dx, dy, w, h);
22928
+ // Restore the gc state.
22929
+ this._canvasGC.restore();
22930
+ };
22851
22931
/**
22852
22932
* Paint the grid content for the given dirty rect.
22853
22933
*
@@ -22878,6 +22958,9 @@ var DataGrid = (function (_super) {
22878
22958
* This method dispatches to the relevant `_draw*` methods.
22879
22959
*/
22880
22960
DataGrid.prototype._draw = function (rx, ry, rw, rh) {
22961
+ // Scale the canvas and buffer GC for the dpi ratio.
22962
+ this._canvasGC.setTransform(this._dpiRatio, 0, 0, this._dpiRatio, 0, 0);
22963
+ this._bufferGC.setTransform(this._dpiRatio, 0, 0, this._dpiRatio, 0, 0);
22881
22964
// Clear the dirty rect of all content.
22882
22965
this._canvasGC.clearRect(rx, ry, rw, rh);
22883
22966
// Draw the void region.
@@ -23428,13 +23511,13 @@ var DataGrid = (function (_super) {
23428
23511
// Compute the actual X bounds for the column.
23429
23512
var x1 = Math.max(rgn.xMin, x);
23430
23513
var x2 = Math.min(x + width - 1, rgn.xMax);
23431
- // Copy the off-screen buffer column into the on-screen canvas.
23514
+ // Blit the off-screen buffer column into the on-screen canvas.
23432
23515
//
23433
23516
// This is *much* faster than drawing directly into the on-screen
23434
23517
// canvas with a clip rect on the column. Managed column clipping
23435
23518
// is required to prevent cell renderers from needing to set up a
23436
23519
// clip rect for handling horizontal overflow text (slow!).
23437
- this._canvasGC.drawImage (this._buffer, x1, y1, x2 - x1 + 1, y2 - y1 + 1, x1, y1, x2 - x1 + 1, y2 - y1 + 1 );
23520
+ this._blit (this._buffer, x1, y1, x2 - x1 + 1, y2 - y1 + 1, x1, y1);
23438
23521
// Increment the running X coordinate.
23439
23522
x += width;
23440
23523
}
0 commit comments