forked from jupyter/nbdime
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make Cells Display Lazily When Diffing Unchanged Cells
Motivation: During diffing Unchanged cells are displayed, which is not necessary. This is a performance issue when there are many unchanged cells. Related Issues: - jupyter#635 Open Questions: - I am struggling with getting the svg images to build properly. - How can this be tested in JupyterLab? Changes: - Alter Notebooks Widget to only display changed cells by using new linked list of cells. - Add new linked list of cells and lazy version of linked list of cells.
- Loading branch information
Showing
10 changed files
with
479 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
import { Panel, Widget } from '@lumino/widgets'; | ||
import type { CellDiffWidget } from './'; | ||
import { LabIcon } from '@jupyterlab/ui-components'; | ||
|
||
import foldDown from './fold-down.svg'; | ||
import foldUp from './fold-up.svg'; | ||
import fold from './fold.svg'; | ||
|
||
export const foldDownIcon = new LabIcon({ | ||
name: 'nbdime:fold-down', | ||
svgstr: foldDown, | ||
}); | ||
|
||
export const foldUpIcon = new LabIcon({ | ||
name: 'nbdime:fold-up', | ||
svgstr: foldUp, | ||
}); | ||
|
||
export const foldIcon = new LabIcon({ | ||
name: 'nbdime:fold', | ||
svgstr: fold, | ||
}); | ||
|
||
export interface ILinkedListCell { | ||
_next: ILinkedListCell | null; | ||
_prev: ILinkedListCell | null; | ||
displayed: boolean; | ||
lazy: boolean; | ||
expandUp: () => void; | ||
expandDown: () => void; | ||
} | ||
|
||
class LinkedListCell extends Panel implements ILinkedListCell { | ||
renderFunc: () => CellDiffWidget; | ||
displayed: boolean; | ||
_next: ILinkedListCell | null; | ||
_prev: ILinkedListCell | null; | ||
lazy: boolean; | ||
|
||
constructor(renderFunc: () => CellDiffWidget) { | ||
super(); | ||
this._next = null; | ||
this._prev = null; | ||
this.renderFunc = renderFunc; | ||
this.displayed = true; | ||
this.renderCell(); | ||
this.addClass('linked-cell'); | ||
this.lazy = false; | ||
} | ||
|
||
protected renderCell() { | ||
this.addWidget(this.renderFunc()); | ||
this.displayed = true; | ||
} | ||
|
||
get next() { | ||
return this._next; | ||
} | ||
|
||
set next(nextCell) { | ||
this._next = nextCell; | ||
if (nextCell === null) { | ||
return; | ||
} | ||
|
||
if (nextCell.lazy) { | ||
nextCell.expandDown(); | ||
} | ||
} | ||
|
||
get prev() { | ||
return this._prev; | ||
} | ||
|
||
set prev(prevCell) { | ||
this._prev = prevCell; | ||
if (prevCell === null) { | ||
return; | ||
} | ||
prevCell._next = this as ILinkedListCell; | ||
if (prevCell.lazy) { | ||
prevCell.expandUp(); | ||
} | ||
} | ||
|
||
expandUp(): void { | ||
return; | ||
} | ||
|
||
expandDown(): void { | ||
return; | ||
} | ||
} | ||
|
||
class LazyDisplayLinkedListCell extends LinkedListCell { | ||
expandButton: HTMLDivElement; | ||
expandButtonDisplayed: boolean; | ||
|
||
// Path: packages/nbdime/src/diff/widget/wrapper_cells.ts | ||
constructor(renderFunc: () => CellDiffWidget) { | ||
super(renderFunc); | ||
this.expandButton = document.createElement('div'); | ||
this.expandButton.className = 'jp-expand-output-wrapper'; | ||
this.expandButtonDisplayed = false; | ||
this.addClass('lazy-linked-cell'); | ||
this.lazy = true; | ||
} | ||
|
||
set prev(prevCell: LinkedListCell | LazyDisplayLinkedListCell) { | ||
this._prev = prevCell; | ||
prevCell.next = this; | ||
} | ||
|
||
set next(nextCell: LinkedListCell | LazyDisplayLinkedListCell) { | ||
this._next = nextCell; | ||
} | ||
|
||
protected renderCell() { | ||
this.displayed = false; | ||
} | ||
|
||
expandUp(): void { | ||
if (this.displayed) { | ||
return; | ||
} | ||
if (this.expandButtonDisplayed) { | ||
this._setupFoldButton(); | ||
} else { | ||
this._setupExpandUpButton(); | ||
} | ||
} | ||
|
||
expandDown(): void { | ||
if (this.displayed) { | ||
return; | ||
} | ||
if (this.expandButtonDisplayed) { | ||
this._setupFoldButton(); | ||
} else { | ||
this._setupExpandDownButton(); | ||
} | ||
} | ||
|
||
_setupFoldButton() { | ||
this.expandButton.innerHTML = ''; | ||
const button = this.createButton('Fold'); | ||
button.onclick = e => { | ||
e.preventDefault(); | ||
this.showLazyCellUp(); | ||
}; | ||
this.expandButton.appendChild(button); | ||
const widget = new Widget({ node: this.expandButton }); | ||
this.addWidget(widget); | ||
} | ||
|
||
_setupExpandUpButton() { | ||
const button = this.createButton('Up'); | ||
button.onclick = e => { | ||
e.preventDefault(); | ||
this.showLazyCellUp(); | ||
}; | ||
this.expandButton.appendChild(button); | ||
const widget = new Widget({ node: this.expandButton }); | ||
this.addWidget(widget); | ||
} | ||
|
||
_setupExpandDownButton() { | ||
const button = this.createButton('Down'); | ||
button.onclick = e => { | ||
e.preventDefault(); | ||
this.showLazyCellDown(); | ||
}; | ||
this.expandButton.appendChild(button); | ||
const widget = new Widget({ node: this.expandButton }); | ||
this.addWidget(widget); | ||
} | ||
|
||
createButton(direction: 'Up' | 'Down' | 'Fold'): HTMLAnchorElement { | ||
this.expandButton.innerHTML = ''; | ||
const button = document.createElement('a'); | ||
button.title = `Expand ${direction}`; | ||
button.setAttribute('aria-label', `Expand ${direction}`); | ||
let icon = this.buttonSvg(direction); | ||
icon.element({ | ||
container: button, | ||
}); | ||
this.expandButtonDisplayed = true; | ||
return button; | ||
} | ||
|
||
buttonSvg(direction: 'Up' | 'Down' | 'Fold'): LabIcon { | ||
if (direction === 'Up') { | ||
return foldUpIcon; | ||
} else if (direction === 'Down') { | ||
return foldDownIcon; | ||
} else { | ||
return foldIcon; | ||
} | ||
} | ||
|
||
showLazyCellUp() { | ||
this.showLazyCell(); | ||
if (this._prev) { | ||
this._prev.expandUp(); | ||
} | ||
} | ||
|
||
showLazyCellDown() { | ||
this.showLazyCell(); | ||
if (this._next) { | ||
this._next.expandDown(); | ||
} | ||
} | ||
|
||
showLazyCell() { | ||
this.addWidget(this.renderFunc()); | ||
this.displayed = true; | ||
this.expandButton.remove(); | ||
} | ||
} | ||
|
||
export { LinkedListCell, LazyDisplayLinkedListCell }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.