preferencesRenderers.ts 39.1 KB
Newer Older
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

R
Rob Lourens 已提交
6 7
import { ContextSubMenu } from 'vs/base/browser/contextmenu';
import { getDomNodePagePosition } from 'vs/base/browser/dom';
8
import { IAction } from 'vs/base/common/actions';
R
Rob Lourens 已提交
9 10
import { Delayer } from 'vs/base/common/async';
import { Emitter, Event } from 'vs/base/common/event';
11
import { IJSONSchema } from 'vs/base/common/jsonSchema';
R
Rob Lourens 已提交
12
import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
A
Alex Dima 已提交
13
import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser';
14
import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorEvents';
R
Rob Lourens 已提交
15 16 17 18
import { Position } from 'vs/editor/common/core/position';
import { IRange, Range } from 'vs/editor/common/core/range';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { IModelDeltaDecoration, ITextModel, TrackedRangeStickiness } from 'vs/editor/common/model';
A
Alex Dima 已提交
19
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
R
Rob Lourens 已提交
20 21 22 23 24 25 26 27 28
import * as nls from 'vs/nls';
import { ConfigurationTarget, IConfigurationService, overrideIdentifierFromKey } from 'vs/platform/configuration/common/configuration';
import { ConfigurationScope, Extensions as ConfigurationExtensions, IConfigurationPropertySchema, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Registry } from 'vs/platform/registry/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { RangeHighlightDecorations } from 'vs/workbench/browser/parts/editor/rangeDecorations';
29
import { DefaultSettingsHeaderWidget, EditPreferenceWidget, SettingsGroupTitleWidget, SettingsHeaderWidget } from 'vs/workbench/contrib/preferences/browser/preferencesWidgets';
30
import { IFilterResult, IPreferencesEditorModel, IPreferencesService, ISetting, ISettingsEditorModel, ISettingsGroup } from 'vs/workbench/services/preferences/common/preferences';
R
Rob Lourens 已提交
31
import { DefaultSettingsEditorModel, SettingsEditorModel, WorkspaceConfigurationEditorModel } from 'vs/workbench/services/preferences/common/preferencesModels';
32 33

export interface IPreferencesRenderer<T> extends IDisposable {
S
Sandeep Somavarapu 已提交
34 35 36 37
	readonly preferencesModel: IPreferencesEditorModel<T>;

	getAssociatedPreferencesModel(): IPreferencesEditorModel<T>;
	setAssociatedPreferencesModel(associatedPreferencesModel: IPreferencesEditorModel<T>): void;
38

39 40
	onFocusPreference: Event<T>;
	onClearFocusPreference: Event<T>;
41
	onUpdatePreference?: Event<{ key: string, value: any, source: T }>;
42

43
	render(): void;
44
	updatePreference(key: string, value: any, source: T): void;
45 46
	focusPreference(setting: T): void;
	clearFocus(setting: T): void;
47
	filterPreferences(filterResult: IFilterResult): void;
48
	editPreference(setting: T): boolean;
49 50 51 52 53 54
}

export class UserSettingsRenderer extends Disposable implements IPreferencesRenderer<ISetting> {

	private settingHighlighter: SettingHighlighter;
	private editSettingActionRenderer: EditSettingRenderer;
55
	private highlightMatchesRenderer: HighlightMatchesRenderer;
56
	private modelChangeDelayer: Delayer<void> = new Delayer<void>(200);
S
Sandeep Somavarapu 已提交
57
	private associatedPreferencesModel: IPreferencesEditorModel<ISetting>;
58

59
	private readonly _onFocusPreference = new Emitter<ISetting>();
R
Rob Lourens 已提交
60
	readonly onFocusPreference: Event<ISetting> = this._onFocusPreference.event;
61

62
	private readonly _onClearFocusPreference = new Emitter<ISetting>();
R
Rob Lourens 已提交
63
	readonly onClearFocusPreference: Event<ISetting> = this._onClearFocusPreference.event;
64

M
Matt Bierner 已提交
65
	private readonly _onUpdatePreference: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>();
R
Rob Lourens 已提交
66
	readonly onUpdatePreference: Event<{ key: string, value: any, source: IIndexedSetting }> = this._onUpdatePreference.event;
67

68 69
	private filterResult: IFilterResult;

R
Rob Lourens 已提交
70
	constructor(protected editor: ICodeEditor, readonly preferencesModel: SettingsEditorModel,
71
		@IPreferencesService protected preferencesService: IPreferencesService,
72
		@IConfigurationService private readonly configurationService: IConfigurationService,
73 74 75 76
		@IInstantiationService protected instantiationService: IInstantiationService
	) {
		super();
		this.settingHighlighter = this._register(instantiationService.createInstance(SettingHighlighter, editor, this._onFocusPreference, this._onClearFocusPreference));
77
		this.highlightMatchesRenderer = this._register(instantiationService.createInstance(HighlightMatchesRenderer, editor));
78
		this.editSettingActionRenderer = this._register(this.instantiationService.createInstance(EditSettingRenderer, this.editor, this.preferencesModel, this.settingHighlighter));
79
		this._register(this.editSettingActionRenderer.onUpdateSetting(({ key, value, source }) => this._updatePreference(key, value, source)));
80
		this._register(this.editor.getModel().onDidChangeContent(() => this.modelChangeDelayer.trigger(() => this.onModelChanged())));
S
Sandeep Somavarapu 已提交
81 82 83

	}

R
Rob Lourens 已提交
84
	getAssociatedPreferencesModel(): IPreferencesEditorModel<ISetting> {
S
Sandeep Somavarapu 已提交
85
		return this.associatedPreferencesModel;
S
Sandeep Somavarapu 已提交
86 87
	}

R
Rob Lourens 已提交
88
	setAssociatedPreferencesModel(associatedPreferencesModel: IPreferencesEditorModel<ISetting>): void {
S
Sandeep Somavarapu 已提交
89
		this.associatedPreferencesModel = associatedPreferencesModel;
S
Sandeep Somavarapu 已提交
90
		this.editSettingActionRenderer.associatedPreferencesModel = associatedPreferencesModel;
S
Sandeep Somavarapu 已提交
91 92 93

		// Create header only in Settings editor mode
		this.createHeader();
S
Sandeep Somavarapu 已提交
94 95
	}

S
Sandeep Somavarapu 已提交
96
	protected createHeader(): void {
97
		this._register(new SettingsHeaderWidget(this.editor, '')).setMessage(nls.localize('emptyUserSettingsHeader', "Place your settings here to override the Default Settings."));
98 99
	}

R
Rob Lourens 已提交
100
	render(): void {
101
		this.editSettingActionRenderer.render(this.preferencesModel.settingsGroups, this.associatedPreferencesModel);
102 103 104 105 106
		if (this.filterResult) {
			this.filterPreferences(this.filterResult);
		}
	}

107 108 109 110
	private _updatePreference(key: string, value: any, source: IIndexedSetting): void {
		this._onUpdatePreference.fire({ key, value, source });
		this.updatePreference(key, value, source);
	}
111

R
Rob Lourens 已提交
112
	updatePreference(key: string, value: any, source: IIndexedSetting): void {
113
		const overrideIdentifier = source.overrideOf ? overrideIdentifierFromKey(source.overrideOf.key) : null;
114
		const resource = this.preferencesModel.uri;
115 116
		this.configurationService.updateValue(key, value, { overrideIdentifier, resource }, this.preferencesModel.configurationTarget)
			.then(() => this.onSettingUpdated(source));
117 118 119
	}

