Skip to content

Commit 61849da

Browse files
authored
Fix scrolling in large cells. (#8971)
1 parent acb59d3 commit 61849da

File tree

3 files changed

+32
-18
lines changed

3 files changed

+32
-18
lines changed

news/2 Fixes/8895.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix scrolling in large cells.

src/datascience-ui/native-editor/nativeCell.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,13 @@ export class NativeCell extends React.Component<INativeCellProps> {
219219
switch (e.code) {
220220
case 'ArrowUp':
221221
case 'k':
222-
if ((isFocusedWhenNotSuggesting && e.editorInfo!.isFirstLine) || !this.isFocused()) {
222+
if ((isFocusedWhenNotSuggesting && e.editorInfo!.isFirstLine && !e.shiftKey) || !this.isFocused()) {
223223
this.arrowUpFromCell(e);
224224
}
225225
break;
226226
case 'ArrowDown':
227227
case 'j':
228-
if ((isFocusedWhenNotSuggesting && e.editorInfo!.isLastLine) || !this.isFocused()) {
228+
if ((isFocusedWhenNotSuggesting && e.editorInfo!.isLastLine && !e.shiftKey) || !this.isFocused()) {
229229
this.arrowDownFromCell(e);
230230
}
231231
break;

src/datascience-ui/react-common/monacoEditor.tsx

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ export class MonacoEditor extends React.Component<IMonacoEditorProps, IMonacoEdi
7272
private styleObserver : MutationObserver | undefined;
7373
private watchingMargin: boolean = false;
7474
private throttledUpdateWidgetPosition = throttle(this.updateWidgetPosition.bind(this), 100);
75-
private throttledScrollOntoScreen = throttle(this.scrollOntoScreen.bind(this), 100);
75+
private throttledScrollCurrentPosition = throttle(this.scrollToCurrentPosition.bind(this), 100);
7676
private monacoContainer : HTMLDivElement | undefined;
77-
private lineTops: number[] = [];
77+
private lineTops: {top: number; index: number}[] = [];
7878
private debouncedComputeLineTops = debounce(this.computeLineTops.bind(this), 100);
7979

8080
/**
@@ -192,13 +192,17 @@ export class MonacoEditor extends React.Component<IMonacoEditorProps, IMonacoEdi
192192
this.throttledUpdateWidgetPosition();
193193
this.updateWidgetParent(editor);
194194
this.hideAllOtherHoverAndParameterWidgets();
195-
this.throttledScrollOntoScreen(editor);
195+
196+
// Also update our scroll position, but do that after focus is established.
197+
// This is necessary so that markdown can switch to edit mode before we
198+
// try to scroll to it.
199+
setTimeout(() => this.throttledScrollCurrentPosition(editor), 0) ;
196200
}));
197201

198202
// Track cursor changes and make sure line is on the screen
199203
this.subscriptions.push(editor.onDidChangeCursorPosition(() => {
200204
this.throttledUpdateWidgetPosition();
201-
this.throttledScrollOntoScreen(editor);
205+
this.throttledScrollCurrentPosition(editor);
202206
}));
203207

204208
// Update our margin to include the correct line number style
@@ -311,6 +315,14 @@ export class MonacoEditor extends React.Component<IMonacoEditorProps, IMonacoEdi
311315
}
312316

313317
public getCurrentVisibleLine(): number | undefined {
318+
return this.getCurrentVisibleLinePosOrIndex((pos, _i) => pos);
319+
}
320+
321+
public getVisibleLineCount(): number {
322+
return this.getVisibleLines().length;
323+
}
324+
325+
private getCurrentVisibleLinePosOrIndex(pickResult: (pos: number, index: number) => number): number | undefined {
314326
// Convert the current cursor into a top and use that to find which visible
315327
// line it is in.
316328
if (this.state.editor) {
@@ -320,16 +332,16 @@ export class MonacoEditor extends React.Component<IMonacoEditorProps, IMonacoEdi
320332
const count = this.getVisibleLineCount();
321333
const lineTops = count === this.lineTops.length ? this.lineTops : this.computeLineTops();
322334
for (let i = 0; i < count; i += 1) {
323-
if (top <= lineTops[i]) {
324-
return i;
335+
if (top <= lineTops[i].top) {
336+
return pickResult(i, lineTops[i].index);
325337
}
326338
}
327339
}
328340
}
329341
}
330342

331-
public getVisibleLineCount(): number {
332-
return this.getVisibleLines().length;
343+
private getCurrentVisibleLineIndex(): number | undefined {
344+
return this.getCurrentVisibleLinePosOrIndex((_pos, i) => i);
333345
}
334346

335347
private getVisibleLines(): HTMLDivElement[] {
@@ -343,23 +355,24 @@ export class MonacoEditor extends React.Component<IMonacoEditorProps, IMonacoEdi
343355
return [];
344356
}
345357

346-
private computeLineTops(): number[] {
358+
private computeLineTops() {
347359
const lines = this.getVisibleLines();
348360

349361
// Lines are not sorted by monaco, so we have to sort them by their top value
350-
this.lineTops = lines.map(l => {
362+
this.lineTops = lines.map((l, i) => {
351363
const match = l.style.top ? /(.+)px/.exec(l.style.top) : null;
352-
return match ? parseInt(match[0], 10) : Infinity;
353-
}).sort((a, b) => a - b);
364+
return { top: match ? parseInt(match[0], 10) : Infinity, index: i };
365+
}).sort((a, b) => a.top - b.top);
354366
return this.lineTops;
355367
}
356368

357-
private scrollOntoScreen(_editor: monacoEditor.editor.IStandaloneCodeEditor) {
358-
// Scroll to the visible line that has our current line
369+
private scrollToCurrentPosition(_editor: monacoEditor.editor.IStandaloneCodeEditor) {
370+
// Scroll to the visible line that has our current line. Note: Visible lines are not sorted by monaco
371+
// so we have to retrieve the current line's index (not its visible position)
359372
const visibleLineDivs = this.getVisibleLines();
360-
const current = this.getCurrentVisibleLine();
373+
const current = this.getCurrentVisibleLineIndex();
361374
if (current !== undefined && current >= 0 && visibleLineDivs[current].scrollIntoView) {
362-
visibleLineDivs[current].scrollIntoView({ behavior: 'auto', block: 'nearest', inline: 'nearest' });
375+
visibleLineDivs[current].scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
363376
}
364377
}
365378

0 commit comments

Comments
 (0)