Skip to content

Commit 95af560

Browse files
authoredNov 28, 2023
fix: try to scroll inline preview into view (#5400)
Currently, when inline preview is used at the bottom of the file, it will be invisible. This changes it to scroll down enough to get the inline preview into view. If the inline preview is bigger than the view, we scroll down so that the cursor is at the top of the screen to get the most possible into view
1 parent ee917cf commit 95af560

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed
 

‎src/autocomplete.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class Autocomplete {
9090
}.bind(this));
9191

9292
this.tooltipTimer = lang.delayedCall(this.updateDocTooltip.bind(this), 50);
93+
this.popupTimer = lang.delayedCall(this.$updatePopupPosition.bind(this), 50);
9394

9495
this.stickySelectionTimer = lang.delayedCall(function() {
9596
this.stickySelection = true;
@@ -143,6 +144,7 @@ class Autocomplete {
143144
}
144145
this.hideDocTooltip();
145146
this.stickySelectionTimer.cancel();
147+
this.popupTimer.cancel();
146148
this.stickySelection = false;
147149
}
148150

@@ -160,9 +162,14 @@ class Autocomplete {
160162
this.tooltipTimer.call(null, null);
161163
return;
162164
}
165+
166+
// Update the popup position after a short wait to account for potential scrolling
167+
this.popupTimer.schedule();
168+
this.tooltipTimer.schedule();
169+
} else {
170+
this.popupTimer.call(null, null);
171+
this.tooltipTimer.call(null, null);
163172
}
164-
this.$updatePopupPosition();
165-
this.tooltipTimer.call(null, null);
166173
}
167174

168175
$onPopupShow(hide) {

‎src/autocomplete/inline_test.js

+40
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ var completions = [
4242
value: "f should not show inline",
4343
score: 0,
4444
hideInlinePreview: true
45+
},
46+
{
47+
value: "long\nlong\nlong\nlong\nlong\nlong",
48+
score: 0
49+
},
50+
{
51+
value: "long\nlong\nlong\nlong\nlong\nlong".repeat(100),
52+
score: 0
4553
}
4654
];
4755

@@ -261,6 +269,38 @@ module.exports = {
261269

262270
done();
263271
},
272+
"test: should scroll if inline preview outside": function(done) {
273+
// Fill the editor with new lines to get the cursor to the bottom
274+
// of the container
275+
editor.execCommand("insertstring", "\n".repeat(200));
276+
277+
var deltaY;
278+
var initialScrollBy = editor.renderer.scrollBy;
279+
editor.renderer.scrollBy = function(varX, varY) {
280+
deltaY = varY;
281+
};
282+
283+
inline.show(editor, completions[6], "l");
284+
editor.renderer.$loop._flush();
285+
286+
setTimeout(() => {
287+
// Should scroll 5 lines to get the inline preview into view
288+
assert.strictEqual(deltaY, 50);
289+
290+
inline.hide();
291+
editor.renderer.$loop._flush();
292+
293+
inline.show(editor, completions[7], "l");
294+
editor.renderer.$loop._flush();
295+
296+
setTimeout(() => {
297+
// Should scroll as much as possbile while keeping the cursor on screen
298+
assert.strictEqual(deltaY, 490);
299+
editor.renderer.scrollBy = initialScrollBy;
300+
done();
301+
}, 50);
302+
}, 50);
303+
},
264304
tearDown: function() {
265305
inline.destroy();
266306
editor.destroy();

‎src/virtual_renderer.js

+19
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,25 @@ class VirtualRenderer {
16201620
className: "ace_ghost_text"
16211621
};
16221622
this.session.widgetManager.addLineWidget(this.$ghostTextWidget);
1623+
1624+
// Check wether the line widget fits in the part of the screen currently in view
1625+
var pixelPosition = this.$cursorLayer.getPixelPosition(insertPosition, true);
1626+
var el = this.container;
1627+
var height = el.getBoundingClientRect().height;
1628+
var ghostTextHeight = textLines.length * this.lineHeight;
1629+
var fitsY = ghostTextHeight < height - pixelPosition.top;
1630+
1631+
// If it fits, no action needed
1632+
if (fitsY) return;
1633+
1634+
// If it can fully fit in the screen, scroll down until it fits on the screen
1635+
// if it cannot fully fit, scroll so that the cursor is at the top of the screen
1636+
// to fit as much as possible.
1637+
if (ghostTextHeight < height) {
1638+
this.scrollBy(0, (textLines.length - 1) * this.lineHeight);
1639+
} else {
1640+
this.scrollBy(0, pixelPosition.top);
1641+
}
16231642
}
16241643

16251644
}

0 commit comments

Comments
 (0)
Please sign in to comment.