	private onModelChanged(): void {
M
Matt Bierner 已提交
120
		if (!this.editor.hasModel()) {
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
			// model could have been disposed during the delay
			return;
		}
		this.render();
	}

	private onSettingUpdated(setting: ISetting) {
		this.editor.focus();
		setting = this.getSetting(setting);
		if (setting) {
			// TODO:@sandy Selection range should be template range
			this.editor.setSelection(setting.valueRange);
			this.settingHighlighter.highlight(setting, true);
		}
	}

	private getSetting(setting: ISetting): ISetting {
A
Alex Dima 已提交
138
		const { key, overrideOf } = setting;
139 140 141 142 143 144 145 146 147
		if (overrideOf) {
			const setting = this.getSetting(overrideOf);
			for (const override of setting.overrides) {
				if (override.key === key) {
					return override;
				}
			}
			return null;
		}
148

149 150 151
		return this.preferencesModel.getPreference(key);
	}

R
Rob Lourens 已提交
152
	filterPreferences(filterResult: IFilterResult): void {
153 154
		this.filterResult = filterResult;
		this.settingHighlighter.clear(true);
155
		this.highlightMatchesRenderer.render(filterResult ? filterResult.matches : []);
156 157
	}

R
Rob Lourens 已提交
158
	focusPreference(setting: ISetting): void {
159 160 161
		const s = this.getSetting(setting);
		if (s) {
			this.settingHighlighter.highlight(s, true);
S
Sandeep Somavarapu 已提交
162
			this.editor.setPosition({ lineNumber: s.keyRange.startLineNumber, column: s.keyRange.startColumn });
163 164 165 166 167
		} else {
			this.settingHighlighter.clear(true);
		}
	}

R
Rob Lourens 已提交
168
	clearFocus(setting: ISetting): void {
169 170
		this.settingHighlighter.clear(true);
	}
171

R
Rob Lourens 已提交
172
	editPreference(setting: ISetting): boolean {
R
Rob Lourens 已提交
173 174
		const editableSetting = this.getSetting(setting);
		return editableSetting && this.editSettingActionRenderer.activateOnSetting(editableSetting);
175
	}
176 177 178 179
}

export class WorkspaceSettingsRenderer extends UserSettingsRenderer implements IPreferencesRenderer<ISetting> {

S
Sandeep Somavarapu 已提交
180
	private workspaceConfigurationRenderer: WorkspaceConfigurationRenderer;
181

182
	constructor(editor: ICodeEditor, preferencesModel: SettingsEditorModel,
183 184
		@IPreferencesService preferencesService: IPreferencesService,
		@ITelemetryService telemetryService: ITelemetryService,
185
		@IConfigurationService configurationService: IConfigurationService,
186 187
		@IInstantiationService instantiationService: IInstantiationService
	) {
188
		super(editor, preferencesModel, preferencesService, configurationService, instantiationService);
S
Sandeep Somavarapu 已提交
189
		this.workspaceConfigurationRenderer = this._register(instantiationService.createInstance(WorkspaceConfigurationRenderer, editor, preferencesModel));
190 191
	}

S
Sandeep Somavarapu 已提交
192
	protected createHeader(): void {
193
		this._register(new SettingsHeaderWidget(this.editor, '')).setMessage(nls.localize('emptyWorkspaceSettingsHeader', "Place your settings here to override the User Settings."));
S
Sandeep Somavarapu 已提交
194 195
	}

R
Rob Lourens 已提交
196
	setAssociatedPreferencesModel(associatedPreferencesModel: IPreferencesEditorModel<ISetting>): void {
S
Sandeep Somavarapu 已提交
197 198 199 200
		super.setAssociatedPreferencesModel(associatedPreferencesModel);
		this.workspaceConfigurationRenderer.render(this.getAssociatedPreferencesModel());
	}

R
Rob Lourens 已提交
201
	render(): void {
202
		super.render();
S
Sandeep Somavarapu 已提交
203
		this.workspaceConfigurationRenderer.render(this.getAssociatedPreferencesModel());
204 205 206
	}
}

207 208
export class FolderSettingsRenderer extends UserSettingsRenderer implements IPreferencesRenderer<ISetting> {

209
	constructor(editor: ICodeEditor, preferencesModel: SettingsEditorModel,
210 211
		@IPreferencesService preferencesService: IPreferencesService,
		@ITelemetryService telemetryService: ITelemetryService,
212
		@IConfigurationService configurationService: IConfigurationService,
213 214
		@IInstantiationService instantiationService: IInstantiationService
	) {
215
		super(editor, preferencesModel, preferencesService, configurationService, instantiationService);
216 217
	}

S
Sandeep Somavarapu 已提交
218
	protected createHeader(): void {
219
		this._register(new SettingsHeaderWidget(this.editor, '')).setMessage(nls.localize('emptyFolderSettingsHeader', "Place your folder settings here to override those from the Workspace Settings."));
S
Sandeep Somavarapu 已提交
220 221
	}

222 223
}

