Merge from vscode a5cf1da01d5db3d2557132be8d30f89c38019f6c (#8525)

* Merge from vscode a5cf1da01d5db3d2557132be8d30f89c38019f6c

* remove files we don't want

* fix hygiene

* update distro

* update distro

* fix hygiene

* fix strict nulls

* distro

* distro

* fix tests

* fix tests

* add another edit

* fix viewlet icon

* fix azure dialog

* fix some padding

* fix more padding issues
This commit is contained in:
Anthony Dresser
2019-12-04 19:28:22 -08:00
committed by GitHub
parent a8818ab0df
commit f5ce7fb2a5
1507 changed files with 42813 additions and 27370 deletions

View File

@@ -90,4 +90,5 @@
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
}

View File

@@ -16,6 +16,8 @@ import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
import { Event, Emitter } from 'vs/base/common/event';
import { DataTransfers } from 'vs/base/browser/dnd';
import { isFirefox } from 'vs/base/browser/browser';
export interface IActionViewItem extends IDisposable {
actionRunner: IActionRunner;
@@ -113,6 +115,11 @@ export class BaseActionViewItem extends Disposable implements IActionViewItem {
const enableDragging = this.options && this.options.draggable;
if (enableDragging) {
container.draggable = true;
if (isFirefox) {
// Firefox: requires to set a text data transfer to get going
this._register(DOM.addDisposableListener(container, DOM.EventType.DRAG_START, e => e.dataTransfer?.setData(DataTransfers.TEXT, this._action.label)));
}
}
this._register(DOM.addDisposableListener(element, EventType.Tap, e => this.onClick(e)));

View File

@@ -5,6 +5,8 @@
.monaco-breadcrumbs {
user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
@@ -23,6 +25,10 @@
outline: none;
}
.monaco-breadcrumbs .monaco-breadcrumb-item .codicon-chevron-right {
color: inherit;
}
.monaco-breadcrumbs .monaco-breadcrumb-item:first-of-type::before {
content: ' ';
}

View File

@@ -4,7 +4,6 @@
*--------------------------------------------------------------------------------------------*/
.monaco-text-button {
-moz-box-sizing: border-box;
box-sizing: border-box;
display: inline-block;
width: 100%;
@@ -21,4 +20,4 @@
.monaco-button.disabled {
opacity: 0.4;
cursor: default;
}
}

View File

@@ -42,7 +42,7 @@ function toSplitViewView(view: IView, getHeight: () => number): ISplitViewView {
get maximumSize() { return view.maximumWidth; },
get minimumSize() { return view.minimumWidth; },
onDidChange: Event.map(view.onDidChange, e => e && e.width),
layout: size => view.layout(size, getHeight(), Orientation.HORIZONTAL)
layout: (size, offset) => view.layout(size, getHeight(), 0, offset)
};
}
@@ -81,7 +81,7 @@ export class CenteredViewLayout implements IDisposable {
this.resizeMargins();
}
} else {
this.view.layout(width, height, Orientation.HORIZONTAL);
this.view.layout(width, height, 0, 0);
}
this.didLayout = true;
}

View File

@@ -13,19 +13,10 @@
height: 20px;
border: 1px solid transparent;
padding: 1px;
-webkit-box-sizing: border-box;
-o-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
-ms-user-select: none;
box-sizing: border-box;
user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.monaco-custom-checkbox:hover,

View File

