mirror of
https://github.com/microsoft/vscode.git
synced 2026-08-19 14:22:19 +01:00
Merge branch 'main' into sandy081/logLevel
This commit is contained in:
@@ -2070,11 +2070,12 @@ export class CommandCenter {
|
||||
await this.cleanAll(repository);
|
||||
await item.run(opts);
|
||||
} else if (choice === stash || choice === migrate) {
|
||||
await this.stash(repository);
|
||||
await item.run(opts);
|
||||
if (await this._stash(repository)) {
|
||||
await item.run(opts);
|
||||
|
||||
if (choice === migrate) {
|
||||
await this.stashPopLatest(repository);
|
||||
if (choice === migrate) {
|
||||
await this.stashPopLatest(repository);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2982,7 +2983,7 @@ export class CommandCenter {
|
||||
await commands.executeCommand('revealFileInOS', resourceState.resourceUri);
|
||||
}
|
||||
|
||||
private async _stash(repository: Repository, includeUntracked = false, staged = false): Promise<void> {
|
||||
private async _stash(repository: Repository, includeUntracked = false, staged = false): Promise<boolean> {
|
||||
const noUnstagedChanges = repository.workingTreeGroup.resourceStates.length === 0
|
||||
&& (!includeUntracked || repository.untrackedGroup.resourceStates.length === 0);
|
||||
const noStagedChanges = repository.indexGroup.resourceStates.length === 0;
|
||||
@@ -2990,12 +2991,12 @@ export class CommandCenter {
|
||||
if (staged) {
|
||||
if (noStagedChanges) {
|
||||
window.showInformationMessage(l10n.t('There are no staged changes to stash.'));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (noUnstagedChanges && noStagedChanges) {
|
||||
window.showInformationMessage(l10n.t('There are no changes to stash.'));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3022,7 +3023,7 @@ export class CommandCenter {
|
||||
if (pick === saveAndStash) {
|
||||
await Promise.all(documents.map(d => d.save()));
|
||||
} else if (pick !== stash) {
|
||||
return; // do not stash on cancel
|
||||
return false; // do not stash on cancel
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3040,15 +3041,16 @@ export class CommandCenter {
|
||||
});
|
||||
|
||||
if (typeof message === 'undefined') {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
await repository.createStash(message, includeUntracked, staged);
|
||||
return true;
|
||||
} catch (err) {
|
||||
if (/You do not have the initial commit yet/.test(err.stderr || '')) {
|
||||
window.showInformationMessage(l10n.t('The repository does not have any commits. Please make an initial commit before creating a stash.'));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
throw err;
|
||||
@@ -3056,18 +3058,18 @@ export class CommandCenter {
|
||||
}
|
||||
|
||||
@command('git.stash', { repository: true })
|
||||
stash(repository: Repository): Promise<void> {
|
||||
return this._stash(repository);
|
||||
async stash(repository: Repository): Promise<void> {
|
||||
await this._stash(repository);
|
||||
}
|
||||
|
||||
@command('git.stashStaged', { repository: true })
|
||||
stashStaged(repository: Repository): Promise<void> {
|
||||
return this._stash(repository, false, true);
|
||||
async stashStaged(repository: Repository): Promise<void> {
|
||||
await this._stash(repository, false, true);
|
||||
}
|
||||
|
||||
@command('git.stashIncludeUntracked', { repository: true })
|
||||
stashIncludeUntracked(repository: Repository): Promise<void> {
|
||||
return this._stash(repository, true);
|
||||
async stashIncludeUntracked(repository: Repository): Promise<void> {
|
||||
await this._stash(repository, true);
|
||||
}
|
||||
|
||||
@command('git.stashPop', { repository: true })
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
"name": "Dark+ (Experimental)",
|
||||
"include": "./dark_plus.json",
|
||||
"colors": {
|
||||
"activityBar.activeBorder": "#2488d8",
|
||||
"activityBar.activeBorder": "#0078d4",
|
||||
"activityBar.background": "#181818",
|
||||
"activityBar.border": "#ffffff15",
|
||||
"activityBar.foreground": "#ffffffc5",
|
||||
"activityBar.inactiveForeground": "#ffffff80",
|
||||
"activityBarBadge.background": "#2488d8",
|
||||
"activityBarBadge.foreground": "#000000",
|
||||
"badge.background": "#2488d8",
|
||||
"activityBarBadge.background": "#0078d4",
|
||||
"activityBarBadge.foreground": "#ffffff",
|
||||
"badge.background": "#0078d4",
|
||||
"badge.foreground": "#000000",
|
||||
"button.background": "#2488d8",
|
||||
"button.background": "#0078d4",
|
||||
"button.border": "#ffffff12",
|
||||
"button.foreground": "#000000",
|
||||
"button.hoverBackground": "#2488d8e6",
|
||||
"button.foreground": "#ffffff",
|
||||
"button.hoverBackground": "#0078d4e6",
|
||||
"button.secondaryBackground": "#FFFFFF0F",
|
||||
"button.secondaryForeground": "#ffffffc5",
|
||||
"button.secondaryHoverBackground": "#ffffff15",
|
||||
@@ -34,13 +34,13 @@
|
||||
"editor.background": "#1f1f1f",
|
||||
"editor.findMatchBackground": "#9e6a03",
|
||||
"editor.foreground": "#ffffffd3",
|
||||
"editorCursor.foreground": "#2488d8",
|
||||
"editorCursor.foreground": "#0078d4",
|
||||
"editorGroup.border": "#ffffff17",
|
||||
"editorGroupHeader.tabsBackground": "#181818",
|
||||
"editorGroupHeader.tabsBorder": "#ffffff15",
|
||||
"editorGutter.addedBackground": "#2ea043",
|
||||
"editorGutter.deletedBackground": "#f85149",
|
||||
"editorGutter.modifiedBackground": "#2488d8",
|
||||
"editorGutter.modifiedBackground": "#0078d4",
|
||||
"editorInlayHint.background": "#8b949e33",
|
||||
"editorInlayHint.foreground": "#8b949e",
|
||||
"editorInlayHint.typeBackground": "#8b949e33",
|
||||
@@ -50,7 +50,7 @@
|
||||
"editorOverviewRuler.border": "#010409",
|
||||
"editorWidget.background": "#1f1f1f",
|
||||
"errorForeground": "#f85149",
|
||||
"focusBorder": "#2488d8",
|
||||
"focusBorder": "#0078d4",
|
||||
"foreground": "#ffffffc5",
|
||||
"icon.foreground": "#ffffffc5",
|
||||
"input.background": "#ffffff0f",
|
||||
@@ -72,7 +72,7 @@
|
||||
"panel.background": "#181818",
|
||||
"panel.border": "#ffffff15",
|
||||
"panelInput.border": "#ffffff15",
|
||||
"panelTitle.activeBorder": "#2488d8",
|
||||
"panelTitle.activeBorder": "#0078d4",
|
||||
"panelTitle.activeForeground": "#ffffffc5",
|
||||
"panelTitle.inactiveForeground": "#8b949e",
|
||||
"peekViewEditor.background": "#1f1f1f",
|
||||
@@ -81,7 +81,7 @@
|
||||
"peekViewResult.matchHighlightBackground": "#bb800966",
|
||||
"pickerGroup.border": "#ffffff15",
|
||||
"pickerGroup.foreground": "#8b949e",
|
||||
"progressBar.background": "#2488d8",
|
||||
"progressBar.background": "#0078d4",
|
||||
"quickInput.background": "#1f1f1f",
|
||||
"quickInput.foreground": "#ffffffc5",
|
||||
"scrollbar.shadow": "#484f5833",
|
||||
@@ -101,17 +101,17 @@
|
||||
"sideBarTitle.foreground": "#ffffffc5",
|
||||
"statusBar.background": "#181818",
|
||||
"statusBar.border": "#ffffff15",
|
||||
"statusBar.debuggingBackground": "#fd716c",
|
||||
"statusBar.debuggingForeground": "#000000",
|
||||
"statusBar.debuggingBackground": "#0078d4",
|
||||
"statusBar.debuggingForeground": "#ffffff",
|
||||
"statusBar.foreground": "#ffffffc5",
|
||||
"statusBar.noFolderBackground": "#1f1f1f",
|
||||
"statusBarItem.focusBorder": "#2488d8",
|
||||
"statusBarItem.focusBorder": "#0078d4",
|
||||
"statusBarItem.prominentBackground": "#6e768166",
|
||||
"statusBarItem.remoteBackground": "#2488d8",
|
||||
"statusBarItem.remoteForeground": "#000000",
|
||||
"statusBarItem.remoteBackground": "#0078d4",
|
||||
"statusBarItem.remoteForeground": "#ffffff",
|
||||
"tab.activeBackground": "#1f1f1f",
|
||||
"tab.activeBorder": "#1f1f1f",
|
||||
"tab.activeBorderTop": "#2488d8",
|
||||
"tab.activeBorderTop": "#0078d4",
|
||||
"tab.activeForeground": "#ffffffc5",
|
||||
"tab.border": "#ffffff15",
|
||||
"tab.hoverBackground": "#1f1f1f",
|
||||
@@ -121,12 +121,12 @@
|
||||
"tab.unfocusedActiveBorderTop": "#ffffff15",
|
||||
"tab.unfocusedHoverBackground": "#6e76811a",
|
||||
"terminal.foreground": "#ffffffc5",
|
||||
"terminal.tab.activeBorder": "#2488d8",
|
||||
"terminal.tab.activeBorder": "#0078d4",
|
||||
"textBlockQuote.background": "#010409",
|
||||
"textBlockQuote.border": "#ffffff14",
|
||||
"textCodeBlock.background": "#6e768166",
|
||||
"textLink.activeForeground": "#8bb6f7",
|
||||
"textLink.foreground": "#8bb6f7",
|
||||
"textLink.activeForeground": "#40A6FF",
|
||||
"textLink.foreground": "#40A6FF",
|
||||
"textPreformat.foreground": "#8b949e",
|
||||
"textSeparator.foreground": "#21262d",
|
||||
"titleBar.activeBackground": "#181818",
|
||||
@@ -135,6 +135,7 @@
|
||||
"titleBar.inactiveBackground": "#1f1f1f",
|
||||
"titleBar.inactiveForeground": "#8b949e",
|
||||
"welcomePage.tileBackground": "#ffffff0f",
|
||||
"welcomePage.progress.foreground": "#0078d4",
|
||||
"widgetBorder": "#ffffff15",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -400,12 +400,6 @@
|
||||
"description": "%configuration.suggest.includeCompletionsForImportStatements%",
|
||||
"scope": "resource"
|
||||
},
|
||||
"typescript.suggest.includeCompletionsWithSnippetText": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "%configuration.suggest.includeCompletionsWithSnippetText%",
|
||||
"scope": "resource"
|
||||
},
|
||||
"typescript.reportStyleChecksAsWarnings": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
"configuration.suggest.completeFunctionCalls": "Complete functions with their parameter signature.",
|
||||
"configuration.suggest.includeAutomaticOptionalChainCompletions": "Enable/disable showing completions on potentially undefined values that insert an optional chain call. Requires strict null checks to be enabled.",
|
||||
"configuration.suggest.includeCompletionsForImportStatements": "Enable/disable auto-import-style completions on partially-typed import statements.",
|
||||
"configuration.suggest.includeCompletionsWithSnippetText": "Enable/disable snippet completions from TS Server.",
|
||||
"typescript.tsdk.desc": "Specifies the folder path to the tsserver and `lib*.d.ts` files under a TypeScript install to use for IntelliSense, for example: `./node_modules/typescript/lib`.\n\n- When specified as a user setting, the TypeScript version from `typescript.tsdk` automatically replaces the built-in TypeScript version.\n- When specified as a workspace setting, `typescript.tsdk` allows you to switch to use that workspace version of TypeScript for IntelliSense with the `TypeScript: Select TypeScript version` command.\n\nSee the [TypeScript documentation](https://code.visualstudio.com/docs/typescript/typescript-compiling#_using-newer-typescript-versions) for more detail about managing TypeScript versions.",
|
||||
"typescript.disableAutomaticTypeAcquisition": "Disables [automatic type acquisition](https://code.visualstudio.com/docs/nodejs/working-with-javascript#_typings-and-automatic-type-acquisition). Automatic type acquisition fetches `@types` packages from npm to improve IntelliSense for external libraries.",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": "Enables prompting of users to use the TypeScript version configured in the workspace for Intellisense.",
|
||||
|
||||
+1
-1
@@ -186,7 +186,7 @@ export default class FileConfigurationManager extends Disposable {
|
||||
provideRefactorNotApplicableReason: true,
|
||||
generateReturnInDocTemplate: config.get<boolean>('suggest.jsdoc.generateReturns', true),
|
||||
includeCompletionsForImportStatements: config.get<boolean>('suggest.includeCompletionsForImportStatements', true),
|
||||
includeCompletionsWithSnippetText: config.get<boolean>('suggest.includeCompletionsWithSnippetText', true),
|
||||
includeCompletionsWithSnippetText: true,
|
||||
includeCompletionsWithClassMemberSnippets: config.get<boolean>('suggest.classMemberSnippets.enabled', true),
|
||||
includeCompletionsWithObjectLiteralMethodSnippets: config.get<boolean>('suggest.objectLiteralMethodSnippets.enabled', true),
|
||||
autoImportFileExcludePatterns: this.getAutoImportFileExcludePatternsPreference(preferencesConfig, vscode.workspace.getWorkspaceFolder(document.uri)?.uri),
|
||||
|
||||
@@ -4891,7 +4891,7 @@ export const enum EditorOption {
|
||||
export const EditorOptions = {
|
||||
acceptSuggestionOnCommitCharacter: register(new EditorBooleanOption(
|
||||
EditorOption.acceptSuggestionOnCommitCharacter, 'acceptSuggestionOnCommitCharacter', true,
|
||||
{ markdownDescription: nls.localize('acceptSuggestionOnCommitCharacter', "Controls whether suggestions should be accepted on commit characters. For example, in JavaScript, the semi-colon (`; `) can be a commit character that accepts a suggestion and types that character.") }
|
||||
{ markdownDescription: nls.localize('acceptSuggestionOnCommitCharacter', "Controls whether suggestions should be accepted on commit characters. For example, in JavaScript, the semi-colon (`;`) can be a commit character that accepts a suggestion and types that character.") }
|
||||
)),
|
||||
acceptSuggestionOnEnter: register(new EditorStringEnumOption(
|
||||
EditorOption.acceptSuggestionOnEnter, 'acceptSuggestionOnEnter',
|
||||
|
||||
@@ -48,6 +48,8 @@ class PersistedMenuHideState {
|
||||
private _ignoreChangeEvent: boolean = false;
|
||||
private _data: Record<string, string[] | undefined>;
|
||||
|
||||
private _hiddenByDefaultCache = new Map<string, boolean>();
|
||||
|
||||
constructor(@IStorageService private readonly _storageService: IStorageService) {
|
||||
try {
|
||||
const raw = _storageService.get(PersistedMenuHideState._key, StorageScope.PROFILE, '{}');
|
||||
@@ -78,14 +80,11 @@ class PersistedMenuHideState {
|
||||
}
|
||||
|
||||
private _isHiddenByDefault(menu: MenuId, commandId: string) {
|
||||
let hiddenByDefault = false;
|
||||
for (const item of MenuRegistry.getMenuItems(menu)) {
|
||||
if (isIMenuItem(item) && item.command.id === commandId) {
|
||||
hiddenByDefault = Boolean(item.isHiddenByDefault);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hiddenByDefault;
|
||||
return this._hiddenByDefaultCache.get(`${menu.id}/${commandId}`) ?? false;
|
||||
}
|
||||
|
||||
setDefaultState(menu: MenuId, commandId: string, hidden: boolean): void {
|
||||
this._hiddenByDefaultCache.set(`${menu.id}/${commandId}`, hidden);
|
||||
}
|
||||
|
||||
isHidden(menu: MenuId, commandId: string): boolean {
|
||||
@@ -239,6 +238,10 @@ class MenuInfo {
|
||||
for (const item of items) {
|
||||
if (this._contextKeyService.contextMatchesRules(item.when)) {
|
||||
const isMenuItem = isIMenuItem(item);
|
||||
if (isMenuItem) {
|
||||
this._hiddenStates.setDefaultState(this._id, item.command.id, !!item.isHiddenByDefault);
|
||||
}
|
||||
|
||||
const menuHide = createMenuHide(this._id, isMenuItem ? item.command : item, this._hiddenStates);
|
||||
if (isMenuItem) {
|
||||
// MenuItemAction
|
||||
|
||||
@@ -40,7 +40,7 @@ export class ExtHostLocalizationService implements ExtHostLocalizationShape {
|
||||
|
||||
let key = message;
|
||||
if (comment && comment.length > 0) {
|
||||
key += `/${Array.isArray(comment) ? comment.join() : comment}`;
|
||||
key += `/${Array.isArray(comment) ? comment.join('') : comment}`;
|
||||
}
|
||||
const str = this.bundleCache.get(extensionId)?.contents[key];
|
||||
if (!str) {
|
||||
|
||||
+26
-24
@@ -57,31 +57,33 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
|
||||
|
||||
private onDidInstallExtensions(results: readonly InstallExtensionResult[]): void {
|
||||
for (const e of results) {
|
||||
if (e.local && e.operation === InstallOperation.Install && e.local.manifest.contributes && e.local.manifest.contributes.localizations && e.local.manifest.contributes.localizations.length) {
|
||||
const locale = e.local.manifest.contributes.localizations[0].languageId;
|
||||
if (platform.language !== locale) {
|
||||
const updateAndRestart = platform.locale !== locale;
|
||||
this.notificationService.prompt(
|
||||
Severity.Info,
|
||||
updateAndRestart ? localize('updateLocale', "Would you like to change VS Code's UI language to {0} and restart?", e.local.manifest.contributes.localizations[0].languageName || e.local.manifest.contributes.localizations[0].languageId)
|
||||
: localize('activateLanguagePack', "In order to use VS Code in {0}, VS Code needs to restart.", e.local.manifest.contributes.localizations[0].languageName || e.local.manifest.contributes.localizations[0].languageId),
|
||||
[{
|
||||
label: updateAndRestart ? localize('changeAndRestart', "Change Language and Restart") : localize('restart', "Restart"),
|
||||
run: () => {
|
||||
const updatePromise = updateAndRestart ? this.jsonEditingService.write(this.environmentService.argvResource, [{ path: ['locale'], value: locale }], true) : Promise.resolve(undefined);
|
||||
updatePromise.then(() => this.hostService.restart(), e => this.notificationService.error(e));
|
||||
}
|
||||
}, {
|
||||
label: updateAndRestart ? localize('doNotChangeAndRestart', "Don't Change Language") : localize('doNotRestart', "Don't Restart"),
|
||||
run: () => { }
|
||||
}],
|
||||
{
|
||||
sticky: true,
|
||||
neverShowAgain: { id: 'langugage.update.donotask', isSecondary: true, scope: NeverShowAgainScope.APPLICATION }
|
||||
}
|
||||
);
|
||||
}
|
||||
if (e.operation !== InstallOperation.Install || !e.local?.manifest?.contributes?.localizations?.length) {
|
||||
continue;
|
||||
}
|
||||
const languageId = e.local.manifest.contributes.localizations[0].languageId;
|
||||
if (platform.language === languageId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.notificationService.prompt(
|
||||
Severity.Info,
|
||||
localize('updateLocale', "Would you like to change VS Code's UI language to {0} and restart?", e.local.manifest.contributes.localizations[0].languageName || e.local.manifest.contributes.localizations[0].languageId),
|
||||
[{
|
||||
label: localize('changeAndRestart', "Change Language and Restart"),
|
||||
run: async () => {
|
||||
try {
|
||||
await this.jsonEditingService.write(this.environmentService.argvResource, [{ path: ['locale'], value: languageId }], true);
|
||||
await this.hostService.restart();
|
||||
} catch (e) {
|
||||
this.notificationService.error(e);
|
||||
}
|
||||
}
|
||||
}],
|
||||
{
|
||||
sticky: true,
|
||||
neverShowAgain: { id: 'langugage.update.donotask', isSecondary: true, scope: NeverShowAgainScope.APPLICATION }
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -226,6 +226,7 @@ export interface ICellViewModel extends IGenericCellViewModel {
|
||||
readonly onDidChangeCellStatusBarItems: Event<void>;
|
||||
readonly onCellDecorationsChanged: Event<{ added: INotebookCellDecorationOptions[]; removed: INotebookCellDecorationOptions[] }>;
|
||||
readonly onDidChangeState: Event<CellViewModelStateChangeEvent>;
|
||||
readonly onDidChangeEditorAttachState: Event<void>;
|
||||
readonly editStateSource: string;
|
||||
readonly editorAttached: boolean;
|
||||
isInputCollapsed: boolean;
|
||||
@@ -313,6 +314,18 @@ export interface INotebookDeltaCellStatusBarItems {
|
||||
readonly items: readonly INotebookCellStatusBarItem[];
|
||||
}
|
||||
|
||||
export const enum CellRevealSyncType {
|
||||
Default = 1,
|
||||
Top = 2,
|
||||
Center = 3,
|
||||
CenterIfOutsideViewport = 4
|
||||
}
|
||||
|
||||
export enum CellRevealRangeType {
|
||||
Default = 1,
|
||||
Center = 2,
|
||||
CenterIfOutsideViewport = 3,
|
||||
}
|
||||
|
||||
export enum CellRevealType {
|
||||
NearTopIfOutsideViewport,
|
||||
|
||||
@@ -48,7 +48,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { contrastBorder, errorForeground, focusBorder, foreground, listInactiveSelectionBackground, registerColor, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground, transparent } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { EDITOR_PANE_BACKGROUND, PANEL_BORDER, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { debugIconStartForeground } from 'vs/workbench/contrib/debug/browser/debugColors';
|
||||
import { CellEditState, CellFindMatchWithIndex, CellFocusMode, CellLayoutContext, CellRevealType, IActiveNotebookEditorDelegate, IBaseCellEditorOptions, ICellOutputViewModel, ICellViewModel, ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IFocusNotebookCellOptions, IInsetRenderOutput, IModelDecorationsChangeAccessor, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorDelegate, INotebookEditorMouseEvent, INotebookEditorOptions, INotebookEditorViewState, INotebookViewCellsUpdateEvent, INotebookWebviewMessage, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellEditState, CellFindMatchWithIndex, CellFocusMode, CellLayoutContext, CellRevealRangeType, CellRevealSyncType, CellRevealType, IActiveNotebookEditorDelegate, IBaseCellEditorOptions, ICellOutputViewModel, ICellViewModel, ICommonCellInfo, IDisplayOutputLayoutUpdateRequest, IFocusNotebookCellOptions, IInsetRenderOutput, IModelDecorationsChangeAccessor, INotebookDeltaDecoration, INotebookEditor, INotebookEditorContribution, INotebookEditorContributionDescription, INotebookEditorCreationOptions, INotebookEditorDelegate, INotebookEditorMouseEvent, INotebookEditorOptions, INotebookEditorViewState, INotebookViewCellsUpdateEvent, INotebookWebviewMessage, RenderOutputType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { NotebookEditorExtensionsRegistry } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions';
|
||||
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService';
|
||||
import { notebookDebug } from 'vs/workbench/contrib/notebook/browser/notebookLogger';
|
||||
@@ -1161,9 +1161,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
|
||||
cell.focusMode = CellFocusMode.Editor;
|
||||
await this.revealLineInCenterIfOutsideViewportAsync(cell, selection.startLineNumber);
|
||||
} else if (options?.cellRevealType === CellRevealType.NearTopIfOutsideViewport) {
|
||||
await this.revealNearTopIfOutsideViewportAync(cell);
|
||||
await this._list.revealCellAsync(cell, CellRevealType.NearTopIfOutsideViewport);
|
||||
} else {
|
||||
await this.revealInCenterIfOutsideViewportAsync(cell);
|
||||
await this._list.revealCellAsync(cell, CellRevealType.CenterIfOutsideViewport);
|
||||
}
|
||||
|
||||
const editor = this._renderedEditors.get(cell)!;
|
||||
@@ -1306,8 +1306,8 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
|
||||
|
||||
this._webview = this.instantiationService.createInstance(BackLayerWebView, {
|
||||
get creationOptions() { return that.creationOptions; },
|
||||
setScrollTop(scrollTop: number) { that._listViewInfoAccessor.setScrollTop(scrollTop); },
|
||||
triggerScroll(event: IMouseWheelEvent) { that._listViewInfoAccessor.triggerScroll(event); },
|
||||
setScrollTop(scrollTop: number) { that._list.scrollTop = scrollTop; },
|
||||
triggerScroll(event: IMouseWheelEvent) { that._list.triggerScrollFromMouseWheelEvent(event); },
|
||||
getCellByInfo: that.getCellByInfo.bind(that),
|
||||
getCellById: that._getCellById.bind(that),
|
||||
toggleNotebookCellSelection: that._toggleNotebookCellSelection.bind(that),
|
||||
@@ -1950,63 +1950,55 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
|
||||
}
|
||||
|
||||
scrollToBottom() {
|
||||
this._listViewInfoAccessor.scrollToBottom();
|
||||
this._list.scrollToBottom();
|
||||
}
|
||||
|
||||
revealCellRangeInView(range: ICellRange) {
|
||||
return this._listViewInfoAccessor.revealCellRangeInView(range);
|
||||
return this._list.revealCellsInView(range);
|
||||
}
|
||||
|
||||
revealInView(cell: ICellViewModel) {
|
||||
this._listViewInfoAccessor.revealInView(cell);
|
||||
this._list.revealCell(cell, CellRevealSyncType.Default);
|
||||
}
|
||||
|
||||
revealInViewAtTop(cell: ICellViewModel) {
|
||||
this._listViewInfoAccessor.revealInViewAtTop(cell);
|
||||
}
|
||||
|
||||
revealInCenterIfOutsideViewport(cell: ICellViewModel) {
|
||||
this._listViewInfoAccessor.revealInCenterIfOutsideViewport(cell);
|
||||
}
|
||||
|
||||
async revealInCenterIfOutsideViewportAsync(cell: ICellViewModel) {
|
||||
return this._listViewInfoAccessor.revealInCenterIfOutsideViewportAsync(cell);
|
||||
this._list.revealCell(cell, CellRevealSyncType.Top);
|
||||
}
|
||||
|
||||
revealInCenter(cell: ICellViewModel) {
|
||||
this._listViewInfoAccessor.revealInCenter(cell);
|
||||
this._list.revealCell(cell, CellRevealSyncType.Center);
|
||||
}
|
||||
|
||||
revealNearTopIfOutsideViewportAync(cell: ICellViewModel) {
|
||||
return this._listViewInfoAccessor.revealNearTopIfOutsideViewportAync(cell);
|
||||
revealInCenterIfOutsideViewport(cell: ICellViewModel) {
|
||||
this._list.revealCell(cell, CellRevealSyncType.CenterIfOutsideViewport);
|
||||
}
|
||||
|
||||
async revealLineInViewAsync(cell: ICellViewModel, line: number): Promise<void> {
|
||||
return this._listViewInfoAccessor.revealLineInViewAsync(cell, line);
|
||||
return this._list.revealCellRangeAsync(cell, new Range(line, 1, line, 1), CellRevealRangeType.Default);
|
||||
}
|
||||
|
||||
async revealLineInCenterAsync(cell: ICellViewModel, line: number): Promise<void> {
|
||||
return this._listViewInfoAccessor.revealLineInCenterAsync(cell, line);
|
||||
return this._list.revealCellRangeAsync(cell, new Range(line, 1, line, 1), CellRevealRangeType.Center);
|
||||
}
|
||||
|
||||
async revealLineInCenterIfOutsideViewportAsync(cell: ICellViewModel, line: number): Promise<void> {
|
||||
return this._listViewInfoAccessor.revealLineInCenterIfOutsideViewportAsync(cell, line);
|
||||
return this._list.revealCellRangeAsync(cell, new Range(line, 1, line, 1), CellRevealRangeType.CenterIfOutsideViewport);
|
||||
}
|
||||
|
||||
async revealRangeInViewAsync(cell: ICellViewModel, range: Range): Promise<void> {
|
||||
return this._listViewInfoAccessor.revealRangeInViewAsync(cell, range);
|
||||
return this._list.revealCellRangeAsync(cell, range, CellRevealRangeType.Default);
|
||||
}
|
||||
|
||||
async revealRangeInCenterAsync(cell: ICellViewModel, range: Range): Promise<void> {
|
||||
return this._listViewInfoAccessor.revealRangeInCenterAsync(cell, range);
|
||||
return this._list.revealCellRangeAsync(cell, range, CellRevealRangeType.Center);
|
||||
}
|
||||
|
||||
async revealRangeInCenterIfOutsideViewportAsync(cell: ICellViewModel, range: Range): Promise<void> {
|
||||
return this._listViewInfoAccessor.revealRangeInCenterIfOutsideViewportAsync(cell, range);
|
||||
return this._list.revealCellRangeAsync(cell, range, CellRevealRangeType.CenterIfOutsideViewport);
|
||||
}
|
||||
|
||||
async revealCellOffsetInCenterAsync(cell: ICellViewModel, offset: number): Promise<void> {
|
||||
return this._listViewInfoAccessor.revealCellOffsetInCenterAsync(cell, offset);
|
||||
return this._list.revealCellOffsetInCenterAsync(cell, offset);
|
||||
}
|
||||
|
||||
getViewIndexByModelIndex(index: number): number {
|
||||
@@ -2038,11 +2030,11 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditorD
|
||||
}
|
||||
|
||||
setCellEditorSelection(cell: ICellViewModel, range: Range): void {
|
||||
this._listViewInfoAccessor.setCellEditorSelection(cell, range);
|
||||
this._list.setCellEditorSelection(cell, range);
|
||||
}
|
||||
|
||||
setHiddenAreas(_ranges: ICellRange[]): boolean {
|
||||
return this._listViewInfoAccessor.setHiddenAreas(_ranges);
|
||||
return this._list.setHiddenAreas(_ranges, true);
|
||||
}
|
||||
|
||||
getVisibleRangesPlusViewportAboveAndBelow(): ICellRange[] {
|
||||
|
||||
@@ -18,7 +18,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IListService, IWorkbenchListOptions, WorkbenchList } from 'vs/platform/list/browser/listService';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { CursorAtBoundary, ICellViewModel, CellEditState, CellFocusMode, ICellOutputViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CursorAtBoundary, ICellViewModel, CellEditState, CellFocusMode, ICellOutputViewModel, CellRevealType, CellRevealSyncType, CellRevealRangeType } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellViewModel, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModelImpl';
|
||||
import { diff, NOTEBOOK_EDITOR_CURSOR_BOUNDARY, CellKind, SelectionStateType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { ICellRange, cellRangesToIndexes, reduceCellRanges, cellRangesEqual } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
@@ -31,7 +31,7 @@ import { FastDomNode } from 'vs/base/browser/fastDomNode';
|
||||
import { MarkupCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markupCellViewModel';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
const enum CellRevealType {
|
||||
const enum CellEditorRevealType {
|
||||
Line,
|
||||
Range
|
||||
}
|
||||
@@ -222,7 +222,11 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
|
||||
|
||||
if (focus && focus.cellKind === CellKind.Markup && !focus.isInputCollapsed && !this._viewModel?.options.isReadOnly) {
|
||||
// scroll the cell into view if out of viewport
|
||||
this.revealElementInView(focus);
|
||||
const focusedCellIndex = this._getViewIndexUpperBound(focus);
|
||||
|
||||
if (focusedCellIndex >= 0) {
|
||||
this._revealInViewWithMinimalScrolling(focusedCellIndex);
|
||||
}
|
||||
focus.updateEditState(CellEditState.Editing, 'dbclick');
|
||||
focus.focusMode = CellFocusMode.Editor;
|
||||
}
|
||||
@@ -735,7 +739,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
|
||||
/**
|
||||
* The range will be revealed with as little scrolling as possible.
|
||||
*/
|
||||
revealElementsInView(range: ICellRange) {
|
||||
revealCellsInView(range: ICellRange) {
|
||||
const startIndex = this._getViewIndexUpperBound2(range.start);
|
||||
|
||||
if (startIndex < 0) {
|
||||
@@ -776,24 +780,16 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this._revealInView(startIndex);
|
||||
this._revealInViewWithMinimalScrolling(startIndex);
|
||||
}
|
||||
|
||||
isScrolledToBottom() {
|
||||
if (this.length === 0) {
|
||||
return true;
|
||||
private _revealInViewWithMinimalScrolling(viewIndex: number) {
|
||||
const firstIndex = this.view.firstVisibleIndex;
|
||||
if (viewIndex <= firstIndex) {
|
||||
this._revealInternal(viewIndex, true, CellRevealPosition.Top);
|
||||
} else {
|
||||
this._revealInternal(viewIndex, true, CellRevealPosition.Bottom);
|
||||
}
|
||||
|
||||
const last = this.length - 1;
|
||||
const bottom = this.view.elementHeight(last) + this.view.elementTop(last);
|
||||
const wrapperBottom = this.getViewScrollTop() + this.view.renderHeight;
|
||||
|
||||
if (bottom <= wrapperBottom) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
scrollToBottom() {
|
||||
@@ -805,109 +801,292 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
|
||||
this.view.setScrollTop(scrollHeight - (wrapperBottom - scrollTop) - topInsertToolbarHeight);
|
||||
}
|
||||
|
||||
revealElementInView(cell: ICellViewModel) {
|
||||
//#region Reveal Cell synchronously
|
||||
revealCell(cell: ICellViewModel, revealType: CellRevealSyncType) {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
|
||||
if (index >= 0) {
|
||||
this._revealInView(index);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (revealType) {
|
||||
case CellRevealSyncType.Top:
|
||||
this._revealInternal(index, false, CellRevealPosition.Top);
|
||||
break;
|
||||
case CellRevealSyncType.Center:
|
||||
this._revealInternal(index, false, CellRevealPosition.Center);
|
||||
break;
|
||||
case CellRevealSyncType.CenterIfOutsideViewport:
|
||||
this._revealInternal(index, true, CellRevealPosition.Center);
|
||||
break;
|
||||
case CellRevealSyncType.Default:
|
||||
this._revealInViewWithMinimalScrolling(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
revealElementInViewAtTop(cell: ICellViewModel) {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
private _revealInternal(viewIndex: number, ignoreIfInsideViewport: boolean, revealPosition: CellRevealPosition) {
|
||||
if (viewIndex >= this.view.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (index >= 0) {
|
||||
this._revealInternal(index, false, CellRevealPosition.Top);
|
||||
const scrollTop = this.getViewScrollTop();
|
||||
const wrapperBottom = this.getViewScrollBottom();
|
||||
const elementTop = this.view.elementTop(viewIndex);
|
||||
const elementBottom = this.view.elementHeight(viewIndex) + elementTop;
|
||||
|
||||
if (ignoreIfInsideViewport
|
||||
&& elementTop >= scrollTop
|
||||
&& elementBottom < wrapperBottom) {
|
||||
|
||||
if (revealPosition === CellRevealPosition.Center
|
||||
&& elementBottom > wrapperBottom
|
||||
&& elementTop > (scrollTop + wrapperBottom) / 2) {
|
||||
// the element is partially visible and it's below the center of the viewport
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (revealPosition) {
|
||||
case CellRevealPosition.Top:
|
||||
this.view.setScrollTop(elementTop);
|
||||
this.view.setScrollTop(this.view.elementTop(viewIndex));
|
||||
break;
|
||||
case CellRevealPosition.Center:
|
||||
case CellRevealPosition.NearTop:
|
||||
{
|
||||
// reveal the cell top in the viewport center initially
|
||||
this.view.setScrollTop(elementTop - this.view.renderHeight / 2);
|
||||
// cell rendered already, we now have a more accurate cell height
|
||||
const newElementTop = this.view.elementTop(viewIndex);
|
||||
const newElementHeight = this.view.elementHeight(viewIndex);
|
||||
const renderHeight = this.getViewScrollBottom() - this.getViewScrollTop();
|
||||
if (newElementHeight >= renderHeight) {
|
||||
// cell is larger than viewport, reveal top
|
||||
this.view.setScrollTop(newElementTop);
|
||||
} else if (revealPosition === CellRevealPosition.Center) {
|
||||
this.view.setScrollTop(newElementTop + (newElementHeight / 2) - (renderHeight / 2));
|
||||
} else if (revealPosition === CellRevealPosition.NearTop) {
|
||||
this.view.setScrollTop(newElementTop - (renderHeight / 5));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CellRevealPosition.Bottom:
|
||||
this.view.setScrollTop(this.scrollTop + (elementBottom - wrapperBottom));
|
||||
this.view.setScrollTop(this.scrollTop + (this.view.elementTop(viewIndex) + this.view.elementHeight(viewIndex) - this.getViewScrollBottom()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
revealElementInCenterIfOutsideViewport(cell: ICellViewModel) {
|
||||
//#endregion
|
||||
|
||||
//#region Reveal Cell asynchronously
|
||||
async revealCellAsync(cell: ICellViewModel, revealType: CellRevealType) {
|
||||
const viewIndex = this._getViewIndexUpperBound(cell);
|
||||
|
||||
if (viewIndex < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const revealPosition = revealType === CellRevealType.NearTopIfOutsideViewport ? CellRevealPosition.NearTop : CellRevealPosition.Center;
|
||||
this._revealInternal(viewIndex, true, revealPosition);
|
||||
|
||||
// wait for the editor to be created only if the cell is in editing mode (meaning it has an editor and will focus the editor)
|
||||
if (cell.getEditState() === CellEditState.Editing && !cell.editorAttached) {
|
||||
return getEditorAttachedPromise(cell);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Reveal Cell Editor Range asynchronously
|
||||
async revealCellRangeAsync(cell: ICellViewModel, range: Range, revealType: CellRevealRangeType): Promise<void> {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
|
||||
if (index >= 0) {
|
||||
this._revealInCenterIfOutsideViewport(index);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (revealType) {
|
||||
case CellRevealRangeType.Default:
|
||||
return this._revealRangeInternalAsync(index, range, CellEditorRevealType.Range);
|
||||
case CellRevealRangeType.Center:
|
||||
return this._revealRangeInCenterInternalAsync(index, range, CellEditorRevealType.Range);
|
||||
case CellRevealRangeType.CenterIfOutsideViewport:
|
||||
return this._revealRangeInCenterIfOutsideViewportInternalAsync(index, range, CellEditorRevealType.Range);
|
||||
}
|
||||
}
|
||||
|
||||
revealElementInCenter(cell: ICellViewModel) {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
// List items have real dynamic heights, which means after we set `scrollTop` based on the `elementTop(index)`, the element at `index` might still be removed from the view once all relayouting tasks are done.
|
||||
// For example, we scroll item 10 into the view upwards, in the first round, items 7, 8, 9, 10 are all in the viewport. Then item 7 and 8 resize themselves to be larger and finally item 10 is removed from the view.
|
||||
// To ensure that item 10 is always there, we need to scroll item 10 to the top edge of the viewport.
|
||||
private async _revealRangeInternalAsync(viewIndex: number, range: Range, revealType: CellEditorRevealType): Promise<void> {
|
||||
const scrollTop = this.getViewScrollTop();
|
||||
const wrapperBottom = this.getViewScrollBottom();
|
||||
const elementTop = this.view.elementTop(viewIndex);
|
||||
const element = this.view.element(viewIndex);
|
||||
|
||||
if (index >= 0) {
|
||||
this._revealInCenter(index);
|
||||
if (element.editorAttached) {
|
||||
this._revealRangeCommon(viewIndex, range, revealType, false, false);
|
||||
} else {
|
||||
const elementHeight = this.view.elementHeight(viewIndex);
|
||||
let upwards = false;
|
||||
|
||||
if (elementTop + elementHeight < scrollTop) {
|
||||
// scroll downwards
|
||||
this.view.setScrollTop(elementTop);
|
||||
upwards = false;
|
||||
} else if (elementTop > wrapperBottom) {
|
||||
// scroll upwards
|
||||
this.view.setScrollTop(elementTop - this.view.renderHeight / 2);
|
||||
upwards = true;
|
||||
}
|
||||
|
||||
const editorAttachedPromise = new Promise<void>((resolve, reject) => {
|
||||
element.onDidChangeEditorAttachState(() => {
|
||||
element.editorAttached ? resolve() : reject();
|
||||
});
|
||||
});
|
||||
|
||||
return editorAttachedPromise.then(() => {
|
||||
this._revealRangeCommon(viewIndex, range, revealType, true, upwards);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async revealElementInCenterIfOutsideViewportAsync(cell: ICellViewModel): Promise<void> {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
private async _revealRangeInCenterInternalAsync(viewIndex: number, range: Range, revealType: CellEditorRevealType): Promise<void> {
|
||||
const reveal = (viewIndex: number, range: Range, revealType: CellEditorRevealType) => {
|
||||
const element = this.view.element(viewIndex);
|
||||
const positionOffset = element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
|
||||
const positionOffsetInView = this.view.elementTop(viewIndex) + positionOffset;
|
||||
this.view.setScrollTop(positionOffsetInView - this.view.renderHeight / 2);
|
||||
|
||||
if (index >= 0) {
|
||||
return this._revealIfOutsideViewportAsync(index, CellRevealPosition.Center);
|
||||
if (revealType === CellEditorRevealType.Range) {
|
||||
element.revealRangeInCenter(range);
|
||||
}
|
||||
};
|
||||
|
||||
const elementTop = this.view.elementTop(viewIndex);
|
||||
const viewItemOffset = elementTop;
|
||||
this.view.setScrollTop(viewItemOffset - this.view.renderHeight / 2);
|
||||
const element = this.view.element(viewIndex);
|
||||
|
||||
if (!element.editorAttached) {
|
||||
return getEditorAttachedPromise(element).then(() => reveal(viewIndex, range, revealType));
|
||||
} else {
|
||||
reveal(viewIndex, range, revealType);
|
||||
}
|
||||
}
|
||||
|
||||
async revealNearTopIfOutsideViewportAync(cell: ICellViewModel): Promise<void> {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
private async _revealRangeInCenterIfOutsideViewportInternalAsync(viewIndex: number, range: Range, revealType: CellEditorRevealType): Promise<void> {
|
||||
const reveal = (viewIndex: number, range: Range, revealType: CellEditorRevealType) => {
|
||||
const element = this.view.element(viewIndex);
|
||||
const positionOffset = element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
|
||||
const positionOffsetInView = this.view.elementTop(viewIndex) + positionOffset;
|
||||
this.view.setScrollTop(positionOffsetInView - this.view.renderHeight / 2);
|
||||
|
||||
if (index >= 0) {
|
||||
return this._revealIfOutsideViewportAsync(index, CellRevealPosition.NearTop);
|
||||
if (revealType === CellEditorRevealType.Range) {
|
||||
element.revealRangeInCenter(range);
|
||||
}
|
||||
};
|
||||
|
||||
const scrollTop = this.getViewScrollTop();
|
||||
const wrapperBottom = this.getViewScrollBottom();
|
||||
const elementTop = this.view.elementTop(viewIndex);
|
||||
const viewItemOffset = elementTop;
|
||||
const element = this.view.element(viewIndex);
|
||||
const positionOffset = viewItemOffset + element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
|
||||
|
||||
if (positionOffset < scrollTop || positionOffset > wrapperBottom) {
|
||||
// let it render
|
||||
this.view.setScrollTop(positionOffset - this.view.renderHeight / 2);
|
||||
|
||||
// after rendering, it might be pushed down due to markdown cell dynamic height
|
||||
const newPositionOffset = this.view.elementTop(viewIndex) + element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
|
||||
this.view.setScrollTop(newPositionOffset - this.view.renderHeight / 2);
|
||||
|
||||
// reveal editor
|
||||
if (!element.editorAttached) {
|
||||
return getEditorAttachedPromise(element).then(() => reveal(viewIndex, range, revealType));
|
||||
} else {
|
||||
// for example markdown
|
||||
}
|
||||
} else {
|
||||
if (element.editorAttached) {
|
||||
element.revealRangeInCenter(range);
|
||||
} else {
|
||||
// for example, markdown cell in preview mode
|
||||
return getEditorAttachedPromise(element).then(() => reveal(viewIndex, range, revealType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async revealElementLineInViewAsync(cell: ICellViewModel, line: number): Promise<void> {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
private _revealRangeCommon(viewIndex: number, range: Range, revealType: CellEditorRevealType, newlyCreated: boolean, alignToBottom: boolean) {
|
||||
const element = this.view.element(viewIndex);
|
||||
const scrollTop = this.getViewScrollTop();
|
||||
const wrapperBottom = this.getViewScrollBottom();
|
||||
const positionOffset = element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
|
||||
const elementOriginalHeight = this.view.elementHeight(viewIndex);
|
||||
if (positionOffset >= elementOriginalHeight) {
|
||||
// we are revealing a range that is beyond current element height
|
||||
// if we don't update the element height now, and directly `setTop` to reveal the range
|
||||
// the element might be scrolled out of view
|
||||
// next frame, when we update the element height, the element will never be scrolled back into view
|
||||
const newTotalHeight = element.layoutInfo.totalHeight;
|
||||
this.updateElementHeight(viewIndex, newTotalHeight);
|
||||
}
|
||||
const elementTop = this.view.elementTop(viewIndex);
|
||||
const positionTop = elementTop + positionOffset;
|
||||
|
||||
if (index >= 0) {
|
||||
return this._revealLineInViewAsync(index, line);
|
||||
// TODO@rebornix 30 ---> line height * 1.5
|
||||
if (positionTop < scrollTop) {
|
||||
this.view.setScrollTop(positionTop - 30);
|
||||
} else if (positionTop > wrapperBottom) {
|
||||
this.view.setScrollTop(scrollTop + positionTop - wrapperBottom + 30);
|
||||
} else if (newlyCreated) {
|
||||
// newly scrolled into view
|
||||
if (alignToBottom) {
|
||||
// align to the bottom
|
||||
this.view.setScrollTop(scrollTop + positionTop - wrapperBottom + 30);
|
||||
} else {
|
||||
// align to to top
|
||||
this.view.setScrollTop(positionTop - 30);
|
||||
}
|
||||
}
|
||||
|
||||
if (revealType === CellEditorRevealType.Range) {
|
||||
element.revealRangeInCenter(range);
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region Reveal Cell offset
|
||||
async revealCellOffsetInCenterAsync(cell: ICellViewModel, offset: number): Promise<void> {
|
||||
const viewIndex = this._getViewIndexUpperBound(cell);
|
||||
|
||||
if (viewIndex >= 0) {
|
||||
const element = this.view.element(viewIndex);
|
||||
const elementTop = this.view.elementTop(viewIndex);
|
||||
if (element instanceof MarkupCellViewModel) {
|
||||
return this._revealInCenterIfOutsideViewport(viewIndex);
|
||||
} else {
|
||||
const rangeOffset = element.layoutInfo.outputContainerOffset + offset;
|
||||
this.view.setScrollTop(elementTop - this.view.renderHeight / 2);
|
||||
this.view.setScrollTop(elementTop + rangeOffset - this.view.renderHeight / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async revealElementLineInCenterAsync(cell: ICellViewModel, line: number): Promise<void> {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
|
||||
if (index >= 0) {
|
||||
return this._revealLineInCenterAsync(index, line);
|
||||
}
|
||||
private _revealInCenterIfOutsideViewport(viewIndex: number) {
|
||||
this._revealInternal(viewIndex, true, CellRevealPosition.Center);
|
||||
}
|
||||
|
||||
async revealElementLineInCenterIfOutsideViewportAsync(cell: ICellViewModel, line: number): Promise<void> {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
|
||||
if (index >= 0) {
|
||||
return this._revealLineInCenterIfOutsideViewportAsync(index, line);
|
||||
}
|
||||
}
|
||||
|
||||
async revealElementRangeInViewAsync(cell: ICellViewModel, range: Range): Promise<void> {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
|
||||
if (index >= 0) {
|
||||
return this._revealRangeInView(index, range);
|
||||
}
|
||||
}
|
||||
|
||||
async revealElementRangeInCenterAsync(cell: ICellViewModel, range: Range): Promise<void> {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
|
||||
if (index >= 0) {
|
||||
return this._revealRangeInCenterAsync(index, range);
|
||||
}
|
||||
}
|
||||
|
||||
async revealElementRangeInCenterIfOutsideViewportAsync(cell: ICellViewModel, range: Range): Promise<void> {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
|
||||
if (index >= 0) {
|
||||
return this._revealRangeInCenterIfOutsideViewportAsync(index, range);
|
||||
}
|
||||
}
|
||||
|
||||
async revealElementOffsetInCenterAsync(cell: ICellViewModel, offset: number): Promise<void> {
|
||||
const index = this._getViewIndexUpperBound(cell);
|
||||
|
||||
if (index >= 0) {
|
||||
return this._revealOffset(index, offset);
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
domElementOfElement(element: ICellViewModel): HTMLElement | null {
|
||||
const index = this._getViewIndexUpperBound(element);
|
||||
@@ -940,7 +1119,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
|
||||
this.view.delegateVerticalScrollbarPointerDown(browserEvent);
|
||||
}
|
||||
|
||||
isElementAboveViewport(index: number) {
|
||||
private isElementAboveViewport(index: number) {
|
||||
const elementTop = this.view.elementTop(index);
|
||||
const elementBottom = elementTop + this.view.elementHeight(index);
|
||||
|
||||
@@ -1031,270 +1210,7 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
|
||||
return this.getViewScrollTop() + this.view.renderHeight - topInsertToolbarHeight;
|
||||
}
|
||||
|
||||
private _revealOffset(viewIndex: number, offset: number) {
|
||||
const element = this.view.element(viewIndex);
|
||||
const elementTop = this.view.elementTop(viewIndex);
|
||||
if (element instanceof MarkupCellViewModel) {
|
||||
return this._revealInCenterIfOutsideViewport(viewIndex);
|
||||
} else {
|
||||
const rangeOffset = element.layoutInfo.outputContainerOffset + offset;
|
||||
this.view.setScrollTop(elementTop - this.view.renderHeight / 2);
|
||||
this.view.setScrollTop(elementTop + rangeOffset - this.view.renderHeight / 2);
|
||||
}
|
||||
}
|
||||
|
||||
private _revealRange(viewIndex: number, range: Range, revealType: CellRevealType, newlyCreated: boolean, alignToBottom: boolean) {
|
||||
const element = this.view.element(viewIndex);
|
||||
const scrollTop = this.getViewScrollTop();
|
||||
const wrapperBottom = this.getViewScrollBottom();
|
||||
const positionOffset = element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
|
||||
const elementOriginalHeight = this.view.elementHeight(viewIndex);
|
||||
if (positionOffset >= elementOriginalHeight) {
|
||||
// we are revealing a range that is beyond current element height
|
||||
// if we don't update the element height now, and directly `setTop` to reveal the range
|
||||
// the element might be scrolled out of view
|
||||
// next frame, when we update the element height, the element will never be scrolled back into view
|
||||
const newTotalHeight = element.layoutInfo.totalHeight;
|
||||
this.updateElementHeight(viewIndex, newTotalHeight);
|
||||
}
|
||||
const elementTop = this.view.elementTop(viewIndex);
|
||||
const positionTop = elementTop + positionOffset;
|
||||
|
||||
// TODO@rebornix 30 ---> line height * 1.5
|
||||
if (positionTop < scrollTop) {
|
||||
this.view.setScrollTop(positionTop - 30);
|
||||
} else if (positionTop > wrapperBottom) {
|
||||
this.view.setScrollTop(scrollTop + positionTop - wrapperBottom + 30);
|
||||
} else if (newlyCreated) {
|
||||
// newly scrolled into view
|
||||
if (alignToBottom) {
|
||||
// align to the bottom
|
||||
this.view.setScrollTop(scrollTop + positionTop - wrapperBottom + 30);
|
||||
} else {
|
||||
// align to to top
|
||||
this.view.setScrollTop(positionTop - 30);
|
||||
}
|
||||
}
|
||||
|
||||
if (revealType === CellRevealType.Range) {
|
||||
element.revealRangeInCenter(range);
|
||||
}
|
||||
}
|
||||
|
||||
// List items have real dynamic heights, which means after we set `scrollTop` based on the `elementTop(index)`, the element at `index` might still be removed from the view once all relayouting tasks are done.
|
||||
// For example, we scroll item 10 into the view upwards, in the first round, items 7, 8, 9, 10 are all in the viewport. Then item 7 and 8 resize themselves to be larger and finally item 10 is removed from the view.
|
||||
// To ensure that item 10 is always there, we need to scroll item 10 to the top edge of the viewport.
|
||||
private async _revealRangeInternalAsync(viewIndex: number, range: Range, revealType: CellRevealType): Promise<void> {
|
||||
const scrollTop = this.getViewScrollTop();
|
||||
const wrapperBottom = this.getViewScrollBottom();
|
||||
const elementTop = this.view.elementTop(viewIndex);
|
||||
const element = this.view.element(viewIndex);
|
||||
|
||||
if (element.editorAttached) {
|
||||
this._revealRange(viewIndex, range, revealType, false, false);
|
||||
} else {
|
||||
const elementHeight = this.view.elementHeight(viewIndex);
|
||||
let upwards = false;
|
||||
|
||||
if (elementTop + elementHeight < scrollTop) {
|
||||
// scroll downwards
|
||||
this.view.setScrollTop(elementTop);
|
||||
upwards = false;
|
||||
} else if (elementTop > wrapperBottom) {
|
||||
// scroll upwards
|
||||
this.view.setScrollTop(elementTop - this.view.renderHeight / 2);
|
||||
upwards = true;
|
||||
}
|
||||
|
||||
const editorAttachedPromise = new Promise<void>((resolve, reject) => {
|
||||
element.onDidChangeEditorAttachState(() => {
|
||||
element.editorAttached ? resolve() : reject();
|
||||
});
|
||||
});
|
||||
|
||||
return editorAttachedPromise.then(() => {
|
||||
this._revealRange(viewIndex, range, revealType, true, upwards);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async _revealLineInViewAsync(viewIndex: number, line: number): Promise<void> {
|
||||
return this._revealRangeInternalAsync(viewIndex, new Range(line, 1, line, 1), CellRevealType.Line);
|
||||
}
|
||||
|
||||
private async _revealRangeInView(viewIndex: number, range: Range): Promise<void> {
|
||||
return this._revealRangeInternalAsync(viewIndex, range, CellRevealType.Range);
|
||||
}
|
||||
|
||||
private async _revealRangeInCenterInternalAsync(viewIndex: number, range: Range, revealType: CellRevealType): Promise<void> {
|
||||
const reveal = (viewIndex: number, range: Range, revealType: CellRevealType) => {
|
||||
const element = this.view.element(viewIndex);
|
||||
const positionOffset = element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
|
||||
const positionOffsetInView = this.view.elementTop(viewIndex) + positionOffset;
|
||||
this.view.setScrollTop(positionOffsetInView - this.view.renderHeight / 2);
|
||||
|
||||
if (revealType === CellRevealType.Range) {
|
||||
element.revealRangeInCenter(range);
|
||||
}
|
||||
};
|
||||
|
||||
const elementTop = this.view.elementTop(viewIndex);
|
||||
const viewItemOffset = elementTop;
|
||||
this.view.setScrollTop(viewItemOffset - this.view.renderHeight / 2);
|
||||
const element = this.view.element(viewIndex);
|
||||
|
||||
if (!element.editorAttached) {
|
||||
return getEditorAttachedPromise(element).then(() => reveal(viewIndex, range, revealType));
|
||||
} else {
|
||||
reveal(viewIndex, range, revealType);
|
||||
}
|
||||
}
|
||||
|
||||
private async _revealLineInCenterAsync(viewIndex: number, line: number): Promise<void> {
|
||||
return this._revealRangeInCenterInternalAsync(viewIndex, new Range(line, 1, line, 1), CellRevealType.Line);
|
||||
}
|
||||
|
||||
private _revealRangeInCenterAsync(viewIndex: number, range: Range): Promise<void> {
|
||||
return this._revealRangeInCenterInternalAsync(viewIndex, range, CellRevealType.Range);
|
||||
}
|
||||
|
||||
private async _revealRangeInCenterIfOutsideViewportInternalAsync(viewIndex: number, range: Range, revealType: CellRevealType): Promise<void> {
|
||||
const reveal = (viewIndex: number, range: Range, revealType: CellRevealType) => {
|
||||
const element = this.view.element(viewIndex);
|
||||
const positionOffset = element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
|
||||
const positionOffsetInView = this.view.elementTop(viewIndex) + positionOffset;
|
||||
this.view.setScrollTop(positionOffsetInView - this.view.renderHeight / 2);
|
||||
|
||||
if (revealType === CellRevealType.Range) {
|
||||
element.revealRangeInCenter(range);
|
||||
}
|
||||
};
|
||||
|
||||
const scrollTop = this.getViewScrollTop();
|
||||
const wrapperBottom = this.getViewScrollBottom();
|
||||
const elementTop = this.view.elementTop(viewIndex);
|
||||
const viewItemOffset = elementTop;
|
||||
const element = this.view.element(viewIndex);
|
||||
const positionOffset = viewItemOffset + element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
|
||||
|
||||
if (positionOffset < scrollTop || positionOffset > wrapperBottom) {
|
||||
// let it render
|
||||
this.view.setScrollTop(positionOffset - this.view.renderHeight / 2);
|
||||
|
||||
// after rendering, it might be pushed down due to markdown cell dynamic height
|
||||
const newPositionOffset = this.view.elementTop(viewIndex) + element.getPositionScrollTopOffset(range.startLineNumber, range.startColumn);
|
||||
this.view.setScrollTop(newPositionOffset - this.view.renderHeight / 2);
|
||||
|
||||
// reveal editor
|
||||
if (!element.editorAttached) {
|
||||
return getEditorAttachedPromise(element).then(() => reveal(viewIndex, range, revealType));
|
||||
} else {
|
||||
// for example markdown
|
||||
}
|
||||
} else {
|
||||
if (element.editorAttached) {
|
||||
element.revealRangeInCenter(range);
|
||||
} else {
|
||||
// for example, markdown cell in preview mode
|
||||
return getEditorAttachedPromise(element).then(() => reveal(viewIndex, range, revealType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async _revealIfOutsideViewportAsync(viewIndex: number, revealPosition: CellRevealPosition): Promise<void> {
|
||||
this._revealInternal(viewIndex, true, revealPosition);
|
||||
const element = this.view.element(viewIndex);
|
||||
|
||||
// wait for the editor to be created only if the cell is in editing mode (meaning it has an editor and will focus the editor)
|
||||
if (element.getEditState() === CellEditState.Editing && !element.editorAttached) {
|
||||
return getEditorAttachedPromise(element);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private async _revealLineInCenterIfOutsideViewportAsync(viewIndex: number, line: number): Promise<void> {
|
||||
return this._revealRangeInCenterIfOutsideViewportInternalAsync(viewIndex, new Range(line, 1, line, 1), CellRevealType.Line);
|
||||
}
|
||||
|
||||
private async _revealRangeInCenterIfOutsideViewportAsync(viewIndex: number, range: Range): Promise<void> {
|
||||
return this._revealRangeInCenterIfOutsideViewportInternalAsync(viewIndex, range, CellRevealType.Range);
|
||||
}
|
||||
|
||||
private _revealInternal(viewIndex: number, ignoreIfInsideViewport: boolean, revealPosition: CellRevealPosition) {
|
||||
if (viewIndex >= this.view.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const scrollTop = this.getViewScrollTop();
|
||||
const wrapperBottom = this.getViewScrollBottom();
|
||||
const elementTop = this.view.elementTop(viewIndex);
|
||||
const elementBottom = this.view.elementHeight(viewIndex) + elementTop;
|
||||
|
||||
if (ignoreIfInsideViewport
|
||||
&& elementTop >= scrollTop
|
||||
&& elementBottom < wrapperBottom) {
|
||||
|
||||
if (revealPosition === CellRevealPosition.Center
|
||||
&& elementBottom > wrapperBottom
|
||||
&& elementTop > (scrollTop + wrapperBottom) / 2) {
|
||||
// the element is partially visible and it's below the center of the viewport
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (revealPosition) {
|
||||
case CellRevealPosition.Top:
|
||||
this.view.setScrollTop(elementTop);
|
||||
this.view.setScrollTop(this.view.elementTop(viewIndex));
|
||||
break;
|
||||
case CellRevealPosition.Center:
|
||||
case CellRevealPosition.NearTop:
|
||||
{
|
||||
// reveal the cell top in the viewport center initially
|
||||
this.view.setScrollTop(elementTop - this.view.renderHeight / 2);
|
||||
// cell rendered already, we now have a more accurate cell height
|
||||
const newElementTop = this.view.elementTop(viewIndex);
|
||||
const newElementHeight = this.view.elementHeight(viewIndex);
|
||||
const renderHeight = this.getViewScrollBottom() - this.getViewScrollTop();
|
||||
if (newElementHeight >= renderHeight) {
|
||||
// cell is larger than viewport, reveal top
|
||||
this.view.setScrollTop(newElementTop);
|
||||
} else if (revealPosition === CellRevealPosition.Center) {
|
||||
this.view.setScrollTop(newElementTop + (newElementHeight / 2) - (renderHeight / 2));
|
||||
} else if (revealPosition === CellRevealPosition.NearTop) {
|
||||
this.view.setScrollTop(newElementTop - (renderHeight / 5));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CellRevealPosition.Bottom:
|
||||
this.view.setScrollTop(this.scrollTop + (elementBottom - wrapperBottom));
|
||||
this.view.setScrollTop(this.scrollTop + (this.view.elementTop(viewIndex) + this.view.elementHeight(viewIndex) - this.getViewScrollBottom()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private _revealInView(viewIndex: number) {
|
||||
const firstIndex = this.view.firstVisibleIndex;
|
||||
if (viewIndex <= firstIndex) {
|
||||
this._revealInternal(viewIndex, true, CellRevealPosition.Top);
|
||||
} else {
|
||||
this._revealInternal(viewIndex, true, CellRevealPosition.Bottom);
|
||||
}
|
||||
}
|
||||
|
||||
private _revealInCenter(viewIndex: number) {
|
||||
this._revealInternal(viewIndex, false, CellRevealPosition.Center);
|
||||
}
|
||||
|
||||
private _revealInCenterIfOutsideViewport(viewIndex: number) {
|
||||
this._revealInternal(viewIndex, true, CellRevealPosition.Center);
|
||||
}
|
||||
|
||||
setCellSelection(cell: ICellViewModel, range: Range) {
|
||||
setCellEditorSelection(cell: ICellViewModel, range: Range) {
|
||||
const element = cell as CellViewModel;
|
||||
if (element.editorAttached) {
|
||||
element.setSelection(range);
|
||||
@@ -1303,7 +1219,6 @@ export class NotebookCellList extends WorkbenchList<CellViewModel> implements ID
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override style(styles: IListStyles) {
|
||||
const selectorSuffix = this.view.domId;
|
||||
if (!this.styleElement) {
|
||||
@@ -1449,74 +1364,6 @@ export class ListViewInfoAccessor extends Disposable {
|
||||
super();
|
||||
}
|
||||
|
||||
setScrollTop(scrollTop: number) {
|
||||
this.list.scrollTop = scrollTop;
|
||||
}
|
||||
|
||||
isScrolledToBottom() {
|
||||
return this.list.isScrolledToBottom();
|
||||
}
|
||||
|
||||
scrollToBottom() {
|
||||
this.list.scrollToBottom();
|
||||
}
|
||||
|
||||
revealCellRangeInView(range: ICellRange) {
|
||||
return this.list.revealElementsInView(range);
|
||||
}
|
||||
|
||||
revealInView(cell: ICellViewModel) {
|
||||
this.list.revealElementInView(cell);
|
||||
}
|
||||
|
||||
revealInViewAtTop(cell: ICellViewModel) {
|
||||
this.list.revealElementInViewAtTop(cell);
|
||||
}
|
||||
|
||||
revealInCenterIfOutsideViewport(cell: ICellViewModel) {
|
||||
this.list.revealElementInCenterIfOutsideViewport(cell);
|
||||
}
|
||||
|
||||
async revealInCenterIfOutsideViewportAsync(cell: ICellViewModel) {
|
||||
return this.list.revealElementInCenterIfOutsideViewportAsync(cell);
|
||||
}
|
||||
|
||||
revealInCenter(cell: ICellViewModel) {
|
||||
this.list.revealElementInCenter(cell);
|
||||
}
|
||||
|
||||
async revealNearTopIfOutsideViewportAync(cell: ICellViewModel) {
|
||||
return this.list.revealNearTopIfOutsideViewportAync(cell);
|
||||
}
|
||||
|
||||
async revealLineInViewAsync(cell: ICellViewModel, line: number): Promise<void> {
|
||||
return this.list.revealElementLineInViewAsync(cell, line);
|
||||
}
|
||||
|
||||
async revealLineInCenterAsync(cell: ICellViewModel, line: number): Promise<void> {
|
||||
return this.list.revealElementLineInCenterAsync(cell, line);
|
||||
}
|
||||
|
||||
async revealLineInCenterIfOutsideViewportAsync(cell: ICellViewModel, line: number): Promise<void> {
|
||||
return this.list.revealElementLineInCenterIfOutsideViewportAsync(cell, line);
|
||||
}
|
||||
|
||||
async revealRangeInViewAsync(cell: ICellViewModel, range: Range): Promise<void> {
|
||||
return this.list.revealElementRangeInViewAsync(cell, range);
|
||||
}
|
||||
|
||||
async revealRangeInCenterAsync(cell: ICellViewModel, range: Range): Promise<void> {
|
||||
return this.list.revealElementRangeInCenterAsync(cell, range);
|
||||
}
|
||||
|
||||
async revealRangeInCenterIfOutsideViewportAsync(cell: ICellViewModel, range: Range): Promise<void> {
|
||||
return this.list.revealElementRangeInCenterIfOutsideViewportAsync(cell, range);
|
||||
}
|
||||
|
||||
async revealCellOffsetInCenterAsync(cell: ICellViewModel, offset: number): Promise<void> {
|
||||
return this.list.revealElementOffsetInCenterAsync(cell, offset);
|
||||
}
|
||||
|
||||
getViewIndex(cell: ICellViewModel): number {
|
||||
return this.list.getViewIndex(cell) ?? -1;
|
||||
}
|
||||
@@ -1569,24 +1416,12 @@ export class ListViewInfoAccessor extends Disposable {
|
||||
return this.list.viewModel?.getCellsInRange(range) ?? [];
|
||||
}
|
||||
|
||||
setCellEditorSelection(cell: ICellViewModel, range: Range): void {
|
||||
this.list.setCellSelection(cell, range);
|
||||
}
|
||||
|
||||
setHiddenAreas(_ranges: ICellRange[]): boolean {
|
||||
return this.list.setHiddenAreas(_ranges, true);
|
||||
}
|
||||
|
||||
getVisibleRangesPlusViewportAboveAndBelow(): ICellRange[] {
|
||||
return this.list?.getVisibleRangesPlusViewportAboveAndBelow() ?? [];
|
||||
}
|
||||
|
||||
triggerScroll(event: IMouseWheelEvent) {
|
||||
this.list.triggerScrollFromMouseWheelEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
function getEditorAttachedPromise(element: CellViewModel) {
|
||||
function getEditorAttachedPromise(element: ICellViewModel) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
Event.once(element.onDidChangeEditorAttachState)(() => element.editorAttached ? resolve() : reject());
|
||||
});
|
||||
|
||||
@@ -14,11 +14,12 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ICellOutputViewModel, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellRevealRangeType, CellRevealSyncType, CellRevealType, ICellOutputViewModel, ICellViewModel } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellPartsCollection } from 'vs/workbench/contrib/notebook/browser/view/cellPart';
|
||||
import { CellViewModel, NotebookViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModelImpl';
|
||||
import { ICellRange } from 'vs/workbench/contrib/notebook/common/notebookRange';
|
||||
|
||||
|
||||
export interface INotebookCellList {
|
||||
isDisposed: boolean;
|
||||
viewModel: NotebookViewModel | null;
|
||||
@@ -58,22 +59,12 @@ export interface INotebookCellList {
|
||||
selectElements(elements: ICellViewModel[]): void;
|
||||
getFocusedElements(): ICellViewModel[];
|
||||
getSelectedElements(): ICellViewModel[];
|
||||
revealElementsInView(range: ICellRange): void;
|
||||
isScrolledToBottom(): boolean;
|
||||
revealCellsInView(range: ICellRange): void;
|
||||
scrollToBottom(): void;
|
||||
revealElementInView(element: ICellViewModel): void;
|
||||
revealElementInViewAtTop(element: ICellViewModel): void;
|
||||
revealElementInCenterIfOutsideViewport(element: ICellViewModel): void;
|
||||
revealElementInCenter(element: ICellViewModel): void;
|
||||
revealElementInCenterIfOutsideViewportAsync(element: ICellViewModel): Promise<void>;
|
||||
revealNearTopIfOutsideViewportAync(element: ICellViewModel): Promise<void>;
|
||||
revealElementLineInViewAsync(element: ICellViewModel, line: number): Promise<void>;
|
||||
revealElementLineInCenterAsync(element: ICellViewModel, line: number): Promise<void>;
|
||||
revealElementLineInCenterIfOutsideViewportAsync(element: ICellViewModel, line: number): Promise<void>;
|
||||
revealElementRangeInViewAsync(element: ICellViewModel, range: Range): Promise<void>;
|
||||
revealElementRangeInCenterAsync(element: ICellViewModel, range: Range): Promise<void>;
|
||||
revealElementRangeInCenterIfOutsideViewportAsync(element: ICellViewModel, range: Range): Promise<void>;
|
||||
revealElementOffsetInCenterAsync(element: ICellViewModel, offset: number): Promise<void>;
|
||||
revealCell(cell: ICellViewModel, revealType: CellRevealSyncType): void;
|
||||
revealCellAsync(cell: ICellViewModel, revealType: CellRevealType): Promise<void>;
|
||||
revealCellRangeAsync(cell: ICellViewModel, range: Range, revealType: CellRevealRangeType): Promise<void>;
|
||||
revealCellOffsetInCenterAsync(element: ICellViewModel, offset: number): Promise<void>;
|
||||
setHiddenAreas(_ranges: ICellRange[], triggerViewUpdate: boolean): boolean;
|
||||
domElementOfElement(element: ICellViewModel): HTMLElement | null;
|
||||
focusView(): void;
|
||||
@@ -82,7 +73,7 @@ export interface INotebookCellList {
|
||||
updateElementHeight2(element: ICellViewModel, size: number, anchorElementIndex?: number | null): void;
|
||||
domFocus(): void;
|
||||
focusContainer(): void;
|
||||
setCellSelection(element: ICellViewModel, range: Range): void;
|
||||
setCellEditorSelection(element: ICellViewModel, range: Range): void;
|
||||
style(styles: IListStyles): void;
|
||||
getRenderHeight(): number;
|
||||
getScrollHeight(): number;
|
||||
|
||||
@@ -60,17 +60,17 @@ suite('NotebookCellList', () => {
|
||||
assert.deepStrictEqual(cellList.getViewScrollBottom(), 215);
|
||||
|
||||
// reveal cell 1, top 50, bottom 150, which is fully visible in the viewport
|
||||
cellList.revealElementsInView({ start: 1, end: 2 });
|
||||
cellList.revealCellsInView({ start: 1, end: 2 });
|
||||
assert.deepStrictEqual(cellList.scrollTop, 5);
|
||||
assert.deepStrictEqual(cellList.getViewScrollBottom(), 215);
|
||||
|
||||
// reveal cell 2, top 150, bottom 200, which is fully visible in the viewport
|
||||
cellList.revealElementsInView({ start: 2, end: 3 });
|
||||
cellList.revealCellsInView({ start: 2, end: 3 });
|
||||
assert.deepStrictEqual(cellList.scrollTop, 5);
|
||||
assert.deepStrictEqual(cellList.getViewScrollBottom(), 215);
|
||||
|
||||
// reveal cell 3, top 200, bottom 300, which is partially visible in the viewport
|
||||
cellList.revealElementsInView({ start: 3, end: 4 });
|
||||
cellList.revealCellsInView({ start: 3, end: 4 });
|
||||
assert.deepStrictEqual(cellList.scrollTop, 90);
|
||||
});
|
||||
});
|
||||
@@ -105,7 +105,7 @@ suite('NotebookCellList', () => {
|
||||
assert.deepStrictEqual(cellList.getViewScrollBottom(), 210);
|
||||
|
||||
// reveal cell 3, top 200, bottom 300, which is partially visible in the viewport
|
||||
cellList.revealElementsInView({ start: 3, end: 4 });
|
||||
cellList.revealCellsInView({ start: 3, end: 4 });
|
||||
assert.deepStrictEqual(cellList.scrollTop, 90);
|
||||
|
||||
// scroll to 5
|
||||
@@ -114,7 +114,7 @@ suite('NotebookCellList', () => {
|
||||
assert.deepStrictEqual(cellList.getViewScrollBottom(), 215);
|
||||
|
||||
// reveal cell 0, top 0, bottom 50
|
||||
cellList.revealElementsInView({ start: 0, end: 1 });
|
||||
cellList.revealCellsInView({ start: 0, end: 1 });
|
||||
assert.deepStrictEqual(cellList.scrollTop, 0);
|
||||
});
|
||||
});
|
||||
@@ -150,7 +150,7 @@ suite('NotebookCellList', () => {
|
||||
assert.deepStrictEqual(cellList.scrollTop, 0);
|
||||
assert.deepStrictEqual(cellList.getViewScrollBottom(), 210);
|
||||
|
||||
cellList.revealElementsInView({ start: 4, end: 5 });
|
||||
cellList.revealCellsInView({ start: 4, end: 5 });
|
||||
assert.deepStrictEqual(cellList.scrollTop, 140);
|
||||
// assert.deepStrictEqual(cellList.getViewScrollBottom(), 330);
|
||||
});
|
||||
|
||||
@@ -644,7 +644,7 @@ export function registerTerminalActions() {
|
||||
|
||||
const isRemote = instance ? instance.isRemote : (workbenchEnvironmentService.remoteAuthority ? true : false);
|
||||
const uri = editor.getModel().uri;
|
||||
if ((!isRemote && uri.scheme !== Schemas.file) || (isRemote && uri.scheme !== Schemas.vscodeRemote)) {
|
||||
if ((!isRemote && uri.scheme !== Schemas.file && uri.scheme !== Schemas.vscodeUserData) || (isRemote && uri.scheme !== Schemas.vscodeRemote)) {
|
||||
notificationService.warn(localize('workbench.action.terminal.runActiveFile.noFile', 'Only files on disk can be run in the terminal'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -517,7 +517,46 @@ export function setupTerminalMenus(): void {
|
||||
ContextKeyExpr.or(TerminalContextKeys.webExtensionContributedProfile, TerminalContextKeys.processSupported)
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.ViewTitle,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.Clear,
|
||||
title: localize('workbench.action.terminal.clearLong', "Clear Terminal"),
|
||||
icon: Codicon.clearAll
|
||||
},
|
||||
group: 'navigation',
|
||||
order: 4,
|
||||
isHiddenByDefault: true
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.ViewTitle,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.RunActiveFile,
|
||||
title: localize('workbench.action.terminal.runActiveFile', "Run Active File"),
|
||||
icon: Codicon.run
|
||||
},
|
||||
group: 'navigation',
|
||||
order: 5,
|
||||
isHiddenByDefault: true
|
||||
}
|
||||
},
|
||||
{
|
||||
id: MenuId.ViewTitle,
|
||||
item: {
|
||||
command: {
|
||||
id: TerminalCommandId.RunSelectedText,
|
||||
title: localize('workbench.action.terminal.runSelectedText', "Run Selected Text"),
|
||||
icon: Codicon.selection
|
||||
},
|
||||
group: 'navigation',
|
||||
order: 6,
|
||||
isHiddenByDefault: true
|
||||
}
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
Vendored
+13
-13
@@ -206,7 +206,7 @@ declare module 'vscode' {
|
||||
/**
|
||||
* Get a word-range at the given position. By default words are defined by
|
||||
* common separators, like space, -, _, etc. In addition, per language custom
|
||||
* [word definitions} can be defined. It
|
||||
* [word definitions] can be defined. It
|
||||
* is also possible to provide a custom regular expression.
|
||||
*
|
||||
* * *Note 1:* A custom regular expression must not match the empty string and
|
||||
@@ -9030,7 +9030,7 @@ declare module 'vscode' {
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional information used to implement {@linkcode CustomEditableDocument.backup}.
|
||||
* Additional information used to implement {@linkcode CustomDocumentBackup}.
|
||||
*/
|
||||
interface CustomDocumentBackupContext {
|
||||
/**
|
||||
@@ -12435,11 +12435,11 @@ declare module 'vscode' {
|
||||
export const notebookDocuments: readonly NotebookDocument[];
|
||||
|
||||
/**
|
||||
* Open a notebook. Will return early if this notebook is already {@link notebook.notebookDocuments loaded}. Otherwise
|
||||
* the notebook is loaded and the {@linkcode notebook.onDidOpenNotebookDocument onDidOpenNotebookDocument}-event fires.
|
||||
* Open a notebook. Will return early if this notebook is already {@link notebookDocuments loaded}. Otherwise
|
||||
* the notebook is loaded and the {@linkcode onDidOpenNotebookDocument}-event fires.
|
||||
*
|
||||
* *Note* that the lifecycle of the returned notebook is owned by the editor and not by the extension. That means an
|
||||
* {@linkcode notebook.onDidCloseNotebookDocument onDidCloseNotebookDocument}-event can occur at any time after.
|
||||
* {@linkcode onDidCloseNotebookDocument}-event can occur at any time after.
|
||||
*
|
||||
* *Note* that opening a notebook does not show a notebook editor. This function only returns a notebook document which
|
||||
* can be shown in a notebook editor but it can also be used for other things.
|
||||
@@ -15068,7 +15068,7 @@ declare module 'vscode' {
|
||||
*
|
||||
* @param debugType The debug type for which the provider is registered.
|
||||
* @param provider The {@link DebugConfigurationProvider debug configuration provider} to register.
|
||||
* @param triggerKind The {@link DebugConfigurationProviderTrigger trigger} for which the 'provideDebugConfiguration' method of the provider is registered. If `triggerKind` is missing, the value `DebugConfigurationProviderTriggerKind.Initial` is assumed.
|
||||
* @param triggerKind The {@link DebugConfigurationProviderTriggerKind trigger} for which the 'provideDebugConfiguration' method of the provider is registered. If `triggerKind` is missing, the value `DebugConfigurationProviderTriggerKind.Initial` is assumed.
|
||||
* @return A {@link Disposable} that unregisters this provider when being disposed.
|
||||
*/
|
||||
export function registerDebugConfigurationProvider(debugType: string, provider: DebugConfigurationProvider, triggerKind?: DebugConfigurationProviderTriggerKind): Disposable;
|
||||
@@ -15816,8 +15816,8 @@ declare module 'vscode' {
|
||||
*/
|
||||
export function t(options: {
|
||||
/**
|
||||
* The message to localize. If {@link args} is an array, this message supports index templating where strings like
|
||||
* `{0}` and `{1}` are replaced by the item at that index in the {@link args} array. If `args` is a `Record<string, any>`,
|
||||
* The message to localize. If {@link options.args args} is an array, this message supports index templating where strings like
|
||||
* `{0}` and `{1}` are replaced by the item at that index in the {@link options.args args} array. If `args` is a `Record<string, any>`,
|
||||
* this supports named templating where strings like `{foo}` and `{bar}` are replaced by the value in
|
||||
* the Record for that key (foo, bar, etc).
|
||||
*/
|
||||
@@ -15964,7 +15964,7 @@ declare module 'vscode' {
|
||||
*/
|
||||
export interface TestController {
|
||||
/**
|
||||
* The id of the controller passed in {@link vscode.tests.createTestController}.
|
||||
* The id of the controller passed in {@link tests.createTestController}.
|
||||
* This must be globally unique.
|
||||
*/
|
||||
readonly id: string;
|
||||
@@ -15980,7 +15980,7 @@ declare module 'vscode' {
|
||||
* "test tree."
|
||||
*
|
||||
* The extension controls when to add tests. For example, extensions should
|
||||
* add tests for a file when {@link vscode.workspace.onDidOpenTextDocument}
|
||||
* add tests for a file when {@link workspace.onDidOpenTextDocument}
|
||||
* fires in order for decorations for tests within a file to be visible.
|
||||
*
|
||||
* However, the editor may sometimes explicitly request children using the
|
||||
@@ -16005,7 +16005,7 @@ declare module 'vscode' {
|
||||
* A function provided by the extension that the editor may call to request
|
||||
* children of a test item, if the {@link TestItem.canResolveChildren} is
|
||||
* `true`. When called, the item should discover children and call
|
||||
* {@link vscode.tests.createTestItem} as children are discovered.
|
||||
* {@link TestController.createTestItem} as children are discovered.
|
||||
*
|
||||
* Generally the extension manages the lifecycle of test items, but under
|
||||
* certain conditions the editor may request the children of a specific
|
||||
@@ -16289,7 +16289,7 @@ declare module 'vscode' {
|
||||
|
||||
/**
|
||||
* Tags associated with this test item. May be used in combination with
|
||||
* {@link TestRunProfile.tags}, or simply as an organizational feature.
|
||||
* {@link TestRunProfile.tag tags}, or simply as an organizational feature.
|
||||
*/
|
||||
tags: readonly TestTag[];
|
||||
|
||||
@@ -16602,7 +16602,7 @@ declare module 'vscode' {
|
||||
* Whether or not the group is currently active.
|
||||
*
|
||||
* *Note* that only one tab group is active at a time, but that multiple tab
|
||||
* groups can have an {@link TabGroup.aciveTab active tab}.
|
||||
* groups can have an {@link activeTab active tab}.
|
||||
*
|
||||
* @see {@link Tab.isActive}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user