Skip to content

Commit 12b4451

Browse files
committed
Fix cell DND issues
- Infinite loop in syncing focus/selection where the view cell index is not the same as the model cell index - Error thrown when dragging just above the top of the list
1 parent 0af3fc7 commit 12b4451

3 files changed

Lines changed: 31 additions & 16 deletions

File tree

src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ export interface INotebookEditor extends ICompositeCodeEditor {
364364

365365
export interface INotebookCellList {
366366
readonly contextKeyService: IContextKeyService;
367-
elementAt(position: number): ICellViewModel;
367+
elementAt(position: number): ICellViewModel | undefined;
368368
elementHeight(element: ICellViewModel): number;
369369
onWillScroll: Event<ScrollEvent>;
370370
onDidChangeFocus: Event<IListEvent<ICellViewModel>>;

src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,17 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
6767
this._previousFocusedElements = e.elements;
6868

6969
// if focus is in the list, but is not inside the focused element, then reset focus
70-
if (DOM.isAncestor(document.activeElement, this.rowsContainer)) {
71-
const focusedElement = this.getFocusedElements()[0];
72-
if (focusedElement) {
73-
const focusedDomElement = this.domElementOfElement(focusedElement);
74-
if (focusedDomElement && !DOM.isAncestor(document.activeElement, focusedDomElement)) {
75-
focusedDomElement.focus();
70+
setTimeout(() => {
71+
if (DOM.isAncestor(document.activeElement, this.rowsContainer)) {
72+
const focusedElement = this.getFocusedElements()[0];
73+
if (focusedElement) {
74+
const focusedDomElement = this.domElementOfElement(focusedElement);
75+
if (focusedDomElement && !DOM.isAncestor(document.activeElement, focusedDomElement)) {
76+
focusedDomElement.focus();
77+
}
7678
}
7779
}
78-
}
80+
}, 0);
7981
}));
8082

8183
const notebookEditorCursorAtBoundaryContext = NOTEBOOK_EDITOR_CURSOR_BOUNDARY.bindTo(contextKeyService);
@@ -132,8 +134,13 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
132134

133135
}
134136

135-
elementAt(position: number): ICellViewModel {
136-
return this.element(this.view.indexAt(position));
137+
elementAt(position: number): ICellViewModel | undefined {
138+
const idx = this.view.indexAt(position);
139+
if (idx >= 0) {
140+
return this.element(idx);
141+
}
142+
143+
return undefined;
137144
}
138145

139146
elementHeight(element: ICellViewModel): number {

src/vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -537,11 +537,15 @@ export class CellDragAndDropController extends Disposable {
537537
this._register(domEvent(document.body, DOM.EventType.DRAG_END, true)(this.onGlobalDragEnd.bind(this)));
538538

539539
const addCellDragListener = (eventType: string, handler: (e: CellDragEvent) => void) => {
540-
this._register(
541-
Event.map(
542-
domEvent(notebookEditor.getDomNode(), eventType),
543-
this.toCellDragEvent.bind(this))
544-
(handler));
540+
this._register(DOM.addDisposableListener(
541+
notebookEditor.getDomNode(),
542+
eventType,
543+
e => {
544+
const cellDragEvent = this.toCellDragEvent(e);
545+
if (cellDragEvent) {
546+
handler(cellDragEvent);
547+
}
548+
}));
545549
};
546550

547551
addCellDragListener(DOM.EventType.DRAG_OVER, event => {
@@ -576,10 +580,14 @@ export class CellDragAndDropController extends Disposable {
576580
this.listInsertionIndicator.style.opacity = visible ? '1' : '0';
577581
}
578582

579-
private toCellDragEvent(event: DragEvent): CellDragEvent {
583+
private toCellDragEvent(event: DragEvent): CellDragEvent | undefined {
580584
const targetTop = this.notebookEditor.getDomNode().getBoundingClientRect().top;
581585
const dragOffset = this.list.scrollTop + event.clientY - targetTop;
582586
const draggedOverCell = this.list.elementAt(dragOffset);
587+
if (!draggedOverCell) {
588+
return undefined;
589+
}
590+
583591
const cellTop = this.list.getAbsoluteTopOfElement(draggedOverCell);
584592
const cellHeight = this.list.elementHeight(draggedOverCell);
585593

0 commit comments

Comments
 (0)