Merge from vscode 4d91d96e5e121b38d33508cdef17868bab255eae

This commit is contained in:
ADS Merger
2020-06-18 04:32:54 +00:00
committed by AzureDataStudio
parent a971aee5bd
commit 5e7071e466
1002 changed files with 24201 additions and 13193 deletions

View File

@@ -88,9 +88,13 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
if (href) {
({ href, dimensions } = parseHrefAndDimensions(href));
href = _href(href, true);
if (options.baseUrl) {
href = resolvePath(options.baseUrl, href).toString();
}
try {
const hrefAsUri = URI.parse(href);
if (options.baseUrl && hrefAsUri.scheme === Schemas.file) { // absolute or relative local path, or file: uri
href = resolvePath(options.baseUrl, href).toString();
}
} catch (err) { }
attributes.push(`src="${href}"`);
}
if (text) {
@@ -225,9 +229,12 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
);
function filter(token: { tag: string, attrs: { readonly [key: string]: string } }): boolean {
if (token.tag === 'span' && markdown.isTrusted) {
if (token.attrs['style'] && Object.keys(token.attrs).length === 1) {
if (token.tag === 'span' && markdown.isTrusted && (Object.keys(token.attrs).length === 1)) {
if (token.attrs['style']) {
return !!token.attrs['style'].match(/^(color\:#[0-9a-fA-F]+;)?(background-color\:#[0-9a-fA-F]+;)?$/);
} else if (token.attrs['class']) {
// The class should match codicon rendering in src\vs\base\common\codicons.ts
return !!token.attrs['class'].match(/^codicon codicon-[a-z\-]+( codicon-animation-[a-z\-]+)?$/);
}
return false;
}
@@ -239,7 +246,8 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende
// allowedTags should included everything that markdown renders to.
// Since we have our own sanitize function for marked, it's possible we missed some tag so let insane make sure.
// HTML tags that can result from markdown are from reading https://spec.commonmark.org/0.29/
allowedTags: ['ul', 'li', 'p', 'code', 'blockquote', 'ol', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'em', 'pre', 'table', 'tr', 'td', 'div', 'del', 'a', 'strong', 'br', 'img', 'span'],
// HTML table tags that can result from markdown are from https://github.github.com/gfm/#tables-extension-
allowedTags: ['ul', 'li', 'p', 'code', 'blockquote', 'ol', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'em', 'pre', 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'div', 'del', 'a', 'strong', 'br', 'img', 'span'],
allowedAttributes: {
'a': ['href', 'name', 'target', 'data-href'],
'img': ['src', 'title', 'alt', 'width', 'height'],

View File

@@ -479,27 +479,27 @@ export class ActionBar extends Disposable implements IActionRunner {
DOM.addClass(this.domNode, 'animated');
}
let previousKeys: KeyCode[];
let nextKeys: KeyCode[];
let previousKey: KeyCode;
let nextKey: KeyCode;
switch (this.options.orientation) {
case ActionsOrientation.HORIZONTAL:
previousKeys = [KeyCode.LeftArrow, KeyCode.UpArrow];
nextKeys = [KeyCode.RightArrow, KeyCode.DownArrow];
previousKey = KeyCode.LeftArrow;
nextKey = KeyCode.RightArrow;
break;
case ActionsOrientation.HORIZONTAL_REVERSE:
previousKeys = [KeyCode.RightArrow, KeyCode.DownArrow];
nextKeys = [KeyCode.LeftArrow, KeyCode.UpArrow];
previousKey = KeyCode.RightArrow;
nextKey = KeyCode.LeftArrow;
this.domNode.className += ' reverse';
break;
case ActionsOrientation.VERTICAL:
previousKeys = [KeyCode.LeftArrow, KeyCode.UpArrow];
nextKeys = [KeyCode.RightArrow, KeyCode.DownArrow];
previousKey = KeyCode.UpArrow;
nextKey = KeyCode.DownArrow;
this.domNode.className += ' vertical';
break;
case ActionsOrientation.VERTICAL_REVERSE:
previousKeys = [KeyCode.RightArrow, KeyCode.DownArrow];
nextKeys = [KeyCode.LeftArrow, KeyCode.UpArrow];
previousKey = KeyCode.DownArrow;
nextKey = KeyCode.UpArrow;
this.domNode.className += ' vertical reverse';
break;
}
@@ -508,9 +508,9 @@ export class ActionBar extends Disposable implements IActionRunner {
const event = new StandardKeyboardEvent(e);
let eventHandled = true;
if (previousKeys && (event.equals(previousKeys[0]) || event.equals(previousKeys[1]))) {
if (event.equals(previousKey)) {
this.focusPrevious();
} else if (nextKeys && (event.equals(nextKeys[0]) || event.equals(nextKeys[1]))) {
} else if (event.equals(nextKey)) {
this.focusNext();
} else if (event.equals(KeyCode.Escape)) {
this._onDidCancel.fire();
@@ -696,7 +696,8 @@ export class ActionBar extends Disposable implements IActionRunner {
}
clear(): void {
this.viewItems = dispose(this.viewItems);
dispose(this.viewItems);
this.viewItems = [];
DOM.clearNode(this.actionsList);
}

View File

@@ -11,50 +11,78 @@ import * as dom from 'vs/base/browser/dom';
const MAX_MESSAGE_LENGTH = 20000;
let ariaContainer: HTMLElement;
let alertContainer: HTMLElement;
let alertContainer2: HTMLElement;
let statusContainer: HTMLElement;
let statusContainer2: HTMLElement;
export function setARIAContainer(parent: HTMLElement) {
ariaContainer = document.createElement('div');
ariaContainer.className = 'monaco-aria-container';
alertContainer = document.createElement('div');
alertContainer.className = 'monaco-alert';
alertContainer.setAttribute('role', 'alert');
alertContainer.setAttribute('aria-atomic', 'true');
ariaContainer.appendChild(alertContainer);
const createAlertContainer = () => {
const element = document.createElement('div');
element.className = 'monaco-alert';
element.setAttribute('role', 'alert');
element.setAttribute('aria-atomic', 'true');
ariaContainer.appendChild(element);
return element;
};
alertContainer = createAlertContainer();
alertContainer2 = createAlertContainer();
statusContainer = document.createElement('div');
statusContainer.className = 'monaco-status';
statusContainer.setAttribute('role', 'complementary');
statusContainer.setAttribute('aria-live', 'polite');
statusContainer.setAttribute('aria-atomic', 'true');
ariaContainer.appendChild(statusContainer);
const createStatusContainer = () => {
const element = document.createElement('div');
element.className = 'monaco-status';
element.setAttribute('role', 'complementary');
element.setAttribute('aria-live', 'polite');
element.setAttribute('aria-atomic', 'true');
ariaContainer.appendChild(element);
return element;
};
statusContainer = createStatusContainer();
statusContainer2 = createStatusContainer();
parent.appendChild(ariaContainer);
}
/**
* Given the provided message, will make sure that it is read as alert to screen readers.
*/
export function alert(msg: string): void {
insertMessage(alertContainer, msg);
if (!ariaContainer) {
return;
}
// Use alternate containers such that duplicated messages get read out by screen readers #99466
if (alertContainer.textContent !== msg) {
dom.clearNode(alertContainer2);
insertMessage(alertContainer, msg);
} else {
dom.clearNode(alertContainer);
insertMessage(alertContainer2, msg);
}
}
/**
* Given the provided message, will make sure that it is read as status to screen readers.
*/
export function status(msg: string): void {
if (isMacintosh) {
alert(msg); // VoiceOver does not seem to support status role
} else {
insertMessage(statusContainer, msg);
}
}
function insertMessage(target: HTMLElement, msg: string): void {
if (!ariaContainer) {
return;
}
if (isMacintosh) {
alert(msg); // VoiceOver does not seem to support status role
} else {
if (statusContainer.textContent !== msg) {
dom.clearNode(statusContainer2);
insertMessage(statusContainer, msg);
} else {
dom.clearNode(statusContainer);
insertMessage(statusContainer2, msg);
}
}
}
function insertMessage(target: HTMLElement, msg: string): void {
dom.clearNode(target);
if (msg.length > MAX_MESSAGE_LENGTH) {
msg = msg.substr(0, MAX_MESSAGE_LENGTH);

View File

@@ -18,12 +18,16 @@ import { escape } from 'vs/base/common/strings';
export interface IButtonOptions extends IButtonStyles {
readonly title?: boolean | string;
readonly supportCodicons?: boolean;
readonly secondary?: boolean;
}
export interface IButtonStyles {
buttonBackground?: Color;
buttonHoverBackground?: Color;
buttonForeground?: Color;
buttonSecondaryBackground?: Color;
buttonSecondaryHoverBackground?: Color;
buttonSecondaryForeground?: Color;
buttonBorder?: Color;
}
@@ -41,6 +45,9 @@ export class Button extends Disposable {
private buttonBackground: Color | undefined;
private buttonHoverBackground: Color | undefined;
private buttonForeground: Color | undefined;
private buttonSecondaryBackground: Color | undefined;
private buttonSecondaryHoverBackground: Color | undefined;
private buttonSecondaryForeground: Color | undefined;
private buttonBorder: Color | undefined;
private _onDidClick = this._register(new Emitter<Event>());
@@ -54,9 +61,14 @@ export class Button extends Disposable {
this.options = options || Object.create(null);
mixin(this.options, defaultOptions, false);
this.buttonForeground = this.options.buttonForeground;
this.buttonBackground = this.options.buttonBackground;
this.buttonHoverBackground = this.options.buttonHoverBackground;
this.buttonForeground = this.options.buttonForeground;
this.buttonSecondaryForeground = this.options.buttonSecondaryForeground;
this.buttonSecondaryBackground = this.options.buttonSecondaryBackground;
this.buttonSecondaryHoverBackground = this.options.buttonSecondaryHoverBackground;
this.buttonBorder = this.options.buttonBorder;
this._element = document.createElement('a');
@@ -114,7 +126,12 @@ export class Button extends Disposable {
}
private setHoverBackground(): void {
const hoverBackground = this.buttonHoverBackground ? this.buttonHoverBackground.toString() : null;
let hoverBackground;
if (this.options.secondary) {
hoverBackground = this.buttonSecondaryHoverBackground ? this.buttonSecondaryHoverBackground.toString() : null;
} else {
hoverBackground = this.buttonHoverBackground ? this.buttonHoverBackground.toString() : null;
}
if (hoverBackground) {
this._element.style.backgroundColor = hoverBackground;
}
@@ -124,6 +141,9 @@ export class Button extends Disposable {
this.buttonForeground = styles.buttonForeground;
this.buttonBackground = styles.buttonBackground;
this.buttonHoverBackground = styles.buttonHoverBackground;
this.buttonSecondaryForeground = styles.buttonSecondaryForeground;
this.buttonSecondaryBackground = styles.buttonSecondaryBackground;
this.buttonSecondaryHoverBackground = styles.buttonSecondaryHoverBackground;
this.buttonBorder = styles.buttonBorder;
this.applyStyles();
@@ -132,8 +152,15 @@ export class Button extends Disposable {
// {{SQL CARBON EDIT}} -- removed 'private' access modifier @todo anthonydresser 4/12/19 things needs investigation whether we need this
applyStyles(): void {
if (this._element) {
const background = this.buttonBackground ? this.buttonBackground.toString() : '';
const foreground = this.buttonForeground ? this.buttonForeground.toString() : '';
let background, foreground;
if (this.options.secondary) {
foreground = this.buttonSecondaryForeground ? this.buttonSecondaryForeground.toString() : '';
background = this.buttonSecondaryBackground ? this.buttonSecondaryBackground.toString() : '';
} else {
foreground = this.buttonForeground ? this.buttonForeground.toString() : '';
background = this.buttonBackground ? this.buttonBackground.toString() : '';
}
const border = this.buttonBorder ? this.buttonBorder.toString() : '';
this._element.style.color = foreground;

View File

@@ -23,6 +23,7 @@ export interface ICheckboxOpts extends ICheckboxStyles {
export interface ICheckboxStyles {
inputActiveOptionBorder?: Color;
inputActiveOptionForeground?: Color;
inputActiveOptionBackground?: Color;
}
@@ -34,6 +35,7 @@ export interface ISimpleCheckboxStyles {
const defaultOpts = {
inputActiveOptionBorder: Color.fromHex('#007ACC00'),
inputActiveOptionForeground: Color.fromHex('#FFFFFF'),
inputActiveOptionBackground: Color.fromHex('#0E639C50')
};
@@ -170,6 +172,9 @@ export class Checkbox extends Widget {
if (styles.inputActiveOptionBorder) {
this._opts.inputActiveOptionBorder = styles.inputActiveOptionBorder;
}
if (styles.inputActiveOptionForeground) {
this._opts.inputActiveOptionForeground = styles.inputActiveOptionForeground;
}
if (styles.inputActiveOptionBackground) {
this._opts.inputActiveOptionBackground = styles.inputActiveOptionBackground;
}
@@ -179,6 +184,7 @@ export class Checkbox extends Widget {
protected applyStyles(): void {
if (this.domNode) {
this.domNode.style.borderColor = this._checked && this._opts.inputActiveOptionBorder ? this._opts.inputActiveOptionBorder.toString() : 'transparent';
this.domNode.style.color = this._checked && this._opts.inputActiveOptionForeground ? this._opts.inputActiveOptionForeground.toString() : 'inherit';
this.domNode.style.backgroundColor = this._checked && this._opts.inputActiveOptionBackground ? this._opts.inputActiveOptionBackground.toString() : 'transparent';
}
}

View File

@@ -73,6 +73,7 @@ export class Dialog extends Disposable {
this.modal = this.container.appendChild($(`.monaco-dialog-modal-block${options.type === 'pending' ? '.dimmed' : ''}`));
this.shadowElement = this.modal.appendChild($('.dialog-shadow'));
this.element = this.shadowElement.appendChild($('.monaco-dialog-box'));
this.element.setAttribute('role', 'dialog');
hide(this.element);
// If no button is provided, default to OK
@@ -109,6 +110,28 @@ export class Dialog extends Disposable {
this.toolbarContainer = toolbarRowElement.appendChild($('.dialog-toolbar'));
}
private getAriaLabel(): string {
let typeLabel = nls.localize('dialogInfoMessage', 'Info');
switch (this.options.type) {
case 'error':
nls.localize('dialogErrorMessage', 'Error');
break;
case 'warning':
nls.localize('dialogWarningMessage', 'Warning');
break;
case 'pending':
nls.localize('dialogPendingMessage', 'In Progress');
break;
case 'none':
case 'info':
case 'question':
default:
break;
}
return `${typeLabel}: ${this.message} ${this.options.detail || ''}`;
}
updateMessage(message: string): void {
if (this.messageDetailElement) {
this.messageDetailElement.innerText = message;
@@ -242,7 +265,7 @@ export class Dialog extends Disposable {
this.applyStyles();
this.element.setAttribute('aria-label', this.message);
this.element.setAttribute('aria-label', this.getAriaLabel());
show(this.element);
// Focus first element

View File

@@ -214,6 +214,7 @@ export interface IDropdownMenuOptions extends IBaseDropdownOptions {
actions?: ReadonlyArray<IAction>;
actionProvider?: IActionProvider;
menuClassName?: string;
menuAsChild?: boolean; // scope down for #99448
}
export class DropdownMenu extends BaseDropdown {
@@ -222,6 +223,7 @@ export class DropdownMenu extends BaseDropdown {
private _actions: ReadonlyArray<IAction> = [];
private actionProvider?: IActionProvider;
private menuClassName: string;
private menuAsChild?: boolean;
constructor(container: HTMLElement, options: IDropdownMenuOptions) {
super(container, options);
@@ -230,6 +232,7 @@ export class DropdownMenu extends BaseDropdown {
this.actions = options.actions || [];
this.actionProvider = options.actionProvider;
this.menuClassName = options.menuClassName || '';
this.menuAsChild = !!options.menuAsChild;
}
set menuOptions(options: IMenuOptions | undefined) {
@@ -267,7 +270,7 @@ export class DropdownMenu extends BaseDropdown {
onHide: () => this.onHide(),
actionRunner: this.menuOptions ? this.menuOptions.actionRunner : undefined,
anchorAlignment: this.menuOptions ? this.menuOptions.anchorAlignment : AnchorAlignment.LEFT,
anchorAsContainer: true
anchorAsContainer: this.menuAsChild
});
}
@@ -289,10 +292,11 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
private keybindings?: (action: IAction) => ResolvedKeybinding | undefined;
private clazz: string | undefined;
private anchorAlignmentProvider: (() => AnchorAlignment) | undefined;
private menuAsChild?: boolean;
constructor(action: IAction, menuActions: ReadonlyArray<IAction>, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment);
constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment);
constructor(action: IAction, menuActionsOrProvider: ReadonlyArray<IAction> | IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment) {
constructor(action: IAction, menuActions: ReadonlyArray<IAction>, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment, menuAsChild?: boolean);
constructor(action: IAction, actionProvider: IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment, menuAsChild?: boolean);
constructor(action: IAction, menuActionsOrProvider: ReadonlyArray<IAction> | IActionProvider, contextMenuProvider: IContextMenuProvider, actionViewItemProvider: IActionViewItemProvider | undefined, actionRunner: IActionRunner, keybindings: ((action: IAction) => ResolvedKeybinding | undefined) | undefined, clazz: string | undefined, anchorAlignmentProvider?: () => AnchorAlignment, menuAsChild?: boolean) {
super(null, action);
this.menuActionsOrProvider = menuActionsOrProvider;
@@ -302,6 +306,7 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
this.keybindings = keybindings;
this.clazz = clazz;
this.anchorAlignmentProvider = anchorAlignmentProvider;
this.menuAsChild = menuAsChild;
}
render(container: HTMLElement): void {
@@ -322,7 +327,8 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
const options: IDropdownMenuOptions = {
contextMenuProvider: this.contextMenuProvider,
labelRenderer: labelRenderer
labelRenderer: labelRenderer,
menuAsChild: this.menuAsChild
};
// Render the DropdownMenu around a simple action to toggle it

View File

@@ -35,6 +35,7 @@ export interface IFindInputOptions extends IFindInputStyles {
export interface IFindInputStyles extends IInputBoxStyles {
inputActiveOptionBorder?: Color;
inputActiveOptionForeground?: Color;
inputActiveOptionBackground?: Color;
}
@@ -51,6 +52,7 @@ export class FindInput extends Widget {
private fixFocusOnOptionClickEnabled = true;
private inputActiveOptionBorder?: Color;
private inputActiveOptionForeground?: Color;
private inputActiveOptionBackground?: Color;
private inputBackground?: Color;
private inputForeground?: Color;
@@ -101,6 +103,7 @@ export class FindInput extends Widget {
this.label = options.label || NLS_DEFAULT_LABEL;
this.inputActiveOptionBorder = options.inputActiveOptionBorder;
this.inputActiveOptionForeground = options.inputActiveOptionForeground;
this.inputActiveOptionBackground = options.inputActiveOptionBackground;
this.inputBackground = options.inputBackground;
this.inputForeground = options.inputForeground;
@@ -155,6 +158,7 @@ export class FindInput extends Widget {
appendTitle: appendRegexLabel,
isChecked: false,
inputActiveOptionBorder: this.inputActiveOptionBorder,
inputActiveOptionForeground: this.inputActiveOptionForeground,
inputActiveOptionBackground: this.inputActiveOptionBackground
}));
this._register(this.regex.onChange(viaKeyboard => {
@@ -172,6 +176,7 @@ export class FindInput extends Widget {
appendTitle: appendWholeWordsLabel,
isChecked: false,
inputActiveOptionBorder: this.inputActiveOptionBorder,
inputActiveOptionForeground: this.inputActiveOptionForeground,
inputActiveOptionBackground: this.inputActiveOptionBackground
}));
this._register(this.wholeWords.onChange(viaKeyboard => {
@@ -186,6 +191,7 @@ export class FindInput extends Widget {
appendTitle: appendCaseSensitiveLabel,
isChecked: false,
inputActiveOptionBorder: this.inputActiveOptionBorder,
inputActiveOptionForeground: this.inputActiveOptionForeground,
inputActiveOptionBackground: this.inputActiveOptionBackground
}));
this._register(this.caseSensitive.onChange(viaKeyboard => {
@@ -301,6 +307,7 @@ export class FindInput extends Widget {
public style(styles: IFindInputStyles): void {
this.inputActiveOptionBorder = styles.inputActiveOptionBorder;
this.inputActiveOptionForeground = styles.inputActiveOptionForeground;
this.inputActiveOptionBackground = styles.inputActiveOptionBackground;
this.inputBackground = styles.inputBackground;
this.inputForeground = styles.inputForeground;
@@ -323,6 +330,7 @@ export class FindInput extends Widget {
if (this.domNode) {
const checkBoxStyles: ICheckboxStyles = {
inputActiveOptionBorder: this.inputActiveOptionBorder,
inputActiveOptionForeground: this.inputActiveOptionForeground,
inputActiveOptionBackground: this.inputActiveOptionBackground,
};
this.regex.style(checkBoxStyles);

View File

@@ -12,6 +12,7 @@ export interface IFindInputCheckboxOpts {
readonly appendTitle: string;
readonly isChecked: boolean;
readonly inputActiveOptionBorder?: Color;
readonly inputActiveOptionForeground?: Color;
readonly inputActiveOptionBackground?: Color;
}
@@ -26,6 +27,7 @@ export class CaseSensitiveCheckbox extends Checkbox {
title: NLS_CASE_SENSITIVE_CHECKBOX_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
inputActiveOptionBorder: opts.inputActiveOptionBorder,
inputActiveOptionForeground: opts.inputActiveOptionForeground,
inputActiveOptionBackground: opts.inputActiveOptionBackground
});
}
@@ -38,6 +40,7 @@ export class WholeWordsCheckbox extends Checkbox {
title: NLS_WHOLE_WORD_CHECKBOX_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
inputActiveOptionBorder: opts.inputActiveOptionBorder,
inputActiveOptionForeground: opts.inputActiveOptionForeground,
inputActiveOptionBackground: opts.inputActiveOptionBackground
});
}
@@ -50,6 +53,7 @@ export class RegexCheckbox extends Checkbox {
title: NLS_REGEX_CHECKBOX_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
inputActiveOptionBorder: opts.inputActiveOptionBorder,
inputActiveOptionForeground: opts.inputActiveOptionForeground,
inputActiveOptionBackground: opts.inputActiveOptionBackground
});
}

View File

@@ -33,6 +33,7 @@ export interface IReplaceInputOptions extends IReplaceInputStyles {
export interface IReplaceInputStyles extends IInputBoxStyles {
inputActiveOptionBorder?: Color;
inputActiveOptionForeground?: Color;
inputActiveOptionBackground?: Color;
}
@@ -47,6 +48,7 @@ export class PreserveCaseCheckbox extends Checkbox {
title: NLS_PRESERVE_CASE_LABEL + opts.appendTitle,
isChecked: opts.isChecked,
inputActiveOptionBorder: opts.inputActiveOptionBorder,
inputActiveOptionForeground: opts.inputActiveOptionForeground,
inputActiveOptionBackground: opts.inputActiveOptionBackground
});
}
@@ -63,6 +65,7 @@ export class ReplaceInput extends Widget {
private fixFocusOnOptionClickEnabled = true;
private inputActiveOptionBorder?: Color;
private inputActiveOptionForeground?: Color;
private inputActiveOptionBackground?: Color;
private inputBackground?: Color;
private inputForeground?: Color;
@@ -109,6 +112,7 @@ export class ReplaceInput extends Widget {
this.label = options.label || NLS_DEFAULT_LABEL;
this.inputActiveOptionBorder = options.inputActiveOptionBorder;
this.inputActiveOptionForeground = options.inputActiveOptionForeground;
this.inputActiveOptionBackground = options.inputActiveOptionBackground;
this.inputBackground = options.inputBackground;
this.inputForeground = options.inputForeground;
@@ -160,6 +164,7 @@ export class ReplaceInput extends Widget {
appendTitle: '',
isChecked: false,
inputActiveOptionBorder: this.inputActiveOptionBorder,
inputActiveOptionForeground: this.inputActiveOptionForeground,
inputActiveOptionBackground: this.inputActiveOptionBackground,
}));
this._register(this.preserveCase.onChange(viaKeyboard => {
@@ -271,6 +276,7 @@ export class ReplaceInput extends Widget {
public style(styles: IReplaceInputStyles): void {
this.inputActiveOptionBorder = styles.inputActiveOptionBorder;
this.inputActiveOptionForeground = styles.inputActiveOptionForeground;
this.inputActiveOptionBackground = styles.inputActiveOptionBackground;
this.inputBackground = styles.inputBackground;
this.inputForeground = styles.inputForeground;
@@ -293,6 +299,7 @@ export class ReplaceInput extends Widget {
if (this.domNode) {
const checkBoxStyles: ICheckboxStyles = {
inputActiveOptionBorder: this.inputActiveOptionBorder,
inputActiveOptionForeground: this.inputActiveOptionForeground,
inputActiveOptionBackground: this.inputActiveOptionBackground,
};
this.preserveCase.style(checkBoxStyles);

View File

@@ -35,6 +35,7 @@
}
.monaco-hover p,
.monaco-hover .code,
.monaco-hover ul {
margin: 8px 0;
}
@@ -45,18 +46,20 @@
.monaco-hover hr {
margin-top: 4px;
margin-bottom: -6px;
margin-bottom: -4px;
margin-left: -10px;
margin-right: -10px;
height: 1px;
}
.monaco-hover p:first-child,
.monaco-hover .code:first-child,
.monaco-hover ul:first-child {
margin-top: 0;
}
.monaco-hover p:last-child,
.monaco-hover .code:last-child,
.monaco-hover ul:last-child {
margin-bottom: 0;
}

View File

@@ -55,6 +55,10 @@
white-space: pre; /* enable to show labels that include multiple whitespaces */
}
.vs .monaco-icon-label > .monaco-icon-label-container > .monaco-icon-description-container > .label-description {
opacity: .95;
}
.monaco-icon-label.italic > .monaco-icon-label-container > .monaco-icon-name-container > .label-name,
.monaco-icon-label.italic > .monaco-icon-description-container > .label-description {
font-style: italic;

View File

@@ -6,12 +6,13 @@
import 'vs/css!./list';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import { range } from 'vs/base/common/arrays';
import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent } from './list';
import { List, IListStyles, IListOptions, IListAccessibilityProvider } from './listWidget';
import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent, IListMouseEvent } from './list';
import { List, IListStyles, IListOptions, IListAccessibilityProvider, IListOptionsUpdate } from './listWidget';
import { IPagedModel } from 'vs/base/common/paging';
import { Event } from 'vs/base/common/event';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { IThemable } from 'vs/base/common/styler';
export interface IPagedRenderer<TElement, TTemplateData> extends IListRenderer<TElement, TTemplateData> {
renderPlaceholder(index: number, templateData: TTemplateData): void;
@@ -119,7 +120,7 @@ function fromPagedListOptions<T>(modelProvider: () => IPagedModel<T>, options: I
};
}
export class PagedList<T> implements IDisposable {
export class PagedList<T> implements IThemable, IDisposable {
private list: List<number>;
private _model!: IPagedModel<T>;
@@ -136,6 +137,10 @@ export class PagedList<T> implements IDisposable {
this.list = new List(user, container, virtualDelegate, pagedRenderers, fromPagedListOptions(modelProvider, options));
}
updateOptions(options: IListOptionsUpdate) {
this.list.updateOptions(options);
}
getHTMLElement(): HTMLElement {
return this.list.getHTMLElement();
}
@@ -164,22 +169,30 @@ export class PagedList<T> implements IDisposable {
return this.list.onDidDispose;
}
get onMouseClick(): Event<IListMouseEvent<T>> {
return Event.map(this.list.onMouseClick, ({ element, index, browserEvent }) => ({ element: element === undefined ? undefined : this._model.get(element), index, browserEvent }));
}
get onMouseDblClick(): Event<IListMouseEvent<T>> {
return Event.map(this.list.onMouseDblClick, ({ element, index, browserEvent }) => ({ element: element === undefined ? undefined : this._model.get(element), index, browserEvent }));
}
get onTap(): Event<IListMouseEvent<T>> {
return Event.map(this.list.onTap, ({ element, index, browserEvent }) => ({ element: element === undefined ? undefined : this._model.get(element), index, browserEvent }));
}
get onPointer(): Event<IListMouseEvent<T>> {
return Event.map(this.list.onPointer, ({ element, index, browserEvent }) => ({ element: element === undefined ? undefined : this._model.get(element), index, browserEvent }));
}
get onDidChangeFocus(): Event<IListEvent<T>> {
return Event.map(this.list.onDidChangeFocus, ({ elements, indexes, browserEvent }) => ({ elements: elements.map(e => this._model.get(e)), indexes, browserEvent }));
}
get onDidOpen(): Event<IListEvent<T>> {
return Event.map(this.list.onDidOpen, ({ elements, indexes, browserEvent }) => ({ elements: elements.map(e => this._model.get(e)), indexes, browserEvent }));
}
get onDidChangeSelection(): Event<IListEvent<T>> {
return Event.map(this.list.onDidChangeSelection, ({ elements, indexes, browserEvent }) => ({ elements: elements.map(e => this._model.get(e)), indexes, browserEvent }));
}
get onPin(): Event<IListEvent<T>> {
return Event.map(this.list.onDidPin, ({ elements, indexes, browserEvent }) => ({ elements: elements.map(e => this._model.get(e)), indexes, browserEvent }));
}
get onContextMenu(): Event<IListContextMenuEvent<T>> {
return Event.map(this.list.onContextMenu, ({ element, index, anchor, browserEvent }) => (typeof element === 'undefined' ? { element, index, anchor, browserEvent } : { element: this._model.get(element), index, anchor, browserEvent }));
}
@@ -213,10 +226,6 @@ export class PagedList<T> implements IDisposable {
this.list.scrollLeft = scrollLeft;
}
open(indexes: number[], browserEvent?: UIEvent): void {
this.list.open(indexes, browserEvent);
}
setFocus(indexes: number[]): void {
this.list.setFocus(indexes);
}

View File

@@ -51,6 +51,7 @@ export interface IListViewAccessibilityProvider<T> {
export interface IListViewOptionsUpdate {
readonly additionalScrollHeight?: number;
readonly smoothScrolling?: boolean;
readonly horizontalScrolling?: boolean;
}
export interface IListViewOptions<T> extends IListViewOptionsUpdate {
@@ -61,7 +62,6 @@ export interface IListViewOptions<T> extends IListViewOptionsUpdate {
readonly setRowHeight?: boolean;
readonly supportDynamicHeights?: boolean;
readonly mouseSupport?: boolean;
readonly horizontalScrolling?: boolean;
readonly accessibilityProvider?: IListViewAccessibilityProvider<T>;
readonly transformOptimization?: boolean;
}
@@ -86,7 +86,14 @@ const DefaultOptions = {
export class ElementsDragAndDropData<T, TContext = void> implements IDragAndDropData {
readonly elements: T[];
context: TContext | undefined;
private _context: TContext | undefined;
public get context(): TContext | undefined {
return this._context;
}
public set context(value: TContext | undefined) {
this._context = value;
}
constructor(elements: T[]) {
this.elements = elements;
@@ -220,7 +227,6 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
private setRowLineHeight: boolean;
private setRowHeight: boolean;
private supportDynamicHeights: boolean;
private horizontalScrolling: boolean;
private additionalScrollHeight: number;
private accessibilityProvider: ListViewAccessibilityProvider<T>;
private scrollWidth: number | undefined;
@@ -242,6 +248,35 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
get onWillScroll(): Event<ScrollEvent> { return this.scrollableElement.onWillScroll; }
get containerDomNode(): HTMLElement { return this.rowsContainer; }
private _horizontalScrolling: boolean = false;
private get horizontalScrolling(): boolean { return this._horizontalScrolling; }
private set horizontalScrolling(value: boolean) {
if (value === this._horizontalScrolling) {
return;
}
if (value && this.supportDynamicHeights) {
throw new Error('Horizontal scrolling and dynamic heights not supported simultaneously');
}
this._horizontalScrolling = value;
DOM.toggleClass(this.domNode, 'horizontal-scrolling', this._horizontalScrolling);
if (this._horizontalScrolling) {
for (const item of this.items) {
this.measureItemWidth(item);
}
this.updateScrollWidth();
this.scrollableElement.setScrollDimensions({ width: DOM.getContentWidth(this.domNode) });
this.rowsContainer.style.width = `${Math.max(this.scrollWidth || 0, this.renderWidth)}px`;
} else {
this.scrollableElementWidthDelayer.cancel();
this.scrollableElement.setScrollDimensions({ width: this.renderWidth, scrollWidth: this.renderWidth });
this.rowsContainer.style.width = '';
}
}
constructor(
container: HTMLElement,
private virtualDelegate: IListVirtualDelegate<T>,
@@ -273,8 +308,8 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
DOM.toggleClass(this.domNode, 'mouse-support', typeof options.mouseSupport === 'boolean' ? options.mouseSupport : true);
this.horizontalScrolling = getOrDefault(options, o => o.horizontalScrolling, DefaultOptions.horizontalScrolling);
DOM.toggleClass(this.domNode, 'horizontal-scrolling', this.horizontalScrolling);
this._horizontalScrolling = getOrDefault(options, o => o.horizontalScrolling, DefaultOptions.horizontalScrolling);
DOM.toggleClass(this.domNode, 'horizontal-scrolling', this._horizontalScrolling);
this.additionalScrollHeight = typeof options.additionalScrollHeight === 'undefined' ? 0 : options.additionalScrollHeight;
@@ -293,7 +328,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.scrollable = new Scrollable(getOrDefault(options, o => o.smoothScrolling, false) ? 125 : 0, cb => DOM.scheduleAtNextAnimationFrame(cb));
this.scrollableElement = this.disposables.add(new SmoothScrollableElement(this.rowsContainer, {
alwaysConsumeMouseWheel: true,
horizontal: this.horizontalScrolling ? ScrollbarVisibility.Auto : ScrollbarVisibility.Hidden,
horizontal: ScrollbarVisibility.Auto,
vertical: getOrDefault(options, o => o.verticalScrollMode, DefaultOptions.verticalScrollMode),
useShadows: getOrDefault(options, o => o.useShadows, DefaultOptions.useShadows),
}, this.scrollable));
@@ -322,7 +357,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.layout();
}
updateOptions(options: IListViewOptions<T>) {
updateOptions(options: IListViewOptionsUpdate) {
if (options.additionalScrollHeight !== undefined) {
this.additionalScrollHeight = options.additionalScrollHeight;
}
@@ -330,6 +365,10 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
if (options.smoothScrolling !== undefined) {
this.scrollable.setSmoothScrollDuration(options.smoothScrolling ? 125 : 0);
}
if (options.horizontalScrolling !== undefined) {
this.horizontalScrolling = options.horizontalScrolling;
}
}
triggerScrollFromMouseWheelEvent(browserEvent: IMouseWheelEvent) {
@@ -478,6 +517,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
private eventuallyUpdateScrollWidth(): void {
if (!this.horizontalScrolling) {
this.scrollableElementWidthDelayer.cancel();
return;
}
@@ -489,10 +529,6 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
return;
}
if (this.items.length === 0) {
this.scrollableElement.setScrollDimensions({ scrollWidth: 0 });
}
let scrollWidth = 0;
for (const item of this.items) {
@@ -502,7 +538,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
}
this.scrollWidth = scrollWidth;
this.scrollableElement.setScrollDimensions({ scrollWidth: scrollWidth + 10 });
this.scrollableElement.setScrollDimensions({ scrollWidth: scrollWidth === 0 ? 0 : (scrollWidth + 10) });
}
updateWidth(index: number): void {

View File

@@ -26,6 +26,7 @@ import { clamp } from 'vs/base/common/numbers';
import { matchesPrefix } from 'vs/base/common/filters';
import { IDragAndDropData } from 'vs/base/browser/dnd';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { IThemable } from 'vs/base/common/styler';
interface ITraitChangeEvent {
indexes: number[];
@@ -231,7 +232,6 @@ function isInputElement(e: HTMLElement): boolean {
class KeyboardController<T> implements IDisposable {
private readonly disposables = new DisposableStore();
private openController: IOpenController;
constructor(
private list: List<T>,
@@ -240,8 +240,6 @@ class KeyboardController<T> implements IDisposable {
) {
const multipleSelectionSupport = options.multipleSelectionSupport !== false;
this.openController = options.openController || DefaultOpenController;
const onKeyDown = Event.chain(domEvent(view.domNode, 'keydown'))
.filter(e => !isInputElement(e.target as HTMLElement))
.map(e => new StandardKeyboardEvent(e));
@@ -262,10 +260,6 @@ class KeyboardController<T> implements IDisposable {
e.preventDefault();
e.stopPropagation();
this.list.setSelection(this.list.getFocus(), e.browserEvent);
if (this.openController.shouldOpen(e.browserEvent)) {
this.list.open(this.list.getFocus(), e.browserEvent);
}
}
private onUpArrow(e: StandardKeyboardEvent): void {
@@ -527,24 +521,16 @@ const DefaultMultipleSelectionController = {
isSelectionRangeChangeEvent
};
const DefaultOpenController: IOpenController = {
shouldOpen: (event: UIEvent) => {
if (event instanceof MouseEvent) {
return !isMouseRightClick(event);
}
return true;
}
};
export class MouseController<T> implements IDisposable {
private multipleSelectionSupport: boolean;
readonly multipleSelectionController: IMultipleSelectionController<T> | undefined;
private openController: IOpenController;
private mouseSupport: boolean;
private readonly disposables = new DisposableStore();
private _onPointer = new Emitter<IListMouseEvent<T>>();
readonly onPointer: Event<IListMouseEvent<T>> = this._onPointer.event;
constructor(protected list: List<T>) {
this.multipleSelectionSupport = !(list.options.multipleSelectionSupport === false);
@@ -552,7 +538,6 @@ export class MouseController<T> implements IDisposable {
this.multipleSelectionController = list.options.multipleSelectionController || DefaultMultipleSelectionController;
}
this.openController = list.options.openController || DefaultOpenController;
this.mouseSupport = typeof list.options.mouseSupport === 'undefined' || !!list.options.mouseSupport;
if (this.mouseSupport) {
@@ -563,9 +548,7 @@ export class MouseController<T> implements IDisposable {
this.disposables.add(Gesture.addTarget(list.getHTMLElement()));
}
list.onMouseClick(this.onPointer, this, this.disposables);
list.onMouseMiddleClick(this.onPointer, this, this.disposables);
list.onTap(this.onPointer, this, this.disposables);
Event.any(list.onMouseClick, list.onMouseMiddleClick, list.onTap)(this.onViewPointer, this, this.disposables);
}
protected isSelectionSingleChangeEvent(event: IListMouseEvent<any> | IListTouchEvent<any>): boolean {
@@ -599,7 +582,7 @@ export class MouseController<T> implements IDisposable {
this.list.setFocus(focus, e.browserEvent);
}
protected onPointer(e: IListMouseEvent<T>): void {
protected onViewPointer(e: IListMouseEvent<T>): void {
if (!this.mouseSupport) {
return;
}
@@ -632,11 +615,9 @@ export class MouseController<T> implements IDisposable {
if (!isMouseRightClick(e.browserEvent)) {
this.list.setSelection([focus], e.browserEvent);
if (this.openController.shouldOpen(e.browserEvent)) {
this.list.open([focus], e.browserEvent);
}
}
this._onPointer.fire(e);
}
protected onDoubleClick(e: IListMouseEvent<T>): void {
@@ -650,7 +631,6 @@ export class MouseController<T> implements IDisposable {
const focus = this.list.getFocus();
this.list.setSelection(focus, e.browserEvent);
this.list.pin(focus);
}
private changeSelection(e: IListMouseEvent<T> | IListTouchEvent<T>, reference: number | undefined): void {
@@ -694,10 +674,6 @@ export interface IMultipleSelectionController<T> {
isSelectionRangeChangeEvent(event: IListMouseEvent<T> | IListTouchEvent<T>): boolean;
}
export interface IOpenController {
shouldOpen(event: UIEvent): boolean;
}
export interface IStyleController {
style(styles: IListStyles): void;
}
@@ -841,7 +817,6 @@ export interface IListOptions<T> {
readonly keyboardSupport?: boolean;
readonly multipleSelectionSupport?: boolean;
readonly multipleSelectionController?: IMultipleSelectionController<T>;
readonly openController?: IOpenController;
readonly styleController?: (suffix: string) => IStyleController;
readonly accessibilityProvider?: IListAccessibilityProvider<T>;
@@ -1112,7 +1087,7 @@ export interface IListOptionsUpdate extends IListViewOptionsUpdate {
readonly automaticKeyboardNavigation?: boolean;
}
export class List<T> implements ISpliceable<T>, IDisposable {
export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
private focus: Trait<T>;
private selection: Trait<T>;
@@ -1122,6 +1097,7 @@ export class List<T> implements ISpliceable<T>, IDisposable {
private styleController: IStyleController;
private typeLabelController?: TypeLabelController<T>;
private accessibilityProvider?: IListAccessibilityProvider<T>;
private mouseController: MouseController<T>;
private _ariaLabel: string = '';
protected readonly disposables = new DisposableStore();
@@ -1134,17 +1110,12 @@ export class List<T> implements ISpliceable<T>, IDisposable {
return Event.map(this.eventBufferer.wrapEvent(this.selection.onChange), e => this.toListEvent(e));
}
private readonly _onDidOpen = new Emitter<IListEvent<T>>();
readonly onDidOpen: Event<IListEvent<T>> = this._onDidOpen.event;
private readonly _onDidPin = new Emitter<IListEvent<T>>();
readonly onDidPin: Event<IListEvent<T>> = this._onDidPin.event;
get domId(): string { return this.view.domId; }
get onDidScroll(): Event<ScrollEvent> { return this.view.onDidScroll; }
get onMouseClick(): Event<IListMouseEvent<T>> { return this.view.onMouseClick; }
get onMouseDblClick(): Event<IListMouseEvent<T>> { return this.view.onMouseDblClick; }
get onMouseMiddleClick(): Event<IListMouseEvent<T>> { return this.view.onMouseMiddleClick; }
get onPointer(): Event<IListMouseEvent<T>> { return this.mouseController.onPointer; }
get onMouseUp(): Event<IListMouseEvent<T>> { return this.view.onMouseUp; }
get onMouseDown(): Event<IListMouseEvent<T>> { return this.view.onMouseDown; }
get onMouseOver(): Event<IListMouseEvent<T>> { return this.view.onMouseOver; }
@@ -1263,7 +1234,8 @@ export class List<T> implements ISpliceable<T>, IDisposable {
this.disposables.add(this.typeLabelController);
}
this.disposables.add(this.createMouseController(_options));
this.mouseController = this.createMouseController(_options);
this.disposables.add(this.mouseController);
this.onDidChangeFocus(this._onFocusChange, this, this.disposables);
this.onDidChangeSelection(this._onSelectionChange, this, this.disposables);
@@ -1625,26 +1597,6 @@ export class List<T> implements ISpliceable<T>, IDisposable {
return this.view.domNode;
}
open(indexes: number[], browserEvent?: UIEvent): void {
for (const index of indexes) {
if (index < 0 || index >= this.length) {
throw new ListError(this.user, `Invalid index ${index}`);
}
}
this._onDidOpen.fire({ indexes, elements: indexes.map(i => this.view.element(i)), browserEvent });
}
pin(indexes: number[], browserEvent?: UIEvent): void {
for (const index of indexes) {
if (index < 0 || index >= this.length) {
throw new ListError(this.user, `Invalid index ${index}`);
}
}
this._onDidPin.fire({ indexes, elements: indexes.map(i => this.view.element(i)), browserEvent });
}
style(styles: IListStyles): void {
this.styleController.style(styles);
}
@@ -1687,8 +1639,6 @@ export class List<T> implements ISpliceable<T>, IDisposable {
this._onDidDispose.fire();
this.disposables.dispose();
this._onDidOpen.dispose();
this._onDidPin.dispose();
this._onDidDispose.dispose();
}
}

View File

@@ -446,6 +446,16 @@ export class MenuBar extends Disposable {
return this.container.clientHeight;
}
toggleFocus(): void {
if (!this.isFocused && this.options.visibility !== 'hidden') {
this.mnemonicsInUse = true;
this.focusedMenu = { index: this.numMenusShown > 0 ? 0 : MenuBar.OVERFLOW_INDEX };
this.focusState = MenubarState.FOCUSED;
} else if (!this.isOpen) {
this.setUnfocusedState();
}
}
private updateOverflowAction(): void {
if (!this.menuCache || !this.menuCache.length) {
return;

View File

@@ -343,7 +343,13 @@ export abstract class AbstractScrollableElement extends Widget {
const classifier = MouseWheelClassifier.INSTANCE;
if (SCROLL_WHEEL_SMOOTH_SCROLL_ENABLED) {
classifier.accept(Date.now(), e.deltaX, e.deltaY);
if (platform.isWindows) {
// On Windows, the incoming delta events are multiplied with the device pixel ratio,
// so to get a better classification, simply undo that.
classifier.accept(Date.now(), e.deltaX / window.devicePixelRatio, e.deltaY / window.devicePixelRatio);
} else {
classifier.accept(Date.now(), e.deltaX, e.deltaY);
}
}
// console.log(`${Date.now()}, ${e.deltaY}, ${e.deltaX}`);

View File

@@ -30,7 +30,7 @@
.monaco-select-box-dropdown-container > .select-box-details-pane > .select-box-description-markdown code {
line-height: 15px; /** For some reason, this is needed, otherwise <code> will take up 20px height */
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
font-family: var(--monaco-monospace-font);
}

View File

@@ -475,6 +475,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
// Track initial selection the case user escape, blur
this._currentSelection = this.selected;
this._isVisible = true;
this.selectElement.setAttribute('aria-expanded', 'true');
}
private hideSelectDropDown(focusSelect: boolean) {
@@ -483,6 +484,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
}
this._isVisible = false;
this.selectElement.setAttribute('aria-expanded', 'false');
if (focusSelect) {
this.selectElement.focus();

View File

@@ -29,6 +29,7 @@
display: flex;
cursor: pointer;
align-items: center;
box-sizing: border-box;
}
.monaco-pane-view .pane.horizontal:not(.expanded) > .pane-header {

View File

@@ -69,7 +69,8 @@ export class ToolBar extends Disposable {
this.actionRunner,
this.options.getKeyBinding,
toolBarMoreIcon.classNames,
this.options.anchorAlignmentProvider
this.options.anchorAlignmentProvider,
true
);
this.toggleMenuActionViewItem.value.setActionContext(this.actionBar.context);

View File

@@ -6,7 +6,7 @@
import 'vs/css!./media/tree';
import { IDisposable, dispose, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IListOptions, List, IListStyles, MouseController, DefaultKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/listWidget';
import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IKeyboardNavigationLabelProvider, IIdentityProvider, IKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/list';
import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IKeyboardNavigationLabelProvider, IIdentityProvider, IKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/list';
import { append, $, toggleClass, getDomNodePagePosition, removeClass, addClass, hasClass, hasParentWithClass, createStyleSheet, clearNode, addClasses, removeClasses } from 'vs/base/browser/dom';
import { Event, Relay, Emitter, EventBufferer } from 'vs/base/common/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
@@ -22,7 +22,6 @@ import { getVisibleState, isFilterResult } from 'vs/base/browser/ui/tree/indexTr
import { localize } from 'vs/nls';
import { disposableTimeout } from 'vs/base/common/async';
import { isMacintosh } from 'vs/base/common/platform';
import { values } from 'vs/base/common/map';
import { clamp } from 'vs/base/common/numbers';
import { ScrollEvent } from 'vs/base/common/scrollable';
import { SetMap } from 'vs/base/common/collections';
@@ -922,13 +921,6 @@ function isInputElement(e: HTMLElement): boolean {
return e.tagName === 'INPUT' || e.tagName === 'TEXTAREA';
}
function asTreeEvent<T>(event: IListEvent<ITreeNode<T, any>>): ITreeEvent<T> {
return {
elements: event.elements.map(node => node.element),
browserEvent: event.browserEvent
};
}
function asTreeMouseEvent<T>(event: IListMouseEvent<ITreeNode<T, any>>): ITreeMouseEvent<T> {
let target: TreeMouseEventTarget = TreeMouseEventTarget.Unknown;
@@ -961,8 +953,8 @@ export interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions {
readonly automaticKeyboardNavigation?: boolean;
readonly simpleKeyboardNavigation?: boolean;
readonly filterOnType?: boolean;
readonly openOnSingleClick?: boolean;
readonly smoothScrolling?: boolean;
readonly horizontalScrolling?: boolean;
}
export interface IAbstractTreeOptions<T, TFilterData = void> extends IAbstractTreeOptionsUpdate, IListOptions<T> {
@@ -1042,7 +1034,7 @@ class Trait<T> {
const set = this.createNodeSet();
const visit = (node: ITreeNode<T, any>) => set.delete(node);
deletedNodes.forEach(node => dfs(node, visit));
this.set(values(set));
this.set([...set.values()]);
return;
}
@@ -1091,7 +1083,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
super(list);
}
protected onPointer(e: IListMouseEvent<ITreeNode<T, TFilterData>>): void {
protected onViewPointer(e: IListMouseEvent<ITreeNode<T, TFilterData>>): void {
if (isInputElement(e.browserEvent.target as HTMLElement)) {
return;
}
@@ -1099,19 +1091,14 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
const node = e.element;
if (!node) {
return super.onPointer(e);
return super.onViewPointer(e);
}
if (this.isSelectionRangeChangeEvent(e) || this.isSelectionSingleChangeEvent(e)) {
return super.onPointer(e);
return super.onViewPointer(e);
}
const onTwistie = hasClass(e.browserEvent.target as HTMLElement, 'monaco-tl-twistie');
if (!this.tree.openOnSingleClick && e.browserEvent.detail !== 2 && !onTwistie) {
return super.onPointer(e);
}
let expandOnlyOnTwistieClick = false;
if (typeof this.tree.expandOnlyOnTwistieClick === 'function') {
@@ -1121,7 +1108,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
}
if (expandOnlyOnTwistieClick && !onTwistie) {
return super.onPointer(e);
return super.onViewPointer(e);
}
if (node.collapsible) {
@@ -1135,7 +1122,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
}
}
super.onPointer(e);
super.onViewPointer(e);
}
protected onDoubleClick(e: IListMouseEvent<ITreeNode<T, TFilterData>>): void {
@@ -1238,12 +1225,12 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
get onDidChangeFocus(): Event<ITreeEvent<T>> { return this.eventBufferer.wrapEvent(this.focus.onDidChange); }
get onDidChangeSelection(): Event<ITreeEvent<T>> { return this.eventBufferer.wrapEvent(this.selection.onDidChange); }
get onDidOpen(): Event<ITreeEvent<T>> { return Event.map(this.view.onDidOpen, asTreeEvent); }
get onDidPin(): Event<ITreeEvent<T>> { return Event.map(this.view.onDidPin, asTreeEvent); }
get onMouseClick(): Event<ITreeMouseEvent<T>> { return Event.map(this.view.onMouseClick, asTreeMouseEvent); }
get onMouseDblClick(): Event<ITreeMouseEvent<T>> { return Event.map(this.view.onMouseDblClick, asTreeMouseEvent); }
get onContextMenu(): Event<ITreeContextMenuEvent<T>> { return Event.map(this.view.onContextMenu, asTreeContextMenuEvent); }
get onTap(): Event<ITreeMouseEvent<T>> { return Event.map(this.view.onTap, asTreeMouseEvent); }
get onPointer(): Event<ITreeMouseEvent<T>> { return Event.map(this.view.onPointer, asTreeMouseEvent); }
get onKeyDown(): Event<KeyboardEvent> { return this.view.onKeyDown; }
get onKeyUp(): Event<KeyboardEvent> { return this.view.onKeyUp; }
@@ -1261,7 +1248,6 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
get filterOnType(): boolean { return !!this._options.filterOnType; }
get onDidChangeTypeFilterPattern(): Event<string> { return this.typeFilterController ? this.typeFilterController.onDidChangePattern : Event.None; }
get openOnSingleClick(): boolean { return typeof this._options.openOnSingleClick === 'undefined' ? true : this._options.openOnSingleClick; }
get expandOnlyOnTwistieClick(): boolean | ((e: T) => boolean) { return typeof this._options.expandOnlyOnTwistieClick === 'undefined' ? false : this._options.expandOnlyOnTwistieClick; }
private readonly _onDidUpdateOptions = new Emitter<IAbstractTreeOptions<T, TFilterData>>();
@@ -1328,7 +1314,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
set.add(node);
}
return values(set);
return [...set.values()];
}).event;
if (_options.keyboardSupport !== false) {
@@ -1362,7 +1348,8 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
this.view.updateOptions({
enableKeyboardNavigation: this._options.simpleKeyboardNavigation,
automaticKeyboardNavigation: this._options.automaticKeyboardNavigation,
smoothScrolling: this._options.smoothScrolling
smoothScrolling: this._options.smoothScrolling,
horizontalScrolling: this._options.horizontalScrolling
});
if (this.typeFilterController) {
@@ -1601,11 +1588,6 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
return this.focus.get();
}
open(elements: TRef[], browserEvent?: UIEvent): void {
const indexes = elements.map(e => this.model.getListIndex(e)).filter(i => i >= 0);
this.view.open(indexes, browserEvent);
}
reveal(location: TRef, relativeTop?: number): void {
this.model.expandTo(location);

View File

@@ -16,7 +16,6 @@ import { IDragAndDropData } from 'vs/base/browser/dnd';
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
import { isPromiseCanceledError, onUnexpectedError } from 'vs/base/common/errors';
import { removeClasses, addClasses } from 'vs/base/browser/dom';
import { values } from 'vs/base/common/map';
import { ScrollEvent } from 'vs/base/common/scrollable';
import { ICompressedTreeNode, ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
import { IThemable } from 'vs/base/common/styler';
@@ -331,12 +330,13 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
get onDidChangeFocus(): Event<ITreeEvent<T>> { return Event.map(this.tree.onDidChangeFocus, asTreeEvent); }
get onDidChangeSelection(): Event<ITreeEvent<T>> { return Event.map(this.tree.onDidChangeSelection, asTreeEvent); }
get onDidOpen(): Event<ITreeEvent<T>> { return Event.map(this.tree.onDidOpen, asTreeEvent); }
get onKeyDown(): Event<KeyboardEvent> { return this.tree.onKeyDown; }
get onMouseClick(): Event<ITreeMouseEvent<T>> { return Event.map(this.tree.onMouseClick, asTreeMouseEvent); }
get onMouseDblClick(): Event<ITreeMouseEvent<T>> { return Event.map(this.tree.onMouseDblClick, asTreeMouseEvent); }
get onContextMenu(): Event<ITreeContextMenuEvent<T>> { return Event.map(this.tree.onContextMenu, asTreeContextMenuEvent); }
get onTap(): Event<ITreeMouseEvent<T>> { return Event.map(this.tree.onTap, asTreeMouseEvent); }
get onPointer(): Event<ITreeMouseEvent<T>> { return Event.map(this.tree.onPointer, asTreeMouseEvent); }
get onDidFocus(): Event<void> { return this.tree.onDidFocus; }
get onDidBlur(): Event<void> { return this.tree.onDidBlur; }
@@ -345,7 +345,6 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
get onDidUpdateOptions(): Event<IAsyncDataTreeOptionsUpdate> { return this.tree.onDidUpdateOptions; }
get filterOnType(): boolean { return this.tree.filterOnType; }
get openOnSingleClick(): boolean { return this.tree.openOnSingleClick; }
get expandOnlyOnTwistieClick(): boolean | ((e: T) => boolean) {
if (typeof this.tree.expandOnlyOnTwistieClick === 'boolean') {
return this.tree.expandOnlyOnTwistieClick;
@@ -408,6 +407,10 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
this.tree.updateOptions(options);
}
get options(): IAsyncDataTreeOptions<T, TFilterData> {
return this.tree.options as unknown as IAsyncDataTreeOptions<T, TFilterData>; // {{SQL CARBON EDIT}} strict-null-check
}
// Widget
getHTMLElement(): HTMLElement {
@@ -668,11 +671,6 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return nodes.map(n => n!.element as T);
}
open(elements: T[], browserEvent?: UIEvent): void {
const nodes = elements.map(e => this.getDataNode(e));
this.tree.open(nodes, browserEvent);
}
reveal(element: T, relativeTop?: number): void {
this.tree.reveal(this.getDataNode(element), relativeTop);
}
@@ -904,7 +902,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return childAsyncDataTreeNode;
});
for (const node of values(nodesToForget)) {
for (const node of nodesToForget.values()) {
dfs(node, node => this.nodes.delete(node.element as T));
}