Merge from vscode 966b87dd4013be1a9c06e2b8334522ec61905cc2 (#4696)
@@ -3,18 +3,18 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Event as BaseEvent, Emitter } from 'vs/base/common/event';
|
||||
|
||||
export type EventHandler = HTMLElement | HTMLDocument | Window;
|
||||
|
||||
export interface IDomEvent {
|
||||
<K extends keyof HTMLElementEventMap>(element: EventHandler, type: K, useCapture?: boolean): Event<HTMLElementEventMap[K]>;
|
||||
(element: EventHandler, type: string, useCapture?: boolean): Event<any>;
|
||||
<K extends keyof HTMLElementEventMap>(element: EventHandler, type: K, useCapture?: boolean): BaseEvent<HTMLElementEventMap[K]>;
|
||||
(element: EventHandler, type: string, useCapture?: boolean): BaseEvent<any>;
|
||||
}
|
||||
|
||||
export const domEvent: IDomEvent = (element: EventHandler, type: string, useCapture?: boolean) => {
|
||||
const fn = e => emitter.fire(e);
|
||||
const emitter = new Emitter<any>({
|
||||
const fn = (e: Event) => emitter.fire(e);
|
||||
const emitter = new Emitter<Event>({
|
||||
onFirstListenerAdd: () => {
|
||||
element.addEventListener(type, fn, useCapture);
|
||||
},
|
||||
@@ -27,12 +27,12 @@ export const domEvent: IDomEvent = (element: EventHandler, type: string, useCapt
|
||||
};
|
||||
|
||||
export interface CancellableEvent {
|
||||
preventDefault();
|
||||
stopPropagation();
|
||||
preventDefault(): void;
|
||||
stopPropagation(): void;
|
||||
}
|
||||
|
||||
export function stop<T extends CancellableEvent>(event: Event<T>): Event<T> {
|
||||
return Event.map(event, e => {
|
||||
export function stop<T extends CancellableEvent>(event: BaseEvent<T>): BaseEvent<T> {
|
||||
return BaseEvent.map(event, e => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return e;
|
||||
|
||||
1
src/vs/base/browser/ui/dialog/close-inverse.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9.784 8L13 11.217 11.215 13 8.001 9.786 4.785 13 3 11.216l3.214-3.215L3 4.785 4.784 3 8 6.216 11.216 3 13 4.785 9.784 8.001z" fill="#C5C5C5"/></svg>
|
||||
|
After Width: | Height: | Size: 253 B |
1
src/vs/base/browser/ui/dialog/close.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9.784 8L13 11.217 11.215 13 8.001 9.786 4.785 13 3 11.216l3.214-3.215L3 4.785 4.784 3 8 6.216 11.216 3 13 4.785 9.784 8.001z" fill="#424242"/></svg>
|
||||
|
After Width: | Height: | Size: 253 B |
154
src/vs/base/browser/ui/dialog/dialog.css
Normal file
@@ -0,0 +1,154 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
/** Dialog: Modal Block */
|
||||
.monaco-workbench .dialog-modal-block {
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left:0;
|
||||
top:0;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
/** Dialog: Container */
|
||||
.monaco-workbench .dialog-box {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
top: 200px;
|
||||
left: 50%;
|
||||
margin-left: -250px;
|
||||
width: 500px;
|
||||
min-height: 75px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
/** Dialog: Title Actions Row */
|
||||
.monaco-workbench .dialog-box .dialog-toolbar-row {
|
||||
padding-right: 1px;
|
||||
}
|
||||
|
||||
.monaco-workbench .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-workbench .dialog-box .dialog-close-action {
|
||||
background: url('close.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .dialog-box .dialog-close-action,
|
||||
.hc-black .monaco-workbench .dialog-box .dialog-close-action {
|
||||
background: url('close-inverse.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
/** Dialog: Message Row */
|
||||
.monaco-workbench .dialog-box .dialog-message-row {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
padding: 10px 15px 20px;
|
||||
}
|
||||
|
||||
.monaco-workbench .dialog-box .dialog-message-row .dialog-icon {
|
||||
flex: 0 0 30px;
|
||||
padding-right: 4px;
|
||||
padding-left: 4px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info {
|
||||
background-image: url('info.svg');
|
||||
}
|
||||
|
||||
.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-warning {
|
||||
background-image: url('warning.svg');
|
||||
}
|
||||
|
||||
.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-error {
|
||||
background-image: url('error.svg');
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info,
|
||||
.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info {
|
||||
background-image: url('info-inverse.svg');
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-warning,
|
||||
.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-warning {
|
||||
background-image: url('warning-inverse.svg');
|
||||
}
|
||||
|
||||
.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-error,
|
||||
.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-error {
|
||||
background-image: url('error-inverse.svg');
|
||||
}
|
||||
|
||||
/** Dialog: Message Container */
|
||||
.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding-left: 20px;
|
||||
user-select: text;
|
||||
word-wrap: break-word; /* never overflow long words, but break to next line */
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
/** Dialog: Message */
|
||||
.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container .dialog-message {
|
||||
line-height: 22px;
|
||||
font-size: 18px;
|
||||
flex: 1; /* let the message always grow */
|
||||
white-space: normal;
|
||||
word-wrap: break-word; /* never overflow long words, but break to next line */
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
/** Dialog: Details */
|
||||
.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container .dialog-message-detail {
|
||||
line-height: 22px;
|
||||
flex: 1; /* let the message always grow */
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container .dialog-message a:focus {
|
||||
outline-width: 1px;
|
||||
outline-style: solid;
|
||||
}
|
||||
|
||||
/** Dialog: Buttons Row */
|
||||
.monaco-workbench .dialog-box > .dialog-buttons-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-right: 1px;
|
||||
overflow: hidden; /* buttons row should never overflow */
|
||||
}
|
||||
|
||||
.monaco-workbench .monaco-workbench .dialog-box > .dialog-buttons-row {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/** Dialog: Buttons */
|
||||
.monaco-workbench .monaco-workbench .dialog-box > .dialog-buttons-row > .dialog-buttons {
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.monaco-workbench .dialog-box > .dialog-buttons-row > .dialog-buttons > .monaco-button {
|
||||
max-width: fit-content;
|
||||
padding: 5px 10px;
|
||||
margin: 4px 5px; /* allows button focus outline to be visible */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
187
src/vs/base/browser/ui/dialog/dialog.ts
Normal file
@@ -0,0 +1,187 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./dialog';
|
||||
import * as nls from 'vs/nls';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { $, hide, show, EventHelper, clearNode, removeClasses, addClass, removeNode } from 'vs/base/browser/dom';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { ButtonGroup, 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';
|
||||
|
||||
export interface IDialogOptions {
|
||||
cancelId?: number;
|
||||
detail?: string;
|
||||
type?: 'none' | 'info' | 'error' | 'question' | 'warning';
|
||||
}
|
||||
|
||||
export interface IDialogStyles extends IButtonStyles {
|
||||
dialogForeground?: Color;
|
||||
dialogBackground?: Color;
|
||||
dialogShadow?: Color;
|
||||
}
|
||||
|
||||
export class Dialog extends Disposable {
|
||||
private element: HTMLElement | undefined;
|
||||
private modal: HTMLElement | undefined;
|
||||
private buttonsContainer: HTMLElement | undefined;
|
||||
private iconElement: HTMLElement | undefined;
|
||||
private toolbarContainer: HTMLElement | undefined;
|
||||
private buttonGroup: ButtonGroup | undefined;
|
||||
private styles: IDialogStyles | undefined;
|
||||
|
||||
constructor(private container: HTMLElement, private message: string, private buttons: string[], private options: IDialogOptions) {
|
||||
super();
|
||||
this.modal = this.container.appendChild($('.dialog-modal-block'));
|
||||
this.element = this.modal.appendChild($('.dialog-box'));
|
||||
hide(this.element);
|
||||
|
||||
const buttonsRowElement = this.element.appendChild($('.dialog-buttons-row'));
|
||||
this.buttonsContainer = buttonsRowElement.appendChild($('.dialog-buttons'));
|
||||
|
||||
const messageRowElement = this.element.appendChild($('.dialog-message-row'));
|
||||
this.iconElement = messageRowElement.appendChild($('.dialog-icon'));
|
||||
const messageContainer = messageRowElement.appendChild($('.dialog-message-container'));
|
||||
const messageElement = messageContainer.appendChild($('.dialog-message'));
|
||||
messageElement.innerText = this.message;
|
||||
if (this.options.detail) {
|
||||
const messageDetailElement = messageContainer.appendChild($('.dialog-message-detail'));
|
||||
messageDetailElement.innerText = this.options.detail;
|
||||
}
|
||||
|
||||
const toolbarRowElement = this.element.appendChild($('.dialog-toolbar-row'));
|
||||
this.toolbarContainer = toolbarRowElement.appendChild($('.dialog-toolbar'));
|
||||
}
|
||||
|
||||
async show(): Promise<number> {
|
||||
return new Promise<number>((resolve) => {
|
||||
if (!this.element || !this.buttonsContainer || !this.iconElement || !this.toolbarContainer) {
|
||||
resolve(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.modal) {
|
||||
this._register(domEvent(this.modal, 'mousedown')(e => {
|
||||
// Used to stop focusing of modal with mouse
|
||||
EventHelper.stop(e, true);
|
||||
}));
|
||||
}
|
||||
|
||||
clearNode(this.buttonsContainer);
|
||||
|
||||
let focusedButton = 0;
|
||||
this.buttonGroup = new ButtonGroup(this.buttonsContainer, this.buttons.length, { title: true });
|
||||
this.buttonGroup.buttons.forEach((button, index) => {
|
||||
button.label = mnemonicButtonLabel(this.buttons[index], true);
|
||||
|
||||
this._register(button.onDidClick(e => {
|
||||
EventHelper.stop(e);
|
||||
resolve(index);
|
||||
}));
|
||||
});
|
||||
|
||||
this._register(domEvent(this.element, 'keydown', true)((e: KeyboardEvent) => {
|
||||
const evt = new StandardKeyboardEvent(e);
|
||||
if (evt.equals(KeyCode.Enter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.buttonGroup) {
|
||||
if ((evt.shiftKey && evt.equals(KeyCode.Tab)) || evt.equals(KeyCode.LeftArrow)) {
|
||||
focusedButton = focusedButton + this.buttonGroup.buttons.length - 1;
|
||||
focusedButton = focusedButton % this.buttonGroup.buttons.length;
|
||||
this.buttonGroup.buttons[focusedButton].focus();
|
||||
} else if (evt.equals(KeyCode.Tab) || evt.equals(KeyCode.RightArrow)) {
|
||||
focusedButton++;
|
||||
focusedButton = focusedButton % this.buttonGroup.buttons.length;
|
||||
this.buttonGroup.buttons[focusedButton].focus();
|
||||
}
|
||||
}
|
||||
|
||||
EventHelper.stop(e, true);
|
||||
}));
|
||||
|
||||
this._register(domEvent(this.element, 'keyup', true)((e: KeyboardEvent) => {
|
||||
EventHelper.stop(e, true);
|
||||
const evt = new StandardKeyboardEvent(e);
|
||||
|
||||
if (evt.equals(KeyCode.Escape)) {
|
||||
resolve(this.options.cancelId || 0);
|
||||
}
|
||||
}));
|
||||
|
||||
removeClasses(this.iconElement, 'icon-error', 'icon-warning', 'icon-info');
|
||||
|
||||
switch (this.options.type) {
|
||||
case 'error':
|
||||
addClass(this.iconElement, 'icon-error');
|
||||
break;
|
||||
case 'warning':
|
||||
addClass(this.iconElement, 'icon-warning');
|
||||
break;
|
||||
case 'none':
|
||||
case 'info':
|
||||
case 'question':
|
||||
default:
|
||||
addClass(this.iconElement, 'icon-info');
|
||||
break;
|
||||
}
|
||||
|
||||
const actionBar = new ActionBar(this.toolbarContainer, {});
|
||||
|
||||
const action = new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), 'dialog-close-action', true, () => {
|
||||
resolve(this.options.cancelId || 0);
|
||||
return Promise.resolve();
|
||||
});
|
||||
|
||||
actionBar.push(action, { icon: true, label: false, });
|
||||
|
||||
this.applyStyles();
|
||||
|
||||
show(this.element);
|
||||
|
||||
// Focus first element
|
||||
this.buttonGroup.buttons[focusedButton].focus();
|
||||
});
|
||||
}
|
||||
|
||||
private applyStyles() {
|
||||
if (this.styles) {
|
||||
const style = this.styles;
|
||||
|
||||
const fgColor = style.dialogForeground ? `${style.dialogForeground}` : null;
|
||||
const bgColor = style.dialogBackground ? `${style.dialogBackground}` : null;
|
||||
const shadowColor = style.dialogShadow ? `0 0px 8px ${style.dialogShadow}` : null;
|
||||
|
||||
if (this.element) {
|
||||
this.element.style.color = fgColor;
|
||||
this.element.style.backgroundColor = bgColor;
|
||||
this.element.style.boxShadow = shadowColor;
|
||||
|
||||
if (this.buttonGroup) {
|
||||
this.buttonGroup.buttons.forEach(button => button.style(style));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
style(style: IDialogStyles): void {
|
||||
this.styles = style;
|
||||
this.applyStyles();
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
if (this.modal) {
|
||||
removeNode(this.modal);
|
||||
this.modal = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
26
src/vs/base/browser/ui/dialog/error-inverse.svg
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#CACACC;}
|
||||
.st1{fill:#E51400;}
|
||||
.st2{fill:#FFFFFF;}
|
||||
.st3{fill:#F6F6F6;fill-opacity:0;}
|
||||
.st4{fill:#1A1A1A;}
|
||||
</style>
|
||||
<path id="outline_2_" class="st0" d="M-169.7-71.2c0,1.4-1.2,2.6-2.6,2.6c-1.4,0-2.6-1.2-2.6-2.6s1.2-2.6,2.6-2.6
|
||||
C-170.9-73.8-169.7-72.6-169.7-71.2z"/>
|
||||
<path id="iconBg_2_" class="st1" d="M-172.3-73.5c-1.3,0-2.3,1-2.3,2.3s1,2.3,2.3,2.3s2.3-1,2.3-2.3S-171.1-73.5-172.3-73.5z
|
||||
M-170.9-70.2l-0.5,0.5l-1-1l-1,1l-0.5-0.5l1-1l-1-1l0.5-0.5l1,1l1-1l0.5,0.5l-1,1L-170.9-70.2z"/>
|
||||
<g id="iconFg_2_">
|
||||
<path class="st2" d="M-171.9-71.2l1,1l-0.5,0.5l-1-1l-1,1l-0.5-0.5l1-1l-1-1l0.5-0.5l1,1l1-1l0.5,0.5L-171.9-71.2z"/>
|
||||
</g>
|
||||
<path id="canvas_1_" class="st3" d="M16,16H0V0h16V16z"/>
|
||||
<path id="outline_1_" class="st4" d="M16,8c0,4.4-3.6,8-8,8s-8-3.6-8-8s3.6-8,8-8S16,3.6,16,8z"/>
|
||||
<path id="iconBg_1_" class="st1" d="M8,1C4.1,1,1,4.1,1,8c0,3.9,3.1,7,7,7s7-3.1,7-7S11.9,1,8,1z M12.4,11L11,12.4l-3-3l-3,3L3.6,11
|
||||
l3-3l-3-3L5,3.6l3,3l3-3L12.4,5l-3,3L12.4,11z"/>
|
||||
<g id="iconFg_1_">
|
||||
<path class="st2" d="M9.4,8l3,3L11,12.4l-3-3l-3,3L3.6,11l3-3l-3-3L5,3.6l3,3l3-3L12.4,5L9.4,8z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
25
src/vs/base/browser/ui/dialog/error.svg
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#CACACC;}
|
||||
.st1{fill:#E51400;}
|
||||
.st2{fill:#FFFFFF;}
|
||||
.st3{fill:#F6F6F6;fill-opacity:0;}
|
||||
</style>
|
||||
<path id="outline" class="st0" d="M16,8c0,4.4-3.6,8-8,8s-8-3.6-8-8s3.6-8,8-8S16,3.6,16,8z"/>
|
||||
<path id="iconBg" class="st1" d="M8,1C4.1,1,1,4.1,1,8c0,3.9,3.1,7,7,7s7-3.1,7-7S11.9,1,8,1z M12.4,11L11,12.4l-3-3l-3,3L3.6,11
|
||||
l3-3l-3-3L5,3.6l3,3l3-3L12.4,5l-3,3L12.4,11z"/>
|
||||
<g id="iconFg">
|
||||
<path class="st2" d="M9.4,8l3,3L11,12.4l-3-3l-3,3L3.6,11l3-3l-3-3L5,3.6l3,3l3-3L12.4,5L9.4,8z"/>
|
||||
</g>
|
||||
<path id="canvas_4_" class="st3" d="M16,16H0V0h16V16z"/>
|
||||
<path id="outline_2_" class="st0" d="M-192.7-71.2c0,1.4-1.2,2.6-2.6,2.6s-2.6-1.2-2.6-2.6s1.2-2.6,2.6-2.6S-192.7-72.6-192.7-71.2z
|
||||
"/>
|
||||
<path id="iconBg_2_" class="st1" d="M-195.4-73.5c-1.3,0-2.3,1-2.3,2.3s1,2.3,2.3,2.3c1.3,0,2.3-1,2.3-2.3S-194.1-73.5-195.4-73.5z
|
||||
M-193.9-70.2l-0.5,0.5l-1-1l-1,1l-0.5-0.5l1-1l-1-1l0.5-0.5l1,1l1-1l0.5,0.5l-1,1L-193.9-70.2z"/>
|
||||
<g id="iconFg_2_">
|
||||
<path class="st2" d="M-194.9-71.2l1,1l-0.5,0.5l-1-1l-1,1l-0.5-0.5l1-1l-1-1l0.5-0.5l1,1l1-1l0.5,0.5L-194.9-71.2z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
17
src/vs/base/browser/ui/dialog/info-inverse.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#F6F6F6;fill-opacity:0;}
|
||||
.st1{fill:#1A1A1A;}
|
||||
.st2{fill:#1BA1E2;}
|
||||
.st3{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path id="canvas_1_" class="st0" d="M16,16H0V0h16V16z"/>
|
||||
<path id="outline_1_" class="st1" d="M0,8c0-4.4,3.6-8,8-8s8,3.6,8,8s-3.6,8-8,8S0,12.4,0,8z"/>
|
||||
<path id="iconBg_1_" class="st2" d="M8,1C4.1,1,1,4.1,1,8s3.1,7,7,7s7-3.1,7-7S11.9,1,8,1z M9,13H7V6h2V13z M9,5H7V3h2V5z"/>
|
||||
<g id="iconFg_1_">
|
||||
<path class="st3" d="M7,6h2v7H7V6z M7,5h2V3H7V5z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 834 B |
17
src/vs/base/browser/ui/dialog/info.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#F6F6F6;fill-opacity:0;}
|
||||
.st1{fill:#CACACC;}
|
||||
.st2{fill:#1BA1E2;}
|
||||
.st3{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path id="canvas" class="st0" d="M16,16H0V0h16V16z"/>
|
||||
<path id="outline" class="st1" d="M0,8c0-4.4,3.6-8,8-8s8,3.6,8,8s-3.6,8-8,8S0,12.4,0,8z"/>
|
||||
<path id="iconBg" class="st2" d="M8,1C4.1,1,1,4.1,1,8s3.1,7,7,7s7-3.1,7-7S11.8,1,8,1z M9,13H7V6h2V13z M9,5H7V3h2V5z"/>
|
||||
<g id="iconFg">
|
||||
<path class="st3" d="M7,6h2v7H7V6z M7,5h2V3H7V5z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 822 B |
15
src/vs/base/browser/ui/dialog/warning-inverse.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#F6F6F6;fill-opacity:0;}
|
||||
.st1{fill:#1A1A1A;}
|
||||
.st2{fill:#FFCC00;}
|
||||
</style>
|
||||
<title>StatusWarning_16x</title>
|
||||
<path class="st0" d="M16,0v16H0V0H16z"/>
|
||||
<path class="st1" d="M16,14l-2,2H2l-2-2L7,0h2L16,14z"/>
|
||||
<path class="st2" d="M8.4,1H7.6L1.2,13.8L2.5,15h11l1.3-1.2L8.4,1z M9,13H7v-2h2V13z M9,10H7V5h2V10z"/>
|
||||
<path d="M7,11h2v2H7V11z M7,5v5h2V5H7z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 737 B |
15
src/vs/base/browser/ui/dialog/warning.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#F6F6F6;fill-opacity:0;}
|
||||
.st1{fill:#CACACC;}
|
||||
.st2{fill:#FFCC00;}
|
||||
</style>
|
||||
<title>StatusWarning_16x</title>
|
||||
<path class="st0" d="M16,0v16H0V0H16z"/>
|
||||
<path class="st1" d="M16,14l-2,2H2l-2-2L7,0h2L16,14z"/>
|
||||
<path class="st2" d="M8.4,1H7.6L1.2,13.8L2.5,15h11l1.3-1.2L8.4,1z M9,13H7v-2h2V13z M9,10H7V5h2V10z"/>
|
||||
<path d="M7,11h2v2H7V11z M7,5v5h2V5H7z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 737 B |
@@ -7,7 +7,7 @@ import 'vs/css!./list';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { isNumber } from 'vs/base/common/types';
|
||||
import { range, firstIndex } from 'vs/base/common/arrays';
|
||||
import { range, firstIndex, binarySearch } from 'vs/base/common/arrays';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
@@ -107,10 +107,8 @@ class TraitRenderer<T> implements IListRenderer<T, ITraitTemplateData>
|
||||
|
||||
class Trait<T> implements ISpliceable<boolean>, IDisposable {
|
||||
|
||||
/**
|
||||
* Sorted indexes which have this trait.
|
||||
*/
|
||||
private indexes: number[];
|
||||
private indexes: number[] = [];
|
||||
private sortedIndexes: number[] = [];
|
||||
|
||||
private _onChange = new Emitter<ITraitChangeEvent>();
|
||||
get onChange(): Event<ITraitChangeEvent> { return this._onChange.event; }
|
||||
@@ -122,21 +120,19 @@ class Trait<T> implements ISpliceable<boolean>, IDisposable {
|
||||
return new TraitRenderer<T>(this);
|
||||
}
|
||||
|
||||
constructor(private _trait: string) {
|
||||
this.indexes = [];
|
||||
}
|
||||
constructor(private _trait: string) { }
|
||||
|
||||
splice(start: number, deleteCount: number, elements: boolean[]): void {
|
||||
const diff = elements.length - deleteCount;
|
||||
const end = start + deleteCount;
|
||||
const indexes = [
|
||||
...this.indexes.filter(i => i < start),
|
||||
...this.sortedIndexes.filter(i => i < start),
|
||||
...elements.map((hasTrait, i) => hasTrait ? i + start : -1).filter(i => i !== -1),
|
||||
...this.indexes.filter(i => i >= end).map(i => i + diff)
|
||||
...this.sortedIndexes.filter(i => i >= end).map(i => i + diff)
|
||||
];
|
||||
|
||||
this.renderer.splice(start, deleteCount, elements.length);
|
||||
this.set(indexes);
|
||||
this._set(indexes, indexes);
|
||||
}
|
||||
|
||||
renderIndex(index: number, container: HTMLElement): void {
|
||||
@@ -154,10 +150,17 @@ class Trait<T> implements ISpliceable<boolean>, IDisposable {
|
||||
* @return The old indexes which had this trait.
|
||||
*/
|
||||
set(indexes: number[], browserEvent?: UIEvent): number[] {
|
||||
const result = this.indexes;
|
||||
this.indexes = indexes;
|
||||
return this._set(indexes, [...indexes].sort(numericSort), browserEvent);
|
||||
}
|
||||
|
||||
const toRender = disjunction(result, indexes);
|
||||
private _set(indexes: number[], sortedIndexes: number[], browserEvent?: UIEvent): number[] {
|
||||
const result = this.indexes;
|
||||
const sortedResult = this.sortedIndexes;
|
||||
|
||||
this.indexes = indexes;
|
||||
this.sortedIndexes = sortedIndexes;
|
||||
|
||||
const toRender = disjunction(sortedResult, indexes);
|
||||
this.renderer.renderIndexes(toRender);
|
||||
|
||||
this._onChange.fire({ indexes, browserEvent });
|
||||
@@ -169,7 +172,7 @@ class Trait<T> implements ISpliceable<boolean>, IDisposable {
|
||||
}
|
||||
|
||||
contains(index: number): boolean {
|
||||
return this.indexes.some(i => i === index);
|
||||
return binarySearch(this.sortedIndexes, index, numericSort) >= 0;
|
||||
}
|
||||
|
||||
dispose() {
|
||||
@@ -1334,7 +1337,6 @@ export class List<T> implements ISpliceable<T>, IDisposable {
|
||||
}
|
||||
}
|
||||
|
||||
indexes = indexes.sort(numericSort);
|
||||
this.selection.set(indexes, browserEvent);
|
||||
}
|
||||
|
||||
@@ -1353,7 +1355,6 @@ export class List<T> implements ISpliceable<T>, IDisposable {
|
||||
}
|
||||
}
|
||||
|
||||
indexes = indexes.sort(numericSort);
|
||||
this.focus.set(indexes, browserEvent);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ITreeModel, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeFilter, ITreeNavigator, ICollapseStateChangeEvent, ITreeDragAndDrop, TreeDragOverBubble, TreeVisibility, TreeFilterResult, ITreeModelSpliceEvent } from 'vs/base/browser/ui/tree/tree';
|
||||
import { ISpliceable } from 'vs/base/common/sequence';
|
||||
import { IDragAndDropData, StaticDND, DragAndDropData } from 'vs/base/browser/dnd';
|
||||
import { range, equals } from 'vs/base/common/arrays';
|
||||
import { range, equals, distinctES6 } from 'vs/base/common/arrays';
|
||||
import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { fuzzyScore, FuzzyScore } from 'vs/base/common/filters';
|
||||
@@ -924,7 +924,7 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
|
||||
const additionalSelection: number[] = [];
|
||||
|
||||
elements.forEach((node, index) => {
|
||||
if (this.selectionTrait.has(node)) {
|
||||
if (this.focusTrait.has(node)) {
|
||||
additionalFocus.push(start + index);
|
||||
}
|
||||
|
||||
@@ -934,11 +934,11 @@ class TreeNodeList<T, TFilterData, TRef> extends List<ITreeNode<T, TFilterData>>
|
||||
});
|
||||
|
||||
if (additionalFocus.length > 0) {
|
||||
super.setFocus([...super.getFocus(), ...additionalFocus]);
|
||||
super.setFocus(distinctES6([...super.getFocus(), ...additionalFocus]));
|
||||
}
|
||||
|
||||
if (additionalSelection.length > 0) {
|
||||
super.setSelection([...super.getSelection(), ...additionalSelection]);
|
||||
super.setSelection(distinctES6([...super.getSelection(), ...additionalSelection]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||