未验证 提交 6ff4290a 编写于 作者: A Alex Dima

Add ViewModelEventDispatcher

上级 a1ed3861
...@@ -258,14 +258,13 @@ export class TextAreaHandler extends ViewPart { ...@@ -258,14 +258,13 @@ export class TextAreaHandler extends ViewPart {
const lineNumber = this._selections[0].startLineNumber; const lineNumber = this._selections[0].startLineNumber;
const column = this._selections[0].startColumn - (e.moveOneCharacterLeft ? 1 : 0); const column = this._selections[0].startColumn - (e.moveOneCharacterLeft ? 1 : 0);
this._context.privateViewEventBus.emit(new viewEvents.ViewRevealRangeRequestEvent( this._context.model.revealRange(
'keyboard', 'keyboard',
true,
new Range(lineNumber, column, lineNumber, column), new Range(lineNumber, column, lineNumber, column),
null,
viewEvents.VerticalRevealType.Simple, viewEvents.VerticalRevealType.Simple,
true,
ScrollType.Immediate ScrollType.Immediate
)); );
// Find range pixel position // Find range pixel position
const visibleRange = this._viewHelper.visibleRangeForPositionRelativeToEditor(lineNumber, column); const visibleRange = this._viewHelper.visibleRangeForPositionRelativeToEditor(lineNumber, column);
...@@ -308,12 +307,10 @@ export class TextAreaHandler extends ViewPart { ...@@ -308,12 +307,10 @@ export class TextAreaHandler extends ViewPart {
this._register(this._textAreaInput.onFocus(() => { this._register(this._textAreaInput.onFocus(() => {
this._context.model.setHasFocus(true); this._context.model.setHasFocus(true);
this._context.privateViewEventBus.emit(new viewEvents.ViewFocusChangedEvent(true));
})); }));
this._register(this._textAreaInput.onBlur(() => { this._register(this._textAreaInput.onBlur(() => {
this._context.model.setHasFocus(false); this._context.model.setHasFocus(false);
this._context.privateViewEventBus.emit(new viewEvents.ViewFocusChangedEvent(false));
})); }));
} }
......
...@@ -42,7 +42,6 @@ import { Range } from 'vs/editor/common/core/range'; ...@@ -42,7 +42,6 @@ import { Range } from 'vs/editor/common/core/range';
import { IConfiguration, ScrollType } from 'vs/editor/common/editorCommon'; import { IConfiguration, ScrollType } from 'vs/editor/common/editorCommon';
import { RenderingContext } from 'vs/editor/common/view/renderingContext'; import { RenderingContext } from 'vs/editor/common/view/renderingContext';
import { ViewContext } from 'vs/editor/common/view/viewContext'; 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 * as viewEvents from 'vs/editor/common/view/viewEvents';
import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData'; import { ViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler'; import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
...@@ -64,8 +63,6 @@ export interface IOverlayWidgetData { ...@@ -64,8 +63,6 @@ export interface IOverlayWidgetData {
export class View extends ViewEventHandler { export class View extends ViewEventHandler {
private readonly eventDispatcher: ViewEventDispatcher;
private _scrollbar: EditorScrollbar; private _scrollbar: EditorScrollbar;
private readonly _context: ViewContext; private readonly _context: ViewContext;
private _selections: Selection[]; private _selections: Selection[];
...@@ -107,18 +104,15 @@ export class View extends ViewEventHandler { ...@@ -107,18 +104,15 @@ export class View extends ViewEventHandler {
const viewController = new ViewController(configuration, model, this.outgoingEvents, commandDelegate); const viewController = new ViewController(configuration, model, this.outgoingEvents, commandDelegate);
// The event dispatcher will always go through _renderOnce before dispatching any events // The view context is passed on to most classes (basically to reduce param. counts in ctors)
this.eventDispatcher = new ViewEventDispatcher((callback: () => void) => this._renderOnce(callback)); this._context = new ViewContext(configuration, themeService.getColorTheme(), model);
// Ensure the view is the first event handler in order to update the layout // Ensure the view is the first event handler in order to update the layout
this.eventDispatcher.addEventHandler(this); this._context.addEventHandler(this);
// The view context is passed on to most classes (basically to reduce param. counts in ctors)
this._context = new ViewContext(configuration, themeService.getColorTheme(), model, this.eventDispatcher);
this._register(themeService.onDidColorThemeChange(theme => { this._register(themeService.onDidColorThemeChange(theme => {
this._context.theme.update(theme); this._context.theme.update(theme);
this.eventDispatcher.emit(new viewEvents.ViewThemeChangedEvent()); this._context.model.onDidColorThemeChange();
this.render(true, false); this.render(true, false);
})); }));
...@@ -224,10 +218,6 @@ export class View extends ViewEventHandler { ...@@ -224,10 +218,6 @@ export class View extends ViewEventHandler {
// Pointer handler // Pointer handler
this.pointerHandler = this._register(new PointerHandler(this._context, viewController, this.createPointerHandlerHelper())); this.pointerHandler = this._register(new PointerHandler(this._context, viewController, this.createPointerHandlerHelper()));
this._register(model.addViewEventListener((events: viewEvents.ViewEvent[]) => {
this.eventDispatcher.emitMany(events);
}));
} }
private _flushAccumulatedAndRenderNow(): void { private _flushAccumulatedAndRenderNow(): void {
...@@ -300,7 +290,10 @@ export class View extends ViewEventHandler { ...@@ -300,7 +290,10 @@ export class View extends ViewEventHandler {
} }
// --- begin event handlers // --- begin event handlers
public handleEvents(events: viewEvents.ViewEvent[]): void {
super.handleEvents(events);
this._scheduleRender();
}
public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean { public onConfigurationChanged(e: viewEvents.ViewConfigurationChangedEvent): boolean {
this.domNode.setClassName(this.getEditorClassName()); this.domNode.setClassName(this.getEditorClassName());
this._applyLayout(); this._applyLayout();
...@@ -340,7 +333,7 @@ export class View extends ViewEventHandler { ...@@ -340,7 +333,7 @@ export class View extends ViewEventHandler {
this._renderAnimationFrame = null; this._renderAnimationFrame = null;
} }
this.eventDispatcher.removeEventHandler(this); this._context.removeEventHandler(this);
this.outgoingEvents.dispose(); this.outgoingEvents.dispose();
this.viewLines.dispose(); this.viewLines.dispose();
...@@ -354,12 +347,6 @@ export class View extends ViewEventHandler { ...@@ -354,12 +347,6 @@ export class View extends ViewEventHandler {
super.dispose(); super.dispose();
} }
private _renderOnce<T>(callback: () => T): T {
const r = safeInvokeNoArg(callback);
this._scheduleRender();
return r;
}
private _scheduleRender(): void { private _scheduleRender(): void {
if (this._renderAnimationFrame === null) { if (this._renderAnimationFrame === null) {
this._renderAnimationFrame = dom.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), 100); this._renderAnimationFrame = dom.runAtThisOrScheduleAtNextAnimationFrame(this._onRenderScheduled.bind(this), 100);
...@@ -477,13 +464,9 @@ export class View extends ViewEventHandler { ...@@ -477,13 +464,9 @@ export class View extends ViewEventHandler {
} }
public change(callback: (changeAccessor: IViewZoneChangeAccessor) => any): boolean { public change(callback: (changeAccessor: IViewZoneChangeAccessor) => any): boolean {
return this._renderOnce(() => { const hadAChange = this.viewZones.changeViewZones(callback);
const zonesHaveChanged = this.viewZones.changeViewZones(callback); this._scheduleRender();
if (zonesHaveChanged) { return hadAChange;
this._context.privateViewEventBus.emit(new viewEvents.ViewZonesChangedEvent());
}
return zonesHaveChanged;
});
} }
public render(now: boolean, everything: boolean): void { public render(now: boolean, everything: boolean): void {
......
...@@ -1011,14 +1011,13 @@ export class Minimap extends ViewPart implements IMinimapModel { ...@@ -1011,14 +1011,13 @@ export class Minimap extends ViewPart implements IMinimapModel {
if (this._samplingState) { if (this._samplingState) {
lineNumber = this._samplingState.minimapLines[lineNumber - 1]; lineNumber = this._samplingState.minimapLines[lineNumber - 1];
} }
this._context.privateViewEventBus.emit(new viewEvents.ViewRevealRangeRequestEvent( this._context.model.revealRange(
'mouse', 'mouse',
false,
new Range(lineNumber, 1, lineNumber, 1), new Range(lineNumber, 1, lineNumber, 1),
null,
viewEvents.VerticalRevealType.Center, viewEvents.VerticalRevealType.Center,
false,
ScrollType.Smooth ScrollType.Smooth
)); );
} }
public setScrollTop(scrollTop: number): void { public setScrollTop(scrollTop: number): void {
......
...@@ -222,8 +222,6 @@ export class ViewZones extends ViewPart { ...@@ -222,8 +222,6 @@ export class ViewZones extends ViewPart {
changeAccessor.addZone = invalidFunc; changeAccessor.addZone = invalidFunc;
changeAccessor.removeZone = invalidFunc; changeAccessor.removeZone = invalidFunc;
changeAccessor.layoutZone = invalidFunc; changeAccessor.layoutZone = invalidFunc;
return zonesHaveChanged;
}); });
return zonesHaveChanged; return zonesHaveChanged;
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { IConfiguration } from 'vs/editor/common/editorCommon'; import { IConfiguration } from 'vs/editor/common/editorCommon';
import { ViewEventDispatcher } from 'vs/editor/common/view/viewEventDispatcher';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler'; import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { IViewLayout, IViewModel } from 'vs/editor/common/viewModel/viewModel'; import { IViewLayout, IViewModel } from 'vs/editor/common/viewModel/viewModel';
import { IColorTheme, ThemeType } from 'vs/platform/theme/common/themeService'; import { IColorTheme, ThemeType } from 'vs/platform/theme/common/themeService';
...@@ -37,27 +36,24 @@ export class ViewContext { ...@@ -37,27 +36,24 @@ export class ViewContext {
public readonly configuration: IConfiguration; public readonly configuration: IConfiguration;
public readonly model: IViewModel; public readonly model: IViewModel;
public readonly viewLayout: IViewLayout; public readonly viewLayout: IViewLayout;
public readonly privateViewEventBus: ViewEventDispatcher;
public readonly theme: EditorTheme; public readonly theme: EditorTheme;
constructor( constructor(
configuration: IConfiguration, configuration: IConfiguration,
theme: IColorTheme, theme: IColorTheme,
model: IViewModel, model: IViewModel
privateViewEventBus: ViewEventDispatcher
) { ) {
this.configuration = configuration; this.configuration = configuration;
this.theme = new EditorTheme(theme); this.theme = new EditorTheme(theme);
this.model = model; this.model = model;
this.viewLayout = model.viewLayout; this.viewLayout = model.viewLayout;
this.privateViewEventBus = privateViewEventBus;
} }
public addEventHandler(eventHandler: ViewEventHandler): void { public addEventHandler(eventHandler: ViewEventHandler): void {
this.privateViewEventBus.addEventHandler(eventHandler); this.model.addViewEventHandler(eventHandler);
} }
public removeEventHandler(eventHandler: ViewEventHandler): void { public removeEventHandler(eventHandler: ViewEventHandler): void {
this.privateViewEventBus.removeEventHandler(eventHandler); this.model.removeViewEventHandler(eventHandler);
} }
} }
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as errors from 'vs/base/common/errors'; import { ViewModelEventDispatcher } from 'vs/editor/common/viewModel/viewModelEventDispatcher';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { ScrollEvent } from 'vs/base/common/scrollable'; import { ScrollEvent } from 'vs/base/common/scrollable';
import { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config/editorOptions'; import { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config/editorOptions';
import { Range } from 'vs/editor/common/core/range'; import { Range } from 'vs/editor/common/core/range';
...@@ -330,27 +330,16 @@ export interface IViewEventListener { ...@@ -330,27 +330,16 @@ export interface IViewEventListener {
(events: ViewEvent[]): void; (events: ViewEvent[]): void;
} }
export interface IViewEventEmitter { export class ViewEventEmitter extends Disposable {
addViewEventListener(listener: IViewEventListener): IDisposable;
}
export class ViewEventEmitter extends Disposable implements IViewEventEmitter {
private _listeners: IViewEventListener[];
private _collector: ViewEventsCollector | null; private _collector: ViewEventsCollector | null;
private _collectorCnt: number; private _collectorCnt: number;
constructor() { constructor() {
super(); super();
this._listeners = [];
this._collector = null; this._collector = null;
this._collectorCnt = 0; this._collectorCnt = 0;
} }
public dispose(): void {
this._listeners = [];
super.dispose();
}
protected _beginEmitViewEvents(): ViewEventsCollector { protected _beginEmitViewEvents(): ViewEventsCollector {
this._collectorCnt++; this._collectorCnt++;
if (this._collectorCnt === 1) { if (this._collectorCnt === 1) {
...@@ -359,45 +348,25 @@ export class ViewEventEmitter extends Disposable implements IViewEventEmitter { ...@@ -359,45 +348,25 @@ export class ViewEventEmitter extends Disposable implements IViewEventEmitter {
return this._collector!; return this._collector!;
} }
protected _endEmitViewEvents(): void { protected _endEmitViewEvents(eventDispatcher: ViewModelEventDispatcher): void {
this._collectorCnt--; this._collectorCnt--;
if (this._collectorCnt === 0) { if (this._collectorCnt === 0) {
const events = this._collector!.finalize(); const events = this._collector!.finalize();
this._collector = null; this._collector = null;
if (events.length > 0) { if (events.length > 0) {
this._emit(events); eventDispatcher.emitMany(events);
} }
} }
} }
protected _emitSingleViewEvent(event: ViewEvent): void { protected _emitSingleViewEvent(eventDispatcher: ViewModelEventDispatcher, event: ViewEvent): void {
try { try {
const eventsCollector = this._beginEmitViewEvents(); const eventsCollector = this._beginEmitViewEvents();
eventsCollector.emit(event); eventsCollector.emit(event);
} finally { } finally {
this._endEmitViewEvents(); this._endEmitViewEvents(eventDispatcher);
} }
} }
private _emit(events: ViewEvent[]): void {
const listeners = this._listeners.slice(0);
for (let i = 0, len = listeners.length; i < len; i++) {
safeInvokeListener(listeners[i], events);
}
}
public addViewEventListener(listener: IViewEventListener): IDisposable {
this._listeners.push(listener);
return toDisposable(() => {
let listeners = this._listeners;
for (let i = 0, len = listeners.length; i < len; i++) {
if (listeners[i] === listener) {
listeners.splice(i, 1);
break;
}
}
});
}
} }
export class ViewEventsCollector { export class ViewEventsCollector {
...@@ -421,11 +390,3 @@ export class ViewEventsCollector { ...@@ -421,11 +390,3 @@ export class ViewEventsCollector {
} }
} }
function safeInvokeListener(listener: IViewEventListener, events: ViewEvent[]): void {
try {
listener(events);
} catch (e) {
errors.onUnexpectedError(e);
}
}
...@@ -353,11 +353,12 @@ export class ViewLayout extends Disposable implements IViewLayout { ...@@ -353,11 +353,12 @@ export class ViewLayout extends Disposable implements IViewLayout {
} }
// ---- IVerticalLayoutProvider // ---- IVerticalLayoutProvider
public changeWhitespace(callback: (accessor: IWhitespaceChangeAccessor) => void): void { public changeWhitespace(callback: (accessor: IWhitespaceChangeAccessor) => void): boolean {
const hadAChange = this._linesLayout.changeWhitespace(callback); const hadAChange = this._linesLayout.changeWhitespace(callback);
if (hadAChange) { if (hadAChange) {
this.onHeightMaybeChanged(); this.onHeightMaybeChanged();
} }
return hadAChange;
} }
public getVerticalOffsetForLineNumber(lineNumber: number): number { public getVerticalOffsetForLineNumber(lineNumber: number): number {
return this._linesLayout.getVerticalOffsetForLineNumber(lineNumber); return this._linesLayout.getVerticalOffsetForLineNumber(lineNumber);
......
...@@ -10,12 +10,13 @@ import { IPosition, Position } from 'vs/editor/common/core/position'; ...@@ -10,12 +10,13 @@ import { IPosition, Position } from 'vs/editor/common/core/position';
import { IRange, Range } from 'vs/editor/common/core/range'; import { IRange, Range } from 'vs/editor/common/core/range';
import { INewScrollPosition, ScrollType } from 'vs/editor/common/editorCommon'; import { INewScrollPosition, ScrollType } from 'vs/editor/common/editorCommon';
import { EndOfLinePreference, IActiveIndentGuideInfo, IModelDecorationOptions, TextModelResolvedOptions, ITextModel } from 'vs/editor/common/model'; import { EndOfLinePreference, IActiveIndentGuideInfo, IModelDecorationOptions, TextModelResolvedOptions, ITextModel } from 'vs/editor/common/model';
import { IViewEventEmitter, VerticalRevealType } from 'vs/editor/common/view/viewEvents'; import { VerticalRevealType } from 'vs/editor/common/view/viewEvents';
import { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData'; import { IPartialViewLinesViewportData } from 'vs/editor/common/viewLayout/viewLinesViewportData';
import { IEditorWhitespace, IWhitespaceChangeAccessor } from 'vs/editor/common/viewLayout/linesLayout'; import { IEditorWhitespace, IWhitespaceChangeAccessor } from 'vs/editor/common/viewLayout/linesLayout';
import { EditorTheme } from 'vs/editor/common/view/viewContext'; import { EditorTheme } from 'vs/editor/common/view/viewContext';
import { ICursorSimpleModel, PartialCursorState, CursorState, IColumnSelectData, EditOperationType, CursorConfiguration } from 'vs/editor/common/controller/cursorCommon'; import { ICursorSimpleModel, PartialCursorState, CursorState, IColumnSelectData, EditOperationType, CursorConfiguration } from 'vs/editor/common/controller/cursorCommon';
import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents'; import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
export interface IViewWhitespaceViewportData { export interface IViewWhitespaceViewportData {
readonly id: string; readonly id: string;
...@@ -83,7 +84,7 @@ export interface ICoordinatesConverter { ...@@ -83,7 +84,7 @@ export interface ICoordinatesConverter {
modelPositionIsVisible(modelPosition: Position): boolean; modelPositionIsVisible(modelPosition: Position): boolean;
} }
export interface IViewModel extends IViewEventEmitter, ICursorSimpleModel { export interface IViewModel extends ICursorSimpleModel {
readonly model: ITextModel; readonly model: ITextModel;
...@@ -93,12 +94,16 @@ export interface IViewModel extends IViewEventEmitter, ICursorSimpleModel { ...@@ -93,12 +94,16 @@ export interface IViewModel extends IViewEventEmitter, ICursorSimpleModel {
readonly cursorConfig: CursorConfiguration; readonly cursorConfig: CursorConfiguration;
addViewEventHandler(eventHandler: ViewEventHandler): void;
removeViewEventHandler(eventHandler: ViewEventHandler): void;
/** /**
* Gives a hint that a lot of requests are about to come in for these line numbers. * Gives a hint that a lot of requests are about to come in for these line numbers.
*/ */
setViewport(startLineNumber: number, endLineNumber: number, centeredLineNumber: number): void; setViewport(startLineNumber: number, endLineNumber: number, centeredLineNumber: number): void;
tokenizeViewport(): void; tokenizeViewport(): void;
setHasFocus(hasFocus: boolean): void; setHasFocus(hasFocus: boolean): void;
onDidColorThemeChange(): void;
getDecorationsInViewport(visibleRange: Range): ViewModelDecoration[]; getDecorationsInViewport(visibleRange: Range): ViewModelDecoration[];
getViewLineRenderingData(visibleRange: Range, lineNumber: number): ViewLineRenderingData; getViewLineRenderingData(visibleRange: Range, lineNumber: number): ViewLineRenderingData;
......
...@@ -3,24 +3,25 @@ ...@@ -3,24 +3,25 @@
* Licensed under the MIT License. See License.txt in the project root for license information. * Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { ViewEvent } from 'vs/editor/common/view/viewEvents';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler'; import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { ViewEvent } from 'vs/editor/common/view/viewEvents';
import { IContentSizeChangedEvent } from 'vs/editor/common/editorCommon';
export class ViewEventDispatcher { export class ViewModelEventDispatcher {
private readonly _eventHandlerGateKeeper: (callback: () => void) => void;
private readonly _eventHandlers: ViewEventHandler[]; private readonly _eventHandlers: ViewEventHandler[];
private _eventQueue: ViewEvent[] | null; private _viewEventQueue: ViewEvent[] | null;
private _isConsumingQueue: boolean; private _isConsumingViewEventQueue: boolean;
// private _outgoingContentSizeChangedEvent: OutgoingContentSizeChangedEvent | null;
constructor(eventHandlerGateKeeper: (callback: () => void) => void) { constructor() {
this._eventHandlerGateKeeper = eventHandlerGateKeeper;
this._eventHandlers = []; this._eventHandlers = [];
this._eventQueue = null; this._viewEventQueue = null;
this._isConsumingQueue = false; this._isConsumingViewEventQueue = false;
// this._outgoingContentSizeChangedEvent = null;
} }
public addEventHandler(eventHandler: ViewEventHandler): void { public addViewEventHandler(eventHandler: ViewEventHandler): void {
for (let i = 0, len = this._eventHandlers.length; i < len; i++) { for (let i = 0, len = this._eventHandlers.length; i < len; i++) {
if (this._eventHandlers[i] === eventHandler) { if (this._eventHandlers[i] === eventHandler) {
console.warn('Detected duplicate listener in ViewEventDispatcher', eventHandler); console.warn('Detected duplicate listener in ViewEventDispatcher', eventHandler);
...@@ -29,7 +30,7 @@ export class ViewEventDispatcher { ...@@ -29,7 +30,7 @@ export class ViewEventDispatcher {
this._eventHandlers.push(eventHandler); this._eventHandlers.push(eventHandler);
} }
public removeEventHandler(eventHandler: ViewEventHandler): void { public removeViewEventHandler(eventHandler: ViewEventHandler): void {
for (let i = 0; i < this._eventHandlers.length; i++) { for (let i = 0; i < this._eventHandlers.length; i++) {
if (this._eventHandlers[i] === eventHandler) { if (this._eventHandlers[i] === eventHandler) {
this._eventHandlers.splice(i, 1); this._eventHandlers.splice(i, 1);
...@@ -38,55 +39,58 @@ export class ViewEventDispatcher { ...@@ -38,55 +39,58 @@ export class ViewEventDispatcher {
} }
} }
public emit(event: ViewEvent): void {
if (this._eventQueue) {
this._eventQueue.push(event);
} else {
this._eventQueue = [event];
}
if (!this._isConsumingQueue) {
this.consumeQueue();
}
}
public emitMany(events: ViewEvent[]): void { public emitMany(events: ViewEvent[]): void {
if (this._eventQueue) { if (this._viewEventQueue) {
this._eventQueue = this._eventQueue.concat(events); this._viewEventQueue = this._viewEventQueue.concat(events);
} else { } else {
this._eventQueue = events; this._viewEventQueue = events;
} }
if (!this._isConsumingQueue) { if (!this._isConsumingViewEventQueue) {
this.consumeQueue(); this._consumeViewEventQueue();
} }
} }
private consumeQueue(): void { private _consumeViewEventQueue(): void {
this._eventHandlerGateKeeper(() => {
try { try {
this._isConsumingQueue = true; this._isConsumingViewEventQueue = true;
this._doConsumeQueue(); this._doConsumeQueue();
} finally { } finally {
this._isConsumingQueue = false; this._isConsumingViewEventQueue = false;
} }
});
} }
private _doConsumeQueue(): void { private _doConsumeQueue(): void {
while (this._eventQueue) { while (this._viewEventQueue) {
// Empty event queue, as events might come in while sending these off // Empty event queue, as events might come in while sending these off
let events = this._eventQueue; const events = this._viewEventQueue;
this._eventQueue = null; this._viewEventQueue = null;
// Use a clone of the event handlers list, as they might remove themselves // Use a clone of the event handlers list, as they might remove themselves
let eventHandlers = this._eventHandlers.slice(0); const eventHandlers = this._eventHandlers.slice(0);
for (let i = 0, len = eventHandlers.length; i < len; i++) { for (const eventHandler of eventHandlers) {
eventHandlers[i].handleEvents(events); eventHandler.handleEvents(events);
} }
} }
} }
} }
export class OutgoingContentSizeChangedEvent implements IContentSizeChangedEvent {
private readonly _oldContentWidth: number;
private readonly _oldContentHeight: number;
readonly contentWidth: number;
readonly contentHeight: number;
readonly contentWidthChanged: boolean;
readonly contentHeightChanged: boolean;
constructor(oldContentWidth: number, oldContentHeight: number, contentWidth: number, contentHeight: number) {
this._oldContentWidth = oldContentWidth;
this._oldContentHeight = oldContentHeight;
this.contentWidth = contentWidth;
this.contentHeight = contentHeight;
this.contentWidthChanged = (this._oldContentWidth !== this.contentWidth);
this.contentHeightChanged = (this._oldContentHeight !== this.contentHeight);
}
}
...@@ -29,6 +29,8 @@ import { Cursor } from 'vs/editor/common/controller/cursor'; ...@@ -29,6 +29,8 @@ import { Cursor } from 'vs/editor/common/controller/cursor';
import { PartialCursorState, CursorState, IColumnSelectData, EditOperationType, CursorConfiguration } from 'vs/editor/common/controller/cursorCommon'; import { PartialCursorState, CursorState, IColumnSelectData, EditOperationType, CursorConfiguration } from 'vs/editor/common/controller/cursorCommon';
import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents'; import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents';
import { IWhitespaceChangeAccessor } from 'vs/editor/common/viewLayout/linesLayout'; import { IWhitespaceChangeAccessor } from 'vs/editor/common/viewLayout/linesLayout';
import { ViewModelEventDispatcher } from 'vs/editor/common/viewModel/viewModelEventDispatcher';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
const USE_IDENTITY_LINES_COLLECTION = true; const USE_IDENTITY_LINES_COLLECTION = true;
...@@ -37,6 +39,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -37,6 +39,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
private readonly editorId: number; private readonly editorId: number;
private readonly configuration: IConfiguration; private readonly configuration: IConfiguration;
public readonly model: ITextModel; public readonly model: ITextModel;
private readonly _eventDispatcher: ViewModelEventDispatcher;
public cursorConfig: CursorConfiguration; public cursorConfig: CursorConfiguration;
private readonly _tokenizeViewportSoon: RunOnceScheduler; private readonly _tokenizeViewportSoon: RunOnceScheduler;
private readonly _updateConfigurationViewLineCount: RunOnceScheduler; private readonly _updateConfigurationViewLineCount: RunOnceScheduler;
...@@ -63,6 +66,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -63,6 +66,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
this.editorId = editorId; this.editorId = editorId;
this.configuration = configuration; this.configuration = configuration;
this.model = model; this.model = model;
this._eventDispatcher = new ViewModelEventDispatcher();
this.cursorConfig = new CursorConfiguration(this.model.getLanguageIdentifier(), this.model.getOptions(), this.configuration); this.cursorConfig = new CursorConfiguration(this.model.getLanguageIdentifier(), this.model.getOptions(), this.configuration);
this._tokenizeViewportSoon = this._register(new RunOnceScheduler(() => this.tokenizeViewport(), 50)); this._tokenizeViewportSoon = this._register(new RunOnceScheduler(() => this.tokenizeViewport(), 50));
this._updateConfigurationViewLineCount = this._register(new RunOnceScheduler(() => this._updateConfigurationViewLineCountNow(), 0)); this._updateConfigurationViewLineCount = this._register(new RunOnceScheduler(() => this._updateConfigurationViewLineCountNow(), 0));
...@@ -104,11 +108,11 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -104,11 +108,11 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
if (e.scrollTopChanged) { if (e.scrollTopChanged) {
this._tokenizeViewportSoon.schedule(); this._tokenizeViewportSoon.schedule();
} }
this._emitSingleViewEvent(new viewEvents.ViewScrollChangedEvent(e)); this._emitSingleViewEvent(this._eventDispatcher, new viewEvents.ViewScrollChangedEvent(e));
})); }));
this._register(this.viewLayout.onDidContentSizeChange((e) => { this._register(this.viewLayout.onDidContentSizeChange((e) => {
this._emitSingleViewEvent(new viewEvents.ViewContentSizeChangedEvent(e)); this._emitSingleViewEvent(this._eventDispatcher, new viewEvents.ViewContentSizeChangedEvent(e));
})); }));
this.decorations = new ViewModelDecorations(this.editorId, this.model, this.configuration, this.lines, this.coordinatesConverter); this.decorations = new ViewModelDecorations(this.editorId, this.model, this.configuration, this.lines, this.coordinatesConverter);
...@@ -120,12 +124,12 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -120,12 +124,12 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
const eventsCollector = this._beginEmitViewEvents(); const eventsCollector = this._beginEmitViewEvents();
this._onConfigurationChanged(eventsCollector, e); this._onConfigurationChanged(eventsCollector, e);
} finally { } finally {
this._endEmitViewEvents(); this._endEmitViewEvents(this._eventDispatcher);
} }
})); }));
this._register(MinimapTokensColorTracker.getInstance().onDidChange(() => { this._register(MinimapTokensColorTracker.getInstance().onDidChange(() => {
this._emitSingleViewEvent(new viewEvents.ViewTokensColorsChangedEvent()); this._emitSingleViewEvent(this._eventDispatcher, new viewEvents.ViewTokensColorsChangedEvent());
})); }));
this._updateConfigurationViewLineCountNow(); this._updateConfigurationViewLineCountNow();
...@@ -141,6 +145,14 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -141,6 +145,14 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
this.viewportStartLineTrackedRange = this.model._setTrackedRange(this.viewportStartLineTrackedRange, null, TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges); this.viewportStartLineTrackedRange = this.model._setTrackedRange(this.viewportStartLineTrackedRange, null, TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges);
} }
public addViewEventHandler(eventHandler: ViewEventHandler): void {
this._eventDispatcher.addViewEventHandler(eventHandler);
}
public removeViewEventHandler(eventHandler: ViewEventHandler): void {
this._eventDispatcher.removeViewEventHandler(eventHandler);
}
private _updateConfigurationViewLineCountNow(): void { private _updateConfigurationViewLineCountNow(): void {
this.configuration.setViewLineCount(this.lines.getViewLineCount()); this.configuration.setViewLineCount(this.lines.getViewLineCount());
} }
...@@ -155,6 +167,11 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -155,6 +167,11 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
public setHasFocus(hasFocus: boolean): void { public setHasFocus(hasFocus: boolean): void {
this.hasFocus = hasFocus; this.hasFocus = hasFocus;
this.cursor.setHasFocus(hasFocus); this.cursor.setHasFocus(hasFocus);
this._emitSingleViewEvent(this._eventDispatcher, new viewEvents.ViewFocusChangedEvent(hasFocus));
}
public onDidColorThemeChange(): void {
this._emitSingleViewEvent(this._eventDispatcher, new viewEvents.ViewThemeChangedEvent());
} }
private _onConfigurationChanged(eventsCollector: viewEvents.ViewEventsCollector, e: ConfigurationChangedEvent): void { private _onConfigurationChanged(eventsCollector: viewEvents.ViewEventsCollector, e: ConfigurationChangedEvent): void {
...@@ -308,7 +325,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -308,7 +325,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
this.decorations.onLineMappingChanged(); this.decorations.onLineMappingChanged();
} }
} finally { } finally {
this._endEmitViewEvents(); this._endEmitViewEvents(this._eventDispatcher);
} }
// Update the configuration and reset the centered view line // Update the configuration and reset the centered view line
...@@ -330,7 +347,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -330,7 +347,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
const eventsCollector = this._beginEmitViewEvents(); const eventsCollector = this._beginEmitViewEvents();
this.cursor.onModelContentChanged(eventsCollector, e); this.cursor.onModelContentChanged(eventsCollector, e);
} finally { } finally {
this._endEmitViewEvents(); this._endEmitViewEvents(this._eventDispatcher);
} }
})); }));
...@@ -345,7 +362,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -345,7 +362,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
toLineNumber: viewEndLineNumber toLineNumber: viewEndLineNumber
}; };
} }
this._emitSingleViewEvent(new viewEvents.ViewTokensChangedEvent(viewRanges)); this._emitSingleViewEvent(this._eventDispatcher, new viewEvents.ViewTokensChangedEvent(viewRanges));
if (e.tokenizationSupportChanged) { if (e.tokenizationSupportChanged) {
this._tokenizeViewportSoon.schedule(); this._tokenizeViewportSoon.schedule();
...@@ -353,7 +370,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -353,7 +370,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
})); }));
this._register(this.model.onDidChangeLanguageConfiguration((e) => { this._register(this.model.onDidChangeLanguageConfiguration((e) => {
this._emitSingleViewEvent(new viewEvents.ViewLanguageConfigurationEvent()); this._emitSingleViewEvent(this._eventDispatcher, new viewEvents.ViewLanguageConfigurationEvent());
this.cursorConfig = new CursorConfiguration(this.model.getLanguageIdentifier(), this.model.getOptions(), this.configuration); this.cursorConfig = new CursorConfiguration(this.model.getLanguageIdentifier(), this.model.getOptions(), this.configuration);
this.cursor.updateConfiguration(this.cursorConfig); this.cursor.updateConfiguration(this.cursorConfig);
})); }));
...@@ -375,7 +392,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -375,7 +392,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
this.decorations.onLineMappingChanged(); this.decorations.onLineMappingChanged();
this.viewLayout.onFlushed(this.getLineCount()); this.viewLayout.onFlushed(this.getLineCount());
} finally { } finally {
this._endEmitViewEvents(); this._endEmitViewEvents(this._eventDispatcher);
} }
this._updateConfigurationViewLineCount.schedule(); this._updateConfigurationViewLineCount.schedule();
} }
...@@ -386,7 +403,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -386,7 +403,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
this._register(this.model.onDidChangeDecorations((e) => { this._register(this.model.onDidChangeDecorations((e) => {
this.decorations.onModelDecorationsChanged(); this.decorations.onModelDecorationsChanged();
this._emitSingleViewEvent(new viewEvents.ViewDecorationsChangedEvent(e)); this._emitSingleViewEvent(this._eventDispatcher, new viewEvents.ViewDecorationsChangedEvent(e));
})); }));
} }
...@@ -404,7 +421,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -404,7 +421,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
this.viewLayout.onHeightMaybeChanged(); this.viewLayout.onHeightMaybeChanged();
} }
} finally { } finally {
this._endEmitViewEvents(); this._endEmitViewEvents(this._eventDispatcher);
} }
this._updateConfigurationViewLineCount.schedule(); this._updateConfigurationViewLineCount.schedule();
} }
...@@ -951,7 +968,10 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -951,7 +968,10 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
this.viewLayout.deltaScrollNow(deltaScrollLeft, deltaScrollTop); this.viewLayout.deltaScrollNow(deltaScrollLeft, deltaScrollTop);
} }
public changeWhitespace(callback: (accessor: IWhitespaceChangeAccessor) => void): void { public changeWhitespace(callback: (accessor: IWhitespaceChangeAccessor) => void): void {
return this.viewLayout.changeWhitespace(callback); const hadAChange = this.viewLayout.changeWhitespace(callback);
if (hadAChange) {
this._emitSingleViewEvent(this._eventDispatcher, new viewEvents.ViewZonesChangedEvent());
}
} }
public setMaxLineWidth(maxLineWidth: number): void { public setMaxLineWidth(maxLineWidth: number): void {
this.viewLayout.setMaxLineWidth(maxLineWidth); this.viewLayout.setMaxLineWidth(maxLineWidth);
...@@ -963,7 +983,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel ...@@ -963,7 +983,7 @@ export class ViewModel extends viewEvents.ViewEventEmitter implements IViewModel
const eventsCollector = this._beginEmitViewEvents(); const eventsCollector = this._beginEmitViewEvents();
callback(eventsCollector); callback(eventsCollector);
} finally { } finally {
this._endEmitViewEvents(); this._endEmitViewEvents(this._eventDispatcher);
} }
} }
} }
...@@ -7,6 +7,8 @@ import * as assert from 'assert'; ...@@ -7,6 +7,8 @@ import * as assert from 'assert';
import { Range } from 'vs/editor/common/core/range'; import { Range } from 'vs/editor/common/core/range';
import { EndOfLineSequence } from 'vs/editor/common/model'; import { EndOfLineSequence } from 'vs/editor/common/model';
import { testViewModel } from 'vs/editor/test/common/viewModel/testViewModel'; import { testViewModel } from 'vs/editor/test/common/viewModel/testViewModel';
import { ViewEventHandler } from 'vs/editor/common/viewModel/viewEventHandler';
import { ViewEvent } from 'vs/editor/common/view/viewEvents';
suite('ViewModel', () => { suite('ViewModel', () => {
...@@ -63,9 +65,11 @@ suite('ViewModel', () => { ...@@ -63,9 +65,11 @@ suite('ViewModel', () => {
let viewLineCount: number[] = []; let viewLineCount: number[] = [];
viewLineCount.push(viewModel.getLineCount()); viewLineCount.push(viewModel.getLineCount());
viewModel.addViewEventListener((events) => { viewModel.addViewEventHandler(new class extends ViewEventHandler {
handleEvents(events: ViewEvent[]): void {
// Access the view model // Access the view model
viewLineCount.push(viewModel.getLineCount()); viewLineCount.push(viewModel.getLineCount());
}
}); });
model.undo(); model.undo();
viewLineCount.push(viewModel.getLineCount()); viewLineCount.push(viewModel.getLineCount());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册