Merge from master

This commit is contained in:
Raj Musuku
2019-02-21 17:56:04 -08:00
parent 5a146e34fa
commit 666ae11639
11482 changed files with 119352 additions and 255574 deletions

View File

@@ -2,7 +2,6 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
@@ -29,17 +28,13 @@ export class CharWidthRequest {
}
}
interface ICharWidthReader {
read(): void;
}
class DomCharWidthReader implements ICharWidthReader {
class DomCharWidthReader {
private readonly _bareFontInfo: BareFontInfo;
private readonly _requests: CharWidthRequest[];
private _container: HTMLElement;
private _testElements: HTMLSpanElement[];
private _container: HTMLElement | null;
private _testElements: HTMLSpanElement[] | null;
constructor(bareFontInfo: BareFontInfo, requests: CharWidthRequest[]) {
this._bareFontInfo = bareFontInfo;
@@ -54,13 +49,13 @@ class DomCharWidthReader implements ICharWidthReader {
this._createDomElements();
// Add the container to the DOM
document.body.appendChild(this._container);
document.body.appendChild(this._container!);
// Read character widths
this._readFromDomElements();
// Remove the container from the DOM
document.body.removeChild(this._container);
document.body.removeChild(this._container!);
this._container = null;
this._testElements = null;
@@ -73,7 +68,7 @@ class DomCharWidthReader implements ICharWidthReader {
container.style.width = '50000px';
let regularDomNode = document.createElement('div');
regularDomNode.style.fontFamily = this._bareFontInfo.fontFamily;
regularDomNode.style.fontFamily = this._bareFontInfo.getMassagedFontFamily();
regularDomNode.style.fontWeight = this._bareFontInfo.fontWeight;
regularDomNode.style.fontSize = this._bareFontInfo.fontSize + 'px';
regularDomNode.style.lineHeight = this._bareFontInfo.lineHeight + 'px';
@@ -81,7 +76,7 @@ class DomCharWidthReader implements ICharWidthReader {
container.appendChild(regularDomNode);
let boldDomNode = document.createElement('div');
boldDomNode.style.fontFamily = this._bareFontInfo.fontFamily;
boldDomNode.style.fontFamily = this._bareFontInfo.getMassagedFontFamily();
boldDomNode.style.fontWeight = 'bold';
boldDomNode.style.fontSize = this._bareFontInfo.fontSize + 'px';
boldDomNode.style.lineHeight = this._bareFontInfo.lineHeight + 'px';
@@ -89,7 +84,7 @@ class DomCharWidthReader implements ICharWidthReader {
container.appendChild(boldDomNode);
let italicDomNode = document.createElement('div');
italicDomNode.style.fontFamily = this._bareFontInfo.fontFamily;
italicDomNode.style.fontFamily = this._bareFontInfo.getMassagedFontFamily();
italicDomNode.style.fontWeight = this._bareFontInfo.fontWeight;
italicDomNode.style.fontSize = this._bareFontInfo.fontSize + 'px';
italicDomNode.style.lineHeight = this._bareFontInfo.lineHeight + 'px';
@@ -112,11 +107,11 @@ class DomCharWidthReader implements ICharWidthReader {
parent = italicDomNode;
}
parent.appendChild(document.createElement('br'));
parent!.appendChild(document.createElement('br'));
let testElement = document.createElement('span');
DomCharWidthReader._render(testElement, request);
parent.appendChild(testElement);
parent!.appendChild(testElement);
testElements[i] = testElement;
}
@@ -146,7 +141,7 @@ class DomCharWidthReader implements ICharWidthReader {
private _readFromDomElements(): void {
for (let i = 0, len = this._requests.length; i < len; i++) {
const request = this._requests[i];
const testElement = this._testElements[i];
const testElement = this._testElements![i];
request.fulfill(testElement.offsetWidth / 256);
}

View File

@@ -2,20 +2,19 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Event, Emitter } from 'vs/base/common/event';
import * as browser from 'vs/base/browser/browser';
import { FastDomNode } from 'vs/base/browser/fastDomNode';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import * as platform from 'vs/base/common/platform';
import * as browser from 'vs/base/browser/browser';
import { CommonEditorConfiguration, IEnvConfiguration } from 'vs/editor/common/config/commonEditorConfig';
import { IDimension } from 'vs/editor/common/editorCommon';
import { FontInfo, BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver';
import { FastDomNode } from 'vs/base/browser/fastDomNode';
import { CharWidthRequest, CharWidthRequestType, readCharWidths } from 'vs/editor/browser/config/charWidthReader';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver';
import { CommonEditorConfiguration, IEnvConfiguration } from 'vs/editor/common/config/commonEditorConfig';
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo';
import { IDimension } from 'vs/editor/common/editorCommon';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
class CSSBasedConfigurationCache {
@@ -63,7 +62,7 @@ export function restoreFontInfo(storageService: IStorageService): void {
if (typeof strStoredFontInfo !== 'string') {
return;
}
let storedFontInfo: ISerializedFontInfo[] = null;
let storedFontInfo: ISerializedFontInfo[] | null = null;
try {
storedFontInfo = JSON.parse(strStoredFontInfo);
} catch (err) {
@@ -77,7 +76,9 @@ export function restoreFontInfo(storageService: IStorageService): void {
export function saveFontInfo(storageService: IStorageService): void {
let knownFontInfo = CSSBasedConfiguration.INSTANCE.saveFontInfo();
storageService.store('editorFontInfo', JSON.stringify(knownFontInfo), StorageScope.GLOBAL);
if (knownFontInfo.length > 0) {
storageService.store('editorFontInfo', JSON.stringify(knownFontInfo), StorageScope.GLOBAL);
}
}
export interface ISerializedFontInfo {
@@ -90,6 +91,7 @@ export interface ISerializedFontInfo {
readonly isMonospace: boolean;
readonly typicalHalfwidthCharacterWidth: number;
readonly typicalFullwidthCharacterWidth: number;
readonly canUseHalfwidthRightwardsArrow: boolean;
readonly spaceWidth: number;
readonly maxDigitWidth: number;
}
@@ -99,7 +101,7 @@ class CSSBasedConfiguration extends Disposable {
public static readonly INSTANCE = new CSSBasedConfiguration();
private _cache: CSSBasedConfigurationCache;
private _evictUntrustedReadingsTimeout: number;
private _evictUntrustedReadingsTimeout: any;
private _onDidChange = this._register(new Emitter<void>());
public readonly onDidChange: Event<void> = this._onDidChange.event;
@@ -176,6 +178,7 @@ class CSSBasedConfiguration extends Disposable {
isMonospace: readConfig.isMonospace,
typicalHalfwidthCharacterWidth: Math.max(readConfig.typicalHalfwidthCharacterWidth, 5),
typicalFullwidthCharacterWidth: Math.max(readConfig.typicalFullwidthCharacterWidth, 5),
canUseHalfwidthRightwardsArrow: readConfig.canUseHalfwidthRightwardsArrow,
spaceWidth: Math.max(readConfig.spaceWidth, 5),
maxDigitWidth: Math.max(readConfig.maxDigitWidth, 5),
}, false);
@@ -186,7 +189,7 @@ class CSSBasedConfiguration extends Disposable {
return this._cache.get(bareFontInfo);
}
private static createRequest(chr: string, type: CharWidthRequestType, all: CharWidthRequest[], monospace: CharWidthRequest[]): CharWidthRequest {
private static createRequest(chr: string, type: CharWidthRequestType, all: CharWidthRequest[], monospace: CharWidthRequest[] | null): CharWidthRequest {
let result = new CharWidthRequest(chr, type);
all.push(result);
if (monospace) {
@@ -214,7 +217,9 @@ class CSSBasedConfiguration extends Disposable {
const digit9 = this.createRequest('9', CharWidthRequestType.Regular, all, monospace);
// monospace test: used for whitespace rendering
this.createRequest('→', CharWidthRequestType.Regular, all, monospace);
const rightwardsArrow = this.createRequest('→', CharWidthRequestType.Regular, all, monospace);
const halfwidthRightwardsArrow = this.createRequest('→', CharWidthRequestType.Regular, all, null);
this.createRequest('·', CharWidthRequestType.Regular, all, monospace);
// monospace test: some characters
@@ -256,6 +261,16 @@ class CSSBasedConfiguration extends Disposable {
}
}
let canUseHalfwidthRightwardsArrow = true;
if (isMonospace && halfwidthRightwardsArrow.width !== referenceWidth) {
// using a halfwidth rightwards arrow would break monospace...
canUseHalfwidthRightwardsArrow = false;
}
if (halfwidthRightwardsArrow.width > rightwardsArrow.width) {
// using a halfwidth rightwards arrow would paint a larger arrow than a regular rightwards arrow
canUseHalfwidthRightwardsArrow = false;
}
// let's trust the zoom level only 2s after it was changed.
const canTrustBrowserZoomLevel = (browser.getTimeSinceLastZoomLevelChanged() > 2000);
return new FontInfo({
@@ -268,6 +283,7 @@ class CSSBasedConfiguration extends Disposable {
isMonospace: isMonospace,
typicalHalfwidthCharacterWidth: typicalHalfwidthCharacter.width,
typicalFullwidthCharacterWidth: typicalFullwidthCharacter.width,
canUseHalfwidthRightwardsArrow: canUseHalfwidthRightwardsArrow,
spaceWidth: space.width,
maxDigitWidth: maxDigitWidth
}, canTrustBrowserZoomLevel);
@@ -276,21 +292,8 @@ class CSSBasedConfiguration extends Disposable {
export class Configuration extends CommonEditorConfiguration {
private static _massageFontFamily(fontFamily: string): string {
if (/[,"']/.test(fontFamily)) {
// Looks like the font family might be already escaped
return fontFamily;
}
if (/[+ ]/.test(fontFamily)) {
// Wrap a font family using + or <space> with quotes
return `"${fontFamily}"`;
}
return fontFamily;
}
public static applyFontInfoSlow(domNode: HTMLElement, fontInfo: BareFontInfo): void {
domNode.style.fontFamily = Configuration._massageFontFamily(fontInfo.fontFamily);
domNode.style.fontFamily = fontInfo.getMassagedFontFamily();
domNode.style.fontWeight = fontInfo.fontWeight;
domNode.style.fontSize = fontInfo.fontSize + 'px';
domNode.style.lineHeight = fontInfo.lineHeight + 'px';
@@ -298,7 +301,7 @@ export class Configuration extends CommonEditorConfiguration {
}
public static applyFontInfo(domNode: FastDomNode<HTMLElement>, fontInfo: BareFontInfo): void {
domNode.setFontFamily(Configuration._massageFontFamily(fontInfo.fontFamily));
domNode.setFontFamily(fontInfo.getMassagedFontFamily());
domNode.setFontWeight(fontInfo.fontWeight);
domNode.setFontSize(fontInfo.fontSize);
domNode.setLineHeight(fontInfo.lineHeight);
@@ -307,7 +310,7 @@ export class Configuration extends CommonEditorConfiguration {
private readonly _elementSizeObserver: ElementSizeObserver;
constructor(options: IEditorOptions, referenceDomElement: HTMLElement = null) {
constructor(options: IEditorOptions, referenceDomElement: HTMLElement | null = null) {
super(options);
this._elementSizeObserver = this._register(new ElementSizeObserver(referenceDomElement, () => this._onReferenceDomElementSizeChanged()));

View File

@@ -2,20 +2,19 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Disposable } from 'vs/base/common/lifecycle';
import { IDimension } from 'vs/editor/common/editorCommon';
export class ElementSizeObserver extends Disposable {
private referenceDomElement: HTMLElement;
private measureReferenceDomElementToken: number;
private referenceDomElement: HTMLElement | null;
private measureReferenceDomElementToken: any;
private changeCallback: () => void;
private width: number;
private height: number;
constructor(referenceDomElement: HTMLElement, changeCallback: () => void) {
constructor(referenceDomElement: HTMLElement | null, changeCallback: () => void) {
super();
this.referenceDomElement = referenceDomElement;
this.changeCallback = changeCallback;

View File

@@ -3,31 +3,28 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as nls from 'vs/nls';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import * as types from 'vs/base/common/types';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { Command, EditorCommand, ICommandOptions, registerEditorCommand } from 'vs/editor/browser/editorExtensions';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ColumnSelection, IColumnSelectResult } from 'vs/editor/common/controller/cursorColumnSelection';
import { CursorContext, CursorState, EditOperationType, IColumnSelectData, ICursors, PartialCursorState, RevealTarget } from 'vs/editor/common/controller/cursorCommon';
import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperations';
import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents';
import { CursorMove as CursorMove_, CursorMoveCommands } from 'vs/editor/common/controller/cursorMoveCommands';
import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { CursorState, ICursors, RevealTarget, IColumnSelectData, CursorContext, EditOperationType } from 'vs/editor/common/controller/cursorCommon';
import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents';
import { CursorMoveCommands, CursorMove as CursorMove_ } from 'vs/editor/common/controller/cursorMoveCommands';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { registerEditorCommand, ICommandOptions, EditorCommand, Command } from 'vs/editor/browser/editorExtensions';
import { IColumnSelectResult, ColumnSelection } from 'vs/editor/common/controller/cursorColumnSelection';
import { Handler, ScrollType } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import H = editorCommon.Handler;
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import * as types from 'vs/base/common/types';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { TypeOperations } from 'vs/editor/common/controller/cursorTypeOperations';
import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperations';
import { VerticalRevealType } from 'vs/editor/common/view/viewEvents';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { MenuId } from 'vs/platform/actions/common/actions';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
const CORE_WEIGHT = KeybindingWeight.EditorCore;
@@ -123,7 +120,7 @@ export namespace EditorScroll_ {
select?: boolean;
}
export function parse(args: RawArguments): ParsedArguments {
export function parse(args: RawArguments): ParsedArguments | null {
let direction: Direction;
switch (args.to) {
case RawDirection.Up:
@@ -263,7 +260,7 @@ export namespace CoreNavigationCommands {
CursorMoveCommands.moveTo(cursors.context, cursors.getPrimaryCursor(), this._inSelectionMode, args.position, args.viewPosition)
]
);
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(true, RevealTarget.Primary, ScrollType.Smooth);
}
}
@@ -288,7 +285,7 @@ export namespace CoreNavigationCommands {
toViewLineNumber: result.toLineNumber,
toViewVisualColumn: result.toVisualColumn
});
cursors.reveal(true, (result.reversed ? RevealTarget.TopMost : RevealTarget.BottomMost), editorCommon.ScrollType.Smooth);
cursors.reveal(true, (result.reversed ? RevealTarget.TopMost : RevealTarget.BottomMost), ScrollType.Smooth);
}
protected abstract _getColumnSelectResult(context: CursorContext, primary: CursorState, prevColumnSelectData: IColumnSelectData, args: any): IColumnSelectResult;
@@ -458,7 +455,7 @@ export namespace CoreNavigationCommands {
CursorChangeReason.Explicit,
CursorMoveCommands.move(cursors.context, cursors.getAll(), args)
);
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(true, RevealTarget.Primary, ScrollType.Smooth);
}
}
@@ -705,14 +702,14 @@ export namespace CoreNavigationCommands {
public runCoreEditorCommand(cursors: ICursors, args: any): void {
const context = cursors.context;
let newState: CursorState;
let newState: PartialCursorState;
if (args.wholeLine) {
newState = CursorMoveCommands.line(context, cursors.getPrimaryCursor(), false, args.position, args.viewPosition);
} else {
newState = CursorMoveCommands.moveTo(context, cursors.getPrimaryCursor(), false, args.position, args.viewPosition);
}
const states = cursors.getAll();
const states: PartialCursorState[] = cursors.getAll();
// Check if we should remove a cursor (sort of like a toggle)
if (states.length > 1) {
@@ -722,11 +719,11 @@ export namespace CoreNavigationCommands {
for (let i = 0, len = states.length; i < len; i++) {
const state = states[i];
if (newModelPosition && !state.modelState.selection.containsPosition(newModelPosition)) {
if (newModelPosition && !state.modelState!.selection.containsPosition(newModelPosition)) {
continue;
}
if (newViewPosition && !state.viewState.selection.containsPosition(newViewPosition)) {
if (newViewPosition && !state.viewState!.selection.containsPosition(newViewPosition)) {
continue;
}
@@ -768,8 +765,9 @@ export namespace CoreNavigationCommands {
const lastAddedCursorIndex = cursors.getLastAddedCursorIndex();
let newStates = cursors.getAll().slice(0);
newStates[lastAddedCursorIndex] = CursorMoveCommands.moveTo(context, newStates[lastAddedCursorIndex], true, args.position, args.viewPosition);
const states = cursors.getAll();
let newStates: PartialCursorState[] = states.slice(0);
newStates[lastAddedCursorIndex] = CursorMoveCommands.moveTo(context, states[lastAddedCursorIndex], true, args.position, args.viewPosition);
cursors.context.model.pushStackElement();
cursors.setStates(
@@ -796,7 +794,7 @@ export namespace CoreNavigationCommands {
CursorChangeReason.Explicit,
CursorMoveCommands.moveToBeginningOfLine(cursors.context, cursors.getAll(), this._inSelectionMode)
);
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(true, RevealTarget.Primary, ScrollType.Smooth);
}
}
@@ -845,11 +843,11 @@ export namespace CoreNavigationCommands {
CursorChangeReason.Explicit,
this._exec(cursors.context, cursors.getAll())
);
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(true, RevealTarget.Primary, ScrollType.Smooth);
}
private _exec(context: CursorContext, cursors: CursorState[]): CursorState[] {
let result: CursorState[] = [];
private _exec(context: CursorContext, cursors: CursorState[]): PartialCursorState[] {
let result: PartialCursorState[] = [];
for (let i = 0, len = cursors.length; i < len; i++) {
const cursor = cursors[i];
const lineNumber = cursor.modelState.position.lineNumber;
@@ -875,7 +873,7 @@ export namespace CoreNavigationCommands {
CursorChangeReason.Explicit,
CursorMoveCommands.moveToEndOfLine(cursors.context, cursors.getAll(), this._inSelectionMode)
);
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(true, RevealTarget.Primary, ScrollType.Smooth);
}
}
@@ -924,11 +922,11 @@ export namespace CoreNavigationCommands {
CursorChangeReason.Explicit,
this._exec(cursors.context, cursors.getAll())
);
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(true, RevealTarget.Primary, ScrollType.Smooth);
}
private _exec(context: CursorContext, cursors: CursorState[]): CursorState[] {
let result: CursorState[] = [];
private _exec(context: CursorContext, cursors: CursorState[]): PartialCursorState[] {
let result: PartialCursorState[] = [];
for (let i = 0, len = cursors.length; i < len; i++) {
const cursor = cursors[i];
const lineNumber = cursor.modelState.position.lineNumber;
@@ -955,7 +953,7 @@ export namespace CoreNavigationCommands {
CursorChangeReason.Explicit,
CursorMoveCommands.moveToBeginningOfBuffer(cursors.context, cursors.getAll(), this._inSelectionMode)
);
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(true, RevealTarget.Primary, ScrollType.Smooth);
}
}
@@ -999,7 +997,7 @@ export namespace CoreNavigationCommands {
CursorChangeReason.Explicit,
CursorMoveCommands.moveToEndOfBuffer(cursors.context, cursors.getAll(), this._inSelectionMode)
);
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(true, RevealTarget.Primary, ScrollType.Smooth);
}
}
@@ -1218,7 +1216,7 @@ export namespace CoreNavigationCommands {
CursorMoveCommands.word(cursors.context, cursors.getPrimaryCursor(), this._inSelectionMode, args.position)
]
);
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(true, RevealTarget.Primary, ScrollType.Smooth);
}
}
@@ -1247,8 +1245,9 @@ export namespace CoreNavigationCommands {
const lastAddedCursorIndex = cursors.getLastAddedCursorIndex();
let newStates = cursors.getAll().slice(0);
let lastAddedState = newStates[lastAddedCursorIndex];
const states = cursors.getAll();
let newStates: PartialCursorState[] = states.slice(0);
let lastAddedState = states[lastAddedCursorIndex];
newStates[lastAddedCursorIndex] = CursorMoveCommands.word(context, lastAddedState, lastAddedState.modelState.hasSelection(), args.position);
context.model.pushStackElement();
@@ -1277,7 +1276,7 @@ export namespace CoreNavigationCommands {
CursorMoveCommands.line(cursors.context, cursors.getPrimaryCursor(), this._inSelectionMode, args.position, args.viewPosition)
]
);
cursors.reveal(false, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(false, RevealTarget.Primary, ScrollType.Smooth);
}
}
@@ -1304,8 +1303,9 @@ export namespace CoreNavigationCommands {
public runCoreEditorCommand(cursors: ICursors, args: any): void {
const lastAddedCursorIndex = cursors.getLastAddedCursorIndex();
let newStates = cursors.getAll().slice(0);
newStates[lastAddedCursorIndex] = CursorMoveCommands.line(cursors.context, newStates[lastAddedCursorIndex], this._inSelectionMode, args.position, args.viewPosition);
const states = cursors.getAll();
let newStates: PartialCursorState[] = states.slice(0);
newStates[lastAddedCursorIndex] = CursorMoveCommands.line(cursors.context, states[lastAddedCursorIndex], this._inSelectionMode, args.position, args.viewPosition);
cursors.context.model.pushStackElement();
cursors.setStates(
@@ -1348,7 +1348,7 @@ export namespace CoreNavigationCommands {
CursorChangeReason.Explicit,
CursorMoveCommands.expandLineSelection(cursors.context, cursors.getAll())
);
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(true, RevealTarget.Primary, ScrollType.Smooth);
}
});
@@ -1376,7 +1376,7 @@ export namespace CoreNavigationCommands {
CursorMoveCommands.cancelSelection(cursors.context, cursors.getPrimaryCursor())
]
);
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(true, RevealTarget.Primary, ScrollType.Smooth);
}
});
@@ -1403,7 +1403,7 @@ export namespace CoreNavigationCommands {
cursors.getPrimaryCursor()
]
);
cursors.reveal(true, RevealTarget.Primary, editorCommon.ScrollType.Smooth);
cursors.reveal(true, RevealTarget.Primary, ScrollType.Smooth);
}
});
@@ -1418,7 +1418,7 @@ export namespace CoreNavigationCommands {
public runCoreEditorCommand(cursors: ICursors, args: any): void {
const revealLineArg = <RevealLine_.RawArguments>args;
let lineNumber = revealLineArg.lineNumber + 1;
let lineNumber = (revealLineArg.lineNumber || 0) + 1;
if (lineNumber < 1) {
lineNumber = 1;
}
@@ -1451,7 +1451,7 @@ export namespace CoreNavigationCommands {
const viewRange = cursors.context.convertModelRangeToViewRange(range);
cursors.revealRange(false, viewRange, revealAt, editorCommon.ScrollType.Smooth);
cursors.revealRange(false, viewRange, revealAt, ScrollType.Smooth);
}
});
@@ -1498,7 +1498,20 @@ export namespace CoreNavigationCommands {
export namespace CoreEditingCommands {
export const LineBreakInsert: EditorCommand = registerEditorCommand(new class extends EditorCommand {
export abstract class CoreEditingCommand extends EditorCommand {
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void {
const cursors = editor._getCursors();
if (!cursors) {
// the editor has no view => has no cursors
return;
}
this.runCoreEditingCommand(editor, cursors, args || {});
}
public abstract runCoreEditingCommand(editor: ICodeEditor, cursors: ICursors, args: any): void;
}
export const LineBreakInsert: EditorCommand = registerEditorCommand(new class extends CoreEditingCommand {
constructor() {
super({
id: 'lineBreakInsert',
@@ -1506,19 +1519,19 @@ export namespace CoreEditingCommands {
kbOpts: {
weight: CORE_WEIGHT,
kbExpr: EditorContextKeys.textInputFocus,
primary: null,
primary: 0,
mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_O }
}
});
}
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void {
public runCoreEditingCommand(editor: ICodeEditor, cursors: ICursors, args: any): void {
editor.pushUndoStop();
editor.executeCommands(this.id, TypeOperations.lineBreakInsert(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections()));
editor.executeCommands(this.id, TypeOperations.lineBreakInsert(cursors.context.config, cursors.context.model, cursors.getAll().map(s => s.modelState.selection)));
}
});
export const Outdent: EditorCommand = registerEditorCommand(new class extends EditorCommand {
export const Outdent: EditorCommand = registerEditorCommand(new class extends CoreEditingCommand {
constructor() {
super({
id: 'outdent',
@@ -1534,14 +1547,14 @@ export namespace CoreEditingCommands {
});
}
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void {
public runCoreEditingCommand(editor: ICodeEditor, cursors: ICursors, args: any): void {
editor.pushUndoStop();
editor.executeCommands(this.id, TypeOperations.outdent(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections()));
editor.executeCommands(this.id, TypeOperations.outdent(cursors.context.config, cursors.context.model, cursors.getAll().map(s => s.modelState.selection)));
editor.pushUndoStop();
}
});
export const Tab: EditorCommand = registerEditorCommand(new class extends EditorCommand {
export const Tab: EditorCommand = registerEditorCommand(new class extends CoreEditingCommand {
constructor() {
super({
id: 'tab',
@@ -1557,14 +1570,14 @@ export namespace CoreEditingCommands {
});
}
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void {
public runCoreEditingCommand(editor: ICodeEditor, cursors: ICursors, args: any): void {
editor.pushUndoStop();
editor.executeCommands(this.id, TypeOperations.tab(editor._getCursorConfiguration(), editor.getModel(), editor.getSelections()));
editor.executeCommands(this.id, TypeOperations.tab(cursors.context.config, cursors.context.model, cursors.getAll().map(s => s.modelState.selection)));
editor.pushUndoStop();
}
});
export const DeleteLeft: EditorCommand = registerEditorCommand(new class extends EditorCommand {
export const DeleteLeft: EditorCommand = registerEditorCommand(new class extends CoreEditingCommand {
constructor() {
super({
id: 'deleteLeft',
@@ -1579,9 +1592,8 @@ export namespace CoreEditingCommands {
});
}
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void {
const cursors = editor._getCursors();
const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteLeft(cursors.getPrevEditOperationType(), editor._getCursorConfiguration(), editor.getModel(), editor.getSelections());
public runCoreEditingCommand(editor: ICodeEditor, cursors: ICursors, args: any): void {
const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteLeft(cursors.getPrevEditOperationType(), cursors.context.config, cursors.context.model, cursors.getAll().map(s => s.modelState.selection));
if (shouldPushStackElementBefore) {
editor.pushUndoStop();
}
@@ -1590,7 +1602,7 @@ export namespace CoreEditingCommands {
}
});
export const DeleteRight: EditorCommand = registerEditorCommand(new class extends EditorCommand {
export const DeleteRight: EditorCommand = registerEditorCommand(new class extends CoreEditingCommand {
constructor() {
super({
id: 'deleteRight',
@@ -1604,9 +1616,8 @@ export namespace CoreEditingCommands {
});
}
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void {
const cursors = editor._getCursors();
const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteRight(cursors.getPrevEditOperationType(), editor._getCursorConfiguration(), editor.getModel(), editor.getSelections());
public runCoreEditingCommand(editor: ICodeEditor, cursors: ICursors, args: any): void {
const [shouldPushStackElementBefore, commands] = DeleteOperations.deleteRight(cursors.getPrevEditOperationType(), cursors.context.config, cursors.context.model, cursors.getAll().map(s => s.modelState.selection));
if (shouldPushStackElementBefore) {
editor.pushUndoStop();
}
@@ -1617,10 +1628,6 @@ export namespace CoreEditingCommands {
}
function findFocusedEditor(accessor: ServicesAccessor): ICodeEditor {
return accessor.get(ICodeEditorService).getFocusedCodeEditor();
}
function registerCommand(command: Command) {
command.register();
}
@@ -1644,10 +1651,10 @@ class EditorOrNativeTextInputCommand extends Command {
public runCommand(accessor: ServicesAccessor, args: any): void {
let focusedEditor = findFocusedEditor(accessor);
let focusedEditor = accessor.get(ICodeEditorService).getFocusedCodeEditor();
// Only if editor text focus (i.e. not if editor has widget focus).
if (focusedEditor && focusedEditor.hasTextFocus()) {
return this._runEditorHandler(focusedEditor, args);
return this._runEditorHandler(accessor, focusedEditor, args);
}
// Ignore this action when user is focused on an element that allows for entering text
@@ -1661,18 +1668,18 @@ class EditorOrNativeTextInputCommand extends Command {
let activeEditor = accessor.get(ICodeEditorService).getActiveCodeEditor();
if (activeEditor) {
activeEditor.focus();
return this._runEditorHandler(activeEditor, args);
return this._runEditorHandler(accessor, activeEditor, args);
}
}
private _runEditorHandler(editor: ICodeEditor, args: any): void {
private _runEditorHandler(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void {
let HANDLER = this._editorHandler;
if (typeof HANDLER === 'string') {
editor.trigger('keyboard', HANDLER, args);
} else {
args = args || {};
args.source = 'keyboard';
HANDLER.runEditorCommand(null, editor, args);
HANDLER.runEditorCommand(accessor, editor, args);
}
}
}
@@ -1693,7 +1700,7 @@ class EditorHandlerCommand extends Command {
}
public runCommand(accessor: ServicesAccessor, args: any): void {
const editor = findFocusedEditor(accessor);
const editor = accessor.get(ICodeEditorService).getFocusedCodeEditor();
if (!editor) {
return;
}
@@ -1721,9 +1728,9 @@ registerCommand(new EditorOrNativeTextInputCommand({
}));
registerCommand(new EditorOrNativeTextInputCommand({
editorHandler: H.Undo,
editorHandler: Handler.Undo,
inputHandler: 'undo',
id: H.Undo,
id: Handler.Undo,
precondition: EditorContextKeys.writable,
kbOpts: {
weight: CORE_WEIGHT,
@@ -1737,12 +1744,12 @@ registerCommand(new EditorOrNativeTextInputCommand({
order: 1
}
}));
registerCommand(new EditorHandlerCommand('default:' + H.Undo, H.Undo));
registerCommand(new EditorHandlerCommand('default:' + Handler.Undo, Handler.Undo));
registerCommand(new EditorOrNativeTextInputCommand({
editorHandler: H.Redo,
editorHandler: Handler.Redo,
inputHandler: 'redo',
id: H.Redo,
id: Handler.Redo,
precondition: EditorContextKeys.writable,
kbOpts: {
weight: CORE_WEIGHT,
@@ -1758,16 +1765,16 @@ registerCommand(new EditorOrNativeTextInputCommand({
order: 2
}
}));
registerCommand(new EditorHandlerCommand('default:' + H.Redo, H.Redo));
registerCommand(new EditorHandlerCommand('default:' + Handler.Redo, Handler.Redo));
function registerOverwritableCommand(handlerId: string): void {
registerCommand(new EditorHandlerCommand('default:' + handlerId, handlerId));
registerCommand(new EditorHandlerCommand(handlerId, handlerId));
}
registerOverwritableCommand(H.Type);
registerOverwritableCommand(H.ReplacePreviousChar);
registerOverwritableCommand(H.CompositionStart);
registerOverwritableCommand(H.CompositionEnd);
registerOverwritableCommand(H.Paste);
registerOverwritableCommand(H.Cut);
registerOverwritableCommand(Handler.Type);
registerOverwritableCommand(Handler.ReplacePreviousChar);
registerOverwritableCommand(Handler.CompositionStart);
registerOverwritableCommand(Handler.CompositionEnd);
registerOverwritableCommand(Handler.Paste);
registerOverwritableCommand(Handler.Cut);

View File

@@ -2,31 +2,30 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Disposable } from 'vs/base/common/lifecycle';
import * as platform from 'vs/base/common/platform';
import * as browser from 'vs/base/browser/browser';
import * as dom from 'vs/base/browser/dom';
import { StandardWheelEvent, IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { RunOnceScheduler, TimeoutTimer } from 'vs/base/common/async';
import { Disposable } from 'vs/base/common/lifecycle';
import * as platform from 'vs/base/common/platform';
import { HitTestContext, IViewZoneData, MouseTarget, MouseTargetFactory } from 'vs/editor/browser/controller/mouseTarget';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { ClientCoordinates, EditorMouseEvent, EditorMouseEventFactory, GlobalEditorMouseMoveMonitor, createEditorPagePosition } from 'vs/editor/browser/editorDom';
import { ViewController } from 'vs/editor/browser/view/viewController';
import { IViewCursorRenderData } from 'vs/editor/browser/viewParts/viewCursors/viewCursor';
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
import { Position } from 'vs/editor/common/core/position';
import { Selection } from 'vs/editor/common/core/selection';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { MouseTarget, MouseTargetFactory, IViewZoneData, HitTestContext } from 'vs/editor/browser/controller/mouseTarget';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { TimeoutTimer, RunOnceScheduler } from 'vs/base/common/async';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { HorizontalRange } from 'vs/editor/common/view/renderingContext';
import { EditorMouseEventFactory, GlobalEditorMouseMoveMonitor, EditorMouseEvent, createEditorPagePosition, ClientCoordinates } from 'vs/editor/browser/editorDom';
import { StandardMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
import { IViewCursorRenderData } from 'vs/editor/browser/viewParts/viewCursors/viewCursor';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { ViewController } from 'vs/editor/browser/view/viewController';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
/**
* Merges mouse events when mouse move events are throttled
*/
function createMouseMoveEventMerger(mouseTargetFactory: MouseTargetFactory) {
function createMouseMoveEventMerger(mouseTargetFactory: MouseTargetFactory | null) {
return function (lastEvent: EditorMouseEvent, currentEvent: EditorMouseEvent): EditorMouseEvent {
let targetIsWidget = false;
if (mouseTargetFactory) {
@@ -56,9 +55,9 @@ export interface IPointerHandlerHelper {
/**
* Decode a position from a rendered dom node
*/
getPositionFromDOMInfo(spanNode: HTMLElement, offset: number): Position;
getPositionFromDOMInfo(spanNode: HTMLElement, offset: number): Position | null;
visibleRangeForPosition2(lineNumber: number, column: number): HorizontalRange;
visibleRangeForPosition2(lineNumber: number, column: number): HorizontalRange | null;
getLineWidth(lineNumber: number): number;
}
@@ -109,12 +108,12 @@ export class MouseHandler extends ViewEventHandler {
this._register(mouseEvents.onMouseDown(this.viewHelper.viewDomNode, (e) => this._onMouseDown(e)));
let onMouseWheel = (browserEvent: MouseWheelEvent) => {
let onMouseWheel = (browserEvent: IMouseWheelEvent) => {
if (!this._context.configuration.editor.viewInfo.mouseWheelZoom) {
return;
}
let e = new StandardMouseWheelEvent(browserEvent);
if (e.browserEvent.ctrlKey || e.browserEvent.metaKey) {
let e = new StandardWheelEvent(browserEvent);
if (e.browserEvent!.ctrlKey || e.browserEvent!.metaKey) {
let zoomLevel: number = EditorZoom.getZoomLevel();
let delta = e.deltaY > 0 ? 1 : -1;
EditorZoom.setZoomLevel(zoomLevel + delta);
@@ -123,7 +122,6 @@ export class MouseHandler extends ViewEventHandler {
}
};
this._register(dom.addDisposableListener(this.viewHelper.viewDomNode, 'mousewheel', onMouseWheel, true));
this._register(dom.addDisposableListener(this.viewHelper.viewDomNode, 'DOMMouseScroll', onMouseWheel, true));
this._context.addEventHandler(this);
}
@@ -149,7 +147,7 @@ export class MouseHandler extends ViewEventHandler {
}
// --- end event handlers
public getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget {
public getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget | null {
let clientPos = new ClientCoordinates(clientX, clientY);
let pos = clientPos.toPageCoordinates();
let editorPos = createEditorPagePosition(this.viewHelper.viewDomNode);
@@ -277,7 +275,7 @@ class MouseDownOperation extends Disposable {
private _currentSelection: Selection;
private _isActive: boolean;
private _lastMouseEvent: EditorMouseEvent;
private _lastMouseEvent: EditorMouseEvent | null;
constructor(
context: ViewContext,
@@ -337,7 +335,7 @@ class MouseDownOperation extends Disposable {
this._mouseState.setStartButtons(e);
this._mouseState.setModifiers(e);
let position = this._findMousePosition(e, true);
if (!position) {
if (!position || !position.position) {
// Ignoring because position is unknown
return;
}
@@ -353,7 +351,8 @@ class MouseDownOperation extends Disposable {
&& e.detail < 2 // only single click on a selection can work
&& !this._isActive // the mouse is not down yet
&& !this._currentSelection.isEmpty() // we don't drag single cursor
&& this._currentSelection.containsPosition(position.position) // single click on a selection
&& (position.type === editorBrowser.MouseTargetType.CONTENT_TEXT) // single click on text
&& position.position && this._currentSelection.containsPosition(position.position) // single click on a selection
) {
this._mouseState.isDragAndDrop = true;
this._isActive = true;
@@ -362,11 +361,11 @@ class MouseDownOperation extends Disposable {
createMouseMoveEventMerger(null),
(e) => this._onMouseDownThenMove(e),
() => {
let position = this._findMousePosition(this._lastMouseEvent, true);
let position = this._findMousePosition(this._lastMouseEvent!, true);
this._viewController.emitMouseDrop({
event: this._lastMouseEvent,
target: position ? this._createMouseTarget(this._lastMouseEvent, true) : null // Ignoring because position is unknown, e.g., Content View Zone
event: this._lastMouseEvent!,
target: (position ? this._createMouseTarget(this._lastMouseEvent!, true) : null) // Ignoring because position is unknown, e.g., Content View Zone
});
this._stop();
@@ -399,6 +398,9 @@ class MouseDownOperation extends Disposable {
return;
}
this._onScrollTimeout.setIfNotSet(() => {
if (!this._lastMouseEvent) {
return;
}
let position = this._findMousePosition(this._lastMouseEvent, false);
if (!position) {
// Ignoring because position is unknown
@@ -416,7 +418,7 @@ class MouseDownOperation extends Disposable {
this._currentSelection = e.selections[0];
}
private _getPositionOutsideEditor(e: EditorMouseEvent): MouseTarget {
private _getPositionOutsideEditor(e: EditorMouseEvent): MouseTarget | null {
const editorContent = e.editorPos;
const model = this._context.model;
const viewLayout = this._context.viewLayout;
@@ -464,7 +466,7 @@ class MouseDownOperation extends Disposable {
return null;
}
private _findMousePosition(e: EditorMouseEvent, testEventTarget: boolean): MouseTarget {
private _findMousePosition(e: EditorMouseEvent, testEventTarget: boolean): MouseTarget | null {
let positionOutsideEditor = this._getPositionOutsideEditor(e);
if (positionOutsideEditor) {
return positionOutsideEditor;
@@ -486,7 +488,7 @@ class MouseDownOperation extends Disposable {
return t;
}
private _helpPositionJumpOverViewZone(viewZoneData: IViewZoneData): Position {
private _helpPositionJumpOverViewZone(viewZoneData: IViewZoneData): Position | null {
// Force position on view zones to go above or below depending on where selection started from
let selectionStart = new Position(this._currentSelection.selectionStartLineNumber, this._currentSelection.selectionStartColumn);
let positionBefore = viewZoneData.positionBefore;
@@ -503,6 +505,9 @@ class MouseDownOperation extends Disposable {
}
private _dispatchMouse(position: MouseTarget, inSelectionMode: boolean): void {
if (!position.position) {
return;
}
this._viewController.dispatchMouse({
position: position.position,
mouseColumn: position.mouseColumn,
@@ -546,7 +551,7 @@ class MouseDownState {
private _startedOnLineNumbers: boolean;
public get startedOnLineNumbers(): boolean { return this._startedOnLineNumbers; }
private _lastMouseDownPosition: Position;
private _lastMouseDownPosition: Position | null;
private _lastMouseDownPositionEqualCount: number;
private _lastMouseDownCount: number;
private _lastSetMouseDownCountTime: number;

View File

@@ -2,26 +2,25 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as browser from 'vs/base/browser/browser';
import { IPointerHandlerHelper } from 'vs/editor/browser/controller/mouseHandler';
import { IMouseTarget, MouseTargetType } from 'vs/editor/browser/editorBrowser';
import { ClientCoordinates, EditorMouseEvent, EditorPagePosition, PageCoordinates } from 'vs/editor/browser/editorDom';
import { PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPart';
import { ViewLine } from 'vs/editor/browser/viewParts/lines/viewLine';
import { IViewCursorRenderData } from 'vs/editor/browser/viewParts/viewCursors/viewCursor';
import { EditorLayoutInfo } from 'vs/editor/common/config/editorOptions';
import { Position } from 'vs/editor/common/core/position';
import { Range as EditorRange } from 'vs/editor/common/core/range';
import { MouseTargetType, IMouseTarget } from 'vs/editor/browser/editorBrowser';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { IPointerHandlerHelper } from 'vs/editor/browser/controller/mouseHandler';
import { EditorMouseEvent, PageCoordinates, ClientCoordinates, EditorPagePosition } from 'vs/editor/browser/editorDom';
import * as browser from 'vs/base/browser/browser';
import { IViewCursorRenderData } from 'vs/editor/browser/viewParts/viewCursors/viewCursor';
import { PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPart';
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { EditorLayoutInfo } from 'vs/editor/common/config/editorOptions';
import { ViewLine } from 'vs/editor/browser/viewParts/lines/viewLine';
import { HorizontalRange } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
export interface IViewZoneData {
viewZoneId: number;
positionBefore: Position;
positionAfter: Position;
positionBefore: Position | null;
positionAfter: Position | null;
position: Position;
afterLineNumber: number;
}
@@ -85,20 +84,20 @@ declare var IETextRange: {
};
interface IHitTestResult {
position: Position;
hitTarget: Element;
position: Position | null;
hitTarget: Element | null;
}
export class MouseTarget implements IMouseTarget {
public readonly element: Element;
public readonly element: Element | null;
public readonly type: MouseTargetType;
public readonly mouseColumn: number;
public readonly position: Position;
public readonly range: EditorRange;
public readonly position: Position | null;
public readonly range: EditorRange | null;
public readonly detail: any;
constructor(element: Element, type: MouseTargetType, mouseColumn: number = 0, position: Position = null, range: EditorRange = null, detail: any = null) {
constructor(element: Element | null, type: MouseTargetType, mouseColumn: number = 0, position: Position | null = null, range: EditorRange | null = null, detail: any = null) {
this.element = element;
this.type = type;
this.mouseColumn = mouseColumn;
@@ -248,20 +247,20 @@ export class HitTestContext {
this._viewHelper = viewHelper;
}
public getZoneAtCoord(mouseVerticalOffset: number): IViewZoneData {
public getZoneAtCoord(mouseVerticalOffset: number): IViewZoneData | null {
return HitTestContext.getZoneAtCoord(this._context, mouseVerticalOffset);
}
public static getZoneAtCoord(context: ViewContext, mouseVerticalOffset: number): IViewZoneData {
public static getZoneAtCoord(context: ViewContext, mouseVerticalOffset: number): IViewZoneData | null {
// The target is either a view zone or the empty space after the last view-line
let viewZoneWhitespace = context.viewLayout.getWhitespaceAtVerticalOffset(mouseVerticalOffset);
if (viewZoneWhitespace) {
let viewZoneMiddle = viewZoneWhitespace.verticalOffset + viewZoneWhitespace.height / 2,
lineCount = context.model.getLineCount(),
positionBefore: Position = null,
position: Position,
positionAfter: Position = null;
positionBefore: Position | null = null,
position: Position | null,
positionAfter: Position | null = null;
if (viewZoneWhitespace.afterLineNumber !== lineCount) {
// There are more lines after this view zone
@@ -287,7 +286,7 @@ export class HitTestContext {
afterLineNumber: viewZoneWhitespace.afterLineNumber,
positionBefore: positionBefore,
positionAfter: positionAfter,
position: position
position: position!
};
}
return null;
@@ -324,11 +323,11 @@ export class HitTestContext {
return this._context.viewLayout.getVerticalOffsetForLineNumber(lineNumber);
}
public findAttribute(element: Element, attr: string): string {
public findAttribute(element: Element, attr: string): string | null {
return HitTestContext._findAttribute(element, attr, this._viewHelper.viewDomNode);
}
private static _findAttribute(element: Element, attr: string, stopAt: Element): string {
private static _findAttribute(element: Element, attr: string, stopAt: Element): string | null {
while (element && element !== document.body) {
if (element.hasAttribute && element.hasAttribute(attr)) {
return element.getAttribute(attr);
@@ -345,11 +344,11 @@ export class HitTestContext {
return this._viewHelper.getLineWidth(lineNumber);
}
public visibleRangeForPosition2(lineNumber: number, column: number): HorizontalRange {
public visibleRangeForPosition2(lineNumber: number, column: number): HorizontalRange | null {
return this._viewHelper.visibleRangeForPosition2(lineNumber, column);
}
public getPositionFromDOMInfo(spanNode: HTMLElement, offset: number): Position {
public getPositionFromDOMInfo(spanNode: HTMLElement, offset: number): Position | null {
return this._viewHelper.getPositionFromDOMInfo(spanNode, offset);
}
@@ -387,10 +386,10 @@ abstract class BareHitTestRequest {
class HitTestRequest extends BareHitTestRequest {
private readonly _ctx: HitTestContext;
public readonly target: Element;
public readonly target: Element | null;
public readonly targetPath: Uint8Array;
constructor(ctx: HitTestContext, editorPos: EditorPagePosition, pos: PageCoordinates, target: Element) {
constructor(ctx: HitTestContext, editorPos: EditorPagePosition, pos: PageCoordinates, target: Element | null) {
super(ctx, editorPos, pos);
this._ctx = ctx;
@@ -407,15 +406,19 @@ class HitTestRequest extends BareHitTestRequest {
return `pos(${this.pos.x},${this.pos.y}), editorPos(${this.editorPos.x},${this.editorPos.y}), mouseVerticalOffset: ${this.mouseVerticalOffset}, mouseContentHorizontalOffset: ${this.mouseContentHorizontalOffset}\n\ttarget: ${this.target ? (<HTMLElement>this.target).outerHTML : null}`;
}
public fulfill(type: MouseTargetType, position: Position = null, range: EditorRange = null, detail: any = null): MouseTarget {
public fulfill(type: MouseTargetType, position: Position | null = null, range: EditorRange | null = null, detail: any = null): MouseTarget {
return new MouseTarget(this.target, type, this.mouseColumn, position, range, detail);
}
public withTarget(target: Element): HitTestRequest {
public withTarget(target: Element | null): HitTestRequest {
return new HitTestRequest(this._ctx, this.editorPos, this.pos, target);
}
}
interface ResolvedHitTestRequest extends HitTestRequest {
readonly target: Element;
}
const EMPTY_CONTENT_AFTER_LINES: IEmptyContentData = { isAfterLines: true };
function createEmptyContentDataInLines(horizontalDistanceToText: number): IEmptyContentData {
@@ -452,7 +455,7 @@ export class MouseTargetFactory {
return false;
}
public createMouseTarget(lastViewCursorsRenderData: IViewCursorRenderData[], editorPos: EditorPagePosition, pos: PageCoordinates, target: HTMLElement): IMouseTarget {
public createMouseTarget(lastViewCursorsRenderData: IViewCursorRenderData[], editorPos: EditorPagePosition, pos: PageCoordinates, target: HTMLElement | null): IMouseTarget {
const ctx = new HitTestContext(this._context, this._viewHelper, lastViewCursorsRenderData);
const request = new HitTestRequest(ctx, editorPos, pos, target);
try {
@@ -485,23 +488,26 @@ export class MouseTargetFactory {
return this._createMouseTarget(ctx, request.withTarget(hitTestResult.hitTarget), true);
}
let result: MouseTarget = null;
// we know for a fact that request.target is not null
const resolvedRequest = <ResolvedHitTestRequest>request;
result = result || MouseTargetFactory._hitTestContentWidget(ctx, request);
result = result || MouseTargetFactory._hitTestOverlayWidget(ctx, request);
result = result || MouseTargetFactory._hitTestMinimap(ctx, request);
result = result || MouseTargetFactory._hitTestScrollbarSlider(ctx, request);
result = result || MouseTargetFactory._hitTestViewZone(ctx, request);
result = result || MouseTargetFactory._hitTestMargin(ctx, request);
result = result || MouseTargetFactory._hitTestViewCursor(ctx, request);
result = result || MouseTargetFactory._hitTestTextArea(ctx, request);
result = result || MouseTargetFactory._hitTestViewLines(ctx, request, domHitTestExecuted);
result = result || MouseTargetFactory._hitTestScrollbar(ctx, request);
let result: MouseTarget | null = null;
result = result || MouseTargetFactory._hitTestContentWidget(ctx, resolvedRequest);
result = result || MouseTargetFactory._hitTestOverlayWidget(ctx, resolvedRequest);
result = result || MouseTargetFactory._hitTestMinimap(ctx, resolvedRequest);
result = result || MouseTargetFactory._hitTestScrollbarSlider(ctx, resolvedRequest);
result = result || MouseTargetFactory._hitTestViewZone(ctx, resolvedRequest);
result = result || MouseTargetFactory._hitTestMargin(ctx, resolvedRequest);
result = result || MouseTargetFactory._hitTestViewCursor(ctx, resolvedRequest);
result = result || MouseTargetFactory._hitTestTextArea(ctx, resolvedRequest);
result = result || MouseTargetFactory._hitTestViewLines(ctx, resolvedRequest, domHitTestExecuted);
result = result || MouseTargetFactory._hitTestScrollbar(ctx, resolvedRequest);
return (result || request.fulfill(MouseTargetType.UNKNOWN));
}
private static _hitTestContentWidget(ctx: HitTestContext, request: HitTestRequest): MouseTarget {
private static _hitTestContentWidget(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null {
// Is it a content widget?
if (ElementPath.isChildOfContentWidgets(request.targetPath) || ElementPath.isChildOfOverflowingContentWidgets(request.targetPath)) {
let widgetId = ctx.findAttribute(request.target, 'widgetId');
@@ -514,7 +520,7 @@ export class MouseTargetFactory {
return null;
}
private static _hitTestOverlayWidget(ctx: HitTestContext, request: HitTestRequest): MouseTarget {
private static _hitTestOverlayWidget(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null {
// Is it an overlay widget?
if (ElementPath.isChildOfOverlayWidgets(request.targetPath)) {
let widgetId = ctx.findAttribute(request.target, 'widgetId');
@@ -527,7 +533,7 @@ export class MouseTargetFactory {
return null;
}
private static _hitTestViewCursor(ctx: HitTestContext, request: HitTestRequest): MouseTarget {
private static _hitTestViewCursor(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null {
if (request.target) {
// Check if we've hit a painted cursor
@@ -578,7 +584,7 @@ export class MouseTargetFactory {
return null;
}
private static _hitTestViewZone(ctx: HitTestContext, request: HitTestRequest): MouseTarget {
private static _hitTestViewZone(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null {
let viewZoneData = ctx.getZoneAtCoord(request.mouseVerticalOffset);
if (viewZoneData) {
let mouseTargetType = (request.isInContentArea ? MouseTargetType.CONTENT_VIEW_ZONE : MouseTargetType.GUTTER_VIEW_ZONE);
@@ -588,7 +594,7 @@ export class MouseTargetFactory {
return null;
}
private static _hitTestTextArea(ctx: HitTestContext, request: HitTestRequest): MouseTarget {
private static _hitTestTextArea(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null {
// Is it the textarea?
if (ElementPath.isTextArea(request.targetPath)) {
return request.fulfill(MouseTargetType.TEXTAREA);
@@ -596,7 +602,7 @@ export class MouseTargetFactory {
return null;
}
private static _hitTestMargin(ctx: HitTestContext, request: HitTestRequest): MouseTarget {
private static _hitTestMargin(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null {
if (request.isInMarginArea) {
let res = ctx.getFullLineRangeAtCoord(request.mouseVerticalOffset);
let pos = res.range.getStartPosition();
@@ -629,7 +635,7 @@ export class MouseTargetFactory {
return null;
}
private static _hitTestViewLines(ctx: HitTestContext, request: HitTestRequest, domHitTestExecuted: boolean): MouseTarget {
private static _hitTestViewLines(ctx: HitTestContext, request: ResolvedHitTestRequest, domHitTestExecuted: boolean): MouseTarget | null {
if (!ElementPath.isChildOfViewLines(request.targetPath)) {
return null;
}
@@ -667,7 +673,7 @@ export class MouseTargetFactory {
return this._createMouseTarget(ctx, request.withTarget(hitTestResult.hitTarget), true);
}
private static _hitTestMinimap(ctx: HitTestContext, request: HitTestRequest): MouseTarget {
private static _hitTestMinimap(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null {
if (ElementPath.isChildOfMinimap(request.targetPath)) {
const possibleLineNumber = ctx.getLineNumberAtVerticalOffset(request.mouseVerticalOffset);
const maxColumn = ctx.model.getLineMaxColumn(possibleLineNumber);
@@ -676,7 +682,7 @@ export class MouseTargetFactory {
return null;
}
private static _hitTestScrollbarSlider(ctx: HitTestContext, request: HitTestRequest): MouseTarget {
private static _hitTestScrollbarSlider(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null {
if (ElementPath.isChildOfScrollableElement(request.targetPath)) {
if (request.target && request.target.nodeType === 1) {
let className = request.target.className;
@@ -690,7 +696,7 @@ export class MouseTargetFactory {
return null;
}
private static _hitTestScrollbar(ctx: HitTestContext, request: HitTestRequest): MouseTarget {
private static _hitTestScrollbar(ctx: HitTestContext, request: ResolvedHitTestRequest): MouseTarget | null {
// Is it the overview ruler?
// Is it a child of the scrollable element?
if (ElementPath.isChildOfScrollableElement(request.targetPath)) {
@@ -818,7 +824,7 @@ export class MouseTargetFactory {
// Chrome always hits a TEXT_NODE, while Edge sometimes hits a token span
let startContainer = range.startContainer;
let hitTarget: HTMLElement;
let hitTarget: HTMLElement | null = null;
if (startContainer.nodeType === startContainer.TEXT_NODE) {
// startContainer is expected to be the token text
@@ -843,7 +849,7 @@ export class MouseTargetFactory {
let parent2ClassName = parent2 && parent2.nodeType === parent2.ELEMENT_NODE ? (<HTMLElement>parent2).className : null;
if (parent2ClassName === ViewLine.CLASS_NAME) {
let p = ctx.getPositionFromDOMInfo(<HTMLElement>startContainer, (<HTMLElement>startContainer).textContent.length);
let p = ctx.getPositionFromDOMInfo(<HTMLElement>startContainer, (<HTMLElement>startContainer).textContent!.length);
return {
position: p,
hitTarget: null
@@ -896,8 +902,8 @@ export class MouseTargetFactory {
* Most probably IE
*/
private static _doHitTestWithMoveToPoint(ctx: HitTestContext, coords: ClientCoordinates): IHitTestResult {
let resultPosition: Position = null;
let resultHitTarget: Element = null;
let resultPosition: Position | null = null;
let resultHitTarget: Element | null = null;
let textRange: IETextRange = (<any>document.body).createTextRange();
try {
@@ -920,7 +926,7 @@ export class MouseTargetFactory {
if (parent2ClassName === ViewLine.CLASS_NAME) {
let rangeToContainEntireSpan = textRange.duplicate();
rangeToContainEntireSpan.moveToElementText(parentElement);
rangeToContainEntireSpan.moveToElementText(parentElement!);
rangeToContainEntireSpan.setEndPoint('EndToStart', textRange);
resultPosition = ctx.getPositionFromDOMInfo(<HTMLElement>parentElement, rangeToContainEntireSpan.text.length);

View File

@@ -2,16 +2,15 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IDisposable } from 'vs/base/common/lifecycle';
import * as dom from 'vs/base/browser/dom';
import { EventType, Gesture, GestureEvent } from 'vs/base/browser/touch';
import { MouseHandler, IPointerHandlerHelper } from 'vs/editor/browser/controller/mouseHandler';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IPointerHandlerHelper, MouseHandler } from 'vs/editor/browser/controller/mouseHandler';
import { IMouseTarget } from 'vs/editor/browser/editorBrowser';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { EditorMouseEvent } from 'vs/editor/browser/editorDom';
import { ViewController } from 'vs/editor/browser/view/viewController';
import { ViewContext } from 'vs/editor/common/view/viewContext';
interface IThrottledGestureEvent {
translationX: number;
@@ -235,7 +234,7 @@ export class PointerHandler implements IDisposable {
}
}
public getTargetAtClientPoint(clientX: number, clientY: number): IMouseTarget {
public getTargetAtClientPoint(clientX: number, clientY: number): IMouseTarget | null {
return this.handler.getTargetAtClientPoint(clientX, clientY);
}

View File

@@ -2,35 +2,34 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./textAreaHandler';
import * as platform from 'vs/base/common/platform';
import * as browser from 'vs/base/browser/browser';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import * as platform from 'vs/base/common/platform';
import * as strings from 'vs/base/common/strings';
import { TextAreaInput, ITextAreaInputHost, IPasteData, ICompositionData } from 'vs/editor/browser/controller/textAreaInput';
import { ISimpleModel, ITypeData, TextAreaState, PagedScreenReaderStrategy } from 'vs/editor/browser/controller/textAreaState';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { CopyOptions, ICompositionData, IPasteData, ITextAreaInputHost, TextAreaInput } from 'vs/editor/browser/controller/textAreaInput';
import { ISimpleModel, ITypeData, PagedScreenReaderStrategy, TextAreaState } from 'vs/editor/browser/controller/textAreaState';
import { ViewController } from 'vs/editor/browser/view/viewController';
import { PartFingerprint, PartFingerprints, ViewPart } from 'vs/editor/browser/view/viewPart';
import { LineNumbersOverlay } from 'vs/editor/browser/viewParts/lineNumbers/lineNumbers';
import { Margin } from 'vs/editor/browser/viewParts/margin/margin';
import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { WordCharacterClass, getMapForWordSeparators } from 'vs/editor/common/controller/wordCharacterClassifier';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { Position } from 'vs/editor/common/core/position';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { HorizontalRange, RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { ViewController } from 'vs/editor/browser/view/viewController';
import { ScrollType } from 'vs/editor/common/editorCommon';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { PartFingerprints, PartFingerprint, ViewPart } from 'vs/editor/browser/view/viewPart';
import { Margin } from 'vs/editor/browser/viewParts/margin/margin';
import { LineNumbersOverlay } from 'vs/editor/browser/viewParts/lineNumbers/lineNumbers';
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
import { EndOfLinePreference } from 'vs/editor/common/model';
import { getMapForWordSeparators, WordCharacterClass } from 'vs/editor/common/controller/wordCharacterClassifier';
import { HorizontalRange, RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
export interface ITextAreaHandlerHelper {
visibleRangeForPositionRelativeToEditor(lineNumber: number, column: number): HorizontalRange;
visibleRangeForPositionRelativeToEditor(lineNumber: number, column: number): HorizontalRange | null;
}
class VisibleTextAreaData {
@@ -56,7 +55,7 @@ const canUseZeroSizeTextarea = (browser.isEdgeOrIE || browser.isFirefox);
interface LocalClipboardMetadata {
lastCopiedValue: string;
isFromEmptySelection: boolean;
multicursorText: string[];
multicursorText: string[] | null;
}
/**
@@ -67,17 +66,17 @@ interface LocalClipboardMetadata {
class LocalClipboardMetadataManager {
public static INSTANCE = new LocalClipboardMetadataManager();
private _lastState: LocalClipboardMetadata;
private _lastState: LocalClipboardMetadata | null;
constructor() {
this._lastState = null;
}
public set(state: LocalClipboardMetadata): void {
public set(state: LocalClipboardMetadata | null): void {
this._lastState = state;
}
public get(pastedText: string): LocalClipboardMetadata {
public get(pastedText: string): LocalClipboardMetadata | null {
if (this._lastState && this._lastState.lastCopiedValue === pastedText) {
// match!
return this._lastState;
@@ -100,11 +99,12 @@ export class TextAreaHandler extends ViewPart {
private _fontInfo: BareFontInfo;
private _lineHeight: number;
private _emptySelectionClipboard: boolean;
private _copyWithSyntaxHighlighting: boolean;
/**
* Defined only when the text area is visible (composition case).
*/
private _visibleTextArea: VisibleTextAreaData;
private _visibleTextArea: VisibleTextAreaData | null;
private _selections: Selection[];
public readonly textArea: FastDomNode<HTMLTextAreaElement>;
@@ -128,6 +128,7 @@ export class TextAreaHandler extends ViewPart {
this._fontInfo = conf.fontInfo;
this._lineHeight = conf.lineHeight;
this._emptySelectionClipboard = conf.emptySelectionClipboard;
this._copyWithSyntaxHighlighting = conf.copyWithSyntaxHighlighting;
this._visibleTextArea = null;
this._selections = [new Selection(1, 1, 1, 1)];
@@ -171,7 +172,7 @@ export class TextAreaHandler extends ViewPart {
const multicursorText = (Array.isArray(rawWhatToCopy) ? rawWhatToCopy : null);
const whatToCopy = (Array.isArray(rawWhatToCopy) ? rawWhatToCopy.join(newLineCharacter) : rawWhatToCopy);
let metadata: LocalClipboardMetadata = null;
let metadata: LocalClipboardMetadata | null = null;
if (isFromEmptySelection || multicursorText) {
// Only store the non-default metadata
@@ -190,7 +191,11 @@ export class TextAreaHandler extends ViewPart {
return whatToCopy;
},
getHTMLToCopy: (): string => {
getHTMLToCopy: (): string | null => {
if (!this._copyWithSyntaxHighlighting && !CopyOptions.forceCopyWithSyntaxHighlighting) {
return null;
}
return this._context.model.getHTMLToCopy(this._selections, this._emptySelectionClipboard);
},
@@ -245,7 +250,7 @@ export class TextAreaHandler extends ViewPart {
const metadata = LocalClipboardMetadataManager.INSTANCE.get(e.text);
let pasteOnNewLine = false;
let multicursorText: string[] = null;
let multicursorText: string[] | null = null;
if (metadata) {
pasteOnNewLine = (this._emptySelectionClipboard && metadata.isFromEmptySelection);
multicursorText = metadata.multicursorText;
@@ -302,10 +307,10 @@ export class TextAreaHandler extends ViewPart {
if (browser.isEdgeOrIE) {
// Due to isEdgeOrIE (where the textarea was not cleared initially)
// we cannot assume the text consists only of the composited text
this._visibleTextArea = this._visibleTextArea.setWidth(0);
this._visibleTextArea = this._visibleTextArea!.setWidth(0);
} else {
// adjust width by its size
this._visibleTextArea = this._visibleTextArea.setWidth(measureText(e.data, this._fontInfo));
this._visibleTextArea = this._visibleTextArea!.setWidth(measureText(e.data, this._fontInfo));
}
this._render();
}));
@@ -387,6 +392,9 @@ export class TextAreaHandler extends ViewPart {
if (e.emptySelectionClipboard) {
this._emptySelectionClipboard = conf.emptySelectionClipboard;
}
if (e.copyWithSyntaxHighlighting) {
this._copyWithSyntaxHighlighting = conf.copyWithSyntaxHighlighting;
}
return true;
}
@@ -434,7 +442,7 @@ export class TextAreaHandler extends ViewPart {
// --- end view API
private _primaryCursorVisibleRange: HorizontalRange = null;
private _primaryCursorVisibleRange: HorizontalRange | null = null;
public prepareRender(ctx: RenderingContext): void {
if (this._accessibilitySupport === platform.AccessibilitySupport.Enabled) {
@@ -556,7 +564,7 @@ export class TextAreaHandler extends ViewPart {
function measureText(text: string, fontInfo: BareFontInfo): number {
// adjust width by its size
const canvasElem = <HTMLCanvasElement>document.createElement('canvas');
const context = canvasElem.getContext('2d');
const context = canvasElem.getContext('2d')!;
context.font = createFontString(fontInfo);
const metrics = context.measureText(text);

View File

@@ -2,21 +2,20 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as browser from 'vs/base/browser/browser';
import * as dom from 'vs/base/browser/dom';
import { FastDomNode } from 'vs/base/browser/fastDomNode';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { RunOnceScheduler } from 'vs/base/common/async';
import { Position } from 'vs/editor/common/core/position';
import { Selection } from 'vs/editor/common/core/selection';
import * as strings from 'vs/base/common/strings';
import { Event, Emitter } from 'vs/base/common/event';
import { Emitter, Event } from 'vs/base/common/event';
import { KeyCode } from 'vs/base/common/keyCodes';
import { Disposable } from 'vs/base/common/lifecycle';
import { ITypeData, TextAreaState, ITextAreaWrapper } from 'vs/editor/browser/controller/textAreaState';
import * as browser from 'vs/base/browser/browser';
import * as platform from 'vs/base/common/platform';
import * as dom from 'vs/base/browser/dom';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { FastDomNode } from 'vs/base/browser/fastDomNode';
import * as strings from 'vs/base/common/strings';
import { ITextAreaWrapper, ITypeData, TextAreaState } from 'vs/editor/browser/controller/textAreaState';
import { Position } from 'vs/editor/common/core/position';
import { Selection } from 'vs/editor/common/core/selection';
export interface ICompositionData {
data: string;
@@ -37,7 +36,7 @@ export interface IPasteData {
export interface ITextAreaInputHost {
getPlainTextToCopy(): string;
getHTMLToCopy(): string;
getHTMLToCopy(): string | null;
getScreenReaderContent(currentState: TextAreaState): TextAreaState;
deduceModelPosition(viewAnchorPosition: Position, deltaOffset: number, lineFeedCnt: number): Position;
}
@@ -401,10 +400,10 @@ export class TextAreaInput extends Disposable {
}
const _newSelectionStartPosition = this._textAreaState.deduceEditorPosition(newSelectionStart);
const newSelectionStartPosition = this._host.deduceModelPosition(_newSelectionStartPosition[0], _newSelectionStartPosition[1], _newSelectionStartPosition[2]);
const newSelectionStartPosition = this._host.deduceModelPosition(_newSelectionStartPosition[0]!, _newSelectionStartPosition[1], _newSelectionStartPosition[2]);
const _newSelectionEndPosition = this._textAreaState.deduceEditorPosition(newSelectionEnd);
const newSelectionEndPosition = this._host.deduceModelPosition(_newSelectionEndPosition[0], _newSelectionEndPosition[1], _newSelectionEndPosition[2]);
const newSelectionEndPosition = this._host.deduceModelPosition(_newSelectionEndPosition[0]!, _newSelectionEndPosition[1], _newSelectionEndPosition[2]);
const newSelection = new Selection(
newSelectionStartPosition.lineNumber, newSelectionStartPosition.column,
@@ -480,7 +479,7 @@ export class TextAreaInput extends Disposable {
return;
}
let copyHTML: string = null;
let copyHTML: string | null = null;
if (browser.hasClipboardSupport() && (copyPlainText.length < 65536 || CopyOptions.forceCopyWithSyntaxHighlighting)) {
copyHTML = this._host.getHTMLToCopy();
}
@@ -514,7 +513,7 @@ class ClipboardEventUtils {
throw new Error('ClipboardEventUtils.getTextData: Cannot use text data!');
}
public static setTextData(e: ClipboardEvent, text: string, richText: string): void {
public static setTextData(e: ClipboardEvent, text: string, richText: string | null): void {
if (e.clipboardData) {
e.clipboardData.setData('text/plain', text);
if (richText !== null) {

View File

@@ -2,12 +2,11 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Range } from 'vs/editor/common/core/range';
import { Position } from 'vs/editor/common/core/position';
import { EndOfLinePreference } from 'vs/editor/common/model';
import * as strings from 'vs/base/common/strings';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { EndOfLinePreference } from 'vs/editor/common/model';
export interface ITextAreaWrapper {
getValue(): string;
@@ -36,10 +35,10 @@ export class TextAreaState {
public readonly value: string;
public readonly selectionStart: number;
public readonly selectionEnd: number;
public readonly selectionStartPosition: Position;
public readonly selectionEndPosition: Position;
public readonly selectionStartPosition: Position | null;
public readonly selectionEndPosition: Position | null;
constructor(value: string, selectionStart: number, selectionEnd: number, selectionStartPosition: Position, selectionEndPosition: Position) {
constructor(value: string, selectionStart: number, selectionEnd: number, selectionStartPosition: Position | null, selectionEndPosition: Position | null) {
this.value = value;
this.selectionStart = selectionStart;
this.selectionEnd = selectionEnd;
@@ -67,7 +66,7 @@ export class TextAreaState {
}
}
public deduceEditorPosition(offset: number): [Position, number, number] {
public deduceEditorPosition(offset: number): [Position | null, number, number] {
if (offset <= this.selectionStart) {
const str = this.value.substring(offset, this.selectionStart);
return this._finishDeduceEditorPosition(this.selectionStartPosition, str, -1);
@@ -84,7 +83,7 @@ export class TextAreaState {
return this._finishDeduceEditorPosition(this.selectionEndPosition, str2, -1);
}
private _finishDeduceEditorPosition(anchor: Position, deltaText: string, signum: number): [Position, number, number] {
private _finishDeduceEditorPosition(anchor: Position | null, deltaText: string, signum: number): [Position | null, number, number] {
let lineFeedCnt = 0;
let lastLineFeedIndex = -1;
while ((lastLineFeedIndex = deltaText.indexOf('\n', lastLineFeedIndex + 1)) !== -1) {
@@ -154,7 +153,7 @@ export class TextAreaState {
// the only hints we can use is that the selection is immediately after the inserted emoji
// and that none of the old text has been deleted
let potentialEmojiInput: string = null;
let potentialEmojiInput: string | null = null;
if (currentSelectionStart === currentValue.length) {
// emoji potentially inserted "somewhere" after the previous selection => it should appear at the end of `currentValue`
@@ -248,21 +247,22 @@ export class PagedScreenReaderStrategy {
let selectionEndPage = PagedScreenReaderStrategy._getPageOfLine(selection.endLineNumber);
let selectionEndPageRange = PagedScreenReaderStrategy._getRangeForPage(selectionEndPage);
let pretextRange = selectionStartPageRange.intersectRanges(new Range(1, 1, selection.startLineNumber, selection.startColumn));
let pretextRange = selectionStartPageRange.intersectRanges(new Range(1, 1, selection.startLineNumber, selection.startColumn))!;
let pretext = model.getValueInRange(pretextRange, EndOfLinePreference.LF);
let lastLine = model.getLineCount();
let lastLineMaxColumn = model.getLineMaxColumn(lastLine);
let posttextRange = selectionEndPageRange.intersectRanges(new Range(selection.endLineNumber, selection.endColumn, lastLine, lastLineMaxColumn));
let posttextRange = selectionEndPageRange.intersectRanges(new Range(selection.endLineNumber, selection.endColumn, lastLine, lastLineMaxColumn))!;
let posttext = model.getValueInRange(posttextRange, EndOfLinePreference.LF);
let text: string = null;
let text: string;
if (selectionStartPage === selectionEndPage || selectionStartPage + 1 === selectionEndPage) {
// take full selection
text = model.getValueInRange(selection, EndOfLinePreference.LF);
} else {
let selectionRange1 = selectionStartPageRange.intersectRanges(selection);
let selectionRange2 = selectionEndPageRange.intersectRanges(selection);
let selectionRange1 = selectionStartPageRange.intersectRanges(selection)!;
let selectionRange2 = selectionEndPageRange.intersectRanges(selection)!;
text = (
model.getValueInRange(selectionRange1, EndOfLinePreference.LF)
+ String.fromCharCode(8230)

View File

@@ -2,12 +2,11 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as strings from 'vs/base/common/strings';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
export const enum CodeEditorStateFlag {
Value = 1,
@@ -20,9 +19,9 @@ export class EditorState {
private readonly flags: number;
private readonly position: Position;
private readonly selection: Range;
private readonly modelVersionId: string;
private readonly position: Position | null;
private readonly selection: Range | null;
private readonly modelVersionId: string | null;
private readonly scrollLeft: number;
private readonly scrollTop: number;
@@ -75,7 +74,7 @@ export class EditorState {
export class StableEditorScrollState {
public static capture(editor: ICodeEditor): StableEditorScrollState {
let visiblePosition: Position = null;
let visiblePosition: Position | null = null;
let visiblePositionScrollDelta = 0;
if (editor.getScrollTop() !== 0) {
const visibleRanges = editor.getVisibleRanges();
@@ -89,7 +88,7 @@ export class StableEditorScrollState {
}
constructor(
private readonly _visiblePosition: Position,
private readonly _visiblePosition: Position | null,
private readonly _visiblePositionScrollDelta: number
) {
}

View File

@@ -2,23 +2,22 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { Position, IPosition } from 'vs/editor/common/core/position';
import { Selection } from 'vs/editor/common/core/selection';
import { Range, IRange } from 'vs/editor/common/core/range';
import { IDisposable } from 'vs/base/common/lifecycle';
import * as editorOptions from 'vs/editor/common/config/editorOptions';
import { OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager';
import { IModelContentChangedEvent, IModelLanguageChangedEvent, IModelLanguageConfigurationChangedEvent, IModelOptionsChangedEvent, IModelDecorationsChangedEvent } from 'vs/editor/common/model/textModelEvents';
import { ICursors } from 'vs/editor/common/controller/cursorCommon';
import { ICursorPositionChangedEvent, ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ICursors, CursorConfiguration } from 'vs/editor/common/controller/cursorCommon';
import { IPosition, Position } from 'vs/editor/common/core/position';
import { IRange, Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { IIdentifiedSingleEditOperation, IModelDecoration, IModelDeltaDecoration, ITextModel } 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 { ITextModel, IIdentifiedSingleEditOperation, IModelDecoration, IModelDeltaDecoration } from 'vs/editor/common/model';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
/**
* A view zone is a full horizontal rectangle that 'pushes' text down.
@@ -65,7 +64,7 @@ export interface IViewZone {
/**
* An optional dom node for the view zone that will be placed in the margin area.
*/
marginDomNode?: HTMLElement;
marginDomNode?: HTMLElement | null;
/**
* Callback which gives the relative top of the view zone as it appears (taking scrolling into account).
*/
@@ -100,7 +99,7 @@ export interface IViewZoneChangeAccessor {
/**
* A positioning preference for rendering content widgets.
*/
export enum ContentWidgetPositionPreference {
export const enum ContentWidgetPositionPreference {
/**
* Place the content widget exactly at a position
*/
@@ -122,7 +121,12 @@ export interface IContentWidgetPosition {
* Desired position for the content widget.
* `preference` will also affect the placement.
*/
position: IPosition;
position: IPosition | null;
/**
* Optionally, a range can be provided to further
* define the position of the content widget.
*/
range?: IRange | null;
/**
* Placement preference for position, in order of preference.
*/
@@ -150,13 +154,13 @@ export interface IContentWidget {
* Get the placement of the content widget.
* If null is returned, the content widget will be placed off screen.
*/
getPosition(): IContentWidgetPosition;
getPosition(): IContentWidgetPosition | null;
}
/**
* A positioning preference for rendering overlay widgets.
*/
export enum OverlayWidgetPositionPreference {
export const enum OverlayWidgetPositionPreference {
/**
* Position the overlay widget in the top right corner
*/
@@ -179,7 +183,7 @@ export interface IOverlayWidgetPosition {
/**
* The position preference for the overlay widget.
*/
preference: OverlayWidgetPositionPreference;
preference: OverlayWidgetPositionPreference | null;
}
/**
* An overlay widgets renders on top of the text.
@@ -197,13 +201,13 @@ export interface IOverlayWidget {
* Get the placement of the overlay widget.
* If null is returned, the overlay widget is responsible to place itself.
*/
getPosition(): IOverlayWidgetPosition;
getPosition(): IOverlayWidgetPosition | null;
}
/**
* Type of hit element with the mouse in the editor.
*/
export enum MouseTargetType {
export const enum MouseTargetType {
/**
* Mouse is on top of an unknown element.
*/
@@ -269,7 +273,7 @@ export interface IMouseTarget {
/**
* The target element
*/
readonly element: Element;
readonly element: Element | null;
/**
* The target type
*/
@@ -277,7 +281,7 @@ export interface IMouseTarget {
/**
* The 'approximate' editor position
*/
readonly position: Position;
readonly position: Position | null;
/**
* Desired mouse column (e.g. when position.column gets clamped to text length -- clicking after text on a line).
*/
@@ -285,7 +289,7 @@ export interface IMouseTarget {
/**
* The 'approximate' editor range
*/
readonly range: Range;
readonly range: Range | null;
/**
* Some extra detail.
*/
@@ -298,6 +302,10 @@ export interface IEditorMouseEvent {
readonly event: IMouseEvent;
readonly target: IMouseTarget;
}
export interface IPartialEditorMouseEvent {
readonly event: IMouseEvent;
readonly target: IMouseTarget | null;
}
/**
* An overview ruler
@@ -396,6 +404,14 @@ export interface ICodeEditor extends editorCommon.IEditor {
* @internal
*/
onDidType(listener: (text: string) => void): IDisposable;
/**
* An event emitted after composition has started.
*/
onCompositionStart(listener: () => void): IDisposable;
/**
* An event emitted after composition has ended.
*/
onCompositionEnd(listener: () => void): IDisposable;
/**
* An event emitted when editing failed because the editor is read-only.
* @event
@@ -429,7 +445,7 @@ export interface ICodeEditor extends editorCommon.IEditor {
* @internal
* @event
*/
onMouseDrop(listener: (e: IEditorMouseEvent) => void): IDisposable;
onMouseDrop(listener: (e: IPartialEditorMouseEvent) => void): IDisposable;
/**
* An event emitted on a "contextmenu".
* @event
@@ -444,7 +460,7 @@ export interface ICodeEditor extends editorCommon.IEditor {
* An event emitted on a "mouseleave".
* @event
*/
onMouseLeave(listener: (e: IEditorMouseEvent) => void): IDisposable;
onMouseLeave(listener: (e: IPartialEditorMouseEvent) => void): IDisposable;
/**
* An event emitted on a "keyup".
* @event
@@ -469,7 +485,7 @@ export interface ICodeEditor extends editorCommon.IEditor {
/**
* Saves current view state of the editor in a serializable object.
*/
saveViewState(): editorCommon.ICodeEditorViewState;
saveViewState(): editorCommon.ICodeEditorViewState | null;
/**
* Restores the view state of the editor from a serializable object generated by `saveViewState`.
@@ -497,7 +513,17 @@ export interface ICodeEditor extends editorCommon.IEditor {
/**
* Type the getModel() of IEditor.
*/
getModel(): ITextModel;
getModel(): ITextModel | null;
/**
* Sets the current model attached to this editor.
* If the previous model was created by the editor via the value key in the options
* literal object, it will be destroyed. Otherwise, if the previous model was set
* via setModel, or the model key in the options literal object, the previous model
* will not be destroyed.
* It is safe to call setModel(null) to simply detach the current model from the editor.
*/
setModel(model: ITextModel | null): void;
/**
* Returns the current editor's configuration
@@ -583,26 +609,21 @@ export interface ICodeEditor extends editorCommon.IEditor {
executeEdits(source: string, edits: IIdentifiedSingleEditOperation[], endCursorState?: Selection[]): boolean;
/**
* Execute multiple (concommitent) commands on the editor.
* Execute multiple (concomitant) commands on the editor.
* @param source The source of the call.
* @param command The commands to execute
*/
executeCommands(source: string, commands: editorCommon.ICommand[]): void;
executeCommands(source: string, commands: (editorCommon.ICommand | null)[]): void;
/**
* @internal
*/
_getCursors(): ICursors;
/**
* @internal
*/
_getCursorConfiguration(): CursorConfiguration;
_getCursors(): ICursors | null;
/**
* Get all the decorations on a line (filtering out decorations from other editors).
*/
getLineDecorations(lineNumber: number): IModelDecoration[];
getLineDecorations(lineNumber: number): IModelDecoration[] | null;
/**
* All decorations added through this call will get the ownerId of this editor.
@@ -661,12 +682,12 @@ export interface ICodeEditor extends editorCommon.IEditor {
/**
* @internal
*/
getTelemetryData(): { [key: string]: any; };
getTelemetryData(): { [key: string]: any; } | null;
/**
* Returns the editor's dom node
*/
getDomNode(): HTMLElement;
getDomNode(): HTMLElement | null;
/**
* Add a content widget. Widgets must have unique ids, otherwise they will be overwritten.
@@ -674,7 +695,7 @@ export interface ICodeEditor extends editorCommon.IEditor {
addContentWidget(widget: IContentWidget): void;
/**
* Layout/Reposition a content widget. This is a ping to the editor to call widget.getPosition()
* and update appropiately.
* and update appropriately.
*/
layoutContentWidget(widget: IContentWidget): void;
/**
@@ -688,7 +709,7 @@ export interface ICodeEditor extends editorCommon.IEditor {
addOverlayWidget(widget: IOverlayWidget): void;
/**
* Layout/Reposition an overlay widget. This is a ping to the editor to call widget.getPosition()
* and update appropiately.
* and update appropriately.
*/
layoutOverlayWidget(widget: IOverlayWidget): void;
/**
@@ -719,21 +740,81 @@ export interface ICodeEditor extends editorCommon.IEditor {
*
* @returns Hit test target or null if the coordinates fall outside the editor or the editor has no model.
*/
getTargetAtClientPoint(clientX: number, clientY: number): IMouseTarget;
getTargetAtClientPoint(clientX: number, clientY: number): IMouseTarget | null;
/**
* Get the visible position for `position`.
* The result position takes scrolling into account and is relative to the top left corner of the editor.
* Explanation 1: the results of this method will change for the same `position` if the user scrolls the editor.
* Explanation 2: the results of this method will not change if the container of the editor gets repositioned.
* Warning: the results of this method are innacurate for positions that are outside the current editor viewport.
* Warning: the results of this method are inaccurate for positions that are outside the current editor viewport.
*/
getScrolledVisiblePosition(position: IPosition): { top: number; left: number; height: number; };
getScrolledVisiblePosition(position: IPosition): { top: number; left: number; height: number; } | null;
/**
* Apply the same font settings as the editor to `target`.
*/
applyFontInfo(target: HTMLElement): void;
/**
* Check if the current instance has a model attached.
* @internal
*/
hasModel(): this is IActiveCodeEditor;
}
/**
* @internal
*/
export interface IActiveCodeEditor extends ICodeEditor {
/**
* Returns the primary position of the cursor.
*/
getPosition(): Position;
/**
* Returns the primary selection of the editor.
*/
getSelection(): Selection;
/**
* Returns all the selections of the editor.
*/
getSelections(): Selection[];
/**
* Saves current view state of the editor in a serializable object.
*/
saveViewState(): editorCommon.ICodeEditorViewState;
/**
* Type the getModel() of IEditor.
*/
getModel(): ITextModel;
/**
* @internal
*/
_getCursors(): ICursors;
/**
* Get all the decorations on a line (filtering out decorations from other editors).
*/
getLineDecorations(lineNumber: number): IModelDecoration[];
/**
* Returns the editor's dom node
*/
getDomNode(): HTMLElement;
/**
* Get the visible position for `position`.
* The result position takes scrolling into account and is relative to the top left corner of the editor.
* Explanation 1: the results of this method will change for the same `position` if the user scrolls the editor.
* Explanation 2: the results of this method will not change if the container of the editor gets repositioned.
* Warning: the results of this method are inaccurate for positions that are outside the current editor viewport.
*/
getScrolledVisiblePosition(position: IPosition): { top: number; left: number; height: number; };
}
/**
@@ -778,7 +859,7 @@ export interface IDiffEditor extends editorCommon.IEditor {
/**
* Saves current view state of the editor in a serializable object.
*/
saveViewState(): editorCommon.IDiffEditorViewState;
saveViewState(): editorCommon.IDiffEditorViewState | null;
/**
* Restores the view state of the editor from a serializable object generated by `saveViewState`.
@@ -788,7 +869,17 @@ export interface IDiffEditor extends editorCommon.IEditor {
/**
* Type the getModel() of IEditor.
*/
getModel(): editorCommon.IDiffEditorModel;
getModel(): editorCommon.IDiffEditorModel | null;
/**
* Sets the current model attached to this editor.
* If the previous model was created by the editor via the value key in the options
* literal object, it will be destroyed. Otherwise, if the previous model was set
* via setModel, or the model key in the options literal object, the previous model
* will not be destroyed.
* It is safe to call setModel(null) to simply detach the current model from the editor.
*/
setModel(model: editorCommon.IDiffEditorModel | null): void;
/**
* Get the `original` editor.
@@ -803,19 +894,19 @@ export interface IDiffEditor extends editorCommon.IEditor {
/**
* Get the computed diff information.
*/
getLineChanges(): editorCommon.ILineChange[];
getLineChanges(): editorCommon.ILineChange[] | null;
/**
* Get information based on computed diff about a line number from the original model.
* If the diff computation is not finished or the model is missing, will return null.
*/
getDiffLineInformationForOriginal(lineNumber: number): IDiffLineInformation;
getDiffLineInformationForOriginal(lineNumber: number): IDiffLineInformation | null;
/**
* Get information based on computed diff about a line number from the modified model.
* If the diff computation is not finished or the model is missing, will return null.
*/
getDiffLineInformationForModified(lineNumber: number): IDiffLineInformation;
getDiffLineInformationForModified(lineNumber: number): IDiffLineInformation | null;
}
/**
@@ -843,7 +934,7 @@ export function isDiffEditor(thing: any): thing is IDiffEditor {
/**
*@internal
*/
export function getCodeEditor(thing: any): ICodeEditor {
export function getCodeEditor(thing: any): ICodeEditor | null {
if (isCodeEditor(thing)) {
return thing;
}

View File

@@ -2,12 +2,11 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import * as dom from 'vs/base/browser/dom';
import { GlobalMouseMoveMonitor } from 'vs/base/browser/globalMouseMoveMonitor';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
/**
* Coordinates relative to the whole document (e.g. mouse event's pageX and pageY)
@@ -136,7 +135,7 @@ export class GlobalEditorMouseMoveMonitor extends Disposable {
private _editorViewDomNode: HTMLElement;
private _globalMouseMoveMonitor: GlobalMouseMoveMonitor<EditorMouseEvent>;
private _keydownListener: IDisposable;
private _keydownListener: IDisposable | null;
constructor(editorViewDomNode: HTMLElement) {
super();
@@ -163,7 +162,7 @@ export class GlobalEditorMouseMoveMonitor extends Disposable {
};
this._globalMouseMoveMonitor.startMonitoring(myMerger, mouseMoveCallback, () => {
this._keydownListener.dispose();
this._keydownListener!.dispose();
onStopCallback();
});
}

View File

@@ -2,33 +2,33 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IPosition } from 'vs/base/browser/ui/contextview/contextview';
import { always } from 'vs/base/common/async';
import { illegalArgument } from 'vs/base/common/errors';
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { ServicesAccessor, IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation';
import { URI } from 'vs/base/common/uri';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { Position } from 'vs/editor/common/core/position';
import { IEditorContribution } from 'vs/editor/common/editorCommon';
import { ITextModel } from 'vs/editor/common/model';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
import { CommandsRegistry, ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { KeybindingsRegistry, IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IConstructorSignature1, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindings, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Position } from 'vs/editor/common/core/position';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { IModelService } from 'vs/editor/common/services/modelService';
import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
import { IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ITextModel } from 'vs/editor/common/model';
import { IPosition } from 'vs/base/browser/ui/contextview/contextview';
export type ServicesAccessor = ServicesAccessor;
export type IEditorContributionCtor = IConstructorSignature1<ICodeEditor, editorCommon.IEditorContribution>;
export type IEditorContributionCtor = IConstructorSignature1<ICodeEditor, IEditorContribution>;
//#region Command
export interface ICommandKeybindingsOptions extends IKeybindings {
kbExpr?: ContextKeyExpr;
kbExpr?: ContextKeyExpr | null;
weight: number;
}
export interface ICommandMenubarOptions {
@@ -40,17 +40,17 @@ export interface ICommandMenubarOptions {
}
export interface ICommandOptions {
id: string;
precondition: ContextKeyExpr;
kbOpts?: ICommandKeybindingsOptions;
precondition: ContextKeyExpr | null;
kbOpts?: ICommandKeybindingsOptions | null;
description?: ICommandHandlerDescription;
menubarOpts?: ICommandMenubarOptions;
}
export abstract class Command {
public readonly id: string;
public readonly precondition: ContextKeyExpr;
private readonly _kbOpts: ICommandKeybindingsOptions;
private readonly _menubarOpts: ICommandMenubarOptions;
private readonly _description: ICommandHandlerDescription;
public readonly precondition: ContextKeyExpr | null;
private readonly _kbOpts: ICommandKeybindingsOptions | null | undefined;
private readonly _menubarOpts: ICommandMenubarOptions | null | undefined;
private readonly _description: ICommandHandlerDescription | null | undefined;
constructor(opts: ICommandOptions) {
this.id = opts.id;
@@ -89,7 +89,7 @@ export abstract class Command {
id: this.id,
handler: (accessor, args) => this.runCommand(accessor, args),
weight: this._kbOpts.weight,
when: kbWhen,
when: kbWhen || null,
primary: this._kbOpts.primary,
secondary: this._kbOpts.secondary,
win: this._kbOpts.win,
@@ -108,7 +108,7 @@ export abstract class Command {
}
}
public abstract runCommand(accessor: ServicesAccessor, args: any): void | TPromise<void>;
public abstract runCommand(accessor: ServicesAccessor, args: any): void | Thenable<void>;
}
//#endregion Command
@@ -118,7 +118,7 @@ export abstract class Command {
export interface IContributionCommandOptions<T> extends ICommandOptions {
handler: (controller: T) => void;
}
export interface EditorControllerCommand<T extends editorCommon.IEditorContribution> {
export interface EditorControllerCommand<T extends IEditorContribution> {
new(opts: IContributionCommandOptions<T>): EditorCommand;
}
export abstract class EditorCommand extends Command {
@@ -126,7 +126,7 @@ export abstract class EditorCommand extends Command {
/**
* Create a command class that is bound to a certain editor contribution.
*/
public static bindToContribution<T extends editorCommon.IEditorContribution>(controllerGetter: (editor: ICodeEditor) => T): EditorControllerCommand<T> {
public static bindToContribution<T extends IEditorContribution>(controllerGetter: (editor: ICodeEditor) => T): EditorControllerCommand<T> {
return class EditorControllerCommandImpl extends EditorCommand {
private _callback: (controller: T) => void;
@@ -145,7 +145,7 @@ export abstract class EditorCommand extends Command {
};
}
public runCommand(accessor: ServicesAccessor, args: any): void | TPromise<void> {
public runCommand(accessor: ServicesAccessor, args: any): void | Thenable<void> {
const codeEditorService = accessor.get(ICodeEditorService);
// Find the editor with text focus or active
@@ -162,11 +162,11 @@ export abstract class EditorCommand extends Command {
return;
}
return this.runEditorCommand(editorAccessor, editor, args);
return this.runEditorCommand(editorAccessor, editor!, args);
});
}
public abstract runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | TPromise<void>;
public abstract runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Thenable<void>;
}
//#endregion EditorCommand
@@ -187,7 +187,7 @@ export abstract class EditorAction extends EditorCommand {
public label: string;
public alias: string;
private menuOpts: IEditorCommandMenuOptions;
private menuOpts: IEditorCommandMenuOptions | undefined;
constructor(opts: IActionOptions) {
super(opts);
@@ -213,7 +213,7 @@ export abstract class EditorAction extends EditorCommand {
super.register();
}
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | TPromise<void> {
public runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Thenable<void> {
this.reportTelemetry(accessor, editor);
return this.run(accessor, editor, args || {});
}
@@ -231,7 +231,7 @@ export abstract class EditorAction extends EditorCommand {
accessor.get(ITelemetryService).publicLog('editorActionInvoked', { name: this.label, id: this.id, ...editor.getTelemetryData() });
}
public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | TPromise<void>;
public abstract run(accessor: ServicesAccessor, editor: ICodeEditor, args: any): void | Thenable<void>;
}
//#endregion EditorAction
@@ -260,13 +260,23 @@ export function registerDefaultLanguageCommand(id: string, handler: (model: ITex
}
const model = accessor.get(IModelService).getModel(resource);
if (!model) {
throw illegalArgument('Can not find open model for ' + resource);
if (model) {
const editorPosition = Position.lift(position);
return handler(model, editorPosition, args);
}
const editorPosition = Position.lift(position);
return handler(model, editorPosition, args);
return accessor.get(ITextModelService).createModelReference(resource).then(reference => {
return always(new Promise((resolve, reject) => {
try {
let result = handler(reference.object.textEditorModel, Position.lift(position), args);
resolve(result);
} catch (err) {
reject(err);
}
}), () => {
reference.dispose();
});
});
});
}

View File

@@ -2,35 +2,42 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Event, Emitter } from 'vs/base/common/event';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { IDecorationRenderOptions } from 'vs/editor/common/editorCommon';
import { IModelDecorationOptions, ITextModel } from 'vs/editor/common/model';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { IResourceInput } from 'vs/platform/editor/common/editor';
import { TPromise } from 'vs/base/common/winjs.base';
export abstract class AbstractCodeEditorService implements ICodeEditorService {
export abstract class AbstractCodeEditorService extends Disposable implements ICodeEditorService {
_serviceBrand: any;
private readonly _onCodeEditorAdd: Emitter<ICodeEditor>;
private readonly _onCodeEditorRemove: Emitter<ICodeEditor>;
private _codeEditors: { [editorId: string]: ICodeEditor; };
private readonly _onCodeEditorAdd: Emitter<ICodeEditor> = this._register(new Emitter<ICodeEditor>());
public readonly onCodeEditorAdd: Event<ICodeEditor> = this._onCodeEditorAdd.event;
private readonly _onDiffEditorAdd: Emitter<IDiffEditor>;
private readonly _onDiffEditorRemove: Emitter<IDiffEditor>;
private readonly _onCodeEditorRemove: Emitter<ICodeEditor> = this._register(new Emitter<ICodeEditor>());
public readonly onCodeEditorRemove: Event<ICodeEditor> = this._onCodeEditorRemove.event;
private readonly _onDiffEditorAdd: Emitter<IDiffEditor> = this._register(new Emitter<IDiffEditor>());
public readonly onDiffEditorAdd: Event<IDiffEditor> = this._onDiffEditorAdd.event;
private readonly _onDiffEditorRemove: Emitter<IDiffEditor> = this._register(new Emitter<IDiffEditor>());
public readonly onDiffEditorRemove: Event<IDiffEditor> = this._onDiffEditorRemove.event;
private readonly _onDidChangeTransientModelProperty: Emitter<ITextModel> = this._register(new Emitter<ITextModel>());
public readonly onDidChangeTransientModelProperty: Event<ITextModel> = this._onDidChangeTransientModelProperty.event;
private _codeEditors: { [editorId: string]: ICodeEditor; };
private _diffEditors: { [editorId: string]: IDiffEditor; };
constructor() {
super();
this._codeEditors = Object.create(null);
this._diffEditors = Object.create(null);
this._onCodeEditorAdd = new Emitter<ICodeEditor>();
this._onCodeEditorRemove = new Emitter<ICodeEditor>();
this._onDiffEditorAdd = new Emitter<IDiffEditor>();
this._onDiffEditorRemove = new Emitter<IDiffEditor>();
}
addCodeEditor(editor: ICodeEditor): void {
@@ -38,20 +45,12 @@ export abstract class AbstractCodeEditorService implements ICodeEditorService {
this._onCodeEditorAdd.fire(editor);
}
get onCodeEditorAdd(): Event<ICodeEditor> {
return this._onCodeEditorAdd.event;
}
removeCodeEditor(editor: ICodeEditor): void {
if (delete this._codeEditors[editor.getId()]) {
this._onCodeEditorRemove.fire(editor);
}
}
get onCodeEditorRemove(): Event<ICodeEditor> {
return this._onCodeEditorRemove.event;
}
listCodeEditors(): ICodeEditor[] {
return Object.keys(this._codeEditors).map(id => this._codeEditors[id]);
}
@@ -61,26 +60,18 @@ export abstract class AbstractCodeEditorService implements ICodeEditorService {
this._onDiffEditorAdd.fire(editor);
}
get onDiffEditorAdd(): Event<IDiffEditor> {
return this._onDiffEditorAdd.event;
}
removeDiffEditor(editor: IDiffEditor): void {
if (delete this._diffEditors[editor.getId()]) {
this._onDiffEditorRemove.fire(editor);
}
}
get onDiffEditorRemove(): Event<IDiffEditor> {
return this._onDiffEditorRemove.event;
}
listDiffEditors(): IDiffEditor[] {
return Object.keys(this._diffEditors).map(id => this._diffEditors[id]);
}
getFocusedCodeEditor(): ICodeEditor {
let editorWithWidgetFocus: ICodeEditor = null;
getFocusedCodeEditor(): ICodeEditor | null {
let editorWithWidgetFocus: ICodeEditor | null = null;
let editors = this.listCodeEditors();
for (let i = 0; i < editors.length; i++) {
@@ -101,7 +92,7 @@ export abstract class AbstractCodeEditorService implements ICodeEditorService {
abstract registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string): void;
abstract removeDecorationType(key: string): void;
abstract resolveDecorationOptions(decorationTypeKey: string, writable: boolean): IModelDecorationOptions;
abstract resolveDecorationOptions(decorationTypeKey: string | undefined, writable: boolean): IModelDecorationOptions;
private _transientWatchers: { [uri: string]: ModelTransientSettingWatcher; } = {};
@@ -117,6 +108,7 @@ export abstract class AbstractCodeEditorService implements ICodeEditorService {
}
w.set(key, value);
this._onDidChangeTransientModelProperty.fire(model);
}
public getTransientModelProperty(model: ITextModel, key: string): any {
@@ -133,8 +125,8 @@ export abstract class AbstractCodeEditorService implements ICodeEditorService {
delete this._transientWatchers[w.uri];
}
abstract getActiveCodeEditor(): ICodeEditor;
abstract openCodeEditor(input: IResourceInput, source: ICodeEditor, sideBySide?: boolean): TPromise<ICodeEditor>;
abstract getActiveCodeEditor(): ICodeEditor | null;
abstract openCodeEditor(input: IResourceInput, source: ICodeEditor | null, sideBySide?: boolean): Thenable<ICodeEditor | null>;
}
export class ModelTransientSettingWatcher {

View File

@@ -2,12 +2,10 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { WorkspaceEdit } from 'vs/editor/common/modes';
import { TPromise } from 'vs/base/common/winjs.base';
import { ICodeEditor } from '../editorBrowser';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IProgressRunner } from 'vs/platform/progress/common/progress';
export const IBulkEditService = createDecorator<IBulkEditService>('IWorkspaceEditService');
@@ -25,6 +23,6 @@ export interface IBulkEditResult {
export interface IBulkEditService {
_serviceBrand: any;
apply(edit: WorkspaceEdit, options: IBulkEditOptions): TPromise<IBulkEditResult>;
apply(edit: WorkspaceEdit, options: IBulkEditOptions): Promise<IBulkEditResult>;
}

View File

@@ -2,26 +2,27 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Event } from 'vs/base/common/event';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { IDecorationRenderOptions } from 'vs/editor/common/editorCommon';
import { IModelDecorationOptions, ITextModel } from 'vs/editor/common/model';
import { ICodeEditor, IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { IResourceInput } from 'vs/platform/editor/common/editor';
import { TPromise } from 'vs/base/common/winjs.base';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const ICodeEditorService = createDecorator<ICodeEditorService>('codeEditorService');
export interface ICodeEditorService {
_serviceBrand: any;
onCodeEditorAdd: Event<ICodeEditor>;
onCodeEditorRemove: Event<ICodeEditor>;
readonly onCodeEditorAdd: Event<ICodeEditor>;
readonly onCodeEditorRemove: Event<ICodeEditor>;
readonly onDiffEditorAdd: Event<IDiffEditor>;
readonly onDiffEditorRemove: Event<IDiffEditor>;
readonly onDidChangeTransientModelProperty: Event<ITextModel>;
onDiffEditorAdd: Event<IDiffEditor>;
onDiffEditorRemove: Event<IDiffEditor>;
addCodeEditor(editor: ICodeEditor): void;
removeCodeEditor(editor: ICodeEditor): void;
@@ -34,7 +35,7 @@ export interface ICodeEditorService {
/**
* Returns the current focused code editor (if the focus is in the editor or in an editor widget) or null.
*/
getFocusedCodeEditor(): ICodeEditor;
getFocusedCodeEditor(): ICodeEditor | null;
registerDecorationType(key: string, options: IDecorationRenderOptions, parentTypeKey?: string): void;
removeDecorationType(key: string): void;
@@ -43,6 +44,6 @@ export interface ICodeEditorService {
setTransientModelProperty(model: ITextModel, key: string, value: any): void;
getTransientModelProperty(model: ITextModel, key: string): any;
getActiveCodeEditor(): ICodeEditor;
openCodeEditor(input: IResourceInput, source: ICodeEditor, sideBySide?: boolean): TPromise<ICodeEditor>;
getActiveCodeEditor(): ICodeEditor | null;
openCodeEditor(input: IResourceInput, source: ICodeEditor | null, sideBySide?: boolean): Thenable<ICodeEditor | null>;
}

View File

@@ -2,19 +2,17 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as strings from 'vs/base/common/strings';
import URI from 'vs/base/common/uri';
import * as dom from 'vs/base/browser/dom';
import { IDecorationRenderOptions, IThemeDecorationRenderOptions, IContentDecorationRenderOptions, isThemeColor } from 'vs/editor/common/editorCommon';
import { IModelDecorationOptions, IModelDecorationOverviewRulerOptions, OverviewRulerLane, TrackedRangeStickiness } from 'vs/editor/common/model';
import { AbstractCodeEditorService } from 'vs/editor/browser/services/abstractCodeEditorService';
import { IDisposable, dispose as disposeAll } from 'vs/base/common/lifecycle';
import { IThemeService, ITheme, ThemeColor } from 'vs/platform/theme/common/themeService';
import { IResourceInput } from 'vs/platform/editor/common/editor';
import { TPromise } from 'vs/base/common/winjs.base';
import * as strings from 'vs/base/common/strings';
import { URI } from 'vs/base/common/uri';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { AbstractCodeEditorService } from 'vs/editor/browser/services/abstractCodeEditorService';
import { IContentDecorationRenderOptions, IDecorationRenderOptions, IThemeDecorationRenderOptions, isThemeColor } from 'vs/editor/common/editorCommon';
import { IModelDecorationOptions, IModelDecorationOverviewRulerOptions, OverviewRulerLane, TrackedRangeStickiness } from 'vs/editor/common/model';
import { IResourceInput } from 'vs/platform/editor/common/editor';
import { ITheme, IThemeService, ThemeColor } from 'vs/platform/theme/common/themeService';
export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService {
@@ -68,8 +66,8 @@ export abstract class CodeEditorServiceImpl extends AbstractCodeEditorService {
return provider.getOptions(this, writable);
}
abstract getActiveCodeEditor(): ICodeEditor;
abstract openCodeEditor(input: IResourceInput, source: ICodeEditor, sideBySide?: boolean): TPromise<ICodeEditor>;
abstract getActiveCodeEditor(): ICodeEditor | null;
abstract openCodeEditor(input: IResourceInput, source: ICodeEditor | null, sideBySide?: boolean): Thenable<ICodeEditor | null>;
}
interface IModelDecorationOptionsProvider extends IDisposable {
@@ -81,9 +79,9 @@ class DecorationSubTypeOptionsProvider implements IModelDecorationOptionsProvide
public refCount: number;
private _parentTypeKey: string;
private _beforeContentRules: DecorationCSSRules;
private _afterContentRules: DecorationCSSRules;
private _parentTypeKey: string | undefined;
private _beforeContentRules: DecorationCSSRules | null;
private _afterContentRules: DecorationCSSRules | null;
constructor(themeService: IThemeService, providerArgs: ProviderArguments) {
this._parentTypeKey = providerArgs.parentTypeKey;
@@ -129,32 +127,32 @@ class DecorationTypeOptionsProvider implements IModelDecorationOptionsProvider {
private _disposables: IDisposable[];
public refCount: number;
public className: string;
public className: string | undefined;
public inlineClassName: string;
public inlineClassNameAffectsLetterSpacing: boolean;
public beforeContentClassName: string;
public afterContentClassName: string;
public glyphMarginClassName: string;
public beforeContentClassName: string | undefined;
public afterContentClassName: string | undefined;
public glyphMarginClassName: string | undefined;
public isWholeLine: boolean;
public overviewRuler: IModelDecorationOverviewRulerOptions;
public stickiness: TrackedRangeStickiness;
public stickiness: TrackedRangeStickiness | undefined;
constructor(themeService: IThemeService, providerArgs: ProviderArguments) {
this.refCount = 0;
this._disposables = [];
let createCSSRules = (type: ModelDecorationCSSRuleType) => {
let rules = new DecorationCSSRules(type, providerArgs, themeService);
const createCSSRules = (type: ModelDecorationCSSRuleType) => {
const rules = new DecorationCSSRules(type, providerArgs, themeService);
this._disposables.push(rules);
if (rules.hasContent) {
this._disposables.push(rules);
return rules.className;
}
return void 0;
};
let createInlineCSSRules = (type: ModelDecorationCSSRuleType) => {
let rules = new DecorationCSSRules(type, providerArgs, themeService);
const createInlineCSSRules = (type: ModelDecorationCSSRuleType) => {
const rules = new DecorationCSSRules(type, providerArgs, themeService);
this._disposables.push(rules);
if (rules.hasContent) {
this._disposables.push(rules);
return { className: rules.className, hasLetterSpacing: rules.hasLetterSpacing };
}
return null;
@@ -252,7 +250,7 @@ class DecorationCSSRules {
private _hasContent: boolean;
private _hasLetterSpacing: boolean;
private _ruleType: ModelDecorationCSSRuleType;
private _themeListener: IDisposable;
private _themeListener: IDisposable | null;
private _providerArgs: ProviderArguments;
private _usesThemeColors: boolean;
@@ -280,6 +278,8 @@ class DecorationCSSRules {
this._removeCSS();
this._buildCSS();
});
} else {
this._themeListener = null;
}
}
@@ -363,7 +363,7 @@ class DecorationCSSRules {
/**
* Build the CSS for decorations styled via `className`.
*/
private getCSSTextForModelDecorationClassName(opts: IThemeDecorationRenderOptions): string {
private getCSSTextForModelDecorationClassName(opts: IThemeDecorationRenderOptions | undefined): string {
if (!opts) {
return '';
}
@@ -377,7 +377,7 @@ class DecorationCSSRules {
/**
* Build the CSS for decorations styled via `inlineClassName`.
*/
private getCSSTextForModelDecorationInlineClassName(opts: IThemeDecorationRenderOptions): string {
private getCSSTextForModelDecorationInlineClassName(opts: IThemeDecorationRenderOptions | undefined): string {
if (!opts) {
return '';
}
@@ -392,7 +392,7 @@ class DecorationCSSRules {
/**
* Build the CSS for decorations styled before or after content.
*/
private getCSSTextForModelDecorationContentClassName(opts: IContentDecorationRenderOptions): string {
private getCSSTextForModelDecorationContentClassName(opts: IContentDecorationRenderOptions | undefined): string {
if (!opts) {
return '';
}
@@ -401,14 +401,10 @@ class DecorationCSSRules {
if (typeof opts !== 'undefined') {
this.collectBorderSettingsCSSText(opts, cssTextArr);
if (typeof opts.contentIconPath !== 'undefined') {
if (typeof opts.contentIconPath === 'string') {
cssTextArr.push(strings.format(_CSS_MAP.contentIconPath, URI.file(opts.contentIconPath).toString().replace(/'/g, '%27')));
} else {
cssTextArr.push(strings.format(_CSS_MAP.contentIconPath, URI.revive(opts.contentIconPath).toString(true).replace(/'/g, '%27')));
}
cssTextArr.push(strings.format(_CSS_MAP.contentIconPath, URI.revive(opts.contentIconPath).toString(true).replace(/'/g, '%27')));
}
if (typeof opts.contentText === 'string') {
const truncated = opts.contentText.match(/^.*$/m)[0]; // only take first line
const truncated = opts.contentText.match(/^.*$/m)![0]; // only take first line
const escaped = truncated.replace(/['\\]/g, '\\$&');
cssTextArr.push(strings.format(_CSS_MAP.contentText, escaped));
@@ -425,18 +421,14 @@ class DecorationCSSRules {
/**
* Build the CSS for decorations styled via `glpyhMarginClassName`.
*/
private getCSSTextForModelDecorationGlyphMarginClassName(opts: IThemeDecorationRenderOptions): string {
private getCSSTextForModelDecorationGlyphMarginClassName(opts: IThemeDecorationRenderOptions | undefined): string {
if (!opts) {
return '';
}
let cssTextArr = [];
let cssTextArr: string[] = [];
if (typeof opts.gutterIconPath !== 'undefined') {
if (typeof opts.gutterIconPath === 'string') {
cssTextArr.push(strings.format(_CSS_MAP.gutterIconPath, URI.file(opts.gutterIconPath).toString()));
} else {
cssTextArr.push(strings.format(_CSS_MAP.gutterIconPath, URI.revive(opts.gutterIconPath).toString(true).replace(/'/g, '%27')));
}
cssTextArr.push(strings.format(_CSS_MAP.gutterIconPath, URI.revive(opts.gutterIconPath).toString(true).replace(/'/g, '%27')));
if (typeof opts.gutterIconSize !== 'undefined') {
cssTextArr.push(strings.format(_CSS_MAP.gutterIconSize, opts.gutterIconSize));
}
@@ -491,7 +483,7 @@ class CSSNameHelper {
return 'ced-' + key + '-' + type;
}
public static getSelector(key: string, parentKey: string, ruleType: ModelDecorationCSSRuleType): string {
public static getSelector(key: string, parentKey: string | undefined, ruleType: ModelDecorationCSSRuleType): string {
let selector = '.monaco-editor .' + this.getClassName(key, ruleType);
if (parentKey) {
selector = selector + '.' + this.getClassName(parentKey, ruleType);

View File

@@ -2,19 +2,17 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import URI from 'vs/base/common/uri';
import * as dom from 'vs/base/browser/dom';
import { parse } from 'vs/base/common/marshalling';
import { Schemas } from 'vs/base/common/network';
import { TPromise } from 'vs/base/common/winjs.base';
import * as resources from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { normalize } from 'vs/base/common/paths';
import { ICommandService, CommandsRegistry } from 'vs/platform/commands/common/commands';
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
import { optional } from 'vs/platform/instantiation/common/instantiation';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { optional } from 'vs/platform/instantiation/common/instantiation';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
export class OpenerService implements IOpenerService {
@@ -24,22 +22,24 @@ export class OpenerService implements IOpenerService {
constructor(
@ICodeEditorService private readonly _editorService: ICodeEditorService,
@ICommandService private readonly _commandService: ICommandService,
@optional(ITelemetryService) private _telemetryService: ITelemetryService = NullTelemetryService
@optional(ITelemetryService) private _telemetryService: ITelemetryService | null = NullTelemetryService
) {
//
}
open(resource: URI, options?: { openToSide?: boolean }): TPromise<any> {
open(resource: URI, options?: { openToSide?: boolean }): Promise<any> {
/* __GDPR__
"openerService" : {
"scheme" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this._telemetryService.publicLog('openerService', { scheme: resource.scheme });
if (this._telemetryService) {
/* __GDPR__
"openerService" : {
"scheme" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this._telemetryService.publicLog('openerService', { scheme: resource.scheme });
}
const { scheme, path, query, fragment } = resource;
let promise: TPromise<any> = TPromise.wrap(void 0);
let promise: Thenable<any> | undefined = undefined;
if (scheme === Schemas.http || scheme === Schemas.https || scheme === Schemas.mailto) {
// open http or default mail application
@@ -61,7 +61,7 @@ export class OpenerService implements IOpenerService {
let selection: {
startLineNumber: number;
startColumn: number;
};
} | undefined = undefined;
const match = /^L?(\d+)(?:,(\d+))?/.exec(fragment);
if (match) {
// support file:///some/file.js#73,84
@@ -76,14 +76,14 @@ export class OpenerService implements IOpenerService {
if (!resource.scheme) {
// we cannot handle those
return TPromise.as(undefined);
return Promise.resolve(undefined);
} else if (resource.scheme === Schemas.file) {
resource = resource.with({ path: normalize(resource.path) }); // workaround for non-normalized paths (https://github.com/Microsoft/vscode/issues/12954)
resource = resources.normalizePath(resource); // workaround for non-normalized paths (https://github.com/Microsoft/vscode/issues/12954)
}
promise = this._editorService.openCodeEditor({ resource, options: { selection, } }, this._editorService.getFocusedCodeEditor(), options && options.openToSide);
}
return promise;
return Promise.resolve(promise);
}
}

View File

@@ -3,10 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
export abstract class DynamicViewOverlay extends ViewEventHandler {

View File

@@ -2,20 +2,15 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { CoreEditorCommand, CoreNavigationCommands } from 'vs/editor/browser/controller/coreCommands';
import { IEditorMouseEvent, IPartialEditorMouseEvent } from 'vs/editor/browser/editorBrowser';
import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents';
import { Position } from 'vs/editor/common/core/position';
import { Selection } from 'vs/editor/common/core/selection';
import { IEditorMouseEvent } from 'vs/editor/browser/editorBrowser';
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents';
import { CoreNavigationCommands, CoreEditorCommand } from 'vs/editor/browser/controller/coreCommands';
import { IConfiguration } from 'vs/editor/common/editorCommon';
export interface ExecCoreEditorCommandFunc {
(editorCommand: CoreEditorCommand, args: any): void;
}
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
export interface IMouseDispatchData {
position: Position;
@@ -37,7 +32,9 @@ export interface IMouseDispatchData {
}
export interface ICommandDelegate {
paste(source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[]): void;
executeEditorCommand(editorCommand: CoreEditorCommand, args: any): void;
paste(source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[] | null): void;
type(source: string, text: string): void;
replacePreviousChar(source: string, text: string, replaceCharCnt: number): void;
compositionStart(source: string): void;
@@ -49,30 +46,27 @@ export class ViewController {
private readonly configuration: IConfiguration;
private readonly viewModel: IViewModel;
private readonly _execCoreEditorCommandFunc: ExecCoreEditorCommandFunc;
private readonly outgoingEvents: ViewOutgoingEvents;
private readonly commandDelegate: ICommandDelegate;
constructor(
configuration: IConfiguration,
viewModel: IViewModel,
execCommandFunc: ExecCoreEditorCommandFunc,
outgoingEvents: ViewOutgoingEvents,
commandDelegate: ICommandDelegate
) {
this.configuration = configuration;
this.viewModel = viewModel;
this._execCoreEditorCommandFunc = execCommandFunc;
this.outgoingEvents = outgoingEvents;
this.commandDelegate = commandDelegate;
}
private _execMouseCommand(editorCommand: CoreEditorCommand, args: any): void {
args.source = 'mouse';
this._execCoreEditorCommandFunc(editorCommand, args);
this.commandDelegate.executeEditorCommand(editorCommand, args);
}
public paste(source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[]): void {
public paste(source: string, text: string, pasteOnNewLine: boolean, multicursorText: string[] | null): void {
this.commandDelegate.paste(source, text, pasteOnNewLine, multicursorText);
}
@@ -97,7 +91,7 @@ export class ViewController {
}
public setSelection(source: string, modelSelection: Selection): void {
this._execCoreEditorCommandFunc(CoreNavigationCommands.SetSelection, {
this.commandDelegate.executeEditorCommand(CoreNavigationCommands.SetSelection, {
source: source,
selection: modelSelection
});
@@ -299,7 +293,7 @@ export class ViewController {
this.outgoingEvents.emitMouseMove(e);
}
public emitMouseLeave(e: IEditorMouseEvent): void {
public emitMouseLeave(e: IPartialEditorMouseEvent): void {
this.outgoingEvents.emitMouseLeave(e);
}
@@ -315,7 +309,7 @@ export class ViewController {
this.outgoingEvents.emitMouseDrag(e);
}
public emitMouseDrop(e: IEditorMouseEvent): void {
public emitMouseDrop(e: IPartialEditorMouseEvent): void {
this.outgoingEvents.emitMouseDrop(e);
}
}

View File

@@ -2,32 +2,33 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IDisposable } from 'vs/base/common/lifecycle';
import * as dom from 'vs/base/browser/dom';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { Range } from 'vs/editor/common/core/range';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { IConfiguration } from 'vs/editor/common/editorCommon';
import { TextAreaHandler, ITextAreaHandlerHelper } from 'vs/editor/browser/controller/textAreaHandler';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { onUnexpectedError } from 'vs/base/common/errors';
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 { ViewController, ExecCoreEditorCommandFunc, ICommandDelegate } from 'vs/editor/browser/view/viewController';
import { ViewEventDispatcher } from 'vs/editor/common/view/viewEventDispatcher';
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';
import { PartFingerprint, PartFingerprints, ViewPart } from 'vs/editor/browser/view/viewPart';
import { ViewContentWidgets } from 'vs/editor/browser/viewParts/contentWidgets/contentWidgets';
import { CurrentLineHighlightOverlay } from 'vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight';
import { CurrentLineMarginHighlightOverlay } from 'vs/editor/browser/viewParts/currentLineMarginHighlight/currentLineMarginHighlight';
import { DecorationsOverlay } from 'vs/editor/browser/viewParts/decorations/decorations';
import { EditorScrollbar } from 'vs/editor/browser/viewParts/editorScrollbar/editorScrollbar';
import { GlyphMarginOverlay } from 'vs/editor/browser/viewParts/glyphMargin/glyphMargin';
import { LineNumbersOverlay } from 'vs/editor/browser/viewParts/lineNumbers/lineNumbers';
import { IndentGuidesOverlay } from 'vs/editor/browser/viewParts/indentGuides/indentGuides';
import { LineNumbersOverlay } from 'vs/editor/browser/viewParts/lineNumbers/lineNumbers';
import { ViewLines } from 'vs/editor/browser/viewParts/lines/viewLines';
import { Margin } from 'vs/editor/browser/viewParts/margin/margin';
import { LinesDecorationsOverlay } from 'vs/editor/browser/viewParts/linesDecorations/linesDecorations';
import { Margin } from 'vs/editor/browser/viewParts/margin/margin';
import { MarginViewLineDecorationsOverlay } from 'vs/editor/browser/viewParts/marginDecorations/marginDecorations';
import { Minimap } from 'vs/editor/browser/viewParts/minimap/minimap';
import { ViewOverlayWidgets } from 'vs/editor/browser/viewParts/overlayWidgets/overlayWidgets';
import { DecorationsOverviewRuler } from 'vs/editor/browser/viewParts/overviewRuler/decorationsOverviewRuler';
import { OverviewRuler } from 'vs/editor/browser/viewParts/overviewRuler/overviewRuler';
@@ -36,30 +37,30 @@ import { ScrollDecorationViewPart } from 'vs/editor/browser/viewParts/scrollDeco
import { SelectionsOverlay } from 'vs/editor/browser/viewParts/selections/selections';
import { ViewCursors } from 'vs/editor/browser/viewParts/viewCursors/viewCursors';
import { ViewZones } from 'vs/editor/browser/viewParts/viewZones/viewZones';
import { ViewPart, PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPart';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import { IPointerHandlerHelper } from 'vs/editor/browser/controller/mouseHandler';
import { ViewOutgoingEvents } from 'vs/editor/browser/view/viewOutgoingEvents';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
import { EditorScrollbar } from 'vs/editor/browser/viewParts/editorScrollbar/editorScrollbar';
import { Minimap } from 'vs/editor/browser/viewParts/minimap/minimap';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { IThemeService, getThemeTypeSelector } from 'vs/platform/theme/common/themeService';
import { Cursor } from 'vs/editor/common/controller/cursor';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { Position } from 'vs/editor/common/core/position';
import { IConfiguration } from 'vs/editor/common/editorCommon';
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { ViewEventDispatcher } from 'vs/editor/common/view/viewEventDispatcher';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { IThemeService, getThemeTypeSelector } from 'vs/platform/theme/common/themeService';
export interface IContentWidgetData {
widget: editorBrowser.IContentWidget;
position: editorBrowser.IContentWidgetPosition;
position: editorBrowser.IContentWidgetPosition | null;
}
export interface IOverlayWidgetData {
widget: editorBrowser.IOverlayWidget;
position: editorBrowser.IOverlayWidgetPosition;
position: editorBrowser.IOverlayWidgetPosition | null;
}
const invalidFunc = () => { throw new Error(`Invalid change accessor`); };
export class View extends ViewEventHandler {
private eventDispatcher: ViewEventDispatcher;
@@ -89,7 +90,7 @@ export class View extends ViewEventHandler {
private overflowGuardContainer: FastDomNode<HTMLElement>;
// Actual mutable state
private _renderAnimationFrame: IDisposable;
private _renderAnimationFrame: IDisposable | null;
constructor(
commandDelegate: ICommandDelegate,
@@ -97,14 +98,14 @@ export class View extends ViewEventHandler {
themeService: IThemeService,
model: IViewModel,
cursor: Cursor,
execCoreEditorCommandFunc: ExecCoreEditorCommandFunc
outgoingEvents: ViewOutgoingEvents
) {
super();
this._cursor = cursor;
this._renderAnimationFrame = null;
this.outgoingEvents = new ViewOutgoingEvents(model);
this.outgoingEvents = outgoingEvents;
let viewController = new ViewController(configuration, model, execCoreEditorCommandFunc, this.outgoingEvents, commandDelegate);
let viewController = new ViewController(configuration, model, this.outgoingEvents, commandDelegate);
// The event dispatcher will always go through _renderOnce before dispatching any events
this.eventDispatcher = new ViewEventDispatcher((callback: () => void) => this._renderOnce(callback));
@@ -263,11 +264,7 @@ export class View extends ViewEventHandler {
visibleRangeForPosition2: (lineNumber: number, column: number) => {
this._flushAccumulatedAndRenderNow();
let visibleRanges = this.viewLines.visibleRangesForRange2(new Range(lineNumber, column, lineNumber, column));
if (!visibleRanges) {
return null;
}
return visibleRanges[0];
return this.viewLines.visibleRangeForPosition(new Position(lineNumber, column));
},
getLineWidth: (lineNumber: number) => {
@@ -281,11 +278,7 @@ export class View extends ViewEventHandler {
return {
visibleRangeForPositionRelativeToEditor: (lineNumber: number, column: number) => {
this._flushAccumulatedAndRenderNow();
let visibleRanges = this.viewLines.visibleRangesForRange2(new Range(lineNumber, column, lineNumber, column));
if (!visibleRanges) {
return null;
}
return visibleRanges[0];
return this.viewLines.visibleRangeForPosition(new Position(lineNumber, column));
}
};
}
@@ -464,21 +457,17 @@ export class View extends ViewEventHandler {
});
let viewPosition = this._context.model.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);
this._flushAccumulatedAndRenderNow();
let visibleRanges = this.viewLines.visibleRangesForRange2(new Range(viewPosition.lineNumber, viewPosition.column, viewPosition.lineNumber, viewPosition.column));
if (!visibleRanges) {
const visibleRange = this.viewLines.visibleRangeForPosition(new Position(viewPosition.lineNumber, viewPosition.column));
if (!visibleRange) {
return -1;
}
return visibleRanges[0].left;
return visibleRange.left;
}
public getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget {
public getTargetAtClientPoint(clientX: number, clientY: number): editorBrowser.IMouseTarget | null {
return this.pointerHandler.getTargetAtClientPoint(clientX, clientY);
}
public getInternalEventBus(): ViewOutgoingEvents {
return this.outgoingEvents;
}
public createOverviewRuler(cssClassName: string): OverviewRuler {
return new OverviewRuler(this._context, cssClassName);
}
@@ -509,8 +498,9 @@ export class View extends ViewEventHandler {
safeInvoke1Arg(callback, changeAccessor);
// Invalidate changeAccessor
changeAccessor.addZone = null;
changeAccessor.removeZone = null;
changeAccessor.addZone = invalidFunc;
changeAccessor.removeZone = invalidFunc;
changeAccessor.layoutZone = invalidFunc;
if (zonesHaveChanged) {
this._context.viewLayout.onHeightMaybeChanged();
@@ -552,8 +542,9 @@ export class View extends ViewEventHandler {
public layoutContentWidget(widgetData: IContentWidgetData): void {
let newPosition = widgetData.position ? widgetData.position.position : null;
let newRange = widgetData.position ? widgetData.position.range : null;
let newPreference = widgetData.position ? widgetData.position.preference : null;
this.contentWidgets.setWidgetPosition(widgetData.widget, newPosition, newPreference);
this.contentWidgets.setWidgetPosition(widgetData.widget, newPosition, newRange, newPreference);
this._scheduleRender();
}

View File

@@ -2,18 +2,17 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
import { IStringBuilder, createStringBuilder } from 'vs/editor/common/core/stringBuilder';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { createStringBuilder, IStringBuilder } from 'vs/editor/common/core/stringBuilder';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
/**
* Represents a visible line
*/
export interface IVisibleLine extends ILine {
getDomNode(): HTMLElement;
getDomNode(): HTMLElement | null;
setDomNode(domNode: HTMLElement): void;
/**
@@ -88,7 +87,7 @@ export class RenderedLinesCollection<T extends ILine> {
/**
* @returns Lines that were removed from this collection
*/
public onLinesDeleted(deleteFromLineNumber: number, deleteToLineNumber: number): T[] {
public onLinesDeleted(deleteFromLineNumber: number, deleteToLineNumber: number): T[] | null {
if (this.getCount() === 0) {
// no lines
return null;
@@ -168,7 +167,7 @@ export class RenderedLinesCollection<T extends ILine> {
return someoneNotified;
}
public onLinesInserted(insertFromLineNumber: number, insertToLineNumber: number): T[] {
public onLinesInserted(insertFromLineNumber: number, insertToLineNumber: number): T[] | null {
if (this.getCount() === 0) {
// no lines
return null;
@@ -528,8 +527,8 @@ class ViewLayerRenderer<T extends IVisibleLine> {
let line = ctx.lines[i];
if (wasInvalid[i]) {
let source = <HTMLElement>hugeDomNode.firstChild;
let lineDomNode = line.getDomNode();
lineDomNode.parentNode.replaceChild(source, lineDomNode);
let lineDomNode = line.getDomNode()!;
lineDomNode.parentNode!.replaceChild(source, lineDomNode);
line.setDomNode(source);
}
}

View File

@@ -2,17 +2,16 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Disposable } from 'vs/base/common/lifecycle';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Disposable } from 'vs/base/common/lifecycle';
import { MouseTarget } from 'vs/editor/browser/controller/mouseTarget';
import { IEditorMouseEvent, IMouseTarget, IPartialEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { IScrollEvent } from 'vs/editor/common/editorCommon';
import { IEditorMouseEvent, IMouseTarget, MouseTargetType } from 'vs/editor/browser/editorBrowser';
import { MouseTarget } from 'vs/editor/browser/controller/mouseTarget';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { IViewModel } from 'vs/editor/common/viewModel/viewModel';
export interface EventCallback<T> {
(event: T): void;
@@ -20,18 +19,18 @@ export interface EventCallback<T> {
export class ViewOutgoingEvents extends Disposable {
public onDidScroll: EventCallback<IScrollEvent> = null;
public onDidGainFocus: EventCallback<void> = null;
public onDidLoseFocus: EventCallback<void> = null;
public onKeyDown: EventCallback<IKeyboardEvent> = null;
public onKeyUp: EventCallback<IKeyboardEvent> = null;
public onContextMenu: EventCallback<IEditorMouseEvent> = null;
public onMouseMove: EventCallback<IEditorMouseEvent> = null;
public onMouseLeave: EventCallback<IEditorMouseEvent> = null;
public onMouseUp: EventCallback<IEditorMouseEvent> = null;
public onMouseDown: EventCallback<IEditorMouseEvent> = null;
public onMouseDrag: EventCallback<IEditorMouseEvent> = null;
public onMouseDrop: EventCallback<IEditorMouseEvent> = null;
public onDidScroll: EventCallback<IScrollEvent> | null = null;
public onDidGainFocus: EventCallback<void> | null = null;
public onDidLoseFocus: EventCallback<void> | null = null;
public onKeyDown: EventCallback<IKeyboardEvent> | null = null;
public onKeyUp: EventCallback<IKeyboardEvent> | null = null;
public onContextMenu: EventCallback<IEditorMouseEvent> | null = null;
public onMouseMove: EventCallback<IEditorMouseEvent> | null = null;
public onMouseLeave: EventCallback<IPartialEditorMouseEvent> | null = null;
public onMouseUp: EventCallback<IEditorMouseEvent> | null = null;
public onMouseDown: EventCallback<IEditorMouseEvent> | null = null;
public onMouseDrag: EventCallback<IEditorMouseEvent> | null = null;
public onMouseDrop: EventCallback<IPartialEditorMouseEvent> | null = null;
private _viewModel: IViewModel;
@@ -82,7 +81,7 @@ export class ViewOutgoingEvents extends Disposable {
}
}
public emitMouseLeave(e: IEditorMouseEvent): void {
public emitMouseLeave(e: IPartialEditorMouseEvent): void {
if (this.onMouseLeave) {
this.onMouseLeave(this._convertViewToModelMouseEvent(e));
}
@@ -106,13 +105,15 @@ export class ViewOutgoingEvents extends Disposable {
}
}
public emitMouseDrop(e: IEditorMouseEvent): void {
public emitMouseDrop(e: IPartialEditorMouseEvent): void {
if (this.onMouseDrop) {
this.onMouseDrop(this._convertViewToModelMouseEvent(e));
}
}
private _convertViewToModelMouseEvent(e: IEditorMouseEvent): IEditorMouseEvent {
private _convertViewToModelMouseEvent(e: IEditorMouseEvent): IEditorMouseEvent;
private _convertViewToModelMouseEvent(e: IPartialEditorMouseEvent): IPartialEditorMouseEvent;
private _convertViewToModelMouseEvent(e: IEditorMouseEvent | IPartialEditorMouseEvent): IEditorMouseEvent | IPartialEditorMouseEvent {
if (e.target) {
return {
event: e.event,
@@ -144,14 +145,14 @@ export class ViewOutgoingEvents extends Disposable {
class ExternalMouseTarget implements IMouseTarget {
public readonly element: Element;
public readonly element: Element | null;
public readonly type: MouseTargetType;
public readonly mouseColumn: number;
public readonly position: Position;
public readonly range: Range;
public readonly position: Position | null;
public readonly range: Range | null;
public readonly detail: any;
constructor(element: Element, type: MouseTargetType, mouseColumn: number, position: Position, range: Range, detail: any) {
constructor(element: Element | null, type: MouseTargetType, mouseColumn: number, position: Position | null, range: Range | null, detail: any) {
this.element = element;
this.type = type;
this.mouseColumn = mouseColumn;

View File

@@ -2,19 +2,18 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { IConfiguration } from 'vs/editor/common/editorCommon';
import { IVisibleLine, VisibleLinesCollection, IVisibleLinesHost } from 'vs/editor/browser/view/viewLayer';
import { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';
import { IVisibleLine, IVisibleLinesHost, VisibleLinesCollection } from 'vs/editor/browser/view/viewLayer';
import { ViewPart } from 'vs/editor/browser/view/viewPart';
import { IStringBuilder } from 'vs/editor/common/core/stringBuilder';
import { IConfiguration } from 'vs/editor/common/editorCommon';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
export class ViewOverlays extends ViewPart implements IVisibleLinesHost<ViewOverlayLine> {
@@ -57,7 +56,7 @@ export class ViewOverlays extends ViewPart implements IVisibleLinesHost<ViewOver
let dynamicOverlay = this._dynamicOverlays[i];
dynamicOverlay.dispose();
}
this._dynamicOverlays = null;
this._dynamicOverlays = [];
}
public getDomNode(): FastDomNode<HTMLElement> {
@@ -124,8 +123,6 @@ export class ViewOverlays extends ViewPart implements IVisibleLinesHost<ViewOver
dynamicOverlay.prepareRender(ctx);
dynamicOverlay.onDidRender();
}
return null;
}
public render(ctx: RestrictedRenderingContext): void {
@@ -144,8 +141,8 @@ export class ViewOverlayLine implements IVisibleLine {
private _configuration: IConfiguration;
private _dynamicOverlays: DynamicViewOverlay[];
private _domNode: FastDomNode<HTMLElement>;
private _renderedContent: string;
private _domNode: FastDomNode<HTMLElement> | null;
private _renderedContent: string | null;
private _lineHeight: number;
constructor(configuration: IConfiguration, dynamicOverlays: DynamicViewOverlay[]) {
@@ -157,7 +154,7 @@ export class ViewOverlayLine implements IVisibleLine {
this._renderedContent = null;
}
public getDomNode(): HTMLElement {
public getDomNode(): HTMLElement | null {
if (!this._domNode) {
return null;
}

View File

@@ -2,12 +2,11 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { FastDomNode } from 'vs/base/browser/fastDomNode';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
export abstract class ViewPart extends ViewEventHandler {
@@ -21,7 +20,6 @@ export abstract class ViewPart extends ViewEventHandler {
public dispose(): void {
this._context.removeEventHandler(this);
this._context = null;
super.dispose();
}
@@ -59,7 +57,7 @@ export class PartFingerprints {
return parseInt(r, 10);
}
public static collect(child: Element, stopAt: Element): Uint8Array {
public static collect(child: Element | null, stopAt: Element): Uint8Array {
let result: PartFingerprint[] = [], resultLen = 0;
while (child && child !== document.body) {

View File

@@ -3,15 +3,15 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as dom from 'vs/base/browser/dom';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { ContentWidgetPositionPreference, IContentWidget } from 'vs/editor/browser/editorBrowser';
import { ViewPart, PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPart';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { PartFingerprint, PartFingerprints, ViewPart } from 'vs/editor/browser/view/viewPart';
import { IPosition, Position } from 'vs/editor/common/core/position';
import { IRange, Range } from 'vs/editor/common/core/range';
import { Constants } from 'vs/editor/common/core/uint';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { Position, IPosition } from 'vs/editor/common/core/position';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
@@ -53,8 +53,7 @@ export class ViewContentWidgets extends ViewPart {
public dispose(): void {
super.dispose();
this._widgets = null;
this.domNode = null;
this._widgets = {};
}
// --- begin event handlers
@@ -113,9 +112,9 @@ export class ViewContentWidgets extends ViewPart {
this.setShouldRender();
}
public setWidgetPosition(widget: IContentWidget, position: IPosition, preference: ContentWidgetPositionPreference[]): void {
public setWidgetPosition(widget: IContentWidget, position: IPosition | null | undefined, range: IRange | null | undefined, preference: ContentWidgetPositionPreference[] | null | undefined): void {
const myWidget = this._widgets[widget.getId()];
myWidget.setPosition(position, preference);
myWidget.setPosition(position, range, preference);
this.setShouldRender();
}
@@ -127,7 +126,7 @@ export class ViewContentWidgets extends ViewPart {
delete this._widgets[widgetId];
const domNode = myWidget.domNode.domNode;
domNode.parentNode.removeChild(domNode);
domNode.parentNode!.removeChild(domNode);
domNode.removeAttribute('monaco-visible-content-widget');
this.setShouldRender();
@@ -167,11 +166,13 @@ export class ViewContentWidgets extends ViewPart {
}
interface IBoxLayoutResult {
aboveTop: number;
fitsAbove: boolean;
belowTop: number;
aboveTop: number;
aboveLeft: number;
fitsBelow: boolean;
left: number;
belowTop: number;
belowLeft: number;
}
class Widget {
@@ -189,15 +190,17 @@ class Widget {
private _contentLeft: number;
private _lineHeight: number;
private _position: IPosition;
private _viewPosition: Position;
private _preference: ContentWidgetPositionPreference[];
private _position: IPosition | null;
private _viewPosition: Position | null;
private _range: IRange | null;
private _viewRange: Range | null;
private _preference: ContentWidgetPositionPreference[] | null;
private _cachedDomNodeClientWidth: number;
private _cachedDomNodeClientHeight: number;
private _maxWidth: number;
private _isVisible: boolean;
private _renderData: Coordinate;
private _renderData: Coordinate | null;
constructor(context: ViewContext, viewDomNode: FastDomNode<HTMLElement>, actual: IContentWidget) {
this._context = context;
@@ -214,8 +217,8 @@ class Widget {
this._contentLeft = this._context.configuration.editor.layoutInfo.contentLeft;
this._lineHeight = this._context.configuration.editor.lineHeight;
this._setPosition(null);
this._preference = null;
this._setPosition(null, null);
this._preference = [];
this._cachedDomNodeClientWidth = -1;
this._cachedDomNodeClientHeight = -1;
this._maxWidth = this._getMaxWidth();
@@ -240,12 +243,14 @@ class Widget {
}
public onLineMappingChanged(e: viewEvents.ViewLineMappingChangedEvent): void {
this._setPosition(this._position);
this._setPosition(this._position, this._range);
}
private _setPosition(position: IPosition): void {
this._position = position;
private _setPosition(position: IPosition | null | undefined, range: IRange | null | undefined): void {
this._position = position || null;
this._range = range || null;
this._viewPosition = null;
this._viewRange = null;
if (this._position) {
// Do not trust that widgets give a valid position
@@ -254,24 +259,29 @@ class Widget {
this._viewPosition = this._context.model.coordinatesConverter.convertModelPositionToViewPosition(validModelPosition);
}
}
if (this._range) {
// Do not trust that widgets give a valid position
const validModelRange = this._context.model.validateModelRange(this._range);
this._viewRange = this._context.model.coordinatesConverter.convertModelRangeToViewRange(validModelRange);
}
}
private _getMaxWidth(): number {
return (
this.allowEditorOverflow
? window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
? window.innerWidth || document.documentElement!.clientWidth || document.body.clientWidth
: this._contentWidth
);
}
public setPosition(position: IPosition, preference: ContentWidgetPositionPreference[]): void {
this._setPosition(position);
this._preference = preference;
public setPosition(position: IPosition | null | undefined, range: IRange | null | undefined, preference: ContentWidgetPositionPreference[] | null | undefined): void {
this._setPosition(position, range);
this._preference = preference || null;
this._cachedDomNodeClientWidth = -1;
this._cachedDomNodeClientHeight = -1;
}
private _layoutBoxInViewport(topLeft: Coordinate, width: number, height: number, ctx: RenderingContext): IBoxLayoutResult {
private _layoutBoxInViewport(topLeft: Coordinate, bottomLeft: Coordinate, width: number, height: number, ctx: RenderingContext): IBoxLayoutResult {
// Our visible box is split horizontally by the current line => 2 boxes
// a) the box above the line
@@ -279,7 +289,7 @@ class Widget {
let heightAboveLine = aboveLineTop;
// b) the box under the line
let underLineTop = topLeft.top + this._lineHeight;
let underLineTop = bottomLeft.top + this._lineHeight;
let heightUnderLine = ctx.viewportHeight - underLineTop;
let aboveTop = aboveLineTop - height;
@@ -288,42 +298,54 @@ class Widget {
let fitsBelow = (heightUnderLine >= height);
// And its left
let actualLeft = topLeft.left;
if (actualLeft + width > ctx.scrollLeft + ctx.viewportWidth) {
actualLeft = ctx.scrollLeft + ctx.viewportWidth - width;
let actualAboveLeft = topLeft.left;
let actualBelowLeft = bottomLeft.left;
if (actualAboveLeft + width > ctx.scrollLeft + ctx.viewportWidth) {
actualAboveLeft = ctx.scrollLeft + ctx.viewportWidth - width;
}
if (actualLeft < ctx.scrollLeft) {
actualLeft = ctx.scrollLeft;
if (actualBelowLeft + width > ctx.scrollLeft + ctx.viewportWidth) {
actualBelowLeft = ctx.scrollLeft + ctx.viewportWidth - width;
}
if (actualAboveLeft < ctx.scrollLeft) {
actualAboveLeft = ctx.scrollLeft;
}
if (actualBelowLeft < ctx.scrollLeft) {
actualBelowLeft = ctx.scrollLeft;
}
return {
aboveTop: aboveTop,
fitsAbove: fitsAbove,
belowTop: belowTop,
aboveTop: aboveTop,
aboveLeft: actualAboveLeft,
fitsBelow: fitsBelow,
left: actualLeft
belowTop: belowTop,
belowLeft: actualBelowLeft,
};
}
private _layoutBoxInPage(topLeft: Coordinate, width: number, height: number, ctx: RenderingContext): IBoxLayoutResult {
let left0 = topLeft.left - ctx.scrollLeft;
private _layoutBoxInPage(topLeft: Coordinate, bottomLeft: Coordinate, width: number, height: number, ctx: RenderingContext): IBoxLayoutResult | null {
let aboveLeft0 = topLeft.left - ctx.scrollLeft;
let belowLeft0 = bottomLeft.left - ctx.scrollLeft;
if (left0 < 0 || left0 > this._contentWidth) {
if (aboveLeft0 < 0 || aboveLeft0 > this._contentWidth) {
// Don't render if position is scrolled outside viewport
return null;
}
let aboveTop = topLeft.top - height;
let belowTop = topLeft.top + this._lineHeight;
let left = left0 + this._contentLeft;
let belowTop = bottomLeft.top + this._lineHeight;
let aboveLeft = aboveLeft0 + this._contentLeft;
let belowLeft = belowLeft0 + this._contentLeft;
let domNodePosition = dom.getDomNodePagePosition(this._viewDomNode.domNode);
let absoluteAboveTop = domNodePosition.top + aboveTop - dom.StandardWindow.scrollY;
let absoluteBelowTop = domNodePosition.top + belowTop - dom.StandardWindow.scrollY;
let absoluteLeft = domNodePosition.left + left - dom.StandardWindow.scrollX;
let absoluteAboveLeft = domNodePosition.left + aboveLeft - dom.StandardWindow.scrollX;
let absoluteBelowLeft = domNodePosition.left + belowLeft - dom.StandardWindow.scrollX;
let INNER_WIDTH = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
let INNER_HEIGHT = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
let INNER_WIDTH = window.innerWidth || document.documentElement!.clientWidth || document.body.clientWidth;
let INNER_HEIGHT = window.innerHeight || document.documentElement!.clientHeight || document.body.clientHeight;
// Leave some clearance to the bottom
let TOP_PADDING = 22;
@@ -332,24 +354,35 @@ class Widget {
let fitsAbove = (absoluteAboveTop >= TOP_PADDING),
fitsBelow = (absoluteBelowTop + height <= INNER_HEIGHT - BOTTOM_PADDING);
if (absoluteLeft + width + 20 > INNER_WIDTH) {
let delta = absoluteLeft - (INNER_WIDTH - width - 20);
absoluteLeft -= delta;
left -= delta;
if (absoluteAboveLeft + width + 20 > INNER_WIDTH) {
let delta = absoluteAboveLeft - (INNER_WIDTH - width - 20);
absoluteAboveLeft -= delta;
aboveLeft -= delta;
}
if (absoluteLeft < 0) {
let delta = absoluteLeft;
absoluteLeft -= delta;
left -= delta;
if (absoluteBelowLeft + width + 20 > INNER_WIDTH) {
let delta = absoluteBelowLeft - (INNER_WIDTH - width - 20);
absoluteBelowLeft -= delta;
belowLeft -= delta;
}
if (absoluteAboveLeft < 0) {
let delta = absoluteAboveLeft;
absoluteAboveLeft -= delta;
aboveLeft -= delta;
}
if (absoluteBelowLeft < 0) {
let delta = absoluteBelowLeft;
absoluteBelowLeft -= delta;
belowLeft -= delta;
}
if (this._fixedOverflowWidgets) {
aboveTop = absoluteAboveTop;
belowTop = absoluteBelowTop;
left = absoluteLeft;
aboveLeft = absoluteAboveLeft;
belowLeft = absoluteBelowLeft;
}
return { aboveTop, fitsAbove, belowTop, fitsBelow, left };
return { fitsAbove, aboveTop, aboveLeft, fitsBelow, belowTop, belowLeft };
}
private _prepareRenderWidgetAtExactPositionOverflowing(topLeft: Coordinate): Coordinate {
@@ -359,71 +392,97 @@ class Widget {
/**
* Compute `this._topLeft`
*/
private _getTopLeft(ctx: RenderingContext): Coordinate {
private _getTopAndBottomLeft(ctx: RenderingContext): [Coordinate, Coordinate] | [null, null] {
if (!this._viewPosition) {
return null;
return [null, null];
}
const visibleRange = ctx.visibleRangeForPosition(this._viewPosition);
if (!visibleRange) {
return null;
const visibleRangeForPosition = ctx.visibleRangeForPosition(this._viewPosition);
if (!visibleRangeForPosition) {
return [null, null];
}
const top = ctx.getVerticalOffsetForLineNumber(this._viewPosition.lineNumber) - ctx.scrollTop;
return new Coordinate(top, visibleRange.left);
const topForPosition = ctx.getVerticalOffsetForLineNumber(this._viewPosition.lineNumber) - ctx.scrollTop;
const topLeft = new Coordinate(topForPosition, visibleRangeForPosition.left);
let largestLineNumber = this._viewPosition.lineNumber;
let smallestLeft = visibleRangeForPosition.left;
if (this._viewRange) {
const visibleRangesForRange = ctx.linesVisibleRangesForRange(this._viewRange, false);
if (visibleRangesForRange && visibleRangesForRange.length > 0) {
for (let i = visibleRangesForRange.length - 1; i >= 0; i--) {
const visibleRangesForLine = visibleRangesForRange[i];
if (visibleRangesForLine.lineNumber >= largestLineNumber) {
if (visibleRangesForLine.lineNumber > largestLineNumber) {
largestLineNumber = visibleRangesForLine.lineNumber;
smallestLeft = Constants.MAX_SAFE_SMALL_INTEGER;
}
for (let j = 0, lenJ = visibleRangesForLine.ranges.length; j < lenJ; j++) {
const visibleRange = visibleRangesForLine.ranges[j];
if (visibleRange.left < smallestLeft) {
smallestLeft = visibleRange.left;
}
}
}
}
}
}
const topForBottomLine = ctx.getVerticalOffsetForLineNumber(largestLineNumber) - ctx.scrollTop;
const bottomLeft = new Coordinate(topForBottomLine, smallestLeft);
return [topLeft, bottomLeft];
}
private _prepareRenderWidget(topLeft: Coordinate, ctx: RenderingContext): Coordinate {
if (!topLeft) {
private _prepareRenderWidget(ctx: RenderingContext): Coordinate | null {
const [topLeft, bottomLeft] = this._getTopAndBottomLeft(ctx);
if (!topLeft || !bottomLeft) {
return null;
}
let placement: IBoxLayoutResult = null;
let fetchPlacement = (): void => {
if (placement) {
return;
}
if (this._cachedDomNodeClientWidth === -1 || this._cachedDomNodeClientHeight === -1) {
const domNode = this.domNode.domNode;
this._cachedDomNodeClientWidth = domNode.clientWidth;
this._cachedDomNodeClientHeight = domNode.clientHeight;
}
if (this._cachedDomNodeClientWidth === -1 || this._cachedDomNodeClientHeight === -1) {
const domNode = this.domNode.domNode;
this._cachedDomNodeClientWidth = domNode.clientWidth;
this._cachedDomNodeClientHeight = domNode.clientHeight;
}
if (this.allowEditorOverflow) {
placement = this._layoutBoxInPage(topLeft, this._cachedDomNodeClientWidth, this._cachedDomNodeClientHeight, ctx);
} else {
placement = this._layoutBoxInViewport(topLeft, this._cachedDomNodeClientWidth, this._cachedDomNodeClientHeight, ctx);
}
};
let placement: IBoxLayoutResult | null;
if (this.allowEditorOverflow) {
placement = this._layoutBoxInPage(topLeft, bottomLeft, this._cachedDomNodeClientWidth, this._cachedDomNodeClientHeight, ctx);
} else {
placement = this._layoutBoxInViewport(topLeft, bottomLeft, this._cachedDomNodeClientWidth, this._cachedDomNodeClientHeight, ctx);
}
// Do two passes, first for perfect fit, second picks first option
for (let pass = 1; pass <= 2; pass++) {
for (let i = 0; i < this._preference.length; i++) {
let pref = this._preference[i];
if (pref === ContentWidgetPositionPreference.ABOVE) {
fetchPlacement();
if (!placement) {
// Widget outside of viewport
return null;
}
if (pass === 2 || placement.fitsAbove) {
return new Coordinate(placement.aboveTop, placement.left);
}
} else if (pref === ContentWidgetPositionPreference.BELOW) {
fetchPlacement();
if (!placement) {
// Widget outside of viewport
return null;
}
if (pass === 2 || placement.fitsBelow) {
return new Coordinate(placement.belowTop, placement.left);
}
} else {
if (this.allowEditorOverflow) {
return this._prepareRenderWidgetAtExactPositionOverflowing(topLeft);
if (this._preference) {
for (let pass = 1; pass <= 2; pass++) {
for (let i = 0; i < this._preference.length; i++) {
// placement
let pref = this._preference[i];
if (pref === ContentWidgetPositionPreference.ABOVE) {
if (!placement) {
// Widget outside of viewport
return null;
}
if (pass === 2 || placement.fitsAbove) {
return new Coordinate(placement.aboveTop, placement.aboveLeft);
}
} else if (pref === ContentWidgetPositionPreference.BELOW) {
if (!placement) {
// Widget outside of viewport
return null;
}
if (pass === 2 || placement.fitsBelow) {
return new Coordinate(placement.belowTop, placement.belowLeft);
}
} else {
return topLeft;
if (this.allowEditorOverflow) {
return this._prepareRenderWidgetAtExactPositionOverflowing(topLeft);
} else {
return topLeft;
}
}
}
}
@@ -448,8 +507,7 @@ class Widget {
}
public prepareRender(ctx: RenderingContext): void {
const topLeft = this._getTopLeft(ctx);
this._renderData = this._prepareRenderWidget(topLeft, ctx);
this._renderData = this._prepareRenderWidget(ctx);
}
public render(ctx: RestrictedRenderingContext): void {

View File

@@ -3,15 +3,13 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./currentLineHighlight';
import { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { editorLineHighlight, editorLineHighlightBorder } from 'vs/editor/common/view/editorColorRegistry';
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { editorLineHighlight, editorLineHighlightBorder } from 'vs/editor/common/view/editorColorRegistry';
export class CurrentLineHighlightOverlay extends DynamicViewOverlay {
private _context: ViewContext;
@@ -38,7 +36,6 @@ export class CurrentLineHighlightOverlay extends DynamicViewOverlay {
public dispose(): void {
this._context.removeEventHandler(this);
this._context = null;
super.dispose();
}
@@ -131,12 +128,12 @@ export class CurrentLineHighlightOverlay extends DynamicViewOverlay {
}
registerThemingParticipant((theme, collector) => {
let lineHighlight = theme.getColor(editorLineHighlight);
const lineHighlight = theme.getColor(editorLineHighlight);
if (lineHighlight) {
collector.addRule(`.monaco-editor .view-overlays .current-line { background-color: ${lineHighlight}; }`);
}
if (!lineHighlight || lineHighlight.isTransparent() || theme.defines(editorLineHighlightBorder)) {
let lineHighlightBorder = theme.getColor(editorLineHighlightBorder);
const lineHighlightBorder = theme.getColor(editorLineHighlightBorder);
if (lineHighlightBorder) {
collector.addRule(`.monaco-editor .view-overlays .current-line { border: 2px solid ${lineHighlightBorder}; }`);
if (theme.type === 'hc') {

View File

@@ -3,15 +3,13 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./currentLineMarginHighlight';
import { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { editorLineHighlight, editorLineHighlightBorder } from 'vs/editor/common/view/editorColorRegistry';
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { editorLineHighlight, editorLineHighlightBorder } from 'vs/editor/common/view/editorColorRegistry';
export class CurrentLineMarginHighlightOverlay extends DynamicViewOverlay {
private _context: ViewContext;
@@ -36,7 +34,6 @@ export class CurrentLineMarginHighlightOverlay extends DynamicViewOverlay {
public dispose(): void {
this._context.removeEventHandler(this);
this._context = null;
super.dispose();
}
@@ -125,11 +122,11 @@ export class CurrentLineMarginHighlightOverlay extends DynamicViewOverlay {
}
registerThemingParticipant((theme, collector) => {
let lineHighlight = theme.getColor(editorLineHighlight);
const lineHighlight = theme.getColor(editorLineHighlight);
if (lineHighlight) {
collector.addRule(`.monaco-editor .margin-view-overlays .current-line-margin { background-color: ${lineHighlight}; border: none; }`);
} else {
let lineHighlightBorder = theme.getColor(editorLineHighlightBorder);
const lineHighlightBorder = theme.getColor(editorLineHighlightBorder);
if (lineHighlightBorder) {
collector.addRule(`.monaco-editor .margin-view-overlays .current-line-margin { border: 2px solid ${lineHighlightBorder}; }`);
}

View File

@@ -3,22 +3,20 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./decorations';
import { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';
import { Range } from 'vs/editor/common/core/range';
import { HorizontalRange, RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext, HorizontalRange } from 'vs/editor/common/view/renderingContext';
import { ViewModelDecoration } from 'vs/editor/common/viewModel/viewModel';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { ViewModelDecoration } from 'vs/editor/common/viewModel/viewModel';
export class DecorationsOverlay extends DynamicViewOverlay {
private _context: ViewContext;
private _lineHeight: number;
private _typicalHalfwidthCharacterWidth: number;
private _renderResult: string[];
private _renderResult: string[] | null;
constructor(context: ViewContext) {
super();
@@ -32,7 +30,6 @@ export class DecorationsOverlay extends DynamicViewOverlay {
public dispose(): void {
this._context.removeEventHandler(this);
this._context = null;
this._renderResult = null;
super.dispose();
}
@@ -85,14 +82,14 @@ export class DecorationsOverlay extends DynamicViewOverlay {
// Sort decorations for consistent render output
decorations = decorations.sort((a, b) => {
if (a.options.zIndex < b.options.zIndex) {
if (a.options.zIndex! < b.options.zIndex!) {
return -1;
}
if (a.options.zIndex > b.options.zIndex) {
if (a.options.zIndex! > b.options.zIndex!) {
return 1;
}
const aClassName = a.options.className;
const bClassName = b.options.className;
const aClassName = a.options.className!;
const bClassName = b.options.className!;
if (aClassName < bClassName) {
return -1;
@@ -151,9 +148,9 @@ export class DecorationsOverlay extends DynamicViewOverlay {
const lineHeight = String(this._lineHeight);
const visibleStartLineNumber = ctx.visibleRange.startLineNumber;
let prevClassName: string = null;
let prevClassName: string | null = null;
let prevShowIfCollapsed: boolean = false;
let prevRange: Range = null;
let prevRange: Range | null = null;
for (let i = 0, lenI = decorations.length; i < lenI; i++) {
const d = decorations[i];
@@ -162,23 +159,23 @@ export class DecorationsOverlay extends DynamicViewOverlay {
continue;
}
const className = d.options.className;
const showIfCollapsed = d.options.showIfCollapsed;
const className = d.options.className!;
const showIfCollapsed = Boolean(d.options.showIfCollapsed);
let range = d.range;
if (showIfCollapsed && range.endColumn === 1 && range.endLineNumber !== range.startLineNumber) {
range = new Range(range.startLineNumber, range.startColumn, range.endLineNumber - 1, this._context.model.getLineMaxColumn(range.endLineNumber - 1));
}
if (prevClassName === className && prevShowIfCollapsed === showIfCollapsed && Range.areIntersectingOrTouching(prevRange, range)) {
if (prevClassName === className && prevShowIfCollapsed === showIfCollapsed && Range.areIntersectingOrTouching(prevRange!, range)) {
// merge into previous decoration
prevRange = Range.plusRange(prevRange, range);
prevRange = Range.plusRange(prevRange!, range);
continue;
}
// flush previous decoration
if (prevClassName !== null) {
this._renderNormalDecoration(ctx, prevRange, prevClassName, prevShowIfCollapsed, lineHeight, visibleStartLineNumber, output);
this._renderNormalDecoration(ctx, prevRange!, prevClassName, prevShowIfCollapsed, lineHeight, visibleStartLineNumber, output);
}
prevClassName = className;
@@ -187,7 +184,7 @@ export class DecorationsOverlay extends DynamicViewOverlay {
}
if (prevClassName !== null) {
this._renderNormalDecoration(ctx, prevRange, prevClassName, prevShowIfCollapsed, lineHeight, visibleStartLineNumber, output);
this._renderNormalDecoration(ctx, prevRange!, prevClassName, prevShowIfCollapsed, lineHeight, visibleStartLineNumber, output);
}
}

View File

@@ -2,19 +2,18 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as dom from 'vs/base/browser/dom';
import { ScrollableElementCreationOptions, ScrollableElementChangeOptions } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { IOverviewRulerLayoutInfo, SmoothScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { ScrollableElementChangeOptions, ScrollableElementCreationOptions } from 'vs/base/browser/ui/scrollbar/scrollableElementOptions';
import { PartFingerprint, PartFingerprints, ViewPart } from 'vs/editor/browser/view/viewPart';
import { INewScrollPosition } from 'vs/editor/common/editorCommon';
import { ViewPart, PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPart';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { getThemeTypeSelector } from 'vs/platform/theme/common/themeService';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
export class EditorScrollbar extends ViewPart {

View File

@@ -3,12 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./glyphMargin';
import { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
export class DecorationToRender {
@@ -49,7 +47,7 @@ export abstract class DedupOverlay extends DynamicViewOverlay {
return (a.className < b.className ? -1 : 1);
});
let prevClassName: string = null;
let prevClassName: string | null = null;
let prevEndLineIndex = 0;
for (let i = 0, len = decorations.length; i < len; i++) {
let d = decorations[i];
@@ -81,7 +79,7 @@ export class GlyphMarginOverlay extends DedupOverlay {
private _glyphMargin: boolean;
private _glyphMarginLeft: number;
private _glyphMarginWidth: number;
private _renderResult: string[];
private _renderResult: string[] | null;
constructor(context: ViewContext) {
super();
@@ -96,7 +94,6 @@ export class GlyphMarginOverlay extends DedupOverlay {
public dispose(): void {
this._context.removeEventHandler(this);
this._context = null;
this._renderResult = null;
super.dispose();
}

View File

@@ -3,16 +3,14 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./indentGuides';
import { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { Position } from 'vs/editor/common/core/position';
import { editorActiveIndentGuides, editorIndentGuides } from 'vs/editor/common/view/editorColorRegistry';
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { editorIndentGuides, editorActiveIndentGuides } from 'vs/editor/common/view/editorColorRegistry';
import { Position } from 'vs/editor/common/core/position';
export class IndentGuidesOverlay extends DynamicViewOverlay {
@@ -20,7 +18,7 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
private _primaryLineNumber: number;
private _lineHeight: number;
private _spaceWidth: number;
private _renderResult: string[];
private _renderResult: string[] | null;
private _enabled: boolean;
private _activeIndentEnabled: boolean;
@@ -39,7 +37,6 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
public dispose(): void {
this._context.removeEventHandler(this);
this._context = null;
this._renderResult = null;
super.dispose();
}
@@ -160,11 +157,11 @@ export class IndentGuidesOverlay extends DynamicViewOverlay {
}
registerThemingParticipant((theme, collector) => {
let editorIndentGuidesColor = theme.getColor(editorIndentGuides);
const editorIndentGuidesColor = theme.getColor(editorIndentGuides);
if (editorIndentGuidesColor) {
collector.addRule(`.monaco-editor .lines-content .cigr { box-shadow: 1px 0 0 0 ${editorIndentGuidesColor} inset; }`);
}
let editorActiveIndentGuidesColor = theme.getColor(editorActiveIndentGuides) || editorIndentGuidesColor;
const editorActiveIndentGuidesColor = theme.getColor(editorActiveIndentGuides) || editorIndentGuidesColor;
if (editorActiveIndentGuidesColor) {
collector.addRule(`.monaco-editor .lines-content .cigra { box-shadow: 1px 0 0 0 ${editorActiveIndentGuidesColor} inset; }`);
}

View File

@@ -3,18 +3,16 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./lineNumbers';
import { editorLineNumbers, editorActiveLineNumber } from 'vs/editor/common/view/editorColorRegistry';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import * as platform from 'vs/base/common/platform';
import { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { Position } from 'vs/editor/common/core/position';
import { RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
import { Position } from 'vs/editor/common/core/position';
import { editorActiveLineNumber, editorLineNumbers } from 'vs/editor/common/view/editorColorRegistry';
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
export class LineNumbersOverlay extends DynamicViewOverlay {
@@ -24,11 +22,11 @@ export class LineNumbersOverlay extends DynamicViewOverlay {
private _lineHeight: number;
private _renderLineNumbers: RenderLineNumbersType;
private _renderCustomLineNumbers: (lineNumber: number) => string;
private _renderCustomLineNumbers: ((lineNumber: number) => string) | null;
private _lineNumbersLeft: number;
private _lineNumbersWidth: number;
private _lastCursorModelPosition: Position;
private _renderResult: string[];
private _renderResult: string[] | null;
constructor(context: ViewContext) {
super();
@@ -52,7 +50,6 @@ export class LineNumbersOverlay extends DynamicViewOverlay {
public dispose(): void {
this._context.removeEventHandler(this);
this._context = null;
this._renderResult = null;
super.dispose();
}
@@ -171,7 +168,7 @@ export class LineNumbersOverlay extends DynamicViewOverlay {
// theming
registerThemingParticipant((theme, collector) => {
let lineNumbers = theme.getColor(editorLineNumbers);
const lineNumbers = theme.getColor(editorLineNumbers);
if (lineNumbers) {
collector.addRule(`.monaco-editor .line-numbers { color: ${lineNumbers}; }`);
}

View File

@@ -2,10 +2,9 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { HorizontalRange } from 'vs/editor/common/view/renderingContext';
import { Constants } from 'vs/editor/common/core/uint';
import { HorizontalRange } from 'vs/editor/common/view/renderingContext';
class FloatHorizontalRange {
_floatHorizontalRangeBrand: void;
@@ -49,7 +48,7 @@ export class RangeUtil {
range.selectNodeContents(endNode);
}
private static _readClientRects(startElement: Node, startOffset: number, endElement: Node, endOffset: number, endNode: HTMLElement): ClientRectList {
private static _readClientRects(startElement: Node, startOffset: number, endElement: Node, endOffset: number, endNode: HTMLElement): ClientRectList | DOMRectList | null {
let range = this._createRange();
try {
range.setStart(startElement, startOffset);
@@ -95,7 +94,7 @@ export class RangeUtil {
return result;
}
private static _createHorizontalRangesFromClientRects(clientRects: ClientRectList, clientRectDeltaLeft: number): HorizontalRange[] {
private static _createHorizontalRangesFromClientRects(clientRects: ClientRectList | DOMRectList | null, clientRectDeltaLeft: number): HorizontalRange[] | null {
if (!clientRects || clientRects.length === 0) {
return null;
}
@@ -112,7 +111,7 @@ export class RangeUtil {
return this._mergeAdjacentRanges(result);
}
public static readHorizontalRanges(domNode: HTMLElement, startChildIndex: number, startOffset: number, endChildIndex: number, endOffset: number, clientRectDeltaLeft: number, endNode: HTMLElement): HorizontalRange[] {
public static readHorizontalRanges(domNode: HTMLElement, startChildIndex: number, startOffset: number, endChildIndex: number, endOffset: number, clientRectDeltaLeft: number, endNode: HTMLElement): HorizontalRange[] | null {
// Panic check
let min = 0;
let max = domNode.children.length - 1;
@@ -150,8 +149,8 @@ export class RangeUtil {
return null;
}
startOffset = Math.min(startElement.textContent.length, Math.max(0, startOffset));
endOffset = Math.min(endElement.textContent.length, Math.max(0, endOffset));
startOffset = Math.min(startElement.textContent!.length, Math.max(0, startOffset));
endOffset = Math.min(endElement.textContent!.length, Math.max(0, endOffset));
let clientRects = this._readClientRects(startElement, startOffset, endElement, endOffset, endNode);
return this._createHorizontalRangesFromClientRects(clientRects, clientRectDeltaLeft);

View File

@@ -2,21 +2,20 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as browser from 'vs/base/browser/browser';
import * as platform from 'vs/base/common/platform';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { IConfiguration } from 'vs/editor/common/editorCommon';
import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations';
import { renderViewLine, RenderLineInput, CharacterMapping, ForeignElementType } from 'vs/editor/common/viewLayout/viewLineRenderer';
import * as platform from 'vs/base/common/platform';
import { IVisibleLine } from 'vs/editor/browser/view/viewLayer';
import { RangeUtil } from 'vs/editor/browser/viewParts/lines/rangeUtil';
import { HorizontalRange } from 'vs/editor/common/view/renderingContext';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
import { ThemeType, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService';
import { IStringBuilder } from 'vs/editor/common/core/stringBuilder';
import { IConfiguration } from 'vs/editor/common/editorCommon';
import { HorizontalRange } from 'vs/editor/common/view/renderingContext';
import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations';
import { CharacterMapping, ForeignElementType, RenderLineInput, renderViewLine } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
import { InlineDecorationType } from 'vs/editor/common/viewModel/viewModel';
import { HIGH_CONTRAST, ThemeType } from 'vs/platform/theme/common/themeService';
const canUseFastRenderedViewLine = (function () {
if (platform.isNative) {
@@ -74,6 +73,7 @@ export class ViewLineOptions {
public readonly renderControlCharacters: boolean;
public readonly spaceWidth: number;
public readonly useMonospaceOptimizations: boolean;
public readonly canUseHalfwidthRightwardsArrow: boolean;
public readonly lineHeight: number;
public readonly stopRenderingLineAfter: number;
public readonly fontLigatures: boolean;
@@ -87,6 +87,7 @@ export class ViewLineOptions {
config.editor.fontInfo.isMonospace
&& !config.editor.viewInfo.disableMonospaceOptimizations
);
this.canUseHalfwidthRightwardsArrow = config.editor.fontInfo.canUseHalfwidthRightwardsArrow;
this.lineHeight = config.editor.lineHeight;
this.stopRenderingLineAfter = config.editor.viewInfo.stopRenderingLineAfter;
this.fontLigatures = config.editor.viewInfo.fontLigatures;
@@ -99,6 +100,7 @@ export class ViewLineOptions {
&& this.renderControlCharacters === other.renderControlCharacters
&& this.spaceWidth === other.spaceWidth
&& this.useMonospaceOptimizations === other.useMonospaceOptimizations
&& this.canUseHalfwidthRightwardsArrow === other.canUseHalfwidthRightwardsArrow
&& this.lineHeight === other.lineHeight
&& this.stopRenderingLineAfter === other.stopRenderingLineAfter
&& this.fontLigatures === other.fontLigatures
@@ -112,7 +114,7 @@ export class ViewLine implements IVisibleLine {
private _options: ViewLineOptions;
private _isMaybeInvalid: boolean;
private _renderedViewLine: IRenderedViewLine;
private _renderedViewLine: IRenderedViewLine | null;
constructor(options: ViewLineOptions) {
this._options = options;
@@ -122,7 +124,7 @@ export class ViewLine implements IVisibleLine {
// --- begin IVisibleLineData
public getDomNode(): HTMLElement {
public getDomNode(): HTMLElement | null {
if (this._renderedViewLine && this._renderedViewLine.domNode) {
return this._renderedViewLine.domNode.domNode;
}
@@ -190,6 +192,7 @@ export class ViewLine implements IVisibleLine {
let renderLineInput = new RenderLineInput(
options.useMonospaceOptimizations,
options.canUseHalfwidthRightwardsArrow,
lineData.content,
lineData.continuesWithWrappedLine,
lineData.isBasicASCII,
@@ -222,7 +225,7 @@ export class ViewLine implements IVisibleLine {
sb.appendASCIIString('</div>');
let renderedViewLine: IRenderedViewLine = null;
let renderedViewLine: IRenderedViewLine | null = null;
if (canUseFastRenderedViewLine && lineData.isBasicASCII && options.useMonospaceOptimizations && output.containsForeignElements === ForeignElementType.None) {
if (lineData.content.length < 300 && renderLineInput.lineTokens.getCount() < 100) {
// Browser rounding errors have been observed in Chrome and IE, so using the fast
@@ -279,7 +282,10 @@ export class ViewLine implements IVisibleLine {
return this._renderedViewLine.getWidthIsFast();
}
public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] {
public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
if (!this._renderedViewLine) {
return null;
}
startColumn = startColumn | 0; // @perf
endColumn = endColumn | 0; // @perf
@@ -305,16 +311,19 @@ export class ViewLine implements IVisibleLine {
}
public getColumnOfNodeOffset(lineNumber: number, spanNode: HTMLElement, offset: number): number {
if (!this._renderedViewLine) {
return 1;
}
return this._renderedViewLine.getColumnOfNodeOffset(lineNumber, spanNode, offset);
}
}
interface IRenderedViewLine {
domNode: FastDomNode<HTMLElement>;
domNode: FastDomNode<HTMLElement> | null;
readonly input: RenderLineInput;
getWidth(): number;
getWidthIsFast(): boolean;
getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[];
getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null;
getColumnOfNodeOffset(lineNumber: number, spanNode: HTMLElement, offset: number): number;
}
@@ -323,13 +332,13 @@ interface IRenderedViewLine {
*/
class FastRenderedViewLine implements IRenderedViewLine {
public domNode: FastDomNode<HTMLElement>;
public domNode: FastDomNode<HTMLElement> | null;
public readonly input: RenderLineInput;
private readonly _characterMapping: CharacterMapping;
private readonly _charWidth: number;
constructor(domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping) {
constructor(domNode: FastDomNode<HTMLElement> | null, renderLineInput: RenderLineInput, characterMapping: CharacterMapping) {
this.domNode = domNode;
this.input = renderLineInput;
@@ -345,7 +354,7 @@ class FastRenderedViewLine implements IRenderedViewLine {
return true;
}
public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] {
public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
const startPosition = this._getCharPosition(startColumn);
const endPosition = this._getCharPosition(endColumn);
return [new HorizontalRange(startPosition, endPosition - startPosition)];
@@ -361,7 +370,7 @@ class FastRenderedViewLine implements IRenderedViewLine {
}
public getColumnOfNodeOffset(lineNumber: number, spanNode: HTMLElement, offset: number): number {
let spanNodeTextContentLength = spanNode.textContent.length;
let spanNodeTextContentLength = spanNode.textContent!.length;
let spanIndex = -1;
while (spanNode) {
@@ -390,7 +399,7 @@ class RenderedViewLine implements IRenderedViewLine {
/**
* This is a map that is used only when the line is guaranteed to have no RTL text.
*/
private _pixelOffsetCache: Int32Array;
private _pixelOffsetCache: Int32Array | null;
constructor(domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType) {
this.domNode = domNode;
@@ -435,7 +444,7 @@ class RenderedViewLine implements IRenderedViewLine {
/**
* Visible ranges for a model range
*/
public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] {
public getVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
if (this._pixelOffsetCache !== null) {
// the text is LTR
let startOffset = this._readPixelOffset(startColumn, context);
@@ -454,7 +463,7 @@ class RenderedViewLine implements IRenderedViewLine {
return this._readVisibleRangesForRange(startColumn, endColumn, context);
}
protected _readVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] {
protected _readVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
if (startColumn === endColumn) {
let pixelOffset = this._readPixelOffset(startColumn, context);
if (pixelOffset === -1) {
@@ -526,7 +535,7 @@ class RenderedViewLine implements IRenderedViewLine {
return r[0].left;
}
private _readRawVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] {
private _readRawVisibleRangesForRange(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
@@ -549,7 +558,7 @@ class RenderedViewLine implements IRenderedViewLine {
* Returns the column for the text found at a specific offset inside a rendered dom node
*/
public getColumnOfNodeOffset(lineNumber: number, spanNode: HTMLElement, offset: number): number {
let spanNodeTextContentLength = spanNode.textContent.length;
let spanNodeTextContentLength = spanNode.textContent!.length;
let spanIndex = -1;
while (spanNode) {
@@ -563,7 +572,7 @@ class RenderedViewLine implements IRenderedViewLine {
}
class WebKitRenderedViewLine extends RenderedViewLine {
protected _readVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] {
protected _readVisibleRangesForRange(startColumn: number, endColumn: number, context: DomReadingContext): HorizontalRange[] | null {
let output = super._readVisibleRangesForRange(startColumn, endColumn, context);
if (!output || output.length === 0 || startColumn === endColumn || (startColumn === 1 && endColumn === this._characterMapping.length)) {
@@ -572,20 +581,16 @@ class WebKitRenderedViewLine extends RenderedViewLine {
// WebKit is buggy and returns an expanded range (to contain words in some cases)
// The last client rect is enlarged (I think)
// This is an attempt to patch things up
// Find position of previous column
let beforeEndPixelOffset = this._readPixelOffset(endColumn - 1, context);
// Find position of last column
let endPixelOffset = this._readPixelOffset(endColumn, context);
if (beforeEndPixelOffset !== -1 && endPixelOffset !== -1) {
let isLTR = (beforeEndPixelOffset <= endPixelOffset);
let lastRange = output[output.length - 1];
if (isLTR && lastRange.left < endPixelOffset) {
// Trim down the width of the last visible range to not go after the last column's position
lastRange.width = endPixelOffset - lastRange.left;
if (!this.input.containsRTL) {
// This is an attempt to patch things up
// Find position of last column
let endPixelOffset = this._readPixelOffset(endColumn, context);
if (endPixelOffset !== -1) {
let lastRange = output[output.length - 1];
if (lastRange.left < endPixelOffset) {
// Trim down the width of the last visible range to not go after the last column's position
lastRange.width = endPixelOffset - lastRange.left;
}
}
}
@@ -593,7 +598,7 @@ class WebKitRenderedViewLine extends RenderedViewLine {
}
}
const createRenderedLine: (domNode: FastDomNode<HTMLElement>, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType) => RenderedViewLine = (function () {
const createRenderedLine: (domNode: FastDomNode<HTMLElement> | null, renderLineInput: RenderLineInput, characterMapping: CharacterMapping, containsRTL: boolean, containsForeignElements: ForeignElementType) => RenderedViewLine = (function () {
if (browser.isWebKit) {
return createWebKitRenderedLine;
}

View File

@@ -2,23 +2,22 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./viewLines';
import { RunOnceScheduler } from 'vs/base/common/async';
import { FastDomNode } from 'vs/base/browser/fastDomNode';
import { Range } from 'vs/editor/common/core/range';
import { Position } from 'vs/editor/common/core/position';
import { VisibleLinesCollection, IVisibleLinesHost } from 'vs/editor/browser/view/viewLayer';
import { ViewLineOptions, DomReadingContext, ViewLine } from 'vs/editor/browser/viewParts/lines/viewLine';
import { RunOnceScheduler } from 'vs/base/common/async';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
import { IViewLines, HorizontalRange, LineVisibleRanges } from 'vs/editor/common/view/renderingContext';
import { Viewport } from 'vs/editor/common/viewModel/viewModel';
import { ViewPart, PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPart';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { IVisibleLinesHost, VisibleLinesCollection } from 'vs/editor/browser/view/viewLayer';
import { PartFingerprint, PartFingerprints, ViewPart } from 'vs/editor/browser/view/viewPart';
import { DomReadingContext, ViewLine, ViewLineOptions } from 'vs/editor/browser/viewParts/lines/viewLine';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { ScrollType } from 'vs/editor/common/editorCommon';
import { HorizontalRange, IViewLines, LineVisibleRanges } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
import { Viewport } from 'vs/editor/common/viewModel/viewModel';
class LastRenderedData {
@@ -58,7 +57,7 @@ class HorizontalRevealRequest {
export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>, IViewLines {
/**
* Adds this ammount of pixels to the right of lines (no-one wants to type near the edge of the viewport)
* Adds this amount of pixels to the right of lines (no-one wants to type near the edge of the viewport)
*/
private static readonly HORIZONTAL_EXTRA_PX = 30;
@@ -79,7 +78,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
private _maxLineWidth: number;
private _asyncUpdateLineWidths: RunOnceScheduler;
private _horizontalRevealRequest: HorizontalRevealRequest;
private _horizontalRevealRequest: HorizontalRevealRequest | null;
private _lastRenderedData: LastRenderedData;
constructor(context: ViewContext, linesContent: FastDomNode<HTMLElement>) {
@@ -282,7 +281,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
// ----------- HELPERS FOR OTHERS
public getPositionFromDOMInfo(spanNode: HTMLElement, offset: number): Position {
public getPositionFromDOMInfo(spanNode: HTMLElement, offset: number): Position | null {
let viewLineDomNode = this._getViewLineDomNode(spanNode);
if (viewLineDomNode === null) {
// Couldn't find view line node
@@ -320,7 +319,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
return new Position(lineNumber, column);
}
private _getViewLineDomNode(node: HTMLElement): HTMLElement {
private _getViewLineDomNode(node: HTMLElement | null): HTMLElement | null {
while (node && node.nodeType === 1) {
if (node.className === ViewLine.CLASS_NAME) {
return node;
@@ -356,15 +355,15 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
return this._visibleLines.getVisibleLine(lineNumber).getWidth();
}
public linesVisibleRangesForRange(range: Range, includeNewLines: boolean): LineVisibleRanges[] {
public linesVisibleRangesForRange(_range: Range, includeNewLines: boolean): LineVisibleRanges[] | null {
if (this.shouldRender()) {
// Cannot read from the DOM because it is dirty
// i.e. the model & the dom are out of sync, so I'd be reading something stale
return null;
}
let originalEndLineNumber = range.endLineNumber;
range = Range.intersectRanges(range, this._lastRenderedData.getCurrentVisibleRange());
let originalEndLineNumber = _range.endLineNumber;
const range = Range.intersectRanges(_range, this._lastRenderedData.getCurrentVisibleRange());
if (!range) {
return null;
}
@@ -372,7 +371,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
let visibleRanges: LineVisibleRanges[] = [], visibleRangesLen = 0;
let domReadingContext = new DomReadingContext(this.domNode.domNode, this._textRangeRestingSpot);
let nextLineModelLineNumber: number;
let nextLineModelLineNumber: number = 0;
if (includeNewLines) {
nextLineModelLineNumber = this._context.model.coordinatesConverter.convertViewPositionToModelPosition(new Position(range.startLineNumber, 1)).lineNumber;
}
@@ -412,7 +411,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
return visibleRanges;
}
public visibleRangesForRange2(range: Range): HorizontalRange[] {
private visibleRangesForRange2(_range: Range): HorizontalRange[] | null {
if (this.shouldRender()) {
// Cannot read from the DOM because it is dirty
@@ -420,7 +419,7 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
return null;
}
range = Range.intersectRanges(range, this._lastRenderedData.getCurrentVisibleRange());
const range = Range.intersectRanges(_range, this._lastRenderedData.getCurrentVisibleRange());
if (!range) {
return null;
}
@@ -454,6 +453,14 @@ export class ViewLines extends ViewPart implements IVisibleLinesHost<ViewLine>,
return result;
}
public visibleRangeForPosition(position: Position): HorizontalRange | null {
const visibleRanges = this.visibleRangesForRange2(new Range(position.lineNumber, position.column, position.lineNumber, position.column));
if (!visibleRanges) {
return null;
}
return visibleRanges[0];
}
// --- implementation
public updateLineWidths(): void {

View File

@@ -3,12 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./linesDecorations';
import { DecorationToRender, DedupOverlay } from 'vs/editor/browser/viewParts/glyphMargin/glyphMargin';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
export class LinesDecorationsOverlay extends DedupOverlay {
@@ -17,7 +15,7 @@ export class LinesDecorationsOverlay extends DedupOverlay {
private _decorationsLeft: number;
private _decorationsWidth: number;
private _renderResult: string[];
private _renderResult: string[] | null;
constructor(context: ViewContext) {
super();
@@ -30,7 +28,6 @@ export class LinesDecorationsOverlay extends DedupOverlay {
public dispose(): void {
this._context.removeEventHandler(this);
this._context = null;
this._renderResult = null;
super.dispose();
}

View File

@@ -3,12 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { ViewPart } from 'vs/editor/browser/view/viewPart';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
export class Margin extends ViewPart {

View File

@@ -3,17 +3,15 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./marginDecorations';
import { DecorationToRender, DedupOverlay } from 'vs/editor/browser/viewParts/glyphMargin/glyphMargin';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
export class MarginViewLineDecorationsOverlay extends DedupOverlay {
private _context: ViewContext;
private _renderResult: string[];
private _renderResult: string[] | null;
constructor(context: ViewContext) {
super();
@@ -24,7 +22,6 @@ export class MarginViewLineDecorationsOverlay extends DedupOverlay {
public dispose(): void {
this._context.removeEventHandler(this);
this._context = null;
this._renderResult = null;
super.dispose();
}

View File

@@ -3,38 +3,29 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./minimap';
import { ViewPart, PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPart';
import * as strings from 'vs/base/common/strings';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { getOrCreateMinimapCharRenderer } from 'vs/editor/common/view/runtimeMinimapCharRenderer';
import * as dom from 'vs/base/browser/dom';
import { MinimapCharRenderer, MinimapTokensColorTracker, Constants } from 'vs/editor/common/view/minimapCharRenderer';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { CharCode } from 'vs/base/common/charCode';
import { ViewLineData } from 'vs/editor/common/viewModel/viewModel';
import { ColorId } from 'vs/editor/common/modes';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { GlobalMouseMoveMonitor, IStandardMouseMoveEventData, standardMouseMoveMerger } from 'vs/base/browser/globalMouseMoveMonitor';
import { CharCode } from 'vs/base/common/charCode';
import { IDisposable } from 'vs/base/common/lifecycle';
import { RenderedLinesCollection, ILine } from 'vs/editor/browser/view/viewLayer';
import * as platform from 'vs/base/common/platform';
import * as strings from 'vs/base/common/strings';
import { ILine, RenderedLinesCollection } from 'vs/editor/browser/view/viewLayer';
import { PartFingerprint, PartFingerprints, ViewPart } from 'vs/editor/browser/view/viewPart';
import { RenderMinimap } from 'vs/editor/common/config/editorOptions';
import { Range } from 'vs/editor/common/core/range';
import { RGBA8 } from 'vs/editor/common/core/rgba';
import { IConfiguration, ScrollType } from 'vs/editor/common/editorCommon';
import { ColorId } from 'vs/editor/common/modes';
import { Constants, MinimapCharRenderer, MinimapTokensColorTracker } from 'vs/editor/common/view/minimapCharRenderer';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { getOrCreateMinimapCharRenderer } from 'vs/editor/common/view/runtimeMinimapCharRenderer';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { GlobalMouseMoveMonitor, IStandardMouseMoveEventData, standardMouseMoveMerger } from 'vs/base/browser/globalMouseMoveMonitor';
import * as platform from 'vs/base/common/platform';
import { ViewLineData } from 'vs/editor/common/viewModel/viewModel';
import { scrollbarShadow, scrollbarSliderActiveBackground, scrollbarSliderBackground, scrollbarSliderHoverBackground } from 'vs/platform/theme/common/colorRegistry';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { scrollbarSliderBackground, scrollbarSliderHoverBackground, scrollbarSliderActiveBackground, scrollbarShadow } from 'vs/platform/theme/common/colorRegistry';
const enum RenderMinimap {
None = 0,
Small = 1,
Large = 2,
SmallBlocks = 3,
LargeBlocks = 4,
}
function getMinimapLineHeight(renderMinimap: RenderMinimap): number {
if (renderMinimap === RenderMinimap.Large) {
@@ -114,7 +105,7 @@ class MinimapOptions {
*/
public readonly canvasOuterHeight: number;
constructor(configuration: editorCommon.IConfiguration) {
constructor(configuration: IConfiguration) {
const pixelRatio = configuration.editor.pixelRatio;
const layoutInfo = configuration.editor.layoutInfo;
const viewInfo = configuration.editor.viewInfo;
@@ -222,7 +213,7 @@ class MinimapLayout {
lineCount: number,
scrollTop: number,
scrollHeight: number,
previousLayout: MinimapLayout
previousLayout: MinimapLayout | null
): MinimapLayout {
const pixelRatio = options.pixelRatio;
const minimapLineHeight = getMinimapLineHeight(options.renderMinimap);
@@ -447,8 +438,8 @@ export class Minimap extends ViewPart {
private readonly _sliderMouseDownListener: IDisposable;
private _options: MinimapOptions;
private _lastRenderData: RenderData;
private _buffers: MinimapBuffers;
private _lastRenderData: RenderData | null;
private _buffers: MinimapBuffers | null;
constructor(context: ViewContext) {
super(context);
@@ -509,7 +500,7 @@ export class Minimap extends ViewPart {
new Range(lineNumber, 1, lineNumber, 1),
viewEvents.VerticalRevealType.Center,
false,
editorCommon.ScrollType.Smooth
ScrollType.Smooth
));
});
@@ -583,13 +574,13 @@ export class Minimap extends ViewPart {
private _getBuffer(): ImageData {
if (!this._buffers) {
this._buffers = new MinimapBuffers(
this._canvas.domNode.getContext('2d'),
this._canvas.domNode.getContext('2d')!,
this._options.canvasInnerWidth,
this._options.canvasInnerHeight,
this._tokensColorTracker.getColor(ColorId.DefaultBackground)
);
}
return this._buffers.getBuffer();
return this._buffers!.getBuffer();
}
private _onOptionsMaybeChanged(): boolean {
@@ -742,7 +733,7 @@ export class Minimap extends ViewPart {
getOrCreateMinimapCharRenderer(),
dy,
tabSize,
lineInfo.data[lineIndex]
lineInfo.data[lineIndex]!
);
}
renderedLines[lineIndex] = new MinimapLine(dy);
@@ -754,7 +745,7 @@ export class Minimap extends ViewPart {
const dirtyHeight = dirtyY2 - dirtyY1;
// Finally, paint to the canvas
const ctx = this._canvas.domNode.getContext('2d');
const ctx = this._canvas.domNode.getContext('2d')!;
ctx.putImageData(imageData, 0, 0, 0, dirtyY1, imageData.width, dirtyHeight);
// Save rendered data for reuse on next frame if possible
@@ -770,7 +761,7 @@ export class Minimap extends ViewPart {
startLineNumber: number,
endLineNumber: number,
minimapLineHeight: number,
lastRenderData: RenderData,
lastRenderData: RenderData | null,
): [number, number, boolean[]] {
let needed: boolean[] = [];

View File

@@ -3,19 +3,17 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./overlayWidgets';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { IOverlayWidget, OverlayWidgetPositionPreference } from 'vs/editor/browser/editorBrowser';
import { ViewPart, PartFingerprint, PartFingerprints } from 'vs/editor/browser/view/viewPart';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { PartFingerprint, PartFingerprints, ViewPart } from 'vs/editor/browser/view/viewPart';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
interface IWidgetData {
widget: IOverlayWidget;
preference: OverlayWidgetPositionPreference;
preference: OverlayWidgetPositionPreference | null;
domNode: FastDomNode<HTMLElement>;
}
@@ -51,7 +49,7 @@ export class ViewOverlayWidgets extends ViewPart {
public dispose(): void {
super.dispose();
this._widgets = null;
this._widgets = {};
}
public getDomNode(): FastDomNode<HTMLElement> {
@@ -91,7 +89,7 @@ export class ViewOverlayWidgets extends ViewPart {
this.setShouldRender();
}
public setWidgetPosition(widget: IOverlayWidget, preference: OverlayWidgetPositionPreference): boolean {
public setWidgetPosition(widget: IOverlayWidget, preference: OverlayWidgetPositionPreference | null): boolean {
let widgetData = this._widgets[widget.getId()];
if (widgetData.preference === preference) {
return false;
@@ -110,7 +108,7 @@ export class ViewOverlayWidgets extends ViewPart {
const domNode = widgetData.domNode.domNode;
delete this._widgets[widgetId];
domNode.parentNode.removeChild(domNode);
domNode.parentNode!.removeChild(domNode);
this.setShouldRender();
}
}

View File

@@ -2,20 +2,19 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { ViewPart } from 'vs/editor/browser/view/viewPart';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { Position } from 'vs/editor/common/core/position';
import { TokenizationRegistry } from 'vs/editor/common/modes';
import { IDisposable } from 'vs/base/common/lifecycle';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { editorOverviewRulerBorder, editorCursorForeground } from 'vs/editor/common/view/editorColorRegistry';
import { Color } from 'vs/base/common/color';
import { ITheme } from 'vs/platform/theme/common/themeService';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { Color } from 'vs/base/common/color';
import { IDisposable } from 'vs/base/common/lifecycle';
import { ViewPart } from 'vs/editor/browser/view/viewPart';
import { Position } from 'vs/editor/common/core/position';
import { IConfiguration } from 'vs/editor/common/editorCommon';
import { TokenizationRegistry } from 'vs/editor/common/modes';
import { editorCursorForeground, editorOverviewRulerBorder } from 'vs/editor/common/view/editorColorRegistry';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { ITheme } from 'vs/platform/theme/common/themeService';
class Settings {
@@ -24,13 +23,13 @@ class Settings {
public readonly overviewRulerLanes: number;
public readonly renderBorder: boolean;
public readonly borderColor: string;
public readonly borderColor: string | null;
public readonly hideCursor: boolean;
public readonly cursorColor: string;
public readonly cursorColor: string | null;
public readonly themeType: 'light' | 'dark' | 'hc';
public readonly backgroundColor: string;
public readonly backgroundColor: string | null;
public readonly top: number;
public readonly right: number;
@@ -42,7 +41,7 @@ class Settings {
public readonly x: number[];
public readonly w: number[];
constructor(config: editorCommon.IConfiguration, theme: ITheme) {
constructor(config: IConfiguration, theme: ITheme) {
this.lineHeight = config.editor.lineHeight;
this.pixelRatio = config.editor.pixelRatio;
this.overviewRulerLanes = config.editor.viewInfo.overviewRulerLanes;
@@ -214,7 +213,6 @@ export class DecorationsOverviewRuler extends ViewPart {
this._domNode.setLayerHinting(true);
this._domNode.setAttribute('aria-hidden', 'true');
this._settings = null;
this._updateSettings(false);
this._tokensColorTrackerListener = TokenizationRegistry.onDidChange((e) => {
@@ -233,7 +231,7 @@ export class DecorationsOverviewRuler extends ViewPart {
private _updateSettings(renderNow: boolean): boolean {
const newSettings = new Settings(this._context.configuration, this._context.theme);
if (this._settings !== null && this._settings.equals(newSettings)) {
if (this._settings && this._settings.equals(newSettings)) {
// nothing to do
return false;
}
@@ -311,7 +309,7 @@ export class DecorationsOverviewRuler extends ViewPart {
const minDecorationHeight = (Constants.MIN_DECORATION_HEIGHT * this._settings.pixelRatio) | 0;
const halfMinDecorationHeight = (minDecorationHeight / 2) | 0;
const canvasCtx = this._domNode.domNode.getContext('2d');
const canvasCtx = this._domNode.domNode.getContext('2d')!;
if (this._settings.backgroundColor === null) {
canvasCtx.clearRect(0, 0, canvasWidth, canvasHeight);
} else {
@@ -373,7 +371,7 @@ export class DecorationsOverviewRuler extends ViewPart {
}
// Draw cursors
if (!this._settings.hideCursor) {
if (!this._settings.hideCursor && this._settings.cursorColor) {
const cursorHeight = (2 * this._settings.pixelRatio) | 0;
const halfCursorHeight = (cursorHeight / 2) | 0;
const cursorX = this._settings.x[OverviewRulerLane.Full];

View File

@@ -2,15 +2,14 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { IOverviewRuler } from 'vs/editor/browser/editorBrowser';
import { OverviewRulerPosition } from 'vs/editor/common/config/editorOptions';
import { ColorZone, OverviewRulerZone, OverviewZoneManager } from 'vs/editor/common/view/overviewZoneManager';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { OverviewRulerPosition } from 'vs/editor/common/config/editorOptions';
import { OverviewRulerZone, OverviewZoneManager, ColorZone } from 'vs/editor/common/view/overviewZoneManager';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
export class OverviewRuler extends ViewEventHandler implements IOverviewRuler {
@@ -40,7 +39,6 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler {
public dispose(): void {
this._context.removeEventHandler(this);
this._zoneManager = null;
super.dispose();
}
@@ -119,7 +117,7 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler {
let colorZones = this._zoneManager.resolveColorZones();
let id2Color = this._zoneManager.getId2Color();
let ctx = this._domNode.domNode.getContext('2d');
let ctx = this._domNode.domNode.getContext('2d')!;
ctx.clearRect(0, 0, width, height);
if (colorZones.length > 0) {
this._renderOneLane(ctx, colorZones, id2Color, width);

View File

@@ -3,16 +3,14 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./rulers';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { ViewPart } from 'vs/editor/browser/view/viewPart';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { editorRuler } from 'vs/editor/common/view/editorColorRegistry';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { editorRuler } from 'vs/editor/common/view/editorColorRegistry';
export class Rulers extends ViewPart {
@@ -81,7 +79,7 @@ export class Rulers extends ViewPart {
let removeCount = currentCount - desiredCount;
while (removeCount > 0) {
let node = this._renderedRulers.pop();
let node = this._renderedRulers.pop()!;
this.domNode.removeChild(node);
removeCount--;
}
@@ -101,7 +99,7 @@ export class Rulers extends ViewPart {
}
registerThemingParticipant((theme, collector) => {
let rulerColor = theme.getColor(editorRuler);
const rulerColor = theme.getColor(editorRuler);
if (rulerColor) {
collector.addRule(`.monaco-editor .view-ruler { box-shadow: 1px 0 0 0 ${rulerColor} inset; }`);
}

View File

@@ -3,16 +3,14 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./scrollDecoration';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { ViewPart } from 'vs/editor/browser/view/viewPart';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
export class ScrollDecorationViewPart extends ViewPart {
@@ -97,7 +95,7 @@ export class ScrollDecorationViewPart extends ViewPart {
}
registerThemingParticipant((theme, collector) => {
let shadow = theme.getColor(scrollbarShadow);
const shadow = theme.getColor(scrollbarShadow);
if (shadow) {
collector.addRule(`.monaco-editor .scroll-decoration { box-shadow: ${shadow} 0 6px 6px -6px inset; }`);
}

View File

@@ -3,17 +3,15 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./selections';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { editorSelectionBackground, editorInactiveSelection, editorSelectionForeground } from 'vs/platform/theme/common/colorRegistry';
import { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { HorizontalRange, LineVisibleRanges, RenderingContext } from 'vs/editor/common/view/renderingContext';
import { Range } from 'vs/editor/common/core/range';
import * as browser from 'vs/base/browser/browser';
import { DynamicViewOverlay } from 'vs/editor/browser/view/dynamicViewOverlay';
import { Range } from 'vs/editor/common/core/range';
import { HorizontalRange, LineVisibleRanges, RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { editorInactiveSelection, editorSelectionBackground, editorSelectionForeground } from 'vs/platform/theme/common/colorRegistry';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
const enum CornerStyle {
EXTERN,
@@ -29,8 +27,8 @@ interface IVisibleRangeEndPointStyle {
class HorizontalRangeWithStyle {
public left: number;
public width: number;
public startStyle: IVisibleRangeEndPointStyle;
public endStyle: IVisibleRangeEndPointStyle;
public startStyle: IVisibleRangeEndPointStyle | null;
public endStyle: IVisibleRangeEndPointStyle | null;
constructor(other: HorizontalRange) {
this.left = other.left;
@@ -80,7 +78,7 @@ export class SelectionsOverlay extends DynamicViewOverlay {
private _roundedSelection: boolean;
private _typicalHalfwidthCharacterWidth: number;
private _selections: Range[];
private _renderResult: string[];
private _renderResult: string[] | null;
constructor(context: ViewContext) {
super();
@@ -95,8 +93,6 @@ export class SelectionsOverlay extends DynamicViewOverlay {
public dispose(): void {
this._context.removeEventHandler(this);
this._context = null;
this._selections = null;
this._renderResult = null;
super.dispose();
}
@@ -158,10 +154,10 @@ export class SelectionsOverlay extends DynamicViewOverlay {
return false;
}
private _enrichVisibleRangesWithStyle(viewport: Range, linesVisibleRanges: LineVisibleRangesWithStyle[], previousFrame: LineVisibleRangesWithStyle[]): void {
private _enrichVisibleRangesWithStyle(viewport: Range, linesVisibleRanges: LineVisibleRangesWithStyle[], previousFrame: LineVisibleRangesWithStyle[] | null): void {
const epsilon = this._typicalHalfwidthCharacterWidth / 4;
let previousFrameTop: HorizontalRangeWithStyle = null;
let previousFrameBottom: HorizontalRangeWithStyle = null;
let previousFrameTop: HorizontalRangeWithStyle | null = null;
let previousFrameBottom: HorizontalRangeWithStyle | null = null;
if (previousFrame && previousFrame.length > 0 && linesVisibleRanges.length > 0) {
@@ -225,8 +221,8 @@ export class SelectionsOverlay extends DynamicViewOverlay {
}
} else if (previousFrameTop) {
// Accept some hick-ups near the viewport edges to save on repaints
startStyle.top = previousFrameTop.startStyle.top;
endStyle.top = previousFrameTop.endStyle.top;
startStyle.top = previousFrameTop.startStyle!.top;
endStyle.top = previousFrameTop.endStyle!.top;
}
if (i + 1 < len) {
@@ -247,8 +243,8 @@ export class SelectionsOverlay extends DynamicViewOverlay {
}
} else if (previousFrameBottom) {
// Accept some hick-ups near the viewport edges to save on repaints
startStyle.bottom = previousFrameBottom.startStyle.bottom;
endStyle.bottom = previousFrameBottom.endStyle.bottom;
startStyle.bottom = previousFrameBottom.startStyle!.bottom;
endStyle.bottom = previousFrameBottom.endStyle!.bottom;
}
curLineRange.startStyle = startStyle;
@@ -256,7 +252,7 @@ export class SelectionsOverlay extends DynamicViewOverlay {
}
}
private _getVisibleRangesWithStyle(selection: Range, ctx: RenderingContext, previousFrame: LineVisibleRangesWithStyle[]): LineVisibleRangesWithStyle[] {
private _getVisibleRangesWithStyle(selection: Range, ctx: RenderingContext, previousFrame: LineVisibleRangesWithStyle[] | null): LineVisibleRangesWithStyle[] {
let _linesVisibleRanges = ctx.linesVisibleRangesForRange(selection, true) || [];
let linesVisibleRanges = _linesVisibleRanges.map(toStyled);
let visibleRangesHaveGaps = this._visibleRangesHaveGaps(linesVisibleRanges);
@@ -307,7 +303,9 @@ export class SelectionsOverlay extends DynamicViewOverlay {
let visibleRange = lineVisibleRanges.ranges[j];
if (visibleRangesHaveStyle) {
if (visibleRange.startStyle.top === CornerStyle.INTERN || visibleRange.startStyle.bottom === CornerStyle.INTERN) {
const startStyle = visibleRange.startStyle!;
const endStyle = visibleRange.endStyle!;
if (startStyle.top === CornerStyle.INTERN || startStyle.bottom === CornerStyle.INTERN) {
// Reverse rounded corner to the left
// First comes the selection (blue layer)
@@ -315,15 +313,15 @@ export class SelectionsOverlay extends DynamicViewOverlay {
// Second comes the background (white layer) with inverse border radius
let className = SelectionsOverlay.EDITOR_BACKGROUND_CLASS_NAME;
if (visibleRange.startStyle.top === CornerStyle.INTERN) {
if (startStyle.top === CornerStyle.INTERN) {
className += ' ' + SelectionsOverlay.SELECTION_TOP_RIGHT;
}
if (visibleRange.startStyle.bottom === CornerStyle.INTERN) {
if (startStyle.bottom === CornerStyle.INTERN) {
className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_RIGHT;
}
lineOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left - SelectionsOverlay.ROUNDED_PIECE_WIDTH, SelectionsOverlay.ROUNDED_PIECE_WIDTH);
}
if (visibleRange.endStyle.top === CornerStyle.INTERN || visibleRange.endStyle.bottom === CornerStyle.INTERN) {
if (endStyle.top === CornerStyle.INTERN || endStyle.bottom === CornerStyle.INTERN) {
// Reverse rounded corner to the right
// First comes the selection (blue layer)
@@ -331,10 +329,10 @@ export class SelectionsOverlay extends DynamicViewOverlay {
// Second comes the background (white layer) with inverse border radius
let className = SelectionsOverlay.EDITOR_BACKGROUND_CLASS_NAME;
if (visibleRange.endStyle.top === CornerStyle.INTERN) {
if (endStyle.top === CornerStyle.INTERN) {
className += ' ' + SelectionsOverlay.SELECTION_TOP_LEFT;
}
if (visibleRange.endStyle.bottom === CornerStyle.INTERN) {
if (endStyle.bottom === CornerStyle.INTERN) {
className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_LEFT;
}
lineOutput += this._createSelectionPiece(top, lineHeight, className, visibleRange.left + visibleRange.width, SelectionsOverlay.ROUNDED_PIECE_WIDTH);
@@ -343,16 +341,18 @@ export class SelectionsOverlay extends DynamicViewOverlay {
let className = SelectionsOverlay.SELECTION_CLASS_NAME;
if (visibleRangesHaveStyle) {
if (visibleRange.startStyle.top === CornerStyle.EXTERN) {
const startStyle = visibleRange.startStyle!;
const endStyle = visibleRange.endStyle!;
if (startStyle.top === CornerStyle.EXTERN) {
className += ' ' + SelectionsOverlay.SELECTION_TOP_LEFT;
}
if (visibleRange.startStyle.bottom === CornerStyle.EXTERN) {
if (startStyle.bottom === CornerStyle.EXTERN) {
className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_LEFT;
}
if (visibleRange.endStyle.top === CornerStyle.EXTERN) {
if (endStyle.top === CornerStyle.EXTERN) {
className += ' ' + SelectionsOverlay.SELECTION_TOP_RIGHT;
}
if (visibleRange.endStyle.bottom === CornerStyle.EXTERN) {
if (endStyle.bottom === CornerStyle.EXTERN) {
className += ' ' + SelectionsOverlay.SELECTION_BOTTOM_RIGHT;
}
}
@@ -363,7 +363,7 @@ export class SelectionsOverlay extends DynamicViewOverlay {
}
}
private _previousFrameVisibleRangesWithStyle: LineVisibleRangesWithStyle[][] = [];
private _previousFrameVisibleRangesWithStyle: (LineVisibleRangesWithStyle[] | null)[] = [];
public prepareRender(ctx: RenderingContext): void {
let output: string[] = [];
@@ -374,7 +374,7 @@ export class SelectionsOverlay extends DynamicViewOverlay {
output[lineIndex] = '';
}
let thisFrameVisibleRangesWithStyle: LineVisibleRangesWithStyle[][] = [];
let thisFrameVisibleRangesWithStyle: (LineVisibleRangesWithStyle[] | null)[] = [];
for (let i = 0, len = this._selections.length; i < len; i++) {
let selection = this._selections[i];
if (selection.isEmpty()) {
@@ -404,15 +404,15 @@ export class SelectionsOverlay extends DynamicViewOverlay {
}
registerThemingParticipant((theme, collector) => {
let editorSelectionColor = theme.getColor(editorSelectionBackground);
const editorSelectionColor = theme.getColor(editorSelectionBackground);
if (editorSelectionColor) {
collector.addRule(`.monaco-editor .focused .selected-text { background-color: ${editorSelectionColor}; }`);
}
let editorInactiveSelectionColor = theme.getColor(editorInactiveSelection);
const editorInactiveSelectionColor = theme.getColor(editorInactiveSelection);
if (editorInactiveSelectionColor) {
collector.addRule(`.monaco-editor .selected-text { background-color: ${editorInactiveSelectionColor}; }`);
}
let editorSelectionForegroundColor = theme.getColor(editorSelectionForeground);
const editorSelectionForegroundColor = theme.getColor(editorSelectionForeground);
if (editorSelectionForegroundColor) {
collector.addRule(`.monaco-editor .view-line span.inline-selected-text { color: ${editorSelectionForegroundColor}; }`);
}

View File

@@ -2,18 +2,17 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as dom from 'vs/base/browser/dom';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import * as strings from 'vs/base/common/strings';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import * as dom from 'vs/base/browser/dom';
import * as strings from 'vs/base/common/strings';
export interface IViewCursorRenderData {
domNode: HTMLElement;
@@ -48,7 +47,7 @@ export class ViewCursor {
private _position: Position;
private _lastRenderedContent: string;
private _renderData: ViewCursorRenderData;
private _renderData: ViewCursorRenderData | null;
constructor(context: ViewContext) {
this._context = context;
@@ -118,7 +117,7 @@ export class ViewCursor {
return true;
}
private _prepareRender(ctx: RenderingContext): ViewCursorRenderData {
private _prepareRender(ctx: RenderingContext): ViewCursorRenderData | null {
let textContent = '';
let textContentClassName = '';
@@ -138,8 +137,13 @@ export class ViewCursor {
} else {
width = dom.computeScreenAwareSize(1);
}
let left = visibleRange.left;
if (width >= 2 && left >= 1) {
// try to center cursor
left -= 1;
}
const top = ctx.getVerticalOffsetForLineNumber(this._position.lineNumber) - ctx.bigNumbersDelta;
return new ViewCursorRenderData(top, visibleRange.left, width, this._lineHeight, textContent, textContentClassName);
return new ViewCursorRenderData(top, left, width, this._lineHeight, textContent, textContentClassName);
}
const visibleRangeForCharacter = ctx.linesVisibleRangesForRange(new Range(this._position.lineNumber, this._position.column, this._position.lineNumber, this._position.column + 1), false);
@@ -178,7 +182,7 @@ export class ViewCursor {
this._renderData = this._prepareRender(ctx);
}
public render(ctx: RestrictedRenderingContext): IViewCursorRenderData {
public render(ctx: RestrictedRenderingContext): IViewCursorRenderData | null {
if (!this._renderData) {
this._domNode.setDisplay('none');
return null;

View File

@@ -13,6 +13,11 @@
overflow: hidden;
}
/* -- smooth-caret-animation -- */
.monaco-editor .cursors-layer.cursor-smooth-caret-animation > .cursor {
transition: 80ms;
}
/* -- block-outline-style -- */
.monaco-editor .cursors-layer.cursor-block-outline-style > .cursor {
box-sizing: border-box;

View File

@@ -3,20 +3,18 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./viewCursors';
import { ViewPart } from 'vs/editor/browser/view/viewPart';
import { Position } from 'vs/editor/common/core/position';
import { IViewCursorRenderData, ViewCursor } from 'vs/editor/browser/viewParts/viewCursors/viewCursor';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { TimeoutTimer, IntervalTimer } from 'vs/base/common/async';
import { IntervalTimer, TimeoutTimer } from 'vs/base/common/async';
import { ViewPart } from 'vs/editor/browser/view/viewPart';
import { IViewCursorRenderData, ViewCursor } from 'vs/editor/browser/viewParts/viewCursors/viewCursor';
import { TextEditorCursorBlinkingStyle, TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
import { Position } from 'vs/editor/common/core/position';
import { editorCursorBackground, editorCursorForeground } from 'vs/editor/common/view/editorColorRegistry';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import * as viewEvents from 'vs/editor/common/view/viewEvents';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { editorCursorForeground, editorCursorBackground } from 'vs/editor/common/view/editorColorRegistry';
import { TextEditorCursorBlinkingStyle, TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
export class ViewCursors extends ViewPart {
@@ -25,6 +23,7 @@ export class ViewCursors extends ViewPart {
private _readOnly: boolean;
private _cursorBlinking: TextEditorCursorBlinkingStyle;
private _cursorStyle: TextEditorCursorStyle;
private _cursorSmoothCaretAnimation: boolean;
private _selectionIsEmpty: boolean;
private _isVisible: boolean;
@@ -47,6 +46,7 @@ export class ViewCursors extends ViewPart {
this._readOnly = this._context.configuration.editor.readOnly;
this._cursorBlinking = this._context.configuration.editor.viewInfo.cursorBlinking;
this._cursorStyle = this._context.configuration.editor.viewInfo.cursorStyle;
this._cursorSmoothCaretAnimation = this._context.configuration.editor.viewInfo.cursorSmoothCaretAnimation;
this._selectionIsEmpty = true;
this._primaryCursor = new ViewCursor(this._context);
@@ -89,6 +89,7 @@ export class ViewCursors extends ViewPart {
if (e.viewInfo) {
this._cursorBlinking = this._context.configuration.editor.viewInfo.cursorBlinking;
this._cursorStyle = this._context.configuration.editor.viewInfo.cursorStyle;
this._cursorSmoothCaretAnimation = this._context.configuration.editor.viewInfo.cursorSmoothCaretAnimation;
}
this._primaryCursor.onConfigurationChanged(e);
@@ -297,6 +298,9 @@ export class ViewCursors extends ViewPart {
} else {
result += ' cursor-solid';
}
if (this._cursorSmoothCaretAnimation) {
result += ' cursor-smooth-caret-animation';
}
return result;
}
@@ -349,7 +353,7 @@ export class ViewCursors extends ViewPart {
}
registerThemingParticipant((theme, collector) => {
let caret = theme.getColor(editorCursorForeground);
const caret = theme.getColor(editorCursorForeground);
if (caret) {
let caretBackground = theme.getColor(editorCursorBackground);
if (!caretBackground) {

View File

@@ -2,24 +2,23 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { onUnexpectedError } from 'vs/base/common/errors';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IViewZone } from 'vs/editor/browser/editorBrowser';
import { ViewPart } from 'vs/editor/browser/view/viewPart';
import { ViewContext } from 'vs/editor/common/view/viewContext';
import { Position } from 'vs/editor/common/core/position';
import { RenderingContext, RestrictedRenderingContext } from 'vs/editor/common/view/renderingContext';
import { IViewWhitespaceViewportData } from 'vs/editor/common/viewModel/viewModel';
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';
export interface IMyViewZone {
whitespaceId: number;
delegate: IViewZone;
isVisible: boolean;
domNode: FastDomNode<HTMLElement>;
marginDomNode: FastDomNode<HTMLElement>;
marginDomNode: FastDomNode<HTMLElement> | null;
}
interface IComputedViewZoneProps {
@@ -228,12 +227,12 @@ export class ViewZones extends ViewPart {
zone.domNode.removeAttribute('monaco-visible-view-zone');
zone.domNode.removeAttribute('monaco-view-zone');
zone.domNode.domNode.parentNode.removeChild(zone.domNode.domNode);
zone.domNode.domNode.parentNode!.removeChild(zone.domNode.domNode);
if (zone.marginDomNode) {
zone.marginDomNode.removeAttribute('monaco-visible-view-zone');
zone.marginDomNode.removeAttribute('monaco-view-zone');
zone.marginDomNode.domNode.parentNode.removeChild(zone.marginDomNode.domNode);
zone.marginDomNode.domNode.parentNode!.removeChild(zone.marginDomNode.domNode);
}
this.setShouldRender();
@@ -263,7 +262,7 @@ export class ViewZones extends ViewPart {
public shouldSuppressMouseDownOnViewZone(id: number): boolean {
if (this._zones.hasOwnProperty(id.toString())) {
let zone = this._zones[id.toString()];
return zone.delegate.suppressMouseDown;
return Boolean(zone.delegate.suppressMouseDown);
}
return false;
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,45 +3,43 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/diffEditor';
import * as nls from 'vs/nls';
import { RunOnceScheduler } from 'vs/base/common/async';
import { Disposable } from 'vs/base/common/lifecycle';
import * as objects from 'vs/base/common/objects';
import * as dom from 'vs/base/browser/dom';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import { ISashEvent, IVerticalSashLayoutProvider, Sash, SashState } from 'vs/base/browser/ui/sash/sash';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { Range, IRange } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { LineDecoration } from 'vs/editor/common/viewLayout/lineDecorations';
import { renderViewLine, RenderLineInput } from 'vs/editor/common/viewLayout/viewLineRenderer';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { Position, IPosition } from 'vs/editor/common/core/position';
import { Selection, ISelection } from 'vs/editor/common/core/selection';
import { InlineDecoration, InlineDecorationType, ViewLineRenderingData } from 'vs/editor/common/viewModel/viewModel';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { Event, Emitter } from 'vs/base/common/event';
import * as editorOptions from 'vs/editor/common/config/editorOptions';
import { registerThemingParticipant, IThemeService, ITheme, getThemeTypeSelector } from 'vs/platform/theme/common/themeService';
import { scrollbarShadow, diffInserted, diffRemoved, defaultInsertColor, defaultRemoveColor, diffInsertedOutline, diffRemovedOutline, diffBorder } from 'vs/platform/theme/common/colorRegistry';
import { RunOnceScheduler } from 'vs/base/common/async';
import { Color } from 'vs/base/common/color';
import { OverviewRulerZone } from 'vs/editor/common/view/overviewZoneManager';
import { IEditorWhitespace } from 'vs/editor/common/viewLayout/whitespaceComputer';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
import { DiffReview } from 'vs/editor/browser/widget/diffReview';
import URI from 'vs/base/common/uri';
import { IStringBuilder, createStringBuilder } from 'vs/editor/common/core/stringBuilder';
import { IModelDeltaDecoration, IModelDecorationsChangeAccessor, ITextModel } from 'vs/editor/common/model';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import * as objects from 'vs/base/common/objects';
import { URI } from 'vs/base/common/uri';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { StableEditorScrollState } from 'vs/editor/browser/core/editorState';
import * as editorBrowser from 'vs/editor/browser/editorBrowser';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { DiffReview } from 'vs/editor/browser/widget/diffReview';
import * as editorOptions from 'vs/editor/common/config/editorOptions';
import { IPosition, Position } from 'vs/editor/common/core/position';
import { IRange, Range } from 'vs/editor/common/core/range';
import { ISelection, Selection } from 'vs/editor/common/core/selection';
import { IStringBuilder, createStringBuilder } from 'vs/editor/common/core/stringBuilder';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { IModelDecorationsChangeAccessor, IModelDeltaDecoration, ITextModel } from 'vs/editor/common/model';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
import { IDiffComputationResult, IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
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 { 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';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { defaultInsertColor, defaultRemoveColor, diffBorder, diffInserted, diffInsertedOutline, diffRemoved, diffRemovedOutline, scrollbarShadow } from 'vs/platform/theme/common/colorRegistry';
import { ITheme, IThemeService, getThemeTypeSelector, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
interface IEditorDiffDecorations {
decorations: IModelDeltaDecoration[];
@@ -173,7 +171,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
private _currentlyChangingViewZones: boolean;
private _beginUpdateDecorationsTimeout: number;
private _diffComputationToken: number;
private _lineChanges: editorCommon.ILineChange[];
private _diffComputationResult: IDiffComputationResult | null;
private _isVisible: boolean;
private _isHandlingScrollEvent: boolean;
@@ -283,7 +281,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
this._height = 0;
this._reviewHeight = 0;
this._lineChanges = null;
this._diffComputationResult = null;
const leftContextKeyService = this._contextKeyService.createScoped();
leftContextKeyService.createKey('isInDiffLeftEditor', true);
@@ -525,8 +523,11 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
return editorCommon.EditorType.IDiffEditor;
}
public getLineChanges(): editorCommon.ILineChange[] {
return this._lineChanges;
public getLineChanges(): editorCommon.ILineChange[] | null {
if (!this._diffComputationResult) {
return null;
}
return this._diffComputationResult.changes;
}
public getOriginalEditor(): editorBrowser.ICodeEditor {
@@ -585,7 +586,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
// renderSideBySide
if (renderSideBySideChanged) {
if (this._renderSideBySide) {
this._setStrategy(new DiffEdtorWidgetSideBySide(this._createDataSource(), this._enableSplitViewResizing, ));
this._setStrategy(new DiffEdtorWidgetSideBySide(this._createDataSource(), this._enableSplitViewResizing));
} else {
this._setStrategy(new DiffEdtorWidgetInline(this._createDataSource(), this._enableSplitViewResizing));
}
@@ -621,7 +622,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
}
// Disable any diff computations that will come in
this._lineChanges = null;
this._diffComputationResult = null;
this._diffComputationToken++;
if (model) {
@@ -630,7 +631,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
// Begin comparing
this._beginUpdateDecorations();
} else {
this._lineChanges = null;
this._diffComputationResult = null;
}
this._layoutOverviewViewport();
@@ -644,7 +645,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
return this.modifiedEditor.getVisibleColumnFromPosition(position);
}
public getPosition(): Position {
public getPosition(): Position | null {
return this.modifiedEditor.getPosition();
}
@@ -676,11 +677,11 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
this.modifiedEditor.revealPositionInCenterIfOutsideViewport(position, scrollType);
}
public getSelection(): Selection {
public getSelection(): Selection | null {
return this.modifiedEditor.getSelection();
}
public getSelections(): Selection[] {
public getSelections(): Selection[] | null {
return this.modifiedEditor.getSelections();
}
@@ -849,10 +850,10 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
this._beginUpdateDecorationsTimeout = window.setTimeout(() => this._beginUpdateDecorations(), DiffEditorWidget.UPDATE_DIFF_DECORATIONS_DELAY);
}
private _lastOriginalWarning: URI = null;
private _lastModifiedWarning: URI = null;
private _lastOriginalWarning: URI | null = null;
private _lastModifiedWarning: URI | null = null;
private static _equals(a: URI, b: URI): boolean {
private static _equals(a: URI | null, b: URI | null): boolean {
if (!a && !b) {
return true;
}
@@ -893,7 +894,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
&& currentOriginalModel === this.originalEditor.getModel()
&& currentModifiedModel === this.modifiedEditor.getModel()
) {
this._lineChanges = result;
this._diffComputationResult = result;
this._updateDecorationsRunner.schedule();
this._onDidUpdateDiff.fire();
}
@@ -902,7 +903,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
&& currentOriginalModel === this.originalEditor.getModel()
&& currentModifiedModel === this.modifiedEditor.getModel()
) {
this._lineChanges = null;
this._diffComputationResult = null;
this._updateDecorationsRunner.schedule();
}
});
@@ -917,7 +918,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
if (!this.originalEditor.getModel() || !this.modifiedEditor.getModel()) {
return;
}
let lineChanges = this._lineChanges || [];
const lineChanges = (this._diffComputationResult ? this._diffComputationResult.changes : []);
let foreignOriginal = this._originalEditorState.getForeignViewZones(this.originalEditor.getWhitespaces());
let foreignModified = this._modifiedEditorState.getForeignViewZones(this.modifiedEditor.getWhitespaces());
@@ -944,7 +945,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
clonedOptions.folding = false;
clonedOptions.codeLens = false;
clonedOptions.fixedOverflowWidgets = true;
clonedOptions.lineDecorationsWidth = '2ch';
// clonedOptions.lineDecorationsWidth = '2ch';
if (!clonedOptions.minimap) {
clonedOptions.minimap = {};
}
@@ -1011,7 +1012,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
}
}
private _computeOverviewViewport(): { height: number; top: number; } {
private _computeOverviewViewport(): { height: number; top: number; } | null {
let layoutInfo = this.modifiedEditor.getLayoutInfo();
if (!layoutInfo) {
return null;
@@ -1069,7 +1070,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
this._strategy = newStrategy;
newStrategy.applyColors(this._themeService.getTheme());
if (this._lineChanges) {
if (this._diffComputationResult) {
this._updateDecorations();
}
@@ -1077,17 +1078,18 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
this._measureDomElement(true);
}
private _getLineChangeAtOrBeforeLineNumber(lineNumber: number, startLineNumberExtractor: (lineChange: editorCommon.ILineChange) => number): editorCommon.ILineChange {
if (this._lineChanges.length === 0 || lineNumber < startLineNumberExtractor(this._lineChanges[0])) {
private _getLineChangeAtOrBeforeLineNumber(lineNumber: number, startLineNumberExtractor: (lineChange: editorCommon.ILineChange) => number): editorCommon.ILineChange | null {
const lineChanges = (this._diffComputationResult ? this._diffComputationResult.changes : []);
if (lineChanges.length === 0 || lineNumber < startLineNumberExtractor(lineChanges[0])) {
// There are no changes or `lineNumber` is before the first change
return null;
}
let min = 0, max = this._lineChanges.length - 1;
let min = 0, max = lineChanges.length - 1;
while (min < max) {
let mid = Math.floor((min + max) / 2);
let midStart = startLineNumberExtractor(this._lineChanges[mid]);
let midEnd = (mid + 1 <= max ? startLineNumberExtractor(this._lineChanges[mid + 1]) : Number.MAX_VALUE);
let midStart = startLineNumberExtractor(lineChanges[mid]);
let midEnd = (mid + 1 <= max ? startLineNumberExtractor(lineChanges[mid + 1]) : Number.MAX_VALUE);
if (lineNumber < midStart) {
max = mid - 1;
@@ -1099,7 +1101,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
max = mid;
}
}
return this._lineChanges[min];
return lineChanges[min];
}
private _getEquivalentLineForOriginalLineNumber(lineNumber: number): number {
@@ -1146,8 +1148,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
return originalEquivalentLineNumber + lineChangeOriginalLength - lineChangeModifiedLength + delta;
}
public getDiffLineInformationForOriginal(lineNumber: number): editorBrowser.IDiffLineInformation {
if (!this._lineChanges) {
public getDiffLineInformationForOriginal(lineNumber: number): editorBrowser.IDiffLineInformation | null {
if (!this._diffComputationResult) {
// Cannot answer that which I don't know
return null;
}
@@ -1156,8 +1158,8 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE
};
}
public getDiffLineInformationForModified(lineNumber: number): editorBrowser.IDiffLineInformation {
if (!this._lineChanges) {
public getDiffLineInformationForModified(lineNumber: number): editorBrowser.IDiffLineInformation | null {
if (!this._diffComputationResult) {
// Cannot answer that which I don't know
return null;
}
@@ -1233,15 +1235,20 @@ abstract class DiffEditorWidgetStyle extends Disposable implements IDiffEditorWi
public abstract layout(): number;
}
interface IMyViewZone extends editorBrowser.IViewZone {
interface IMyViewZone {
shouldNotShrink?: boolean;
afterLineNumber: number;
heightInLines: number;
minWidthInPx?: number;
domNode: HTMLElement | null;
marginDomNode?: HTMLElement | null;
}
class ForeignViewZonesIterator {
private _index: number;
private _source: IEditorWhitespace[];
public current: IEditorWhitespace;
public current: IEditorWhitespace | null;
constructor(source: IEditorWhitespace[]) {
this._source = source;
@@ -1272,7 +1279,7 @@ abstract class ViewZonesComputer {
}
public getViewZones(): IEditorsZones {
let result: IEditorsZones = {
let result: { original: IMyViewZone[]; modified: IMyViewZone[]; } = {
original: [],
modified: []
};
@@ -1288,7 +1295,7 @@ abstract class ViewZonesComputer {
return a.afterLineNumber - b.afterLineNumber;
};
let addAndCombineIfPossible = (destination: editorBrowser.IViewZone[], item: IMyViewZone) => {
let addAndCombineIfPossible = (destination: IMyViewZone[], item: IMyViewZone) => {
if (item.domNode === null && destination.length > 0) {
let lastItem = destination[destination.length - 1];
if (lastItem.afterLineNumber === item.afterLineNumber && lastItem.domNode === null) {
@@ -1335,10 +1342,17 @@ abstract class ViewZonesComputer {
} else {
viewZoneLineNumber = originalEndEquivalentLineNumber;
}
let marginDomNode: HTMLDivElement | null = null;
if (lineChange && lineChange.modifiedStartLineNumber <= modifiedForeignVZ.current.afterLineNumber && modifiedForeignVZ.current.afterLineNumber <= lineChange.modifiedEndLineNumber) {
marginDomNode = this._createOriginalMarginDomNodeForModifiedForeignViewZoneInAddedRegion();
}
stepOriginal.push({
afterLineNumber: viewZoneLineNumber,
heightInLines: modifiedForeignVZ.current.heightInLines,
domNode: null
domNode: null,
marginDomNode: marginDomNode
});
modifiedForeignVZ.advance();
}
@@ -1444,9 +1458,11 @@ abstract class ViewZonesComputer {
return result;
}
protected abstract _produceOriginalFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone;
protected abstract _createOriginalMarginDomNodeForModifiedForeignViewZoneInAddedRegion(): HTMLDivElement | null;
protected abstract _produceModifiedFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone;
protected abstract _produceOriginalFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone | null;
protected abstract _produceModifiedFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone | null;
}
function createDecoration(startLineNumber: number, startColumn: number, endLineNumber: number, endColumn: number, options: ModelDecorationOptions) {
@@ -1737,7 +1753,11 @@ class SideBySideViewZonesComputer extends ViewZonesComputer {
super(lineChanges, originalForeignVZ, modifiedForeignVZ);
}
protected _produceOriginalFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone {
protected _createOriginalMarginDomNodeForModifiedForeignViewZoneInAddedRegion(): HTMLDivElement | null {
return null;
}
protected _produceOriginalFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone | null {
if (lineChangeModifiedLength > lineChangeOriginalLength) {
return {
afterLineNumber: Math.max(lineChange.originalStartLineNumber, lineChange.originalEndLineNumber),
@@ -1748,7 +1768,7 @@ class SideBySideViewZonesComputer extends ViewZonesComputer {
return null;
}
protected _produceModifiedFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone {
protected _produceModifiedFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone | null {
if (lineChangeOriginalLength > lineChangeModifiedLength) {
return {
afterLineNumber: Math.max(lineChange.modifiedStartLineNumber, lineChange.modifiedEndLineNumber),
@@ -1897,10 +1917,15 @@ class InlineViewZonesComputer extends ViewZonesComputer {
this.renderIndicators = renderIndicators;
}
protected _produceOriginalFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone {
protected _createOriginalMarginDomNodeForModifiedForeignViewZoneInAddedRegion(): HTMLDivElement | null {
let result = document.createElement('div');
result.className = 'inline-added-margin-view-zone';
return result;
}
protected _produceOriginalFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone | null {
let marginDomNode = document.createElement('div');
marginDomNode.className = 'inline-added-margin-view-zone';
Configuration.applyFontInfoSlow(marginDomNode, this.modifiedEditorConfiguration.fontInfo);
return {
afterLineNumber: Math.max(lineChange.originalStartLineNumber, lineChange.originalEndLineNumber),
@@ -1910,7 +1935,7 @@ class InlineViewZonesComputer extends ViewZonesComputer {
};
}
protected _produceModifiedFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone {
protected _produceModifiedFromDiff(lineChange: editorCommon.ILineChange, lineChangeOriginalLength: number, lineChangeModifiedLength: number): IMyViewZone | null {
let decorations: InlineDecoration[] = [];
if (lineChange.charChanges) {
for (let j = 0, lengthJ = lineChange.charChanges.length; j < lengthJ; j++) {
@@ -1982,6 +2007,7 @@ class InlineViewZonesComputer extends ViewZonesComputer {
const containsRTL = ViewLineRenderingData.containsRTL(lineContent, isBasicASCII, originalModel.mightContainRTL());
const output = renderViewLine(new RenderLineInput(
(config.fontInfo.isMonospace && !config.viewInfo.disableMonospaceOptimizations),
config.fontInfo.canUseHalfwidthRightwardsArrow,
lineContent,
false,
isBasicASCII,
@@ -2048,7 +2074,7 @@ registerThemingParticipant((theme, collector) => {
collector.addRule(`.monaco-diff-editor.side-by-side .editor.modified { box-shadow: -6px 0 5px -5px ${shadow}; }`);
}
let border = theme.getColor(diffBorder);
const border = theme.getColor(diffBorder);
if (border) {
collector.addRule(`.monaco-diff-editor.side-by-side .editor.modified { border-left: 1px solid ${border}; }`);
}

View File

@@ -2,16 +2,15 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'vs/base/common/assert';
import { Emitter, Event } from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import * as objects from 'vs/base/common/objects';
import { IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
import { Range } from 'vs/editor/common/core/range';
import { ILineChange, ScrollType } from 'vs/editor/common/editorCommon';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
import { IDiffEditor } from 'vs/editor/browser/editorBrowser';
import { Event, Emitter } from 'vs/base/common/event';
interface IDiffRange {
@@ -59,7 +58,7 @@ export class DiffNavigator {
this.nextIdx = -1;
this.ranges = [];
this.ignoreSelectionChange = false;
this.revealFirst = this._options.alwaysRevealFirst;
this.revealFirst = Boolean(this._options.alwaysRevealFirst);
// hook up to diff editor for diff, disposal, and caret move
this._disposables.push(this._editor.onDidDispose(() => this.dispose()));
@@ -104,7 +103,7 @@ export class DiffNavigator {
}
}
private _compute(lineChanges: ILineChange[]): void {
private _compute(lineChanges: ILineChange[] | null): void {
// new ranges
this.ranges = [];
@@ -151,6 +150,10 @@ export class DiffNavigator {
private _initIdx(fwd: boolean): void {
let found = false;
let position = this._editor.getPosition();
if (!position) {
this.nextIdx = 0;
return;
}
for (let i = 0, len = this.ranges.length; i < len && !found; i++) {
let range = this.ranges[i].range;
if (position.isBeforeOrEqual(range.getStartPosition())) {
@@ -216,7 +219,7 @@ export class DiffNavigator {
dispose(this._disposables);
this._disposables.length = 0;
this._onDidUpdate.dispose();
this.ranges = null;
this.ranges = [];
this.disposed = true;
}
}

View File

@@ -2,35 +2,34 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!./media/diffReview';
import * as nls from 'vs/nls';
import { Disposable } from 'vs/base/common/lifecycle';
import * as dom from 'vs/base/browser/dom';
import { FastDomNode, createFastDomNode } from 'vs/base/browser/fastDomNode';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { renderViewLine2 as renderViewLine, RenderLineInput } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { LineTokens } from 'vs/editor/common/core/lineTokens';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { Position } from 'vs/editor/common/core/position';
import { ColorId, MetadataConsts, FontStyle } from 'vs/editor/common/modes';
import * as editorOptions from 'vs/editor/common/config/editorOptions';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { editorLineNumbers } from 'vs/editor/common/view/editorColorRegistry';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { Action } from 'vs/base/common/actions';
import { registerEditorAction, EditorAction, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { Disposable } from 'vs/base/common/lifecycle';
import { Configuration } from 'vs/editor/browser/config/configuration';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction, ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editorExtensions';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import * as editorOptions from 'vs/editor/common/config/editorOptions';
import { LineTokens } from 'vs/editor/common/core/lineTokens';
import { Position } from 'vs/editor/common/core/position';
import { ILineChange, ScrollType } from 'vs/editor/common/editorCommon';
import { ITextModel, TextModelResolvedOptions } from 'vs/editor/common/model';
import { ColorId, FontStyle, MetadataConsts } from 'vs/editor/common/modes';
import { editorLineNumbers } from 'vs/editor/common/view/editorColorRegistry';
import { RenderLineInput, renderViewLine2 as renderViewLine } from 'vs/editor/common/viewLayout/viewLineRenderer';
import { ViewLineRenderingData } from 'vs/editor/common/viewModel/viewModel';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { scrollbarShadow } from 'vs/platform/theme/common/colorRegistry';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
const DIFF_LINES_PADDING = 3;
@@ -263,7 +262,7 @@ export class DiffReview extends Disposable {
if (jumpToLineNumber !== -1) {
this._diffEditor.setPosition(new Position(jumpToLineNumber, 1));
this._diffEditor.revealPosition(new Position(jumpToLineNumber, 1), editorCommon.ScrollType.Immediate);
this._diffEditor.revealPosition(new Position(jumpToLineNumber, 1), ScrollType.Immediate);
}
}
@@ -359,7 +358,7 @@ export class DiffReview extends Disposable {
return DiffReview._mergeAdjacent(lineChanges, originalModel.getLineCount(), modifiedModel.getLineCount());
}
private static _mergeAdjacent(lineChanges: editorCommon.ILineChange[], originalLineCount: number, modifiedLineCount: number): Diff[] {
private static _mergeAdjacent(lineChanges: ILineChange[], originalLineCount: number, modifiedLineCount: number): Diff[] {
if (!lineChanges || lineChanges.length === 0) {
return [];
}
@@ -769,6 +768,7 @@ export class DiffReview extends Disposable {
const containsRTL = ViewLineRenderingData.containsRTL(lineContent, isBasicASCII, model.mightContainRTL());
const r = renderViewLine(new RenderLineInput(
(config.fontInfo.isMonospace && !config.viewInfo.disableMonospaceOptimizations),
config.fontInfo.canUseHalfwidthRightwardsArrow,
lineContent,
false,
isBasicASCII,
@@ -791,7 +791,7 @@ export class DiffReview extends Disposable {
// theming
registerThemingParticipant((theme, collector) => {
let lineNumbers = theme.getColor(editorLineNumbers);
const lineNumbers = theme.getColor(editorLineNumbers);
if (lineNumbers) {
collector.addRule(`.monaco-diff-editor .diff-review-line-number { color: ${lineNumbers}; }`);
}

View File

@@ -2,20 +2,19 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as objects from 'vs/base/common/objects';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { IConfigurationChangedEvent, IDiffEditorOptions, IEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
import { IConfigurationChangedEvent, IEditorOptions, IDiffEditorOptions } from 'vs/editor/common/config/editorOptions';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { DiffEditorWidget } from 'vs/editor/browser/widget/diffEditorWidget';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IThemeService } from 'vs/platform/theme/common/themeService';
export class EmbeddedCodeEditorWidget extends CodeEditorWidget {

View File

@@ -41,6 +41,8 @@
opacity: 0.7;
background-repeat: no-repeat;
background-position: 50% 50%;
background-position: center;
background-size: 11px 11px;
}
.monaco-editor.hc-black .insert-sign,
.monaco-diff-editor.hc-black .insert-sign,