224 225
export class DefaultSettingsRenderer extends Disposable implements IPreferencesRenderer<ISetting> {

226
	private _associatedPreferencesModel: IPreferencesEditorModel<ISetting>;
227
	private settingHighlighter: SettingHighlighter;
S
Sandeep Somavarapu 已提交
228
	private settingsHeaderRenderer: DefaultSettingsHeaderRenderer;
229 230 231 232
	private settingsGroupTitleRenderer: SettingsGroupTitleRenderer;
	private filteredMatchesRenderer: FilteredMatchesRenderer;
	private hiddenAreasRenderer: HiddenAreasRenderer;
	private editSettingActionRenderer: EditSettingRenderer;
233 234
	private bracesHidingRenderer: BracesHidingRenderer;
	private filterResult: IFilterResult;
235

M
Matt Bierner 已提交
236
	private readonly _onUpdatePreference: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>();
R
Rob Lourens 已提交
237
	readonly onUpdatePreference: Event<{ key: string, value: any, source: IIndexedSetting }> = this._onUpdatePreference.event;
238

239
	private readonly _onFocusPreference = new Emitter<ISetting>();
R
Rob Lourens 已提交
240
	readonly onFocusPreference: Event<ISetting> = this._onFocusPreference.event;
241

242
	private readonly _onClearFocusPreference = new Emitter<ISetting>();
R
Rob Lourens 已提交
243
	readonly onClearFocusPreference: Event<ISetting> = this._onClearFocusPreference.event;
244

R
Rob Lourens 已提交
245
	constructor(protected editor: ICodeEditor, readonly preferencesModel: DefaultSettingsEditorModel,
246
		@IPreferencesService protected preferencesService: IPreferencesService,
247
		@IInstantiationService protected instantiationService: IInstantiationService,
248 249 250
	) {
		super();
		this.settingHighlighter = this._register(instantiationService.createInstance(SettingHighlighter, editor, this._onFocusPreference, this._onClearFocusPreference));
S
Sandeep Somavarapu 已提交
251
		this.settingsHeaderRenderer = this._register(instantiationService.createInstance(DefaultSettingsHeaderRenderer, editor));
252 253
		this.settingsGroupTitleRenderer = this._register(instantiationService.createInstance(SettingsGroupTitleRenderer, editor));
		this.filteredMatchesRenderer = this._register(instantiationService.createInstance(FilteredMatchesRenderer, editor));
254
		this.editSettingActionRenderer = this._register(instantiationService.createInstance(EditSettingRenderer, editor, preferencesModel, this.settingHighlighter));
255 256
		this.bracesHidingRenderer = this._register(instantiationService.createInstance(BracesHidingRenderer, editor, preferencesModel));
		this.hiddenAreasRenderer = this._register(instantiationService.createInstance(HiddenAreasRenderer, editor, [this.settingsGroupTitleRenderer, this.filteredMatchesRenderer, this.bracesHidingRenderer]));
R
Rob Lourens 已提交
257

258 259
		this._register(this.editSettingActionRenderer.onUpdateSetting(e => this._onUpdatePreference.fire(e)));
		this._register(this.settingsGroupTitleRenderer.onHiddenAreasChanged(() => this.hiddenAreasRenderer.render()));
S
Sandeep Somavarapu 已提交
260
		this._register(preferencesModel.onDidChangeGroups(() => this.render()));
261 262
	}

R
Rob Lourens 已提交
263
	getAssociatedPreferencesModel(): IPreferencesEditorModel<ISetting> {
264 265 266
		return this._associatedPreferencesModel;
	}

R
Rob Lourens 已提交
267
	setAssociatedPreferencesModel(associatedPreferencesModel: IPreferencesEditorModel<ISetting>): void {
268 269 270 271
		this._associatedPreferencesModel = associatedPreferencesModel;
		this.editSettingActionRenderer.associatedPreferencesModel = associatedPreferencesModel;
	}

R
Rob Lourens 已提交
272
	render() {
273
		this.settingsGroupTitleRenderer.render(this.preferencesModel.settingsGroups);
274
		this.editSettingActionRenderer.render(this.preferencesModel.settingsGroups, this._associatedPreferencesModel);
275
		this.settingHighlighter.clear(true);
276
		this.bracesHidingRenderer.render(null, this.preferencesModel.settingsGroups);
277
		this.settingsGroupTitleRenderer.showGroup(0);
278 279 280
		this.hiddenAreasRenderer.render();
	}

R
Rob Lourens 已提交
281
	filterPreferences(filterResult: IFilterResult): void {
282
		this.filterResult = filterResult;
283

R
Rob Lourens 已提交
284
		if (filterResult) {
285
			this.filteredMatchesRenderer.render(filterResult, this.preferencesModel.settingsGroups);
286
			this.settingsGroupTitleRenderer.render(null);
287
			this.settingsHeaderRenderer.render(filterResult);
R
Rob Lourens 已提交
288
			this.settingHighlighter.clear(true);
289
			this.bracesHidingRenderer.render(filterResult, this.preferencesModel.settingsGroups);
R
Rob Lourens 已提交
290 291
			this.editSettingActionRenderer.render(filterResult.filteredGroups, this._associatedPreferencesModel);
		} else {
292
			this.settingHighlighter.clear(true);
293
			this.filteredMatchesRenderer.render(null, this.preferencesModel.settingsGroups);
294
			this.settingsHeaderRenderer.render(null);
295
			this.settingsGroupTitleRenderer.render(this.preferencesModel.settingsGroups);
296
			this.settingsGroupTitleRenderer.showGroup(0);
297
			this.bracesHidingRenderer.render(null, this.preferencesModel.settingsGroups);
298
			this.editSettingActionRenderer.render(this.preferencesModel.settingsGroups, this._associatedPreferencesModel);
299
		}
R
Rob Lourens 已提交
300

301 302 303
		this.hiddenAreasRenderer.render();
	}

R
Rob Lourens 已提交
304
	focusPreference(s: ISetting): void {
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
		const setting = this.getSetting(s);
		if (setting) {
			this.settingsGroupTitleRenderer.showSetting(setting);
			this.settingHighlighter.highlight(setting, true);
		} else {
			this.settingHighlighter.clear(true);
		}
	}

	private getSetting(setting: ISetting): ISetting {
		const { key, overrideOf } = setting;
		if (overrideOf) {
			const setting = this.getSetting(overrideOf);
			for (const override of setting.overrides) {
				if (override.key === key) {
					return override;
				}
			}
			return null;
		}
		const settingsGroups = this.filterResult ? this.filterResult.filteredGroups : this.preferencesModel.settingsGroups;
		return this.getPreference(key, settingsGroups);
	}

