Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re #209154. Render code editor at maximum height of the viewport #225203

Merged
merged 1 commit into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ export interface INotebookEditor {
readonly onDidFocusWidget: Event<void>;
readonly onDidBlurWidget: Event<void>;
readonly onDidScroll: Event<void>;
readonly onDidChangeLayout: Event<void>;
readonly onDidChangeActiveCell: Event<void>;
readonly onDidChangeActiveKernel: Event<void>;
readonly onMouseUp: Event<INotebookEditorMouseEvent>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { PixelRatio } from 'vs/base/browser/pixelRatio';
import { PreventDefaultContextMenuItemsContextKeyName } from 'vs/workbench/contrib/webview/browser/webview.contribution';
import { NotebookAccessibilityProvider } from 'vs/workbench/contrib/notebook/browser/notebookAccessibilityProvider';
import { NotebookHorizontalTracker } from 'vs/workbench/contrib/notebook/browser/viewParts/notebookHorizontalTracker';

const $ = DOM.$;

Expand Down Expand Up @@ -150,6 +151,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
readonly onDidChangeDecorations: Event<void> = this._onDidChangeDecorations.event;
private readonly _onDidScroll = this._register(new Emitter<void>());
readonly onDidScroll: Event<void> = this._onDidScroll.event;
private readonly _onDidChangeLayout = this._register(new Emitter<void>());
readonly onDidChangeLayout: Event<void> = this._onDidChangeLayout.event;
private readonly _onDidChangeActiveCell = this._register(new Emitter<void>());
readonly onDidChangeActiveCell: Event<void> = this._onDidChangeActiveCell.event;
private readonly _onDidChangeFocus = this._register(new Emitter<void>());
Expand Down Expand Up @@ -323,6 +326,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
this._notebookOptions,
eventDispatcher,
language => this.getBaseCellEditorOptions(language));
this._register(this._viewContext.eventDispatcher.onDidChangeLayout(() => {
this._onDidChangeLayout.fire();
}));
this._register(this._viewContext.eventDispatcher.onDidChangeCellState(e => {
this._onDidChangeCellState.fire(e);
}));
Expand Down Expand Up @@ -610,6 +616,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
this._list.scrollableElement.appendChild(this._notebookOverviewRulerContainer);
this._registerNotebookOverviewRuler();

this._register(this.instantiationService.createInstance(NotebookHorizontalTracker, this, this._list.scrollableElement));

this._overflowContainer = document.createElement('div');
this._overflowContainer.classList.add('notebook-overflow-widget-container', 'monaco-editor');
DOM.append(parent, this._overflowContainer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Codicon } from 'vs/base/common/codicons';
import { ThemeIcon } from 'vs/base/common/themables';
import { Event } from 'vs/base/common/event';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { clamp } from 'vs/base/common/numbers';
import * as strings from 'vs/base/common/strings';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { IDimension } from 'vs/editor/common/core/dimension';
Expand Down Expand Up @@ -66,6 +67,7 @@ export class CodeCell extends Disposable {
this.initializeEditor(editorHeight);
this._renderedInputCollapseState = false; // editor is always expanded initially

this.registerNotebookEditorListeners();
this.registerViewCellLayoutChange();
this.registerCellEditorEventListeners();
this.registerDecorations();
Expand Down Expand Up @@ -264,12 +266,52 @@ export class CodeCell extends Disposable {
}
}

private registerNotebookEditorListeners() {
this._register(this.notebookEditor.onDidScroll(() => {
this.adjustEditorPosition();
}));

this._register(this.notebookEditor.onDidChangeLayout(() => {
this.adjustEditorPosition();
this.onCellWidthChange();
}));
}

