@21epub/epub-thirdparty
Version:
epub-thirdparty
1,153 lines (1,152 loc) • 70.9 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
import '../services/markerDecorations.js';
import './media/editor.css';
import * as nls from '../../../nls.js';
import * as dom from '../../../base/browser/dom.js';
import { onUnexpectedError } from '../../../base/common/errors.js';
import { Emitter } from '../../../base/common/event.js';
import { Disposable, dispose } from '../../../base/common/lifecycle.js';
import { Schemas } from '../../../base/common/network.js';
import { Configuration } from '../config/configuration.js';
import { EditorExtensionsRegistry } from '../editorExtensions.js';
import { ICodeEditorService } from '../services/codeEditorService.js';
import { View } from '../view/viewImpl.js';
import { ViewUserInputEvents } from '../view/viewUserInputEvents.js';
import { filterValidationDecorations } from '../../common/config/editorOptions.js';
import { CursorsController } from '../../common/controller/cursor.js';
import { CursorColumns } from '../../common/controller/cursorCommon.js';
import { Position } from '../../common/core/position.js';
import { Range } from '../../common/core/range.js';
import { Selection } from '../../common/core/selection.js';
import { InternalEditorAction } from '../../common/editorAction.js';
import * as editorCommon from '../../common/editorCommon.js';
import { EditorContextKeys } from '../../common/editorContextKeys.js';
import * as modes from '../../common/modes.js';
import { editorUnnecessaryCodeBorder, editorUnnecessaryCodeOpacity } from '../../common/view/editorColorRegistry.js';
import { editorErrorBorder, editorErrorForeground, editorHintBorder, editorHintForeground, editorInfoBorder, editorInfoForeground, editorWarningBorder, editorWarningForeground, editorForeground, editorErrorBackground, editorInfoBackground, editorWarningBackground } from '../../../platform/theme/common/colorRegistry.js';
import { ViewModel } from '../../common/viewModel/viewModelImpl.js';
import { ICommandService } from '../../../platform/commands/common/commands.js';
import { IContextKeyService } from '../../../platform/contextkey/common/contextkey.js';
import { IInstantiationService } from '../../../platform/instantiation/common/instantiation.js';
import { ServiceCollection } from '../../../platform/instantiation/common/serviceCollection.js';
import { INotificationService } from '../../../platform/notification/common/notification.js';
import { IThemeService, registerThemingParticipant } from '../../../platform/theme/common/themeService.js';
import { IAccessibilityService } from '../../../platform/accessibility/common/accessibility.js';
import { withNullAsUndefined } from '../../../base/common/types.js';
import { MonospaceLineBreaksComputerFactory } from '../../common/viewModel/monospaceLineBreaksComputer.js';
import { DOMLineBreaksComputerFactory } from '../view/domLineBreaksComputer.js';
import { WordOperations } from '../../common/controller/cursorWordOperations.js';
let EDITOR_ID = 0;
class ModelData {
constructor(model, viewModel, view, hasRealView, listenersToRemove) {
this.model = model;
this.viewModel = viewModel;
this.view = view;
this.hasRealView = hasRealView;
this.listenersToRemove = listenersToRemove;
}
dispose() {
dispose(this.listenersToRemove);
this.model.onBeforeDetached();
if (this.hasRealView) {
this.view.dispose();
}
this.viewModel.dispose();
}
}
let CodeEditorWidget = class CodeEditorWidget extends Disposable {
constructor(domElement, _options, codeEditorWidgetOptions, instantiationService, codeEditorService, commandService, contextKeyService, themeService, notificationService, accessibilityService) {
super();
//#region Eventing
this._onDidDispose = this._register(new Emitter());
this.onDidDispose = this._onDidDispose.event;
this._onDidChangeModelContent = this._register(new Emitter());
this.onDidChangeModelContent = this._onDidChangeModelContent.event;
this._onDidChangeModelLanguage = this._register(new Emitter());
this.onDidChangeModelLanguage = this._onDidChangeModelLanguage.event;
this._onDidChangeModelLanguageConfiguration = this._register(new Emitter());
this.onDidChangeModelLanguageConfiguration = this._onDidChangeModelLanguageConfiguration.event;
this._onDidChangeModelOptions = this._register(new Emitter());
this.onDidChangeModelOptions = this._onDidChangeModelOptions.event;
this._onDidChangeModelDecorations = this._register(new Emitter());
this.onDidChangeModelDecorations = this._onDidChangeModelDecorations.event;
this._onDidChangeConfiguration = this._register(new Emitter());
this.onDidChangeConfiguration = this._onDidChangeConfiguration.event;
this._onDidChangeModel = this._register(new Emitter());
this.onDidChangeModel = this._onDidChangeModel.event;
this._onDidChangeCursorPosition = this._register(new Emitter());
this.onDidChangeCursorPosition = this._onDidChangeCursorPosition.event;
this._onDidChangeCursorSelection = this._register(new Emitter());
this.onDidChangeCursorSelection = this._onDidChangeCursorSelection.event;
this._onDidAttemptReadOnlyEdit = this._register(new Emitter());
this.onDidAttemptReadOnlyEdit = this._onDidAttemptReadOnlyEdit.event;
this._onDidLayoutChange = this._register(new Emitter());
this.onDidLayoutChange = this._onDidLayoutChange.event;
this._editorTextFocus = this._register(new BooleanEventEmitter());
this.onDidFocusEditorText = this._editorTextFocus.onDidChangeToTrue;
this.onDidBlurEditorText = this._editorTextFocus.onDidChangeToFalse;
this._editorWidgetFocus = this._register(new BooleanEventEmitter());
this.onDidFocusEditorWidget = this._editorWidgetFocus.onDidChangeToTrue;
this.onDidBlurEditorWidget = this._editorWidgetFocus.onDidChangeToFalse;
this._onWillType = this._register(new Emitter());
this.onWillType = this._onWillType.event;
this._onDidType = this._register(new Emitter());
this.onDidType = this._onDidType.event;
this._onDidCompositionStart = this._register(new Emitter());
this.onDidCompositionStart = this._onDidCompositionStart.event;
this._onDidCompositionEnd = this._register(new Emitter());
this.onDidCompositionEnd = this._onDidCompositionEnd.event;
this._onDidPaste = this._register(new Emitter());
this.onDidPaste = this._onDidPaste.event;
this._onMouseUp = this._register(new Emitter());
this.onMouseUp = this._onMouseUp.event;
this._onMouseDown = this._register(new Emitter());
this.onMouseDown = this._onMouseDown.event;
this._onMouseDrag = this._register(new Emitter());
this.onMouseDrag = this._onMouseDrag.event;
this._onMouseDrop = this._register(new Emitter());
this.onMouseDrop = this._onMouseDrop.event;
this._onMouseDropCanceled = this._register(new Emitter());
this.onMouseDropCanceled = this._onMouseDropCanceled.event;
this._onContextMenu = this._register(new Emitter());
this.onContextMenu = this._onContextMenu.event;
this._onMouseMove = this._register(new Emitter());
this.onMouseMove = this._onMouseMove.event;
this._onMouseLeave = this._register(new Emitter());
this.onMouseLeave = this._onMouseLeave.event;
this._onMouseWheel = this._register(new Emitter());
this.onMouseWheel = this._onMouseWheel.event;
this._onKeyUp = this._register(new Emitter());
this.onKeyUp = this._onKeyUp.event;
this._onKeyDown = this._register(new Emitter());
this.onKeyDown = this._onKeyDown.event;
this._onDidContentSizeChange = this._register(new Emitter());
this.onDidContentSizeChange = this._onDidContentSizeChange.event;
this._onDidScrollChange = this._register(new Emitter());
this.onDidScrollChange = this._onDidScrollChange.event;
this._onDidChangeViewZones = this._register(new Emitter());
this.onDidChangeViewZones = this._onDidChangeViewZones.event;
this._onDidChangeHiddenAreas = this._register(new Emitter());
this.onDidChangeHiddenAreas = this._onDidChangeHiddenAreas.event;
const options = Object.assign({}, _options);
this._domElement = domElement;
this._overflowWidgetsDomNode = options.overflowWidgetsDomNode;
delete options.overflowWidgetsDomNode;
this._id = (++EDITOR_ID);
this._decorationTypeKeysToIds = {};
this._decorationTypeSubtypes = {};
this.isSimpleWidget = codeEditorWidgetOptions.isSimpleWidget || false;
this._telemetryData = codeEditorWidgetOptions.telemetryData;
this._configuration = this._register(this._createConfiguration(options, accessibilityService));
this._register(this._configuration.onDidChange((e) => {
this._onDidChangeConfiguration.fire(e);
const options = this._configuration.options;
if (e.hasChanged(129 /* layoutInfo */)) {
const layoutInfo = options.get(129 /* layoutInfo */);
this._onDidLayoutChange.fire(layoutInfo);
}
}));
this._contextKeyService = this._register(contextKeyService.createScoped(this._domElement));
this._notificationService = notificationService;
this._codeEditorService = codeEditorService;
this._commandService = commandService;
this._themeService = themeService;
this._register(new EditorContextKeysManager(this, this._contextKeyService));
this._register(new EditorModeContext(this, this._contextKeyService));
this._instantiationService = instantiationService.createChild(new ServiceCollection([IContextKeyService, this._contextKeyService]));
this._modelData = null;
this._contributions = {};
this._actions = {};
this._focusTracker = new CodeEditorWidgetFocusTracker(domElement);
this._register(this._focusTracker.onChange(() => {
this._editorWidgetFocus.setValue(this._focusTracker.hasFocus());
}));
this._contentWidgets = {};
this._overlayWidgets = {};
let contributions;
if (Array.isArray(codeEditorWidgetOptions.contributions)) {
contributions = codeEditorWidgetOptions.contributions;
}
else {
contributions = EditorExtensionsRegistry.getEditorContributions();
}
for (const desc of contributions) {
if (this._contributions[desc.id]) {
onUnexpectedError(new Error(`Cannot have two contributions with the same id ${desc.id}`));
continue;
}
try {
const contribution = this._instantiationService.createInstance(desc.ctor, this);
this._contributions[desc.id] = contribution;
}
catch (err) {
onUnexpectedError(err);
}
}
EditorExtensionsRegistry.getEditorActions().forEach((action) => {
if (this._actions[action.id]) {
onUnexpectedError(new Error(`Cannot have two actions with the same id ${action.id}`));
return;
}
const internalAction = new InternalEditorAction(action.id, action.label, action.alias, withNullAsUndefined(action.precondition), () => {
return this._instantiationService.invokeFunction((accessor) => {
return Promise.resolve(action.runEditorCommand(accessor, this, null));
});
}, this._contextKeyService);
this._actions[internalAction.id] = internalAction;
});
this._codeEditorService.addCodeEditor(this);
}
_createConfiguration(options, accessibilityService) {
return new Configuration(this.isSimpleWidget, options, this._domElement, accessibilityService);
}
getId() {
return this.getEditorType() + ':' + this._id;
}
getEditorType() {
return editorCommon.EditorType.ICodeEditor;
}
dispose() {
this._codeEditorService.removeCodeEditor(this);
this._focusTracker.dispose();
const keys = Object.keys(this._contributions);
for (let i = 0, len = keys.length; i < len; i++) {
const contributionId = keys[i];
this._contributions[contributionId].dispose();
}
this._contributions = {};
this._actions = {};
this._contentWidgets = {};
this._overlayWidgets = {};
this._removeDecorationTypes();
this._postDetachModelCleanup(this._detachModel());
this._onDidDispose.fire();
super.dispose();
}
invokeWithinContext(fn) {
return this._instantiationService.invokeFunction(fn);
}
updateOptions(newOptions) {
this._configuration.updateOptions(newOptions);
}
getOptions() {
return this._configuration.options;
}
getOption(id) {
return this._configuration.options.get(id);
}
getRawOptions() {
return this._configuration.getRawOptions();
}
getOverflowWidgetsDomNode() {
return this._overflowWidgetsDomNode;
}
getConfiguredWordAtPosition(position) {
if (!this._modelData) {
return null;
}
return WordOperations.getWordAtPosition(this._modelData.model, this._configuration.options.get(115 /* wordSeparators */), position);
}
getValue(options = null) {
if (!this._modelData) {
return '';
}
const preserveBOM = (options && options.preserveBOM) ? true : false;
let eolPreference = 0 /* TextDefined */;
if (options && options.lineEnding && options.lineEnding === '\n') {
eolPreference = 1 /* LF */;
}
else if (options && options.lineEnding && options.lineEnding === '\r\n') {
eolPreference = 2 /* CRLF */;
}
return this._modelData.model.getValue(eolPreference, preserveBOM);
}
setValue(newValue) {
if (!this._modelData) {
return;
}
this._modelData.model.setValue(newValue);
}
getModel() {
if (!this._modelData) {
return null;
}
return this._modelData.model;
}
setModel(_model = null) {
const model = _model;
if (this._modelData === null && model === null) {
// Current model is the new model
return;
}
if (this._modelData && this._modelData.model === model) {
// Current model is the new model
return;
}
const hasTextFocus = this.hasTextFocus();
const detachedModel = this._detachModel();
this._attachModel(model);
if (hasTextFocus && this.hasModel()) {
this.focus();
}
const e = {
oldModelUrl: detachedModel ? detachedModel.uri : null,
newModelUrl: model ? model.uri : null
};
this._removeDecorationTypes();
this._onDidChangeModel.fire(e);
this._postDetachModelCleanup(detachedModel);
}
_removeDecorationTypes() {
this._decorationTypeKeysToIds = {};
if (this._decorationTypeSubtypes) {
for (let decorationType in this._decorationTypeSubtypes) {
const subTypes = this._decorationTypeSubtypes[decorationType];
for (let subType in subTypes) {
this._removeDecorationType(decorationType + '-' + subType);
}
}
this._decorationTypeSubtypes = {};
}
}
getVisibleRanges() {
if (!this._modelData) {
return [];
}
return this._modelData.viewModel.getVisibleRanges();
}
getVisibleRangesPlusViewportAboveBelow() {
if (!this._modelData) {
return [];
}
return this._modelData.viewModel.getVisibleRangesPlusViewportAboveBelow();
}
getWhitespaces() {
if (!this._modelData) {
return [];
}
return this._modelData.viewModel.viewLayout.getWhitespaces();
}
static _getVerticalOffsetForPosition(modelData, modelLineNumber, modelColumn) {
const modelPosition = modelData.model.validatePosition({
lineNumber: modelLineNumber,
column: modelColumn
});
const viewPosition = modelData.viewModel.coordinatesConverter.convertModelPositionToViewPosition(modelPosition);
return modelData.viewModel.viewLayout.getVerticalOffsetForLineNumber(viewPosition.lineNumber);
}
getTopForLineNumber(lineNumber) {
if (!this._modelData) {
return -1;
}
return CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, lineNumber, 1);
}
getTopForPosition(lineNumber, column) {
if (!this._modelData) {
return -1;
}
return CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, lineNumber, column);
}
setHiddenAreas(ranges) {
if (this._modelData) {
this._modelData.viewModel.setHiddenAreas(ranges.map(r => Range.lift(r)));
}
}
getVisibleColumnFromPosition(rawPosition) {
if (!this._modelData) {
return rawPosition.column;
}
const position = this._modelData.model.validatePosition(rawPosition);
const tabSize = this._modelData.model.getOptions().tabSize;
return CursorColumns.visibleColumnFromColumn(this._modelData.model.getLineContent(position.lineNumber), position.column, tabSize) + 1;
}
getPosition() {
if (!this._modelData) {
return null;
}
return this._modelData.viewModel.getPosition();
}
setPosition(position) {
if (!this._modelData) {
return;
}
if (!Position.isIPosition(position)) {
throw new Error('Invalid arguments');
}
this._modelData.viewModel.setSelections('api', [{
selectionStartLineNumber: position.lineNumber,
selectionStartColumn: position.column,
positionLineNumber: position.lineNumber,
positionColumn: position.column
}]);
}
_sendRevealRange(modelRange, verticalType, revealHorizontal, scrollType) {
if (!this._modelData) {
return;
}
if (!Range.isIRange(modelRange)) {
throw new Error('Invalid arguments');
}
const validatedModelRange = this._modelData.model.validateRange(modelRange);
const viewRange = this._modelData.viewModel.coordinatesConverter.convertModelRangeToViewRange(validatedModelRange);
this._modelData.viewModel.revealRange('api', revealHorizontal, viewRange, verticalType, scrollType);
}
revealLine(lineNumber, scrollType = 0 /* Smooth */) {
this._revealLine(lineNumber, 0 /* Simple */, scrollType);
}
revealLineInCenter(lineNumber, scrollType = 0 /* Smooth */) {
this._revealLine(lineNumber, 1 /* Center */, scrollType);
}
revealLineInCenterIfOutsideViewport(lineNumber, scrollType = 0 /* Smooth */) {
this._revealLine(lineNumber, 2 /* CenterIfOutsideViewport */, scrollType);
}
revealLineNearTop(lineNumber, scrollType = 0 /* Smooth */) {
this._revealLine(lineNumber, 5 /* NearTop */, scrollType);
}
_revealLine(lineNumber, revealType, scrollType) {
if (typeof lineNumber !== 'number') {
throw new Error('Invalid arguments');
}
this._sendRevealRange(new Range(lineNumber, 1, lineNumber, 1), revealType, false, scrollType);
}
revealPosition(position, scrollType = 0 /* Smooth */) {
this._revealPosition(position, 0 /* Simple */, true, scrollType);
}
revealPositionInCenter(position, scrollType = 0 /* Smooth */) {
this._revealPosition(position, 1 /* Center */, true, scrollType);
}
revealPositionInCenterIfOutsideViewport(position, scrollType = 0 /* Smooth */) {
this._revealPosition(position, 2 /* CenterIfOutsideViewport */, true, scrollType);
}
revealPositionNearTop(position, scrollType = 0 /* Smooth */) {
this._revealPosition(position, 5 /* NearTop */, true, scrollType);
}
_revealPosition(position, verticalType, revealHorizontal, scrollType) {
if (!Position.isIPosition(position)) {
throw new Error('Invalid arguments');
}
this._sendRevealRange(new Range(position.lineNumber, position.column, position.lineNumber, position.column), verticalType, revealHorizontal, scrollType);
}
getSelection() {
if (!this._modelData) {
return null;
}
return this._modelData.viewModel.getSelection();
}
getSelections() {
if (!this._modelData) {
return null;
}
return this._modelData.viewModel.getSelections();
}
setSelection(something) {
const isSelection = Selection.isISelection(something);
const isRange = Range.isIRange(something);
if (!isSelection && !isRange) {
throw new Error('Invalid arguments');
}
if (isSelection) {
this._setSelectionImpl(something);
}
else if (isRange) {
// act as if it was an IRange
const selection = {
selectionStartLineNumber: something.startLineNumber,
selectionStartColumn: something.startColumn,
positionLineNumber: something.endLineNumber,
positionColumn: something.endColumn
};
this._setSelectionImpl(selection);
}
}
_setSelectionImpl(sel) {
if (!this._modelData) {
return;
}
const selection = new Selection(sel.selectionStartLineNumber, sel.selectionStartColumn, sel.positionLineNumber, sel.positionColumn);
this._modelData.viewModel.setSelections('api', [selection]);
}
revealLines(startLineNumber, endLineNumber, scrollType = 0 /* Smooth */) {
this._revealLines(startLineNumber, endLineNumber, 0 /* Simple */, scrollType);
}
revealLinesInCenter(startLineNumber, endLineNumber, scrollType = 0 /* Smooth */) {
this._revealLines(startLineNumber, endLineNumber, 1 /* Center */, scrollType);
}
revealLinesInCenterIfOutsideViewport(startLineNumber, endLineNumber, scrollType = 0 /* Smooth */) {
this._revealLines(startLineNumber, endLineNumber, 2 /* CenterIfOutsideViewport */, scrollType);
}
revealLinesNearTop(startLineNumber, endLineNumber, scrollType = 0 /* Smooth */) {
this._revealLines(startLineNumber, endLineNumber, 5 /* NearTop */, scrollType);
}
_revealLines(startLineNumber, endLineNumber, verticalType, scrollType) {
if (typeof startLineNumber !== 'number' || typeof endLineNumber !== 'number') {
throw new Error('Invalid arguments');
}
this._sendRevealRange(new Range(startLineNumber, 1, endLineNumber, 1), verticalType, false, scrollType);
}
revealRange(range, scrollType = 0 /* Smooth */, revealVerticalInCenter = false, revealHorizontal = true) {
this._revealRange(range, revealVerticalInCenter ? 1 /* Center */ : 0 /* Simple */, revealHorizontal, scrollType);
}
revealRangeInCenter(range, scrollType = 0 /* Smooth */) {
this._revealRange(range, 1 /* Center */, true, scrollType);
}
revealRangeInCenterIfOutsideViewport(range, scrollType = 0 /* Smooth */) {
this._revealRange(range, 2 /* CenterIfOutsideViewport */, true, scrollType);
}
revealRangeNearTop(range, scrollType = 0 /* Smooth */) {
this._revealRange(range, 5 /* NearTop */, true, scrollType);
}
revealRangeNearTopIfOutsideViewport(range, scrollType = 0 /* Smooth */) {
this._revealRange(range, 6 /* NearTopIfOutsideViewport */, true, scrollType);
}
revealRangeAtTop(range, scrollType = 0 /* Smooth */) {
this._revealRange(range, 3 /* Top */, true, scrollType);
}
_revealRange(range, verticalType, revealHorizontal, scrollType) {
if (!Range.isIRange(range)) {
throw new Error('Invalid arguments');
}
this._sendRevealRange(Range.lift(range), verticalType, revealHorizontal, scrollType);
}
setSelections(ranges, source = 'api', reason = 0 /* NotSet */) {
if (!this._modelData) {
return;
}
if (!ranges || ranges.length === 0) {
throw new Error('Invalid arguments');
}
for (let i = 0, len = ranges.length; i < len; i++) {
if (!Selection.isISelection(ranges[i])) {
throw new Error('Invalid arguments');
}
}
this._modelData.viewModel.setSelections(source, ranges, reason);
}
getContentWidth() {
if (!this._modelData) {
return -1;
}
return this._modelData.viewModel.viewLayout.getContentWidth();
}
getScrollWidth() {
if (!this._modelData) {
return -1;
}
return this._modelData.viewModel.viewLayout.getScrollWidth();
}
getScrollLeft() {
if (!this._modelData) {
return -1;
}
return this._modelData.viewModel.viewLayout.getCurrentScrollLeft();
}
getContentHeight() {
if (!this._modelData) {
return -1;
}
return this._modelData.viewModel.viewLayout.getContentHeight();
}
getScrollHeight() {
if (!this._modelData) {
return -1;
}
return this._modelData.viewModel.viewLayout.getScrollHeight();
}
getScrollTop() {
if (!this._modelData) {
return -1;
}
return this._modelData.viewModel.viewLayout.getCurrentScrollTop();
}
setScrollLeft(newScrollLeft, scrollType = 1 /* Immediate */) {
if (!this._modelData) {
return;
}
if (typeof newScrollLeft !== 'number') {
throw new Error('Invalid arguments');
}
this._modelData.viewModel.setScrollPosition({
scrollLeft: newScrollLeft
}, scrollType);
}
setScrollTop(newScrollTop, scrollType = 1 /* Immediate */) {
if (!this._modelData) {
return;
}
if (typeof newScrollTop !== 'number') {
throw new Error('Invalid arguments');
}
this._modelData.viewModel.setScrollPosition({
scrollTop: newScrollTop
}, scrollType);
}
setScrollPosition(position, scrollType = 1 /* Immediate */) {
if (!this._modelData) {
return;
}
this._modelData.viewModel.setScrollPosition(position, scrollType);
}
saveViewState() {
if (!this._modelData) {
return null;
}
const contributionsState = {};
const keys = Object.keys(this._contributions);
for (const id of keys) {
const contribution = this._contributions[id];
if (typeof contribution.saveViewState === 'function') {
contributionsState[id] = contribution.saveViewState();
}
}
const cursorState = this._modelData.viewModel.saveCursorState();
const viewState = this._modelData.viewModel.saveState();
return {
cursorState: cursorState,
viewState: viewState,
contributionsState: contributionsState
};
}
restoreViewState(s) {
if (!this._modelData || !this._modelData.hasRealView) {
return;
}
const codeEditorState = s;
if (codeEditorState && codeEditorState.cursorState && codeEditorState.viewState) {
const cursorState = codeEditorState.cursorState;
if (Array.isArray(cursorState)) {
this._modelData.viewModel.restoreCursorState(cursorState);
}
else {
// Backwards compatibility
this._modelData.viewModel.restoreCursorState([cursorState]);
}
const contributionsState = codeEditorState.contributionsState || {};
const keys = Object.keys(this._contributions);
for (let i = 0, len = keys.length; i < len; i++) {
const id = keys[i];
const contribution = this._contributions[id];
if (typeof contribution.restoreViewState === 'function') {
contribution.restoreViewState(contributionsState[id]);
}
}
const reducedState = this._modelData.viewModel.reduceRestoreState(codeEditorState.viewState);
this._modelData.view.restoreState(reducedState);
}
}
getContribution(id) {
return (this._contributions[id] || null);
}
getActions() {
const result = [];
const keys = Object.keys(this._actions);
for (let i = 0, len = keys.length; i < len; i++) {
const id = keys[i];
result.push(this._actions[id]);
}
return result;
}
getSupportedActions() {
let result = this.getActions();
result = result.filter(action => action.isSupported());
return result;
}
getAction(id) {
return this._actions[id] || null;
}
trigger(source, handlerId, payload) {
payload = payload || {};
switch (handlerId) {
case "compositionStart" /* CompositionStart */:
this._startComposition();
return;
case "compositionEnd" /* CompositionEnd */:
this._endComposition(source);
return;
case "type" /* Type */: {
const args = payload;
this._type(source, args.text || '');
return;
}
case "replacePreviousChar" /* ReplacePreviousChar */: {
const args = payload;
this._compositionType(source, args.text || '', args.replaceCharCnt || 0, 0, 0);
return;
}
case "compositionType" /* CompositionType */: {
const args = payload;
this._compositionType(source, args.text || '', args.replacePrevCharCnt || 0, args.replaceNextCharCnt || 0, args.positionDelta || 0);
return;
}
case "paste" /* Paste */: {
const args = payload;
this._paste(source, args.text || '', args.pasteOnNewLine || false, args.multicursorText || null, args.mode || null);
return;
}
case "cut" /* Cut */:
this._cut(source);
return;
}
const action = this.getAction(handlerId);
if (action) {
Promise.resolve(action.run()).then(undefined, onUnexpectedError);
return;
}
if (!this._modelData) {
return;
}
if (this._triggerEditorCommand(source, handlerId, payload)) {
return;
}
this._triggerCommand(handlerId, payload);
}
_triggerCommand(handlerId, payload) {
this._commandService.executeCommand(handlerId, payload);
}
_startComposition() {
if (!this._modelData) {
return;
}
this._modelData.viewModel.startComposition();
this._onDidCompositionStart.fire();
}
_endComposition(source) {
if (!this._modelData) {
return;
}
this._modelData.viewModel.endComposition(source);
this._onDidCompositionEnd.fire();
}
_type(source, text) {
if (!this._modelData || text.length === 0) {
return;
}
if (source === 'keyboard') {
this._onWillType.fire(text);
}
this._modelData.viewModel.type(text, source);
if (source === 'keyboard') {
this._onDidType.fire(text);
}
}
_compositionType(source, text, replacePrevCharCnt, replaceNextCharCnt, positionDelta) {
if (!this._modelData) {
return;
}
this._modelData.viewModel.compositionType(text, replacePrevCharCnt, replaceNextCharCnt, positionDelta, source);
}
_paste(source, text, pasteOnNewLine, multicursorText, mode) {
if (!this._modelData || text.length === 0) {
return;
}
const startPosition = this._modelData.viewModel.getSelection().getStartPosition();
this._modelData.viewModel.paste(text, pasteOnNewLine, multicursorText, source);
const endPosition = this._modelData.viewModel.getSelection().getStartPosition();
if (source === 'keyboard') {
this._onDidPaste.fire({
range: new Range(startPosition.lineNumber, startPosition.column, endPosition.lineNumber, endPosition.column),
languageId: mode
});
}
}
_cut(source) {
if (!this._modelData) {
return;
}
this._modelData.viewModel.cut(source);
}
_triggerEditorCommand(source, handlerId, payload) {
const command = EditorExtensionsRegistry.getEditorCommand(handlerId);
if (command) {
payload = payload || {};
payload.source = source;
this._instantiationService.invokeFunction((accessor) => {
Promise.resolve(command.runEditorCommand(accessor, this, payload)).then(undefined, onUnexpectedError);
});
return true;
}
return false;
}
_getViewModel() {
if (!this._modelData) {
return null;
}
return this._modelData.viewModel;
}
pushUndoStop() {
if (!this._modelData) {
return false;
}
if (this._configuration.options.get(80 /* readOnly */)) {
// read only editor => sorry!
return false;
}
this._modelData.model.pushStackElement();
return true;
}
popUndoStop() {
if (!this._modelData) {
return false;
}
if (this._configuration.options.get(80 /* readOnly */)) {
// read only editor => sorry!
return false;
}
this._modelData.model.popStackElement();
return true;
}
executeEdits(source, edits, endCursorState) {
if (!this._modelData) {
return false;
}
if (this._configuration.options.get(80 /* readOnly */)) {
// read only editor => sorry!
return false;
}
let cursorStateComputer;
if (!endCursorState) {
cursorStateComputer = () => null;
}
else if (Array.isArray(endCursorState)) {
cursorStateComputer = () => endCursorState;
}
else {
cursorStateComputer = endCursorState;
}
this._modelData.viewModel.executeEdits(source, edits, cursorStateComputer);
return true;
}
executeCommand(source, command) {
if (!this._modelData) {
return;
}
this._modelData.viewModel.executeCommand(command, source);
}
executeCommands(source, commands) {
if (!this._modelData) {
return;
}
this._modelData.viewModel.executeCommands(commands, source);
}
changeDecorations(callback) {
if (!this._modelData) {
// callback will not be called
return null;
}
return this._modelData.model.changeDecorations(callback, this._id);
}
getLineDecorations(lineNumber) {
if (!this._modelData) {
return null;
}
return this._modelData.model.getLineDecorations(lineNumber, this._id, filterValidationDecorations(this._configuration.options));
}
deltaDecorations(oldDecorations, newDecorations) {
if (!this._modelData) {
return [];
}
if (oldDecorations.length === 0 && newDecorations.length === 0) {
return oldDecorations;
}
return this._modelData.model.deltaDecorations(oldDecorations, newDecorations, this._id);
}
removeDecorations(decorationTypeKey) {
// remove decorations for type and sub type
const oldDecorationsIds = this._decorationTypeKeysToIds[decorationTypeKey];
if (oldDecorationsIds) {
this.deltaDecorations(oldDecorationsIds, []);
}
if (this._decorationTypeKeysToIds.hasOwnProperty(decorationTypeKey)) {
delete this._decorationTypeKeysToIds[decorationTypeKey];
}
if (this._decorationTypeSubtypes.hasOwnProperty(decorationTypeKey)) {
delete this._decorationTypeSubtypes[decorationTypeKey];
}
}
getLayoutInfo() {
const options = this._configuration.options;
const layoutInfo = options.get(129 /* layoutInfo */);
return layoutInfo;
}
createOverviewRuler(cssClassName) {
if (!this._modelData || !this._modelData.hasRealView) {
return null;
}
return this._modelData.view.createOverviewRuler(cssClassName);
}
getContainerDomNode() {
return this._domElement;
}
getDomNode() {
if (!this._modelData || !this._modelData.hasRealView) {
return null;
}
return this._modelData.view.domNode.domNode;
}
delegateVerticalScrollbarMouseDown(browserEvent) {
if (!this._modelData || !this._modelData.hasRealView) {
return;
}
this._modelData.view.delegateVerticalScrollbarMouseDown(browserEvent);
}
layout(dimension) {
this._configuration.observeReferenceElement(dimension);
this.render();
}
focus() {
if (!this._modelData || !this._modelData.hasRealView) {
return;
}
this._modelData.view.focus();
}
hasTextFocus() {
if (!this._modelData || !this._modelData.hasRealView) {
return false;
}
return this._modelData.view.isFocused();
}
hasWidgetFocus() {
return this._focusTracker && this._focusTracker.hasFocus();
}
addContentWidget(widget) {
const widgetData = {
widget: widget,
position: widget.getPosition()
};
if (this._contentWidgets.hasOwnProperty(widget.getId())) {
console.warn('Overwriting a content widget with the same id.');
}
this._contentWidgets[widget.getId()] = widgetData;
if (this._modelData && this._modelData.hasRealView) {
this._modelData.view.addContentWidget(widgetData);
}
}
layoutContentWidget(widget) {
const widgetId = widget.getId();
if (this._contentWidgets.hasOwnProperty(widgetId)) {
const widgetData = this._contentWidgets[widgetId];
widgetData.position = widget.getPosition();
if (this._modelData && this._modelData.hasRealView) {
this._modelData.view.layoutContentWidget(widgetData);
}
}
}
removeContentWidget(widget) {
const widgetId = widget.getId();
if (this._contentWidgets.hasOwnProperty(widgetId)) {
const widgetData = this._contentWidgets[widgetId];
delete this._contentWidgets[widgetId];
if (this._modelData && this._modelData.hasRealView) {
this._modelData.view.removeContentWidget(widgetData);
}
}
}
addOverlayWidget(widget) {
const widgetData = {
widget: widget,
position: widget.getPosition()
};
if (this._overlayWidgets.hasOwnProperty(widget.getId())) {
console.warn('Overwriting an overlay widget with the same id.');
}
this._overlayWidgets[widget.getId()] = widgetData;
if (this._modelData && this._modelData.hasRealView) {
this._modelData.view.addOverlayWidget(widgetData);
}
}
layoutOverlayWidget(widget) {
const widgetId = widget.getId();
if (this._overlayWidgets.hasOwnProperty(widgetId)) {
const widgetData = this._overlayWidgets[widgetId];
widgetData.position = widget.getPosition();
if (this._modelData && this._modelData.hasRealView) {
this._modelData.view.layoutOverlayWidget(widgetData);
}
}
}
removeOverlayWidget(widget) {
const widgetId = widget.getId();
if (this._overlayWidgets.hasOwnProperty(widgetId)) {
const widgetData = this._overlayWidgets[widgetId];
delete this._overlayWidgets[widgetId];
if (this._modelData && this._modelData.hasRealView) {
this._modelData.view.removeOverlayWidget(widgetData);
}
}
}
changeViewZones(callback) {
if (!this._modelData || !this._modelData.hasRealView) {
return;
}
this._modelData.view.change(callback);
}
getTargetAtClientPoint(clientX, clientY) {
if (!this._modelData || !this._modelData.hasRealView) {
return null;
}
return this._modelData.view.getTargetAtClientPoint(clientX, clientY);
}
getScrolledVisiblePosition(rawPosition) {
if (!this._modelData || !this._modelData.hasRealView) {
return null;
}
const position = this._modelData.model.validatePosition(rawPosition);
const options = this._configuration.options;
const layoutInfo = options.get(129 /* layoutInfo */);
const top = CodeEditorWidget._getVerticalOffsetForPosition(this._modelData, position.lineNumber, position.column) - this.getScrollTop();
const left = this._modelData.view.getOffsetForColumn(position.lineNumber, position.column) + layoutInfo.glyphMarginWidth + layoutInfo.lineNumbersWidth + layoutInfo.decorationsWidth - this.getScrollLeft();
return {
top: top,
left: left,
height: options.get(58 /* lineHeight */)
};
}
getOffsetForColumn(lineNumber, column) {
if (!this._modelData || !this._modelData.hasRealView) {
return -1;
}
return this._modelData.view.getOffsetForColumn(lineNumber, column);
}
render(forceRedraw = false) {
if (!this._modelData || !this._modelData.hasRealView) {
return;
}
this._modelData.view.render(true, forceRedraw);
}
setAriaOptions(options) {
if (!this._modelData || !this._modelData.hasRealView) {
return;
}
this._modelData.view.setAriaOptions(options);
}
applyFontInfo(target) {
Configuration.applyFontInfoSlow(target, this._configuration.options.get(43 /* fontInfo */));
}
_attachModel(model) {
if (!model) {
this._modelData = null;
return;
}
const listenersToRemove = [];
this._domElement.setAttribute('data-mode-id', model.getLanguageId());
this._configuration.setIsDominatedByLongLines(model.isDominatedByLongLines());
this._configuration.setMaxLineNumber(model.getLineCount());
model.onBeforeAttached();
const viewModel = new ViewModel(this._id, this._configuration, model, DOMLineBreaksComputerFactory.create(), MonospaceLineBreaksComputerFactory.create(this._configuration.options), (callback) => dom.scheduleAtNextAnimationFrame(callback));
listenersToRemove.push(model.onDidChangeDecorations((e) => this._onDidChangeModelDecorations.fire(e)));
listenersToRemove.push(model.onDidChangeLanguage((e) => {
this._domElement.setAttribute('data-mode-id', model.getLanguageId());
this._onDidChangeModelLanguage.fire(e);
}));
listenersToRemove.push(model.onDidChangeLanguageConfiguration((e) => this._onDidChangeModelLanguageConfiguration.fire(e)));
listenersToRemove.push(model.onDidChangeContent((e) => this._onDidChangeModelContent.fire(e)));
listenersToRemove.push(model.onDidChangeOptions((e) => this._onDidChangeModelOptions.fire(e)));
// Someone might destroy the model from under the editor, so prevent any exceptions by setting a null model
listenersToRemove.push(model.onWillDispose(() => this.setModel(null)));
listenersToRemove.push(viewModel.onEvent((e) => {
switch (e.kind) {
case 0 /* ContentSizeChanged */:
this._onDidContentSizeChange.fire(e);
break;
case 1 /* FocusChanged */:
this._editorTextFocus.setValue(e.hasFocus);
break;
case 2 /* ScrollChanged */:
this._onDidScrollChange.fire(e);
break;
case 3 /* ViewZonesChanged */:
this._onDidChangeViewZones.fire();
break;
case 4 /* HiddenAreasChanged */:
this._onDidChangeHiddenAreas.fire();
break;
case 5 /* ReadOnlyEditAttempt */:
this._onDidAttemptReadOnlyEdit.fire();
break;
case 6 /* CursorStateChanged */: {
if (e.reachedMaxCursorCount) {
this._notificationService.warn(nls.localize('cursors.maximum', "The number of cursors has been limited to {0}.", CursorsController.MAX_CURSOR_COUNT));
}
const positions = [];
for (let i = 0, len = e.selections.length; i < len; i++) {
positions[i] = e.selections[i].getPosition();
}
const e1 = {
position: positions[0],
secondaryPositions: positions.slice(1),
reason: e.reason,
source: e.source
};
this._onDidChangeCursorPosition.fire(e1);
const e2 = {
selection: e.selections[0],
secondarySelections: e.selections.slice(1),
modelVersionId: e.modelVersionId,
oldSelections: e.oldSelections,
oldModelVersionId: e.oldModelVersionId,
source: e.source,
reason: e.reason
};
this._onDidChangeCursorSelection.fire(e2);
break;
}
}
}));
const [view, hasRealView] = this._createView(viewModel);
if (hasRealView) {
this._domElement.appendChild(view.domNode.domNode);
let keys = Object.keys(this._contentWidgets);
for (let i = 0, len = keys.length; i < len; i++) {
const widgetId = keys[i];
view.addContentWidget(this._contentWidgets[widgetId]);
}
keys = Object.keys(this._overlayWidgets);
for (let i = 0, len = keys.length; i < len; i++) {
const widgetId = keys[i];
view.addOverlayWidget(this._overlayWidgets[widgetId]);
}
view.render(false, true);
view.domNode.domNode.setAttribute('data-uri', model.uri.toString());
}
this._modelData = new ModelData(model, viewModel, view, hasRealView, listenersToRemove);
}
_createView(viewModel) {
let commandDelegate;
if (this.isSimpleWidget) {
commandDelegate = {
paste: (text, pasteOnNewLine, multicursorText, mode) => {
this._paste('keyboard', text, pasteOnNewLine, multicursorText, mode);
},
type: (text) => {
this._type('keyboard', text);
},
compositionType: (text, replacePrevCharCnt, replaceNextCharCnt, positionDelta) => {
this._compositionType('keyboard', text, replacePrevCharCnt, replaceNextCharCnt, positionDelta);
},
startComposition: () => {
this._startComposition();
},
endComposition: () => {
this._endComposition('keyboard');
},
cut: () => {
this._cut('keyboard');
}
};
}
else {
commandDelegate = {
paste: (text, pasteOnNewLine, multicursorText, mode) => {
const payload = { text, pasteOnNewLine, multicursorText, mode };
this._commandService.executeCommand("paste" /* Paste */, payload);