未验证 提交 0a3df930 编写于 作者: R Rob Lourens 提交者: GitHub

Merge pull request #97185 from ctmayn/focus-notebook-output

Focus notebook output
......@@ -4,24 +4,24 @@
*--------------------------------------------------------------------------------------------*/
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { URI } from 'vs/base/common/uri';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { localize } from 'vs/nls';
import { Action2, IAction2Options, MenuId, MenuItemAction, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext, InputFocusedContextKey } from 'vs/platform/contextkey/common/contextkeys';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { BaseCellRenderTemplate, CellEditState, CellRunState, ICellViewModel, INotebookEditor, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_CELL_RUNNABLE, NOTEBOOK_CELL_TYPE, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_EDITABLE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
import { BaseCellRenderTemplate, CellEditState, CellRunState, ICellViewModel, INotebookEditor, NOTEBOOK_CELL_EDITABLE, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE, NOTEBOOK_CELL_RUNNABLE, NOTEBOOK_CELL_TYPE, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CellKind, NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IModelService } from 'vs/editor/common/services/modelService';
import { getIconClasses } from 'vs/editor/common/services/getIconClasses';
import { IQuickInputService, IQuickPickItem, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
import { URI } from 'vs/base/common/uri';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
// Notebook Commands
const EXECUTE_NOTEBOOK_COMMAND_ID = 'notebook.execute';
......@@ -66,6 +66,7 @@ const EXECUTE_CELL_INSERT_BELOW = 'notebook.cell.executeAndInsertBelow';
const CLEAR_CELL_OUTPUTS_COMMAND_ID = 'notebook.cell.clearOutputs';
const CHANGE_CELL_LANGUAGE = 'notebook.cell.changeLanguage';
const FOCUS_OUTPUT_COMMAND_ID = 'notebook.cell.focusOutput';
export const NOTEBOOK_ACTIONS_CATEGORY = localize('notebookActions.category', "Notebook");
......@@ -207,11 +208,11 @@ registerAction2(class extends Action2 {
// Try to select below, fall back on inserting
const nextCell = editor.viewModel?.viewCells[idx + 1];
if (nextCell) {
editor.focusNotebookCell(nextCell, activeCell.editState === CellEditState.Editing);
editor.focusNotebookCell(nextCell, activeCell.editState === CellEditState.Editing ? 'editor' : 'container');
} else {
const newCell = editor.insertNotebookCell(activeCell, CellKind.Code, 'below');
if (newCell) {
editor.focusNotebookCell(newCell, true);
editor.focusNotebookCell(newCell, 'editor');
}
}
}
......@@ -245,7 +246,7 @@ registerAction2(class extends Action2 {
const newCell = editor.insertNotebookCell(activeCell, CellKind.Code, 'below');
if (newCell) {
editor.focusNotebookCell(newCell, true);
editor.focusNotebookCell(newCell, 'editor');
}
}
});
......@@ -320,7 +321,7 @@ registerAction2(class extends Action2 {
activeCell.editState = CellEditState.Preview;
}
editor.focusNotebookCell(activeCell, false);
editor.focusNotebookCell(activeCell, 'container');
}
}
});
......@@ -473,7 +474,7 @@ export async function changeCellToKind(kind: CellKind, context: INotebookCellAct
newCell.model.language = language;
}
notebookEditor.focusNotebookCell(newCell, cell.editState === CellEditState.Editing);
notebookEditor.focusNotebookCell(newCell, cell.editState === CellEditState.Editing ? 'editor' : 'container');
notebookEditor.deleteNotebookCell(cell);
return newCell;
......@@ -528,7 +529,7 @@ abstract class InsertCellCommand extends Action2 {
const newCell = context.notebookEditor.insertNotebookCell(context.cell, this.kind, this.direction, undefined, context.ui);
if (newCell) {
context.notebookEditor.focusNotebookCell(newCell, true);
context.notebookEditor.focusNotebookCell(newCell, 'editor');
}
}
}
......@@ -699,7 +700,6 @@ registerAction2(class extends Action2 {
}
});
registerAction2(class extends Action2 {
constructor() {
super(
......@@ -740,12 +740,12 @@ registerAction2(class extends Action2 {
// deletion succeeds, move focus to the next cell
const nextCellIdx = index < context.notebookEditor.viewModel!.length ? index : context.notebookEditor.viewModel!.length - 1;
if (nextCellIdx >= 0) {
context.notebookEditor.focusNotebookCell(context.notebookEditor.viewModel!.viewCells[nextCellIdx], false);
context.notebookEditor.focusNotebookCell(context.notebookEditor.viewModel!.viewCells[nextCellIdx], 'container');
} else {
// No cells left, insert a new empty one
const newCell = context.notebookEditor.insertNotebookCell(undefined, context.cell.cellKind);
if (newCell) {
context.notebookEditor.focusNotebookCell(newCell, true);
context.notebookEditor.focusNotebookCell(newCell, 'editor');
}
}
}
......@@ -759,7 +759,7 @@ async function moveCell(context: INotebookCellActionContext, direction: 'up' | '
if (result) {
// move cell command only works when the cell container has focus
context.notebookEditor.focusNotebookCell(context.cell, false);
context.notebookEditor.focusNotebookCell(context.cell, 'container');
}
}
......@@ -768,7 +768,7 @@ async function copyCell(context: INotebookCellActionContext, direction: 'up' | '
const newCellDirection = direction === 'up' ? 'above' : 'below';
const newCell = context.notebookEditor.insertNotebookCell(context.cell, context.cell.cellKind, newCellDirection, text);
if (newCell) {
context.notebookEditor.focusNotebookCell(newCell, false);
context.notebookEditor.focusNotebookCell(newCell, 'container');
}
}
......@@ -1074,7 +1074,7 @@ registerAction2(class extends Action2 {
return;
}
editor.focusNotebookCell(newCell, true);
editor.focusNotebookCell(newCell, 'editor');
}
});
......@@ -1119,10 +1119,39 @@ registerAction2(class extends Action2 {
return;
}
editor.focusNotebookCell(newCell, true);
editor.focusNotebookCell(newCell, 'editor');
}
});
registerAction2(class extends Action2 {
constructor() {
super({
id: FOCUS_OUTPUT_COMMAND_ID,
title: localize('focusOutput', 'Focus output'),
category: NOTEBOOK_ACTIONS_CATEGORY,
keybinding: {
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED),
primary: KeyMod.CtrlCmd | KeyCode.DownArrow,
weight: EDITOR_WIDGET_ACTION_WEIGHT
}
});
}
async run(accessor: ServicesAccessor, context?: INotebookCellActionContext): Promise<void> {
if (!isCellActionContext(context)) {
context = getActiveCellContext(accessor);
if (!context) {
return;
}
}
const editor = context.notebookEditor;
const activeCell = context.cell;
editor.focusNotebookCell(activeCell, 'output');
}
});
registerAction2(class extends Action2 {
constructor() {
super({
......@@ -1217,7 +1246,7 @@ registerAction2(class extends Action2 {
}
const firstCell = editor.viewModel.viewCells[0];
editor.focusNotebookCell(firstCell, false);
editor.focusNotebookCell(firstCell, 'container');
}
});
......@@ -1251,7 +1280,7 @@ registerAction2(class extends Action2 {
}
const firstCell = editor.viewModel.viewCells[editor.viewModel.length - 1];
editor.focusNotebookCell(firstCell, false);
editor.focusNotebookCell(firstCell, 'container');
}
});
......@@ -1366,7 +1395,7 @@ export class ChangeCellLanguageAction extends Action2 {
if (selection.languageId === 'markdown' && context.cell?.language !== 'markdown') {
const newCell = await changeCellToKind(CellKind.Markdown, { cell: context.cell, notebookEditor: context.notebookEditor });
if (newCell) {
context.notebookEditor.focusNotebookCell(newCell, true);
context.notebookEditor.focusNotebookCell(newCell, 'editor');
}
} else if (selection.languageId !== 'markdown' && context.cell?.language === 'markdown') {
await changeCellToKind(CellKind.Code, { cell: context.cell, notebookEditor: context.notebookEditor }, selection.languageId);
......@@ -1435,7 +1464,7 @@ async function splitCell(context: INotebookCellActionContext): Promise<void> {
if (context.cell.cellKind === CellKind.Code) {
const newCells = await context.notebookEditor.splitNotebookCell(context.cell);
if (newCells) {
context.notebookEditor.focusNotebookCell(newCells[newCells.length - 1], true);
context.notebookEditor.focusNotebookCell(newCells[newCells.length - 1], 'editor');
}
}
}
......@@ -1473,7 +1502,7 @@ registerAction2(class extends Action2 {
async function joinCells(context: INotebookCellActionContext, direction: 'above' | 'below'): Promise<void> {
const cell = await context.notebookEditor.joinNotebookCells(context.cell, direction, CellKind.Code);
if (cell) {
context.notebookEditor.focusNotebookCell(cell, true);
context.notebookEditor.focusNotebookCell(cell, 'editor');
}
}
......
......@@ -15,10 +15,10 @@ import { ScrollEvent } from 'vs/base/common/scrollable';
import { URI } from 'vs/base/common/uri';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { Range } from 'vs/editor/common/core/range';
import { IPosition } from 'vs/editor/common/core/position';
import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { Range } from 'vs/editor/common/core/range';
import { FindMatch, IReadonlyTextBuffer, ITextModel } from 'vs/editor/common/model';
import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer';
import { CellLanguageStatusBarItem } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer';
import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
......@@ -223,7 +223,7 @@ export interface INotebookEditor {
/**
* Focus the container of a cell (the monaco editor inside is not focused).
*/
focusNotebookCell(cell: ICellViewModel, focusEditor: boolean): void;
focusNotebookCell(cell: ICellViewModel, focus: 'editor' | 'container' | 'output'): void;
/**
* Execute the given notebook cell
......
......@@ -3,19 +3,22 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/notebook';
import { getZoomLevel } from 'vs/base/browser/browser';
import * as DOM from 'vs/base/browser/dom';
import { IMouseWheelEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { Color, RGBA } from 'vs/base/common/color';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
import { DisposableStore, MutableDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
import { combinedDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
import 'vs/css!./media/notebook';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { IPosition, Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { ICompositeCodeEditor, IEditor } from 'vs/editor/common/editorCommon';
import { IReadonlyTextBuffer } from 'vs/editor/common/model';
import * as nls from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
......@@ -28,26 +31,23 @@ import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/com
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
import { EditorOptions, IEditorCloseEvent, IEditorMemento } from 'vs/workbench/common/editor';
import { CELL_MARGIN, CELL_RUN_GUTTER, EDITOR_TOP_MARGIN, EDITOR_TOP_PADDING, EDITOR_BOTTOM_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
import { CellEditState, CellFocusMode, ICellRange, ICellViewModel, INotebookCellList, INotebookEditor, INotebookEditorMouseEvent, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, INotebookEditorContribution, NOTEBOOK_EDITOR_RUNNABLE, IEditableCellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { CELL_MARGIN, CELL_RUN_GUTTER, EDITOR_BOTTOM_PADDING, EDITOR_TOP_MARGIN, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
import { CellEditState, CellFocusMode, ICellRange, ICellViewModel, IEditableCellViewModel, INotebookCellList, INotebookEditor, INotebookEditorContribution, INotebookEditorMouseEvent, NotebookLayoutInfo, NOTEBOOK_EDITOR_EDITABLE, NOTEBOOK_EDITOR_EXECUTING_NOTEBOOK, NOTEBOOK_EDITOR_FOCUSED, NOTEBOOK_EDITOR_RUNNABLE } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions';
import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookEditorInput';
import { NotebookEditorModel } from 'vs/workbench/contrib/notebook/common/notebookEditorModel';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { NotebookCellList } from 'vs/workbench/contrib/notebook/browser/view/notebookCellList';
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer';
import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView';
import { CodeCellRenderer, MarkdownCellRenderer, NotebookCellListDelegate, CellDragAndDropController } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer';
import { CellDragAndDropController, CodeCellRenderer, MarkdownCellRenderer, NotebookCellListDelegate } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
import { CellViewModel, IModelDecorationsChangeAccessor, INotebookEditorViewState, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { CellKind, CellUri, IOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookEditorModel } from 'vs/workbench/contrib/notebook/common/notebookEditorModel';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils';
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IPosition, Position } from 'vs/editor/common/core/position';
import { IReadonlyTextBuffer } from 'vs/editor/common/model';
const $ = DOM.$;
const NOTEBOOK_EDITOR_VIEW_STATE_PREFERENCE_KEY = 'NotebookEditorViewState';
......@@ -1118,14 +1118,26 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
}
}
focusNotebookCell(cell: ICellViewModel, focusEditor: boolean) {
if (focusEditor) {
focusNotebookCell(cell: ICellViewModel, focusItem: 'editor' | 'container' | 'output') {
if (focusItem === 'editor') {
this.selectElement(cell);
this.list?.focusView();
cell.editState = CellEditState.Editing;
cell.focusMode = CellFocusMode.Editor;
this.revealInCenterIfOutsideViewport(cell);
} else if (focusItem === 'output') {
this.selectElement(cell);
this.list?.focusView();
if (!this.webview) {
return;
}
this.webview.focusOutput(cell.id);
cell.editState = CellEditState.Preview;
cell.focusMode = CellFocusMode.Container;
this.revealInCenterIfOutsideViewport(cell);
} else {
let itemDOM = this.list?.domElementOfElement(cell);
if (document.activeElement && itemDOM && itemDOM.contains(document.activeElement)) {
......
......@@ -4,22 +4,22 @@
*--------------------------------------------------------------------------------------------*/
import * as DOM from 'vs/base/browser/dom';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import * as path from 'vs/base/common/path';
import { isWeb } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import * as UUID from 'vs/base/common/uuid';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { CELL_MARGIN, CELL_RUN_GUTTER } from 'vs/workbench/contrib/notebook/browser/constants';
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { IOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService';
import { IWebviewService, WebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewResourceScheme } from 'vs/workbench/contrib/webview/common/resourceLoader';
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
import { CELL_MARGIN, CELL_RUN_GUTTER } from 'vs/workbench/contrib/notebook/browser/constants';
import { Emitter, Event } from 'vs/base/common/event';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { getPathFromAmdModule } from 'vs/base/common/amd';
import { isWeb } from 'vs/base/common/platform';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
export interface IDimensionMessage {
__vscode_notebook_message: boolean;
......@@ -54,10 +54,22 @@ export interface IScrollAckMessage {
version: number;
}
export interface IBlurOutputMessage {
__vscode_notebook_message: boolean;
type: 'focus-editor';
id: string;
focusNext?: boolean;
}
export interface IClearMessage {
type: 'clear';
}
export interface IFocusOutputMessage {
type: 'focus-output';
id: string;
}
export interface ICreationRequestMessage {
type: 'html';
content: string;
......@@ -93,7 +105,7 @@ export interface IUpdatePreloadResourceMessage {
resources: string[];
}
type IMessage = IDimensionMessage | IScrollAckMessage | IWheelMessage | IMouseEnterMessage | IMouseLeaveMessage;
type IMessage = IDimensionMessage | IScrollAckMessage | IWheelMessage | IMouseEnterMessage | IMouseLeaveMessage | IBlurOutputMessage;
let version = 0;
export class BackLayerWebView extends Disposable {
......@@ -108,6 +120,7 @@ export class BackLayerWebView extends Disposable {
private readonly _onMessage = this._register(new Emitter<any>());
public readonly onMessage: Event<any> = this._onMessage.event;
private _initalized: Promise<void>;
private activeCellId: string | undefined;
constructor(
......@@ -288,10 +301,23 @@ ${loaderJs}
let cellOutputContainer = document.getElementById(id);
let outputId = event.data.outputId;
if (!cellOutputContainer) {
const container = document.getElementById('container');
let upperWrapperElement = document.createElement('div');
upperWrapperElement.tabIndex = 0;
container.appendChild(upperWrapperElement);
upperWrapperElement.addEventListener('focus', () => {
vscode.postMessage({
__vscode_notebook_message: true,
type: 'focus-editor',
id: outputId,
});
});
let newElement = document.createElement('div');
newElement.id = id;
document.getElementById('container').appendChild(newElement);
container.appendChild(newElement);
cellOutputContainer = newElement;
cellOutputContainer.addEventListener('mouseenter', () => {
......@@ -310,6 +336,32 @@ ${loaderJs}
data: { }
});
});
const handleKeyDown = (event) => {
if (event.defaultPrevented || !(event.key === 'ArrowUp' && event.ctrlKey)) {
return;
}
vscode.postMessage({
__vscode_notebook_message: true,
type: 'focus-editor',
id: outputId,
});
};
cellOutputContainer.addEventListener("keydown", handleKeyDown);
let lowerWrapperElement = document.createElement('div');
lowerWrapperElement.tabIndex = 0;
container.appendChild(lowerWrapperElement);
lowerWrapperElement.addEventListener('focus', () => {
vscode.postMessage({
__vscode_notebook_message: true,
type: 'focus-editor',
id: outputId,
focusNext: true
});
});
}
let outputNode = document.createElement('div');
......@@ -384,6 +436,15 @@ ${loaderJs}
preloadsContainer.appendChild(scriptTag)
}
break;
case 'focus-output':
{
let cellOutputContainer = document.getElementById(id);
if(cellOutputContainer){
const focusableElement = cellOutputContainer.querySelector('[tabindex="0"], [href], button, input, option, select, textarea');
focusableElement && focusableElement.focus();
}
break;
}
}
});
}());
......@@ -405,6 +466,15 @@ ${loaderJs}
initialize(content: string) {
this.webview = this._createInset(this.webviewService, content);
this.webview.mountTo(this.element);
this.webview.onDidFocus(() => {
if (this.activeCellId) {
this.webview.sendMessage({
type: 'focus-output',
id: this.activeCellId
});
this.activeCellId = undefined;
}
});
this._register(this.webview.onDidClickLink(link => {
this.openerService.open(link, { fromUserGesture: true });
......@@ -445,6 +515,25 @@ ${loaderJs}
preventDefault: () => { },
stopPropagation: () => { }
});
} else if (data.type === 'focus-editor') {
const info = this.resolveOutputId(data.id);
if (info) {
if (data.focusNext) {
const idx = this.notebookEditor.viewModel?.getCellIndex(info.cell);
if (typeof idx !== 'number') {
return;
}
const newCell = this.notebookEditor.viewModel?.viewCells[idx + 1];
if (!newCell) {
return;
}
this.notebookEditor.focusNotebookCell(newCell, 'editor');
} else {
this.notebookEditor.focusNotebookCell(info.cell, 'editor');
}
}
}
return;
}
......@@ -589,6 +678,11 @@ ${loaderJs}
this.reversedInsetMapping = new Map();
}
focusOutput(cellId: string) {
this.activeCellId = cellId;
this.webview.focus();
}
updateRendererPreloads(preloads: Set<number>) {
let resources: string[] = [];
let extensionLocations: URI[] = [];
......
......@@ -3,8 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// eslint-disable-next-line code-import-patterns
import 'vs/css!vs/workbench/contrib/notebook/browser/media/notebook';
import { getZoomLevel } from 'vs/base/browser/browser';
import * as DOM from 'vs/base/browser/dom';
import { domEvent } from 'vs/base/browser/event';
......@@ -21,11 +19,14 @@ import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecyc
import { deepClone } from 'vs/base/common/objects';
import * as platform from 'vs/base/common/platform';
import { escape } from 'vs/base/common/strings';
// eslint-disable-next-line code-import-patterns
import 'vs/css!vs/workbench/contrib/notebook/browser/media/notebook';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { EditorOption, EDITOR_FONT_DEFAULTS, IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { Range } from 'vs/editor/common/core/range';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ITextModel } from 'vs/editor/common/model';
import * as modes from 'vs/editor/common/modes';
import { tokenizeLineToHTML } from 'vs/editor/common/modes/textToHtmlTokenizer';
......@@ -37,6 +38,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { BOTTOM_CELL_TOOLBAR_HEIGHT, EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_MARGIN, EDITOR_TOP_PADDING } from 'vs/workbench/contrib/notebook/browser/constants';
......@@ -50,8 +52,6 @@ import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewMod
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { CellKind, NotebookCellRunState } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
const $ = DOM.$;
......@@ -586,14 +586,14 @@ export class CellDragAndDropController extends Disposable {
private moveCell(draggedCell: ICellViewModel, ontoCell: ICellViewModel, direction: 'above' | 'below') {
const editState = draggedCell.editState;
this.notebookEditor.moveCell(draggedCell, ontoCell, direction);
this.notebookEditor.focusNotebookCell(draggedCell, editState === CellEditState.Editing);
this.notebookEditor.focusNotebookCell(draggedCell, editState === CellEditState.Editing ? 'editor' : 'container');
}
private copyCell(draggedCell: ICellViewModel, ontoCell: ICellViewModel, direction: 'above' | 'below') {
const editState = draggedCell.editState;
const newCell = this.notebookEditor.insertNotebookCell(ontoCell, draggedCell.cellKind, direction, draggedCell.getText());
if (newCell) {
this.notebookEditor.focusNotebookCell(newCell, editState === CellEditState.Editing);
this.notebookEditor.focusNotebookCell(newCell, editState === CellEditState.Editing ? 'editor' : 'container');
}
}
......
......@@ -3,24 +3,24 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { URI } from 'vs/base/common/uri';
import { CellKind, IOutput, CellUri, NotebookCellMetadata, INotebookEditorModel } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { NotebookViewModel, IModelDecorationsChangeAccessor, CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotebookEditor, NotebookLayoutInfo, ICellViewModel, ICellRange, INotebookEditorMouseEvent, INotebookEditorContribution } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer';
import { Emitter, Event } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { Range } from 'vs/editor/common/core/range';
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { EditorModel } from 'vs/workbench/common/editor';
import { ICellRange, ICellViewModel, INotebookEditor, INotebookEditorContribution, INotebookEditorMouseEvent, NotebookLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer';
import { NotebookEventDispatcher } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
import { CellViewModel, IModelDecorationsChangeAccessor, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel';
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
import { CellKind, CellUri, INotebookEditorModel, IOutput, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
import { Webview } from 'vs/workbench/contrib/webview/browser/webview';
import { IDisposable } from 'vs/base/common/lifecycle';
import { Emitter, Event } from 'vs/base/common/event';
import { EditorModel } from 'vs/workbench/common/editor';
export class TestCell extends NotebookCellTextModel {
constructor(
public viewType: string,
......@@ -171,7 +171,7 @@ export class TestNotebookEditor implements INotebookEditor {
saveNotebookCell(cell: CellViewModel): void {
// throw new Error('Method not implemented.');
}
focusNotebookCell(cell: CellViewModel, focusEditor: boolean): void {
focusNotebookCell(cell: CellViewModel, focusItem: 'editor' | 'container' | 'output'): void {
// throw new Error('Method not implemented.');
}
getActiveCell(): CellViewModel | undefined {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册