mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 817eb6b0c720a4ecbc13c020afbbebfed667aa09 (#7356)
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
@font-face {
|
||||
font-family: "codicon";
|
||||
src: url("./codicon.ttf?e042d2dda15ef7b36b910e3edf539f26") format("truetype");
|
||||
src: url("./codicon.ttf?3b584136fb1f0186a1ee578cdcb5240b") format("truetype");
|
||||
}
|
||||
|
||||
.codicon[class*='codicon-'] {
|
||||
@@ -203,152 +203,153 @@
|
||||
.codicon-folder-active:before { content: "\f162" }
|
||||
.codicon-folder-opened:before { content: "\f163" }
|
||||
.codicon-folder:before { content: "\f164" }
|
||||
.codicon-gift:before { content: "\f165" }
|
||||
.codicon-gist-secret:before { content: "\f166" }
|
||||
.codicon-gist:before { content: "\f167" }
|
||||
.codicon-git-commit:before { content: "\f168" }
|
||||
.codicon-git-compare:before { content: "\f169" }
|
||||
.codicon-git-merge:before { content: "\f16a" }
|
||||
.codicon-github-action:before { content: "\f16b" }
|
||||
.codicon-github-alt:before { content: "\f16c" }
|
||||
.codicon-github:before { content: "\f16d" }
|
||||
.codicon-globe:before { content: "\f16e" }
|
||||
.codicon-go-to-file:before { content: "\f16f" }
|
||||
.codicon-grabber:before { content: "\f170" }
|
||||
.codicon-graph:before { content: "\f171" }
|
||||
.codicon-gripper:before { content: "\f172" }
|
||||
.codicon-heart:before { content: "\f173" }
|
||||
.codicon-history:before { content: "\f174" }
|
||||
.codicon-home:before { content: "\f175" }
|
||||
.codicon-horizontal-rule:before { content: "\f176" }
|
||||
.codicon-hubot:before { content: "\f177" }
|
||||
.codicon-inbox:before { content: "\f178" }
|
||||
.codicon-interface:before { content: "\f179" }
|
||||
.codicon-issue-closed:before { content: "\f17a" }
|
||||
.codicon-issue-reopened:before { content: "\f17b" }
|
||||
.codicon-issues:before { content: "\f17c" }
|
||||
.codicon-italic:before { content: "\f17d" }
|
||||
.codicon-jersey:before { content: "\f17e" }
|
||||
.codicon-json:before { content: "\f17f" }
|
||||
.codicon-kebab-vertical:before { content: "\f180" }
|
||||
.codicon-key:before { content: "\f181" }
|
||||
.codicon-keyword:before { content: "\f182" }
|
||||
.codicon-law:before { content: "\f183" }
|
||||
.codicon-lightbulb-autofix:before { content: "\f184" }
|
||||
.codicon-link-external:before { content: "\f185" }
|
||||
.codicon-link:before { content: "\f186" }
|
||||
.codicon-list-ordered:before { content: "\f187" }
|
||||
.codicon-list-unordered:before { content: "\f188" }
|
||||
.codicon-live-share:before { content: "\f189" }
|
||||
.codicon-loading:before { content: "\f18a" }
|
||||
.codicon-location:before { content: "\f18b" }
|
||||
.codicon-mail-read:before { content: "\f18c" }
|
||||
.codicon-mail:before { content: "\f18d" }
|
||||
.codicon-markdown:before { content: "\f18e" }
|
||||
.codicon-megaphone:before { content: "\f18f" }
|
||||
.codicon-mention:before { content: "\f190" }
|
||||
.codicon-method:before { content: "\f191" }
|
||||
.codicon-milestone:before { content: "\f192" }
|
||||
.codicon-misc:before { content: "\f193" }
|
||||
.codicon-mortar-board:before { content: "\f194" }
|
||||
.codicon-move:before { content: "\f195" }
|
||||
.codicon-multiple-windows:before { content: "\f196" }
|
||||
.codicon-mute:before { content: "\f197" }
|
||||
.codicon-namespace:before { content: "\f198" }
|
||||
.codicon-no-newline:before { content: "\f199" }
|
||||
.codicon-note:before { content: "\f19a" }
|
||||
.codicon-numeric:before { content: "\f19b" }
|
||||
.codicon-octoface:before { content: "\f19c" }
|
||||
.codicon-open-preview:before { content: "\f19d" }
|
||||
.codicon-operator:before { content: "\f19e" }
|
||||
.codicon-package:before { content: "\f19f" }
|
||||
.codicon-paintcan:before { content: "\f1a0" }
|
||||
.codicon-parameter:before { content: "\f1a1" }
|
||||
.codicon-pause:before { content: "\f1a2" }
|
||||
.codicon-pin:before { content: "\f1a3" }
|
||||
.codicon-play:before { content: "\f1a4" }
|
||||
.codicon-plug:before { content: "\f1a5" }
|
||||
.codicon-preserve-case:before { content: "\f1a6" }
|
||||
.codicon-preview:before { content: "\f1a7" }
|
||||
.codicon-project:before { content: "\f1a8" }
|
||||
.codicon-property:before { content: "\f1a9" }
|
||||
.codicon-pulse:before { content: "\f1aa" }
|
||||
.codicon-question:before { content: "\f1ab" }
|
||||
.codicon-quote:before { content: "\f1ac" }
|
||||
.codicon-radio-tower:before { content: "\f1ad" }
|
||||
.codicon-reactions:before { content: "\f1ae" }
|
||||
.codicon-references:before { content: "\f1af" }
|
||||
.codicon-refresh:before { content: "\f1b0" }
|
||||
.codicon-regex:before { content: "\f1b1" }
|
||||
.codicon-remote:before { content: "\f1b2" }
|
||||
.codicon-remove:before { content: "\f1b3" }
|
||||
.codicon-replace-all:before { content: "\f1b4" }
|
||||
.codicon-replace:before { content: "\f1b5" }
|
||||
.codicon-repo-clone:before { content: "\f1b6" }
|
||||
.codicon-repo-force-push:before { content: "\f1b7" }
|
||||
.codicon-repo-pull:before { content: "\f1b8" }
|
||||
.codicon-repo-push:before { content: "\f1b9" }
|
||||
.codicon-report:before { content: "\f1ba" }
|
||||
.codicon-request-changes:before { content: "\f1bb" }
|
||||
.codicon-restart:before { content: "\f1bc" }
|
||||
.codicon-rocket:before { content: "\f1bd" }
|
||||
.codicon-root-folder-opened:before { content: "\f1be" }
|
||||
.codicon-root-folder:before { content: "\f1bf" }
|
||||
.codicon-rss:before { content: "\f1c0" }
|
||||
.codicon-ruby:before { content: "\f1c1" }
|
||||
.codicon-ruler:before { content: "\f1c2" }
|
||||
.codicon-save-all:before { content: "\f1c3" }
|
||||
.codicon-save-as:before { content: "\f1c4" }
|
||||
.codicon-save:before { content: "\f1c5" }
|
||||
.codicon-screen-full:before { content: "\f1c6" }
|
||||
.codicon-screen-normal:before { content: "\f1c7" }
|
||||
.codicon-search-stop:before { content: "\f1c8" }
|
||||
.codicon-selection:before { content: "\f1c9" }
|
||||
.codicon-server:before { content: "\f1ca" }
|
||||
.codicon-settings:before { content: "\f1cb" }
|
||||
.codicon-shield:before { content: "\f1cc" }
|
||||
.codicon-smiley:before { content: "\f1cd" }
|
||||
.codicon-snippet:before { content: "\f1ce" }
|
||||
.codicon-sort-precedence:before { content: "\f1cf" }
|
||||
.codicon-split-horizontal:before { content: "\f1d0" }
|
||||
.codicon-split-vertical:before { content: "\f1d1" }
|
||||
.codicon-squirrel:before { content: "\f1d2" }
|
||||
.codicon-star-empty:before { content: "\f1d3" }
|
||||
.codicon-star-full:before { content: "\f1d4" }
|
||||
.codicon-star-half:before { content: "\f1d5" }
|
||||
.codicon-start:before { content: "\f1d6" }
|
||||
.codicon-step-into:before { content: "\f1d7" }
|
||||
.codicon-step-out:before { content: "\f1d8" }
|
||||
.codicon-step-over:before { content: "\f1d9" }
|
||||
.codicon-string:before { content: "\f1da" }
|
||||
.codicon-structure:before { content: "\f1db" }
|
||||
.codicon-tasklist:before { content: "\f1dc" }
|
||||
.codicon-telescope:before { content: "\f1dd" }
|
||||
.codicon-text-size:before { content: "\f1de" }
|
||||
.codicon-three-bars:before { content: "\f1df" }
|
||||
.codicon-thumbsdown:before { content: "\f1e0" }
|
||||
.codicon-thumbsup:before { content: "\f1e1" }
|
||||
.codicon-tools:before { content: "\f1e2" }
|
||||
.codicon-trash:before { content: "\f1e3" }
|
||||
.codicon-triangle-down:before { content: "\f1e4" }
|
||||
.codicon-triangle-left:before { content: "\f1e5" }
|
||||
.codicon-triangle-right:before { content: "\f1e6" }
|
||||
.codicon-triangle-up:before { content: "\f1e7" }
|
||||
.codicon-twitter:before { content: "\f1e8" }
|
||||
.codicon-unfold:before { content: "\f1e9" }
|
||||
.codicon-unlock:before { content: "\f1ea" }
|
||||
.codicon-unmute:before { content: "\f1eb" }
|
||||
.codicon-unverified:before { content: "\f1ec" }
|
||||
.codicon-variable:before { content: "\f1ed" }
|
||||
.codicon-verified:before { content: "\f1ee" }
|
||||
.codicon-versions:before { content: "\f1ef" }
|
||||
.codicon-vm-active:before { content: "\f1f0" }
|
||||
.codicon-vm-outline:before { content: "\f1f1" }
|
||||
.codicon-vm-running:before { content: "\f1f2" }
|
||||
.codicon-watch:before { content: "\f1f3" }
|
||||
.codicon-whitespace:before { content: "\f1f4" }
|
||||
.codicon-whole-word:before { content: "\f1f5" }
|
||||
.codicon-window:before { content: "\f1f6" }
|
||||
.codicon-word-wrap:before { content: "\f1f7" }
|
||||
.codicon-zoom-in:before { content: "\f1f8" }
|
||||
.codicon-zoom-out:before { content: "\f1f9" }
|
||||
.codicon-gear:before { content: "\f165" }
|
||||
.codicon-gift:before { content: "\f166" }
|
||||
.codicon-gist-secret:before { content: "\f167" }
|
||||
.codicon-gist:before { content: "\f168" }
|
||||
.codicon-git-commit:before { content: "\f169" }
|
||||
.codicon-git-compare:before { content: "\f16a" }
|
||||
.codicon-git-merge:before { content: "\f16b" }
|
||||
.codicon-github-action:before { content: "\f16c" }
|
||||
.codicon-github-alt:before { content: "\f16d" }
|
||||
.codicon-github:before { content: "\f16e" }
|
||||
.codicon-globe:before { content: "\f16f" }
|
||||
.codicon-go-to-file:before { content: "\f170" }
|
||||
.codicon-grabber:before { content: "\f171" }
|
||||
.codicon-graph:before { content: "\f172" }
|
||||
.codicon-gripper:before { content: "\f173" }
|
||||
.codicon-heart:before { content: "\f174" }
|
||||
.codicon-history:before { content: "\f175" }
|
||||
.codicon-home:before { content: "\f176" }
|
||||
.codicon-horizontal-rule:before { content: "\f177" }
|
||||
.codicon-hubot:before { content: "\f178" }
|
||||
.codicon-inbox:before { content: "\f179" }
|
||||
.codicon-interface:before { content: "\f17a" }
|
||||
.codicon-issue-closed:before { content: "\f17b" }
|
||||
.codicon-issue-reopened:before { content: "\f17c" }
|
||||
.codicon-issues:before { content: "\f17d" }
|
||||
.codicon-italic:before { content: "\f17e" }
|
||||
.codicon-jersey:before { content: "\f17f" }
|
||||
.codicon-json:before { content: "\f180" }
|
||||
.codicon-kebab-vertical:before { content: "\f181" }
|
||||
.codicon-key:before { content: "\f182" }
|
||||
.codicon-keyword:before { content: "\f183" }
|
||||
.codicon-law:before { content: "\f184" }
|
||||
.codicon-lightbulb-autofix:before { content: "\f185" }
|
||||
.codicon-link-external:before { content: "\f186" }
|
||||
.codicon-link:before { content: "\f187" }
|
||||
.codicon-list-ordered:before { content: "\f188" }
|
||||
.codicon-list-unordered:before { content: "\f189" }
|
||||
.codicon-live-share:before { content: "\f18a" }
|
||||
.codicon-loading:before { content: "\f18b" }
|
||||
.codicon-location:before { content: "\f18c" }
|
||||
.codicon-mail-read:before { content: "\f18d" }
|
||||
.codicon-mail:before { content: "\f18e" }
|
||||
.codicon-markdown:before { content: "\f18f" }
|
||||
.codicon-megaphone:before { content: "\f190" }
|
||||
.codicon-mention:before { content: "\f191" }
|
||||
.codicon-method:before { content: "\f192" }
|
||||
.codicon-milestone:before { content: "\f193" }
|
||||
.codicon-misc:before { content: "\f194" }
|
||||
.codicon-mortar-board:before { content: "\f195" }
|
||||
.codicon-move:before { content: "\f196" }
|
||||
.codicon-multiple-windows:before { content: "\f197" }
|
||||
.codicon-mute:before { content: "\f198" }
|
||||
.codicon-namespace:before { content: "\f199" }
|
||||
.codicon-no-newline:before { content: "\f19a" }
|
||||
.codicon-note:before { content: "\f19b" }
|
||||
.codicon-numeric:before { content: "\f19c" }
|
||||
.codicon-octoface:before { content: "\f19d" }
|
||||
.codicon-open-preview:before { content: "\f19e" }
|
||||
.codicon-operator:before { content: "\f19f" }
|
||||
.codicon-package:before { content: "\f1a0" }
|
||||
.codicon-paintcan:before { content: "\f1a1" }
|
||||
.codicon-parameter:before { content: "\f1a2" }
|
||||
.codicon-pause:before { content: "\f1a3" }
|
||||
.codicon-pin:before { content: "\f1a4" }
|
||||
.codicon-play:before { content: "\f1a5" }
|
||||
.codicon-plug:before { content: "\f1a6" }
|
||||
.codicon-preserve-case:before { content: "\f1a7" }
|
||||
.codicon-preview:before { content: "\f1a8" }
|
||||
.codicon-project:before { content: "\f1a9" }
|
||||
.codicon-property:before { content: "\f1aa" }
|
||||
.codicon-pulse:before { content: "\f1ab" }
|
||||
.codicon-question:before { content: "\f1ac" }
|
||||
.codicon-quote:before { content: "\f1ad" }
|
||||
.codicon-radio-tower:before { content: "\f1ae" }
|
||||
.codicon-reactions:before { content: "\f1af" }
|
||||
.codicon-references:before { content: "\f1b0" }
|
||||
.codicon-refresh:before { content: "\f1b1" }
|
||||
.codicon-regex:before { content: "\f1b2" }
|
||||
.codicon-remote:before { content: "\f1b3" }
|
||||
.codicon-remove:before { content: "\f1b4" }
|
||||
.codicon-replace-all:before { content: "\f1b5" }
|
||||
.codicon-replace:before { content: "\f1b6" }
|
||||
.codicon-repo-clone:before { content: "\f1b7" }
|
||||
.codicon-repo-force-push:before { content: "\f1b8" }
|
||||
.codicon-repo-pull:before { content: "\f1b9" }
|
||||
.codicon-repo-push:before { content: "\f1ba" }
|
||||
.codicon-report:before { content: "\f1bb" }
|
||||
.codicon-request-changes:before { content: "\f1bc" }
|
||||
.codicon-restart:before { content: "\f1bd" }
|
||||
.codicon-rocket:before { content: "\f1be" }
|
||||
.codicon-root-folder-opened:before { content: "\f1bf" }
|
||||
.codicon-root-folder:before { content: "\f1c0" }
|
||||
.codicon-rss:before { content: "\f1c1" }
|
||||
.codicon-ruby:before { content: "\f1c2" }
|
||||
.codicon-ruler:before { content: "\f1c3" }
|
||||
.codicon-save-all:before { content: "\f1c4" }
|
||||
.codicon-save-as:before { content: "\f1c5" }
|
||||
.codicon-save:before { content: "\f1c6" }
|
||||
.codicon-screen-full:before { content: "\f1c7" }
|
||||
.codicon-screen-normal:before { content: "\f1c8" }
|
||||
.codicon-search-stop:before { content: "\f1c9" }
|
||||
.codicon-selection:before { content: "\f1ca" }
|
||||
.codicon-server:before { content: "\f1cb" }
|
||||
.codicon-settings:before { content: "\f1cc" }
|
||||
.codicon-shield:before { content: "\f1cd" }
|
||||
.codicon-smiley:before { content: "\f1ce" }
|
||||
.codicon-snippet:before { content: "\f1cf" }
|
||||
.codicon-sort-precedence:before { content: "\f1d0" }
|
||||
.codicon-split-horizontal:before { content: "\f1d1" }
|
||||
.codicon-split-vertical:before { content: "\f1d2" }
|
||||
.codicon-squirrel:before { content: "\f1d3" }
|
||||
.codicon-star-empty:before { content: "\f1d4" }
|
||||
.codicon-star-full:before { content: "\f1d5" }
|
||||
.codicon-star-half:before { content: "\f1d6" }
|
||||
.codicon-start:before { content: "\f1d7" }
|
||||
.codicon-step-into:before { content: "\f1d8" }
|
||||
.codicon-step-out:before { content: "\f1d9" }
|
||||
.codicon-step-over:before { content: "\f1da" }
|
||||
.codicon-string:before { content: "\f1db" }
|
||||
.codicon-structure:before { content: "\f1dc" }
|
||||
.codicon-tasklist:before { content: "\f1dd" }
|
||||
.codicon-telescope:before { content: "\f1de" }
|
||||
.codicon-text-size:before { content: "\f1df" }
|
||||
.codicon-three-bars:before { content: "\f1e0" }
|
||||
.codicon-thumbsdown:before { content: "\f1e1" }
|
||||
.codicon-thumbsup:before { content: "\f1e2" }
|
||||
.codicon-tools:before { content: "\f1e3" }
|
||||
.codicon-trash:before { content: "\f1e4" }
|
||||
.codicon-triangle-down:before { content: "\f1e5" }
|
||||
.codicon-triangle-left:before { content: "\f1e6" }
|
||||
.codicon-triangle-right:before { content: "\f1e7" }
|
||||
.codicon-triangle-up:before { content: "\f1e8" }
|
||||
.codicon-twitter:before { content: "\f1e9" }
|
||||
.codicon-unfold:before { content: "\f1ea" }
|
||||
.codicon-unlock:before { content: "\f1eb" }
|
||||
.codicon-unmute:before { content: "\f1ec" }
|
||||
.codicon-unverified:before { content: "\f1ed" }
|
||||
.codicon-variable:before { content: "\f1ee" }
|
||||
.codicon-verified:before { content: "\f1ef" }
|
||||
.codicon-versions:before { content: "\f1f0" }
|
||||
.codicon-vm-active:before { content: "\f1f1" }
|
||||
.codicon-vm-outline:before { content: "\f1f2" }
|
||||
.codicon-vm-running:before { content: "\f1f3" }
|
||||
.codicon-watch:before { content: "\f1f4" }
|
||||
.codicon-whitespace:before { content: "\f1f5" }
|
||||
.codicon-whole-word:before { content: "\f1f6" }
|
||||
.codicon-window:before { content: "\f1f7" }
|
||||
.codicon-word-wrap:before { content: "\f1f8" }
|
||||
.codicon-zoom-in:before { content: "\f1f9" }
|
||||
.codicon-zoom-out:before { content: "\f1fa" }
|
||||
|
||||
Binary file not shown.
@@ -1,24 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { escape } from 'vs/base/common/strings';
|
||||
|
||||
export function renderCodicons(text: string): string {
|
||||
return escape(text);
|
||||
}
|
||||
|
||||
export class CodiconLabel {
|
||||
|
||||
private _container: HTMLElement;
|
||||
|
||||
constructor(container: HTMLElement) {
|
||||
this._container = container;
|
||||
}
|
||||
|
||||
set text(text: string) {
|
||||
this._container.innerHTML = renderCodicons(text || '');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -295,7 +295,7 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem {
|
||||
|
||||
render(container: HTMLElement): void {
|
||||
const labelRenderer: ILabelRenderer = (el: HTMLElement): IDisposable | null => {
|
||||
this.element = append(el, $('a.action-label.icon'));
|
||||
this.element = append(el, $('a.action-label.codicon'));
|
||||
if (this.clazz) {
|
||||
addClasses(this.element, this.clazz);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ export interface IReplaceInputOptions extends IReplaceInputStyles {
|
||||
|
||||
export interface IReplaceInputStyles extends IInputBoxStyles {
|
||||
inputActiveOptionBorder?: Color;
|
||||
inputActiveOptionBackground?: Color;
|
||||
}
|
||||
|
||||
const NLS_DEFAULT_LABEL = nls.localize('defaultLabel', "input");
|
||||
@@ -44,7 +45,8 @@ export class PreserveCaseCheckbox extends Checkbox {
|
||||
actionClassName: 'codicon-preserve-case',
|
||||
title: NLS_PRESERVE_CASE_LABEL + opts.appendTitle,
|
||||
isChecked: opts.isChecked,
|
||||
inputActiveOptionBorder: opts.inputActiveOptionBorder
|
||||
inputActiveOptionBorder: opts.inputActiveOptionBorder,
|
||||
inputActiveOptionBackground: opts.inputActiveOptionBackground
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -60,6 +62,7 @@ export class ReplaceInput extends Widget {
|
||||
private fixFocusOnOptionClickEnabled = true;
|
||||
|
||||
private inputActiveOptionBorder?: Color;
|
||||
private inputActiveOptionBackground?: Color;
|
||||
private inputBackground?: Color;
|
||||
private inputForeground?: Color;
|
||||
private inputBorder?: Color;
|
||||
@@ -105,6 +108,7 @@ export class ReplaceInput extends Widget {
|
||||
this.label = options.label || NLS_DEFAULT_LABEL;
|
||||
|
||||
this.inputActiveOptionBorder = options.inputActiveOptionBorder;
|
||||
this.inputActiveOptionBackground = options.inputActiveOptionBackground;
|
||||
this.inputBackground = options.inputBackground;
|
||||
this.inputForeground = options.inputForeground;
|
||||
this.inputBorder = options.inputBorder;
|
||||
@@ -181,6 +185,7 @@ export class ReplaceInput extends Widget {
|
||||
|
||||
public style(styles: IReplaceInputStyles): void {
|
||||
this.inputActiveOptionBorder = styles.inputActiveOptionBorder;
|
||||
this.inputActiveOptionBackground = styles.inputActiveOptionBackground;
|
||||
this.inputBackground = styles.inputBackground;
|
||||
this.inputForeground = styles.inputForeground;
|
||||
this.inputBorder = styles.inputBorder;
|
||||
@@ -202,6 +207,7 @@ export class ReplaceInput extends Widget {
|
||||
if (this.domNode) {
|
||||
const checkBoxStyles: ICheckboxStyles = {
|
||||
inputActiveOptionBorder: this.inputActiveOptionBorder,
|
||||
inputActiveOptionBackground: this.inputActiveOptionBackground,
|
||||
};
|
||||
this.preserveCase.style(checkBoxStyles);
|
||||
|
||||
@@ -281,7 +287,8 @@ export class ReplaceInput extends Widget {
|
||||
this.preserveCase = this._register(new PreserveCaseCheckbox({
|
||||
appendTitle: '',
|
||||
isChecked: false,
|
||||
inputActiveOptionBorder: this.inputActiveOptionBorder
|
||||
inputActiveOptionBorder: this.inputActiveOptionBorder,
|
||||
inputActiveOptionBackground: this.inputActiveOptionBackground,
|
||||
}));
|
||||
this._register(this.preserveCase.onChange(viaKeyboard => {
|
||||
this._onDidOptionChange.fire(viaKeyboard);
|
||||
|
||||
@@ -188,12 +188,12 @@ class BranchNode implements ISplitView, IDisposable {
|
||||
return this.orientation === Orientation.HORIZONTAL ? this.maximumSize : this.maximumOrthogonalSize;
|
||||
}
|
||||
|
||||
private _onDidChange = new Emitter<number | undefined>();
|
||||
private readonly _onDidChange = new Emitter<number | undefined>();
|
||||
readonly onDidChange: Event<number | undefined> = this._onDidChange.event;
|
||||
|
||||
private childrenChangeDisposable: IDisposable = Disposable.None;
|
||||
|
||||
private _onDidSashReset = new Emitter<number[]>();
|
||||
private readonly _onDidSashReset = new Emitter<number[]>();
|
||||
readonly onDidSashReset: Event<number[]> = this._onDidSashReset.event;
|
||||
private splitviewSashResetDisposable: IDisposable = Disposable.None;
|
||||
private childrenSashResetDisposable: IDisposable = Disposable.None;
|
||||
@@ -539,7 +539,7 @@ class LeafNode implements ISplitView, IDisposable {
|
||||
this._onDidSetLinkedNode.fire(undefined);
|
||||
}
|
||||
|
||||
private _onDidSetLinkedNode = new Emitter<number | undefined>();
|
||||
private readonly _onDidSetLinkedNode = new Emitter<number | undefined>();
|
||||
private _onDidViewChange: Event<number | undefined>;
|
||||
readonly onDidChange: Event<number | undefined>;
|
||||
|
||||
|
||||
@@ -79,7 +79,10 @@ export interface IKeyboardNavigationLabelProvider<T> {
|
||||
* element always match.
|
||||
*/
|
||||
getKeyboardNavigationLabel(element: T): { toString(): string | undefined; } | undefined;
|
||||
mightProducePrintableCharacter?(event: IKeyboardEvent): boolean;
|
||||
}
|
||||
|
||||
export interface IKeyboardNavigationDelegate {
|
||||
mightProducePrintableCharacter(event: IKeyboardEvent): boolean;
|
||||
}
|
||||
|
||||
export const enum ListDragOverEffect {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./list';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { range } from 'vs/base/common/arrays';
|
||||
import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent } from './list';
|
||||
import { List, IListStyles, IListOptions } from './listWidget';
|
||||
@@ -32,7 +32,7 @@ class PagedRenderer<TElement, TTemplateData> implements IListRenderer<number, IT
|
||||
|
||||
renderTemplate(container: HTMLElement): ITemplateData<TTemplateData> {
|
||||
const data = this.renderer.renderTemplate(container);
|
||||
return { data, disposable: { dispose: () => { } } };
|
||||
return { data, disposable: Disposable.None };
|
||||
}
|
||||
|
||||
renderElement(index: number, _: number, data: ITemplateData<TTemplateData>, height: number | undefined): void {
|
||||
@@ -127,7 +127,7 @@ export class PagedList<T> implements IDisposable {
|
||||
}
|
||||
|
||||
get onPin(): Event<IListEvent<T>> {
|
||||
return Event.map(this.list.onPin, ({ elements, indexes }) => ({ elements: elements.map(e => this._model.get(e)), indexes }));
|
||||
return Event.map(this.list.onDidPin, ({ elements, indexes }) => ({ elements: elements.map(e => this._model.get(e)), indexes }));
|
||||
}
|
||||
|
||||
get onContextMenu(): Event<IListContextMenuEvent<T>> {
|
||||
|
||||
@@ -190,7 +190,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
|
||||
|
||||
private readonly disposables: DisposableStore = new DisposableStore();
|
||||
|
||||
private _onDidChangeContentHeight = new Emitter<number>();
|
||||
private readonly _onDidChangeContentHeight = new Emitter<number>();
|
||||
readonly onDidChangeContentHeight: Event<number> = Event.latch(this._onDidChangeContentHeight.event);
|
||||
get contentHeight(): number { return this.rangeMap.size; }
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { Event, Emitter, EventBufferer } from 'vs/base/common/event';
|
||||
import { domEvent } from 'vs/base/browser/event';
|
||||
import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent, IListMouseEvent, IListTouchEvent, IListGestureEvent, IIdentityProvider, IKeyboardNavigationLabelProvider, IListDragAndDrop, IListDragOverReaction, ListAriaRootRole, ListError } from './list';
|
||||
import { IListVirtualDelegate, IListRenderer, IListEvent, IListContextMenuEvent, IListMouseEvent, IListTouchEvent, IListGestureEvent, IIdentityProvider, IKeyboardNavigationLabelProvider, IListDragAndDrop, IListDragOverReaction, ListAriaRootRole, ListError, IKeyboardNavigationDelegate } from './list';
|
||||
import { ListView, IListViewOptions, IListViewDragAndDrop, IAriaProvider } from './listView';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
@@ -110,7 +110,7 @@ class Trait<T> implements ISpliceable<boolean>, IDisposable {
|
||||
private indexes: number[] = [];
|
||||
private sortedIndexes: number[] = [];
|
||||
|
||||
private _onChange = new Emitter<ITraitChangeEvent>();
|
||||
private readonly _onChange = new Emitter<ITraitChangeEvent>();
|
||||
readonly onChange: Event<ITraitChangeEvent> = this._onChange.event;
|
||||
|
||||
get trait(): string { return this._trait; }
|
||||
@@ -176,7 +176,7 @@ class Trait<T> implements ISpliceable<boolean>, IDisposable {
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this._onChange = dispose(this._onChange);
|
||||
dispose(this._onChange);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,16 +322,18 @@ enum TypeLabelControllerState {
|
||||
Typing
|
||||
}
|
||||
|
||||
export function mightProducePrintableCharacter(event: IKeyboardEvent): boolean {
|
||||
if (event.ctrlKey || event.metaKey || event.altKey) {
|
||||
return false;
|
||||
}
|
||||
export const DefaultKeyboardNavigationDelegate = new class implements IKeyboardNavigationDelegate {
|
||||
mightProducePrintableCharacter(event: IKeyboardEvent): boolean {
|
||||
if (event.ctrlKey || event.metaKey || event.altKey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (event.keyCode >= KeyCode.KEY_A && event.keyCode <= KeyCode.KEY_Z)
|
||||
|| (event.keyCode >= KeyCode.KEY_0 && event.keyCode <= KeyCode.KEY_9)
|
||||
|| (event.keyCode >= KeyCode.NUMPAD_0 && event.keyCode <= KeyCode.NUMPAD_9)
|
||||
|| (event.keyCode >= KeyCode.US_SEMICOLON && event.keyCode <= KeyCode.US_QUOTE);
|
||||
}
|
||||
return (event.keyCode >= KeyCode.KEY_A && event.keyCode <= KeyCode.KEY_Z)
|
||||
|| (event.keyCode >= KeyCode.KEY_0 && event.keyCode <= KeyCode.KEY_9)
|
||||
|| (event.keyCode >= KeyCode.NUMPAD_0 && event.keyCode <= KeyCode.NUMPAD_9)
|
||||
|| (event.keyCode >= KeyCode.US_SEMICOLON && event.keyCode <= KeyCode.US_QUOTE);
|
||||
}
|
||||
};
|
||||
|
||||
class TypeLabelController<T> implements IDisposable {
|
||||
|
||||
@@ -347,7 +349,8 @@ class TypeLabelController<T> implements IDisposable {
|
||||
constructor(
|
||||
private list: List<T>,
|
||||
private view: ListView<T>,
|
||||
private keyboardNavigationLabelProvider: IKeyboardNavigationLabelProvider<T>
|
||||
private keyboardNavigationLabelProvider: IKeyboardNavigationLabelProvider<T>,
|
||||
private delegate: IKeyboardNavigationDelegate
|
||||
) {
|
||||
this.updateOptions(list.options);
|
||||
}
|
||||
@@ -379,7 +382,7 @@ class TypeLabelController<T> implements IDisposable {
|
||||
.filter(e => !isInputElement(e.target as HTMLElement))
|
||||
.filter(() => this.automaticKeyboardNavigation || this.triggered)
|
||||
.map(event => new StandardKeyboardEvent(event))
|
||||
.filter(this.keyboardNavigationLabelProvider.mightProducePrintableCharacter ? e => this.keyboardNavigationLabelProvider.mightProducePrintableCharacter!(e) : e => mightProducePrintableCharacter(e))
|
||||
.filter(e => this.delegate.mightProducePrintableCharacter(e))
|
||||
.forEach(e => { e.stopPropagation(); e.preventDefault(); })
|
||||
.map(event => event.browserEvent.key)
|
||||
.event;
|
||||
@@ -818,6 +821,7 @@ export interface IListOptions<T> extends IListStyles {
|
||||
readonly enableKeyboardNavigation?: boolean;
|
||||
readonly automaticKeyboardNavigation?: boolean;
|
||||
readonly keyboardNavigationLabelProvider?: IKeyboardNavigationLabelProvider<T>;
|
||||
readonly keyboardNavigationDelegate?: IKeyboardNavigationDelegate;
|
||||
readonly ariaRole?: ListAriaRootRole;
|
||||
readonly ariaLabel?: string;
|
||||
readonly keyboardSupport?: boolean;
|
||||
@@ -1107,13 +1111,11 @@ export class List<T> implements ISpliceable<T>, IDisposable {
|
||||
return Event.map(this.eventBufferer.wrapEvent(this.selection.onChange), e => this.toListEvent(e));
|
||||
}
|
||||
|
||||
private _onDidOpen = new Emitter<IListEvent<T>>();
|
||||
private readonly _onDidOpen = new Emitter<IListEvent<T>>();
|
||||
readonly onDidOpen: Event<IListEvent<T>> = this._onDidOpen.event;
|
||||
|
||||
private _onPin = new Emitter<number[]>();
|
||||
@memoize get onPin(): Event<IListEvent<T>> {
|
||||
return Event.map(this._onPin.event, indexes => this.toListEvent({ indexes }));
|
||||
}
|
||||
private readonly _onDidPin = new Emitter<IListEvent<T>>();
|
||||
readonly onDidPin: Event<IListEvent<T>> = this._onDidPin.event;
|
||||
|
||||
get domId(): string { return this.view.domId; }
|
||||
get onDidScroll(): Event<ScrollEvent> { return this.view.onDidScroll; }
|
||||
@@ -1166,7 +1168,7 @@ export class List<T> implements ISpliceable<T>, IDisposable {
|
||||
readonly onDidFocus: Event<void>;
|
||||
readonly onDidBlur: Event<void>;
|
||||
|
||||
private _onDidDispose = new Emitter<void>();
|
||||
private readonly _onDidDispose = new Emitter<void>();
|
||||
readonly onDidDispose: Event<void> = this._onDidDispose.event;
|
||||
|
||||
constructor(
|
||||
@@ -1228,7 +1230,8 @@ export class List<T> implements ISpliceable<T>, IDisposable {
|
||||
}
|
||||
|
||||
if (_options.keyboardNavigationLabelProvider) {
|
||||
this.typeLabelController = new TypeLabelController(this, this.view, _options.keyboardNavigationLabelProvider);
|
||||
const delegate = _options.keyboardNavigationDelegate || DefaultKeyboardNavigationDelegate;
|
||||
this.typeLabelController = new TypeLabelController(this, this.view, _options.keyboardNavigationLabelProvider, delegate);
|
||||
this.disposables.add(this.typeLabelController);
|
||||
}
|
||||
|
||||
@@ -1582,14 +1585,14 @@ export class List<T> implements ISpliceable<T>, IDisposable {
|
||||
this._onDidOpen.fire({ indexes, elements: indexes.map(i => this.view.element(i)), browserEvent });
|
||||
}
|
||||
|
||||
pin(indexes: number[]): void {
|
||||
pin(indexes: number[], browserEvent?: UIEvent): void {
|
||||
for (const index of indexes) {
|
||||
if (index < 0 || index >= this.length) {
|
||||
throw new ListError(this.user, `Invalid index ${index}`);
|
||||
}
|
||||
}
|
||||
|
||||
this._onPin.fire(indexes);
|
||||
this._onDidPin.fire({ indexes, elements: indexes.map(i => this.view.element(i)), browserEvent });
|
||||
}
|
||||
|
||||
style(styles: IListStyles): void {
|
||||
@@ -1626,7 +1629,7 @@ export class List<T> implements ISpliceable<T>, IDisposable {
|
||||
this.disposables.dispose();
|
||||
|
||||
this._onDidOpen.dispose();
|
||||
this._onPin.dispose();
|
||||
this._onDidPin.dispose();
|
||||
this._onDidDispose.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,6 @@ class SelectListRenderer implements IListRenderer<ISelectOptionItem, ISelectList
|
||||
|
||||
get templateId(): string { return SELECT_OPTION_ENTRY_TEMPLATE_ID; }
|
||||
|
||||
constructor() { }
|
||||
|
||||
renderTemplate(container: HTMLElement): ISelectListTemplateData {
|
||||
const data: ISelectListTemplateData = Object.create(null);
|
||||
data.disposables = [];
|
||||
|
||||
@@ -76,6 +76,9 @@
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
margin-right: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* Bold font style does not go well with CJK fonts */
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4 8C4 8.19778 3.94135 8.39112 3.83147 8.55557C3.72159 8.72002 3.56541 8.84819 3.38268 8.92388C3.19996 8.99957 2.99889 9.01937 2.80491 8.98079C2.61093 8.9422 2.43275 8.84696 2.29289 8.70711C2.15304 8.56725 2.0578 8.38907 2.01922 8.19509C1.98063 8.00111 2.00043 7.80004 2.07612 7.61732C2.15181 7.43459 2.27998 7.27841 2.44443 7.16853C2.60888 7.05865 2.80222 7 3 7C3.26522 7 3.51957 7.10536 3.70711 7.29289C3.89464 7.48043 4 7.73478 4 8Z" fill="#C5C5C5"/>
|
||||
<path d="M9 8C9 8.19778 8.94135 8.39112 8.83147 8.55557C8.72159 8.72002 8.56541 8.84819 8.38268 8.92388C8.19996 8.99957 7.99889 9.01937 7.80491 8.98079C7.61093 8.9422 7.43275 8.84696 7.29289 8.70711C7.15304 8.56725 7.0578 8.38907 7.01922 8.19509C6.98063 8.00111 7.00043 7.80004 7.07612 7.61732C7.15181 7.43459 7.27998 7.27841 7.44443 7.16853C7.60888 7.05865 7.80222 7 8 7C8.26522 7 8.51957 7.10536 8.70711 7.29289C8.89464 7.48043 9 7.73478 9 8Z" fill="#C5C5C5"/>
|
||||
<path d="M14 8C14 8.19778 13.9414 8.39112 13.8315 8.55557C13.7216 8.72002 13.5654 8.84819 13.3827 8.92388C13.2 8.99957 12.9989 9.01937 12.8049 8.98079C12.6109 8.9422 12.4327 8.84696 12.2929 8.70711C12.153 8.56725 12.0578 8.38907 12.0192 8.19509C11.9806 8.00111 12.0004 7.80004 12.0761 7.61732C12.1518 7.43459 12.28 7.27841 12.4444 7.16853C12.6089 7.05865 12.8022 7 13 7C13.2652 7 13.5196 7.10536 13.7071 7.29289C13.8946 7.48043 14 7.73478 14 8Z" fill="#C5C5C5"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,5 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4 8C4 8.19778 3.94135 8.39112 3.83147 8.55557C3.72159 8.72002 3.56541 8.84819 3.38268 8.92388C3.19996 8.99957 2.99889 9.01937 2.80491 8.98079C2.61093 8.9422 2.43275 8.84696 2.29289 8.70711C2.15304 8.56725 2.0578 8.38907 2.01922 8.19509C1.98063 8.00111 2.00043 7.80004 2.07612 7.61732C2.15181 7.43459 2.27998 7.27841 2.44443 7.16853C2.60888 7.05865 2.80222 7 3 7C3.26522 7 3.51957 7.10536 3.70711 7.29289C3.89464 7.48043 4 7.73478 4 8Z" fill="white"/>
|
||||
<path d="M9 8C9 8.19778 8.94135 8.39112 8.83147 8.55557C8.72159 8.72002 8.56541 8.84819 8.38268 8.92388C8.19996 8.99957 7.99889 9.01937 7.80491 8.98079C7.61093 8.9422 7.43275 8.84696 7.29289 8.70711C7.15304 8.56725 7.0578 8.38907 7.01922 8.19509C6.98063 8.00111 7.00043 7.80004 7.07612 7.61732C7.15181 7.43459 7.27998 7.27841 7.44443 7.16853C7.60888 7.05865 7.80222 7 8 7C8.26522 7 8.51957 7.10536 8.70711 7.29289C8.89464 7.48043 9 7.73478 9 8Z" fill="white"/>
|
||||
<path d="M14 8C14 8.19778 13.9414 8.39112 13.8315 8.55557C13.7216 8.72002 13.5654 8.84819 13.3827 8.92388C13.2 8.99957 12.9989 9.01937 12.8049 8.98079C12.6109 8.9422 12.4327 8.84696 12.2929 8.70711C12.153 8.56725 12.0578 8.38907 12.0192 8.19509C11.9806 8.00111 12.0004 7.80004 12.0761 7.61732C12.1518 7.43459 12.28 7.27841 12.4444 7.16853C12.6089 7.05865 12.8022 7 13 7C13.2652 7 13.5196 7.10536 13.7071 7.29289C13.8946 7.48043 14 7.73478 14 8Z" fill="white"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,5 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4 8C4 8.19778 3.94135 8.39112 3.83147 8.55557C3.72159 8.72002 3.56541 8.84819 3.38268 8.92388C3.19996 8.99957 2.99889 9.01937 2.80491 8.98079C2.61093 8.9422 2.43275 8.84696 2.29289 8.70711C2.15304 8.56725 2.0578 8.38907 2.01922 8.19509C1.98063 8.00111 2.00043 7.80004 2.07612 7.61732C2.15181 7.43459 2.27998 7.27841 2.44443 7.16853C2.60888 7.05865 2.80222 7 3 7C3.26522 7 3.51957 7.10536 3.70711 7.29289C3.89464 7.48043 4 7.73478 4 8Z" fill="#424242"/>
|
||||
<path d="M9 8C9 8.19778 8.94135 8.39112 8.83147 8.55557C8.72159 8.72002 8.56541 8.84819 8.38268 8.92388C8.19996 8.99957 7.99889 9.01937 7.80491 8.98079C7.61093 8.9422 7.43275 8.84696 7.29289 8.70711C7.15304 8.56725 7.0578 8.38907 7.01922 8.19509C6.98063 8.00111 7.00043 7.80004 7.07612 7.61732C7.15181 7.43459 7.27998 7.27841 7.44443 7.16853C7.60888 7.05865 7.80222 7 8 7C8.26522 7 8.51957 7.10536 8.70711 7.29289C8.89464 7.48043 9 7.73478 9 8Z" fill="#424242"/>
|
||||
<path d="M14 8C14 8.19778 13.9414 8.39112 13.8315 8.55557C13.7216 8.72002 13.5654 8.84819 13.3827 8.92388C13.2 8.99957 12.9989 9.01937 12.8049 8.98079C12.6109 8.9422 12.4327 8.84696 12.2929 8.70711C12.153 8.56725 12.0578 8.38907 12.0192 8.19509C11.9806 8.00111 12.0004 7.80004 12.0761 7.61732C12.1518 7.43459 12.28 7.27841 12.4444 7.16853C12.6089 7.05865 12.8022 7 13 7C13.2652 7 13.5196 7.10536 13.7071 7.29289C13.8946 7.48043 14 7.73478 14 8Z" fill="#424242"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -7,15 +7,3 @@
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.vs .monaco-toolbar .action-label.toolbar-toggle-more {
|
||||
background-image: url('ellipsis-light.svg');
|
||||
}
|
||||
|
||||
.vs-dark .monaco-toolbar .action-label.toolbar-toggle-more {
|
||||
background-image: url('ellipsis-dark.svg');
|
||||
}
|
||||
|
||||
.hc-black .monaco-toolbar .action-label.toolbar-toggle-more {
|
||||
background-image: url('ellipsis-hc.svg');
|
||||
}
|
||||
@@ -65,7 +65,7 @@ export class ToolBar extends Disposable {
|
||||
this.options.actionViewItemProvider,
|
||||
this.actionRunner,
|
||||
this.options.getKeyBinding,
|
||||
'toolbar-toggle-more',
|
||||
'codicon-more',
|
||||
this.options.anchorAlignmentProvider
|
||||
);
|
||||
this.toggleMenuActionViewItem.value.setActionContext(this.actionBar.context);
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
|
||||
import 'vs/css!./media/tree';
|
||||
import { IDisposable, dispose, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IListOptions, List, IListStyles, mightProducePrintableCharacter, MouseController } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IKeyboardNavigationLabelProvider, IIdentityProvider } from 'vs/base/browser/ui/list/list';
|
||||
import { IListOptions, List, IListStyles, MouseController, DefaultKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/listWidget';
|
||||
import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IKeyboardNavigationLabelProvider, IIdentityProvider, IKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { append, $, toggleClass, getDomNodePagePosition, removeClass, addClass, hasClass, hasParentWithClass, createStyleSheet, clearNode } from 'vs/base/browser/dom';
|
||||
import { Event, Relay, Emitter, EventBufferer } from 'vs/base/common/event';
|
||||
import { StandardKeyboardEvent, IKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ITreeModel, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeFilter, ITreeNavigator, ICollapseStateChangeEvent, ITreeDragAndDrop, TreeDragOverBubble, TreeVisibility, TreeFilterResult, ITreeModelSpliceEvent, TreeMouseEventTarget } 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, distinctES6 } from 'vs/base/common/arrays';
|
||||
import { range, equals, distinctES6, fromSet } 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';
|
||||
@@ -567,7 +567,7 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
private _empty: boolean = false;
|
||||
get empty(): boolean { return this._empty; }
|
||||
|
||||
private _onDidChangeEmptyState = new Emitter<boolean>();
|
||||
private readonly _onDidChangeEmptyState = new Emitter<boolean>();
|
||||
readonly onDidChangeEmptyState: Event<boolean> = Event.latch(this._onDidChangeEmptyState.event);
|
||||
|
||||
private positionClassName = 'ne';
|
||||
@@ -581,7 +581,7 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
private automaticKeyboardNavigation = true;
|
||||
private triggered = false;
|
||||
|
||||
private _onDidChangePattern = new Emitter<string>();
|
||||
private readonly _onDidChangePattern = new Emitter<string>();
|
||||
readonly onDidChangePattern = this._onDidChangePattern.event;
|
||||
|
||||
private enabledDisposables: IDisposable[] = [];
|
||||
@@ -592,7 +592,7 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
model: ITreeModel<T, TFilterData, any>,
|
||||
private view: List<ITreeNode<T, TFilterData>>,
|
||||
private filter: TypeFilter<T>,
|
||||
private keyboardNavigationLabelProvider: IKeyboardNavigationLabelProvider<T>
|
||||
private keyboardNavigationDelegate: IKeyboardNavigationDelegate
|
||||
) {
|
||||
this.domNode = $(`.monaco-list-type-filter.${this.positionClassName}`);
|
||||
this.domNode.draggable = true;
|
||||
@@ -658,13 +658,12 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
|
||||
return;
|
||||
}
|
||||
|
||||
const isPrintableCharEvent = this.keyboardNavigationLabelProvider.mightProducePrintableCharacter ? (e: IKeyboardEvent) => this.keyboardNavigationLabelProvider.mightProducePrintableCharacter!(e) : (e: IKeyboardEvent) => mightProducePrintableCharacter(e);
|
||||
const onKeyDown = Event.chain(domEvent(this.view.getHTMLElement(), 'keydown'))
|
||||
.filter(e => !isInputElement(e.target as HTMLElement) || e.target === this.filterOnTypeDomNode)
|
||||
.map(e => new StandardKeyboardEvent(e))
|
||||
.filter(this.keyboardNavigationEventFilter || (() => true))
|
||||
.filter(() => this.automaticKeyboardNavigation || this.triggered)
|
||||
.filter(e => isPrintableCharEvent(e) || ((this.pattern.length > 0 || this.triggered) && ((e.keyCode === KeyCode.Escape || e.keyCode === KeyCode.Backspace) && !e.altKey && !e.ctrlKey && !e.metaKey) || (e.keyCode === KeyCode.Backspace && (isMacintosh ? (e.altKey && !e.metaKey) : e.ctrlKey) && !e.shiftKey)))
|
||||
.filter(e => this.keyboardNavigationDelegate.mightProducePrintableCharacter(e) || ((this.pattern.length > 0 || this.triggered) && ((e.keyCode === KeyCode.Escape || e.keyCode === KeyCode.Backspace) && !e.altKey && !e.ctrlKey && !e.metaKey) || (e.keyCode === KeyCode.Backspace && (isMacintosh ? (e.altKey && !e.metaKey) : e.ctrlKey) && !e.shiftKey)))
|
||||
.forEach(e => { e.stopPropagation(); e.preventDefault(); })
|
||||
.event;
|
||||
|
||||
@@ -935,7 +934,7 @@ class Trait<T> {
|
||||
private nodes: ITreeNode<T, any>[] = [];
|
||||
private elements: T[] | undefined;
|
||||
|
||||
private _onDidChange = new Emitter<ITreeEvent<T>>();
|
||||
private readonly _onDidChange = new Emitter<ITreeEvent<T>>();
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
private _nodeSet: Set<ITreeNode<T, any>> | undefined;
|
||||
@@ -1189,6 +1188,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
||||
get onDidChangeFocus(): Event<ITreeEvent<T>> { return this.eventBufferer.wrapEvent(this.focus.onDidChange); }
|
||||
get onDidChangeSelection(): Event<ITreeEvent<T>> { return this.eventBufferer.wrapEvent(this.selection.onDidChange); }
|
||||
get onDidOpen(): Event<ITreeEvent<T>> { return Event.map(this.view.onDidOpen, asTreeEvent); }
|
||||
get onDidPin(): Event<ITreeEvent<T>> { return Event.map(this.view.onDidPin, asTreeEvent); }
|
||||
|
||||
get onMouseClick(): Event<ITreeMouseEvent<T>> { return Event.map(this.view.onMouseClick, asTreeMouseEvent); }
|
||||
get onMouseDblClick(): Event<ITreeMouseEvent<T>> { return Event.map(this.view.onMouseDblClick, asTreeMouseEvent); }
|
||||
@@ -1204,7 +1204,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
||||
get onDidChangeCollapseState(): Event<ICollapseStateChangeEvent<T, TFilterData>> { return this.model.onDidChangeCollapseState; }
|
||||
get onDidChangeRenderNodeCount(): Event<ITreeNode<T, TFilterData>> { return this.model.onDidChangeRenderNodeCount; }
|
||||
|
||||
private _onWillRefilter = new Emitter<void>();
|
||||
private readonly _onWillRefilter = new Emitter<void>();
|
||||
readonly onWillRefilter: Event<void> = this._onWillRefilter.event;
|
||||
|
||||
get filterOnType(): boolean { return !!this._options.filterOnType; }
|
||||
@@ -1213,7 +1213,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
||||
get openOnSingleClick(): boolean { return typeof this._options.openOnSingleClick === 'undefined' ? true : this._options.openOnSingleClick; }
|
||||
get expandOnlyOnTwistieClick(): boolean | ((e: T) => boolean) { return typeof this._options.expandOnlyOnTwistieClick === 'undefined' ? false : this._options.expandOnlyOnTwistieClick; }
|
||||
|
||||
private _onDidUpdateOptions = new Emitter<IAbstractTreeOptions<T, TFilterData>>();
|
||||
private readonly _onDidUpdateOptions = new Emitter<IAbstractTreeOptions<T, TFilterData>>();
|
||||
readonly onDidUpdateOptions: Event<IAbstractTreeOptions<T, TFilterData>> = this._onDidUpdateOptions.event;
|
||||
|
||||
get onDidDispose(): Event<void> { return this.view.onDidDispose; }
|
||||
@@ -1228,7 +1228,7 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
||||
const treeDelegate = new ComposedTreeDelegate<T, ITreeNode<T, TFilterData>>(delegate);
|
||||
|
||||
const onDidChangeCollapseStateRelay = new Relay<ICollapseStateChangeEvent<T, TFilterData>>();
|
||||
const onDidChangeActiveNodes = new Relay<ITreeNode<T, TFilterData>[]>();
|
||||
const onDidChangeActiveNodes = new Emitter<ITreeNode<T, TFilterData>[]>();
|
||||
const activeNodes = new EventCollection(onDidChangeActiveNodes.event);
|
||||
this.disposables.push(activeNodes);
|
||||
|
||||
@@ -1251,11 +1251,23 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
||||
onDidChangeCollapseStateRelay.input = this.model.onDidChangeCollapseState;
|
||||
|
||||
this.model.onDidSplice(e => {
|
||||
this.focus.onDidModelSplice(e);
|
||||
this.selection.onDidModelSplice(e);
|
||||
}, null, this.disposables);
|
||||
this.eventBufferer.bufferEvents(() => {
|
||||
this.focus.onDidModelSplice(e);
|
||||
this.selection.onDidModelSplice(e);
|
||||
});
|
||||
|
||||
onDidChangeActiveNodes.input = Event.map(Event.any<any>(this.focus.onDidChange, this.selection.onDidChange, this.model.onDidSplice), () => [...this.focus.getNodes(), ...this.selection.getNodes()]);
|
||||
const set = new Set<ITreeNode<T, TFilterData>>();
|
||||
|
||||
for (const node of this.focus.getNodes()) {
|
||||
set.add(node);
|
||||
}
|
||||
|
||||
for (const node of this.selection.getNodes()) {
|
||||
set.add(node);
|
||||
}
|
||||
|
||||
onDidChangeActiveNodes.fire(fromSet(set));
|
||||
}, null, this.disposables);
|
||||
|
||||
if (_options.keyboardSupport !== false) {
|
||||
const onKeyDown = Event.chain(this.view.onKeyDown)
|
||||
@@ -1268,7 +1280,8 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
|
||||
}
|
||||
|
||||
if (_options.keyboardNavigationLabelProvider) {
|
||||
this.typeFilterController = new TypeFilterController(this, this.model, this.view, filter!, _options.keyboardNavigationLabelProvider);
|
||||
const delegate = _options.keyboardNavigationDelegate || DefaultKeyboardNavigationDelegate;
|
||||
this.typeFilterController = new TypeFilterController(this, this.model, this.view, filter!, delegate);
|
||||
this.focusNavigationFilter = node => this.typeFilterController!.shouldAllowFocus(node);
|
||||
this.disposables.push(this.typeFilterController!);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ComposedTreeDelegate, IAbstractTreeOptions, IAbstractTreeOptionsUpdate } from 'vs/base/browser/ui/tree/abstractTree';
|
||||
import { ObjectTree, IObjectTreeOptions, CompressibleObjectTree, ICompressibleTreeRenderer } from 'vs/base/browser/ui/tree/objectTree';
|
||||
import { ObjectTree, IObjectTreeOptions, CompressibleObjectTree, ICompressibleTreeRenderer, ICompressibleKeyboardNavigationLabelProvider, ICompressibleObjectTreeOptions } from 'vs/base/browser/ui/tree/objectTree';
|
||||
import { IListVirtualDelegate, IIdentityProvider, IListDragAndDrop, IListDragOverReaction } from 'vs/base/browser/ui/list/list';
|
||||
import { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter, ICollapseStateChangeEvent, IAsyncDataSource, ITreeDragAndDrop, TreeError, WeakMapper } from 'vs/base/browser/ui/tree/tree';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
@@ -1010,6 +1010,24 @@ export interface ITreeCompressionDelegate<T> {
|
||||
isIncompressible(element: T): boolean;
|
||||
}
|
||||
|
||||
function asCompressibleObjectTreeOptions<TInput, T, TFilterData>(options?: ICompressibleAsyncDataTreeOptions<T, TFilterData>): ICompressibleObjectTreeOptions<IAsyncDataTreeNode<TInput, T>, TFilterData> | undefined {
|
||||
const objectTreeOptions = options && asObjectTreeOptions(options);
|
||||
|
||||
return objectTreeOptions && {
|
||||
...objectTreeOptions,
|
||||
keyboardNavigationLabelProvider: objectTreeOptions.keyboardNavigationLabelProvider && {
|
||||
...objectTreeOptions.keyboardNavigationLabelProvider,
|
||||
getCompressedNodeKeyboardNavigationLabel(els) {
|
||||
return options!.keyboardNavigationLabelProvider!.getCompressedNodeKeyboardNavigationLabel(els.map(e => e.element as T));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export interface ICompressibleAsyncDataTreeOptions<T, TFilterData = void> extends IAsyncDataTreeOptions<T, TFilterData> {
|
||||
readonly keyboardNavigationLabelProvider?: ICompressibleKeyboardNavigationLabelProvider<T>;
|
||||
}
|
||||
|
||||
export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends AsyncDataTree<TInput, T, TFilterData> {
|
||||
|
||||
protected readonly compressibleNodeMapper: CompressibleAsyncDataTreeNodeMapper<TInput, T, TFilterData> = new WeakMapper(node => new CompressibleAsyncDataTreeNodeWrapper(node));
|
||||
@@ -1031,11 +1049,11 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
|
||||
container: HTMLElement,
|
||||
delegate: IListVirtualDelegate<T>,
|
||||
renderers: ICompressibleTreeRenderer<T, TFilterData, any>[],
|
||||
options: IAsyncDataTreeOptions<T, TFilterData>
|
||||
options: ICompressibleAsyncDataTreeOptions<T, TFilterData>
|
||||
): ObjectTree<IAsyncDataTreeNode<TInput, T>, TFilterData> {
|
||||
const objectTreeDelegate = new ComposedTreeDelegate<TInput | T, IAsyncDataTreeNode<TInput, T>>(delegate);
|
||||
const objectTreeRenderers = renderers.map(r => new CompressibleAsyncDataTreeRenderer(r, this.nodeMapper, () => this.compressibleNodeMapper, this._onDidChangeNodeSlowState.event));
|
||||
const objectTreeOptions = asObjectTreeOptions<TInput, T, TFilterData>(options) || {};
|
||||
const objectTreeOptions = asCompressibleObjectTreeOptions<TInput, T, TFilterData>(options) || {};
|
||||
|
||||
return new CompressibleObjectTree(user, container, objectTreeDelegate, objectTreeRenderers, objectTreeOptions);
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ function mapOptions<T, TFilterData>(compressedNodeUnwrapper: CompressedNodeUnwra
|
||||
...options,
|
||||
sorter: options.sorter && {
|
||||
compare(node: ICompressedTreeNode<T>, otherNode: ICompressedTreeNode<T>): number {
|
||||
return options.sorter!.compare(compressedNodeUnwrapper(node), compressedNodeUnwrapper(otherNode));
|
||||
return options.sorter!.compare(node.elements[0], otherNode.elements[0]);
|
||||
}
|
||||
},
|
||||
identityProvider: options.identityProvider && {
|
||||
|
||||
@@ -162,9 +162,10 @@ export class DataTree<TInput, T, TFilterData = void> extends AbstractTree<T | nu
|
||||
const children = this.dataSource.getChildren(element);
|
||||
const elements = Iterator.map<any, ITreeElement<T>>(Iterator.fromArray(children), element => {
|
||||
const { elements: children, size } = this.iterate(element, isCollapsed);
|
||||
const collapsible = this.dataSource.hasChildren ? this.dataSource.hasChildren(element) : undefined;
|
||||
const collapsed = size === 0 ? undefined : (isCollapsed && isCollapsed(element));
|
||||
|
||||
return { element, children, collapsed };
|
||||
return { element, children, collapsible, collapsed };
|
||||
});
|
||||
|
||||
return { elements, size: children.length };
|
||||
|
||||
@@ -62,17 +62,17 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
|
||||
private root: IIndexTreeNode<T, TFilterData>;
|
||||
private eventBufferer = new EventBufferer();
|
||||
|
||||
private _onDidChangeCollapseState = new Emitter<ICollapseStateChangeEvent<T, TFilterData>>();
|
||||
private readonly _onDidChangeCollapseState = new Emitter<ICollapseStateChangeEvent<T, TFilterData>>();
|
||||
readonly onDidChangeCollapseState: Event<ICollapseStateChangeEvent<T, TFilterData>> = this.eventBufferer.wrapEvent(this._onDidChangeCollapseState.event);
|
||||
|
||||
private _onDidChangeRenderNodeCount = new Emitter<ITreeNode<T, TFilterData>>();
|
||||
private readonly _onDidChangeRenderNodeCount = new Emitter<ITreeNode<T, TFilterData>>();
|
||||
readonly onDidChangeRenderNodeCount: Event<ITreeNode<T, TFilterData>> = this.eventBufferer.wrapEvent(this._onDidChangeRenderNodeCount.event);
|
||||
|
||||
private collapseByDefault: boolean;
|
||||
private filter?: ITreeFilter<T, TFilterData>;
|
||||
private autoExpandSingleChildren: boolean;
|
||||
|
||||
private _onDidSplice = new Emitter<ITreeModelSpliceEvent<T, TFilterData>>();
|
||||
private readonly _onDidSplice = new Emitter<ITreeModelSpliceEvent<T, TFilterData>>();
|
||||
readonly onDidSplice = this._onDidSplice.event;
|
||||
|
||||
constructor(
|
||||
@@ -169,7 +169,7 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
|
||||
parentNode.visibleChildrenCount += insertedVisibleChildrenCount - deletedVisibleChildrenCount;
|
||||
|
||||
if (revealed && visible) {
|
||||
const visibleDeleteCount = deletedNodes.reduce((r, node) => r + node.renderNodeCount, 0);
|
||||
const visibleDeleteCount = deletedNodes.reduce((r, node) => r + (node.visible ? node.renderNodeCount : 0), 0);
|
||||
|
||||
this._updateAncestorsRenderNodeCount(parentNode, renderNodeCount - visibleDeleteCount);
|
||||
this.list.splice(listIndex, visibleDeleteCount, treeListElementsToInsert);
|
||||
|
||||
@@ -8,9 +8,10 @@ import { AbstractTree, IAbstractTreeOptions } from 'vs/base/browser/ui/tree/abst
|
||||
import { ISpliceable } from 'vs/base/common/sequence';
|
||||
import { ITreeNode, ITreeModel, ITreeElement, ITreeRenderer, ITreeSorter, ICollapseStateChangeEvent } from 'vs/base/browser/ui/tree/tree';
|
||||
import { ObjectTreeModel, IObjectTreeModel } from 'vs/base/browser/ui/tree/objectTreeModel';
|
||||
import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { IListVirtualDelegate, IKeyboardNavigationLabelProvider } from 'vs/base/browser/ui/list/list';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { CompressibleObjectTreeModel, ElementMapper, ICompressedTreeNode, ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
|
||||
export interface IObjectTreeOptions<T, TFilterData = void> extends IAbstractTreeOptions<T, TFilterData> {
|
||||
sorter?: ITreeSorter<T>;
|
||||
@@ -77,9 +78,12 @@ class CompressibleRenderer<T, TFilterData, TTemplateData> implements ITreeRender
|
||||
readonly templateId: string;
|
||||
readonly onDidChangeTwistieState: Event<T> | undefined;
|
||||
|
||||
compressedTreeNodeProvider: ICompressedTreeNodeProvider<T, TFilterData>;
|
||||
@memoize
|
||||
private get compressedTreeNodeProvider(): ICompressedTreeNodeProvider<T, TFilterData> {
|
||||
return this._compressedTreeNodeProvider();
|
||||
}
|
||||
|
||||
constructor(private renderer: ICompressibleTreeRenderer<T, TFilterData, TTemplateData>) {
|
||||
constructor(private _compressedTreeNodeProvider: () => ICompressedTreeNodeProvider<T, TFilterData>, private renderer: ICompressibleTreeRenderer<T, TFilterData, TTemplateData>) {
|
||||
this.templateId = renderer.templateId;
|
||||
|
||||
if (renderer.onDidChangeTwistieState) {
|
||||
@@ -127,7 +131,38 @@ class CompressibleRenderer<T, TFilterData, TTemplateData> implements ITreeRender
|
||||
}
|
||||
}
|
||||
|
||||
export class CompressibleObjectTree<T extends NonNullable<any>, TFilterData = void> extends ObjectTree<T, TFilterData> {
|
||||
export interface ICompressibleKeyboardNavigationLabelProvider<T> extends IKeyboardNavigationLabelProvider<T> {
|
||||
getCompressedNodeKeyboardNavigationLabel(elements: T[]): { toString(): string | undefined; } | undefined;
|
||||
}
|
||||
|
||||
export interface ICompressibleObjectTreeOptions<T, TFilterData = void> extends IObjectTreeOptions<T, TFilterData> {
|
||||
readonly keyboardNavigationLabelProvider?: ICompressibleKeyboardNavigationLabelProvider<T>;
|
||||
}
|
||||
|
||||
function asObjectTreeOptions<T, TFilterData>(compressedTreeNodeProvider: () => ICompressedTreeNodeProvider<T, TFilterData>, options?: ICompressibleObjectTreeOptions<T, TFilterData>): IObjectTreeOptions<T, TFilterData> | undefined {
|
||||
return options && {
|
||||
...options,
|
||||
keyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && {
|
||||
getKeyboardNavigationLabel(e: T) {
|
||||
let compressedTreeNode: ITreeNode<ICompressedTreeNode<T>, TFilterData>;
|
||||
|
||||
try {
|
||||
compressedTreeNode = compressedTreeNodeProvider().getCompressedTreeNode(e);
|
||||
} catch {
|
||||
return options.keyboardNavigationLabelProvider!.getKeyboardNavigationLabel(e);
|
||||
}
|
||||
|
||||
if (compressedTreeNode.element.elements.length === 1) {
|
||||
return options.keyboardNavigationLabelProvider!.getKeyboardNavigationLabel(e);
|
||||
} else {
|
||||
return options.keyboardNavigationLabelProvider!.getCompressedNodeKeyboardNavigationLabel(compressedTreeNode.element.elements);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export class CompressibleObjectTree<T extends NonNullable<any>, TFilterData = void> extends ObjectTree<T, TFilterData> implements ICompressedTreeNodeProvider<T, TFilterData> {
|
||||
|
||||
protected model: CompressibleObjectTreeModel<T, TFilterData>;
|
||||
|
||||
@@ -136,11 +171,11 @@ export class CompressibleObjectTree<T extends NonNullable<any>, TFilterData = vo
|
||||
container: HTMLElement,
|
||||
delegate: IListVirtualDelegate<T>,
|
||||
renderers: ICompressibleTreeRenderer<T, TFilterData, any>[],
|
||||
options: IObjectTreeOptions<T, TFilterData> = {}
|
||||
options: ICompressibleObjectTreeOptions<T, TFilterData> = {}
|
||||
) {
|
||||
const compressibleRenderers = renderers.map(r => new CompressibleRenderer(r));
|
||||
super(user, container, delegate, compressibleRenderers, options);
|
||||
compressibleRenderers.forEach(r => r.compressedTreeNodeProvider = this);
|
||||
const compressedTreeNodeProvider = () => this;
|
||||
const compressibleRenderers = renderers.map(r => new CompressibleRenderer(compressedTreeNodeProvider, r));
|
||||
super(user, container, delegate, compressibleRenderers, asObjectTreeOptions(compressedTreeNodeProvider, options));
|
||||
}
|
||||
|
||||
setChildren(element: T | null, children?: ISequence<ICompressedTreeElement<T>>): void {
|
||||
|
||||
@@ -9,6 +9,7 @@ import { IndexTreeModel, IIndexTreeModelOptions } from 'vs/base/browser/ui/tree/
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { ITreeModel, ITreeNode, ITreeElement, ITreeSorter, ICollapseStateChangeEvent, ITreeModelSpliceEvent, TreeError } from 'vs/base/browser/ui/tree/tree';
|
||||
import { IIdentityProvider } from 'vs/base/browser/ui/list/list';
|
||||
import { mergeSort } from 'vs/base/common/arrays';
|
||||
|
||||
export type ITreeNodeCallback<T, TFilterData> = (node: ITreeNode<T, TFilterData>) => void;
|
||||
|
||||
@@ -123,7 +124,7 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
|
||||
let iterator = elements ? getSequenceIterator(elements) : Iterator.empty<ITreeElement<T>>();
|
||||
|
||||
if (this.sorter) {
|
||||
iterator = Iterator.fromArray(Iterator.collect(iterator).sort(this.sorter.compare.bind(this.sorter)));
|
||||
iterator = Iterator.fromArray(mergeSort(Iterator.collect(iterator), this.sorter.compare.bind(this.sorter)));
|
||||
}
|
||||
|
||||
return Iterator.map(iterator, treeElement => {
|
||||
|
||||
@@ -164,6 +164,7 @@ export interface ITreeNavigator<T> {
|
||||
}
|
||||
|
||||
export interface IDataSource<TInput, T> {
|
||||
hasChildren?(element: TInput | T): boolean;
|
||||
getChildren(element: TInput | T): T[];
|
||||
}
|
||||
|
||||
|
||||
@@ -22,4 +22,4 @@ export class CollapseAllAction<TInput, T, TFilterData = void> extends Action {
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ export function getPathFromAmdModule(requirefn: typeof require, relativePath: st
|
||||
|
||||
/**
|
||||
* Reference a resource that might be inlined.
|
||||
* Do not inline icons that will be used by the native mac touchbar.
|
||||
* Do not rename this method unless you adopt the build scripts.
|
||||
*/
|
||||
export function registerAndGetAmdImageURL(absolutePath: string): string {
|
||||
|
||||
@@ -372,6 +372,12 @@ export function distinctES6<T>(array: ReadonlyArray<T>): T[] {
|
||||
});
|
||||
}
|
||||
|
||||
export function fromSet<T>(set: Set<T>): T[] {
|
||||
const result: T[] = [];
|
||||
set.forEach(o => result.push(o));
|
||||
return result;
|
||||
}
|
||||
|
||||
export function uniqueFilter<T>(keyFn: (t: T) => string): (t: T) => boolean {
|
||||
const seen: { [key: string]: boolean; } = Object.create(null);
|
||||
|
||||
@@ -418,6 +424,12 @@ export function first<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean, notF
|
||||
return index < 0 ? notFoundValue : array[index];
|
||||
}
|
||||
|
||||
export function firstOrDefault<T, NotFound = T>(array: ReadonlyArray<T>, notFoundValue: NotFound): T | NotFound;
|
||||
export function firstOrDefault<T>(array: ReadonlyArray<T>): T | undefined;
|
||||
export function firstOrDefault<T, NotFound = T>(array: ReadonlyArray<T>, notFoundValue?: NotFound): T | NotFound | undefined {
|
||||
return array.length > 0 ? array[0] : notFoundValue;
|
||||
}
|
||||
|
||||
export function commonPrefixLength<T>(one: ReadonlyArray<T>, other: ReadonlyArray<T>, equals: (a: T, b: T) => boolean = (a, b) => a === b): number {
|
||||
let result = 0;
|
||||
|
||||
|
||||
@@ -97,6 +97,12 @@ export function fromMap<T>(original: Map<string, T>): IStringDictionary<T> {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function mapValues<V>(map: Map<any, V>): V[] {
|
||||
const result: V[] = [];
|
||||
map.forEach(v => result.push(v));
|
||||
return result;
|
||||
}
|
||||
|
||||
export class SetMap<K, V> {
|
||||
|
||||
private map = new Map<K, Set<V>>();
|
||||
|
||||
@@ -24,40 +24,64 @@ export function createDecorator(mapFn: (fn: Function, key: string) => Function):
|
||||
};
|
||||
}
|
||||
|
||||
export function memoize(target: any, key: string, descriptor: any) {
|
||||
let fnKey: string | null = null;
|
||||
let fn: Function | null = null;
|
||||
let memoizeId = 0;
|
||||
export function createMemoizer() {
|
||||
const memoizeKeyPrefix = `$memoize${memoizeId++}`;
|
||||
let self: any = undefined;
|
||||
|
||||
if (typeof descriptor.value === 'function') {
|
||||
fnKey = 'value';
|
||||
fn = descriptor.value;
|
||||
const result = function memoize(target: any, key: string, descriptor: any) {
|
||||
let fnKey: string | null = null;
|
||||
let fn: Function | null = null;
|
||||
|
||||
if (fn!.length !== 0) {
|
||||
console.warn('Memoize should only be used in functions with zero parameters');
|
||||
}
|
||||
} else if (typeof descriptor.get === 'function') {
|
||||
fnKey = 'get';
|
||||
fn = descriptor.get;
|
||||
}
|
||||
if (typeof descriptor.value === 'function') {
|
||||
fnKey = 'value';
|
||||
fn = descriptor.value;
|
||||
|
||||
if (!fn) {
|
||||
throw new Error('not supported');
|
||||
}
|
||||
|
||||
const memoizeKey = `$memoize$${key}`;
|
||||
|
||||
descriptor[fnKey!] = function (...args: any[]) {
|
||||
if (!this.hasOwnProperty(memoizeKey)) {
|
||||
Object.defineProperty(this, memoizeKey, {
|
||||
configurable: false,
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
value: fn!.apply(this, args)
|
||||
});
|
||||
if (fn!.length !== 0) {
|
||||
console.warn('Memoize should only be used in functions with zero parameters');
|
||||
}
|
||||
} else if (typeof descriptor.get === 'function') {
|
||||
fnKey = 'get';
|
||||
fn = descriptor.get;
|
||||
}
|
||||
|
||||
return this[memoizeKey];
|
||||
if (!fn) {
|
||||
throw new Error('not supported');
|
||||
}
|
||||
|
||||
const memoizeKey = `${memoizeKeyPrefix}:${key}`;
|
||||
descriptor[fnKey!] = function (...args: any[]) {
|
||||
self = this;
|
||||
|
||||
if (!this.hasOwnProperty(memoizeKey)) {
|
||||
Object.defineProperty(this, memoizeKey, {
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
value: fn!.apply(this, args)
|
||||
});
|
||||
}
|
||||
|
||||
return this[memoizeKey];
|
||||
};
|
||||
};
|
||||
|
||||
result.clear = () => {
|
||||
if (typeof self === 'undefined') {
|
||||
return;
|
||||
}
|
||||
Object.getOwnPropertyNames(self).forEach(property => {
|
||||
if (property.indexOf(memoizeKeyPrefix) === 0) {
|
||||
delete self[property];
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function memoize(target: any, key: string, descriptor: any) {
|
||||
return createMemoizer()(target, key, descriptor);
|
||||
}
|
||||
|
||||
export interface IDebouceReducer<T> {
|
||||
@@ -87,4 +111,4 @@ export function debounce<T>(delay: number, reducer?: IDebouceReducer<T>, initial
|
||||
}, delay);
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,7 +451,7 @@ class LeakageMonitor {
|
||||
* Sample:
|
||||
class Document {
|
||||
|
||||
private _onDidChange = new Emitter<(value:string)=>any>();
|
||||
private readonly _onDidChange = new Emitter<(value:string)=>any>();
|
||||
|
||||
public onDidChange = this._onDidChange.event;
|
||||
|
||||
@@ -808,7 +808,7 @@ export class Relay<T> implements IDisposable {
|
||||
private inputEvent: Event<T> = Event.None;
|
||||
private inputEventListener: IDisposable = Disposable.None;
|
||||
|
||||
private emitter = new Emitter<T>({
|
||||
private readonly emitter = new Emitter<T>({
|
||||
onFirstListenerDidAdd: () => {
|
||||
this.listening = true;
|
||||
this.inputEventListener = this.inputEvent(this.emitter.fire, this.emitter);
|
||||
|
||||
@@ -11,7 +11,7 @@ export class HistoryNavigator<T> implements INavigator<T> {
|
||||
private _limit: number;
|
||||
private _navigator!: ArrayNavigator<T>;
|
||||
|
||||
constructor(history: T[] = [], limit: number = 10) {
|
||||
constructor(history: readonly T[] = [], limit: number = 10) {
|
||||
this._initialize(history);
|
||||
this._limit = limit;
|
||||
this._onChange();
|
||||
@@ -62,7 +62,8 @@ export class HistoryNavigator<T> implements INavigator<T> {
|
||||
|
||||
private _onChange() {
|
||||
this._reduceToLimit();
|
||||
this._navigator = new ArrayNavigator(this._elements, 0, this._elements.length, this._elements.length);
|
||||
const elements = this._elements;
|
||||
this._navigator = new ArrayNavigator(elements, 0, elements.length, elements.length);
|
||||
}
|
||||
|
||||
private _reduceToLimit() {
|
||||
@@ -72,7 +73,7 @@ export class HistoryNavigator<T> implements INavigator<T> {
|
||||
}
|
||||
}
|
||||
|
||||
private _initialize(history: T[]): void {
|
||||
private _initialize(history: readonly T[]): void {
|
||||
this._history = new Set();
|
||||
for (const entry of history) {
|
||||
this._history.add(entry);
|
||||
|
||||
@@ -18,6 +18,22 @@ export interface Iterator<T> {
|
||||
next(): IteratorResult<T>;
|
||||
}
|
||||
|
||||
interface NativeIteratorYieldResult<TYield> {
|
||||
done?: false;
|
||||
value: TYield;
|
||||
}
|
||||
|
||||
interface NativeIteratorReturnResult<TReturn> {
|
||||
done: true;
|
||||
value: TReturn;
|
||||
}
|
||||
|
||||
type NativeIteratorResult<T, TReturn = any> = NativeIteratorYieldResult<T> | NativeIteratorReturnResult<TReturn>;
|
||||
|
||||
export interface NativeIterator<T> {
|
||||
next(): NativeIteratorResult<T>;
|
||||
}
|
||||
|
||||
export module Iterator {
|
||||
const _empty: Iterator<any> = {
|
||||
next() {
|
||||
@@ -56,6 +72,20 @@ export module Iterator {
|
||||
};
|
||||
}
|
||||
|
||||
export function fromNativeIterator<T>(it: NativeIterator<T>): Iterator<T> {
|
||||
return {
|
||||
next(): IteratorResult<T> {
|
||||
const result = it.next();
|
||||
|
||||
if (result.done) {
|
||||
return FIN;
|
||||
}
|
||||
|
||||
return { done: false, value: result.value };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function from<T>(elements: Iterator<T> | T[] | undefined): Iterator<T> {
|
||||
if (!elements) {
|
||||
return Iterator.empty();
|
||||
@@ -160,12 +190,12 @@ export interface INextIterator<T> {
|
||||
|
||||
export class ArrayIterator<T> implements INextIterator<T> {
|
||||
|
||||
private items: T[];
|
||||
private readonly items: readonly T[];
|
||||
protected start: number;
|
||||
protected end: number;
|
||||
protected index: number;
|
||||
|
||||
constructor(items: T[], start: number = 0, end: number = items.length, index = start - 1) {
|
||||
constructor(items: readonly T[], start: number = 0, end: number = items.length, index = start - 1) {
|
||||
this.items = items;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
@@ -193,7 +223,7 @@ export class ArrayIterator<T> implements INextIterator<T> {
|
||||
|
||||
export class ArrayNavigator<T> extends ArrayIterator<T> implements INavigator<T> {
|
||||
|
||||
constructor(items: T[], start: number = 0, end: number = items.length, index = start - 1) {
|
||||
constructor(items: readonly T[], start: number = 0, end: number = items.length, index = start - 1) {
|
||||
super(items, start, end, index);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ export interface IJSONSchema {
|
||||
markdownDescription?: string; // VSCode extension
|
||||
doNotSuggest?: boolean; // VSCode extension
|
||||
allowComments?: boolean; // VSCode extension
|
||||
allowsTrailingCommas?: boolean; // VSCode extension
|
||||
allowTrailingCommas?: boolean; // VSCode extension
|
||||
}
|
||||
|
||||
export interface IJSONSchemaMap {
|
||||
|
||||
191
src/vs/base/common/resourceTree.ts
Normal file
191
src/vs/base/common/resourceTree.ts
Normal file
@@ -0,0 +1,191 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import * as paths from 'vs/base/common/path';
|
||||
import { Iterator } from 'vs/base/common/iterator';
|
||||
import { relativePath, joinPath } from 'vs/base/common/resources';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { mapValues } from 'vs/base/common/collections';
|
||||
|
||||
export interface ILeafNode<T, C = void> {
|
||||
readonly uri: URI;
|
||||
readonly relativePath: string;
|
||||
readonly name: string;
|
||||
readonly element: T;
|
||||
readonly context: C;
|
||||
}
|
||||
|
||||
export interface IBranchNode<T, C = void> {
|
||||
readonly uri: URI;
|
||||
readonly relativePath: string;
|
||||
readonly name: string;
|
||||
readonly size: number;
|
||||
readonly children: Iterator<INode<T, C>>;
|
||||
readonly parent: IBranchNode<T, C> | undefined;
|
||||
readonly context: C;
|
||||
get(childName: string): INode<T, C> | undefined;
|
||||
}
|
||||
|
||||
export type INode<T, C> = IBranchNode<T, C> | ILeafNode<T, C>;
|
||||
|
||||
// Internals
|
||||
|
||||
class Node<C> {
|
||||
|
||||
@memoize
|
||||
get name(): string { return paths.posix.basename(this.relativePath); }
|
||||
|
||||
constructor(readonly uri: URI, readonly relativePath: string, readonly context: C) { }
|
||||
}
|
||||
|
||||
class BranchNode<T, C> extends Node<C> implements IBranchNode<T, C> {
|
||||
|
||||
private _children = new Map<string, BranchNode<T, C> | LeafNode<T, C>>();
|
||||
|
||||
get size(): number {
|
||||
return this._children.size;
|
||||
}
|
||||
|
||||
get children(): Iterator<BranchNode<T, C> | LeafNode<T, C>> {
|
||||
return Iterator.fromArray(mapValues(this._children));
|
||||
}
|
||||
|
||||
constructor(uri: URI, relativePath: string, context: C, readonly parent: IBranchNode<T, C> | undefined = undefined) {
|
||||
super(uri, relativePath, context);
|
||||
}
|
||||
|
||||
get(path: string): BranchNode<T, C> | LeafNode<T, C> | undefined {
|
||||
return this._children.get(path);
|
||||
}
|
||||
|
||||
set(path: string, child: BranchNode<T, C> | LeafNode<T, C>): void {
|
||||
this._children.set(path, child);
|
||||
}
|
||||
|
||||
delete(path: string): void {
|
||||
this._children.delete(path);
|
||||
}
|
||||
}
|
||||
|
||||
class LeafNode<T, C> extends Node<C> implements ILeafNode<T, C> {
|
||||
|
||||
constructor(uri: URI, path: string, context: C, readonly element: T) {
|
||||
super(uri, path, context);
|
||||
}
|
||||
}
|
||||
|
||||
function collect<T, C>(node: INode<T, C>, result: T[]): T[] {
|
||||
if (ResourceTree.isBranchNode(node)) {
|
||||
Iterator.forEach(node.children, child => collect(child, result));
|
||||
} else {
|
||||
result.push(node.element);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export class ResourceTree<T extends NonNullable<any>, C> {
|
||||
|
||||
readonly root: BranchNode<T, C>;
|
||||
|
||||
static isBranchNode<T, C>(obj: any): obj is IBranchNode<T, C> {
|
||||
return obj instanceof BranchNode;
|
||||
}
|
||||
|
||||
static getRoot<T, C>(node: IBranchNode<T, C>): IBranchNode<T, C> {
|
||||
while (node.parent) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static collect<T, C>(node: INode<T, C>): T[] {
|
||||
return collect(node, []);
|
||||
}
|
||||
|
||||
constructor(context: C, rootURI: URI = URI.file('/')) {
|
||||
this.root = new BranchNode(rootURI, '', context);
|
||||
}
|
||||
|
||||
add(uri: URI, element: T): void {
|
||||
const key = relativePath(this.root.uri, uri) || uri.fsPath;
|
||||
const parts = key.split(/[\\\/]/).filter(p => !!p);
|
||||
let node = this.root;
|
||||
let path = '';
|
||||
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
const name = parts[i];
|
||||
path = path + '/' + name;
|
||||
|
||||
let child = node.get(name);
|
||||
|
||||
if (!child) {
|
||||
if (i < parts.length - 1) {
|
||||
child = new BranchNode(joinPath(this.root.uri, path), path, this.root.context, node);
|
||||
node.set(name, child);
|
||||
} else {
|
||||
child = new LeafNode(uri, path, this.root.context, element);
|
||||
node.set(name, child);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(child instanceof BranchNode)) {
|
||||
if (i < parts.length - 1) {
|
||||
throw new Error('Inconsistent tree: can\'t override leaf with branch.');
|
||||
}
|
||||
|
||||
// replace
|
||||
node.set(name, new LeafNode(uri, path, this.root.context, element));
|
||||
return;
|
||||
} else if (i === parts.length - 1) {
|
||||
throw new Error('Inconsistent tree: can\'t override branch with leaf.');
|
||||
}
|
||||
|
||||
node = child;
|
||||
}
|
||||
}
|
||||
|
||||
delete(uri: URI): T | undefined {
|
||||
const key = relativePath(this.root.uri, uri) || uri.fsPath;
|
||||
const parts = key.split(/[\\\/]/).filter(p => !!p);
|
||||
return this._delete(this.root, parts, 0);
|
||||
}
|
||||
|
||||
private _delete(node: BranchNode<T, C>, parts: string[], index: number): T | undefined {
|
||||
const name = parts[index];
|
||||
const child = node.get(name);
|
||||
|
||||
if (!child) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// not at end
|
||||
if (index < parts.length - 1) {
|
||||
if (child instanceof BranchNode) {
|
||||
const result = this._delete(child, parts, index + 1);
|
||||
|
||||
if (typeof result !== 'undefined' && child.size === 0) {
|
||||
node.delete(name);
|
||||
}
|
||||
|
||||
return result;
|
||||
} else {
|
||||
throw new Error('Inconsistent tree: Expected a branch, found a leaf instead.');
|
||||
}
|
||||
}
|
||||
|
||||
//at end
|
||||
if (child instanceof BranchNode) {
|
||||
// TODO: maybe we can allow this
|
||||
throw new Error('Inconsistent tree: Expected a leaf, found a branch instead.');
|
||||
}
|
||||
|
||||
node.delete(name);
|
||||
return child.element;
|
||||
}
|
||||
}
|
||||
@@ -24,11 +24,11 @@ export class Sequence<T> implements ISequence<T>, ISpliceable<T> {
|
||||
|
||||
readonly elements: T[] = [];
|
||||
|
||||
private _onDidSplice = new Emitter<ISplice<T>>();
|
||||
private readonly _onDidSplice = new Emitter<ISplice<T>>();
|
||||
readonly onDidSplice: Event<ISplice<T>> = this._onDidSplice.event;
|
||||
|
||||
splice(start: number, deleteCount: number, toInsert: T[] = []): void {
|
||||
this.elements.splice(start, deleteCount, ...toInsert);
|
||||
this._onDidSplice.fire({ start, deleteCount, toInsert });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Menu, MenuItem, BrowserWindow, ipcMain } from 'electron';
|
||||
import { Menu, MenuItem, BrowserWindow, ipcMain, IpcMainEvent } from 'electron';
|
||||
import { ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHANNEL, CONTEXT_MENU_CHANNEL, IPopupOptions } from 'vs/base/parts/contextmenu/common/contextmenu';
|
||||
|
||||
export function registerContextMenuListener(): void {
|
||||
ipcMain.on(CONTEXT_MENU_CHANNEL, (event: Electron.IpcMainEvent, contextMenuId: number, items: ISerializableContextMenuItem[], onClickChannel: string, options?: IPopupOptions) => {
|
||||
ipcMain.on(CONTEXT_MENU_CHANNEL, (event: IpcMainEvent, contextMenuId: number, items: ISerializableContextMenuItem[], onClickChannel: string, options?: IPopupOptions) => {
|
||||
const menu = createMenu(event, onClickChannel, items);
|
||||
|
||||
menu.popup({
|
||||
@@ -27,7 +27,7 @@ export function registerContextMenuListener(): void {
|
||||
});
|
||||
}
|
||||
|
||||
function createMenu(event: Electron.IpcMainEvent, onClickChannel: string, items: ISerializableContextMenuItem[]): Menu {
|
||||
function createMenu(event: IpcMainEvent, onClickChannel: string, items: ISerializableContextMenuItem[]): Menu {
|
||||
const menu = new Menu();
|
||||
|
||||
items.forEach(item => {
|
||||
@@ -65,4 +65,4 @@ function createMenu(event: Electron.IpcMainEvent, onClickChannel: string, items:
|
||||
});
|
||||
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +150,10 @@ export const enum ProtocolConstants {
|
||||
* If there is no reconnection within this time-frame, consider the connection permanently closed...
|
||||
*/
|
||||
ReconnectionGraceTime = 3 * 60 * 60 * 1000, // 3hrs
|
||||
/**
|
||||
* Maximal grace time between the first and the last reconnection...
|
||||
*/
|
||||
ReconnectionShortGraceTime = 5 * 60 * 1000, // 5min
|
||||
}
|
||||
|
||||
class ProtocolMessage {
|
||||
@@ -347,10 +351,10 @@ export class Protocol extends Disposable implements IMessagePassingProtocol {
|
||||
private _socketWriter: ProtocolWriter;
|
||||
private _socketReader: ProtocolReader;
|
||||
|
||||
private _onMessage = new Emitter<VSBuffer>();
|
||||
private readonly _onMessage = new Emitter<VSBuffer>();
|
||||
readonly onMessage: Event<VSBuffer> = this._onMessage.event;
|
||||
|
||||
private _onClose = new Emitter<void>();
|
||||
private readonly _onClose = new Emitter<void>();
|
||||
readonly onClose: Event<void> = this._onClose.event;
|
||||
|
||||
constructor(socket: ISocket) {
|
||||
|
||||
@@ -442,7 +442,7 @@ export class ChannelClient implements IChannelClient, IDisposable {
|
||||
private lastRequestId: number = 0;
|
||||
private protocolListener: IDisposable | null;
|
||||
|
||||
private _onDidInitialize = new Emitter<void>();
|
||||
private readonly _onDidInitialize = new Emitter<void>();
|
||||
readonly onDidInitialize = this._onDidInitialize.event;
|
||||
|
||||
constructor(private protocol: IMessagePassingProtocol) {
|
||||
@@ -660,7 +660,7 @@ export class IPCServer<TContext = string> implements IChannelServer<TContext>, I
|
||||
private channels = new Map<string, IServerChannel<TContext>>();
|
||||
private _connections = new Set<Connection<TContext>>();
|
||||
|
||||
private _onDidChangeConnections = new Emitter<Connection<TContext>>();
|
||||
private readonly _onDidChangeConnections = new Emitter<Connection<TContext>>();
|
||||
readonly onDidChangeConnections: Event<Connection<TContext>> = this._onDidChangeConnections.event;
|
||||
|
||||
get connections(): Connection<TContext>[] {
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { IPCServer, ClientConnectionEvent } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { Protocol } from 'vs/base/parts/ipc/node/ipc.electron';
|
||||
import { ipcMain } from 'electron';
|
||||
import { ipcMain, WebContents } from 'electron';
|
||||
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
|
||||
interface IIPCEvent {
|
||||
event: { sender: Electron.WebContents; };
|
||||
event: { sender: WebContents; };
|
||||
message: Buffer | null;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export class Server extends IPCServer {
|
||||
private static Clients = new Map<number, IDisposable>();
|
||||
|
||||
private static getOnDidClientConnect(): Event<ClientConnectionEvent> {
|
||||
const onHello = Event.fromNodeEventEmitter<Electron.WebContents>(ipcMain, 'ipc:hello', ({ sender }) => sender);
|
||||
const onHello = Event.fromNodeEventEmitter<WebContents>(ipcMain, 'ipc:hello', ({ sender }) => sender);
|
||||
|
||||
return Event.map(onHello, webContents => {
|
||||
const id = webContents.id;
|
||||
|
||||
@@ -92,7 +92,7 @@ export class Client implements IChannelClient, IDisposable {
|
||||
private _client: IPCClient | null;
|
||||
private channels = new Map<string, IChannel>();
|
||||
|
||||
private _onDidProcessExit = new Emitter<{ code: number, signal: string }>();
|
||||
private readonly _onDidProcessExit = new Emitter<{ code: number, signal: string }>();
|
||||
readonly onDidProcessExit = this._onDidProcessExit.event;
|
||||
|
||||
constructor(private modulePath: string, private options: IIPCOptions) {
|
||||
|
||||
@@ -16,7 +16,7 @@ class QueueProtocol implements IMessagePassingProtocol {
|
||||
private buffering = true;
|
||||
private buffers: VSBuffer[] = [];
|
||||
|
||||
private _onMessage = new Emitter<VSBuffer>({
|
||||
private readonly _onMessage = new Emitter<VSBuffer>({
|
||||
onFirstListenerDidAdd: () => {
|
||||
for (const buffer of this.buffers) {
|
||||
this._onMessage.fire(buffer);
|
||||
@@ -57,7 +57,7 @@ function createProtocolPair(): [IMessagePassingProtocol, IMessagePassingProtocol
|
||||
|
||||
class TestIPCClient extends IPCClient<string> {
|
||||
|
||||
private _onDidDisconnect = new Emitter<void>();
|
||||
private readonly _onDidDisconnect = new Emitter<void>();
|
||||
readonly onDidDisconnect = this._onDidDisconnect.event;
|
||||
|
||||
constructor(protocol: IMessagePassingProtocol, id: string) {
|
||||
@@ -107,7 +107,7 @@ interface ITestService {
|
||||
|
||||
class TestService implements ITestService {
|
||||
|
||||
private _pong = new Emitter<string>();
|
||||
private readonly _pong = new Emitter<string>();
|
||||
readonly pong = this._pong.event;
|
||||
|
||||
marco(): Promise<string> {
|
||||
|
||||
@@ -20,7 +20,7 @@ export interface ITestService {
|
||||
|
||||
export class TestService implements ITestService {
|
||||
|
||||
private _onMarco = new Emitter<IMarcoPoloEvent>();
|
||||
private readonly _onMarco = new Emitter<IMarcoPoloEvent>();
|
||||
onMarco: Event<IMarcoPoloEvent> = this._onMarco.event;
|
||||
|
||||
marco(): Promise<string> {
|
||||
@@ -76,4 +76,4 @@ export class TestServiceClient implements ITestService {
|
||||
cancelMe(): Promise<boolean> {
|
||||
return this.channel.call('cancelMe');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ suite('Storage Library', () => {
|
||||
await mkdirp(storageDir);
|
||||
|
||||
class TestSQLiteStorageDatabase extends SQLiteStorageDatabase {
|
||||
private _onDidChangeItemsExternal = new Emitter<IStorageItemsChangeEvent>();
|
||||
private readonly _onDidChangeItemsExternal = new Emitter<IStorageItemsChangeEvent>();
|
||||
get onDidChangeItemsExternal(): Event<IStorageItemsChangeEvent> { return this._onDidChangeItemsExternal.event; }
|
||||
|
||||
fireDidChangeItemsExternal(event: IStorageItemsChangeEvent): void {
|
||||
|
||||
@@ -77,7 +77,7 @@ export class Tree implements _.ITree {
|
||||
readonly onDidExpandItem: Event<Model.IItemExpandEvent> = this._onDidExpandItem.event;
|
||||
private _onDidCollapseItem = new Relay<Model.IItemCollapseEvent>();
|
||||
readonly onDidCollapseItem: Event<Model.IItemCollapseEvent> = this._onDidCollapseItem.event;
|
||||
private _onDispose = new Emitter<void>();
|
||||
private readonly _onDispose = new Emitter<void>();
|
||||
readonly onDidDispose: Event<void> = this._onDispose.event;
|
||||
|
||||
constructor(container: HTMLElement, configuration: _.ITreeConfiguration, options: _.ITreeOptions = {}) {
|
||||
|
||||
@@ -259,29 +259,29 @@ export class Item {
|
||||
|
||||
private traits: { [trait: string]: boolean; };
|
||||
|
||||
private _onDidCreate = new Emitter<Item>();
|
||||
private readonly _onDidCreate = new Emitter<Item>();
|
||||
readonly onDidCreate: Event<Item> = this._onDidCreate.event;
|
||||
private _onDidReveal = new Emitter<IItemRevealEvent>();
|
||||
private readonly _onDidReveal = new Emitter<IItemRevealEvent>();
|
||||
readonly onDidReveal: Event<IItemRevealEvent> = this._onDidReveal.event;
|
||||
private _onExpand = new Emitter<IItemExpandEvent>();
|
||||
private readonly _onExpand = new Emitter<IItemExpandEvent>();
|
||||
readonly onExpand: Event<IItemExpandEvent> = this._onExpand.event;
|
||||
private _onDidExpand = new Emitter<IItemExpandEvent>();
|
||||
private readonly _onDidExpand = new Emitter<IItemExpandEvent>();
|
||||
readonly onDidExpand: Event<IItemExpandEvent> = this._onDidExpand.event;
|
||||
private _onCollapse = new Emitter<IItemCollapseEvent>();
|
||||
private readonly _onCollapse = new Emitter<IItemCollapseEvent>();
|
||||
readonly onCollapse: Event<IItemCollapseEvent> = this._onCollapse.event;
|
||||
private _onDidCollapse = new Emitter<IItemCollapseEvent>();
|
||||
private readonly _onDidCollapse = new Emitter<IItemCollapseEvent>();
|
||||
readonly onDidCollapse: Event<IItemCollapseEvent> = this._onDidCollapse.event;
|
||||
private _onDidAddTrait = new Emitter<IItemTraitEvent>();
|
||||
private readonly _onDidAddTrait = new Emitter<IItemTraitEvent>();
|
||||
readonly onDidAddTrait: Event<IItemTraitEvent> = this._onDidAddTrait.event;
|
||||
private _onDidRemoveTrait = new Emitter<IItemCollapseEvent>();
|
||||
private readonly _onDidRemoveTrait = new Emitter<IItemCollapseEvent>();
|
||||
readonly onDidRemoveTrait: Event<IItemCollapseEvent> = this._onDidRemoveTrait.event;
|
||||
private _onDidRefresh = new Emitter<Item>();
|
||||
private readonly _onDidRefresh = new Emitter<Item>();
|
||||
readonly onDidRefresh: Event<Item> = this._onDidRefresh.event;
|
||||
private _onRefreshChildren = new Emitter<IItemChildrenRefreshEvent>();
|
||||
private readonly _onRefreshChildren = new Emitter<IItemChildrenRefreshEvent>();
|
||||
readonly onRefreshChildren: Event<IItemChildrenRefreshEvent> = this._onRefreshChildren.event;
|
||||
private _onDidRefreshChildren = new Emitter<IItemChildrenRefreshEvent>();
|
||||
private readonly _onDidRefreshChildren = new Emitter<IItemChildrenRefreshEvent>();
|
||||
readonly onDidRefreshChildren: Event<IItemChildrenRefreshEvent> = this._onDidRefreshChildren.event;
|
||||
private _onDidDispose = new Emitter<Item>();
|
||||
private readonly _onDidDispose = new Emitter<Item>();
|
||||
readonly onDidDispose: Event<Item> = this._onDidDispose.event;
|
||||
|
||||
private _isDisposed: boolean;
|
||||
@@ -868,19 +868,19 @@ export class TreeModel {
|
||||
private registryDisposable: IDisposable = Disposable.None;
|
||||
private traitsToItems: ITraitMap;
|
||||
|
||||
private _onSetInput = new Emitter<IInputEvent>();
|
||||
private readonly _onSetInput = new Emitter<IInputEvent>();
|
||||
readonly onSetInput: Event<IInputEvent> = this._onSetInput.event;
|
||||
private _onDidSetInput = new Emitter<IInputEvent>();
|
||||
private readonly _onDidSetInput = new Emitter<IInputEvent>();
|
||||
readonly onDidSetInput: Event<IInputEvent> = this._onDidSetInput.event;
|
||||
private _onRefresh = new Emitter<IRefreshEvent>();
|
||||
private readonly _onRefresh = new Emitter<IRefreshEvent>();
|
||||
readonly onRefresh: Event<IRefreshEvent> = this._onRefresh.event;
|
||||
private _onDidRefresh = new Emitter<IRefreshEvent>();
|
||||
private readonly _onDidRefresh = new Emitter<IRefreshEvent>();
|
||||
readonly onDidRefresh: Event<IRefreshEvent> = this._onDidRefresh.event;
|
||||
private _onDidHighlight = new Emitter<_.IHighlightEvent>();
|
||||
private readonly _onDidHighlight = new Emitter<_.IHighlightEvent>();
|
||||
readonly onDidHighlight: Event<_.IHighlightEvent> = this._onDidHighlight.event;
|
||||
private _onDidSelect = new Emitter<_.ISelectionEvent>();
|
||||
private readonly _onDidSelect = new Emitter<_.ISelectionEvent>();
|
||||
readonly onDidSelect: Event<_.ISelectionEvent> = this._onDidSelect.event;
|
||||
private _onDidFocus = new Emitter<_.IFocusEvent>();
|
||||
private readonly _onDidFocus = new Emitter<_.IFocusEvent>();
|
||||
readonly onDidFocus: Event<_.IFocusEvent> = this._onDidFocus.event;
|
||||
|
||||
private _onDidRevealItem = new Relay<IItemRevealEvent>();
|
||||
|
||||
@@ -1081,10 +1081,10 @@ class DynamicModel implements _.IDataSource {
|
||||
private data: any;
|
||||
public promiseFactory: { (): Promise<any>; } | null;
|
||||
|
||||
private _onGetChildren = new Emitter<any>();
|
||||
private readonly _onGetChildren = new Emitter<any>();
|
||||
readonly onGetChildren: Event<any> = this._onGetChildren.event;
|
||||
|
||||
private _onDidGetChildren = new Emitter<any>();
|
||||
private readonly _onDidGetChildren = new Emitter<any>();
|
||||
readonly onDidGetChildren: Event<any> = this._onDidGetChildren.event;
|
||||
|
||||
constructor() {
|
||||
|
||||
@@ -10,7 +10,7 @@ import { IView } from 'vs/base/browser/ui/grid/grid';
|
||||
|
||||
export class TestView implements IView {
|
||||
|
||||
private _onDidChange = new Emitter<{ width: number; height: number; } | undefined>();
|
||||
private readonly _onDidChange = new Emitter<{ width: number; height: number; } | undefined>();
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
get minimumWidth(): number { return this._minimumWidth; }
|
||||
@@ -28,7 +28,7 @@ export class TestView implements IView {
|
||||
private _element: HTMLElement = document.createElement('div');
|
||||
get element(): HTMLElement { this._onDidGetElement.fire(); return this._element; }
|
||||
|
||||
private _onDidGetElement = new Emitter<void>();
|
||||
private readonly _onDidGetElement = new Emitter<void>();
|
||||
readonly onDidGetElement = this._onDidGetElement.event;
|
||||
|
||||
private _width = 0;
|
||||
@@ -39,10 +39,10 @@ export class TestView implements IView {
|
||||
|
||||
get size(): [number, number] { return [this.width, this.height]; }
|
||||
|
||||
private _onDidLayout = new Emitter<{ width: number; height: number; }>();
|
||||
private readonly _onDidLayout = new Emitter<{ width: number; height: number; }>();
|
||||
readonly onDidLayout: Event<{ width: number; height: number; }> = this._onDidLayout.event;
|
||||
|
||||
private _onDidFocus = new Emitter<void>();
|
||||
private readonly _onDidFocus = new Emitter<void>();
|
||||
readonly onDidFocus: Event<void> = this._onDidFocus.event;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Sash, SashState } from 'vs/base/browser/ui/sash/sash';
|
||||
|
||||
class TestView implements IView {
|
||||
|
||||
private _onDidChange = new Emitter<number | undefined>();
|
||||
private readonly _onDidChange = new Emitter<number | undefined>();
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
get minimumSize(): number { return this._minimumSize; }
|
||||
@@ -22,17 +22,17 @@ class TestView implements IView {
|
||||
private _element: HTMLElement = document.createElement('div');
|
||||
get element(): HTMLElement { this._onDidGetElement.fire(); return this._element; }
|
||||
|
||||
private _onDidGetElement = new Emitter<void>();
|
||||
private readonly _onDidGetElement = new Emitter<void>();
|
||||
readonly onDidGetElement = this._onDidGetElement.event;
|
||||
|
||||
private _size = 0;
|
||||
get size(): number { return this._size; }
|
||||
private _orthogonalSize: number | undefined = 0;
|
||||
get orthogonalSize(): number | undefined { return this._orthogonalSize; }
|
||||
private _onDidLayout = new Emitter<{ size: number; orthogonalSize: number | undefined }>();
|
||||
private readonly _onDidLayout = new Emitter<{ size: number; orthogonalSize: number | undefined }>();
|
||||
readonly onDidLayout = this._onDidLayout.event;
|
||||
|
||||
private _onDidFocus = new Emitter<void>();
|
||||
private readonly _onDidFocus = new Emitter<void>();
|
||||
readonly onDidFocus = this._onDidFocus.event;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -690,4 +690,38 @@ suite('IndexTreeModel', function () {
|
||||
assert.deepEqual(model.getNodeLocation(list[3]), [0, 5]);
|
||||
});
|
||||
});
|
||||
|
||||
test('refilter with filtered out nodes', function () {
|
||||
const list: ITreeNode<string>[] = [];
|
||||
let query = new RegExp('');
|
||||
const filter = new class implements ITreeFilter<string> {
|
||||
filter(element: string): boolean {
|
||||
return query.test(element);
|
||||
}
|
||||
};
|
||||
|
||||
const model = new IndexTreeModel<string>('test', toSpliceable(list), 'root', { filter });
|
||||
|
||||
model.splice([0], 0, Iterator.fromArray([
|
||||
{ element: 'silver' },
|
||||
{ element: 'gold' },
|
||||
{ element: 'platinum' }
|
||||
]));
|
||||
|
||||
assert.deepEqual(toArray(list), ['silver', 'gold', 'platinum']);
|
||||
|
||||
query = /platinum/;
|
||||
model.refilter();
|
||||
assert.deepEqual(toArray(list), ['platinum']);
|
||||
|
||||
model.splice([0], Number.POSITIVE_INFINITY, Iterator.fromArray([
|
||||
{ element: 'silver' },
|
||||
{ element: 'gold' },
|
||||
{ element: 'platinum' }
|
||||
]));
|
||||
assert.deepEqual(toArray(list), ['platinum']);
|
||||
|
||||
model.refilter();
|
||||
assert.deepEqual(toArray(list), ['platinum']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import { memoize, createMemoizer } from 'vs/base/common/decorators';
|
||||
|
||||
suite('Decorators', () => {
|
||||
test('memoize should memoize methods', () => {
|
||||
@@ -125,4 +125,24 @@ suite('Decorators', () => {
|
||||
assert.equal(foo.answer, 42);
|
||||
}
|
||||
});
|
||||
|
||||
test('memoize clear', () => {
|
||||
const memoizer = createMemoizer();
|
||||
let counter = 0;
|
||||
class Foo {
|
||||
@memoizer
|
||||
get answer() { return ++counter; }
|
||||
}
|
||||
|
||||
const foo = new Foo();
|
||||
assert.equal(foo.answer, 1);
|
||||
assert.equal(foo.answer, 1);
|
||||
memoizer.clear();
|
||||
assert.equal(foo.answer, 2);
|
||||
assert.equal(foo.answer, 2);
|
||||
memoizer.clear();
|
||||
assert.equal(foo.answer, 3);
|
||||
assert.equal(foo.answer, 3);
|
||||
assert.equal(foo.answer, 3);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Samples {
|
||||
|
||||
export class Document3 {
|
||||
|
||||
private _onDidChange = new Emitter<string>();
|
||||
private readonly _onDidChange = new Emitter<string>();
|
||||
|
||||
onDidChange: Event<string> = this._onDidChange.event;
|
||||
|
||||
|
||||
49
src/vs/base/test/common/resourceTree.test.ts
Normal file
49
src/vs/base/test/common/resourceTree.test.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { ResourceTree, IBranchNode, ILeafNode } from 'vs/base/common/resourceTree';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
suite('ResourceTree', function () {
|
||||
test('ctor', function () {
|
||||
const tree = new ResourceTree<string, null>(null);
|
||||
assert(ResourceTree.isBranchNode(tree.root));
|
||||
assert.equal(tree.root.size, 0);
|
||||
});
|
||||
|
||||
test('simple', function () {
|
||||
const tree = new ResourceTree<string, null>(null);
|
||||
|
||||
tree.add(URI.file('/foo/bar.txt'), 'bar contents');
|
||||
assert(ResourceTree.isBranchNode(tree.root));
|
||||
assert.equal(tree.root.size, 1);
|
||||
|
||||
let foo = tree.root.get('foo') as IBranchNode<string, null>;
|
||||
assert(foo);
|
||||
assert(ResourceTree.isBranchNode(foo));
|
||||
assert.equal(foo.size, 1);
|
||||
|
||||
let bar = foo.get('bar.txt') as ILeafNode<string, null>;
|
||||
assert(bar);
|
||||
assert(!ResourceTree.isBranchNode(bar));
|
||||
assert.equal(bar.element, 'bar contents');
|
||||
|
||||
tree.add(URI.file('/hello.txt'), 'hello contents');
|
||||
assert.equal(tree.root.size, 2);
|
||||
|
||||
let hello = tree.root.get('hello.txt') as ILeafNode<string, null>;
|
||||
assert(hello);
|
||||
assert(!ResourceTree.isBranchNode(hello));
|
||||
assert.equal(hello.element, 'hello contents');
|
||||
|
||||
tree.delete(URI.file('/foo/bar.txt'));
|
||||
assert.equal(tree.root.size, 1);
|
||||
hello = tree.root.get('hello.txt') as ILeafNode<string, null>;
|
||||
assert(hello);
|
||||
assert(!ResourceTree.isBranchNode(hello));
|
||||
assert.equal(hello.element, 'hello contents');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user