提交 45c32dc9 编写于 作者: R Rob Lourens

Settings editor as tree - expand/collapse settings with long descriptions

上级 7299d524
......@@ -109,7 +109,6 @@
.settings-editor > .settings-body > .settings-tree-container .setting-item {
cursor: default;
white-space: normal;
padding: 3px 0px;
display: flex;
height: 100%;
}
......@@ -164,14 +163,18 @@
white-space: pre-wrap;
}
/* .settings-editor > .settings-body > .settings-tree-container .setting-item.is-expanded .setting-item-description,
.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-item-measure-helper .setting-item-description {
.settings-editor > .settings-body > .settings-tree-container .setting-measure-container.monaco-tree-row {
padding-left: 15px;
}
.settings-editor > .settings-body > .settings-tree-container .setting-item.is-expanded .setting-item-description,
.settings-editor > .settings-body > .settings-tree-container .setting-item.setting-measure-helper .setting-item-description {
height: initial;
}
.settings-editor > .settings-body > .settings-tree-container .setting-item.is-expandable .setting-item-description {
cursor: pointer;
} */
}
.settings-editor > .settings-body > .settings-tree-container .setting-item .setting-item-value {
display: flex;
......@@ -219,6 +222,19 @@
visibility: hidden;
}
.settings-editor > .settings-body > .settings-tree-container .setting-item .expand-indicator {
visibility: hidden;
position: absolute;
bottom: 3px;
width: calc(100% - 190px);
text-align: center;
opacity: .5;
}
.settings-editor > .settings-body > .settings-tree-container .setting-item.is-expandable .expand-indicator {
visibility: visible;
}
.vs-dark .settings-editor > .settings-body > .settings-tree-container .setting-item .setting-item-value > .setting-reset-button.monaco-button {
background: url("clean-dark.svg") center center no-repeat;
}
......
......@@ -24,7 +24,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { EditorOptions } from 'vs/workbench/common/editor';
import { SearchWidget, SettingsTarget, SettingsTargetsWidget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets';
import { ISettingsEditorViewState, SearchResultIdx, SearchResultModel, SettingsAccessibilityProvider, SettingsDataSource, SettingsRenderer, SettingsTreeController, SettingsTreeFilter, TreeElement, TreeItemType } from 'vs/workbench/parts/preferences/browser/settingsTree';
import { ISettingsEditorViewState, SearchResultIdx, SearchResultModel, SettingsAccessibilityProvider, SettingsDataSource, SettingsRenderer, SettingsTreeController, SettingsTreeFilter, TreeElement } from 'vs/workbench/parts/preferences/browser/settingsTree';
import { IPreferencesSearchService, ISearchProvider } from 'vs/workbench/parts/preferences/common/preferences';
import { IPreferencesService, ISearchResult, ISettingsEditorModel } from 'vs/workbench/services/preferences/common/preferences';
import { SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput';
......@@ -55,7 +55,7 @@ export class SettingsEditor2 extends BaseEditor {
private pendingSettingModifiedReport: { key: string, value: any };
private focusedElement: TreeElement;
private selectedElement: TreeElement;
private viewState: ISettingsEditorViewState;
private searchResultModel: SearchResultModel;
......@@ -185,8 +185,8 @@ export class SettingsEditor2 extends BaseEditor {
private createList(parent: HTMLElement): void {
this.settingsTreeContainer = DOM.append(parent, $('.settings-tree-container'));
this.treeDataSource = this.instantiationService.createInstance(SettingsDataSource, { settingsTarget: ConfigurationTarget.USER });
const renderer = this.instantiationService.createInstance(SettingsRenderer, {});
this.treeDataSource = this.instantiationService.createInstance(SettingsDataSource, this.viewState);
const renderer = this.instantiationService.createInstance(SettingsRenderer, this.viewState, this.settingsTreeContainer);
this._register(renderer.onDidChangeSetting(e => this.onDidChangeSetting(e.key, e.value)));
this._register(renderer.onDidClickButton(e => this.onDidClickShowAllSettings()));
......@@ -206,17 +206,15 @@ export class SettingsEditor2 extends BaseEditor {
});
this.settingsTree.onDidChangeFocus(e => {
if (this.focusedElement && this.focusedElement.type === TreeItemType.setting) {
const row = document.getElementById(this.focusedElement.id);
setTabindexes(row, -1);
if (this.selectedElement) {
this.settingsTree.refresh(this.selectedElement);
}
this.focusedElement = e.focus;
if (this.focusedElement && this.focusedElement.type === TreeItemType.setting) {
const row = document.getElementById(this.focusedElement.id);
setTabindexes(row, 0);
if (e.focus) {
this.settingsTree.refresh(e.focus);
}
this.selectedElement = e.focus;
});
}
......@@ -467,57 +465,3 @@ export class SettingsEditor2 extends BaseEditor {
this.settingsTree.layout(listHeight, 800);
}
}
function setTabindexes(element: HTMLElement, tabIndex: number): void {
const focusableElements = element.querySelectorAll('input, button, select, a');
for (let i = 0; focusableElements && i < focusableElements.length; i++) {
const element = focusableElements[i];
(<HTMLElement>element).tabIndex = tabIndex;
}
}
// class SettingItemDelegate implements IDelegate<ListEntry> {
// constructor(private measureContainer: HTMLElement) {
// }
// getHeight(entry: ListEntry) {
// if (entry.templateId === SETTINGS_GROUP_ENTRY_TEMPLATE_ID) {
// return 30;
// }
// if (entry.templateId === SETTINGS_ENTRY_TEMPLATE_ID) {
// if (entry.isExpanded) {
// return this.getDynamicHeight(entry);
// } else {
// return 68;
// }
// }
// if (entry.templateId === BUTTON_ROW_ENTRY_TEMPLATE) {
// return 60;
// }
// return 0;
// }
// getTemplateId(element: ListEntry) {
// return element.templateId;
// }
// private getDynamicHeight(entry: ISettingItemEntry): number {
// return measureSettingItemEntry(entry, this.measureContainer);
// }
// }
// function measureSettingItemEntry(entry: ISettingItemEntry, measureContainer: HTMLElement): number {
// const measureHelper = DOM.append(measureContainer, $('.setting-item-measure-helper.monaco-list-row'));
// const template = SettingItemRenderer.renderTemplate(measureHelper);
// SettingItemRenderer.renderElement(entry, 0, template);
// const height = measureHelper.offsetHeight;
// measureContainer.removeChild(measureHelper);
// return height;
// }
......@@ -23,6 +23,7 @@ import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant }
import { SettingsTarget } from 'vs/workbench/parts/preferences/browser/preferencesWidgets';
import { ISearchResult, ISetting, ISettingsGroup } from 'vs/workbench/services/preferences/common/preferences';
import { DefaultSettingsEditorModel } from 'vs/workbench/services/preferences/common/preferencesModels';
import { renderOcticons } from 'vs/base/browser/ui/octiconLabel/octiconLabel';
const $ = DOM.$;
......@@ -113,6 +114,8 @@ export class SettingsDataSource implements IDataSource {
id: `${group.id}_${setting.key}`,
setting,
isExpanded: false,
value: displayValue,
isConfigured,
overriddenScopeList,
......@@ -210,6 +213,7 @@ export interface ISettingItemTemplate extends IDisposableTemplate {
categoryElement: HTMLElement;
labelElement: HTMLElement;
descriptionElement: HTMLElement;
expandIndicatorElement: HTMLElement;
valueElement: HTMLElement;
overridesElement: HTMLElement;
}
......@@ -227,9 +231,9 @@ export interface IButtonRowTemplate extends IDisposableTemplate {
entry?: IButtonElement;
}
const SETTINGS_ENTRY_TEMPLATE_ID = 'settings.entry.template';
const SETTINGS_GROUP_ENTRY_TEMPLATE_ID = 'settings.group.template';
const BUTTON_ROW_ENTRY_TEMPLATE = 'settings.buttonRow.template';
const SETTINGS_ELEMENT_TEMPLATE_ID = 'settings.entry.template';
const SETTINGS_GROUP_ELEMENT_TEMPLATE_ID = 'settings.group.template';
const BUTTON_ROW_ELEMENT_TEMPLATE = 'settings.buttonRow.template';
export interface ISettingChangeEvent {
key: string;
......@@ -247,11 +251,16 @@ export class SettingsRenderer implements IRenderer {
private readonly _onDidOpenSettings: Emitter<void> = new Emitter<void>();
public readonly onDidOpenSettings: Event<void> = this._onDidOpenSettings.event;
private measureContainer: HTMLElement;
constructor(
private viewState: ISettingsEditorViewState,
_measureContainer: HTMLElement,
@IThemeService private themeService: IThemeService,
@IContextViewService private contextViewService: IContextViewService
) { }
) {
this.measureContainer = DOM.append(_measureContainer, $('.setting-measure-container.monaco-tree-row'));
}
getHeight(tree: ITree, element: TreeElement): number {
if (element.type === TreeItemType.groupTitle) {
......@@ -259,7 +268,12 @@ export class SettingsRenderer implements IRenderer {
}
if (element.type === TreeItemType.setting) {
return 68;
const isSelected = this.elementIsSelected(tree, element);
if (isSelected) {
return this.measureSettingElementHeight(tree, element);
} else {
return 68;
}
}
if (element.type === TreeItemType.buttonRow) {
......@@ -269,32 +283,43 @@ export class SettingsRenderer implements IRenderer {
return 0;
}
private measureSettingElementHeight(tree: ITree, element: ISettingElement): number {
const measureHelper = DOM.append(this.measureContainer, $('.setting-measure-helper'));
const template = this.renderSettingTemplate(measureHelper);
this.renderSettingElement(tree, element, template, true);
const height = measureHelper.offsetHeight;
this.measureContainer.removeChild(measureHelper);
return height;
}
getTemplateId(tree: ITree, element: TreeElement): string {
if (element.type === TreeItemType.groupTitle) {
return SETTINGS_GROUP_ENTRY_TEMPLATE_ID;
return SETTINGS_GROUP_ELEMENT_TEMPLATE_ID;
}
if (element.type === TreeItemType.buttonRow) {
return BUTTON_ROW_ENTRY_TEMPLATE;
return BUTTON_ROW_ELEMENT_TEMPLATE;
}
if (element.type === TreeItemType.setting) {
return SETTINGS_ENTRY_TEMPLATE_ID;
return SETTINGS_ELEMENT_TEMPLATE_ID;
}
return '';
}
renderTemplate(tree: ITree, templateId: string, container: HTMLElement) {
if (templateId === SETTINGS_GROUP_ENTRY_TEMPLATE_ID) {
if (templateId === SETTINGS_GROUP_ELEMENT_TEMPLATE_ID) {
return this.renderGroupTitleTemplate(container);
}
if (templateId === BUTTON_ROW_ENTRY_TEMPLATE) {
if (templateId === BUTTON_ROW_ELEMENT_TEMPLATE) {
return this.renderButtonRowTemplate(container);
}
if (templateId === SETTINGS_ENTRY_TEMPLATE_ID) {
if (templateId === SETTINGS_ELEMENT_TEMPLATE_ID) {
return this.renderSettingTemplate(container);
}
......@@ -347,6 +372,7 @@ export class SettingsRenderer implements IRenderer {
const labelElement = DOM.append(titleElement, $('span.setting-item-label'));
const overridesElement = DOM.append(titleElement, $('span.setting-item-overrides'));
const descriptionElement = DOM.append(leftElement, $('.setting-item-description'));
const expandIndicatorElement = DOM.append(leftElement, $('.expand-indicator'));
const valueElement = DOM.append(rightElement, $('.setting-item-value'));
......@@ -359,6 +385,7 @@ export class SettingsRenderer implements IRenderer {
categoryElement,
labelElement,
descriptionElement,
expandIndicatorElement,
valueElement,
overridesElement
};
......@@ -367,25 +394,33 @@ export class SettingsRenderer implements IRenderer {
}
renderElement(tree: ITree, element: TreeElement, templateId: string, template: any): void {
if (templateId === SETTINGS_ENTRY_TEMPLATE_ID) {
return this.renderSettingElement(<ISettingElement>element, template);
if (templateId === SETTINGS_ELEMENT_TEMPLATE_ID) {
return this.renderSettingElement(tree, <ISettingElement>element, template);
}
if (templateId === SETTINGS_GROUP_ENTRY_TEMPLATE_ID) {
if (templateId === SETTINGS_GROUP_ELEMENT_TEMPLATE_ID) {
(<IGroupTitleTemplate>template).labelElement.textContent = (<IGroupElement>element).group.title;
return;
}
if (templateId === BUTTON_ROW_ENTRY_TEMPLATE) {
if (templateId === BUTTON_ROW_ELEMENT_TEMPLATE) {
return this.renderButtonRowElement(<IButtonElement>element, template);
}
}
private renderSettingElement(element: ISettingElement, template: ISettingItemTemplate): void {
private elementIsSelected(tree: ITree, element: TreeElement): boolean {
const selection = tree.getFocus();
const selectedElement: TreeElement = selection;
return selectedElement && selectedElement.id === element.id;
}
private renderSettingElement(tree: ITree, element: ISettingElement, template: ISettingItemTemplate, measuring?: boolean): void {
const isSelected = this.elementIsSelected(tree, element);
const setting = element.setting;
template.context = element;
DOM.toggleClass(template.parent, 'is-configured', element.isConfigured);
DOM.toggleClass(template.parent, 'is-expanded', isSelected);
template.containerElement.id = element.id;
const titleTooltip = setting.key;
......@@ -398,9 +433,19 @@ export class SettingsRenderer implements IRenderer {
template.descriptionElement.textContent = element.description;
template.descriptionElement.title = element.description;
// const expandedHeight = measureSettingItemEntry(entry, that.measureContainer);
// entry.isExpandable = expandedHeight > 68;
// DOM.toggleClass(template.parent, 'is-expandable', entry.isExpandable);
if (!measuring) {
const expandedHeight = this.measureSettingElementHeight(tree, element);
const isExpandable = expandedHeight > 68;
DOM.toggleClass(template.parent, 'is-expandable', isExpandable);
if (isSelected) {
template.expandIndicatorElement.innerHTML = renderOcticons('$(chevron-up)');
} else if (isExpandable) {
template.expandIndicatorElement.innerHTML = renderOcticons('$(chevron-down)');
} else {
template.expandIndicatorElement.innerHTML = '';
}
}
this.renderValue(element, template);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册