UNPKG

13 kBJavaScriptView Raw
1"use strict";
2// *****************************************************************************
3// Copyright (C) 2017 TypeFox and others.
4//
5// This program and the accompanying materials are made available under the
6// terms of the Eclipse Public License v. 2.0 which is available at
7// http://www.eclipse.org/legal/epl-2.0.
8//
9// This Source Code may also be made available under the following Secondary
10// Licenses when the conditions for such availability set forth in the Eclipse
11// Public License v. 2.0 are satisfied: GNU General Public License, version 2
12// with the GNU Classpath Exception which is available at
13// https://www.gnu.org/software/classpath/license.html.
14//
15// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16// *****************************************************************************
17var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20 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;
21 return c > 3 && r && Object.defineProperty(target, key, r), r;
22};
23var __metadata = (this && this.__metadata) || function (k, v) {
24 if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
25};
26Object.defineProperty(exports, "__esModule", { value: true });
27exports.TreeModelImpl = exports.TreeModel = void 0;
28const inversify_1 = require("inversify");
29const event_1 = require("../../common/event");
30const disposable_1 = require("../../common/disposable");
31const logger_1 = require("../../common/logger");
32const tree_1 = require("./tree");
33const tree_selection_1 = require("./tree-selection");
34const tree_expansion_1 = require("./tree-expansion");
35const tree_navigation_1 = require("./tree-navigation");
36const tree_iterator_1 = require("./tree-iterator");
37const tree_search_1 = require("./tree-search");
38const tree_focus_service_1 = require("./tree-focus-service");
39/**
40 * The tree model.
41 */
42exports.TreeModel = Symbol('TreeModel');
43let TreeModelImpl = class TreeModelImpl {
44 constructor() {
45 this.onChangedEmitter = new event_1.Emitter();
46 this.onOpenNodeEmitter = new event_1.Emitter();
47 this.toDispose = new disposable_1.DisposableCollection();
48 }
49 init() {
50 this.toDispose.push(this.tree);
51 this.toDispose.push(this.tree.onChanged(() => this.fireChanged()));
52 this.toDispose.push(this.selectionService);
53 this.toDispose.push(this.expansionService);
54 this.toDispose.push(this.expansionService.onExpansionChanged(node => {
55 this.fireChanged();
56 this.handleExpansion(node);
57 }));
58 this.toDispose.push(this.onOpenNodeEmitter);
59 this.toDispose.push(this.onChangedEmitter);
60 this.toDispose.push(this.treeSearch);
61 }
62 dispose() {
63 this.toDispose.dispose();
64 }
65 handleExpansion(node) {
66 this.selectIfAncestorOfSelected(node);
67 }
68 /**
69 * Select the given node if it is the ancestor of a selected node.
70 */
71 selectIfAncestorOfSelected(node) {
72 if (!node.expanded && this.selectedNodes.some(selectedNode => tree_1.CompositeTreeNode.isAncestor(node, selectedNode))) {
73 if (tree_selection_1.SelectableTreeNode.isVisible(node)) {
74 this.selectNode(node);
75 }
76 }
77 }
78 get root() {
79 return this.tree.root;
80 }
81 set root(root) {
82 this.tree.root = root;
83 }
84 get onChanged() {
85 return this.onChangedEmitter.event;
86 }
87 get onOpenNode() {
88 return this.onOpenNodeEmitter.event;
89 }
90 fireChanged() {
91 this.onChangedEmitter.fire(undefined);
92 }
93 get onNodeRefreshed() {
94 return this.tree.onNodeRefreshed;
95 }
96 getNode(id) {
97 return this.tree.getNode(id);
98 }
99 getFocusedNode() {
100 return this.focusService.focusedNode;
101 }
102 validateNode(node) {
103 return this.tree.validateNode(node);
104 }
105 async refresh(parent) {
106 if (parent) {
107 return this.tree.refresh(parent);
108 }
109 return this.tree.refresh();
110 }
111 // tslint:disable-next-line:typedef
112 get selectedNodes() {
113 return this.selectionService.selectedNodes;
114 }
115 // tslint:disable-next-line:typedef
116 get onSelectionChanged() {
117 return this.selectionService.onSelectionChanged;
118 }
119 get onExpansionChanged() {
120 return this.expansionService.onExpansionChanged;
121 }
122 async expandNode(raw) {
123 for (const node of this.getExpansionCandidates(raw)) {
124 if (tree_expansion_1.ExpandableTreeNode.is(node)) {
125 return this.expansionService.expandNode(node);
126 }
127 }
128 return undefined;
129 }
130 *getExpansionCandidates(raw) {
131 yield raw;
132 yield this.getFocusedNode();
133 yield* this.selectedNodes;
134 }
135 async collapseNode(raw) {
136 for (const node of this.getExpansionCandidates(raw)) {
137 if (tree_expansion_1.ExpandableTreeNode.is(node)) {
138 return this.expansionService.collapseNode(node);
139 }
140 }
141 return false;
142 }
143 async collapseAll(raw) {
144 const node = raw || this.getFocusedNode();
145 if (tree_selection_1.SelectableTreeNode.is(node)) {
146 this.selectNode(node);
147 }
148 if (tree_1.CompositeTreeNode.is(node)) {
149 return this.expansionService.collapseAll(node);
150 }
151 return false;
152 }
153 async toggleNodeExpansion(raw) {
154 for (const node of raw ? [raw] : this.selectedNodes) {
155 if (tree_expansion_1.ExpandableTreeNode.is(node)) {
156 await this.expansionService.toggleNodeExpansion(node);
157 }
158 }
159 }
160 selectPrevNode(type = tree_selection_1.TreeSelection.SelectionType.DEFAULT) {
161 const node = this.getPrevSelectableNode();
162 if (node) {
163 this.addSelection({ node, type });
164 }
165 }
166 getPrevSelectableNode(node = this.getFocusedNode()) {
167 if (!node) {
168 return this.getNextSelectableNode(this.root);
169 }
170 const iterator = this.createBackwardIterator(node);
171 return iterator && this.doGetNextNode(iterator, this.isVisibleSelectableNode.bind(this));
172 }
173 selectNextNode(type = tree_selection_1.TreeSelection.SelectionType.DEFAULT) {
174 const node = this.getNextSelectableNode();
175 if (node) {
176 this.addSelection({ node, type });
177 }
178 }
179 getNextSelectableNode(node) {
180 var _a;
181 if (node === void 0) { node = (_a = this.getFocusedNode()) !== null && _a !== void 0 ? _a : this.root; }
182 const iterator = this.createIterator(node);
183 return iterator && this.doGetNextNode(iterator, this.isVisibleSelectableNode.bind(this));
184 }
185 doGetNextNode(iterator, criterion) {
186 // Skip the first item. // TODO: clean this up, and skip the first item in a different way without loading everything.
187 iterator.next();
188 let result = iterator.next();
189 while (!result.done) {
190 if (criterion(result.value)) {
191 return result.value;
192 }
193 result = iterator.next();
194 }
195 return undefined;
196 }
197 isVisibleSelectableNode(node) {
198 return tree_selection_1.SelectableTreeNode.isVisible(node);
199 }
200 createBackwardIterator(node) {
201 const { filteredNodes } = this.treeSearch;
202 if (filteredNodes.length === 0) {
203 return node ? new tree_iterator_1.BottomUpTreeIterator(node, { pruneCollapsed: true }) : undefined;
204 }
205 if (node && filteredNodes.indexOf(node) === -1) {
206 return undefined;
207 }
208 return tree_iterator_1.Iterators.cycle(filteredNodes.slice().reverse(), node);
209 }
210 createIterator(node) {
211 const { filteredNodes } = this.treeSearch;
212 if (filteredNodes.length === 0) {
213 return node && this.createForwardIteratorForNode(node);
214 }
215 if (node && filteredNodes.indexOf(node) === -1) {
216 return undefined;
217 }
218 return tree_iterator_1.Iterators.cycle(filteredNodes, node);
219 }
220 createForwardIteratorForNode(node) {
221 return new tree_iterator_1.TopDownTreeIterator(node, { pruneCollapsed: true });
222 }
223 openNode(raw) {
224 const node = raw !== null && raw !== void 0 ? raw : this.focusService.focusedNode;
225 if (node) {
226 this.doOpenNode(node);
227 this.onOpenNodeEmitter.fire(node);
228 }
229 }
230 doOpenNode(node) {
231 if (tree_expansion_1.ExpandableTreeNode.is(node)) {
232 this.toggleNodeExpansion(node);
233 }
234 }
235 selectParent() {
236 const node = this.getFocusedNode();
237 if (node) {
238 const parent = tree_selection_1.SelectableTreeNode.getVisibleParent(node);
239 if (parent) {
240 this.selectNode(parent);
241 }
242 }
243 }
244 async navigateTo(nodeOrId) {
245 if (nodeOrId) {
246 const node = typeof nodeOrId === 'string' ? this.getNode(nodeOrId) : nodeOrId;
247 if (node) {
248 this.navigationService.push(node);
249 await this.doNavigate(node);
250 return node;
251 }
252 }
253 return undefined;
254 }
255 canNavigateForward() {
256 return !!this.navigationService.next;
257 }
258 canNavigateBackward() {
259 return !!this.navigationService.prev;
260 }
261 async navigateForward() {
262 const node = this.navigationService.advance();
263 if (node) {
264 await this.doNavigate(node);
265 }
266 }
267 async navigateBackward() {
268 const node = this.navigationService.retreat();
269 if (node) {
270 await this.doNavigate(node);
271 }
272 }
273 async doNavigate(node) {
274 this.tree.root = node;
275 if (tree_expansion_1.ExpandableTreeNode.is(node)) {
276 await this.expandNode(node);
277 }
278 if (tree_selection_1.SelectableTreeNode.is(node)) {
279 this.selectNode(node);
280 }
281 }
282 addSelection(selectionOrTreeNode) {
283 this.selectionService.addSelection(selectionOrTreeNode);
284 }
285 clearSelection() {
286 this.selectionService.clearSelection();
287 }
288 selectNode(node) {
289 this.addSelection(node);
290 }
291 toggleNode(node) {
292 this.addSelection({ node, type: tree_selection_1.TreeSelection.SelectionType.TOGGLE });
293 }
294 selectRange(node) {
295 this.addSelection({ node, type: tree_selection_1.TreeSelection.SelectionType.RANGE });
296 }
297 storeState() {
298 return {
299 selection: this.selectionService.storeState()
300 };
301 }
302 restoreState(state) {
303 if (state.selection) {
304 this.selectionService.restoreState(state.selection);
305 }
306 }
307 get onDidChangeBusy() {
308 return this.tree.onDidChangeBusy;
309 }
310 markAsBusy(node, ms, token) {
311 return this.tree.markAsBusy(node, ms, token);
312 }
313 get onDidUpdate() {
314 return this.tree.onDidUpdate;
315 }
316 markAsChecked(node, checked) {
317 this.tree.markAsChecked(node, checked);
318 }
319};
320__decorate([
321 (0, inversify_1.inject)(logger_1.ILogger),
322 __metadata("design:type", Object)
323], TreeModelImpl.prototype, "logger", void 0);
324__decorate([
325 (0, inversify_1.inject)(tree_1.Tree),
326 __metadata("design:type", Object)
327], TreeModelImpl.prototype, "tree", void 0);
328__decorate([
329 (0, inversify_1.inject)(tree_selection_1.TreeSelectionService),
330 __metadata("design:type", Object)
331], TreeModelImpl.prototype, "selectionService", void 0);
332__decorate([
333 (0, inversify_1.inject)(tree_expansion_1.TreeExpansionService),
334 __metadata("design:type", Object)
335], TreeModelImpl.prototype, "expansionService", void 0);
336__decorate([
337 (0, inversify_1.inject)(tree_navigation_1.TreeNavigationService),
338 __metadata("design:type", tree_navigation_1.TreeNavigationService)
339], TreeModelImpl.prototype, "navigationService", void 0);
340__decorate([
341 (0, inversify_1.inject)(tree_focus_service_1.TreeFocusService),
342 __metadata("design:type", Object)
343], TreeModelImpl.prototype, "focusService", void 0);
344__decorate([
345 (0, inversify_1.inject)(tree_search_1.TreeSearch),
346 __metadata("design:type", tree_search_1.TreeSearch)
347], TreeModelImpl.prototype, "treeSearch", void 0);
348__decorate([
349 (0, inversify_1.postConstruct)(),
350 __metadata("design:type", Function),
351 __metadata("design:paramtypes", []),
352 __metadata("design:returntype", void 0)
353], TreeModelImpl.prototype, "init", null);
354TreeModelImpl = __decorate([
355 (0, inversify_1.injectable)()
356], TreeModelImpl);
357exports.TreeModelImpl = TreeModelImpl;
358//# sourceMappingURL=tree-model.js.map
\No newline at end of file