提交 88b1952c 编写于 作者: R rebornix

layoutinfo on view models

上级 2d03b83b
......@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Event } from 'vs/base/common/event';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
......@@ -27,6 +28,42 @@ export interface NotebookLayoutInfo {
fontInfo: BareFontInfo;
}
export interface NotebookLayoutChangeEvent {
width?: boolean;
height?: boolean;
fontInfo?: boolean;
}
export interface NotebookViewLayoutAccessor {
layoutInfo: NotebookLayoutInfo | null;
onDidChangeLayout: Event<NotebookLayoutChangeEvent>;
}
export interface CodeCellLayoutInfo {
readonly fontInfo: BareFontInfo | null;
readonly editorHeight: number;
readonly editorWidth: number;
readonly totalHeight: number;
readonly outputTotalHeight: number;
readonly indicatorHeight: number;
}
export interface CodeCellLayoutChangeEvent {
editorHeight?: boolean;
outputHeight?: boolean;
totalHeight?: boolean;
outerWidth?: boolean;
}
export interface MarkdownCellLayoutInfo {
readonly fontInfo: BareFontInfo | null;
readonly editorWidth: number;
}
export interface MarkdownCellLayoutChangeEvent {
outerWidth?: boolean;
}
export interface ICellViewModel {
readonly id: string;
handle: number;
......
......@@ -332,6 +332,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
}
this.notebookViewModel = this.instantiationService.createInstance(NotebookViewModel, input.viewType!, model);
this.notebookViewModel?.updateLayoutInfo(this.getLayoutInfo());
const viewState = this.loadTextEditorViewState(input);
this.notebookViewModel.restoreEditorViewState(viewState);
......@@ -413,6 +414,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
DOM.toggleClass(this.rootElement, 'narrow-width', dimension.width < 600);
DOM.size(this.body, dimension.width, dimension.height);
this.list?.layout(dimension.height, dimension.width);
this.notebookViewModel?.updateLayoutInfo(this.getLayoutInfo());
}
protected saveState(): void {
......@@ -659,9 +661,6 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
fontInfo: this.fontInfo!
};
}
getFontInfo(): BareFontInfo | undefined {
return this.fontInfo;
}
triggerScroll(event: IMouseWheelEvent) {
this.list?.triggerScrollFromMouseWheelEvent(event);
......
......@@ -14,7 +14,7 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { CELL_MARGIN, EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING, RUN_BUTTON_WIDTH } from 'vs/workbench/contrib/notebook/browser/constants';
import { EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
interface IMimeTypeRenderer extends IQuickPickItem {
index: number;
......@@ -32,12 +32,9 @@ export class CodeCell extends Disposable {
) {
super();
let width: number;
const listDimension = notebookEditor.getLayoutInfo();
width = listDimension.width - CELL_MARGIN * 2 - RUN_BUTTON_WIDTH;
const lineNum = viewCell.lineCount;
const lineHeight = notebookEditor.getLayoutInfo().fontInfo.lineHeight;
const width = this.viewCell.layoutInfo.editorWidth;
const lineNum = this.viewCell.lineCount;
const lineHeight = this.viewCell.layoutInfo.fontInfo?.lineHeight || 17;
const totalHeight = lineNum * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING;
templateData.editor?.layout(
{
......@@ -57,10 +54,8 @@ export class CodeCell extends Disposable {
templateData.editor?.focus();
}
let realContentHeight = templateData.editor?.getContentHeight();
let width: number;
const listDimension = notebookEditor.getLayoutInfo();
width = listDimension.width - CELL_MARGIN * 2 - RUN_BUTTON_WIDTH;
const realContentHeight = templateData.editor?.getContentHeight();
const width = this.viewCell.layoutInfo.editorWidth;
if (realContentHeight !== undefined && realContentHeight !== totalHeight) {
templateData.editor?.layout(
......@@ -266,11 +261,10 @@ export class CodeCell extends Disposable {
if (hasDynamicHeight) {
let clientHeight = outputItemDiv.clientHeight;
let listDimension = this.notebookEditor.getLayoutInfo();
let dimension = listDimension ? {
width: listDimension.width - CELL_MARGIN * 2 - RUN_BUTTON_WIDTH,
let dimension = {
width: this.viewCell.layoutInfo.editorWidth,
height: clientHeight
} : undefined;
};
const elementSizeObserver = getResizesObserver(outputItemDiv, dimension, () => {
if (this.templateData.outputContainer && document.body.contains(this.templateData.outputContainer!)) {
let height = elementSizeObserver.getHeight() + 8 * 2; // include padding
......
......@@ -12,7 +12,7 @@ import { INotebookEditor, CellRenderTemplate, CellFocusMode, CellState } from 'v
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { raceCancellation } from 'vs/base/common/async';
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
import { CELL_MARGIN, EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
import { EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
export class StatefullMarkdownCell extends Disposable {
private editor: CodeEditorWidget | null = null;
......@@ -38,16 +38,9 @@ export class StatefullMarkdownCell extends Disposable {
const viewUpdate = () => {
if (viewCell.state === CellState.Editing) {
// switch to editing mode
let width: number;
const listDimension = notebookEditor.getLayoutInfo();
width = listDimension.width - CELL_MARGIN * 2;
// if (listDimension) {
// } else {
// width = this.cellContainer.clientWidth - 24 /** for scrollbar and margin right */;
// }
let width = viewCell.layoutInfo.editorWidth;
const lineNum = viewCell.lineCount;
const lineHeight = notebookEditor.getLayoutInfo().fontInfo.lineHeight;
const lineHeight = viewCell.layoutInfo.fontInfo?.lineHeight || 17;
const totalHeight = Math.max(lineNum, 1) * lineHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING;
if (this.editor) {
......
......@@ -70,7 +70,7 @@ export class DeleteCellEdit implements IResourceUndoRedoElement {
throw new Error('Notebook Insert Cell not implemented for Undo/Redo');
}
const cell = createCellViewModel(this.instantiationService, this.notebookViewModel.viewType, this.notebookViewModel.handle, this._rawCell);
const cell = createCellViewModel(this.instantiationService, this.notebookViewModel, this._rawCell);
this.editingDelegate.insertCell(this.insertIndex, cell);
}
......
......@@ -8,24 +8,11 @@ import * as UUID from 'vs/base/common/uuid';
import * as model from 'vs/editor/common/model';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer';
import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
import { CellState, ICellViewModel, CellFindMatch } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING, CELL_MARGIN, RUN_BUTTON_WIDTH } from 'vs/workbench/contrib/notebook/browser/constants';
import { CellState, ICellViewModel, CellFindMatch, NotebookViewLayoutAccessor, CodeCellLayoutChangeEvent, CodeCellLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellKind, ICell, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { BaseCellViewModel } from './baseCellViewModel';
export interface CodeCellLayoutInfo {
readonly editorHeight: number;
readonly totalHeight: number;
readonly outputTotalHeight: number;
readonly indicatorHeight: number;
}
export interface CodeCellLayoutChangeEvent {
editorHeight?: boolean;
outputHeight?: boolean;
totalHeight?: boolean;
}
export class CodeCellViewModel extends BaseCellViewModel implements ICellViewModel {
cellKind: CellKind.Code = CellKind.Code;
protected readonly _onDidChangeOutputs = new Emitter<NotebookCellOutputsSplice[]>();
......@@ -72,6 +59,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
readonly viewType: string,
readonly notebookHandle: number,
readonly cell: ICell,
private _layoutAccessor: NotebookViewLayoutAccessor,
@ITextModelService private readonly _modelService: ITextModelService,
) {
super(viewType, notebookHandle, cell, UUID.generateUuid());
......@@ -87,11 +75,19 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
this._buffer = null;
this._layoutInfo = {
fontInfo: _layoutAccessor.layoutInfo?.fontInfo || null,
editorHeight: 0,
editorWidth: 0,
outputTotalHeight: 0,
totalHeight: 0,
indicatorHeight: 0
};
this._register(_layoutAccessor.onDidChangeLayout((e) => {
if (e.width) {
this.layoutChange({ outerWidth: true });
}
}));
}
layoutChange(state: CodeCellLayoutChangeEvent) {
......@@ -102,9 +98,11 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
? EDITOR_TOOLBAR_HEIGHT + this.editorHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + 16 + outputTotalHeight
: EDITOR_TOOLBAR_HEIGHT + this.editorHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + outputTotalHeight;
const indicatorHeight = totalHeight - EDITOR_TOOLBAR_HEIGHT - 16;
const editorWidth = this._layoutAccessor.layoutInfo ? this._layoutAccessor.layoutInfo.width - CELL_MARGIN * 2 - RUN_BUTTON_WIDTH : 0;
this._layoutInfo = {
fontInfo: this._layoutAccessor.layoutInfo?.fontInfo || null,
editorHeight: this._editorHeight,
editorWidth,
outputTotalHeight,
totalHeight,
indicatorHeight
......
......@@ -8,10 +8,11 @@ import * as UUID from 'vs/base/common/uuid';
import * as model from 'vs/editor/common/model';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { CellState, ICellViewModel, CellFindMatch } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellState, ICellViewModel, CellFindMatch, NotebookViewLayoutAccessor, MarkdownCellLayoutInfo, MarkdownCellLayoutChangeEvent } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { MarkdownRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/mdRenderer';
import { BaseCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/baseCellViewModel';
import { CellKind, ICell } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CELL_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants';
export class MarkdownCellViewModel extends BaseCellViewModel implements ICellViewModel {
cellKind: CellKind.Markdown = CellKind.Markdown;
......@@ -20,14 +21,46 @@ export class MarkdownCellViewModel extends BaseCellViewModel implements ICellVie
private readonly _onDidChangeContent: Emitter<void> = this._register(new Emitter<void>());
public readonly onDidChangeContent: Event<void> = this._onDidChangeContent.event;
private _layoutInfo: MarkdownCellLayoutInfo;
get layoutInfo() {
return this._layoutInfo;
}
protected readonly _onDidChangeLayout = new Emitter<MarkdownCellLayoutChangeEvent>();
readonly onDidChangeLayout = this._onDidChangeLayout.event;
constructor(
readonly viewType: string,
readonly notebookHandle: number,
readonly cell: ICell,
private _layoutAccessor: NotebookViewLayoutAccessor,
@IInstantiationService private readonly _instaService: IInstantiationService,
@ITextModelService private readonly _modelService: ITextModelService) {
super(viewType, notebookHandle, cell, UUID.generateUuid());
this._layoutInfo = {
fontInfo: this._layoutAccessor.layoutInfo?.fontInfo || null,
editorWidth: 0
};
this._register(_layoutAccessor.onDidChangeLayout((e) => {
if (e.width) {
this.layoutChange({ outerWidth: true });
}
}));
}
layoutChange(state: MarkdownCellLayoutChangeEvent) {
// recompute
const editorWidth = this._layoutAccessor.layoutInfo ? this._layoutAccessor.layoutInfo.width - CELL_MARGIN * 2 : 0;
this._layoutInfo = {
fontInfo: this._layoutAccessor.layoutInfo?.fontInfo || null,
editorWidth
};
this._onDidChangeLayout.fire(state);
}
hasDynamicHeight() {
......
......@@ -14,7 +14,7 @@ import { IModelDeltaDecoration } from 'vs/editor/common/model';
import { WorkspaceTextEdit } from 'vs/editor/common/modes';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { CellFindMatch, CellState, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellFindMatch, CellState, ICellViewModel, NotebookLayoutInfo, NotebookLayoutChangeEvent, NotebookViewLayoutAccessor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput';
import { DeleteCellEdit, InsertCellEdit, MoveCellEdit } from 'vs/workbench/contrib/notebook/browser/viewModel/cellEdit';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
......@@ -54,7 +54,7 @@ export interface INotebookViewCellsUpdateEvent {
splices: NotebookViewCellsSplice[];
}
export class NotebookViewModel extends Disposable {
export class NotebookViewModel extends Disposable implements NotebookViewLayoutAccessor {
private _localStore: DisposableStore = this._register(new DisposableStore());
private _viewCells: CellViewModel[] = [];
......@@ -98,6 +98,13 @@ export class NotebookViewModel extends Disposable {
return null;
}
protected readonly _onDidChangeLayout = new Emitter<NotebookLayoutChangeEvent>();
readonly onDidChangeLayout = this._onDidChangeLayout.event;
private _layoutInfo: NotebookLayoutInfo | null = null;
get layoutInfo() {
return this._layoutInfo;
}
constructor(
public viewType: string,
private _model: NotebookEditorModel,
......@@ -112,14 +119,14 @@ export class NotebookViewModel extends Disposable {
synchronous: true,
splices: e.map(splice => {
return [splice[0], splice[1], splice[2].map(cell => {
return createCellViewModel(this.instantiationService, this.viewType, this.handle, cell);
return createCellViewModel(this.instantiationService, this, cell);
})];
})
});
}));
this._viewCells = this._model!.notebook!.cells.map(cell => {
return createCellViewModel(this.instantiationService, this.viewType, this._model!.notebook!.handle, cell);
return createCellViewModel(this.instantiationService, this, cell);
});
}
......@@ -153,7 +160,7 @@ export class NotebookViewModel extends Disposable {
}
insertCell(index: number, cell: ICell, synchronous: boolean): CellViewModel {
let newCell: CellViewModel = createCellViewModel(this.instantiationService, this.viewType, this.handle, cell);
let newCell: CellViewModel = createCellViewModel(this.instantiationService, this, cell);
this._viewCells!.splice(index, 0, newCell);
this._model.insertCell(newCell.cell, index);
this._localStore.add(newCell);
......@@ -373,6 +380,24 @@ export class NotebookViewModel extends Disposable {
return this._model === model;
}
updateLayoutInfo(layoutInfo: NotebookLayoutInfo | null) {
if (layoutInfo === null) {
return;
}
if (this._layoutInfo === null) {
this._layoutInfo = layoutInfo;
this._onDidChangeLayout.fire({ width: true, height: true });
return;
}
let widthChanged = layoutInfo.width !== this._layoutInfo.width;
let heightChanged = layoutInfo.height !== this._layoutInfo.height;
this._layoutInfo = layoutInfo;
this._onDidChangeLayout.fire({ width: widthChanged, height: heightChanged });
}
dispose() {
this._localStore.clear();
this._viewCells.forEach(cell => {
......@@ -386,10 +411,10 @@ export class NotebookViewModel extends Disposable {
export type CellViewModel = CodeCellViewModel | MarkdownCellViewModel;
export function createCellViewModel(instantiationService: IInstantiationService, viewType: string, notebookHandle: number, cell: ICell) {
export function createCellViewModel(instantiationService: IInstantiationService, notebookViewModel: NotebookViewModel, cell: ICell) {
if (cell.cellKind === CellKind.Code) {
return instantiationService.createInstance(CodeCellViewModel, viewType, notebookHandle, cell);
return instantiationService.createInstance(CodeCellViewModel, notebookViewModel.viewType, notebookViewModel.handle, cell, notebookViewModel);
} else {
return instantiationService.createInstance(MarkdownCellViewModel, viewType, notebookHandle, cell);
return instantiationService.createInstance(MarkdownCellViewModel, notebookViewModel.viewType, notebookViewModel.handle, cell, notebookViewModel);
}
}
......@@ -7,7 +7,7 @@ import { Emitter, Event } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri';
import { PieceTreeTextBufferFactory } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder';
import { CellKind, ICell, IOutput, NotebookCellOutputsSplice, CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookViewModel, IModelDecorationsChangeAccessor, CellViewModel, createCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { NotebookViewModel, IModelDecorationsChangeAccessor, CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput';
import { INotebookEditor, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
......@@ -178,10 +178,10 @@ export class TestNotebookEditor implements INotebookEditor {
}
}
export function createTestCellViewModel(instantiationService: IInstantiationService, viewType: string, notebookHandle: number, cellhandle: number, source: string[], language: string, cellKind: CellKind, outputs: IOutput[]) {
const mockCell = new TestCell(viewType, cellhandle, source, language, cellKind, outputs);
return createCellViewModel(instantiationService, viewType, notebookHandle, mockCell);
}
// export function createTestCellViewModel(instantiationService: IInstantiationService, viewType: string, notebookHandle: number, cellhandle: number, source: string[], language: string, cellKind: CellKind, outputs: IOutput[]) {
// const mockCell = new TestCell(viewType, cellhandle, source, language, cellKind, outputs);
// return createCellViewModel(instantiationService, viewType, notebookHandle, mockCell);
// }
export function withTestNotebook(instantiationService: IInstantiationService, blukEditService: IBulkEditService, undoRedoService: IUndoRedoService, cells: [string[], string, CellKind, IOutput[]][], callback: (editor: TestNotebookEditor, viewModel: NotebookViewModel) => void) {
const viewType = 'notebook';
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册