untitledEditorModel.ts 4.9 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

7
import {IDisposable} from 'vs/base/common/lifecycle';
E
Erich Gamma 已提交
8 9
import {TPromise} from 'vs/base/common/winjs.base';
import {EditorModel, IEncodingSupport} from 'vs/workbench/common/editor';
10
import {StringEditorModel} from 'vs/workbench/common/editor/stringEditorModel';
E
Erich Gamma 已提交
11
import URI from 'vs/base/common/uri';
A
Alex Dima 已提交
12
import {EventType, EndOfLinePreference} from 'vs/editor/common/editorCommon';
13
import {EventType as WorkbenchEventType, ResourceEvent} from 'vs/workbench/common/events';
E
Erich Gamma 已提交
14
import {IFilesConfiguration} from 'vs/platform/files/common/files';
15
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
E
Erich Gamma 已提交
16 17 18
import {IEventService} from 'vs/platform/event/common/event';
import {IModeService} from 'vs/editor/common/services/modeService';
import {IModelService} from 'vs/editor/common/services/modelService';
19 20
import {IMode} from 'vs/editor/common/modes';
import {isUnspecific} from 'vs/base/common/mime';
21
import Event, {Emitter} from 'vs/base/common/event';
E
Erich Gamma 已提交
22 23

export class UntitledEditorModel extends StringEditorModel implements IEncodingSupport {
A
Alex Dima 已提交
24
	private textModelChangeListener: IDisposable;
25
	private configurationChangeListener: IDisposable;
E
Erich Gamma 已提交
26 27

	private dirty: boolean;
28 29
	private _onDidChangeDirty: Emitter<void>;

E
Erich Gamma 已提交
30 31 32 33 34
	private configuredEncoding: string;
	private preferredEncoding: string;

	constructor(
		value: string,
35
		mime: string,
E
Erich Gamma 已提交
36 37 38 39 40 41 42
		resource: URI,
		hasAssociatedFilePath: boolean,
		@IModeService modeService: IModeService,
		@IModelService modelService: IModelService,
		@IEventService private eventService: IEventService,
		@IConfigurationService private configurationService: IConfigurationService
	) {
43
		super(value, mime, resource, modeService, modelService);
E
Erich Gamma 已提交
44 45 46

		this.dirty = hasAssociatedFilePath; // untitled associated to file path are dirty right away

47 48
		this._onDidChangeDirty = new Emitter<void>();

E
Erich Gamma 已提交
49 50 51
		this.registerListeners();
	}

52 53 54 55
	public get onDidChangeDirty(): Event<void> {
		return this._onDidChangeDirty.event;
	}

56 57 58 59 60 61 62 63
	protected getOrCreateMode(modeService: IModeService, mime: string, firstLineText?: string): TPromise<IMode> {
		if (isUnspecific(mime)) {
			return modeService.getOrCreateModeByFilenameOrFirstLine(this.resource.fsPath, firstLineText); // lookup mode via resource path if the provided mime is unspecific
		}

		return super.getOrCreateMode(modeService, mime, firstLineText);
	}

E
Erich Gamma 已提交
64 65 66
	private registerListeners(): void {

		// Config Changes
67
		this.configurationChangeListener = this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange(e.config));
E
Erich Gamma 已提交
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
	}

	private onConfigurationChange(configuration: IFilesConfiguration): void {
		this.configuredEncoding = configuration && configuration.files && configuration.files.encoding;
	}

	public getValue(): string {
		if (this.textEditorModel) {
			return this.textEditorModel.getValue(EndOfLinePreference.TextDefined, true /* Preserve BOM */);
		}

		return null;
	}

	public getModeId(): string {
		if (this.textEditorModel) {
			return this.textEditorModel.getModeId();
		}

		return null;
	}

	public getEncoding(): string {
		return this.preferredEncoding || this.configuredEncoding;
	}

	public setEncoding(encoding: string): void {
		let oldEncoding = this.getEncoding();
		this.preferredEncoding = encoding;

		// Emit if it changed
		if (oldEncoding !== this.preferredEncoding) {
			this.eventService.emit(WorkbenchEventType.RESOURCE_ENCODING_CHANGED, new ResourceEvent(this.resource));
		}
	}

	public isDirty(): boolean {
		return this.dirty;
	}

108 109 110
	public revert(): void {
		this.dirty = false;

111
		this._onDidChangeDirty.fire();
112 113
	}

E
Erich Gamma 已提交
114 115
	public load(): TPromise<EditorModel> {
		return super.load().then((model) => {
116
			const configuration = this.configurationService.getConfiguration<IFilesConfiguration>();
E
Erich Gamma 已提交
117

118 119
			// Encoding
			this.configuredEncoding = configuration && configuration.files && configuration.files.encoding;
E
Erich Gamma 已提交
120

121
			// Listen to content changes
A
Alex Dima 已提交
122
			this.textModelChangeListener = this.textEditorModel.onDidChangeContent(() => this.onModelContentChanged());
E
Erich Gamma 已提交
123

124 125 126
			// Emit initial dirty event if we are
			if (this.dirty) {
				setTimeout(() => {
127
					this._onDidChangeDirty.fire();
128 129
				}, 0 /* prevent race condition between creating model and emitting dirty event */);
			}
E
Erich Gamma 已提交
130

131
			return model;
E
Erich Gamma 已提交
132 133 134
		});
	}

A
Alex Dima 已提交
135
	private onModelContentChanged(): void {
E
Erich Gamma 已提交
136 137
		if (!this.dirty) {
			this.dirty = true;
138
			this._onDidChangeDirty.fire();
E
Erich Gamma 已提交
139 140 141 142 143 144 145
		}
	}

	public dispose(): void {
		super.dispose();

		if (this.textModelChangeListener) {
A
Alex Dima 已提交
146
			this.textModelChangeListener.dispose();
E
Erich Gamma 已提交
147 148 149
			this.textModelChangeListener = null;
		}

150 151 152
		if (this.configurationChangeListener) {
			this.configurationChangeListener.dispose();
			this.configurationChangeListener = null;
E
Erich Gamma 已提交
153 154 155
		}
	}
}