mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-08 17:19:48 +01:00
Settings editor - load settings in pages for much better perf #56296
This commit is contained in:
@@ -673,7 +673,7 @@ export class TreeView extends HeightMap {
|
||||
}
|
||||
|
||||
public getLastVisibleElement(): any {
|
||||
const item = this.itemAtIndex(this.indexAt(this.lastRenderTop + this.lastRenderHeight));
|
||||
const item = this.itemAtIndex(this.indexAt(this.lastRenderTop + this.lastRenderHeight - 1));
|
||||
return item && item.model.getElement();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ import { SuggestEnabledInput } from 'vs/workbench/parts/codeEditor/browser/sugge
|
||||
import { PreferencesEditor } from 'vs/workbench/parts/preferences/browser/preferencesEditor';
|
||||
import { SettingsTarget, SettingsTargetsWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets';
|
||||
import { commonlyUsedData, tocData } from 'vs/workbench/parts/preferences/browser/settingsLayout';
|
||||
import { resolveExtensionsSettings, resolveSettingsTree, SettingsRenderer, SettingsTree } from 'vs/workbench/parts/preferences/browser/settingsTree';
|
||||
import { ISettingsEditorViewState, MODIFIED_SETTING_TAG, ONLINE_SERVICES_SETTING_TAG, SearchResultIdx, SearchResultModel, SettingsTreeGroupElement, SettingsTreeModel, SettingsTreeSettingElement, countSettingGroupChildrenWithPredicate } from 'vs/workbench/parts/preferences/browser/settingsTreeModels';
|
||||
import { resolveExtensionsSettings, resolveSettingsTree, SettingsRenderer, SettingsTree, SimplePagedDataSource, SettingsDataSource } from 'vs/workbench/parts/preferences/browser/settingsTree';
|
||||
import { ISettingsEditorViewState, MODIFIED_SETTING_TAG, ONLINE_SERVICES_SETTING_TAG, SearchResultIdx, SearchResultModel, SettingsTreeGroupElement, SettingsTreeModel, countSettingGroupChildrenWithPredicate, SettingsTreeSettingElement } from 'vs/workbench/parts/preferences/browser/settingsTreeModels';
|
||||
import { TOCRenderer, TOCTree, TOCTreeModel } from 'vs/workbench/parts/preferences/browser/tocTree';
|
||||
import { CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, IPreferencesSearchService, ISearchProvider } from 'vs/workbench/parts/preferences/common/preferences';
|
||||
import { IEditorGroup } from 'vs/workbench/services/group/common/editorGroupsService';
|
||||
@@ -71,6 +71,7 @@ export class SettingsEditor2 extends BaseEditor {
|
||||
private settingsTreeContainer: HTMLElement;
|
||||
private settingsTree: Tree;
|
||||
private settingsTreeRenderer: SettingsRenderer;
|
||||
private settingsTreeDataSource: SimplePagedDataSource;
|
||||
private tocTreeModel: TOCTreeModel;
|
||||
private settingsTreeModel: SettingsTreeModel;
|
||||
private noResultsMessage: HTMLElement;
|
||||
@@ -426,14 +427,19 @@ export class SettingsEditor2 extends BaseEditor {
|
||||
}));
|
||||
|
||||
this._register(this.tocTree.onDidChangeFocus(e => {
|
||||
const element = e.focus;
|
||||
const element: SettingsTreeGroupElement = e.focus;
|
||||
if (this.searchResultModel) {
|
||||
this.viewState.filterToCategory = element;
|
||||
this.renderTree();
|
||||
}
|
||||
|
||||
if (element && (!e.payload || !e.payload.fromScroll)) {
|
||||
this.settingsTree.reveal(element, 0);
|
||||
let refreshP = TPromise.wrap(null);
|
||||
if (this.settingsTreeDataSource.pageTo(element.index)) {
|
||||
refreshP = this.renderTree();
|
||||
}
|
||||
|
||||
refreshP.then(() => this.settingsTree.reveal(element, 0));
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -463,11 +469,15 @@ export class SettingsEditor2 extends BaseEditor {
|
||||
this.settingsTree.reveal(element);
|
||||
}));
|
||||
|
||||
this.settingsTreeDataSource = this.instantiationService.createInstance(SimplePagedDataSource,
|
||||
this.instantiationService.createInstance(SettingsDataSource, this.viewState));
|
||||
|
||||
this.settingsTree = this._register(this.instantiationService.createInstance(SettingsTree,
|
||||
this.settingsTreeContainer,
|
||||
this.viewState,
|
||||
{
|
||||
renderer: this.settingsTreeRenderer
|
||||
renderer: this.settingsTreeRenderer,
|
||||
dataSource: this.settingsTreeDataSource
|
||||
}));
|
||||
this.settingsTree.getHTMLElement().attributes.removeNamedItem('tabindex');
|
||||
|
||||
@@ -516,6 +526,8 @@ export class SettingsEditor2 extends BaseEditor {
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateTreePagingByScroll();
|
||||
|
||||
const elementToSync = this.settingsTree.getFirstVisibleElement();
|
||||
const element = elementToSync instanceof SettingsTreeSettingElement ? elementToSync.parent :
|
||||
elementToSync instanceof SettingsTreeGroupElement ? elementToSync :
|
||||
@@ -536,6 +548,13 @@ export class SettingsEditor2 extends BaseEditor {
|
||||
}
|
||||
}
|
||||
|
||||
private updateTreePagingByScroll(): void {
|
||||
const lastVisibleElement = this.settingsTree.getLastVisibleElement();
|
||||
if (lastVisibleElement && this.settingsTreeDataSource.pageTo(lastVisibleElement.index)) {
|
||||
this.renderTree();
|
||||
}
|
||||
}
|
||||
|
||||
private updateChangedSetting(key: string, value: any): TPromise<void> {
|
||||
// ConfigurationService displays the error if this fails.
|
||||
// Force a render afterwards because onDidConfigurationUpdate doesn't fire if the update doesn't result in an effective setting value change
|
||||
|
||||
@@ -39,7 +39,7 @@ import { editorBackground, errorForeground, focusBorder, foreground, inputValida
|
||||
import { attachButtonStyler, attachInputBoxStyler, attachSelectBoxStyler, attachStyler } from 'vs/platform/theme/common/styler';
|
||||
import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { ITOCEntry } from 'vs/workbench/parts/preferences/browser/settingsLayout';
|
||||
import { ISettingsEditorViewState, isExcludeSetting, SettingsTreeElement, SettingsTreeGroupElement, SettingsTreeNewExtensionsElement, SettingsTreeSettingElement, settingKeyToDisplayFormat } from 'vs/workbench/parts/preferences/browser/settingsTreeModels';
|
||||
import { ISettingsEditorViewState, isExcludeSetting, SettingsTreeElement, SettingsTreeGroupElement, SettingsTreeNewExtensionsElement, settingKeyToDisplayFormat, SettingsTreeSettingElement } from 'vs/workbench/parts/preferences/browser/settingsTreeModels';
|
||||
import { ExcludeSettingWidget, IExcludeDataItem, settingsHeaderForeground, settingsNumberInputBackground, settingsNumberInputBorder, settingsNumberInputForeground, settingsSelectBackground, settingsSelectBorder, settingsSelectListBorder, settingsSelectForeground, settingsTextInputBackground, settingsTextInputBorder, settingsTextInputForeground } from 'vs/workbench/parts/preferences/browser/settingsWidgets';
|
||||
import { ISetting, ISettingsGroup } from 'vs/workbench/services/preferences/common/preferences';
|
||||
|
||||
@@ -206,6 +206,58 @@ export class SettingsDataSource implements IDataSource {
|
||||
}
|
||||
}
|
||||
|
||||
export class SimplePagedDataSource implements IDataSource {
|
||||
private static readonly SETTINGS_PER_PAGE = 30;
|
||||
|
||||
private loadedToIndex: number;
|
||||
|
||||
constructor(private realDataSource: IDataSource) {
|
||||
this.loadedToIndex = SimplePagedDataSource.SETTINGS_PER_PAGE * 2;
|
||||
}
|
||||
|
||||
pageTo(index: number): boolean {
|
||||
if (index > this.loadedToIndex - SimplePagedDataSource.SETTINGS_PER_PAGE) {
|
||||
this.loadedToIndex = (Math.ceil(index / SimplePagedDataSource.SETTINGS_PER_PAGE) + 1) * SimplePagedDataSource.SETTINGS_PER_PAGE;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
getId(tree: ITree, element: any): string {
|
||||
return this.realDataSource.getId(tree, element);
|
||||
}
|
||||
|
||||
hasChildren(tree: ITree, element: any): boolean {
|
||||
return this.realDataSource.hasChildren(tree, element);
|
||||
}
|
||||
|
||||
getChildren(tree: ITree, element: SettingsTreeGroupElement): TPromise<any> {
|
||||
return this.realDataSource.getChildren(tree, element).then(realChildren => {
|
||||
return this._getChildren(realChildren);
|
||||
});
|
||||
}
|
||||
|
||||
_getChildren(realChildren: SettingsTreeElement[]): any[] {
|
||||
const lastChild = realChildren[realChildren.length - 1];
|
||||
if (lastChild && lastChild.index > this.loadedToIndex) {
|
||||
return realChildren.filter(child => {
|
||||
return child.index < this.loadedToIndex;
|
||||
});
|
||||
} else {
|
||||
return realChildren;
|
||||
}
|
||||
}
|
||||
|
||||
getParent(tree: ITree, element: any): TPromise<any> {
|
||||
return this.realDataSource.getParent(tree, element);
|
||||
}
|
||||
|
||||
shouldAutoexpand(tree: ITree, element: any): boolean {
|
||||
return this.realDataSource.shouldAutoexpand(tree, element);
|
||||
}
|
||||
}
|
||||
|
||||
interface IDisposableTemplate {
|
||||
toDispose: IDisposable[];
|
||||
}
|
||||
@@ -1374,7 +1426,6 @@ export class SettingsTree extends NonExpandableOrSelectableTree {
|
||||
|
||||
const controller = instantiationService.createInstance(SettingsTreeController);
|
||||
const fullConfiguration = <ITreeConfiguration>{
|
||||
dataSource: instantiationService.createInstance(SettingsDataSource, viewState),
|
||||
controller,
|
||||
accessibilityProvider: instantiationService.createInstance(SettingsAccessibilityProvider),
|
||||
filter: instantiationService.createInstance(SettingsTreeFilter, viewState),
|
||||
|
||||
@@ -25,6 +25,11 @@ export interface ISettingsEditorViewState {
|
||||
export abstract class SettingsTreeElement {
|
||||
id: string;
|
||||
parent: SettingsTreeGroupElement;
|
||||
|
||||
/**
|
||||
* Index assigned in display order, used for paging.
|
||||
*/
|
||||
index: number;
|
||||
}
|
||||
|
||||
export class SettingsTreeGroupElement extends SettingsTreeElement {
|
||||
@@ -42,8 +47,8 @@ export class SettingsTreeNewExtensionsElement extends SettingsTreeElement {
|
||||
export class SettingsTreeSettingElement extends SettingsTreeElement {
|
||||
setting: ISetting;
|
||||
|
||||
_displayCategory: string;
|
||||
_displayLabel: string;
|
||||
private _displayCategory: string;
|
||||
private _displayLabel: string;
|
||||
|
||||
/**
|
||||
* scopeValue || defaultValue, for rendering convenience.
|
||||
@@ -70,8 +75,9 @@ export class SettingsTreeSettingElement extends SettingsTreeElement {
|
||||
description: string;
|
||||
valueType: 'enum' | 'string' | 'integer' | 'number' | 'boolean' | 'exclude' | 'complex' | 'nullable-integer' | 'nullable-number';
|
||||
|
||||
constructor(setting: ISetting, parent: SettingsTreeGroupElement, inspectResult: IInspectResult) {
|
||||
constructor(setting: ISetting, parent: SettingsTreeGroupElement, index: number, inspectResult: IInspectResult) {
|
||||
super();
|
||||
this.index = index;
|
||||
this.setting = setting;
|
||||
this.parent = parent;
|
||||
this.id = sanitizeId(parent.id + '_' + setting.key);
|
||||
@@ -193,7 +199,7 @@ export function countSettingGroupChildrenWithPredicate(tree: SettingsTreeGroupEl
|
||||
|
||||
export class SettingsTreeModel {
|
||||
protected _root: SettingsTreeGroupElement;
|
||||
private _treeElementsById = new Map<string, SettingsTreeElement>();
|
||||
protected _treeElementsById = new Map<string, SettingsTreeElement>();
|
||||
private _treeElementsBySettingName = new Map<string, SettingsTreeSettingElement[]>();
|
||||
private _tocRoot: ITOCEntry;
|
||||
|
||||
@@ -243,6 +249,8 @@ export class SettingsTreeModel {
|
||||
|
||||
private createSettingsTreeGroupElement(tocEntry: ITOCEntry, parent?: SettingsTreeGroupElement): SettingsTreeGroupElement {
|
||||
const element = new SettingsTreeGroupElement();
|
||||
const index = this._treeElementsById.size;
|
||||
element.index = index;
|
||||
element.id = tocEntry.id;
|
||||
element.label = tocEntry.label;
|
||||
element.parent = parent;
|
||||
@@ -273,8 +281,9 @@ export class SettingsTreeModel {
|
||||
}
|
||||
|
||||
private createSettingsTreeSettingElement(setting: ISetting, parent: SettingsTreeGroupElement): SettingsTreeSettingElement {
|
||||
const index = this._treeElementsById.size;
|
||||
const inspectResult = inspectSetting(setting.key, this._viewState.settingsTarget, this._configurationService);
|
||||
const element = new SettingsTreeSettingElement(setting, parent, inspectResult);
|
||||
const element = new SettingsTreeSettingElement(setting, parent, index, inspectResult);
|
||||
this._treeElementsById.set(element.id, element);
|
||||
|
||||
const nameElements = this._treeElementsBySettingName.get(setting.key) || [];
|
||||
@@ -449,8 +458,11 @@ export class SearchResultModel extends SettingsTreeModel {
|
||||
|
||||
if (this.newExtensionSearchResults && this.newExtensionSearchResults.filterMatches.length) {
|
||||
const newExtElement = new SettingsTreeNewExtensionsElement();
|
||||
newExtElement.index = this._treeElementsById.size;
|
||||
newExtElement.parent = this._root;
|
||||
newExtElement.id = 'newExtensions';
|
||||
this._treeElementsById.set(newExtElement.id, newExtElement);
|
||||
|
||||
const resultExtensionIds = this.newExtensionSearchResults.filterMatches
|
||||
.map(result => (<IExtensionSetting>result.setting))
|
||||
.filter(setting => setting.extensionName && setting.extensionPublisher)
|
||||
|
||||
Reference in New Issue
Block a user