	private getPreference(key: string, settingsGroups: ISettingsGroup[]): ISetting {
		for (const group of settingsGroups) {
			for (const section of group.sections) {
				for (const setting of section.settings) {
					if (setting.key === key) {
						return setting;
					}
				}
			}
		}
		return null;
340 341
	}

R
Rob Lourens 已提交
342
	clearFocus(setting: ISetting): void {
343 344 345
		this.settingHighlighter.clear(true);
	}

R
Rob Lourens 已提交
346
	updatePreference(key: string, value: any, source: ISetting): void {
347
	}
348

R
Rob Lourens 已提交
349
	editPreference(setting: ISetting): boolean {
350 351
		return this.editSettingActionRenderer.activateOnSetting(setting);
	}
352 353 354
}

export interface HiddenAreasProvider {
A
Alex Dima 已提交
355
	hiddenAreas: IRange[];
356 357
}

358 359 360
export class BracesHidingRenderer extends Disposable implements HiddenAreasProvider {
	private _result: IFilterResult;
	private _settingsGroups: ISettingsGroup[];
361

362
	constructor(private editor: ICodeEditor) {
363 364 365
		super();
	}

366 367 368 369
	render(result: IFilterResult, settingsGroups: ISettingsGroup[]): void {
		this._result = result;
		this._settingsGroups = settingsGroups;
	}
R
Rob Lourens 已提交
370

371 372 373
	get hiddenAreas(): IRange[] {
		// Opening square brace
		const hiddenAreas = [
374 375
			{
				startLineNumber: 1,
376
				startColumn: 1,
377
				endLineNumber: 2,
378
				endColumn: 1
379 380
			}
		];
381

382
		const hideBraces = (group: ISettingsGroup, hideExtraLine?: boolean) => {
383 384 385 386
			// Opening curly brace
			hiddenAreas.push({
				startLineNumber: group.range.startLineNumber - 3,
				startColumn: 1,
387
				endLineNumber: group.range.startLineNumber - (hideExtraLine ? 1 : 3),
388 389 390 391 392 393 394 395 396 397 398 399
				endColumn: 1
			});

			// Closing curly brace
			hiddenAreas.push({
				startLineNumber: group.range.endLineNumber + 1,
				startColumn: 1,
				endLineNumber: group.range.endLineNumber + 4,
				endColumn: 1
			});
		};

400
		this._settingsGroups.forEach(g => hideBraces(g));
401
		if (this._result) {
402
			this._result.filteredGroups.forEach((g, i) => hideBraces(g, true));
403 404 405 406 407 408 409 410 411 412 413 414 415
		}

		// Closing square brace
		const lineCount = this.editor.getModel().getLineCount();
		hiddenAreas.push({
			startLineNumber: lineCount,
			startColumn: 1,
			endLineNumber: lineCount,
			endColumn: 1
		});


		return hiddenAreas;
416 417 418 419
	}

}

S
Sandeep Somavarapu 已提交
420
class DefaultSettingsHeaderRenderer extends Disposable {
S
Sandeep Somavarapu 已提交
421

422
	private settingsHeaderWidget: DefaultSettingsHeaderWidget;
R
Rob Lourens 已提交
423
	readonly onClick: Event<void>;
S
Sandeep Somavarapu 已提交
424

S
Sandeep Somavarapu 已提交
425
	constructor(editor: ICodeEditor) {
S
Sandeep Somavarapu 已提交
426
		super();
S
Sandeep Somavarapu 已提交
427
		this.settingsHeaderWidget = this._register(new DefaultSettingsHeaderWidget(editor, ''));
428
		this.onClick = this.settingsHeaderWidget.onClick;
S
Sandeep Somavarapu 已提交
429 430
	}

R
Rob Lourens 已提交
431
	render(filterResult: IFilterResult) {
432
		const hasSettings = !filterResult || filterResult.filteredGroups.length > 0;
433
		this.settingsHeaderWidget.toggleMessage(hasSettings);
S
Sandeep Somavarapu 已提交
434 435 436
	}
}

437 438
export class SettingsGroupTitleRenderer extends Disposable implements HiddenAreasProvider {

439
	private readonly _onHiddenAreasChanged = new Emitter<void>();
440
	get onHiddenAreasChanged(): Event<void> { return this._onHiddenAreasChanged.event; }
441 442 443 444 445 446 447

	private settingsGroups: ISettingsGroup[];
	private hiddenGroups: ISettingsGroup[] = [];
	private settingsGroupTitleWidgets: SettingsGroupTitleWidget[];
	private disposables: IDisposable[] = [];

	constructor(private editor: ICodeEditor,
448
		@IInstantiationService private readonly instantiationService: IInstantiationService
449 450 451 452
	) {
		super();
	}

R
Rob Lourens 已提交
453
	get hiddenAreas(): IRange[] {
A
Alex Dima 已提交
454
		const hiddenAreas: IRange[] = [];
455 456 457 458 459 460
		for (const group of this.hiddenGroups) {
			hiddenAreas.push(group.range);
		}
		return hiddenAreas;
	}

R
Rob Lourens 已提交
461
	render(settingsGroups: ISettingsGroup[]) {
462
		this.disposeWidgets();
R
Rob Lourens 已提交
463 464 465 466
		if (!settingsGroups) {
			return;
		}

467 468 469
		this.settingsGroups = settingsGroups.slice();
		this.settingsGroupTitleWidgets = [];
		for (const group of this.settingsGroups.slice().reverse()) {
470 471 472 473
			if (group.sections.every(sect => sect.settings.length === 0)) {
				continue;
			}

474 475 476 477 478 479 480 481 482
			const settingsGroupTitleWidget = this.instantiationService.createInstance(SettingsGroupTitleWidget, this.editor, group);
			settingsGroupTitleWidget.render();
			this.settingsGroupTitleWidgets.push(settingsGroupTitleWidget);
			this.disposables.push(settingsGroupTitleWidget);
			this.disposables.push(settingsGroupTitleWidget.onToggled(collapsed => this.onToggled(collapsed, settingsGroupTitleWidget.settingsGroup)));
		}
		this.settingsGroupTitleWidgets.reverse();
	}

R
Rob Lourens 已提交
483
	showGroup(groupIdx: number) {
484 485 486 487
		const shownGroup = this.settingsGroupTitleWidgets[groupIdx].settingsGroup;

		this.hiddenGroups = this.settingsGroups.filter(g => g !== shownGroup);
		for (const groupTitleWidget of this.settingsGroupTitleWidgets.filter(widget => widget.settingsGroup !== shownGroup)) {
488 489 490 491 492
			groupTitleWidget.toggleCollapse(true);
		}
		this._onHiddenAreasChanged.fire();
	}

R
Rob Lourens 已提交
493
	showSetting(setting: ISetting): void {
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
		const settingsGroupTitleWidget = this.settingsGroupTitleWidgets.filter(widget => Range.containsRange(widget.settingsGroup.range, setting.range))[0];
		if (settingsGroupTitleWidget && settingsGroupTitleWidget.isCollapsed()) {
			settingsGroupTitleWidget.toggleCollapse(false);
			this.hiddenGroups.splice(this.hiddenGroups.indexOf(settingsGroupTitleWidget.settingsGroup), 1);
			this._onHiddenAreasChanged.fire();
		}
	}

