mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 4d91d96e5e121b38d33508cdef17868bab255eae
This commit is contained in:
committed by
AzureDataStudio
parent
a971aee5bd
commit
5e7071e466
@@ -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'],
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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}`);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.monaco-pane-view .pane.horizontal:not(.expanded) > .pane-header {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user