From 7d25474f3642270f0d9fee8812146c5929489650 Mon Sep 17 00:00:00 2001 From: Omar Sadat Date: Mon, 10 May 2021 14:39:51 -0400 Subject: [PATCH] tree: use dot decoration on folders The following commit updates the rendering of tail decorations for composite tree nodes (nodes that contain children nodes like folders). The following updates the rendering of tail decorations for composite tree nodes (nodes that contain children nodes like folders). The updates include : - rendering a generic icon decoration (dot) for composite nodes with children with decoration data. - updates to the rendering logic to only render the decoration data with the highest priority so no duplicate generic icons are present. --- .../core/src/browser/tree/tree-widget.tsx | 82 +++++++++++++++---- .../src/browser/problem/problem-decorator.ts | 6 ++ 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/packages/core/src/browser/tree/tree-widget.tsx b/packages/core/src/browser/tree/tree-widget.tsx index 085f2a9f6df73..eb418ece3503e 100644 --- a/packages/core/src/browser/tree/tree-widget.tsx +++ b/packages/core/src/browser/tree/tree-widget.tsx @@ -729,26 +729,31 @@ export class TreeWidget extends ReactWidget implements StatefulWidget { * @param node the tree node. * @param icon the icon. */ - protected decorateIcon(node: TreeNode, icon: React.ReactNode | null): React.ReactNode { - // eslint-disable-next-line no-null/no-null - if (icon === null) { - // eslint-disable-next-line no-null/no-null - return null; + protected decorateIcon(node: TreeNode, icon: React.ReactNode): React.ReactNode { + // icon can be null or undefined + if (!icon) { + return; } - const overlayIcons: React.ReactNode[] = []; - new Map(this.getDecorationData(node, 'iconOverlay').reverse().filter(notEmpty) - .map(overlay => [overlay.position, overlay] as [TreeDecoration.IconOverlayPosition, TreeDecoration.IconOverlay | TreeDecoration.IconClassOverlay])) - .forEach((overlay, position) => { - const iconClasses = [TreeDecoration.Styles.DECORATOR_SIZE_CLASS, TreeDecoration.IconOverlayPosition.getStyle(position)]; + // if multiple overlays have the same overlay.position attribute, we'll de-duplicate those and only process the first one from the decoration array + const seenPosition = new Set(); + const overlays = this.getDecorationData(node, 'iconOverlay').filter(notEmpty); + + for (const overlay of overlays) { + if (!seenPosition.has(overlay.position)) { + seenPosition.add(overlay.position); + const iconClasses = [TreeDecoration.Styles.DECORATOR_SIZE_CLASS, TreeDecoration.IconOverlayPosition.getStyle(overlay.position)]; const style = (color?: string) => color === undefined ? {} : { color }; + if (overlay.background) { - overlayIcons.push( - ); + overlayIcons.push(); } - const overlayIcon = (overlay as TreeDecoration.IconOverlay).icon || (overlay as TreeDecoration.IconClassOverlay).iconClass; + + const overlayIcon = 'icon' in overlay ? overlay.icon : overlay.iconClass; overlayIcons.push(); - }); + } + } if (overlayIcons.length > 0) { return
{icon}{overlayIcons}
; @@ -763,14 +768,59 @@ export class TreeWidget extends ReactWidget implements StatefulWidget { * @param props the node properties. */ protected renderTailDecorations(node: TreeNode, props: NodeProps): React.ReactNode { + const decorationData = this.getDecorationData(node, 'tailDecorations').filter(notEmpty).reduce((acc, current) => acc.concat(current), []); + + if (decorationData.length === 0) { + return; + } + + if (CompositeTreeNode.is(node)) { + // If the node is a composite, we just want to use the decorationData with the highest priority (last element). + return this.renderTailDecorationsForCompositeNode(node, props, decorationData); + } else { + return this.renderTailDecorationsForNode(node, props, decorationData); + } + } + /** + * Render the tree node tail decorations for the highest priority. + * @param node the tree node. + * @param props the node properties. + * @param tailDecorations the decorationData array + */ + + protected renderTailDecorationsForCompositeNode(node: TreeNode, props: NodeProps, tailDecorations: + (TreeDecoration.TailDecoration | TreeDecoration.TailDecorationIcon | TreeDecoration.TailDecorationIconClass)[]): React.ReactNode { + const decoration = tailDecorations[tailDecorations.length - 1]; + const { tooltip } = decoration as TreeDecoration.TailDecoration; + const { fontData } = decoration as TreeDecoration.TailDecoration; + const color = (decoration as TreeDecoration.TailDecorationIcon).color; + const className = [TREE_NODE_SEGMENT_CLASS, TREE_NODE_TAIL_CLASS].join(' '); + const style = fontData ? this.applyFontStyles({}, fontData) : color ? { color } : undefined; + const content = ; + return
+ {content} +
; + } + + /** + * Render the tree node tail decorations if the node is not a composite. + * @param node the tree node. + * @param props the node properties. + * @param tailDecorations the decorationData array + */ + + protected renderTailDecorationsForNode(node: TreeNode, props: NodeProps, tailDecorations: + (TreeDecoration.TailDecoration | TreeDecoration.TailDecorationIcon | TreeDecoration.TailDecorationIconClass)[]): React.ReactNode { + return - {this.getDecorationData(node, 'tailDecorations').filter(notEmpty).reduce((acc, current) => acc.concat(current), []).map((decoration, index) => { + {tailDecorations!.map((decoration, index) => { + // If the node is not a composite, we apply the map method on the array of DecorationData. const { tooltip } = decoration; const { data, fontData } = decoration as TreeDecoration.TailDecoration; const color = (decoration as TreeDecoration.TailDecorationIcon).color; - const icon = (decoration as TreeDecoration.TailDecorationIcon).icon || (decoration as TreeDecoration.TailDecorationIconClass).iconClass; const className = [TREE_NODE_SEGMENT_CLASS, TREE_NODE_TAIL_CLASS].join(' '); const style = fontData ? this.applyFontStyles({}, fontData) : color ? { color } : undefined; + const icon = (decoration as TreeDecoration.TailDecorationIcon).icon || (decoration as TreeDecoration.TailDecorationIconClass).iconClass; const content = data ? data : icon ? : ''; return
{content} diff --git a/packages/markers/src/browser/problem/problem-decorator.ts b/packages/markers/src/browser/problem/problem-decorator.ts index 0aac3d40c53eb..7230f09112404 100644 --- a/packages/markers/src/browser/problem/problem-decorator.ts +++ b/packages/markers/src/browser/problem/problem-decorator.ts @@ -134,6 +134,12 @@ export class ProblemDecorator implements TreeDecorator { fontData: { color, }, + tailDecorations: [ + { + data: 'allo', + color + } + ], iconOverlay: { position, icon,