	private onToggled(collapsed: boolean, group: ISettingsGroup) {
		const index = this.hiddenGroups.indexOf(group);
		if (collapsed) {
			const currentPosition = this.editor.getPosition();
			if (group.range.startLineNumber <= currentPosition.lineNumber && group.range.endLineNumber >= currentPosition.lineNumber) {
				this.editor.setPosition({ lineNumber: group.range.startLineNumber - 1, column: 1 });
			}
			this.hiddenGroups.push(group);
		} else {
			this.hiddenGroups.splice(index, 1);
		}
		this._onHiddenAreasChanged.fire();
	}

	private disposeWidgets() {
		this.hiddenGroups = [];
		this.disposables = dispose(this.disposables);
	}

R
Rob Lourens 已提交
521
	dispose() {
522 523 524 525 526 527 528
		this.disposeWidgets();
		super.dispose();
	}
}

export class HiddenAreasRenderer extends Disposable {

S
Sandeep Somavarapu 已提交
529
	constructor(private editor: ICodeEditor, private hiddenAreasProviders: HiddenAreasProvider[]
530 531 532 533
	) {
		super();
	}

R
Rob Lourens 已提交
534
	render() {
A
Alex Dima 已提交
535
		const ranges: IRange[] = [];
536 537 538 539 540 541
		for (const hiddenAreaProvider of this.hiddenAreasProviders) {
			ranges.push(...hiddenAreaProvider.hiddenAreas);
		}
		this.editor.setHiddenAreas(ranges);
	}

R
Rob Lourens 已提交
542
	dispose() {
543 544 545 546 547 548 549 550
		this.editor.setHiddenAreas([]);
		super.dispose();
	}
}

export class FilteredMatchesRenderer extends Disposable implements HiddenAreasProvider {

	private decorationIds: string[] = [];
R
Rob Lourens 已提交
551
	hiddenAreas: IRange[] = [];
552

S
Sandeep Somavarapu 已提交
553
	constructor(private editor: ICodeEditor
554 555 556 557
	) {
		super();
	}

R
Rob Lourens 已提交
558
	render(result: IFilterResult, allSettingsGroups: ISettingsGroup[]): void {
559 560 561 562
		const model = this.editor.getModel();
		this.hiddenAreas = [];
		if (result) {
			this.hiddenAreas = this.computeHiddenRanges(result.filteredGroups, result.allGroups, model);
563
			this.decorationIds = this.editor.deltaDecorations(this.decorationIds, result.matches.map(match => this.createDecoration(match, model)));
564
		} else {
565
			this.hiddenAreas = this.computeHiddenRanges(null, allSettingsGroups, model);
566
			this.decorationIds = this.editor.deltaDecorations(this.decorationIds, []);
567 568 569
		}
	}

A
Alex Dima 已提交
570
	private createDecoration(range: IRange, model: ITextModel): IModelDeltaDecoration {
571 572
		return {
			range,
A
Alex Dima 已提交
573
			options: FilteredMatchesRenderer._FIND_MATCH
574 575 576
		};
	}

A
Alex Dima 已提交
577 578 579 580 581
	private static readonly _FIND_MATCH = ModelDecorationOptions.register({
		stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
		className: 'findMatch'
	});

A
Alex Dima 已提交
582
	private computeHiddenRanges(filteredGroups: ISettingsGroup[], allSettingsGroups: ISettingsGroup[], model: ITextModel): IRange[] {
583
		// Hide the contents of hidden groups
A
Alex Dima 已提交
584
		const notMatchesRanges: IRange[] = [];
585 586
		if (filteredGroups) {
			allSettingsGroups.forEach((group, i) => {
587 588
				notMatchesRanges.push({
					startLineNumber: group.range.startLineNumber - 1,
589
					startColumn: group.range.startColumn,
590
					endLineNumber: group.range.endLineNumber,
591
					endColumn: group.range.endColumn
592
				});
593
			});
594 595
		}

596
		return notMatchesRanges;
597 598
	}

R
Rob Lourens 已提交
599
	dispose() {
600
		this.decorationIds = this.editor.deltaDecorations(this.decorationIds, []);
601 602 603 604
		super.dispose();
	}
}

605
export class HighlightMatchesRenderer extends Disposable {
606 607 608

	private decorationIds: string[] = [];

S
Sandeep Somavarapu 已提交
609
	constructor(private editor: ICodeEditor
610 611 612 613
	) {
		super();
	}

R
Rob Lourens 已提交
614
	render(matches: IRange[]): void {
615
		const model = this.editor.getModel();
616
		this.decorationIds = this.editor.deltaDecorations(this.decorationIds, matches.map(match => this.createDecoration(match, model)));
617 618
	}

619
	private static readonly _FIND_MATCH = ModelDecorationOptions.register({
620
		stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
621 622 623
		className: 'findMatch'
	});

A
Alex Dima 已提交
624
	private createDecoration(range: IRange, model: ITextModel): IModelDeltaDecoration {
625 626
		return {
			range,
627
			options: HighlightMatchesRenderer._FIND_MATCH
628 629 630
		};
	}

R
Rob Lourens 已提交
631
	dispose() {
632
		this.decorationIds = this.editor.deltaDecorations(this.decorationIds, []);
633 634 635 636
		super.dispose();
	}
}

637
export interface IIndexedSetting extends ISetting {
638
	index: number;
639
	groupId: string;
640 641
}

