viewEvents.ts 8.5 KB
Newer Older
1 2 3 4 5 6 7 8
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
A
Alex Dima 已提交
9
import { ScrollEvent } from 'vs/base/common/scrollable';
A
Alex Dima 已提交
10
import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions';
11
import * as errors from 'vs/base/common/errors';
12
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
13
import { ScrollType } from 'vs/editor/common/editorCommon';
14

A
Alex Dima 已提交
15
export const enum ViewEventType {
A
Alex Dima 已提交
16
	ViewConfigurationChanged = 1,
17 18 19 20 21 22 23 24 25 26 27 28 29 30
	ViewCursorStateChanged = 2,
	ViewDecorationsChanged = 3,
	ViewFlushed = 4,
	ViewFocusChanged = 5,
	ViewLineMappingChanged = 6,
	ViewLinesChanged = 7,
	ViewLinesDeleted = 8,
	ViewLinesInserted = 9,
	ViewRevealRangeRequest = 10,
	ViewScrollChanged = 11,
	ViewTokensChanged = 12,
	ViewTokensColorsChanged = 13,
	ViewZonesChanged = 14,
	ViewThemeChanged = 15
A
Alex Dima 已提交
31 32
}

33
export class ViewConfigurationChangedEvent {
A
Alex Dima 已提交
34

35
	public readonly type = ViewEventType.ViewConfigurationChanged;
A
Alex Dima 已提交
36

37
	public readonly canUseLayerHinting: boolean;
38
	public readonly pixelRatio: boolean;
A
Alex Dima 已提交
39
	public readonly editorClassName: boolean;
40 41
	public readonly lineHeight: boolean;
	public readonly readOnly: boolean;
42
	public readonly accessibilitySupport: boolean;
43
	public readonly emptySelectionClipboard: boolean;
44 45
	public readonly layoutInfo: boolean;
	public readonly fontInfo: boolean;
A
Alex Dima 已提交
46
	public readonly viewInfo: boolean;
47 48 49
	public readonly wrappingInfo: boolean;

	constructor(source: IConfigurationChangedEvent) {
50
		this.canUseLayerHinting = source.canUseLayerHinting;
51
		this.pixelRatio = source.pixelRatio;
A
Alex Dima 已提交
52
		this.editorClassName = source.editorClassName;
53 54
		this.lineHeight = source.lineHeight;
		this.readOnly = source.readOnly;
55
		this.accessibilitySupport = source.accessibilitySupport;
56
		this.emptySelectionClipboard = source.emptySelectionClipboard;
57 58 59 60
		this.layoutInfo = source.layoutInfo;
		this.fontInfo = source.fontInfo;
		this.viewInfo = source.viewInfo;
		this.wrappingInfo = source.wrappingInfo;
A
Alex Dima 已提交
61
	}
62 63
}

64
export class ViewCursorStateChangedEvent {
65

66
	public readonly type = ViewEventType.ViewCursorStateChanged;
A
Alex Dima 已提交
67

68
	/**
69
	 * The primary selection is always at index 0.
70
	 */
71
	public readonly selections: Selection[];
72 73 74 75
	/**
	 * Is the primary cursor in the editable range?
	 */
	public readonly isInEditableRange: boolean;
A
Alex Dima 已提交
76

A
Alex Dima 已提交
77
	constructor(selections: Selection[], isInEditableRange: boolean) {
78
		this.selections = selections;
79
		this.isInEditableRange = isInEditableRange;
A
Alex Dima 已提交
80
	}
81 82
}

83
export class ViewDecorationsChangedEvent {
84

85
	public readonly type = ViewEventType.ViewDecorationsChanged;
A
Alex Dima 已提交
86

87 88 89 90
	constructor() {
		// Nothing to do
	}
}
A
Alex Dima 已提交
91

92
export class ViewFlushedEvent {
93 94 95 96 97

	public readonly type = ViewEventType.ViewFlushed;

	constructor() {
		// Nothing to do
A
Alex Dima 已提交
98
	}
99 100
}

