monaco-editor
Version:
A browser based code editor
894 lines (893 loc) • 57.8 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
import { createStyleSheet, isActiveElement, isKeyboardEvent } from '../../../base/browser/dom.js';
import { PagedList } from '../../../base/browser/ui/list/listPaging.js';
import { DefaultStyleController, isSelectionRangeChangeEvent, isSelectionSingleChangeEvent, List, TypeNavigationMode } from '../../../base/browser/ui/list/listWidget.js';
import { Table } from '../../../base/browser/ui/table/tableWidget.js';
import { TreeFindMode, TreeFindMatchType } from '../../../base/browser/ui/tree/abstractTree.js';
import { AsyncDataTree, CompressibleAsyncDataTree } from '../../../base/browser/ui/tree/asyncDataTree.js';
import { DataTree } from '../../../base/browser/ui/tree/dataTree.js';
import { CompressibleObjectTree, ObjectTree } from '../../../base/browser/ui/tree/objectTree.js';
import { Emitter, Event } from '../../../base/common/event.js';
import { combinedDisposable, Disposable, DisposableStore, dispose, toDisposable } from '../../../base/common/lifecycle.js';
import { localize } from '../../../nls.js';
import { IConfigurationService } from '../../configuration/common/configuration.js';
import { Extensions as ConfigurationExtensions } from '../../configuration/common/configurationRegistry.js';
import { ContextKeyExpr, IContextKeyService, RawContextKey } from '../../contextkey/common/contextkey.js';
import { InputFocusedContextKey } from '../../contextkey/common/contextkeys.js';
import { IContextViewService } from '../../contextview/browser/contextView.js';
import { createDecorator, IInstantiationService } from '../../instantiation/common/instantiation.js';
import { IKeybindingService } from '../../keybinding/common/keybinding.js';
import { Registry } from '../../registry/common/platform.js';
import { defaultFindWidgetStyles, defaultListStyles, getListStyles } from '../../theme/browser/defaultStyles.js';
export const IListService = createDecorator('listService');
export class ListService {
get lastFocusedList() {
return this._lastFocusedWidget;
}
constructor() {
this.disposables = new DisposableStore();
this.lists = [];
this._lastFocusedWidget = undefined;
this._hasCreatedStyleController = false;
}
setLastFocusedList(widget) {
var _a, _b;
if (widget === this._lastFocusedWidget) {
return;
}
(_a = this._lastFocusedWidget) === null || _a === void 0 ? void 0 : _a.getHTMLElement().classList.remove('last-focused');
this._lastFocusedWidget = widget;
(_b = this._lastFocusedWidget) === null || _b === void 0 ? void 0 : _b.getHTMLElement().classList.add('last-focused');
}
register(widget, extraContextKeys) {
if (!this._hasCreatedStyleController) {
this._hasCreatedStyleController = true;
// create a shared default tree style sheet for performance reasons
const styleController = new DefaultStyleController(createStyleSheet(), '');
styleController.style(defaultListStyles);
}
if (this.lists.some(l => l.widget === widget)) {
throw new Error('Cannot register the same widget multiple times');
}
// Keep in our lists list
const registeredList = { widget, extraContextKeys };
this.lists.push(registeredList);
// Check for currently being focused
if (isActiveElement(widget.getHTMLElement())) {
this.setLastFocusedList(widget);
}
return combinedDisposable(widget.onDidFocus(() => this.setLastFocusedList(widget)), toDisposable(() => this.lists.splice(this.lists.indexOf(registeredList), 1)), widget.onDidDispose(() => {
this.lists = this.lists.filter(l => l !== registeredList);
if (this._lastFocusedWidget === widget) {
this.setLastFocusedList(undefined);
}
}));
}
dispose() {
this.disposables.dispose();
}
}
export const RawWorkbenchListScrollAtBoundaryContextKey = new RawContextKey('listScrollAtBoundary', 'none');
export const WorkbenchListScrollAtTopContextKey = ContextKeyExpr.or(RawWorkbenchListScrollAtBoundaryContextKey.isEqualTo('top'), RawWorkbenchListScrollAtBoundaryContextKey.isEqualTo('both'));
export const WorkbenchListScrollAtBottomContextKey = ContextKeyExpr.or(RawWorkbenchListScrollAtBoundaryContextKey.isEqualTo('bottom'), RawWorkbenchListScrollAtBoundaryContextKey.isEqualTo('both'));
export const RawWorkbenchListFocusContextKey = new RawContextKey('listFocus', true);
export const WorkbenchTreeStickyScrollFocused = new RawContextKey('treestickyScrollFocused', false);
export const WorkbenchListSupportsMultiSelectContextKey = new RawContextKey('listSupportsMultiselect', true);
export const WorkbenchListFocusContextKey = ContextKeyExpr.and(RawWorkbenchListFocusContextKey, ContextKeyExpr.not(InputFocusedContextKey), WorkbenchTreeStickyScrollFocused.negate());
export const WorkbenchListHasSelectionOrFocus = new RawContextKey('listHasSelectionOrFocus', false);
export const WorkbenchListDoubleSelection = new RawContextKey('listDoubleSelection', false);
export const WorkbenchListMultiSelection = new RawContextKey('listMultiSelection', false);
export const WorkbenchListSelectionNavigation = new RawContextKey('listSelectionNavigation', false);
export const WorkbenchListSupportsFind = new RawContextKey('listSupportsFind', true);
export const WorkbenchTreeElementCanCollapse = new RawContextKey('treeElementCanCollapse', false);
export const WorkbenchTreeElementHasParent = new RawContextKey('treeElementHasParent', false);
export const WorkbenchTreeElementCanExpand = new RawContextKey('treeElementCanExpand', false);
export const WorkbenchTreeElementHasChild = new RawContextKey('treeElementHasChild', false);
export const WorkbenchTreeFindOpen = new RawContextKey('treeFindOpen', false);
const WorkbenchListTypeNavigationModeKey = 'listTypeNavigationMode';
/**
* @deprecated in favor of WorkbenchListTypeNavigationModeKey
*/
const WorkbenchListAutomaticKeyboardNavigationLegacyKey = 'listAutomaticKeyboardNavigation';
function createScopedContextKeyService(contextKeyService, widget) {
const result = contextKeyService.createScoped(widget.getHTMLElement());
RawWorkbenchListFocusContextKey.bindTo(result);
return result;
}
function createScrollObserver(contextKeyService, widget) {
const listScrollAt = RawWorkbenchListScrollAtBoundaryContextKey.bindTo(contextKeyService);
const update = () => {
const atTop = widget.scrollTop === 0;
// We need a threshold `1` since scrollHeight is rounded.
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#determine_if_an_element_has_been_totally_scrolled
const atBottom = widget.scrollHeight - widget.renderHeight - widget.scrollTop < 1;
if (atTop && atBottom) {
listScrollAt.set('both');
}
else if (atTop) {
listScrollAt.set('top');
}
else if (atBottom) {
listScrollAt.set('bottom');
}
else {
listScrollAt.set('none');
}
};
update();
return widget.onDidScroll(update);
}
const multiSelectModifierSettingKey = 'workbench.list.multiSelectModifier';
const openModeSettingKey = 'workbench.list.openMode';
const horizontalScrollingKey = 'workbench.list.horizontalScrolling';
const defaultFindModeSettingKey = 'workbench.list.defaultFindMode';
const typeNavigationModeSettingKey = 'workbench.list.typeNavigationMode';
/** @deprecated in favor of `workbench.list.defaultFindMode` and `workbench.list.typeNavigationMode` */
const keyboardNavigationSettingKey = 'workbench.list.keyboardNavigation';
const scrollByPageKey = 'workbench.list.scrollByPage';
const defaultFindMatchTypeSettingKey = 'workbench.list.defaultFindMatchType';
const treeIndentKey = 'workbench.tree.indent';
const treeRenderIndentGuidesKey = 'workbench.tree.renderIndentGuides';
const listSmoothScrolling = 'workbench.list.smoothScrolling';
const mouseWheelScrollSensitivityKey = 'workbench.list.mouseWheelScrollSensitivity';
const fastScrollSensitivityKey = 'workbench.list.fastScrollSensitivity';
const treeExpandMode = 'workbench.tree.expandMode';
const treeStickyScroll = 'workbench.tree.enableStickyScroll';
const treeStickyScrollMaxElements = 'workbench.tree.stickyScrollMaxItemCount';
function useAltAsMultipleSelectionModifier(configurationService) {
return configurationService.getValue(multiSelectModifierSettingKey) === 'alt';
}
class MultipleSelectionController extends Disposable {
constructor(configurationService) {
super();
this.configurationService = configurationService;
this.useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
this.registerListeners();
}
registerListeners() {
this._register(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(multiSelectModifierSettingKey)) {
this.useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(this.configurationService);
}
}));
}
isSelectionSingleChangeEvent(event) {
if (this.useAltAsMultipleSelectionModifier) {
return event.browserEvent.altKey;
}
return isSelectionSingleChangeEvent(event);
}
isSelectionRangeChangeEvent(event) {
return isSelectionRangeChangeEvent(event);
}
}
function toWorkbenchListOptions(accessor, options) {
var _a;
const configurationService = accessor.get(IConfigurationService);
const keybindingService = accessor.get(IKeybindingService);
const disposables = new DisposableStore();
const result = {
...options,
keyboardNavigationDelegate: { mightProducePrintableCharacter(e) { return keybindingService.mightProducePrintableCharacter(e); } },
smoothScrolling: Boolean(configurationService.getValue(listSmoothScrolling)),
mouseWheelScrollSensitivity: configurationService.getValue(mouseWheelScrollSensitivityKey),
fastScrollSensitivity: configurationService.getValue(fastScrollSensitivityKey),
multipleSelectionController: (_a = options.multipleSelectionController) !== null && _a !== void 0 ? _a : disposables.add(new MultipleSelectionController(configurationService)),
keyboardNavigationEventFilter: createKeyboardNavigationEventFilter(keybindingService),
scrollByPage: Boolean(configurationService.getValue(scrollByPageKey))
};
return [result, disposables];
}
let WorkbenchList = class WorkbenchList extends List {
constructor(user, container, delegate, renderers, options, contextKeyService, listService, configurationService, instantiationService) {
const horizontalScrolling = typeof options.horizontalScrolling !== 'undefined' ? options.horizontalScrolling : Boolean(configurationService.getValue(horizontalScrollingKey));
const [workbenchListOptions, workbenchListOptionsDisposable] = instantiationService.invokeFunction(toWorkbenchListOptions, options);
super(user, container, delegate, renderers, {
keyboardSupport: false,
...workbenchListOptions,
horizontalScrolling,
});
this.disposables.add(workbenchListOptionsDisposable);
this.contextKeyService = createScopedContextKeyService(contextKeyService, this);
this.disposables.add(createScrollObserver(this.contextKeyService, this));
this.listSupportsMultiSelect = WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService);
this.listSupportsMultiSelect.set(options.multipleSelectionSupport !== false);
const listSelectionNavigation = WorkbenchListSelectionNavigation.bindTo(this.contextKeyService);
listSelectionNavigation.set(Boolean(options.selectionNavigation));
this.listHasSelectionOrFocus = WorkbenchListHasSelectionOrFocus.bindTo(this.contextKeyService);
this.listDoubleSelection = WorkbenchListDoubleSelection.bindTo(this.contextKeyService);
this.listMultiSelection = WorkbenchListMultiSelection.bindTo(this.contextKeyService);
this.horizontalScrolling = options.horizontalScrolling;
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
this.disposables.add(this.contextKeyService);
this.disposables.add(listService.register(this));
this.updateStyles(options.overrideStyles);
this.disposables.add(this.onDidChangeSelection(() => {
const selection = this.getSelection();
const focus = this.getFocus();
this.contextKeyService.bufferChangeEvents(() => {
this.listHasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);
this.listMultiSelection.set(selection.length > 1);
this.listDoubleSelection.set(selection.length === 2);
});
}));
this.disposables.add(this.onDidChangeFocus(() => {
const selection = this.getSelection();
const focus = this.getFocus();
this.listHasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);
}));
this.disposables.add(configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(multiSelectModifierSettingKey)) {
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
}
let options = {};
if (e.affectsConfiguration(horizontalScrollingKey) && this.horizontalScrolling === undefined) {
const horizontalScrolling = Boolean(configurationService.getValue(horizontalScrollingKey));
options = { ...options, horizontalScrolling };
}
if (e.affectsConfiguration(scrollByPageKey)) {
const scrollByPage = Boolean(configurationService.getValue(scrollByPageKey));
options = { ...options, scrollByPage };
}
if (e.affectsConfiguration(listSmoothScrolling)) {
const smoothScrolling = Boolean(configurationService.getValue(listSmoothScrolling));
options = { ...options, smoothScrolling };
}
if (e.affectsConfiguration(mouseWheelScrollSensitivityKey)) {
const mouseWheelScrollSensitivity = configurationService.getValue(mouseWheelScrollSensitivityKey);
options = { ...options, mouseWheelScrollSensitivity };
}
if (e.affectsConfiguration(fastScrollSensitivityKey)) {
const fastScrollSensitivity = configurationService.getValue(fastScrollSensitivityKey);
options = { ...options, fastScrollSensitivity };
}
if (Object.keys(options).length > 0) {
this.updateOptions(options);
}
}));
this.navigator = new ListResourceNavigator(this, { configurationService, ...options });
this.disposables.add(this.navigator);
}
updateOptions(options) {
super.updateOptions(options);
if (options.overrideStyles !== undefined) {
this.updateStyles(options.overrideStyles);
}
if (options.multipleSelectionSupport !== undefined) {
this.listSupportsMultiSelect.set(!!options.multipleSelectionSupport);
}
}
updateStyles(styles) {
this.style(styles ? getListStyles(styles) : defaultListStyles);
}
};
WorkbenchList = __decorate([
__param(5, IContextKeyService),
__param(6, IListService),
__param(7, IConfigurationService),
__param(8, IInstantiationService)
], WorkbenchList);
export { WorkbenchList };
let WorkbenchPagedList = class WorkbenchPagedList extends PagedList {
constructor(user, container, delegate, renderers, options, contextKeyService, listService, configurationService, instantiationService) {
const horizontalScrolling = typeof options.horizontalScrolling !== 'undefined' ? options.horizontalScrolling : Boolean(configurationService.getValue(horizontalScrollingKey));
const [workbenchListOptions, workbenchListOptionsDisposable] = instantiationService.invokeFunction(toWorkbenchListOptions, options);
super(user, container, delegate, renderers, {
keyboardSupport: false,
...workbenchListOptions,
horizontalScrolling,
});
this.disposables = new DisposableStore();
this.disposables.add(workbenchListOptionsDisposable);
this.contextKeyService = createScopedContextKeyService(contextKeyService, this);
this.disposables.add(createScrollObserver(this.contextKeyService, this.widget));
this.horizontalScrolling = options.horizontalScrolling;
this.listSupportsMultiSelect = WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService);
this.listSupportsMultiSelect.set(options.multipleSelectionSupport !== false);
const listSelectionNavigation = WorkbenchListSelectionNavigation.bindTo(this.contextKeyService);
listSelectionNavigation.set(Boolean(options.selectionNavigation));
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
this.disposables.add(this.contextKeyService);
this.disposables.add(listService.register(this));
this.updateStyles(options.overrideStyles);
this.disposables.add(configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(multiSelectModifierSettingKey)) {
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
}
let options = {};
if (e.affectsConfiguration(horizontalScrollingKey) && this.horizontalScrolling === undefined) {
const horizontalScrolling = Boolean(configurationService.getValue(horizontalScrollingKey));
options = { ...options, horizontalScrolling };
}
if (e.affectsConfiguration(scrollByPageKey)) {
const scrollByPage = Boolean(configurationService.getValue(scrollByPageKey));
options = { ...options, scrollByPage };
}
if (e.affectsConfiguration(listSmoothScrolling)) {
const smoothScrolling = Boolean(configurationService.getValue(listSmoothScrolling));
options = { ...options, smoothScrolling };
}
if (e.affectsConfiguration(mouseWheelScrollSensitivityKey)) {
const mouseWheelScrollSensitivity = configurationService.getValue(mouseWheelScrollSensitivityKey);
options = { ...options, mouseWheelScrollSensitivity };
}
if (e.affectsConfiguration(fastScrollSensitivityKey)) {
const fastScrollSensitivity = configurationService.getValue(fastScrollSensitivityKey);
options = { ...options, fastScrollSensitivity };
}
if (Object.keys(options).length > 0) {
this.updateOptions(options);
}
}));
this.navigator = new ListResourceNavigator(this, { configurationService, ...options });
this.disposables.add(this.navigator);
}
updateOptions(options) {
super.updateOptions(options);
if (options.overrideStyles !== undefined) {
this.updateStyles(options.overrideStyles);
}
if (options.multipleSelectionSupport !== undefined) {
this.listSupportsMultiSelect.set(!!options.multipleSelectionSupport);
}
}
updateStyles(styles) {
this.style(styles ? getListStyles(styles) : defaultListStyles);
}
dispose() {
this.disposables.dispose();
super.dispose();
}
};
WorkbenchPagedList = __decorate([
__param(5, IContextKeyService),
__param(6, IListService),
__param(7, IConfigurationService),
__param(8, IInstantiationService)
], WorkbenchPagedList);
export { WorkbenchPagedList };
let WorkbenchTable = class WorkbenchTable extends Table {
constructor(user, container, delegate, columns, renderers, options, contextKeyService, listService, configurationService, instantiationService) {
const horizontalScrolling = typeof options.horizontalScrolling !== 'undefined' ? options.horizontalScrolling : Boolean(configurationService.getValue(horizontalScrollingKey));
const [workbenchListOptions, workbenchListOptionsDisposable] = instantiationService.invokeFunction(toWorkbenchListOptions, options);
super(user, container, delegate, columns, renderers, {
keyboardSupport: false,
...workbenchListOptions,
horizontalScrolling,
});
this.disposables.add(workbenchListOptionsDisposable);
this.contextKeyService = createScopedContextKeyService(contextKeyService, this);
this.disposables.add(createScrollObserver(this.contextKeyService, this));
this.listSupportsMultiSelect = WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService);
this.listSupportsMultiSelect.set(options.multipleSelectionSupport !== false);
const listSelectionNavigation = WorkbenchListSelectionNavigation.bindTo(this.contextKeyService);
listSelectionNavigation.set(Boolean(options.selectionNavigation));
this.listHasSelectionOrFocus = WorkbenchListHasSelectionOrFocus.bindTo(this.contextKeyService);
this.listDoubleSelection = WorkbenchListDoubleSelection.bindTo(this.contextKeyService);
this.listMultiSelection = WorkbenchListMultiSelection.bindTo(this.contextKeyService);
this.horizontalScrolling = options.horizontalScrolling;
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
this.disposables.add(this.contextKeyService);
this.disposables.add(listService.register(this));
this.updateStyles(options.overrideStyles);
this.disposables.add(this.onDidChangeSelection(() => {
const selection = this.getSelection();
const focus = this.getFocus();
this.contextKeyService.bufferChangeEvents(() => {
this.listHasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);
this.listMultiSelection.set(selection.length > 1);
this.listDoubleSelection.set(selection.length === 2);
});
}));
this.disposables.add(this.onDidChangeFocus(() => {
const selection = this.getSelection();
const focus = this.getFocus();
this.listHasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);
}));
this.disposables.add(configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(multiSelectModifierSettingKey)) {
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
}
let options = {};
if (e.affectsConfiguration(horizontalScrollingKey) && this.horizontalScrolling === undefined) {
const horizontalScrolling = Boolean(configurationService.getValue(horizontalScrollingKey));
options = { ...options, horizontalScrolling };
}
if (e.affectsConfiguration(scrollByPageKey)) {
const scrollByPage = Boolean(configurationService.getValue(scrollByPageKey));
options = { ...options, scrollByPage };
}
if (e.affectsConfiguration(listSmoothScrolling)) {
const smoothScrolling = Boolean(configurationService.getValue(listSmoothScrolling));
options = { ...options, smoothScrolling };
}
if (e.affectsConfiguration(mouseWheelScrollSensitivityKey)) {
const mouseWheelScrollSensitivity = configurationService.getValue(mouseWheelScrollSensitivityKey);
options = { ...options, mouseWheelScrollSensitivity };
}
if (e.affectsConfiguration(fastScrollSensitivityKey)) {
const fastScrollSensitivity = configurationService.getValue(fastScrollSensitivityKey);
options = { ...options, fastScrollSensitivity };
}
if (Object.keys(options).length > 0) {
this.updateOptions(options);
}
}));
this.navigator = new TableResourceNavigator(this, { configurationService, ...options });
this.disposables.add(this.navigator);
}
updateOptions(options) {
super.updateOptions(options);
if (options.overrideStyles !== undefined) {
this.updateStyles(options.overrideStyles);
}
if (options.multipleSelectionSupport !== undefined) {
this.listSupportsMultiSelect.set(!!options.multipleSelectionSupport);
}
}
updateStyles(styles) {
this.style(styles ? getListStyles(styles) : defaultListStyles);
}
dispose() {
this.disposables.dispose();
super.dispose();
}
};
WorkbenchTable = __decorate([
__param(6, IContextKeyService),
__param(7, IListService),
__param(8, IConfigurationService),
__param(9, IInstantiationService)
], WorkbenchTable);
export { WorkbenchTable };
class ResourceNavigator extends Disposable {
constructor(widget, options) {
var _a;
super();
this.widget = widget;
this._onDidOpen = this._register(new Emitter());
this.onDidOpen = this._onDidOpen.event;
this._register(Event.filter(this.widget.onDidChangeSelection, e => isKeyboardEvent(e.browserEvent))(e => this.onSelectionFromKeyboard(e)));
this._register(this.widget.onPointer((e) => this.onPointer(e.element, e.browserEvent)));
this._register(this.widget.onMouseDblClick((e) => this.onMouseDblClick(e.element, e.browserEvent)));
if (typeof (options === null || options === void 0 ? void 0 : options.openOnSingleClick) !== 'boolean' && (options === null || options === void 0 ? void 0 : options.configurationService)) {
this.openOnSingleClick = (options === null || options === void 0 ? void 0 : options.configurationService.getValue(openModeSettingKey)) !== 'doubleClick';
this._register(options === null || options === void 0 ? void 0 : options.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(openModeSettingKey)) {
this.openOnSingleClick = (options === null || options === void 0 ? void 0 : options.configurationService.getValue(openModeSettingKey)) !== 'doubleClick';
}
}));
}
else {
this.openOnSingleClick = (_a = options === null || options === void 0 ? void 0 : options.openOnSingleClick) !== null && _a !== void 0 ? _a : true;
}
}
onSelectionFromKeyboard(event) {
if (event.elements.length !== 1) {
return;
}
const selectionKeyboardEvent = event.browserEvent;
const preserveFocus = typeof selectionKeyboardEvent.preserveFocus === 'boolean' ? selectionKeyboardEvent.preserveFocus : true;
const pinned = typeof selectionKeyboardEvent.pinned === 'boolean' ? selectionKeyboardEvent.pinned : !preserveFocus;
const sideBySide = false;
this._open(this.getSelectedElement(), preserveFocus, pinned, sideBySide, event.browserEvent);
}
onPointer(element, browserEvent) {
if (!this.openOnSingleClick) {
return;
}
const isDoubleClick = browserEvent.detail === 2;
if (isDoubleClick) {
return;
}
const isMiddleClick = browserEvent.button === 1;
const preserveFocus = true;
const pinned = isMiddleClick;
const sideBySide = browserEvent.ctrlKey || browserEvent.metaKey || browserEvent.altKey;
this._open(element, preserveFocus, pinned, sideBySide, browserEvent);
}
onMouseDblClick(element, browserEvent) {
if (!browserEvent) {
return;
}
// copied from AbstractTree
const target = browserEvent.target;
const onTwistie = target.classList.contains('monaco-tl-twistie')
|| (target.classList.contains('monaco-icon-label') && target.classList.contains('folder-icon') && browserEvent.offsetX < 16);
if (onTwistie) {
return;
}
const preserveFocus = false;
const pinned = true;
const sideBySide = (browserEvent.ctrlKey || browserEvent.metaKey || browserEvent.altKey);
this._open(element, preserveFocus, pinned, sideBySide, browserEvent);
}
_open(element, preserveFocus, pinned, sideBySide, browserEvent) {
if (!element) {
return;
}
this._onDidOpen.fire({
editorOptions: {
preserveFocus,
pinned,
revealIfVisible: true
},
sideBySide,
element,
browserEvent
});
}
}
class ListResourceNavigator extends ResourceNavigator {
constructor(widget, options) {
super(widget, options);
this.widget = widget;
}
getSelectedElement() {
return this.widget.getSelectedElements()[0];
}
}
class TableResourceNavigator extends ResourceNavigator {
constructor(widget, options) {
super(widget, options);
}
getSelectedElement() {
return this.widget.getSelectedElements()[0];
}
}
class TreeResourceNavigator extends ResourceNavigator {
constructor(widget, options) {
super(widget, options);
}
getSelectedElement() {
var _a;
return (_a = this.widget.getSelection()[0]) !== null && _a !== void 0 ? _a : undefined;
}
}
function createKeyboardNavigationEventFilter(keybindingService) {
let inMultiChord = false;
return event => {
if (event.toKeyCodeChord().isModifierKey()) {
return false;
}
if (inMultiChord) {
inMultiChord = false;
return false;
}
const result = keybindingService.softDispatch(event, event.target);
if (result.kind === 1 /* ResultKind.MoreChordsNeeded */) {
inMultiChord = true;
return false;
}
inMultiChord = false;
return result.kind === 0 /* ResultKind.NoMatchingKb */;
};
}
let WorkbenchObjectTree = class WorkbenchObjectTree extends ObjectTree {
constructor(user, container, delegate, renderers, options, instantiationService, contextKeyService, listService, configurationService) {
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options);
super(user, container, delegate, renderers, treeOptions);
this.disposables.add(disposable);
this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, configurationService);
this.disposables.add(this.internals);
}
updateOptions(options) {
super.updateOptions(options);
this.internals.updateOptions(options);
}
};
WorkbenchObjectTree = __decorate([
__param(5, IInstantiationService),
__param(6, IContextKeyService),
__param(7, IListService),
__param(8, IConfigurationService)
], WorkbenchObjectTree);
export { WorkbenchObjectTree };
let WorkbenchCompressibleObjectTree = class WorkbenchCompressibleObjectTree extends CompressibleObjectTree {
constructor(user, container, delegate, renderers, options, instantiationService, contextKeyService, listService, configurationService) {
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options);
super(user, container, delegate, renderers, treeOptions);
this.disposables.add(disposable);
this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, configurationService);
this.disposables.add(this.internals);
}
updateOptions(options = {}) {
super.updateOptions(options);
if (options.overrideStyles) {
this.internals.updateStyleOverrides(options.overrideStyles);
}
this.internals.updateOptions(options);
}
};
WorkbenchCompressibleObjectTree = __decorate([
__param(5, IInstantiationService),
__param(6, IContextKeyService),
__param(7, IListService),
__param(8, IConfigurationService)
], WorkbenchCompressibleObjectTree);
export { WorkbenchCompressibleObjectTree };
let WorkbenchDataTree = class WorkbenchDataTree extends DataTree {
constructor(user, container, delegate, renderers, dataSource, options, instantiationService, contextKeyService, listService, configurationService) {
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options);
super(user, container, delegate, renderers, dataSource, treeOptions);
this.disposables.add(disposable);
this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, configurationService);
this.disposables.add(this.internals);
}
updateOptions(options = {}) {
super.updateOptions(options);
if (options.overrideStyles !== undefined) {
this.internals.updateStyleOverrides(options.overrideStyles);
}
this.internals.updateOptions(options);
}
};
WorkbenchDataTree = __decorate([
__param(6, IInstantiationService),
__param(7, IContextKeyService),
__param(8, IListService),
__param(9, IConfigurationService)
], WorkbenchDataTree);
export { WorkbenchDataTree };
let WorkbenchAsyncDataTree = class WorkbenchAsyncDataTree extends AsyncDataTree {
get onDidOpen() { return this.internals.onDidOpen; }
constructor(user, container, delegate, renderers, dataSource, options, instantiationService, contextKeyService, listService, configurationService) {
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options);
super(user, container, delegate, renderers, dataSource, treeOptions);
this.disposables.add(disposable);
this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, configurationService);
this.disposables.add(this.internals);
}
updateOptions(options = {}) {
super.updateOptions(options);
if (options.overrideStyles) {
this.internals.updateStyleOverrides(options.overrideStyles);
}
this.internals.updateOptions(options);
}
};
WorkbenchAsyncDataTree = __decorate([
__param(6, IInstantiationService),
__param(7, IContextKeyService),
__param(8, IListService),
__param(9, IConfigurationService)
], WorkbenchAsyncDataTree);
export { WorkbenchAsyncDataTree };
let WorkbenchCompressibleAsyncDataTree = class WorkbenchCompressibleAsyncDataTree extends CompressibleAsyncDataTree {
constructor(user, container, virtualDelegate, compressionDelegate, renderers, dataSource, options, instantiationService, contextKeyService, listService, configurationService) {
const { options: treeOptions, getTypeNavigationMode, disposable } = instantiationService.invokeFunction(workbenchTreeDataPreamble, options);
super(user, container, virtualDelegate, compressionDelegate, renderers, dataSource, treeOptions);
this.disposables.add(disposable);
this.internals = new WorkbenchTreeInternals(this, options, getTypeNavigationMode, options.overrideStyles, contextKeyService, listService, configurationService);
this.disposables.add(this.internals);
}
updateOptions(options) {
super.updateOptions(options);
this.internals.updateOptions(options);
}
};
WorkbenchCompressibleAsyncDataTree = __decorate([
__param(7, IInstantiationService),
__param(8, IContextKeyService),
__param(9, IListService),
__param(10, IConfigurationService)
], WorkbenchCompressibleAsyncDataTree);
export { WorkbenchCompressibleAsyncDataTree };
function getDefaultTreeFindMode(configurationService) {
const value = configurationService.getValue(defaultFindModeSettingKey);
if (value === 'highlight') {
return TreeFindMode.Highlight;
}
else if (value === 'filter') {
return TreeFindMode.Filter;
}
const deprecatedValue = configurationService.getValue(keyboardNavigationSettingKey);
if (deprecatedValue === 'simple' || deprecatedValue === 'highlight') {
return TreeFindMode.Highlight;
}
else if (deprecatedValue === 'filter') {
return TreeFindMode.Filter;
}
return undefined;
}
function getDefaultTreeFindMatchType(configurationService) {
const value = configurationService.getValue(defaultFindMatchTypeSettingKey);
if (value === 'fuzzy') {
return TreeFindMatchType.Fuzzy;
}
else if (value === 'contiguous') {
return TreeFindMatchType.Contiguous;
}
return undefined;
}
function workbenchTreeDataPreamble(accessor, options) {
var _a;
const configurationService = accessor.get(IConfigurationService);
const contextViewService = accessor.get(IContextViewService);
const contextKeyService = accessor.get(IContextKeyService);
const instantiationService = accessor.get(IInstantiationService);
const getTypeNavigationMode = () => {
// give priority to the context key value to specify a value
const modeString = contextKeyService.getContextKeyValue(WorkbenchListTypeNavigationModeKey);
if (modeString === 'automatic') {
return TypeNavigationMode.Automatic;
}
else if (modeString === 'trigger') {
return TypeNavigationMode.Trigger;
}
// also check the deprecated context key to set the mode to 'trigger'
const modeBoolean = contextKeyService.getContextKeyValue(WorkbenchListAutomaticKeyboardNavigationLegacyKey);
if (modeBoolean === false) {
return TypeNavigationMode.Trigger;
}
// finally, check the setting
const configString = configurationService.getValue(typeNavigationModeSettingKey);
if (configString === 'automatic') {
return TypeNavigationMode.Automatic;
}
else if (configString === 'trigger') {
return TypeNavigationMode.Trigger;
}
return undefined;
};
const horizontalScrolling = options.horizontalScrolling !== undefined ? options.horizontalScrolling : Boolean(configurationService.getValue(horizontalScrollingKey));
const [workbenchListOptions, disposable] = instantiationService.invokeFunction(toWorkbenchListOptions, options);
const paddingBottom = options.paddingBottom;
const renderIndentGuides = options.renderIndentGuides !== undefined ? options.renderIndentGuides : configurationService.getValue(treeRenderIndentGuidesKey);
return {
getTypeNavigationMode,
disposable,
options: {
// ...options, // TODO@Joao why is this not splatted here?
keyboardSupport: false,
...workbenchListOptions,
indent: typeof configurationService.getValue(treeIndentKey) === 'number' ? configurationService.getValue(treeIndentKey) : undefined,
renderIndentGuides,
smoothScrolling: Boolean(configurationService.getValue(listSmoothScrolling)),
defaultFindMode: getDefaultTreeFindMode(configurationService),
defaultFindMatchType: getDefaultTreeFindMatchType(configurationService),
horizontalScrolling,
scrollByPage: Boolean(configurationService.getValue(scrollByPageKey)),
paddingBottom: paddingBottom,
hideTwistiesOfChildlessElements: options.hideTwistiesOfChildlessElements,
expandOnlyOnTwistieClick: (_a = options.expandOnlyOnTwistieClick) !== null && _a !== void 0 ? _a : (configurationService.getValue(treeExpandMode) === 'doubleClick'),
contextViewProvider: contextViewService,
findWidgetStyles: defaultFindWidgetStyles,
enableStickyScroll: Boolean(configurationService.getValue(treeStickyScroll)),
stickyScrollMaxItemCount: Number(configurationService.getValue(treeStickyScrollMaxElements)),
}
};
}
let WorkbenchTreeInternals = class WorkbenchTreeInternals {
get onDidOpen() { return this.navigator.onDidOpen; }
constructor(tree, options, getTypeNavigationMode, overrideStyles, contextKeyService, listService, configurationService) {
var _a;
this.tree = tree;
this.disposables = [];
this.contextKeyService = createScopedContextKeyService(contextKeyService, tree);
this.disposables.push(createScrollObserver(this.contextKeyService, tree));
this.listSupportsMultiSelect = WorkbenchListSupportsMultiSelectContextKey.bindTo(this.contextKeyService);
this.listSupportsMultiSelect.set(options.multipleSelectionSupport !== false);
const listSelectionNavigation = WorkbenchListSelectionNavigation.bindTo(this.contextKeyService);
listSelectionNavigation.set(Boolean(options.selectionNavigation));
this.listSupportFindWidget = WorkbenchListSupportsFind.bindTo(this.contextKeyService);
this.listSupportFindWidget.set((_a = options.findWidgetEnabled) !== null && _a !== void 0 ? _a : true);
this.hasSelectionOrFocus = WorkbenchListHasSelectionOrFocus.bindTo(this.contextKeyService);
this.hasDoubleSelection = WorkbenchListDoubleSelection.bindTo(this.contextKeyService);
this.hasMultiSelection = WorkbenchListMultiSelection.bindTo(this.contextKeyService);
this.treeElementCanCollapse = WorkbenchTreeElementCanCollapse.bindTo(this.contextKeyService);
this.treeElementHasParent = WorkbenchTreeElementHasParent.bindTo(this.contextKeyService);
this.treeElementCanExpand = WorkbenchTreeElementCanExpand.bindTo(this.contextKeyService);
this.treeElementHasChild = WorkbenchTreeElementHasChild.bindTo(this.contextKeyService);
this.treeFindOpen = WorkbenchTreeFindOpen.bindTo(this.contextKeyService);
this.treeStickyScrollFocused = WorkbenchTreeStickyScrollFocused.bindTo(this.contextKeyService);
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
this.updateStyleOverrides(overrideStyles);
const updateCollapseContextKeys = () => {
const focus = tree.getFocus()[0];
if (!focus) {
return;
}
const node = tree.getNode(focus);
this.treeElementCanCollapse.set(node.collapsible && !node.collapsed);
this.treeElementHasParent.set(!!tree.getParentElement(focus));
this.treeElementCanExpand.set(node.collapsible && node.collapsed);
this.treeElementHasChild.set(!!tree.getFirstElementChild(focus));
};
const interestingContextKeys = new Set();
interestingContextKeys.add(WorkbenchListTypeNavigationModeKey);
interestingContextKeys.add(WorkbenchListAutomaticKeyboardNavigationLegacyKey);
this.disposables.push(this.contextKeyService, listService.register(tree), tree.onDidChangeSelection(() => {
const selection = tree.getSelection();
const focus = tree.getFocus();
this.contextKeyService.bufferChangeEvents(() => {
this.hasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);
this.hasMultiSelection.set(selection.length > 1);
this.hasDoubleSelection.set(selection.length === 2);
});
}), tree.onDidChangeFocus(() => {
const selection = tree.getSelection();
const focus = tree.getFocus();
this.hasSelectionOrFocus.set(selection.length > 0 || focus.length > 0);
updateCollapseContextKeys();
}), tree.onDidChangeCollapseState(updateCollapseContextKeys), tree.onDidChangeModel(updateCollapseContextKeys), tree.onDidChangeFindOpenState(enabled => this.treeFindOpen.set(enabled)), tree.onDidChangeStickyScrollFocused(focused => this.treeStickyScrollFocused.set(focused)), configurationService.onDidChangeConfiguration(e => {
let newOptions = {};
if (e.affectsConfiguration(multiSelectModifierSettingKey)) {
this._useAltAsMultipleSelectionModifier = useAltAsMultipleSelectionModifier(configurationService);
}
if (e.affectsConfiguration(treeIndentKey)) {
const indent = configurationService.getValue(treeIndentKey);
newOptions = { ...newOptions, indent };
}
if (e.affectsConfiguration(treeRenderIndentGuidesKey) && options.renderIndentGuides === undefined) {
const renderIndentGuides = configurationService.getValue(treeRenderIndentGuidesKey);
newOptions = { ...newOptions, renderIndentGuides };
}
if (e.affectsConfiguration(listSmoothScrolling)) {
const smoothScrolling = Boolean(configurationService.getValue(listSmoothScrolling));
newOptions = { ...newOptions, smoothScrolling };
}
if (e.affectsConfiguration(defaultFindModeSettingKey) || e.affectsConfiguration(keyboardNavigationSettingKey)) {
const defaultFindMode = getDefaultTreeFindMode(configurationService);
newOptions = { ...newOptions, defaultFindMode };
}
if (e.affectsConfiguration(typeNavigationModeSettingKey) || e.affectsConfiguration(keyboardNavigationSettingKey)) {
const typeNavigationMode = getTypeNavigationMode();
newOptions = { ...newOptions, typeNavigationMode };
}
if (e.affectsConfiguration(defaultFindMatchTypeSettingKey)) {
const defaultFindMatchType = getDefaultTreeFindMatchType(configurationService);
newOptions = { ...newOptions, defaultFindMatchType };
}
if (e.affectsConfiguration(horizontalScrollingKey) && options.horizontalScrolling === undefined) {
const horizontalScrolling = Boolean(configurationService.getValue(horizontalScrollingKey));
newOptions = { ...newOptions, horizontalScrolling };
}
if (e.affectsConfiguration(scrollByPageKey)) {
const scrollByPage = Boolean(configurationService.getValue(scrollByPageKey));
newOptions = { ...newOptions, scrollByPage };
}
if (e.affectsConfiguration(treeExpandMode) && options.expandOnlyOnTwistieClick === undefined) {
newOptions = { ...newOptions, expandOnlyOnTwistieClick: configurationService.getValue(treeExpandMode) === 'doubleClick' };
}
if (e.affectsConfiguration(treeStickyScroll)) {
const enableStickyScroll = configurationService.getValue(treeStickyScroll);
newOptions = { ...newOptions, enableStickyScroll };
}
if (e.affectsConfiguration(treeStickyScrollMaxElements)) {
const stickyScrollMaxItemCount = Math.max(1, configurationService.getValue(treeStickyScrollMaxElements));
newOptions = { ...newOptions, stickyScrollMaxItemCount };
}
if (e.affectsConfiguration(mouseWheelScrollSensitivityKey)) {
const mouseWheelScrollSensitivity = configurationService.getValue(mouseWheelScrollSensitivityKey);
newOptions = { ...newOptions, mouseWheelScrollSensitivity };
}
if (e.affectsConfiguration(fastScrollSensitivityKey)) {
const fastScrollSensitivity = configurationService.getValue(fastScrollSensitivityKey);
newOptions = { ...newOptions, fastScrollSensitivity };
}
if (Object.keys(newOptions).length > 0) {
tree.updateOptions(newOptions);
}
}), this.contextKeyService.onDidChangeContext(e => {
if (e.affectsSome(interestingContextKeys)) {
tree.updateOptions({ typeNavigationMode: getTypeNavigationMode() });
}
}));
this.navigator = new TreeResourceNavigator(tree, { configurationService, ...options });
this.disposables.push(this.navigator);
}
updateOptions(options) {
if (options.multipleSelectionSupport !== undefined) {