@@ -113,6 +113,8 @@ export class Checkbox extends Widget {
ev.preventDefault();
});
this.ignoreGesture(this.domNode);
this.onkeydown(this.domNode, (keyboardEvent) => {
if (keyboardEvent.keyCode === KeyCode.Space || keyboardEvent.keyCode === KeyCode.Enter) {
this.checked = !this._checked;

View File

@@ -5,7 +5,7 @@
@font-face {
font-family: "codicon";
src: url("./codicon.ttf?3a05fcfc657285cdb4cd3eba790b7462") format("truetype");
src: url("./codicon.ttf?c4e66586cd3ad4acc55fc456c0760dec") format("truetype");
}
.codicon[class*='codicon-'] {
@@ -16,10 +16,9 @@
text-align: center;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
@@ -70,6 +69,10 @@
.codicon-eye-watch:before { content: "\ea70" }
.codicon-circle-filled:before { content: "\ea71" }
.codicon-primitive-dot:before { content: "\ea71" }
.codicon-close-dirty:before { content: "\ea71" }
.codicon-debug-breakpoint:before { content: "\ea71" }
.codicon-debug-breakpoint-disabled:before { content: "\ea71" }
.codicon-debug-hint:before { content: "\ea71" }
.codicon-primitive-square:before { content: "\ea72" }
.codicon-edit:before { content: "\ea73" }
.codicon-pencil:before { content: "\ea73" }
@@ -93,6 +96,7 @@
.codicon-file:before { content: "\ea7b" }
.codicon-file-text:before { content: "\ea7b" }
.codicon-more:before { content: "\ea7c" }
.codicon-ellipsis:before { content: "\ea7c" }
.codicon-kebab-horizontal:before { content: "\ea7c" }
.codicon-mail-reply:before { content: "\ea7d" }
.codicon-reply:before { content: "\ea7d" }
@@ -139,7 +143,6 @@
.codicon-symbol-parameter:before { content: "\ea92" }
.codicon-symbol-type-parameter:before { content: "\ea92" }
.codicon-symbol-key:before { content: "\ea93" }
.codicon-symbol-string:before { content: "\ea93" }
.codicon-symbol-text:before { content: "\ea93" }
.codicon-symbol-reference:before { content: "\ea94" }
.codicon-go-to-file:before { content: "\ea94" }
@@ -147,237 +150,259 @@
.codicon-symbol-value:before { content: "\ea95" }
.codicon-symbol-ruler:before { content: "\ea96" }
.codicon-symbol-unit:before { content: "\ea96" }
.codicon-activate-breakpoints:before { content: "\f101" }
.codicon-archive:before { content: "\f102" }
.codicon-arrow-both:before { content: "\f103" }
.codicon-arrow-down:before { content: "\f104" }
.codicon-arrow-left:before { content: "\f105" }
.codicon-arrow-right:before { content: "\f106" }
.codicon-arrow-small-down:before { content: "\f107" }
.codicon-arrow-small-left:before { content: "\f108" }
.codicon-arrow-small-right:before { content: "\f109" }
.codicon-arrow-small-up:before { content: "\f10a" }
.codicon-arrow-up:before { content: "\f10b" }
.codicon-bell:before { content: "\f10c" }
.codicon-bold:before { content: "\f10d" }
.codicon-book:before { content: "\f10e" }
.codicon-bookmark:before { content: "\f10f" }
.codicon-breakpoint-conditional-unverified:before { content: "\f110" }
.codicon-breakpoint-conditional:before { content: "\f111" }
.codicon-breakpoint-data-unverified:before { content: "\f112" }
.codicon-breakpoint-data:before { content: "\f113" }
.codicon-breakpoint-log-unverified:before { content: "\f114" }
.codicon-breakpoint-log:before { content: "\f115" }
.codicon-briefcase:before { content: "\f116" }
.codicon-broadcast:before { content: "\f117" }
.codicon-browser:before { content: "\f118" }
.codicon-bug:before { content: "\f119" }
.codicon-calendar:before { content: "\f11a" }
.codicon-case-sensitive:before { content: "\f11b" }
.codicon-check:before { content: "\f11c" }
.codicon-checklist:before { content: "\f11d" }
.codicon-chevron-down:before { content: "\f11e" }
.codicon-chevron-left:before { content: "\f11f" }
.codicon-chevron-right:before { content: "\f120" }
.codicon-chevron-up:before { content: "\f121" }
.codicon-chrome-close:before { content: "\f122" }
.codicon-chrome-maximize:before { content: "\f123" }
.codicon-chrome-minimize:before { content: "\f124" }
.codicon-chrome-restore:before { content: "\f125" }
.codicon-circle-outline:before { content: "\f126" }
.codicon-circle-slash:before { content: "\f127" }
.codicon-circuit-board:before { content: "\f128" }
.codicon-clear-all:before { content: "\f129" }
.codicon-clippy:before { content: "\f12a" }
.codicon-close-all:before { content: "\f12b" }
.codicon-cloud-download:before { content: "\f12c" }
.codicon-cloud-upload:before { content: "\f12d" }
.codicon-code:before { content: "\f12e" }
.codicon-collapse-all:before { content: "\f12f" }
.codicon-color-mode:before { content: "\f130" }
.codicon-comment-discussion:before { content: "\f131" }
.codicon-compare-changes:before { content: "\f132" }
.codicon-continue:before { content: "\f133" }
.codicon-credit-card:before { content: "\f134" }
.codicon-current-and-breakpoint:before { content: "\f135" }
.codicon-current:before { content: "\f136" }
.codicon-dash:before { content: "\f137" }
.codicon-dashboard:before { content: "\f138" }
.codicon-database:before { content: "\f139" }
.codicon-debug-disconnect:before { content: "\f13a" }
.codicon-debug-pause:before { content: "\f13b" }
.codicon-debug-restart:before { content: "\f13c" }
.codicon-debug-start:before { content: "\f13d" }
.codicon-debug-step-into:before { content: "\f13e" }
.codicon-debug-step-out:before { content: "\f13f" }
.codicon-debug-step-over:before { content: "\f140" }
.codicon-debug-stop:before { content: "\f141" }
.codicon-debug:before { content: "\f142" }
.codicon-device-camera-video:before { content: "\f143" }
.codicon-device-camera:before { content: "\f144" }
.codicon-device-mobile:before { content: "\f145" }
.codicon-diff-added:before { content: "\f146" }
.codicon-diff-ignored:before { content: "\f147" }
.codicon-diff-modified:before { content: "\f148" }
.codicon-diff-removed:before { content: "\f149" }
.codicon-diff-renamed:before { content: "\f14a" }
.codicon-diff:before { content: "\f14b" }
.codicon-discard:before { content: "\f14c" }
.codicon-editor-layout:before { content: "\f14d" }
.codicon-ellipsis:before { content: "\f14e" }
.codicon-empty-window:before { content: "\f14f" }
.codicon-exclude:before { content: "\f150" }
.codicon-extensions:before { content: "\f151" }
.codicon-eye-closed:before { content: "\f152" }
.codicon-file-binary:before { content: "\f153" }
.codicon-file-code:before { content: "\f154" }
.codicon-file-media:before { content: "\f155" }
.codicon-file-pdf:before { content: "\f156" }
.codicon-file-submodule:before { content: "\f157" }
.codicon-file-symlink-directory:before { content: "\f158" }
.codicon-file-symlink-file:before { content: "\f159" }
.codicon-file-zip:before { content: "\f15a" }
.codicon-files:before { content: "\f15b" }
.codicon-filter:before { content: "\f15c" }
.codicon-flame:before { content: "\f15d" }
.codicon-fold-down:before { content: "\f15e" }
.codicon-fold-up:before { content: "\f15f" }
.codicon-fold:before { content: "\f160" }
.codicon-folder-active:before { content: "\f161" }
.codicon-folder-opened:before { content: "\f162" }
.codicon-gear:before { content: "\f163" }
.codicon-gift:before { content: "\f164" }
.codicon-gist-secret:before { content: "\f165" }
.codicon-gist:before { content: "\f166" }
.codicon-git-commit:before { content: "\f167" }
.codicon-git-compare:before { content: "\f168" }
.codicon-git-merge:before { content: "\f169" }
.codicon-github-action:before { content: "\f16a" }
.codicon-github-alt:before { content: "\f16b" }
.codicon-globe:before { content: "\f16c" }
.codicon-grabber:before { content: "\f16d" }
.codicon-graph:before { content: "\f16e" }
.codicon-gripper:before { content: "\f16f" }
.codicon-heart:before { content: "\f170" }
.codicon-home:before { content: "\f171" }
.codicon-horizontal-rule:before { content: "\f172" }
.codicon-hubot:before { content: "\f173" }
.codicon-inbox:before { content: "\f174" }
.codicon-issue-closed:before { content: "\f175" }
.codicon-issue-reopened:before { content: "\f176" }
.codicon-issues:before { content: "\f177" }
.codicon-italic:before { content: "\f178" }
.codicon-jersey:before { content: "\f179" }
.codicon-json:before { content: "\f17a" }
.codicon-kebab-vertical:before { content: "\f17b" }
.codicon-law:before { content: "\f17c" }
.codicon-lightbulb-autofix:before { content: "\f17d" }
.codicon-link-external:before { content: "\f17e" }
.codicon-link:before { content: "\f17f" }
.codicon-list-ordered:before { content: "\f180" }
.codicon-list-unordered:before { content: "\f181" }
.codicon-live-share:before { content: "\f182" }
.codicon-loading:before { content: "\f183" }
.codicon-location:before { content: "\f184" }
.codicon-mail-read:before { content: "\f185" }
.codicon-mail:before { content: "\f186" }
.codicon-markdown:before { content: "\f187" }
.codicon-megaphone:before { content: "\f188" }
.codicon-mention:before { content: "\f189" }
.codicon-milestone:before { content: "\f18a" }
.codicon-mortar-board:before { content: "\f18b" }
.codicon-move:before { content: "\f18c" }
.codicon-multiple-windows:before { content: "\f18d" }
.codicon-mute:before { content: "\f18e" }
.codicon-no-newline:before { content: "\f18f" }
.codicon-note:before { content: "\f190" }
.codicon-octoface:before { content: "\f191" }
.codicon-open-preview:before { content: "\f192" }
.codicon-package:before { content: "\f193" }
.codicon-paintcan:before { content: "\f194" }
.codicon-pin:before { content: "\f195" }
.codicon-play:before { content: "\f196" }
.codicon-plug:before { content: "\f197" }
.codicon-preserve-case:before { content: "\f198" }
.codicon-preview:before { content: "\f199" }
.codicon-project:before { content: "\f19a" }
.codicon-pulse:before { content: "\f19b" }
.codicon-question:before { content: "\f19c" }
.codicon-quote:before { content: "\f19d" }
.codicon-radio-tower:before { content: "\f19e" }
.codicon-reactions:before { content: "\f19f" }
.codicon-references:before { content: "\f1a0" }
.codicon-refresh:before { content: "\f1a1" }
.codicon-regex:before { content: "\f1a2" }
.codicon-remote:before { content: "\f1a3" }
.codicon-remove:before { content: "\f1a4" }
.codicon-replace-all:before { content: "\f1a5" }
.codicon-replace:before { content: "\f1a6" }
.codicon-repo-clone:before { content: "\f1a7" }
.codicon-repo-force-push:before { content: "\f1a8" }
.codicon-repo-pull:before { content: "\f1a9" }
.codicon-repo-push:before { content: "\f1aa" }
.codicon-report:before { content: "\f1ab" }
.codicon-request-changes:before { content: "\f1ac" }
.codicon-rocket:before { content: "\f1ad" }
.codicon-root-folder-opened:before { content: "\f1ae" }
.codicon-root-folder:before { content: "\f1af" }
.codicon-rss:before { content: "\f1b0" }
.codicon-ruby:before { content: "\f1b1" }
.codicon-save-all:before { content: "\f1b2" }
.codicon-save-as:before { content: "\f1b3" }
.codicon-save:before { content: "\f1b4" }
.codicon-screen-full:before { content: "\f1b5" }
.codicon-screen-normal:before { content: "\f1b6" }
.codicon-search-stop:before { content: "\f1b7" }
.codicon-selection:before { content: "\f1b8" }
.codicon-server:before { content: "\f1b9" }
.codicon-settings:before { content: "\f1ba" }
.codicon-shield:before { content: "\f1bb" }
.codicon-smiley:before { content: "\f1bc" }
.codicon-sort-precedence:before { content: "\f1bd" }
.codicon-split-horizontal:before { content: "\f1be" }
.codicon-split-vertical:before { content: "\f1bf" }
.codicon-squirrel:before { content: "\f1c0" }
.codicon-star-full:before { content: "\f1c1" }
.codicon-star-half:before { content: "\f1c2" }
.codicon-symbol-class:before { content: "\f1c3" }
.codicon-symbol-color:before { content: "\f1c4" }
.codicon-symbol-constant:before { content: "\f1c5" }
.codicon-symbol-enum-member:before { content: "\f1c6" }
.codicon-symbol-field:before { content: "\f1c7" }
.codicon-symbol-file:before { content: "\f1c8" }
.codicon-symbol-interface:before { content: "\f1c9" }
.codicon-symbol-keyword:before { content: "\f1ca" }
.codicon-symbol-misc:before { content: "\f1cb" }
.codicon-symbol-operator:before { content: "\f1cc" }
.codicon-symbol-property:before { content: "\f1cd" }
.codicon-symbol-snippet:before { content: "\f1ce" }
.codicon-tasklist:before { content: "\f1cf" }
.codicon-telescope:before { content: "\f1d0" }
.codicon-text-size:before { content: "\f1d1" }
.codicon-three-bars:before { content: "\f1d2" }
.codicon-thumbsdown:before { content: "\f1d3" }
.codicon-thumbsup:before { content: "\f1d4" }
.codicon-tools:before { content: "\f1d5" }
.codicon-triangle-down:before { content: "\f1d6" }
.codicon-triangle-left:before { content: "\f1d7" }
.codicon-triangle-right:before { content: "\f1d8" }
.codicon-triangle-up:before { content: "\f1d9" }
.codicon-twitter:before { content: "\f1da" }
.codicon-unfold:before { content: "\f1db" }
.codicon-unlock:before { content: "\f1dc" }
.codicon-unmute:before { content: "\f1dd" }
.codicon-unverified:before { content: "\f1de" }
.codicon-verified:before { content: "\f1df" }
.codicon-versions:before { content: "\f1e0" }
.codicon-vm-active:before { content: "\f1e1" }
.codicon-vm-outline:before { content: "\f1e2" }
.codicon-vm-running:before { content: "\f1e3" }
.codicon-watch:before { content: "\f1e4" }
.codicon-whitespace:before { content: "\f1e5" }
.codicon-whole-word:before { content: "\f1e6" }
.codicon-window:before { content: "\f1e7" }
.codicon-word-wrap:before { content: "\f1e8" }
.codicon-zoom-in:before { content: "\f1e9" }
.codicon-zoom-out:before { content: "\f1ea" }
.codicon-activate-breakpoints:before { content: "\ea97" }
.codicon-archive:before { content: "\ea98" }
.codicon-arrow-both:before { content: "\ea99" }
.codicon-arrow-down:before { content: "\ea9a" }
.codicon-arrow-left:before { content: "\ea9b" }
.codicon-arrow-right:before { content: "\ea9c" }
.codicon-arrow-small-down:before { content: "\ea9d" }
.codicon-arrow-small-left:before { content: "\ea9e" }
.codicon-arrow-small-right:before { content: "\ea9f" }
.codicon-arrow-small-up:before { content: "\eaa0" }
.codicon-arrow-up:before { content: "\eaa1" }
.codicon-bell:before { content: "\eaa2" }
.codicon-bold:before { content: "\eaa3" }
.codicon-book:before { content: "\eaa4" }
.codicon-bookmark:before { content: "\eaa5" }
.codicon-debug-breakpoint-conditional-unverified:before { content: "\eaa6" }
.codicon-debug-breakpoint-conditional:before { content: "\eaa7" }
.codicon-debug-breakpoint-conditional-disabled:before { content: "\eaa7" }
.codicon-debug-breakpoint-data-unverified:before { content: "\eaa8" }
.codicon-debug-breakpoint-data:before { content: "\eaa9" }
.codicon-debug-breakpoint-data-disabled:before { content: "\eaa9" }
.codicon-debug-breakpoint-log-unverified:before { content: "\eaaa" }
.codicon-debug-breakpoint-log:before { content: "\eaab" }
.codicon-debug-breakpoint-log-disabled:before { content: "\eaab" }
.codicon-briefcase:before { content: "\eaac" }
.codicon-broadcast:before { content: "\eaad" }
.codicon-browser:before { content: "\eaae" }
.codicon-bug:before { content: "\eaaf" }
.codicon-calendar:before { content: "\eab0" }
.codicon-case-sensitive:before { content: "\eab1" }
.codicon-check:before { content: "\eab2" }
.codicon-checklist:before { content: "\eab3" }
.codicon-chevron-down:before { content: "\eab4" }
.codicon-chevron-left:before { content: "\eab5" }
.codicon-chevron-right:before { content: "\eab6" }
.codicon-chevron-up:before { content: "\eab7" }
.codicon-chrome-close:before { content: "\eab8" }
.codicon-chrome-maximize:before { content: "\eab9" }
.codicon-chrome-minimize:before { content: "\eaba" }
.codicon-chrome-restore:before { content: "\eabb" }
.codicon-circle-outline:before { content: "\eabc" }
.codicon-debug-breakpoint-unverified:before { content: "\eabc" }
.codicon-circle-slash:before { content: "\eabd" }
.codicon-circuit-board:before { content: "\eabe" }
.codicon-clear-all:before { content: "\eabf" }
.codicon-clippy:before { content: "\eac0" }
.codicon-close-all:before { content: "\eac1" }
.codicon-cloud-download:before { content: "\eac2" }
.codicon-cloud-upload:before { content: "\eac3" }
.codicon-code:before { content: "\eac4" }
.codicon-collapse-all:before { content: "\eac5" }
.codicon-color-mode:before { content: "\eac6" }
.codicon-comment-discussion:before { content: "\eac7" }
.codicon-compare-changes:before { content: "\eac8" }
.codicon-credit-card:before { content: "\eac9" }
.codicon-dash:before { content: "\eacc" }
.codicon-dashboard:before { content: "\eacd" }
.codicon-database:before { content: "\eace" }
.codicon-debug-continue:before { content: "\eacf" }
.codicon-debug-disconnect:before { content: "\ead0" }
.codicon-debug-pause:before { content: "\ead1" }
.codicon-debug-restart:before { content: "\ead2" }
.codicon-debug-start:before { content: "\ead3" }
.codicon-debug-step-into:before { content: "\ead4" }
.codicon-debug-step-out:before { content: "\ead5" }
.codicon-debug-step-over:before { content: "\ead6" }
.codicon-debug-stop:before { content: "\ead7" }
.codicon-debug:before { content: "\ead8" }
.codicon-device-camera-video:before { content: "\ead9" }
.codicon-device-camera:before { content: "\eada" }
.codicon-device-mobile:before { content: "\eadb" }
.codicon-diff-added:before { content: "\eadc" }
.codicon-diff-ignored:before { content: "\eadd" }
.codicon-diff-modified:before { content: "\eade" }
.codicon-diff-removed:before { content: "\eadf" }
.codicon-diff-renamed:before { content: "\eae0" }
.codicon-diff:before { content: "\eae1" }
.codicon-discard:before { content: "\eae2" }
.codicon-editor-layout:before { content: "\eae3" }
.codicon-empty-window:before { content: "\eae4" }
.codicon-exclude:before { content: "\eae5" }
.codicon-extensions:before { content: "\eae6" }
.codicon-eye-closed:before { content: "\eae7" }
.codicon-file-binary:before { content: "\eae8" }
.codicon-file-code:before { content: "\eae9" }
.codicon-file-media:before { content: "\eaea" }
.codicon-file-pdf:before { content: "\eaeb" }
.codicon-file-submodule:before { content: "\eaec" }
.codicon-file-symlink-directory:before { content: "\eaed" }
.codicon-file-symlink-file:before { content: "\eaee" }
.codicon-file-zip:before { content: "\eaef" }
.codicon-files:before { content: "\eaf0" }
.codicon-filter:before { content: "\eaf1" }
.codicon-flame:before { content: "\eaf2" }
.codicon-fold-down:before { content: "\eaf3" }
.codicon-fold-up:before { content: "\eaf4" }
.codicon-fold:before { content: "\eaf5" }
.codicon-folder-active:before { content: "\eaf6" }
.codicon-folder-opened:before { content: "\eaf7" }
.codicon-gear:before { content: "\eaf8" }
.codicon-gift:before { content: "\eaf9" }
.codicon-gist-secret:before { content: "\eafa" }
.codicon-gist:before { content: "\eafb" }
.codicon-git-commit:before { content: "\eafc" }
.codicon-git-compare:before { content: "\eafd" }
.codicon-git-merge:before { content: "\eafe" }
.codicon-github-action:before { content: "\eaff" }
.codicon-github-alt:before { content: "\eb00" }
.codicon-globe:before { content: "\eb01" }
.codicon-grabber:before { content: "\eb02" }
.codicon-graph:before { content: "\eb03" }
.codicon-gripper:before { content: "\eb04" }
.codicon-heart:before { content: "\eb05" }
.codicon-home:before { content: "\eb06" }
.codicon-horizontal-rule:before { content: "\eb07" }
.codicon-hubot:before { content: "\eb08" }
.codicon-inbox:before { content: "\eb09" }
.codicon-issue-closed:before { content: "\eb0a" }
.codicon-issue-reopened:before { content: "\eb0b" }
.codicon-issues:before { content: "\eb0c" }
.codicon-italic:before { content: "\eb0d" }
.codicon-jersey:before { content: "\eb0e" }
.codicon-json:before { content: "\eb0f" }
.codicon-kebab-vertical:before { content: "\eb10" }
.codicon-key:before { content: "\eb11" }
.codicon-law:before { content: "\eb12" }
.codicon-lightbulb-autofix:before { content: "\eb13" }
.codicon-link-external:before { content: "\eb14" }
.codicon-link:before { content: "\eb15" }
.codicon-list-ordered:before { content: "\eb16" }
.codicon-list-unordered:before { content: "\eb17" }
.codicon-live-share:before { content: "\eb18" }
.codicon-loading:before { content: "\eb19" }
.codicon-location:before { content: "\eb1a" }
.codicon-mail-read:before { content: "\eb1b" }
.codicon-mail:before { content: "\eb1c" }
.codicon-markdown:before { content: "\eb1d" }
.codicon-megaphone:before { content: "\eb1e" }
.codicon-mention:before { content: "\eb1f" }
.codicon-milestone:before { content: "\eb20" }
.codicon-mortar-board:before { content: "\eb21" }
.codicon-move:before { content: "\eb22" }
.codicon-multiple-windows:before { content: "\eb23" }
.codicon-mute:before { content: "\eb24" }
.codicon-no-newline:before { content: "\eb25" }
.codicon-note:before { content: "\eb26" }
.codicon-octoface:before { content: "\eb27" }
.codicon-open-preview:before { content: "\eb28" }
.codicon-package:before { content: "\eb29" }
.codicon-paintcan:before { content: "\eb2a" }
.codicon-pin:before { content: "\eb2b" }
.codicon-play:before { content: "\eb2c" }
.codicon-plug:before { content: "\eb2d" }
.codicon-preserve-case:before { content: "\eb2e" }
.codicon-preview:before { content: "\eb2f" }
.codicon-project:before { content: "\eb30" }
.codicon-pulse:before { content: "\eb31" }
.codicon-question:before { content: "\eb32" }
.codicon-quote:before { content: "\eb33" }
.codicon-radio-tower:before { content: "\eb34" }
.codicon-reactions:before { content: "\eb35" }
.codicon-references:before { content: "\eb36" }
.codicon-refresh:before { content: "\eb37" }
.codicon-regex:before { content: "\eb38" }
.codicon-remote-explorer:before { content: "\eb39" }
.codicon-remote:before { content: "\eb3a" }
.codicon-remove:before { content: "\eb3b" }
.codicon-replace-all:before { content: "\eb3c" }
.codicon-replace:before { content: "\eb3d" }
.codicon-repo-clone:before { content: "\eb3e" }
.codicon-repo-force-push:before { content: "\eb3f" }
.codicon-repo-pull:before { content: "\eb40" }
.codicon-repo-push:before { content: "\eb41" }
.codicon-report:before { content: "\eb42" }
.codicon-request-changes:before { content: "\eb43" }
.codicon-rocket:before { content: "\eb44" }
.codicon-root-folder-opened:before { content: "\eb45" }
.codicon-root-folder:before { content: "\eb46" }
.codicon-rss:before { content: "\eb47" }
.codicon-ruby:before { content: "\eb48" }
.codicon-save-all:before { content: "\eb49" }
.codicon-save-as:before { content: "\eb4a" }
.codicon-save:before { content: "\eb4b" }
.codicon-screen-full:before { content: "\eb4c" }
.codicon-screen-normal:before { content: "\eb4d" }
.codicon-search-stop:before { content: "\eb4e" }
.codicon-server:before { content: "\eb50" }
.codicon-settings-gear:before { content: "\eb51" }
.codicon-settings:before { content: "\eb52" }
.codicon-shield:before { content: "\eb53" }
.codicon-smiley:before { content: "\eb54" }
.codicon-sort-precedence:before { content: "\eb55" }
.codicon-split-horizontal:before { content: "\eb56" }
.codicon-split-vertical:before { content: "\eb57" }
.codicon-squirrel:before { content: "\eb58" }
.codicon-star-full:before { content: "\eb59" }
.codicon-star-half:before { content: "\eb5a" }
.codicon-symbol-class:before { content: "\eb5b" }
.codicon-symbol-color:before { content: "\eb5c" }
.codicon-symbol-constant:before { content: "\eb5d" }
.codicon-symbol-enum-member:before { content: "\eb5e" }
.codicon-symbol-field:before { content: "\eb5f" }
.codicon-symbol-file:before { content: "\eb60" }
.codicon-symbol-interface:before { content: "\eb61" }
.codicon-symbol-keyword:before { content: "\eb62" }
.codicon-symbol-misc:before { content: "\eb63" }
.codicon-symbol-operator:before { content: "\eb64" }
.codicon-symbol-property:before { content: "\eb65" }
.codicon-symbol-snippet:before { content: "\eb66" }
.codicon-tasklist:before { content: "\eb67" }
.codicon-telescope:before { content: "\eb68" }
.codicon-text-size:before { content: "\eb69" }
.codicon-three-bars:before { content: "\eb6a" }
.codicon-thumbsdown:before { content: "\eb6b" }
.codicon-thumbsup:before { content: "\eb6c" }
.codicon-tools:before { content: "\eb6d" }
.codicon-triangle-down:before { content: "\eb6e" }
.codicon-triangle-left:before { content: "\eb6f" }
.codicon-triangle-right:before { content: "\eb70" }
.codicon-triangle-up:before { content: "\eb71" }
.codicon-twitter:before { content: "\eb72" }
.codicon-unfold:before { content: "\eb73" }
.codicon-unlock:before { content: "\eb74" }
.codicon-unmute:before { content: "\eb75" }
.codicon-unverified:before { content: "\eb76" }
.codicon-verified:before { content: "\eb77" }
.codicon-versions:before { content: "\eb78" }
.codicon-vm-active:before { content: "\eb79" }
.codicon-vm-outline:before { content: "\eb7a" }
.codicon-vm-running:before { content: "\eb7b" }
.codicon-watch:before { content: "\eb7c" }
.codicon-whitespace:before { content: "\eb7d" }
.codicon-whole-word:before { content: "\eb7e" }
.codicon-window:before { content: "\eb7f" }
.codicon-word-wrap:before { content: "\eb80" }
.codicon-zoom-in:before { content: "\eb81" }
.codicon-zoom-out:before { content: "\eb82" }
.codicon-list-filter:before { content: "\eb83" }
.codicon-list-flat:before { content: "\eb84" }
.codicon-list-selection:before { content: "\eb85" }
.codicon-selection:before { content: "\eb85" }
.codicon-list-tree:before { content: "\eb86" }
.codicon-debug-breakpoint-function-unverified:before { content: "\eb87" }
.codicon-debug-breakpoint-function:before { content: "\eb88" }
.codicon-debug-breakpoint-function-disabled:before { content: "\eb88" }
.codicon-debug-breakpoint-stackframe-active:before { content: "\eb89" }
.codicon-debug-breakpoint-stackframe-dot:before { content: "\eb8a" }
.codicon-debug-breakpoint-stackframe:before { content: "\eb8b" }
.codicon-debug-breakpoint-stackframe-focused:before { content: "\eb8b" }
.codicon-debug-breakpoint-unsupported:before { content: "\eb8c" }
.codicon-symbol-string:before { content: "\eb8d" }
.codicon-debug-reverse-continue:before { content: "\eb8e" }
.codicon-debug-step-back:before { content: "\eb8f" }
.codicon-debug-restart-frame:before { content: "\eb90" }
.codicon-debug-alternate:before { content: "\eb91" }
.codicon-debug-alt:before { content: "\f101" }

View File

@@ -5,8 +5,10 @@
import 'vs/css!./contextview';
import * as DOM from 'vs/base/browser/dom';
import * as platform from 'vs/base/common/platform';
import { IDisposable, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Range } from 'vs/base/common/range';
import { BrowserFeatures } from 'vs/base/browser/canIUse';
export interface IAnchor {
x: number;
@@ -178,7 +180,7 @@ export class ContextView extends Disposable {
return;
}
if (this.delegate!.canRelayout === false) {
if (this.delegate!.canRelayout === false && !(platform.isIOS && BrowserFeatures.pointerEvents)) {
this.hide();
return;
}

View File

@@ -8,6 +8,7 @@ import { $, append } from 'vs/base/browser/dom';
import { format } from 'vs/base/common/strings';
import { Color } from 'vs/base/common/color';
import { mixin } from 'vs/base/common/objects';
import { IThemable } from 'vs/base/common/styler';
export interface ICountBadgeOptions extends ICountBadgetyles {
count?: number;
@@ -26,7 +27,7 @@ const defaultOpts = {
badgeForeground: Color.fromHex('#FFFFFF')
};
export class CountBadge {
export class CountBadge implements IThemable {
private element: HTMLElement;
private count: number = 0;

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00001 8.70714L11.6465 12.3536L12.3536 11.6465L8.70711 8.00004L12.3536 4.35359L11.6465 3.64648L8.00001 7.29293L4.35356 3.64648L3.64645 4.35359L7.2929 8.00004L3.64645 11.6465L4.35356 12.3536L8.00001 8.70714Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 379 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00001 8.70714L11.6465 12.3536L12.3536 11.6465L8.70711 8.00004L12.3536 4.35359L11.6465 3.64648L8.00001 7.29293L4.35356 3.64648L3.64645 4.35359L7.2929 8.00004L3.64645 11.6465L4.35356 12.3536L8.00001 8.70714Z" fill="#424242"/>
</svg>

Before

Width:  |  Height:  |  Size: 379 B

View File

@@ -27,12 +27,12 @@
min-width: 500px;
max-width: 90%;
min-height: 75px;
padding: 5px;
padding: 10px;
}
/** Dialog: Title Actions Row */
.monaco-workbench .dialog-box .dialog-toolbar-row {
padding-right: 1px;
padding-bottom: 4px;
}
.monaco-workbench .dialog-box .action-label {
@@ -46,73 +46,19 @@
}
.monaco-workbench .dialog-box .dialog-close-action {
background: url('close-light.svg') center center no-repeat;
}
.vs-dark .monaco-workbench .dialog-box .dialog-close-action,
.hc-black .monaco-workbench .dialog-box .dialog-close-action {
background: url('close-dark.svg') center center no-repeat;
}
/** Dialog: Message Row */
.monaco-workbench .dialog-box .dialog-message-row {
display: flex;
flex-grow: 1;
padding: 10px 15px 20px;
align-items: center;
padding: 0 10px;
}
.monaco-workbench .dialog-box .dialog-message-row .dialog-icon {
flex: 0 0 40px;
height: 40px;
.monaco-workbench .dialog-box .dialog-message-row > .codicon {
flex: 0 0 48px;
height: 48px;
align-self: baseline;
background-position: center;
background-repeat: no-repeat;
background-size: 40px;
}
.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending {
background-image: url('pending.svg');
}
.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info {
background-image: url('info-light.svg');
}
.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-warning {
background-image: url('warning-light.svg');
}
.vs .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-error {
background-image: url('error-light.svg');
}
.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending {
background-image: url('pending-dark.svg');
}
.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info,
.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-info {
background-image: url('info-dark.svg');
}
.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-warning,
.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-warning {
background-image: url('warning-dark.svg');
}
.vs-dark .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-error,
.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-error {
background-image: url('error-dark.svg');
}
.hc-black .monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending {
background-image: url('pending-hc.svg');
}
.monaco-workbench .dialog-box .dialog-message-row .dialog-icon.icon-pending {
background-size: 30px;
font-size: 48px;
}
/** Dialog: Message Container */
@@ -121,8 +67,10 @@
flex-direction: column;
overflow: hidden;
text-overflow: ellipsis;
padding-left: 20px;
padding-left: 24px;
user-select: text;
-webkit-user-select: text;
-ms-user-select: text;
word-wrap: break-word; /* never overflow long words, but break to next line */
white-space: normal;
}
@@ -134,7 +82,10 @@
flex: 1; /* let the message always grow */
white-space: normal;
word-wrap: break-word; /* never overflow long words, but break to next line */
padding-bottom: 10px;
min-height: 48px; /* matches icon height */
margin-bottom: 8px;
display: flex;
align-items: center;
}
/** Dialog: Details */
@@ -154,6 +105,13 @@
display: flex;
}
.monaco-workbench .dialog-box .dialog-message-row .dialog-message-container .dialog-checkbox-row .dialog-checkbox-message {
cursor: pointer;
user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
/** Dialog: Buttons Row */
.monaco-workbench .dialog-box > .dialog-buttons-row {
display: flex;
@@ -166,6 +124,7 @@
.monaco-workbench .dialog-box > .dialog-buttons-row {
display: flex;
white-space: nowrap;
padding: 20px 10px 10px;
}
/** Dialog: Buttons */
@@ -175,7 +134,8 @@
}
.monaco-workbench .dialog-box > .dialog-buttons-row > .dialog-buttons > .monaco-button {
max-width: fit-content;
width: fit-content;
width: -moz-fit-content;
padding: 5px 10px;
margin: 4px 5px; /* allows button focus outline to be visible */
overflow: hidden;

View File

@@ -6,7 +6,7 @@
import 'vs/css!./dialog';
import * as nls from 'vs/nls';
import { Disposable } from 'vs/base/common/lifecycle';
import { $, hide, show, EventHelper, clearNode, removeClasses, addClass, removeNode, isAncestor } from 'vs/base/browser/dom';
import { $, hide, show, EventHelper, clearNode, removeClasses, addClass, addClasses, removeNode, isAncestor, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { domEvent } from 'vs/base/browser/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
@@ -75,7 +75,8 @@ export class Dialog extends Disposable {
if (this.options.detail) {
const messageElement = messageContainer.appendChild($('.dialog-message'));
messageElement.innerText = this.message;
const messageTextElement = messageElement.appendChild($('.dialog-message-text'));
messageTextElement.innerText = this.message;
}
this.messageDetailElement = messageContainer.appendChild($('.dialog-message-detail'));
@@ -84,12 +85,13 @@ export class Dialog extends Disposable {
if (this.options.checkboxLabel) {
const checkboxRowElement = messageContainer.appendChild($('.dialog-checkbox-row'));
this.checkbox = this._register(new SimpleCheckbox(this.options.checkboxLabel, !!this.options.checkboxChecked));
const checkbox = this.checkbox = this._register(new SimpleCheckbox(this.options.checkboxLabel, !!this.options.checkboxChecked));
checkboxRowElement.appendChild(this.checkbox.domNode);
checkboxRowElement.appendChild(checkbox.domNode);
const checkboxMessageElement = checkboxRowElement.appendChild($('.dialog-checkbox-message'));
checkboxMessageElement.innerText = this.options.checkboxLabel;
this._register(addDisposableListener(checkboxMessageElement, EventType.CLICK, () => checkbox.checked = !checkbox.checked));
}
const toolbarRowElement = this.element.appendChild($('.dialog-toolbar-row'));
@@ -198,29 +200,30 @@ export class Dialog extends Disposable {
}
}));
removeClasses(this.iconElement, 'icon-error', 'icon-warning', 'icon-info');
addClass(this.iconElement, 'codicon');
removeClasses(this.iconElement, 'codicon-alert', 'codicon-warning', 'codicon-info');
switch (this.options.type) {
case 'error':
addClass(this.iconElement, 'icon-error');
addClass(this.iconElement, 'codicon-error');
break;
case 'warning':
addClass(this.iconElement, 'icon-warning');
addClass(this.iconElement, 'codicon-warning');
break;
case 'pending':
addClass(this.iconElement, 'icon-pending');
addClasses(this.iconElement, 'codicon-loading', 'codicon-animation-spin');
break;
case 'none':
case 'info':
case 'question':
default:
addClass(this.iconElement, 'icon-info');
addClass(this.iconElement, 'codicon-info');
break;
}
const actionBar = new ActionBar(this.toolbarContainer, {});
const action = new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), 'dialog-close-action', true, () => {
const action = new Action('dialog.close', nls.localize('dialogClose', "Close Dialog"), 'codicon codicon-close', true, () => {
resolve({ button: this.options.cancelId || 0, checkboxChecked: this.checkbox ? this.checkbox.checked : undefined });
return Promise.resolve();
});

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.58318 2.02842C9.96435 2.16331 11.2561 2.77279 12.2383 3.75307C13.3643 4.87923 13.9978 6.40584 14 7.99829C14.0004 9.38617 13.5196 10.7313 12.6396 11.8045C11.7595 12.8778 10.5345 13.6127 9.17333 13.8841C7.81215 14.1556 6.39895 13.9467 5.1745 13.2931C3.95005 12.6394 2.99008 11.5815 2.45814 10.2995C1.92619 9.0175 1.85517 7.59072 2.25717 6.26222C2.65917 4.93373 3.50933 3.7857 4.66282 3.0137C5.8163 2.24171 7.20177 1.89351 8.58318 2.02842ZM8.68038 1.03316C10.292 1.19055 11.7993 1.90184 12.9453 3.04585C14.2587 4.35938 14.9976 6.14013 15 7.99764C15.0005 9.61695 14.4396 11.1864 13.4129 12.4385C12.3861 13.6907 10.9569 14.5482 9.36889 14.8648C7.78084 15.1815 6.13211 14.9378 4.70359 14.1752C3.27506 13.4127 2.1551 12.1784 1.53449 10.6828C0.913887 9.18708 0.831027 7.52251 1.30003 5.97259C1.76903 4.42268 2.76089 3.08331 4.10662 2.18265C5.45236 1.28199 7.06873 0.875761 8.68038 1.03316ZM5.52498 5L8.00004 7.47506L10.4751 5L11.1822 5.70711L8.70714 8.18217L11.1818 10.6569L10.4747 11.364L8.00004 8.88927L5.52535 11.364L4.81824 10.6569L7.29293 8.18217L4.81787 5.70711L5.52498 5Z" fill="#F48771"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.58318 2.02842C9.96435 2.16331 11.2561 2.77279 12.2383 3.75307C13.3643 4.87923 13.9978 6.40584 14 7.99829C14.0004 9.38617 13.5196 10.7313 12.6396 11.8045C11.7595 12.8778 10.5345 13.6127 9.17333 13.8841C7.81215 14.1556 6.39895 13.9467 5.1745 13.2931C3.95005 12.6394 2.99008 11.5815 2.45814 10.2995C1.92619 9.0175 1.85517 7.59072 2.25717 6.26222C2.65917 4.93373 3.50933 3.7857 4.66282 3.0137C5.8163 2.24171 7.20177 1.89351 8.58318 2.02842ZM8.68038 1.03316C10.292 1.19055 11.7993 1.90184 12.9453 3.04585C14.2587 4.35938 14.9976 6.14013 15 7.99764C15.0005 9.61695 14.4396 11.1864 13.4129 12.4385C12.3861 13.6907 10.9569 14.5482 9.36889 14.8648C7.78084 15.1815 6.13211 14.9378 4.70359 14.1752C3.27506 13.4127 2.1551 12.1784 1.53449 10.6828C0.913887 9.18708 0.831027 7.52251 1.30003 5.97259C1.76903 4.42268 2.76089 3.08331 4.10662 2.18265C5.45236 1.28199 7.06873 0.875761 8.68038 1.03316ZM5.52498 5L8.00004 7.47506L10.4751 5L11.1822 5.70711L8.70714 8.18217L11.1818 10.6569L10.4747 11.364L8.00004 8.88927L5.52535 11.364L4.81824 10.6569L7.29293 8.18217L4.81787 5.70711L5.52498 5Z" fill="#A1260D"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 7.5C3 4.46243 5.46243 2 8.5 2C11.5376 2 14 4.46243 14 7.5C14 10.5376 11.5376 13 8.5 13C5.46243 13 3 10.5376 3 7.5ZM2 7.5C2 3.91015 4.91015 1 8.5 1C12.0899 1 15 3.91015 15 7.5C15 11.0899 12.0899 14 8.5 14C4.91015 14 2 11.0899 2 7.5ZM8 4V5H9V4H8ZM8 6L8 10H9L9 6H8Z" fill="#75BEFF"/>
</svg>

Before

Width:  |  Height:  |  Size: 436 B

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 7.5C3 4.46243 5.46243 2 8.5 2C11.5376 2 14 4.46243 14 7.5C14 10.5376 11.5376 13 8.5 13C5.46243 13 3 10.5376 3 7.5ZM2 7.5C2 3.91015 4.91015 1 8.5 1C12.0899 1 15 3.91015 15 7.5C15 11.0899 12.0899 14 8.5 14C4.91015 14 2 11.0899 2 7.5ZM8 4V5H9V4H8ZM8 6L8 10H9L9 6H8Z" fill="#007ACC"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 7.5C3 4.46243 5.46243 2 8.5 2C11.5376 2 14 4.46243 14 7.5C14 10.5376 11.5376 13 8.5 13C5.46243 13 3 10.5376 3 7.5ZM2 7.5C2 3.91015 4.91015 1 8.5 1C12.0899 1 15 3.91015 15 7.5C15 11.0899 12.0899 14 8.5 14C4.91015 14 2 11.0899 2 7.5ZM8 4V5H9V4H8ZM8 6L8 10H9L9 6H8Z" fill="#007ACC"/>
</svg>

Before

Width:  |  Height:  |  Size: 769 B

View File

@@ -1,31 +0,0 @@
<?xml version='1.0' standalone='no' ?>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
<style>
circle {
animation: ball 1.04s steps(8) infinite;
}
circle:nth-child(2) { animation-delay: 0.13s; }
circle:nth-child(3) { animation-delay: 0.26s; }
circle:nth-child(4) { animation-delay: 0.39s; }
circle:nth-child(5) { animation-delay: 0.52s; }
circle:nth-child(6) { animation-delay: 0.65s; }
circle:nth-child(7) { animation-delay: 0.78s; }
circle:nth-child(8) { animation-delay: 0.91s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
}
</style>
<g style="fill:grey;">
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,31 +0,0 @@
<?xml version='1.0' standalone='no' ?>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
<style>
circle {
animation: ball 1.04s steps(8) infinite;
}
circle:nth-child(2) { animation-delay: 0.13s; }
circle:nth-child(3) { animation-delay: 0.26s; }
circle:nth-child(4) { animation-delay: 0.39s; }
circle:nth-child(5) { animation-delay: 0.52s; }
circle:nth-child(6) { animation-delay: 0.65s; }
circle:nth-child(7) { animation-delay: 0.78s; }
circle:nth-child(8) { animation-delay: 0.91s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
}
</style>
<g style="fill:white;">
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,31 +0,0 @@
<?xml version='1.0' standalone='no' ?>
<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='10px' height='10px'>
<style>
circle {
animation: ball 1.04s steps(8) infinite;
}
circle:nth-child(2) { animation-delay: 0.13s; }
circle:nth-child(3) { animation-delay: 0.26s; }
circle:nth-child(4) { animation-delay: 0.39s; }
circle:nth-child(5) { animation-delay: 0.52s; }
circle:nth-child(6) { animation-delay: 0.65s; }
circle:nth-child(7) { animation-delay: 0.78s; }
circle:nth-child(8) { animation-delay: 0.91s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
}
</style>
<g>
<circle cx='5' cy='1' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='2.1716' r='1' style='opacity:0.3;' />
<circle cx='9' cy='5' r='1' style='opacity:0.3;' />
<circle cx='7.8284' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='5' cy='9' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='7.8284' r='1' style='opacity:0.3;' />
<circle cx='1' cy='5' r='1' style='opacity:0.3;' />
<circle cx='2.1716' cy='2.1716' r='1' style='opacity:0.3;' />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.12 13.9725L15 12.5L9.37927 2H7.61924L1.9985 12.5L2.87852 13.9725H14.12ZM2.87852 12.9725L8.49925 2.47249L14.12 12.9725H2.87852ZM7.98952 6H8.98802V10H7.98952V6ZM7.98952 11H8.98802V12H7.98952V11Z" fill="#FFCC00"/>
</svg>

Before

Width:  |  Height:  |  Size: 367 B

View File

@@ -1,4 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.12 13.9725L15 12.5L9.37927 2H7.61924L1.9985 12.5L2.87852 13.9725H14.12ZM2.87852 12.9725L8.49925 2.47249L14.12 12.9725H2.87852ZM7.98952 6H8.98802V10H7.98952V6ZM7.98952 11H8.98802V12H7.98952V11Z" fill="#FFCC00"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.12 13.9725L15 12.5L9.37927 2H7.61924L1.9985 12.5L2.87852 13.9725H14.12ZM2.87852 12.9725L8.49925 2.47249L14.12 12.9725H2.87852ZM7.98952 6H8.98802V10H7.98952V6ZM7.98952 11H8.98802V12H7.98952V11Z" fill="#DDB100"/>
</svg>

Before

Width:  |  Height:  |  Size: 631 B

View File

@@ -5,12 +5,10 @@
.monaco-dropdown {
height: 100%;
display: inline-block;
padding: 0;
}
.monaco-dropdown > .dropdown-label {
display: inline-block;
cursor: pointer;
height: 100%;
}

View File

@@ -396,30 +396,18 @@ export class FindInput extends Widget {
}
public validate(): void {
if (this.inputBox) {
this.inputBox.validate();
}
this.inputBox.validate();
}
public showMessage(message: InputBoxMessage): void {
if (this.inputBox) {
this.inputBox.showMessage(message);
}
this.inputBox.showMessage(message);
}
public clearMessage(): void {
if (this.inputBox) {
this.inputBox.hideMessage();
}
this.inputBox.hideMessage();
}
private clearValidation(): void {
if (this.inputBox) {
this.inputBox.hideMessage();
}
}
public dispose(): void {
super.dispose();
this.inputBox.hideMessage();
}
}

View File

@@ -605,7 +605,7 @@ export type GridNodeDescriptor = { size?: number, groups?: GridNodeDescriptor[]
export type GridDescriptor = { orientation: Orientation, groups?: GridNodeDescriptor[] };
export function sanitizeGridNodeDescriptor(nodeDescriptor: GridNodeDescriptor): void {
if (nodeDescriptor.groups && nodeDescriptor.groups.length === 0) {
if (nodeDescriptor.groups && nodeDescriptor.groups.length <= 1) {
nodeDescriptor.groups = undefined;
}

View File

@@ -30,7 +30,7 @@ export interface IView {
readonly onDidChange: Event<IViewSize | undefined>;
readonly priority?: LayoutPriority;
readonly snap?: boolean;
layout(width: number, height: number, orientation: Orientation): void;
layout(width: number, height: number, top: number, left: number): void;
setVisible?(visible: boolean): void;
}
@@ -69,10 +69,10 @@ export function orthogonal(orientation: Orientation): Orientation {
}
export interface Box {
top: number;
left: number;
width: number;
height: number;
readonly top: number;
readonly left: number;
readonly width: number;
readonly height: number;
}
export interface GridLeafNode {
@@ -117,11 +117,19 @@ export interface IGridViewOptions {
readonly layoutController?: ILayoutController;
}
class BranchNode implements ISplitView, IDisposable {
interface ILayoutContext {
readonly orthogonalSize: number;
readonly absoluteOffset: number;
readonly absoluteOrthogonalOffset: number;
readonly absoluteSize: number;
readonly absoluteOrthogonalSize: number;
}
class BranchNode implements ISplitView<ILayoutContext>, IDisposable {
readonly element: HTMLElement;
readonly children: Node[] = [];
private splitview: SplitView;
private splitview: SplitView<ILayoutContext>;
private _size: number;
get size(): number { return this._size; }
@@ -129,6 +137,9 @@ class BranchNode implements ISplitView, IDisposable {
private _orthogonalSize: number;
get orthogonalSize(): number { return this._orthogonalSize; }
private absoluteOffset: number = 0;
private absoluteOrthogonalOffset: number = 0;
private _styles: IGridViewStyles;
get styles(): IGridViewStyles { return this._styles; }
@@ -140,6 +151,14 @@ class BranchNode implements ISplitView, IDisposable {
return this.orientation === Orientation.HORIZONTAL ? this.orthogonalSize : this.size;
}
get top(): number {
return this.orientation === Orientation.HORIZONTAL ? this.absoluteOffset : this.absoluteOrthogonalOffset;
}
get left(): number {
return this.orientation === Orientation.HORIZONTAL ? this.absoluteOrthogonalOffset : this.absoluteOffset;
}
get minimumSize(): number {
return this.children.length === 0 ? 0 : Math.max(...this.children.map(c => c.minimumOrthogonalSize));
}
@@ -221,7 +240,7 @@ class BranchNode implements ISplitView, IDisposable {
if (!childDescriptors) {
// Normal behavior, we have no children yet, just set up the splitview
this.splitview = new SplitView(this.element, { orientation, styles, proportionalLayout });
this.splitview.layout(size, orthogonalSize);
this.splitview.layout(size, { orthogonalSize, absoluteOffset: 0, absoluteOrthogonalOffset: 0, absoluteSize: size, absoluteOrthogonalSize: orthogonalSize });
} else {
// Reconstruction behavior, we want to reconstruct a splitview
const descriptor = {
@@ -268,20 +287,32 @@ class BranchNode implements ISplitView, IDisposable {
}
}
layout(size: number, orthogonalSize: number | undefined): void {
layout(size: number, offset: number, ctx: ILayoutContext | undefined): void {
if (!this.layoutController.isLayoutEnabled) {
return;
}
if (typeof orthogonalSize !== 'number') {
if (typeof ctx === 'undefined') {
throw new Error('Invalid state');
}
// branch nodes should flip the normal/orthogonal directions
this._size = orthogonalSize;
this._size = ctx.orthogonalSize;
this._orthogonalSize = size;
this.absoluteOffset = ctx.absoluteOffset + offset;
this.absoluteOrthogonalOffset = ctx.absoluteOrthogonalOffset;
this.splitview.layout(orthogonalSize, size);
this.splitview.layout(ctx.orthogonalSize, {
orthogonalSize: size,
absoluteOffset: this.absoluteOrthogonalOffset,
absoluteOrthogonalOffset: this.absoluteOffset,
absoluteSize: ctx.absoluteOrthogonalSize,
absoluteOrthogonalSize: ctx.absoluteSize
});
// Disable snapping on views which sit on the edges of the grid
this.splitview.startSnappingEnabled = this.absoluteOrthogonalOffset > 0;
this.splitview.endSnappingEnabled = this.absoluteOrthogonalOffset + ctx.orthogonalSize < ctx.absoluteOrthogonalSize;
}
setVisible(visible: boolean): void {
@@ -511,7 +542,7 @@ class BranchNode implements ISplitView, IDisposable {
}
}
class LeafNode implements ISplitView, IDisposable {
class LeafNode implements ISplitView<ILayoutContext>, IDisposable {
private _size: number = 0;
get size(): number { return this._size; }
@@ -519,6 +550,9 @@ class LeafNode implements ISplitView, IDisposable {
private _orthogonalSize: number;
get orthogonalSize(): number { return this._orthogonalSize; }
private absoluteOffset: number = 0;
private absoluteOrthogonalOffset: number = 0;
readonly onDidSashReset: Event<number[]> = Event.None;
private _onDidLinkedWidthNodeChange = new Relay<number | undefined>();
@@ -565,6 +599,14 @@ class LeafNode implements ISplitView, IDisposable {
return this.orientation === Orientation.HORIZONTAL ? this.size : this.orthogonalSize;
}
get top(): number {
return this.orientation === Orientation.HORIZONTAL ? this.absoluteOffset : this.absoluteOrthogonalOffset;
}
get left(): number {
return this.orientation === Orientation.HORIZONTAL ? this.absoluteOrthogonalOffset : this.absoluteOffset;
}
get element(): HTMLElement {
return this.view.element;
}
@@ -617,18 +659,20 @@ class LeafNode implements ISplitView, IDisposable {
// noop
}
layout(size: number, orthogonalSize: number | undefined): void {
layout(size: number, offset: number, ctx: ILayoutContext | undefined): void {
if (!this.layoutController.isLayoutEnabled) {
return;
}
if (typeof orthogonalSize !== 'number') {
if (typeof ctx === 'undefined') {
throw new Error('Invalid state');
}
this._size = size;
this._orthogonalSize = orthogonalSize;
this.view.layout(this.width, this.height, orthogonal(this.orientation));
this._orthogonalSize = ctx.orthogonalSize;
this.absoluteOffset = ctx.absoluteOffset + offset;
this.absoluteOrthogonalOffset = ctx.absoluteOrthogonalOffset;
this.view.layout(this.width, this.height, this.top, this.left);
}
setVisible(visible: boolean): void {
@@ -715,7 +759,7 @@ export class GridView implements IDisposable {
const { size, orthogonalSize } = this._root;
this.root = flipNode(this._root, orthogonalSize, size);
this.root.layout(size, orthogonalSize);
this.root.layout(size, 0, { orthogonalSize, absoluteOffset: 0, absoluteOrthogonalOffset: 0, absoluteSize: size, absoluteOrthogonalSize: orthogonalSize });
}
get width(): number { return this.root.width; }
@@ -771,7 +815,7 @@ export class GridView implements IDisposable {
this.firstLayoutController.isLayoutEnabled = true;
const [size, orthogonalSize] = this.root.orientation === Orientation.HORIZONTAL ? [height, width] : [width, height];
this.root.layout(size, orthogonalSize);
this.root.layout(size, 0, { orthogonalSize, absoluteOffset: 0, absoluteOrthogonalOffset: 0, absoluteSize: size, absoluteOrthogonalSize: orthogonalSize });
}
addView(view: IView, size: number | Sizing, location: number[]): void {
@@ -1032,7 +1076,7 @@ export class GridView implements IDisposable {
getView(location?: number[]): GridNode;
getView(location?: number[]): GridNode {
const node = location ? this.getNode(location)[1] : this._root;
return this._getViews(node, this.orientation, { top: 0, left: 0, width: this.width, height: this.height });
return this._getViews(node, this.orientation);
}
static deserialize<T extends ISerializableView>(json: ISerializedGridView, deserializer: IViewDeserializer<T>, options: IGridViewOptions = {}): GridView {
@@ -1076,24 +1120,20 @@ export class GridView implements IDisposable {
return result;
}
private _getViews(node: Node, orientation: Orientation, box: Box, cachedVisibleSize?: number): GridNode {
private _getViews(node: Node, orientation: Orientation, cachedVisibleSize?: number): GridNode {
const box = { top: node.top, left: node.left, width: node.width, height: node.height };
if (node instanceof LeafNode) {
return { view: node.view, box, cachedVisibleSize };
}
const children: GridNode[] = [];
let i = 0;
let offset = 0;
for (const child of node.children) {
const childOrientation = orthogonal(orientation);
const childBox: Box = orientation === Orientation.HORIZONTAL
? { top: box.top, left: box.left + offset, width: child.width, height: box.height }
: { top: box.top + offset, left: box.left, width: box.width, height: child.height };
const cachedVisibleSize = node.getChildCachedVisibleSize(i++);
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i];
const cachedVisibleSize = node.getChildCachedVisibleSize(i);
children.push(this._getViews(child, childOrientation, childBox, cachedVisibleSize));
offset += orientation === Orientation.HORIZONTAL ? child.width : child.height;
children.push(this._getViews(child, orthogonal(orientation), cachedVisibleSize));
}
return { children, box };

View File

@@ -84,7 +84,11 @@ export class HighlightedLabel {
}
this.domNode.innerHTML = htmlContent;
this.domNode.title = this.title;
if (this.title) {
this.domNode.title = this.title;
} else {
this.domNode.removeAttribute('title');
}
this.didEverRender = true;
}

View File

@@ -8,6 +8,7 @@ import * as dom from 'vs/base/browser/dom';
import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel';
import { IMatch } from 'vs/base/common/filters';
import { Disposable } from 'vs/base/common/lifecycle';
import { Range } from 'vs/base/common/range';
export interface IIconLabelCreationOptions {
supportHighlights?: boolean;
@@ -24,6 +25,8 @@ export interface IIconLabelValueOptions {
matches?: IMatch[];
labelEscapeNewLines?: boolean;
descriptionMatches?: IMatch[];
readonly separator?: string;
readonly domId?: string;
}
class FastLabelNode {
@@ -86,9 +89,10 @@ class FastLabelNode {
}
export class IconLabel extends Disposable {
private domNode: FastLabelNode;
private labelDescriptionContainer: FastLabelNode;
private labelNode: FastLabelNode | HighlightedLabel;
private descriptionContainer: FastLabelNode;
private nameNode: Label | LabelWithHighlights;
private descriptionNode: FastLabelNode | HighlightedLabel | undefined;
private descriptionNodeFactory: () => FastLabelNode | HighlightedLabel;
@@ -97,18 +101,21 @@ export class IconLabel extends Disposable {
this.domNode = this._register(new FastLabelNode(dom.append(container, dom.$('.monaco-icon-label'))));
this.labelDescriptionContainer = this._register(new FastLabelNode(dom.append(this.domNode.element, dom.$('.monaco-icon-label-description-container'))));
const labelContainer = dom.append(this.domNode.element, dom.$('.monaco-icon-label-container'));
const nameContainer = dom.append(labelContainer, dom.$('span.monaco-icon-name-container'));
this.descriptionContainer = this._register(new FastLabelNode(dom.append(labelContainer, dom.$('span.monaco-icon-description-container'))));
if (options?.supportHighlights) {
this.labelNode = new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name')), !!options.supportCodicons);
this.nameNode = new LabelWithHighlights(nameContainer, !!options.supportCodicons);
} else {
this.labelNode = this._register(new FastLabelNode(dom.append(this.labelDescriptionContainer.element, dom.$('a.label-name'))));
this.nameNode = new Label(nameContainer);
}
if (options?.supportDescriptionHighlights) {
this.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description')), !!options.supportCodicons);
this.descriptionNodeFactory = () => new HighlightedLabel(dom.append(this.descriptionContainer.element, dom.$('span.label-description')), !!options.supportCodicons);
} else {
this.descriptionNodeFactory = () => this._register(new FastLabelNode(dom.append(this.labelDescriptionContainer.element, dom.$('span.label-description'))));
this.descriptionNodeFactory = () => this._register(new FastLabelNode(dom.append(this.descriptionContainer.element, dom.$('span.label-description'))));
}
}
@@ -116,7 +123,7 @@ export class IconLabel extends Disposable {
return this.domNode.element;
}
setLabel(label?: string, description?: string, options?: IIconLabelValueOptions): void {
setLabel(label: string | string[], description?: string, options?: IIconLabelValueOptions): void {
const classes = ['monaco-icon-label'];
if (options) {
if (options.extraClasses) {
@@ -131,11 +138,7 @@ export class IconLabel extends Disposable {
this.domNode.className = classes.join(' ');
this.domNode.title = options?.title || '';
if (this.labelNode instanceof HighlightedLabel) {
this.labelNode.set(label || '', options?.matches, options?.title, options?.labelEscapeNewLines);
} else {
this.labelNode.textContent = label || '';
}
this.nameNode.setLabel(label, options);
if (description || this.descriptionNode) {
if (!this.descriptionNode) {
@@ -157,3 +160,112 @@ export class IconLabel extends Disposable {
}
}
}
class Label {
private label: string | string[] | undefined = undefined;
private singleLabel: HTMLElement | undefined = undefined;
constructor(private container: HTMLElement) { }
setLabel(label: string | string[], options?: IIconLabelValueOptions): void {
if (this.label === label) {
return;
}
this.label = label;
if (typeof label === 'string') {
if (!this.singleLabel) {
this.container.innerHTML = '';
dom.removeClass(this.container, 'multiple');
this.singleLabel = dom.append(this.container, dom.$('a.label-name', { id: options?.domId }));
}
this.singleLabel.textContent = label;
} else {
this.container.innerHTML = '';
dom.addClass(this.container, 'multiple');
this.singleLabel = undefined;
for (let i = 0; i < label.length; i++) {
const l = label[i];
const id = options?.domId && `${options?.domId}_${i}`;
dom.append(this.container, dom.$('a.label-name', { id, 'data-icon-label-count': label.length, 'data-icon-label-index': i }, l));
if (i < label.length - 1) {
dom.append(this.container, dom.$('span.label-separator', undefined, options?.separator || '/'));
}
}
}
}
}
function splitMatches(labels: string[], separator: string, matches: IMatch[] | undefined): IMatch[][] | undefined {
if (!matches) {
return undefined;
}
let labelStart = 0;
return labels.map(label => {
const labelRange = { start: labelStart, end: labelStart + label.length };
const result = matches
.map(match => Range.intersect(labelRange, match))
.filter(range => !Range.isEmpty(range))
.map(({ start, end }) => ({ start: start - labelStart, end: end - labelStart }));
labelStart = labelRange.end + separator.length;
return result;
});
}
class LabelWithHighlights {
private label: string | string[] | undefined = undefined;
private singleLabel: HighlightedLabel | undefined = undefined;
constructor(private container: HTMLElement, private supportCodicons: boolean) { }
setLabel(label: string | string[], options?: IIconLabelValueOptions): void {
if (this.label === label) {
return;
}
this.label = label;
if (typeof label === 'string') {
if (!this.singleLabel) {
this.container.innerHTML = '';
dom.removeClass(this.container, 'multiple');
this.singleLabel = new HighlightedLabel(dom.append(this.container, dom.$('a.label-name', { id: options?.domId })), this.supportCodicons);
}
this.singleLabel.set(label, options?.matches, options?.title, options?.labelEscapeNewLines);
} else {
this.container.innerHTML = '';
dom.addClass(this.container, 'multiple');
this.singleLabel = undefined;
const separator = options?.separator || '/';
const matches = splitMatches(label, separator, options?.matches);
for (let i = 0; i < label.length; i++) {
const l = label[i];
const m = matches ? matches[i] : undefined;
const id = options?.domId && `${options?.domId}_${i}`;
const name = dom.$('a.label-name', { id, 'data-icon-label-count': label.length, 'data-icon-label-index': i });
const highlightedLabel = new HighlightedLabel(dom.append(this.container, name), this.supportCodicons);
highlightedLabel.set(l, m, options?.title, options?.labelEscapeNewLines);
if (i < label.length - 1) {
dom.append(name, dom.$('span.label-separator', undefined, separator));
}
}
}
}
}

View File

@@ -25,30 +25,38 @@
/* fonts icons */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: top;
flex-shrink: 0; /* fix for https://github.com/Microsoft/vscode/issues/13787 */
}
.monaco-icon-label > .monaco-icon-label-description-container {
overflow: hidden; /* this causes the label/description to shrink first if decorations are enabled */
.monaco-icon-label > .monaco-icon-label-container {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
flex: 1;
}
.monaco-icon-label > .monaco-icon-label-description-container > .label-name {
.monaco-icon-label > .monaco-icon-label-container > .monaco-icon-name-container > .label-name {
color: inherit;
white-space: pre; /* enable to show labels that include multiple whitespaces */
}
.monaco-icon-label > .monaco-icon-label-description-container > .label-description {
.monaco-icon-label > .monaco-icon-label-container > .monaco-icon-name-container > .label-name > .label-separator {
margin: 0 2px;
opacity: 0.5;
}
.monaco-icon-label > .monaco-icon-label-container > .monaco-icon-description-container > .label-description {
opacity: .7;
margin-left: 0.5em;
font-size: 0.9em;
white-space: pre; /* enable to show labels that include multiple whitespaces */
}
.monaco-icon-label.italic > .monaco-icon-label-description-container > .label-name,
.monaco-icon-label.italic > .monaco-icon-label-description-container > .label-description {
.monaco-icon-label.italic > .monaco-icon-label-container > .monaco-icon-name-container > .label-name,
.monaco-icon-label.italic > .monaco-icon-description-container > .label-description {
font-style: italic;
}
@@ -57,7 +65,6 @@
font-size: 90%;
font-weight: 600;
padding: 0 16px 0 5px;
margin-left: auto;
text-align: center;
}

View File

@@ -7,12 +7,7 @@
position: relative;
display: block;
padding: 0;
-webkit-box-sizing: border-box;
-o-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
line-height: auto !important;
box-sizing: border-box;
/* Customizable */
font-size: inherit;
@@ -37,11 +32,7 @@
.monaco-inputbox > .wrapper > .input {
display: inline-block;
-webkit-box-sizing: border-box;
-o-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
box-sizing: border-box;
width: 100%;
height: 100%;
line-height: inherit;
@@ -58,31 +49,26 @@
.monaco-inputbox > .wrapper > textarea.input {
display: block;
-ms-overflow-style: none; /* IE 10+ */
overflow: -moz-scrollbars-none; /* Firefox */
scrollbar-width: none; /* Firefox ^64 */
-ms-overflow-style: none; /* IE 10+: hide scrollbars */
scrollbar-width: none; /* Firefox: hide scrollbars */
outline: none;
}
.monaco-inputbox > .wrapper > textarea.input::-webkit-scrollbar {
display: none; /* Chrome + Safari: hide scrollbar */
}
.monaco-inputbox > .wrapper > textarea.input.empty {
white-space: nowrap;
}
.monaco-inputbox > .wrapper > textarea.input::-webkit-scrollbar {
display: none;
}
.monaco-inputbox > .wrapper > .mirror {
position: absolute;
display: inline-block;
width: 100%;
top: 0;
left: 0;
-webkit-box-sizing: border-box;
-o-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
box-sizing: border-box;
white-space: pre-wrap;
visibility: hidden;
word-wrap: break-word;
@@ -99,11 +85,7 @@
overflow: hidden;
text-align: left;
width: 100%;
-webkit-box-sizing: border-box;
-o-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
box-sizing: border-box;
padding: 0.4em;
font-size: 12px;
line-height: 17px;

View File

@@ -183,7 +183,7 @@ export class InputBox extends Widget {
this.maxHeight = typeof this.options.flexibleMaxHeight === 'number' ? this.options.flexibleMaxHeight : Number.POSITIVE_INFINITY;
this.mirror = dom.append(wrapper, $('div.mirror'));
this.mirror.innerHTML = '&nbsp;';
this.mirror.innerHTML = '&#160;';
this.scrollableElement = new ScrollableElement(this.element, { vertical: ScrollbarVisibility.Auto });
@@ -242,6 +242,8 @@ export class InputBox extends Widget {
});
}
this.ignoreGesture(this.input);
setTimeout(() => this.updateMirror(), 0);
// Support actions
@@ -327,6 +329,7 @@ export class InputBox extends Widget {
}
public disable(): void {
this.blur();
this.input.disabled = true;
this._hideMessage();
}
@@ -561,7 +564,7 @@ export class InputBox extends Widget {
if (mirrorTextContent) {
this.mirror.textContent = value + suffix;
} else {
this.mirror.innerHTML = '&nbsp;';
this.mirror.innerHTML = '&#160;';
}
this.layout();

View File

@@ -11,12 +11,9 @@
}
.monaco-list.mouse-support {
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: -moz-none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.monaco-list > .monaco-scrollable-element {
@@ -36,10 +33,7 @@
.monaco-list-row {
position: absolute;
-moz-box-sizing: border-box;
-o-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
box-sizing: border-box;
overflow: hidden;
width: 100%;
}
@@ -59,6 +53,10 @@
outline: 0 !important;
}
.monaco-list:focus .monaco-list-row.selected .codicon {
color: inherit;
}
/* Dnd */
.monaco-drag-image {
display: inline-block;
@@ -115,54 +113,28 @@
}
.monaco-list-type-filter > .controls > * {
border: none;
box-sizing: border-box;
-webkit-appearance: none;
-moz-appearance: none;
background: none;
width: 16px;
height: 16px;
margin: 0 0 0 2px;
flex-shrink: 0;
margin: 0;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.monaco-list-type-filter > .controls > .filter:checked::before {
content: "\eb83" !important; /* codicon-list-filter */
}
.monaco-list-type-filter > .controls > .filter {
-webkit-appearance: none;
width: 16px;
height: 16px;
background: url("media/no-filter-light.svg");
background-position: 50% 50%;
cursor: pointer;
}
.monaco-list-type-filter > .controls > .filter:checked {
background-image: url("media/filter-light.svg");
}
.vs-dark .monaco-list-type-filter > .controls > .filter {
background-image: url("media/no-filter-dark.svg");
}
.vs-dark .monaco-list-type-filter > .controls > .filter:checked {
background-image: url("media/filter-dark.svg");
}
.hc-black .monaco-list-type-filter > .controls > .filter {
background-image: url("media/no-filter-hc.svg");
}
.hc-black .monaco-list-type-filter > .controls > .filter:checked {
background-image: url("media/filter-hc.svg");
}
.monaco-list-type-filter > .controls > .clear {
border: none;
background: url("media/close-light.svg");
cursor: pointer;
}
.vs-dark .monaco-list-type-filter > .controls > .clear {
background-image: url("media/close-dark.svg");
}
.hc-black .monaco-list-type-filter > .controls > .clear {
background-image: url("media/close-hc.svg");
margin-left: 4px;
}
.monaco-list-type-filter-message {
@@ -191,4 +163,4 @@
.monaco-list-type-filter.dragging {
cursor: grabbing;
}
}

View File

@@ -103,10 +103,11 @@ export const ListDragOverReactions = {
export interface IListDragAndDrop<T> {
getDragURI(element: T): string | null;
getDragLabel?(elements: T[]): string | undefined;
getDragLabel?(elements: T[], originalEvent: DragEvent): string | undefined;
onDragStart?(data: IDragAndDropData, originalEvent: DragEvent): void;
onDragOver(data: IDragAndDropData, targetElement: T | undefined, targetIndex: number | undefined, originalEvent: DragEvent): boolean | IListDragOverReaction;
drop(data: IDragAndDropData, targetElement: T | undefined, targetIndex: number | undefined, originalEvent: DragEvent): void;
onDragEnd?(originalEvent: DragEvent): void;
}
export class ListError extends Error {

View File

@@ -20,6 +20,7 @@ import { Range, IRange } from 'vs/base/common/range';
import { equals, distinct } from 'vs/base/common/arrays';
import { DataTransfers, StaticDND, IDragAndDropData } from 'vs/base/browser/dnd';
import { disposableTimeout, Delayer } from 'vs/base/common/async';
import { isFirefox } from 'vs/base/browser/browser';
interface IItem<T> {
readonly id: string;
@@ -73,9 +74,10 @@ const DefaultOptions = {
horizontalScrolling: false
};
export class ElementsDragAndDropData<T> implements IDragAndDropData {
export class ElementsDragAndDropData<T, TContext = void> implements IDragAndDropData {
readonly elements: T[];
context: TContext | undefined;
constructor(elements: T[]) {
this.elements = elements;
@@ -83,7 +85,7 @@ export class ElementsDragAndDropData<T> implements IDragAndDropData {
update(): void { }
getData(): any {
getData(): T[] {
return this.elements;
}
}
@@ -98,7 +100,7 @@ export class ExternalElementsDragAndDropData<T> implements IDragAndDropData {
update(): void { }
getData(): any {
getData(): T[] {
return this.elements;
}
}
@@ -233,7 +235,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.rowsContainer = document.createElement('div');
this.rowsContainer.className = 'monaco-list-rows';
this.rowsContainer.style.willChange = 'transform';
this.rowsContainer.style.transform = 'translate3d(0px, 0px, 0px)';
this.disposables.add(Gesture.addTarget(this.rowsContainer));
this.scrollableElement = this.disposables.add(new ScrollableElement(this.rowsContainer, {
@@ -595,7 +597,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
return;
}
item.row.domNode.style.width = 'fit-content';
item.row.domNode.style.width = isFirefox ? '-moz-fit-content' : 'fit-content';
item.width = DOM.getContentWidth(item.row.domNode);
const style = window.getComputedStyle(item.row.domNode);
@@ -765,7 +767,7 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
let label: string | undefined;
if (this.dnd.getDragLabel) {
label = this.dnd.getDragLabel(elements);
label = this.dnd.getDragLabel(elements, event);
}
if (typeof label === 'undefined') {
@@ -845,10 +847,6 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
feedback = distinct(feedback).filter(i => i >= -1 && i < this.length).sort();
feedback = feedback[0] === -1 ? [-1] : feedback;
if (feedback.length === 0) {
throw new Error('Invalid empty feedback list');
}
if (equalsDragFeedback(this.currentDragFeedback, feedback)) {
return true;
}
@@ -858,7 +856,11 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
if (feedback[0] === -1) { // entire list feedback
DOM.addClass(this.domNode, 'drop-target');
this.currentDragFeedbackDisposable = toDisposable(() => DOM.removeClass(this.domNode, 'drop-target'));
DOM.addClass(this.rowsContainer, 'drop-target');
this.currentDragFeedbackDisposable = toDisposable(() => {
DOM.removeClass(this.domNode, 'drop-target');
DOM.removeClass(this.rowsContainer, 'drop-target');
});
} else {
for (const index of feedback) {
const item = this.items[index]!;
@@ -909,12 +911,16 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
this.dnd.drop(dragData, event.element, event.index, event.browserEvent);
}
private onDragEnd(): void {
private onDragEnd(event: DragEvent): void {
this.canDrop = false;
this.teardownDragAndDropScrollTopAnimation();
this.clearDragOverFeedback();
this.currentDragData = undefined;
StaticDND.CurrentDragAndDropData = undefined;
if (this.dnd.onDragEnd) {
this.dnd.onDragEnd(event);
}
}
private clearDragOverFeedback(): void {

View File

@@ -702,16 +702,27 @@ export interface IAccessibilityProvider<T> {
* https://www.w3.org/TR/wai-aria/#aria-level
*/
getAriaLevel?(element: T): number | undefined;
onDidChangeActiveDescendant?: Event<void>;
getActiveDescendantId?(element: T): string | undefined;
}
export class DefaultStyleController implements IStyleController {
constructor(private styleElement: HTMLStyleElement, private selectorSuffix?: string) { }
constructor(private styleElement: HTMLStyleElement, private selectorSuffix: string) { }
style(styles: IListStyles): void {
const suffix = this.selectorSuffix ? `.${this.selectorSuffix}` : '';
const suffix = this.selectorSuffix && `.${this.selectorSuffix}`;
const content: string[] = [];
if (styles.listBackground) {
if (styles.listBackground.isOpaque()) {
content.push(`.monaco-list${suffix} .monaco-list-rows { background: ${styles.listBackground}; }`);
} else if (!platform.isMacintosh) { // subpixel AA doesn't exist in macOS
console.warn(`List with id '${this.selectorSuffix}' was styled with a non-opaque background color. This will break sub-pixel antialiasing.`);
}
}
if (styles.listFocusBackground) {
content.push(`.monaco-list${suffix}:focus .monaco-list-row.focused { background-color: ${styles.listFocusBackground}; }`);
content.push(`.monaco-list${suffix}:focus .monaco-list-row.focused:hover { background-color: ${styles.listFocusBackground}; }`); // overwrite :hover style in this case!
@@ -788,6 +799,7 @@ export class DefaultStyleController implements IStyleController {
if (styles.listDropBackground) {
content.push(`
.monaco-list${suffix}.drop-target,
.monaco-list${suffix} .monaco-list-rows.drop-target,
.monaco-list${suffix} .monaco-list-row.drop-target { background-color: ${styles.listDropBackground} !important; color: inherit !important; }
`);
}
@@ -815,7 +827,7 @@ export class DefaultStyleController implements IStyleController {
}
}
export interface IListOptions<T> extends IListStyles {
export interface IListOptions<T> {
readonly identityProvider?: IIdentityProvider<T>;
readonly dnd?: IListDragAndDrop<T>;
readonly enableKeyboardNavigation?: boolean;
@@ -828,7 +840,7 @@ export interface IListOptions<T> extends IListStyles {
readonly multipleSelectionSupport?: boolean;
readonly multipleSelectionController?: IMultipleSelectionController<T>;
readonly openController?: IOpenController;
readonly styleController?: IStyleController;
readonly styleController?: (suffix: string) => IStyleController;
readonly accessibilityProvider?: IAccessibilityProvider<T>;
// list view options
@@ -842,6 +854,7 @@ export interface IListOptions<T> extends IListStyles {
}
export interface IListStyles {
listBackground?: Color;
listFocusBackground?: Color;
listFocusForeground?: Color;
listActiveSelectionBackground?: Color;
@@ -1062,9 +1075,9 @@ class ListViewDragAndDrop<T> implements IListViewDragAndDrop<T> {
return this.dnd.getDragURI(element);
}
getDragLabel?(elements: T[]): string | undefined {
getDragLabel?(elements: T[], originalEvent: DragEvent): string | undefined {
if (this.dnd.getDragLabel) {
return this.dnd.getDragLabel(elements);
return this.dnd.getDragLabel(elements, originalEvent);
}
return undefined;
@@ -1080,6 +1093,12 @@ class ListViewDragAndDrop<T> implements IListViewDragAndDrop<T> {
return this.dnd.onDragOver(data, targetElement, targetIndex, originalEvent);
}
onDragEnd(originalEvent: DragEvent): void {
if (this.dnd.onDragEnd) {
this.dnd.onDragEnd(originalEvent);
}
}
drop(data: IDragAndDropData, targetElement: T, targetIndex: number, originalEvent: DragEvent): void {
this.dnd.drop(data, targetElement, targetIndex, originalEvent);
}
@@ -1097,9 +1116,9 @@ export class List<T> implements ISpliceable<T>, IDisposable {
private eventBufferer = new EventBufferer();
private view: ListView<T>;
private spliceable: ISpliceable<T>;
private styleElement: HTMLStyleElement;
private styleController: IStyleController;
private typeLabelController?: TypeLabelController<T>;
private accessibilityProvider?: IAccessibilityProvider<T>;
protected readonly disposables = new DisposableStore();
@@ -1185,8 +1204,14 @@ export class List<T> implements ISpliceable<T>, IDisposable {
const baseRenderers: IListRenderer<T, ITraitTemplateData>[] = [this.focus.renderer, this.selection.renderer];
if (_options.accessibilityProvider) {
baseRenderers.push(new AccessibiltyRenderer<T>(_options.accessibilityProvider));
this.accessibilityProvider = _options.accessibilityProvider;
if (this.accessibilityProvider) {
baseRenderers.push(new AccessibiltyRenderer<T>(this.accessibilityProvider));
if (this.accessibilityProvider.onDidChangeActiveDescendant) {
this.accessibilityProvider.onDidChangeActiveDescendant(this.onDidChangeActiveDescendant, this, this.disposables);
}
}
renderers = renderers.map(r => new PipelineRenderer(r.templateId, [...baseRenderers, r]));
@@ -1198,11 +1223,18 @@ export class List<T> implements ISpliceable<T>, IDisposable {
this.view = new ListView(container, virtualDelegate, renderers, viewOptions);
this.updateAriaRole();
if (typeof _options.ariaRole !== 'string') {
this.view.domNode.setAttribute('role', ListAriaRootRole.TREE);
} else {
this.view.domNode.setAttribute('role', _options.ariaRole);
}
this.styleElement = DOM.createStyleSheet(this.view.domNode);
this.styleController = _options.styleController || new DefaultStyleController(this.styleElement, this.view.domId);
if (_options.styleController) {
this.styleController = _options.styleController(this.view.domId);
} else {
const styleElement = DOM.createStyleSheet(this.view.domNode);
this.styleController = new DefaultStyleController(styleElement, this.view.domId);
}
this.spliceable = new CombinedSpliceable([
new TraitSpliceable(this.focus, this.view, _options.identityProvider),
@@ -1239,8 +1271,6 @@ export class List<T> implements ISpliceable<T>, IDisposable {
if (_options.ariaLabel) {
this.view.domNode.setAttribute('aria-label', localize('aria list', "{0}. Use the navigation keys to navigate.", _options.ariaLabel));
}
this.style(_options);
}
protected createMouseController(options: IListOptions<T>): MouseController<T> {
@@ -1603,23 +1633,23 @@ export class List<T> implements ISpliceable<T>, IDisposable {
private _onFocusChange(): void {
const focus = this.focus.get();
if (focus.length > 0) {
this.view.domNode.setAttribute('aria-activedescendant', this.view.getElementDomId(focus[0]));
} else {
this.view.domNode.removeAttribute('aria-activedescendant');
}
this.updateAriaRole();
DOM.toggleClass(this.view.domNode, 'element-focused', focus.length > 0);
this.onDidChangeActiveDescendant();
}
private updateAriaRole(): void {
if (typeof this.options.ariaRole !== 'string') {
this.view.domNode.setAttribute('role', ListAriaRootRole.TREE);
private onDidChangeActiveDescendant(): void {
const focus = this.focus.get();
if (focus.length > 0) {
let id: string | undefined;
if (this.accessibilityProvider?.getActiveDescendantId) {
id = this.accessibilityProvider.getActiveDescendantId(this.view.element(focus[0]));
}
this.view.domNode.setAttribute('aria-activedescendant', id || this.view.getElementDomId(focus[0]));
} else {
this.view.domNode.setAttribute('role', this.options.ariaRole);
this.view.domNode.removeAttribute('aria-activedescendant');
}
}

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00001 8.70714L11.6465 12.3536L12.3536 11.6465L8.70711 8.00004L12.3536 4.35359L11.6465 3.64648L8.00001 7.29293L4.35356 3.64648L3.64645 4.35359L7.2929 8.00004L3.64645 11.6465L4.35356 12.3536L8.00001 8.70714Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 379 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00001 8.70714L11.6465 12.3536L12.3536 11.6465L8.70711 8.00004L12.3536 4.35359L11.6465 3.64648L8.00001 7.29293L4.35356 3.64648L3.64645 4.35359L7.2929 8.00004L3.64645 11.6465L4.35356 12.3536L8.00001 8.70714Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 379 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.00001 8.70714L11.6465 12.3536L12.3536 11.6465L8.70711 8.00004L12.3536 4.35359L11.6465 3.64648L8.00001 7.29293L4.35356 3.64648L3.64645 4.35359L7.2929 8.00004L3.64645 11.6465L4.35356 12.3536L8.00001 8.70714Z" fill="#424242"/>
</svg>

Before

Width:  |  Height:  |  Size: 379 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 12V11H10V12H6ZM4 7H12V8H4V7ZM14 3V4H2V3H14Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 177 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 12V11H10V12H6ZM4 7H12V8H4V7ZM14 3V4H2V3H14Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 175 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 12V11H10V12H6ZM4 7H12V8H4V7ZM14 3V4H2V3H14Z" fill="#424242"/>
</svg>

Before

Width:  |  Height:  |  Size: 177 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 12L1 11H10V12H1ZM1 7H15V8H1L1 7ZM12 3V4H1L1 3H12Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 183 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 12L1 11H10V12H1ZM1 7H15V8H1L1 7ZM12 3V4H1L1 3H12Z" fill="#C5C5C5"/>
</svg>

Before

Width:  |  Height:  |  Size: 183 B

View File

@@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 12L1 11H10V12H1ZM1 7H15V8H1L1 7ZM12 3V4H1L1 3H12Z" fill="#424242"/>
</svg>

Before

Width:  |  Height:  |  Size: 183 B

View File

@@ -15,7 +15,6 @@
.monaco-menu .monaco-action-bar.vertical .action-item {
padding: 0;
transform: none;
display: -ms-flexbox;
display: flex;
}
@@ -24,9 +23,7 @@
}
.monaco-menu .monaco-action-bar.vertical .action-menu-item {
-ms-flex: 1 1 auto;
flex: 1 1 auto;
display: -ms-flexbox;
display: flex;
height: 2em;
align-items: center;
@@ -34,7 +31,6 @@
}
.monaco-menu .monaco-action-bar.vertical .action-label {
-ms-flex: 1 1 auto;
flex: 1 1 auto;
text-decoration: none;
padding: 0 1em;
@@ -46,7 +42,6 @@
.monaco-menu .monaco-action-bar.vertical .keybinding,
.monaco-menu .monaco-action-bar.vertical .submenu-indicator {
display: inline-block;
-ms-flex: 2 1 auto;
flex: 2 1 auto;
padding: 0 1em;
text-align: right;
@@ -56,8 +51,8 @@
.monaco-menu .monaco-action-bar.vertical .submenu-indicator {
height: 100%;
-webkit-mask: url('submenu.svg') no-repeat 90% 50%/13px 13px;
mask: url('submenu.svg') no-repeat 90% 50%/13px 13px;
-webkit-mask: url('submenu.svg') no-repeat 90% 50%/13px 13px;
}
.monaco-menu .monaco-action-bar.vertical .action-item.disabled .keybinding,
@@ -67,11 +62,7 @@
.monaco-menu .monaco-action-bar.vertical .action-label:not(.separator) {
display: inline-block;
-webkit-box-sizing: border-box;
-o-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
box-sizing: border-box;
margin: 0;
}
@@ -80,7 +71,6 @@
overflow: visible;
}
.monaco-menu .monaco-action-bar.vertical .action-item .monaco-submenu {
position: absolute;
}
@@ -104,8 +94,8 @@
.monaco-menu .monaco-action-bar.vertical .menu-item-check {
position: absolute;
visibility: hidden;
-webkit-mask: url('check.svg') no-repeat 50% 56%/15px 15px;
mask: url('check.svg') no-repeat 50% 56%/15px 15px;
-webkit-mask: url('check.svg') no-repeat 50% 56%/15px 15px;
width: 1em;
height: 100%;
}
@@ -119,10 +109,6 @@
.context-view.monaco-menu-container {
outline: 0;
border: none;
-webkit-animation: fadeIn 0.083s linear;
-o-animation: fadeIn 0.083s linear;
-moz-animation: fadeIn 0.083s linear;
-ms-animation: fadeIn 0.083s linear;
animation: fadeIn 0.083s linear;
}
@@ -173,6 +159,10 @@
outline: 0;
}
.menubar.compact {
flex-shrink: 0;
}
.menubar.compact > .menubar-menu-button {
width: 100%;
height: 100%;
@@ -204,22 +194,24 @@
}
.menubar.compact .toolbar-toggle-more {
position: absolute;
left: 0px;
top: 0px;
background-position: center;
background-repeat: no-repeat;
background-size: 16px;
cursor: pointer;
width: 100%;
height: 100%;
}
.menubar .toolbar-toggle-more {
display: inline-block;
padding: 0;
-webkit-mask: url('ellipsis.svg') no-repeat 50% 55%/14px 14px;
mask: url('ellipsis.svg') no-repeat 50% 55%/14px 14px;
-webkit-mask: url('ellipsis.svg') no-repeat 50% 55%/14px 14px;
}
.menubar.compact .toolbar-toggle-more {
-webkit-mask: url('menu.svg') no-repeat 50% 55%/16px 16px;
mask: url('menu.svg') no-repeat 50% 55%/16px 16px;
-webkit-mask: url('menu.svg') no-repeat 50% 55%/16px 16px;
}

View File

@@ -6,7 +6,7 @@
import 'vs/css!./menu';
import * as nls from 'vs/nls';
import * as strings from 'vs/base/common/strings';
import { IActionRunner, IAction, Action } from 'vs/base/common/actions';
import { IActionRunner, IAction, Action, IActionViewItem } from 'vs/base/common/actions';
import { ActionBar, IActionViewItemProvider, ActionsOrientation, Separator, ActionViewItem, IActionViewItemOptions, BaseActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { ResolvedKeybinding, KeyCode } from 'vs/base/common/keyCodes';
import { addClass, EventType, EventHelper, EventLike, removeTabIndexAndUpdateFocus, isAncestor, hasClass, addDisposableListener, removeClass, append, $, addClasses, removeClasses } from 'vs/base/browser/dom';
@@ -205,8 +205,8 @@ export class Menu extends ActionBar {
container.appendChild(this.scrollableElement.getDomNode());
this.scrollableElement.scanDomNode();
this.viewItems.filter(item => !(item instanceof MenuSeparatorActionViewItem)).forEach((item: BaseMenuActionViewItem, index: number, array: any[]) => {
item.updatePositionInSet(index + 1, array.length);
this.viewItems.filter(item => !(item instanceof MenuSeparatorActionViewItem)).forEach((item: IActionViewItem, index: number, array: any[]) => {
(item as BaseMenuActionViewItem).updatePositionInSet(index + 1, array.length);
});
}
@@ -215,7 +215,7 @@ export class Menu extends ActionBar {
const fgColor = style.foregroundColor ? `${style.foregroundColor}` : '';
const bgColor = style.backgroundColor ? `${style.backgroundColor}` : '';
const border = style.borderColor ? `2px solid ${style.borderColor}` : '';
const border = style.borderColor ? `1px solid ${style.borderColor}` : '';
const shadow = style.shadowColor ? `0 2px 4px ${style.shadowColor}` : '';
container.style.border = border;
@@ -661,7 +661,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
if (this.item) {
addClass(this.item, 'monaco-submenu-item');
this.item.setAttribute('aria-haspopup', 'true');
this.updateAriaExpanded('false');
this.submenuIndicator = append(this.item, $('span.submenu-indicator'));
this.submenuIndicator.setAttribute('aria-hidden', 'true');
}
@@ -726,7 +726,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
if (this.parentData.submenu && (force || (this.parentData.submenu !== this.mysubmenu))) {
this.parentData.submenu.dispose();
this.parentData.submenu = undefined;
this.updateAriaExpanded('false');
if (this.submenuContainer) {
this.submenuDisposables.clear();
this.submenuContainer = undefined;
@@ -740,6 +740,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
}
if (!this.parentData.submenu) {
this.updateAriaExpanded('true');
this.submenuContainer = append(this.element, $('div.monaco-submenu'));
addClasses(this.submenuContainer, 'menubar-menu-items-holder', 'context-view');
@@ -778,13 +779,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
this.parentData.parent.focus();
if (this.parentData.submenu) {
this.parentData.submenu.dispose();
this.parentData.submenu = undefined;
}
this.submenuDisposables.clear();
this.submenuContainer = undefined;
this.cleanupExistingSubmenu(true);
}
}));
@@ -799,13 +794,7 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
this.submenuDisposables.add(this.parentData.submenu.onDidCancel(() => {
this.parentData.parent.focus();
if (this.parentData.submenu) {
this.parentData.submenu.dispose();
this.parentData.submenu = undefined;
}
this.submenuDisposables.clear();
this.submenuContainer = undefined;
this.cleanupExistingSubmenu(true);
}));
this.parentData.submenu.focus(selectFirstItem);
@@ -816,6 +805,12 @@ class SubmenuMenuActionViewItem extends BaseMenuActionViewItem {
}
}
private updateAriaExpanded(value: string): void {
if (this.item) {
this.item?.setAttribute('aria-expanded', value);
}
}
protected applyStyle(): void {
super.applyStyle();

View File

@@ -309,7 +309,7 @@ export class MenuBar extends Disposable {
createOverflowMenu(): void {
const label = this.options.compactMode !== undefined ? nls.localize('mAppMenu', 'Application Menu') : nls.localize('mMore', "...");
const buttonElement = $('div.menubar-menu-button', { 'role': 'menuitem', 'tabindex': -1, 'aria-label': label, 'aria-haspopup': true });
const buttonElement = $('div.menubar-menu-button', { 'role': 'menuitem', 'tabindex': -1, 'aria-label': label, 'title': label, 'aria-haspopup': true });
const titleElement = $('div.menubar-menu-title.toolbar-toggle-more', { 'role': 'none', 'aria-hidden': true });
buttonElement.appendChild(titleElement);

View File

@@ -35,19 +35,7 @@
animation-duration: 4s;
animation-iteration-count: infinite;
animation-timing-function: linear;
-ms-animation-name: progress;
-ms-animation-duration: 4s;
-ms-animation-iteration-count: infinite;
-ms-animation-timing-function: linear;
-webkit-animation-name: progress;
-webkit-animation-duration: 4s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
-moz-animation-name: progress;
-moz-animation-duration: 4s;
-moz-animation-iteration-count: infinite;
-moz-animation-timing-function: linear;
will-change: transform;
transform: translate3d(0px, 0px, 0px);
}
/**
@@ -58,6 +46,3 @@
* 100%: 50 * 100 - 50 (do not overflow): 4950%
*/
@keyframes progress { from { transform: translateX(0%) scaleX(1) } 50% { transform: translateX(2500%) scaleX(3) } to { transform: translateX(4950%) scaleX(1) } }
@-ms-keyframes progress { from { transform: translateX(0%) scaleX(1) } 50% { transform: translateX(2500%) scaleX(3) } to { transform: translateX(4950%) scaleX(1) } }
@-webkit-keyframes progress { from { transform: translateX(0%) scaleX(1) } 50% { transform: translateX(2500%) scaleX(3) } to { transform: translateX(4950%) scaleX(1) } }
@-moz-keyframes progress { from { transform: translateX(0%) scaleX(1) } 50% { transform: translateX(2500%) scaleX(3) } to { transform: translateX(4950%) scaleX(1) } }

View File

@@ -99,6 +99,7 @@ export abstract class AbstractScrollbar extends Widget {
this.slider.setHeight(height);
}
this.slider.setLayerHinting(true);
this.slider.setContain('strict');
this.domNode.domNode.appendChild(this.slider.domNode);

View File

@@ -64,7 +64,7 @@ export class MouseWheelClassifier {
return false;
}
// 0.5 * last + 0.25 * before last + 0.125 * before before last + ...
// 0.5 * last + 0.25 * 2nd last + 0.125 * 3rd last + ...
let remainingInfluence = 1;
let score = 0;
let iteration = 1;

View File

@@ -16,11 +16,7 @@
.monaco-select-box-dropdown-container {
display: none;
-webkit-box-sizing: border-box;
-o-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
box-sizing: border-box;
}
.monaco-select-box-dropdown-container > .select-box-details-pane > .select-box-description-markdown * {
@@ -55,11 +51,7 @@
padding-right: 1px;
width: 100%;
overflow: hidden;
-webkit-box-sizing: border-box;
-o-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
box-sizing: border-box;
}
.monaco-select-box-dropdown-container > .select-box-details-pane {

View File

@@ -10,6 +10,7 @@ import * as dom from 'vs/base/browser/dom';
import * as arrays from 'vs/base/common/arrays';
import { ISelectBoxDelegate, ISelectOptionItem, ISelectBoxOptions, ISelectBoxStyles, ISelectData } from 'vs/base/browser/ui/selectBox/selectBox';
import { isMacintosh } from 'vs/base/common/platform';
import { Gesture, EventType } from 'vs/base/browser/touch';
export class SelectBoxNative extends Disposable implements ISelectBoxDelegate {
@@ -44,6 +45,12 @@ export class SelectBoxNative extends Disposable implements ISelectBoxDelegate {
}
private registerListeners() {
this._register(Gesture.addTarget(this.selectElement));
[EventType.Tap].forEach(eventType => {
this._register(dom.addDisposableListener(this.selectElement, eventType, (e) => {
this.selectElement.focus();
}));
});
this._register(dom.addStandardDisposableListener(this.selectElement, 'change', (e) => {
this.selectElement.title = e.target.value;

View File

@@ -1,100 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-panel-view {
width: 100%;
height: 100%;
}
.monaco-panel-view .panel {
overflow: hidden;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.monaco-panel-view .panel > .panel-header {
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
overflow: hidden;
display: flex;
cursor: pointer;
}
.monaco-panel-view .panel > .panel-header > .twisties {
width: 20px;
display: flex;
align-items: center;
justify-content: center;
transform-origin: center;
color: inherit;
flex-shrink: 0;
}
.monaco-panel-view .panel > .panel-header.expanded > .twisties::before {
transform: rotate(90deg);
}
/* TODO: actions should be part of the panel, but they aren't yet */
.monaco-panel-view .panel > .panel-header > .actions {
display: none;
flex: 1;
}
/* TODO: actions should be part of the panel, but they aren't yet */
.monaco-panel-view .panel:hover > .panel-header.expanded > .actions,
.monaco-panel-view .panel > .panel-header.actions-always-visible.expanded > .actions,
.monaco-panel-view .panel > .panel-header.focused.expanded > .actions {
display: initial;
}
/* TODO: actions should be part of the panel, but they aren't yet */
.monaco-panel-view .panel > .panel-header > .actions .action-label.icon,
.monaco-panel-view .panel > .panel-header > .actions .action-label.codicon {
width: 28px;
height: 22px;
background-size: 16px;
background-position: center center;
background-repeat: no-repeat;
margin-right: 0;
display: flex;
align-items: center;
justify-content: center;
color: inherit;
}
/* Bold font style does not go well with CJK fonts */
.monaco-panel-view:lang(zh-Hans) .panel > .panel-header,
.monaco-panel-view:lang(zh-Hant) .panel > .panel-header,
.monaco-panel-view:lang(ja) .panel > .panel-header,
.monaco-panel-view:lang(ko) .panel > .panel-header {
font-weight: normal;
}
.monaco-panel-view .panel > .panel-header.hidden {
display: none;
}
.monaco-panel-view .panel > .panel-body {
overflow: hidden;
flex: 1;
}
/* Animation */
.monaco-panel-view.animated .split-view-view {
transition-duration: 0.15s;
transition-timing-function: ease-out;
}
.monaco-panel-view.animated.vertical .split-view-view {
transition-property: height;
}
.monaco-panel-view.animated.horizontal .split-view-view {
transition-property: width;
}

View File

@@ -0,0 +1,101 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-pane-view {
width: 100%;
height: 100%;
}
.monaco-pane-view .pane {
overflow: hidden;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
.monaco-pane-view .pane > .pane-header {
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
overflow: hidden;
display: flex;
cursor: pointer;
align-items: center;
}
.monaco-pane-view .pane > .pane-header > .twisties {
width: 20px;
display: flex;
align-items: center;
justify-content: center;
transform-origin: center;
color: inherit;
flex-shrink: 0;
}
.monaco-pane-view .pane > .pane-header.expanded > .twisties::before {
transform: rotate(90deg);
}
/* TODO: actions should be part of the pane, but they aren't yet */
.monaco-pane-view .pane > .pane-header > .actions {
display: none;
flex: 1;
}
/* TODO: actions should be part of the pane, but they aren't yet */
.monaco-pane-view .pane:hover > .pane-header.expanded > .actions,
.monaco-pane-view .pane > .pane-header.actions-always-visible.expanded > .actions,
.monaco-pane-view .pane > .pane-header.focused.expanded > .actions {
display: initial;
}
/* TODO: actions should be part of the pane, but they aren't yet */
.monaco-pane-view .pane > .pane-header > .actions .action-label.icon,
.monaco-pane-view .pane > .pane-header > .actions .action-label.codicon {
width: 28px;
height: 22px;
background-size: 16px;
background-position: center center;
background-repeat: no-repeat;
margin-right: 0;
display: flex;
align-items: center;
justify-content: center;
color: inherit;
}
/* Bold font style does not go well with CJK fonts */
.monaco-pane-view:lang(zh-Hans) .pane > .pane-header,
.monaco-pane-view:lang(zh-Hant) .pane > .pane-header,
.monaco-pane-view:lang(ja) .pane > .pane-header,
.monaco-pane-view:lang(ko) .pane > .pane-header {
font-weight: normal;
}
.monaco-pane-view .pane > .pane-header.hidden {
display: none;
}
.monaco-pane-view .pane > .pane-body {
overflow: hidden;
flex: 1;
}
/* Animation */
.monaco-pane-view.animated .split-view-view {
transition-duration: 0.15s;
transition-timing-function: ease-out;
}
.monaco-pane-view.animated.vertical .split-view-view {
transition-property: height;
}
.monaco-pane-view.animated.horizontal .split-view-view {
transition-property: width;
}

View File

@@ -3,25 +3,27 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./panelview';
import 'vs/css!./paneview';
import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
import { domEvent } from 'vs/base/browser/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
import { $, append, addClass, removeClass, toggleClass, trackFocus } from 'vs/base/browser/dom';
import { $, append, addClass, removeClass, toggleClass, trackFocus, EventHelper } from 'vs/base/browser/dom';
import { firstIndex } from 'vs/base/common/arrays';
import { Color, RGBA } from 'vs/base/common/color';
import { SplitView, IView } from './splitview';
import { isFirefox } from 'vs/base/browser/browser';
import { DataTransfers } from 'vs/base/browser/dnd';
export interface IPanelOptions {
export interface IPaneOptions {
ariaHeaderLabel?: string;
minimumBodySize?: number;
maximumBodySize?: number;
expanded?: boolean;
}
export interface IPanelStyles {
export interface IPaneStyles {
dropBackground?: Color;
headerForeground?: Color;
headerBackground?: Color;
@@ -29,7 +31,7 @@ export interface IPanelStyles {
}
/**
* A Panel is a structured SplitView view.
* A Pane is a structured SplitView view.
*
* WARNING: You must call `render()` after you contruct it.
* It can't be done automatically at the end of the ctor
@@ -37,7 +39,7 @@ export interface IPanelStyles {
* Subclasses wouldn't be able to set own properties
* before the `render()` call, thus forbiding their use.
*/
export abstract class Panel extends Disposable implements IView {
export abstract class Pane extends Disposable implements IView {
private static readonly HEADER_SIZE = 22;
@@ -52,7 +54,7 @@ export abstract class Panel extends Disposable implements IView {
private _minimumBodySize: number;
private _maximumBodySize: number;
private ariaHeaderLabel: string;
private styles: IPanelStyles = {};
private styles: IPaneStyles = {};
private animationTimer: number | undefined = undefined;
private readonly _onDidChange = this._register(new Emitter<number | undefined>());
@@ -93,7 +95,7 @@ export abstract class Panel extends Disposable implements IView {
}
private get headerSize(): number {
return this.headerVisible ? Panel.HEADER_SIZE : 0;
return this.headerVisible ? Pane.HEADER_SIZE : 0;
}
get minimumSize(): number {
@@ -114,14 +116,14 @@ export abstract class Panel extends Disposable implements IView {
width: number = 0;
constructor(options: IPanelOptions = {}) {
constructor(options: IPaneOptions = {}) {
super();
this._expanded = typeof options.expanded === 'undefined' ? true : !!options.expanded;
this.ariaHeaderLabel = options.ariaHeaderLabel || '';
this._minimumBodySize = typeof options.minimumBodySize === 'number' ? options.minimumBodySize : 120;
this._maximumBodySize = typeof options.maximumBodySize === 'number' ? options.maximumBodySize : Number.POSITIVE_INFINITY;
this.element = $('.panel');
this.element = $('.pane');
}
isExpanded(): boolean {
@@ -167,7 +169,7 @@ export abstract class Panel extends Disposable implements IView {
}
render(): void {
this.header = $('.panel-header');
this.header = $('.pane-header');
append(this.element, this.header);
this.header.setAttribute('tabindex', '0');
this.header.setAttribute('role', 'toolbar');
@@ -196,12 +198,12 @@ export abstract class Panel extends Disposable implements IView {
this._register(domEvent(this.header, 'click')
(() => this.setExpanded(!this.isExpanded()), null));
this.body = append(this.element, $('.panel-body'));
this.body = append(this.element, $('.pane-body'));
this.renderBody(this.body);
}
layout(height: number): void {
const headerSize = this.headerVisible ? Panel.HEADER_SIZE : 0;
const headerSize = this.headerVisible ? Pane.HEADER_SIZE : 0;
if (this.isExpanded()) {
this.layoutBody(height - headerSize, this.width);
@@ -209,7 +211,7 @@ export abstract class Panel extends Disposable implements IView {
}
}
style(styles: IPanelStyles): void {
style(styles: IPaneStyles): void {
this.styles = styles;
if (!this.header) {
@@ -240,31 +242,31 @@ export abstract class Panel extends Disposable implements IView {
}
interface IDndContext {
draggable: PanelDraggable | null;
draggable: PaneDraggable | null;
}
class PanelDraggable extends Disposable {
class PaneDraggable extends Disposable {
private static readonly DefaultDragOverBackgroundColor = new Color(new RGBA(128, 128, 128, 0.5));
private dragOverCounter = 0; // see https://github.com/Microsoft/vscode/issues/14470
private _onDidDrop = this._register(new Emitter<{ from: Panel, to: Panel }>());
private _onDidDrop = this._register(new Emitter<{ from: Pane, to: Pane }>());
readonly onDidDrop = this._onDidDrop.event;
constructor(private panel: Panel, private dnd: IPanelDndController, private context: IDndContext) {
constructor(private pane: Pane, private dnd: IPaneDndController, private context: IDndContext) {
super();
panel.draggableElement.draggable = true;
this._register(domEvent(panel.draggableElement, 'dragstart')(this.onDragStart, this));
this._register(domEvent(panel.dropTargetElement, 'dragenter')(this.onDragEnter, this));
this._register(domEvent(panel.dropTargetElement, 'dragleave')(this.onDragLeave, this));
this._register(domEvent(panel.dropTargetElement, 'dragend')(this.onDragEnd, this));
this._register(domEvent(panel.dropTargetElement, 'drop')(this.onDrop, this));
pane.draggableElement.draggable = true;
this._register(domEvent(pane.draggableElement, 'dragstart')(this.onDragStart, this));
this._register(domEvent(pane.dropTargetElement, 'dragenter')(this.onDragEnter, this));
this._register(domEvent(pane.dropTargetElement, 'dragleave')(this.onDragLeave, this));
this._register(domEvent(pane.dropTargetElement, 'dragend')(this.onDragEnd, this));
this._register(domEvent(pane.dropTargetElement, 'drop')(this.onDrop, this));
}
private onDragStart(e: DragEvent): void {
if (!this.dnd.canDrag(this.panel) || !e.dataTransfer) {
if (!this.dnd.canDrag(this.pane) || !e.dataTransfer) {
e.preventDefault();
e.stopPropagation();
return;
@@ -272,7 +274,12 @@ class PanelDraggable extends Disposable {
e.dataTransfer.effectAllowed = 'move';
const dragImage = append(document.body, $('.monaco-drag-image', {}, this.panel.draggableElement.textContent || ''));
if (isFirefox) {
// Firefox: requires to set a text data transfer to get going
e.dataTransfer?.setData(DataTransfers.TEXT, this.pane.draggableElement.textContent || '');
}
const dragImage = append(document.body, $('.monaco-drag-image', {}, this.pane.draggableElement.textContent || ''));
e.dataTransfer.setDragImage(dragImage, -10, -10);
setTimeout(() => document.body.removeChild(dragImage), 0);
@@ -284,7 +291,7 @@ class PanelDraggable extends Disposable {
return;
}
if (!this.dnd.canDrop(this.context.draggable.panel, this.panel)) {
if (!this.dnd.canDrop(this.context.draggable.pane, this.pane)) {
return;
}
@@ -297,7 +304,7 @@ class PanelDraggable extends Disposable {
return;
}
if (!this.dnd.canDrop(this.context.draggable.panel, this.panel)) {
if (!this.dnd.canDrop(this.context.draggable.pane, this.pane)) {
return;
}
@@ -323,11 +330,13 @@ class PanelDraggable extends Disposable {
return;
}
EventHelper.stop(e);
this.dragOverCounter = 0;
this.render();
if (this.dnd.canDrop(this.context.draggable.panel, this.panel) && this.context.draggable !== this) {
this._onDidDrop.fire({ from: this.context.draggable.panel, to: this.panel });
if (this.dnd.canDrop(this.context.draggable.pane, this.pane) && this.context.draggable !== this) {
this._onDidDrop.fire({ from: this.context.draggable.pane, to: this.pane });
}
this.context.draggable = null;
@@ -337,106 +346,106 @@ class PanelDraggable extends Disposable {
let backgroundColor: string | null = null;
if (this.dragOverCounter > 0) {
backgroundColor = (this.panel.dropBackground || PanelDraggable.DefaultDragOverBackgroundColor).toString();
backgroundColor = (this.pane.dropBackground || PaneDraggable.DefaultDragOverBackgroundColor).toString();
}
this.panel.dropTargetElement.style.backgroundColor = backgroundColor || '';
this.pane.dropTargetElement.style.backgroundColor = backgroundColor || '';
}
}
export interface IPanelDndController {
canDrag(panel: Panel): boolean;
canDrop(panel: Panel, overPanel: Panel): boolean;
export interface IPaneDndController {
canDrag(pane: Pane): boolean;
canDrop(pane: Pane, overPane: Pane): boolean;
}
export class DefaultPanelDndController implements IPanelDndController {
export class DefaultPaneDndController implements IPaneDndController {
canDrag(panel: Panel): boolean {
canDrag(pane: Pane): boolean {
return true;
}
canDrop(panel: Panel, overPanel: Panel): boolean {
canDrop(pane: Pane, overPane: Pane): boolean {
return true;
}
}
export interface IPanelViewOptions {
dnd?: IPanelDndController;
export interface IPaneViewOptions {
dnd?: IPaneDndController;
}
interface IPanelItem {
panel: Panel;
interface IPaneItem {
pane: Pane;
disposable: IDisposable;
}
export class PanelView extends Disposable {
export class PaneView extends Disposable {
private dnd: IPanelDndController | undefined;
private dnd: IPaneDndController | undefined;
private dndContext: IDndContext = { draggable: null };
private el: HTMLElement;
private panelItems: IPanelItem[] = [];
private paneItems: IPaneItem[] = [];
private width: number = 0;
private splitview: SplitView;
private animationTimer: number | undefined = undefined;
private _onDidDrop = this._register(new Emitter<{ from: Panel, to: Panel }>());
readonly onDidDrop: Event<{ from: Panel, to: Panel }> = this._onDidDrop.event;
private _onDidDrop = this._register(new Emitter<{ from: Pane, to: Pane }>());
readonly onDidDrop: Event<{ from: Pane, to: Pane }> = this._onDidDrop.event;
readonly onDidSashChange: Event<number>;
constructor(container: HTMLElement, options: IPanelViewOptions = {}) {
constructor(container: HTMLElement, options: IPaneViewOptions = {}) {
super();
this.dnd = options.dnd;
this.el = append(container, $('.monaco-panel-view'));
this.el = append(container, $('.monaco-pane-view'));
this.splitview = this._register(new SplitView(this.el));
this.onDidSashChange = this.splitview.onDidSashChange;
}
addPanel(panel: Panel, size: number, index = this.splitview.length): void {
addPane(pane: Pane, size: number, index = this.splitview.length): void {
const disposables = new DisposableStore();
panel.onDidChangeExpansionState(this.setupAnimation, this, disposables);
pane.onDidChangeExpansionState(this.setupAnimation, this, disposables);
const panelItem = { panel, disposable: disposables };
this.panelItems.splice(index, 0, panelItem);
panel.width = this.width;
this.splitview.addView(panel, size, index);
const paneItem = { pane: pane, disposable: disposables };
this.paneItems.splice(index, 0, paneItem);
pane.width = this.width;
this.splitview.addView(pane, size, index);
if (this.dnd) {
const draggable = new PanelDraggable(panel, this.dnd, this.dndContext);
const draggable = new PaneDraggable(pane, this.dnd, this.dndContext);
disposables.add(draggable);
disposables.add(draggable.onDidDrop(this._onDidDrop.fire, this._onDidDrop));
}
}
removePanel(panel: Panel): void {
const index = firstIndex(this.panelItems, item => item.panel === panel);
removePane(pane: Pane): void {
const index = firstIndex(this.paneItems, item => item.pane === pane);
if (index === -1) {
return;
}
this.splitview.removeView(index);
const panelItem = this.panelItems.splice(index, 1)[0];
panelItem.disposable.dispose();
const paneItem = this.paneItems.splice(index, 1)[0];
paneItem.disposable.dispose();
}
movePanel(from: Panel, to: Panel): void {
const fromIndex = firstIndex(this.panelItems, item => item.panel === from);
const toIndex = firstIndex(this.panelItems, item => item.panel === to);
movePane(from: Pane, to: Pane): void {
const fromIndex = firstIndex(this.paneItems, item => item.pane === from);
const toIndex = firstIndex(this.paneItems, item => item.pane === to);
if (fromIndex === -1 || toIndex === -1) {
return;
}
const [panelItem] = this.panelItems.splice(fromIndex, 1);
this.panelItems.splice(toIndex, 0, panelItem);
const [paneItem] = this.paneItems.splice(fromIndex, 1);
this.paneItems.splice(toIndex, 0, paneItem);
this.splitview.moveView(fromIndex, toIndex);
}
resizePanel(panel: Panel, size: number): void {
const index = firstIndex(this.panelItems, item => item.panel === panel);
resizePane(pane: Pane, size: number): void {
const index = firstIndex(this.paneItems, item => item.pane === pane);
if (index === -1) {
return;
@@ -445,8 +454,8 @@ export class PanelView extends Disposable {
this.splitview.resizeView(index, size);
}
getPanelSize(panel: Panel): number {
const index = firstIndex(this.panelItems, item => item.panel === panel);
getPaneSize(pane: Pane): number {
const index = firstIndex(this.paneItems, item => item.pane === pane);
if (index === -1) {
return -1;
@@ -458,8 +467,8 @@ export class PanelView extends Disposable {
layout(height: number, width: number): void {
this.width = width;
for (const panelItem of this.panelItems) {
panelItem.panel.width = width;
for (const paneItem of this.paneItems) {
paneItem.pane.width = width;
}
this.splitview.layout(height);
@@ -481,6 +490,6 @@ export class PanelView extends Disposable {
dispose(): void {
super.dispose();
this.panelItems.forEach(i => i.disposable.dispose());
this.paneItems.forEach(i => i.disposable.dispose());
}
}

View File

@@ -23,14 +23,14 @@ const defaultStyles: ISplitViewStyles = {
separatorBorder: Color.transparent
};
export interface ISplitViewOptions {
export interface ISplitViewOptions<TLayoutContext = undefined> {
readonly orientation?: Orientation; // default Orientation.VERTICAL
readonly styles?: ISplitViewStyles;
readonly orthogonalStartSash?: Sash;
readonly orthogonalEndSash?: Sash;
readonly inverseAltBehavior?: boolean;
readonly proportionalLayout?: boolean; // default true,
readonly descriptor?: ISplitViewDescriptor;
readonly descriptor?: ISplitViewDescriptor<TLayoutContext>;
}
/**
@@ -42,14 +42,14 @@ export const enum LayoutPriority {
High
}
export interface IView {
export interface IView<TLayoutContext = undefined> {
readonly element: HTMLElement;
readonly minimumSize: number;
readonly maximumSize: number;
readonly onDidChange: Event<number | undefined>;
readonly priority?: LayoutPriority;
readonly snap?: boolean;
layout(size: number, orthogonalSize: number | undefined): void;
layout(size: number, offset: number, context: TLayoutContext | undefined): void;
setVisible?(visible: boolean): void;
}
@@ -62,7 +62,7 @@ interface ISashEvent {
type ViewItemSize = number | { cachedVisibleSize: number };
abstract class ViewItem {
abstract class ViewItem<TLayoutContext> {
private _size: number;
set size(size: number) {
@@ -109,9 +109,13 @@ abstract class ViewItem {
get priority(): LayoutPriority | undefined { return this.view.priority; }
get snap(): boolean { return !!this.view.snap; }
set enabled(enabled: boolean) {
this.container.style.pointerEvents = enabled ? null : 'none';
}
constructor(
protected container: HTMLElement,
private view: IView,
private view: IView<TLayoutContext>,
size: ViewItemSize,
private disposable: IDisposable
) {
@@ -125,31 +129,31 @@ abstract class ViewItem {
}
}
layout(position: number, orthogonalSize: number | undefined): void {
this.layoutContainer(position);
this.view.layout(this.size, orthogonalSize);
layout(offset: number, layoutContext: TLayoutContext | undefined): void {
this.layoutContainer(offset);
this.view.layout(this.size, offset, layoutContext);
}
abstract layoutContainer(position: number): void;
abstract layoutContainer(offset: number): void;
dispose(): IView {
dispose(): IView<TLayoutContext> {
this.disposable.dispose();
return this.view;
}
}
class VerticalViewItem extends ViewItem {
class VerticalViewItem<TLayoutContext> extends ViewItem<TLayoutContext> {
layoutContainer(position: number): void {
this.container.style.top = `${position}px`;
layoutContainer(offset: number): void {
this.container.style.top = `${offset}px`;
this.container.style.height = `${this.size}px`;
}
}
class HorizontalViewItem extends ViewItem {
class HorizontalViewItem<TLayoutContext> extends ViewItem<TLayoutContext> {
layoutContainer(position: number): void {
this.container.style.left = `${position}px`;
layoutContainer(offset: number): void {
this.container.style.left = `${offset}px`;
this.container.style.width = `${this.size}px`;
}
}
@@ -194,26 +198,26 @@ export namespace Sizing {
export function Invisible(cachedVisibleSize: number): InvisibleSizing { return { type: 'invisible', cachedVisibleSize }; }
}
export interface ISplitViewDescriptor {
export interface ISplitViewDescriptor<TLayoutContext> {
size: number;
views: {
visible?: boolean;
size: number;
view: IView;
view: IView<TLayoutContext>;
}[];
}
export class SplitView extends Disposable {
export class SplitView<TLayoutContext = undefined> extends Disposable {
readonly orientation: Orientation;
readonly el: HTMLElement;
private sashContainer: HTMLElement;
private viewContainer: HTMLElement;
private size = 0;
private orthogonalSize: number | undefined;
private layoutContext: TLayoutContext | undefined;
private contentSize = 0;
private proportions: undefined | number[] = undefined;
private viewItems: ViewItem[] = [];
private viewItems: ViewItem<TLayoutContext>[] = [];
private sashItems: ISashItem[] = [];
private sashDragState: ISashDragState | undefined;
private state: State = State.Idle;
@@ -262,7 +266,29 @@ export class SplitView extends Disposable {
return this.sashItems.map(s => s.sash);
}
constructor(container: HTMLElement, options: ISplitViewOptions = {}) {
private _startSnappingEnabled = true;
get startSnappingEnabled(): boolean { return this._startSnappingEnabled; }
set startSnappingEnabled(startSnappingEnabled: boolean) {
if (this._startSnappingEnabled === startSnappingEnabled) {
return;
}
this._startSnappingEnabled = startSnappingEnabled;
this.updateSashEnablement();
}
private _endSnappingEnabled = true;
get endSnappingEnabled(): boolean { return this._endSnappingEnabled; }
set endSnappingEnabled(endSnappingEnabled: boolean) {
if (this._endSnappingEnabled === endSnappingEnabled) {
return;
}
this._endSnappingEnabled = endSnappingEnabled;
this.updateSashEnablement();
}
constructor(container: HTMLElement, options: ISplitViewOptions<TLayoutContext> = {}) {
super();
this.orientation = types.isUndefined(options.orientation) ? Orientation.VERTICAL : options.orientation;
@@ -305,11 +331,11 @@ export class SplitView extends Disposable {
}
}
addView(view: IView, size: number | Sizing, index = this.viewItems.length): void {
addView(view: IView<TLayoutContext>, size: number | Sizing, index = this.viewItems.length): void {
this.doAddView(view, size, index, false);
}
removeView(index: number, sizing?: Sizing): IView {
removeView(index: number, sizing?: Sizing): IView<TLayoutContext> {
if (this.state !== State.Idle) {
throw new Error('Cant modify splitview');
}
@@ -401,10 +427,10 @@ export class SplitView extends Disposable {
return viewItem.cachedVisibleSize;
}
layout(size: number, orthogonalSize?: number): void {
layout(size: number, layoutContext?: TLayoutContext): void {
const previousSize = Math.max(this.size, this.contentSize);
this.size = size;
this.orthogonalSize = orthogonalSize;
this.layoutContext = layoutContext;
if (!this.proportions) {
const indexes = range(this.viewItems.length);
@@ -430,6 +456,10 @@ export class SplitView extends Disposable {
}
private onSashStart({ sash, start, alt }: ISashEvent): void {
for (const item of this.viewItems) {
item.enabled = false;
}
const index = firstIndex(this.sashItems, item => item.sash === sash);
// This way, we can press Alt while we resize a sash, macOS style!
@@ -535,9 +565,13 @@ export class SplitView extends Disposable {
this._onDidSashChange.fire(index);
this.sashDragState!.disposable.dispose();
this.saveProportions();
for (const item of this.viewItems) {
item.enabled = true;
}
}
private onViewChange(item: ViewItem, size: number | undefined): void {
private onViewChange(item: ViewItem<TLayoutContext>, size: number | undefined): void {
const index = this.viewItems.indexOf(item);
if (index < 0 || index >= this.viewItems.length) {
@@ -584,7 +618,7 @@ export class SplitView extends Disposable {
}
distributeViewSizes(): void {
const flexibleViewItems: ViewItem[] = [];
const flexibleViewItems: ViewItem<TLayoutContext>[] = [];
let flexibleSize = 0;
for (const item of this.viewItems) {
@@ -615,7 +649,7 @@ export class SplitView extends Disposable {
return this.viewItems[index].size;
}
private doAddView(view: IView, size: number | Sizing, index = this.viewItems.length, skipLayout?: boolean): void {
private doAddView(view: IView<TLayoutContext>, size: number | Sizing, index = this.viewItems.length, skipLayout?: boolean): void {
if (this.state !== State.Idle) {
throw new Error('Cant modify splitview');
}
@@ -849,17 +883,19 @@ export class SplitView extends Disposable {
this.contentSize = this.viewItems.reduce((r, i) => r + i.size, 0);
// Layout views
let position = 0;
let offset = 0;
for (const viewItem of this.viewItems) {
viewItem.layout(position, this.orthogonalSize);
position += viewItem.size;
viewItem.layout(offset, this.layoutContext);
offset += viewItem.size;
}
// Layout sashes
this.sashItems.forEach(item => item.sash.layout());
this.updateSashEnablement();
}
// Update sashes enablement
private updateSashEnablement(): void {
let previous = false;
const collapsesDown = this.viewItems.map(i => previous = (i.size - i.minimumSize > 0) || previous);
@@ -873,7 +909,12 @@ export class SplitView extends Disposable {
previous = false;
const expandsUp = reverseViews.map(i => previous = (i.maximumSize - i.size > 0) || previous).reverse();
this.sashItems.forEach(({ sash }, index) => {
let position = 0;
for (let index = 0; index < this.sashItems.length; index++) {
const { sash } = this.sashItems[index];
const viewItem = this.viewItems[index];
position += viewItem.size;
const min = !(collapsesDown[index] && expandsUp[index + 1]);
const max = !(expandsDown[index] && collapsesUp[index + 1]);
@@ -886,9 +927,9 @@ export class SplitView extends Disposable {
const snappedBefore = typeof snapBeforeIndex === 'number' && !this.viewItems[snapBeforeIndex].visible;
const snappedAfter = typeof snapAfterIndex === 'number' && !this.viewItems[snapAfterIndex].visible;
if (snappedBefore && collapsesUp[index]) {
if (snappedBefore && collapsesUp[index] && (position > 0 || this.startSnappingEnabled)) {
sash.state = SashState.Minimum;
} else if (snappedAfter && collapsesDown[index]) {
} else if (snappedAfter && collapsesDown[index] && (position < this.contentSize || this.endSnappingEnabled)) {
sash.state = SashState.Maximum;
} else {
sash.state = SashState.Disabled;
@@ -900,8 +941,7 @@ export class SplitView extends Disposable {
} else {
sash.state = SashState.Enabled;
}
// }
});
}
}
private getSashPosition(sash: Sash): number {

View File

@@ -52,7 +52,7 @@ export class ToolBar extends Disposable {
orientation: options.orientation,
ariaLabel: options.ariaLabel,
actionRunner: options.actionRunner,
actionViewItemProvider: (action: Action) => {
actionViewItemProvider: (action: IAction) => {
// Return special action item for the toggle menu action
if (action.id === ToggleMenuAction.ID) {

View File

@@ -7,7 +7,7 @@ import 'vs/css!./media/tree';
import { IDisposable, dispose, Disposable, toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { IListOptions, List, IListStyles, MouseController, DefaultKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/listWidget';
import { IListVirtualDelegate, IListRenderer, IListMouseEvent, IListEvent, IListContextMenuEvent, IListDragAndDrop, IListDragOverReaction, IKeyboardNavigationLabelProvider, IIdentityProvider, IKeyboardNavigationDelegate } from 'vs/base/browser/ui/list/list';
import { append, $, toggleClass, getDomNodePagePosition, removeClass, addClass, hasClass, hasParentWithClass, createStyleSheet, clearNode } from 'vs/base/browser/dom';
import { append, $, toggleClass, getDomNodePagePosition, removeClass, addClass, hasClass, hasParentWithClass, createStyleSheet, clearNode, addClasses, removeClasses } from 'vs/base/browser/dom';
import { Event, Relay, Emitter, EventBufferer } from 'vs/base/common/event';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { KeyCode } from 'vs/base/common/keyCodes';
@@ -27,10 +27,24 @@ import { clamp } from 'vs/base/common/numbers';
import { ScrollEvent } from 'vs/base/common/scrollable';
import { SetMap } from 'vs/base/common/collections';
class TreeElementsDragAndDropData<T, TFilterData, TContext> extends ElementsDragAndDropData<T, TContext> {
set context(context: TContext | undefined) {
this.data.context = context;
}
get context(): TContext | undefined {
return this.data.context;
}
constructor(private data: ElementsDragAndDropData<ITreeNode<T, TFilterData>, TContext>) {
super(data.elements.map(node => node.element));
}
}
function asTreeDragAndDropData<T, TFilterData>(data: IDragAndDropData): IDragAndDropData {
if (data instanceof ElementsDragAndDropData) {
const nodes = (data as ElementsDragAndDropData<ITreeNode<T, TFilterData>>).elements;
return new ElementsDragAndDropData(nodes.map(node => node.element));
return new TreeElementsDragAndDropData(data);
}
return data;
@@ -47,9 +61,9 @@ class TreeNodeListDragAndDrop<T, TFilterData, TRef> implements IListDragAndDrop<
return this.dnd.getDragURI(node.element);
}
getDragLabel(nodes: ITreeNode<T, TFilterData>[]): string | undefined {
getDragLabel(nodes: ITreeNode<T, TFilterData>[], originalEvent: DragEvent): string | undefined {
if (this.dnd.getDragLabel) {
return this.dnd.getDragLabel(nodes.map(node => node.element));
return this.dnd.getDragLabel(nodes.map(node => node.element), originalEvent);
}
return undefined;
@@ -87,7 +101,7 @@ class TreeNodeListDragAndDrop<T, TFilterData, TRef> implements IListDragAndDrop<
}, 500);
}
if (typeof result === 'boolean' || !result.accept || typeof result.bubble === 'undefined') {
if (typeof result === 'boolean' || !result.accept || typeof result.bubble === 'undefined' || result.feedback) {
if (!raw) {
const accept = typeof result === 'boolean' ? result : result.accept;
const effect = typeof result === 'boolean' ? undefined : result.effect;
@@ -121,6 +135,12 @@ class TreeNodeListDragAndDrop<T, TFilterData, TRef> implements IListDragAndDrop<
this.dnd.drop(asTreeDragAndDropData(data), targetNode && targetNode.element, targetIndex, originalEvent);
}
onDragEnd(originalEvent: DragEvent): void {
if (this.dnd.onDragEnd) {
this.dnd.onDragEnd(originalEvent);
}
}
}
function asListOptions<T, TFilterData, TRef>(modelProvider: () => ITreeModel<T, TFilterData, TRef>, options?: IAbstractTreeOptions<T, TFilterData>): IListOptions<ITreeNode<T, TFilterData>> | undefined {
@@ -141,12 +161,16 @@ function asListOptions<T, TFilterData, TRef>(modelProvider: () => ITreeModel<T,
}
},
accessibilityProvider: options.accessibilityProvider && {
...options.accessibilityProvider,
getAriaLabel(e) {
return options.accessibilityProvider!.getAriaLabel(e.element);
},
getAriaLevel(node) {
return node.depth;
}
},
getActiveDescendantId: options.accessibilityProvider.getActiveDescendantId && (node => {
return options.accessibilityProvider!.getActiveDescendantId!(node.element);
})
},
keyboardNavigationLabelProvider: options.keyboardNavigationLabelProvider && {
...options.keyboardNavigationLabelProvider,
@@ -211,6 +235,8 @@ export enum RenderIndentGuides {
interface ITreeRendererOptions {
readonly indent?: number;
readonly renderIndentGuides?: RenderIndentGuides;
// TODO@joao replace this with collapsible: boolean | 'ondemand'
readonly hideTwistiesOfChildlessElements?: boolean;
}
interface IRenderData<TTemplateData> {
@@ -244,6 +270,7 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
private renderedElements = new Map<T, ITreeNode<T, TFilterData>>();
private renderedNodes = new Map<ITreeNode<T, TFilterData>, IRenderData<TTemplateData>>();
private indent: number = TreeRenderer.DefaultIndent;
private hideTwistiesOfChildlessElements: boolean = false;
private shouldRenderIndentGuides: boolean = false;
private renderedIndentGuides = new SetMap<ITreeNode<T, TFilterData>, HTMLDivElement>();
@@ -290,6 +317,10 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
}
}
}
if (typeof options.hideTwistiesOfChildlessElements !== 'undefined') {
this.hideTwistiesOfChildlessElements = options.hideTwistiesOfChildlessElements;
}
}
renderTemplate(container: HTMLElement): ITreeListTemplateData<TTemplateData> {
@@ -309,7 +340,7 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
}
const indent = TreeRenderer.DefaultIndent + (node.depth - 1) * this.indent;
templateData.twistie.style.marginLeft = `${indent}px`;
templateData.twistie.style.paddingLeft = `${indent}px`;
templateData.indent.style.width = `${indent + this.indent - 16}px`;
this.renderTwistie(node, templateData);
@@ -365,10 +396,12 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
this.renderer.renderTwistie(node.element, templateData.twistie);
}
toggleClass(templateData.twistie, 'codicon', node.collapsible);
toggleClass(templateData.twistie, 'codicon-chevron-down', node.collapsible);
toggleClass(templateData.twistie, 'collapsible', node.collapsible);
toggleClass(templateData.twistie, 'collapsed', node.collapsible && node.collapsed);
if (node.collapsible && (!this.hideTwistiesOfChildlessElements || node.visibleChildrenCount > 0)) {
addClasses(templateData.twistie, 'codicon', 'codicon-chevron-down', 'collapsible');
toggleClass(templateData.twistie, 'collapsed', node.collapsed);
} else {
removeClasses(templateData.twistie, 'codicon', 'codicon-chevron-down', 'collapsible', 'collapsed');
}
if (node.collapsible) {
templateData.container.setAttribute('aria-expanded', String(!node.collapsed));
@@ -430,12 +463,16 @@ class TreeRenderer<T, TFilterData, TRef, TTemplateData> implements IListRenderer
nodes.forEach(node => {
const ref = model.getNodeLocation(node);
const parentRef = model.getParentNodeLocation(ref);
try {
const parentRef = model.getParentNodeLocation(ref);
if (node.collapsible && node.children.length > 0 && !node.collapsed) {
set.add(node);
} else if (parentRef) {
set.add(model.getNode(parentRef));
if (node.collapsible && node.children.length > 0 && !node.collapsed) {
set.add(node);
} else if (parentRef) {
set.add(model.getNode(parentRef));
}
} catch {
// noop
}
});
@@ -601,14 +638,14 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
const controls = append(this.domNode, $('.controls'));
this._filterOnType = !!tree.options.filterOnType;
this.filterOnTypeDomNode = append(controls, $<HTMLInputElement>('input.filter'));
this.filterOnTypeDomNode = append(controls, $<HTMLInputElement>('input.filter.codicon.codicon-list-selection'));
this.filterOnTypeDomNode.type = 'checkbox';
this.filterOnTypeDomNode.checked = this._filterOnType;
this.filterOnTypeDomNode.tabIndex = -1;
this.updateFilterOnTypeTitle();
domEvent(this.filterOnTypeDomNode, 'input')(this.onDidChangeFilterOnType, this, this.disposables);
this.clearDomNode = append(controls, $<HTMLInputElement>('button.clear'));
this.clearDomNode = append(controls, $<HTMLInputElement>('button.clear.codicon.codicon-close'));
this.clearDomNode.tabIndex = -1;
this.clearDomNode.title = localize('clear', "Clear");
@@ -657,7 +694,7 @@ class TypeFilterController<T, TFilterData> implements IDisposable {
const onKeyDown = Event.chain(domEvent(this.view.getHTMLElement(), 'keydown'))
.filter(e => !isInputElement(e.target as HTMLElement) || e.target === this.filterOnTypeDomNode)
.filter(e => e.key !== 'Dead')
.filter(e => e.key !== 'Dead' && !/^Media/.test(e.key))
.map(e => new StandardKeyboardEvent(e))
.filter(this.keyboardNavigationEventFilter || (() => true))
.filter(() => this.automaticKeyboardNavigation || this.triggered)
@@ -918,7 +955,6 @@ export interface IAbstractTreeOptions<T, TFilterData = void> extends IAbstractTr
readonly collapseByDefault?: boolean; // defaults to false
readonly filter?: ITreeFilter<T, TFilterData>;
readonly dnd?: ITreeDragAndDrop<T>;
readonly autoExpandSingleChildren?: boolean;
readonly keyboardNavigationEventFilter?: IKeyboardNavigationEventFilter;
readonly expandOnlyOnTwistieClick?: boolean | ((e: T) => boolean);
readonly additionalScrollHeight?: number;
@@ -1385,8 +1421,13 @@ export abstract class AbstractTree<T, TFilterData, TRef> implements IDisposable
return this.view.renderHeight;
}
get firstVisibleElement(): T {
get firstVisibleElement(): T | undefined {
const index = this.view.firstVisibleIndex;
if (index < 0 || index >= this.view.length) {
return undefined;
}
const node = this.view.element(index);
return node.element;
}

View File

@@ -6,7 +6,7 @@
import { ComposedTreeDelegate, IAbstractTreeOptions, IAbstractTreeOptionsUpdate } from 'vs/base/browser/ui/tree/abstractTree';
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 { ITreeElement, ITreeNode, ITreeRenderer, ITreeEvent, ITreeMouseEvent, ITreeContextMenuEvent, ITreeSorter, ICollapseStateChangeEvent, IAsyncDataSource, ITreeDragAndDrop, TreeError, WeakMapper, ITreeFilter, TreeVisibility, TreeFilterResult } from 'vs/base/browser/ui/tree/tree';
import { IDisposable, dispose, DisposableStore } from 'vs/base/common/lifecycle';
import { Emitter, Event } from 'vs/base/common/event';
import { timeout, CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
@@ -19,6 +19,8 @@ import { toggleClass } from 'vs/base/browser/dom';
import { values } from 'vs/base/common/map';
import { ScrollEvent } from 'vs/base/common/scrollable';
import { ICompressedTreeNode, ICompressedTreeElement } from 'vs/base/browser/ui/tree/compressedObjectTreeModel';
import { IThemable } from 'vs/base/common/styler';
import { isFilterResult, getVisibleState } from 'vs/base/browser/ui/tree/indexTreeModel';
interface IAsyncDataTreeNode<TInput, T> {
element: TInput | T;
@@ -149,20 +151,24 @@ function asTreeContextMenuEvent<TInput, T>(e: ITreeContextMenuEvent<IAsyncDataTr
};
}
export enum ChildrenResolutionReason {
Refresh,
Expand
}
class AsyncDataTreeElementsDragAndDropData<TInput, T, TContext> extends ElementsDragAndDropData<T, TContext> {
export interface IChildrenResolutionEvent<T> {
readonly element: T | null;
readonly reason: ChildrenResolutionReason;
set context(context: TContext | undefined) {
this.data.context = context;
}
get context(): TContext | undefined {
return this.data.context;
}
constructor(private data: ElementsDragAndDropData<IAsyncDataTreeNode<TInput, T>, TContext>) {
super(data.elements.map(node => node.element as T));
}
}
function asAsyncDataTreeDragAndDropData<TInput, T>(data: IDragAndDropData): IDragAndDropData {
if (data instanceof ElementsDragAndDropData) {
const nodes = (data as ElementsDragAndDropData<IAsyncDataTreeNode<TInput, T>>).elements;
return new ElementsDragAndDropData(nodes.map(node => node.element));
return new AsyncDataTreeElementsDragAndDropData(data);
}
return data;
@@ -176,9 +182,9 @@ class AsyncDataTreeNodeListDragAndDrop<TInput, T> implements IListDragAndDrop<IA
return this.dnd.getDragURI(node.element as T);
}
getDragLabel(nodes: IAsyncDataTreeNode<TInput, T>[]): string | undefined {
getDragLabel(nodes: IAsyncDataTreeNode<TInput, T>[], originalEvent: DragEvent): string | undefined {
if (this.dnd.getDragLabel) {
return this.dnd.getDragLabel(nodes.map(node => node.element as T));
return this.dnd.getDragLabel(nodes.map(node => node.element as T), originalEvent);
}
return undefined;
@@ -197,6 +203,12 @@ class AsyncDataTreeNodeListDragAndDrop<TInput, T> implements IListDragAndDrop<IA
drop(data: IDragAndDropData, targetNode: IAsyncDataTreeNode<TInput, T> | undefined, targetIndex: number | undefined, originalEvent: DragEvent): void {
this.dnd.drop(asAsyncDataTreeDragAndDropData(data), targetNode && targetNode.element as T, targetIndex, originalEvent);
}
onDragEnd(originalEvent: DragEvent): void {
if (this.dnd.onDragEnd) {
this.dnd.onDragEnd(originalEvent);
}
}
}
function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOptions<T, TFilterData>): IObjectTreeOptions<IAsyncDataTreeNode<TInput, T>, TFilterData> | undefined {
@@ -218,9 +230,16 @@ function asObjectTreeOptions<TInput, T, TFilterData>(options?: IAsyncDataTreeOpt
}
},
accessibilityProvider: options.accessibilityProvider && {
...options.accessibilityProvider,
getAriaLabel(e) {
return options.accessibilityProvider!.getAriaLabel(e.element as T);
}
},
getAriaLevel: options.accessibilityProvider!.getAriaLevel && (node => {
return options.accessibilityProvider!.getAriaLevel!(node.element as T);
}),
getActiveDescendantId: options.accessibilityProvider.getActiveDescendantId && (node => {
return options.accessibilityProvider!.getActiveDescendantId!(node.element as T);
})
},
filter: options.filter && {
filter(e, parentVisibility) {
@@ -271,10 +290,10 @@ function dfs<TInput, T>(node: IAsyncDataTreeNode<TInput, T>, fn: (node: IAsyncDa
node.children.forEach(child => dfs(child, fn));
}
export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable {
export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable, IThemable {
private readonly tree: ObjectTree<IAsyncDataTreeNode<TInput, T>, TFilterData>;
private readonly root: IAsyncDataTreeNode<TInput, T>;
protected readonly tree: ObjectTree<IAsyncDataTreeNode<TInput, T>, TFilterData>;
protected readonly root: IAsyncDataTreeNode<TInput, T>;
private readonly nodes = new Map<null | T, IAsyncDataTreeNode<TInput, T>>();
private readonly sorter?: ITreeSorter<T>;
private readonly collapseByDefault?: { (e: T): boolean; };
@@ -282,7 +301,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
private readonly subTreeRefreshPromises = new Map<IAsyncDataTreeNode<TInput, T>, Promise<void>>();
private readonly refreshPromises = new Map<IAsyncDataTreeNode<TInput, T>, CancelablePromise<T[]>>();
private readonly identityProvider?: IIdentityProvider<T>;
protected readonly identityProvider?: IIdentityProvider<T>;
private readonly autoExpandSingleChildren: boolean;
private readonly _onDidRender = new Emitter<void>();
@@ -323,7 +342,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
get onDidDispose(): Event<void> { return this.tree.onDidDispose; }
constructor(
private user: string,
protected user: string,
container: HTMLElement,
delegate: IListVirtualDelegate<T>,
renderers: ITreeRenderer<T, TFilterData, any>[],
@@ -411,10 +430,6 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return this.tree.renderHeight;
}
get firstVisibleElement(): T {
return this.tree.firstVisibleElement!.element as T;
}
get lastVisibleElement(): T {
return this.tree.lastVisibleElement!.element as T;
}
@@ -445,7 +460,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
const viewStateContext = viewState && { viewState, focus: [], selection: [] } as IAsyncDataTreeViewStateContext<TInput, T>;
await this._updateChildren(input, true, viewStateContext);
await this._updateChildren(input, true, false, viewStateContext);
if (viewStateContext) {
this.tree.setFocus(viewStateContext.focus);
@@ -457,11 +472,11 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
}
}
async updateChildren(element: TInput | T = this.root.element, recursive = true): Promise<void> {
await this._updateChildren(element, recursive);
async updateChildren(element: TInput | T = this.root.element, recursive = true, rerender = false): Promise<void> {
await this._updateChildren(element, recursive, rerender);
}
private async _updateChildren(element: TInput | T = this.root.element, recursive = true, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): Promise<void> {
private async _updateChildren(element: TInput | T = this.root.element, recursive = true, rerender = false, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): Promise<void> {
if (typeof this.root.element === 'undefined') {
throw new TreeError(this.user, 'Tree input not set');
}
@@ -471,7 +486,17 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
await Event.toPromise(this._onDidRender.event);
}
await this.refreshAndRenderNode(this.getDataNode(element), recursive, ChildrenResolutionReason.Refresh, viewStateContext);
const node = this.getDataNode(element);
await this.refreshAndRenderNode(node, recursive, viewStateContext);
if (rerender) {
try {
this.tree.rerender(node);
} catch {
// missing nodes are fine, this could've resulted from
// parallel refresh calls, removing `node` altogether
}
}
}
resort(element: TInput | T = this.root.element, recursive = true): void {
@@ -653,18 +678,9 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
return node;
}
private async refreshAndRenderNode(node: IAsyncDataTreeNode<TInput, T>, recursive: boolean, reason: ChildrenResolutionReason, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): Promise<void> {
private async refreshAndRenderNode(node: IAsyncDataTreeNode<TInput, T>, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): Promise<void> {
await this.refreshNode(node, recursive, viewStateContext);
this.render(node, viewStateContext);
if (node !== this.root && this.autoExpandSingleChildren && reason === ChildrenResolutionReason.Expand) {
const treeNode = this.tree.getNode(node);
const visibleChildren = treeNode.children.filter(node => node.visible);
if (visibleChildren.length === 1) {
await this.tree.expand(visibleChildren[0].element, false);
}
}
}
private async refreshNode(node: IAsyncDataTreeNode<TInput, T>, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): Promise<void> {
@@ -752,12 +768,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
result = createCancelablePromise(async () => {
const children = await this.dataSource.getChildren(node.element!);
if (this.sorter) {
children.sort(this.sorter.compare.bind(this.sorter));
}
return children;
return this.processChildren(children);
});
this.refreshPromises.set(node, result);
@@ -770,7 +781,7 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
if (deep) {
this.collapse(node.element.element as T);
} else {
this.refreshAndRenderNode(node.element, false, ChildrenResolutionReason.Expand)
this.refreshAndRenderNode(node.element, false)
.catch(onUnexpectedError);
}
}
@@ -783,13 +794,14 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
}
const nodesToForget = new Map<T, IAsyncDataTreeNode<TInput, T>>();
const childrenTreeNodesById = new Map<string, ITreeNode<IAsyncDataTreeNode<TInput, T> | null, TFilterData>>();
const childrenTreeNodesById = new Map<string, { node: IAsyncDataTreeNode<TInput, T>, collapsed: boolean }>();
for (const child of node.children) {
nodesToForget.set(child.element as T, child);
if (this.identityProvider) {
childrenTreeNodesById.set(child.id!, this.tree.getNode(child));
const collapsed = this.tree.isCollapsed(child);
childrenTreeNodesById.set(child.id!, { node: child, collapsed });
}
}
@@ -810,10 +822,10 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
}
const id = this.identityProvider.getId(element).toString();
const childNode = childrenTreeNodesById.get(id);
const result = childrenTreeNodesById.get(id);
if (childNode) {
const asyncDataTreeNode = childNode.element!;
if (result) {
const asyncDataTreeNode = result.node;
nodesToForget.delete(asyncDataTreeNode.element as T);
this.nodes.delete(asyncDataTreeNode.element as T);
@@ -823,8 +835,10 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
asyncDataTreeNode.hasChildren = hasChildren;
if (recursive) {
if (childNode.collapsed) {
dfs(asyncDataTreeNode, node => node.stale = true);
if (result.collapsed) {
asyncDataTreeNode.children.forEach(node => dfs(node, node => this.nodes.delete(node.element as T)));
asyncDataTreeNode.children.splice(0, asyncDataTreeNode.children.length);
asyncDataTreeNode.stale = true;
} else {
childrenToRefresh.push(asyncDataTreeNode);
}
@@ -866,10 +880,16 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
node.children.splice(0, node.children.length, ...children);
// TODO@joao this doesn't take filter into account
if (node !== this.root && this.autoExpandSingleChildren && children.length === 1 && childrenToRefresh.length === 0) {
children[0].collapsedByDefault = false;
childrenToRefresh.push(children[0]);
}
return childrenToRefresh;
}
private render(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): void {
protected render(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): void {
const children = node.children.map(node => this.asTreeElement(node, viewStateContext));
this.tree.setChildren(node === this.root ? null : node, children);
@@ -881,6 +901,14 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
}
protected asTreeElement(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): ITreeElement<IAsyncDataTreeNode<TInput, T>> {
if (node.stale) {
return {
element: node,
collapsible: node.hasChildren,
collapsed: true
};
}
let collapsed: boolean | undefined;
if (viewStateContext && viewStateContext.viewState.expanded && node.id && viewStateContext.viewState.expanded.indexOf(node.id) > -1) {
@@ -899,6 +927,14 @@ export class AsyncDataTree<TInput, T, TFilterData = void> implements IDisposable
};
}
protected processChildren(children: T[]): T[] {
if (this.sorter) {
children.sort(this.sorter.compare.bind(this.sorter));
}
return children;
}
// view state
getViewState(): IAsyncDataTreeViewState {
@@ -994,6 +1030,12 @@ class CompressibleAsyncDataTreeRenderer<TInput, T, TFilterData, TTemplateData> i
}
}
disposeCompressedElements(node: ITreeNode<ICompressedTreeNode<IAsyncDataTreeNode<TInput, T>>, TFilterData>, index: number, templateData: IDataTreeListTemplateData<TTemplateData>, height: number | undefined): void {
if (this.renderer.disposeCompressedElements) {
this.renderer.disposeCompressedElements(this.compressibleNodeMapperProvider().map(node) as ITreeNode<ICompressedTreeNode<T>, TFilterData>, index, templateData.templateData, height);
}
}
disposeTemplate(templateData: IDataTreeListTemplateData<TTemplateData>): void {
this.renderer.disposeTemplate(templateData.templateData);
}
@@ -1023,12 +1065,19 @@ function asCompressibleObjectTreeOptions<TInput, T, TFilterData>(options?: IComp
}
export interface ICompressibleAsyncDataTreeOptions<T, TFilterData = void> extends IAsyncDataTreeOptions<T, TFilterData> {
readonly compressionEnabled?: boolean;
readonly keyboardNavigationLabelProvider?: ICompressibleKeyboardNavigationLabelProvider<T>;
}
export interface ICompressibleAsyncDataTreeOptionsUpdate extends IAsyncDataTreeOptionsUpdate {
readonly compressionEnabled?: boolean;
}
export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends AsyncDataTree<TInput, T, TFilterData> {
protected readonly tree!: CompressibleObjectTree<IAsyncDataTreeNode<TInput, T>, TFilterData>;
protected readonly compressibleNodeMapper: CompressibleAsyncDataTreeNodeMapper<TInput, T, TFilterData> = new WeakMapper(node => new CompressibleAsyncDataTreeNodeWrapper(node));
private filter?: ITreeFilter<T, TFilterData>;
constructor(
user: string,
@@ -1037,9 +1086,10 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
private compressionDelegate: ITreeCompressionDelegate<T>,
renderers: ICompressibleTreeRenderer<T, TFilterData, any>[],
dataSource: IAsyncDataSource<TInput, T>,
options: IAsyncDataTreeOptions<T, TFilterData> = {}
options: ICompressibleAsyncDataTreeOptions<T, TFilterData> = {}
) {
super(user, container, virtualDelegate, renderers, dataSource, options);
this.filter = options.filter;
}
protected createTree(
@@ -1062,4 +1112,137 @@ export class CompressibleAsyncDataTree<TInput, T, TFilterData = void> extends As
...super.asTreeElement(node, viewStateContext)
};
}
updateOptions(options: ICompressibleAsyncDataTreeOptionsUpdate = {}): void {
this.tree.updateOptions(options);
}
getViewState(): IAsyncDataTreeViewState {
if (!this.identityProvider) {
throw new TreeError(this.user, 'Can\'t get tree view state without an identity provider');
}
const getId = (element: T) => this.identityProvider!.getId(element).toString();
const focus = this.getFocus().map(getId);
const selection = this.getSelection().map(getId);
const expanded: string[] = [];
const root = this.tree.getCompressedTreeNode();
const queue = [root];
while (queue.length > 0) {
const node = queue.shift()!;
if (node !== root && node.collapsible && !node.collapsed) {
for (const asyncNode of node.element!.elements) {
expanded.push(getId(asyncNode.element as T));
}
}
queue.push(...node.children);
}
return { focus, selection, expanded, scrollTop: this.scrollTop };
}
protected render(node: IAsyncDataTreeNode<TInput, T>, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): void {
if (!this.identityProvider) {
return super.render(node, viewStateContext);
}
// Preserve traits across compressions. Hacky but does the trick.
// This is hard to fix properly since it requires rewriting the traits
// across trees and lists. Let's just keep it this way for now.
const getId = (element: T) => this.identityProvider!.getId(element).toString();
const getUncompressedIds = (nodes: IAsyncDataTreeNode<TInput, T>[]): Set<string> => {
const result = new Set<string>();
for (const node of nodes) {
const compressedNode = this.tree.getCompressedTreeNode(node === this.root ? null : node);
if (!compressedNode.element) {
continue;
}
for (const node of compressedNode.element.elements) {
result.add(getId(node.element as T));
}
}
return result;
};
const oldSelection = getUncompressedIds(this.tree.getSelection() as IAsyncDataTreeNode<TInput, T>[]);
const oldFocus = getUncompressedIds(this.tree.getFocus() as IAsyncDataTreeNode<TInput, T>[]);
super.render(node, viewStateContext);
const selection = this.getSelection();
let didChangeSelection = false;
const focus = this.getFocus();
let didChangeFocus = false;
const visit = (node: ITreeNode<ICompressedTreeNode<IAsyncDataTreeNode<TInput, T>> | null, TFilterData>) => {
const compressedNode = node.element;
if (compressedNode) {
for (let i = 0; i < compressedNode.elements.length; i++) {
const id = getId(compressedNode.elements[i].element as T);
if (oldSelection.has(id)) {
selection.push(compressedNode.elements[compressedNode.elements.length - 1].element as T);
didChangeSelection = true;
}
if (oldFocus.has(id)) {
focus.push(compressedNode.elements[compressedNode.elements.length - 1].element as T);
didChangeFocus = true;
}
}
}
node.children.forEach(visit);
};
visit(this.tree.getCompressedTreeNode(node === this.root ? null : node));
if (didChangeSelection) {
this.setSelection(selection);
}
if (didChangeFocus) {
this.setFocus(focus);
}
}
// For compressed async data trees, `TreeVisibility.Recurse` doesn't currently work
// and we have to filter everything beforehand
// Related to #85193 and #85835
protected processChildren(children: T[]): T[] {
if (this.filter) {
children = children.filter(e => {
const result = this.filter!.filter(e, TreeVisibility.Visible);
const visibility = getVisibility(result);
if (visibility === TreeVisibility.Recurse) {
throw new Error('Recursive tree visibility not supported in async data compressed trees');
}
return visibility === TreeVisibility.Visible;
});
}
return super.processChildren(children);
}
}
function getVisibility<TFilterData>(filterResult: TreeFilterResult<TFilterData>): TreeVisibility {
if (typeof filterResult === 'boolean') {
return filterResult ? TreeVisibility.Visible : TreeVisibility.Hidden;
} else if (isFilterResult(filterResult)) {
return getVisibleState(filterResult.visibility);
} else {
return getVisibleState(filterResult);
}
}

View File

@@ -11,7 +11,7 @@ import { IObjectTreeModelOptions, ObjectTreeModel, IObjectTreeModel } from 'vs/b
// Exported only for test reasons, do not use directly
export interface ICompressedTreeElement<T> extends ITreeElement<T> {
readonly children?: Iterator<ICompressedTreeElement<T>> | ICompressedTreeElement<T>[];
readonly children?: ISequence<ICompressedTreeElement<T>>;
readonly incompressible?: boolean;
}
@@ -100,16 +100,15 @@ export function decompress<T>(element: ITreeElement<ICompressedTreeNode<T>>): IC
function splice<T>(treeElement: ICompressedTreeElement<T>, element: T, children: Iterator<ICompressedTreeElement<T>>): ICompressedTreeElement<T> {
if (treeElement.element === element) {
return { element, children };
return { ...treeElement, children };
}
return {
...treeElement,
children: Iterator.map(Iterator.from(treeElement.children), e => splice(e, element, children))
};
return { ...treeElement, children: Iterator.map(Iterator.from(treeElement.children), e => splice(e, element, children)) };
}
interface ICompressedObjectTreeModelOptions<T, TFilterData> extends IObjectTreeModelOptions<ICompressedTreeNode<T>, TFilterData> { }
interface ICompressedObjectTreeModelOptions<T, TFilterData> extends IObjectTreeModelOptions<ICompressedTreeNode<T>, TFilterData> {
readonly compressionEnabled?: boolean;
}
// Exported only for test reasons, do not use directly
export class CompressedObjectTreeModel<T extends NonNullable<any>, TFilterData extends NonNullable<any> = void> implements ITreeModel<ICompressedTreeNode<T> | null, TFilterData, T | null> {
@@ -122,7 +121,7 @@ export class CompressedObjectTreeModel<T extends NonNullable<any>, TFilterData e
private model: ObjectTreeModel<ICompressedTreeNode<T>, TFilterData>;
private nodes = new Map<T | null, ICompressedTreeNode<T>>();
private enabled: boolean = true;
private enabled: boolean;
get size(): number { return this.nodes.size; }
@@ -132,13 +131,13 @@ export class CompressedObjectTreeModel<T extends NonNullable<any>, TFilterData e
options: ICompressedObjectTreeModelOptions<T, TFilterData> = {}
) {
this.model = new ObjectTreeModel(user, list, options);
this.enabled = typeof options.compressionEnabled === 'undefined' ? true : options.compressionEnabled;
}
setChildren(
element: T | null,
children: ISequence<ICompressedTreeElement<T>> | undefined
): void {
if (element === null) {
const compressedChildren = Iterator.map(Iterator.from(children), this.enabled ? compress : noCompress);
this._setChildren(null, compressedChildren);
@@ -368,6 +367,7 @@ function mapOptions<T, TFilterData>(compressedNodeUnwrapper: CompressedNodeUnwra
}
export interface ICompressibleObjectTreeModelOptions<T, TFilterData> extends IObjectTreeModelOptions<T, TFilterData> {
readonly compressionEnabled?: boolean;
readonly elementMapper?: ElementMapper<T>;
}
@@ -493,7 +493,7 @@ export class CompressibleObjectTreeModel<T extends NonNullable<any>, TFilterData
return this.model.resort(element, recursive);
}
getCompressedTreeNode(element: T): ITreeNode<ICompressedTreeNode<T>, TFilterData> {
return this.model.getNode(element) as ITreeNode<ICompressedTreeNode<T>, TFilterData>;
getCompressedTreeNode(location: T | null = null): ITreeNode<ICompressedTreeNode<T> | null, TFilterData> {
return this.model.getNode(location);
}
}

View File

@@ -11,7 +11,7 @@ import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list
import { Iterator } from 'vs/base/common/iterator';
export interface IDataTreeOptions<T, TFilterData = void> extends IAbstractTreeOptions<T, TFilterData> {
sorter?: ITreeSorter<T>;
readonly sorter?: ITreeSorter<T>;
}
export interface IDataTreeViewState {

View File

@@ -442,6 +442,7 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
if (visibility === TreeVisibility.Hidden) {
node.visible = false;
node.renderNodeCount = 0;
return false;
}

View File

@@ -3,11 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-panel-view .panel > .panel-header h3.title {
.monaco-pane-view .pane > .pane-header h3.title {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
font-size: 11px;
-webkit-margin-before: 0;
-webkit-margin-after: 0;
margin: 0;
}

View File

@@ -14,7 +14,7 @@
height: 100%;
position: absolute;
top: 0;
left: 18px;
left: 16px;
pointer-events: none;
}
@@ -41,7 +41,7 @@
.monaco-tl-twistie {
font-size: 10px;
text-align: right;
margin-right: 6px;
padding-right: 6px;
flex-shrink: 0;
width: 16px;
display: flex !important;

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { ISequence } from 'vs/base/common/iterator';
import { AbstractTree, IAbstractTreeOptions } from 'vs/base/browser/ui/tree/abstractTree';
import { AbstractTree, IAbstractTreeOptions, IAbstractTreeOptionsUpdate } from 'vs/base/browser/ui/tree/abstractTree';
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';
@@ -56,7 +56,7 @@ export class ObjectTree<T extends NonNullable<any>, TFilterData = void> extends
}
interface ICompressedTreeNodeProvider<T, TFilterData> {
getCompressedTreeNode(element: T): ITreeNode<ICompressedTreeNode<T>, TFilterData>;
getCompressedTreeNode(location: T | null): ITreeNode<ICompressedTreeNode<T> | null, TFilterData>;
}
export interface ICompressibleTreeRenderer<T, TFilterData = void, TTemplateData = void> extends ITreeRenderer<T, TFilterData, TTemplateData> {
@@ -69,7 +69,7 @@ interface CompressibleTemplateData<T, TFilterData, TTemplateData> {
readonly data: TTemplateData;
}
class CompressibleRenderer<T, TFilterData, TTemplateData> implements ITreeRenderer<T, TFilterData, CompressibleTemplateData<T, TFilterData, TTemplateData>> {
class CompressibleRenderer<T extends NonNullable<any>, TFilterData, TTemplateData> implements ITreeRenderer<T, TFilterData, CompressibleTemplateData<T, TFilterData, TTemplateData>> {
readonly templateId: string;
readonly onDidChangeTwistieState: Event<T> | undefined;
@@ -93,7 +93,7 @@ class CompressibleRenderer<T, TFilterData, TTemplateData> implements ITreeRender
}
renderElement(node: ITreeNode<T, TFilterData>, index: number, templateData: CompressibleTemplateData<T, TFilterData, TTemplateData>, height: number | undefined): void {
const compressedTreeNode = this.compressedTreeNodeProvider.getCompressedTreeNode(node.element);
const compressedTreeNode = this.compressedTreeNodeProvider.getCompressedTreeNode(node.element) as ITreeNode<ICompressedTreeNode<T>, TFilterData>;
if (compressedTreeNode.element.elements.length === 1) {
templateData.compressedTreeNode = undefined;
@@ -132,6 +132,7 @@ export interface ICompressibleKeyboardNavigationLabelProvider<T> extends IKeyboa
}
export interface ICompressibleObjectTreeOptions<T, TFilterData = void> extends IObjectTreeOptions<T, TFilterData> {
readonly compressionEnabled?: boolean;
readonly elementMapper?: ElementMapper<T>;
readonly keyboardNavigationLabelProvider?: ICompressibleKeyboardNavigationLabelProvider<T>;
}
@@ -144,7 +145,7 @@ function asObjectTreeOptions<T, TFilterData>(compressedTreeNodeProvider: () => I
let compressedTreeNode: ITreeNode<ICompressedTreeNode<T>, TFilterData>;
try {
compressedTreeNode = compressedTreeNodeProvider().getCompressedTreeNode(e);
compressedTreeNode = compressedTreeNodeProvider().getCompressedTreeNode(e) as ITreeNode<ICompressedTreeNode<T>, TFilterData>;
} catch {
return options.keyboardNavigationLabelProvider!.getKeyboardNavigationLabel(e);
}
@@ -159,6 +160,10 @@ function asObjectTreeOptions<T, TFilterData>(compressedTreeNodeProvider: () => I
};
}
export interface ICompressibleObjectTreeOptionsUpdate extends IAbstractTreeOptionsUpdate {
readonly compressionEnabled?: boolean;
}
export class CompressibleObjectTree<T extends NonNullable<any>, TFilterData = void> extends ObjectTree<T, TFilterData> implements ICompressedTreeNodeProvider<T, TFilterData> {
protected model!: CompressibleObjectTreeModel<T, TFilterData>;
@@ -171,7 +176,7 @@ export class CompressibleObjectTree<T extends NonNullable<any>, TFilterData = vo
options: ICompressibleObjectTreeOptions<T, TFilterData> = {}
) {
const compressedTreeNodeProvider = () => this;
const compressibleRenderers = renderers.map(r => new CompressibleRenderer(compressedTreeNodeProvider, r));
const compressibleRenderers = renderers.map(r => new CompressibleRenderer<T, TFilterData, any>(compressedTreeNodeProvider, r));
super(user, container, delegate, compressibleRenderers, asObjectTreeOptions(compressedTreeNodeProvider, options));
}
@@ -183,15 +188,15 @@ export class CompressibleObjectTree<T extends NonNullable<any>, TFilterData = vo
return new CompressibleObjectTreeModel(user, view, options);
}
isCompressionEnabled(): boolean {
return this.model.isCompressionEnabled();
updateOptions(optionsUpdate: ICompressibleObjectTreeOptionsUpdate = {}): void {
super.updateOptions(optionsUpdate);
if (typeof optionsUpdate.compressionEnabled !== 'undefined') {
this.model.setCompressionEnabled(optionsUpdate.compressionEnabled);
}
}
setCompressionEnabled(enabled: boolean): void {
this.model.setCompressionEnabled(enabled);
}
getCompressedTreeNode(element: T): ITreeNode<ICompressedTreeNode<T>, TFilterData> {
return this.model.getCompressedTreeNode(element)!;
getCompressedTreeNode(element: T | null = null): ITreeNode<ICompressedTreeNode<T> | null, TFilterData> {
return this.model.getCompressedTreeNode(element);
}
}

View File

@@ -257,7 +257,12 @@ export class ObjectTreeModel<T extends NonNullable<any>, TFilterData extends Non
throw new TreeError(this.user, `Invalid getParentNodeLocation call`);
}
const node = this.nodes.get(element)!;
const node = this.nodes.get(element);
if (!node) {
throw new TreeError(this.user, `Tree element not found: ${element}`);
}
const location = this.model.getNodeLocation(node);
const parentLocation = this.model.getParentNodeLocation(location);
const parent = this.model.getNode(parentLocation);

View File

@@ -7,6 +7,7 @@ import * as dom from 'vs/base/browser/dom';
import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { IMouseEvent, StandardMouseEvent } from 'vs/base/browser/mouseEvent';
import { Disposable } from 'vs/base/common/lifecycle';
import { Gesture } from 'vs/base/browser/touch';
export abstract class Widget extends Disposable {
@@ -49,4 +50,8 @@ export abstract class Widget extends Disposable {
protected onchange(domNode: HTMLElement, listener: (e: Event) => void): void {
this._register(dom.addDisposableListener(domNode, dom.EventType.CHANGE, listener));
}
protected ignoreGesture(domNode: HTMLElement): void {
Gesture.ignoreTarget(domNode);
}
}