David Schuldenfrei
David Schuldenfrei

Reputation: 71

VsCode extension. How to select a tree view item on right click

I am writitng a VsCode extension. When the user Right Clicks on an item in the tree view, he gets the popup command, whose actions apply to the previously selected item. In VsCode itself, this isn't the case. RightCliking on New File, for instance, adds a file to the currently highlighted folder (Not the selected one). How can I replicate this behavior in my extensions?

Upvotes: 2

Views: 2610

Answers (2)

maninak
maninak

Reputation: 2726

VS Code automatically passes the matching child of the returned value of TreeDataProvider.getChildren() (colloquially called a "treeItem node" in the community) as the first param when calling your command.

So if you define a command like this:

commands.registerCommand('myExtension.peelOrange', (orange: Orange) => {
  /* do stuff */
})

then just make sure that your TreeDataProvider.getChildren() looks like the following:

export const orangesTreeDataProvider: TreeDataProvider<Orange> = {
  getTreeItem: (elem) => {
    return {
      contextValue: 'orange',
      id: elem.id,
      label: `${elem.weight} kg`,
    }
  },
  getChildren: (elem) => {
    const oranges: Orange[] = [orange1, orange2, /*...*/]
    return oranges
  }
}

As already explained, the shape of the param passed in your command will be whatever shape the items in the returned array of getChildren() have. To keep it simple I've kept it all as type Orange, but in a real-world use case you may find you need to attach additional metadata and methods on each of those oranges to be available inside getTreeItem() or the myExtension.peelOrange command. In such a case that new type would be called OrangeNode according to the conventions.

Upvotes: 0

David Schuldenfrei
David Schuldenfrei

Reputation: 71

I found the solution. When registering the command, which the right-click runs, add a parameter which is the Tree Node. When the command is invoked via the menu popup, this tree node will be the highlighted node, and not the selected node. For example replace the code

commands.registerCommand('myExtension.myCommand', () => this.command());

and later on:

command() {
}

with

commands.registerCommand('myExtension.myCommand', command(), this);

and later on:

command(node: TreeNode) {
    if (node) {
    } 
}

The if (node) is necessary, if the command may be invoked from a different context (like a button), in which case node would be undefined.

Upvotes: 2

Related Questions