0
# File Tree Widget System
1
2
Interactive file tree widget providing a hierarchical view of the filesystem with lazy loading, drag-and-drop support, context menus, and full integration with Theia's tree framework. Essential for file explorers and file selection interfaces.
3
4
## Capabilities
5
6
### FileTree Class
7
8
Core tree implementation providing filesystem-specific tree behavior with lazy loading and file/directory distinction.
9
10
```typescript { .api }
11
/**
12
* Tree implementation for file system with lazy loading
13
*/
14
@injectable()
15
class FileTree extends TreeImpl {
16
/** Resolve child nodes for a parent node with lazy loading */
17
resolveChildren(parent: CompositeTreeNode): Promise<TreeNode[]>;
18
19
/** Resolve file statistics for a file stat node */
20
protected resolveFileStat(node: FileStatNode): Promise<FileStat | undefined>;
21
22
/** Convert file statistics to tree nodes */
23
protected toNodes(fileStat: FileStat, parent: CompositeTreeNode): Promise<TreeNode[]>;
24
25
/** Create individual tree node from file statistics */
26
protected toNode(fileStat: FileStat, parent: CompositeTreeNode): FileNode | DirNode;
27
}
28
```
29
30
### File Tree Model
31
32
Model class managing tree state, navigation, file system event handling, and location services.
33
34
```typescript { .api }
35
/**
36
* Model managing tree state, navigation, and events
37
*/
38
@injectable()
39
interface FileTreeModel extends CompressedTreeModel, LocationService {
40
/** Current root location of the file tree */
41
location: URI | undefined;
42
43
/** Get available drives/roots for navigation */
44
drives(): Promise<URI[]>;
45
46
/** Get currently selected file stat nodes */
47
readonly selectedFileStatNodes: Readonly<FileStatNode>[];
48
49
/** Find tree nodes by URI */
50
getNodesByUri(uri: URI): IterableIterator<TreeNode>;
51
52
/** Navigate to a specific location */
53
navigateTo(uri: URI): Promise<TreeNode | undefined>;
54
55
/** Copy file or directory to target location */
56
copy(source: URI, target: Readonly<FileStatNode>): Promise<URI>;
57
58
/** Move file or directory between locations */
59
move(source: TreeNode, target: TreeNode): Promise<URI | undefined>;
60
61
/** Handle file system change events */
62
protected onFilesChanged(changes: FileChangesEvent): void;
63
64
/** Check if root directory is affected by changes */
65
protected isRootAffected(changes: FileChangesEvent): boolean;
66
67
/** Get URIs affected by file system changes */
68
protected getAffectedUris(changes: FileChangesEvent): URI[];
69
70
/** Refresh nodes affected by file system changes */
71
protected refreshAffectedNodes(uris: URI[]): boolean;
72
73
/** Get tree nodes affected by URI changes */
74
protected getAffectedNodes(uris: URI[]): Map<string, CompositeTreeNode>;
75
76
/** Check if user should replace existing file */
77
protected shouldReplace(fileName: string): Promise<boolean>;
78
79
/** Refresh the tree or specific node */
80
refresh(node?: CompositeTreeNode): Promise<void>;
81
82
/** Paste from clipboard */
83
paste(node?: TreeNode): Promise<void>;
84
}
85
```
86
87
### File Tree Widget
88
89
Main widget component providing the complete file tree user interface with context menus, drag-and-drop, and keyboard navigation.
90
91
```typescript { .api }
92
/**
93
* Tree widget component with drag/drop and context menu support
94
*/
95
@injectable()
96
interface FileTreeWidget extends TreeWidget {
97
/** File tree model instance */
98
override readonly model: FileTreeModel;
99
100
/** Upload service for drag-and-drop file uploads */
101
protected readonly uploadService: FileUploadService;
102
103
/** Icon theme service for file icons */
104
protected readonly iconThemeService: IconThemeService;
105
106
/** Create custom node CSS class names */
107
protected createNodeClassNames(node: TreeNode, props: NodeProps): string[];
108
109
/** Render icon for tree node */
110
protected renderIcon(node: TreeNode, props: NodeProps): React.ReactNode;
111
112
/** Get tooltip text for node */
113
protected getNodeTooltip(node: TreeNode): string | undefined;
114
115
/** Handle drag start event for file operations */
116
protected handleDragStartEvent(node: TreeNode, event: React.DragEvent): void;
117
118
/** Handle drag over event for drop target validation */
119
protected handleDragOverEvent(node: TreeNode | undefined, event: React.DragEvent): void;
120
121
/** Handle drop event for file operations */
122
protected handleDropEvent(node: TreeNode | undefined, event: React.DragEvent): Promise<void>;
123
124
/** Get drop effect (copy or move) based on modifier keys */
125
protected getDropEffect(event: React.DragEvent): 'copy' | 'move';
126
127
/** Check if explorer arrows should be hidden */
128
protected get hidesExplorerArrows(): boolean;
129
130
/** Serialize node for storage */
131
protected deflateForStorage(node: TreeNode): object;
132
133
/** Deserialize node from storage */
134
protected inflateFromStorage(node: any, parent?: TreeNode): TreeNode;
135
}
136
```
137
138
### Tree Node Types
139
140
Type definitions for different kinds of tree nodes representing files and directories.
141
142
```typescript { .api }
143
/**
144
* Base tree node with file statistics
145
*/
146
interface FileStatNode extends SelectableTreeNode, Mutable<UriSelection>, FileSelection {
147
/** File statistics for this node (added at runtime) */
148
fileStat: FileStat;
149
}
150
151
/**
152
* Tree node representing a file
153
*/
154
type FileNode = FileStatNode;
155
156
/**
157
* Tree node representing a directory
158
*/
159
type DirNode = FileStatNode & ExpandableTreeNode;
160
```
161
162
### File Tree Label Provider
163
164
Service providing labels, icons, and decorations for tree nodes.
165
166
```typescript { .api }
167
/**
168
* Provides labels and icons for file tree nodes
169
*/
170
@injectable()
171
interface FileTreeLabelProvider extends LabelProvider {
172
/** Get display name for file stat node */
173
getName(element: FileStatNode): string;
174
175
/** Get long name (full path) for file stat node */
176
getLongName(element: FileStatNode): string;
177
178
/** Get icon class for file stat node */
179
getIcon(element: FileStatNode): string;
180
181
/** Get CSS classes for file stat node */
182
getClassNames(element: FileStatNode): string[];
183
184
/** Check if element affects this node's label */
185
affects(element: FileStatNode, event: DidChangeLabelEvent): boolean;
186
}
187
```
188
189
### File Tree Container
190
191
Dependency injection container configuration for file tree components.
192
193
```typescript { .api }
194
/**
195
* Create configured file tree container
196
*/
197
function createFileTreeContainer(parent: interfaces.Container): interfaces.Container;
198
199
/**
200
* Create configured file tree widget
201
*/
202
function createFileTreeWidget(parent: interfaces.Container): FileTreeWidget;
203
```
204
205
### File Tree Decorator Adapter
206
207
Decoration service for adding badges, colors, and visual indicators to tree nodes.
208
209
```typescript { .api }
210
/**
211
* Tree decorator for file-specific decorations
212
*/
213
@injectable()
214
interface FileTreeDecoratorAdapter extends TreeDecorator {
215
/** Unique identifier for this decorator */
216
readonly id: string;
217
218
/** Event fired when decorations change */
219
readonly onDidChangeDecorations: Event<(tree: Tree) => Map<string, TreeDecoration.Data>>;
220
221
/** Get decorations for all nodes in tree */
222
decorations(tree: Tree): MaybePromise<Map<string, TreeDecoration.Data>>;
223
224
/** Merge node and bubbled decorations */
225
protected mergeDecorations(ownDecoration?: TreeDecoration.Data, bubbledDecoration?: TreeDecoration.Data): TreeDecoration.Data | undefined;
226
227
/** Convert decorations to Theia format */
228
protected toTheiaDecoration(decorations: Decoration[], bubble?: boolean): TreeDecoration.Data;
229
230
/** Get URI for tree node */
231
protected getUriForNode(node: TreeNode): string | undefined;
232
233
/** Trigger decoration change event */
234
fireDidChangeDecorations(): void;
235
}
236
```
237
238
### Constants and CSS Classes
239
240
CSS classes and constants used by file tree components.
241
242
```typescript { .api }
243
/** Main file tree CSS class */
244
const FILE_TREE_CLASS = 'theia-FileTree';
245
246
/** File stat node CSS class */
247
const FILE_STAT_NODE_CLASS = 'theia-FileStatNode';
248
249
/** Directory node CSS class */
250
const DIR_NODE_CLASS = 'theia-DirNode';
251
252
/** File stat icon CSS class */
253
const FILE_STAT_ICON_CLASS = 'theia-FileStatIcon';
254
255
/** File tree container factory with default props */
256
function createFileTreeContainer(
257
parent: interfaces.Container,
258
overrides?: Partial<TreeContainerProps>
259
): Container;
260
```
261
262
**Usage Examples:**
263
264
```typescript
265
import { FileTreeWidget, FileTreeModel } from "@theia/filesystem/lib/browser";
266
import { URI } from "@theia/core/lib/common/uri";
267
268
// Create and configure file tree widget
269
const container = createFileTreeContainer(parentContainer);
270
const fileTree = container.get(FileTreeWidget);
271
272
// Set root location
273
fileTree.model.location = URI.parse('file:///workspace');
274
275
// Handle selection changes
276
fileTree.model.onSelectionChanged(selection => {
277
const selectedNodes = fileTree.model.selectedFileStatNodes;
278
for (const node of selectedNodes) {
279
console.log(`Selected: ${node.fileStat.resource.toString()}`);
280
}
281
});
282
283
// Navigate programmatically
284
await fileTree.model.navigateTo(URI.parse('file:///workspace/src'));
285
286
// Reveal specific file
287
await fileTree.revealFile(URI.parse('file:///workspace/package.json'));
288
289
// Handle file operations
290
fileTree.model.onDidFileOperation(event => {
291
console.log(`Operation: ${FileOperation[event.operation]} on ${event.target}`);
292
});
293
294
// Create files and folders
295
fileTree.createFile(); // Creates in current directory
296
fileTree.createFolder(); // Creates in current directory
297
298
// File upload
299
fileTree.model.onWillUpload(event => {
300
console.log(`Uploading to: ${event.parent.fileStat.resource}`);
301
});
302
303
// Custom context menu
304
fileTree.registerMenuAction({
305
commandId: 'custom.action',
306
label: 'Custom Action',
307
when: 'explorerResourceIsFile'
308
});
309
```
310
311
### Advanced Tree Operations
312
313
```typescript
314
import { FileTree } from "@theia/filesystem/lib/browser";
315
316
// Custom tree with additional functionality
317
@injectable()
318
class CustomFileTree extends FileTree {
319
320
// Override node creation for custom behavior
321
protected toNode(fileStat: FileStat, parent: CompositeTreeNode): FileNode | DirNode {
322
const node = super.toNode(fileStat, parent);
323
324
// Add custom properties
325
if (node.fileStat.isFile && node.fileStat.name.endsWith('.ts')) {
326
(node as any).isTypeScript = true;
327
}
328
329
return node;
330
}
331
332
// Custom filtering
333
protected async toNodes(fileStat: FileStat, parent: CompositeTreeNode): Promise<TreeNode[]> {
334
const nodes = await super.toNodes(fileStat, parent);
335
336
// Filter out hidden files
337
return nodes.filter(node =>
338
!node.name.startsWith('.') || this.showHiddenFiles
339
);
340
}
341
}
342
343
// Multi-selection operations
344
const selectedNodes = fileTree.model.selectedFileStatNodes;
345
if (selectedNodes.length > 1) {
346
// Bulk operations
347
await fileTree.delete(selectedNodes);
348
}
349
```