Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List: move away from styler #169844

Merged
merged 8 commits into from Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/vs/base/browser/ui/actionbar/actionViewItems.ts
Expand Up @@ -11,7 +11,7 @@ import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { IHoverDelegate } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
import { ICustomHover, setupCustomHover } from 'vs/base/browser/ui/iconLabel/iconLabelHover';
import { ISelectBoxOptions, ISelectOptionItem, SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
import { ISelectBoxOptions, ISelectBoxStyles, ISelectOptionItem, SelectBox } from 'vs/base/browser/ui/selectBox/selectBox';
import { IToggleStyles } from 'vs/base/browser/ui/toggle/toggle';
import { Action, ActionRunner, IAction, IActionChangeEvent, IActionRunner, Separator } from 'vs/base/common/actions';
import { Disposable } from 'vs/base/common/lifecycle';
Expand Down Expand Up @@ -418,10 +418,10 @@ export class ActionViewItem extends BaseActionViewItem {
export class SelectActionViewItem extends BaseActionViewItem {
protected selectBox: SelectBox;

constructor(ctx: unknown, action: IAction, options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, selectBoxOptions?: ISelectBoxOptions) {
constructor(ctx: unknown, action: IAction, options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles, selectBoxOptions?: ISelectBoxOptions) {
super(ctx, action);

this.selectBox = new SelectBox(options, selected, contextViewProvider, undefined, selectBoxOptions);
this.selectBox = new SelectBox(options, selected, contextViewProvider, styles, selectBoxOptions);
this.selectBox.setFocusable(false);

this._register(this.selectBox);
Expand Down
3 changes: 1 addition & 2 deletions src/vs/base/browser/ui/list/listPaging.ts
Expand Up @@ -9,7 +9,6 @@ import { Event } from 'vs/base/common/event';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { IPagedModel } from 'vs/base/common/paging';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { IThemable } from 'vs/base/common/styler';
import 'vs/css!./list';
import { IListContextMenuEvent, IListEvent, IListMouseEvent, IListRenderer, IListVirtualDelegate } from './list';
import { IListAccessibilityProvider, IListOptions, IListOptionsUpdate, IListStyles, List, TypeNavigationMode } from './listWidget';
Expand Down Expand Up @@ -119,7 +118,7 @@ function fromPagedListOptions<T>(modelProvider: () => IPagedModel<T>, options: I
};
}

export class PagedList<T> implements IThemable, IDisposable {
export class PagedList<T> implements IDisposable {

private list: List<number>;
private _model!: IPagedModel<T>;
Expand Down
102 changes: 53 additions & 49 deletions src/vs/base/browser/ui/list/listWidget.ts
Expand Up @@ -20,11 +20,9 @@ import { matchesPrefix } from 'vs/base/common/filters';
import { KeyCode } from 'vs/base/common/keyCodes';
import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
import { clamp } from 'vs/base/common/numbers';
import { mixin } from 'vs/base/common/objects';
import * as platform from 'vs/base/common/platform';
import { ScrollbarVisibility, ScrollEvent } from 'vs/base/common/scrollable';
import { ISpliceable } from 'vs/base/common/sequence';
import { IThemable } from 'vs/base/common/styler';
import { isNumber } from 'vs/base/common/types';
import 'vs/css!./list';
import { IIdentityProvider, IKeyboardNavigationDelegate, IKeyboardNavigationLabelProvider, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IListEvent, IListGestureEvent, IListMouseEvent, IListRenderer, IListTouchEvent, IListVirtualDelegate, ListError } from './list';
Expand Down Expand Up @@ -797,11 +795,7 @@ export class DefaultStyleController implements IStyleController {
const content: string[] = [];

if (styles.listBackground) {
if (styles.listBackground.isOpaque()) {
content.push(`.monaco-list${suffix} .monaco-list-rows { background: ${styles.listBackground}; }`);
} else if (!platform.isMacintosh) { // subpixel AA doesn't exist in macOS
console.warn(`List with id '${this.selectorSuffix}' was styled with a non-opaque background color. This will break sub-pixel antialiasing.`);
}
content.push(`.monaco-list${suffix} .monaco-list-rows { background: ${styles.listBackground}; }`);
}

if (styles.listFocusBackground) {
Expand Down Expand Up @@ -972,47 +966,59 @@ export interface IListOptions<T> extends IListOptionsUpdate {
}

export interface IListStyles {
listBackground?: Color;
listFocusBackground?: Color;
listFocusForeground?: Color;
listActiveSelectionBackground?: Color;
listActiveSelectionForeground?: Color;
listActiveSelectionIconForeground?: Color;
listFocusAndSelectionOutline?: Color;
listFocusAndSelectionBackground?: Color;
listFocusAndSelectionForeground?: Color;
listInactiveSelectionBackground?: Color;
listInactiveSelectionIconForeground?: Color;
listInactiveSelectionForeground?: Color;
listInactiveFocusForeground?: Color;
listInactiveFocusBackground?: Color;
listHoverBackground?: Color;
listHoverForeground?: Color;
listDropBackground?: Color;
listFocusOutline?: Color;
listInactiveFocusOutline?: Color;
listSelectionOutline?: Color;
listHoverOutline?: Color;
treeIndentGuidesStroke?: Color;
tableColumnsBorder?: Color;
tableOddRowsBackgroundColor?: Color;
listBackground: string | undefined;
listFocusBackground: string | undefined;
listFocusForeground: string | undefined;
listActiveSelectionBackground: string | undefined;
listActiveSelectionForeground: string | undefined;
listActiveSelectionIconForeground: string | undefined;
listFocusAndSelectionOutline: string | undefined;
listFocusAndSelectionBackground: string | undefined;
listFocusAndSelectionForeground: string | undefined;
listInactiveSelectionBackground: string | undefined;
listInactiveSelectionIconForeground: string | undefined;
listInactiveSelectionForeground: string | undefined;
listInactiveFocusForeground: string | undefined;
listInactiveFocusBackground: string | undefined;
listHoverBackground: string | undefined;
listHoverForeground: string | undefined;
listDropBackground: string | undefined;
listFocusOutline: string | undefined;
listInactiveFocusOutline: string | undefined;
listSelectionOutline: string | undefined;
listHoverOutline: string | undefined;
treeIndentGuidesStroke: string | undefined;
treeInactiveIndentGuidesStroke: string | undefined;
tableColumnsBorder: string | undefined;
tableOddRowsBackgroundColor: string | undefined;
}

const defaultStyles: IListStyles = {
listFocusBackground: Color.fromHex('#7FB0D0'),
listActiveSelectionBackground: Color.fromHex('#0E639C'),
listActiveSelectionForeground: Color.fromHex('#FFFFFF'),
listActiveSelectionIconForeground: Color.fromHex('#FFFFFF'),
listFocusAndSelectionOutline: Color.fromHex('#90C2F9'),
listFocusAndSelectionBackground: Color.fromHex('#094771'),
listFocusAndSelectionForeground: Color.fromHex('#FFFFFF'),
listInactiveSelectionBackground: Color.fromHex('#3F3F46'),
listInactiveSelectionIconForeground: Color.fromHex('#FFFFFF'),
listHoverBackground: Color.fromHex('#2A2D2E'),
listDropBackground: Color.fromHex('#383B3D'),
treeIndentGuidesStroke: Color.fromHex('#a9a9a9'),
tableColumnsBorder: Color.fromHex('#cccccc').transparent(0.2),
tableOddRowsBackgroundColor: Color.fromHex('#cccccc').transparent(0.04)
export const unthemedListStyles: IListStyles = {
listFocusBackground: '#7FB0D0',
listActiveSelectionBackground: '#0E639C',
listActiveSelectionForeground: '#FFFFFF',
listActiveSelectionIconForeground: '#FFFFFF',
listFocusAndSelectionOutline: '#90C2F9',
listFocusAndSelectionBackground: '#094771',
listFocusAndSelectionForeground: '#FFFFFF',
listInactiveSelectionBackground: '#3F3F46',
listInactiveSelectionIconForeground: '#FFFFFF',
listHoverBackground: '#2A2D2E',
listDropBackground: '#383B3D',
treeIndentGuidesStroke: '#a9a9a9',
treeInactiveIndentGuidesStroke: Color.fromHex('#a9a9a9').transparent(0.4).toString(),
tableColumnsBorder: Color.fromHex('#cccccc').transparent(0.2).toString(),
tableOddRowsBackgroundColor: Color.fromHex('#cccccc').transparent(0.04).toString(),
listBackground: undefined,
listFocusForeground: undefined,
listInactiveSelectionForeground: undefined,
listInactiveFocusForeground: undefined,
listInactiveFocusBackground: undefined,
listHoverForeground: undefined,
listFocusOutline: undefined,
listInactiveFocusOutline: undefined,
listSelectionOutline: undefined,
listHoverOutline: undefined
};

const DefaultOptions: IListOptions<any> = {
Expand Down Expand Up @@ -1241,7 +1247,7 @@ class ListViewDragAndDrop<T> implements IListViewDragAndDrop<T> {
* - Dynamic element height support
* - Drag-and-drop support
*/
export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
export class List<T> implements ISpliceable<T>, IDisposable {

private focus = new Trait<T>('focused');
private selection: Trait<T>;
Expand Down Expand Up @@ -1339,8 +1345,6 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
const role = this._options.accessibilityProvider && this._options.accessibilityProvider.getWidgetRole ? this._options.accessibilityProvider?.getWidgetRole() : 'list';
this.selection = new SelectionTrait(role !== 'listbox');

mixin(_options, defaultStyles, false);

const baseRenderers: IListRenderer<T, ITraitTemplateData>[] = [this.focus.renderer, this.selection.renderer];

this.accessibilityProvider = _options.accessibilityProvider;
Expand Down
46 changes: 19 additions & 27 deletions src/vs/base/browser/ui/selectBox/selectBox.ts
Expand Up @@ -5,16 +5,13 @@

import { IContentActionHandler } from 'vs/base/browser/formattedTextRenderer';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { IListStyles } from 'vs/base/browser/ui/list/listWidget';
import { IListStyles, unthemedListStyles } from 'vs/base/browser/ui/list/listWidget';
import { SelectBoxList } from 'vs/base/browser/ui/selectBox/selectBoxCustom';
import { SelectBoxNative } from 'vs/base/browser/ui/selectBox/selectBoxNative';
import { Widget } from 'vs/base/browser/ui/widget';
import { Color } from 'vs/base/common/color';
import { Event } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
import { deepClone } from 'vs/base/common/objects';
import { isMacintosh } from 'vs/base/common/platform';
import { IThemable } from 'vs/base/common/styler';
import 'vs/css!./selectBox';


Expand All @@ -34,8 +31,6 @@ export interface ISelectBoxDelegate extends IDisposable {

// Delegated Widget interface
render(container: HTMLElement): void;
style(styles: ISelectBoxStyles): void;
applyStyles(): void;
}

export interface ISelectBoxOptions {
Expand All @@ -58,30 +53,35 @@ export interface ISelectOptionItem {
}

export interface ISelectBoxStyles extends IListStyles {
selectBackground?: Color;
selectListBackground?: Color;
selectForeground?: Color;
decoratorRightForeground?: Color;
selectBorder?: Color;
selectListBorder?: Color;
focusBorder?: Color;
readonly selectBackground: string | undefined;
readonly selectListBackground: string | undefined;
readonly selectForeground: string | undefined;
readonly decoratorRightForeground: string | undefined;
readonly selectBorder: string | undefined;
readonly selectListBorder: string | undefined;
readonly focusBorder: string | undefined;
}

export const defaultStyles = {
selectBackground: Color.fromHex('#3C3C3C'),
selectForeground: Color.fromHex('#F0F0F0'),
selectBorder: Color.fromHex('#3C3C3C')
export const unthemedSelectBoxStyles: ISelectBoxStyles = {
...unthemedListStyles,
selectBackground: '#3C3C3C',
selectForeground: '#F0F0F0',
selectBorder: '#3C3C3C',
decoratorRightForeground: undefined,
selectListBackground: undefined,
selectListBorder: undefined,
focusBorder: undefined,
};

export interface ISelectData {
selected: string;
index: number;
}

export class SelectBox extends Widget implements ISelectBoxDelegate, IThemable {
export class SelectBox extends Widget implements ISelectBoxDelegate {
private selectBoxDelegate: ISelectBoxDelegate;

constructor(options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles = deepClone(defaultStyles), selectBoxOptions?: ISelectBoxOptions) {
constructor(options: ISelectOptionItem[], selected: number, contextViewProvider: IContextViewProvider, styles: ISelectBoxStyles, selectBoxOptions?: ISelectBoxOptions) {
super();

// Default to native SelectBox for OSX unless overridden
Expand Down Expand Up @@ -127,12 +127,4 @@ export class SelectBox extends Widget implements ISelectBoxDelegate, IThemable {
render(container: HTMLElement): void {
this.selectBoxDelegate.render(container);
}

style(styles: ISelectBoxStyles): void {
this.selectBoxDelegate.style(styles);
}

applyStyles(): void {
this.selectBoxDelegate.applyStyles();
}
}
64 changes: 25 additions & 39 deletions src/vs/base/browser/ui/selectBox/selectBoxCustom.ts
Expand Up @@ -87,7 +87,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
private options: ISelectOptionItem[] = [];
private selected: number;
private readonly _onDidSelect: Emitter<ISelectData>;
private styles: ISelectBoxStyles;
private readonly styles: ISelectBoxStyles;
private listRenderer!: SelectListRenderer;
private contextViewProvider!: IContextViewProvider;
private selectDropDownContainer!: HTMLElement;
Expand All @@ -107,6 +107,8 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi

super();
this._isVisible = false;
this.styles = styles;

this.selectBoxOptions = selectBoxOptions || Object.create(null);

if (typeof this.selectBoxOptions.minBottomMargin !== 'number') {
Expand All @@ -131,8 +133,6 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
this._onDidSelect = new Emitter<ISelectData>();
this._register(this._onDidSelect);

this.styles = styles;

this.registerListeners();
this.constructSelectDropDown(contextViewProvider);

Expand All @@ -142,6 +142,8 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
this.setOptions(options, selected);
}

this.initStyleSheet();

}

// IDelegate - List renderer
Expand Down Expand Up @@ -336,15 +338,13 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
this.container = container;
container.classList.add('select-container');
container.appendChild(this.selectElement);
this.applyStyles();
this.styleSelectElement();
}

public style(styles: ISelectBoxStyles): void {
private initStyleSheet(): void {

const content: string[] = [];

this.styles = styles;

// Style non-native select mode

if (this.styles.listFocusBackground) {
Expand All @@ -359,7 +359,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:not(.focused) .option-decorator-right { color: ${this.styles.decoratorRightForeground}; }`);
}

if (this.styles.selectBackground && this.styles.selectBorder && !this.styles.selectBorder.equals(this.styles.selectBackground)) {
if (this.styles.selectBackground && this.styles.selectBorder && this.styles.selectBorder !== this.styles.selectBackground) {
content.push(`.monaco-select-box-dropdown-container { border: 1px solid ${this.styles.selectBorder} } `);
content.push(`.monaco-select-box-dropdown-container > .select-box-details-pane.border-top { border-top: 1px solid ${this.styles.selectBorder} } `);
content.push(`.monaco-select-box-dropdown-container > .select-box-details-pane.border-bottom { border-bottom: 1px solid ${this.styles.selectBorder} } `);
Expand Down Expand Up @@ -394,43 +394,29 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
content.push(`.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row.option-disabled:hover { background-color: transparent !important; color: inherit !important; outline: none !important; }`);

this.styleElement.textContent = content.join('\n');

this.applyStyles();
}

public applyStyles(): void {

// Style parent select

if (this.selectElement) {
const background = this.styles.selectBackground ? this.styles.selectBackground.toString() : '';
const foreground = this.styles.selectForeground ? this.styles.selectForeground.toString() : '';
const border = this.styles.selectBorder ? this.styles.selectBorder.toString() : '';

this.selectElement.style.backgroundColor = background;
this.selectElement.style.color = foreground;
this.selectElement.style.borderColor = border;
}
private styleSelectElement(): void {
const background = this.styles.selectBackground ?? '';
const foreground = this.styles.selectForeground ?? '';
const border = this.styles.selectBorder ?? '';

// Style drop down select list (non-native mode only)

if (this.selectList) {
this.styleList();
}
this.selectElement.style.backgroundColor = background;
this.selectElement.style.color = foreground;
this.selectElement.style.borderColor = border;
}

private styleList() {
if (this.selectList) {
const background = this.styles.selectBackground ? this.styles.selectBackground.toString() : '';
this.selectList.style({});

const listBackground = this.styles.selectListBackground ? this.styles.selectListBackground.toString() : background;
this.selectDropDownListContainer.style.backgroundColor = listBackground;
this.selectionDetailsPane.style.backgroundColor = listBackground;
const optionsBorder = this.styles.focusBorder ? this.styles.focusBorder.toString() : '';
this.selectDropDownContainer.style.outlineColor = optionsBorder;
this.selectDropDownContainer.style.outlineOffset = '-1px';
}
const background = this.styles.selectBackground ?? '';

const listBackground = this.styles.selectListBackground ? this.styles.selectListBackground : background;
this.selectDropDownListContainer.style.backgroundColor = listBackground;
this.selectionDetailsPane.style.backgroundColor = listBackground;
const optionsBorder = this.styles.focusBorder ? this.styles.focusBorder : '';
this.selectDropDownContainer.style.outlineColor = optionsBorder;
this.selectDropDownContainer.style.outlineOffset = '-1px';

this.selectList.style(this.styles);
}

private createOption(value: string, index: number, disabled?: boolean): HTMLOptionElement {
Expand Down