提交 6aadb1ad 编写于 作者: A Alex Dima

Send text editor properties updates in a single event

上级 ad63cf5a
......@@ -409,11 +409,12 @@ export class MainThreadDocumentsAndEditors {
}
private _toTextEditorAddData(textEditor: MainThreadTextEditor): ITextEditorAddData {
const props = textEditor.getProperties();
return {
id: textEditor.getId(),
documentUri: textEditor.getModel().uri,
options: textEditor.getConfiguration(),
selections: textEditor.getSelections(),
options: props.options,
selections: props.selections,
editorPosition: this._findEditorPosition(textEditor)
};
}
......
......@@ -14,27 +14,130 @@ import { Selection, ISelection } from 'vs/editor/common/core/selection';
import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2';
import { EndOfLine, TextEditorLineNumbersStyle } from 'vs/workbench/api/node/extHostTypes';
import { TextEditorCursorStyle, cursorStyleToString, RenderLineNumbersType } from 'vs/editor/common/config/editorOptions';
import { ICursorSelectionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
import { IResolvedTextEditorConfiguration, ISelectionChangeEvent, ITextEditorConfigurationUpdate, TextEditorRevealType, IApplyEditsOptions, IUndoStopOptions } from 'vs/workbench/api/node/extHost.protocol';
import { IResolvedTextEditorConfiguration, ITextEditorConfigurationUpdate, TextEditorRevealType, IApplyEditsOptions, IUndoStopOptions, IEditorPropertiesChangeData } from 'vs/workbench/api/node/extHost.protocol';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ITextModel, ISingleEditOperation, EndOfLineSequence, IIdentifiedSingleEditOperation, ITextModelUpdateOptions } from 'vs/editor/common/model';
function configurationsEqual(a: IResolvedTextEditorConfiguration, b: IResolvedTextEditorConfiguration) {
if (a && !b || !a && b) {
return false;
export interface IFocusTracker {
onGainedFocus(): void;
onLostFocus(): void;
}
export class MainThreadTextEditorProperties {
public static readFromEditor(previousProperties: MainThreadTextEditorProperties, model: ITextModel, codeEditor: ICodeEditor): MainThreadTextEditorProperties {
const selections = MainThreadTextEditorProperties._readSelectionsFromCodeEditor(previousProperties, codeEditor);
const options = MainThreadTextEditorProperties._readOptionsFromCodeEditor(previousProperties, model, codeEditor);
return new MainThreadTextEditorProperties(selections, options);
}
if (!a && !b) {
private static _readSelectionsFromCodeEditor(previousProperties: MainThreadTextEditorProperties, codeEditor: ICodeEditor): Selection[] {
if (codeEditor) {
return codeEditor.getSelections();
}
if (previousProperties) {
return previousProperties.selections;
}
return [new Selection(1, 1, 1, 1)];
}
private static _readOptionsFromCodeEditor(previousProperties: MainThreadTextEditorProperties, model: ITextModel, codeEditor: ICodeEditor): IResolvedTextEditorConfiguration {
if (model.isDisposed()) {
// shutdown time
return previousProperties.options;
}
let cursorStyle: TextEditorCursorStyle;
let lineNumbers: TextEditorLineNumbersStyle;
if (codeEditor) {
const codeEditorOpts = codeEditor.getConfiguration();
cursorStyle = codeEditorOpts.viewInfo.cursorStyle;
switch (codeEditorOpts.viewInfo.renderLineNumbers) {
case RenderLineNumbersType.Off:
lineNumbers = TextEditorLineNumbersStyle.Off;
break;
case RenderLineNumbersType.Relative:
lineNumbers = TextEditorLineNumbersStyle.Relative;
break;
default:
lineNumbers = TextEditorLineNumbersStyle.On;
break;
}
} else if (previousProperties) {
cursorStyle = previousProperties.options.cursorStyle;
lineNumbers = previousProperties.options.lineNumbers;
} else {
cursorStyle = TextEditorCursorStyle.Line;
lineNumbers = TextEditorLineNumbersStyle.On;
}
const modelOptions = model.getOptions();
return {
insertSpaces: modelOptions.insertSpaces,
tabSize: modelOptions.tabSize,
cursorStyle: cursorStyle,
lineNumbers: lineNumbers
};
}
constructor(
public readonly selections: Selection[],
public readonly options: IResolvedTextEditorConfiguration
) {
}
public generateDelta(oldProps: MainThreadTextEditorProperties, selectionChangeSource: string): IEditorPropertiesChangeData {
let delta = {
options: null,
selections: null
};
if (!oldProps || !MainThreadTextEditorProperties._selectionsEqual(oldProps.selections, this.selections)) {
delta.selections = {
selections: this.selections,
source: selectionChangeSource
};
}
if (!oldProps || !MainThreadTextEditorProperties._optionsEqual(oldProps.options, this.options)) {
delta.options = this.options;
}
if (delta.selections || delta.options) {
// something changed
return delta;
}
// nothing changed
return null;
}
private static _selectionsEqual(a: Selection[], b: Selection[]): boolean {
if (a.length !== b.length) {
return false;
}
for (let i = 0; i < a.length; i++) {
if (!a[i].equalsSelection(b[i])) {
return false;
}
}
return true;
}
return (
a.tabSize === b.tabSize
&& a.insertSpaces === b.insertSpaces
);
}
export interface IFocusTracker {
onGainedFocus(): void;
onLostFocus(): void;
private static _optionsEqual(a: IResolvedTextEditorConfiguration, b: IResolvedTextEditorConfiguration): boolean {
if (a && !b || !a && b) {
return false;
}
if (!a && !b) {
return true;
}
return (
a.tabSize === b.tabSize
&& a.insertSpaces === b.insertSpaces
&& a.cursorStyle === b.cursorStyle
&& a.lineNumbers === b.lineNumbers
);
}
}
/**
......@@ -51,11 +154,8 @@ export class MainThreadTextEditor {
private _focusTracker: IFocusTracker;
private _codeEditorListeners: IDisposable[];
private _lastSelection: Selection[];
private _configuration: IResolvedTextEditorConfiguration;
private _onSelectionChanged: Emitter<ISelectionChangeEvent>;
private _onConfigurationChanged: Emitter<IResolvedTextEditorConfiguration>;
private _properties: MainThreadTextEditorProperties;
private _onPropertiesChanged: Emitter<IEditorPropertiesChangeData>;
constructor(
id: string,
......@@ -71,17 +171,16 @@ export class MainThreadTextEditor {
this._modelService = modelService;
this._codeEditorListeners = [];
this._onSelectionChanged = new Emitter<ISelectionChangeEvent>();
this._onConfigurationChanged = new Emitter<IResolvedTextEditorConfiguration>();
this._properties = null;
this._onPropertiesChanged = new Emitter<IEditorPropertiesChangeData>();
this._lastSelection = [new Selection(1, 1, 1, 1)];
this._modelListeners = [];
this._modelListeners.push(this._model.onDidChangeOptions((e) => {
this._setConfiguration(this._readConfiguration(this._model, this._codeEditor));
this._updatePropertiesNow(null);
}));
this.setCodeEditor(codeEditor);
this._setConfiguration(this._readConfiguration(this._model, this._codeEditor));
this._updatePropertiesNow(null);
}
public dispose(): void {
......@@ -91,6 +190,21 @@ export class MainThreadTextEditor {
this._codeEditorListeners = dispose(this._codeEditorListeners);
}
private _updatePropertiesNow(selectionChangeSource: string): void {
this._setProperties(
MainThreadTextEditorProperties.readFromEditor(this._properties, this._model, this._codeEditor),
selectionChangeSource
);
}
private _setProperties(newProperties: MainThreadTextEditorProperties, selectionChangeSource: string): void {
const delta = newProperties.generateDelta(this._properties, selectionChangeSource);
this._properties = newProperties;
if (delta) {
this._onPropertiesChanged.fire(delta);
}
}
public getId(): string {
return this._id;
}
......@@ -122,27 +236,20 @@ export class MainThreadTextEditor {
this.setCodeEditor(null);
}));
let forwardSelection = (event?: ICursorSelectionChangedEvent) => {
this._lastSelection = this._codeEditor.getSelections();
this._onSelectionChanged.fire({
selections: this._lastSelection,
source: event && event.source
});
};
this._codeEditorListeners.push(this._codeEditor.onDidChangeCursorSelection(forwardSelection));
if (!Selection.selectionsArrEqual(this._lastSelection, this._codeEditor.getSelections())) {
forwardSelection();
}
this._codeEditorListeners.push(this._codeEditor.onDidFocusEditor(() => {
this._focusTracker.onGainedFocus();
}));
this._codeEditorListeners.push(this._codeEditor.onDidBlurEditor(() => {
this._focusTracker.onLostFocus();
}));
this._codeEditorListeners.push(this._codeEditor.onDidChangeCursorSelection((e) => {
this._updatePropertiesNow(e.source);
}));
this._codeEditorListeners.push(this._codeEditor.onDidChangeConfiguration(() => {
this._setConfiguration(this._readConfiguration(this._model, this._codeEditor));
this._updatePropertiesNow(null);
}));
this._setConfiguration(this._readConfiguration(this._model, this._codeEditor));
this._updatePropertiesNow(null);
}
}
......@@ -150,19 +257,12 @@ export class MainThreadTextEditor {
return !!this._codeEditor;
}
public get onSelectionChanged(): Event<ISelectionChangeEvent> {
return this._onSelectionChanged.event;
public getProperties(): MainThreadTextEditorProperties {
return this._properties;
}
public get onConfigurationChanged(): Event<IResolvedTextEditorConfiguration> {
return this._onConfigurationChanged.event;
}
public getSelections(): Selection[] {
if (this._codeEditor) {
return this._codeEditor.getSelections();
}
return this._lastSelection;
public get onPropertiesChanged(): Event<IEditorPropertiesChangeData> {
return this._onPropertiesChanged.event;
}
public setSelections(selections: ISelection[]): void {
......@@ -170,11 +270,12 @@ export class MainThreadTextEditor {
this._codeEditor.setSelections(selections);
return;
}
this._lastSelection = selections.map(Selection.liftSelection);
}
public getConfiguration(): IResolvedTextEditorConfiguration {
return this._configuration;
const newSelections = selections.map(Selection.liftSelection);
this._setProperties(
new MainThreadTextEditorProperties(newSelections, this._properties.options),
null
);
}
private _setIndentConfiguration(newConfiguration: ITextEditorConfigurationUpdate): void {
......@@ -280,47 +381,6 @@ export class MainThreadTextEditor {
}
}
private _readConfiguration(model: ITextModel, codeEditor: ICodeEditor): IResolvedTextEditorConfiguration {
if (model.isDisposed()) {
// shutdown time
return this._configuration;
}
let cursorStyle = this._configuration ? this._configuration.cursorStyle : TextEditorCursorStyle.Line;
let lineNumbers: TextEditorLineNumbersStyle = this._configuration ? this._configuration.lineNumbers : TextEditorLineNumbersStyle.On;
if (codeEditor) {
let codeEditorOpts = codeEditor.getConfiguration();
cursorStyle = codeEditorOpts.viewInfo.cursorStyle;
switch (codeEditorOpts.viewInfo.renderLineNumbers) {
case RenderLineNumbersType.Off:
lineNumbers = TextEditorLineNumbersStyle.Off;
break;
case RenderLineNumbersType.Relative:
lineNumbers = TextEditorLineNumbersStyle.Relative;
break;
default:
lineNumbers = TextEditorLineNumbersStyle.On;
break;
}
}
let indent = model.getOptions();
return {
insertSpaces: indent.insertSpaces,
tabSize: indent.tabSize,
cursorStyle: cursorStyle,
lineNumbers: lineNumbers
};
}
private _setConfiguration(newConfiguration: IResolvedTextEditorConfiguration): void {
if (configurationsEqual(this._configuration, newConfiguration)) {
return;
}
this._configuration = newConfiguration;
this._onConfigurationChanged.fire(this._configuration);
}
public isFocused(): boolean {
if (this._codeEditor) {
return this._codeEditor.isFocused();
......
......@@ -79,11 +79,8 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
private _onTextEditorAdd(textEditor: MainThreadTextEditor): void {
let id = textEditor.getId();
let toDispose: IDisposable[] = [];
toDispose.push(textEditor.onConfigurationChanged((opts) => {
this._proxy.$acceptOptionsChanged(id, opts);
}));
toDispose.push(textEditor.onSelectionChanged((event) => {
this._proxy.$acceptSelectionsChanged(id, event);
toDispose.push(textEditor.onPropertiesChanged((data) => {
this._proxy.$acceptEditorPropertiesChanged(id, data);
}));
this._textEditorsListenersMap[id] = toDispose;
......
......@@ -154,11 +154,6 @@ export interface MainThreadDocumentsShape extends IDisposable {
$trySaveDocument(uri: UriComponents): TPromise<boolean>;
}
export interface ISelectionChangeEvent {
selections: Selection[];
source?: string;
}
export interface ITextEditorConfigurationUpdate {
tabSize?: number | 'auto';
insertSpaces?: boolean | 'auto';
......@@ -516,9 +511,17 @@ export interface ITextEditorAddData {
export interface ITextEditorPositionData {
[id: string]: EditorPosition;
}
export interface IEditorPropertiesChangeData {
options: IResolvedTextEditorConfiguration | null;
selections: ISelectionChangeEvent | null;
}
export interface ISelectionChangeEvent {
selections: Selection[];
source?: string;
}
export interface ExtHostEditorsShape {
$acceptOptionsChanged(id: string, opts: IResolvedTextEditorConfiguration): void;
$acceptSelectionsChanged(id: string, event: ISelectionChangeEvent): void;
$acceptEditorPropertiesChanged(id: string, props: IEditorPropertiesChangeData): void;
$acceptEditorPositionData(data: ITextEditorPositionData): void;
}
......
......@@ -12,7 +12,7 @@ import * as TypeConverters from './extHostTypeConverters';
import { TextEditorDecorationType, ExtHostTextEditor } from './extHostTextEditor';
import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors';
import { Position as EditorPosition } from 'vs/platform/editor/common/editor';
import { MainContext, MainThreadTextEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IResolvedTextEditorConfiguration, ISelectionChangeEvent, IMainContext, WorkspaceEditDto } from './extHost.protocol';
import { MainContext, MainThreadTextEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IMainContext, WorkspaceEditDto, IEditorPropertiesChangeData } from './extHost.protocol';
import * as vscode from 'vscode';
export class ExtHostEditors implements ExtHostEditorsShape {
......@@ -113,25 +113,34 @@ export class ExtHostEditors implements ExtHostEditorsShape {
// --- called from main thread
$acceptOptionsChanged(id: string, opts: IResolvedTextEditorConfiguration): void {
let editor = this._extHostDocumentsAndEditors.getEditor(id);
editor._acceptOptions(opts);
this._onDidChangeTextEditorOptions.fire({
textEditor: editor,
options: opts
});
}
$acceptSelectionsChanged(id: string, event: ISelectionChangeEvent): void {
const kind = TextEditorSelectionChangeKind.fromValue(event.source);
const selections = event.selections.map(TypeConverters.toSelection);
$acceptEditorPropertiesChanged(id: string, data: IEditorPropertiesChangeData): void {
const textEditor = this._extHostDocumentsAndEditors.getEditor(id);
textEditor._acceptSelections(selections);
this._onDidChangeTextEditorSelection.fire({
textEditor,
selections,
kind
});
// (1) set all properties
if (data.options) {
textEditor._acceptOptions(data.options);
}
if (data.selections) {
const selections = data.selections.selections.map(TypeConverters.toSelection);
textEditor._acceptSelections(selections);
}
// (2) fire change events
if (data.options) {
this._onDidChangeTextEditorOptions.fire({
textEditor: textEditor,
options: data.options
});
}
if (data.selections) {
const kind = TextEditorSelectionChangeKind.fromValue(data.selections.source);
const selections = data.selections.selections.map(TypeConverters.toSelection);
this._onDidChangeTextEditorSelection.fire({
textEditor,
selections,
kind
});
}
}
$acceptEditorPositionData(data: ITextEditorPositionData): void {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册