101
export class ViewFocusChangedEvent {
102

103
	public readonly type = ViewEventType.ViewFocusChanged;
A
Alex Dima 已提交
104

105
	public readonly isFocused: boolean;
A
Alex Dima 已提交
106

107 108
	constructor(isFocused: boolean) {
		this.isFocused = isFocused;
A
Alex Dima 已提交
109
	}
110 111
}

A
Alex Dima 已提交
112
export class ViewLineMappingChangedEvent {
A
Alex Dima 已提交
113

A
Alex Dima 已提交
114
	public readonly type = ViewEventType.ViewLineMappingChanged;
115

A
Alex Dima 已提交
116 117
	constructor() {
		// Nothing to do
118 119 120
	}
}

A
Alex Dima 已提交
121
export class ViewLinesChangedEvent {
122

A
Alex Dima 已提交
123
	public readonly type = ViewEventType.ViewLinesChanged;
124

A
Alex Dima 已提交
125 126 127 128 129 130 131 132 133 134 135 136
	/**
	 * The first line that has changed.
	 */
	public readonly fromLineNumber: number;
	/**
	 * The last line that has changed.
	 */
	public readonly toLineNumber: number;

	constructor(fromLineNumber: number, toLineNumber: number) {
		this.fromLineNumber = fromLineNumber;
		this.toLineNumber = toLineNumber;
137 138 139
	}
}

140
export class ViewLinesDeletedEvent {
141 142 143

	public readonly type = ViewEventType.ViewLinesDeleted;

144
	/**
145
	 * At what line the deletion began (inclusive).
146
	 */
147
	public readonly fromLineNumber: number;
148
	/**
149
	 * At what line the deletion stopped (inclusive).
150
	 */
151
	public readonly toLineNumber: number;
A
Alex Dima 已提交
152

153 154 155
	constructor(fromLineNumber: number, toLineNumber: number) {
		this.fromLineNumber = fromLineNumber;
		this.toLineNumber = toLineNumber;
A
Alex Dima 已提交
156
	}
157 158
}

159
export class ViewLinesInsertedEvent {
160

161
	public readonly type = ViewEventType.ViewLinesInserted;
A
Alex Dima 已提交
162

163
	/**
164
	 * Before what line did the insertion begin
165
	 */
166
	public readonly fromLineNumber: number;
167
	/**
168
	 * `toLineNumber` - `fromLineNumber` + 1 denotes the number of lines that were inserted
169
	 */
170
	public readonly toLineNumber: number;
A
Alex Dima 已提交
171

172 173 174
	constructor(fromLineNumber: number, toLineNumber: number) {
		this.fromLineNumber = fromLineNumber;
		this.toLineNumber = toLineNumber;
A
Alex Dima 已提交
175
	}
176 177
}

178 179 180 181 182 183 184 185
export const enum VerticalRevealType {
	Simple = 0,
	Center = 1,
	CenterIfOutsideViewport = 2,
	Top = 3,
	Bottom = 4
}

186
export class ViewRevealRangeRequestEvent {
187

A
Alex Dima 已提交
188
	public readonly type = ViewEventType.ViewRevealRangeRequest;
A
Alex Dima 已提交
189

190 191 192
	/**
	 * Range to be reavealed.
	 */
A
Alex Dima 已提交
193
	public readonly range: Range;
194

A
Alex Dima 已提交
195
	public readonly verticalType: VerticalRevealType;
196 197 198 199
	/**
	 * If true: there should be a horizontal & vertical revealing
	 * If false: there should be just a vertical revealing
	 */
A
Alex Dima 已提交
200 201
	public readonly revealHorizontal: boolean;

202 203 204
	public readonly scrollType: ScrollType;

	constructor(range: Range, verticalType: VerticalRevealType, revealHorizontal: boolean, scrollType: ScrollType) {
A
Alex Dima 已提交
205 206 207
		this.range = range;
		this.verticalType = verticalType;
		this.revealHorizontal = revealHorizontal;
208
		this.scrollType = scrollType;
A
Alex Dima 已提交
209
	}
210 211
}

