Skip to content

Commit

Permalink
vscode: Support TreeItemLabel in TreeItem
Browse files Browse the repository at this point in the history
* Add `TreeItemLabel` to theia.d.ts
* Align `TreeItem.label` with VS Code API to support `TreeItemLabel` as a value
* Extend plugin tree view implementation to support showing `TreeItemLabel.highlights`
  * Extend `TreeViewNode` to also extend `DecoratedTreeNode`
  * Set highlights in tree node's decoration data to displays them

Fixes eclipse-theia#11148

Contributed on behalf of STMicroelectronics

Signed-off-by: Lucas Koehler <[email protected]>
  • Loading branch information
lucas-koehler committed Jun 13, 2022
1 parent b3adc5a commit 925bbce
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

- [plugin] moved `WebviewViewResolveContext` from `window` to `root` namespace [#11216](https://github.com/eclipse-theia/theia/pull/11216) - Contributed on behalf of STMicroelectronics
- [plugin] Add support for property `color` of `ThemeIcon`. [#11243](https://github.com/eclipse-theia/theia/pull/11243) - Contributed on behalf of STMicroelectronics
- [plugin] Add support for `TreeItemLabel` in `TreeItem`. [#11288](https://github.com/eclipse-theia/theia/pull/11288) - Contributed on behalf of STMicroelectronics

<a name="breaking_changes_1.27.0">[Breaking Changes:](#breaking_changes_1.27.0)</a>

Expand Down
2 changes: 2 additions & 0 deletions packages/plugin-ext/src/common/plugin-api-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,8 @@ export interface TreeViewItem {
id: string;

label: string;
/** Label highlights given as tuples of inclusive start index and exclusive end index. */
highlights?: [number, number][];

description?: string | boolean;

Expand Down
21 changes: 18 additions & 3 deletions packages/plugin-ext/src/main/browser/view/tree-view-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ import { MarkdownString } from '@theia/core/lib/common/markdown-rendering';
import { LabelParser } from '@theia/core/lib/browser/label-parser';
import { AccessibilityInformation } from '@theia/plugin';
import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
import { DecoratedTreeNode } from '@theia/core/lib/browser/tree/tree-decorator';
import { WidgetDecoration } from '@theia/core/lib/browser/widget-decoration';

export const TREE_NODE_HYPERLINK = 'theia-TreeNodeHyperlink';
export const VIEW_ITEM_CONTEXT_MENU: MenuPath = ['view-item-context-menu'];
Expand All @@ -57,7 +59,7 @@ export interface SelectionEventHandler {
readonly contextSelection: boolean;
}

export interface TreeViewNode extends SelectableTreeNode {
export interface TreeViewNode extends SelectableTreeNode, DecoratedTreeNode {
contextValue?: string;
command?: Command;
resourceUri?: string;
Expand All @@ -69,7 +71,7 @@ export interface TreeViewNode extends SelectableTreeNode {
}
export namespace TreeViewNode {
export function is(arg: TreeNode | undefined): arg is TreeViewNode {
return !!arg && SelectableTreeNode.is(arg);
return !!arg && SelectableTreeNode.is(arg) && DecoratedTreeNode.is(arg);
}
}

Expand All @@ -79,7 +81,7 @@ export interface CompositeTreeViewNode extends TreeViewNode, ExpandableTreeNode,
}
export namespace CompositeTreeViewNode {
export function is(arg: TreeNode | undefined): arg is CompositeTreeViewNode {
return !!arg && SelectableTreeNode.is(arg) && ExpandableTreeNode.is(arg) && CompositeTreeNode.is(arg);
return TreeViewNode.is(arg) && ExpandableTreeNode.is(arg) && CompositeTreeNode.is(arg);
}
}

Expand Down Expand Up @@ -150,11 +152,13 @@ export class PluginTree extends TreeImpl {
}

protected createTreeNode(item: TreeViewItem, parent: CompositeTreeNode): TreeNode {
const decorationData = this.toDecorationData(item);
const icon = this.toIconClass(item);
const resourceUri = item.resourceUri && URI.revive(item.resourceUri).toString();
const themeIcon = item.themeIcon ? item.themeIcon : item.collapsibleState !== TreeViewItemCollapsibleState.None ? { id: 'folder' } : { id: 'file' };
const update: Partial<TreeViewNode> = {
name: item.label,
decorationData,
icon,
description: item.description,
themeIcon,
Expand Down Expand Up @@ -191,6 +195,17 @@ export class PluginTree extends TreeImpl {
}, update);
}

protected toDecorationData(item: TreeViewItem): WidgetDecoration.Data {
let decoration: WidgetDecoration.Data = {};
if (item.highlights) {
const highlight = {
ranges: item.highlights.map(h => ({ offset: h[0], length: h[1] - h[0] }))
};
decoration = { highlight };
}
return decoration;
}

protected toIconClass(item: TreeViewItem): string | undefined {
if (item.icon) {
return 'fa ' + item.icon;
Expand Down
21 changes: 12 additions & 9 deletions packages/plugin-ext/src/plugin/tree/tree-views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import {
TreeDataProvider, TreeView, TreeViewExpansionEvent, TreeItem2, TreeItemLabel,
TreeDataProvider, TreeView, TreeViewExpansionEvent, TreeItem, TreeItemLabel,
TreeViewSelectionChangeEvent, TreeViewVisibilityChangeEvent
} from '@theia/plugin';
// TODO: extract `@theia/util` for event, disposable, cancellation and common types
Expand Down Expand Up @@ -295,16 +295,17 @@ class TreeViewExtImpl<T> implements Disposable {
return undefined;
}

private getTreeItemLabel(treeItem: TreeItem2): string | undefined {
private getTreeItemLabel(treeItem: TreeItem): string | undefined {
const treeItemLabel: string | TreeItemLabel | undefined = treeItem.label;
if (typeof treeItemLabel === 'object' && typeof treeItemLabel.label === 'string') {
return treeItemLabel.label;
} else {
return treeItem.label;
}
return typeof treeItemLabel === 'object' ? treeItemLabel.label : treeItemLabel;
}

private getTreeItemLabelHighlights(treeItem: TreeItem): [number, number][] | undefined {
const treeItemLabel: string | TreeItemLabel | undefined = treeItem.label;
return typeof treeItemLabel === 'object' ? treeItemLabel.highlights : undefined;
}

private getTreeItemIdLabel(treeItem: TreeItem2): string | undefined {
private getTreeItemIdLabel(treeItem: TreeItem): string | undefined {
let idLabel = this.getTreeItemLabel(treeItem);
// Use resource URI if label is not set
if (idLabel === undefined && treeItem.resourceUri) {
Expand Down Expand Up @@ -341,10 +342,11 @@ class TreeViewExtImpl<T> implements Disposable {

// Ask data provider for a tree item for the value
// Data provider must return theia.TreeItem
const treeItem: TreeItem2 = await this.treeDataProvider.getTreeItem(value);
const treeItem = await this.treeDataProvider.getTreeItem(value);
// Convert theia.TreeItem to the TreeViewItem

const label = this.getTreeItemLabel(treeItem);
const highlights = this.getTreeItemLabelHighlights(treeItem);
const idLabel = this.getTreeItemIdLabel(treeItem);

// Generate the ID
Expand Down Expand Up @@ -379,6 +381,7 @@ class TreeViewExtImpl<T> implements Disposable {
const treeViewItem = {
id,
label,
highlights,
icon,
iconUrl,
themeIcon,
Expand Down
21 changes: 19 additions & 2 deletions packages/plugin/src/theia.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5349,7 +5349,7 @@ export module '@theia/plugin' {
/**
* A human-readable string describing this item. When `falsy`, it is derived from [resourceUri](#TreeItem.resourceUri).
*/
label?: string;
label?: string | TreeItemLabel;

/**
* Optional id for the tree item that has to be unique across tree. The id is used to preserve the selection and expansion state of the tree item.
Expand Down Expand Up @@ -5425,7 +5425,7 @@ export module '@theia/plugin' {
* @param label A human-readable string describing this item
* @param collapsibleState [TreeItemCollapsibleState](#TreeItemCollapsibleState) of the tree item. Default is [TreeItemCollapsibleState.None](#TreeItemCollapsibleState.None)
*/
constructor(label: string, collapsibleState?: TreeItemCollapsibleState);
constructor(label: string | TreeItemLabel, collapsibleState?: TreeItemCollapsibleState);

/**
* @param resourceUri The [uri](#Uri) of the resource representing this item.
Expand All @@ -5452,6 +5452,23 @@ export module '@theia/plugin' {
Expanded = 2
}

/**
* Label describing the {@link TreeItem Tree item}
*/
export interface TreeItemLabel {

/**
* A human-readable string describing the {@link TreeItem Tree item}.
*/
label: string;

/**
* Ranges in the label to highlight. A range is defined as a tuple of two numbers where the
* first is the inclusive start index and the second the exclusive end index
*/
highlights?: [number, number][];
}

/**
* Represents the configuration. It is a merged view of
*
Expand Down

0 comments on commit 925bbce

Please sign in to comment.