|
1 | 1 | import { DisposableObject } from "../common/disposable-object"; |
2 | 2 | import { QueryTreeDataProvider } from "./query-tree-data-provider"; |
3 | 3 | import { QueryDiscovery } from "./query-discovery"; |
4 | | -import { window } from "vscode"; |
| 4 | +import { TextEditor, TreeView, window } from "vscode"; |
5 | 5 | import { App } from "../common/app"; |
| 6 | +import { QueryTreeViewItem } from "./query-tree-view-item"; |
6 | 7 |
|
7 | 8 | export class QueriesPanel extends DisposableObject { |
| 9 | + private readonly dataProvider: QueryTreeDataProvider; |
| 10 | + private readonly treeView: TreeView<QueryTreeViewItem>; |
| 11 | + |
8 | 12 | public constructor( |
9 | 13 | queryDiscovery: QueryDiscovery, |
10 | 14 | readonly app: App, |
11 | 15 | ) { |
12 | 16 | super(); |
13 | 17 |
|
14 | | - const dataProvider = new QueryTreeDataProvider(queryDiscovery, app); |
| 18 | + this.dataProvider = new QueryTreeDataProvider(queryDiscovery, app); |
| 19 | + |
| 20 | + this.treeView = window.createTreeView("codeQLQueries", { |
| 21 | + treeDataProvider: this.dataProvider, |
| 22 | + }); |
| 23 | + this.push(this.treeView); |
| 24 | + |
| 25 | + this.subscribeToTreeSelectionEvents(); |
| 26 | + } |
| 27 | + |
| 28 | + private subscribeToTreeSelectionEvents(): void { |
| 29 | + // Keep track of whether the user has changed their text editor while |
| 30 | + // the tree view was not visible. If so, we will focus the text editor |
| 31 | + // in the tree view when it becomes visible. |
| 32 | + let changedTextEditor: TextEditor | undefined = undefined; |
| 33 | + |
| 34 | + window.onDidChangeActiveTextEditor((textEditor) => { |
| 35 | + if (!this.treeView.visible) { |
| 36 | + changedTextEditor = textEditor; |
| 37 | + |
| 38 | + return; |
| 39 | + } |
| 40 | + |
| 41 | + // Reset the changedTextEditor variable so we don't try to show it when |
| 42 | + // the tree view becomes next visible. |
| 43 | + changedTextEditor = undefined; |
| 44 | + |
| 45 | + if (!textEditor) { |
| 46 | + return; |
| 47 | + } |
| 48 | + |
| 49 | + void this.revealTextEditor(textEditor); |
| 50 | + }); |
| 51 | + |
| 52 | + this.treeView.onDidChangeVisibility((e) => { |
| 53 | + if (!e.visible) { |
| 54 | + return; |
| 55 | + } |
| 56 | + |
| 57 | + if (!changedTextEditor) { |
| 58 | + return; |
| 59 | + } |
| 60 | + |
| 61 | + void this.revealTextEditor(changedTextEditor); |
| 62 | + }); |
| 63 | + |
| 64 | + // If there is an active text editor when activating the extension, we want to show it in the tree view. |
| 65 | + if (window.activeTextEditor) { |
| 66 | + // We need to wait for the data provider to load its data. Without this, we will end up in a situation |
| 67 | + // where we're trying to show an item that does not exist yet since the query discoverer has not yet |
| 68 | + // finished running. |
| 69 | + const initialEventDisposable = this.dataProvider.onDidChangeTreeData( |
| 70 | + () => { |
| 71 | + if (window.activeTextEditor && this.treeView.visible) { |
| 72 | + void this.revealTextEditor(window.activeTextEditor); |
| 73 | + } |
| 74 | + |
| 75 | + // We only want to listen to this event once, so dispose of the listener to unsubscribe. |
| 76 | + initialEventDisposable.dispose(); |
| 77 | + }, |
| 78 | + ); |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + private revealTextEditor(textEditor: TextEditor): void { |
| 83 | + const filePath = textEditor.document.uri.fsPath; |
| 84 | + |
| 85 | + const item = this.dataProvider.getTreeItemByPath(filePath); |
| 86 | + if (!item) { |
| 87 | + return; |
| 88 | + } |
| 89 | + |
| 90 | + if ( |
| 91 | + this.treeView.selection.length === 1 && |
| 92 | + this.treeView.selection[0].path === item.path |
| 93 | + ) { |
| 94 | + // The item is already selected |
| 95 | + return; |
| 96 | + } |
15 | 97 |
|
16 | | - const treeView = window.createTreeView("codeQLQueries", { |
17 | | - treeDataProvider: dataProvider, |
| 98 | + void this.treeView.reveal(item, { |
| 99 | + select: true, |
| 100 | + focus: false, |
18 | 101 | }); |
19 | | - this.push(treeView); |
20 | 102 | } |
21 | 103 | } |
0 commit comments