diff --git a/packages/core/src/browser/common-frontend-contribution.ts b/packages/core/src/browser/common-frontend-contribution.ts
index 0772465578dc3..59b91ba310b48 100644
--- a/packages/core/src/browser/common-frontend-contribution.ts
+++ b/packages/core/src/browser/common-frontend-contribution.ts
@@ -1090,7 +1090,7 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
// if not yet contributed by Monaco, check runtime css variables to learn.
// TODO: Following are not yet supported/no respective elements in theia:
// list.focusBackground, list.focusForeground, list.inactiveFocusBackground, list.filterMatchBorder,
- // list.dropBackground, listFilterWidget.outline, listFilterWidget.noMatchesOutline, tree.indentGuidesStroke
+ // list.dropBackground, listFilterWidget.outline, listFilterWidget.noMatchesOutline
// list.invalidItemForeground,
// list.warningForeground, list.errorForeground => tree node needs an respective class
{ id: 'list.activeSelectionBackground', defaults: { dark: '#094771', light: '#0074E8' }, description: 'List/Tree background color for the selected item when the list/tree is active. An active list/tree has keyboard focus, an inactive does not.' },
@@ -1100,6 +1100,7 @@ export class CommonFrontendContribution implements FrontendApplicationContributi
{ id: 'list.hoverBackground', defaults: { dark: '#2A2D2E', light: '#F0F0F0' }, description: 'List/Tree background when hovering over items using the mouse.' },
{ id: 'list.hoverForeground', description: 'List/Tree foreground when hovering over items using the mouse.' },
{ id: 'list.filterMatchBackground', defaults: { dark: 'editor.findMatchHighlightBackground', light: 'editor.findMatchHighlightBackground' }, description: 'Background color of the filtered match.' },
+ { id: 'tree.inactiveIndentGuidesStroke', defaults: { dark: Color.transparent('tree.indentGuidesStroke', 0.4), light: Color.transparent('tree.indentGuidesStroke', 0.4), hc: Color.transparent('tree.indentGuidesStroke', 0.4) }, description: 'Tree stroke color for the inactive indentation guides.' },
// Editor Group & Tabs colors should be aligned with https://code.visualstudio.com/api/references/theme-color#editor-groups-tabs
{
diff --git a/packages/core/src/browser/core-preferences.ts b/packages/core/src/browser/core-preferences.ts
index 0bbbda9d654b3..e4dcd5ae3eeed 100644
--- a/packages/core/src/browser/core-preferences.ts
+++ b/packages/core/src/browser/core-preferences.ts
@@ -72,6 +72,12 @@ export const corePreferenceSchema: PreferenceSchema = {
'scope': 'language-overridable',
'enumDescriptions': Object.keys(SUPPORTED_ENCODINGS).map(key => SUPPORTED_ENCODINGS[key].labelLong),
'included': Object.keys(SUPPORTED_ENCODINGS).length > 1
+ },
+ 'workbench.tree.renderIndentGuides': {
+ type: 'string',
+ enum: ['onHover', 'none', 'always'],
+ default: 'onHover',
+ description: 'Controls whether the tree should render indent guides.'
}
}
};
@@ -85,6 +91,7 @@ export interface CoreConfiguration {
'workbench.iconTheme'?: string | null;
'workbench.silentNotifications': boolean;
'files.encoding': string
+ 'workbench.tree.renderIndentGuides': 'onHover' | 'none' | 'always';
}
export const CorePreferences = Symbol('CorePreferences');
diff --git a/packages/core/src/browser/style/tree.css b/packages/core/src/browser/style/tree.css
index cf40dd2f687eb..b17c617a16c58 100644
--- a/packages/core/src/browser/style/tree.css
+++ b/packages/core/src/browser/style/tree.css
@@ -139,3 +139,16 @@
.theia-tree-element-node {
width: 100%
}
+
+.theia-tree-node-indent {
+ position: absolute;
+ height: var(--theia-content-line-height);
+ border-right: var(--theia-border-width) solid transparent;
+}
+.theia-tree-node-indent.always,
+.theia-TreeContainer:hover .theia-tree-node-indent.hover {
+ border-color: var(--theia-tree-inactiveIndentGuidesStroke);
+}
+.theia-tree-node-indent.active {
+ border-color: var(--theia-tree-indentGuidesStroke);
+}
diff --git a/packages/core/src/browser/tree/tree-widget.tsx b/packages/core/src/browser/tree/tree-widget.tsx
index cfaec1187ac83..00f4a77e268a5 100644
--- a/packages/core/src/browser/tree/tree-widget.tsx
+++ b/packages/core/src/browser/tree/tree-widget.tsx
@@ -38,6 +38,7 @@ import { ElementExt } from '@phosphor/domutils';
import { TreeWidgetSelection } from './tree-widget-selection';
import { MaybePromise } from '../../common/types';
import { LabelProvider } from '../label-provider';
+import { CorePreferences } from '../core-preferences';
const debounce = require('lodash.debounce');
@@ -52,6 +53,7 @@ export const TREE_NODE_SEGMENT_GROW_CLASS = 'theia-TreeNodeSegmentGrow';
export const EXPANDABLE_TREE_NODE_CLASS = 'theia-ExpandableTreeNode';
export const COMPOSITE_TREE_NODE_CLASS = 'theia-CompositeTreeNode';
export const TREE_NODE_CAPTION_CLASS = 'theia-TreeNodeCaption';
+export const TREE_NODE_INDENT_GUIDE_CLASS = 'theia-tree-node-indent';
export const TreeProps = Symbol('TreeProps');
@@ -162,6 +164,9 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
@inject(LabelProvider)
protected readonly labelProvider: LabelProvider;
+ @inject(CorePreferences)
+ protected readonly corePreferences: CorePreferences;
+
protected shouldScrollToRow = true;
constructor(
@@ -251,6 +256,11 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
})
]);
}
+ this.toDispose.push(this.corePreferences.onPreferenceChanged(preference => {
+ if (preference.preferenceName === 'workbench.tree.renderIndentGuides') {
+ this.update();
+ }
+ }));
}
/**
@@ -478,7 +488,10 @@ export class TreeWidget extends ReactWidget implements StatefulWidget {
* Actually render the node row.
*/
protected doRenderNodeRow({ index, node, depth }: TreeWidget.NodeRow): React.ReactNode {
- return this.renderNode(node, { depth });
+ return