642 643
class EditSettingRenderer extends Disposable {

644
	private editPreferenceWidgetForCursorPosition: EditPreferenceWidget<IIndexedSetting>;
645
	private editPreferenceWidgetForMouseMove: EditPreferenceWidget<IIndexedSetting>;
646

S
Sandeep Somavarapu 已提交
647
	private settingsGroups: ISettingsGroup[] = [];
R
Rob Lourens 已提交
648
	associatedPreferencesModel: IPreferencesEditorModel<ISetting>;
649 650
	private toggleEditPreferencesForMouseMoveDelayer: Delayer<void>;

M
Matt Bierner 已提交
651
	private readonly _onUpdateSetting: Emitter<{ key: string, value: any, source: IIndexedSetting }> = new Emitter<{ key: string, value: any, source: IIndexedSetting }>();
R
Rob Lourens 已提交
652
	readonly onUpdateSetting: Event<{ key: string, value: any, source: IIndexedSetting }> = this._onUpdateSetting.event;
653 654 655

	constructor(private editor: ICodeEditor, private masterSettingsModel: ISettingsEditorModel,
		private settingHighlighter: SettingHighlighter,
656 657
		@IInstantiationService private readonly instantiationService: IInstantiationService,
		@IContextMenuService private readonly contextMenuService: IContextMenuService
658 659 660
	) {
		super();

661 662
		this.editPreferenceWidgetForCursorPosition = <EditPreferenceWidget<IIndexedSetting>>this._register(this.instantiationService.createInstance(EditPreferenceWidget, editor));
		this.editPreferenceWidgetForMouseMove = <EditPreferenceWidget<IIndexedSetting>>this._register(this.instantiationService.createInstance(EditPreferenceWidget, editor));
663 664
		this.toggleEditPreferencesForMouseMoveDelayer = new Delayer<void>(75);

665
		this._register(this.editPreferenceWidgetForCursorPosition.onClick(e => this.onEditSettingClicked(this.editPreferenceWidgetForCursorPosition, e)));
S
Sandeep Somavarapu 已提交
666
		this._register(this.editPreferenceWidgetForMouseMove.onClick(e => this.onEditSettingClicked(this.editPreferenceWidgetForMouseMove, e)));
667 668 669 670 671 672

		this._register(this.editor.onDidChangeCursorPosition(positionChangeEvent => this.onPositionChanged(positionChangeEvent)));
		this._register(this.editor.onMouseMove(mouseMoveEvent => this.onMouseMoved(mouseMoveEvent)));
		this._register(this.editor.onDidChangeConfiguration(() => this.onConfigurationChanged()));
	}

R
Rob Lourens 已提交
673
	render(settingsGroups: ISettingsGroup[], associatedPreferencesModel: IPreferencesEditorModel<ISetting>): void {
674
		this.editPreferenceWidgetForCursorPosition.hide();
675 676
		this.editPreferenceWidgetForMouseMove.hide();
		this.settingsGroups = settingsGroups;
677
		this.associatedPreferencesModel = associatedPreferencesModel;
678 679 680

		const settings = this.getSettings(this.editor.getPosition().lineNumber);
		if (settings.length) {
681
			this.showEditPreferencesWidget(this.editPreferenceWidgetForCursorPosition, settings);
682 683 684 685 686 687 688 689
		}
	}

	private isDefaultSettings(): boolean {
		return this.masterSettingsModel instanceof DefaultSettingsEditorModel;
	}

	private onConfigurationChanged(): void {
690
		if (!this.editor.getConfiguration().viewInfo.glyphMargin) {
691
			this.editPreferenceWidgetForCursorPosition.hide();
692 693 694 695
			this.editPreferenceWidgetForMouseMove.hide();
		}
	}

696
	private onPositionChanged(positionChangeEvent: ICursorPositionChangedEvent) {
697 698 699
		this.editPreferenceWidgetForMouseMove.hide();
		const settings = this.getSettings(positionChangeEvent.position.lineNumber);
		if (settings.length) {
700
			this.showEditPreferencesWidget(this.editPreferenceWidgetForCursorPosition, settings);
701
		} else {
702
			this.editPreferenceWidgetForCursorPosition.hide();
703 704 705 706 707 708 709 710 711 712
		}
	}

	private onMouseMoved(mouseMoveEvent: IEditorMouseEvent): void {
		const editPreferenceWidget = this.getEditPreferenceWidgetUnderMouse(mouseMoveEvent);
		if (editPreferenceWidget) {
			this.onMouseOver(editPreferenceWidget);
			return;
		}
		this.settingHighlighter.clear();
713
		this.toggleEditPreferencesForMouseMoveDelayer.trigger(() => this.toggleEditPreferenceWidgetForMouseMove(mouseMoveEvent));
714 715 716
	}

	private getEditPreferenceWidgetUnderMouse(mouseMoveEvent: IEditorMouseEvent): EditPreferenceWidget<ISetting> {
A
Alex Dima 已提交
717
		if (mouseMoveEvent.target.type === MouseTargetType.GUTTER_GLYPH_MARGIN) {
S
Sandeep Somavarapu 已提交
718 719 720 721
			const line = mouseMoveEvent.target.position.lineNumber;
			if (this.editPreferenceWidgetForMouseMove.getLine() === line && this.editPreferenceWidgetForMouseMove.isVisible()) {
				return this.editPreferenceWidgetForMouseMove;
			}
722 723
			if (this.editPreferenceWidgetForCursorPosition.getLine() === line && this.editPreferenceWidgetForCursorPosition.isVisible()) {
				return this.editPreferenceWidgetForCursorPosition;
S
Sandeep Somavarapu 已提交
724
			}
725 726 727 728
		}
		return null;
	}

729
	private toggleEditPreferenceWidgetForMouseMove(mouseMoveEvent: IEditorMouseEvent): void {
730 731 732 733 734 735 736 737
		const settings = mouseMoveEvent.target.position ? this.getSettings(mouseMoveEvent.target.position.lineNumber) : null;
		if (settings && settings.length) {
			this.showEditPreferencesWidget(this.editPreferenceWidgetForMouseMove, settings);
		} else {
			this.editPreferenceWidgetForMouseMove.hide();
		}
	}

738
	private showEditPreferencesWidget(editPreferencesWidget: EditPreferenceWidget<ISetting>, settings: IIndexedSetting[]) {
S
Sandeep Somavarapu 已提交
739
		const line = settings[0].valueRange.startLineNumber;
740
		if (this.editor.getConfiguration().viewInfo.glyphMargin && this.marginFreeFromOtherDecorations(line)) {
S
Sandeep Somavarapu 已提交
741
			editPreferencesWidget.show(line, nls.localize('editTtile', "Edit"), settings);
742
			const editPreferenceWidgetToHide = editPreferencesWidget === this.editPreferenceWidgetForCursorPosition ? this.editPreferenceWidgetForMouseMove : this.editPreferenceWidgetForCursorPosition;
743 744 745 746
			editPreferenceWidgetToHide.hide();
		}
	}

S
Sandeep Somavarapu 已提交
747 748 749
	private marginFreeFromOtherDecorations(line: number): boolean {
		const decorations = this.editor.getLineDecorations(line);
		if (decorations) {
A
Alex Dima 已提交
750
			for (const { options } of decorations) {
S
Sandeep Somavarapu 已提交
751 752 753 754 755 756 757 758
				if (options.glyphMarginClassName && options.glyphMarginClassName.indexOf(EditPreferenceWidget.GLYPH_MARGIN_CLASS_NAME) === -1) {
					return false;
				}
			}
		}
		return true;
	}

759
	private getSettings(lineNumber: number): IIndexedSetting[] {
760 761
		const configurationMap = this.getConfigurationsMap();
		return this.getSettingsAtLineNumber(lineNumber).filter(setting => {
R
Rob Lourens 已提交
762
			const configurationNode = configurationMap[setting.key];
S
Sandeep Somavarapu 已提交
763 764
			if (configurationNode) {
				if (this.isDefaultSettings()) {
S
Sandeep Somavarapu 已提交
765 766 767 768
					if (setting.key === 'launch') {
						// Do not show because of https://github.com/Microsoft/vscode/issues/32593
						return false;
					}
S
Sandeep Somavarapu 已提交
769 770 771
					return true;
				}
				if (configurationNode.type === 'boolean' || configurationNode.enum) {
772
					if ((<SettingsEditorModel>this.masterSettingsModel).configurationTarget !== ConfigurationTarget.WORKSPACE_FOLDER) {
S
Sandeep Somavarapu 已提交
773 774 775 776 777 778 779 780
						return true;
					}
					if (configurationNode.scope === ConfigurationScope.RESOURCE) {
						return true;
					}
				}
			}
			return false;
781 782 783
		});
	}

784 785 786 787
	private getSettingsAtLineNumber(lineNumber: number): IIndexedSetting[] {
		// index of setting, across all groups/sections
		let index = 0;

788
		const settings: IIndexedSetting[] = [];
789 790 791 792 793 794 795 796 797 798 799
		for (const group of this.settingsGroups) {
			if (group.range.startLineNumber > lineNumber) {
				break;
			}
			if (lineNumber >= group.range.startLineNumber && lineNumber <= group.range.endLineNumber) {
				for (const section of group.sections) {
					for (const setting of section.settings) {
						if (setting.range.startLineNumber > lineNumber) {
							break;
						}
						if (lineNumber >= setting.range.startLineNumber && lineNumber <= setting.range.endLineNumber) {
800
							if (!this.isDefaultSettings() && setting.overrides.length) {
801 802 803
								// Only one level because override settings cannot have override settings
								for (const overrideSetting of setting.overrides) {
									if (lineNumber >= overrideSetting.range.startLineNumber && lineNumber <= overrideSetting.range.endLineNumber) {
804
										settings.push({ ...overrideSetting, index, groupId: group.id });
805 806 807
									}
								}
							} else {
808
								settings.push({ ...setting, index, groupId: group.id });
809 810
							}
						}
811 812

						index++;
813 814 815 816 817 818 819 820 821 822 823
					}
				}
			}
		}
		return settings;
	}

	private onMouseOver(editPreferenceWidget: EditPreferenceWidget<ISetting>): void {
		this.settingHighlighter.highlight(editPreferenceWidget.preferences[0]);
	}

824
	private onEditSettingClicked(editPreferenceWidget: EditPreferenceWidget<IIndexedSetting>, e: IEditorMouseEvent): void {
B
Benjamin Pasero 已提交
825
		const anchor = { x: e.event.posx, y: e.event.posy + 10 };
826
		const actions = this.getSettings(editPreferenceWidget.getLine()).length === 1 ? this.getActions(editPreferenceWidget.preferences[0], this.getConfigurationsMap()[editPreferenceWidget.preferences[0].key])
827 828 829
			: editPreferenceWidget.preferences.map(setting => new ContextSubMenu(setting.key, this.getActions(setting, this.getConfigurationsMap()[setting.key])));
		this.contextMenuService.showContextMenu({
			getAnchor: () => anchor,
830
			getActions: () => actions
831 832 833
		});
	}

R
Rob Lourens 已提交
834
	activateOnSetting(setting: ISetting): boolean {
835 836 837 838 839 840 841 842 843 844
		const startLine = setting.keyRange.startLineNumber;
		const settings = this.getSettings(startLine);
		if (!settings.length) {
			return false;
		}

		this.editPreferenceWidgetForMouseMove.show(startLine, '', settings);
		const actions = this.getActions(this.editPreferenceWidgetForMouseMove.preferences[0], this.getConfigurationsMap()[this.editPreferenceWidgetForMouseMove.preferences[0].key]);
		this.contextMenuService.showContextMenu({
			getAnchor: () => this.toAbsoluteCoords(new Position(startLine, 1)),
845
			getActions: () => actions
846 847 848 849 850 851 852 853 854 855 856 857 858 859
		});

		return true;
	}

	private toAbsoluteCoords(position: Position): { x: number, y: number } {
		const positionCoords = this.editor.getScrolledVisiblePosition(position);
		const editorCoords = getDomNodePagePosition(this.editor.getDomNode());
		const x = editorCoords.left + positionCoords.left;
		const y = editorCoords.top + positionCoords.top + positionCoords.height;

		return { x, y: y + 10 };
	}

S
Sandeep Somavarapu 已提交
860
	private getConfigurationsMap(): { [qualifiedKey: string]: IConfigurationPropertySchema } {
861 862 863
		return Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).getConfigurationProperties();
	}

