From 39979bc69f7aeb272ef78cfaa6934dfb92bf577b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20ROU=C3=8BN=C3=89?= Date: Thu, 13 Jun 2024 15:35:51 +0200 Subject: [PATCH] [3624] Fix issue with header separator not spanning entire node width MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: https://github.com/eclipse-sirius/sirius-web/issues/3624 Signed-off-by: Florian ROUËNÉ --- CHANGELOG.adoc | 1 + .../src/converter/IconLabelNodeConverter.ts | 2 + .../src/converter/convertLabel.ts | 14 ++++++- .../src/renderer/DiagramRenderer.types.ts | 4 ++ .../src/renderer/Label.tsx | 39 +++++++++++++++---- .../layout/FreeFormNodeLayoutHandler.ts | 7 ++-- .../src/renderer/layout/layoutNode.ts | 8 ++-- .../src/nodes/EllipseNodeLayoutHandler.ts | 2 +- 8 files changed, 60 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 0bcca80849e..0f630b1820f 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -54,6 +54,7 @@ More existing APIs will be migrated to this new common pattern. - https://github.com/eclipse-sirius/sirius-web/issues/3575[#3575] [core] Restore support for studio palette colors - https://github.com/eclipse-sirius/sirius-web/issues/3582[#3582] [tree] Restore the initial direct edit tree item label for the explorer - https://github.com/eclipse-sirius/sirius-web/issues/3611[#3611] [diagram] Fix missing creation tool image in the contextual palette +- https://github.com/eclipse-sirius/sirius-web/issues/3624[#3624] [diagram] Fix an issue where the header separator does not fill the entire width of the node === New Features diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/converter/IconLabelNodeConverter.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/converter/IconLabelNodeConverter.ts index ce487101b92..2aa76e11971 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/converter/IconLabelNodeConverter.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/converter/IconLabelNodeConverter.ts @@ -99,6 +99,8 @@ const toIconLabelNode = ( isHeader: insideLabel.isHeader, displayHeaderSeparator: insideLabel.displayHeaderSeparator, overflowStrategy: insideLabel.overflowStrategy, + headerSeparatorStyle: {}, + headerPosition: undefined, }; } diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/converter/convertLabel.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/converter/convertLabel.ts index df72189c3ce..97f338d66f1 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/converter/convertLabel.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/converter/convertLabel.ts @@ -45,19 +45,29 @@ export const convertInsideLabel = ( }, iconURL: labelStyle.iconURL, overflowStrategy: gqlInsideLabel.overflowStrategy, + headerSeparatorStyle: { + width: '100%', + }, + headerPosition: undefined, }; const alignement = AlignmentMap[gqlInsideLabel.insideLabelLocation]; if (alignement && alignement.isPrimaryVerticalAlignment) { if (alignement.primaryAlignment === 'TOP') { + if (insideLabel.isHeader) { + insideLabel.headerPosition = 'TOP'; + } if (insideLabel.displayHeaderSeparator && hasVisibleChild) { - insideLabel.style.borderBottom = borderStyle; + insideLabel.headerSeparatorStyle.borderBottom = borderStyle; } data.style = { ...data.style, display: 'flex', flexDirection: 'column', justifyContent: 'flex-start' }; } if (alignement.primaryAlignment === 'BOTTOM') { + if (insideLabel.isHeader) { + insideLabel.headerPosition = 'BOTTOM'; + } if (insideLabel.displayHeaderSeparator && hasVisibleChild) { - insideLabel.style.borderTop = borderStyle; + insideLabel.headerSeparatorStyle.borderTop = borderStyle; } data.style = { ...data.style, display: 'flex', flexDirection: 'column', justifyContent: 'flex-end' }; } diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/DiagramRenderer.types.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/DiagramRenderer.types.ts index 8b9c1e29b4f..433370326a8 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/DiagramRenderer.types.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/DiagramRenderer.types.ts @@ -88,8 +88,12 @@ export interface InsideLabel { isHeader: boolean; displayHeaderSeparator: boolean; overflowStrategy: LabelOverflowStrategy; + headerSeparatorStyle: React.CSSProperties; + headerPosition: HeaderPosition | undefined; } +export type HeaderPosition = 'TOP' | 'BOTTOM'; + export type LabelOverflowStrategy = 'NONE' | 'WRAP' | 'ELLIPSIS'; export interface EdgeLabel { diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/Label.tsx b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/Label.tsx index ce48dd59071..42e49f97903 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/Label.tsx +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/Label.tsx @@ -28,6 +28,27 @@ const getOverflowStrategy = (label: EdgeLabel | InsideLabel | OutsideLabel): Lab return undefined; }; +const isDisplayTopHeaderSeparator = (label: EdgeLabel | InsideLabel | OutsideLabel): boolean => { + if ('displayHeaderSeparator' in label) { + return label.displayHeaderSeparator && label.headerPosition === 'BOTTOM'; + } + return false; +}; + +const isDisplayBottomHeaderSeparator = (label: EdgeLabel | InsideLabel | OutsideLabel): boolean => { + if ('displayHeaderSeparator' in label) { + return label.displayHeaderSeparator && label.headerPosition === 'TOP'; + } + return false; +}; + +const getHeaderSeparatorStyle = (label: EdgeLabel | InsideLabel | OutsideLabel): React.CSSProperties | undefined => { + if ('headerSeparatorStyle' in label) { + return label.headerSeparatorStyle; + } + return undefined; +}; + const labelStyle = ( theme: Theme, style: React.CSSProperties, @@ -109,12 +130,16 @@ export const Label = memo(({ diagramElementId, label, faded, transform }: LabelP ); return ( -
- {content} -
+ <> + {isDisplayTopHeaderSeparator(label) &&
} +
+ {content} +
+ {isDisplayBottomHeaderSeparator(label) &&
} + ); }); diff --git a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/FreeFormNodeLayoutHandler.ts b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/FreeFormNodeLayoutHandler.ts index e8c4739550e..55c3ba5f515 100644 --- a/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/FreeFormNodeLayoutHandler.ts +++ b/packages/diagrams/frontend/sirius-components-diagrams/src/renderer/layout/FreeFormNodeLayoutHandler.ts @@ -84,8 +84,6 @@ export class FreeFormNodeLayoutHandler implements INodeLayoutHandler node.data.isBorderNode); const directNodesChildren = directChildren.filter((child) => !child.data.isBorderNode); @@ -95,7 +93,7 @@ export class FreeFormNodeLayoutHandler implements INodeLayoutHandler previouseNode.id === child.id); const previousPosition = computePreviousPosition(previousNode, child); const createdNode = newlyAddedNode?.id === child.id ? newlyAddedNode : undefined; - const headerHeightFootprint = getHeaderHeightFootprint(labelElement, withHeader, displayHeaderSeparator); + const headerHeightFootprint = getHeaderHeightFootprint(labelElement, node.data.insideLabel, 'TOP'); if (!!createdNode) { child.position = createdNode.position; @@ -128,6 +126,7 @@ export class FreeFormNodeLayoutHandler implements INodeLayoutHandler { let headerHeightFootprint = 0; + const withHeader: boolean = insideLabel?.isHeader ?? false; + const displayHeaderSeparator: boolean = insideLabel?.displayHeaderSeparator ?? false; if (!labelElement) { return headerHeightFootprint; } - if (withHeader) { + if (withHeader && insideLabel?.headerPosition === headerPosition) { headerHeightFootprint = labelElement.getBoundingClientRect().height; if (displayHeaderSeparator) { headerHeightFootprint += rectangularNodePadding; diff --git a/packages/sirius-web/frontend/sirius-web/src/nodes/EllipseNodeLayoutHandler.ts b/packages/sirius-web/frontend/sirius-web/src/nodes/EllipseNodeLayoutHandler.ts index edfc43d4fe9..b94d339cdcd 100644 --- a/packages/sirius-web/frontend/sirius-web/src/nodes/EllipseNodeLayoutHandler.ts +++ b/packages/sirius-web/frontend/sirius-web/src/nodes/EllipseNodeLayoutHandler.ts @@ -78,7 +78,7 @@ export class EllipseNodeLayoutHandler implements INodeLayoutHandler { const previousNode = (previousDiagram?.nodes ?? []).find((previouseNode) => previouseNode.id === child.id); const previousPosition = computePreviousPosition(previousNode, child); const createdNode = newlyAddedNode?.id === child.id ? newlyAddedNode : undefined; - const headerHeightFootprint = labelElement ? getHeaderHeightFootprint(labelElement, false, false) : 0; + const headerHeightFootprint = labelElement ? getHeaderHeightFootprint(labelElement, null, null) : 0; if (!!createdNode) { child.position = createdNode.position;