untitledEditorModel.ts 5.4 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
	private configuredEncoding: string;
	private preferredEncoding: string;

33 34
	private hasAssociatedFilePath: boolean;

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

47
		this.hasAssociatedFilePath = hasAssociatedFilePath;
E
Erich Gamma 已提交
48 49
		this.dirty = hasAssociatedFilePath; // untitled associated to file path are dirty right away

50 51
		this._onDidChangeDirty = new Emitter<void>();

E
Erich Gamma 已提交
52 53 54
		this.registerListeners();
	}

55 56 57 58
	public get onDidChangeDirty(): Event<void> {
		return this._onDidChangeDirty.event;
	}

59 60 61 62 63 64 65 66
	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 已提交
67 68 69
	private registerListeners(): void {

		// Config Changes
70
		this.configurationChangeListener = this.configurationService.onDidUpdateConfiguration(e => this.onConfigurationChange(e.config));
E
Erich Gamma 已提交
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
	}

	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 {
98
		const oldEncoding = this.getEncoding();
E
Erich Gamma 已提交
99 100 101 102 103 104 105 106 107 108 109 110
		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;
	}

111 112 113
	public revert(): void {
		this.dirty = false;

114
		this._onDidChangeDirty.fire();
115 116
	}

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

121 122
			// Encoding
			this.configuredEncoding = configuration && configuration.files && configuration.files.encoding;
E
Erich Gamma 已提交
123

124
			// Listen to content changes
B
Benjamin Pasero 已提交
125
			this.textModelChangeListener = this.textEditorModel.onDidChangeContent(e => this.onModelContentChanged());
E
Erich Gamma 已提交
126

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

134
			return model;
E
Erich Gamma 已提交
135 136 137
		});
	}

B
Benjamin Pasero 已提交
138
	private onModelContentChanged(): void {
139 140

		// turn dirty if we were not
E
Erich Gamma 已提交
141 142
		if (!this.dirty) {
			this.dirty = true;
143
			this._onDidChangeDirty.fire();
E
Erich Gamma 已提交
144
		}
145 146 147

		// mark the untitled editor as non-dirty once its content becomes empty and we do
		// not have an associated path set
B
Benjamin Pasero 已提交
148
		else if (!this.hasAssociatedFilePath && this.textEditorModel.getLineCount() === 1 && this.textEditorModel.getLineContent(1) === '') {
149 150 151
			this.dirty = false;
			this._onDidChangeDirty.fire();
		}
E
Erich Gamma 已提交
152 153 154 155 156 157
	}

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

		if (this.textModelChangeListener) {
A
Alex Dima 已提交
158
			this.textModelChangeListener.dispose();
E
Erich Gamma 已提交
159 160 161
			this.textModelChangeListener = null;
		}

162 163 164
		if (this.configurationChangeListener) {
			this.configurationChangeListener.dispose();
			this.configurationChangeListener = null;
E
Erich Gamma 已提交
165 166 167
		}
	}
}