Skip to content

Commit 1415112

Browse files
committed
list, tree: cleanup style application
related to microsoft#84715
1 parent 7c526f2 commit 1415112

6 files changed

Lines changed: 67 additions & 46 deletions

File tree

src/vs/base/browser/ui/list/listWidget.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -706,12 +706,20 @@ export interface IAccessibilityProvider<T> {
706706

707707
export class DefaultStyleController implements IStyleController {
708708

709-
constructor(private styleElement: HTMLStyleElement, private selectorSuffix?: string) { }
709+
constructor(private styleElement: HTMLStyleElement, private selectorSuffix: string) { }
710710

711711
style(styles: IListStyles): void {
712-
const suffix = this.selectorSuffix ? `.${this.selectorSuffix}` : '';
712+
const suffix = this.selectorSuffix && `.${this.selectorSuffix}`;
713713
const content: string[] = [];
714714

715+
if (styles.listBackground) {
716+
if (styles.listBackground.isOpaque()) {
717+
content.push(`.monaco-list${suffix} .monaco-list-rows { background: ${styles.listBackground}; }`);
718+
} else {
719+
console.warn(`List with id '${this.selectorSuffix}' was styled with a non-opaque background color. This will break sub-pixel antialiasing.`);
720+
}
721+
}
722+
715723
if (styles.listFocusBackground) {
716724
content.push(`.monaco-list${suffix}:focus .monaco-list-row.focused { background-color: ${styles.listFocusBackground}; }`);
717725
content.push(`.monaco-list${suffix}:focus .monaco-list-row.focused:hover { background-color: ${styles.listFocusBackground}; }`); // overwrite :hover style in this case!
@@ -815,7 +823,7 @@ export class DefaultStyleController implements IStyleController {
815823
}
816824
}
817825

818-
export interface IListOptions<T> extends IListStyles {
826+
export interface IListOptions<T> {
819827
readonly identityProvider?: IIdentityProvider<T>;
820828
readonly dnd?: IListDragAndDrop<T>;
821829
readonly enableKeyboardNavigation?: boolean;
@@ -828,7 +836,7 @@ export interface IListOptions<T> extends IListStyles {
828836
readonly multipleSelectionSupport?: boolean;
829837
readonly multipleSelectionController?: IMultipleSelectionController<T>;
830838
readonly openController?: IOpenController;
831-
readonly styleController?: IStyleController;
839+
readonly styleController?: (suffix: string) => IStyleController;
832840
readonly accessibilityProvider?: IAccessibilityProvider<T>;
833841

834842
// list view options
@@ -842,6 +850,7 @@ export interface IListOptions<T> extends IListStyles {
842850
}
843851

844852
export interface IListStyles {
853+
listBackground?: Color;
845854
listFocusBackground?: Color;
846855
listFocusForeground?: Color;
847856
listActiveSelectionBackground?: Color;
@@ -1103,7 +1112,6 @@ export class List<T> implements ISpliceable<T>, IDisposable {
11031112
private eventBufferer = new EventBufferer();
11041113
private view: ListView<T>;
11051114
private spliceable: ISpliceable<T>;
1106-
private styleElement: HTMLStyleElement;
11071115
private styleController: IStyleController;
11081116
private typeLabelController?: TypeLabelController<T>;
11091117

@@ -1210,9 +1218,12 @@ export class List<T> implements ISpliceable<T>, IDisposable {
12101218
this.view.domNode.setAttribute('role', _options.ariaRole);
12111219
}
12121220

1213-
this.styleElement = DOM.createStyleSheet(this.view.domNode);
1214-
1215-
this.styleController = _options.styleController || new DefaultStyleController(this.styleElement, this.view.domId);
1221+
if (_options.styleController) {
1222+
this.styleController = _options.styleController(this.view.domId);
1223+
} else {
1224+
const styleElement = DOM.createStyleSheet(this.view.domNode);
1225+
this.styleController = new DefaultStyleController(styleElement, this.view.domId);
1226+
}
12161227

12171228
this.spliceable = new CombinedSpliceable([
12181229
new TraitSpliceable(this.focus, this.view, _options.identityProvider),
@@ -1249,8 +1260,6 @@ export class List<T> implements ISpliceable<T>, IDisposable {
12491260
if (_options.ariaLabel) {
12501261
this.view.domNode.setAttribute('aria-label', localize('aria list', "{0}. Use the navigation keys to navigate.", _options.ariaLabel));
12511262
}
1252-
1253-
this.style(_options);
12541263
}
12551264

12561265
protected createMouseController(options: IListOptions<T>): MouseController<T> {

src/vs/platform/list/browser/listService.ts

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { IEditorOptions } from 'vs/platform/editor/common/editor';
2222
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
2323
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
2424
import { Registry } from 'vs/platform/registry/common/platform';
25-
import { attachListStyler, computeStyles, defaultListStyles } from 'vs/platform/theme/common/styler';
25+
import { attachListStyler, computeStyles, defaultListStyles, IColorMapping } from 'vs/platform/theme/common/styler';
2626
import { IThemeService } from 'vs/platform/theme/common/themeService';
2727
import { InputFocusedContextKey } from 'vs/platform/contextkey/common/contextkeys';
2828
import { ObjectTree, IObjectTreeOptions, ICompressibleTreeRenderer, CompressibleObjectTree, ICompressibleObjectTreeOptions } from 'vs/base/browser/ui/tree/objectTree';
@@ -259,7 +259,7 @@ export class WorkbenchList<T> extends List<T> {
259259
super(user, container, delegate, renderers,
260260
{
261261
keyboardSupport: false,
262-
styleController: new DefaultStyleController(getSharedListStyleSheet()),
262+
styleController: id => new DefaultStyleController(getSharedListStyleSheet(), id),
263263
...computeStyles(themeService.getTheme(), defaultListStyles),
264264
...workbenchListOptions,
265265
horizontalScrolling
@@ -340,7 +340,7 @@ export class WorkbenchPagedList<T> extends PagedList<T> {
340340
super(user, container, delegate, renderers,
341341
{
342342
keyboardSupport: false,
343-
styleController: new DefaultStyleController(getSharedListStyleSheet()),
343+
styleController: id => new DefaultStyleController(getSharedListStyleSheet(), id),
344344
...computeStyles(themeService.getTheme(), defaultListStyles),
345345
...workbenchListOptions,
346346
horizontalScrolling
@@ -777,6 +777,10 @@ function createKeyboardNavigationEventFilter(container: HTMLElement, keybindingS
777777
};
778778
}
779779

780+
export interface IWorkbenchObjectTreeOptions<T, TFilterData> extends IObjectTreeOptions<T, TFilterData> {
781+
readonly overrideStyles?: IColorMapping;
782+
}
783+
780784
export class WorkbenchObjectTree<T extends NonNullable<any>, TFilterData = void> extends ObjectTree<T, TFilterData> {
781785

782786
private internals: WorkbenchTreeInternals<any, T, TFilterData>;
@@ -788,22 +792,26 @@ export class WorkbenchObjectTree<T extends NonNullable<any>, TFilterData = void>
788792
container: HTMLElement,
789793
delegate: IListVirtualDelegate<T>,
790794
renderers: ITreeRenderer<T, TFilterData, any>[],
791-
options: IObjectTreeOptions<T, TFilterData>,
795+
options: IWorkbenchObjectTreeOptions<T, TFilterData>,
792796
@IContextKeyService contextKeyService: IContextKeyService,
793797
@IListService listService: IListService,
794798
@IThemeService themeService: IThemeService,
795799
@IConfigurationService configurationService: IConfigurationService,
796800
@IKeybindingService keybindingService: IKeybindingService,
797801
@IAccessibilityService accessibilityService: IAccessibilityService
798802
) {
799-
const { options: treeOptions, getAutomaticKeyboardNavigation, disposable } = workbenchTreeDataPreamble(container, options, contextKeyService, themeService, configurationService, keybindingService, accessibilityService);
803+
const { options: treeOptions, getAutomaticKeyboardNavigation, disposable } = workbenchTreeDataPreamble(container, options, contextKeyService, configurationService, keybindingService, accessibilityService);
800804
super(user, container, delegate, renderers, treeOptions);
801805
this.disposables.add(disposable);
802-
this.internals = new WorkbenchTreeInternals(this, treeOptions, getAutomaticKeyboardNavigation, contextKeyService, listService, themeService, configurationService, accessibilityService);
806+
this.internals = new WorkbenchTreeInternals(this, treeOptions, getAutomaticKeyboardNavigation, options.overrideStyles, contextKeyService, listService, themeService, configurationService, accessibilityService);
803807
this.disposables.add(this.internals);
804808
}
805809
}
806810

811+
export interface IWorkbenchCompressibleObjectTreeOptions<T, TFilterData> extends ICompressibleObjectTreeOptions<T, TFilterData> {
812+
readonly overrideStyles?: IColorMapping;
813+
}
814+
807815
export class WorkbenchCompressibleObjectTree<T extends NonNullable<any>, TFilterData = void> extends CompressibleObjectTree<T, TFilterData> {
808816

809817
private internals: WorkbenchTreeInternals<any, T, TFilterData>;
@@ -815,22 +823,26 @@ export class WorkbenchCompressibleObjectTree<T extends NonNullable<any>, TFilter
815823
container: HTMLElement,
816824
delegate: IListVirtualDelegate<T>,
817825
renderers: ICompressibleTreeRenderer<T, TFilterData, any>[],
818-
options: ICompressibleObjectTreeOptions<T, TFilterData>,
826+
options: IWorkbenchCompressibleObjectTreeOptions<T, TFilterData>,
819827
@IContextKeyService contextKeyService: IContextKeyService,
820828
@IListService listService: IListService,
821829
@IThemeService themeService: IThemeService,
822830
@IConfigurationService configurationService: IConfigurationService,
823831
@IKeybindingService keybindingService: IKeybindingService,
824832
@IAccessibilityService accessibilityService: IAccessibilityService
825833
) {
826-
const { options: treeOptions, getAutomaticKeyboardNavigation, disposable } = workbenchTreeDataPreamble(container, options, contextKeyService, themeService, configurationService, keybindingService, accessibilityService);
834+
const { options: treeOptions, getAutomaticKeyboardNavigation, disposable } = workbenchTreeDataPreamble(container, options, contextKeyService, configurationService, keybindingService, accessibilityService);
827835
super(user, container, delegate, renderers, treeOptions);
828836
this.disposables.add(disposable);
829-
this.internals = new WorkbenchTreeInternals(this, treeOptions, getAutomaticKeyboardNavigation, contextKeyService, listService, themeService, configurationService, accessibilityService);
837+
this.internals = new WorkbenchTreeInternals(this, treeOptions, getAutomaticKeyboardNavigation, options.overrideStyles, contextKeyService, listService, themeService, configurationService, accessibilityService);
830838
this.disposables.add(this.internals);
831839
}
832840
}
833841

842+
export interface IWorkbenchDataTreeOptions<T, TFilterData> extends IDataTreeOptions<T, TFilterData> {
843+
readonly overrideStyles?: IColorMapping;
844+
}
845+
834846
export class WorkbenchDataTree<TInput, T, TFilterData = void> extends DataTree<TInput, T, TFilterData> {
835847

836848
private internals: WorkbenchTreeInternals<TInput, T, TFilterData>;
@@ -843,22 +855,26 @@ export class WorkbenchDataTree<TInput, T, TFilterData = void> extends DataTree<T
843855
delegate: IListVirtualDelegate<T>,
844856
renderers: ITreeRenderer<T, TFilterData, any>[],
845857
dataSource: IDataSource<TInput, T>,
846-
options: IDataTreeOptions<T, TFilterData>,
858+
options: IWorkbenchDataTreeOptions<T, TFilterData>,
847859
@IContextKeyService contextKeyService: IContextKeyService,
848860
@IListService listService: IListService,
849861
@IThemeService themeService: IThemeService,
850862
@IConfigurationService configurationService: IConfigurationService,
851863
@IKeybindingService keybindingService: IKeybindingService,
852864
@IAccessibilityService accessibilityService: IAccessibilityService
853865
) {
854-
const { options: treeOptions, getAutomaticKeyboardNavigation, disposable } = workbenchTreeDataPreamble(container, options, contextKeyService, themeService, configurationService, keybindingService, accessibilityService);
866+
const { options: treeOptions, getAutomaticKeyboardNavigation, disposable } = workbenchTreeDataPreamble(container, options, contextKeyService, configurationService, keybindingService, accessibilityService);
855867
super(user, container, delegate, renderers, dataSource, treeOptions);
856868
this.disposables.add(disposable);
857-
this.internals = new WorkbenchTreeInternals(this, treeOptions, getAutomaticKeyboardNavigation, contextKeyService, listService, themeService, configurationService, accessibilityService);
869+
this.internals = new WorkbenchTreeInternals(this, treeOptions, getAutomaticKeyboardNavigation, options.overrideStyles, contextKeyService, listService, themeService, configurationService, accessibilityService);
858870
this.disposables.add(this.internals);
859871
}
860872
}
861873

874+
export interface IWorkbenchAsyncDataTreeOptions<T, TFilterData> extends IAsyncDataTreeOptions<T, TFilterData> {
875+
readonly overrideStyles?: IColorMapping;
876+
}
877+
862878
export class WorkbenchAsyncDataTree<TInput, T, TFilterData = void> extends AsyncDataTree<TInput, T, TFilterData> {
863879

864880
private internals: WorkbenchTreeInternals<TInput, T, TFilterData>;
@@ -871,22 +887,26 @@ export class WorkbenchAsyncDataTree<TInput, T, TFilterData = void> extends Async
871887
delegate: IListVirtualDelegate<T>,
872888
renderers: ITreeRenderer<T, TFilterData, any>[],
873889
dataSource: IAsyncDataSource<TInput, T>,
874-
options: IAsyncDataTreeOptions<T, TFilterData>,
890+
options: IWorkbenchAsyncDataTreeOptions<T, TFilterData>,
875891
@IContextKeyService contextKeyService: IContextKeyService,
876892
@IListService listService: IListService,
877893
@IThemeService themeService: IThemeService,
878894
@IConfigurationService configurationService: IConfigurationService,
879895
@IKeybindingService keybindingService: IKeybindingService,
880896
@IAccessibilityService accessibilityService: IAccessibilityService
881897
) {
882-
const { options: treeOptions, getAutomaticKeyboardNavigation, disposable } = workbenchTreeDataPreamble(container, options, contextKeyService, themeService, configurationService, keybindingService, accessibilityService);
898+
const { options: treeOptions, getAutomaticKeyboardNavigation, disposable } = workbenchTreeDataPreamble(container, options, contextKeyService, configurationService, keybindingService, accessibilityService);
883899
super(user, container, delegate, renderers, dataSource, treeOptions);
884900
this.disposables.add(disposable);
885-
this.internals = new WorkbenchTreeInternals(this, treeOptions, getAutomaticKeyboardNavigation, contextKeyService, listService, themeService, configurationService, accessibilityService);
901+
this.internals = new WorkbenchTreeInternals(this, treeOptions, getAutomaticKeyboardNavigation, options.overrideStyles, contextKeyService, listService, themeService, configurationService, accessibilityService);
886902
this.disposables.add(this.internals);
887903
}
888904
}
889905

906+
export interface IWorkbenchCompressibleAsyncDataTreeOptions<T, TFilterData> extends ICompressibleAsyncDataTreeOptions<T, TFilterData> {
907+
readonly overrideStyles?: IColorMapping;
908+
}
909+
890910
export class WorkbenchCompressibleAsyncDataTree<TInput, T, TFilterData = void> extends CompressibleAsyncDataTree<TInput, T, TFilterData> {
891911

892912
private internals: WorkbenchTreeInternals<TInput, T, TFilterData>;
@@ -900,18 +920,18 @@ export class WorkbenchCompressibleAsyncDataTree<TInput, T, TFilterData = void> e
900920
compressionDelegate: ITreeCompressionDelegate<T>,
901921
renderers: ICompressibleTreeRenderer<T, TFilterData, any>[],
902922
dataSource: IAsyncDataSource<TInput, T>,
903-
options: ICompressibleAsyncDataTreeOptions<T, TFilterData>,
923+
options: IWorkbenchCompressibleAsyncDataTreeOptions<T, TFilterData>,
904924
@IContextKeyService contextKeyService: IContextKeyService,
905925
@IListService listService: IListService,
906926
@IThemeService themeService: IThemeService,
907927
@IConfigurationService configurationService: IConfigurationService,
908928
@IKeybindingService keybindingService: IKeybindingService,
909929
@IAccessibilityService accessibilityService: IAccessibilityService
910930
) {
911-
const { options: treeOptions, getAutomaticKeyboardNavigation, disposable } = workbenchTreeDataPreamble(container, options, contextKeyService, themeService, configurationService, keybindingService, accessibilityService);
931+
const { options: treeOptions, getAutomaticKeyboardNavigation, disposable } = workbenchTreeDataPreamble(container, options, contextKeyService, configurationService, keybindingService, accessibilityService);
912932
super(user, container, virtualDelegate, compressionDelegate, renderers, dataSource, treeOptions);
913933
this.disposables.add(disposable);
914-
this.internals = new WorkbenchTreeInternals(this, treeOptions, getAutomaticKeyboardNavigation, contextKeyService, listService, themeService, configurationService, accessibilityService);
934+
this.internals = new WorkbenchTreeInternals(this, treeOptions, getAutomaticKeyboardNavigation, options.overrideStyles, contextKeyService, listService, themeService, configurationService, accessibilityService);
915935
this.disposables.add(this.internals);
916936
}
917937
}
@@ -920,7 +940,6 @@ function workbenchTreeDataPreamble<T, TFilterData, TOptions extends IAbstractTre
920940
container: HTMLElement,
921941
options: TOptions,
922942
contextKeyService: IContextKeyService,
923-
themeService: IThemeService,
924943
configurationService: IConfigurationService,
925944
keybindingService: IKeybindingService,
926945
accessibilityService: IAccessibilityService,
@@ -956,8 +975,7 @@ function workbenchTreeDataPreamble<T, TFilterData, TOptions extends IAbstractTre
956975
options: {
957976
// ...options, // TODO@Joao why is this not splatted here?
958977
keyboardSupport: false,
959-
styleController: new DefaultStyleController(getSharedListStyleSheet()),
960-
...computeStyles(themeService.getTheme(), defaultListStyles),
978+
styleController: id => new DefaultStyleController(getSharedListStyleSheet(), id),
961979
...workbenchListOptions,
962980
indent: configurationService.getValue<number>(treeIndentKey),
963981
renderIndentGuides: configurationService.getValue<RenderIndentGuides>(treeRenderIndentGuidesKey),
@@ -986,6 +1004,7 @@ class WorkbenchTreeInternals<TInput, T, TFilterData> {
9861004
tree: WorkbenchObjectTree<T, TFilterData> | CompressibleObjectTree<T, TFilterData> | WorkbenchDataTree<TInput, T, TFilterData> | WorkbenchAsyncDataTree<TInput, T, TFilterData> | WorkbenchCompressibleAsyncDataTree<TInput, T, TFilterData>,
9871005
options: IAbstractTreeOptions<T, TFilterData> | IAsyncDataTreeOptions<T, TFilterData>,
9881006
getAutomaticKeyboardNavigation: () => boolean | undefined,
1007+
overrideStyles: IColorMapping | undefined,
9891008
@IContextKeyService contextKeyService: IContextKeyService,
9901009
@IListService listService: IListService,
9911010
@IThemeService themeService: IThemeService,
@@ -1017,7 +1036,7 @@ class WorkbenchTreeInternals<TInput, T, TFilterData> {
10171036
this.disposables.push(
10181037
this.contextKeyService,
10191038
(listService as ListService).register(tree),
1020-
attachListStyler(tree, themeService),
1039+
attachListStyler(tree, themeService, overrideStyles),
10211040
tree.onDidChangeSelection(() => {
10221041
const selection = tree.getSelection();
10231042
const focus = tree.getFocus();

0 commit comments

Comments
 (0)