mirror of
https://github.com/Microsoft/vscode
synced 2024-10-12 22:37:41 +00:00
Merge branch 'master' into misolori/icon-font-breakpoints
This commit is contained in:
commit
7766a5d0f0
6
.vscode/tasks.json
vendored
6
.vscode/tasks.json
vendored
|
@ -33,15 +33,15 @@
|
|||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "strict-initialization-watch",
|
||||
"label": "TS - Strict Initialization",
|
||||
"script": "strict-function-types-watch",
|
||||
"label": "TS - Strict Function Types",
|
||||
"isBackground": true,
|
||||
"presentation": {
|
||||
"reveal": "never"
|
||||
},
|
||||
"problemMatcher": {
|
||||
"base": "$tsc-watch",
|
||||
"owner": "typescript-strict-initialization",
|
||||
"owner": "typescript-function-types",
|
||||
"applyTo": "allDocuments"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -4,23 +4,11 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { getLocation, parse, visit } from 'jsonc-parser';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { SettingsDocument } from './settingsDocumentHelper';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
const fadedDecoration = vscode.window.createTextEditorDecorationType({
|
||||
light: {
|
||||
color: '#757575'
|
||||
},
|
||||
dark: {
|
||||
color: '#878787'
|
||||
}
|
||||
});
|
||||
|
||||
let pendingLaunchJsonDecoration: NodeJS.Timer;
|
||||
|
||||
export function activate(context: vscode.ExtensionContext): void {
|
||||
//settings.json suggestions
|
||||
context.subscriptions.push(registerSettingsCompletions());
|
||||
|
@ -33,18 +21,6 @@ export function activate(context: vscode.ExtensionContext): void {
|
|||
|
||||
// task.json variable suggestions
|
||||
context.subscriptions.push(registerVariableCompletions('**/tasks.json'));
|
||||
|
||||
// launch.json decorations
|
||||
context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(editor => updateLaunchJsonDecorations(editor), null, context.subscriptions));
|
||||
context.subscriptions.push(vscode.workspace.onDidChangeTextDocument(event => {
|
||||
if (vscode.window.activeTextEditor && event.document === vscode.window.activeTextEditor.document) {
|
||||
if (pendingLaunchJsonDecoration) {
|
||||
clearTimeout(pendingLaunchJsonDecoration);
|
||||
}
|
||||
pendingLaunchJsonDecoration = setTimeout(() => updateLaunchJsonDecorations(vscode.window.activeTextEditor), 1000);
|
||||
}
|
||||
}, null, context.subscriptions));
|
||||
updateLaunchJsonDecorations(vscode.window.activeTextEditor);
|
||||
}
|
||||
|
||||
function registerSettingsCompletions(): vscode.Disposable {
|
||||
|
@ -153,39 +129,6 @@ function provideInstalledExtensionProposals(extensionsContent: IExtensionsConten
|
|||
return undefined;
|
||||
}
|
||||
|
||||
function updateLaunchJsonDecorations(editor: vscode.TextEditor | undefined): void {
|
||||
if (!editor || path.basename(editor.document.fileName) !== 'launch.json') {
|
||||
return;
|
||||
}
|
||||
|
||||
const ranges: vscode.Range[] = [];
|
||||
let addPropertyAndValue = false;
|
||||
let depthInArray = 0;
|
||||
visit(editor.document.getText(), {
|
||||
onObjectProperty: (property, offset, length) => {
|
||||
// Decorate attributes which are unlikely to be edited by the user.
|
||||
// Only decorate "configurations" if it is not inside an array (compounds have a configurations property which should not be decorated).
|
||||
addPropertyAndValue = property === 'version' || property === 'type' || property === 'request' || property === 'compounds' || (property === 'configurations' && depthInArray === 0);
|
||||
if (addPropertyAndValue) {
|
||||
ranges.push(new vscode.Range(editor.document.positionAt(offset), editor.document.positionAt(offset + length)));
|
||||
}
|
||||
},
|
||||
onLiteralValue: (_value, offset, length) => {
|
||||
if (addPropertyAndValue) {
|
||||
ranges.push(new vscode.Range(editor.document.positionAt(offset), editor.document.positionAt(offset + length)));
|
||||
}
|
||||
},
|
||||
onArrayBegin: (_offset: number, _length: number) => {
|
||||
depthInArray++;
|
||||
},
|
||||
onArrayEnd: (_offset: number, _length: number) => {
|
||||
depthInArray--;
|
||||
}
|
||||
});
|
||||
|
||||
editor.setDecorations(fadedDecoration, ranges);
|
||||
}
|
||||
|
||||
vscode.languages.registerDocumentSymbolProvider({ pattern: '**/launch.json', language: 'jsonc' }, {
|
||||
provideDocumentSymbols(document: vscode.TextDocument, _token: vscode.CancellationToken): vscode.ProviderResult<vscode.SymbolInformation[]> {
|
||||
const result: vscode.SymbolInformation[] = [];
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"main": "./out/cssServerMain",
|
||||
"dependencies": {
|
||||
"vscode-css-languageservice": "^4.0.3-next.19",
|
||||
"vscode-css-languageservice": "^4.0.3-next.20",
|
||||
"vscode-languageserver": "^6.0.0-next.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -781,10 +781,10 @@ supports-color@^5.3.0:
|
|||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
vscode-css-languageservice@^4.0.3-next.19:
|
||||
version "4.0.3-next.19"
|
||||
resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.19.tgz#b7dc58fb8d1968877724e163b6ef20b26c0b5ff6"
|
||||
integrity sha512-wWSo2MZvd8aEI9lf/Asy0MP0Ao6xAzhBeEWxGcF+Ms/zcV4lDRkyFCNzwDt0OgWRzsBNaEBXfjeWLq9rNXkREA==
|
||||
vscode-css-languageservice@^4.0.3-next.20:
|
||||
version "4.0.3-next.20"
|
||||
resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.20.tgz#d0c4933c33e356617ccfaeb6b7144be196b8b3d9"
|
||||
integrity sha512-9j32ppmJauPg9XYieAS6alCGazTaeEi8nhSAb11le5qfFNWep4Ngz7dNc/UMlt6hB7BESRyk2B8MM/KTlnsNBw==
|
||||
dependencies:
|
||||
vscode-languageserver-textdocument "^1.0.0-next.4"
|
||||
vscode-languageserver-types "^3.15.0-next.6"
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"main": "./out/htmlServerMain",
|
||||
"dependencies": {
|
||||
"vscode-css-languageservice": "^4.0.3-next.19",
|
||||
"vscode-css-languageservice": "^4.0.3-next.20",
|
||||
"vscode-html-languageservice": "^3.0.4-next.8",
|
||||
"vscode-languageserver": "^6.0.0-next.3",
|
||||
"vscode-nls": "^4.1.1",
|
||||
|
|
|
@ -611,10 +611,10 @@ supports-color@^5.3.0:
|
|||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
vscode-css-languageservice@^4.0.3-next.19:
|
||||
version "4.0.3-next.19"
|
||||
resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.19.tgz#b7dc58fb8d1968877724e163b6ef20b26c0b5ff6"
|
||||
integrity sha512-wWSo2MZvd8aEI9lf/Asy0MP0Ao6xAzhBeEWxGcF+Ms/zcV4lDRkyFCNzwDt0OgWRzsBNaEBXfjeWLq9rNXkREA==
|
||||
vscode-css-languageservice@^4.0.3-next.20:
|
||||
version "4.0.3-next.20"
|
||||
resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-4.0.3-next.20.tgz#d0c4933c33e356617ccfaeb6b7144be196b8b3d9"
|
||||
integrity sha512-9j32ppmJauPg9XYieAS6alCGazTaeEi8nhSAb11le5qfFNWep4Ngz7dNc/UMlt6hB7BESRyk2B8MM/KTlnsNBw==
|
||||
dependencies:
|
||||
vscode-languageserver-textdocument "^1.0.0-next.4"
|
||||
vscode-languageserver-types "^3.15.0-next.6"
|
||||
|
|
|
@ -54,9 +54,11 @@ function registerMarkdownLanguageFeatures(
|
|||
{ language: 'markdown', scheme: 'untitled' }
|
||||
];
|
||||
|
||||
const charPattern = '(\\p{Alphabetic}|\\p{Number}|\\p{Nonspacing_Mark})';
|
||||
|
||||
return vscode.Disposable.from(
|
||||
vscode.languages.setLanguageConfiguration('markdown', {
|
||||
wordPattern: new RegExp('(\\p{Alphabetic}|\\p{Number}|\\p{Nonspacing_Mark})+', 'ug'),
|
||||
wordPattern: new RegExp(`${charPattern}((${charPattern}|[_])?${charPattern})*`, 'ug'),
|
||||
}),
|
||||
vscode.languages.registerDocumentSymbolProvider(selector, symbolProvider),
|
||||
vscode.languages.registerDocumentLinkProvider(selector, new LinkProvider()),
|
||||
|
|
|
@ -401,7 +401,10 @@ export default class BufferSyncSupport extends Disposable {
|
|||
this.pendingGetErr?.cancel();
|
||||
this.pendingDiagnostics.clear();
|
||||
this.synchronizer.reset();
|
||||
}
|
||||
|
||||
public reinitialize(): void {
|
||||
this.reset();
|
||||
for (const buffer of this.syncedBuffers.allBuffers) {
|
||||
buffer.open();
|
||||
}
|
||||
|
|
|
@ -82,6 +82,10 @@ class TypeScriptAutoFixProvider implements vscode.CodeActionProvider {
|
|||
return undefined;
|
||||
}
|
||||
const { edit, fixedDiagnostics } = autoFixResponse;
|
||||
if (!edit.size) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const codeAction = new vscode.CodeAction(
|
||||
localize('autoFix.label', 'Auto fix'),
|
||||
TypeScriptAutoFixProvider.kind);
|
||||
|
@ -105,11 +109,11 @@ class TypeScriptAutoFixProvider implements vscode.CodeActionProvider {
|
|||
};
|
||||
const response = await this.client.execute('getCodeFixes', args, token);
|
||||
if (response.type !== 'response' || !response.body || response.body.length > 1) {
|
||||
return undefined;
|
||||
continue;
|
||||
}
|
||||
|
||||
const fix = response.body[0];
|
||||
if (new Set<string>(['fixClassIncorrectlyImplementsInterface', 'spelling']).has(fix.fixName)) {
|
||||
if (['fixClassIncorrectlyImplementsInterface', 'spelling'].includes(fix.fixName)) {
|
||||
typeConverters.WorkspaceEdit.withFileCodeEdits(edit, this.client, fix.changes);
|
||||
fixedDiagnostics.push(diagnostic);
|
||||
}
|
||||
|
|
|
@ -182,8 +182,6 @@ export default class TypeScriptServiceClientHost extends Disposable {
|
|||
|
||||
private populateService(): void {
|
||||
this.fileConfigurationManager.reset();
|
||||
this.client.bufferSyncSupport.reset();
|
||||
this.client.bufferSyncSupport.requestAllDiagnostics();
|
||||
|
||||
// See https://github.com/Microsoft/TypeScript/issues/5530
|
||||
vscode.workspace.saveAll(false).then(() => {
|
||||
|
|
|
@ -465,6 +465,8 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
|||
}
|
||||
|
||||
private serviceStarted(resendModels: boolean): void {
|
||||
this.bufferSyncSupport.reset();
|
||||
|
||||
const configureOptions: Proto.ConfigureRequestArguments = {
|
||||
hostInfo: 'vscode',
|
||||
preferences: {
|
||||
|
@ -476,6 +478,8 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
|||
this.setCompilerOptionsForInferredProjects(this._configuration);
|
||||
if (resendModels) {
|
||||
this._onResendModelsRequested.fire();
|
||||
this.bufferSyncSupport.reinitialize();
|
||||
this.bufferSyncSupport.requestAllDiagnostics();
|
||||
}
|
||||
|
||||
// Reconfigure any plugins
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
"smoketest": "cd test/smoke && node test/index.js",
|
||||
"download-builtin-extensions": "node build/lib/builtInExtensions.js",
|
||||
"monaco-compile-check": "tsc -p src/tsconfig.monaco.json --noEmit",
|
||||
"strict-initialization-watch": "tsc --watch -p src/tsconfig.json --noEmit --strictPropertyInitialization",
|
||||
"strict-function-types-watch": "tsc --watch -p src/tsconfig.json --noEmit --strictFunctionTypes",
|
||||
"update-distro": "node build/npm/update-distro.js",
|
||||
"web": "node scripts/code-web.js"
|
||||
},
|
||||
|
@ -45,7 +45,7 @@
|
|||
"onigasm-umd": "^2.2.4",
|
||||
"semver-umd": "^5.5.3",
|
||||
"spdlog": "^0.11.1",
|
||||
"sudo-prompt": "9.1.0",
|
||||
"sudo-prompt": "9.1.1",
|
||||
"v8-inspect-profiler": "^0.0.20",
|
||||
"vscode-minimist": "^1.2.2",
|
||||
"vscode-nsfw": "1.2.8",
|
||||
|
|
|
@ -55,5 +55,6 @@ export const BrowserFeatures = {
|
|||
return KeyboardSupport.None;
|
||||
})(),
|
||||
|
||||
touch: 'ontouchstart' in window || navigator.maxTouchPoints > 0 || window.navigator.msMaxTouchPoints > 0
|
||||
touch: 'ontouchstart' in window || navigator.maxTouchPoints > 0 || window.navigator.msMaxTouchPoints > 0,
|
||||
pointerEvents: browser.isSafari && window.PointerEvent && ('ontouchstart' in window || navigator.maxTouchPoints > 0 || window.navigator.msMaxTouchPoints > 0)
|
||||
};
|
||||
|
|
|
@ -281,6 +281,21 @@ export function addDisposableNonBubblingMouseOutListener(node: Element, handler:
|
|||
});
|
||||
}
|
||||
|
||||
export function addDisposableNonBubblingPointerOutListener(node: Element, handler: (event: MouseEvent) => void): IDisposable {
|
||||
return addDisposableListener(node, 'pointerout', (e: MouseEvent) => {
|
||||
// Mouse out bubbles, so this is an attempt to ignore faux mouse outs coming from children elements
|
||||
let toElement: Node | null = <Node>(e.relatedTarget || e.target);
|
||||
while (toElement && toElement !== node) {
|
||||
toElement = toElement.parentNode;
|
||||
}
|
||||
if (toElement === node) {
|
||||
return;
|
||||
}
|
||||
|
||||
handler(e);
|
||||
});
|
||||
}
|
||||
|
||||
interface IRequestAnimationFrame {
|
||||
(callback: (time: number) => void): number;
|
||||
}
|
||||
|
@ -428,7 +443,7 @@ export interface DOMEvent {
|
|||
}
|
||||
|
||||
const MINIMUM_TIME_MS = 16;
|
||||
const DEFAULT_EVENT_MERGER: IEventMerger<DOMEvent, DOMEvent> = function (lastEvent: DOMEvent, currentEvent: DOMEvent) {
|
||||
const DEFAULT_EVENT_MERGER: IEventMerger<DOMEvent, DOMEvent> = function (lastEvent: DOMEvent | null, currentEvent: DOMEvent) {
|
||||
return currentEvent;
|
||||
};
|
||||
|
||||
|
@ -852,6 +867,8 @@ export const EventType = {
|
|||
MOUSE_OUT: 'mouseout',
|
||||
MOUSE_ENTER: 'mouseenter',
|
||||
MOUSE_LEAVE: 'mouseleave',
|
||||
POINTER_UP: 'pointerup',
|
||||
POINTER_DOWN: 'pointerdown',
|
||||
CONTEXT_MENU: 'contextmenu',
|
||||
WHEEL: 'wheel',
|
||||
// Keyboard
|
||||
|
|
|
@ -7,6 +7,7 @@ import * as dom from 'vs/base/browser/dom';
|
|||
import { IframeUtils } from 'vs/base/browser/iframe';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { BrowserFeatures } from 'vs/base/browser/canIUse';
|
||||
|
||||
export interface IStandardMouseMoveEventData {
|
||||
leftButton: boolean;
|
||||
|
@ -15,7 +16,7 @@ export interface IStandardMouseMoveEventData {
|
|||
}
|
||||
|
||||
export interface IEventMerger<R> {
|
||||
(lastEvent: R, currentEvent: MouseEvent): R;
|
||||
(lastEvent: R | null, currentEvent: MouseEvent): R;
|
||||
}
|
||||
|
||||
export interface IMouseMoveCallback<R> {
|
||||
|
@ -26,7 +27,7 @@ export interface IOnStopCallback {
|
|||
(): void;
|
||||
}
|
||||
|
||||
export function standardMouseMoveMerger(lastEvent: IStandardMouseMoveEventData, currentEvent: MouseEvent): IStandardMouseMoveEventData {
|
||||
export function standardMouseMoveMerger(lastEvent: IStandardMouseMoveEventData | null, currentEvent: MouseEvent): IStandardMouseMoveEventData {
|
||||
let ev = new StandardMouseEvent(currentEvent);
|
||||
ev.preventDefault();
|
||||
return {
|
||||
|
@ -38,10 +39,10 @@ export function standardMouseMoveMerger(lastEvent: IStandardMouseMoveEventData,
|
|||
|
||||
export class GlobalMouseMoveMonitor<R> implements IDisposable {
|
||||
|
||||
private readonly hooks = new DisposableStore();
|
||||
private mouseMoveEventMerger: IEventMerger<R> | null = null;
|
||||
private mouseMoveCallback: IMouseMoveCallback<R> | null = null;
|
||||
private onStopCallback: IOnStopCallback | null = null;
|
||||
protected readonly hooks = new DisposableStore();
|
||||
protected mouseMoveEventMerger: IEventMerger<R> | null = null;
|
||||
protected mouseMoveCallback: IMouseMoveCallback<R> | null = null;
|
||||
protected onStopCallback: IOnStopCallback | null = null;
|
||||
|
||||
public dispose(): void {
|
||||
this.stopMonitoring(false);
|
||||
|
@ -84,12 +85,14 @@ export class GlobalMouseMoveMonitor<R> implements IDisposable {
|
|||
this.onStopCallback = onStopCallback;
|
||||
|
||||
let windowChain = IframeUtils.getSameOriginWindowChain();
|
||||
const mouseMove = BrowserFeatures.pointerEvents ? 'pointermove' : 'mousemove';
|
||||
const mouseUp = BrowserFeatures.pointerEvents ? 'pointerup' : 'mouseup';
|
||||
for (const element of windowChain) {
|
||||
this.hooks.add(dom.addDisposableThrottledListener(element.window.document, 'mousemove',
|
||||
this.hooks.add(dom.addDisposableThrottledListener(element.window.document, mouseMove,
|
||||
(data: R) => this.mouseMoveCallback!(data),
|
||||
(lastEvent: R, currentEvent) => this.mouseMoveEventMerger!(lastEvent, currentEvent as MouseEvent)
|
||||
(lastEvent: R | null, currentEvent) => this.mouseMoveEventMerger!(lastEvent, currentEvent as MouseEvent)
|
||||
));
|
||||
this.hooks.add(dom.addDisposableListener(element.window.document, 'mouseup', (e: MouseEvent) => this.stopMonitoring(true)));
|
||||
this.hooks.add(dom.addDisposableListener(element.window.document, mouseUp, (e: MouseEvent) => this.stopMonitoring(true)));
|
||||
}
|
||||
|
||||
if (IframeUtils.hasDifferentOriginAncestor()) {
|
||||
|
|
|
@ -50,19 +50,19 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
|
|||
const _href = function (href: string, isDomUri: boolean): string {
|
||||
const data = markdown.uris && markdown.uris[href];
|
||||
if (!data) {
|
||||
return href;
|
||||
return href; // no uri exists
|
||||
}
|
||||
let uri = URI.revive(data);
|
||||
if (URI.parse(href).toString() === uri.toString()) {
|
||||
return href; // no tranformation performed
|
||||
}
|
||||
if (isDomUri) {
|
||||
uri = DOM.asDomUri(uri);
|
||||
}
|
||||
if (uri.query) {
|
||||
uri = uri.with({ query: _uriMassage(uri.query) });
|
||||
}
|
||||
if (data) {
|
||||
href = uri.toString(true);
|
||||
}
|
||||
return href;
|
||||
return uri.toString();
|
||||
};
|
||||
|
||||
// signal to code-block render that the
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'vs/css!./contextview';
|
|||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IDisposable, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Range } from 'vs/base/common/range';
|
||||
import { BrowserFeatures } from 'vs/base/browser/canIUse';
|
||||
|
||||
export interface IAnchor {
|
||||
x: number;
|
||||
|
@ -178,7 +179,7 @@ export class ContextView extends Disposable {
|
|||
return;
|
||||
}
|
||||
|
||||
if (this.delegate!.canRelayout === false) {
|
||||
if (this.delegate!.canRelayout === false && !BrowserFeatures.pointerEvents) {
|
||||
this.hide();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -543,7 +543,7 @@ export function fuzzyScore(pattern: string, patternLow: string, patternStart: nu
|
|||
const patternLen = pattern.length > _maxLen ? _maxLen : pattern.length;
|
||||
const wordLen = word.length > _maxLen ? _maxLen : word.length;
|
||||
|
||||
if (patternStart >= patternLen || wordStart >= wordLen || patternLen > wordLen) {
|
||||
if (patternStart >= patternLen || wordStart >= wordLen || (patternLen - patternStart) > (wordLen - wordStart)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,11 +69,11 @@ function validateString(value: string, name: string) {
|
|||
}
|
||||
}
|
||||
|
||||
function isPathSeparator(code: number) {
|
||||
function isPathSeparator(code: number | undefined) {
|
||||
return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
|
||||
}
|
||||
|
||||
function isPosixPathSeparator(code: number) {
|
||||
function isPosixPathSeparator(code: number | undefined) {
|
||||
return code === CHAR_FORWARD_SLASH;
|
||||
}
|
||||
|
||||
|
|
|
@ -498,4 +498,9 @@ suite('Filters', () => {
|
|||
fuzzyScore
|
||||
);
|
||||
});
|
||||
|
||||
test('"Go to Symbol" with the exact method name doesn\'t work as expected #84787', function () {
|
||||
const match = fuzzyScore(':get', ':get', 1, 'get', 'get', 0, true);
|
||||
assert.ok(Boolean(match));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -438,15 +438,8 @@ export class CodeWindow extends Disposable implements ICodeWindow {
|
|||
|
||||
// Inject headers when requests are incoming
|
||||
const urls = ['https://marketplace.visualstudio.com/*', 'https://*.vsassets.io/*'];
|
||||
this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, (details, cb) => {
|
||||
this.marketplaceHeadersPromise.then(headers => {
|
||||
const requestHeaders = objects.assign(details.requestHeaders, headers) as { [key: string]: string | undefined };
|
||||
if (!this.configurationService.getValue('extensions.disableExperimentalAzureSearch')) {
|
||||
requestHeaders['Cookie'] = `${requestHeaders['Cookie'] ? requestHeaders['Cookie'] + ';' : ''}EnableExternalSearchForVSCode=true`;
|
||||
}
|
||||
cb({ cancel: false, requestHeaders });
|
||||
});
|
||||
});
|
||||
this._win.webContents.session.webRequest.onBeforeSendHeaders({ urls }, (details, cb) =>
|
||||
this.marketplaceHeadersPromise.then(headers => cb({ cancel: false, requestHeaders: objects.assign(details.requestHeaders, headers) as { [key: string]: string | undefined } })));
|
||||
}
|
||||
|
||||
private onWindowError(error: WindowError): void {
|
||||
|
|
|
@ -26,8 +26,8 @@ import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
|||
/**
|
||||
* Merges mouse events when mouse move events are throttled
|
||||
*/
|
||||
function createMouseMoveEventMerger(mouseTargetFactory: MouseTargetFactory | null) {
|
||||
return function (lastEvent: EditorMouseEvent, currentEvent: EditorMouseEvent): EditorMouseEvent {
|
||||
export function createMouseMoveEventMerger(mouseTargetFactory: MouseTargetFactory | null) {
|
||||
return function (lastEvent: EditorMouseEvent | null, currentEvent: EditorMouseEvent): EditorMouseEvent {
|
||||
let targetIsWidget = false;
|
||||
if (mouseTargetFactory) {
|
||||
targetIsWidget = mouseTargetFactory.mouseTargetIsWidget(currentEvent);
|
||||
|
@ -71,8 +71,7 @@ export class MouseHandler extends ViewEventHandler {
|
|||
protected viewHelper: IPointerHandlerHelper;
|
||||
protected mouseTargetFactory: MouseTargetFactory;
|
||||
private readonly _asyncFocus: RunOnceScheduler;
|
||||
|
||||
private readonly _mouseDownOperation: MouseDownOperation;
|
||||
protected readonly _mouseDownOperation: MouseDownOperation;
|
||||
private lastMouseLeaveTime: number;
|
||||
|
||||
constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {
|
||||
|
@ -179,7 +178,7 @@ export class MouseHandler extends ViewEventHandler {
|
|||
});
|
||||
}
|
||||
|
||||
private _onMouseMove(e: EditorMouseEvent): void {
|
||||
public _onMouseMove(e: EditorMouseEvent): void {
|
||||
if (this._mouseDownOperation.isActive()) {
|
||||
// In selection/drag operation
|
||||
return;
|
||||
|
@ -196,7 +195,7 @@ export class MouseHandler extends ViewEventHandler {
|
|||
});
|
||||
}
|
||||
|
||||
private _onMouseLeave(e: EditorMouseEvent): void {
|
||||
public _onMouseLeave(e: EditorMouseEvent): void {
|
||||
this.lastMouseLeaveTime = (new Date()).getTime();
|
||||
this.viewController.emitMouseLeave({
|
||||
event: e,
|
||||
|
|
|
@ -6,18 +6,19 @@
|
|||
import * as dom from 'vs/base/browser/dom';
|
||||
import { EventType, Gesture, GestureEvent } from 'vs/base/browser/touch';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IPointerHandlerHelper, MouseHandler } from 'vs/editor/browser/controller/mouseHandler';
|
||||
import { IPointerHandlerHelper, MouseHandler, createMouseMoveEventMerger } from 'vs/editor/browser/controller/mouseHandler';
|
||||
import { IMouseTarget } from 'vs/editor/browser/editorBrowser';
|
||||
import { EditorMouseEvent } from 'vs/editor/browser/editorDom';
|
||||
import { EditorMouseEvent, EditorPointerEventFactory } from 'vs/editor/browser/editorDom';
|
||||
import { ViewController } from 'vs/editor/browser/view/viewController';
|
||||
import { ViewContext } from 'vs/editor/common/view/viewContext';
|
||||
import { BrowserFeatures } from 'vs/base/browser/canIUse';
|
||||
|
||||
interface IThrottledGestureEvent {
|
||||
translationX: number;
|
||||
translationY: number;
|
||||
}
|
||||
|
||||
function gestureChangeEventMerger(lastEvent: IThrottledGestureEvent, currentEvent: MSGestureEvent): IThrottledGestureEvent {
|
||||
function gestureChangeEventMerger(lastEvent: IThrottledGestureEvent | null, currentEvent: MSGestureEvent): IThrottledGestureEvent {
|
||||
const r = {
|
||||
translationY: currentEvent.translationY,
|
||||
translationX: currentEvent.translationX
|
||||
|
@ -52,7 +53,7 @@ class MsPointerHandler extends MouseHandler implements IDisposable {
|
|||
const penGesture = new MSGesture();
|
||||
touchGesture.target = this.viewHelper.linesContentDomNode;
|
||||
penGesture.target = this.viewHelper.linesContentDomNode;
|
||||
this.viewHelper.linesContentDomNode.addEventListener('MSPointerDown', (e: MSPointerEvent) => {
|
||||
this.viewHelper.linesContentDomNode.addEventListener(<any>'MSPointerDown', (e: MSPointerEvent) => {
|
||||
// Circumvent IE11 breaking change in e.pointerType & TypeScript's stale definitions
|
||||
const pointerType = <any>e.pointerType;
|
||||
if (pointerType === ((<any>e).MSPOINTER_TYPE_MOUSE || 'mouse')) {
|
||||
|
@ -66,7 +67,7 @@ class MsPointerHandler extends MouseHandler implements IDisposable {
|
|||
penGesture.addPointer(e.pointerId);
|
||||
}
|
||||
});
|
||||
this._register(dom.addDisposableThrottledListener<IThrottledGestureEvent>(this.viewHelper.linesContentDomNode, 'MSGestureChange', (e) => this._onGestureChange(e), gestureChangeEventMerger));
|
||||
this._register(dom.addDisposableThrottledListener<IThrottledGestureEvent, MSGestureEvent>(this.viewHelper.linesContentDomNode, 'MSGestureChange', (e) => this._onGestureChange(e), gestureChangeEventMerger));
|
||||
this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, 'MSGestureTap', (e) => this._onCaptureGestureTap(e), true));
|
||||
}
|
||||
}, 100);
|
||||
|
@ -131,7 +132,7 @@ class StandardPointerHandler extends MouseHandler implements IDisposable {
|
|||
const penGesture = new MSGesture();
|
||||
touchGesture.target = this.viewHelper.linesContentDomNode;
|
||||
penGesture.target = this.viewHelper.linesContentDomNode;
|
||||
this.viewHelper.linesContentDomNode.addEventListener('pointerdown', (e: MSPointerEvent) => {
|
||||
this.viewHelper.linesContentDomNode.addEventListener('pointerdown', (e: PointerEvent) => {
|
||||
const pointerType = <any>e.pointerType;
|
||||
if (pointerType === 'mouse') {
|
||||
this._lastPointerType = 'mouse';
|
||||
|
@ -144,7 +145,7 @@ class StandardPointerHandler extends MouseHandler implements IDisposable {
|
|||
penGesture.addPointer(e.pointerId);
|
||||
}
|
||||
});
|
||||
this._register(dom.addDisposableThrottledListener<IThrottledGestureEvent>(this.viewHelper.linesContentDomNode, 'MSGestureChange', (e) => this._onGestureChange(e), gestureChangeEventMerger));
|
||||
this._register(dom.addDisposableThrottledListener<IThrottledGestureEvent, MSGestureEvent>(this.viewHelper.linesContentDomNode, 'MSGestureChange', (e) => this._onGestureChange(e), gestureChangeEventMerger));
|
||||
this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, 'MSGestureTap', (e) => this._onCaptureGestureTap(e), true));
|
||||
}
|
||||
}, 100);
|
||||
|
@ -185,6 +186,67 @@ class StandardPointerHandler extends MouseHandler implements IDisposable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently only tested on iOS 13/ iPadOS.
|
||||
*/
|
||||
export class PointerEventHandler extends MouseHandler {
|
||||
private _lastPointerType: string;
|
||||
constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {
|
||||
super(context, viewController, viewHelper);
|
||||
|
||||
this._register(Gesture.addTarget(this.viewHelper.linesContentDomNode));
|
||||
this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Tap, (e) => this.onTap(e)));
|
||||
this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Change, (e) => this.onChange(e)));
|
||||
this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, EventType.Contextmenu, (e: MouseEvent) => this._onContextMenu(new EditorMouseEvent(e, this.viewHelper.viewDomNode), false)));
|
||||
|
||||
this._lastPointerType = 'mouse';
|
||||
|
||||
this.viewHelper.linesContentDomNode.addEventListener('pointerdown', (e: any) => {
|
||||
const pointerType = <any>e.pointerType;
|
||||
if (pointerType === 'mouse') {
|
||||
this._lastPointerType = 'mouse';
|
||||
return;
|
||||
} else if (pointerType === 'touch') {
|
||||
this._lastPointerType = 'touch';
|
||||
} else {
|
||||
this._lastPointerType = 'pen';
|
||||
}
|
||||
});
|
||||
|
||||
// PonterEvents
|
||||
const pointerEvents = new EditorPointerEventFactory(this.viewHelper.viewDomNode);
|
||||
|
||||
this._register(pointerEvents.onPointerMoveThrottled(this.viewHelper.viewDomNode,
|
||||
(e) => this._onMouseMove(e),
|
||||
createMouseMoveEventMerger(this.mouseTargetFactory), MouseHandler.MOUSE_MOVE_MINIMUM_TIME));
|
||||
this._register(pointerEvents.onPointerUp(this.viewHelper.viewDomNode, (e) => this._onMouseUp(e)));
|
||||
this._register(pointerEvents.onPointerLeave(this.viewHelper.viewDomNode, (e) => this._onMouseLeave(e)));
|
||||
this._register(pointerEvents.onPointerDown(this.viewHelper.viewDomNode, (e) => this._onMouseDown(e)));
|
||||
}
|
||||
|
||||
private onTap(event: GestureEvent): void {
|
||||
event.preventDefault();
|
||||
this.viewHelper.focusTextArea();
|
||||
const target = this._createMouseTarget(new EditorMouseEvent(event, this.viewHelper.viewDomNode), false);
|
||||
|
||||
if (target.position) {
|
||||
this.viewController.moveTo(target.position);
|
||||
}
|
||||
}
|
||||
|
||||
private onChange(e: GestureEvent): void {
|
||||
if (this._lastPointerType === 'touch') {
|
||||
this._context.viewLayout.deltaScrollNow(-e.translationX, -e.translationY);
|
||||
}
|
||||
}
|
||||
|
||||
public _onMouseDown(e: EditorMouseEvent): void {
|
||||
if (this._lastPointerType !== 'touch') {
|
||||
super._onMouseDown(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TouchHandler extends MouseHandler {
|
||||
|
||||
constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {
|
||||
|
@ -221,6 +283,8 @@ export class PointerHandler extends Disposable {
|
|||
super();
|
||||
if (window.navigator.msPointerEnabled) {
|
||||
this.handler = this._register(new MsPointerHandler(context, viewController, viewHelper));
|
||||
} else if (((<any>window).PointerEvent && BrowserFeatures.pointerEvents)) {
|
||||
this.handler = this._register(new PointerEventHandler(context, viewController, viewHelper));
|
||||
} else if ((<any>window).TouchEvent) {
|
||||
this.handler = this._register(new TouchHandler(context, viewController, viewHelper));
|
||||
} else if (window.navigator.pointerEnabled || (<any>window).PointerEvent) {
|
||||
|
|
|
@ -16,7 +16,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
|
|||
import { IIdentifiedSingleEditOperation, IModelDecoration, IModelDeltaDecoration, ITextModel, ICursorStateComputer } from 'vs/editor/common/model';
|
||||
import { IModelContentChangedEvent, IModelDecorationsChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent } from 'vs/editor/common/model/textModelEvents';
|
||||
import { OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager';
|
||||
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
|
||||
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/linesLayout';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IDiffComputationResult } from 'vs/editor/common/services/editorWorkerService';
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ export class EditorMouseEvent extends StandardMouseEvent {
|
|||
}
|
||||
|
||||
export interface EditorMouseEventMerger {
|
||||
(lastEvent: EditorMouseEvent, currentEvent: EditorMouseEvent): EditorMouseEvent;
|
||||
(lastEvent: EditorMouseEvent | null, currentEvent: EditorMouseEvent): EditorMouseEvent;
|
||||
}
|
||||
|
||||
export class EditorMouseEventFactory {
|
||||
|
@ -124,17 +124,55 @@ export class EditorMouseEventFactory {
|
|||
}
|
||||
|
||||
public onMouseMoveThrottled(target: HTMLElement, callback: (e: EditorMouseEvent) => void, merger: EditorMouseEventMerger, minimumTimeMs: number): IDisposable {
|
||||
const myMerger: dom.IEventMerger<EditorMouseEvent, MouseEvent> = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => {
|
||||
const myMerger: dom.IEventMerger<EditorMouseEvent, MouseEvent> = (lastEvent: EditorMouseEvent | null, currentEvent: MouseEvent): EditorMouseEvent => {
|
||||
return merger(lastEvent, this._create(currentEvent));
|
||||
};
|
||||
return dom.addDisposableThrottledListener<EditorMouseEvent, MouseEvent>(target, 'mousemove', callback, myMerger, minimumTimeMs);
|
||||
}
|
||||
}
|
||||
|
||||
export class EditorPointerEventFactory {
|
||||
|
||||
private readonly _editorViewDomNode: HTMLElement;
|
||||
|
||||
constructor(editorViewDomNode: HTMLElement) {
|
||||
this._editorViewDomNode = editorViewDomNode;
|
||||
}
|
||||
|
||||
private _create(e: MouseEvent): EditorMouseEvent {
|
||||
return new EditorMouseEvent(e, this._editorViewDomNode);
|
||||
}
|
||||
|
||||
public onPointerUp(target: HTMLElement, callback: (e: EditorMouseEvent) => void): IDisposable {
|
||||
return dom.addDisposableListener(target, 'pointerup', (e: MouseEvent) => {
|
||||
callback(this._create(e));
|
||||
});
|
||||
}
|
||||
|
||||
public onPointerDown(target: HTMLElement, callback: (e: EditorMouseEvent) => void): IDisposable {
|
||||
return dom.addDisposableListener(target, 'pointerdown', (e: MouseEvent) => {
|
||||
callback(this._create(e));
|
||||
});
|
||||
}
|
||||
|
||||
public onPointerLeave(target: HTMLElement, callback: (e: EditorMouseEvent) => void): IDisposable {
|
||||
return dom.addDisposableNonBubblingPointerOutListener(target, (e: MouseEvent) => {
|
||||
callback(this._create(e));
|
||||
});
|
||||
}
|
||||
|
||||
public onPointerMoveThrottled(target: HTMLElement, callback: (e: EditorMouseEvent) => void, merger: EditorMouseEventMerger, minimumTimeMs: number): IDisposable {
|
||||
const myMerger: dom.IEventMerger<EditorMouseEvent, MouseEvent> = (lastEvent: EditorMouseEvent | null, currentEvent: MouseEvent): EditorMouseEvent => {
|
||||
return merger(lastEvent, this._create(currentEvent));
|
||||
};
|
||||
return dom.addDisposableThrottledListener<EditorMouseEvent, MouseEvent>(target, 'pointermove', callback, myMerger, minimumTimeMs);
|
||||
}
|
||||
}
|
||||
|
||||
export class GlobalEditorMouseMoveMonitor extends Disposable {
|
||||
|
||||
private readonly _editorViewDomNode: HTMLElement;
|
||||
private readonly _globalMouseMoveMonitor: GlobalMouseMoveMonitor<EditorMouseEvent>;
|
||||
protected readonly _globalMouseMoveMonitor: GlobalMouseMoveMonitor<EditorMouseEvent>;
|
||||
private _keydownListener: IDisposable | null;
|
||||
|
||||
constructor(editorViewDomNode: HTMLElement) {
|
||||
|
@ -157,7 +195,7 @@ export class GlobalEditorMouseMoveMonitor extends Disposable {
|
|||
this._globalMouseMoveMonitor.stopMonitoring(true);
|
||||
}, true);
|
||||
|
||||
const myMerger: dom.IEventMerger<EditorMouseEvent, MouseEvent> = (lastEvent: EditorMouseEvent, currentEvent: MouseEvent): EditorMouseEvent => {
|
||||
const myMerger: dom.IEventMerger<EditorMouseEvent, MouseEvent> = (lastEvent: EditorMouseEvent | null, currentEvent: MouseEvent): EditorMouseEvent => {
|
||||
return merger(lastEvent, new EditorMouseEvent(currentEvent, this._editorViewDomNode));
|
||||
};
|
||||
|
||||
|
|
|
@ -307,7 +307,7 @@ export function registerEditorContribution<Services extends BrandedService[]>(id
|
|||
EditorContributionRegistry.INSTANCE.registerEditorContribution(id, ctor);
|
||||
}
|
||||
|
||||
export function registerDiffEditorContribution(id: string, ctor: IDiffEditorContributionCtor): void {
|
||||
export function registerDiffEditorContribution<Services extends BrandedService[]>(id: string, ctor: { new(editor: IDiffEditor, ...services: Services): IEditorContribution }): void {
|
||||
EditorContributionRegistry.INSTANCE.registerDiffEditorContribution(id, ctor);
|
||||
}
|
||||
|
||||
|
@ -363,7 +363,7 @@ class EditorContributionRegistry {
|
|||
return this.editorContributions.slice(0);
|
||||
}
|
||||
|
||||
public registerDiffEditorContribution(id: string, ctor: IDiffEditorContributionCtor): void {
|
||||
public registerDiffEditorContribution<Services extends BrandedService[]>(id: string, ctor: { new(editor: IDiffEditor, ...services: Services): IEditorContribution }): void {
|
||||
this.diffEditorContributions.push({ id, ctor });
|
||||
}
|
||||
|
||||
|
|
|
@ -4,58 +4,132 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as dom from 'vs/base/browser/dom';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { LinkedList } from 'vs/base/common/linkedList';
|
||||
import { parse } from 'vs/base/common/marshalling';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import { equalsIgnoreCase } from 'vs/base/common/strings';
|
||||
import { normalizePath } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IOpener, IOpenerService, IValidator, IExternalUriResolver, OpenOptions, ResolveExternalUriOptions, IResolvedExternalUri, IExternalOpener } from 'vs/platform/opener/common/opener';
|
||||
import { IOpener, IOpenerService, IValidator, IExternalUriResolver, OpenOptions, ResolveExternalUriOptions, IResolvedExternalUri, IExternalOpener, matchesScheme } from 'vs/platform/opener/common/opener';
|
||||
import { EditorOpenContext } from 'vs/platform/editor/common/editor';
|
||||
|
||||
export class OpenerService extends Disposable implements IOpenerService {
|
||||
|
||||
class CommandOpener implements IOpener {
|
||||
|
||||
constructor(@ICommandService private readonly _commandService: ICommandService) { }
|
||||
|
||||
async open(target: URI | string) {
|
||||
if (!matchesScheme(target, Schemas.command)) {
|
||||
return false;
|
||||
}
|
||||
// run command or bail out if command isn't known
|
||||
if (typeof target === 'string') {
|
||||
target = URI.parse(target);
|
||||
}
|
||||
if (!CommandsRegistry.getCommand(target.path)) {
|
||||
throw new Error(`command '${target.path}' NOT known`);
|
||||
}
|
||||
// execute as command
|
||||
let args: any = [];
|
||||
try {
|
||||
args = parse(target.query);
|
||||
if (!Array.isArray(args)) {
|
||||
args = [args];
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore error
|
||||
}
|
||||
await this._commandService.executeCommand(target.path, ...args);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class EditorOpener implements IOpener {
|
||||
|
||||
constructor(@ICodeEditorService private readonly _editorService: ICodeEditorService) { }
|
||||
|
||||
async open(target: URI | string, options: OpenOptions) {
|
||||
if (typeof target === 'string') {
|
||||
target = URI.parse(target);
|
||||
}
|
||||
let selection: { startLineNumber: number; startColumn: number; } | undefined = undefined;
|
||||
const match = /^L?(\d+)(?:,(\d+))?/.exec(target.fragment);
|
||||
if (match) {
|
||||
// support file:///some/file.js#73,84
|
||||
// support file:///some/file.js#L73
|
||||
selection = {
|
||||
startLineNumber: parseInt(match[1]),
|
||||
startColumn: match[2] ? parseInt(match[2]) : 1
|
||||
};
|
||||
// remove fragment
|
||||
target = target.with({ fragment: '' });
|
||||
}
|
||||
|
||||
if (target.scheme === Schemas.file) {
|
||||
target = normalizePath(target); // workaround for non-normalized paths (https://github.com/Microsoft/vscode/issues/12954)
|
||||
}
|
||||
|
||||
await this._editorService.openCodeEditor(
|
||||
{ resource: target, options: { selection, context: options?.fromUserGesture ? EditorOpenContext.USER : EditorOpenContext.API } },
|
||||
this._editorService.getFocusedCodeEditor(),
|
||||
options?.openToSide
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export class OpenerService implements IOpenerService {
|
||||
|
||||
_serviceBrand: undefined;
|
||||
|
||||
private readonly _openers = new LinkedList<IOpener>();
|
||||
private readonly _validators = new LinkedList<IValidator>();
|
||||
private readonly _resolvers = new LinkedList<IExternalUriResolver>();
|
||||
|
||||
private _externalOpener: IExternalOpener;
|
||||
|
||||
constructor(
|
||||
@ICodeEditorService private readonly _editorService: ICodeEditorService,
|
||||
@ICommandService private readonly _commandService: ICommandService,
|
||||
@ICodeEditorService editorService: ICodeEditorService,
|
||||
@ICommandService commandService: ICommandService,
|
||||
) {
|
||||
super();
|
||||
|
||||
// Default external opener is going through window.open()
|
||||
this._externalOpener = {
|
||||
openExternal: href => {
|
||||
dom.windowOpenNoOpener(href);
|
||||
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
};
|
||||
|
||||
// Default opener: maito, http(s), command, and catch-all-editors
|
||||
this._openers.push({
|
||||
open: async (target: URI | string, options?: OpenOptions) => {
|
||||
if (options?.openExternal || matchesScheme(target, Schemas.mailto) || matchesScheme(target, Schemas.http) || matchesScheme(target, Schemas.https)) {
|
||||
// open externally
|
||||
await this._doOpenExternal(target, options);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
this._openers.push(new CommandOpener(commandService));
|
||||
this._openers.push(new EditorOpener(editorService));
|
||||
}
|
||||
|
||||
registerOpener(opener: IOpener): IDisposable {
|
||||
const remove = this._openers.push(opener);
|
||||
|
||||
const remove = this._openers.unshift(opener);
|
||||
return { dispose: remove };
|
||||
}
|
||||
|
||||
registerValidator(validator: IValidator): IDisposable {
|
||||
const remove = this._validators.push(validator);
|
||||
|
||||
return { dispose: remove };
|
||||
}
|
||||
|
||||
registerExternalUriResolver(resolver: IExternalUriResolver): IDisposable {
|
||||
const remove = this._resolvers.push(resolver);
|
||||
|
||||
return { dispose: remove };
|
||||
}
|
||||
|
||||
|
@ -63,30 +137,24 @@ export class OpenerService extends Disposable implements IOpenerService {
|
|||
this._externalOpener = externalOpener;
|
||||
}
|
||||
|
||||
async open(resource: URI, options?: OpenOptions): Promise<boolean> {
|
||||
|
||||
// no scheme ?!?
|
||||
if (!resource.scheme) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
async open(target: URI | string, options?: OpenOptions): Promise<boolean> {
|
||||
|
||||
// check with contributed validators
|
||||
for (const validator of this._validators.toArray()) {
|
||||
if (!(await validator.shouldOpen(resource))) {
|
||||
if (!(await validator.shouldOpen(target))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// check with contributed openers
|
||||
for (const opener of this._openers.toArray()) {
|
||||
const handled = await opener.open(resource, options);
|
||||
const handled = await opener.open(target, options);
|
||||
if (handled) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// use default openers
|
||||
return this._doOpen(resource, options);
|
||||
return false;
|
||||
}
|
||||
|
||||
async resolveExternalUri(resource: URI, options?: ResolveExternalUriOptions): Promise<IResolvedExternalUri> {
|
||||
|
@ -100,68 +168,19 @@ export class OpenerService extends Disposable implements IOpenerService {
|
|||
return { resolved: resource, dispose: () => { } };
|
||||
}
|
||||
|
||||
private async _doOpen(resource: URI, options: OpenOptions | undefined): Promise<boolean> {
|
||||
const { scheme, path, query, fragment } = resource;
|
||||
private async _doOpenExternal(resource: URI | string, options: OpenOptions | undefined): Promise<boolean> {
|
||||
|
||||
if (options?.openExternal || equalsIgnoreCase(scheme, Schemas.mailto) || equalsIgnoreCase(scheme, Schemas.http) || equalsIgnoreCase(scheme, Schemas.https)) {
|
||||
// open externally
|
||||
return this._doOpenExternal(resource, options);
|
||||
//todo@joh IExternalUriResolver should support `uri: URI | string`
|
||||
const uri = typeof resource === 'string' ? URI.parse(resource) : resource;
|
||||
const { resolved } = await this.resolveExternalUri(uri, options);
|
||||
|
||||
if (typeof resource === 'string' && uri.toString() === resolved.toString()) {
|
||||
// open the url-string AS IS
|
||||
return this._externalOpener.openExternal(resource);
|
||||
} else {
|
||||
// open URI using the toString(noEncode)+encodeURI-trick
|
||||
return this._externalOpener.openExternal(encodeURI(resolved.toString(true)));
|
||||
}
|
||||
|
||||
if (equalsIgnoreCase(scheme, Schemas.command)) {
|
||||
// run command or bail out if command isn't known
|
||||
if (!CommandsRegistry.getCommand(path)) {
|
||||
throw new Error(`command '${path}' NOT known`);
|
||||
}
|
||||
// execute as command
|
||||
let args: any = [];
|
||||
try {
|
||||
args = parse(query);
|
||||
if (!Array.isArray(args)) {
|
||||
args = [args];
|
||||
}
|
||||
} catch (e) {
|
||||
// ignore error
|
||||
}
|
||||
|
||||
await this._commandService.executeCommand(path, ...args);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// finally open in editor
|
||||
let selection: { startLineNumber: number; startColumn: number; } | undefined = undefined;
|
||||
const match = /^L?(\d+)(?:,(\d+))?/.exec(fragment);
|
||||
if (match) {
|
||||
// support file:///some/file.js#73,84
|
||||
// support file:///some/file.js#L73
|
||||
selection = {
|
||||
startLineNumber: parseInt(match[1]),
|
||||
startColumn: match[2] ? parseInt(match[2]) : 1
|
||||
};
|
||||
// remove fragment
|
||||
resource = resource.with({ fragment: '' });
|
||||
}
|
||||
|
||||
if (resource.scheme === Schemas.file) {
|
||||
resource = resources.normalizePath(resource); // workaround for non-normalized paths (https://github.com/Microsoft/vscode/issues/12954)
|
||||
}
|
||||
|
||||
await this._editorService.openCodeEditor(
|
||||
{ resource, options: { selection, context: options?.fromUserGesture ? EditorOpenContext.USER : EditorOpenContext.API } },
|
||||
this._editorService.getFocusedCodeEditor(),
|
||||
options?.openToSide
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async _doOpenExternal(resource: URI, options: OpenOptions | undefined): Promise<boolean> {
|
||||
const { resolved } = await this.resolveExternalUri(resource, options);
|
||||
|
||||
// TODO@Jo neither encodeURI nor toString(true) should be needed
|
||||
// once we go with URL and not URI
|
||||
return this._externalOpener.openExternal(encodeURI(resolved.toString(true)));
|
||||
}
|
||||
|
||||
dispose() {
|
||||
|
|
|
@ -11,7 +11,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
|||
import { IPointerHandlerHelper } from 'vs/editor/browser/controller/mouseHandler';
|
||||
import { PointerHandler } from 'vs/editor/browser/controller/pointerHandler';
|
||||
import { ITextAreaHandlerHelper, TextAreaHandler } from 'vs/editor/browser/controller/textAreaHandler';
|
||||
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
|
||||
import { IContentWidget, IContentWidgetPosition, IOverlayWidget, IOverlayWidgetPosition, IMouseTarget, IViewZoneChangeAccessor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICommandDelegate, ViewController } from 'vs/editor/browser/view/viewController';
|
||||
import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents';
|
||||
import { ContentViewOverlays, MarginViewOverlays } from 'vs/editor/browser/view/viewOverlays';
|
||||
|
@ -51,17 +51,15 @@ import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
|||
|
||||
|
||||
export interface IContentWidgetData {
|
||||
widget: editorBrowser.IContentWidget;
|
||||
position: editorBrowser.IContentWidgetPosition | null;
|
||||
widget: IContentWidget;
|
||||
position: IContentWidgetPosition | null;
|
||||
}
|
||||
|
||||
export interface IOverlayWidgetData {
|
||||
widget: editorBrowser.IOverlayWidget;
|
||||
position: editorBrowser.IOverlayWidgetPosition | null;
|
||||
widget: IOverlayWidget;
|
||||
position: IOverlayWidgetPosition | null;
|
||||
}
|
||||
|
||||
const invalidFunc = () => { throw new Error(`Invalid change accessor`); };
|
||||
|
||||
export class View extends ViewEventHandler {
|
||||
|
||||
private readonly eventDispatcher: ViewEventDispatcher;
|
||||
|
@ -348,7 +346,7 @@ export class View extends ViewEventHandler {
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
private _renderOnce(callback: () => any): any {
|
||||
private _renderOnce<T>(callback: () => T): T {
|
||||
const r = safeInvokeNoArg(callback);
|
||||
this._scheduleRender();
|
||||
return r;
|
||||
|
@ -458,7 +456,7 @@ export class View extends ViewEventHandler {
|
|||
return visibleRange.left;
|
||||
}
|
||||
|
||||
public getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget | null {
|
||||
public getTargetAtClientPoint(clientX: number, clientY: number): IMouseTarget | null {
|
||||
return this.pointerHandler.getTargetAtClientPoint(clientX, clientY);
|
||||
}
|
||||
|
||||
|
@ -466,42 +464,15 @@ export class View extends ViewEventHandler {
|
|||
return new OverviewRuler(this._context, cssClassName);
|
||||
}
|
||||
|
||||
public change(callback: (changeAccessor: editorBrowser.IViewZoneChangeAccessor) => any): boolean {
|
||||
let zonesHaveChanged = false;
|
||||
|
||||
this._renderOnce(() => {
|
||||
const changeAccessor: editorBrowser.IViewZoneChangeAccessor = {
|
||||
addZone: (zone: editorBrowser.IViewZone): string => {
|
||||
zonesHaveChanged = true;
|
||||
return this.viewZones.addZone(zone);
|
||||
},
|
||||
removeZone: (id: string): void => {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
zonesHaveChanged = this.viewZones.removeZone(id) || zonesHaveChanged;
|
||||
},
|
||||
layoutZone: (id: string): void => {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
zonesHaveChanged = this.viewZones.layoutZone(id) || zonesHaveChanged;
|
||||
}
|
||||
};
|
||||
|
||||
safeInvoke1Arg(callback, changeAccessor);
|
||||
|
||||
// Invalidate changeAccessor
|
||||
changeAccessor.addZone = invalidFunc;
|
||||
changeAccessor.removeZone = invalidFunc;
|
||||
changeAccessor.layoutZone = invalidFunc;
|
||||
|
||||
public change(callback: (changeAccessor: IViewZoneChangeAccessor) => any): boolean {
|
||||
return this._renderOnce(() => {
|
||||
const zonesHaveChanged = this.viewZones.changeViewZones(callback);
|
||||
if (zonesHaveChanged) {
|
||||
this._context.viewLayout.onHeightMaybeChanged();
|
||||
this._context.privateViewEventBus.emit(new viewEvents.ViewZonesChangedEvent());
|
||||
}
|
||||
return zonesHaveChanged;
|
||||
});
|
||||
return zonesHaveChanged;
|
||||
}
|
||||
|
||||
public render(now: boolean, everything: boolean): void {
|
||||
|
@ -582,10 +553,3 @@ function safeInvokeNoArg(func: Function): any {
|
|||
}
|
||||
}
|
||||
|
||||
function safeInvoke1Arg(func: Function, arg1: any): any {
|
||||
try {
|
||||
return func(arg1);
|
||||
} catch (e) {
|
||||
onUnexpectedError(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -407,7 +407,7 @@ class FastRenderedViewLine implements IRenderedViewLine {
|
|||
*/
|
||||
class RenderedViewLine implements IRenderedViewLine {
|
||||
|
||||
public domNode: FastDomNode<HTMLElement>;
|
||||
public domNode: FastDomNode<HTMLElement> | null;
|
||||
public readonly input: RenderLineInput;
|
||||
|
||||
protected readonly _characterMapping: CharacterMapping;
|
||||
|
@ -420,7 +420,7 @@ class RenderedViewLine implements IRenderedViewLine {
|
|||
*/
|
||||
private readonly _pixelOffsetCache: Int32Array | null;
|
||||
|
||||
constructor(domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType) {
|
||||
constructor(domNode: FastDomNode<HTMLElement> | null, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType) {
|
||||
this.domNode = domNode;
|
||||
this.input = renderLineInput;
|
||||
this._characterMapping = characterMapping;
|
||||
|
@ -439,16 +439,19 @@ class RenderedViewLine implements IRenderedViewLine {
|
|||
|
||||
// --- Reading from the DOM methods
|
||||
|
||||
protected _getReadingTarget(): HTMLElement {
|
||||
return <HTMLSpanElement>this.domNode.domNode.firstChild;
|
||||
protected _getReadingTarget(myDomNode: FastDomNode<HTMLElement>): HTMLElement {
|
||||
return <HTMLSpanElement>myDomNode.domNode.firstChild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Width of the line in pixels
|
||||
*/
|
||||
public getWidth(): number {
|
||||
if (!this.domNode) {
|
||||
return 0;
|
||||
}
|
||||
if (this._cachedWidth === -1) {
|
||||
this._cachedWidth = this._getReadingTarget().offsetWidth;
|
||||
this._cachedWidth = this._getReadingTarget(this.domNode).offsetWidth;
|
||||
}
|
||||
return this._cachedWidth;
|
||||
}
|
||||
|
@ -464,14 +467,17 @@ class RenderedViewLine implements IRenderedViewLine {
|
|||
* Visible ranges for a model range
|
||||
*/
|
||||
public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
|
||||
if (!this.domNode) {
|
||||
return null;
|
||||
}
|
||||
if (this._pixelOffsetCache !== null) {
|
||||
// the text is LTR
|
||||
const startOffset = this._readPixelOffset(startColumn, context);
|
||||
const startOffset = this._readPixelOffset(this.domNode, startColumn, context);
|
||||
if (startOffset === -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const endOffset = this._readPixelOffset(endColumn, context);
|
||||
const endOffset = this._readPixelOffset(this.domNode, endColumn, context);
|
||||
if (endOffset === -1) {
|
||||
return null;
|
||||
}
|
||||
|
@ -479,23 +485,23 @@ class RenderedViewLine implements IRenderedViewLine {
|
|||
return [new HorizontalRange(startOffset, endOffset - startOffset)];
|
||||
}
|
||||
|
||||
return this._readVisibleRangesForRange(startColumn, endColumn, context);
|
||||
return this._readVisibleRangesForRange(this.domNode, startColumn, endColumn, context);
|
||||
}
|
||||
|
||||
protected _readVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
|
||||
protected _readVisibleRangesForRange(domNode: FastDomNode<HTMLElement>, startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
|
||||
if (startColumn === endColumn) {
|
||||
const pixelOffset = this._readPixelOffset(startColumn, context);
|
||||
const pixelOffset = this._readPixelOffset(domNode, startColumn, context);
|
||||
if (pixelOffset === -1) {
|
||||
return null;
|
||||
} else {
|
||||
return [new HorizontalRange(pixelOffset, 0)];
|
||||
}
|
||||
} else {
|
||||
return this._readRawVisibleRangesForRange(startColumn, endColumn, context);
|
||||
return this._readRawVisibleRangesForRange(domNode, startColumn, endColumn, context);
|
||||
}
|
||||
}
|
||||
|
||||
protected _readPixelOffset(column: number, context: DomReadingContext): number {
|
||||
protected _readPixelOffset(domNode: FastDomNode<HTMLElement>, column: number, context: DomReadingContext): number {
|
||||
if (this._characterMapping.length === 0) {
|
||||
// This line has no content
|
||||
if (this._containsForeignElements === ForeignElementType.None) {
|
||||
|
@ -520,18 +526,18 @@ class RenderedViewLine implements IRenderedViewLine {
|
|||
return cachedPixelOffset;
|
||||
}
|
||||
|
||||
const result = this._actualReadPixelOffset(column, context);
|
||||
const result = this._actualReadPixelOffset(domNode, column, context);
|
||||
this._pixelOffsetCache[column] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
return this._actualReadPixelOffset(column, context);
|
||||
return this._actualReadPixelOffset(domNode, column, context);
|
||||
}
|
||||
|
||||
private _actualReadPixelOffset(column: number, context: DomReadingContext): number {
|
||||
private _actualReadPixelOffset(domNode: FastDomNode<HTMLElement>, column: number, context: DomReadingContext): number {
|
||||
if (this._characterMapping.length === 0) {
|
||||
// This line has no content
|
||||
const r = RangeUtil.readHorizontalRanges(this._getReadingTarget(), 0, 0, 0, 0, context.clientRectDeltaLeft, context.endNode);
|
||||
const r = RangeUtil.readHorizontalRanges(this._getReadingTarget(domNode), 0, 0, 0, 0, context.clientRectDeltaLeft, context.endNode);
|
||||
if (!r || r.length === 0) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -547,14 +553,14 @@ class RenderedViewLine implements IRenderedViewLine {
|
|||
const partIndex = CharacterMapping.getPartIndex(partData);
|
||||
const charOffsetInPart = CharacterMapping.getCharIndex(partData);
|
||||
|
||||
const r = RangeUtil.readHorizontalRanges(this._getReadingTarget(), partIndex, charOffsetInPart, partIndex, charOffsetInPart, context.clientRectDeltaLeft, context.endNode);
|
||||
const r = RangeUtil.readHorizontalRanges(this._getReadingTarget(domNode), partIndex, charOffsetInPart, partIndex, charOffsetInPart, context.clientRectDeltaLeft, context.endNode);
|
||||
if (!r || r.length === 0) {
|
||||
return -1;
|
||||
}
|
||||
return r[0].left;
|
||||
}
|
||||
|
||||
private _readRawVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
|
||||
private _readRawVisibleRangesForRange(domNode: FastDomNode<HTMLElement>, startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
|
||||
|
||||
if (startColumn === 1 && endColumn === this._characterMapping.length) {
|
||||
// This branch helps IE with bidi text & gives a performance boost to other browsers when reading visible ranges for an entire line
|
||||
|
@ -570,7 +576,7 @@ class RenderedViewLine implements IRenderedViewLine {
|
|||
const endPartIndex = CharacterMapping.getPartIndex(endPartData);
|
||||
const endCharOffsetInPart = CharacterMapping.getCharIndex(endPartData);
|
||||
|
||||
return RangeUtil.readHorizontalRanges(this._getReadingTarget(), startPartIndex, startCharOffsetInPart, endPartIndex, endCharOffsetInPart, context.clientRectDeltaLeft, context.endNode);
|
||||
return RangeUtil.readHorizontalRanges(this._getReadingTarget(domNode), startPartIndex, startCharOffsetInPart, endPartIndex, endCharOffsetInPart, context.clientRectDeltaLeft, context.endNode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -591,8 +597,8 @@ class RenderedViewLine implements IRenderedViewLine {
|
|||
}
|
||||
|
||||
class WebKitRenderedViewLine extends RenderedViewLine {
|
||||
protected _readVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
|
||||
const output = super._readVisibleRangesForRange(startColumn, endColumn, context);
|
||||
protected _readVisibleRangesForRange(domNode: FastDomNode<HTMLElement>, startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
|
||||
const output = super._readVisibleRangesForRange(domNode, startColumn, endColumn, context);
|
||||
|
||||
if (!output || output.length === 0 || startColumn === endColumn || (startColumn === 1 && endColumn === this._characterMapping.length)) {
|
||||
return output;
|
||||
|
@ -603,7 +609,7 @@ class WebKitRenderedViewLine extends RenderedViewLine {
|
|||
if (!this.input.containsRTL) {
|
||||
// This is an attempt to patch things up
|
||||
// Find position of last column
|
||||
const endPixelOffset = this._readPixelOffset(endColumn, context);
|
||||
const endPixelOffset = this._readPixelOffset(domNode, endColumn, context);
|
||||
if (endPixelOffset !== -1) {
|
||||
const lastRange = output[output.length - 1];
|
||||
if (lastRange.left < endPixelOffset) {
|
||||
|
@ -624,10 +630,10 @@ const createRenderedLine: (domNode: FastDomNode<HTMLElement> | null, renderLineI
|
|||
return createNormalRenderedLine;
|
||||
})();
|
||||
|
||||
function createWebKitRenderedLine(domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType): RenderedViewLine {
|
||||
function createWebKitRenderedLine(domNode: FastDomNode<HTMLElement> | null, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType): RenderedViewLine {
|
||||
return new WebKitRenderedViewLine(domNode, renderLineInput, characterMapping, containsRTL, containsForeignElements);
|
||||
}
|
||||
|
||||
function createNormalRenderedLine(domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType): RenderedViewLine {
|
||||
function createNormalRenderedLine(domNode: FastDomNode<HTMLElement> | null, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType): RenderedViewLine {
|
||||
return new RenderedViewLine(domNode, renderLineInput, characterMapping, containsRTL, containsForeignElements);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { IViewZone } from 'vs/editor/browser/editorBrowser';
|
||||
import { IViewZone, IViewZoneChangeAccessor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ViewPart } from 'vs/editor/browser/view/viewPart';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
|
||||
|
@ -13,7 +13,7 @@ import { ViewContext } from 'vs/editor/common/view/viewContext';
|
|||
import * as viewEvents from 'vs/editor/common/view/viewEvents';
|
||||
import { IViewWhitespaceViewportData } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
|
||||
import { IWhitespaceChangeAccessor, IEditorWhitespace } from 'vs/editor/common/viewLayout/linesLayout';
|
||||
|
||||
export interface IMyViewZone {
|
||||
whitespaceId: string;
|
||||
|
@ -29,6 +29,8 @@ interface IComputedViewZoneProps {
|
|||
minWidthInPx: number;
|
||||
}
|
||||
|
||||
const invalidFunc = () => { throw new Error(`Invalid change accessor`); };
|
||||
|
||||
export class ViewZones extends ViewPart {
|
||||
|
||||
private _zones: { [id: string]: IMyViewZone; };
|
||||
|
@ -72,20 +74,29 @@ export class ViewZones extends ViewPart {
|
|||
// ---- begin view event handlers
|
||||
|
||||
private _recomputeWhitespacesProps(): boolean {
|
||||
let hadAChange = false;
|
||||
|
||||
const keys = Object.keys(this._zones);
|
||||
for (let i = 0, len = keys.length; i < len; i++) {
|
||||
const id = keys[i];
|
||||
const zone = this._zones[id];
|
||||
const props = this._computeWhitespaceProps(zone.delegate);
|
||||
if (this._context.viewLayout.changeWhitespace(id, props.afterViewLineNumber, props.heightInPx)) {
|
||||
this._safeCallOnComputedHeight(zone.delegate, props.heightInPx);
|
||||
hadAChange = true;
|
||||
}
|
||||
const whitespaces = this._context.viewLayout.getWhitespaces();
|
||||
const oldWhitespaces = new Map<string, IEditorWhitespace>();
|
||||
for (const whitespace of whitespaces) {
|
||||
oldWhitespaces.set(whitespace.id, whitespace);
|
||||
}
|
||||
return this._context.viewLayout.changeWhitespace((whitespaceAccessor: IWhitespaceChangeAccessor) => {
|
||||
let hadAChange = false;
|
||||
|
||||
return hadAChange;
|
||||
const keys = Object.keys(this._zones);
|
||||
for (let i = 0, len = keys.length; i < len; i++) {
|
||||
const id = keys[i];
|
||||
const zone = this._zones[id];
|
||||
const props = this._computeWhitespaceProps(zone.delegate);
|
||||
const oldWhitespace = oldWhitespaces.get(id);
|
||||
if (oldWhitespace && (oldWhitespace.afterLineNumber !== props.afterViewLineNumber || oldWhitespace.height !== props.heightInPx)) {
|
||||
whitespaceAccessor.changeOneWhitespace(id, props.afterViewLineNumber, props.heightInPx);
|
||||
this._safeCallOnComputedHeight(zone.delegate, props.heightInPx);
|
||||
hadAChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hadAChange;
|
||||
});
|
||||
}
|
||||
|
||||
public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {
|
||||
|
@ -138,7 +149,6 @@ export class ViewZones extends ViewPart {
|
|||
return 10000;
|
||||
}
|
||||
|
||||
|
||||
private _computeWhitespaceProps(zone: IViewZone): IComputedViewZoneProps {
|
||||
if (zone.afterLineNumber === 0) {
|
||||
return {
|
||||
|
@ -188,9 +198,44 @@ export class ViewZones extends ViewPart {
|
|||
};
|
||||
}
|
||||
|
||||
public addZone(zone: IViewZone): string {
|
||||
public changeViewZones(callback: (changeAccessor: IViewZoneChangeAccessor) => any): boolean {
|
||||
|
||||
return this._context.viewLayout.changeWhitespace((whitespaceAccessor: IWhitespaceChangeAccessor) => {
|
||||
let zonesHaveChanged = false;
|
||||
|
||||
const changeAccessor: IViewZoneChangeAccessor = {
|
||||
addZone: (zone: IViewZone): string => {
|
||||
zonesHaveChanged = true;
|
||||
return this._addZone(whitespaceAccessor, zone);
|
||||
},
|
||||
removeZone: (id: string): void => {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
zonesHaveChanged = this._removeZone(whitespaceAccessor, id) || zonesHaveChanged;
|
||||
},
|
||||
layoutZone: (id: string): void => {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
zonesHaveChanged = this._layoutZone(whitespaceAccessor, id) || zonesHaveChanged;
|
||||
}
|
||||
};
|
||||
|
||||
safeInvoke1Arg(callback, changeAccessor);
|
||||
|
||||
// Invalidate changeAccessor
|
||||
changeAccessor.addZone = invalidFunc;
|
||||
changeAccessor.removeZone = invalidFunc;
|
||||
changeAccessor.layoutZone = invalidFunc;
|
||||
|
||||
return zonesHaveChanged;
|
||||
});
|
||||
}
|
||||
|
||||
private _addZone(whitespaceAccessor: IWhitespaceChangeAccessor, zone: IViewZone): string {
|
||||
const props = this._computeWhitespaceProps(zone);
|
||||
const whitespaceId = this._context.viewLayout.addWhitespace(props.afterViewLineNumber, this._getZoneOrdinal(zone), props.heightInPx, props.minWidthInPx);
|
||||
const whitespaceId = whitespaceAccessor.insertWhitespace(props.afterViewLineNumber, this._getZoneOrdinal(zone), props.heightInPx, props.minWidthInPx);
|
||||
|
||||
const myZone: IMyViewZone = {
|
||||
whitespaceId: whitespaceId,
|
||||
|
@ -224,11 +269,11 @@ export class ViewZones extends ViewPart {
|
|||
return myZone.whitespaceId;
|
||||
}
|
||||
|
||||
public removeZone(id: string): boolean {
|
||||
private _removeZone(whitespaceAccessor: IWhitespaceChangeAccessor, id: string): boolean {
|
||||
if (this._zones.hasOwnProperty(id)) {
|
||||
const zone = this._zones[id];
|
||||
delete this._zones[id];
|
||||
this._context.viewLayout.removeWhitespace(zone.whitespaceId);
|
||||
whitespaceAccessor.removeWhitespace(zone.whitespaceId);
|
||||
|
||||
zone.domNode.removeAttribute('monaco-visible-view-zone');
|
||||
zone.domNode.removeAttribute('monaco-view-zone');
|
||||
|
@ -247,21 +292,20 @@ export class ViewZones extends ViewPart {
|
|||
return false;
|
||||
}
|
||||
|
||||
public layoutZone(id: string): boolean {
|
||||
let changed = false;
|
||||
private _layoutZone(whitespaceAccessor: IWhitespaceChangeAccessor, id: string): boolean {
|
||||
if (this._zones.hasOwnProperty(id)) {
|
||||
const zone = this._zones[id];
|
||||
const props = this._computeWhitespaceProps(zone.delegate);
|
||||
// const newOrdinal = this._getZoneOrdinal(zone.delegate);
|
||||
changed = this._context.viewLayout.changeWhitespace(zone.whitespaceId, props.afterViewLineNumber, props.heightInPx) || changed;
|
||||
whitespaceAccessor.changeOneWhitespace(zone.whitespaceId, props.afterViewLineNumber, props.heightInPx);
|
||||
// TODO@Alex: change `newOrdinal` too
|
||||
|
||||
if (changed) {
|
||||
this._safeCallOnComputedHeight(zone.delegate, props.heightInPx);
|
||||
this.setShouldRender();
|
||||
}
|
||||
this._safeCallOnComputedHeight(zone.delegate, props.heightInPx);
|
||||
this.setShouldRender();
|
||||
|
||||
return true;
|
||||
}
|
||||
return changed;
|
||||
return false;
|
||||
}
|
||||
|
||||
public shouldSuppressMouseDownOnViewZone(id: string): boolean {
|
||||
|
@ -365,3 +409,11 @@ export class ViewZones extends ViewPart {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function safeInvoke1Arg(func: Function, arg1: any): any {
|
||||
try {
|
||||
return func(arg1);
|
||||
} catch (e) {
|
||||
onUnexpectedError(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ import * as modes from 'vs/editor/common/modes';
|
|||
import { editorUnnecessaryCodeBorder, editorUnnecessaryCodeOpacity } from 'vs/editor/common/view/editorColorRegistry';
|
||||
import { editorErrorBorder, editorErrorForeground, editorHintBorder, editorHintForeground, editorInfoBorder, editorInfoForeground, editorWarningBorder, editorWarningForeground, editorForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { VerticalRevealType } from 'vs/editor/common/view/viewEvents';
|
||||
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
|
||||
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/linesLayout';
|
||||
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
|
|
|
@ -32,7 +32,7 @@ import { IDiffComputationResult, IEditorWorkerService } from 'vs/editor/common/s
|
|||
import { OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager';
|
||||
import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations';
|
||||
import { RenderLineInput, renderViewLine } from 'vs/editor/common/viewLayout/viewLineRenderer';
|
||||
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
|
||||
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/linesLayout';
|
||||
import { InlineDecoration, InlineDecorationType, ViewLineRenderingData } from 'vs/editor/common/viewModel/viewModel';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
@ -1376,12 +1376,16 @@ abstract class ViewZonesComputer {
|
|||
|
||||
private readonly lineChanges: editorCommon.ILineChange[];
|
||||
private readonly originalForeignVZ: IEditorWhitespace[];
|
||||
private readonly originalLineHeight: number;
|
||||
private readonly modifiedForeignVZ: IEditorWhitespace[];
|
||||
private readonly modifiedLineHeight: number;
|
||||
|
||||
constructor(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], modifiedForeignVZ: IEditorWhitespace[]) {
|
||||
constructor(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], originalLineHeight: number, modifiedForeignVZ: IEditorWhitespace[], modifiedLineHeight: number) {
|
||||
this.lineChanges = lineChanges;
|
||||
this.originalForeignVZ = originalForeignVZ;
|
||||
this.originalLineHeight = originalLineHeight;
|
||||
this.modifiedForeignVZ = modifiedForeignVZ;
|
||||
this.modifiedLineHeight = modifiedLineHeight;
|
||||
}
|
||||
|
||||
public getViewZones(): IEditorsZones {
|
||||
|
@ -1456,7 +1460,7 @@ abstract class ViewZonesComputer {
|
|||
|
||||
stepOriginal.push({
|
||||
afterLineNumber: viewZoneLineNumber,
|
||||
heightInLines: modifiedForeignVZ.current.heightInLines,
|
||||
heightInLines: modifiedForeignVZ.current.height / this.modifiedLineHeight,
|
||||
domNode: null,
|
||||
marginDomNode: marginDomNode
|
||||
});
|
||||
|
@ -1473,7 +1477,7 @@ abstract class ViewZonesComputer {
|
|||
}
|
||||
stepModified.push({
|
||||
afterLineNumber: viewZoneLineNumber,
|
||||
heightInLines: originalForeignVZ.current.heightInLines,
|
||||
heightInLines: originalForeignVZ.current.height / this.originalLineHeight,
|
||||
domNode: null
|
||||
});
|
||||
originalForeignVZ.advance();
|
||||
|
@ -1732,7 +1736,7 @@ class DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffE
|
|||
}
|
||||
|
||||
protected _getViewZones(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], modifiedForeignVZ: IEditorWhitespace[], originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor): IEditorsZones {
|
||||
let c = new SideBySideViewZonesComputer(lineChanges, originalForeignVZ, modifiedForeignVZ);
|
||||
let c = new SideBySideViewZonesComputer(lineChanges, originalForeignVZ, originalEditor.getOption(EditorOption.lineHeight), modifiedForeignVZ, modifiedEditor.getOption(EditorOption.lineHeight));
|
||||
return c.getViewZones();
|
||||
}
|
||||
|
||||
|
@ -1859,8 +1863,8 @@ class DiffEditorWidgetSideBySide extends DiffEditorWidgetStyle implements IDiffE
|
|||
|
||||
class SideBySideViewZonesComputer extends ViewZonesComputer {
|
||||
|
||||
constructor(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], modifiedForeignVZ: IEditorWhitespace[]) {
|
||||
super(lineChanges, originalForeignVZ, modifiedForeignVZ);
|
||||
constructor(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], originalLineHeight: number, modifiedForeignVZ: IEditorWhitespace[], modifiedLineHeight: number) {
|
||||
super(lineChanges, originalForeignVZ, originalLineHeight, modifiedForeignVZ, modifiedLineHeight);
|
||||
}
|
||||
|
||||
protected _createOriginalMarginDomNodeForModifiedForeignViewZoneInAddedRegion(): HTMLDivElement | null {
|
||||
|
@ -2020,7 +2024,7 @@ class InlineViewZonesComputer extends ViewZonesComputer {
|
|||
private readonly renderIndicators: boolean;
|
||||
|
||||
constructor(lineChanges: editorCommon.ILineChange[], originalForeignVZ: IEditorWhitespace[], modifiedForeignVZ: IEditorWhitespace[], originalEditor: editorBrowser.ICodeEditor, modifiedEditor: editorBrowser.ICodeEditor, renderIndicators: boolean) {
|
||||
super(lineChanges, originalForeignVZ, modifiedForeignVZ);
|
||||
super(lineChanges, originalForeignVZ, originalEditor.getOption(EditorOption.lineHeight), modifiedForeignVZ, modifiedEditor.getOption(EditorOption.lineHeight));
|
||||
this.originalModel = originalEditor.getModel()!;
|
||||
this.modifiedEditorOptions = modifiedEditor.getOptions();
|
||||
this.modifiedEditorTabSize = modifiedEditor.getModel()!.getOptions().tabSize;
|
||||
|
|
|
@ -4,44 +4,157 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
|
||||
import { IEditorWhitespace, WhitespaceComputer } from 'vs/editor/common/viewLayout/whitespaceComputer';
|
||||
import { IViewWhitespaceViewportData } from 'vs/editor/common/viewModel/viewModel';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
|
||||
export interface IEditorWhitespace {
|
||||
readonly id: string;
|
||||
readonly afterLineNumber: number;
|
||||
readonly height: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* An accessor that allows for whtiespace to be added, removed or changed in bulk.
|
||||
*/
|
||||
export interface IWhitespaceChangeAccessor {
|
||||
insertWhitespace(afterLineNumber: number, ordinal: number, heightInPx: number, minWidth: number): string;
|
||||
changeOneWhitespace(id: string, newAfterLineNumber: number, newHeight: number): void;
|
||||
removeWhitespace(id: string): void;
|
||||
}
|
||||
|
||||
interface IPendingChange { id: string; newAfterLineNumber: number; newHeight: number; }
|
||||
interface IPendingRemove { id: string; }
|
||||
|
||||
class PendingChanges {
|
||||
private _hasPending: boolean;
|
||||
private _inserts: EditorWhitespace[];
|
||||
private _changes: IPendingChange[];
|
||||
private _removes: IPendingRemove[];
|
||||
|
||||
constructor() {
|
||||
this._hasPending = false;
|
||||
this._inserts = [];
|
||||
this._changes = [];
|
||||
this._removes = [];
|
||||
}
|
||||
|
||||
public insert(x: EditorWhitespace): void {
|
||||
this._hasPending = true;
|
||||
this._inserts.push(x);
|
||||
}
|
||||
|
||||
public change(x: IPendingChange): void {
|
||||
this._hasPending = true;
|
||||
this._changes.push(x);
|
||||
}
|
||||
|
||||
public remove(x: IPendingRemove): void {
|
||||
this._hasPending = true;
|
||||
this._removes.push(x);
|
||||
}
|
||||
|
||||
public mustCommit(): boolean {
|
||||
return this._hasPending;
|
||||
}
|
||||
|
||||
public commit(linesLayout: LinesLayout): void {
|
||||
if (!this._hasPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
const inserts = this._inserts;
|
||||
const changes = this._changes;
|
||||
const removes = this._removes;
|
||||
|
||||
this._hasPending = false;
|
||||
this._inserts = [];
|
||||
this._changes = [];
|
||||
this._removes = [];
|
||||
|
||||
linesLayout._commitPendingChanges(inserts, changes, removes);
|
||||
}
|
||||
}
|
||||
|
||||
export class EditorWhitespace implements IEditorWhitespace {
|
||||
public id: string;
|
||||
public afterLineNumber: number;
|
||||
public ordinal: number;
|
||||
public height: number;
|
||||
public minWidth: number;
|
||||
public prefixSum: number;
|
||||
|
||||
constructor(id: string, afterLineNumber: number, ordinal: number, height: number, minWidth: number) {
|
||||
this.id = id;
|
||||
this.afterLineNumber = afterLineNumber;
|
||||
this.ordinal = ordinal;
|
||||
this.height = height;
|
||||
this.minWidth = minWidth;
|
||||
this.prefixSum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Layouting of objects that take vertical space (by having a height) and push down other objects.
|
||||
*
|
||||
* These objects are basically either text (lines) or spaces between those lines (whitespaces).
|
||||
* This provides commodity operations for working with lines that contain whitespace that pushes lines lower (vertically).
|
||||
* This is written with no knowledge of an editor in mind.
|
||||
*/
|
||||
export class LinesLayout {
|
||||
|
||||
/**
|
||||
* Keep track of the total number of lines.
|
||||
* This is useful for doing binary searches or for doing hit-testing.
|
||||
*/
|
||||
private _lineCount: number;
|
||||
private static INSTANCE_COUNT = 0;
|
||||
|
||||
/**
|
||||
* The height of a line in pixels.
|
||||
*/
|
||||
private readonly _instanceId: string;
|
||||
private readonly _pendingChanges: PendingChanges;
|
||||
private _lastWhitespaceId: number;
|
||||
private _arr: EditorWhitespace[];
|
||||
private _prefixSumValidIndex: number;
|
||||
private _minWidth: number;
|
||||
private _lineCount: number;
|
||||
private _lineHeight: number;
|
||||
|
||||
/**
|
||||
* Contains whitespace information in pixels
|
||||
*/
|
||||
private readonly _whitespaces: WhitespaceComputer;
|
||||
|
||||
constructor(lineCount: number, lineHeight: number) {
|
||||
this._instanceId = strings.singleLetterHash(++LinesLayout.INSTANCE_COUNT);
|
||||
this._pendingChanges = new PendingChanges();
|
||||
this._lastWhitespaceId = 0;
|
||||
this._arr = [];
|
||||
this._prefixSumValidIndex = -1;
|
||||
this._minWidth = -1; /* marker for not being computed */
|
||||
this._lineCount = lineCount;
|
||||
this._lineHeight = lineHeight;
|
||||
this._whitespaces = new WhitespaceComputer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the insertion index for a new value inside a sorted array of values.
|
||||
* If the value is already present in the sorted array, the insertion index will be after the already existing value.
|
||||
*/
|
||||
public static findInsertionIndex(arr: EditorWhitespace[], afterLineNumber: number, ordinal: number): number {
|
||||
let low = 0;
|
||||
let high = arr.length;
|
||||
|
||||
while (low < high) {
|
||||
const mid = ((low + high) >>> 1);
|
||||
|
||||
if (afterLineNumber === arr[mid].afterLineNumber) {
|
||||
if (ordinal < arr[mid].ordinal) {
|
||||
high = mid;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
} else if (afterLineNumber < arr[mid].afterLineNumber) {
|
||||
high = mid;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return low;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the height of a line in pixels.
|
||||
*/
|
||||
public setLineHeight(lineHeight: number): void {
|
||||
this._checkPendingChanges();
|
||||
this._lineHeight = lineHeight;
|
||||
}
|
||||
|
||||
|
@ -51,37 +164,153 @@ export class LinesLayout {
|
|||
* @param lineCount New number of lines.
|
||||
*/
|
||||
public onFlushed(lineCount: number): void {
|
||||
this._checkPendingChanges();
|
||||
this._lineCount = lineCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new whitespace of a certain height after a line number.
|
||||
* The whitespace has a "sticky" characteristic.
|
||||
* Irrespective of edits above or below `afterLineNumber`, the whitespace will follow the initial line.
|
||||
*
|
||||
* @param afterLineNumber The conceptual position of this whitespace. The whitespace will follow this line as best as possible even when deleting/inserting lines above/below.
|
||||
* @param heightInPx The height of the whitespace, in pixels.
|
||||
* @return An id that can be used later to mutate or delete the whitespace
|
||||
*/
|
||||
public insertWhitespace(afterLineNumber: number, ordinal: number, heightInPx: number, minWidth: number): string {
|
||||
return this._whitespaces.insertWhitespace(afterLineNumber, ordinal, heightInPx, minWidth);
|
||||
public changeWhitespace<T>(callback: (accessor: IWhitespaceChangeAccessor) => T): T {
|
||||
try {
|
||||
const accessor = {
|
||||
insertWhitespace: (afterLineNumber: number, ordinal: number, heightInPx: number, minWidth: number): string => {
|
||||
afterLineNumber = afterLineNumber | 0;
|
||||
ordinal = ordinal | 0;
|
||||
heightInPx = heightInPx | 0;
|
||||
minWidth = minWidth | 0;
|
||||
|
||||
const id = this._instanceId + (++this._lastWhitespaceId);
|
||||
this._pendingChanges.insert(new EditorWhitespace(id, afterLineNumber, ordinal, heightInPx, minWidth));
|
||||
return id;
|
||||
},
|
||||
changeOneWhitespace: (id: string, newAfterLineNumber: number, newHeight: number): void => {
|
||||
newAfterLineNumber = newAfterLineNumber | 0;
|
||||
newHeight = newHeight | 0;
|
||||
|
||||
this._pendingChanges.change({ id, newAfterLineNumber, newHeight });
|
||||
},
|
||||
removeWhitespace: (id: string): void => {
|
||||
this._pendingChanges.remove({ id });
|
||||
}
|
||||
};
|
||||
return callback(accessor);
|
||||
} finally {
|
||||
this._pendingChanges.commit(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change properties associated with a certain whitespace.
|
||||
*/
|
||||
public changeWhitespace(id: string, newAfterLineNumber: number, newHeight: number): boolean {
|
||||
return this._whitespaces.changeWhitespace(id, newAfterLineNumber, newHeight);
|
||||
public _commitPendingChanges(inserts: EditorWhitespace[], changes: IPendingChange[], removes: IPendingRemove[]): void {
|
||||
if (inserts.length > 0 || removes.length > 0) {
|
||||
this._minWidth = -1; /* marker for not being computed */
|
||||
}
|
||||
|
||||
if (inserts.length + changes.length + removes.length <= 1) {
|
||||
// when only one thing happened, handle it "delicately"
|
||||
for (const insert of inserts) {
|
||||
this._insertWhitespace(insert);
|
||||
}
|
||||
for (const change of changes) {
|
||||
this._changeOneWhitespace(change.id, change.newAfterLineNumber, change.newHeight);
|
||||
}
|
||||
for (const remove of removes) {
|
||||
const index = this._findWhitespaceIndex(remove.id);
|
||||
if (index === -1) {
|
||||
continue;
|
||||
}
|
||||
this._removeWhitespace(index);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// simply rebuild the entire datastructure
|
||||
|
||||
const toRemove = new Set<string>();
|
||||
for (const remove of removes) {
|
||||
toRemove.add(remove.id);
|
||||
}
|
||||
|
||||
const toChange = new Map<string, IPendingChange>();
|
||||
for (const change of changes) {
|
||||
toChange.set(change.id, change);
|
||||
}
|
||||
|
||||
const applyRemoveAndChange = (whitespaces: EditorWhitespace[]): EditorWhitespace[] => {
|
||||
let result: EditorWhitespace[] = [];
|
||||
for (const whitespace of whitespaces) {
|
||||
if (toRemove.has(whitespace.id)) {
|
||||
continue;
|
||||
}
|
||||
if (toChange.has(whitespace.id)) {
|
||||
const change = toChange.get(whitespace.id)!;
|
||||
whitespace.afterLineNumber = change.newAfterLineNumber;
|
||||
whitespace.height = change.newHeight;
|
||||
}
|
||||
result.push(whitespace);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const result = applyRemoveAndChange(this._arr).concat(applyRemoveAndChange(inserts));
|
||||
result.sort((a, b) => {
|
||||
if (a.afterLineNumber === b.afterLineNumber) {
|
||||
return a.ordinal - b.ordinal;
|
||||
}
|
||||
return a.afterLineNumber - b.afterLineNumber;
|
||||
});
|
||||
|
||||
this._arr = result;
|
||||
this._prefixSumValidIndex = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an existing whitespace.
|
||||
*
|
||||
* @param id The whitespace to remove
|
||||
* @return Returns true if the whitespace is found and it is removed.
|
||||
*/
|
||||
public removeWhitespace(id: string): boolean {
|
||||
return this._whitespaces.removeWhitespace(id);
|
||||
private _checkPendingChanges(): void {
|
||||
if (this._pendingChanges.mustCommit()) {
|
||||
console.warn(`Commiting pending changes before change accessor leaves due to read access.`);
|
||||
this._pendingChanges.commit(this);
|
||||
}
|
||||
}
|
||||
|
||||
private _insertWhitespace(whitespace: EditorWhitespace): void {
|
||||
const insertIndex = LinesLayout.findInsertionIndex(this._arr, whitespace.afterLineNumber, whitespace.ordinal);
|
||||
this._arr.splice(insertIndex, 0, whitespace);
|
||||
this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, insertIndex - 1);
|
||||
}
|
||||
|
||||
private _findWhitespaceIndex(id: string): number {
|
||||
const arr = this._arr;
|
||||
for (let i = 0, len = arr.length; i < len; i++) {
|
||||
if (arr[i].id === id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private _changeOneWhitespace(id: string, newAfterLineNumber: number, newHeight: number): void {
|
||||
const index = this._findWhitespaceIndex(id);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
if (this._arr[index].height !== newHeight) {
|
||||
this._arr[index].height = newHeight;
|
||||
this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, index - 1);
|
||||
}
|
||||
if (this._arr[index].afterLineNumber !== newAfterLineNumber) {
|
||||
// `afterLineNumber` changed for this whitespace
|
||||
|
||||
// Record old whitespace
|
||||
const whitespace = this._arr[index];
|
||||
|
||||
// Since changing `afterLineNumber` can trigger a reordering, we're gonna remove this whitespace
|
||||
this._removeWhitespace(index);
|
||||
|
||||
whitespace.afterLineNumber = newAfterLineNumber;
|
||||
|
||||
// And add it again
|
||||
this._insertWhitespace(whitespace);
|
||||
}
|
||||
}
|
||||
|
||||
private _removeWhitespace(removeIndex: number): void {
|
||||
this._arr.splice(removeIndex, 1);
|
||||
this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, removeIndex - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,8 +320,24 @@ export class LinesLayout {
|
|||
* @param toLineNumber The line number at which the deletion ended, inclusive
|
||||
*/
|
||||
public onLinesDeleted(fromLineNumber: number, toLineNumber: number): void {
|
||||
this._checkPendingChanges();
|
||||
fromLineNumber = fromLineNumber | 0;
|
||||
toLineNumber = toLineNumber | 0;
|
||||
|
||||
this._lineCount -= (toLineNumber - fromLineNumber + 1);
|
||||
this._whitespaces.onLinesDeleted(fromLineNumber, toLineNumber);
|
||||
for (let i = 0, len = this._arr.length; i < len; i++) {
|
||||
const afterLineNumber = this._arr[i].afterLineNumber;
|
||||
|
||||
if (fromLineNumber <= afterLineNumber && afterLineNumber <= toLineNumber) {
|
||||
// The line this whitespace was after has been deleted
|
||||
// => move whitespace to before first deleted line
|
||||
this._arr[i].afterLineNumber = fromLineNumber - 1;
|
||||
} else if (afterLineNumber > toLineNumber) {
|
||||
// The line this whitespace was after has been moved up
|
||||
// => move whitespace up
|
||||
this._arr[i].afterLineNumber -= (toLineNumber - fromLineNumber + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -102,8 +347,53 @@ export class LinesLayout {
|
|||
* @param toLineNumber The line number at which the insertion ended, inclusive.
|
||||
*/
|
||||
public onLinesInserted(fromLineNumber: number, toLineNumber: number): void {
|
||||
this._checkPendingChanges();
|
||||
fromLineNumber = fromLineNumber | 0;
|
||||
toLineNumber = toLineNumber | 0;
|
||||
|
||||
this._lineCount += (toLineNumber - fromLineNumber + 1);
|
||||
this._whitespaces.onLinesInserted(fromLineNumber, toLineNumber);
|
||||
for (let i = 0, len = this._arr.length; i < len; i++) {
|
||||
const afterLineNumber = this._arr[i].afterLineNumber;
|
||||
|
||||
if (fromLineNumber <= afterLineNumber) {
|
||||
this._arr[i].afterLineNumber += (toLineNumber - fromLineNumber + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sum of all the whitespaces.
|
||||
*/
|
||||
public getWhitespacesTotalHeight(): number {
|
||||
this._checkPendingChanges();
|
||||
if (this._arr.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
return this.getWhitespacesAccumulatedHeight(this._arr.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sum of the heights of the whitespaces at [0..index].
|
||||
* This includes the whitespace at `index`.
|
||||
*
|
||||
* @param index The index of the whitespace.
|
||||
* @return The sum of the heights of all whitespaces before the one at `index`, including the one at `index`.
|
||||
*/
|
||||
public getWhitespacesAccumulatedHeight(index: number): number {
|
||||
this._checkPendingChanges();
|
||||
index = index | 0;
|
||||
|
||||
let startIndex = Math.max(0, this._prefixSumValidIndex + 1);
|
||||
if (startIndex === 0) {
|
||||
this._arr[0].prefixSum = this._arr[0].height;
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
for (let i = startIndex; i <= index; i++) {
|
||||
this._arr[i].prefixSum = this._arr[i - 1].prefixSum + this._arr[i].height;
|
||||
}
|
||||
this._prefixSumValidIndex = Math.max(this._prefixSumValidIndex, index);
|
||||
return this._arr[index].prefixSum;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,11 +402,81 @@ export class LinesLayout {
|
|||
* @return The sum of heights for all objects.
|
||||
*/
|
||||
public getLinesTotalHeight(): number {
|
||||
let linesHeight = this._lineHeight * this._lineCount;
|
||||
let whitespacesHeight = this._whitespaces.getTotalHeight();
|
||||
this._checkPendingChanges();
|
||||
const linesHeight = this._lineHeight * this._lineCount;
|
||||
const whitespacesHeight = this.getWhitespacesTotalHeight();
|
||||
return linesHeight + whitespacesHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the accumulated height of whitespaces before the given line number.
|
||||
*
|
||||
* @param lineNumber The line number
|
||||
*/
|
||||
public getWhitespaceAccumulatedHeightBeforeLineNumber(lineNumber: number): number {
|
||||
this._checkPendingChanges();
|
||||
lineNumber = lineNumber | 0;
|
||||
|
||||
const lastWhitespaceBeforeLineNumber = this._findLastWhitespaceBeforeLineNumber(lineNumber);
|
||||
|
||||
if (lastWhitespaceBeforeLineNumber === -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this.getWhitespacesAccumulatedHeight(lastWhitespaceBeforeLineNumber);
|
||||
}
|
||||
|
||||
private _findLastWhitespaceBeforeLineNumber(lineNumber: number): number {
|
||||
lineNumber = lineNumber | 0;
|
||||
|
||||
// Find the whitespace before line number
|
||||
const arr = this._arr;
|
||||
let low = 0;
|
||||
let high = arr.length - 1;
|
||||
|
||||
while (low <= high) {
|
||||
const delta = (high - low) | 0;
|
||||
const halfDelta = (delta / 2) | 0;
|
||||
const mid = (low + halfDelta) | 0;
|
||||
|
||||
if (arr[mid].afterLineNumber < lineNumber) {
|
||||
if (mid + 1 >= arr.length || arr[mid + 1].afterLineNumber >= lineNumber) {
|
||||
return mid;
|
||||
} else {
|
||||
low = (mid + 1) | 0;
|
||||
}
|
||||
} else {
|
||||
high = (mid - 1) | 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private _findFirstWhitespaceAfterLineNumber(lineNumber: number): number {
|
||||
lineNumber = lineNumber | 0;
|
||||
|
||||
const lastWhitespaceBeforeLineNumber = this._findLastWhitespaceBeforeLineNumber(lineNumber);
|
||||
const firstWhitespaceAfterLineNumber = lastWhitespaceBeforeLineNumber + 1;
|
||||
|
||||
if (firstWhitespaceAfterLineNumber < this._arr.length) {
|
||||
return firstWhitespaceAfterLineNumber;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the index of the first whitespace which has `afterLineNumber` >= `lineNumber`.
|
||||
* @return The index of the first whitespace with `afterLineNumber` >= `lineNumber` or -1 if no whitespace is found.
|
||||
*/
|
||||
public getFirstWhitespaceIndexAfterLineNumber(lineNumber: number): number {
|
||||
this._checkPendingChanges();
|
||||
lineNumber = lineNumber | 0;
|
||||
|
||||
return this._findFirstWhitespaceAfterLineNumber(lineNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the vertical offset (the sum of heights for all objects above) a certain line number.
|
||||
*
|
||||
|
@ -124,6 +484,7 @@ export class LinesLayout {
|
|||
* @return The sum of heights for all objects above `lineNumber`.
|
||||
*/
|
||||
public getVerticalOffsetForLineNumber(lineNumber: number): number {
|
||||
this._checkPendingChanges();
|
||||
lineNumber = lineNumber | 0;
|
||||
|
||||
let previousLinesHeight: number;
|
||||
|
@ -133,36 +494,40 @@ export class LinesLayout {
|
|||
previousLinesHeight = 0;
|
||||
}
|
||||
|
||||
let previousWhitespacesHeight = this._whitespaces.getAccumulatedHeightBeforeLineNumber(lineNumber);
|
||||
const previousWhitespacesHeight = this.getWhitespaceAccumulatedHeightBeforeLineNumber(lineNumber);
|
||||
|
||||
return previousLinesHeight + previousWhitespacesHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the accumulated height of whitespaces before the given line number.
|
||||
*
|
||||
* @param lineNumber The line number
|
||||
*/
|
||||
public getWhitespaceAccumulatedHeightBeforeLineNumber(lineNumber: number): number {
|
||||
return this._whitespaces.getAccumulatedHeightBeforeLineNumber(lineNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if there is any whitespace in the document.
|
||||
*/
|
||||
public hasWhitespace(): boolean {
|
||||
return this._whitespaces.getCount() > 0;
|
||||
this._checkPendingChanges();
|
||||
return this.getWhitespacesCount() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum min width for all whitespaces.
|
||||
*/
|
||||
public getWhitespaceMinWidth(): number {
|
||||
return this._whitespaces.getMinWidth();
|
||||
this._checkPendingChanges();
|
||||
if (this._minWidth === -1) {
|
||||
let minWidth = 0;
|
||||
for (let i = 0, len = this._arr.length; i < len; i++) {
|
||||
minWidth = Math.max(minWidth, this._arr[i].minWidth);
|
||||
}
|
||||
this._minWidth = minWidth;
|
||||
}
|
||||
return this._minWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if `verticalOffset` is below all lines.
|
||||
*/
|
||||
public isAfterLines(verticalOffset: number): boolean {
|
||||
let totalHeight = this.getLinesTotalHeight();
|
||||
this._checkPendingChanges();
|
||||
const totalHeight = this.getLinesTotalHeight();
|
||||
return verticalOffset > totalHeight;
|
||||
}
|
||||
|
||||
|
@ -175,6 +540,7 @@ export class LinesLayout {
|
|||
* @return The line number at or after vertical offset `verticalOffset`.
|
||||
*/
|
||||
public getLineNumberAtOrAfterVerticalOffset(verticalOffset: number): number {
|
||||
this._checkPendingChanges();
|
||||
verticalOffset = verticalOffset | 0;
|
||||
|
||||
if (verticalOffset < 0) {
|
||||
|
@ -187,9 +553,9 @@ export class LinesLayout {
|
|||
let maxLineNumber = linesCount;
|
||||
|
||||
while (minLineNumber < maxLineNumber) {
|
||||
let midLineNumber = ((minLineNumber + maxLineNumber) / 2) | 0;
|
||||
const midLineNumber = ((minLineNumber + maxLineNumber) / 2) | 0;
|
||||
|
||||
let midLineNumberVerticalOffset = this.getVerticalOffsetForLineNumber(midLineNumber) | 0;
|
||||
const midLineNumberVerticalOffset = this.getVerticalOffsetForLineNumber(midLineNumber) | 0;
|
||||
|
||||
if (verticalOffset >= midLineNumberVerticalOffset + lineHeight) {
|
||||
// vertical offset is after mid line number
|
||||
|
@ -218,6 +584,7 @@ export class LinesLayout {
|
|||
* @return A structure describing the lines positioned between `verticalOffset1` and `verticalOffset2`.
|
||||
*/
|
||||
public getLinesViewportData(verticalOffset1: number, verticalOffset2: number): IPartialViewLinesViewportData {
|
||||
this._checkPendingChanges();
|
||||
verticalOffset1 = verticalOffset1 | 0;
|
||||
verticalOffset2 = verticalOffset2 | 0;
|
||||
const lineHeight = this._lineHeight;
|
||||
|
@ -230,8 +597,8 @@ export class LinesLayout {
|
|||
let endLineNumber = this._lineCount | 0;
|
||||
|
||||
// Also keep track of what whitespace we've got
|
||||
let whitespaceIndex = this._whitespaces.getFirstWhitespaceIndexAfterLineNumber(startLineNumber) | 0;
|
||||
const whitespaceCount = this._whitespaces.getCount() | 0;
|
||||
let whitespaceIndex = this.getFirstWhitespaceIndexAfterLineNumber(startLineNumber) | 0;
|
||||
const whitespaceCount = this.getWhitespacesCount() | 0;
|
||||
let currentWhitespaceHeight: number;
|
||||
let currentWhitespaceAfterLineNumber: number;
|
||||
|
||||
|
@ -240,8 +607,8 @@ export class LinesLayout {
|
|||
currentWhitespaceAfterLineNumber = endLineNumber + 1;
|
||||
currentWhitespaceHeight = 0;
|
||||
} else {
|
||||
currentWhitespaceAfterLineNumber = this._whitespaces.getAfterLineNumberForWhitespaceIndex(whitespaceIndex) | 0;
|
||||
currentWhitespaceHeight = this._whitespaces.getHeightForWhitespaceIndex(whitespaceIndex) | 0;
|
||||
currentWhitespaceAfterLineNumber = this.getAfterLineNumberForWhitespaceIndex(whitespaceIndex) | 0;
|
||||
currentWhitespaceHeight = this.getHeightForWhitespaceIndex(whitespaceIndex) | 0;
|
||||
}
|
||||
|
||||
let currentVerticalOffset = startLineNumberVerticalOffset;
|
||||
|
@ -258,7 +625,7 @@ export class LinesLayout {
|
|||
currentLineRelativeOffset -= bigNumbersDelta;
|
||||
}
|
||||
|
||||
let linesOffsets: number[] = [];
|
||||
const linesOffsets: number[] = [];
|
||||
|
||||
const verticalCenter = verticalOffset1 + (verticalOffset2 - verticalOffset1) / 2;
|
||||
let centeredLineNumber = -1;
|
||||
|
@ -267,8 +634,8 @@ export class LinesLayout {
|
|||
for (let lineNumber = startLineNumber; lineNumber <= endLineNumber; lineNumber++) {
|
||||
|
||||
if (centeredLineNumber === -1) {
|
||||
let currentLineTop = currentVerticalOffset;
|
||||
let currentLineBottom = currentVerticalOffset + lineHeight;
|
||||
const currentLineTop = currentVerticalOffset;
|
||||
const currentLineBottom = currentVerticalOffset + lineHeight;
|
||||
if ((currentLineTop <= verticalCenter && verticalCenter < currentLineBottom) || currentLineTop > verticalCenter) {
|
||||
centeredLineNumber = lineNumber;
|
||||
}
|
||||
|
@ -291,8 +658,8 @@ export class LinesLayout {
|
|||
if (whitespaceIndex >= whitespaceCount) {
|
||||
currentWhitespaceAfterLineNumber = endLineNumber + 1;
|
||||
} else {
|
||||
currentWhitespaceAfterLineNumber = this._whitespaces.getAfterLineNumberForWhitespaceIndex(whitespaceIndex) | 0;
|
||||
currentWhitespaceHeight = this._whitespaces.getHeightForWhitespaceIndex(whitespaceIndex) | 0;
|
||||
currentWhitespaceAfterLineNumber = this.getAfterLineNumberForWhitespaceIndex(whitespaceIndex) | 0;
|
||||
currentWhitespaceHeight = this.getHeightForWhitespaceIndex(whitespaceIndex) | 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,9 +702,10 @@ export class LinesLayout {
|
|||
}
|
||||
|
||||
public getVerticalOffsetForWhitespaceIndex(whitespaceIndex: number): number {
|
||||
this._checkPendingChanges();
|
||||
whitespaceIndex = whitespaceIndex | 0;
|
||||
|
||||
let afterLineNumber = this._whitespaces.getAfterLineNumberForWhitespaceIndex(whitespaceIndex);
|
||||
const afterLineNumber = this.getAfterLineNumberForWhitespaceIndex(whitespaceIndex);
|
||||
|
||||
let previousLinesHeight: number;
|
||||
if (afterLineNumber >= 1) {
|
||||
|
@ -348,7 +716,7 @@ export class LinesLayout {
|
|||
|
||||
let previousWhitespacesHeight: number;
|
||||
if (whitespaceIndex > 0) {
|
||||
previousWhitespacesHeight = this._whitespaces.getAccumulatedHeight(whitespaceIndex - 1);
|
||||
previousWhitespacesHeight = this.getWhitespacesAccumulatedHeight(whitespaceIndex - 1);
|
||||
} else {
|
||||
previousWhitespacesHeight = 0;
|
||||
}
|
||||
|
@ -356,30 +724,28 @@ export class LinesLayout {
|
|||
}
|
||||
|
||||
public getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset: number): number {
|
||||
this._checkPendingChanges();
|
||||
verticalOffset = verticalOffset | 0;
|
||||
|
||||
let midWhitespaceIndex: number,
|
||||
minWhitespaceIndex = 0,
|
||||
maxWhitespaceIndex = this._whitespaces.getCount() - 1,
|
||||
midWhitespaceVerticalOffset: number,
|
||||
midWhitespaceHeight: number;
|
||||
let minWhitespaceIndex = 0;
|
||||
let maxWhitespaceIndex = this.getWhitespacesCount() - 1;
|
||||
|
||||
if (maxWhitespaceIndex < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Special case: nothing to be found
|
||||
let maxWhitespaceVerticalOffset = this.getVerticalOffsetForWhitespaceIndex(maxWhitespaceIndex);
|
||||
let maxWhitespaceHeight = this._whitespaces.getHeightForWhitespaceIndex(maxWhitespaceIndex);
|
||||
const maxWhitespaceVerticalOffset = this.getVerticalOffsetForWhitespaceIndex(maxWhitespaceIndex);
|
||||
const maxWhitespaceHeight = this.getHeightForWhitespaceIndex(maxWhitespaceIndex);
|
||||
if (verticalOffset >= maxWhitespaceVerticalOffset + maxWhitespaceHeight) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (minWhitespaceIndex < maxWhitespaceIndex) {
|
||||
midWhitespaceIndex = Math.floor((minWhitespaceIndex + maxWhitespaceIndex) / 2);
|
||||
const midWhitespaceIndex = Math.floor((minWhitespaceIndex + maxWhitespaceIndex) / 2);
|
||||
|
||||
midWhitespaceVerticalOffset = this.getVerticalOffsetForWhitespaceIndex(midWhitespaceIndex);
|
||||
midWhitespaceHeight = this._whitespaces.getHeightForWhitespaceIndex(midWhitespaceIndex);
|
||||
const midWhitespaceVerticalOffset = this.getVerticalOffsetForWhitespaceIndex(midWhitespaceIndex);
|
||||
const midWhitespaceHeight = this.getHeightForWhitespaceIndex(midWhitespaceIndex);
|
||||
|
||||
if (verticalOffset >= midWhitespaceVerticalOffset + midWhitespaceHeight) {
|
||||
// vertical offset is after whitespace
|
||||
|
@ -402,27 +768,28 @@ export class LinesLayout {
|
|||
* @return Precisely the whitespace that is layouted at `verticaloffset` or null.
|
||||
*/
|
||||
public getWhitespaceAtVerticalOffset(verticalOffset: number): IViewWhitespaceViewportData | null {
|
||||
this._checkPendingChanges();
|
||||
verticalOffset = verticalOffset | 0;
|
||||
|
||||
let candidateIndex = this.getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset);
|
||||
const candidateIndex = this.getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset);
|
||||
|
||||
if (candidateIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (candidateIndex >= this._whitespaces.getCount()) {
|
||||
if (candidateIndex >= this.getWhitespacesCount()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let candidateTop = this.getVerticalOffsetForWhitespaceIndex(candidateIndex);
|
||||
const candidateTop = this.getVerticalOffsetForWhitespaceIndex(candidateIndex);
|
||||
|
||||
if (candidateTop > verticalOffset) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let candidateHeight = this._whitespaces.getHeightForWhitespaceIndex(candidateIndex);
|
||||
let candidateId = this._whitespaces.getIdForWhitespaceIndex(candidateIndex);
|
||||
let candidateAfterLineNumber = this._whitespaces.getAfterLineNumberForWhitespaceIndex(candidateIndex);
|
||||
const candidateHeight = this.getHeightForWhitespaceIndex(candidateIndex);
|
||||
const candidateId = this.getIdForWhitespaceIndex(candidateIndex);
|
||||
const candidateAfterLineNumber = this.getAfterLineNumberForWhitespaceIndex(candidateIndex);
|
||||
|
||||
return {
|
||||
id: candidateId,
|
||||
|
@ -440,11 +807,12 @@ export class LinesLayout {
|
|||
* @return An array with all the whitespaces in the viewport. If no whitespace is in viewport, the array is empty.
|
||||
*/
|
||||
public getWhitespaceViewportData(verticalOffset1: number, verticalOffset2: number): IViewWhitespaceViewportData[] {
|
||||
this._checkPendingChanges();
|
||||
verticalOffset1 = verticalOffset1 | 0;
|
||||
verticalOffset2 = verticalOffset2 | 0;
|
||||
|
||||
let startIndex = this.getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset1);
|
||||
let endIndex = this._whitespaces.getCount() - 1;
|
||||
const startIndex = this.getWhitespaceIndexAtOrAfterVerticallOffset(verticalOffset1);
|
||||
const endIndex = this.getWhitespacesCount() - 1;
|
||||
|
||||
if (startIndex < 0) {
|
||||
return [];
|
||||
|
@ -452,15 +820,15 @@ export class LinesLayout {
|
|||
|
||||
let result: IViewWhitespaceViewportData[] = [];
|
||||
for (let i = startIndex; i <= endIndex; i++) {
|
||||
let top = this.getVerticalOffsetForWhitespaceIndex(i);
|
||||
let height = this._whitespaces.getHeightForWhitespaceIndex(i);
|
||||
const top = this.getVerticalOffsetForWhitespaceIndex(i);
|
||||
const height = this.getHeightForWhitespaceIndex(i);
|
||||
if (top >= verticalOffset2) {
|
||||
break;
|
||||
}
|
||||
|
||||
result.push({
|
||||
id: this._whitespaces.getIdForWhitespaceIndex(i),
|
||||
afterLineNumber: this._whitespaces.getAfterLineNumberForWhitespaceIndex(i),
|
||||
id: this.getIdForWhitespaceIndex(i),
|
||||
afterLineNumber: this.getAfterLineNumberForWhitespaceIndex(i),
|
||||
verticalOffset: top,
|
||||
height: height
|
||||
});
|
||||
|
@ -473,6 +841,54 @@ export class LinesLayout {
|
|||
* Get all whitespaces.
|
||||
*/
|
||||
public getWhitespaces(): IEditorWhitespace[] {
|
||||
return this._whitespaces.getWhitespaces(this._lineHeight);
|
||||
this._checkPendingChanges();
|
||||
return this._arr.slice(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of whitespaces.
|
||||
*/
|
||||
public getWhitespacesCount(): number {
|
||||
this._checkPendingChanges();
|
||||
return this._arr.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `id` for whitespace at index `index`.
|
||||
*
|
||||
* @param index The index of the whitespace.
|
||||
* @return `id` of whitespace at `index`.
|
||||
*/
|
||||
public getIdForWhitespaceIndex(index: number): string {
|
||||
this._checkPendingChanges();
|
||||
index = index | 0;
|
||||
|
||||
return this._arr[index].id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `afterLineNumber` for whitespace at index `index`.
|
||||
*
|
||||
* @param index The index of the whitespace.
|
||||
* @return `afterLineNumber` of whitespace at `index`.
|
||||
*/
|
||||
public getAfterLineNumberForWhitespaceIndex(index: number): number {
|
||||
this._checkPendingChanges();
|
||||
index = index | 0;
|
||||
|
||||
return this._arr[index].afterLineNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `height` for whitespace at index `index`.
|
||||
*
|
||||
* @param index The index of the whitespace.
|
||||
* @return `height` of whitespace at `index`.
|
||||
*/
|
||||
public getHeightForWhitespaceIndex(index: number): number {
|
||||
this._checkPendingChanges();
|
||||
index = index | 0;
|
||||
|
||||
return this._arr[index].height;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,8 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
|||
import { IScrollPosition, ScrollEvent, Scrollable, ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||
import { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { LinesLayout } from 'vs/editor/common/viewLayout/linesLayout';
|
||||
import { LinesLayout, IEditorWhitespace, IWhitespaceChangeAccessor } from 'vs/editor/common/viewLayout/linesLayout';
|
||||
import { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
|
||||
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
|
||||
import { IViewLayout, IViewWhitespaceViewportData, Viewport } from 'vs/editor/common/viewModel/viewModel';
|
||||
|
||||
const SMOOTH_SCROLLING_TIME = 125;
|
||||
|
@ -194,15 +193,8 @@ export class ViewLayout extends Disposable implements IViewLayout {
|
|||
}
|
||||
|
||||
// ---- IVerticalLayoutProvider
|
||||
|
||||
public addWhitespace(afterLineNumber: number, ordinal: number, height: number, minWidth: number): string {
|
||||
return this._linesLayout.insertWhitespace(afterLineNumber, ordinal, height, minWidth);
|
||||
}
|
||||
public changeWhitespace(id: string, newAfterLineNumber: number, newHeight: number): boolean {
|
||||
return this._linesLayout.changeWhitespace(id, newAfterLineNumber, newHeight);
|
||||
}
|
||||
public removeWhitespace(id: string): boolean {
|
||||
return this._linesLayout.removeWhitespace(id);
|
||||
public changeWhitespace<T>(callback: (accessor: IWhitespaceChangeAccessor) => T): T {
|
||||
return this._linesLayout.changeWhitespace(callback);
|
||||
}
|
||||
public getVerticalOffsetForLineNumber(lineNumber: number): number {
|
||||
return this._linesLayout.getVerticalOffsetForLineNumber(lineNumber);
|
||||
|
|
|
@ -1,493 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
|
||||
export interface IEditorWhitespace {
|
||||
readonly id: string;
|
||||
readonly afterLineNumber: number;
|
||||
readonly heightInLines: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represent whitespaces in between lines and provide fast CRUD management methods.
|
||||
* The whitespaces are sorted ascending by `afterLineNumber`.
|
||||
*/
|
||||
export class WhitespaceComputer {
|
||||
|
||||
private static INSTANCE_COUNT = 0;
|
||||
|
||||
private readonly _instanceId: string;
|
||||
|
||||
/**
|
||||
* heights[i] is the height in pixels for whitespace at index i
|
||||
*/
|
||||
private readonly _heights: number[];
|
||||
|
||||
/**
|
||||
* minWidths[i] is the min width in pixels for whitespace at index i
|
||||
*/
|
||||
private readonly _minWidths: number[];
|
||||
|
||||
/**
|
||||
* afterLineNumbers[i] is the line number whitespace at index i is after
|
||||
*/
|
||||
private readonly _afterLineNumbers: number[];
|
||||
|
||||
/**
|
||||
* ordinals[i] is the orinal of the whitespace at index i
|
||||
*/
|
||||
private readonly _ordinals: number[];
|
||||
|
||||
/**
|
||||
* prefixSum[i] = SUM(heights[j]), 1 <= j <= i
|
||||
*/
|
||||
private readonly _prefixSum: number[];
|
||||
|
||||
/**
|
||||
* prefixSum[i], 1 <= i <= prefixSumValidIndex can be trusted
|
||||
*/
|
||||
private _prefixSumValidIndex: number;
|
||||
|
||||
/**
|
||||
* ids[i] is the whitespace id of whitespace at index i
|
||||
*/
|
||||
private readonly _ids: string[];
|
||||
|
||||
/**
|
||||
* index at which a whitespace is positioned (inside heights, afterLineNumbers, prefixSum members)
|
||||
*/
|
||||
private readonly _whitespaceId2Index: {
|
||||
[id: string]: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* last whitespace id issued
|
||||
*/
|
||||
private _lastWhitespaceId: number;
|
||||
|
||||
private _minWidth: number;
|
||||
|
||||
constructor() {
|
||||
this._instanceId = strings.singleLetterHash(++WhitespaceComputer.INSTANCE_COUNT);
|
||||
this._heights = [];
|
||||
this._minWidths = [];
|
||||
this._ids = [];
|
||||
this._afterLineNumbers = [];
|
||||
this._ordinals = [];
|
||||
this._prefixSum = [];
|
||||
this._prefixSumValidIndex = -1;
|
||||
this._whitespaceId2Index = {};
|
||||
this._lastWhitespaceId = 0;
|
||||
this._minWidth = -1; /* marker for not being computed */
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the insertion index for a new value inside a sorted array of values.
|
||||
* If the value is already present in the sorted array, the insertion index will be after the already existing value.
|
||||
*/
|
||||
public static findInsertionIndex(sortedArray: number[], value: number, ordinals: number[], valueOrdinal: number): number {
|
||||
let low = 0;
|
||||
let high = sortedArray.length;
|
||||
|
||||
while (low < high) {
|
||||
let mid = ((low + high) >>> 1);
|
||||
|
||||
if (value === sortedArray[mid]) {
|
||||
if (valueOrdinal < ordinals[mid]) {
|
||||
high = mid;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
} else if (value < sortedArray[mid]) {
|
||||
high = mid;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return low;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new whitespace of a certain height after a line number.
|
||||
* The whitespace has a "sticky" characteristic.
|
||||
* Irrespective of edits above or below `afterLineNumber`, the whitespace will follow the initial line.
|
||||
*
|
||||
* @param afterLineNumber The conceptual position of this whitespace. The whitespace will follow this line as best as possible even when deleting/inserting lines above/below.
|
||||
* @param heightInPx The height of the whitespace, in pixels.
|
||||
* @return An id that can be used later to mutate or delete the whitespace
|
||||
*/
|
||||
public insertWhitespace(afterLineNumber: number, ordinal: number, heightInPx: number, minWidth: number): string {
|
||||
afterLineNumber = afterLineNumber | 0;
|
||||
ordinal = ordinal | 0;
|
||||
heightInPx = heightInPx | 0;
|
||||
minWidth = minWidth | 0;
|
||||
|
||||
let id = this._instanceId + (++this._lastWhitespaceId);
|
||||
let insertionIndex = WhitespaceComputer.findInsertionIndex(this._afterLineNumbers, afterLineNumber, this._ordinals, ordinal);
|
||||
this._insertWhitespaceAtIndex(id, insertionIndex, afterLineNumber, ordinal, heightInPx, minWidth);
|
||||
this._minWidth = -1; /* marker for not being computed */
|
||||
return id;
|
||||
}
|
||||
|
||||
private _insertWhitespaceAtIndex(id: string, insertIndex: number, afterLineNumber: number, ordinal: number, heightInPx: number, minWidth: number): void {
|
||||
insertIndex = insertIndex | 0;
|
||||
afterLineNumber = afterLineNumber | 0;
|
||||
ordinal = ordinal | 0;
|
||||
heightInPx = heightInPx | 0;
|
||||
minWidth = minWidth | 0;
|
||||
|
||||
this._heights.splice(insertIndex, 0, heightInPx);
|
||||
this._minWidths.splice(insertIndex, 0, minWidth);
|
||||
this._ids.splice(insertIndex, 0, id);
|
||||
this._afterLineNumbers.splice(insertIndex, 0, afterLineNumber);
|
||||
this._ordinals.splice(insertIndex, 0, ordinal);
|
||||
this._prefixSum.splice(insertIndex, 0, 0);
|
||||
|
||||
let keys = Object.keys(this._whitespaceId2Index);
|
||||
for (let i = 0, len = keys.length; i < len; i++) {
|
||||
let sid = keys[i];
|
||||
let oldIndex = this._whitespaceId2Index[sid];
|
||||
if (oldIndex >= insertIndex) {
|
||||
this._whitespaceId2Index[sid] = oldIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
this._whitespaceId2Index[id] = insertIndex;
|
||||
this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, insertIndex - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change properties associated with a certain whitespace.
|
||||
*/
|
||||
public changeWhitespace(id: string, newAfterLineNumber: number, newHeight: number): boolean {
|
||||
newAfterLineNumber = newAfterLineNumber | 0;
|
||||
newHeight = newHeight | 0;
|
||||
|
||||
let hasChanges = false;
|
||||
hasChanges = this.changeWhitespaceHeight(id, newHeight) || hasChanges;
|
||||
hasChanges = this.changeWhitespaceAfterLineNumber(id, newAfterLineNumber) || hasChanges;
|
||||
return hasChanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the height of an existing whitespace
|
||||
*
|
||||
* @param id The whitespace to change
|
||||
* @param newHeightInPx The new height of the whitespace, in pixels
|
||||
* @return Returns true if the whitespace is found and if the new height is different than the old height
|
||||
*/
|
||||
public changeWhitespaceHeight(id: string, newHeightInPx: number): boolean {
|
||||
newHeightInPx = newHeightInPx | 0;
|
||||
|
||||
if (this._whitespaceId2Index.hasOwnProperty(id)) {
|
||||
let index = this._whitespaceId2Index[id];
|
||||
if (this._heights[index] !== newHeightInPx) {
|
||||
this._heights[index] = newHeightInPx;
|
||||
this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, index - 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the line number after which an existing whitespace flows.
|
||||
*
|
||||
* @param id The whitespace to change
|
||||
* @param newAfterLineNumber The new line number the whitespace will follow
|
||||
* @return Returns true if the whitespace is found and if the new line number is different than the old line number
|
||||
*/
|
||||
public changeWhitespaceAfterLineNumber(id: string, newAfterLineNumber: number): boolean {
|
||||
newAfterLineNumber = newAfterLineNumber | 0;
|
||||
|
||||
if (this._whitespaceId2Index.hasOwnProperty(id)) {
|
||||
let index = this._whitespaceId2Index[id];
|
||||
if (this._afterLineNumbers[index] !== newAfterLineNumber) {
|
||||
// `afterLineNumber` changed for this whitespace
|
||||
|
||||
// Record old ordinal
|
||||
let ordinal = this._ordinals[index];
|
||||
|
||||
// Record old height
|
||||
let heightInPx = this._heights[index];
|
||||
|
||||
// Record old min width
|
||||
let minWidth = this._minWidths[index];
|
||||
|
||||
// Since changing `afterLineNumber` can trigger a reordering, we're gonna remove this whitespace
|
||||
this.removeWhitespace(id);
|
||||
|
||||
// And add it again
|
||||
let insertionIndex = WhitespaceComputer.findInsertionIndex(this._afterLineNumbers, newAfterLineNumber, this._ordinals, ordinal);
|
||||
this._insertWhitespaceAtIndex(id, insertionIndex, newAfterLineNumber, ordinal, heightInPx, minWidth);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an existing whitespace.
|
||||
*
|
||||
* @param id The whitespace to remove
|
||||
* @return Returns true if the whitespace is found and it is removed.
|
||||
*/
|
||||
public removeWhitespace(id: string): boolean {
|
||||
if (this._whitespaceId2Index.hasOwnProperty(id)) {
|
||||
let index = this._whitespaceId2Index[id];
|
||||
delete this._whitespaceId2Index[id];
|
||||
this._removeWhitespaceAtIndex(index);
|
||||
this._minWidth = -1; /* marker for not being computed */
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private _removeWhitespaceAtIndex(removeIndex: number): void {
|
||||
removeIndex = removeIndex | 0;
|
||||
|
||||
this._heights.splice(removeIndex, 1);
|
||||
this._minWidths.splice(removeIndex, 1);
|
||||
this._ids.splice(removeIndex, 1);
|
||||
this._afterLineNumbers.splice(removeIndex, 1);
|
||||
this._ordinals.splice(removeIndex, 1);
|
||||
this._prefixSum.splice(removeIndex, 1);
|
||||
this._prefixSumValidIndex = Math.min(this._prefixSumValidIndex, removeIndex - 1);
|
||||
|
||||
let keys = Object.keys(this._whitespaceId2Index);
|
||||
for (let i = 0, len = keys.length; i < len; i++) {
|
||||
let sid = keys[i];
|
||||
let oldIndex = this._whitespaceId2Index[sid];
|
||||
if (oldIndex >= removeIndex) {
|
||||
this._whitespaceId2Index[sid] = oldIndex - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the computer that lines have been deleted (a continuous zone of lines).
|
||||
* This gives it a chance to update `afterLineNumber` for whitespaces, giving the "sticky" characteristic.
|
||||
*
|
||||
* @param fromLineNumber The line number at which the deletion started, inclusive
|
||||
* @param toLineNumber The line number at which the deletion ended, inclusive
|
||||
*/
|
||||
public onLinesDeleted(fromLineNumber: number, toLineNumber: number): void {
|
||||
fromLineNumber = fromLineNumber | 0;
|
||||
toLineNumber = toLineNumber | 0;
|
||||
|
||||
for (let i = 0, len = this._afterLineNumbers.length; i < len; i++) {
|
||||
let afterLineNumber = this._afterLineNumbers[i];
|
||||
|
||||
if (fromLineNumber <= afterLineNumber && afterLineNumber <= toLineNumber) {
|
||||
// The line this whitespace was after has been deleted
|
||||
// => move whitespace to before first deleted line
|
||||
this._afterLineNumbers[i] = fromLineNumber - 1;
|
||||
} else if (afterLineNumber > toLineNumber) {
|
||||
// The line this whitespace was after has been moved up
|
||||
// => move whitespace up
|
||||
this._afterLineNumbers[i] -= (toLineNumber - fromLineNumber + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the computer that lines have been inserted (a continuous zone of lines).
|
||||
* This gives it a chance to update `afterLineNumber` for whitespaces, giving the "sticky" characteristic.
|
||||
*
|
||||
* @param fromLineNumber The line number at which the insertion started, inclusive
|
||||
* @param toLineNumber The line number at which the insertion ended, inclusive.
|
||||
*/
|
||||
public onLinesInserted(fromLineNumber: number, toLineNumber: number): void {
|
||||
fromLineNumber = fromLineNumber | 0;
|
||||
toLineNumber = toLineNumber | 0;
|
||||
|
||||
for (let i = 0, len = this._afterLineNumbers.length; i < len; i++) {
|
||||
let afterLineNumber = this._afterLineNumbers[i];
|
||||
|
||||
if (fromLineNumber <= afterLineNumber) {
|
||||
this._afterLineNumbers[i] += (toLineNumber - fromLineNumber + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sum of all the whitespaces.
|
||||
*/
|
||||
public getTotalHeight(): number {
|
||||
if (this._heights.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
return this.getAccumulatedHeight(this._heights.length - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sum of the heights of the whitespaces at [0..index].
|
||||
* This includes the whitespace at `index`.
|
||||
*
|
||||
* @param index The index of the whitespace.
|
||||
* @return The sum of the heights of all whitespaces before the one at `index`, including the one at `index`.
|
||||
*/
|
||||
public getAccumulatedHeight(index: number): number {
|
||||
index = index | 0;
|
||||
|
||||
let startIndex = Math.max(0, this._prefixSumValidIndex + 1);
|
||||
if (startIndex === 0) {
|
||||
this._prefixSum[0] = this._heights[0];
|
||||
startIndex++;
|
||||
}
|
||||
|
||||
for (let i = startIndex; i <= index; i++) {
|
||||
this._prefixSum[i] = this._prefixSum[i - 1] + this._heights[i];
|
||||
}
|
||||
this._prefixSumValidIndex = Math.max(this._prefixSumValidIndex, index);
|
||||
return this._prefixSum[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all whitespaces with `afterLineNumber` < `lineNumber` and return the sum of their heights.
|
||||
*
|
||||
* @param lineNumber The line number whitespaces should be before.
|
||||
* @return The sum of the heights of the whitespaces before `lineNumber`.
|
||||
*/
|
||||
public getAccumulatedHeightBeforeLineNumber(lineNumber: number): number {
|
||||
lineNumber = lineNumber | 0;
|
||||
|
||||
let lastWhitespaceBeforeLineNumber = this._findLastWhitespaceBeforeLineNumber(lineNumber);
|
||||
|
||||
if (lastWhitespaceBeforeLineNumber === -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return this.getAccumulatedHeight(lastWhitespaceBeforeLineNumber);
|
||||
}
|
||||
|
||||
private _findLastWhitespaceBeforeLineNumber(lineNumber: number): number {
|
||||
lineNumber = lineNumber | 0;
|
||||
|
||||
// Find the whitespace before line number
|
||||
let afterLineNumbers = this._afterLineNumbers;
|
||||
let low = 0;
|
||||
let high = afterLineNumbers.length - 1;
|
||||
|
||||
while (low <= high) {
|
||||
let delta = (high - low) | 0;
|
||||
let halfDelta = (delta / 2) | 0;
|
||||
let mid = (low + halfDelta) | 0;
|
||||
|
||||
if (afterLineNumbers[mid] < lineNumber) {
|
||||
if (mid + 1 >= afterLineNumbers.length || afterLineNumbers[mid + 1] >= lineNumber) {
|
||||
return mid;
|
||||
} else {
|
||||
low = (mid + 1) | 0;
|
||||
}
|
||||
} else {
|
||||
high = (mid - 1) | 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private _findFirstWhitespaceAfterLineNumber(lineNumber: number): number {
|
||||
lineNumber = lineNumber | 0;
|
||||
|
||||
let lastWhitespaceBeforeLineNumber = this._findLastWhitespaceBeforeLineNumber(lineNumber);
|
||||
let firstWhitespaceAfterLineNumber = lastWhitespaceBeforeLineNumber + 1;
|
||||
|
||||
if (firstWhitespaceAfterLineNumber < this._heights.length) {
|
||||
return firstWhitespaceAfterLineNumber;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the index of the first whitespace which has `afterLineNumber` >= `lineNumber`.
|
||||
* @return The index of the first whitespace with `afterLineNumber` >= `lineNumber` or -1 if no whitespace is found.
|
||||
*/
|
||||
public getFirstWhitespaceIndexAfterLineNumber(lineNumber: number): number {
|
||||
lineNumber = lineNumber | 0;
|
||||
|
||||
return this._findFirstWhitespaceAfterLineNumber(lineNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of whitespaces.
|
||||
*/
|
||||
public getCount(): number {
|
||||
return this._heights.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum min width for all whitespaces.
|
||||
*/
|
||||
public getMinWidth(): number {
|
||||
if (this._minWidth === -1) {
|
||||
let minWidth = 0;
|
||||
for (let i = 0, len = this._minWidths.length; i < len; i++) {
|
||||
minWidth = Math.max(minWidth, this._minWidths[i]);
|
||||
}
|
||||
this._minWidth = minWidth;
|
||||
}
|
||||
return this._minWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `afterLineNumber` for whitespace at index `index`.
|
||||
*
|
||||
* @param index The index of the whitespace.
|
||||
* @return `afterLineNumber` of whitespace at `index`.
|
||||
*/
|
||||
public getAfterLineNumberForWhitespaceIndex(index: number): number {
|
||||
index = index | 0;
|
||||
|
||||
return this._afterLineNumbers[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `id` for whitespace at index `index`.
|
||||
*
|
||||
* @param index The index of the whitespace.
|
||||
* @return `id` of whitespace at `index`.
|
||||
*/
|
||||
public getIdForWhitespaceIndex(index: number): string {
|
||||
index = index | 0;
|
||||
|
||||
return this._ids[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the `height` for whitespace at index `index`.
|
||||
*
|
||||
* @param index The index of the whitespace.
|
||||
* @return `height` of whitespace at `index`.
|
||||
*/
|
||||
public getHeightForWhitespaceIndex(index: number): number {
|
||||
index = index | 0;
|
||||
|
||||
return this._heights[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all whitespaces.
|
||||
*/
|
||||
public getWhitespaces(deviceLineHeight: number): IEditorWhitespace[] {
|
||||
deviceLineHeight = deviceLineHeight | 0;
|
||||
|
||||
let result: IEditorWhitespace[] = [];
|
||||
for (let i = 0; i < this._heights.length; i++) {
|
||||
result.push({
|
||||
id: this._ids[i],
|
||||
afterLineNumber: this._afterLineNumbers[i],
|
||||
heightInLines: this._heights[i] / deviceLineHeight
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ import { INewScrollPosition } from 'vs/editor/common/editorCommon';
|
|||
import { EndOfLinePreference, IActiveIndentGuideInfo, IModelDecorationOptions, TextModelResolvedOptions } from 'vs/editor/common/model';
|
||||
import { IViewEventListener } from 'vs/editor/common/view/viewEvents';
|
||||
import { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
|
||||
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
|
||||
import { IEditorWhitespace, IWhitespaceChangeAccessor } from 'vs/editor/common/viewLayout/linesLayout';
|
||||
import { ITheme } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
export interface IViewWhitespaceViewportData {
|
||||
|
@ -69,20 +69,8 @@ export interface IViewLayout {
|
|||
getWhitespaceAtVerticalOffset(verticalOffset: number): IViewWhitespaceViewportData | null;
|
||||
|
||||
// --------------- Begin vertical whitespace management
|
||||
changeWhitespace<T>(callback: (accessor: IWhitespaceChangeAccessor) => T): T;
|
||||
|
||||
/**
|
||||
* Reserve rendering space.
|
||||
* @return an identifier that can be later used to remove or change the whitespace.
|
||||
*/
|
||||
addWhitespace(afterLineNumber: number, ordinal: number, height: number, minWidth: number): string;
|
||||
/**
|
||||
* Change the properties of a whitespace.
|
||||
*/
|
||||
changeWhitespace(id: string, newAfterLineNumber: number, newHeight: number): boolean;
|
||||
/**
|
||||
* Remove rendering space
|
||||
*/
|
||||
removeWhitespace(id: string): boolean;
|
||||
/**
|
||||
* Get the layout information for whitespaces currently in the viewport
|
||||
*/
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import * as assert from 'assert';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { assertType } from 'vs/base/common/types';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { Selection } from 'vs/editor/common/core/selection';
|
||||
|
@ -55,8 +56,10 @@ suite('CodeActionModel', () => {
|
|||
|
||||
const contextKeys = new MockContextKeyService();
|
||||
const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
|
||||
disposables.add(model.onDidChangeState((e: CodeActionsState.Triggered) => {
|
||||
assert.equal(e.trigger.type, 'auto');
|
||||
disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
|
||||
assertType(e.type === CodeActionsState.Type.Triggered);
|
||||
|
||||
assert.strictEqual(e.trigger.type, 'auto');
|
||||
assert.ok(e.actions);
|
||||
|
||||
e.actions.then(fixes => {
|
||||
|
@ -94,7 +97,9 @@ suite('CodeActionModel', () => {
|
|||
return new Promise((resolve, reject) => {
|
||||
const contextKeys = new MockContextKeyService();
|
||||
const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
|
||||
disposables.add(model.onDidChangeState((e: CodeActionsState.Triggered) => {
|
||||
disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
|
||||
assertType(e.type === CodeActionsState.Type.Triggered);
|
||||
|
||||
assert.equal(e.trigger.type, 'auto');
|
||||
assert.ok(e.actions);
|
||||
e.actions.then(fixes => {
|
||||
|
@ -130,7 +135,9 @@ suite('CodeActionModel', () => {
|
|||
await new Promise(resolve => {
|
||||
const contextKeys = new MockContextKeyService();
|
||||
const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
|
||||
disposables.add(model.onDidChangeState((e: CodeActionsState.Triggered) => {
|
||||
disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
|
||||
assertType(e.type === CodeActionsState.Type.Triggered);
|
||||
|
||||
assert.equal(e.trigger.type, 'auto');
|
||||
const selection = <Selection>e.rangeOrSelection;
|
||||
assert.deepEqual(selection.selectionStartLineNumber, 1);
|
||||
|
@ -153,7 +160,9 @@ suite('CodeActionModel', () => {
|
|||
let triggerCount = 0;
|
||||
const contextKeys = new MockContextKeyService();
|
||||
const model = disposables.add(new CodeActionModel(editor, markerService, contextKeys, undefined));
|
||||
disposables.add(model.onDidChangeState((e: CodeActionsState.Triggered) => {
|
||||
disposables.add(model.onDidChangeState((e: CodeActionsState.State) => {
|
||||
assertType(e.type === CodeActionsState.Type.Triggered);
|
||||
|
||||
assert.equal(e.trigger.type, 'auto');
|
||||
++triggerCount;
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
|
|||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { ICodeLensCache } from 'vs/editor/contrib/codelens/codeLensCache';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
import { createStyleSheet } from 'vs/base/browser/dom';
|
||||
import { hash } from 'vs/base/common/hash';
|
||||
|
||||
export class CodeLensContribution implements editorCommon.IEditorContribution {
|
||||
|
||||
|
@ -27,6 +29,8 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
|||
|
||||
private readonly _globalToDispose = new DisposableStore();
|
||||
private readonly _localToDispose = new DisposableStore();
|
||||
private readonly _styleElement: HTMLStyleElement;
|
||||
private readonly _styleClassName: string;
|
||||
private _lenses: CodeLensWidget[] = [];
|
||||
private _currentFindCodeLensSymbolsPromise: CancelablePromise<CodeLensModel> | undefined;
|
||||
private _oldCodeLensModels = new DisposableStore();
|
||||
|
@ -53,7 +57,16 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
|||
}
|
||||
}));
|
||||
this._globalToDispose.add(CodeLensProviderRegistry.onDidChange(this._onModelChange, this));
|
||||
this._globalToDispose.add(this._editor.onDidChangeConfiguration(e => {
|
||||
if (e.hasChanged(EditorOption.fontInfo)) {
|
||||
this._updateLensStyle();
|
||||
}
|
||||
}));
|
||||
this._onModelChange();
|
||||
|
||||
this._styleClassName = hash(this._editor.getId()).toString(16);
|
||||
this._styleElement = createStyleSheet();
|
||||
this._updateLensStyle();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
@ -63,6 +76,15 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
|||
dispose(this._currentCodeLensModel);
|
||||
}
|
||||
|
||||
private _updateLensStyle(): void {
|
||||
const options = this._editor.getOptions();
|
||||
const fontInfo = options.get(EditorOption.fontInfo);
|
||||
const lineHeight = options.get(EditorOption.lineHeight);
|
||||
|
||||
const newStyle = `.monaco-editor .codelens-decoration.${this._styleClassName} { height: ${Math.round(lineHeight * 1.1)}px; line-height: ${lineHeight}px; font-size: ${Math.round(fontInfo.fontSize * 0.9)}px; padding-right: ${Math.round(fontInfo.fontSize * 0.45)}px;}`;
|
||||
this._styleElement.innerHTML = newStyle;
|
||||
}
|
||||
|
||||
private _localDispose(): void {
|
||||
if (this._currentFindCodeLensSymbolsPromise) {
|
||||
this._currentFindCodeLensSymbolsPromise.cancel();
|
||||
|
@ -200,13 +222,6 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
|||
this._disposeAllLenses(undefined, undefined);
|
||||
}
|
||||
}));
|
||||
this._localToDispose.add(this._editor.onDidChangeConfiguration(e => {
|
||||
if (e.hasChanged(EditorOption.fontInfo)) {
|
||||
for (const lens of this._lenses) {
|
||||
lens.updateHeight();
|
||||
}
|
||||
}
|
||||
}));
|
||||
this._localToDispose.add(this._editor.onMouseUp(e => {
|
||||
if (e.target.type === editorBrowser.MouseTargetType.CONTENT_WIDGET && e.target.element && e.target.element.tagName === 'A') {
|
||||
for (const lens of this._lenses) {
|
||||
|
@ -222,8 +237,10 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
|||
}
|
||||
|
||||
private _disposeAllLenses(decChangeAccessor: IModelDecorationsChangeAccessor | undefined, viewZoneChangeAccessor: editorBrowser.IViewZoneChangeAccessor | undefined): void {
|
||||
let helper = new CodeLensHelper();
|
||||
this._lenses.forEach((lens) => lens.dispose(helper, viewZoneChangeAccessor));
|
||||
const helper = new CodeLensHelper();
|
||||
for (const lens of this._lenses) {
|
||||
lens.dispose(helper, viewZoneChangeAccessor);
|
||||
}
|
||||
if (decChangeAccessor) {
|
||||
helper.commit(decChangeAccessor);
|
||||
}
|
||||
|
@ -276,7 +293,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
|||
groupsIndex++;
|
||||
codeLensIndex++;
|
||||
} else {
|
||||
this._lenses.splice(codeLensIndex, 0, new CodeLensWidget(groups[groupsIndex], this._editor, helper, viewZoneAccessor, () => this._detectVisibleLenses && this._detectVisibleLenses.schedule()));
|
||||
this._lenses.splice(codeLensIndex, 0, new CodeLensWidget(groups[groupsIndex], this._editor, this._styleClassName, helper, viewZoneAccessor, () => this._detectVisibleLenses && this._detectVisibleLenses.schedule()));
|
||||
codeLensIndex++;
|
||||
groupsIndex++;
|
||||
}
|
||||
|
@ -290,7 +307,7 @@ export class CodeLensContribution implements editorCommon.IEditorContribution {
|
|||
|
||||
// Create extra symbols
|
||||
while (groupsIndex < groups.length) {
|
||||
this._lenses.push(new CodeLensWidget(groups[groupsIndex], this._editor, helper, viewZoneAccessor, () => this._detectVisibleLenses && this._detectVisibleLenses.schedule()));
|
||||
this._lenses.push(new CodeLensWidget(groups[groupsIndex], this._editor, this._styleClassName, helper, viewZoneAccessor, () => this._detectVisibleLenses && this._detectVisibleLenses.schedule()));
|
||||
groupsIndex++;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.monaco-editor .codelens-decoration.invisible-cl {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
0% { opacity: 0; visibility: visible;}
|
||||
100% { opacity: 1; }
|
||||
|
|
|
@ -15,7 +15,6 @@ import { editorCodeLensForeground } from 'vs/editor/common/view/editorColorRegis
|
|||
import { CodeLensItem } from 'vs/editor/contrib/codelens/codelens';
|
||||
import { editorActiveLinkForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { EditorOption } from 'vs/editor/common/config/editorOptions';
|
||||
|
||||
class CodeLensViewZone implements editorBrowser.IViewZone {
|
||||
|
||||
|
@ -61,33 +60,24 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
|
|||
private readonly _commands = new Map<string, Command>();
|
||||
|
||||
private _widgetPosition?: editorBrowser.IContentWidgetPosition;
|
||||
private _isEmpty: boolean = true;
|
||||
|
||||
constructor(
|
||||
editor: editorBrowser.ICodeEditor,
|
||||
className: string,
|
||||
symbolRange: Range,
|
||||
lenses: Array<CodeLens | undefined | null>
|
||||
) {
|
||||
this._id = 'codeLensWidget' + (++CodeLensContentWidget._idPool);
|
||||
this._editor = editor;
|
||||
this._id = (CodeLensContentWidget._idPool++).toString();
|
||||
|
||||
this.setSymbolRange(symbolRange);
|
||||
|
||||
this._domNode = document.createElement('span');
|
||||
this._domNode.className = 'codelens-decoration';
|
||||
this.updateHeight();
|
||||
this._domNode.className = `codelens-decoration ${className}`;
|
||||
this.withCommands(lenses, false);
|
||||
}
|
||||
|
||||
updateHeight(): void {
|
||||
const options = this._editor.getOptions();
|
||||
const fontInfo = options.get(EditorOption.fontInfo);
|
||||
const lineHeight = options.get(EditorOption.lineHeight);
|
||||
this._domNode.style.height = `${Math.round(lineHeight * 1.1)}px`;
|
||||
this._domNode.style.lineHeight = `${lineHeight}px`;
|
||||
this._domNode.style.fontSize = `${Math.round(fontInfo.fontSize * 0.9)}px`;
|
||||
this._domNode.style.paddingRight = `${Math.round(fontInfo.fontSize * 0.45)}px`;
|
||||
}
|
||||
|
||||
withCommands(lenses: Array<CodeLens | undefined | null>, animate: boolean): void {
|
||||
this._commands.clear();
|
||||
|
||||
|
@ -119,12 +109,15 @@ class CodeLensContentWidget implements editorBrowser.IContentWidget {
|
|||
|
||||
} else {
|
||||
// symbols and commands
|
||||
const wasEmpty = this._domNode.innerHTML === '' || this._domNode.innerHTML === ' ';
|
||||
this._domNode.innerHTML = innerHtml || ' ';
|
||||
if (!innerHtml) {
|
||||
innerHtml = ' ';
|
||||
}
|
||||
this._domNode.innerHTML = innerHtml;
|
||||
this._editor.layoutContentWidget(this);
|
||||
if (wasEmpty && animate) {
|
||||
if (this._isEmpty && animate) {
|
||||
dom.addClass(this._domNode, 'fadein');
|
||||
}
|
||||
this._isEmpty = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,6 +201,7 @@ export class CodeLensWidget {
|
|||
constructor(
|
||||
data: CodeLensItem[],
|
||||
editor: editorBrowser.ICodeEditor,
|
||||
className: string,
|
||||
helper: CodeLensHelper,
|
||||
viewZoneChangeAccessor: editorBrowser.IViewZoneChangeAccessor,
|
||||
updateCallback: Function
|
||||
|
@ -236,7 +230,7 @@ export class CodeLensWidget {
|
|||
});
|
||||
|
||||
if (range) {
|
||||
this._contentWidget = new CodeLensContentWidget(editor, range, lenses);
|
||||
this._contentWidget = new CodeLensContentWidget(editor, className, range, lenses);
|
||||
this._viewZone = new CodeLensViewZone(range.startLineNumber - 1, updateCallback);
|
||||
|
||||
this._viewZoneId = viewZoneChangeAccessor.addZone(this._viewZone);
|
||||
|
@ -306,10 +300,6 @@ export class CodeLensWidget {
|
|||
}
|
||||
}
|
||||
|
||||
updateHeight(): void {
|
||||
this._contentWidget.updateHeight();
|
||||
}
|
||||
|
||||
getCommand(link: HTMLLinkElement): Command | undefined {
|
||||
return this._contentWidget.getCommand(link);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
|||
import { ColorPickerModel } from 'vs/editor/contrib/colorPicker/colorPickerModel';
|
||||
import { editorHoverBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { BrowserFeatures } from 'vs/base/browser/canIUse';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
|
@ -150,7 +151,7 @@ class SaturationBox extends Disposable {
|
|||
|
||||
this.layout();
|
||||
|
||||
this._register(dom.addDisposableListener(this.domNode, dom.EventType.MOUSE_DOWN, e => this.onMouseDown(e)));
|
||||
this._register(dom.addDisposableListener(this.domNode, BrowserFeatures.pointerEvents ? dom.EventType.POINTER_DOWN : dom.EventType.MOUSE_DOWN, e => this.onMouseDown(e)));
|
||||
this._register(this.model.onDidChangeColor(this.onDidChangeColor, this));
|
||||
this.monitor = null;
|
||||
}
|
||||
|
@ -165,7 +166,7 @@ class SaturationBox extends Disposable {
|
|||
|
||||
this.monitor.startMonitoring(standardMouseMoveMerger, event => this.onDidChangePosition(event.posx - origin.left, event.posy - origin.top), () => null);
|
||||
|
||||
const mouseUpListener = dom.addDisposableListener(document, dom.EventType.MOUSE_UP, () => {
|
||||
const mouseUpListener = dom.addDisposableListener(document, BrowserFeatures.pointerEvents ? dom.EventType.POINTER_UP : dom.EventType.MOUSE_UP, () => {
|
||||
this._onColorFlushed.fire();
|
||||
mouseUpListener.dispose();
|
||||
if (this.monitor) {
|
||||
|
@ -250,7 +251,7 @@ abstract class Strip extends Disposable {
|
|||
this.slider = dom.append(this.domNode, $('.slider'));
|
||||
this.slider.style.top = `0px`;
|
||||
|
||||
this._register(dom.addDisposableListener(this.domNode, dom.EventType.MOUSE_DOWN, e => this.onMouseDown(e)));
|
||||
this._register(dom.addDisposableListener(this.domNode, BrowserFeatures.pointerEvents ? dom.EventType.POINTER_DOWN : dom.EventType.MOUSE_DOWN, e => this.onMouseDown(e)));
|
||||
this.layout();
|
||||
}
|
||||
|
||||
|
@ -272,7 +273,7 @@ abstract class Strip extends Disposable {
|
|||
|
||||
monitor.startMonitoring(standardMouseMoveMerger, event => this.onDidChangeTop(event.posy - origin.top), () => null);
|
||||
|
||||
const mouseUpListener = dom.addDisposableListener(document, dom.EventType.MOUSE_UP, () => {
|
||||
const mouseUpListener = dom.addDisposableListener(document, BrowserFeatures.pointerEvents ? dom.EventType.POINTER_UP : dom.EventType.MOUSE_UP, () => {
|
||||
this._onColorFlushed.fire();
|
||||
mouseUpListener.dispose();
|
||||
monitor.stopMonitoring(true);
|
||||
|
|
|
@ -8,7 +8,7 @@ import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
|||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { isMacintosh } from 'vs/base/common/platform';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ICodeEditor, IEditorMouseEvent, IMouseTarget, MouseTargetType } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICodeEditor, IEditorMouseEvent, IMouseTarget, MouseTargetType, IPartialEditorMouseEvent } from 'vs/editor/browser/editorBrowser';
|
||||
import { registerEditorContribution } from 'vs/editor/browser/editorExtensions';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
|
@ -50,7 +50,7 @@ export class DragAndDropController extends Disposable implements editorCommon.IE
|
|||
this._register(this._editor.onMouseDown((e: IEditorMouseEvent) => this._onEditorMouseDown(e)));
|
||||
this._register(this._editor.onMouseUp((e: IEditorMouseEvent) => this._onEditorMouseUp(e)));
|
||||
this._register(this._editor.onMouseDrag((e: IEditorMouseEvent) => this._onEditorMouseDrag(e)));
|
||||
this._register(this._editor.onMouseDrop((e: IEditorMouseEvent) => this._onEditorMouseDrop(e)));
|
||||
this._register(this._editor.onMouseDrop((e: IPartialEditorMouseEvent) => this._onEditorMouseDrop(e)));
|
||||
this._register(this._editor.onKeyDown((e: IKeyboardEvent) => this.onEditorKeyDown(e)));
|
||||
this._register(this._editor.onKeyUp((e: IKeyboardEvent) => this.onEditorKeyUp(e)));
|
||||
this._register(this._editor.onDidBlurEditorWidget(() => this.onEditorBlur()));
|
||||
|
@ -143,7 +143,7 @@ export class DragAndDropController extends Disposable implements editorCommon.IE
|
|||
}
|
||||
}
|
||||
|
||||
private _onEditorMouseDrop(mouseEvent: IEditorMouseEvent): void {
|
||||
private _onEditorMouseDrop(mouseEvent: IPartialEditorMouseEvent): void {
|
||||
if (mouseEvent.target && (this._hitContent(mouseEvent.target) || this._hitMargin(mouseEvent.target)) && mouseEvent.target.position) {
|
||||
let newCursorPosition = new Position(mouseEvent.target.position.lineNumber, mouseEvent.target.position.column);
|
||||
|
||||
|
|
|
@ -423,7 +423,7 @@ export class FoldingController extends Disposable implements IEditorContribution
|
|||
if (iconClicked || isCollapsed) {
|
||||
let toToggle = [region];
|
||||
if (e.event.middleButton || e.event.shiftKey) {
|
||||
toToggle.push(...foldingModel.getRegionsInside(region, r => r.isCollapsed === isCollapsed));
|
||||
toToggle.push(...foldingModel.getRegionsInside(region, (r: FoldingRegion) => r.isCollapsed === isCollapsed));
|
||||
}
|
||||
foldingModel.toggleCollapseState(toToggle);
|
||||
this.reveal({ lineNumber, column: 1 });
|
||||
|
|
|
@ -204,7 +204,7 @@ export class FoldingModel {
|
|||
return null;
|
||||
}
|
||||
|
||||
getRegionsInside(region: FoldingRegion | null, filter?: (r: FoldingRegion, level?: number) => boolean): FoldingRegion[] {
|
||||
getRegionsInside(region: FoldingRegion | null, filter?: RegionFilter | RegionFilterWithLevel): FoldingRegion[] {
|
||||
let result: FoldingRegion[] = [];
|
||||
let index = region ? region.regionIndex + 1 : 0;
|
||||
let endLineNumber = region ? region.endLineNumber : Number.MAX_VALUE;
|
||||
|
@ -229,7 +229,7 @@ export class FoldingModel {
|
|||
for (let i = index, len = this._regions.length; i < len; i++) {
|
||||
let current = this._regions.toRegion(i);
|
||||
if (this._regions.getStartLineNumber(i) < endLineNumber) {
|
||||
if (!filter || filter(current)) {
|
||||
if (!filter || (filter as RegionFilter)(current)) {
|
||||
result.push(current);
|
||||
}
|
||||
} else {
|
||||
|
@ -242,6 +242,10 @@ export class FoldingModel {
|
|||
|
||||
}
|
||||
|
||||
type RegionFilter = (r: FoldingRegion) => boolean;
|
||||
type RegionFilterWithLevel = (r: FoldingRegion, level: number) => boolean;
|
||||
|
||||
|
||||
/**
|
||||
* Collapse or expand the regions at the given locations
|
||||
* @param levels The number of levels. Use 1 to only impact the regions at the location, use Number.MAX_VALUE for all levels.
|
||||
|
|
|
@ -119,8 +119,9 @@ abstract class SymbolNavigationAction extends EditorAction {
|
|||
|
||||
} else {
|
||||
const next = model.firstReference()!;
|
||||
const targetEditor = await this._openReference(editor, editorService, next, this._configuration.openToSide);
|
||||
if (targetEditor && model.references.length > 1 && gotoLocation === 'gotoAndPeek') {
|
||||
const peek = model.references.length > 1 && gotoLocation === 'gotoAndPeek';
|
||||
const targetEditor = await this._openReference(editor, editorService, next, this._configuration.openToSide, !peek);
|
||||
if (peek && targetEditor) {
|
||||
this._openInPeek(targetEditor, model);
|
||||
} else {
|
||||
model.dispose();
|
||||
|
@ -134,7 +135,7 @@ abstract class SymbolNavigationAction extends EditorAction {
|
|||
}
|
||||
}
|
||||
|
||||
private _openReference(editor: ICodeEditor, editorService: ICodeEditorService, reference: Location | LocationLink, sideBySide: boolean): Promise<ICodeEditor | null> {
|
||||
private async _openReference(editor: ICodeEditor, editorService: ICodeEditorService, reference: Location | LocationLink, sideBySide: boolean, highlight: boolean): Promise<ICodeEditor | undefined> {
|
||||
// range is the target-selection-range when we have one
|
||||
// and the the fallback is the 'full' range
|
||||
let range: IRange | undefined = undefined;
|
||||
|
@ -145,13 +146,29 @@ abstract class SymbolNavigationAction extends EditorAction {
|
|||
range = reference.range;
|
||||
}
|
||||
|
||||
return editorService.openCodeEditor({
|
||||
const targetEditor = await editorService.openCodeEditor({
|
||||
resource: reference.uri,
|
||||
options: {
|
||||
selection: Range.collapseToStart(range),
|
||||
revealInCenterIfOutsideViewport: true
|
||||
}
|
||||
}, editor, sideBySide);
|
||||
|
||||
if (!targetEditor) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (highlight) {
|
||||
const modelNow = targetEditor.getModel();
|
||||
const ids = targetEditor.deltaDecorations([], [{ range, options: { className: 'rangeHighlight' } }]);
|
||||
setTimeout(() => {
|
||||
if (targetEditor.getModel() === modelNow) {
|
||||
targetEditor.deltaDecorations(ids, []);
|
||||
}
|
||||
}, 350);
|
||||
}
|
||||
|
||||
return targetEditor;
|
||||
}
|
||||
|
||||
private _openInPeek(target: ICodeEditor, model: ReferencesModel) {
|
||||
|
|
|
@ -227,6 +227,7 @@ export class ReferenceWidget extends peekView.PeekViewWidget {
|
|||
this.setModel(undefined);
|
||||
this._callOnDispose.dispose();
|
||||
this._disposeOnNewModel.dispose();
|
||||
this._preview.setModel(null); // drop all view-zones, workaround for https://github.com/microsoft/vscode/issues/84726
|
||||
dispose(this._preview);
|
||||
dispose(this._previewNotAvailableMessage);
|
||||
dispose(this._tree);
|
||||
|
|
|
@ -207,7 +207,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
|
|||
private readonly _themeService: IThemeService,
|
||||
private readonly _keybindingService: IKeybindingService,
|
||||
private readonly _modeService: IModeService,
|
||||
private readonly _openerService: IOpenerService | null = NullOpenerService,
|
||||
private readonly _openerService: IOpenerService = NullOpenerService,
|
||||
) {
|
||||
super(ModesContentHoverWidget.ID, editor);
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ export class ModesGlyphHoverWidget extends GlyphHoverWidget {
|
|||
constructor(
|
||||
editor: ICodeEditor,
|
||||
modeService: IModeService,
|
||||
openerService: IOpenerService | null = NullOpenerService,
|
||||
openerService: IOpenerService = NullOpenerService,
|
||||
) {
|
||||
super(ModesGlyphHoverWidget.ID, editor);
|
||||
|
||||
|
|
|
@ -44,17 +44,9 @@ export class Link implements ILink {
|
|||
return this._link.tooltip;
|
||||
}
|
||||
|
||||
resolve(token: CancellationToken): Promise<URI> {
|
||||
async resolve(token: CancellationToken): Promise<URI | string> {
|
||||
if (this._link.url) {
|
||||
try {
|
||||
if (typeof this._link.url === 'string') {
|
||||
return Promise.resolve(URI.parse(this._link.url));
|
||||
} else {
|
||||
return Promise.resolve(this._link.url);
|
||||
}
|
||||
} catch (e) {
|
||||
return Promise.reject(new Error('invalid'));
|
||||
}
|
||||
return this._link.url;
|
||||
}
|
||||
|
||||
if (typeof this._provider.resolveLink === 'function') {
|
||||
|
|
|
@ -7,7 +7,6 @@ import { IMarkdownString } from 'vs/base/common/htmlContent';
|
|||
import { renderMarkdown, MarkdownRenderOptions } from 'vs/base/browser/markdownRenderer';
|
||||
import { IOpenerService, NullOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { IModeService } from 'vs/editor/common/services/modeService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { tokenizeToString } from 'vs/editor/common/modes/textToHtmlTokenizer';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
|
@ -29,7 +28,7 @@ export class MarkdownRenderer extends Disposable {
|
|||
constructor(
|
||||
private readonly _editor: ICodeEditor,
|
||||
@IModeService private readonly _modeService: IModeService,
|
||||
@optional(IOpenerService) private readonly _openerService: IOpenerService | null = NullOpenerService,
|
||||
@optional(IOpenerService) private readonly _openerService: IOpenerService = NullOpenerService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
@ -64,15 +63,7 @@ export class MarkdownRenderer extends Disposable {
|
|||
codeBlockRenderCallback: () => this._onDidRenderCodeBlock.fire(),
|
||||
actionHandler: {
|
||||
callback: (content) => {
|
||||
let uri: URI | undefined;
|
||||
try {
|
||||
uri = URI.parse(content);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
if (uri && this._openerService) {
|
||||
this._openerService.open(uri, { fromUserGesture: true }).catch(onUnexpectedError);
|
||||
}
|
||||
this._openerService.open(content, { fromUserGesture: true }).catch(onUnexpectedError);
|
||||
},
|
||||
disposeables
|
||||
}
|
||||
|
|
|
@ -21,7 +21,11 @@
|
|||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.monaco-editor .peekview-widget .head .peekview-title .meta::before {
|
||||
.monaco-editor .peekview-widget .head .peekview-title .meta {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.monaco-editor .peekview-widget .head .peekview-title .meta:not(:empty)::before {
|
||||
content: '-';
|
||||
padding: 0 0.3em;
|
||||
}
|
||||
|
|
|
@ -89,7 +89,7 @@ export module StaticServices {
|
|||
|
||||
let _all: LazyStaticService<any>[] = [];
|
||||
|
||||
function define<T>(serviceId: ServiceIdentifier<T>, factory: (overrides: IEditorOverrideServices) => T): LazyStaticService<T> {
|
||||
function define<T>(serviceId: ServiceIdentifier<T>, factory: (overrides: IEditorOverrideServices | undefined) => T): LazyStaticService<T> {
|
||||
let r = new LazyStaticService(serviceId, factory);
|
||||
_all.push(r);
|
||||
return r;
|
||||
|
|
|
@ -8,6 +8,7 @@ import { URI } from 'vs/base/common/uri';
|
|||
import { OpenerService } from 'vs/editor/browser/services/openerService';
|
||||
import { TestCodeEditorService } from 'vs/editor/test/browser/editorTestServices';
|
||||
import { CommandsRegistry, ICommandService, NullCommandService } from 'vs/platform/commands/common/commands';
|
||||
import { matchesScheme } from 'vs/platform/opener/common/opener';
|
||||
|
||||
suite('OpenerService', function () {
|
||||
const editorService = new TestCodeEditorService();
|
||||
|
@ -28,27 +29,27 @@ suite('OpenerService', function () {
|
|||
lastCommand = undefined;
|
||||
});
|
||||
|
||||
test('delegate to editorService, scheme:///fff', function () {
|
||||
test('delegate to editorService, scheme:///fff', async function () {
|
||||
const openerService = new OpenerService(editorService, NullCommandService);
|
||||
openerService.open(URI.parse('another:///somepath'));
|
||||
await openerService.open(URI.parse('another:///somepath'));
|
||||
assert.equal(editorService.lastInput!.options!.selection, undefined);
|
||||
});
|
||||
|
||||
test('delegate to editorService, scheme:///fff#L123', function () {
|
||||
test('delegate to editorService, scheme:///fff#L123', async function () {
|
||||
const openerService = new OpenerService(editorService, NullCommandService);
|
||||
|
||||
openerService.open(URI.parse('file:///somepath#L23'));
|
||||
await openerService.open(URI.parse('file:///somepath#L23'));
|
||||
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
|
||||
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 1);
|
||||
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
|
||||
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
|
||||
assert.equal(editorService.lastInput!.resource.fragment, '');
|
||||
|
||||
openerService.open(URI.parse('another:///somepath#L23'));
|
||||
await openerService.open(URI.parse('another:///somepath#L23'));
|
||||
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
|
||||
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 1);
|
||||
|
||||
openerService.open(URI.parse('another:///somepath#L23,45'));
|
||||
await openerService.open(URI.parse('another:///somepath#L23,45'));
|
||||
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
|
||||
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 45);
|
||||
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
|
||||
|
@ -56,17 +57,17 @@ suite('OpenerService', function () {
|
|||
assert.equal(editorService.lastInput!.resource.fragment, '');
|
||||
});
|
||||
|
||||
test('delegate to editorService, scheme:///fff#123,123', function () {
|
||||
test('delegate to editorService, scheme:///fff#123,123', async function () {
|
||||
const openerService = new OpenerService(editorService, NullCommandService);
|
||||
|
||||
openerService.open(URI.parse('file:///somepath#23'));
|
||||
await openerService.open(URI.parse('file:///somepath#23'));
|
||||
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
|
||||
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 1);
|
||||
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
|
||||
assert.equal(editorService.lastInput!.options!.selection!.endColumn, undefined);
|
||||
assert.equal(editorService.lastInput!.resource.fragment, '');
|
||||
|
||||
openerService.open(URI.parse('file:///somepath#23,45'));
|
||||
await openerService.open(URI.parse('file:///somepath#23,45'));
|
||||
assert.equal(editorService.lastInput!.options!.selection!.startLineNumber, 23);
|
||||
assert.equal(editorService.lastInput!.options!.selection!.startColumn, 45);
|
||||
assert.equal(editorService.lastInput!.options!.selection!.endLineNumber, undefined);
|
||||
|
@ -74,22 +75,22 @@ suite('OpenerService', function () {
|
|||
assert.equal(editorService.lastInput!.resource.fragment, '');
|
||||
});
|
||||
|
||||
test('delegate to commandsService, command:someid', function () {
|
||||
test('delegate to commandsService, command:someid', async function () {
|
||||
const openerService = new OpenerService(editorService, commandService);
|
||||
|
||||
const id = `aCommand${Math.random()}`;
|
||||
CommandsRegistry.registerCommand(id, function () { });
|
||||
|
||||
openerService.open(URI.parse('command:' + id));
|
||||
await openerService.open(URI.parse('command:' + id));
|
||||
assert.equal(lastCommand!.id, id);
|
||||
assert.equal(lastCommand!.args.length, 0);
|
||||
|
||||
openerService.open(URI.parse('command:' + id).with({ query: '123' }));
|
||||
await openerService.open(URI.parse('command:' + id).with({ query: '123' }));
|
||||
assert.equal(lastCommand!.id, id);
|
||||
assert.equal(lastCommand!.args.length, 1);
|
||||
assert.equal(lastCommand!.args[0], '123');
|
||||
|
||||
openerService.open(URI.parse('command:' + id).with({ query: JSON.stringify([12, true]) }));
|
||||
await openerService.open(URI.parse('command:' + id).with({ query: JSON.stringify([12, true]) }));
|
||||
assert.equal(lastCommand!.id, id);
|
||||
assert.equal(lastCommand!.args.length, 2);
|
||||
assert.equal(lastCommand!.args[0], 12);
|
||||
|
@ -199,4 +200,18 @@ suite('OpenerService', function () {
|
|||
assert.equal(v1, 2);
|
||||
assert.equal(v2, 0);
|
||||
});
|
||||
|
||||
test('matchesScheme', function () {
|
||||
assert.ok(matchesScheme('https://microsoft.com', 'https'));
|
||||
assert.ok(matchesScheme('http://microsoft.com', 'http'));
|
||||
assert.ok(matchesScheme('hTTPs://microsoft.com', 'https'));
|
||||
assert.ok(matchesScheme('httP://microsoft.com', 'http'));
|
||||
assert.ok(matchesScheme(URI.parse('https://microsoft.com'), 'https'));
|
||||
assert.ok(matchesScheme(URI.parse('http://microsoft.com'), 'http'));
|
||||
assert.ok(matchesScheme(URI.parse('hTTPs://microsoft.com'), 'https'));
|
||||
assert.ok(matchesScheme(URI.parse('httP://microsoft.com'), 'http'));
|
||||
assert.ok(!matchesScheme(URI.parse('https://microsoft.com'), 'http'));
|
||||
assert.ok(!matchesScheme(URI.parse('htt://microsoft.com'), 'http'));
|
||||
assert.ok(!matchesScheme(URI.parse('z://microsoft.com'), 'http'));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,10 +3,28 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { LinesLayout } from 'vs/editor/common/viewLayout/linesLayout';
|
||||
import { LinesLayout, EditorWhitespace } from 'vs/editor/common/viewLayout/linesLayout';
|
||||
|
||||
suite('Editor ViewLayout - LinesLayout', () => {
|
||||
|
||||
function insertWhitespace(linesLayout: LinesLayout, afterLineNumber: number, ordinal: number, heightInPx: number, minWidth: number): string {
|
||||
return linesLayout.changeWhitespace((accessor) => {
|
||||
return accessor.insertWhitespace(afterLineNumber, ordinal, heightInPx, minWidth);
|
||||
});
|
||||
}
|
||||
|
||||
function changeOneWhitespace(linesLayout: LinesLayout, id: string, newAfterLineNumber: number, newHeight: number): void {
|
||||
linesLayout.changeWhitespace((accessor) => {
|
||||
accessor.changeOneWhitespace(id, newAfterLineNumber, newHeight);
|
||||
});
|
||||
}
|
||||
|
||||
function removeWhitespace(linesLayout: LinesLayout, id: string): void {
|
||||
linesLayout.changeWhitespace((accessor) => {
|
||||
accessor.removeWhitespace(id);
|
||||
});
|
||||
}
|
||||
|
||||
test('LinesLayout 1', () => {
|
||||
|
||||
// Start off with 10 lines
|
||||
|
@ -39,7 +57,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
|||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(29), 3);
|
||||
|
||||
// Add whitespace of height 5px after 2nd line
|
||||
linesLayout.insertWhitespace(2, 0, 5, 0);
|
||||
insertWhitespace(linesLayout, 2, 0, 5, 0);
|
||||
// lines: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
// whitespace: a(2,5)
|
||||
assert.equal(linesLayout.getLinesTotalHeight(), 105);
|
||||
|
@ -63,8 +81,8 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
|||
assert.equal(linesLayout.getLineNumberAtOrAfterVerticalOffset(105), 10);
|
||||
|
||||
// Add two more whitespaces of height 5px
|
||||
linesLayout.insertWhitespace(3, 0, 5, 0);
|
||||
linesLayout.insertWhitespace(4, 0, 5, 0);
|
||||
insertWhitespace(linesLayout, 3, 0, 5, 0);
|
||||
insertWhitespace(linesLayout, 4, 0, 5, 0);
|
||||
// lines: [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
|
||||
// whitespace: a(2,5), b(3, 5), c(4, 5)
|
||||
assert.equal(linesLayout.getLinesTotalHeight(), 115);
|
||||
|
@ -120,7 +138,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
|||
|
||||
// Start off with 10 lines and one whitespace after line 2, of height 5
|
||||
let linesLayout = new LinesLayout(10, 1);
|
||||
let a = linesLayout.insertWhitespace(2, 0, 5, 0);
|
||||
let a = insertWhitespace(linesLayout, 2, 0, 5, 0);
|
||||
|
||||
// 10 lines
|
||||
// whitespace: - a(2,5)
|
||||
|
@ -139,7 +157,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
|||
// Change whitespace height
|
||||
// 10 lines
|
||||
// whitespace: - a(2,10)
|
||||
linesLayout.changeWhitespace(a, 2, 10);
|
||||
changeOneWhitespace(linesLayout, a, 2, 10);
|
||||
assert.equal(linesLayout.getLinesTotalHeight(), 20);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 1);
|
||||
|
@ -155,7 +173,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
|||
// Change whitespace position
|
||||
// 10 lines
|
||||
// whitespace: - a(5,10)
|
||||
linesLayout.changeWhitespace(a, 5, 10);
|
||||
changeOneWhitespace(linesLayout, a, 5, 10);
|
||||
assert.equal(linesLayout.getLinesTotalHeight(), 20);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 1);
|
||||
|
@ -200,7 +218,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
|||
|
||||
// Remove whitespace
|
||||
// 10 lines
|
||||
linesLayout.removeWhitespace(a);
|
||||
removeWhitespace(linesLayout, a);
|
||||
assert.equal(linesLayout.getLinesTotalHeight(), 10);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(1), 0);
|
||||
assert.equal(linesLayout.getVerticalOffsetForLineNumber(2), 1);
|
||||
|
@ -216,7 +234,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
|||
|
||||
test('LinesLayout getLineNumberAtOrAfterVerticalOffset', () => {
|
||||
let linesLayout = new LinesLayout(10, 1);
|
||||
linesLayout.insertWhitespace(6, 0, 10, 0);
|
||||
insertWhitespace(linesLayout, 6, 0, 10, 0);
|
||||
|
||||
// 10 lines
|
||||
// whitespace: - a(6,10)
|
||||
|
@ -265,7 +283,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
|||
|
||||
test('LinesLayout getCenteredLineInViewport', () => {
|
||||
let linesLayout = new LinesLayout(10, 1);
|
||||
linesLayout.insertWhitespace(6, 0, 10, 0);
|
||||
insertWhitespace(linesLayout, 6, 0, 10, 0);
|
||||
|
||||
// 10 lines
|
||||
// whitespace: - a(6,10)
|
||||
|
@ -348,7 +366,7 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
|||
|
||||
test('LinesLayout getLinesViewportData 1', () => {
|
||||
let linesLayout = new LinesLayout(10, 10);
|
||||
linesLayout.insertWhitespace(6, 0, 100, 0);
|
||||
insertWhitespace(linesLayout, 6, 0, 100, 0);
|
||||
|
||||
// 10 lines
|
||||
// whitespace: - a(6,100)
|
||||
|
@ -479,11 +497,10 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
|||
assert.deepEqual(viewportData.relativeVerticalOffset, [160, 170, 180, 190]);
|
||||
});
|
||||
|
||||
|
||||
test('LinesLayout getLinesViewportData 2 & getWhitespaceViewportData', () => {
|
||||
let linesLayout = new LinesLayout(10, 10);
|
||||
let a = linesLayout.insertWhitespace(6, 0, 100, 0);
|
||||
let b = linesLayout.insertWhitespace(7, 0, 50, 0);
|
||||
let a = insertWhitespace(linesLayout, 6, 0, 100, 0);
|
||||
let b = insertWhitespace(linesLayout, 7, 0, 50, 0);
|
||||
|
||||
// 10 lines
|
||||
// whitespace: - a(6,100), b(7, 50)
|
||||
|
@ -553,8 +570,8 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
|||
|
||||
test('LinesLayout getWhitespaceAtVerticalOffset', () => {
|
||||
let linesLayout = new LinesLayout(10, 10);
|
||||
let a = linesLayout.insertWhitespace(6, 0, 100, 0);
|
||||
let b = linesLayout.insertWhitespace(7, 0, 50, 0);
|
||||
let a = insertWhitespace(linesLayout, 6, 0, 100, 0);
|
||||
let b = insertWhitespace(linesLayout, 7, 0, 50, 0);
|
||||
|
||||
let whitespace = linesLayout.getWhitespaceAtVerticalOffset(0);
|
||||
assert.equal(whitespace, null);
|
||||
|
@ -592,4 +609,536 @@ suite('Editor ViewLayout - LinesLayout', () => {
|
|||
whitespace = linesLayout.getWhitespaceAtVerticalOffset(220);
|
||||
assert.equal(whitespace, null);
|
||||
});
|
||||
|
||||
test('LinesLayout', () => {
|
||||
|
||||
const linesLayout = new LinesLayout(100, 20);
|
||||
|
||||
// Insert a whitespace after line number 2, of height 10
|
||||
const a = insertWhitespace(linesLayout, 2, 0, 10, 0);
|
||||
// whitespaces: a(2, 10)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 1);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 10);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 10);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 10);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 10);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 10);
|
||||
|
||||
// Insert a whitespace again after line number 2, of height 20
|
||||
let b = insertWhitespace(linesLayout, 2, 0, 20, 0);
|
||||
// whitespaces: a(2, 10), b(2, 20)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 2);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 10);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 20);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 10);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 30);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 30);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 30);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 30);
|
||||
|
||||
// Change last inserted whitespace height to 30
|
||||
changeOneWhitespace(linesLayout, b, 2, 30);
|
||||
// whitespaces: a(2, 10), b(2, 30)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 2);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 10);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 30);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 10);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 40);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 40);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 40);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 40);
|
||||
|
||||
// Remove last inserted whitespace
|
||||
removeWhitespace(linesLayout, b);
|
||||
// whitespaces: a(2, 10)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 1);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 10);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 10);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 10);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 10);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 10);
|
||||
|
||||
// Add a whitespace before the first line of height 50
|
||||
b = insertWhitespace(linesLayout, 0, 0, 50, 0);
|
||||
// whitespaces: b(0, 50), a(2, 10)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 2);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 50);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 10);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 50);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 60);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 60);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 60);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 60);
|
||||
|
||||
// Add a whitespace after line 4 of height 20
|
||||
insertWhitespace(linesLayout, 4, 0, 20, 0);
|
||||
// whitespaces: b(0, 50), a(2, 10), c(4, 20)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 3);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 50);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 10);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 4);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(2), 20);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 50);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 60);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(2), 80);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 80);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 60);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 60);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 80);
|
||||
|
||||
// Add a whitespace after line 3 of height 30
|
||||
insertWhitespace(linesLayout, 3, 0, 30, 0);
|
||||
// whitespaces: b(0, 50), a(2, 10), d(3, 30), c(4, 20)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 4);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 50);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 10);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 3);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(2), 30);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(3), 4);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(3), 20);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 50);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 60);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(2), 90);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(3), 110);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 110);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 60);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 90);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 110);
|
||||
|
||||
// Change whitespace after line 2 to height of 100
|
||||
changeOneWhitespace(linesLayout, a, 2, 100);
|
||||
// whitespaces: b(0, 50), a(2, 100), d(3, 30), c(4, 20)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 4);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 50);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 2);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 100);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 3);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(2), 30);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(3), 4);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(3), 20);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 50);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 150);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(2), 180);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(3), 200);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 200);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 150);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 180);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 200);
|
||||
|
||||
// Remove whitespace after line 2
|
||||
removeWhitespace(linesLayout, a);
|
||||
// whitespaces: b(0, 50), d(3, 30), c(4, 20)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 3);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 50);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 30);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 4);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(2), 20);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 50);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 80);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(2), 100);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 100);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 80);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 100);
|
||||
|
||||
// Remove whitespace before line 1
|
||||
removeWhitespace(linesLayout, b);
|
||||
// whitespaces: d(3, 30), c(4, 20)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 2);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 30);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 4);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 20);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 30);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 50);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 30);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 50);
|
||||
|
||||
// Delete line 1
|
||||
linesLayout.onLinesDeleted(1, 1);
|
||||
// whitespaces: d(2, 30), c(3, 20)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 2);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 30);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 20);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 30);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 50);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 30);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 50);
|
||||
|
||||
// Insert a line before line 1
|
||||
linesLayout.onLinesInserted(1, 1);
|
||||
// whitespaces: d(3, 30), c(4, 20)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 2);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 30);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 4);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 20);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 30);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 50);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 30);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 50);
|
||||
|
||||
// Delete line 4
|
||||
linesLayout.onLinesDeleted(4, 4);
|
||||
// whitespaces: d(3, 30), c(3, 20)
|
||||
assert.equal(linesLayout.getWhitespacesCount(), 2);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(0), 30);
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(linesLayout.getHeightForWhitespaceIndex(1), 20);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(0), 30);
|
||||
assert.equal(linesLayout.getWhitespacesAccumulatedHeight(1), 50);
|
||||
assert.equal(linesLayout.getWhitespacesTotalHeight(), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(3), 0);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(4), 50);
|
||||
assert.equal(linesLayout.getWhitespaceAccumulatedHeightBeforeLineNumber(5), 50);
|
||||
});
|
||||
|
||||
test('LinesLayout findInsertionIndex', () => {
|
||||
|
||||
const makeInternalWhitespace = (afterLineNumbers: number[], ordinal: number = 0) => {
|
||||
return afterLineNumbers.map((afterLineNumber) => new EditorWhitespace('', afterLineNumber, ordinal, 0, 0));
|
||||
};
|
||||
|
||||
let arr: EditorWhitespace[];
|
||||
|
||||
arr = makeInternalWhitespace([]);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 0);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 0);
|
||||
|
||||
arr = makeInternalWhitespace([1]);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1);
|
||||
|
||||
arr = makeInternalWhitespace([1, 3]);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2);
|
||||
|
||||
arr = makeInternalWhitespace([1, 3, 5]);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 3);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3);
|
||||
|
||||
arr = makeInternalWhitespace([1, 3, 5], 3);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 0);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3);
|
||||
|
||||
arr = makeInternalWhitespace([1, 3, 5, 7]);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 3);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 7, 0), 4);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 8, 0), 4);
|
||||
|
||||
arr = makeInternalWhitespace([1, 3, 5, 7, 9]);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 3);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 7, 0), 4);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 8, 0), 4);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 9, 0), 5);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 10, 0), 5);
|
||||
|
||||
arr = makeInternalWhitespace([1, 3, 5, 7, 9, 11]);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 3);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 7, 0), 4);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 8, 0), 4);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 9, 0), 5);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 10, 0), 5);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 11, 0), 6);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 12, 0), 6);
|
||||
|
||||
arr = makeInternalWhitespace([1, 3, 5, 7, 9, 11, 13]);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 3);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 7, 0), 4);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 8, 0), 4);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 9, 0), 5);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 10, 0), 5);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 11, 0), 6);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 12, 0), 6);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 13, 0), 7);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 14, 0), 7);
|
||||
|
||||
arr = makeInternalWhitespace([1, 3, 5, 7, 9, 11, 13, 15]);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 0, 0), 0);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 1, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 2, 0), 1);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 3, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 4, 0), 2);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 5, 0), 3);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 6, 0), 3);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 7, 0), 4);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 8, 0), 4);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 9, 0), 5);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 10, 0), 5);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 11, 0), 6);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 12, 0), 6);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 13, 0), 7);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 14, 0), 7);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 15, 0), 8);
|
||||
assert.equal(LinesLayout.findInsertionIndex(arr, 16, 0), 8);
|
||||
});
|
||||
|
||||
test('LinesLayout changeWhitespaceAfterLineNumber & getFirstWhitespaceIndexAfterLineNumber', () => {
|
||||
const linesLayout = new LinesLayout(100, 20);
|
||||
|
||||
const a = insertWhitespace(linesLayout, 0, 0, 1, 0);
|
||||
const b = insertWhitespace(linesLayout, 7, 0, 1, 0);
|
||||
const c = insertWhitespace(linesLayout, 3, 0, 1, 0);
|
||||
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 0);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), c); // 3
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(2), b); // 7
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7);
|
||||
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 1); // c
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 1); // c
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 1); // c
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // --
|
||||
|
||||
// Do not really move a
|
||||
changeOneWhitespace(linesLayout, a, 1, 1);
|
||||
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 1
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 1);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), c); // 3
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(2), b); // 7
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7);
|
||||
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // a
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 1); // c
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 1); // c
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // --
|
||||
|
||||
|
||||
// Do not really move a
|
||||
changeOneWhitespace(linesLayout, a, 2, 1);
|
||||
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 2
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 2);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), c); // 3
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(2), b); // 7
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7);
|
||||
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // a
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 0); // a
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 1); // c
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // --
|
||||
|
||||
|
||||
// Change a to conflict with c => a gets placed after c
|
||||
changeOneWhitespace(linesLayout, a, 3, 1);
|
||||
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), c); // 3
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), a); // 3
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(2), b); // 7
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7);
|
||||
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // c
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 0); // c
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 0); // c
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // --
|
||||
|
||||
|
||||
// Make a no-op
|
||||
changeOneWhitespace(linesLayout, c, 3, 1);
|
||||
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), c); // 3
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), a); // 3
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(2), b); // 7
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7);
|
||||
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // c
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 0); // c
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 0); // c
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // --
|
||||
|
||||
|
||||
|
||||
// Conflict c with b => c gets placed after b
|
||||
changeOneWhitespace(linesLayout, c, 7, 1);
|
||||
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 3
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(0), 3);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), b); // 7
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(1), 7);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(2), c); // 7
|
||||
assert.equal(linesLayout.getAfterLineNumberForWhitespaceIndex(2), 7);
|
||||
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(1), 0); // a
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(2), 0); // a
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(3), 0); // a
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(4), 1); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(5), 1); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(6), 1); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(7), 1); // b
|
||||
assert.equal(linesLayout.getFirstWhitespaceIndexAfterLineNumber(8), -1); // --
|
||||
});
|
||||
|
||||
test('LinesLayout Bug', () => {
|
||||
const linesLayout = new LinesLayout(100, 20);
|
||||
|
||||
const a = insertWhitespace(linesLayout, 0, 0, 1, 0);
|
||||
const b = insertWhitespace(linesLayout, 7, 0, 1, 0);
|
||||
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), b); // 7
|
||||
|
||||
const c = insertWhitespace(linesLayout, 3, 0, 1, 0);
|
||||
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), c); // 3
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(2), b); // 7
|
||||
|
||||
const d = insertWhitespace(linesLayout, 2, 0, 1, 0);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), d); // 2
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(2), c); // 3
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(3), b); // 7
|
||||
|
||||
const e = insertWhitespace(linesLayout, 8, 0, 1, 0);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), d); // 2
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(2), c); // 3
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(3), b); // 7
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(4), e); // 8
|
||||
|
||||
const f = insertWhitespace(linesLayout, 11, 0, 1, 0);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), d); // 2
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(2), c); // 3
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(3), b); // 7
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(4), e); // 8
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(5), f); // 11
|
||||
|
||||
const g = insertWhitespace(linesLayout, 10, 0, 1, 0);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), d); // 2
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(2), c); // 3
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(3), b); // 7
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(4), e); // 8
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(5), g); // 10
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(6), f); // 11
|
||||
|
||||
const h = insertWhitespace(linesLayout, 0, 0, 1, 0);
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(1), h); // 0
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(2), d); // 2
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(3), c); // 3
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(4), b); // 7
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(5), e); // 8
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(6), g); // 10
|
||||
assert.equal(linesLayout.getIdForWhitespaceIndex(7), f); // 11
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,558 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import * as assert from 'assert';
|
||||
import { WhitespaceComputer } from 'vs/editor/common/viewLayout/whitespaceComputer';
|
||||
|
||||
suite('Editor ViewLayout - WhitespaceComputer', () => {
|
||||
|
||||
test('WhitespaceComputer', () => {
|
||||
|
||||
let whitespaceComputer = new WhitespaceComputer();
|
||||
|
||||
// Insert a whitespace after line number 2, of height 10
|
||||
let a = whitespaceComputer.insertWhitespace(2, 0, 10, 0);
|
||||
// whitespaces: a(2, 10)
|
||||
assert.equal(whitespaceComputer.getCount(), 1);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 2);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 10);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 10);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 10);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 10);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 10);
|
||||
|
||||
// Insert a whitespace again after line number 2, of height 20
|
||||
let b = whitespaceComputer.insertWhitespace(2, 0, 20, 0);
|
||||
// whitespaces: a(2, 10), b(2, 20)
|
||||
assert.equal(whitespaceComputer.getCount(), 2);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 2);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 10);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 2);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(1), 20);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 10);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(1), 30);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 30);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 30);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 30);
|
||||
|
||||
// Change last inserted whitespace height to 30
|
||||
whitespaceComputer.changeWhitespaceHeight(b, 30);
|
||||
// whitespaces: a(2, 10), b(2, 30)
|
||||
assert.equal(whitespaceComputer.getCount(), 2);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 2);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 10);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 2);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(1), 30);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 10);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(1), 40);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 40);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 40);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 40);
|
||||
|
||||
// Remove last inserted whitespace
|
||||
whitespaceComputer.removeWhitespace(b);
|
||||
// whitespaces: a(2, 10)
|
||||
assert.equal(whitespaceComputer.getCount(), 1);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 2);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 10);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 10);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 10);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 10);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 10);
|
||||
|
||||
// Add a whitespace before the first line of height 50
|
||||
b = whitespaceComputer.insertWhitespace(0, 0, 50, 0);
|
||||
// whitespaces: b(0, 50), a(2, 10)
|
||||
assert.equal(whitespaceComputer.getCount(), 2);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 0);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 50);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 2);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(1), 10);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(1), 60);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 60);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 60);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 60);
|
||||
|
||||
// Add a whitespace after line 4 of height 20
|
||||
whitespaceComputer.insertWhitespace(4, 0, 20, 0);
|
||||
// whitespaces: b(0, 50), a(2, 10), c(4, 20)
|
||||
assert.equal(whitespaceComputer.getCount(), 3);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 0);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 50);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 2);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(1), 10);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(2), 4);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(2), 20);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(1), 60);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(2), 80);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 80);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 60);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 60);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(5), 80);
|
||||
|
||||
// Add a whitespace after line 3 of height 30
|
||||
whitespaceComputer.insertWhitespace(3, 0, 30, 0);
|
||||
// whitespaces: b(0, 50), a(2, 10), d(3, 30), c(4, 20)
|
||||
assert.equal(whitespaceComputer.getCount(), 4);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 0);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 50);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 2);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(1), 10);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(2), 3);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(2), 30);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(3), 4);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(3), 20);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(1), 60);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(2), 90);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(3), 110);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 110);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 60);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 90);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(5), 110);
|
||||
|
||||
// Change whitespace after line 2 to height of 100
|
||||
whitespaceComputer.changeWhitespaceHeight(a, 100);
|
||||
// whitespaces: b(0, 50), a(2, 100), d(3, 30), c(4, 20)
|
||||
assert.equal(whitespaceComputer.getCount(), 4);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 0);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 50);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 2);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(1), 100);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(2), 3);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(2), 30);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(3), 4);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(3), 20);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(1), 150);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(2), 180);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(3), 200);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 200);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 150);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 180);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(5), 200);
|
||||
|
||||
// Remove whitespace after line 2
|
||||
whitespaceComputer.removeWhitespace(a);
|
||||
// whitespaces: b(0, 50), d(3, 30), c(4, 20)
|
||||
assert.equal(whitespaceComputer.getCount(), 3);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 0);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 50);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(1), 30);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(2), 4);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(2), 20);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(1), 80);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(2), 100);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 100);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 80);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(5), 100);
|
||||
|
||||
// Remove whitespace before line 1
|
||||
whitespaceComputer.removeWhitespace(b);
|
||||
// whitespaces: d(3, 30), c(4, 20)
|
||||
assert.equal(whitespaceComputer.getCount(), 2);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 3);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 30);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 4);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(1), 20);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 30);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(1), 50);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 30);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(5), 50);
|
||||
|
||||
// Delete line 1
|
||||
whitespaceComputer.onLinesDeleted(1, 1);
|
||||
// whitespaces: d(2, 30), c(3, 20)
|
||||
assert.equal(whitespaceComputer.getCount(), 2);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 2);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 30);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(1), 20);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 30);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(1), 50);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 30);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(5), 50);
|
||||
|
||||
// Insert a line before line 1
|
||||
whitespaceComputer.onLinesInserted(1, 1);
|
||||
// whitespaces: d(3, 30), c(4, 20)
|
||||
assert.equal(whitespaceComputer.getCount(), 2);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 3);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 30);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 4);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(1), 20);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 30);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(1), 50);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 30);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(5), 50);
|
||||
|
||||
// Delete line 4
|
||||
whitespaceComputer.onLinesDeleted(4, 4);
|
||||
// whitespaces: d(3, 30), c(3, 20)
|
||||
assert.equal(whitespaceComputer.getCount(), 2);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 3);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(0), 30);
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(whitespaceComputer.getHeightForWhitespaceIndex(1), 20);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(0), 30);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeight(1), 50);
|
||||
assert.equal(whitespaceComputer.getTotalHeight(), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(1), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(2), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(3), 0);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(4), 50);
|
||||
assert.equal(whitespaceComputer.getAccumulatedHeightBeforeLineNumber(5), 50);
|
||||
});
|
||||
|
||||
test('WhitespaceComputer findInsertionIndex', () => {
|
||||
|
||||
let makeArray = (size: number, fillValue: number) => {
|
||||
let r: number[] = [];
|
||||
for (let i = 0; i < size; i++) {
|
||||
r[i] = fillValue;
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
||||
let arr: number[];
|
||||
let ordinals: number[];
|
||||
|
||||
arr = [];
|
||||
ordinals = makeArray(arr.length, 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 0, ordinals, 0), 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 1, ordinals, 0), 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 2, ordinals, 0), 0);
|
||||
|
||||
arr = [1];
|
||||
ordinals = makeArray(arr.length, 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 0, ordinals, 0), 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 1, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 2, ordinals, 0), 1);
|
||||
|
||||
arr = [1, 3];
|
||||
ordinals = makeArray(arr.length, 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 0, ordinals, 0), 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 1, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 2, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 3, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 4, ordinals, 0), 2);
|
||||
|
||||
arr = [1, 3, 5];
|
||||
ordinals = makeArray(arr.length, 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 0, ordinals, 0), 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 1, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 2, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 3, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 4, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 5, ordinals, 0), 3);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 6, ordinals, 0), 3);
|
||||
|
||||
arr = [1, 3, 5];
|
||||
ordinals = makeArray(arr.length, 3);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 0, ordinals, 0), 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 1, ordinals, 0), 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 2, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 3, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 4, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 5, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 6, ordinals, 0), 3);
|
||||
|
||||
arr = [1, 3, 5, 7];
|
||||
ordinals = makeArray(arr.length, 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 0, ordinals, 0), 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 1, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 2, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 3, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 4, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 5, ordinals, 0), 3);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 6, ordinals, 0), 3);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 7, ordinals, 0), 4);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 8, ordinals, 0), 4);
|
||||
|
||||
arr = [1, 3, 5, 7, 9];
|
||||
ordinals = makeArray(arr.length, 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 0, ordinals, 0), 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 1, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 2, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 3, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 4, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 5, ordinals, 0), 3);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 6, ordinals, 0), 3);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 7, ordinals, 0), 4);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 8, ordinals, 0), 4);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 9, ordinals, 0), 5);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 10, ordinals, 0), 5);
|
||||
|
||||
arr = [1, 3, 5, 7, 9, 11];
|
||||
ordinals = makeArray(arr.length, 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 0, ordinals, 0), 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 1, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 2, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 3, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 4, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 5, ordinals, 0), 3);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 6, ordinals, 0), 3);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 7, ordinals, 0), 4);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 8, ordinals, 0), 4);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 9, ordinals, 0), 5);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 10, ordinals, 0), 5);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 11, ordinals, 0), 6);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 12, ordinals, 0), 6);
|
||||
|
||||
arr = [1, 3, 5, 7, 9, 11, 13];
|
||||
ordinals = makeArray(arr.length, 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 0, ordinals, 0), 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 1, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 2, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 3, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 4, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 5, ordinals, 0), 3);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 6, ordinals, 0), 3);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 7, ordinals, 0), 4);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 8, ordinals, 0), 4);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 9, ordinals, 0), 5);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 10, ordinals, 0), 5);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 11, ordinals, 0), 6);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 12, ordinals, 0), 6);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 13, ordinals, 0), 7);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 14, ordinals, 0), 7);
|
||||
|
||||
arr = [1, 3, 5, 7, 9, 11, 13, 15];
|
||||
ordinals = makeArray(arr.length, 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 0, ordinals, 0), 0);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 1, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 2, ordinals, 0), 1);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 3, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 4, ordinals, 0), 2);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 5, ordinals, 0), 3);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 6, ordinals, 0), 3);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 7, ordinals, 0), 4);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 8, ordinals, 0), 4);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 9, ordinals, 0), 5);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 10, ordinals, 0), 5);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 11, ordinals, 0), 6);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 12, ordinals, 0), 6);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 13, ordinals, 0), 7);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 14, ordinals, 0), 7);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 15, ordinals, 0), 8);
|
||||
assert.equal(WhitespaceComputer.findInsertionIndex(arr, 16, ordinals, 0), 8);
|
||||
});
|
||||
|
||||
test('WhitespaceComputer changeWhitespaceAfterLineNumber & getFirstWhitespaceIndexAfterLineNumber', () => {
|
||||
let whitespaceComputer = new WhitespaceComputer();
|
||||
|
||||
let a = whitespaceComputer.insertWhitespace(0, 0, 1, 0);
|
||||
let b = whitespaceComputer.insertWhitespace(7, 0, 1, 0);
|
||||
let c = whitespaceComputer.insertWhitespace(3, 0, 1, 0);
|
||||
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 0);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), c); // 3
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(2), b); // 7
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(2), 7);
|
||||
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(1), 1); // c
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(2), 1); // c
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(3), 1); // c
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(8), -1); // --
|
||||
|
||||
// Do not really move a
|
||||
whitespaceComputer.changeWhitespaceAfterLineNumber(a, 1);
|
||||
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), a); // 1
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 1);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), c); // 3
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(2), b); // 7
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(2), 7);
|
||||
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(1), 0); // a
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(2), 1); // c
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(3), 1); // c
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(8), -1); // --
|
||||
|
||||
|
||||
// Do not really move a
|
||||
whitespaceComputer.changeWhitespaceAfterLineNumber(a, 2);
|
||||
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), a); // 2
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 2);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), c); // 3
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(2), b); // 7
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(2), 7);
|
||||
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(1), 0); // a
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(2), 0); // a
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(3), 1); // c
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(8), -1); // --
|
||||
|
||||
|
||||
// Change a to conflict with c => a gets placed after c
|
||||
whitespaceComputer.changeWhitespaceAfterLineNumber(a, 3);
|
||||
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), c); // 3
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 3);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), a); // 3
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(2), b); // 7
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(2), 7);
|
||||
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(1), 0); // c
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(2), 0); // c
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(3), 0); // c
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(8), -1); // --
|
||||
|
||||
|
||||
// Make a no-op
|
||||
whitespaceComputer.changeWhitespaceAfterLineNumber(c, 3);
|
||||
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), c); // 3
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 3);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), a); // 3
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 3);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(2), b); // 7
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(2), 7);
|
||||
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(1), 0); // c
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(2), 0); // c
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(3), 0); // c
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(4), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(5), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(6), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(7), 2); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(8), -1); // --
|
||||
|
||||
|
||||
|
||||
// Conflict c with b => c gets placed after b
|
||||
whitespaceComputer.changeWhitespaceAfterLineNumber(c, 7);
|
||||
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), a); // 3
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(0), 3);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), b); // 7
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(1), 7);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(2), c); // 7
|
||||
assert.equal(whitespaceComputer.getAfterLineNumberForWhitespaceIndex(2), 7);
|
||||
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(1), 0); // a
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(2), 0); // a
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(3), 0); // a
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(4), 1); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(5), 1); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(6), 1); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(7), 1); // b
|
||||
assert.equal(whitespaceComputer.getFirstWhitespaceIndexAfterLineNumber(8), -1); // --
|
||||
});
|
||||
|
||||
|
||||
test('WhitespaceComputer Bug', () => {
|
||||
let whitespaceComputer = new WhitespaceComputer();
|
||||
|
||||
let a = whitespaceComputer.insertWhitespace(0, 0, 1, 0);
|
||||
let b = whitespaceComputer.insertWhitespace(7, 0, 1, 0);
|
||||
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), b); // 7
|
||||
|
||||
let c = whitespaceComputer.insertWhitespace(3, 0, 1, 0);
|
||||
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), c); // 3
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(2), b); // 7
|
||||
|
||||
let d = whitespaceComputer.insertWhitespace(2, 0, 1, 0);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), d); // 2
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(2), c); // 3
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(3), b); // 7
|
||||
|
||||
let e = whitespaceComputer.insertWhitespace(8, 0, 1, 0);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), d); // 2
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(2), c); // 3
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(3), b); // 7
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(4), e); // 8
|
||||
|
||||
let f = whitespaceComputer.insertWhitespace(11, 0, 1, 0);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), d); // 2
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(2), c); // 3
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(3), b); // 7
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(4), e); // 8
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(5), f); // 11
|
||||
|
||||
let g = whitespaceComputer.insertWhitespace(10, 0, 1, 0);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), d); // 2
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(2), c); // 3
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(3), b); // 7
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(4), e); // 8
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(5), g); // 10
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(6), f); // 11
|
||||
|
||||
let h = whitespaceComputer.insertWhitespace(0, 0, 1, 0);
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(0), a); // 0
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(1), h); // 0
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(2), d); // 2
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(3), c); // 3
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(4), b); // 7
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(5), e); // 8
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(6), g); // 10
|
||||
assert.equal(whitespaceComputer.getIdForWhitespaceIndex(7), f); // 11
|
||||
});
|
||||
});
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { SyncDescriptor0, createSyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { IConstructorSignature2, createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IConstructorSignature2, createDecorator, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindings, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { ICommandService, ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
|
@ -296,7 +296,13 @@ export class SyncActionDescriptor {
|
|||
private readonly _keybindingContext: ContextKeyExpr | undefined;
|
||||
private readonly _keybindingWeight: number | undefined;
|
||||
|
||||
constructor(ctor: IConstructorSignature2<string, string, Action>,
|
||||
public static create<Services extends BrandedService[]>(ctor: { new(id: string, label: string, ...services: Services): Action },
|
||||
id: string, label: string | undefined, keybindings?: IKeybindings, keybindingContext?: ContextKeyExpr, keybindingWeight?: number
|
||||
): SyncActionDescriptor {
|
||||
return new SyncActionDescriptor(ctor as IConstructorSignature2<string, string, Action>, id, label, keybindings, keybindingContext, keybindingWeight);
|
||||
}
|
||||
|
||||
private constructor(ctor: IConstructorSignature2<string, string, Action>,
|
||||
id: string, label: string | undefined, keybindings?: IKeybindings, keybindingContext?: ContextKeyExpr, keybindingWeight?: number
|
||||
) {
|
||||
this._id = id;
|
||||
|
|
|
@ -86,6 +86,7 @@ export interface ParsedArgs {
|
|||
'disable-gpu'?: boolean;
|
||||
'nolazy'?: boolean;
|
||||
'force-device-scale-factor'?: string;
|
||||
'force-renderer-accessibility'?: boolean;
|
||||
}
|
||||
|
||||
export const IEnvironmentService = createDecorator<IEnvironmentService>('environmentService');
|
||||
|
|
|
@ -118,6 +118,7 @@ export const OPTIONS: OptionDescriptions<Required<ParsedArgs>> = {
|
|||
'inspect-brk': { type: 'string' },
|
||||
'nolazy': { type: 'boolean' }, // node inspect
|
||||
'force-device-scale-factor': { type: 'string' },
|
||||
'force-renderer-accessibility': { type: 'boolean' },
|
||||
'_urls': { type: 'string[]' },
|
||||
|
||||
_: { type: 'string[]' } // main arguments
|
||||
|
|
|
@ -217,6 +217,16 @@ export class ExtensionManagementService extends Disposable implements IExtension
|
|||
} else if (semver.gt(existing.manifest.version, manifest.version)) {
|
||||
return this.uninstall(existing, true);
|
||||
}
|
||||
} else {
|
||||
// Remove the extension with same version if it is already uninstalled.
|
||||
// Installing a VSIX extension shall replace the existing extension always.
|
||||
return this.unsetUninstalledAndGetLocal(identifierWithVersion)
|
||||
.then(existing => {
|
||||
if (existing) {
|
||||
return this.removeExtension(existing, 'existing').then(null, e => Promise.reject(new Error(nls.localize('restartCode', "Please restart VS Code before reinstalling {0}.", manifest.displayName || manifest.name))));
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
return undefined;
|
||||
})
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
import { URI } from 'vs/base/common/uri';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { equalsIgnoreCase, startsWithIgnoreCase } from 'vs/base/common/strings';
|
||||
|
||||
export const IOpenerService = createDecorator<IOpenerService>('openerService');
|
||||
|
||||
|
@ -35,8 +36,7 @@ export interface IResolvedExternalUri extends IDisposable {
|
|||
}
|
||||
|
||||
export interface IOpener {
|
||||
open(resource: URI, options?: OpenInternalOptions): Promise<boolean>;
|
||||
open(resource: URI, options?: OpenExternalOptions): Promise<boolean>;
|
||||
open(resource: URI | string, options?: OpenInternalOptions | OpenExternalOptions): Promise<boolean>;
|
||||
}
|
||||
|
||||
export interface IExternalOpener {
|
||||
|
@ -44,7 +44,7 @@ export interface IExternalOpener {
|
|||
}
|
||||
|
||||
export interface IValidator {
|
||||
shouldOpen(resource: URI): Promise<boolean>;
|
||||
shouldOpen(resource: URI | string): Promise<boolean>;
|
||||
}
|
||||
|
||||
export interface IExternalUriResolver {
|
||||
|
@ -83,8 +83,7 @@ export interface IOpenerService {
|
|||
* @param resource A resource
|
||||
* @return A promise that resolves when the opening is done.
|
||||
*/
|
||||
open(resource: URI, options?: OpenInternalOptions): Promise<boolean>;
|
||||
open(resource: URI, options?: OpenExternalOptions): Promise<boolean>;
|
||||
open(resource: URI | string, options?: OpenInternalOptions | OpenExternalOptions): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Resolve a resource to its external form.
|
||||
|
@ -101,3 +100,11 @@ export const NullOpenerService: IOpenerService = Object.freeze({
|
|||
async open() { return false; },
|
||||
async resolveExternalUri(uri: URI) { return { resolved: uri, dispose() { } }; },
|
||||
});
|
||||
|
||||
export function matchesScheme(target: URI | string, scheme: string) {
|
||||
if (URI.isUri(target)) {
|
||||
return equalsIgnoreCase(target.scheme, scheme);
|
||||
} else {
|
||||
return startsWithIgnoreCase(target, scheme + ':');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,8 +89,8 @@ async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptio
|
|||
options.host,
|
||||
options.port,
|
||||
`reconnectionToken=${options.reconnectionToken}&reconnection=${options.reconnectionProtocol ? 'true' : 'false'}`,
|
||||
(err: any, socket: ISocket) => {
|
||||
if (err) {
|
||||
(err: any, socket: ISocket | undefined) => {
|
||||
if (err || !socket) {
|
||||
options.logService.error(`${logPrefix} socketFactory.connect() failed. Error:`);
|
||||
options.logService.error(err);
|
||||
e(err);
|
||||
|
|
|
@ -446,7 +446,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments
|
|||
|
||||
private registerPanel(commentsPanelAlreadyConstructed: boolean) {
|
||||
if (!commentsPanelAlreadyConstructed) {
|
||||
Registry.as<PanelRegistry>(PanelExtensions.Panels).registerPanel(new PanelDescriptor(
|
||||
Registry.as<PanelRegistry>(PanelExtensions.Panels).registerPanel(PanelDescriptor.create(
|
||||
CommentsPanel,
|
||||
COMMENTS_PANEL_ID,
|
||||
COMMENTS_PANEL_TITLE,
|
||||
|
|
|
@ -30,7 +30,8 @@ import { ILogService } from 'vs/platform/log/common/log';
|
|||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
import { extHostCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
|
||||
import { ISaveParticipant, SaveReason, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { ISaveParticipant, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
import { ExtHostContext, ExtHostDocumentSaveParticipantShape, IExtHostContext } from '../common/extHost.protocol';
|
||||
|
||||
export interface ICodeActionsOnSaveOptions {
|
||||
|
|
|
@ -42,9 +42,17 @@ export class MainThreadWindow implements MainThreadWindowShape {
|
|||
return Promise.resolve(this.hostService.hasFocus);
|
||||
}
|
||||
|
||||
async $openUri(uriComponents: UriComponents, options: IOpenUriOptions): Promise<boolean> {
|
||||
async $openUri(uriComponents: UriComponents, uriString: string | undefined, options: IOpenUriOptions): Promise<boolean> {
|
||||
const uri = URI.from(uriComponents);
|
||||
return this.openerService.open(uri, { openExternal: true, allowTunneling: options.allowTunneling });
|
||||
let target: URI | string;
|
||||
if (uriString && URI.parse(uriString).toString() === uri.toString()) {
|
||||
// called with string and no transformation happened -> keep string
|
||||
target = uriString;
|
||||
} else {
|
||||
// called with URI or transformed -> use uri
|
||||
target = uri;
|
||||
}
|
||||
return this.openerService.open(target, { openExternal: true, allowTunneling: options.allowTunneling });
|
||||
}
|
||||
|
||||
async $asExternalUri(uriComponents: UriComponents, options: IOpenUriOptions): Promise<UriComponents> {
|
||||
|
|
|
@ -335,7 +335,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
|||
super(id, `${id}.state`, true, configurationService, layoutService, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService);
|
||||
}
|
||||
}
|
||||
const viewletDescriptor = new ViewletDescriptor(
|
||||
const viewletDescriptor = ViewletDescriptor.create(
|
||||
CustomViewlet,
|
||||
id,
|
||||
title,
|
||||
|
@ -359,7 +359,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
|||
}
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(
|
||||
new SyncActionDescriptor(OpenCustomViewletAction, id, localize('showViewlet', "Show {0}", title)),
|
||||
SyncActionDescriptor.create(OpenCustomViewletAction, id, localize('showViewlet', "Show {0}", title)),
|
||||
`View: Show ${title}`,
|
||||
localize('view', "View")
|
||||
);
|
||||
|
|
|
@ -185,8 +185,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
|||
}
|
||||
|
||||
return activeTextEditor.edit((edit: vscode.TextEditorEdit) => {
|
||||
args.unshift(activeTextEditor, edit);
|
||||
callback.apply(thisArg, args);
|
||||
callback.apply(thisArg, [activeTextEditor, edit, ...args]);
|
||||
|
||||
}).then((result) => {
|
||||
if (!result) {
|
||||
|
|
|
@ -45,7 +45,7 @@ import { ITerminalDimensions, IShellLaunchConfig } from 'vs/workbench/contrib/te
|
|||
import { ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
import * as search from 'vs/workbench/services/search/common/search';
|
||||
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
|
||||
export interface IEnvironment {
|
||||
|
@ -759,7 +759,7 @@ export interface IOpenUriOptions {
|
|||
|
||||
export interface MainThreadWindowShape extends IDisposable {
|
||||
$getWindowVisibility(): Promise<boolean>;
|
||||
$openUri(uri: UriComponents, options: IOpenUriOptions): Promise<boolean>;
|
||||
$openUri(uri: UriComponents, uriString: string | undefined, options: IOpenUriOptions): Promise<boolean>;
|
||||
$asExternalUri(uri: UriComponents, options: IOpenUriOptions): Promise<UriComponents>;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, IResou
|
|||
import { TextEdit } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { Range, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';
|
||||
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
import * as vscode from 'vscode';
|
||||
import { LinkedList } from 'vs/base/common/linkedList';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
|
|
@ -245,9 +245,9 @@ class OpenNodeModuleFactory implements INodeModuleFactory {
|
|||
return this.callOriginal(target, options);
|
||||
}
|
||||
if (uri.scheme === 'http' || uri.scheme === 'https') {
|
||||
return mainThreadWindow.$openUri(uri, { allowTunneling: true });
|
||||
return mainThreadWindow.$openUri(uri, target, { allowTunneling: true });
|
||||
} else if (uri.scheme === 'mailto' || uri.scheme === this._appUriScheme) {
|
||||
return mainThreadWindow.$openUri(uri, {});
|
||||
return mainThreadWindow.$openUri(uri, target, {});
|
||||
}
|
||||
return this.callOriginal(target, options);
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ import { EndOfLineSequence, TrackedRangeStickiness } from 'vs/editor/common/mode
|
|||
import * as vscode from 'vscode';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ProgressLocation as MainProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import * as editorRange from 'vs/editor/common/core/range';
|
||||
import { ISelection } from 'vs/editor/common/core/selection';
|
||||
|
@ -31,7 +31,6 @@ import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log';
|
|||
import { coalesce, isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
|
||||
|
||||
|
||||
export interface PositionLike {
|
||||
line: number;
|
||||
character: number;
|
||||
|
|
|
@ -39,7 +39,9 @@ export class ExtHostWindow implements ExtHostWindowShape {
|
|||
}
|
||||
|
||||
openUri(stringOrUri: string | URI, options: IOpenUriOptions): Promise<boolean> {
|
||||
let uriAsString: string | undefined;
|
||||
if (typeof stringOrUri === 'string') {
|
||||
uriAsString = stringOrUri;
|
||||
try {
|
||||
stringOrUri = URI.parse(stringOrUri);
|
||||
} catch (e) {
|
||||
|
@ -51,7 +53,7 @@ export class ExtHostWindow implements ExtHostWindowShape {
|
|||
} else if (stringOrUri.scheme === Schemas.command) {
|
||||
return Promise.reject(`Invalid scheme '${stringOrUri.scheme}'`);
|
||||
}
|
||||
return this._proxy.$openUri(stringOrUri, options);
|
||||
return this._proxy.$openUri(stringOrUri, uriAsString, options);
|
||||
}
|
||||
|
||||
async asExternalUri(uri: URI, options: IOpenUriOptions): Promise<URI> {
|
||||
|
|
|
@ -38,6 +38,7 @@ import { ISignService } from 'vs/platform/sign/common/sign';
|
|||
import { IExtHostTerminalService } from 'vs/workbench/api/common/extHostTerminalService';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IExtHostDebugService } from 'vs/workbench/api/common/extHostDebugService';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
|
||||
export class ExtHostDebugService implements IExtHostDebugService, ExtHostDebugServiceShape {
|
||||
|
||||
|
@ -114,7 +115,7 @@ export class ExtHostDebugService implements IExtHostDebugService, ExtHostDebugSe
|
|||
|
||||
this._onDidStartDebugSession = new Emitter<vscode.DebugSession>();
|
||||
this._onDidTerminateDebugSession = new Emitter<vscode.DebugSession>();
|
||||
this._onDidChangeActiveDebugSession = new Emitter<vscode.DebugSession>();
|
||||
this._onDidChangeActiveDebugSession = new Emitter<vscode.DebugSession | undefined>();
|
||||
this._onDidReceiveDebugSessionCustomEvent = new Emitter<vscode.DebugSessionCustomEvent>();
|
||||
|
||||
this._debugServiceProxy = extHostRpcService.getProxy(MainContext.MainThreadDebugService);
|
||||
|
@ -511,11 +512,11 @@ export class ExtHostDebugService implements IExtHostDebugService, ExtHostDebugSe
|
|||
}
|
||||
this._debugServiceProxy.$acceptDAError(debugAdapterHandle, err.name, err.message, err.stack);
|
||||
});
|
||||
debugAdapter.onExit((code: number) => {
|
||||
debugAdapter.onExit((code: number | null) => {
|
||||
if (tracker && tracker.onExit) {
|
||||
tracker.onExit(code, undefined);
|
||||
tracker.onExit(withNullAsUndefined(code), undefined);
|
||||
}
|
||||
this._debugServiceProxy.$acceptDAExit(debugAdapterHandle, code, undefined);
|
||||
this._debugServiceProxy.$acceptDAExit(debugAdapterHandle, withNullAsUndefined(code), undefined);
|
||||
});
|
||||
|
||||
if (tracker && tracker.onWillStartSession) {
|
||||
|
|
|
@ -214,9 +214,9 @@ class LogStorageAction extends Action {
|
|||
|
||||
const developerCategory = nls.localize('developer', "Developer");
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(InspectContextKeysAction, InspectContextKeysAction.ID, InspectContextKeysAction.LABEL), 'Developer: Inspect Context Keys', developerCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleScreencastModeAction, ToggleScreencastModeAction.ID, ToggleScreencastModeAction.LABEL), 'Developer: Toggle Screencast Mode', developerCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(LogStorageAction, LogStorageAction.ID, LogStorageAction.LABEL), 'Developer: Log Storage Database Contents', developerCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(InspectContextKeysAction, InspectContextKeysAction.ID, InspectContextKeysAction.LABEL), 'Developer: Inspect Context Keys', developerCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleScreencastModeAction, ToggleScreencastModeAction.ID, ToggleScreencastModeAction.LABEL), 'Developer: Toggle Screencast Mode', developerCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(LogStorageAction, LogStorageAction.ID, LogStorageAction.LABEL), 'Developer: Log Storage Database Contents', developerCategory);
|
||||
|
||||
// Screencast Mode
|
||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||
|
|
|
@ -248,39 +248,39 @@ const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActio
|
|||
const helpCategory = nls.localize('help', "Help");
|
||||
|
||||
if (KeybindingsReferenceAction.AVAILABLE) {
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(KeybindingsReferenceAction, KeybindingsReferenceAction.ID, KeybindingsReferenceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_R) }), 'Help: Keyboard Shortcuts Reference', helpCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(KeybindingsReferenceAction, KeybindingsReferenceAction.ID, KeybindingsReferenceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_R) }), 'Help: Keyboard Shortcuts Reference', helpCategory);
|
||||
}
|
||||
|
||||
if (OpenDocumentationUrlAction.AVAILABLE) {
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenDocumentationUrlAction, OpenDocumentationUrlAction.ID, OpenDocumentationUrlAction.LABEL), 'Help: Documentation', helpCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenDocumentationUrlAction, OpenDocumentationUrlAction.ID, OpenDocumentationUrlAction.LABEL), 'Help: Documentation', helpCategory);
|
||||
}
|
||||
|
||||
if (OpenIntroductoryVideosUrlAction.AVAILABLE) {
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenIntroductoryVideosUrlAction, OpenIntroductoryVideosUrlAction.ID, OpenIntroductoryVideosUrlAction.LABEL), 'Help: Introductory Videos', helpCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenIntroductoryVideosUrlAction, OpenIntroductoryVideosUrlAction.ID, OpenIntroductoryVideosUrlAction.LABEL), 'Help: Introductory Videos', helpCategory);
|
||||
}
|
||||
|
||||
if (OpenTipsAndTricksUrlAction.AVAILABLE) {
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenTipsAndTricksUrlAction, OpenTipsAndTricksUrlAction.ID, OpenTipsAndTricksUrlAction.LABEL), 'Help: Tips and Tricks', helpCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenTipsAndTricksUrlAction, OpenTipsAndTricksUrlAction.ID, OpenTipsAndTricksUrlAction.LABEL), 'Help: Tips and Tricks', helpCategory);
|
||||
}
|
||||
|
||||
if (OpenNewsletterSignupUrlAction.AVAILABLE) {
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenNewsletterSignupUrlAction, OpenNewsletterSignupUrlAction.ID, OpenNewsletterSignupUrlAction.LABEL), 'Help: Tips and Tricks', helpCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenNewsletterSignupUrlAction, OpenNewsletterSignupUrlAction.ID, OpenNewsletterSignupUrlAction.LABEL), 'Help: Tips and Tricks', helpCategory);
|
||||
}
|
||||
|
||||
if (OpenTwitterUrlAction.AVAILABLE) {
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenTwitterUrlAction, OpenTwitterUrlAction.ID, OpenTwitterUrlAction.LABEL), 'Help: Join Us on Twitter', helpCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenTwitterUrlAction, OpenTwitterUrlAction.ID, OpenTwitterUrlAction.LABEL), 'Help: Join Us on Twitter', helpCategory);
|
||||
}
|
||||
|
||||
if (OpenRequestFeatureUrlAction.AVAILABLE) {
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenRequestFeatureUrlAction, OpenRequestFeatureUrlAction.ID, OpenRequestFeatureUrlAction.LABEL), 'Help: Search Feature Requests', helpCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenRequestFeatureUrlAction, OpenRequestFeatureUrlAction.ID, OpenRequestFeatureUrlAction.LABEL), 'Help: Search Feature Requests', helpCategory);
|
||||
}
|
||||
|
||||
if (OpenLicenseUrlAction.AVAILABLE) {
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenLicenseUrlAction, OpenLicenseUrlAction.ID, OpenLicenseUrlAction.LABEL), 'Help: View License', helpCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenLicenseUrlAction, OpenLicenseUrlAction.ID, OpenLicenseUrlAction.LABEL), 'Help: View License', helpCategory);
|
||||
}
|
||||
|
||||
if (OpenPrivacyStatementUrlAction.AVAILABE) {
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenPrivacyStatementUrlAction, OpenPrivacyStatementUrlAction.ID, OpenPrivacyStatementUrlAction.LABEL), 'Help: Privacy Statement', helpCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenPrivacyStatementUrlAction, OpenPrivacyStatementUrlAction.ID, OpenPrivacyStatementUrlAction.LABEL), 'Help: Privacy Statement', helpCategory);
|
||||
}
|
||||
|
||||
// --- Menu Registration
|
||||
|
|
|
@ -56,7 +56,7 @@ export class ToggleActivityBarVisibilityAction extends Action {
|
|||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleActivityBarVisibilityAction, ToggleActivityBarVisibilityAction.ID, ToggleActivityBarVisibilityAction.LABEL), 'View: Toggle Activity Bar Visibility', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleActivityBarVisibilityAction, ToggleActivityBarVisibilityAction.ID, ToggleActivityBarVisibilityAction.LABEL), 'View: Toggle Activity Bar Visibility', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '2_workbench_layout',
|
||||
|
@ -91,7 +91,7 @@ class ToggleCenteredLayout extends Action {
|
|||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleCenteredLayout, ToggleCenteredLayout.ID, ToggleCenteredLayout.LABEL), 'View: Toggle Centered Layout', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleCenteredLayout, ToggleCenteredLayout.ID, ToggleCenteredLayout.LABEL), 'View: Toggle Centered Layout', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '1_toggle_view',
|
||||
|
@ -143,7 +143,7 @@ export class ToggleEditorLayoutAction extends Action {
|
|||
}
|
||||
|
||||
const group = viewCategory;
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleEditorLayoutAction, ToggleEditorLayoutAction.ID, ToggleEditorLayoutAction.LABEL, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_0, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_0 } }), 'View: Toggle Vertical/Horizontal Editor Layout', group);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleEditorLayoutAction, ToggleEditorLayoutAction.ID, ToggleEditorLayoutAction.LABEL, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_0, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_0 } }), 'View: Toggle Vertical/Horizontal Editor Layout', group);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarLayoutMenu, {
|
||||
group: 'z_flip',
|
||||
|
@ -186,7 +186,7 @@ export class ToggleSidebarPositionAction extends Action {
|
|||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.LABEL), 'View: Toggle Side Bar Position', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.LABEL), 'View: Toggle Side Bar Position', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '3_workbench_layout_move',
|
||||
|
@ -231,7 +231,7 @@ export class ToggleEditorVisibilityAction extends Action {
|
|||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleEditorVisibilityAction, ToggleEditorVisibilityAction.ID, ToggleEditorVisibilityAction.LABEL), 'View: Toggle Editor Area Visibility', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleEditorVisibilityAction, ToggleEditorVisibilityAction.ID, ToggleEditorVisibilityAction.LABEL), 'View: Toggle Editor Area Visibility', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '2_workbench_layout',
|
||||
|
@ -266,7 +266,7 @@ export class ToggleSidebarVisibilityAction extends Action {
|
|||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleSidebarVisibilityAction, ToggleSidebarVisibilityAction.ID, ToggleSidebarVisibilityAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_B }), 'View: Toggle Side Bar Visibility', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleSidebarVisibilityAction, ToggleSidebarVisibilityAction.ID, ToggleSidebarVisibilityAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_B }), 'View: Toggle Side Bar Visibility', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {
|
||||
group: '2_appearance',
|
||||
|
@ -313,7 +313,7 @@ export class ToggleStatusbarVisibilityAction extends Action {
|
|||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleStatusbarVisibilityAction, ToggleStatusbarVisibilityAction.ID, ToggleStatusbarVisibilityAction.LABEL), 'View: Toggle Status Bar Visibility', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleStatusbarVisibilityAction, ToggleStatusbarVisibilityAction.ID, ToggleStatusbarVisibilityAction.LABEL), 'View: Toggle Status Bar Visibility', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '2_workbench_layout',
|
||||
|
@ -350,7 +350,7 @@ class ToggleTabsVisibilityAction extends Action {
|
|||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleTabsVisibilityAction, ToggleTabsVisibilityAction.ID, ToggleTabsVisibilityAction.LABEL, {
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleTabsVisibilityAction, ToggleTabsVisibilityAction.ID, ToggleTabsVisibilityAction.LABEL, {
|
||||
primary: undefined,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_W, },
|
||||
linux: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_W, }
|
||||
|
@ -379,7 +379,7 @@ class ToggleZenMode extends Action {
|
|||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleZenMode, ToggleZenMode.ID, ToggleZenMode.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_Z) }), 'View: Toggle Zen Mode', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleZenMode, ToggleZenMode.ID, ToggleZenMode.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_Z) }), 'View: Toggle Zen Mode', viewCategory);
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '1_toggle_view',
|
||||
|
@ -442,7 +442,7 @@ export class ToggleMenuBarAction extends Action {
|
|||
}
|
||||
|
||||
if (isWindows || isLinux || isWeb) {
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleMenuBarAction, ToggleMenuBarAction.ID, ToggleMenuBarAction.LABEL), 'View: Toggle Menu Bar', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleMenuBarAction, ToggleMenuBarAction.ID, ToggleMenuBarAction.LABEL), 'View: Toggle Menu Bar', viewCategory);
|
||||
}
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
|
@ -529,5 +529,5 @@ export class DecreaseViewSizeAction extends BaseResizeViewAction {
|
|||
}
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(IncreaseViewSizeAction, IncreaseViewSizeAction.ID, IncreaseViewSizeAction.LABEL, undefined), 'View: Increase Current View Size', viewCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(DecreaseViewSizeAction, DecreaseViewSizeAction.ID, DecreaseViewSizeAction.LABEL, undefined), 'View: Decrease Current View Size', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(IncreaseViewSizeAction, IncreaseViewSizeAction.ID, IncreaseViewSizeAction.LABEL, undefined), 'View: Increase Current View Size', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(DecreaseViewSizeAction, DecreaseViewSizeAction.ID, DecreaseViewSizeAction.LABEL, undefined), 'View: Decrease Current View Size', viewCategory);
|
||||
|
|
|
@ -280,7 +280,7 @@ class NavigateDownAction extends BaseNavigationAction {
|
|||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
const viewCategory = nls.localize('view', "View");
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateUpAction, NavigateUpAction.ID, NavigateUpAction.LABEL, undefined), 'View: Navigate to the View Above', viewCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateDownAction, NavigateDownAction.ID, NavigateDownAction.LABEL, undefined), 'View: Navigate to the View Below', viewCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateLeftAction, NavigateLeftAction.ID, NavigateLeftAction.LABEL, undefined), 'View: Navigate to the View on the Left', viewCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateRightAction, NavigateRightAction.ID, NavigateRightAction.LABEL, undefined), 'View: Navigate to the View on the Right', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NavigateUpAction, NavigateUpAction.ID, NavigateUpAction.LABEL, undefined), 'View: Navigate to the View Above', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NavigateDownAction, NavigateDownAction.ID, NavigateDownAction.LABEL, undefined), 'View: Navigate to the View Below', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NavigateLeftAction, NavigateLeftAction.ID, NavigateLeftAction.LABEL, undefined), 'View: Navigate to the View on the Left', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NavigateRightAction, NavigateRightAction.ID, NavigateRightAction.LABEL, undefined), 'View: Navigate to the View on the Right', viewCategory);
|
||||
|
|
|
@ -269,18 +269,18 @@ const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActio
|
|||
// --- Actions Registration
|
||||
|
||||
const fileCategory = nls.localize('file', "File");
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NewWindowAction, NewWindowAction.ID, NewWindowAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_N }), 'New Window');
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenRecentAction, QuickOpenRecentAction.ID, QuickOpenRecentAction.LABEL), 'File: Quick Open Recent...', fileCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenRecentAction, OpenRecentAction.ID, OpenRecentAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_R, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_R } }), 'File: Open Recent...', fileCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NewWindowAction, NewWindowAction.ID, NewWindowAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_N }), 'New Window');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenRecentAction, QuickOpenRecentAction.ID, QuickOpenRecentAction.LABEL), 'File: Quick Open Recent...', fileCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenRecentAction, OpenRecentAction.ID, OpenRecentAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_R, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_R } }), 'File: Open Recent...', fileCategory);
|
||||
|
||||
const viewCategory = nls.localize('view', "View");
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleFullScreenAction, ToggleFullScreenAction.ID, ToggleFullScreenAction.LABEL, { primary: KeyCode.F11, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_F } }), 'View: Toggle Full Screen', viewCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleFullScreenAction, ToggleFullScreenAction.ID, ToggleFullScreenAction.LABEL, { primary: KeyCode.F11, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_F } }), 'View: Toggle Full Screen', viewCategory);
|
||||
|
||||
const developerCategory = nls.localize('developer', "Developer");
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ReloadWindowAction, ReloadWindowAction.ID, ReloadWindowAction.LABEL), 'Developer: Reload Window', developerCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ReloadWindowAction, ReloadWindowAction.ID, ReloadWindowAction.LABEL), 'Developer: Reload Window', developerCategory);
|
||||
|
||||
const helpCategory = nls.localize('help', "Help");
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ShowAboutDialogAction, ShowAboutDialogAction.ID, ShowAboutDialogAction.LABEL), `Help: About`, helpCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ShowAboutDialogAction, ShowAboutDialogAction.ID, ShowAboutDialogAction.LABEL), `Help: About`, helpCategory);
|
||||
|
||||
// --- Commands/Keybindings Registration
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import { IHostService } from 'vs/workbench/services/host/browser/host';
|
|||
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { IWorkspacesService, hasWorkspaceFileExtension } from 'vs/platform/workspaces/common/workspaces';
|
||||
|
||||
export class OpenFileAction extends Action {
|
||||
|
||||
|
@ -213,7 +213,7 @@ export class SaveWorkspaceAsAction extends Action {
|
|||
|
||||
async run(): Promise<any> {
|
||||
const configPathUri = await this.workspaceEditingService.pickNewWorkspacePath();
|
||||
if (configPathUri) {
|
||||
if (configPathUri && hasWorkspaceFileExtension(configPathUri)) {
|
||||
switch (this.contextService.getWorkbenchState()) {
|
||||
case WorkbenchState.EMPTY:
|
||||
case WorkbenchState.FOLDER:
|
||||
|
@ -259,11 +259,11 @@ export class DuplicateWorkspaceInNewWindowAction extends Action {
|
|||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
const workspacesCategory = nls.localize('workspaces', "Workspaces");
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(AddRootFolderAction, AddRootFolderAction.ID, AddRootFolderAction.LABEL), 'Workspaces: Add Folder to Workspace...', workspacesCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(GlobalRemoveRootFolderAction, GlobalRemoveRootFolderAction.ID, GlobalRemoveRootFolderAction.LABEL), 'Workspaces: Remove Folder from Workspace...', workspacesCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseWorkspaceAction, CloseWorkspaceAction.ID, CloseWorkspaceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'Workspaces: Close Workspace', workspacesCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(SaveWorkspaceAsAction, SaveWorkspaceAsAction.ID, SaveWorkspaceAsAction.LABEL), 'Workspaces: Save Workspace As...', workspacesCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(DuplicateWorkspaceInNewWindowAction, DuplicateWorkspaceInNewWindowAction.ID, DuplicateWorkspaceInNewWindowAction.LABEL), 'Workspaces: Duplicate Workspace in New Window', workspacesCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(AddRootFolderAction, AddRootFolderAction.ID, AddRootFolderAction.LABEL), 'Workspaces: Add Folder to Workspace...', workspacesCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(GlobalRemoveRootFolderAction, GlobalRemoveRootFolderAction.ID, GlobalRemoveRootFolderAction.LABEL), 'Workspaces: Remove Folder from Workspace...', workspacesCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(CloseWorkspaceAction, CloseWorkspaceAction.ID, CloseWorkspaceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'Workspaces: Close Workspace', workspacesCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(SaveWorkspaceAsAction, SaveWorkspaceAsAction.ID, SaveWorkspaceAsAction.LABEL), 'Workspaces: Save Workspace As...', workspacesCategory);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(DuplicateWorkspaceInNewWindowAction, DuplicateWorkspaceInNewWindowAction.ID, DuplicateWorkspaceInNewWindowAction.LABEL), 'Workspaces: Duplicate Workspace in New Window', workspacesCategory);
|
||||
|
||||
// --- Menu Registration
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import { EditorInput } from 'vs/workbench/common/editor';
|
|||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { IConstructorSignature0, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IConstructorSignature0, IInstantiationService, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { find } from 'vs/base/common/arrays';
|
||||
|
||||
export interface IEditorDescriptor {
|
||||
|
@ -54,6 +54,14 @@ export interface IEditorRegistry {
|
|||
*/
|
||||
export class EditorDescriptor implements IEditorDescriptor {
|
||||
|
||||
public static create<Services extends BrandedService[]>(
|
||||
ctor: { new(...services: Services): BaseEditor },
|
||||
id: string,
|
||||
name: string
|
||||
): EditorDescriptor {
|
||||
return new EditorDescriptor(ctor as IConstructorSignature0<BaseEditor>, id, name);
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly ctor: IConstructorSignature0<BaseEditor>,
|
||||
private readonly id: string,
|
||||
|
|
|
@ -9,7 +9,7 @@ import { Composite, CompositeDescriptor, CompositeRegistry } from 'vs/workbench/
|
|||
import { Action } from 'vs/base/common/actions';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IConstructorSignature0, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { isAncestor } from 'vs/base/browser/dom';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
|
||||
|
@ -20,7 +20,11 @@ export abstract class Panel extends Composite implements IPanel { }
|
|||
*/
|
||||
export class PanelDescriptor extends CompositeDescriptor<Panel> {
|
||||
|
||||
constructor(ctor: IConstructorSignature0<Panel>, id: string, name: string, cssClass?: string, order?: number, _commandId?: string) {
|
||||
public static create<Services extends BrandedService[]>(ctor: { new(...services: Services): Panel }, id: string, name: string, cssClass?: string, order?: number, _commandId?: string): PanelDescriptor {
|
||||
return new PanelDescriptor(ctor as IConstructorSignature0<Panel>, id, name, cssClass, order, _commandId);
|
||||
}
|
||||
|
||||
private constructor(ctor: IConstructorSignature0<Panel>, id: string, name: string, cssClass?: string, order?: number, _commandId?: string) {
|
||||
super(ctor, id, name, cssClass, order, _commandId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -267,8 +267,8 @@ export class NextSideBarViewAction extends SwitchSideBarViewAction {
|
|||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(PreviousSideBarViewAction, PreviousSideBarViewAction.ID, PreviousSideBarViewAction.LABEL), 'View: Previous Side Bar View', nls.localize('view', "View"));
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NextSideBarViewAction, NextSideBarViewAction.ID, NextSideBarViewAction.LABEL), 'View: Next Side Bar View', nls.localize('view', "View"));
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(PreviousSideBarViewAction, PreviousSideBarViewAction.ID, PreviousSideBarViewAction.LABEL), 'View: Previous Side Bar View', nls.localize('view', "View"));
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NextSideBarViewAction, NextSideBarViewAction.ID, NextSideBarViewAction.LABEL), 'View: Next Side Bar View', nls.localize('view', "View"));
|
||||
|
||||
registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ import { IFilesConfigurationService } from 'vs/workbench/services/filesConfigura
|
|||
|
||||
// Register String Editor
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
new EditorDescriptor(
|
||||
EditorDescriptor.create(
|
||||
TextResourceEditor,
|
||||
TextResourceEditor.ID,
|
||||
nls.localize('textEditor', "Text Editor"),
|
||||
|
@ -70,7 +70,7 @@ Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
|||
|
||||
// Register Text Diff Editor
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
new EditorDescriptor(
|
||||
EditorDescriptor.create(
|
||||
TextDiffEditor,
|
||||
TextDiffEditor.ID,
|
||||
nls.localize('textDiffEditor', "Text Diff Editor")
|
||||
|
@ -82,7 +82,7 @@ Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
|||
|
||||
// Register Binary Resource Diff Editor
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
new EditorDescriptor(
|
||||
EditorDescriptor.create(
|
||||
BinaryResourceDiffEditor,
|
||||
BinaryResourceDiffEditor.ID,
|
||||
nls.localize('binaryDiffEditor', "Binary Diff Editor")
|
||||
|
@ -93,7 +93,7 @@ Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
|||
);
|
||||
|
||||
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
|
||||
new EditorDescriptor(
|
||||
EditorDescriptor.create(
|
||||
SideBySideEditor,
|
||||
SideBySideEditor.ID,
|
||||
nls.localize('sideBySideEditor', "Side by Side Editor")
|
||||
|
@ -226,11 +226,11 @@ Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).regi
|
|||
|
||||
// Register Status Actions
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeModeAction, ChangeModeAction.ID, ChangeModeAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_M) }), 'Change Language Mode');
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeEOLAction, ChangeEOLAction.ID, ChangeEOLAction.LABEL), 'Change End of Line Sequence');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ChangeModeAction, ChangeModeAction.ID, ChangeModeAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_M) }), 'Change Language Mode');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ChangeEOLAction, ChangeEOLAction.ID, ChangeEOLAction.LABEL), 'Change End of Line Sequence');
|
||||
|
||||
if (Object.keys(SUPPORTED_ENCODINGS).length > 1) {
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ChangeEncodingAction, ChangeEncodingAction.ID, ChangeEncodingAction.LABEL), 'Change File Encoding');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ChangeEncodingAction, ChangeEncodingAction.ID, ChangeEncodingAction.LABEL), 'Change File Encoding');
|
||||
}
|
||||
|
||||
export class QuickOpenActionContributor extends ActionBarContributor {
|
||||
|
@ -279,7 +279,7 @@ const editorPickerContextKey = 'inEditorsPicker';
|
|||
const editorPickerContext = ContextKeyExpr.and(inQuickOpenContext, ContextKeyExpr.has(editorPickerContextKey));
|
||||
|
||||
Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen).registerQuickOpenHandler(
|
||||
new QuickOpenHandlerDescriptor(
|
||||
QuickOpenHandlerDescriptor.create(
|
||||
ActiveEditorGroupPicker,
|
||||
ActiveEditorGroupPicker.ID,
|
||||
editorCommands.NAVIGATE_IN_ACTIVE_GROUP_PREFIX,
|
||||
|
@ -295,7 +295,7 @@ Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen).registerQuickOpen
|
|||
);
|
||||
|
||||
Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen).registerQuickOpenHandler(
|
||||
new QuickOpenHandlerDescriptor(
|
||||
QuickOpenHandlerDescriptor.create(
|
||||
AllEditorsPicker,
|
||||
AllEditorsPicker.ID,
|
||||
editorCommands.NAVIGATE_ALL_EDITORS_GROUP_PREFIX,
|
||||
|
@ -312,84 +312,84 @@ Registry.as<IQuickOpenRegistry>(QuickOpenExtensions.Quickopen).registerQuickOpen
|
|||
|
||||
// Register Editor Actions
|
||||
const category = nls.localize('view', "View");
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenNextEditorInGroup, OpenNextEditorInGroup.ID, OpenNextEditorInGroup.LABEL), 'View: Open Next Editor in Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenPreviousEditorInGroup, OpenPreviousEditorInGroup.ID, OpenPreviousEditorInGroup.LABEL), 'View: Open Previous Editor in Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenLastEditorInGroup, OpenLastEditorInGroup.ID, OpenLastEditorInGroup.LABEL, { primary: KeyMod.Alt | KeyCode.KEY_0, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_9], mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_0, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_9] } }), 'View: Open Last Editor in Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenFirstEditorInGroup, OpenFirstEditorInGroup.ID, OpenFirstEditorInGroup.LABEL), 'View: Open First Editor in Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenNextRecentlyUsedEditorAction, OpenNextRecentlyUsedEditorAction.ID, OpenNextRecentlyUsedEditorAction.LABEL), 'View: Open Next Recently Used Editor', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenPreviousRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorAction.ID, OpenPreviousRecentlyUsedEditorAction.LABEL), 'View: Open Previous Recently Used Editor', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ShowAllEditorsAction, ShowAllEditorsAction.ID, ShowAllEditorsAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_P), mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Tab } }), 'View: Show All Editors', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ShowEditorsInActiveGroupAction, ShowEditorsInActiveGroupAction.ID, ShowEditorsInActiveGroupAction.LABEL), 'View: Show Editors in Active Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenNextEditor, OpenNextEditor.ID, OpenNextEditor.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.PageDown, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_CLOSE_SQUARE_BRACKET] } }), 'View: Open Next Editor', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenPreviousEditor, OpenPreviousEditor.ID, OpenPreviousEditor.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.PageUp, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_OPEN_SQUARE_BRACKET] } }), 'View: Open Previous Editor', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ReopenClosedEditorAction, ReopenClosedEditorAction.ID, ReopenClosedEditorAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_T }), 'View: Reopen Closed Editor', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ClearRecentFilesAction, ClearRecentFilesAction.ID, ClearRecentFilesAction.LABEL), 'File: Clear Recently Opened', nls.localize('file', "File"));
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseAllEditorsAction, CloseAllEditorsAction.ID, CloseAllEditorsAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_W) }), 'View: Close All Editors', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseAllEditorGroupsAction, CloseAllEditorGroupsAction.ID, CloseAllEditorGroupsAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_W) }), 'View: Close All Editor Groups', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseLeftEditorsInGroupAction, CloseLeftEditorsInGroupAction.ID, CloseLeftEditorsInGroupAction.LABEL), 'View: Close Editors to the Left in Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseEditorsInOtherGroupsAction, CloseEditorsInOtherGroupsAction.ID, CloseEditorsInOtherGroupsAction.LABEL), 'View: Close Editors in Other Groups', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseEditorInAllGroupsAction, CloseEditorInAllGroupsAction.ID, CloseEditorInAllGroupsAction.LABEL), 'View: Close Editor in All Groups', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(SplitEditorAction, SplitEditorAction.ID, SplitEditorAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.US_BACKSLASH }), 'View: Split Editor', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(SplitEditorOrthogonalAction, SplitEditorOrthogonalAction.ID, SplitEditorOrthogonalAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_BACKSLASH) }), 'View: Split Editor Orthogonal', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(SplitEditorLeftAction, SplitEditorLeftAction.ID, SplitEditorLeftAction.LABEL), 'View: Split Editor Left', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(SplitEditorRightAction, SplitEditorRightAction.ID, SplitEditorRightAction.LABEL), 'View: Split Editor Right', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(SplitEditorUpAction, SplitEditorUpAction.ID, SplitEditorUpAction.LABEL), 'Split Editor Up', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(SplitEditorDownAction, SplitEditorDownAction.ID, SplitEditorDownAction.LABEL), 'View: Split Editor Down', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(JoinTwoGroupsAction, JoinTwoGroupsAction.ID, JoinTwoGroupsAction.LABEL), 'View: Join Editor Group with Next Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(JoinAllGroupsAction, JoinAllGroupsAction.ID, JoinAllGroupsAction.LABEL), 'View: Join All Editor Groups', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateBetweenGroupsAction, NavigateBetweenGroupsAction.ID, NavigateBetweenGroupsAction.LABEL), 'View: Navigate Between Editor Groups', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ResetGroupSizesAction, ResetGroupSizesAction.ID, ResetGroupSizesAction.LABEL), 'View: Reset Editor Group Sizes', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ToggleGroupSizesAction, ToggleGroupSizesAction.ID, ToggleGroupSizesAction.LABEL), 'View: Toggle Editor Group Sizes', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MaximizeGroupAction, MaximizeGroupAction.ID, MaximizeGroupAction.LABEL), 'View: Maximize Editor Group and Hide Side Bar', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MinimizeOtherGroupsAction, MinimizeOtherGroupsAction.ID, MinimizeOtherGroupsAction.LABEL), 'View: Maximize Editor Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveEditorLeftInGroupAction, MoveEditorLeftInGroupAction.ID, MoveEditorLeftInGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.PageUp, mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow) } }), 'View: Move Editor Left', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveEditorRightInGroupAction, MoveEditorRightInGroupAction.ID, MoveEditorRightInGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.PageDown, mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow) } }), 'View: Move Editor Right', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveGroupLeftAction, MoveGroupLeftAction.ID, MoveGroupLeftAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.LeftArrow) }), 'View: Move Editor Group Left', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveGroupRightAction, MoveGroupRightAction.ID, MoveGroupRightAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.RightArrow) }), 'View: Move Editor Group Right', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveGroupUpAction, MoveGroupUpAction.ID, MoveGroupUpAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.UpArrow) }), 'View: Move Editor Group Up', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveGroupDownAction, MoveGroupDownAction.ID, MoveGroupDownAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.DownArrow) }), 'View: Move Editor Group Down', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveEditorToPreviousGroupAction, MoveEditorToPreviousGroupAction.ID, MoveEditorToPreviousGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.LeftArrow } }), 'View: Move Editor into Previous Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveEditorToNextGroupAction, MoveEditorToNextGroupAction.ID, MoveEditorToNextGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.RightArrow } }), 'View: Move Editor into Next Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveEditorToFirstGroupAction, MoveEditorToFirstGroupAction.ID, MoveEditorToFirstGroupAction.LABEL, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_1, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_1 } }), 'View: Move Editor into First Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveEditorToLastGroupAction, MoveEditorToLastGroupAction.ID, MoveEditorToLastGroupAction.LABEL, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_9, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_9 } }), 'View: Move Editor into Last Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveEditorToLeftGroupAction, MoveEditorToLeftGroupAction.ID, MoveEditorToLeftGroupAction.LABEL), 'View: Move Editor into Left Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveEditorToRightGroupAction, MoveEditorToRightGroupAction.ID, MoveEditorToRightGroupAction.LABEL), 'View: Move Editor into Right Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveEditorToAboveGroupAction, MoveEditorToAboveGroupAction.ID, MoveEditorToAboveGroupAction.LABEL), 'View: Move Editor into Above Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(MoveEditorToBelowGroupAction, MoveEditorToBelowGroupAction.ID, MoveEditorToBelowGroupAction.LABEL), 'View: Move Editor into Below Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusActiveGroupAction, FocusActiveGroupAction.ID, FocusActiveGroupAction.LABEL), 'View: Focus Active Editor Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusFirstGroupAction, FocusFirstGroupAction.ID, FocusFirstGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_1 }), 'View: Focus First Editor Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusLastGroupAction, FocusLastGroupAction.ID, FocusLastGroupAction.LABEL), 'View: Focus Last Editor Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusPreviousGroup, FocusPreviousGroup.ID, FocusPreviousGroup.LABEL), 'View: Focus Previous Editor Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusNextGroup, FocusNextGroup.ID, FocusNextGroup.LABEL), 'View: Focus Next Editor Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusLeftGroup, FocusLeftGroup.ID, FocusLeftGroup.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.LeftArrow) }), 'View: Focus Left Editor Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusRightGroup, FocusRightGroup.ID, FocusRightGroup.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.RightArrow) }), 'View: Focus Right Editor Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusAboveGroup, FocusAboveGroup.ID, FocusAboveGroup.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.UpArrow) }), 'View: Focus Above Editor Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusBelowGroup, FocusBelowGroup.ID, FocusBelowGroup.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.DownArrow) }), 'View: Focus Below Editor Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NewEditorGroupLeftAction, NewEditorGroupLeftAction.ID, NewEditorGroupLeftAction.LABEL), 'View: New Editor Group to the Left', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NewEditorGroupRightAction, NewEditorGroupRightAction.ID, NewEditorGroupRightAction.LABEL), 'View: New Editor Group to the Right', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NewEditorGroupAboveAction, NewEditorGroupAboveAction.ID, NewEditorGroupAboveAction.LABEL), 'View: New Editor Group Above', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NewEditorGroupBelowAction, NewEditorGroupBelowAction.ID, NewEditorGroupBelowAction.LABEL), 'View: New Editor Group Below', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateForwardAction, NavigateForwardAction.ID, NavigateForwardAction.LABEL, { primary: 0, win: { primary: KeyMod.Alt | KeyCode.RightArrow }, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.US_MINUS }, linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_MINUS } }), 'Go Forward');
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateBackwardsAction, NavigateBackwardsAction.ID, NavigateBackwardsAction.LABEL, { primary: 0, win: { primary: KeyMod.Alt | KeyCode.LeftArrow }, mac: { primary: KeyMod.WinCtrl | KeyCode.US_MINUS }, linux: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.US_MINUS } }), 'Go Back');
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateToLastEditLocationAction, NavigateToLastEditLocationAction.ID, NavigateToLastEditLocationAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_Q) }), 'Go to Last Edit Location');
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(NavigateLastAction, NavigateLastAction.ID, NavigateLastAction.LABEL), 'Go Last');
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenPreviousEditorFromHistoryAction, OpenPreviousEditorFromHistoryAction.ID, OpenPreviousEditorFromHistoryAction.LABEL), 'Open Previous Editor from History');
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ClearEditorHistoryAction, ClearEditorHistoryAction.ID, ClearEditorHistoryAction.LABEL), 'Clear Editor History');
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(RevertAndCloseEditorAction, RevertAndCloseEditorAction.ID, RevertAndCloseEditorAction.LABEL), 'View: Revert and Close Editor', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutSingleAction, EditorLayoutSingleAction.ID, EditorLayoutSingleAction.LABEL), 'View: Single Column Editor Layout', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoColumnsAction, EditorLayoutTwoColumnsAction.ID, EditorLayoutTwoColumnsAction.LABEL), 'View: Two Columns Editor Layout', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutThreeColumnsAction, EditorLayoutThreeColumnsAction.ID, EditorLayoutThreeColumnsAction.LABEL), 'View: Three Columns Editor Layout', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoRowsAction, EditorLayoutTwoRowsAction.ID, EditorLayoutTwoRowsAction.LABEL), 'View: Two Rows Editor Layout', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutThreeRowsAction, EditorLayoutThreeRowsAction.ID, EditorLayoutThreeRowsAction.LABEL), 'View: Three Rows Editor Layout', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoByTwoGridAction, EditorLayoutTwoByTwoGridAction.ID, EditorLayoutTwoByTwoGridAction.LABEL), 'View: Grid Editor Layout (2x2)', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoRowsRightAction, EditorLayoutTwoRowsRightAction.ID, EditorLayoutTwoRowsRightAction.LABEL), 'View: Two Rows Right Editor Layout', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(EditorLayoutTwoColumnsBottomAction, EditorLayoutTwoColumnsBottomAction.ID, EditorLayoutTwoColumnsBottomAction.LABEL), 'View: Two Columns Bottom Editor Layout', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenNextEditorInGroup, OpenNextEditorInGroup.ID, OpenNextEditorInGroup.LABEL), 'View: Open Next Editor in Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenPreviousEditorInGroup, OpenPreviousEditorInGroup.ID, OpenPreviousEditorInGroup.LABEL), 'View: Open Previous Editor in Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenLastEditorInGroup, OpenLastEditorInGroup.ID, OpenLastEditorInGroup.LABEL, { primary: KeyMod.Alt | KeyCode.KEY_0, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_9], mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_0, secondary: [KeyMod.CtrlCmd | KeyCode.KEY_9] } }), 'View: Open Last Editor in Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenFirstEditorInGroup, OpenFirstEditorInGroup.ID, OpenFirstEditorInGroup.LABEL), 'View: Open First Editor in Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenNextRecentlyUsedEditorAction, OpenNextRecentlyUsedEditorAction.ID, OpenNextRecentlyUsedEditorAction.LABEL), 'View: Open Next Recently Used Editor', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenPreviousRecentlyUsedEditorAction, OpenPreviousRecentlyUsedEditorAction.ID, OpenPreviousRecentlyUsedEditorAction.LABEL), 'View: Open Previous Recently Used Editor', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ShowAllEditorsAction, ShowAllEditorsAction.ID, ShowAllEditorsAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_P), mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Tab } }), 'View: Show All Editors', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ShowEditorsInActiveGroupAction, ShowEditorsInActiveGroupAction.ID, ShowEditorsInActiveGroupAction.LABEL), 'View: Show Editors in Active Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenNextEditor, OpenNextEditor.ID, OpenNextEditor.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.PageDown, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_CLOSE_SQUARE_BRACKET] } }), 'View: Open Next Editor', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenPreviousEditor, OpenPreviousEditor.ID, OpenPreviousEditor.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.PageUp, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_OPEN_SQUARE_BRACKET] } }), 'View: Open Previous Editor', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ReopenClosedEditorAction, ReopenClosedEditorAction.ID, ReopenClosedEditorAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_T }), 'View: Reopen Closed Editor', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ClearRecentFilesAction, ClearRecentFilesAction.ID, ClearRecentFilesAction.LABEL), 'File: Clear Recently Opened', nls.localize('file', "File"));
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(CloseAllEditorsAction, CloseAllEditorsAction.ID, CloseAllEditorsAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_W) }), 'View: Close All Editors', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(CloseAllEditorGroupsAction, CloseAllEditorGroupsAction.ID, CloseAllEditorGroupsAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_W) }), 'View: Close All Editor Groups', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(CloseLeftEditorsInGroupAction, CloseLeftEditorsInGroupAction.ID, CloseLeftEditorsInGroupAction.LABEL), 'View: Close Editors to the Left in Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(CloseEditorsInOtherGroupsAction, CloseEditorsInOtherGroupsAction.ID, CloseEditorsInOtherGroupsAction.LABEL), 'View: Close Editors in Other Groups', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(CloseEditorInAllGroupsAction, CloseEditorInAllGroupsAction.ID, CloseEditorInAllGroupsAction.LABEL), 'View: Close Editor in All Groups', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(SplitEditorAction, SplitEditorAction.ID, SplitEditorAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.US_BACKSLASH }), 'View: Split Editor', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(SplitEditorOrthogonalAction, SplitEditorOrthogonalAction.ID, SplitEditorOrthogonalAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.US_BACKSLASH) }), 'View: Split Editor Orthogonal', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(SplitEditorLeftAction, SplitEditorLeftAction.ID, SplitEditorLeftAction.LABEL), 'View: Split Editor Left', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(SplitEditorRightAction, SplitEditorRightAction.ID, SplitEditorRightAction.LABEL), 'View: Split Editor Right', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(SplitEditorUpAction, SplitEditorUpAction.ID, SplitEditorUpAction.LABEL), 'Split Editor Up', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(SplitEditorDownAction, SplitEditorDownAction.ID, SplitEditorDownAction.LABEL), 'View: Split Editor Down', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(JoinTwoGroupsAction, JoinTwoGroupsAction.ID, JoinTwoGroupsAction.LABEL), 'View: Join Editor Group with Next Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(JoinAllGroupsAction, JoinAllGroupsAction.ID, JoinAllGroupsAction.LABEL), 'View: Join All Editor Groups', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NavigateBetweenGroupsAction, NavigateBetweenGroupsAction.ID, NavigateBetweenGroupsAction.LABEL), 'View: Navigate Between Editor Groups', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ResetGroupSizesAction, ResetGroupSizesAction.ID, ResetGroupSizesAction.LABEL), 'View: Reset Editor Group Sizes', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleGroupSizesAction, ToggleGroupSizesAction.ID, ToggleGroupSizesAction.LABEL), 'View: Toggle Editor Group Sizes', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MaximizeGroupAction, MaximizeGroupAction.ID, MaximizeGroupAction.LABEL), 'View: Maximize Editor Group and Hide Side Bar', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MinimizeOtherGroupsAction, MinimizeOtherGroupsAction.ID, MinimizeOtherGroupsAction.LABEL), 'View: Maximize Editor Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveEditorLeftInGroupAction, MoveEditorLeftInGroupAction.ID, MoveEditorLeftInGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.PageUp, mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow) } }), 'View: Move Editor Left', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveEditorRightInGroupAction, MoveEditorRightInGroupAction.ID, MoveEditorRightInGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.PageDown, mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow) } }), 'View: Move Editor Right', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveGroupLeftAction, MoveGroupLeftAction.ID, MoveGroupLeftAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.LeftArrow) }), 'View: Move Editor Group Left', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveGroupRightAction, MoveGroupRightAction.ID, MoveGroupRightAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.RightArrow) }), 'View: Move Editor Group Right', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveGroupUpAction, MoveGroupUpAction.ID, MoveGroupUpAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.UpArrow) }), 'View: Move Editor Group Up', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveGroupDownAction, MoveGroupDownAction.ID, MoveGroupDownAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.DownArrow) }), 'View: Move Editor Group Down', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveEditorToPreviousGroupAction, MoveEditorToPreviousGroupAction.ID, MoveEditorToPreviousGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.LeftArrow } }), 'View: Move Editor into Previous Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveEditorToNextGroupAction, MoveEditorToNextGroupAction.ID, MoveEditorToNextGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.RightArrow } }), 'View: Move Editor into Next Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveEditorToFirstGroupAction, MoveEditorToFirstGroupAction.ID, MoveEditorToFirstGroupAction.LABEL, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_1, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_1 } }), 'View: Move Editor into First Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveEditorToLastGroupAction, MoveEditorToLastGroupAction.ID, MoveEditorToLastGroupAction.LABEL, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.KEY_9, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_9 } }), 'View: Move Editor into Last Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveEditorToLeftGroupAction, MoveEditorToLeftGroupAction.ID, MoveEditorToLeftGroupAction.LABEL), 'View: Move Editor into Left Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveEditorToRightGroupAction, MoveEditorToRightGroupAction.ID, MoveEditorToRightGroupAction.LABEL), 'View: Move Editor into Right Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveEditorToAboveGroupAction, MoveEditorToAboveGroupAction.ID, MoveEditorToAboveGroupAction.LABEL), 'View: Move Editor into Above Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(MoveEditorToBelowGroupAction, MoveEditorToBelowGroupAction.ID, MoveEditorToBelowGroupAction.LABEL), 'View: Move Editor into Below Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(FocusActiveGroupAction, FocusActiveGroupAction.ID, FocusActiveGroupAction.LABEL), 'View: Focus Active Editor Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(FocusFirstGroupAction, FocusFirstGroupAction.ID, FocusFirstGroupAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_1 }), 'View: Focus First Editor Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(FocusLastGroupAction, FocusLastGroupAction.ID, FocusLastGroupAction.LABEL), 'View: Focus Last Editor Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(FocusPreviousGroup, FocusPreviousGroup.ID, FocusPreviousGroup.LABEL), 'View: Focus Previous Editor Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(FocusNextGroup, FocusNextGroup.ID, FocusNextGroup.LABEL), 'View: Focus Next Editor Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(FocusLeftGroup, FocusLeftGroup.ID, FocusLeftGroup.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.LeftArrow) }), 'View: Focus Left Editor Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(FocusRightGroup, FocusRightGroup.ID, FocusRightGroup.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.RightArrow) }), 'View: Focus Right Editor Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(FocusAboveGroup, FocusAboveGroup.ID, FocusAboveGroup.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.UpArrow) }), 'View: Focus Above Editor Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(FocusBelowGroup, FocusBelowGroup.ID, FocusBelowGroup.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.DownArrow) }), 'View: Focus Below Editor Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NewEditorGroupLeftAction, NewEditorGroupLeftAction.ID, NewEditorGroupLeftAction.LABEL), 'View: New Editor Group to the Left', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NewEditorGroupRightAction, NewEditorGroupRightAction.ID, NewEditorGroupRightAction.LABEL), 'View: New Editor Group to the Right', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NewEditorGroupAboveAction, NewEditorGroupAboveAction.ID, NewEditorGroupAboveAction.LABEL), 'View: New Editor Group Above', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NewEditorGroupBelowAction, NewEditorGroupBelowAction.ID, NewEditorGroupBelowAction.LABEL), 'View: New Editor Group Below', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NavigateForwardAction, NavigateForwardAction.ID, NavigateForwardAction.LABEL, { primary: 0, win: { primary: KeyMod.Alt | KeyCode.RightArrow }, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.US_MINUS }, linux: { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.US_MINUS } }), 'Go Forward');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NavigateBackwardsAction, NavigateBackwardsAction.ID, NavigateBackwardsAction.LABEL, { primary: 0, win: { primary: KeyMod.Alt | KeyCode.LeftArrow }, mac: { primary: KeyMod.WinCtrl | KeyCode.US_MINUS }, linux: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.US_MINUS } }), 'Go Back');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NavigateToLastEditLocationAction, NavigateToLastEditLocationAction.ID, NavigateToLastEditLocationAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_Q) }), 'Go to Last Edit Location');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(NavigateLastAction, NavigateLastAction.ID, NavigateLastAction.LABEL), 'Go Last');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenPreviousEditorFromHistoryAction, OpenPreviousEditorFromHistoryAction.ID, OpenPreviousEditorFromHistoryAction.LABEL), 'Open Previous Editor from History');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ClearEditorHistoryAction, ClearEditorHistoryAction.ID, ClearEditorHistoryAction.LABEL), 'Clear Editor History');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(RevertAndCloseEditorAction, RevertAndCloseEditorAction.ID, RevertAndCloseEditorAction.LABEL), 'View: Revert and Close Editor', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(EditorLayoutSingleAction, EditorLayoutSingleAction.ID, EditorLayoutSingleAction.LABEL), 'View: Single Column Editor Layout', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(EditorLayoutTwoColumnsAction, EditorLayoutTwoColumnsAction.ID, EditorLayoutTwoColumnsAction.LABEL), 'View: Two Columns Editor Layout', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(EditorLayoutThreeColumnsAction, EditorLayoutThreeColumnsAction.ID, EditorLayoutThreeColumnsAction.LABEL), 'View: Three Columns Editor Layout', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(EditorLayoutTwoRowsAction, EditorLayoutTwoRowsAction.ID, EditorLayoutTwoRowsAction.LABEL), 'View: Two Rows Editor Layout', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(EditorLayoutThreeRowsAction, EditorLayoutThreeRowsAction.ID, EditorLayoutThreeRowsAction.LABEL), 'View: Three Rows Editor Layout', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(EditorLayoutTwoByTwoGridAction, EditorLayoutTwoByTwoGridAction.ID, EditorLayoutTwoByTwoGridAction.LABEL), 'View: Grid Editor Layout (2x2)', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(EditorLayoutTwoRowsRightAction, EditorLayoutTwoRowsRightAction.ID, EditorLayoutTwoRowsRightAction.LABEL), 'View: Two Rows Right Editor Layout', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(EditorLayoutTwoColumnsBottomAction, EditorLayoutTwoColumnsBottomAction.ID, EditorLayoutTwoColumnsBottomAction.LABEL), 'View: Two Columns Bottom Editor Layout', category);
|
||||
|
||||
// Register Editor Picker Actions including quick navigate support
|
||||
const openNextEditorKeybinding = { primary: KeyMod.CtrlCmd | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyCode.Tab } };
|
||||
const openPreviousEditorKeybinding = { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.Tab } };
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenNextRecentlyUsedEditorInGroupAction, OpenNextRecentlyUsedEditorInGroupAction.ID, OpenNextRecentlyUsedEditorInGroupAction.LABEL, openNextEditorKeybinding), 'View: Open Next Recently Used Editor in Group', category);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenPreviousRecentlyUsedEditorInGroupAction, OpenPreviousRecentlyUsedEditorInGroupAction.ID, OpenPreviousRecentlyUsedEditorInGroupAction.LABEL, openPreviousEditorKeybinding), 'View: Open Previous Recently Used Editor in Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenNextRecentlyUsedEditorInGroupAction, OpenNextRecentlyUsedEditorInGroupAction.ID, OpenNextRecentlyUsedEditorInGroupAction.LABEL, openNextEditorKeybinding), 'View: Open Next Recently Used Editor in Group', category);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenPreviousRecentlyUsedEditorInGroupAction, OpenPreviousRecentlyUsedEditorInGroupAction.ID, OpenPreviousRecentlyUsedEditorInGroupAction.LABEL, openPreviousEditorKeybinding), 'View: Open Previous Recently Used Editor in Group', category);
|
||||
|
||||
const quickOpenNavigateNextInEditorPickerId = 'workbench.action.quickOpenNavigateNextInEditorPicker';
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
|
|
|
@ -507,7 +507,7 @@ export class CloseOneEditorAction extends Action {
|
|||
|
||||
// Close specific editor in group
|
||||
if (typeof editorIndex === 'number') {
|
||||
const editorAtIndex = group.getEditor(editorIndex);
|
||||
const editorAtIndex = group.getEditorByIndex(editorIndex);
|
||||
if (editorAtIndex) {
|
||||
return group.closeEditor(editorAtIndex);
|
||||
}
|
||||
|
|
|
@ -318,7 +318,7 @@ function registerOpenEditorAtIndexCommands(): void {
|
|||
const editorService = accessor.get(IEditorService);
|
||||
const activeControl = editorService.activeControl;
|
||||
if (activeControl) {
|
||||
const editor = activeControl.group.getEditor(editorIndex);
|
||||
const editor = activeControl.group.getEditorByIndex(editorIndex);
|
||||
if (editor) {
|
||||
editorService.openEditor(editor);
|
||||
}
|
||||
|
@ -448,7 +448,7 @@ export function splitEditor(editorGroupService: IEditorGroupsService, direction:
|
|||
// Split editor (if it can be split)
|
||||
let editorToCopy: IEditorInput | undefined;
|
||||
if (context && typeof context.editorIndex === 'number') {
|
||||
editorToCopy = sourceGroup.getEditor(context.editorIndex);
|
||||
editorToCopy = sourceGroup.getEditorByIndex(context.editorIndex);
|
||||
} else {
|
||||
editorToCopy = types.withNullAsUndefined(sourceGroup.activeEditor);
|
||||
}
|
||||
|
@ -548,7 +548,7 @@ function registerCloseEditorCommands() {
|
|||
if (group) {
|
||||
const editors = coalesce(contexts
|
||||
.filter(context => context.groupId === groupId)
|
||||
.map(context => typeof context.editorIndex === 'number' ? group.getEditor(context.editorIndex) : group.activeEditor));
|
||||
.map(context => typeof context.editorIndex === 'number' ? group.getEditorByIndex(context.editorIndex) : group.activeEditor));
|
||||
|
||||
return group.closeEditors(editors);
|
||||
}
|
||||
|
@ -603,7 +603,7 @@ function registerCloseEditorCommands() {
|
|||
if (group) {
|
||||
const editors = contexts
|
||||
.filter(context => context.groupId === groupId)
|
||||
.map(context => typeof context.editorIndex === 'number' ? group.getEditor(context.editorIndex) : group.activeEditor);
|
||||
.map(context => typeof context.editorIndex === 'number' ? group.getEditorByIndex(context.editorIndex) : group.activeEditor);
|
||||
const editorsToClose = group.editors.filter(e => editors.indexOf(e) === -1);
|
||||
|
||||
if (group.activeEditor) {
|
||||
|
@ -715,7 +715,7 @@ function resolveCommandsContext(editorGroupService: IEditorGroupsService, contex
|
|||
|
||||
// Resolve from context
|
||||
let group = context && typeof context.groupId === 'number' ? editorGroupService.getGroup(context.groupId) : undefined;
|
||||
let editor = group && context && typeof context.editorIndex === 'number' ? types.withNullAsUndefined(group.getEditor(context.editorIndex)) : undefined;
|
||||
let editor = group && context && typeof context.editorIndex === 'number' ? types.withNullAsUndefined(group.getEditorByIndex(context.editorIndex)) : undefined;
|
||||
let control = group ? group.activeControl : undefined;
|
||||
|
||||
// Fallback to active group as needed
|
||||
|
|
|
@ -518,11 +518,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
|||
editorsToClose.push(editor.master, editor.details);
|
||||
}
|
||||
|
||||
// Close the editor when it is no longer open in any group including diff editors
|
||||
// Dispose the editor when it is no longer open in any group including diff editors
|
||||
editorsToClose.forEach(editorToClose => {
|
||||
const resource = editorToClose ? editorToClose.getResource() : undefined; // prefer resource to not close right-hand side editors of a diff editor
|
||||
if (!this.accessor.groups.some(groupView => groupView.group.contains(resource || editorToClose))) {
|
||||
editorToClose.close();
|
||||
if (!this.accessor.groups.some(groupView => groupView.group.contains(editorToClose, true /* include side by side editor master & details */))) {
|
||||
editorToClose.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -761,8 +760,8 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
|||
return this.editors;
|
||||
}
|
||||
|
||||
getEditor(index: number): EditorInput | undefined {
|
||||
return this._group.getEditor(index);
|
||||
getEditorByIndex(index: number): EditorInput | undefined {
|
||||
return this._group.getEditorByIndex(index);
|
||||
}
|
||||
|
||||
getIndexOfEditor(editor: EditorInput): number {
|
||||
|
@ -1121,7 +1120,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
|||
}
|
||||
|
||||
// Check for dirty and veto
|
||||
const veto = await this.handleDirty([editor]);
|
||||
const veto = await this.handleDirtyClosing([editor]);
|
||||
if (veto) {
|
||||
return;
|
||||
}
|
||||
|
@ -1232,7 +1231,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
|||
this._group.closeEditor(editor);
|
||||
}
|
||||
|
||||
private async handleDirty(editors: EditorInput[]): Promise<boolean /* veto */> {
|
||||
private async handleDirtyClosing(editors: EditorInput[]): Promise<boolean /* veto */> {
|
||||
if (!editors.length) {
|
||||
return false; // no veto
|
||||
}
|
||||
|
@ -1241,13 +1240,13 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
|||
|
||||
// To prevent multiple confirmation dialogs from showing up one after the other
|
||||
// we check if a pending confirmation is currently showing and if so, join that
|
||||
let handleDirtyPromise = this.mapEditorToPendingConfirmation.get(editor);
|
||||
if (!handleDirtyPromise) {
|
||||
handleDirtyPromise = this.doHandleDirty(editor);
|
||||
this.mapEditorToPendingConfirmation.set(editor, handleDirtyPromise);
|
||||
let handleDirtyClosingPromise = this.mapEditorToPendingConfirmation.get(editor);
|
||||
if (!handleDirtyClosingPromise) {
|
||||
handleDirtyClosingPromise = this.doHandleDirtyClosing(editor);
|
||||
this.mapEditorToPendingConfirmation.set(editor, handleDirtyClosingPromise);
|
||||
}
|
||||
|
||||
const veto = await handleDirtyPromise;
|
||||
const veto = await handleDirtyClosingPromise;
|
||||
|
||||
// Make sure to remove from our map of cached pending confirmations
|
||||
this.mapEditorToPendingConfirmation.delete(editor);
|
||||
|
@ -1258,16 +1257,40 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
|||
}
|
||||
|
||||
// Otherwise continue with the remainders
|
||||
return this.handleDirty(editors);
|
||||
return this.handleDirtyClosing(editors);
|
||||
}
|
||||
|
||||
private async doHandleDirty(editor: EditorInput): Promise<boolean /* veto */> {
|
||||
if (
|
||||
!editor.isDirty() || // editor must be dirty
|
||||
this.accessor.groups.some(groupView => groupView !== this && groupView.group.contains(editor, true /* support side by side */)) || // editor is opened in other group
|
||||
editor instanceof SideBySideEditorInput && this.isOpened(editor.master) // side by side editor master is still opened
|
||||
) {
|
||||
private async doHandleDirtyClosing(editor: EditorInput): Promise<boolean /* veto */> {
|
||||
if (!editor.isDirty()) {
|
||||
return false; // editor must be dirty
|
||||
}
|
||||
|
||||
if (editor instanceof SideBySideEditorInput && this.isOpened(editor.master)) {
|
||||
return false; // master-side of editor is still opened somewhere else
|
||||
}
|
||||
|
||||
// Note: we explicitly decide to ask for confirm if closing a normal editor even
|
||||
// if it is opened in a side-by-side editor in the group. This decision is made
|
||||
// because it may be less obvious that one side of a side by side editor is dirty
|
||||
// and can still be changed.
|
||||
|
||||
if (this.accessor.groups.some(groupView => {
|
||||
if (groupView === this) {
|
||||
return false; // skip this group to avoid false assumptions about the editor being opened still
|
||||
}
|
||||
|
||||
const otherGroup = groupView.group;
|
||||
if (otherGroup.contains(editor)) {
|
||||
return true; // exact editor still opened
|
||||
}
|
||||
|
||||
if (editor instanceof SideBySideEditorInput && otherGroup.contains(editor.master)) {
|
||||
return true; // master side of side by side editor still opened
|
||||
}
|
||||
|
||||
return false;
|
||||
})) {
|
||||
return false; // editor is still editable somewhere else
|
||||
}
|
||||
|
||||
// Switch to editor that we want to handle and confirm to save/revert
|
||||
|
@ -1324,7 +1347,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
|||
const editors = this.getEditorsToClose(args);
|
||||
|
||||
// Check for dirty and veto
|
||||
const veto = await this.handleDirty(editors.slice(0));
|
||||
const veto = await this.handleDirtyClosing(editors.slice(0));
|
||||
if (veto) {
|
||||
return;
|
||||
}
|
||||
|
@ -1403,7 +1426,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
|||
|
||||
// Check for dirty and veto
|
||||
const editors = this._group.getEditors(true);
|
||||
const veto = await this.handleDirty(editors.slice(0));
|
||||
const veto = await this.handleDirtyClosing(editors.slice(0));
|
||||
if (veto) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,21 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.monaco-workbench.windows .part.editor > .content .editor-group-container > .title,
|
||||
.monaco-workbench.linux .part.editor > .content .editor-group-container > .title,
|
||||
.monaco-workbench.web .part.editor > .content .editor-group-container > .title {
|
||||
/*
|
||||
* Explicitly put the part onto its own layer to help Chrome to
|
||||
* render the content with LCD-anti-aliasing. By partioning the
|
||||
* workbench into multiple layers, we can ensure that a bad
|
||||
* behaving part is not making another part fallback to greyscale
|
||||
* rendering.
|
||||
*
|
||||
* macOS: does not render LCD-anti-aliased.
|
||||
*/
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title:not(.tabs) {
|
||||
display: flex; /* when tabs are not shown, use flex layout */
|
||||
flex-wrap: nowrap;
|
||||
|
|
|
@ -501,7 +501,7 @@ export class TabsTitleControl extends TitleControl {
|
|||
}
|
||||
|
||||
// Open tabs editor
|
||||
const input = this.group.getEditor(index);
|
||||
const input = this.group.getEditorByIndex(index);
|
||||
if (input) {
|
||||
this.group.openEditor(input);
|
||||
}
|
||||
|
@ -512,7 +512,7 @@ export class TabsTitleControl extends TitleControl {
|
|||
const showContextMenu = (e: Event) => {
|
||||
EventHelper.stop(e);
|
||||
|
||||
const input = this.group.getEditor(index);
|
||||
const input = this.group.getEditorByIndex(index);
|
||||
if (input) {
|
||||
this.onContextMenu(input, e, tab);
|
||||
}
|
||||
|
@ -562,7 +562,7 @@ export class TabsTitleControl extends TitleControl {
|
|||
// Run action on Enter/Space
|
||||
if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
|
||||
handled = true;
|
||||
const input = this.group.getEditor(index);
|
||||
const input = this.group.getEditorByIndex(index);
|
||||
if (input) {
|
||||
this.group.openEditor(input);
|
||||
}
|
||||
|
@ -581,7 +581,7 @@ export class TabsTitleControl extends TitleControl {
|
|||
targetIndex = this.group.count - 1;
|
||||
}
|
||||
|
||||
const target = this.group.getEditor(targetIndex);
|
||||
const target = this.group.getEditorByIndex(targetIndex);
|
||||
if (target) {
|
||||
handled = true;
|
||||
this.group.openEditor(target, { preserveFocus: true });
|
||||
|
@ -603,7 +603,7 @@ export class TabsTitleControl extends TitleControl {
|
|||
disposables.add(addDisposableListener(tab, EventType.DBLCLICK, (e: MouseEvent) => {
|
||||
EventHelper.stop(e);
|
||||
|
||||
const editor = this.group.getEditor(index);
|
||||
const editor = this.group.getEditorByIndex(index);
|
||||
if (editor && this.group.isPinned(editor)) {
|
||||
this.accessor.arrangeGroups(GroupsArrangement.TOGGLE, this.group);
|
||||
} else {
|
||||
|
@ -615,7 +615,7 @@ export class TabsTitleControl extends TitleControl {
|
|||
disposables.add(addDisposableListener(tab, EventType.CONTEXT_MENU, (e: Event) => {
|
||||
EventHelper.stop(e, true);
|
||||
|
||||
const input = this.group.getEditor(index);
|
||||
const input = this.group.getEditorByIndex(index);
|
||||
if (input) {
|
||||
this.onContextMenu(input, e, tab);
|
||||
}
|
||||
|
@ -623,7 +623,7 @@ export class TabsTitleControl extends TitleControl {
|
|||
|
||||
// Drag support
|
||||
disposables.add(addDisposableListener(tab, EventType.DRAG_START, (e: DragEvent) => {
|
||||
const editor = this.group.getEditor(index);
|
||||
const editor = this.group.getEditorByIndex(index);
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
@ -669,7 +669,7 @@ export class TabsTitleControl extends TitleControl {
|
|||
const data = this.editorTransfer.getData(DraggedEditorIdentifier.prototype);
|
||||
if (Array.isArray(data)) {
|
||||
const localDraggedEditor = data[0].identifier;
|
||||
if (localDraggedEditor.editor === this.group.getEditor(index) && localDraggedEditor.groupId === this.group.id) {
|
||||
if (localDraggedEditor.editor === this.group.getEditorByIndex(index) && localDraggedEditor.groupId === this.group.id) {
|
||||
if (e.dataTransfer) {
|
||||
e.dataTransfer.dropEffect = 'none';
|
||||
}
|
||||
|
@ -739,7 +739,7 @@ export class TabsTitleControl extends TitleControl {
|
|||
|
||||
private updateDropFeedback(element: HTMLElement, isDND: boolean, index?: number): void {
|
||||
const isTab = (typeof index === 'number');
|
||||
const editor = typeof index === 'number' ? this.group.getEditor(index) : undefined;
|
||||
const editor = typeof index === 'number' ? this.group.getEditorByIndex(index) : undefined;
|
||||
const isActiveTab = isTab && !!editor && this.group.isActive(editor);
|
||||
|
||||
// Background
|
||||
|
|
|
@ -16,7 +16,8 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
|
|||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { ITextFileService, SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { SaveReason } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
import { ITextResourceConfigurationService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { isDiffEditor, isCodeEditor, getCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
|
|
|
@ -243,14 +243,14 @@ export class NextPanelViewAction extends SwitchPanelViewAction {
|
|||
}
|
||||
|
||||
const actionRegistry = Registry.as<IWorkbenchActionRegistry>(WorkbenchExtensions.WorkbenchActions);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(TogglePanelAction, TogglePanelAction.ID, TogglePanelAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_J }), 'View: Toggle Panel', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(FocusPanelAction, FocusPanelAction.ID, FocusPanelAction.LABEL), 'View: Focus into Panel', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleMaximizedPanelAction, ToggleMaximizedPanelAction.ID, ToggleMaximizedPanelAction.LABEL), 'View: Toggle Maximized Panel', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ClosePanelAction, ClosePanelAction.ID, ClosePanelAction.LABEL), 'View: Close Panel', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(TogglePanelPositionAction, TogglePanelPositionAction.ID, TogglePanelPositionAction.LABEL), 'View: Toggle Panel Position', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ToggleMaximizedPanelAction, ToggleMaximizedPanelAction.ID, undefined), 'View: Toggle Panel Position', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(PreviousPanelViewAction, PreviousPanelViewAction.ID, PreviousPanelViewAction.LABEL), 'View: Previous Panel View', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(NextPanelViewAction, NextPanelViewAction.ID, NextPanelViewAction.LABEL), 'View: Next Panel View', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(TogglePanelAction, TogglePanelAction.ID, TogglePanelAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_J }), 'View: Toggle Panel', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FocusPanelAction, FocusPanelAction.ID, FocusPanelAction.LABEL), 'View: Focus into Panel', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleMaximizedPanelAction, ToggleMaximizedPanelAction.ID, ToggleMaximizedPanelAction.LABEL), 'View: Toggle Maximized Panel', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ClosePanelAction, ClosePanelAction.ID, ClosePanelAction.LABEL), 'View: Close Panel', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(TogglePanelPositionAction, TogglePanelPositionAction.ID, TogglePanelPositionAction.LABEL), 'View: Toggle Panel Position', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleMaximizedPanelAction, ToggleMaximizedPanelAction.ID, undefined), 'View: Toggle Panel Position', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(PreviousPanelViewAction, PreviousPanelViewAction.ID, PreviousPanelViewAction.LABEL), 'View: Previous Panel View', nls.localize('view', "View"));
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(NextPanelViewAction, NextPanelViewAction.ID, NextPanelViewAction.LABEL), 'View: Next Panel View', nls.localize('view', "View"));
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, {
|
||||
group: '2_workbench_layout',
|
||||
|
|
|
@ -14,4 +14,4 @@ import { inQuickOpenContext } from 'vs/workbench/browser/parts/quickopen/quickop
|
|||
KeybindingsRegistry.registerCommandAndKeybindingRule(QuickPickManyToggle);
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(BackAction, BackAction.ID, BackAction.LABEL, { primary: 0, win: { primary: KeyMod.Alt | KeyCode.LeftArrow }, mac: { primary: KeyMod.WinCtrl | KeyCode.US_MINUS }, linux: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.US_MINUS } }, inQuickOpenContext, KeybindingWeight.WorkbenchContrib + 50), 'Back');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(BackAction, BackAction.ID, BackAction.LABEL, { primary: 0, win: { primary: KeyMod.Alt | KeyCode.LeftArrow }, mac: { primary: KeyMod.WinCtrl | KeyCode.US_MINUS }, linux: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.US_MINUS } }, inQuickOpenContext, KeybindingWeight.WorkbenchContrib + 50), 'Back');
|
||||
|
|
|
@ -69,11 +69,11 @@ MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
|
|||
command: { id: QUICKOPEN_ACTION_ID, title: { value: QUICKOPEN_ACION_LABEL, original: 'Go to File...' } }
|
||||
});
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenSelectNextAction, QuickOpenSelectNextAction.ID, QuickOpenSelectNextAction.LABEL, { primary: 0, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_N } }, inQuickOpenContext, KeybindingWeight.WorkbenchContrib + 50), 'Select Next in Quick Open');
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenSelectPreviousAction, QuickOpenSelectPreviousAction.ID, QuickOpenSelectPreviousAction.LABEL, { primary: 0, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_P } }, inQuickOpenContext, KeybindingWeight.WorkbenchContrib + 50), 'Select Previous in Quick Open');
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenNavigateNextAction, QuickOpenNavigateNextAction.ID, QuickOpenNavigateNextAction.LABEL), 'Navigate Next in Quick Open');
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenNavigatePreviousAction, QuickOpenNavigatePreviousAction.ID, QuickOpenNavigatePreviousAction.LABEL), 'Navigate Previous in Quick Open');
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(RemoveFromEditorHistoryAction, RemoveFromEditorHistoryAction.ID, RemoveFromEditorHistoryAction.LABEL), 'Remove From History');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenSelectNextAction, QuickOpenSelectNextAction.ID, QuickOpenSelectNextAction.LABEL, { primary: 0, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_N } }, inQuickOpenContext, KeybindingWeight.WorkbenchContrib + 50), 'Select Next in Quick Open');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenSelectPreviousAction, QuickOpenSelectPreviousAction.ID, QuickOpenSelectPreviousAction.LABEL, { primary: 0, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_P } }, inQuickOpenContext, KeybindingWeight.WorkbenchContrib + 50), 'Select Previous in Quick Open');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenNavigateNextAction, QuickOpenNavigateNextAction.ID, QuickOpenNavigateNextAction.LABEL), 'Navigate Next in Quick Open');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(QuickOpenNavigatePreviousAction, QuickOpenNavigatePreviousAction.ID, QuickOpenNavigatePreviousAction.LABEL), 'Navigate Previous in Quick Open');
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(RemoveFromEditorHistoryAction, RemoveFromEditorHistoryAction.ID, RemoveFromEditorHistoryAction.LABEL), 'Remove From History');
|
||||
|
||||
const quickOpenNavigateNextInFilePickerId = 'workbench.action.quickOpenNavigateNextInFilePicker';
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
|
@ -98,4 +98,4 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
|||
primary: globalQuickOpenKeybinding.mac.primary | KeyMod.Shift,
|
||||
secondary: undefined
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -320,7 +320,7 @@ class FocusSideBarAction extends Action {
|
|||
}
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(FocusSideBarAction, FocusSideBarAction.ID, FocusSideBarAction.LABEL, {
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(FocusSideBarAction, FocusSideBarAction.ID, FocusSideBarAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_0
|
||||
}), 'View: Focus into Side Bar', nls.localize('viewCategory', "View"));
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
* macOS: does not render LCD-anti-aliased.
|
||||
*/
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.titlebar > .titlebar-drag-region {
|
||||
|
@ -118,6 +120,7 @@
|
|||
height: 100%;
|
||||
width: 138px;
|
||||
margin-left: auto;
|
||||
transform: translate3d(0px, 0px, 0px);
|
||||
}
|
||||
|
||||
.monaco-workbench.fullscreen .part.titlebar > .window-controls-container {
|
||||
|
|
|
@ -42,6 +42,7 @@ import { IElectronService } from 'vs/platform/electron/node/electron';
|
|||
import { optional } from 'vs/platform/instantiation/common/instantiation';
|
||||
// tslint:disable-next-line: import-patterns layering TODO@sbatten
|
||||
import { IElectronEnvironmentService } from 'vs/workbench/services/electron/electron-browser/electronEnvironmentService';
|
||||
import { BrowserFeatures } from 'vs/base/browser/canIUse';
|
||||
|
||||
export abstract class MenubarControl extends Disposable {
|
||||
|
||||
|
@ -673,7 +674,7 @@ export class CustomMenubarControl extends MenubarControl {
|
|||
}
|
||||
|
||||
this._register(DOM.addDisposableListener(window, DOM.EventType.RESIZE, () => {
|
||||
if (this.menubar) {
|
||||
if (this.menubar && !BrowserFeatures.pointerEvents) {
|
||||
this.menubar.blur();
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -350,22 +350,26 @@ export abstract class FilterViewContainerViewlet extends ViewContainerViewlet {
|
|||
}));
|
||||
|
||||
this._register(this.viewsModel.onDidChangeActiveViews((viewDescriptors) => {
|
||||
viewDescriptors.forEach(descriptor => {
|
||||
let filterOnValue = this.getFilterOn(descriptor);
|
||||
if (!filterOnValue) {
|
||||
return;
|
||||
}
|
||||
if (!this.allViews.has(filterOnValue)) {
|
||||
this.allViews.set(filterOnValue, new Map());
|
||||
}
|
||||
this.allViews.get(filterOnValue)!.set(descriptor.id, descriptor);
|
||||
if (filterOnValue !== this.filterValue) {
|
||||
this.viewsModel.setVisible(descriptor.id, false);
|
||||
}
|
||||
});
|
||||
this.updateAllViews(viewDescriptors);
|
||||
}));
|
||||
}
|
||||
|
||||
private updateAllViews(viewDescriptors: IViewDescriptor[]) {
|
||||
viewDescriptors.forEach(descriptor => {
|
||||
let filterOnValue = this.getFilterOn(descriptor);
|
||||
if (!filterOnValue) {
|
||||
return;
|
||||
}
|
||||
if (!this.allViews.has(filterOnValue)) {
|
||||
this.allViews.set(filterOnValue, new Map());
|
||||
}
|
||||
this.allViews.get(filterOnValue)!.set(descriptor.id, descriptor);
|
||||
if (filterOnValue !== this.filterValue) {
|
||||
this.viewsModel.setVisible(descriptor.id, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected addConstantViewDescriptors(constantViewDescriptors: IViewDescriptor[]) {
|
||||
constantViewDescriptors.forEach(viewDescriptor => this.constantViewDescriptors.set(viewDescriptor.id, viewDescriptor));
|
||||
}
|
||||
|
@ -415,6 +419,10 @@ export abstract class FilterViewContainerViewlet extends ViewContainerViewlet {
|
|||
}
|
||||
|
||||
onDidAddViews(added: IAddedViewDescriptorRef[]): ViewletPanel[] {
|
||||
// Check that allViews is ready
|
||||
if (this.allViews.size === 0) {
|
||||
this.updateAllViews(this.viewsModel.viewDescriptors);
|
||||
}
|
||||
const panels: ViewletPanel[] = super.onDidAddViews(added);
|
||||
for (let i = 0; i < added.length; i++) {
|
||||
if (this.constantViewDescriptors.has(added[i].viewDescriptor.id)) {
|
||||
|
|
|
@ -15,7 +15,7 @@ import { QuickOpenEntry, QuickOpenEntryGroup } from 'vs/base/parts/quickopen/bro
|
|||
import { EditorOptions, EditorInput, IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { IResourceInput, IEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { IQuickOpenService } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import { IConstructorSignature0, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IConstructorSignature0, IInstantiationService, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
|
||||
|
@ -136,9 +136,13 @@ export class QuickOpenHandlerDescriptor {
|
|||
private id: string;
|
||||
private ctor: IConstructorSignature0<QuickOpenHandler>;
|
||||
|
||||
constructor(ctor: IConstructorSignature0<QuickOpenHandler>, id: string, prefix: string, contextKey: string | undefined, description: string, instantProgress?: boolean);
|
||||
constructor(ctor: IConstructorSignature0<QuickOpenHandler>, id: string, prefix: string, contextKey: string | undefined, helpEntries: QuickOpenHandlerHelpEntry[], instantProgress?: boolean);
|
||||
constructor(ctor: IConstructorSignature0<QuickOpenHandler>, id: string, prefix: string, contextKey: string | undefined, param: string | QuickOpenHandlerHelpEntry[], instantProgress: boolean = false) {
|
||||
public static create<Services extends BrandedService[]>(ctor: { new(...services: Services): QuickOpenHandler }, id: string, prefix: string, contextKey: string | undefined, description: string, instantProgress?: boolean): QuickOpenHandlerDescriptor;
|
||||
public static create<Services extends BrandedService[]>(ctor: { new(...services: Services): QuickOpenHandler }, id: string, prefix: string, contextKey: string | undefined, helpEntries: QuickOpenHandlerHelpEntry[], instantProgress?: boolean): QuickOpenHandlerDescriptor;
|
||||
public static create<Services extends BrandedService[]>(ctor: { new(...services: Services): QuickOpenHandler }, id: string, prefix: string, contextKey: string | undefined, param: string | QuickOpenHandlerHelpEntry[], instantProgress: boolean = false): QuickOpenHandlerDescriptor {
|
||||
return new QuickOpenHandlerDescriptor(ctor as IConstructorSignature0<QuickOpenHandler>, id, prefix, contextKey, param, instantProgress);
|
||||
}
|
||||
|
||||
private constructor(ctor: IConstructorSignature0<QuickOpenHandler>, id: string, prefix: string, contextKey: string | undefined, param: string | QuickOpenHandlerHelpEntry[], instantProgress: boolean = false) {
|
||||
this.ctor = ctor;
|
||||
this.id = id;
|
||||
this.prefix = prefix;
|
||||
|
|
|
@ -175,6 +175,9 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||
// allow to select text in monaco editor instances.
|
||||
if (isSafari) {
|
||||
collector.addRule(`
|
||||
body.web {
|
||||
touch-action: none;
|
||||
}
|
||||
.monaco-workbench .monaco-editor .view-lines {
|
||||
user-select: text;
|
||||
-webkit-user-select: text;
|
||||
|
|
|
@ -10,7 +10,7 @@ import { Action, IAction } from 'vs/base/common/actions';
|
|||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { IViewlet } from 'vs/workbench/common/viewlet';
|
||||
import { Composite, CompositeDescriptor, CompositeRegistry } from 'vs/workbench/browser/composite';
|
||||
import { IConstructorSignature0 } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IConstructorSignature0, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ToggleSidebarVisibilityAction, ToggleSidebarPositionAction } from 'vs/workbench/browser/actions/layoutActions';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
|
@ -56,7 +56,18 @@ export abstract class Viewlet extends Composite implements IViewlet {
|
|||
*/
|
||||
export class ViewletDescriptor extends CompositeDescriptor<Viewlet> {
|
||||
|
||||
constructor(
|
||||
public static create<Services extends BrandedService[]>(
|
||||
ctor: { new(...services: Services): Viewlet },
|
||||
id: string,
|
||||
name: string,
|
||||
cssClass?: string,
|
||||
order?: number,
|
||||
iconUrl?: URI
|
||||
): ViewletDescriptor {
|
||||
return new ViewletDescriptor(ctor as IConstructorSignature0<Viewlet>, id, name, cssClass, order, iconUrl);
|
||||
}
|
||||
|
||||
private constructor(
|
||||
ctor: IConstructorSignature0<Viewlet>,
|
||||
id: string,
|
||||
name: string,
|
||||
|
|
|
@ -10,7 +10,7 @@ import { URI } from 'vs/base/common/uri';
|
|||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IEditor as ICodeEditor, IEditorViewState, ScrollType, IDiffEditor } from 'vs/editor/common/editorCommon';
|
||||
import { IEditorModel, IEditorOptions, ITextEditorOptions, IBaseResourceInput, IResourceInput, EditorActivation, EditorOpenContext } from 'vs/platform/editor/common/editor';
|
||||
import { IInstantiationService, IConstructorSignature0, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IInstantiationService, IConstructorSignature0, ServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { RawContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
|
@ -20,6 +20,7 @@ import { ActionRunner, IAction } from 'vs/base/common/actions';
|
|||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IPathData } from 'vs/platform/windows/common/windows';
|
||||
import { coalesce, firstOrDefault } from 'vs/base/common/arrays';
|
||||
import { ISaveOptions, IRevertOptions } from 'vs/workbench/services/workingCopy/common/workingCopyService';
|
||||
|
||||
export const ActiveEditorContext = new RawContextKey<string | null>('activeEditor', null);
|
||||
export const ActiveEditorIsSaveableContext = new RawContextKey<boolean>('activeEditorIsSaveable', false);
|
||||
|
@ -175,7 +176,7 @@ export interface IEditorInputFactoryRegistry {
|
|||
* @param editorInputId the identifier of the editor input
|
||||
* @param factory the editor input factory for serialization/deserialization
|
||||
*/
|
||||
registerEditorInputFactory(editorInputId: string, ctor: IConstructorSignature0<IEditorInputFactory>): void;
|
||||
registerEditorInputFactory<Services extends BrandedService[]>(editorInputId: string, ctor: { new(...Services: Services): IEditorInputFactory }): void;
|
||||
|
||||
/**
|
||||
* Returns the editor input factory for the given editor input.
|
||||
|
@ -261,25 +262,12 @@ export const enum Verbosity {
|
|||
LONG
|
||||
}
|
||||
|
||||
export interface IRevertOptions {
|
||||
|
||||
/**
|
||||
* Forces to load the contents of the editor again even if the editor is not dirty.
|
||||
*/
|
||||
force?: boolean;
|
||||
|
||||
/**
|
||||
* A soft revert will clear dirty state of an editor but will not attempt to load it.
|
||||
*/
|
||||
soft?: boolean;
|
||||
}
|
||||
|
||||
export interface IEditorInput extends IDisposable {
|
||||
|
||||
/**
|
||||
* Triggered when this input is disposed.
|
||||
*/
|
||||
onDispose: Event<void>;
|
||||
readonly onDispose: Event<void>;
|
||||
|
||||
/**
|
||||
* Returns the associated resource of this input.
|
||||
|
@ -316,6 +304,11 @@ export interface IEditorInput extends IDisposable {
|
|||
*/
|
||||
isDirty(): boolean;
|
||||
|
||||
/**
|
||||
* Saves the editor if it is dirty.
|
||||
*/
|
||||
save(options?: ISaveOptions): Promise<boolean>;
|
||||
|
||||
/**
|
||||
* Reverts this input.
|
||||
*/
|
||||
|
@ -333,14 +326,14 @@ export interface IEditorInput extends IDisposable {
|
|||
*/
|
||||
export abstract class EditorInput extends Disposable implements IEditorInput {
|
||||
|
||||
protected readonly _onDidChangeDirty: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChangeDirty: Event<void> = this._onDidChangeDirty.event;
|
||||
protected readonly _onDidChangeDirty = this._register(new Emitter<void>());
|
||||
readonly onDidChangeDirty = this._onDidChangeDirty.event;
|
||||
|
||||
protected readonly _onDidChangeLabel: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidChangeLabel: Event<void> = this._onDidChangeLabel.event;
|
||||
protected readonly _onDidChangeLabel = this._register(new Emitter<void>());
|
||||
readonly onDidChangeLabel = this._onDidChangeLabel.event;
|
||||
|
||||
private readonly _onDispose: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDispose: Event<void> = this._onDispose.event;
|
||||
private readonly _onDispose = this._register(new Emitter<void>());
|
||||
readonly onDispose = this._onDispose.event;
|
||||
|
||||
private disposed: boolean = false;
|
||||
|
||||
|
@ -418,7 +411,7 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
|
|||
/**
|
||||
* Saves the editor if it is dirty. Subclasses return a promise with a boolean indicating the success of the operation.
|
||||
*/
|
||||
save(): Promise<boolean> {
|
||||
save(options?: ISaveOptions): Promise<boolean> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
|
@ -429,13 +422,6 @@ export abstract class EditorInput extends Disposable implements IEditorInput {
|
|||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this input is no longer opened in any editor. Subclasses can free resources as needed.
|
||||
*/
|
||||
close(): void {
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses can set this to false if it does not make sense to split the editor input.
|
||||
*/
|
||||
|
@ -560,12 +546,12 @@ export class SideBySideEditorInput extends EditorInput {
|
|||
return this.master.isDirty();
|
||||
}
|
||||
|
||||
save(): Promise<boolean> {
|
||||
return this.master.save();
|
||||
save(options?: ISaveOptions): Promise<boolean> {
|
||||
return this.master.save(options);
|
||||
}
|
||||
|
||||
revert(): Promise<boolean> {
|
||||
return this.master.revert();
|
||||
revert(options?: IRevertOptions): Promise<boolean> {
|
||||
return this.master.revert(options);
|
||||
}
|
||||
|
||||
getTelemetryDescriptor(): { [key: string]: unknown } {
|
||||
|
@ -640,8 +626,8 @@ export interface ITextEditorModel extends IEditorModel {
|
|||
*/
|
||||
export class EditorModel extends Disposable implements IEditorModel {
|
||||
|
||||
private readonly _onDispose: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDispose: Event<void> = this._onDispose.event;
|
||||
private readonly _onDispose = this._register(new Emitter<void>());
|
||||
readonly onDispose = this._onDispose.event;
|
||||
|
||||
/**
|
||||
* Causes this model to load returning a promise when loading is completed.
|
||||
|
|
|
@ -4,13 +4,11 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Extensions, IEditorInputFactoryRegistry, EditorInput, toResource, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, SideBySideEditorInput, CloseDirection, IEditorInput, SideBySideEditor } from 'vs/workbench/common/editor';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Extensions, IEditorInputFactoryRegistry, EditorInput, IEditorIdentifier, IEditorCloseEvent, GroupIdentifier, CloseDirection, IEditorInput, SideBySideEditorInput } from 'vs/workbench/common/editor';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
|
||||
import { dispose, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { coalesce } from 'vs/base/common/arrays';
|
||||
|
||||
const EditorOpenPositioning = {
|
||||
|
@ -60,31 +58,31 @@ export class EditorGroup extends Disposable {
|
|||
//#region events
|
||||
|
||||
private readonly _onDidEditorActivate = this._register(new Emitter<EditorInput>());
|
||||
readonly onDidEditorActivate: Event<EditorInput> = this._onDidEditorActivate.event;
|
||||
readonly onDidEditorActivate = this._onDidEditorActivate.event;
|
||||
|
||||
private readonly _onDidEditorOpen = this._register(new Emitter<EditorInput>());
|
||||
readonly onDidEditorOpen: Event<EditorInput> = this._onDidEditorOpen.event;
|
||||
readonly onDidEditorOpen = this._onDidEditorOpen.event;
|
||||
|
||||
private readonly _onDidEditorClose = this._register(new Emitter<EditorCloseEvent>());
|
||||
readonly onDidEditorClose: Event<EditorCloseEvent> = this._onDidEditorClose.event;
|
||||
readonly onDidEditorClose = this._onDidEditorClose.event;
|
||||
|
||||
private readonly _onDidEditorDispose = this._register(new Emitter<EditorInput>());
|
||||
readonly onDidEditorDispose: Event<EditorInput> = this._onDidEditorDispose.event;
|
||||
readonly onDidEditorDispose = this._onDidEditorDispose.event;
|
||||
|
||||
private readonly _onDidEditorBecomeDirty = this._register(new Emitter<EditorInput>());
|
||||
readonly onDidEditorBecomeDirty: Event<EditorInput> = this._onDidEditorBecomeDirty.event;
|
||||
readonly onDidEditorBecomeDirty = this._onDidEditorBecomeDirty.event;
|
||||
|
||||
private readonly _onDidEditorLabelChange = this._register(new Emitter<EditorInput>());
|
||||
readonly onDidEditorLabelChange: Event<EditorInput> = this._onDidEditorLabelChange.event;
|
||||
readonly onDidEditorLabelChange = this._onDidEditorLabelChange.event;
|
||||
|
||||
private readonly _onDidEditorMove = this._register(new Emitter<EditorInput>());
|
||||
readonly onDidEditorMove: Event<EditorInput> = this._onDidEditorMove.event;
|
||||
readonly onDidEditorMove = this._onDidEditorMove.event;
|
||||
|
||||
private readonly _onDidEditorPin = this._register(new Emitter<EditorInput>());
|
||||
readonly onDidEditorPin: Event<EditorInput> = this._onDidEditorPin.event;
|
||||
readonly onDidEditorPin = this._onDidEditorPin.event;
|
||||
|
||||
private readonly _onDidEditorUnpin = this._register(new Emitter<EditorInput>());
|
||||
readonly onDidEditorUnpin: Event<EditorInput> = this._onDidEditorUnpin.event;
|
||||
readonly onDidEditorUnpin = this._onDidEditorUnpin.event;
|
||||
|
||||
//#endregion
|
||||
|
||||
|
@ -93,7 +91,6 @@ export class EditorGroup extends Disposable {
|
|||
|
||||
private editors: EditorInput[] = [];
|
||||
private mru: EditorInput[] = [];
|
||||
private mapResourceToEditorCount: ResourceMap<number> = new ResourceMap<number>();
|
||||
|
||||
private preview: EditorInput | null = null; // editor in preview state
|
||||
private active: EditorInput | null = null; // editor in active state
|
||||
|
@ -135,26 +132,8 @@ export class EditorGroup extends Disposable {
|
|||
return mru ? this.mru.slice(0) : this.editors.slice(0);
|
||||
}
|
||||
|
||||
getEditor(index: number): EditorInput | undefined;
|
||||
getEditor(resource: URI): EditorInput | undefined;
|
||||
getEditor(arg1: number | URI): EditorInput | undefined {
|
||||
if (typeof arg1 === 'number') {
|
||||
return this.editors[arg1];
|
||||
}
|
||||
|
||||
const resource: URI = arg1;
|
||||
if (!this.contains(resource)) {
|
||||
return undefined; // fast check for resource opened or not
|
||||
}
|
||||
|
||||
for (const editor of this.editors) {
|
||||
const editorResource = toResource(editor, { supportSideBySide: SideBySideEditor.MASTER });
|
||||
if (editorResource?.toString() === resource.toString()) {
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
getEditorByIndex(index: number): EditorInput | undefined {
|
||||
return this.editors[index];
|
||||
}
|
||||
|
||||
get activeEditor(): EditorInput | null {
|
||||
|
@ -509,7 +488,6 @@ export class EditorGroup extends Disposable {
|
|||
// Add
|
||||
if (!del && editor) {
|
||||
this.mru.push(editor); // make it LRU editor
|
||||
this.updateResourceMap(editor, false /* add */); // add new to resource map
|
||||
}
|
||||
|
||||
// Remove / Replace
|
||||
|
@ -519,41 +497,11 @@ export class EditorGroup extends Disposable {
|
|||
// Remove
|
||||
if (del && !editor) {
|
||||
this.mru.splice(indexInMRU, 1); // remove from MRU
|
||||
this.updateResourceMap(editorToDeleteOrReplace, true /* delete */); // remove from resource map
|
||||
}
|
||||
|
||||
// Replace
|
||||
else if (del && editor) {
|
||||
this.mru.splice(indexInMRU, 1, editor); // replace MRU at location
|
||||
this.updateResourceMap(editor, false /* add */); // add new to resource map
|
||||
this.updateResourceMap(editorToDeleteOrReplace, true /* delete */); // remove replaced from resource map
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private updateResourceMap(editor: EditorInput, remove: boolean): void {
|
||||
const resource = toResource(editor, { supportSideBySide: SideBySideEditor.MASTER });
|
||||
if (resource) {
|
||||
|
||||
// It is possible to have the same resource opened twice (once as normal input and once as diff input)
|
||||
// So we need to do ref counting on the resource to provide the correct picture
|
||||
const counter = this.mapResourceToEditorCount.get(resource) || 0;
|
||||
|
||||
// Add
|
||||
let newCounter: number;
|
||||
if (!remove) {
|
||||
newCounter = counter + 1;
|
||||
}
|
||||
|
||||
// Delete
|
||||
else {
|
||||
newCounter = counter - 1;
|
||||
}
|
||||
|
||||
if (newCounter > 0) {
|
||||
this.mapResourceToEditorCount.set(resource, newCounter);
|
||||
} else {
|
||||
this.mapResourceToEditorCount.delete(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -572,28 +520,20 @@ export class EditorGroup extends Disposable {
|
|||
return -1;
|
||||
}
|
||||
|
||||
contains(editorOrResource: EditorInput | URI): boolean;
|
||||
contains(editor: EditorInput, supportSideBySide?: boolean): boolean;
|
||||
contains(editorOrResource: EditorInput | URI, supportSideBySide?: boolean): boolean {
|
||||
if (editorOrResource instanceof EditorInput) {
|
||||
const index = this.indexOf(editorOrResource);
|
||||
if (index >= 0) {
|
||||
contains(candidate: EditorInput, searchInSideBySideEditors?: boolean): boolean {
|
||||
for (const editor of this.editors) {
|
||||
if (this.matches(editor, candidate)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (supportSideBySide && editorOrResource instanceof SideBySideEditorInput) {
|
||||
const index = this.indexOf(editorOrResource.master);
|
||||
if (index >= 0) {
|
||||
if (searchInSideBySideEditors && editor instanceof SideBySideEditorInput) {
|
||||
if (this.matches(editor.master, candidate) || this.matches(editor.details, candidate)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const counter = this.mapResourceToEditorCount.get(editorOrResource);
|
||||
|
||||
return typeof counter === 'number' && counter > 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private setMostRecentlyUsed(editor: EditorInput): void {
|
||||
|
@ -619,7 +559,6 @@ export class EditorGroup extends Disposable {
|
|||
const group = this.instantiationService.createInstance(EditorGroup, undefined);
|
||||
group.editors = this.editors.slice(0);
|
||||
group.mru = this.mru.slice(0);
|
||||
group.mapResourceToEditorCount = this.mapResourceToEditorCount.clone();
|
||||
group.preview = this.preview;
|
||||
group.active = this.active;
|
||||
group.editorOpenPositioning = this.editorOpenPositioning;
|
||||
|
@ -678,7 +617,6 @@ export class EditorGroup extends Disposable {
|
|||
const editor = factory.deserialize(this.instantiationService, e.value);
|
||||
if (editor) {
|
||||
this.registerEditorListeners(editor);
|
||||
this.updateResourceMap(editor, false /* add */);
|
||||
}
|
||||
|
||||
return editor;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue