#18132 - Improve settings editor layout

- Extend search across left and right editors
- Show tabs inside settings editor to show user and workspace settings
- Improve highlighting of settings
This commit is contained in:
Sandeep Somavarapu
2017-01-19 00:15:21 +01:00
parent bc518b8ee5
commit 0294010dbf
11 changed files with 759 additions and 371 deletions
+2
View File
@@ -88,6 +88,7 @@ export interface INavigator<T> extends IIterator<T> {
parent(): T;
first(): T;
last(): T;
next(): T;
}
export class MappedNavigator<T, R> extends MappedIterator<T, R> implements INavigator<R> {
@@ -101,4 +102,5 @@ export class MappedNavigator<T, R> extends MappedIterator<T, R> implements INavi
parent() { return this.fn(this.navigator.parent()); }
first() { return this.fn(this.navigator.first()); }
last() { return this.fn(this.navigator.last()); }
next() { return this.fn(this.navigator.next()); }
}
+2 -4
View File
@@ -452,8 +452,7 @@ export class VSCodeMenu {
}
private getPreferencesMenu(): Electron.MenuItem {
const userSettings = this.createMenuItem(nls.localize({ key: 'miOpenSettings', comment: ['&& denotes a mnemonic'] }, "&&User Settings"), 'workbench.action.openGlobalSettings');
const workspaceSettings = this.createMenuItem(nls.localize({ key: 'miOpenWorkspaceSettings', comment: ['&& denotes a mnemonic'] }, "&&Workspace Settings"), 'workbench.action.openWorkspaceSettings');
const settings = this.createMenuItem(nls.localize({ key: 'miOpenSettings', comment: ['&& denotes a mnemonic'] }, "&&Settings"), 'workbench.action.openSettings');
const kebindingSettings = this.createMenuItem(nls.localize({ key: 'miOpenKeymap', comment: ['&& denotes a mnemonic'] }, "&&Keyboard Shortcuts"), 'workbench.action.openGlobalKeybindings');
const keymapExtensions = this.createMenuItem(nls.localize({ key: 'miOpenKeymapExtensions', comment: ['&& denotes a mnemonic'] }, "&&Keymap Extensions"), 'workbench.extensions.action.showRecommendedKeymapExtensions');
const snippetsSettings = this.createMenuItem(nls.localize({ key: 'miOpenSnippets', comment: ['&& denotes a mnemonic'] }, "User &&Snippets"), 'workbench.action.openSnippets');
@@ -461,8 +460,7 @@ export class VSCodeMenu {
const iconThemeSelection = this.createMenuItem(nls.localize({ key: 'miSelectIconTheme', comment: ['&& denotes a mnemonic'] }, "File &&Icon Theme"), 'workbench.action.selectIconTheme');
const preferencesMenu = new Menu();
preferencesMenu.append(userSettings);
preferencesMenu.append(workspaceSettings);
preferencesMenu.append(settings);
preferencesMenu.append(__separator__());
preferencesMenu.append(kebindingSettings);
preferencesMenu.append(keymapExtensions);
@@ -5,6 +5,7 @@
import { IDisposable } from 'vs/base/common/lifecycle';
import URI from 'vs/base/common/uri';
import Event, { Emitter } from 'vs/base/common/event';
import * as editorCommon from 'vs/editor/common/editorCommon';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { toResource } from 'vs/workbench/common/editor';
@@ -21,12 +22,16 @@ export class RangeHighlightDecorations implements IDisposable {
private editor: editorCommon.ICommonCodeEditor = null;
private editorDisposables: IDisposable[] = [];
private _onHighlightRemoved: Emitter<void> = new Emitter<void>();
public readonly onHighlghtRemoved: Event<void> = this._onHighlightRemoved.event;
constructor( @IWorkbenchEditorService private editorService: IWorkbenchEditorService) {
}
public removeHighlightRange() {
if (this.editor && this.rangeHighlightDecorationId) {
this.doRemoveRangeHighlight(this.editor, this.rangeHighlightDecorationId);
if (this.editor && this.editor.getModel() && this.rangeHighlightDecorationId) {
this.editor.deltaDecorations([this.rangeHighlightDecorationId], []);
this._onHighlightRemoved.fire();
}
this.rangeHighlightDecorationId = null;
}
@@ -67,12 +72,12 @@ export class RangeHighlightDecorations implements IDisposable {
|| e.reason === editorCommon.CursorChangeReason.Undo
|| e.reason === editorCommon.CursorChangeReason.Redo
) {
this.doRemoveRangeHighlight(this.editor, this.rangeHighlightDecorationId);
this.removeHighlightRange();
}
}));
this.editorDisposables.push(this.editor.onDidChangeModel(() => { this.doRemoveRangeHighlight(this.editor, this.rangeHighlightDecorationId); }));
this.editorDisposables.push(this.editor.onDidChangeModel(() => { this.removeHighlightRange(); }));
this.editorDisposables.push(this.editor.onDidDispose(() => {
this.doRemoveRangeHighlight(this.editor, this.rangeHighlightDecorationId);
this.removeHighlightRange();
this.editor = null;
}));
}
@@ -83,10 +88,6 @@ export class RangeHighlightDecorations implements IDisposable {
this.editorDisposables = [];
}
private doRemoveRangeHighlight(model: editorCommon.ICommonCodeEditor, rangeHighlightDecorationId: string) {
model.deltaDecorations([rangeHighlightDecorationId], []);
}
private createRangeHighlightDecoration(isWholeLine: boolean = true): editorCommon.IModelDecorationOptions {
return {
stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
@@ -3,57 +3,83 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.settings-header-widget {
border-bottom: 1px solid #efefef;
.preferences-editor > .preferences-header {
border-bottom: 1px solid #efeff2;
display: flex;
flex-wrap: wrap;
padding-left: 27px;
padding-right: 32px;
padding-bottom: 11px;
padding-top: 11px;
}
.vs-dark .settings-header-widget {
.vs-dark .preferences-editor > .preferences-header {
border-bottom: 1px solid #2d2d2d;
}
.settings-tabs-widget {
display: flex;
flex-wrap: wrap;
}
.settings-tabs-widget > .settings-tab {
text-transform: uppercase;
font-size: 12px;
font-weight: bold;
margin-left: 20px;
padding-top: 6px;
cursor: pointer;
}
.settings-tabs-widget > .settings-tab.active {
border-bottom: 2px solid #ccc;
}
.settings-tabs-widget > .settings-tab.disabled {
opacity: 0.5;
cursor: default;
}
.preferences-header > .settings-header-widget {
flex: 1;
display: flex;
position: relative;
}
.settings-header-widget > .settings-header-container {
padding-top: 8px;
padding-left: 27px;
padding-right: 32px;
}
.settings-header-widget > .settings-count-widget {
margin: 5px 0px;
padding: 0px 8px;
position: absolute;
right: 10px;
border-radius: 2px;
}
.settings-header-widget > .settings-count-widget:not(.no-results) {
background-color: #EFEFF2;
}
.hc-black .settings-header-widget > .settings-count-widget:not(.no-results),
.vs-dark .settings-header-widget > .settings-count-widget:not(.no-results) {
background-color: #2D2D30;
}
.settings-header-widget > .settings-count-widget.no-results {
background-color: rgba(255,0,0,0.5);
}
.hc-black .settings-header-widget > .settings-count-widget.no-results,
.vs-dark .settings-header-widget > .settings-count-widget.no-results {
background-color: rgba(255,0,0,0.3);
}
.settings-header-widget > .settings-search-container {
padding-left: 27px;
padding-right: 32px;
padding-bottom: 11px;
padding-top: 11px;
}
.vs .settings-header-widget > .settings-search-container {
background: #efeff2;
}
.vs-dark .settings-header-widget > .settings-search-container {
background: #2d2d30;
}
.settings-header-widget > .settings-header-container > .settings-title-container {
display: flex
}
.settings-header-widget > .settings-header-container > .settings-title-container > .settings-info-container {
white-space: pre-wrap;
margin-bottom: 8px;
font-size: 12px;
}
.vs .settings-header-widget > .settings-header-container > .settings-title-container > .settings-info-container {
color: #6f6f6f;
}
.vs-dark .settings-header-widget > .settings-header-container > .settings-title-container > .settings-info-container {
color: #bbbbbb;
}
.hc-black .settings-header-widget > .settings-header-container > .settings-title-container > .settings-info-container {
color: white;
}
.settings-header-widget > .settings-header-container > .settings-title-container > .settings-info-container .title-label {
text-transform: uppercase;
font-weight: bold;
flex: 1;
}
.settings-header-widget > .settings-search-container > .settings-search-input {
@@ -62,6 +88,7 @@
.settings-header-widget > .settings-search-container > .settings-search-input > .monaco-inputbox {
height: 30px;
min-width: 350px;
}
.vs .settings-header-widget > .settings-search-container > .settings-search-input > .monaco-inputbox {
@@ -80,6 +107,14 @@
background-image: url('search_inverse.svg');
}
.vs-dark .preferences-editor .side-by-side-preferences-editor > .editable-preferences-editor-container {
box-shadow: -6px 0 5px -5px black;
}
.preferences-editor .side-by-side-preferences-editor > .editable-preferences-editor-container {
box-shadow: -6px 0 5px -5px #DDD;
}
.monaco-editor .settings-group-title-widget {
z-index: 1;
}
@@ -102,7 +137,6 @@
color: white;
}
.monaco-editor.vs-dark .settings-group-title-widget .title-container.focused,
.monaco-editor.vs .settings-group-title-widget .title-container.focused {
outline: none !important;
@@ -182,36 +216,4 @@
.vs-dark .title-actions .action-item .icon.collapseAll,
.vs-dark .editor-actions .action-item .icon.collapseAll {
background: url('collapseAll_inverse.svg') center center no-repeat;
}
.monaco-editor .settings-count-widget {
padding: 4px 10px 4px 10px;
display: none;
position: absolute;
top: 4px;
right: 28px;
border-radius: 2px;
z-index: 1;
}
.monaco-editor .settings-count-widget.show {
display: inherit;
}
.monaco-editor .settings-count-widget.show:not(.no-results) {
background-color: #EFEFF2;
}
.monaco-editor.hc-black .settings-count-widget.show:not(.no-results),
.monaco-editor.vs-dark .settings-count-widget.show:not(.no-results) {
background-color: #2D2D30;
}
.monaco-editor .settings-count-widget.show.no-results {
background-color: rgba(255,0,0,0.5);
}
.monaco-editor.hc-black .settings-count-widget.show.no-results,
.monaco-editor.vs-dark .settings-count-widget.show.no-results {
background-color: rgba(255,0,0,0.3);
}
@@ -14,8 +14,8 @@ import { MenuId, MenuRegistry, SyncActionDescriptor } from 'vs/platform/actions/
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { DefaultPreferencesEditor, DefaultPreferencesEditorInput } from 'vs/workbench/parts/preferences/browser/preferencesEditor';
import { OpenGlobalSettingsAction, OpenGlobalKeybindingsAction, OpenWorkspaceSettingsAction } from 'vs/workbench/parts/preferences/browser/preferencesActions';
import { DefaultPreferencesEditorInput, PreferencesEditor, PreferencesEditorInput } from 'vs/workbench/parts/preferences/browser/preferencesEditor';
import { OpenSettingsAction, OpenGlobalSettingsAction, OpenGlobalKeybindingsAction, OpenWorkspaceSettingsAction } from 'vs/workbench/parts/preferences/browser/preferencesActions';
import { IPreferencesService, CONTEXT_DEFAULT_SETTINGS_EDITOR, DEFAULT_EDITOR_COMMAND_COLLAPSE_ALL } from 'vs/workbench/parts/preferences/common/preferences';
import { PreferencesService } from 'vs/workbench/parts/preferences/browser/preferencesService';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
@@ -27,21 +27,84 @@ registerSingleton(IPreferencesService, PreferencesService);
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditor(
new EditorDescriptor(
DefaultPreferencesEditor.ID,
PreferencesEditor.ID,
nls.localize('defaultPreferencesEditor', "Default Preferences Editor"),
'vs/workbench/parts/preferences/browser/preferencesEditor',
'DefaultPreferencesEditor'
'PreferencesEditor'
),
[
new SyncDescriptor(DefaultPreferencesEditorInput)
new SyncDescriptor(PreferencesEditorInput)
]
);
interface ISerializedPreferencesEditorInput {
name: string;
description: string;
detailsSerialized: string;
masterSerialized: string;
detailsTypeId: string;
masterTypeId: string;
}
// Register Preferences Editor Input Factory
class PreferencesEditorInputFactory implements IEditorInputFactory {
public serialize(editorInput: EditorInput): string {
const input = <PreferencesEditorInput>editorInput;
if (input.details && input.master) {
const registry = Registry.as<IEditorRegistry>(EditorExtensions.Editors);
const detailsInputFactory = registry.getEditorInputFactory(input.details.getTypeId());
const masterInputFactory = registry.getEditorInputFactory(input.master.getTypeId());
if (detailsInputFactory && masterInputFactory) {
const detailsSerialized = detailsInputFactory.serialize(input.details);
const masterSerialized = masterInputFactory.serialize(input.master);
if (detailsSerialized && masterSerialized) {
return JSON.stringify(<ISerializedPreferencesEditorInput>{
name: input.getName(),
description: input.getDescription(),
detailsSerialized,
masterSerialized,
detailsTypeId: input.details.getTypeId(),
masterTypeId: input.master.getTypeId()
});
}
}
}
return null;
}
public deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): EditorInput {
const deserialized: ISerializedPreferencesEditorInput = JSON.parse(serializedEditorInput);
const registry = Registry.as<IEditorRegistry>(EditorExtensions.Editors);
const detailsInputFactory = registry.getEditorInputFactory(deserialized.detailsTypeId);
const masterInputFactory = registry.getEditorInputFactory(deserialized.masterTypeId);
if (detailsInputFactory && masterInputFactory) {
const detailsInput = detailsInputFactory.deserialize(instantiationService, deserialized.detailsSerialized);
const masterInput = masterInputFactory.deserialize(instantiationService, deserialized.masterSerialized);
if (detailsInput && masterInput) {
return new PreferencesEditorInput(deserialized.name, deserialized.description, detailsInput, masterInput);
}
}
return null;
}
}
interface ISerializedDefaultPreferencesEditorInput {
resource: string;
}
// Register Editor Input Factory for Default Preferences Input
// Register Default Preferences Editor Input Factory
class DefaultPreferencesEditorInputFactory implements IEditorInputFactory {
public serialize(editorInput: EditorInput): string {
@@ -59,17 +122,19 @@ class DefaultPreferencesEditorInputFactory implements IEditorInputFactory {
}
}
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditorInputFactory(PreferencesEditorInput.ID, PreferencesEditorInputFactory);
Registry.as<IEditorRegistry>(EditorExtensions.Editors).registerEditorInputFactory(DefaultPreferencesEditorInput.ID, DefaultPreferencesEditorInputFactory);
// Contribute Global Actions
const category = nls.localize('preferences', "Preferences");
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL, {
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenSettingsAction, OpenSettingsAction.ID, OpenSettingsAction.LABEL, {
primary: null,
mac: { primary: KeyMod.CtrlCmd | KeyCode.US_COMMA }
}), 'Preferences: Open User Settings', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenGlobalKeybindingsAction, OpenGlobalKeybindingsAction.ID, OpenGlobalKeybindingsAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_S) }), 'Preferences: Open Keyboard Shortcuts', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenGlobalSettingsAction, OpenGlobalSettingsAction.ID, OpenGlobalSettingsAction.LABEL), 'Preferences: Open User Settings', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenWorkspaceSettingsAction, OpenWorkspaceSettingsAction.ID, OpenWorkspaceSettingsAction.LABEL), 'Preferences: Open Workspace Settings', category);
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenGlobalKeybindingsAction, OpenGlobalKeybindingsAction.ID, OpenGlobalKeybindingsAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_S) }), 'Preferences: Open Keyboard Shortcuts', category);
MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
command: {
@@ -9,6 +9,24 @@ import * as nls from 'vs/nls';
import { Action } from 'vs/base/common/actions';
import { IPreferencesService } from 'vs/workbench/parts/preferences/common/preferences';
export class OpenSettingsAction extends Action {
public static ID = 'workbench.action.openSettings';
public static LABEL = nls.localize('openSettings', "Open Settings");
constructor(
id: string,
label: string,
@IPreferencesService private preferencesService: IPreferencesService
) {
super(id, label);
}
public run(event?: any): TPromise<void> {
return this.preferencesService.openSettings();
}
}
export class OpenGlobalSettingsAction extends Action {
public static ID = 'workbench.action.openGlobalSettings';
@@ -10,16 +10,18 @@ import * as DOM from 'vs/base/browser/dom';
import { Delayer } from 'vs/base/common/async';
import { Dimension, Builder } from 'vs/base/browser/builder';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import { flatten } from 'vs/base/common/arrays';
import { ArrayIterator } from 'vs/base/common/iterator';
import { flatten, distinct } from 'vs/base/common/arrays';
import { ArrayNavigator, IIterator } from 'vs/base/common/iterator';
import { IAction } from 'vs/base/common/actions';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import Event, { Emitter } from 'vs/base/common/event';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor';
import { Registry } from 'vs/platform/platform';
import { EditorOptions, toResource } from 'vs/workbench/common/editor';
import { toResource, SideBySideEditorInput, EditorOptions, EditorInput, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/common/editor';
import { BaseEditor, EditorDescriptor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { ResourceEditorModel } from 'vs/workbench/common/editor/resourceEditorModel';
import { IEditorControl, IEditor } from 'vs/platform/editor/common/editor';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
import * as editorCommon from 'vs/editor/common/editorCommon';
@@ -35,7 +37,7 @@ import { SettingsEditorModel, DefaultSettingsEditorModel } from 'vs/workbench/pa
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
import { ICodeEditor, IEditorMouseEvent, IEditorContributionCtor } from 'vs/editor/browser/editorBrowser';
import { IContextMenuService, ContextSubMenu } from 'vs/platform/contextview/browser/contextView';
import { DefaultSettingsHeaderWidget, SettingsGroupTitleWidget, SettingsCountWidget, EditPreferenceWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets';
import { SearchWidget, SettingsTabsWidget, SettingsGroupTitleWidget, EditPreferenceWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets';
import { IContextKeyService, IContextKey, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { CommonEditorRegistry, EditorCommand, Command } from 'vs/editor/common/editorCommonExtensions';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -49,21 +51,26 @@ import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/edi
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { ITextModelResolverService } from 'vs/editor/common/services/resolverService';
import { RangeHighlightDecorations } from 'vs/workbench/common/editor/rangeDecorations';
import { IConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditing';
import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { VSash } from 'vs/base/browser/ui/sash/sash';
import { Widget } from 'vs/base/browser/ui/widget';
// Ignore following contributions
import { FoldingController } from 'vs/editor/contrib/folding/browser/folding';
import { FindController } from 'vs/editor/contrib/find/browser/find';
import { SelectionHighlighter } from 'vs/editor/contrib/find/common/findController';
export class PreferencesEditorInput extends SideBySideEditorInput {
public static ID: string = 'workbench.editorinputs.preferencesEditorInput';
getTypeId(): string {
return PreferencesEditorInput.ID;
}
}
export class DefaultPreferencesEditorInput extends ResourceEditorInput {
public static ID = 'workbench.editorinputs.defaultpreferences';
private _willDispose = new Emitter<void>();
public willDispose: Event<void> = this._willDispose.event;
constructor(defaultSettingsResource: URI,
@ITextModelResolverService textModelResolverService: ITextModelResolverService
) {
@@ -74,10 +81,6 @@ export class DefaultPreferencesEditorInput extends ResourceEditorInput {
return DefaultPreferencesEditorInput.ID;
}
supportsSplitEditor(): boolean {
return false;
}
matches(other: any): boolean {
if (!super.matches(other)) {
return false;
@@ -87,10 +90,268 @@ export class DefaultPreferencesEditorInput extends ResourceEditorInput {
}
return true;
}
}
dispose() {
this._willDispose.fire();
this._willDispose.dispose();
export class PreferencesEditor extends BaseEditor {
public static ID: string = 'workbench.editor.preferencesEditor';
private headerContainer: HTMLElement;
private searchWidget: SearchWidget;
private settingsTabsWidget: SettingsTabsWidget;
private sideBySidePreferencesWidget: SideBySidePreferencesWidget;
private delayedFilterLogging: Delayer<void>;
private disposablesByInput: IDisposable[] = [];
constructor(
@IPreferencesService private preferencesService: IPreferencesService,
@IEnvironmentService private environmentService: IEnvironmentService,
@ITelemetryService telemetryService: ITelemetryService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IInstantiationService private instantiationService: IInstantiationService
) {
super(PreferencesEditor.ID, telemetryService);
this.delayedFilterLogging = new Delayer<void>(1000);
}
public createEditor(parent: Builder): void {
const parentElement = parent.getHTMLElement();
DOM.addClass(parentElement, 'preferences-editor');
this.headerContainer = DOM.append(parentElement, DOM.$('.preferences-header'));
this.searchWidget = this._register(this.instantiationService.createInstance(SearchWidget, this.headerContainer));
this._register(this.searchWidget.onDidChange(value => this.filterPreferences(value.trim())));
this._register(this.searchWidget.onEnter(value => this.focusNextPreference()));
this.settingsTabsWidget = this._register(this.instantiationService.createInstance(SettingsTabsWidget, this.headerContainer));
this._register(this.settingsTabsWidget.onSwitch(() => this.switchSettings()));
const editorsContainer = DOM.append(parentElement, DOM.$('.preferences-editors-container'));
this.sideBySidePreferencesWidget = this._register(this.instantiationService.createInstance(SideBySidePreferencesWidget, editorsContainer));
}
public setInput(newInput: PreferencesEditorInput, options?: EditorOptions): TPromise<void> {
const oldInput = <PreferencesEditorInput>this.input;
return super.setInput(newInput, options)
.then(() => this.updateInput(oldInput, newInput, options));
}
public layout(dimension: Dimension): void {
const headerHeight = DOM.getTotalHeight(this.headerContainer);
this.sideBySidePreferencesWidget.layout(new Dimension(dimension.width, dimension.height - headerHeight));
}
public getControl(): IEditorControl {
const editablePreferencesEditor = this.sideBySidePreferencesWidget.getEditablePreferencesEditor();
return editablePreferencesEditor ? editablePreferencesEditor.getControl() : null;
}
public focus(): void {
this.searchWidget.focus();
}
private updateInput(oldInput: PreferencesEditorInput, newInput: PreferencesEditorInput, options?: EditorOptions): TPromise<void> {
const editablePreferencesUri = toResource(newInput.master);
this.settingsTabsWidget.show(editablePreferencesUri.toString() === this.preferencesService.userSettingsResource.toString() ? ConfigurationTarget.USER : ConfigurationTarget.WORKSPACE);
this.disposablesByInput = dispose(this.disposablesByInput);
return this.sideBySidePreferencesWidget.setInput(<DefaultPreferencesEditorInput>newInput.details, newInput.master, options).then(() => {
this.showTotalCount();
if (!this.getDefaultPreferencesRenderer()) {
return;
}
this.getDefaultPreferencesRenderer().onFocusPreference(setting => this.getEditablePreferencesRenderer().focusPreference(setting), this.disposablesByInput);
this.getDefaultPreferencesRenderer().onClearFocusPreference(setting => this.getEditablePreferencesRenderer().clearFocus(setting), this.disposablesByInput);
this.filterPreferences(this.searchWidget.value());
});
}
private switchSettings(): void {
const promise = this.input.isDirty() ? this.input.save() : TPromise.as(true);
promise.done(value => this.preferencesService.switchSettings());
}
private filterPreferences(filter: string) {
if (!this.getDefaultPreferencesRenderer()) {
return;
}
const defaultPreferencesRenderer = this.getDefaultPreferencesRenderer();
const editablePreferencesRender = this.getEditablePreferencesRenderer();
if (filter) {
this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(filter));
const filterResult = defaultPreferencesRenderer.preferencesModel.filterSettings(filter);
defaultPreferencesRenderer.filterPreferences(filterResult);
editablePreferencesRender.filterPreferences(filterResult);
const count = this.getCount(filterResult.filteredGroups);
this.searchWidget.showMessage(this.showSearchResultsMessage(count), count);
} else {
defaultPreferencesRenderer.filterPreferences(null);
editablePreferencesRender.filterPreferences(null);
this.showTotalCount();
}
}
private showTotalCount(): void {
if (this.getDefaultPreferencesRenderer()) {
const count = this.getCount(this.getDefaultPreferencesRenderer().preferencesModel.settingsGroups);
this.searchWidget.showMessage(nls.localize('totalSettingsMessage', "Total {0} Settings", count), count);
}
}
private showSearchResultsMessage(count: number): string {
return count === 0 ? nls.localize('noSettingsFound', "No Settings matched") :
count === 1 ? nls.localize('oneSettingFound', "1 Setting matched") :
nls.localize('settingsFound', "{0} Settings matched", count);
}
private focusNextPreference() {
const defaultPreferencesRenderer = this.getDefaultPreferencesRenderer();
if (defaultPreferencesRenderer) {
const setting = defaultPreferencesRenderer.iterator.next();
if (setting) {
defaultPreferencesRenderer.focusPreference(setting);
this.getEditablePreferencesRenderer().focusPreference(setting);
}
}
}
private getDefaultPreferencesRenderer(): IPreferencesRenderer {
const detailsEditor = this.sideBySidePreferencesWidget.getDefaultPreferencesEditor();
if (detailsEditor) {
return (<CodeEditor>this.sideBySidePreferencesWidget.getDefaultPreferencesEditor().getControl()).getContribution<PreferencesEditorContribution>(DefaultSettingsEditorContribution.ID).getPreferencesRenderer();
}
return null;
}
private getEditablePreferencesRenderer(): IPreferencesRenderer {
if (this.sideBySidePreferencesWidget.getEditablePreferencesEditor()) {
return (<CodeEditor>this.sideBySidePreferencesWidget.getEditablePreferencesEditor().getControl()).getContribution<PreferencesEditorContribution>(SettingsEditorContribution.ID).getPreferencesRenderer();
}
return null;
}
private reportFilteringUsed(filter: string): void {
let data = {};
data['filter'] = filter;
this.telemetryService.publicLog('defaultSettings.filter', data);
}
private getCount(settingsGroups: ISettingsGroup[]): number {
let count = 0;
for (const group of settingsGroups) {
for (const section of group.sections) {
count += section.settings.length;
}
}
return count;
}
}
export class SideBySidePreferencesWidget extends Widget {
private dimension: Dimension;
private defaultPreferencesEditor: DefaultPreferencesEditor;
private defaultPreferencesEditorContainer: HTMLElement;
private editablePreferencesEditor: BaseEditor;
private editablePreferencesEditorContainer: HTMLElement;
private sash: VSash;
constructor(parent: HTMLElement, @IInstantiationService private instantiationService: IInstantiationService) {
super();
this.create(parent);
}
private create(parentElement: HTMLElement): void {
DOM.addClass(parentElement, 'side-by-side-preferences-editor');
this.createSash(parentElement);
this.defaultPreferencesEditorContainer = DOM.append(parentElement, DOM.$('.default-preferences-editor-container'));
this.defaultPreferencesEditorContainer.style.position = 'absolute';
this.defaultPreferencesEditor = this.instantiationService.createInstance(DefaultPreferencesEditor);
this.defaultPreferencesEditor.create(new Builder(this.defaultPreferencesEditorContainer));
this.editablePreferencesEditorContainer = DOM.append(parentElement, DOM.$('.editable-preferences-editor-container'));
this.editablePreferencesEditorContainer.style.position = 'absolute';
}
public setInput(defaultPreferencesEditorInput: DefaultPreferencesEditorInput, editablePreferencesEditorInput: EditorInput, options?: EditorOptions): TPromise<void> {
return this.getOrCreateEditablePreferencesEditor(editablePreferencesEditorInput)
.then(() => {
this.dolayout(this.sash.getVerticalSashLeft());
return TPromise.join([this.defaultPreferencesEditor.updateInput(defaultPreferencesEditorInput, options, toResource(editablePreferencesEditorInput), this.editablePreferencesEditor),
this.editablePreferencesEditor.setInput(editablePreferencesEditorInput, options)])
.then(() => null);
});
}
public layout(dimension: Dimension): void {
this.dimension = dimension;
this.sash.setDimenesion(this.dimension);
}
public getEditablePreferencesEditor(): IEditor {
return this.editablePreferencesEditor;
}
public getDefaultPreferencesEditor(): DefaultPreferencesEditor {
return this.defaultPreferencesEditor;
}
private getOrCreateEditablePreferencesEditor(editorInput: EditorInput): TPromise<BaseEditor> {
if (this.editablePreferencesEditor) {
return TPromise.as(this.editablePreferencesEditor);
}
const descriptor = Registry.as<IEditorRegistry>(EditorExtensions.Editors).getEditor(editorInput);
return this.instantiationService.createInstance(<EditorDescriptor>descriptor)
.then((editor: BaseEditor) => {
this.editablePreferencesEditor = editor;
this.editablePreferencesEditor.create(new Builder(this.editablePreferencesEditorContainer));
this.editablePreferencesEditor.setVisible(true);
return editor;
});
}
private createSash(parentElement: HTMLElement): void {
this.sash = this._register(new VSash(parentElement, 220));
this._register(this.sash.onPositionChange(position => this.dolayout(position)));
}
private dolayout(splitPoint: number): void {
if (!this.editablePreferencesEditor || !this.dimension) {
return;
}
const masterEditorWidth = this.dimension.width - splitPoint;
const detailsEditorWidth = this.dimension.width - masterEditorWidth;
this.defaultPreferencesEditorContainer.style.width = `${detailsEditorWidth}px`;
this.defaultPreferencesEditorContainer.style.height = `${this.dimension.height}px`;
this.defaultPreferencesEditorContainer.style.left = '0px';
this.editablePreferencesEditorContainer.style.width = `${masterEditorWidth}px`;
this.editablePreferencesEditorContainer.style.height = `${this.dimension.height}px`;
this.editablePreferencesEditorContainer.style.left = `${splitPoint}px`;
this.defaultPreferencesEditor.layout(new Dimension(detailsEditorWidth, this.dimension.height));
this.editablePreferencesEditor.layout(new Dimension(masterEditorWidth, this.dimension.height));
}
private disposeEditors(): void {
if (this.defaultPreferencesEditor) {
this.defaultPreferencesEditor.dispose();
this.defaultPreferencesEditor = null;
}
if (this.editablePreferencesEditor) {
this.editablePreferencesEditor.dispose();
this.editablePreferencesEditor = null;
}
}
public dispose(): void {
this.disposeEditors();
super.dispose();
}
}
@@ -99,9 +360,6 @@ export class DefaultPreferencesEditor extends BaseTextEditor {
public static ID: string = 'workbench.editor.defaultPreferences';
private defaultSettingHeaderWidget: DefaultSettingsHeaderWidget;
private delayedFilterLogging: Delayer<void>;
constructor(
@ITelemetryService telemetryService: ITelemetryService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@@ -115,19 +373,10 @@ export class DefaultPreferencesEditor extends BaseTextEditor {
@IModeService modeService: IModeService,
) {
super(DefaultPreferencesEditor.ID, telemetryService, instantiationService, storageService, configurationService, themeService, modeService);
this.delayedFilterLogging = new Delayer<void>(1000);
}
public createEditorControl(parent: Builder, configuration: editorCommon.IEditorOptions): editorCommon.IEditor {
const parentContainer = parent.getHTMLElement();
this.defaultSettingHeaderWidget = this._register(this.instantiationService.createInstance(DefaultSettingsHeaderWidget, parentContainer));
this._register(this.defaultSettingHeaderWidget.onDidChange(value => this.filterPreferences(value)));
this._register(this.defaultSettingHeaderWidget.onEnter(value => this.focusNextPreference()));
const defaultPreferencesEditor = this.instantiationService.createInstance(DefaultPreferencesCodeEditor, parentContainer, configuration);
return defaultPreferencesEditor;
return this.instantiationService.createInstance(DefaultPreferencesCodeEditor, parent.getHTMLElement(), configuration);
}
protected getConfigurationOverrides(): editorCommon.IEditorOptions {
@@ -146,66 +395,30 @@ export class DefaultPreferencesEditor extends BaseTextEditor {
return options;
}
setInput(input: DefaultPreferencesEditorInput, options: EditorOptions): TPromise<void> {
return super.setInput(input, options).then(() => this.updateInput());
updateInput(input: DefaultPreferencesEditorInput, options: EditorOptions, editablePreferencesUri: URI, settingsEditor: BaseEditor): TPromise<void> {
return this.setInput(input, options)
.then(() => this.input.resolve()
.then(editorModel => TPromise.join<any>([
editorModel.load(),
this.preferencesService.resolvePreferencesEditorModel(editablePreferencesUri)
]))
.then(([editorModel, preferencesModel]) => (<DefaultPreferencesCodeEditor>this.getControl()).setModels((<ResourceEditorModel>editorModel).textEditorModel, <SettingsEditorModel>preferencesModel, settingsEditor)));
}
public layout(dimension: Dimension) {
this.defaultSettingHeaderWidget.layout(dimension);
const headerHeight = DOM.getTotalHeight(this.defaultSettingHeaderWidget.domNode);
this.getControl().layout({
height: dimension.height - headerHeight,
width: dimension.width
});
}
public focus(): void {
if (this.input) {
this.defaultSettingHeaderWidget.focus();
} else {
super.focus();
}
}
private updateInput(): TPromise<void> {
return this.input.resolve()
.then(editorModel => TPromise.join<any>([
editorModel.load(),
// Default preferences editor is always part of side by side editor hence getting the master preferences model from active editor
// TODO:@sandy check with Ben
this.preferencesService.resolvePreferencesEditorModel(toResource(this.editorService.getActiveEditorInput(), { supportSideBySide: true }))
]))
.then(([editorModel, preferencesModel]) => (<DefaultPreferencesCodeEditor>this.getControl()).setModels((<ResourceEditorModel>editorModel).textEditorModel, <SettingsEditorModel>preferencesModel));
}
private filterPreferences(filter: string) {
this.delayedFilterLogging.trigger(() => this.reportFilteringUsed(filter));
(<DefaultSettingsRenderer>this.getDefaultPreferencesContribution().getPreferencesRenderer()).filterPreferences(filter.trim());
}
private focusNextPreference() {
(<DefaultSettingsRenderer>this.getDefaultPreferencesContribution().getPreferencesRenderer()).focusNextSetting();
this.getControl().layout(dimension);
}
public clearInput(): void {
this.getControl().setModel(null);
super.clearInput();
}
private getDefaultPreferencesContribution(): PreferencesEditorContribution {
return (<CodeEditor>this.getControl()).getContribution<PreferencesEditorContribution>(DefaultSettingsEditorContribution.ID);
}
private reportFilteringUsed(filter: string): void {
let data = {};
data['filter'] = filter;
this.telemetryService.publicLog('defaultSettings.filter', data);
}
}
class DefaultPreferencesCodeEditor extends CodeEditor {
private _settingsModel: SettingsEditorModel;
private _settingsEditor: BaseEditor;
protected _getContributions(): IEditorContributionCtor[] {
let contributions = super._getContributions();
@@ -215,19 +428,31 @@ class DefaultPreferencesCodeEditor extends CodeEditor {
return contributions;
}
setModels(model: editorCommon.IModel, settingsModel: SettingsEditorModel): void {
setModels(model: editorCommon.IModel, settingsModel: SettingsEditorModel, settingsEditor: BaseEditor): void {
this._settingsModel = settingsModel;
this._settingsEditor = settingsEditor;
return super.setModel(model);
}
get settingsModel(): SettingsEditorModel {
return this._settingsModel;
}
get settingsEditor(): BaseEditor {
return this._settingsEditor;
}
}
export interface IPreferencesRenderer {
render();
iterator: IIterator<ISetting>;
onFocusPreference: Event<ISetting>;
onClearFocusPreference: Event<ISetting>;
preferencesModel: ISettingsEditorModel;
render(): void;
updatePreference(setting: ISetting, value: any): void;
filterPreferences(filterResult: IFilterResult): void;
focusPreference(setting: ISetting): void;
clearFocus(setting: ISetting): void;
dispose();
}
@@ -285,7 +510,7 @@ export class DefaultSettingsEditorContribution extends PreferencesEditorContribu
protected createPreferencesRenderer(editorModel: IPreferencesEditorModel): IPreferencesRenderer {
if (editorModel instanceof DefaultSettingsEditorModel) {
return this.instantiationService.createInstance(DefaultSettingsRenderer, this.editor, editorModel, (<DefaultPreferencesCodeEditor>this.editor).settingsModel);
return this.instantiationService.createInstance(DefaultSettingsRenderer, this.editor, editorModel);
}
return null;
}
@@ -317,9 +542,17 @@ export class SettingsRenderer extends Disposable implements IPreferencesRenderer
private initializationPromise: TPromise<void>;
private settingHighlighter: SettingHighlighter;
private editSettingActionRenderer: EditSettingRenderer;
private highlightPreferencesRenderer: HighlightPreferencesRenderer;
private defaultSettingsModel: DefaultSettingsEditorModel;
private modelChangeDelayer: Delayer<void> = new Delayer<void>(200);
constructor(protected editor: ICodeEditor, protected settingsEditorModel: SettingsEditorModel,
private _onFocusPreference: Emitter<ISetting> = new Emitter<ISetting>();
public readonly onFocusPreference: Event<ISetting> = this._onFocusPreference.event;
private _onClearFocusPreference: Emitter<ISetting> = new Emitter<ISetting>();
public readonly onClearFocusPreference: Event<ISetting> = this._onClearFocusPreference.event;
constructor(protected editor: ICodeEditor, public readonly preferencesModel: SettingsEditorModel,
@IPreferencesService protected preferencesService: IPreferencesService,
@ITelemetryService private telemetryService: ITelemetryService,
@IConfigurationEditingService private configurationEditingService: IConfigurationEditingService,
@@ -327,18 +560,26 @@ export class SettingsRenderer extends Disposable implements IPreferencesRenderer
@IInstantiationService protected instantiationService: IInstantiationService
) {
super();
this.settingHighlighter = this._register(instantiationService.createInstance(SettingHighlighter, editor));
this.settingHighlighter = this._register(instantiationService.createInstance(SettingHighlighter, editor, this._onFocusPreference, this._onClearFocusPreference));
this.highlightPreferencesRenderer = this._register(instantiationService.createInstance(HighlightPreferencesRenderer, editor));
this.initializationPromise = this.initialize();
}
public get iterator(): IIterator<ISetting> {
return null;
}
public render(): void {
this.initializationPromise.then(() => this.editSettingActionRenderer.render(this.settingsEditorModel.settingsGroups));
this.initializationPromise.then(() => {
this.editSettingActionRenderer.render(this.preferencesModel.settingsGroups);
});
}
private initialize(): TPromise<void> {
return this.preferencesService.createDefaultPreferencesEditorModel(this.preferencesService.defaultSettingsResource)
.then(defaultSettingsModel => {
this.editSettingActionRenderer = this._register(this.instantiationService.createInstance(EditSettingRenderer, this.editor, this.settingsEditorModel, defaultSettingsModel, this.settingHighlighter));
this.defaultSettingsModel = <DefaultSettingsEditorModel>defaultSettingsModel;
this.editSettingActionRenderer = this._register(this.instantiationService.createInstance(EditSettingRenderer, this.editor, this.preferencesModel, () => defaultSettingsModel, this.settingHighlighter));
this._register(this.editor.getModel().onDidChangeContent(() => this.modelChangeDelayer.trigger(() => this.onModelChanged())));
this._register(this.editSettingActionRenderer.onUpdateSetting(({setting, value}) => this.updatePreference(setting, value)));
return null;
@@ -355,16 +596,48 @@ export class SettingsRenderer extends Disposable implements IPreferencesRenderer
public updatePreference(setting: ISetting, value: any): void {
this.telemetryService.publicLog('defaultSettingsActions.copySetting', { userConfigurationKeys: [setting.key] });
this.configurationEditingService.writeConfiguration(this.settingsEditorModel.configurationTarget, { key: setting.key, value }, { writeToBuffer: true, autoSave: true })
this.configurationEditingService.writeConfiguration(this.preferencesModel.configurationTarget, { key: setting.key, value }, { writeToBuffer: true, autoSave: true })
.then(() => this.onSettingUpdated(setting), error => this.messageService.show(Severity.Error, error));
}
private onSettingUpdated(setting: ISetting) {
this.editor.focus();
setting = this.settingsEditorModel.getSetting(setting.key);
setting = this.preferencesModel.getSetting(setting.key);
// TODO:@sandy Selection range should be template range
this.editor.setSelection(setting.valueRange);
this.settingHighlighter.highlight(this.settingsEditorModel.getSetting(setting.key), true);
this.settingHighlighter.highlight(this.preferencesModel.getSetting(setting.key), true);
}
public filterPreferences(filterResult: IFilterResult): void {
this.highlightPreferencesRenderer.render([]);
this.settingHighlighter.clear(true);
if (this.defaultSettingsModel && filterResult) {
const settings = distinct(filterResult.filteredGroups.reduce((settings: ISetting[], settingsGroup: ISettingsGroup) => {
for (const section of settingsGroup.sections) {
for (const setting of section.settings) {
const s = this.preferencesModel.getSetting(setting.key);
if (s) {
settings.push(s);
}
}
}
return settings;
}, []));
this.highlightPreferencesRenderer.render(settings);
}
}
public focusPreference(setting: ISetting): void {
const s = this.preferencesModel.getSetting(setting.key);
if (s) {
this.settingHighlighter.highlight(s, true);
} else {
this.settingHighlighter.clear(true);
}
}
public clearFocus(setting: ISetting): void {
this.settingHighlighter.clear(true);
}
}
@@ -378,10 +651,14 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
private filteredSettingsNavigationRenderer: FilteredSettingsNavigationRenderer;
private hiddenAreasRenderer: HiddenAreasRenderer;
private editSettingActionRenderer: EditSettingRenderer;
private settingsCountWidget: SettingsCountWidget;
constructor(protected editor: ICodeEditor, protected defaultSettingsEditorModel: DefaultSettingsEditorModel,
private settingsEditorModel: SettingsEditorModel,
private _onFocusPreference: Emitter<ISetting> = new Emitter<ISetting>();
public readonly onFocusPreference: Event<ISetting> = this._onFocusPreference.event;
private _onClearFocusPreference: Emitter<ISetting> = new Emitter<ISetting>();
public readonly onClearFocusPreference: Event<ISetting> = this._onClearFocusPreference.event;
constructor(protected editor: ICodeEditor, public readonly preferencesModel: DefaultSettingsEditorModel,
@IPreferencesService protected preferencesService: IPreferencesService,
@IContextKeyService contextKeyService: IContextKeyService,
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@@ -389,50 +666,53 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
) {
super();
this.defaultSettingsEditorContextKey = CONTEXT_DEFAULT_SETTINGS_EDITOR.bindTo(contextKeyService);
this.settingHighlighter = this._register(instantiationService.createInstance(SettingHighlighter, editor));
this.settingHighlighter = this._register(instantiationService.createInstance(SettingHighlighter, editor, this._onFocusPreference, this._onClearFocusPreference));
this.settingsGroupTitleRenderer = this._register(instantiationService.createInstance(SettingsGroupTitleRenderer, editor));
this.filteredMatchesRenderer = this._register(instantiationService.createInstance(FilteredMatchesRenderer, editor));
this.filteredSettingsNavigationRenderer = this._register(instantiationService.createInstance(FilteredSettingsNavigationRenderer, editor, this.settingHighlighter));
this.editSettingActionRenderer = this._register(instantiationService.createInstance(EditSettingRenderer, editor, defaultSettingsEditorModel, settingsEditorModel, this.settingHighlighter));
this.editSettingActionRenderer = this._register(instantiationService.createInstance(EditSettingRenderer, editor, preferencesModel, () => (<DefaultPreferencesCodeEditor>this.editor).settingsModel, this.settingHighlighter));
this._register(this.editSettingActionRenderer.onUpdateSetting(({setting, value}) => this.updatePreference(setting, value)));
this.settingsCountWidget = this._register(instantiationService.createInstance(SettingsCountWidget, editor, this.getCount(defaultSettingsEditorModel.settingsGroups)));
const paranthesisHidingRenderer = this._register(instantiationService.createInstance(StaticContentHidingRenderer, editor, defaultSettingsEditorModel.settingsGroups));
const paranthesisHidingRenderer = this._register(instantiationService.createInstance(StaticContentHidingRenderer, editor, preferencesModel.settingsGroups));
this.hiddenAreasRenderer = this._register(instantiationService.createInstance(HiddenAreasRenderer, editor, [this.settingsGroupTitleRenderer, this.filteredMatchesRenderer, paranthesisHidingRenderer]));
this._register(this.settingsGroupTitleRenderer.onHiddenAreasChanged(() => this.hiddenAreasRenderer.render()));
}
public get iterator(): IIterator<ISetting> {
return this.filteredSettingsNavigationRenderer;
}
public render() {
this.defaultSettingsEditorContextKey.set(true);
this.settingsGroupTitleRenderer.render(this.defaultSettingsEditorModel.settingsGroups);
this.editSettingActionRenderer.render(this.defaultSettingsEditorModel.settingsGroups);
this.settingsCountWidget.render();
this.settingsGroupTitleRenderer.render(this.preferencesModel.settingsGroups);
this.editSettingActionRenderer.render(this.preferencesModel.settingsGroups);
this.hiddenAreasRenderer.render();
this.filteredSettingsNavigationRenderer.render([]);
this.settingsGroupTitleRenderer.showGroup(1);
this.hiddenAreasRenderer.render();
}
public filterPreferences(filter: string) {
const filterResult = this.defaultSettingsEditorModel.filterSettings(filter);
this.filteredMatchesRenderer.render(filterResult);
this.settingsGroupTitleRenderer.render(filterResult.filteredGroups);
this.settingsCountWidget.show(this.getCount(filterResult.filteredGroups));
if (!filter) {
public filterPreferences(filterResult: IFilterResult): void {
if (!filterResult) {
this.filteredSettingsNavigationRenderer.render([]);
this.filteredMatchesRenderer.render(null);
this.settingsGroupTitleRenderer.render(this.preferencesModel.settingsGroups);
this.settingsGroupTitleRenderer.showGroup(1);
} else {
this.filteredMatchesRenderer.render(filterResult);
this.settingsGroupTitleRenderer.render(filterResult.filteredGroups);
this.filteredSettingsNavigationRenderer.render(filterResult.filteredGroups);
}
this.hiddenAreasRenderer.render();
}
public focusNextSetting(): void {
const setting = this.filteredSettingsNavigationRenderer.next();
if (setting) {
this.settingsGroupTitleRenderer.showSetting(setting);
}
public focusPreference(setting: ISetting): void {
this.settingsGroupTitleRenderer.showSetting(setting);
this.settingHighlighter.highlight(setting, true);
}
public clearFocus(setting: ISetting): void {
this.settingHighlighter.clear(true);
}
public collapseAll() {
@@ -447,23 +727,7 @@ export class DefaultSettingsRenderer extends Disposable implements IPreferencesR
}
private getEditableSettingsEditor(): editorCommon.ICommonCodeEditor {
return this.editorService.getVisibleEditors()
.filter(editor => {
if (editorCommon.isCommonCodeEditor(editor.getControl())) {
return (<editorCommon.ICommonCodeEditor>editor.getControl()).getModel().uri.fsPath === this.settingsEditorModel.uri.fsPath;
}
})
.map(editor => <editorCommon.ICommonCodeEditor>editor.getControl())[0];
}
private getCount(settingsGroups: ISettingsGroup[]): number {
let count = 0;
for (const group of settingsGroups) {
for (const section of group.sections) {
count += section.settings.length;
}
}
return count;
return <editorCommon.ICommonCodeEditor>(<DefaultPreferencesCodeEditor>this.editor).settingsEditor.getControl();
}
dispose() {
@@ -722,21 +986,58 @@ export class FilteredMatchesRenderer extends Disposable implements HiddenAreasPr
}
}
class FilteredSettingsNavigationRenderer extends Disposable {
export class HighlightPreferencesRenderer extends Disposable {
private iterator: ArrayIterator<ISetting>;
private decorationIds: string[] = [];
constructor(private editor: ICodeEditor,
@IInstantiationService private instantiationService: IInstantiationService
) {
super();
}
public render(settings: ISetting[]): void {
const model = this.editor.getModel();
this.editor.changeDecorations(changeAccessor => {
this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, []);
});
if (settings.length) {
this.editor.changeDecorations(changeAccessor => {
this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, settings.map(setting => this.createDecoration(setting.keyRange, model)));
});
}
}
private createDecoration(range: editorCommon.IRange, model: editorCommon.IModel): editorCommon.IModelDeltaDecoration {
return {
range,
options: {
stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
className: 'findMatch'
}
};
}
public dispose() {
if (this.decorationIds) {
this.decorationIds = this.editor.changeDecorations(changeAccessor => {
return changeAccessor.deltaDecorations(this.decorationIds, []);
});
}
super.dispose();
}
}
class FilteredSettingsNavigationRenderer extends Disposable implements IIterator<ISetting> {
private iterator: ArrayNavigator<ISetting>;
constructor(private editor: ICodeEditor, private settingHighlighter: SettingHighlighter) {
super();
}
public next(): ISetting {
let setting = this.iterator.next() || this.iterator.first();
if (setting) {
this.settingHighlighter.highlight(setting, true);
return setting;
}
return null;
return this.iterator.next() || this.iterator.first();
}
public render(filteredGroups: ISettingsGroup[]) {
@@ -747,7 +1048,7 @@ class FilteredSettingsNavigationRenderer extends Disposable {
settings.push(...section.settings);
}
}
this.iterator = new ArrayIterator<ISetting>(settings);
this.iterator = new ArrayNavigator<ISetting>(settings);
}
}
@@ -763,7 +1064,7 @@ class EditSettingRenderer extends Disposable {
public readonly onUpdateSetting: Event<{ setting: ISetting, value: any }> = this._onUpdateSetting.event;
constructor(private editor: ICodeEditor, private masterSettingsModel: ISettingsEditorModel,
private otherSettingsModel: ISettingsEditorModel,
private otherSettingsModel: () => ISettingsEditorModel,
private settingHighlighter: SettingHighlighter,
@IPreferencesService private preferencesService: IPreferencesService,
@IInstantiationService private instantiationService: IInstantiationService,
@@ -921,7 +1222,7 @@ class EditSettingRenderer extends Disposable {
}
private getDefaultActions(setting: ISetting): IAction[] {
const settingInOtherModel = this.otherSettingsModel.getSetting(setting.key);
const settingInOtherModel = this.otherSettingsModel().getSetting(setting.key);
if (this.isDefaultSettings()) {
return [<IAction>{
id: 'setDefaultValue',
@@ -942,14 +1243,20 @@ class SettingHighlighter extends Disposable {
private fixedHighlighter: RangeHighlightDecorations;
private volatileHighlighter: RangeHighlightDecorations;
private highlightedSetting: ISetting;
constructor(private editor: editorCommon.ICommonCodeEditor, @IInstantiationService instantiationService: IInstantiationService) {
constructor(private editor: editorCommon.ICommonCodeEditor, private focusEventEmitter: Emitter<ISetting>, private clearFocusEventEmitter: Emitter<ISetting>,
@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();
@@ -960,6 +1267,7 @@ class SettingHighlighter extends Disposable {
}, this.editor);
this.editor.revealLinesInCenterIfOutsideViewport(setting.valueRange.startLineNumber, setting.valueRange.endLineNumber - 1);
this.focusEventEmitter.fire(setting);
}
clear(fix: boolean = false): void {
@@ -967,6 +1275,7 @@ class SettingHighlighter extends Disposable {
if (fix) {
this.fixedHighlighter.removeHighlightRange();
}
this.clearFocusEventEmitter.fire(this.highlightedSetting);
}
}
@@ -10,13 +10,13 @@ import URI from 'vs/base/common/uri';
import { LinkedMap as Map } from 'vs/base/common/map';
import * as labels from 'vs/base/common/labels';
import { Disposable } from 'vs/base/common/lifecycle';
import { SideBySideEditorInput, EditorInput } from 'vs/workbench/common/editor';
import { EditorInput, toResource } from 'vs/workbench/common/editor';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceConfigurationService, WORKSPACE_CONFIG_DEFAULT_PATH } from 'vs/workbench/services/configuration/common/configuration';
import { Position, IEditor } from 'vs/platform/editor/common/editor';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { Position } from 'vs/platform/editor/common/editor';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IFileService, IFileOperationResult, FileOperationResult } from 'vs/platform/files/common/files';
import { IMessageService, Severity, IChoiceService } from 'vs/platform/message/common/message';
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
@@ -26,11 +26,9 @@ import { IConfigurationEditingService, ConfigurationTarget } from 'vs/workbench/
import { IPreferencesService, IPreferencesEditorModel } from 'vs/workbench/parts/preferences/common/preferences';
import { SettingsEditorModel, DefaultSettingsEditorModel, DefaultKeybindingsEditorModel } from 'vs/workbench/parts/preferences/common/preferencesModels';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { DefaultPreferencesEditorInput } from 'vs/workbench/parts/preferences/browser/preferencesEditor';
import { DefaultPreferencesEditorInput, PreferencesEditorInput } from 'vs/workbench/parts/preferences/browser/preferencesEditor';
import { ITextModelResolverService } from 'vs/editor/common/services/resolverService';
const SETTINGS_INFO_IGNORE_KEY = 'settings.workspace.info.ignore';
interface IWorkbenchSettingsConfiguration {
workbench: {
settings: {
@@ -45,8 +43,7 @@ export class PreferencesService extends Disposable implements IPreferencesServic
// TODO:@sandy merge these models into editor inputs by extending resource editor model
private defaultPreferencesEditorModels: Map<URI, IPreferencesEditorModel>;
private defaultSettingsEditorInputForUser: DefaultPreferencesEditorInput;
private defaultSettingsEditorInputForWorkspace: DefaultPreferencesEditorInput;
private lastOpenedSettingsInput: PreferencesEditorInput = null;
constructor(
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@@ -66,11 +63,25 @@ export class PreferencesService extends Disposable implements IPreferencesServic
) {
super();
this.defaultPreferencesEditorModels = new Map<URI, IPreferencesEditorModel>();
this.editorGroupService.onEditorsChanged(() => {
const activeEditorInput = this.editorService.getActiveEditorInput();
if (activeEditorInput instanceof PreferencesEditorInput) {
this.lastOpenedSettingsInput = activeEditorInput;
}
});
}
readonly defaultSettingsResource = URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: '/settings.json' });
readonly defaultKeybindingsResource = URI.from({ scheme: network.Schemas.vscode, authority: 'defaultsettings', path: '/keybindings.json' });
get userSettingsResource(): URI {
return this.getEditableSettingsURI(ConfigurationTarget.USER);
}
get workspaceSettingsResource(): URI {
return this.getEditableSettingsURI(ConfigurationTarget.WORKSPACE);
}
createDefaultPreferencesEditorModel(uri: URI): TPromise<IPreferencesEditorModel> {
const editorModel = this.defaultPreferencesEditorModels.get(uri);
if (editorModel) {
@@ -114,12 +125,12 @@ export class PreferencesService extends Disposable implements IPreferencesServic
return TPromise.wrap(null);
}
openSettings(): TPromise<void> {
return this.doOpenSettings(this.getSettingsConfigurationTarget(this.lastOpenedSettingsInput), false);
}
openGlobalSettings(): TPromise<void> {
if (this.configurationService.hasWorkspaceConfiguration() && !this.storageService.getBoolean(SETTINGS_INFO_IGNORE_KEY, StorageScope.WORKSPACE)) {
this.promptToOpenWorkspaceSettings();
}
// Open settings
return this.openSettings(ConfigurationTarget.USER);
return this.doOpenSettings(ConfigurationTarget.USER);
}
openWorkspaceSettings(): TPromise<void> {
@@ -127,7 +138,27 @@ export class PreferencesService extends Disposable implements IPreferencesServic
this.messageService.show(Severity.Info, nls.localize('openFolderFirst', "Open a folder first to create workspace settings"));
return TPromise.as(null);
}
return this.openSettings(ConfigurationTarget.WORKSPACE);
return this.doOpenSettings(ConfigurationTarget.WORKSPACE);
}
switchSettings(): TPromise<void> {
const activeEditorInput = this.editorService.getActiveEditorInput();
if (activeEditorInput instanceof PreferencesEditorInput) {
const fromTarget = this.getSettingsConfigurationTarget(activeEditorInput);
const toTarget = ConfigurationTarget.USER === fromTarget ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER;
return this.getOrCreateEditableSettingsEditorInput(toTarget)
.then(toInput => {
const replaceWith = new PreferencesEditorInput(toInput.getName(), toInput.getDescription(), this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.defaultSettingsResource), toInput);
return this.editorService.replaceEditors([{
toReplace: this.lastOpenedSettingsInput,
replaceWith
}]).then(() => {
this.lastOpenedSettingsInput = replaceWith;
});
});
} else {
this.openSettings();
}
}
openGlobalKeybindingSettings(): TPromise<void> {
@@ -135,13 +166,25 @@ export class PreferencesService extends Disposable implements IPreferencesServic
return this.openTwoEditors(this.defaultKeybindingsResource, URI.file(this.environmentService.appKeybindingsPath), emptyContents).then(() => null);
}
private openEditableSettings(configurationTarget: ConfigurationTarget): TPromise<IEditor> {
const emptySettingsContents = this.getEmptyEditableSettingsContent(configurationTarget);
const settingsResource = this.getEditableSettingsURI(configurationTarget);
return this.createIfNotExists(settingsResource, emptySettingsContents).then(() => this.editorService.openEditor({
resource: settingsResource,
options: { pinned: true }
}));
private doOpenSettings(configurationTarget: ConfigurationTarget, checkToOpenDefaultSettings: boolean = true): TPromise<void> {
const openDefaultSettings = !checkToOpenDefaultSettings || !!this.configurationService.getConfiguration<IWorkbenchSettingsConfiguration>().workbench.settings.openDefaultSettings;
return this.getOrCreateEditableSettingsEditorInput(configurationTarget)
.then(editableSettingsEditorInput => {
if (openDefaultSettings) {
const defaultPreferencesEditorInput = this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.defaultSettingsResource);
const preferencesEditorInput = new PreferencesEditorInput(editableSettingsEditorInput.getName(), editableSettingsEditorInput.getDescription(), defaultPreferencesEditorInput, <EditorInput>editableSettingsEditorInput);
this.lastOpenedSettingsInput = preferencesEditorInput;
return this.editorService.openEditor(preferencesEditorInput, { pinned: true });
}
return this.editorService.openEditor(editableSettingsEditorInput, { pinned: true });
}).then(() => null);
}
private getOrCreateEditableSettingsEditorInput(configurationTarget: ConfigurationTarget): TPromise<EditorInput> {
const resource = this.getEditableSettingsURI(configurationTarget);
const editableSettingsEmptyContent = this.getEmptyEditableSettingsContent(configurationTarget);
return this.createIfNotExists(resource, editableSettingsEmptyContent)
.then(() => this.editorService.createInput({ resource }));
}
private resolveSettingsEditorModel(configurationTarget: ConfigurationTarget): TPromise<SettingsEditorModel> {
@@ -179,58 +222,6 @@ export class PreferencesService extends Disposable implements IPreferencesServic
return null;
}
private promptToOpenWorkspaceSettings() {
this.choiceService.choose(Severity.Info, nls.localize('workspaceHasSettings', "The currently opened folder contains workspace settings that may override user settings"),
[nls.localize('openWorkspaceSettings', "Open Workspace Settings"), nls.localize('neverShowAgain', "Don't show again"), nls.localize('close', "Close")]
).then(choice => {
switch (choice) {
case 0:
const editorCount = this.editorService.getVisibleEditors().length;
return this.editorService.openEditor({ resource: this.contextService.toResource(WORKSPACE_CONFIG_DEFAULT_PATH), options: { pinned: true } }, editorCount === 2 ? Position.THREE : editorCount === 1 ? Position.TWO : void 0);
case 1:
this.storageService.store(SETTINGS_INFO_IGNORE_KEY, true, StorageScope.WORKSPACE);
default:
return TPromise.as(true);
}
});
}
private openSettings(configurationTarget: ConfigurationTarget): TPromise<void> {
const openDefaultSettings = !!this.configurationService.getConfiguration<IWorkbenchSettingsConfiguration>().workbench.settings.openDefaultSettings;
if (openDefaultSettings) {
const emptySettingsContents = this.getEmptyEditableSettingsContent(configurationTarget);
const settingsResource = this.getEditableSettingsURI(configurationTarget);
return this.openSideBySideEditor(this.getDefaultSettingsEditorInput(configurationTarget), settingsResource, emptySettingsContents);
}
return this.openEditableSettings(configurationTarget).then(() => null);
}
private getDefaultSettingsEditorInput(configurationTarget: ConfigurationTarget): DefaultPreferencesEditorInput {
switch (configurationTarget) {
case ConfigurationTarget.USER:
if (!this.defaultSettingsEditorInputForUser) {
this.defaultSettingsEditorInputForUser = this._register(this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.defaultSettingsResource));
}
return this.defaultSettingsEditorInputForUser;
case ConfigurationTarget.WORKSPACE:
if (!this.defaultSettingsEditorInputForWorkspace) {
this.defaultSettingsEditorInputForWorkspace = this._register(this.instantiationService.createInstance(DefaultPreferencesEditorInput, this.defaultSettingsResource));
}
return this.defaultSettingsEditorInputForWorkspace;
}
}
private openSideBySideEditor(leftHandDefaultInput: EditorInput, editableResource: URI, defaultEditableContents: string): TPromise<void> {
// Create as needed and open in editor
return this.createIfNotExists(editableResource, defaultEditableContents).then(() => {
return this.editorService.createInput({ resource: editableResource }).then(typedRightHandEditableInput => {
const sideBySideInput = new SideBySideEditorInput(typedRightHandEditableInput.getName(), typedRightHandEditableInput.getDescription(), leftHandDefaultInput, <EditorInput>typedRightHandEditableInput);
this.editorService.openEditor(sideBySideInput, { pinned: true });
return;
});
});
}
private openTwoEditors(leftHandDefault: URI, editableResource: URI, defaultEditableContents: string): TPromise<void> {
// Create as needed and open in editor
return this.createIfNotExists(editableResource, defaultEditableContents).then(() => {
@@ -255,6 +246,14 @@ export class PreferencesService extends Disposable implements IPreferencesServic
});
}
private getSettingsConfigurationTarget(preferencesEditorInput: PreferencesEditorInput): ConfigurationTarget {
if (preferencesEditorInput) {
const resource = toResource(preferencesEditorInput.master);
return resource.toString() === this.userSettingsResource.toString() ? ConfigurationTarget.USER : ConfigurationTarget.WORKSPACE;
}
return ConfigurationTarget.USER;
}
private fetchMostCommonlyUsedSettings(): TPromise<string[]> {
return TPromise.wrap([
'editor.fontSize',
@@ -5,7 +5,6 @@
import { localize } from 'vs/nls';
import * as DOM from 'vs/base/browser/dom';
import { Dimension } from 'vs/base/browser/builder';
import { Widget } from 'vs/base/browser/ui/widget';
import Event, { Emitter } from 'vs/base/common/event';
import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
@@ -17,6 +16,8 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { IContextViewService, IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { ISettingsGroup } from 'vs/workbench/parts/preferences/common/preferences';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
export class SettingsGroupTitleWidget extends Widget implements IViewZone {
@@ -176,11 +177,51 @@ export class SettingsGroupTitleWidget extends Widget implements IViewZone {
}
}
export class DefaultSettingsHeaderWidget extends Widget {
export class SettingsTabsWidget extends Widget {
private userSettingsTab: HTMLElement;
private workspaceSettingsTab: HTMLElement;
private _onSwitch: Emitter<void> = new Emitter<void>();
public readonly onSwitch: Event<void> = this._onSwitch.event;
constructor(parent: HTMLElement, @IWorkspaceContextService private contextService: IWorkspaceContextService, ) {
super();
this.create(parent);
}
private create(parent: HTMLElement): void {
const settingsTabsWidget = DOM.append(parent, DOM.$('.settings-tabs-widget'));
this.userSettingsTab = DOM.append(settingsTabsWidget, DOM.$('.settings-tab'));
DOM.append(this.userSettingsTab, DOM.$('')).textContent = localize('userSettings', "User Settings");
this.onclick(this.userSettingsTab, () => this.onClick(this.userSettingsTab));
this.workspaceSettingsTab = DOM.append(settingsTabsWidget, DOM.$('.settings-tab'));
DOM.append(this.workspaceSettingsTab, DOM.$('')).textContent = localize('workspaceSettings', "Workspace Settings");
if (!this.contextService.hasWorkspace()) {
DOM.addClass(this.workspaceSettingsTab, 'disabled');
} else {
this.onclick(this.workspaceSettingsTab, () => this.onClick(this.workspaceSettingsTab));
}
}
public show(configurationTarget: ConfigurationTarget): void {
DOM.toggleClass(this.userSettingsTab, 'active', ConfigurationTarget.USER === configurationTarget);
DOM.toggleClass(this.workspaceSettingsTab, 'active', ConfigurationTarget.WORKSPACE === configurationTarget);
}
private onClick(element: HTMLElement): void {
if (!DOM.hasClass(element, 'active')) {
this._onSwitch.fire();
}
}
}
export class SearchWidget extends Widget {
public domNode: HTMLElement;
private headerContainer: HTMLElement;
private countElement: HTMLElement;
private searchContainer: HTMLElement;
private inputBox: InputBox;
@@ -201,40 +242,38 @@ export class DefaultSettingsHeaderWidget extends Widget {
private create(parent: HTMLElement) {
this.domNode = DOM.append(parent, DOM.$('div.settings-header-widget'));
this.headerContainer = DOM.append(this.domNode, DOM.$('div.settings-header-container'));
const titleContainer = DOM.append(this.headerContainer, DOM.$('div.settings-title-container'));
this.createInfoContainer(DOM.append(titleContainer, DOM.$('div.settings-info-container')));
this.createSearchContainer(DOM.append(this.domNode, DOM.$('div.settings-search-container')));
}
private createInfoContainer(infoContainer: HTMLElement) {
DOM.append(infoContainer, DOM.$('span.title-label')).textContent = localize('defaultSettingsTitle', "Default Settings");
DOM.append(infoContainer, DOM.$('span')).textContent = localize('defaultSettingsInfo', " - Overwrite these by placing them into your settings file to the right");
this.countElement = DOM.append(this.domNode, DOM.$('.settings-count-widget'));
}
private createSearchContainer(searchContainer: HTMLElement) {
this.searchContainer = searchContainer;
const searchInput = DOM.append(this.searchContainer, DOM.$('div.settings-search-input'));
this.inputBox = this._register(new InputBox(searchInput, this.contextViewService, {
ariaLabel: localize('SearchSettingsWidget.AriaLabel', "Search default settings"),
placeholder: localize('SearchSettingsWidget.Placeholder', "Search Default Settings")
ariaLabel: localize('SearchSettingsWidget.AriaLabel', "Search settings"),
placeholder: localize('SearchSettingsWidget.Placeholder', "Search Settings")
}));
this.inputBox.onDidChange(value => this._onDidChange.fire(value));
this.onkeyup(this.inputBox.inputElement, (e) => this._onKeyUp(e));
}
public showMessage(message: string, count: number): void {
this.countElement.textContent = message;
DOM.toggleClass(this.countElement, 'no-results', count === 0);
}
public focus() {
this.inputBox.focus();
}
public layout(dimension: Dimension): void {
this.inputBox.width = dimension.width - 62;
}
public clear() {
this.inputBox.value = '';
}
public value(): string {
return this.inputBox.value;
}
private _onKeyUp(keyboardEvent: IKeyboardEvent): void {
let handled = false;
switch (keyboardEvent.keyCode) {
@@ -300,55 +339,6 @@ export class FloatingClickWidget extends Widget implements IOverlayWidget {
}
}
export class SettingsCountWidget extends Widget implements IOverlayWidget {
private _domNode: HTMLElement;
constructor(private editor: ICodeEditor, private total: number
) {
super();
}
public render() {
this._domNode = DOM.$('.settings-count-widget');
this.editor.addOverlayWidget(this);
}
public show(count: number) {
if (count === this.total) {
DOM.removeClass(this._domNode, 'show');
} else {
if (count === 0) {
this._domNode.textContent = localize('noSettings', "No settings found");
DOM.addClass(this._domNode, 'no-results');
} else {
this._domNode.textContent = localize('showCount', "Showing {0} of {1} Settings", count, this.total);
DOM.removeClass(this._domNode, 'no-results');
}
DOM.addClass(this._domNode, 'show');
}
}
public dispose(): void {
this.editor.removeOverlayWidget(this);
super.dispose();
}
public getId(): string {
return 'editor.overlayWidget.settingsCountWidget';
}
public getDomNode(): HTMLElement {
return this._domNode;
}
public getPosition(): IOverlayWidgetPosition {
return {
preference: null
};
}
}
export class EditPreferenceWidget<T> extends Widget implements IOverlayWidget {
private static counter: number = 1;
@@ -61,11 +61,15 @@ export interface IPreferencesService {
_serviceBrand: any;
defaultSettingsResource: URI;
userSettingsResource: URI;
workspaceSettingsResource: URI;
defaultKeybindingsResource: URI;
createDefaultPreferencesEditorModel(uri: URI): TPromise<IPreferencesEditorModel>;
resolvePreferencesEditorModel(uri: URI): TPromise<IPreferencesEditorModel>;
openSettings(): TPromise<void>;
switchSettings(): TPromise<void>;
openGlobalSettings(): TPromise<void>;
openWorkspaceSettings(): TPromise<void>;
openGlobalKeybindingSettings(): TPromise<void>;
@@ -459,7 +459,7 @@ export class DefaultSettingsEditorModel extends AbstractSettingsModel implements
return <ISettingsGroup>{
id: 'mostCommonlyUsed',
range: null,
title: nls.localize('commonlyUsed', "Most Commonly Used"),
title: nls.localize('commonlyUsed', "Commonly Used"),
titleRange: null,
sections: [
{