提交 f48e190b 编写于 作者: R rebornix

cursor movement first cut

上级 35b51327
...@@ -425,14 +425,14 @@ export function registerAction2(ctor: { new(): Action2 }): IDisposable { ...@@ -425,14 +425,14 @@ export function registerAction2(ctor: { new(): Action2 }): IDisposable {
KeybindingsRegistry.registerKeybindingRule({ KeybindingsRegistry.registerKeybindingRule({
...item, ...item,
id: command.id, id: command.id,
when: ContextKeyExpr.and(command.precondition, item.when) when: command.precondition ? ContextKeyExpr.and(command.precondition, item.when) : item.when
}); });
} }
} else if (keybinding) { } else if (keybinding) {
KeybindingsRegistry.registerKeybindingRule({ KeybindingsRegistry.registerKeybindingRule({
...keybinding, ...keybinding,
id: command.id, id: command.id,
when: ContextKeyExpr.and(command.precondition, keybinding.when) when: command.precondition ? ContextKeyExpr.and(command.precondition, keybinding.when) : keybinding.when
}); });
} }
......
...@@ -12,8 +12,8 @@ import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebook ...@@ -12,8 +12,8 @@ import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebook
import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { NOTEBOOK_EDITOR_FOCUSED, NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEditor'; import { NOTEBOOK_EDITOR_FOCUSED, NotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookEditor';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED, CellState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { CellKind, NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel';
registerAction2(class extends Action2 { registerAction2(class extends Action2 {
...@@ -153,6 +153,10 @@ registerAction2(class extends Action2 { ...@@ -153,6 +153,10 @@ registerAction2(class extends Action2 {
let activeCell = editor.getActiveCell(); let activeCell = editor.getActiveCell();
if (activeCell) { if (activeCell) {
if (activeCell.cellKind === CellKind.Markdown) {
activeCell.state = CellState.Read;
}
editor.focusNotebookCell(activeCell, false); editor.focusNotebookCell(activeCell, false);
} }
} }
...@@ -361,3 +365,109 @@ function changeActiveCellToKind(kind: CellKind, accessor: ServicesAccessor): voi ...@@ -361,3 +365,109 @@ function changeActiveCellToKind(kind: CellKind, accessor: ServicesAccessor): voi
editor.focusNotebookCell(newCell, false); editor.focusNotebookCell(newCell, false);
editor.deleteNotebookCell(activeCell); editor.deleteNotebookCell(activeCell);
} }
function getActiveCell(accessor: ServicesAccessor): [NotebookEditor, CellViewModel] | undefined {
const editorService = accessor.get(IEditorService);
const notebookService = accessor.get(INotebookService);
const resource = editorService.activeEditor?.resource;
if (!resource) {
return;
}
const editor = getActiveNotebookEditor(editorService);
if (!editor) {
return;
}
const notebookProviders = notebookService.getContributedNotebookProviders(resource);
if (!notebookProviders.length) {
return;
}
const activeCell = editor.getActiveCell();
if (!activeCell) {
return;
}
return [editor, activeCell];
}
registerAction2(class extends Action2 {
constructor() {
super({
id: 'workbench.action.notebook.cursorDown',
title: 'Notebook Cursor Move Down',
keybinding: {
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.has(InputFocusedContextKey), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('top'), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('none')),
primary: KeyCode.DownArrow,
weight: KeybindingWeight.WorkbenchContrib
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const activeCellRet = getActiveCell(accessor);
if (!activeCellRet) {
return;
}
const [editor, activeCell] = activeCellRet;
const idx = editor.viewModel?.getViewCellIndex(activeCell);
if (typeof idx !== 'number') {
return;
}
const newCell = editor.viewModel?.viewCells[idx + 1];
if (!newCell) {
return;
}
editor.focusNotebookCell(newCell, true);
}
});
registerAction2(class extends Action2 {
constructor() {
super({
id: 'workbench.action.notebook.cursorUp',
title: 'Notebook Cursor Move Up',
keybinding: {
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.has(InputFocusedContextKey), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('bottom'), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('none')),
primary: KeyCode.UpArrow,
weight: KeybindingWeight.WorkbenchContrib
},
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const activeCellRet = getActiveCell(accessor);
if (!activeCellRet) {
return;
}
const [editor, activeCell] = activeCellRet;
const idx = editor.viewModel?.getViewCellIndex(activeCell);
if (typeof idx !== 'number') {
return;
}
if (idx < 1) {
// we don't do loop
return;
}
const newCell = editor.viewModel?.viewCells[idx - 1];
if (!newCell) {
return;
}
editor.focusNotebookCell(newCell, true);
}
});
...@@ -220,3 +220,15 @@ export enum CellState { ...@@ -220,3 +220,15 @@ export enum CellState {
*/ */
Editing Editing
} }
export enum CellFocusMode {
Container,
Editor
}
export enum CursorAtBoundary {
None,
Top,
Bottom,
Both
}
...@@ -21,7 +21,7 @@ import { contrastBorder, editorBackground, focusBorder, foreground, textBlockQuo ...@@ -21,7 +21,7 @@ import { contrastBorder, editorBackground, focusBorder, foreground, textBlockQuo
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor'; import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorOptions, IEditorMemento, ICompositeCodeEditor, IEditorCloseEvent } from 'vs/workbench/common/editor'; import { EditorOptions, IEditorMemento, ICompositeCodeEditor, IEditorCloseEvent } from 'vs/workbench/common/editor';
import { INotebookEditor, NotebookLayoutInfo, CellState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { INotebookEditor, NotebookLayoutInfo, CellState, CellFocusMode } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebookEditorInput, NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput'; import { NotebookEditorInput, NotebookEditorModel } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput';
import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService'; import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService';
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer'; import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer';
...@@ -186,6 +186,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { ...@@ -186,6 +186,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
this.body, this.body,
this.instantiationService.createInstance(NotebookCellListDelegate), this.instantiationService.createInstance(NotebookCellListDelegate),
renders, renders,
this.contextKeyService,
{ {
setRowLineHeight: false, setRowLineHeight: false,
setRowHeight: false, setRowHeight: false,
...@@ -212,7 +213,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { ...@@ -212,7 +213,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
listInactiveFocusBackground: editorBackground, listInactiveFocusBackground: editorBackground,
listInactiveFocusOutline: editorBackground, listInactiveFocusOutline: editorBackground,
} }
} },
); );
this.control = new NotebookCodeEditors(this.list, this.renderedEditors); this.control = new NotebookCodeEditors(this.list, this.renderedEditors);
...@@ -595,18 +596,22 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor { ...@@ -595,18 +596,22 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
const index = this.notebookViewModel!.getViewCellIndex(cell); const index = this.notebookViewModel!.getViewCellIndex(cell);
if (focusEditor) { if (focusEditor) {
this.list?.setFocus([index]);
this.list?.setSelection([index]);
this.list?.focusView();
cell.state = CellState.PreviewContent;
cell.focusMode = CellFocusMode.Editor;
} else { } else {
let itemDOM = this.list?.domElementAtIndex(index); let itemDOM = this.list?.domElementAtIndex(index);
if (document.activeElement && itemDOM && itemDOM.contains(document.activeElement)) { if (document.activeElement && itemDOM && itemDOM.contains(document.activeElement)) {
(document.activeElement as HTMLElement).blur(); (document.activeElement as HTMLElement).blur();
} }
cell.state = CellState.Read; this.list?.setFocus([index]);
this.list?.setSelection([index]);
this.list?.focusView();
} }
this.list?.setFocus([index]);
this.list?.focusView();
} }
//#endregion //#endregion
......
...@@ -15,11 +15,12 @@ import { IThemeService } from 'vs/platform/theme/common/themeService'; ...@@ -15,11 +15,12 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent'; import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { isMacintosh } from 'vs/base/common/platform'; import { isMacintosh } from 'vs/base/common/platform';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel';
import { EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { EDITOR_TOP_PADDING, NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { Range } from 'vs/editor/common/core/range'; import { Range } from 'vs/editor/common/core/range';
import { CellRevealType, CellRevealPosition } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellRevealType, CellRevealPosition, CursorAtBoundary } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle'; import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
export class NotebookCellList extends WorkbenchList<CellViewModel> implements IDisposable { export class NotebookCellList extends WorkbenchList<CellViewModel> implements IDisposable {
get onWillScroll(): Event<ScrollEvent> { return this.view.onWillScroll; } get onWillScroll(): Event<ScrollEvent> { return this.view.onWillScroll; }
...@@ -34,8 +35,8 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID ...@@ -34,8 +35,8 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
container: HTMLElement, container: HTMLElement,
delegate: IListVirtualDelegate<CellViewModel>, delegate: IListVirtualDelegate<CellViewModel>,
renderers: IListRenderer<CellViewModel, any>[], renderers: IListRenderer<CellViewModel, any>[],
contextKeyService: IContextKeyService,
options: IWorkbenchListOptions<CellViewModel>, options: IWorkbenchListOptions<CellViewModel>,
@IContextKeyService contextKeyService: IContextKeyService,
@IListService listService: IListService, @IListService listService: IListService,
@IThemeService themeService: IThemeService, @IThemeService themeService: IThemeService,
@IConfigurationService configurationService: IConfigurationService, @IConfigurationService configurationService: IConfigurationService,
...@@ -53,6 +54,48 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID ...@@ -53,6 +54,48 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
}); });
this._previousSelectedElements = e.elements; this._previousSelectedElements = e.elements;
})); }));
const notebookEditorCursorAtBoundaryContext = NOTEBOOK_EDITOR_CURSOR_BOUNDARY.bindTo(contextKeyService);
notebookEditorCursorAtBoundaryContext.set('none');
let cursorSelectionLisener: IDisposable | null = null;
const recomputeContext = (element: CellViewModel) => {
switch (element.cursorAtBoundary()) {
case CursorAtBoundary.Both:
notebookEditorCursorAtBoundaryContext.set('both');
break;
case CursorAtBoundary.Top:
notebookEditorCursorAtBoundaryContext.set('top');
break;
case CursorAtBoundary.Bottom:
notebookEditorCursorAtBoundaryContext.set('bottom');
break;
default:
notebookEditorCursorAtBoundaryContext.set('none');
break;
}
return;
};
// Cursor Boundary context
this._localDisposableStore.add(this.onDidChangeFocus((e) => {
cursorSelectionLisener?.dispose();
if (e.elements.length) {
// we only validate the first focused element
const focusedElement = e.elements[0];
cursorSelectionLisener = focusedElement.onDidChangeCursorSelection(() => {
recomputeContext(focusedElement);
});
recomputeContext(focusedElement);
return;
}
// reset context
notebookEditorCursorAtBoundaryContext.set('none');
}));
} }
domElementAtIndex(index: number): HTMLElement | null { domElementAtIndex(index: number): HTMLElement | null {
......
...@@ -9,7 +9,7 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; ...@@ -9,7 +9,7 @@ import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel'; import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookCellViewModel';
import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver';
import { CELL_MARGIN, IOutput, EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING, ITransformedDisplayOutputDto, IRenderOutput, CellOutputKind } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { CELL_MARGIN, IOutput, EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING, ITransformedDisplayOutputDto, IRenderOutput, CellOutputKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellRenderTemplate, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellRenderTemplate, INotebookEditor, CellFocusMode } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { raceCancellation } from 'vs/base/common/async'; import { raceCancellation } from 'vs/base/common/async';
import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
...@@ -86,6 +86,12 @@ export class CodeCell extends Disposable { ...@@ -86,6 +86,12 @@ export class CodeCell extends Disposable {
} }
}); });
this._register(viewCell.onDidChangeFocusMode(() => {
if (viewCell.focusMode === CellFocusMode.Editor) {
templateData.editor?.focus();
}
}));
let cellWidthResizeObserver = getResizesObserver(templateData.cellContainer, { let cellWidthResizeObserver = getResizesObserver(templateData.cellContainer, {
width: width, width: width,
height: totalHeight height: totalHeight
......
...@@ -10,7 +10,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions'; ...@@ -10,7 +10,7 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver'; import { getResizesObserver } from 'vs/workbench/contrib/notebook/browser/view/renderers/sizeObserver';
import { CELL_MARGIN, EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { CELL_MARGIN, EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookEditor, CellRenderTemplate } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { INotebookEditor, CellRenderTemplate, CellFocusMode } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { raceCancellation } from 'vs/base/common/async'; import { raceCancellation } from 'vs/base/common/async';
...@@ -194,6 +194,12 @@ export class StatefullMarkdownCell extends Disposable { ...@@ -194,6 +194,12 @@ export class StatefullMarkdownCell extends Disposable {
viewUpdate(); viewUpdate();
})); }));
this._register(viewCell.onDidChangeFocusMode(() => {
if (viewCell.focusMode === CellFocusMode.Editor) {
this.editor?.focus();
}
}));
viewUpdate(); viewUpdate();
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event'; import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import * as UUID from 'vs/base/common/uuid'; import * as UUID from 'vs/base/common/uuid';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { Range } from 'vs/editor/common/core/range'; import { Range } from 'vs/editor/common/core/range';
...@@ -16,7 +16,7 @@ import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer' ...@@ -16,7 +16,7 @@ import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer'
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { MarkdownRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/mdRenderer'; import { MarkdownRenderer } from 'vs/workbench/contrib/notebook/browser/view/renderers/mdRenderer';
import { CellKind, EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING, ICell, IOutput, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { CellKind, EDITOR_BOTTOM_PADDING, EDITOR_TOP_PADDING, ICell, IOutput, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { CellFindMatch, CellState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; import { CellFindMatch, CellState, CursorAtBoundary, CellFocusMode } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
export class CellViewModel extends Disposable { export class CellViewModel extends Disposable {
...@@ -26,6 +26,8 @@ export class CellViewModel extends Disposable { ...@@ -26,6 +26,8 @@ export class CellViewModel extends Disposable {
readonly onDidDispose = this._onDidDispose.event; readonly onDidDispose = this._onDidDispose.event;
protected readonly _onDidChangeEditingState = new Emitter<void>(); protected readonly _onDidChangeEditingState = new Emitter<void>();
readonly onDidChangeEditingState = this._onDidChangeEditingState.event; readonly onDidChangeEditingState = this._onDidChangeEditingState.event;
protected readonly _onDidChangeFocusMode = new Emitter<void>();
readonly onDidChangeFocusMode = this._onDidChangeFocusMode.event;
protected readonly _onDidChangeOutputs = new Emitter<NotebookCellOutputsSplice[]>(); protected readonly _onDidChangeOutputs = new Emitter<NotebookCellOutputsSplice[]>();
readonly onDidChangeOutputs = this._onDidChangeOutputs.event; readonly onDidChangeOutputs = this._onDidChangeOutputs.event;
private _outputCollection: number[] = []; private _outputCollection: number[] = [];
...@@ -74,6 +76,17 @@ export class CellViewModel extends Disposable { ...@@ -74,6 +76,17 @@ export class CellViewModel extends Disposable {
this._onDidChangeEditingState.fire(); this._onDidChangeEditingState.fire();
} }
private _focusMode: CellFocusMode = CellFocusMode.Container;
get focusMode() {
return this._focusMode;
}
set focusMode(newMode: CellFocusMode) {
this._focusMode = newMode;
this._onDidChangeFocusMode.fire();
}
private _selfSizeMonitoring: boolean = false; private _selfSizeMonitoring: boolean = false;
set selfSizeMonitoring(newVal: boolean) { set selfSizeMonitoring(newVal: boolean) {
...@@ -106,6 +119,10 @@ export class CellViewModel extends Disposable { ...@@ -106,6 +119,10 @@ export class CellViewModel extends Disposable {
private _editorViewStates: editorCommon.ICodeEditorViewState | null; private _editorViewStates: editorCommon.ICodeEditorViewState | null;
private _lastDecorationId: number = 0; private _lastDecorationId: number = 0;
private _resolvedDecorations = new Map<string, { id?: string, options: model.IModelDeltaDecoration }>(); private _resolvedDecorations = new Map<string, { id?: string, options: model.IModelDeltaDecoration }>();
private readonly _onDidChangeCursorSelection: Emitter<void> = this._register(new Emitter<void>());
public readonly onDidChangeCursorSelection: Event<void> = this._onDidChangeCursorSelection.event;
private _cursorChangeListener: IDisposable | null = null;
readonly id: string = UUID.generateUuid(); readonly id: string = UUID.generateUuid();
...@@ -300,6 +317,8 @@ export class CellViewModel extends Disposable { ...@@ -300,6 +317,8 @@ export class CellViewModel extends Disposable {
} }
}); });
this._cursorChangeListener = this._textEditor.onDidChangeCursorSelection(() => this._onDidChangeCursorSelection.fire());
this._onDidChangeCursorSelection.fire();
this._onDidChangeEditorAttachState.fire(true); this._onDidChangeEditorAttachState.fire(true);
} }
...@@ -315,6 +334,7 @@ export class CellViewModel extends Disposable { ...@@ -315,6 +334,7 @@ export class CellViewModel extends Disposable {
} }
}); });
this._textEditor = undefined; this._textEditor = undefined;
this._cursorChangeListener?.dispose();
this._onDidChangeEditorAttachState.fire(false); this._onDidChangeEditorAttachState.fire(false);
} }
...@@ -373,11 +393,46 @@ export class CellViewModel extends Disposable { ...@@ -373,11 +393,46 @@ export class CellViewModel extends Disposable {
} }
onDeselect() { onDeselect() {
if (this.state === CellState.PreviewContent) { if (this.cellKind === CellKind.Code) {
this.state = CellState.Read;
} else if (this.state === CellState.PreviewContent) {
this.state = CellState.Read; this.state = CellState.Read;
} }
} }
cursorAtBoundary(): CursorAtBoundary {
if (!this._textEditor) {
return CursorAtBoundary.None;
}
// only validate primary cursor
const selection = this._textEditor.getSelection();
// only validate empty cursor
if (!selection || !selection.isEmpty()) {
return CursorAtBoundary.None;
}
// we don't allow attaching text editor without a model
const lineCnt = this._textEditor.getModel()!.getLineCount();
if (selection.startLineNumber === lineCnt) {
// bottom
if (selection.startLineNumber === 1) {
return CursorAtBoundary.Both;
} else {
return CursorAtBoundary.Bottom;
}
}
if (selection.startLineNumber === 1) {
return CursorAtBoundary.Top;
}
return CursorAtBoundary.None;
}
getMarkdownRenderer() { getMarkdownRenderer() {
if (!this._mdRenderer) { if (!this._mdRenderer) {
this._mdRenderer = this._instaService.createInstance(MarkdownRenderer); this._mdRenderer = this._instaService.createInstance(MarkdownRenderer);
......
...@@ -12,6 +12,7 @@ import { URI } from 'vs/base/common/uri'; ...@@ -12,6 +12,7 @@ import { URI } from 'vs/base/common/uri';
import * as editorCommon from 'vs/editor/common/editorCommon'; import * as editorCommon from 'vs/editor/common/editorCommon';
import { PieceTreeTextBufferFactory } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder'; import { PieceTreeTextBufferFactory } from 'vs/editor/common/model/pieceTreeTextBuffer/pieceTreeTextBufferBuilder';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
export enum CellKind { export enum CellKind {
Markdown = 1, Markdown = 1,
...@@ -329,3 +330,5 @@ export function diff<T>(before: T[], after: T[], contains: (a: T) => boolean): I ...@@ -329,3 +330,5 @@ export function diff<T>(before: T[], after: T[], contains: (a: T) => boolean): I
export interface ICellEditorViewState { export interface ICellEditorViewState {
selections: editorCommon.ICursorState[]; selections: editorCommon.ICursorState[];
} }
export const NOTEBOOK_EDITOR_CURSOR_BOUNDARY = new RawContextKey<'none' | 'top' | 'bottom' | 'both'>('notebookEditorCursorAtBoundary', 'none');
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册