@theia/core
Version:
Theia is a cloud & desktop IDE framework implemented in TypeScript.
358 lines • 13 kB
JavaScript
"use strict";
// *****************************************************************************
// Copyright (C) 2017 TypeFox and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// http://www.eclipse.org/legal/epl-2.0.
//
// This Source Code may also be made available under the following Secondary
// Licenses when the conditions for such availability set forth in the Eclipse
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
// with the GNU Classpath Exception which is available at
// https://www.gnu.org/software/classpath/license.html.
//
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
// *****************************************************************************
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 __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TreeModelImpl = exports.TreeModel = void 0;
const inversify_1 = require("inversify");
const event_1 = require("../../common/event");
const disposable_1 = require("../../common/disposable");
const logger_1 = require("../../common/logger");
const tree_1 = require("./tree");
const tree_selection_1 = require("./tree-selection");
const tree_expansion_1 = require("./tree-expansion");
const tree_navigation_1 = require("./tree-navigation");
const tree_iterator_1 = require("./tree-iterator");
const tree_search_1 = require("./tree-search");
const tree_focus_service_1 = require("./tree-focus-service");
/**
* The tree model.
*/
exports.TreeModel = Symbol('TreeModel');
let TreeModelImpl = class TreeModelImpl {
constructor() {
this.onChangedEmitter = new event_1.Emitter();
this.onOpenNodeEmitter = new event_1.Emitter();
this.toDispose = new disposable_1.DisposableCollection();
}
init() {
this.toDispose.push(this.tree);
this.toDispose.push(this.tree.onChanged(() => this.fireChanged()));
this.toDispose.push(this.selectionService);
this.toDispose.push(this.expansionService);
this.toDispose.push(this.expansionService.onExpansionChanged(node => {
this.fireChanged();
this.handleExpansion(node);
}));
this.toDispose.push(this.onOpenNodeEmitter);
this.toDispose.push(this.onChangedEmitter);
this.toDispose.push(this.treeSearch);
}
dispose() {
this.toDispose.dispose();
}
handleExpansion(node) {
this.selectIfAncestorOfSelected(node);
}
/**
* Select the given node if it is the ancestor of a selected node.
*/
selectIfAncestorOfSelected(node) {
if (!node.expanded && this.selectedNodes.some(selectedNode => tree_1.CompositeTreeNode.isAncestor(node, selectedNode))) {
if (tree_selection_1.SelectableTreeNode.isVisible(node)) {
this.selectNode(node);
}
}
}
get root() {
return this.tree.root;
}
set root(root) {
this.tree.root = root;
}
get onChanged() {
return this.onChangedEmitter.event;
}
get onOpenNode() {
return this.onOpenNodeEmitter.event;
}
fireChanged() {
this.onChangedEmitter.fire(undefined);
}
get onNodeRefreshed() {
return this.tree.onNodeRefreshed;
}
getNode(id) {
return this.tree.getNode(id);
}
getFocusedNode() {
return this.focusService.focusedNode;
}
validateNode(node) {
return this.tree.validateNode(node);
}
async refresh(parent) {
if (parent) {
return this.tree.refresh(parent);
}
return this.tree.refresh();
}
// tslint:disable-next-line:typedef
get selectedNodes() {
return this.selectionService.selectedNodes;
}
// tslint:disable-next-line:typedef
get onSelectionChanged() {
return this.selectionService.onSelectionChanged;
}
get onExpansionChanged() {
return this.expansionService.onExpansionChanged;
}
async expandNode(raw) {
for (const node of this.getExpansionCandidates(raw)) {
if (tree_expansion_1.ExpandableTreeNode.is(node)) {
return this.expansionService.expandNode(node);
}
}
return undefined;
}
*getExpansionCandidates(raw) {
yield raw;
yield this.getFocusedNode();
yield* this.selectedNodes;
}
async collapseNode(raw) {
for (const node of this.getExpansionCandidates(raw)) {
if (tree_expansion_1.ExpandableTreeNode.is(node)) {
return this.expansionService.collapseNode(node);
}
}
return false;
}
async collapseAll(raw) {
const node = raw || this.getFocusedNode();
if (tree_selection_1.SelectableTreeNode.is(node)) {
this.selectNode(node);
}
if (tree_1.CompositeTreeNode.is(node)) {
return this.expansionService.collapseAll(node);
}
return false;
}
async toggleNodeExpansion(raw) {
for (const node of raw ? [raw] : this.selectedNodes) {
if (tree_expansion_1.ExpandableTreeNode.is(node)) {
await this.expansionService.toggleNodeExpansion(node);
}
}
}
selectPrevNode(type = tree_selection_1.TreeSelection.SelectionType.DEFAULT) {
const node = this.getPrevSelectableNode();
if (node) {
this.addSelection({ node, type });
}
}
getPrevSelectableNode(node = this.getFocusedNode()) {
if (!node) {
return this.getNextSelectableNode(this.root);
}
const iterator = this.createBackwardIterator(node);
return iterator && this.doGetNextNode(iterator, this.isVisibleSelectableNode.bind(this));
}
selectNextNode(type = tree_selection_1.TreeSelection.SelectionType.DEFAULT) {
const node = this.getNextSelectableNode();
if (node) {
this.addSelection({ node, type });
}
}
getNextSelectableNode(node) {
var _a;
if (node === void 0) { node = (_a = this.getFocusedNode()) !== null && _a !== void 0 ? _a : this.root; }
const iterator = this.createIterator(node);
return iterator && this.doGetNextNode(iterator, this.isVisibleSelectableNode.bind(this));
}
doGetNextNode(iterator, criterion) {
// Skip the first item. // TODO: clean this up, and skip the first item in a different way without loading everything.
iterator.next();
let result = iterator.next();
while (!result.done) {
if (criterion(result.value)) {
return result.value;
}
result = iterator.next();
}
return undefined;
}
isVisibleSelectableNode(node) {
return tree_selection_1.SelectableTreeNode.isVisible(node);
}
createBackwardIterator(node) {
const { filteredNodes } = this.treeSearch;
if (filteredNodes.length === 0) {
return node ? new tree_iterator_1.BottomUpTreeIterator(node, { pruneCollapsed: true }) : undefined;
}
if (node && filteredNodes.indexOf(node) === -1) {
return undefined;
}
return tree_iterator_1.Iterators.cycle(filteredNodes.slice().reverse(), node);
}
createIterator(node) {
const { filteredNodes } = this.treeSearch;
if (filteredNodes.length === 0) {
return node && this.createForwardIteratorForNode(node);
}
if (node && filteredNodes.indexOf(node) === -1) {
return undefined;
}
return tree_iterator_1.Iterators.cycle(filteredNodes, node);
}
createForwardIteratorForNode(node) {
return new tree_iterator_1.TopDownTreeIterator(node, { pruneCollapsed: true });
}
openNode(raw) {
const node = raw !== null && raw !== void 0 ? raw : this.focusService.focusedNode;
if (node) {
this.doOpenNode(node);
this.onOpenNodeEmitter.fire(node);
}
}
doOpenNode(node) {
if (tree_expansion_1.ExpandableTreeNode.is(node)) {
this.toggleNodeExpansion(node);
}
}
selectParent() {
const node = this.getFocusedNode();
if (node) {
const parent = tree_selection_1.SelectableTreeNode.getVisibleParent(node);
if (parent) {
this.selectNode(parent);
}
}
}
async navigateTo(nodeOrId) {
if (nodeOrId) {
const node = typeof nodeOrId === 'string' ? this.getNode(nodeOrId) : nodeOrId;
if (node) {
this.navigationService.push(node);
await this.doNavigate(node);
return node;
}
}
return undefined;
}
canNavigateForward() {
return !!this.navigationService.next;
}
canNavigateBackward() {
return !!this.navigationService.prev;
}
async navigateForward() {
const node = this.navigationService.advance();
if (node) {
await this.doNavigate(node);
}
}
async navigateBackward() {
const node = this.navigationService.retreat();
if (node) {
await this.doNavigate(node);
}
}
async doNavigate(node) {
this.tree.root = node;
if (tree_expansion_1.ExpandableTreeNode.is(node)) {
await this.expandNode(node);
}
if (tree_selection_1.SelectableTreeNode.is(node)) {
this.selectNode(node);
}
}
addSelection(selectionOrTreeNode) {
this.selectionService.addSelection(selectionOrTreeNode);
}
clearSelection() {
this.selectionService.clearSelection();
}
selectNode(node) {
this.addSelection(node);
}
toggleNode(node) {
this.addSelection({ node, type: tree_selection_1.TreeSelection.SelectionType.TOGGLE });
}
selectRange(node) {
this.addSelection({ node, type: tree_selection_1.TreeSelection.SelectionType.RANGE });
}
storeState() {
return {
selection: this.selectionService.storeState()
};
}
restoreState(state) {
if (state.selection) {
this.selectionService.restoreState(state.selection);
}
}
get onDidChangeBusy() {
return this.tree.onDidChangeBusy;
}
markAsBusy(node, ms, token) {
return this.tree.markAsBusy(node, ms, token);
}
get onDidUpdate() {
return this.tree.onDidUpdate;
}
markAsChecked(node, checked) {
this.tree.markAsChecked(node, checked);
}
};
__decorate([
(0, inversify_1.inject)(logger_1.ILogger),
__metadata("design:type", Object)
], TreeModelImpl.prototype, "logger", void 0);
__decorate([
(0, inversify_1.inject)(tree_1.Tree),
__metadata("design:type", Object)
], TreeModelImpl.prototype, "tree", void 0);
__decorate([
(0, inversify_1.inject)(tree_selection_1.TreeSelectionService),
__metadata("design:type", Object)
], TreeModelImpl.prototype, "selectionService", void 0);
__decorate([
(0, inversify_1.inject)(tree_expansion_1.TreeExpansionService),
__metadata("design:type", Object)
], TreeModelImpl.prototype, "expansionService", void 0);
__decorate([
(0, inversify_1.inject)(tree_navigation_1.TreeNavigationService),
__metadata("design:type", tree_navigation_1.TreeNavigationService)
], TreeModelImpl.prototype, "navigationService", void 0);
__decorate([
(0, inversify_1.inject)(tree_focus_service_1.TreeFocusService),
__metadata("design:type", Object)
], TreeModelImpl.prototype, "focusService", void 0);
__decorate([
(0, inversify_1.inject)(tree_search_1.TreeSearch),
__metadata("design:type", tree_search_1.TreeSearch)
], TreeModelImpl.prototype, "treeSearch", void 0);
__decorate([
(0, inversify_1.postConstruct)(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], TreeModelImpl.prototype, "init", null);
TreeModelImpl = __decorate([
(0, inversify_1.injectable)()
], TreeModelImpl);
exports.TreeModelImpl = TreeModelImpl;
//# sourceMappingURL=tree-model.js.map