private adjustEditorPosition() {
const extraOffset = - 6 /** distance to the top of the cell editor, which is 6px under the focus indicator */ - 1 /** border */;
const min = 0;

const scrollTop = this.notebookEditor.scrollTop;
const elementTop = this.notebookEditor.getAbsoluteTopOfElement(this.viewCell);
const diff = scrollTop - elementTop + extraOffset;

const notebookEditorLayout = this.notebookEditor.getLayoutInfo();

// we should stop adjusting the top when users are viewing the bottom of the cell editor
const editorMaxHeight = notebookEditorLayout.height
- notebookEditorLayout.stickyHeight
- 26 /** notebook toolbar */;

const maxTop =
this.viewCell.layoutInfo.editorHeight
// + this.viewCell.layoutInfo.statusBarHeight
- editorMaxHeight
;
const top = maxTop > 20 ?
clamp(min, diff, maxTop) :
min;
this.templateData.editorPart.style.top = `${top}px`;
// scroll the editor with top
this.templateData.editor?.setScrollTop(top);
}

private registerViewCellLayoutChange() {
this._register(this.viewCell.onDidChangeLayout((e) => {
if (e.outerWidth !== undefined) {
const layoutInfo = this.templateData.editor.getLayoutInfo();
if (layoutInfo.width !== this.viewCell.layoutInfo.editorWidth) {
this.onCellWidthChange();
this.adjustEditorPosition();
}
}
}));
Expand Down Expand Up @@ -532,7 +574,17 @@ export class CodeCell extends Disposable {
}

private layoutEditor(dimension: IDimension): void {
this.templateData.editor?.layout(dimension, true);
const editorLayout = this.notebookEditor.getLayoutInfo();
const maxHeight = Math.min(
editorLayout.height
- editorLayout.stickyHeight
- 26 /** notebook toolbar */,
dimension.height
);
this.templateData.editor?.layout({
width: dimension.width,
height: maxHeight
}, true);
}

private onCellWidthChange(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1152,9 +1152,6 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
// Scrolled into view from above
this.view.setScrollTop(positionTop - 30);
}


element.revealRangeInCenter(range);
}
//#endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,12 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
width: 0,
height: 0
},
scrollbar: {
vertical: 'hidden',
horizontal: 'auto',
handleMouseWheel: false,
useShadows: false,
},
}, {
contributions: this.notebookEditor.creationOptions.cellEditorContributions
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { addDisposableListener, EventType, getWindow } from 'vs/base/browser/dom';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { Disposable } from 'vs/base/common/lifecycle';
import { isChrome } from 'vs/base/common/platform';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditor/codeEditorWidget';
import { INotebookEditorDelegate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';

export class NotebookHorizontalTracker extends Disposable {
constructor(
private readonly _notebookEditor: INotebookEditorDelegate,
private readonly _listViewScrollablement: HTMLElement,
) {
super();

this._register(addDisposableListener(this._listViewScrollablement, EventType.MOUSE_WHEEL, (event: IMouseWheelEvent) => {
if (event.deltaX === 0) {
return;
}

const hoveringOnEditor = this._notebookEditor.codeEditors.find(editor => {
const editorLayout = editor[1].getLayoutInfo();
if (editorLayout.contentWidth === editorLayout.width) {
// no overflow
return false;
}

const editorDOM = editor[1].getDomNode();
if (editorDOM && editorDOM.contains(event.target as HTMLElement)) {
return true;
}

return false;
});

if (!hoveringOnEditor) {
return;
}

const targetWindow = getWindow(event);
const evt = {
deltaMode: event.deltaMode,
deltaX: event.deltaX,
deltaY: 0,
deltaZ: 0,
wheelDelta: event.wheelDelta && isChrome ? (event.wheelDelta / targetWindow.devicePixelRatio) : event.wheelDelta,
wheelDeltaX: event.wheelDeltaX && isChrome ? (event.wheelDeltaX / targetWindow.devicePixelRatio) : event.wheelDeltaX,
wheelDeltaY: 0,
detail: event.detail,
shiftKey: event.shiftKey,
type: event.type,
defaultPrevented: false,
preventDefault: () => { },
stopPropagation: () => { }
};

(hoveringOnEditor[1] as CodeEditorWidget).delegateScrollFromMouseWheelEvent(evt as any);
}));
}
}
Loading