chore(vscode): update to 1.56.0

This commit is contained in:
Akash Satheesan
2021-04-30 20:25:17 +05:30
1749 changed files with 88014 additions and 43316 deletions

View File

@@ -20,7 +20,7 @@ export interface IContextMenuDelegate {
getActions(): readonly IAction[];
getCheckedActionsRepresentation?(action: IAction): 'radio' | 'checkbox';
getActionViewItem?(action: IAction): IActionViewItem | undefined;
getActionsContext?(event?: IContextMenuEvent): any;
getActionsContext?(event?: IContextMenuEvent): unknown;
getKeyBinding?(action: IAction): ResolvedKeybinding | undefined;
getMenuClassName?(): string;
onHide?(didCancel: boolean): void;

View File

@@ -42,7 +42,7 @@ export class DelayedDragHandler extends Disposable {
}
}
dispose(): void {
override dispose(): void {
super.dispose();
this.clearDragTimeout();
@@ -89,7 +89,7 @@ export function applyDragImage(event: DragEvent, label: string | null, clazz: st
export interface IDragAndDropData {
update(dataTransfer: DataTransfer): void;
getData(): any;
getData(): unknown;
}
export class DragAndDropData<T> implements IDragAndDropData {

View File

@@ -1193,18 +1193,21 @@ export function computeScreenAwareSize(cssPx: number): number {
* to change the location of the current page.
* See https://mathiasbynens.github.io/rel-noopener/
*/
export function windowOpenNoOpener(url: string): void {
export function windowOpenNoOpener(url: string): boolean {
if (browser.isElectron || browser.isEdgeLegacyWebView) {
// In VSCode, window.open() always returns null...
// The same is true for a WebView (see https://github.com/microsoft/monaco-editor/issues/628)
// Also call directly window.open in sandboxed Electron (see https://github.com/microsoft/monaco-editor/issues/2220)
window.open(url);
return true;
} else {
let newTab = window.open();
if (newTab) {
(newTab as any).opener = null;
newTab.location.href = url;
return true;
}
return false;
}
}
@@ -1409,37 +1412,8 @@ export function multibyteAwareBtoa(str: string): string {
*/
export namespace WebFileSystemAccess {
// https://wicg.github.io/file-system-access/#dom-window-showdirectorypicker
export interface FileSystemAccess {
showDirectoryPicker: () => Promise<FileSystemDirectoryHandle>;
}
// https://wicg.github.io/file-system-access/#api-filesystemdirectoryhandle
export interface FileSystemDirectoryHandle {
readonly kind: 'directory',
readonly name: string,
getFileHandle: (name: string, options?: { create?: boolean }) => Promise<FileSystemFileHandle>;
getDirectoryHandle: (name: string, options?: { create?: boolean }) => Promise<FileSystemDirectoryHandle>;
}
// https://wicg.github.io/file-system-access/#api-filesystemfilehandle
export interface FileSystemFileHandle {
readonly kind: 'file',
readonly name: string,
createWritable: (options?: { keepExistingData?: boolean }) => Promise<FileSystemWritableFileStream>;
}
// https://wicg.github.io/file-system-access/#api-filesystemwritablefilestream
export interface FileSystemWritableFileStream {
write: (buffer: Uint8Array) => Promise<void>;
close: () => Promise<void>;
}
export function supported(obj: any & Window): obj is FileSystemAccess {
const candidate = obj as FileSystemAccess | undefined;
if (typeof candidate?.showDirectoryPicker === 'function') {
export function supported(obj: any & Window): boolean {
if (typeof obj?.showDirectoryPicker === 'function') {
return true;
}
@@ -1589,7 +1563,7 @@ export class ModifierKeyEmitter extends Emitter<IModifierKeyStatus> {
return ModifierKeyEmitter.instance;
}
dispose() {
override dispose() {
super.dispose();
this._subscriptions.dispose();
}

View File

@@ -9,7 +9,7 @@ export type EventHandler = HTMLElement | HTMLDocument | Window;
export interface IDomEvent {
<K extends keyof HTMLElementEventMap>(element: EventHandler, type: K, useCapture?: boolean): BaseEvent<HTMLElementEventMap[K]>;
(element: EventHandler, type: string, useCapture?: boolean): BaseEvent<any>;
(element: EventHandler, type: string, useCapture?: boolean): BaseEvent<unknown>;
}
export const domEvent: IDomEvent = (element: EventHandler, type: string, useCapture?: boolean) => {

View File

@@ -16,6 +16,7 @@ export interface FormattedTextRenderOptions {
readonly className?: string;
readonly inline?: boolean;
readonly actionHandler?: IContentActionHandler;
readonly renderCodeSegements?: boolean;
}
export function renderText(text: string, options: FormattedTextRenderOptions = {}): HTMLElement {
@@ -26,7 +27,7 @@ export function renderText(text: string, options: FormattedTextRenderOptions = {
export function renderFormattedText(formattedText: string, options: FormattedTextRenderOptions = {}): HTMLElement {
const element = createElement(options);
_renderFormattedText(element, parseFormattedText(formattedText), options.actionHandler);
_renderFormattedText(element, parseFormattedText(formattedText, !!options.renderCodeSegements), options.actionHandler, options.renderCodeSegements);
return element;
}
@@ -75,6 +76,7 @@ const enum FormatType {
Italics,
Action,
ActionClose,
Code,
NewLine
}
@@ -85,7 +87,7 @@ interface IFormatParseTree {
children?: IFormatParseTree[];
}
function _renderFormattedText(element: Node, treeNode: IFormatParseTree, actionHandler?: IContentActionHandler) {
function _renderFormattedText(element: Node, treeNode: IFormatParseTree, actionHandler?: IContentActionHandler, renderCodeSegements?: boolean) {
let child: Node | undefined;
if (treeNode.type === FormatType.Text) {
@@ -94,6 +96,8 @@ function _renderFormattedText(element: Node, treeNode: IFormatParseTree, actionH
child = document.createElement('b');
} else if (treeNode.type === FormatType.Italics) {
child = document.createElement('i');
} else if (treeNode.type === FormatType.Code && renderCodeSegements) {
child = document.createElement('code');
} else if (treeNode.type === FormatType.Action && actionHandler) {
const a = document.createElement('a');
a.href = '#';
@@ -114,12 +118,12 @@ function _renderFormattedText(element: Node, treeNode: IFormatParseTree, actionH
if (child && Array.isArray(treeNode.children)) {
treeNode.children.forEach((nodeChild) => {
_renderFormattedText(child!, nodeChild, actionHandler);
_renderFormattedText(child!, nodeChild, actionHandler, renderCodeSegements);
});
}
}
function parseFormattedText(content: string): IFormatParseTree {
function parseFormattedText(content: string, parseCodeSegments: boolean): IFormatParseTree {
const root: IFormatParseTree = {
type: FormatType.Root,
@@ -134,19 +138,19 @@ function parseFormattedText(content: string): IFormatParseTree {
while (!stream.eos()) {
let next = stream.next();
const isEscapedFormatType = (next === '\\' && formatTagType(stream.peek()) !== FormatType.Invalid);
const isEscapedFormatType = (next === '\\' && formatTagType(stream.peek(), parseCodeSegments) !== FormatType.Invalid);
if (isEscapedFormatType) {
next = stream.next(); // unread the backslash if it escapes a format tag type
}
if (!isEscapedFormatType && isFormatTag(next) && next === stream.peek()) {
if (!isEscapedFormatType && isFormatTag(next, parseCodeSegments) && next === stream.peek()) {
stream.advance();
if (current.type === FormatType.Text) {
current = stack.pop()!;
}
const type = formatTagType(next);
const type = formatTagType(next, parseCodeSegments);
if (current.type === type || (current.type === FormatType.Action && type === FormatType.ActionClose)) {
current = stack.pop()!;
} else {
@@ -200,11 +204,11 @@ function parseFormattedText(content: string): IFormatParseTree {
return root;
}
function isFormatTag(char: string): boolean {
return formatTagType(char) !== FormatType.Invalid;
function isFormatTag(char: string, supportCodeSegments: boolean): boolean {
return formatTagType(char, supportCodeSegments) !== FormatType.Invalid;
}
function formatTagType(char: string): FormatType {
function formatTagType(char: string, supportCodeSegments: boolean): FormatType {
switch (char) {
case '*':
return FormatType.Bold;
@@ -214,6 +218,8 @@ function formatTagType(char: string): FormatType {
return FormatType.Action;
case ']':
return FormatType.ActionClose;
case '`':
return supportCodeSegments ? FormatType.Code : FormatType.Invalid;
default:
return FormatType.Invalid;
}

View File

@@ -136,7 +136,7 @@ export class Gesture extends Disposable {
return 'ontouchstart' in window || navigator.maxTouchPoints > 0 || (window as Window).navigator.msMaxTouchPoints > 0;
}
public dispose(): void {
public override dispose(): void {
if (this.handle) {
this.handle.dispose();
this.handle = null;

View File

@@ -27,12 +27,12 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
element: HTMLElement | undefined;
_context: any;
_context: unknown;
_action: IAction;
private _actionRunner: IActionRunner | undefined;
constructor(context: any, action: IAction, protected options: IBaseActionViewItemOptions = {}) {
constructor(context: unknown, action: IAction, protected options: IBaseActionViewItemOptions = {}) {
super();
this._context = context || this;
@@ -174,6 +174,10 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
}
}
isFocused(): boolean {
return !!this.element?.classList.contains('focused');
}
blur(): void {
if (this.element) {
this.element.blur();
@@ -212,7 +216,7 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
// implement in subclass
}
dispose(): void {
override dispose(): void {
if (this.element) {
this.element.remove();
this.element = undefined;
@@ -231,7 +235,7 @@ export interface IActionViewItemOptions extends IBaseActionViewItemOptions {
export class ActionViewItem extends BaseActionViewItem {
protected label: HTMLElement | undefined;
protected options: IActionViewItemOptions;
protected override options: IActionViewItemOptions;
private cssClass?: string;
@@ -244,7 +248,7 @@ export class ActionViewItem extends BaseActionViewItem {
this.cssClass = '';
}
render(container: HTMLElement): void {
override render(container: HTMLElement): void {
super.render(container);
if (this.element) {
@@ -276,32 +280,36 @@ export class ActionViewItem extends BaseActionViewItem {
// Only set the tabIndex on the element once it is about to get focused
// That way this element wont be a tab stop when it is not needed #106441
focus(): void {
override focus(): void {
if (this.label) {
this.label.tabIndex = 0;
this.label.focus();
}
}
blur(): void {
override isFocused(): boolean {
return !!this.label && this.label?.tabIndex === 0;
}
override blur(): void {
if (this.label) {
this.label.tabIndex = -1;
}
}
setFocusable(focusable: boolean): void {
override setFocusable(focusable: boolean): void {
if (this.label) {
this.label.tabIndex = focusable ? 0 : -1;
}
}
updateLabel(): void {
override updateLabel(): void {
if (this.options.label && this.label) {
this.label.textContent = this.getAction().label;
}
}
updateTooltip(): void {
override updateTooltip(): void {
let title: string | null = null;
if (this.getAction().tooltip) {
@@ -320,7 +328,7 @@ export class ActionViewItem extends BaseActionViewItem {
}
}
updateClass(): void {
override updateClass(): void {
if (this.cssClass && this.label) {
this.label.classList.remove(...this.cssClass.split(' '));
}
@@ -343,7 +351,7 @@ export class ActionViewItem extends BaseActionViewItem {
}
}
updateEnabled(): void {
override updateEnabled(): void {
if (this.getAction().enabled) {
if (this.label) {
this.label.removeAttribute('aria-disabled');
@@ -365,7 +373,7 @@ export class ActionViewItem extends BaseActionViewItem {
}
}
updateChecked(): void {
override updateChecked(): void {
if (this.label) {
if (this.getAction().checked) {
this.label.classList.add('checked');
@@ -407,23 +415,23 @@ export class SelectActionViewItem extends BaseActionViewItem {
return option;
}
setFocusable(focusable: boolean): void {
override setFocusable(focusable: boolean): void {
this.selectBox.setFocusable(focusable);
}
focus(): void {
override focus(): void {
if (this.selectBox) {
this.selectBox.focus();
}
}
blur(): void {
override blur(): void {
if (this.selectBox) {
this.selectBox.blur();
}
}
render(container: HTMLElement): void {
override render(container: HTMLElement): void {
this.selectBox.render(container);
}
}

View File

@@ -4,16 +4,17 @@
*--------------------------------------------------------------------------------------------*/
.monaco-action-bar {
text-align: right;
white-space: nowrap;
height: 100%;
}
.monaco-action-bar .actions-container {
display: flex;
margin: 0 auto;
padding: 0;
height: 100%;
width: 100%;
justify-content: flex-end;
align-items: center;
}
.monaco-action-bar.vertical .actions-container {
@@ -21,9 +22,10 @@
}
.monaco-action-bar .action-item {
display: block;
align-items: center;
justify-content: center;
cursor: pointer;
display: inline-block;
transition: transform 50ms ease;
position: relative; /* DO NOT REMOVE - this is the key to preventing the ghosting icon bug in Chrome 42 */
}
@@ -31,23 +33,22 @@
cursor: default;
}
.monaco-action-bar.animated .action-item.active {
transform: scale(1.272019649, 1.272019649); /* 1.272019649 = √φ */
}
.monaco-action-bar .action-item .icon,
.monaco-action-bar .action-item .codicon {
display: inline-block;
display: block;
}
.monaco-action-bar .action-item .codicon {
display: flex;
align-items: center;
width: 16px;
height: 16px;
}
.monaco-action-bar .action-label {
font-size: 11px;
margin-right: 4px;
padding: 3px;
border-radius: 5px;
}
.monaco-action-bar .action-item.disabled .action-label,
@@ -74,10 +75,6 @@
margin-right: .8em;
}
.monaco-action-bar.animated.vertical .action-item.active {
transform: translate(5px, 0);
}
.secondary-actions .monaco-action-bar .action-label {
margin-left: 6px;
}

View File

@@ -15,7 +15,7 @@ import { IActionViewItemOptions, ActionViewItem, BaseActionViewItem } from 'vs/b
export interface IActionViewItem extends IDisposable {
actionRunner: IActionRunner;
setActionContext(context: any): void;
setActionContext(context: unknown): void;
render(element: HTMLElement): void;
isEnabled(): boolean;
focus(fromRight?: boolean): void; // TODO@isidorn what is this?
@@ -38,7 +38,7 @@ export interface ActionTrigger {
export interface IActionBarOptions {
readonly orientation?: ActionsOrientation;
readonly context?: any;
readonly context?: unknown;
readonly actionViewItemProvider?: IActionViewItemProvider;
readonly actionRunner?: IActionRunner;
readonly ariaLabel?: string;
@@ -264,11 +264,11 @@ export class ActionBar extends Disposable implements IActionRunner {
}
}
get context(): any {
get context(): unknown {
return this._context;
}
set context(context: any) {
set context(context: unknown) {
this._context = context;
this.viewItems.forEach(i => i.setActionContext(context));
}
@@ -525,11 +525,11 @@ export class ActionBar extends Disposable implements IActionRunner {
}
}
run(action: IAction, context?: unknown): Promise<void> {
return this._actionRunner.run(action, context);
async run(action: IAction, context?: unknown): Promise<void> {
await this._actionRunner.run(action, context);
}
dispose(): void {
override dispose(): void {
dispose(this.viewItems);
this.viewItems = [];

View File

@@ -24,6 +24,9 @@
height: 100%;
outline: none;
}
.monaco-breadcrumbs.disabled .monaco-breadcrumb-item {
cursor: default;
}
.monaco-breadcrumbs .monaco-breadcrumb-item .codicon-breadcrumb-separator {
color: inherit;

View File

@@ -56,6 +56,7 @@ export class BreadcrumbsWidget {
private readonly _nodes = new Array<HTMLDivElement>();
private readonly _freeNodes = new Array<HTMLDivElement>();
private _enabled: boolean = true;
private _focusedItemIdx: number = -1;
private _selectedItemIdx: number = -1;
@@ -155,13 +156,18 @@ export class BreadcrumbsWidget {
content += `.monaco-breadcrumbs .monaco-breadcrumb-item.focused.selected { color: ${style.breadcrumbsFocusAndSelectionForeground}}\n`;
}
if (style.breadcrumbsHoverForeground) {
content += `.monaco-breadcrumbs .monaco-breadcrumb-item:hover:not(.focused):not(.selected) { color: ${style.breadcrumbsHoverForeground}}\n`;
content += `.monaco-breadcrumbs:not(.disabled ) .monaco-breadcrumb-item:hover:not(.focused):not(.selected) { color: ${style.breadcrumbsHoverForeground}}\n`;
}
if (this._styleElement.innerText !== content) {
this._styleElement.innerText = content;
}
}
setEnabled(value: boolean) {
this._enabled = value;
this._domNode.classList.toggle('disabled', !this._enabled);
}
domFocus(): void {
let idx = this._focusedItemIdx >= 0 ? this._focusedItemIdx : this._items.length - 1;
if (idx >= 0 && idx < this._items.length) {
@@ -326,6 +332,9 @@ export class BreadcrumbsWidget {
}
private _onClick(event: IMouseEvent): void {
if (!this._enabled) {
return;
}
for (let el: HTMLElement | null = event.target; el; el = el.parentElement) {
let idx = this._nodes.indexOf(el as HTMLDivElement);
if (idx >= 0) {

View File

@@ -22,8 +22,9 @@
text-decoration: none !important;
}
.monaco-button.disabled:focus,
.monaco-button.disabled {
opacity: 0.4;
opacity: 0.4 !important;
cursor: default;
}
@@ -39,3 +40,15 @@
.monaco-button-dropdown > .monaco-dropdown-button {
margin-left: 1px;
}
.monaco-description-button {
flex-direction: column;
}
.monaco-description-button .monaco-button-label {
font-weight: 500;
}
.monaco-description-button .monaco-button-description {
font-style: italic;
}

View File

@@ -50,6 +50,10 @@ export interface IButton extends IDisposable {
hasFocus(): boolean;
}
export interface IButtonWithDescription extends IButton {
description: string;
}
export class Button extends Disposable implements IButton {
private _element: HTMLElement;
@@ -303,6 +307,207 @@ export class ButtonWithDropdown extends Disposable implements IButton {
}
}
export class ButtonWithDescription extends Disposable implements IButtonWithDescription {
private _element: HTMLElement;
private _labelElement: HTMLElement;
private _descriptionElement: HTMLElement;
private options: IButtonOptions;
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>());
get onDidClick(): BaseEvent<Event> { return this._onDidClick.event; }
private focusTracker: IFocusTracker;
constructor(container: HTMLElement, options?: IButtonOptions) {
super();
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.buttonSecondaryForeground = this.options.buttonSecondaryForeground;
this.buttonSecondaryBackground = this.options.buttonSecondaryBackground;
this.buttonSecondaryHoverBackground = this.options.buttonSecondaryHoverBackground;
this.buttonBorder = this.options.buttonBorder;
this._element = document.createElement('a');
this._element.classList.add('monaco-button');
this._element.classList.add('monaco-description-button');
this._element.tabIndex = 0;
this._element.setAttribute('role', 'button');
this._labelElement = document.createElement('div');
this._labelElement.classList.add('monaco-button-label');
this._labelElement.tabIndex = -1;
this._element.appendChild(this._labelElement);
this._descriptionElement = document.createElement('div');
this._descriptionElement.classList.add('monaco-button-description');
this._descriptionElement.tabIndex = -1;
this._element.appendChild(this._descriptionElement);
container.appendChild(this._element);
this._register(Gesture.addTarget(this._element));
[EventType.CLICK, TouchEventType.Tap].forEach(eventType => {
this._register(addDisposableListener(this._element, eventType, e => {
if (!this.enabled) {
EventHelper.stop(e);
return;
}
this._onDidClick.fire(e);
}));
});
this._register(addDisposableListener(this._element, EventType.KEY_DOWN, e => {
const event = new StandardKeyboardEvent(e);
let eventHandled = false;
if (this.enabled && (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space))) {
this._onDidClick.fire(e);
eventHandled = true;
} else if (event.equals(KeyCode.Escape)) {
this._element.blur();
eventHandled = true;
}
if (eventHandled) {
EventHelper.stop(event, true);
}
}));
this._register(addDisposableListener(this._element, EventType.MOUSE_OVER, e => {
if (!this._element.classList.contains('disabled')) {
this.setHoverBackground();
}
}));
this._register(addDisposableListener(this._element, EventType.MOUSE_OUT, e => {
this.applyStyles(); // restore standard styles
}));
// Also set hover background when button is focused for feedback
this.focusTracker = this._register(trackFocus(this._element));
this._register(this.focusTracker.onDidFocus(() => this.setHoverBackground()));
this._register(this.focusTracker.onDidBlur(() => this.applyStyles())); // restore standard styles
this.applyStyles();
}
private setHoverBackground(): void {
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;
}
}
style(styles: IButtonStyles): void {
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();
}
private applyStyles(): void {
if (this._element) {
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;
this._element.style.backgroundColor = background;
this._element.style.borderWidth = border ? '1px' : '';
this._element.style.borderStyle = border ? 'solid' : '';
this._element.style.borderColor = border;
}
}
get element(): HTMLElement {
return this._element;
}
set label(value: string) {
this._element.classList.add('monaco-text-button');
if (this.options.supportIcons) {
reset(this._labelElement, ...renderLabelWithIcons(value));
} else {
this._labelElement.textContent = value;
}
if (typeof this.options.title === 'string') {
this._element.title = this.options.title;
} else if (this.options.title) {
this._element.title = value;
}
}
set description(value: string) {
if (this.options.supportIcons) {
reset(this._descriptionElement, ...renderLabelWithIcons(value));
} else {
this._descriptionElement.textContent = value;
}
}
set icon(icon: CSSIcon) {
this._element.classList.add(...CSSIcon.asClassNameArray(icon));
}
set enabled(value: boolean) {
if (value) {
this._element.classList.remove('disabled');
this._element.setAttribute('aria-disabled', String(false));
this._element.tabIndex = 0;
} else {
this._element.classList.add('disabled');
this._element.setAttribute('aria-disabled', String(true));
}
}
get enabled() {
return !this._element.classList.contains('disabled');
}
focus(): void {
this._element.focus();
}
hasFocus(): boolean {
return this._element === document.activeElement;
}
}
export class ButtonBar extends Disposable {
private _buttons: IButton[] = [];
@@ -321,6 +526,12 @@ export class ButtonBar extends Disposable {
return button;
}
addButtonWithDescription(options?: IButtonOptions): IButtonWithDescription {
const button = this._register(new ButtonWithDescription(this.container, options));
this.pushButton(button);
return button;
}
addButtonWithDropdown(options: IButtonWithDropdownOptions): IButton {
const button = this._register(new ButtonWithDropdown(this.container, options));
this.pushButton(button);

View File

@@ -44,7 +44,7 @@ export class CheckboxActionViewItem extends BaseActionViewItem {
protected checkbox: Checkbox | undefined;
protected readonly disposables = new DisposableStore();
render(container: HTMLElement): void {
override render(container: HTMLElement): void {
this.element = container;
this.disposables.clear();
@@ -59,7 +59,7 @@ export class CheckboxActionViewItem extends BaseActionViewItem {
this.element.appendChild(this.checkbox.domNode);
}
updateEnabled(): void {
override updateEnabled(): void {
if (this.checkbox) {
if (this.isEnabled()) {
this.checkbox.enable();
@@ -69,33 +69,33 @@ export class CheckboxActionViewItem extends BaseActionViewItem {
}
}
updateChecked(): void {
override updateChecked(): void {
if (this.checkbox) {
this.checkbox.checked = this._action.checked;
}
}
focus(): void {
override focus(): void {
if (this.checkbox) {
this.checkbox.domNode.tabIndex = 0;
this.checkbox.focus();
}
}
blur(): void {
override blur(): void {
if (this.checkbox) {
this.checkbox.domNode.tabIndex = -1;
this.checkbox.domNode.blur();
}
}
setFocusable(focusable: boolean): void {
override setFocusable(focusable: boolean): void {
if (this.checkbox) {
this.checkbox.domNode.tabIndex = focusable ? 0 : -1;
}
}
dispose(): void {
override dispose(): void {
this.disposables.dispose();
super.dispose();
}

View File

@@ -13,7 +13,10 @@
}
}
.codicon-sync.codicon-modifier-spin, .codicon-loading.codicon-modifier-spin, .codicon-gear.codicon-modifier-spin {
.codicon-sync.codicon-modifier-spin,
.codicon-loading.codicon-modifier-spin,
.codicon-gear.codicon-modifier-spin,
.codicon-notebook-state-executing.codicon-modifier-spin {
/* Use steps to throttle FPS to reduce CPU usage */
animation: codicon-spin 1.5s steps(30) infinite;
}

View File

@@ -45,7 +45,7 @@ export interface IDelegate {
anchorAxisAlignment?: AnchorAxisAlignment; // default: vertical
canRelayout?: boolean; // default: true
onDOMEvent?(e: Event, activeElement: HTMLElement): void;
onHide?(data?: any): void;
onHide?(data?: unknown): void;
}
export interface IContextViewProvider {
@@ -324,7 +324,7 @@ export class ContextView extends Disposable {
this.view.style.width = 'initial';
}
hide(data?: any): void {
hide(data?: unknown): void {
const delegate = this.delegate;
this.delegate = null;
@@ -351,7 +351,7 @@ export class ContextView extends Disposable {
}
}
dispose(): void {
override dispose(): void {
this.hide();
super.dispose();

View File

@@ -10,7 +10,7 @@
width: 100%;
left:0;
top:0;
z-index: 2000;
z-index: 2600;
display: flex;
justify-content: center;
align-items: center;
@@ -34,17 +34,12 @@
/** Dialog: Title Actions Row */
.monaco-dialog-box .dialog-toolbar-row {
height: 22px;
padding-bottom: 4px;
}
.monaco-dialog-box .action-label {
height: 16px;
min-width: 16px;
background-size: 16px;
background-position: 50%;
background-repeat: no-repeat;
margin: 0px;
margin-left: 4px;
.monaco-dialog-box .dialog-toolbar-row .actions-container {
justify-content: flex-end;
}
/** Dialog: Message Row */
@@ -144,6 +139,10 @@
overflow: hidden;
}
.monaco-dialog-box > .dialog-buttons-row > .dialog-buttons.centered {
justify-content: center;
}
.monaco-dialog-box > .dialog-buttons-row > .dialog-buttons > .monaco-button {
width: fit-content;
width: -moz-fit-content;

View File

@@ -11,7 +11,7 @@ import { domEvent } from 'vs/base/browser/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { Color } from 'vs/base/common/color';
import { ButtonBar, IButtonStyles } from 'vs/base/browser/ui/button/button';
import { ButtonBar, ButtonWithDescription, IButtonStyles } from 'vs/base/browser/ui/button/button';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { Action } from 'vs/base/common/actions';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
@@ -34,6 +34,10 @@ export interface IDialogOptions {
readonly type?: 'none' | 'info' | 'error' | 'question' | 'warning' | 'pending';
readonly inputs?: IDialogInputOptions[];
readonly keyEventProcessor?: (event: StandardKeyboardEvent) => void;
readonly renderBody?: (container: HTMLElement) => void;
readonly icon?: Codicon;
readonly buttonDetails?: string[];
readonly disableCloseAction?: boolean;
}
export interface IDialogResult {
@@ -53,6 +57,8 @@ export interface IDialogStyles extends IButtonStyles, ISimpleCheckboxStyles {
readonly inputBackground?: Color;
readonly inputForeground?: Color;
readonly inputBorder?: Color;
readonly textLinkForeground?: Color;
}
interface ButtonMapEntry {
@@ -71,6 +77,7 @@ export class Dialog extends Disposable {
private modalElement: HTMLElement | undefined;
private readonly buttonsContainer: HTMLElement;
private readonly messageDetailElement: HTMLElement;
private readonly messageContainer: HTMLElement;
private readonly iconElement: HTMLElement;
private readonly checkbox: SimpleCheckbox | undefined;
private readonly toolbarContainer: HTMLElement;
@@ -83,7 +90,7 @@ export class Dialog extends Disposable {
constructor(private container: HTMLElement, private message: string, buttons: string[], private options: IDialogOptions) {
super();
this.modalElement = this.container.appendChild($(`.monaco-dialog-modal-block${options.type === 'pending' ? '.dimmed' : ''}`));
this.modalElement = this.container.appendChild($(`.monaco-dialog-modal-block.dimmed`));
this.shadowElement = this.modalElement.appendChild($('.dialog-shadow'));
this.element = this.shadowElement.appendChild($('.monaco-dialog-box'));
this.element.setAttribute('role', 'dialog');
@@ -95,20 +102,29 @@ export class Dialog extends Disposable {
const messageRowElement = this.element.appendChild($('.dialog-message-row'));
this.iconElement = messageRowElement.appendChild($('.dialog-icon'));
const messageContainer = messageRowElement.appendChild($('.dialog-message-container'));
this.messageContainer = messageRowElement.appendChild($('.dialog-message-container'));
if (this.options.detail) {
const messageElement = messageContainer.appendChild($('.dialog-message'));
if (this.options.detail || this.options.renderBody) {
const messageElement = this.messageContainer.appendChild($('.dialog-message'));
const messageTextElement = messageElement.appendChild($('.dialog-message-text'));
messageTextElement.innerText = this.message;
}
this.messageDetailElement = messageContainer.appendChild($('.dialog-message-detail'));
this.messageDetailElement.innerText = this.options.detail ? this.options.detail : message;
this.messageDetailElement = this.messageContainer.appendChild($('.dialog-message-detail'));
if (this.options.detail || !this.options.renderBody) {
this.messageDetailElement.innerText = this.options.detail ? this.options.detail : message;
} else {
this.messageDetailElement.style.display = 'none';
}
if (this.options.renderBody) {
const customBody = this.messageContainer.appendChild($('.dialog-message-body'));
this.options.renderBody(customBody);
}
if (this.options.inputs) {
this.inputs = this.options.inputs.map(input => {
const inputRowElement = messageContainer.appendChild($('.dialog-message-input'));
const inputRowElement = this.messageContainer.appendChild($('.dialog-message-input'));
const inputBox = this._register(new InputBox(inputRowElement, undefined, {
placeholder: input.placeholder,
@@ -126,7 +142,7 @@ export class Dialog extends Disposable {
}
if (this.options.checkboxLabel) {
const checkboxRowElement = messageContainer.appendChild($('.dialog-checkbox-row'));
const checkboxRowElement = this.messageContainer.appendChild($('.dialog-checkbox-row'));
const checkbox = this.checkbox = this._register(new SimpleCheckbox(this.options.checkboxLabel, !!this.options.checkboxChecked));
@@ -175,12 +191,16 @@ export class Dialog extends Disposable {
const buttonBar = this.buttonBar = this._register(new ButtonBar(this.buttonsContainer));
const buttonMap = this.rearrangeButtons(this.buttons, this.options.cancelId);
this.buttonsContainer.classList.toggle('centered');
// Handle button clicks
buttonMap.forEach((entry, index) => {
const button = this._register(buttonBar.addButton({ title: true }));
const primary = buttonMap[index].index === 0;
const button = this.options.buttonDetails ? this._register(buttonBar.addButtonWithDescription({ title: true, secondary: !primary })) : this._register(buttonBar.addButton({ title: true, secondary: !primary }));
button.label = mnemonicButtonLabel(buttonMap[index].label, true);
if (button instanceof ButtonWithDescription) {
button.description = this.options.buttonDetails![buttonMap[index].index];
}
this._register(button.onDidClick(e => {
if (e) {
EventHelper.stop(e);
@@ -287,7 +307,7 @@ export class Dialog extends Disposable {
EventHelper.stop(e, true);
const evt = new StandardKeyboardEvent(e);
if (evt.equals(KeyCode.Escape)) {
if (!this.options.disableCloseAction && evt.equals(KeyCode.Escape)) {
resolve({
button: this.options.cancelId || 0,
checkboxChecked: this.checkbox ? this.checkbox.checked : undefined
@@ -313,34 +333,41 @@ export class Dialog extends Disposable {
this.iconElement.classList.remove(...dialogErrorIcon.classNamesArray, ...dialogWarningIcon.classNamesArray, ...dialogInfoIcon.classNamesArray, ...Codicon.loading.classNamesArray, spinModifierClassName);
switch (this.options.type) {
case 'error':
this.iconElement.classList.add(...dialogErrorIcon.classNamesArray);
break;
case 'warning':
this.iconElement.classList.add(...dialogWarningIcon.classNamesArray);
break;
case 'pending':
this.iconElement.classList.add(...Codicon.loading.classNamesArray, spinModifierClassName);
break;
case 'none':
case 'info':
case 'question':
default:
this.iconElement.classList.add(...dialogInfoIcon.classNamesArray);
break;
if (this.options.icon) {
this.iconElement.classList.add(...this.options.icon.classNamesArray);
} else {
switch (this.options.type) {
case 'error':
this.iconElement.classList.add(...dialogErrorIcon.classNamesArray);
break;
case 'warning':
this.iconElement.classList.add(...dialogWarningIcon.classNamesArray);
break;
case 'pending':
this.iconElement.classList.add(...Codicon.loading.classNamesArray, spinModifierClassName);
break;
case 'none':
case 'info':
case 'question':
default:
this.iconElement.classList.add(...dialogInfoIcon.classNamesArray);
break;
}
}
const actionBar = this._register(new ActionBar(this.toolbarContainer, {}));
const action = this._register(new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), dialogCloseIcon.classNames, true, async () => {
resolve({
button: this.options.cancelId || 0,
checkboxChecked: this.checkbox ? this.checkbox.checked : undefined
});
}));
if (!this.options.disableCloseAction) {
const actionBar = this._register(new ActionBar(this.toolbarContainer, {}));
actionBar.push(action, { icon: true, label: false, });
const action = this._register(new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), dialogCloseIcon.classNames, true, async () => {
resolve({
button: this.options.cancelId || 0,
checkboxChecked: this.checkbox ? this.checkbox.checked : undefined
});
}));
actionBar.push(action, { icon: true, label: false, });
}
this.applyStyles();
@@ -369,6 +396,7 @@ export class Dialog extends Disposable {
const bgColor = style.dialogBackground;
const shadowColor = style.dialogShadow ? `0 0px 8px ${style.dialogShadow}` : '';
const border = style.dialogBorder ? `1px solid ${style.dialogBorder}` : '';
const linkFgColor = style.textLinkForeground;
this.shadowElement.style.boxShadow = shadowColor;
@@ -389,6 +417,12 @@ export class Dialog extends Disposable {
this.messageDetailElement.style.color = messageDetailColor.makeOpaque(bgColor).toString();
}
if (linkFgColor) {
for (const el of this.messageContainer.getElementsByTagName('a')) {
el.style.color = linkFgColor.toString();
}
}
let color;
switch (this.options.type) {
case 'error':
@@ -417,7 +451,7 @@ export class Dialog extends Disposable {
this.applyStyles();
}
dispose(): void {
override dispose(): void {
super.dispose();
if (this.modalElement) {

View File

@@ -11,8 +11,29 @@
.monaco-dropdown > .dropdown-label {
cursor: pointer;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.monaco-dropdown > .dropdown-label > .action-label.disabled {
cursor: default;
}
.monaco-dropdown-with-primary {
display: flex !important;
flex-direction: row;
border-radius: 5px;
}
.monaco-dropdown-with-primary > .action-container > .action-label {
margin-right: 0;
}
.monaco-dropdown-with-primary > .dropdown-action-container > .monaco-dropdown > .dropdown-label .codicon[class*='codicon-'] {
font-size: 12px;
padding-left: 0px;
padding-right: 0px;
line-height: 16px;
margin-left: -4px;
}

View File

@@ -125,7 +125,7 @@ export class BaseDropdown extends ActionRunner {
this.hide();
}
dispose(): void {
override dispose(): void {
super.dispose();
this.hide();
@@ -159,7 +159,7 @@ export class Dropdown extends BaseDropdown {
this.contextViewProvider = options.contextViewProvider;
}
show(): void {
override show(): void {
super.show();
this.element.classList.add('active');
@@ -187,7 +187,7 @@ export class Dropdown extends BaseDropdown {
this.element.classList.remove('active');
}
hide(): void {
override hide(): void {
super.hide();
if (this.contextViewProvider) {
@@ -250,7 +250,7 @@ export class DropdownMenu extends BaseDropdown {
this._actions = actions;
}
show(): void {
override show(): void {
super.show();
this.element.classList.add('active');
@@ -269,7 +269,7 @@ export class DropdownMenu extends BaseDropdown {
});
}
hide(): void {
override hide(): void {
super.hide();
}

View File

@@ -7,14 +7,15 @@ import 'vs/css!./dropdown';
import { Action, IAction, IActionRunner } from 'vs/base/common/actions';
import { IDisposable } from 'vs/base/common/lifecycle';
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
import { append, $ } from 'vs/base/browser/dom';
import { KeyCode, ResolvedKeybinding } from 'vs/base/common/keyCodes';
import { append, $, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { Emitter } from 'vs/base/common/event';
import { ActionViewItem, BaseActionViewItem, IActionViewItemOptions, IBaseActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { IActionProvider, DropdownMenu, IDropdownMenuOptions, ILabelRenderer } from 'vs/base/browser/ui/dropdown/dropdown';
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
import { Codicon } from 'vs/base/common/codicons';
import { IActionViewItemProvider } from 'vs/base/browser/ui/actionbar/actionbar';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
export interface IKeybindingProvider {
(action: IAction): ResolvedKeybinding | undefined;
@@ -42,23 +43,26 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
private _onDidChangeVisibility = this._register(new Emitter<boolean>());
readonly onDidChangeVisibility = this._onDidChangeVisibility.event;
protected override readonly options: IDropdownMenuActionViewItemOptions;
constructor(
action: IAction,
menuActionsOrProvider: readonly IAction[] | IActionProvider,
contextMenuProvider: IContextMenuProvider,
protected options: IDropdownMenuActionViewItemOptions = {}
options: IDropdownMenuActionViewItemOptions = Object.create(null)
) {
super(null, action, options);
this.menuActionsOrProvider = menuActionsOrProvider;
this.contextMenuProvider = contextMenuProvider;
this.options = options;
if (this.options.actionRunner) {
this.actionRunner = this.options.actionRunner;
}
}
render(container: HTMLElement): void {
override render(container: HTMLElement): void {
this.actionItem = container;
const labelRenderer: ILabelRenderer = (el: HTMLElement): IDisposable | null => {
@@ -123,7 +127,7 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
this.updateEnabled();
}
setActionContext(newContext: unknown): void {
override setActionContext(newContext: unknown): void {
super.setActionContext(newContext);
if (this.dropdownMenu) {
@@ -141,7 +145,7 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
}
}
protected updateEnabled(): void {
protected override updateEnabled(): void {
const disabled = !this.getAction().enabled;
this.actionItem?.classList.toggle('disabled', disabled);
this.element?.classList.toggle('disabled', disabled);
@@ -166,7 +170,7 @@ export class ActionWithDropdownActionViewItem extends ActionViewItem {
super(context, action, options);
}
render(container: HTMLElement): void {
override render(container: HTMLElement): void {
super.render(container);
if (this.element) {
this.element.classList.add('action-dropdown-item');
@@ -181,6 +185,36 @@ export class ActionWithDropdownActionViewItem extends ActionViewItem {
};
this.dropdownMenuActionViewItem = new DropdownMenuActionViewItem(this._register(new Action('dropdownAction', undefined)), menuActionsProvider, this.contextMenuProvider, { classNames: ['dropdown', ...Codicon.dropDownButton.classNamesArray, ...(<IActionWithDropdownActionViewItemOptions>this.options).menuActionClassNames || []] });
this.dropdownMenuActionViewItem.render(this.element);
this._register(addDisposableListener(this.element, EventType.KEY_DOWN, e => {
const event = new StandardKeyboardEvent(e);
let handled: boolean = false;
if (this.dropdownMenuActionViewItem?.isFocused() && event.equals(KeyCode.LeftArrow)) {
handled = true;
this.dropdownMenuActionViewItem?.blur();
this.focus();
} else if (this.isFocused() && event.equals(KeyCode.RightArrow)) {
handled = true;
this.blur();
this.dropdownMenuActionViewItem?.focus();
}
if (handled) {
event.preventDefault();
event.stopPropagation();
}
}));
}
}
override blur(): void {
super.blur();
this.dropdownMenuActionViewItem?.blur();
}
override setFocusable(focusable: boolean): void {
super.setFocusable(focusable);
this.dropdownMenuActionViewItem?.setFocusable(focusable);
}
}

View File

@@ -0,0 +1,106 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
import { ActionViewItem, BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
import { DropdownMenuActionViewItem } from 'vs/base/browser/ui/dropdown/dropdownActionViewItem';
import { IAction } from 'vs/base/common/actions';
import * as DOM from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
export class DropdownWithPrimaryActionViewItem extends BaseActionViewItem {
private _primaryAction: ActionViewItem;
private _dropdown: DropdownMenuActionViewItem;
private _container: HTMLElement | null = null;
private toDispose: IDisposable[];
constructor(
primaryAction: IAction,
dropdownAction: IAction,
dropdownMenuActions: IAction[],
_className: string,
private readonly _contextMenuProvider: IContextMenuProvider,
dropdownIcon?: string
) {
super(null, primaryAction);
this._primaryAction = new ActionViewItem(undefined, primaryAction, {
icon: true,
label: false
});
this._dropdown = new DropdownMenuActionViewItem(dropdownAction, dropdownMenuActions, this._contextMenuProvider, {
menuAsChild: true
});
this.toDispose = [];
}
override render(container: HTMLElement): void {
this._container = container;
super.render(this._container);
this._container.classList.add('monaco-dropdown-with-primary');
const primaryContainer = DOM.$('.action-container');
this._primaryAction.render(DOM.append(this._container, primaryContainer));
const dropdownContainer = DOM.$('.dropdown-action-container');
this._dropdown.render(DOM.append(this._container, dropdownContainer));
this.toDispose.push(DOM.addDisposableListener(primaryContainer, DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => {
const event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.RightArrow)) {
this._primaryAction.element!.tabIndex = -1;
this._dropdown.focus();
event.stopPropagation();
}
}));
this.toDispose.push(DOM.addDisposableListener(dropdownContainer, DOM.EventType.KEY_DOWN, (e: KeyboardEvent) => {
const event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.LeftArrow)) {
this._primaryAction.element!.tabIndex = 0;
this._dropdown.setFocusable(false);
this._primaryAction.element?.focus();
event.stopPropagation();
}
}));
}
override focus(fromRight?: boolean): void {
if (fromRight) {
this._dropdown.focus();
} else {
this._primaryAction.element!.tabIndex = 0;
this._primaryAction.element!.focus();
}
}
override blur(): void {
this._primaryAction.element!.tabIndex = -1;
this._dropdown.blur();
this._container!.blur();
}
override setFocusable(focusable: boolean): void {
if (focusable) {
this._primaryAction.element!.tabIndex = 0;
} else {
this._primaryAction.element!.tabIndex = -1;
this._dropdown.setFocusable(false);
}
}
override dispose(): void {
this.toDispose = dispose(this.toDispose);
}
update(dropdownAction: IAction, dropdownMenuActions: IAction[], dropdownIcon?: string): void {
this._dropdown?.dispose();
this._dropdown = new DropdownMenuActionViewItem(dropdownAction, dropdownMenuActions, this._contextMenuProvider, {
menuAsChild: true,
classNames: ['codicon', dropdownIcon || 'codicon-chevron-down']
});
if (this.element) {
this._dropdown.render(this.element);
}
}
}

View File

@@ -382,7 +382,7 @@ export class ReplaceInput extends Widget {
this.domNode.style.width = newWidth + 'px';
}
public dispose(): void {
public override dispose(): void {
super.dispose();
}
}

View File

@@ -521,51 +521,6 @@ export class SerializableGrid<T extends ISerializableView> extends Grid<T> {
return { type: 'branch', data: node.children.map(c => SerializableGrid.serializeNode(c, orthogonal(orientation))), size };
}
private static deserializeNode<T extends ISerializableView>(json: ISerializedNode, orientation: Orientation, box: Box, deserializer: IViewDeserializer<T>): GridNode<T> {
if (!json || typeof json !== 'object') {
throw new Error('Invalid JSON');
}
if (json.type === 'branch') {
if (!Array.isArray(json.data)) {
throw new Error('Invalid JSON: \'data\' property of branch must be an array.');
}
const children: GridNode<T>[] = [];
let offset = 0;
for (const child of json.data) {
if (typeof child.size !== 'number') {
throw new Error('Invalid JSON: \'size\' property of node must be a number.');
}
const childSize = child.type === 'leaf' && child.visible === false ? 0 : child.size;
const childBox: Box = orientation === Orientation.HORIZONTAL
? { top: box.top, left: box.left + offset, width: childSize, height: box.height }
: { top: box.top + offset, left: box.left, width: box.width, height: childSize };
children.push(SerializableGrid.deserializeNode(child, orthogonal(orientation), childBox, deserializer));
offset += childSize;
}
return { children, box };
} else if (json.type === 'leaf') {
const view: T = deserializer.fromJSON(json.data);
return { view, box, cachedVisibleSize: json.visible === false ? json.size : undefined };
}
throw new Error('Invalid JSON: \'type\' property must be either \'branch\' or \'leaf\'.');
}
private static getFirstLeaf<T extends IView>(node: GridNode<T>): GridLeafNode<T> {
if (!isGridBranchNode(node)) {
return node;
}
return SerializableGrid.getFirstLeaf(node.children[0]);
}
static deserialize<T extends ISerializableView>(json: ISerializedGrid, deserializer: IViewDeserializer<T>, options: IGridOptions = {}): SerializableGrid<T> {
if (typeof json.orientation !== 'number') {
throw new Error('Invalid JSON: \'orientation\' property must be a number.');
@@ -596,7 +551,7 @@ export class SerializableGrid<T extends ISerializableView> extends Grid<T> {
};
}
layout(width: number, height: number): void {
override layout(width: number, height: number): void {
super.layout(width, height);
if (this.initialLayoutContext) {

View File

@@ -30,8 +30,7 @@
}
.monaco-hover .markdown-hover > .hover-contents:not(.code-hover-contents) hr {
/* This is a strange rule but it avoids https://github.com/microsoft/vscode/issues/96795, just 100vw on its own caused the actual hover width to increase */
min-width: calc(100% + 100vw);
min-width: 100%;
}
.monaco-hover p,

View File

@@ -10,6 +10,10 @@ import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableEle
const $ = dom.$;
export const enum HoverPosition {
LEFT, RIGHT, BELOW, ABOVE
}
export class HoverWidget extends Disposable {
public readonly containerDomNode: HTMLElement;

View File

@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { AnchorPosition } from 'vs/base/browser/ui/contextview/contextview';
import { HoverPosition } from 'vs/base/browser/ui/hover/hoverWidget';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { IDisposable } from 'vs/base/common/lifecycle';
@@ -15,7 +15,7 @@ export interface IHoverDelegateTarget extends IDisposable {
export interface IHoverDelegateOptions {
text: IMarkdownString | string;
target: IHoverDelegateTarget | HTMLElement;
anchorPosition?: AnchorPosition;
hoverPosition?: HoverPosition;
}
export interface IHoverDelegate {

View File

@@ -11,12 +11,12 @@ import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { Range } from 'vs/base/common/range';
import { equals } from 'vs/base/common/objects';
import { IHoverDelegate, IHoverDelegateOptions, IHoverDelegateTarget } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
import { AnchorPosition } from 'vs/base/browser/ui/contextview/contextview';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { isFunction, isString } from 'vs/base/common/types';
import { domEvent } from 'vs/base/browser/event';
import { localize } from 'vs/nls';
import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
import { HoverPosition } from 'vs/base/browser/ui/hover/hoverWidget';
export interface IIconLabelCreationOptions {
supportHighlights?: boolean;
@@ -222,12 +222,12 @@ export class IconLabel extends Disposable {
let isHovering = false;
let tokenSource: CancellationTokenSource;
let hoverDisposable: IDisposable | undefined;
function mouseOver(this: HTMLElement, e: MouseEvent): any {
function mouseOver(this: HTMLElement, e: MouseEvent): void {
if (isHovering) {
return;
}
tokenSource = new CancellationTokenSource();
function mouseLeaveOrDown(this: HTMLElement, e: MouseEvent): any {
function mouseLeaveOrDown(this: HTMLElement, e: MouseEvent): void {
const isMouseDown = e.type === dom.EventType.MOUSE_DOWN;
if (isMouseDown) {
hoverDisposable?.dispose();
@@ -245,7 +245,7 @@ export class IconLabel extends Disposable {
const mouseDownDisposable = domEvent(htmlElement, dom.EventType.MOUSE_DOWN, true)(mouseLeaveOrDown.bind(htmlElement));
isHovering = true;
function mouseMove(this: HTMLElement, e: MouseEvent): any {
function mouseMove(this: HTMLElement, e: MouseEvent): void {
mouseX = e.x;
}
const mouseMoveDisposable = domEvent(htmlElement, dom.EventType.MOUSE_MOVE, true)(mouseMove.bind(htmlElement));
@@ -260,7 +260,7 @@ export class IconLabel extends Disposable {
hoverOptions = {
text: localize('iconLabel.loading', "Loading..."),
target,
anchorPosition: AnchorPosition.BELOW
hoverPosition: HoverPosition.BELOW
};
hoverDisposable = IconLabel.adjustXAndShowCustomHover(hoverOptions, mouseX, hoverDelegate, isHovering);
@@ -269,7 +269,7 @@ export class IconLabel extends Disposable {
hoverOptions = {
text: resolvedTooltip,
target,
anchorPosition: AnchorPosition.BELOW
hoverPosition: HoverPosition.BELOW
};
// awaiting the tooltip could take a while. Make sure we're still hovering.
hoverDisposable = IconLabel.adjustXAndShowCustomHover(hoverOptions, mouseX, hoverDelegate, isHovering);

View File

@@ -610,7 +610,7 @@ export class InputBox extends Widget {
}
}
public dispose(): void {
public override dispose(): void {
this._hideMessage();
this.message = null;

View File

@@ -11,13 +11,10 @@
.monaco-keybinding > .monaco-keybinding-key {
display: inline-block;
border: solid 1px rgba(204, 204, 204, 0.4);
border-bottom-color: rgba(187, 187, 187, 0.4);
border-style: solid;
border-width: 1px;
border-radius: 3px;
box-shadow: inset 0 -1px 0 rgba(187, 187, 187, 0.4);
background-color: rgba(221, 221, 221, 0.4);
vertical-align: middle;
color: #555;
font-size: 11px;
padding: 3px 5px;
margin: 0 2px;
@@ -31,19 +28,10 @@
margin-right: 0;
}
.hc-black .monaco-keybinding > .monaco-keybinding-key,
.vs-dark .monaco-keybinding > .monaco-keybinding-key {
background-color: rgba(128, 128, 128, 0.17);
color: #ccc;
border: solid 1px rgba(51, 51, 51, 0.6);
border-bottom-color: rgba(68, 68, 68, 0.6);
box-shadow: inset 0 -1px 0 rgba(68, 68, 68, 0.6);
}
.monaco-keybinding > .monaco-keybinding-key-separator {
display: inline-block;
}
.monaco-keybinding > .monaco-keybinding-key-chord-separator {
width: 6px;
}
}

View File

@@ -10,6 +10,8 @@ import { ResolvedKeybinding, ResolvedKeybindingPart } from 'vs/base/common/keyCo
import { UILabelProvider } from 'vs/base/common/keybindingLabels';
import * as dom from 'vs/base/browser/dom';
import { localize } from 'vs/nls';
import { IThemable } from 'vs/base/common/styler';
import { Color } from 'vs/base/common/color';
const $ = dom.$;
@@ -26,18 +28,44 @@ export interface Matches {
chordPart: PartMatches;
}
export interface KeybindingLabelOptions {
renderUnboundKeybindings: boolean;
export interface KeybindingLabelOptions extends IKeybindingLabelStyles {
renderUnboundKeybindings?: boolean;
}
export class KeybindingLabel {
export interface IKeybindingLabelStyles {
keybindingLabelBackground?: Color;
keybindingLabelForeground?: Color;
keybindingLabelBorder?: Color;
keybindingLabelBottomBorder?: Color;
keybindingLabelShadow?: Color;
}
export class KeybindingLabel implements IThemable {
private domNode: HTMLElement;
private options: KeybindingLabelOptions;
private readonly keyElements = new Set<HTMLSpanElement>();
private keybinding: ResolvedKeybinding | undefined;
private matches: Matches | undefined;
private didEverRender: boolean;
constructor(container: HTMLElement, private os: OperatingSystem, private options?: KeybindingLabelOptions) {
private labelBackground: Color | undefined;
private labelForeground: Color | undefined;
private labelBorder: Color | undefined;
private labelBottomBorder: Color | undefined;
private labelShadow: Color | undefined;
constructor(container: HTMLElement, private os: OperatingSystem, options?: KeybindingLabelOptions) {
this.options = options || Object.create(null);
this.labelBackground = this.options.keybindingLabelBackground;
this.labelForeground = this.options.keybindingLabelForeground;
this.labelBorder = this.options.keybindingLabelBorder;
this.labelBottomBorder = this.options.keybindingLabelBottomBorder;
this.labelShadow = this.options.keybindingLabelShadow;
this.domNode = dom.append(container, $('.monaco-keybinding'));
this.didEverRender = false;
container.appendChild(this.domNode);
@@ -58,7 +86,7 @@ export class KeybindingLabel {
}
private render() {
dom.clearNode(this.domNode);
this.clear();
if (this.keybinding) {
let [firstPart, chordPart] = this.keybinding.getParts();
@@ -74,9 +102,16 @@ export class KeybindingLabel {
this.renderUnbound(this.domNode);
}
this.applyStyles();
this.didEverRender = true;
}
private clear(): void {
dom.clearNode(this.domNode);
this.keyElements.clear();
}
private renderPart(parent: HTMLElement, part: ResolvedKeybindingPart, match: PartMatches | null) {
const modifierLabels = UILabelProvider.modifierLabels[this.os];
if (part.ctrlKey) {
@@ -98,14 +133,54 @@ export class KeybindingLabel {
}
private renderKey(parent: HTMLElement, label: string, highlight: boolean, separator: string): void {
dom.append(parent, $('span.monaco-keybinding-key' + (highlight ? '.highlight' : ''), undefined, label));
dom.append(parent, this.createKeyElement(label, highlight ? '.highlight' : ''));
if (separator) {
dom.append(parent, $('span.monaco-keybinding-key-separator', undefined, separator));
}
}
private renderUnbound(parent: HTMLElement): void {
dom.append(parent, $('span.monaco-keybinding-key', undefined, localize('unbound', "Unbound")));
dom.append(parent, this.createKeyElement(localize('unbound', "Unbound")));
}
private createKeyElement(label: string, extraClass = ''): HTMLElement {
const keyElement = $('span.monaco-keybinding-key' + extraClass, undefined, label);
this.keyElements.add(keyElement);
return keyElement;
}
style(styles: IKeybindingLabelStyles): void {
this.labelBackground = styles.keybindingLabelBackground;
this.labelForeground = styles.keybindingLabelForeground;
this.labelBorder = styles.keybindingLabelBorder;
this.labelBottomBorder = styles.keybindingLabelBottomBorder;
this.labelShadow = styles.keybindingLabelShadow;
this.applyStyles();
}
private applyStyles() {
if (this.element) {
for (const keyElement of this.keyElements) {
if (this.labelBackground) {
keyElement.style.backgroundColor = this.labelBackground?.toString();
}
if (this.labelBorder) {
keyElement.style.borderColor = this.labelBorder.toString();
}
if (this.labelBottomBorder) {
keyElement.style.borderBottomColor = this.labelBottomBorder.toString();
}
if (this.labelShadow) {
keyElement.style.boxShadow = `inset 0 -1px 0 ${this.labelShadow}`;
}
}
if (this.labelForeground) {
this.element.style.color = this.labelForeground.toString();
}
}
}
private static areSame(a: Matches | undefined, b: Matches | undefined): boolean {

View File

@@ -339,7 +339,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
container.appendChild(this.domNode);
this.scrollableElement.onScroll(this.onScroll, this, this.disposables);
domEvent(this.rowsContainer, TouchEventType.Change)(this.onTouchChange, this, this.disposables);
domEvent(this.rowsContainer, TouchEventType.Change)(e => this.onTouchChange(e as GestureEvent), this, this.disposables);
// Prevent the monaco-scrollable-element from scrolling
// https://github.com/microsoft/vscode/issues/44181
@@ -362,6 +362,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
updateOptions(options: IListViewOptionsUpdate) {
if (options.additionalScrollHeight !== undefined) {
this.additionalScrollHeight = options.additionalScrollHeight;
this.scrollableElement.setScrollDimensions({ scrollHeight: this.scrollHeight });
}
if (options.smoothScrolling !== undefined) {
@@ -407,6 +408,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.items[index].size = size;
this.render(lastRenderRange, Math.max(0, this.lastRenderTop + heightDiff), this.lastRenderHeight, undefined, undefined, true);
this.setScrollTop(this.lastRenderTop);
this.eventuallyUpdateScrollDimensions();
@@ -679,12 +681,12 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
if (this.supportDynamicHeights) {
this._rerender(this.scrollTop, this.renderHeight);
}
}
if (this.horizontalScrolling) {
this.scrollableElement.setScrollDimensions({
width: typeof width === 'number' ? width : getContentWidth(this.domNode)
});
}
if (this.horizontalScrolling) {
this.scrollableElement.setScrollDimensions({
width: typeof width === 'number' ? width : getContentWidth(this.domNode)
});
}
}
@@ -898,7 +900,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
@memoize get onMouseOut(): Event<IListMouseEvent<T>> { return Event.map(domEvent(this.domNode, 'mouseout'), e => this.toMouseEvent(e)); }
@memoize get onContextMenu(): Event<IListMouseEvent<T>> { return Event.map(domEvent(this.domNode, 'contextmenu'), e => this.toMouseEvent(e)); }
@memoize get onTouchStart(): Event<IListTouchEvent<T>> { return Event.map(domEvent(this.domNode, 'touchstart'), e => this.toTouchEvent(e)); }
@memoize get onTap(): Event<IListGestureEvent<T>> { return Event.map(domEvent(this.rowsContainer, TouchEventType.Tap), e => this.toGestureEvent(e)); }
@memoize get onTap(): Event<IListGestureEvent<T>> { return Event.map(domEvent(this.rowsContainer, TouchEventType.Tap), e => this.toGestureEvent(e as GestureEvent)); }
private toMouseEvent(browserEvent: MouseEvent): IListMouseEvent<T> {
const index = this.getItemIndexFromEventTarget(browserEvent.target || null);

View File

@@ -188,7 +188,7 @@ class SelectionTrait<T> extends Trait<T> {
super('selected');
}
renderIndex(index: number, container: HTMLElement): void {
override renderIndex(index: number, container: HTMLElement): void {
super.renderIndex(index, container);
if (this.setAriaSelected) {
@@ -1635,13 +1635,13 @@ export class List<T> implements ISpliceable<T>, IThemable, IDisposable {
this.view.setScrollTop(m * clamp(relativeTop, 0, 1) + elementTop);
} else {
const viewItemBottom = elementTop + elementHeight;
const wrapperBottom = scrollTop + this.view.renderHeight;
const scrollBottom = scrollTop + this.view.renderHeight;
if (elementTop < scrollTop && viewItemBottom >= wrapperBottom) {
if (elementTop < scrollTop && viewItemBottom >= scrollBottom) {
// The element is already overflowing the viewport, no-op
} else if (elementTop < scrollTop) {
} else if (elementTop < scrollTop || (viewItemBottom >= scrollBottom && elementHeight >= this.view.renderHeight)) {
this.view.setScrollTop(elementTop);
} else if (viewItemBottom >= wrapperBottom) {
} else if (viewItemBottom >= scrollBottom) {
this.view.setScrollTop(viewItemBottom - this.view.renderHeight);
}
}

View File

@@ -37,7 +37,7 @@ export enum Direction {
}
export interface IMenuOptions {
context?: any;
context?: unknown;
actionViewItemProvider?: IActionViewItemProvider;
actionRunner?: IActionRunner;
getKeyBinding?: (action: IAction) => ResolvedKeybinding | undefined;
@@ -264,7 +264,7 @@ export class Menu extends ActionBar {
}
}
getContainer(): HTMLElement {
override getContainer(): HTMLElement {
return this.scrollableElement.getDomNode();
}
@@ -309,7 +309,7 @@ export class Menu extends ActionBar {
}
}
protected updateFocus(fromRight?: boolean): void {
protected override updateFocus(fromRight?: boolean): void {
super.updateFocus(fromRight, true);
if (typeof this.focusedItem !== 'undefined') {
@@ -385,7 +385,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
public container: HTMLElement | undefined;
protected options: IMenuItemOptions;
protected override options: IMenuItemOptions;
protected item: HTMLElement | undefined;
private runOnceToEnableMouseUp: RunOnceScheduler;
@@ -465,7 +465,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
this._register(this.runOnceToEnableMouseUp);
}
render(container: HTMLElement): void {
override render(container: HTMLElement): void {
super.render(container);
if (!this.element) {
@@ -504,12 +504,12 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
this.updateChecked();
}
blur(): void {
override blur(): void {
super.blur();
this.applyStyle();
}
focus(): void {
override focus(): void {
super.focus();
if (this.item) {
@@ -526,7 +526,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
}
}
updateLabel(): void {
override updateLabel(): void {
if (!this.label) {
return;
}
@@ -579,7 +579,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
}
}
updateTooltip(): void {
override updateTooltip(): void {
let title: string | null = null;
if (this.getAction().tooltip) {
@@ -598,7 +598,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
}
}
updateClass(): void {
override updateClass(): void {
if (this.cssClass && this.item) {
this.item.classList.remove(...this.cssClass.split(' '));
}
@@ -614,7 +614,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
}
}
updateEnabled(): void {
override updateEnabled(): void {
if (this.getAction().enabled) {
if (this.element) {
this.element.classList.remove('disabled');
@@ -639,7 +639,7 @@ class BaseMenuActionViewItem extends BaseActionViewItem {
}
}
updateChecked(): void {
override updateChecked(): void {
if (!this.item) {
return;
}
@@ -724,7 +724,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
}, 750);
}
render(container: HTMLElement): void {
override render(container: HTMLElement): void {
super.render(container);
if (!this.element) {
@@ -783,7 +783,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
}));
}
updateEnabled(): void {
override updateEnabled(): void {
// override on submenu entry
// native menus do not observe enablement on sumbenus
// we mimic that behavior
@@ -794,7 +794,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
this.createSubmenu(selectFirst);
}
onClick(e: EventLike): void {
override onClick(e: EventLike): void {
// stop clicking from trying to run an action
EventHelper.stop(e, true);
@@ -925,7 +925,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
}
}
protected applyStyle(): void {
protected override applyStyle(): void {
super.applyStyle();
if (!this.menuStyle) {
@@ -944,7 +944,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
}
}
dispose(): void {
override dispose(): void {
super.dispose();
this.hideScheduler.dispose();

View File

@@ -422,7 +422,7 @@ export class MenuBar extends Disposable {
}
}
dispose(): void {
override dispose(): void {
super.dispose();
this.menuCache.forEach(menuBarMenu => {

View File

@@ -211,7 +211,7 @@ export class Sash extends Disposable {
this._register(domEvent(this.el, 'mouseleave')(() => Sash.onMouseLeave(this)));
this._register(Gesture.addTarget(this.el));
this._register(domEvent(this.el, EventType.Start)(this.onTouchStart, this));
this._register(domEvent(this.el, EventType.Start)(e => this.onTouchStart(e as GestureEvent), this));
if (typeof options.size === 'number') {
this.size = options.size;
@@ -430,6 +430,10 @@ export class Sash extends Disposable {
}
}
clearSashHoverState(): void {
Sash.onMouseLeave(this);
}
layout(): void {
if (this.orientation === Orientation.VERTICAL) {
const verticalProvider = (<IVerticalSashLayoutProvider>this.layoutProvider);
@@ -484,7 +488,7 @@ export class Sash extends Disposable {
return undefined;
}
dispose(): void {
override dispose(): void {
super.dispose();
this.el.remove();
}

View File

@@ -214,7 +214,7 @@ export abstract class AbstractScrollableElement extends Widget {
this._domNode.appendChild(this._topShadowDomNode.domNode);
this._topLeftShadowDomNode = createFastDomNode(document.createElement('div'));
this._topLeftShadowDomNode.setClassName('shadow top-left-corner');
this._topLeftShadowDomNode.setClassName('shadow');
this._domNode.appendChild(this._topLeftShadowDomNode.domNode);
} else {
this._leftShadowDomNode = null;
@@ -239,7 +239,7 @@ export abstract class AbstractScrollableElement extends Widget {
this._revealOnScroll = true;
}
public dispose(): void {
public override dispose(): void {
this._mouseWheelToDispose = dispose(this._mouseWheelToDispose);
super.dispose();
}
@@ -484,9 +484,12 @@ export abstract class AbstractScrollableElement extends Widget {
const enableTop = scrollState.scrollTop > 0;
const enableLeft = scrollState.scrollLeft > 0;
this._leftShadowDomNode!.setClassName('shadow' + (enableLeft ? ' left' : ''));
this._topShadowDomNode!.setClassName('shadow' + (enableTop ? ' top' : ''));
this._topLeftShadowDomNode!.setClassName('shadow top-left-corner' + (enableTop ? ' top' : '') + (enableLeft ? ' left' : ''));
const leftClassName = (enableLeft ? ' left' : '');
const topClassName = (enableTop ? ' top' : '');
const topLeftClassName = (enableLeft || enableTop ? ' top-left-corner' : '');
this._leftShadowDomNode!.setClassName(`shadow${leftClassName}`);
this._topShadowDomNode!.setClassName(`shadow${topClassName}`);
this._topLeftShadowDomNode!.setClassName(`shadow${topLeftClassName}${topClassName}${leftClassName}`);
}
}

View File

@@ -1046,7 +1046,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi
}
}
public dispose(): void {
public override dispose(): void {
this.hideSelectDropDown(false);
super.dispose();
}

View File

@@ -52,6 +52,14 @@
margin-left: auto;
}
.monaco-pane-view .pane > .pane-header > .actions .action-item {
margin-right: 4px;
}
.monaco-pane-view .pane > .pane-header > .actions .action-label {
padding: 2px;
}
/* TODO: actions should be part of the pane, but they aren't yet */
.monaco-pane-view .pane:hover > .pane-header.expanded > .actions,
.monaco-pane-view .pane:focus-within > .pane-header.expanded > .actions,
@@ -60,22 +68,6 @@
display: initial;
}
/* TODO: actions should be part of the pane, but they aren't yet */
.monaco-pane-view .pane > .pane-header > .actions .action-label.icon,
.monaco-pane-view .pane > .pane-header > .actions .action-label.codicon {
width: 28px;
height: 22px;
background-size: 16px;
background-position: center center;
background-repeat: no-repeat;
margin-right: 0;
display: flex;
align-items: center;
justify-content: center;
color: inherit;
outline-offset: -2px;
}
.monaco-pane-view .pane > .pane-header .monaco-action-bar .action-item.select-container {
cursor: default;
}

View File

@@ -568,7 +568,7 @@ export class PaneView extends Disposable {
}, 200);
}
dispose(): void {
override dispose(): void {
super.dispose();
this.paneItems.forEach(i => i.disposable.dispose());

View File

@@ -1022,7 +1022,7 @@ export class SplitView<TLayoutContext = undefined> extends Disposable {
return undefined;
}
dispose(): void {
override dispose(): void {
super.dispose();
this.viewItems.forEach(i => i.dispose());

View File

@@ -3,6 +3,10 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-toolbar {
height: 100%;
}
.monaco-toolbar .toolbar-toggle-more {
display: inline-block;
padding: 0;

View File

@@ -181,7 +181,7 @@ export class ToolBar extends Disposable {
this.actionBar.clear();
}
dispose(): void {
override dispose(): void {
this.clear();
super.dispose();
}
@@ -202,7 +202,7 @@ class ToggleMenuAction extends Action {
this.toggleDropdownMenu = toggleDropdownMenu;
}
async run(): Promise<void> {
override async run(): Promise<void> {
this.toggleDropdownMenu();
}

View File

@@ -29,11 +29,11 @@ import { treeItemExpandedIcon, treeFilterOnTypeOnIcon, treeFilterOnTypeOffIcon,
class TreeElementsDragAndDropData<T, TFilterData, TContext> extends ElementsDragAndDropData<T, TContext> {
set context(context: TContext | undefined) {
override set context(context: TContext | undefined) {
this.data.context = context;
}
get context(): TContext | undefined {
override get context(): TContext | undefined {
return this.data.context;
}
@@ -1091,7 +1091,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
super(list);
}
protected onViewPointer(e: IListMouseEvent<ITreeNode<T, TFilterData>>): void {
protected override onViewPointer(e: IListMouseEvent<ITreeNode<T, TFilterData>>): void {
if (isInputElement(e.browserEvent.target as HTMLElement) || isMonacoEditor(e.browserEvent.target as HTMLElement)) {
return;
}
@@ -1141,7 +1141,7 @@ class TreeNodeListMouseController<T, TFilterData, TRef> extends MouseController<
super.onViewPointer(e);
}
protected onDoubleClick(e: IListMouseEvent<ITreeNode<T, TFilterData>>): void {
protected override onDoubleClick(e: IListMouseEvent<ITreeNode<T, TFilterData>>): void {
const onTwistie = (e.browserEvent.target as HTMLElement).classList.contains('monaco-tl-twistie');
if (onTwistie || !this.tree.expandOnDoubleClick) {
@@ -1175,11 +1175,11 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
super(user, container, virtualDelegate, renderers, options);
}
protected createMouseController(options: ITreeNodeListOptions<T, TFilterData, TRef>): MouseController<ITreeNode<T, TFilterData>> {
protected override createMouseController(options: ITreeNodeListOptions<T, TFilterData, TRef>): MouseController<ITreeNode<T, TFilterData>> {
return new TreeNodeListMouseController(this, options.tree);
}
splice(start: number, deleteCount: number, elements: ITreeNode<T, TFilterData>[] = []): void {
override splice(start: number, deleteCount: number, elements: ITreeNode<T, TFilterData>[] = []): void {
super.splice(start, deleteCount, elements);
if (elements.length === 0) {
@@ -1217,7 +1217,7 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
}
}
setFocus(indexes: number[], browserEvent?: UIEvent, fromAPI = false): void {
override setFocus(indexes: number[], browserEvent?: UIEvent, fromAPI = false): void {
super.setFocus(indexes, browserEvent);
if (!fromAPI) {
@@ -1225,7 +1225,7 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
}
}
setSelection(indexes: number[], browserEvent?: UIEvent, fromAPI = false): void {
override setSelection(indexes: number[], browserEvent?: UIEvent, fromAPI = false): void {
super.setSelection(indexes, browserEvent);
if (!fromAPI) {
@@ -1233,7 +1233,7 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
}
}
setAnchor(index: number | undefined, fromAPI = false): void {
override setAnchor(index: number | undefined, fromAPI = false): void {
super.setAnchor(index);
if (!fromAPI) {

View File

@@ -157,11 +157,11 @@ function asTreeContextMenuEvent<TInput, T>(e: ITreeContextMenuEvent<IAsyncDataTr
class AsyncDataTreeElementsDragAndDropData<TInput, T, TContext> extends ElementsDragAndDropData<T, TContext> {
set context(context: TContext | undefined) {
override set context(context: TContext | undefined) {
this.data.context = context;
}
get context(): TContext | undefined {
override get context(): TContext | undefined {
return this.data.context;
}
@@ -1131,7 +1131,7 @@ export interface ICompressibleAsyncDataTreeOptionsUpdate extends IAsyncDataTreeO
export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends AsyncDataTree<TInput, T, TFilterData> {
protected readonly tree!: CompressibleObjectTree<IAsyncDataTreeNode<TInput, T>, TFilterData>;
protected override readonly tree!: CompressibleObjectTree<IAsyncDataTreeNode<TInput, T>, TFilterData>;
protected readonly compressibleNodeMapper: CompressibleAsyncDataTreeNodeMapper<TInput, T, TFilterData> = new WeakMapper(node => new CompressibleAsyncDataTreeNodeWrapper(node));
private filter?: ITreeFilter<T, TFilterData>;
@@ -1148,7 +1148,7 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
this.filter = options.filter;
}
protected createTree(
protected override createTree(
user: string,
container: HTMLElement,
delegate: IListVirtualDelegate<T>,
@@ -1162,18 +1162,18 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
return new CompressibleObjectTree(user, container, objectTreeDelegate, objectTreeRenderers, objectTreeOptions);
}
protected asTreeElement(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): ICompressedTreeElement<IAsyncDataTreeNode<TInput, T>> {
protected override asTreeElement(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): ICompressedTreeElement<IAsyncDataTreeNode<TInput, T>> {
return {
incompressible: this.compressionDelegate.isIncompressible(node.element as T),
...super.asTreeElement(node, viewStateContext)
};
}
updateOptions(options: ICompressibleAsyncDataTreeOptionsUpdate = {}): void {
override updateOptions(options: ICompressibleAsyncDataTreeOptionsUpdate = {}): void {
this.tree.updateOptions(options);
}
getViewState(): IAsyncDataTreeViewState {
override getViewState(): IAsyncDataTreeViewState {
if (!this.identityProvider) {
throw new TreeError(this.user, 'Can\'t get tree view state without an identity provider');
}
@@ -1201,7 +1201,7 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
return { focus, selection, expanded, scrollTop: this.scrollTop };
}
protected render(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): void {
protected override render(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): void {
if (!this.identityProvider) {
return super.render(node, viewStateContext);
}
@@ -1277,7 +1277,7 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
// For compressed async data trees, `TreeVisibility.Recurse` doesn't currently work
// and we have to filter everything beforehand
// Related to #85193 and #85835
protected processChildren(children: Iterable<T>): Iterable<T> {
protected override processChildren(children: Iterable<T>): Iterable<T> {
if (this.filter) {
children = Iterable.filter(children, e => {
const result = this.filter!.filter(e, TreeVisibility.Visible);

View File

@@ -23,7 +23,7 @@ export interface IDataTreeViewState {
export class DataTree<TInput, T, TFilterData = void> extends AbstractTree<T | null, TFilterData, T | null> {
protected model!: ObjectTreeModel<T, TFilterData>;
protected override model!: ObjectTreeModel<T, TFilterData>;
private input: TInput | undefined;
private identityProvider: IIdentityProvider<T> | undefined;

View File

@@ -14,7 +14,7 @@ export interface IIndexTreeOptions<T, TFilterData = void> extends IAbstractTreeO
export class IndexTree<T, TFilterData = void> extends AbstractTree<T, TFilterData, number[]> {
protected model!: IndexTreeModel<T, TFilterData>;
protected override model!: IndexTreeModel<T, TFilterData>;
constructor(
user: string,

View File

@@ -38,9 +38,9 @@ export interface IObjectTreeSetChildrenOptions<T> {
export class ObjectTree<T extends NonNullable<any>, TFilterData = void> extends AbstractTree<T | null, TFilterData, T | null> {
protected model!: IObjectTreeModel<T, TFilterData>;
protected override model!: IObjectTreeModel<T, TFilterData>;
get onDidChangeCollapseState(): Event<ICollapseStateChangeEvent<T | null, TFilterData>> { return this.model.onDidChangeCollapseState; }
override get onDidChangeCollapseState(): Event<ICollapseStateChangeEvent<T | null, TFilterData>> { return this.model.onDidChangeCollapseState; }
constructor(
user: string,
@@ -194,7 +194,7 @@ export interface ICompressibleObjectTreeOptionsUpdate extends IAbstractTreeOptio
export class CompressibleObjectTree<T extends NonNullable<any>, TFilterData = void> extends ObjectTree<T, TFilterData> implements ICompressedTreeNodeProvider<T, TFilterData> {
protected model!: CompressibleObjectTreeModel<T, TFilterData>;
protected override model!: CompressibleObjectTreeModel<T, TFilterData>;
constructor(
user: string,
@@ -208,15 +208,15 @@ export class CompressibleObjectTree<T extends NonNullable<any>, TFilterData = vo
super(user, container, delegate, compressibleRenderers, asObjectTreeOptions<T, TFilterData>(compressedTreeNodeProvider, options));
}
setChildren(element: T | null, children: Iterable<ICompressedTreeElement<T>> = Iterable.empty(), options?: IObjectTreeSetChildrenOptions<T>): void {
override setChildren(element: T | null, children: Iterable<ICompressedTreeElement<T>> = Iterable.empty(), options?: IObjectTreeSetChildrenOptions<T>): void {
this.model.setChildren(element, children, options);
}
protected createModel(user: string, view: IList<ITreeNode<T, TFilterData>>, options: ICompressibleObjectTreeOptions<T, TFilterData>): ITreeModel<T | null, TFilterData, T | null> {
protected override createModel(user: string, view: IList<ITreeNode<T, TFilterData>>, options: ICompressibleObjectTreeOptions<T, TFilterData>): ITreeModel<T | null, TFilterData, T | null> {
return new CompressibleObjectTreeModel(user, view, options);
}
updateOptions(optionsUpdate: ICompressibleObjectTreeOptionsUpdate = {}): void {
override updateOptions(optionsUpdate: ICompressibleObjectTreeOptionsUpdate = {}): void {
super.updateOptions(optionsUpdate);
if (typeof optionsUpdate.compressionEnabled !== 'undefined') {

View File

@@ -13,11 +13,9 @@ export class CollapseAllAction<TInput, T, TFilterData = void> extends Action {
super('vs.tree.collapse', nls.localize('collapse all', "Collapse All"), 'collapse-all', enabled);
}
async run(): Promise<any> {
override async run(): Promise<any> {
this.viewer.collapseAll();
this.viewer.setSelection([]);
this.viewer.setFocus([]);
this.viewer.domFocus();
this.viewer.focusFirst();
}
}