864
	private getActions(setting: IIndexedSetting, jsonSchema: IJSONSchema): IAction[] {
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
		if (jsonSchema.type === 'boolean') {
			return [<IAction>{
				id: 'truthyValue',
				label: 'true',
				enabled: true,
				run: () => this.updateSetting(setting.key, true, setting)
			}, <IAction>{
				id: 'falsyValue',
				label: 'false',
				enabled: true,
				run: () => this.updateSetting(setting.key, false, setting)
			}];
		}
		if (jsonSchema.enum) {
			return jsonSchema.enum.map(value => {
				return <IAction>{
					id: value,
					label: JSON.stringify(value),
					enabled: true,
					run: () => this.updateSetting(setting.key, value, setting)
				};
			});
		}
		return this.getDefaultActions(setting);
	}

891
	private getDefaultActions(setting: IIndexedSetting): IAction[] {
892
		if (this.isDefaultSettings()) {
893
			const settingInOtherModel = this.associatedPreferencesModel.getPreference(setting.key);
894 895 896 897 898 899 900 901 902 903
			return [<IAction>{
				id: 'setDefaultValue',
				label: settingInOtherModel ? nls.localize('replaceDefaultValue', "Replace in Settings") : nls.localize('copyDefaultValue', "Copy to Settings"),
				enabled: true,
				run: () => this.updateSetting(setting.key, setting.value, setting)
			}];
		}
		return [];
	}

904
	private updateSetting(key: string, value: any, source: IIndexedSetting): void {
905
		this._onUpdateSetting.fire({ key, value, source });
906 907 908 909 910 911 912 913 914
	}
}

class SettingHighlighter extends Disposable {

	private fixedHighlighter: RangeHighlightDecorations;
	private volatileHighlighter: RangeHighlightDecorations;
	private highlightedSetting: ISetting;

M
Matt Bierner 已提交
915
	constructor(private editor: ICodeEditor, private readonly focusEventEmitter: Emitter<ISetting>, private readonly clearFocusEventEmitter: Emitter<ISetting>,
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935
		@IInstantiationService instantiationService: IInstantiationService
	) {
		super();
		this.fixedHighlighter = this._register(instantiationService.createInstance(RangeHighlightDecorations));
		this.volatileHighlighter = this._register(instantiationService.createInstance(RangeHighlightDecorations));
		this.fixedHighlighter.onHighlghtRemoved(() => this.clearFocusEventEmitter.fire(this.highlightedSetting));
		this.volatileHighlighter.onHighlghtRemoved(() => this.clearFocusEventEmitter.fire(this.highlightedSetting));
	}

	highlight(setting: ISetting, fix: boolean = false) {
		this.highlightedSetting = setting;
		this.volatileHighlighter.removeHighlightRange();
		this.fixedHighlighter.removeHighlightRange();

		const highlighter = fix ? this.fixedHighlighter : this.volatileHighlighter;
		highlighter.highlightRange({
			range: setting.valueRange,
			resource: this.editor.getModel().uri
		}, this.editor);

S
Sandeep Somavarapu 已提交
936
		this.editor.revealLineInCenterIfOutsideViewport(setting.valueRange.startLineNumber, editorCommon.ScrollType.Smooth);
937 938 939 940 941 942 943 944 945 946 947 948
		this.focusEventEmitter.fire(setting);
	}

	clear(fix: boolean = false): void {
		this.volatileHighlighter.removeHighlightRange();
		if (fix) {
			this.fixedHighlighter.removeHighlightRange();
		}
		this.clearFocusEventEmitter.fire(this.highlightedSetting);
	}
}

S
Sandeep Somavarapu 已提交
949 950 951
class WorkspaceConfigurationRenderer extends Disposable {

	private decorationIds: string[] = [];
S
Sandeep Somavarapu 已提交
952
	private associatedSettingsEditorModel: IPreferencesEditorModel<ISetting>;
S
Sandeep Somavarapu 已提交
953 954
	private renderingDelayer: Delayer<void> = new Delayer<void>(200);

955
	constructor(private editor: ICodeEditor, private workspaceSettingsEditorModel: SettingsEditorModel,
956
		@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService
S
Sandeep Somavarapu 已提交
957 958
	) {
		super();
S
Sandeep Somavarapu 已提交
959
		this._register(this.editor.getModel().onDidChangeContent(() => this.renderingDelayer.trigger(() => this.render(this.associatedSettingsEditorModel))));
S
Sandeep Somavarapu 已提交
960 961
	}

R
Rob Lourens 已提交
962
	render(associatedSettingsEditorModel: IPreferencesEditorModel<ISetting>): void {
S
Sandeep Somavarapu 已提交
963 964 965
		this.associatedSettingsEditorModel = associatedSettingsEditorModel;
		// Dim other configurations in workspace configuration file only in the context of Settings Editor
		if (this.associatedSettingsEditorModel && this.workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE && this.workspaceSettingsEditorModel instanceof WorkspaceConfigurationEditorModel) {
S
Sandeep Somavarapu 已提交
966
			const ranges: IRange[] = [];
S
Sandeep Somavarapu 已提交
967
			for (const settingsGroup of this.workspaceSettingsEditorModel.configurationGroups) {
S
Sandeep Somavarapu 已提交
968 969 970 971 972 973 974 975 976 977 978 979 980
				for (const section of settingsGroup.sections) {
					for (const setting of section.settings) {
						if (setting.key !== 'settings') {
							ranges.push({
								startLineNumber: setting.keyRange.startLineNumber,
								startColumn: setting.keyRange.startColumn - 1,
								endLineNumber: setting.valueRange.endLineNumber,
								endColumn: setting.valueRange.endColumn
							});
						}
					}
				}
			}
981
			this.decorationIds = this.editor.deltaDecorations(this.decorationIds, ranges.map(range => this.createDecoration(range, this.editor.getModel())));
S
Sandeep Somavarapu 已提交
982 983 984
		}
	}

985
	private static readonly _DIM_CONFIGURATION_ = ModelDecorationOptions.register({
986
		stickiness: TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
S
Sandeep Somavarapu 已提交
987 988 989
		inlineClassName: 'dim-configuration'
	});

A
Alex Dima 已提交
990
	private createDecoration(range: IRange, model: ITextModel): IModelDeltaDecoration {
S
Sandeep Somavarapu 已提交
991 992 993 994 995 996
		return {
			range,
			options: WorkspaceConfigurationRenderer._DIM_CONFIGURATION_
		};
	}

R
Rob Lourens 已提交
997
	dispose(): void {
998
		this.decorationIds = this.editor.deltaDecorations(this.decorationIds, []);
999 1000
		super.dispose();
	}
1001
}