212
export class ViewScrollChangedEvent {
A
Alex Dima 已提交
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238

	public readonly type = ViewEventType.ViewScrollChanged;

	public readonly scrollWidth: number;
	public readonly scrollLeft: number;
	public readonly scrollHeight: number;
	public readonly scrollTop: number;

	public readonly scrollWidthChanged: boolean;
	public readonly scrollLeftChanged: boolean;
	public readonly scrollHeightChanged: boolean;
	public readonly scrollTopChanged: boolean;

	constructor(source: ScrollEvent) {
		this.scrollWidth = source.scrollWidth;
		this.scrollLeft = source.scrollLeft;
		this.scrollHeight = source.scrollHeight;
		this.scrollTop = source.scrollTop;

		this.scrollWidthChanged = source.scrollWidthChanged;
		this.scrollLeftChanged = source.scrollLeftChanged;
		this.scrollHeightChanged = source.scrollHeightChanged;
		this.scrollTopChanged = source.scrollTopChanged;
	}
}

239
export class ViewTokensChangedEvent {
A
Alex Dima 已提交
240

241
	public readonly type = ViewEventType.ViewTokensChanged;
A
Alex Dima 已提交
242

243 244 245 246 247 248 249 250 251 252
	public readonly ranges: {
		/**
		 * Start line number of range
		 */
		readonly fromLineNumber: number;
		/**
		 * End line number of range
		 */
		readonly toLineNumber: number;
	}[];
A
Alex Dima 已提交
253

254 255 256 257 258
	constructor(ranges: { fromLineNumber: number; toLineNumber: number; }[]) {
		this.ranges = ranges;
	}
}

259 260 261 262 263 264 265 266
export class ViewThemeChangedEvent {

	public readonly type = ViewEventType.ViewThemeChanged;

	constructor() {
	}
}

267 268 269 270 271 272 273 274 275
export class ViewTokensColorsChangedEvent {

	public readonly type = ViewEventType.ViewTokensColorsChanged;

	constructor() {
		// Nothing to do
	}
}

276
export class ViewZonesChangedEvent {
277 278 279 280 281

	public readonly type = ViewEventType.ViewZonesChanged;

	constructor() {
		// Nothing to do
A
Alex Dima 已提交
282
	}
283
}
284 285 286

export type ViewEvent = (
	ViewConfigurationChangedEvent
287
	| ViewCursorStateChangedEvent
288 289 290
	| ViewDecorationsChangedEvent
	| ViewFlushedEvent
	| ViewFocusChangedEvent
A
Alex Dima 已提交
291
	| ViewLinesChangedEvent
292 293 294 295 296 297
	| ViewLineMappingChangedEvent
	| ViewLinesDeletedEvent
	| ViewLinesInsertedEvent
	| ViewRevealRangeRequestEvent
	| ViewScrollChangedEvent
	| ViewTokensChangedEvent
298
	| ViewTokensColorsChangedEvent
299
	| ViewZonesChangedEvent
300
	| ViewThemeChangedEvent
301
);
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349

export interface IViewEventListener {
	(events: ViewEvent[]): void;
}

export class ViewEventEmitter extends Disposable {
	private _listeners: IViewEventListener[];

	constructor() {
		super();
		this._listeners = [];
	}

	public dispose(): void {
		this._listeners = [];
		super.dispose();
	}

	protected _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 addEventListener(listener: (events: ViewEvent[]) => void): IDisposable {
		this._listeners.push(listener);
		return {
			dispose: () => {
				let listeners = this._listeners;
				for (let i = 0, len = listeners.length; i < len; i++) {
					if (listeners[i] === listener) {
						listeners.splice(i, 1);
						break;
					}
				}
			}
		};
	}
}

function safeInvokeListener(listener: IViewEventListener, events: ViewEvent[]): void {
	try {
		listener(events);
	} catch (e) {
		errors.onUnexpectedError(e);
	}
}