From 8f429c59bc1537d32f55496086785083a544286a Mon Sep 17 00:00:00 2001 From: Axel RICHARD Date: Tue, 16 Sep 2025 16:11:20 +0200 Subject: [PATCH] [1525] Add support for the management of the appearance of custom nodes Bug: https://github.com/eclipse-syson/syson/issues/1525 Signed-off-by: Axel RICHARD --- CHANGELOG.adoc | 6 + .../nodes/SysMLImportedPackageNodeStyle.java | 12 + .../application/nodes/SysMLNoteNodeStyle.java | 12 + .../nodes/SysMLPackageNodeStyle.java | 12 + .../nodes/SysMLViewFrameNodeStyle.java | 13 + ...sMLImportedPackageNodeAppearanceInput.java | 26 ++ .../dto/EditSysMLNoteNodeAppearanceInput.java | 25 ++ .../EditSysMLPackageNodeAppearanceInput.java | 25 ++ ...EditSysMLViewFrameNodeAppearanceInput.java | 25 ++ ...sMLImportedPackageNodeAppearanceInput.java | 23 ++ .../dto/SysMLNoteNodeAppearanceInput.java | 23 ++ .../dto/SysMLPackageNodeAppearanceInput.java | 23 ++ .../SysMLViewFrameNodeAppearanceInput.java | 23 ++ ...ortedPackageNodeAppearanceDataFetcher.java | 58 ++++ ...ditSysMLNoteNodeAppearanceDataFetcher.java | 58 ++++ ...SysMLPackageNodeAppearanceDataFetcher.java | 58 ++++ ...sMLViewFrameNodeAppearanceDataFetcher.java | 58 ++++ ...ckageNodeStyleAppearanceChangeHandler.java | 53 ++++ ...LNoteNodeStyleAppearanceChangeHandler.java | 53 ++++ ...ckageNodeStyleAppearanceChangeHandler.java | 53 ++++ ...FrameNodeStyleAppearanceChangeHandler.java | 55 ++++ ...rtedPackageNodeAppearanceEventHandler.java | 106 ++++++++ ...itSysMLNoteNodeAppearanceEventHandler.java | 106 ++++++++ ...ysMLPackageNodeAppearanceEventHandler.java | 106 ++++++++ ...MLViewFrameNodeAppearanceEventHandler.java | 108 ++++++++ ...LImportedPackageNodeAppearanceHandler.java | 170 ++++++++++++ .../SysMLNoteNodeAppearanceHandler.java | 168 ++++++++++++ .../SysMLPackageNodeAppearanceHandler.java | 168 ++++++++++++ .../SysMLViewFrameNodeAppearanceHandler.java | 196 ++++++++++++++ .../schema/sysmlcustomnodes.graphqls | 76 ++++++ ...dPackageNodeAppearanceControllerTests.java | 246 +++++++++++++++++ ...ysMLNoteNodeAppearanceControllerTests.java | 246 +++++++++++++++++ ...LPackageNodeAppearanceControllerTests.java | 246 +++++++++++++++++ ...iewFrameNodeAppearanceControllerTests.java | 249 ++++++++++++++++++ ...edPackageNodeAppearanceMutationRunner.java | 61 +++++ ...SysMLNoteNodeAppearanceMutationRunner.java | 61 +++++ ...MLPackageNodeAppearanceMutationRunner.java | 61 +++++ ...ViewFrameNodeAppearanceMutationRunner.java | 61 +++++ .../data/AllCustomNodesProjectData.java | 63 +++++ .../database-content/AllCustomNodes.sql | 100 +++++++ .../test/resources/scripts/dump-test-data.sh | 6 +- .../pages/release-notes/2025.10.0.adoc | 1 + frontend/syson-components/src/index.ts | 37 ++- ...tedPackageNodePaletteAppearanceSection.tsx | 39 +++ ...ckageNodePaletteAppearanceSection.types.ts | 19 ++ .../SysMLImportedPackageNodePart.tsx | 96 +++++++ .../SysMLImportedPackageNodePart.types.ts | 25 ++ ...pdateSysMLImportedPackageNodeAppearance.ts | 74 ++++++ ...ysMLImportedPackageNodeAppearance.types.ts | 47 ++++ .../SysMLNoteNodePaletteAppearanceSection.tsx | 39 +++ ...LNoteNodePaletteAppearanceSection.types.ts | 19 ++ .../src/nodes/note/SysMLNoteNodePart.tsx | 93 +++++++ .../src/nodes/note/SysMLNoteNodePart.types.ts | 25 ++ .../note/useUpdateSysMLNoteNodeAppearance.ts | 74 ++++++ .../useUpdateSysMLNoteNodeAppearance.types.ts | 47 ++++ ...sMLPackageNodePaletteAppearanceSection.tsx | 39 +++ ...ckageNodePaletteAppearanceSection.types.ts | 19 ++ .../nodes/package/SysMLPackageNodePart.tsx | 93 +++++++ .../package/SysMLPackageNodePart.types.ts | 25 ++ .../useUpdateSysMLPackageNodeAppearance.ts | 74 ++++++ ...eUpdateSysMLPackageNodeAppearance.types.ts | 48 ++++ ...LViewFrameNodePaletteAppearanceSection.tsx | 39 +++ ...FrameNodePaletteAppearanceSection.types.ts | 20 ++ .../view_frame/SysMLViewFrameNodePart.tsx | 101 +++++++ .../SysMLViewFrameNodePart.types.ts | 26 ++ .../useUpdateSysMLViewFrameNodeAppearance.ts | 74 ++++++ ...pdateSysMLViewFrameNodeAppearance.types.ts | 48 ++++ frontend/syson/src/index.tsx | 56 +++- 68 files changed, 4585 insertions(+), 10 deletions(-) create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLImportedPackageNodeAppearanceInput.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLNoteNodeAppearanceInput.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLPackageNodeAppearanceInput.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLViewFrameNodeAppearanceInput.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLImportedPackageNodeAppearanceInput.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLNoteNodeAppearanceInput.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLPackageNodeAppearanceInput.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLViewFrameNodeAppearanceInput.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLImportedPackageNodeAppearanceDataFetcher.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLNoteNodeAppearanceDataFetcher.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLPackageNodeAppearanceDataFetcher.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLViewFrameNodeAppearanceDataFetcher.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLImportedPackageNodeStyleAppearanceChangeHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLNoteNodeStyleAppearanceChangeHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLPackageNodeStyleAppearanceChangeHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLViewFrameNodeStyleAppearanceChangeHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLImportedPackageNodeAppearanceEventHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLNoteNodeAppearanceEventHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLPackageNodeAppearanceEventHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLViewFrameNodeAppearanceEventHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLImportedPackageNodeAppearanceHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLNoteNodeAppearanceHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLPackageNodeAppearanceHandler.java create mode 100644 backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLViewFrameNodeAppearanceHandler.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLImportedPackageNodeAppearanceControllerTests.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLNoteNodeAppearanceControllerTests.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLPackageNodeAppearanceControllerTests.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLViewFrameNodeAppearanceControllerTests.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLImportedPackageNodeAppearanceMutationRunner.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLNoteNodeAppearanceMutationRunner.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLPackageNodeAppearanceMutationRunner.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLViewFrameNodeAppearanceMutationRunner.java create mode 100644 backend/application/syson-application/src/test/java/org/eclipse/syson/application/data/AllCustomNodesProjectData.java create mode 100644 backend/application/syson-application/src/test/resources/scripts/database-content/AllCustomNodes.sql create mode 100644 frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePaletteAppearanceSection.tsx create mode 100644 frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePaletteAppearanceSection.types.ts create mode 100644 frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePart.tsx create mode 100644 frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePart.types.ts create mode 100644 frontend/syson-components/src/nodes/imported_package/useUpdateSysMLImportedPackageNodeAppearance.ts create mode 100644 frontend/syson-components/src/nodes/imported_package/useUpdateSysMLImportedPackageNodeAppearance.types.ts create mode 100644 frontend/syson-components/src/nodes/note/SysMLNoteNodePaletteAppearanceSection.tsx create mode 100644 frontend/syson-components/src/nodes/note/SysMLNoteNodePaletteAppearanceSection.types.ts create mode 100644 frontend/syson-components/src/nodes/note/SysMLNoteNodePart.tsx create mode 100644 frontend/syson-components/src/nodes/note/SysMLNoteNodePart.types.ts create mode 100644 frontend/syson-components/src/nodes/note/useUpdateSysMLNoteNodeAppearance.ts create mode 100644 frontend/syson-components/src/nodes/note/useUpdateSysMLNoteNodeAppearance.types.ts create mode 100644 frontend/syson-components/src/nodes/package/SysMLPackageNodePaletteAppearanceSection.tsx create mode 100644 frontend/syson-components/src/nodes/package/SysMLPackageNodePaletteAppearanceSection.types.ts create mode 100644 frontend/syson-components/src/nodes/package/SysMLPackageNodePart.tsx create mode 100644 frontend/syson-components/src/nodes/package/SysMLPackageNodePart.types.ts create mode 100644 frontend/syson-components/src/nodes/package/useUpdateSysMLPackageNodeAppearance.ts create mode 100644 frontend/syson-components/src/nodes/package/useUpdateSysMLPackageNodeAppearance.types.ts create mode 100644 frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePaletteAppearanceSection.tsx create mode 100644 frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePaletteAppearanceSection.types.ts create mode 100644 frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePart.tsx create mode 100644 frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePart.types.ts create mode 100644 frontend/syson-components/src/nodes/view_frame/useUpdateSysMLViewFrameNodeAppearance.ts create mode 100644 frontend/syson-components/src/nodes/view_frame/useUpdateSysMLViewFrameNodeAppearance.types.ts diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 2255cd20d..b39fadd10 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -82,6 +82,12 @@ Consumers may override this by providing an implementation of `org.eclipse.syson - https://github.com/eclipse-syson/syson/issues/1314[#1314] [diagrams] (Almost) All node descriptions are now synchronized (based on the exposed elements of ViewUsages). This contribution allows to switch from one _ViewDefinition_ to another one in a _ViewUsage_ without having to re-create the diagram. +- https://github.com/eclipse-syson/syson/issues/1525[#1525] [diagrams] Add support for the management of the appearance of custom nodes (`Package`, `ImportedPackage`, `Note` and `ViewFrame`) with the extension point `PaletteAppearanceSectionContribution`. +* `DiagramImporterSysMLPackageNodeStyleAppearanceChangeHandler implements IDiagramImporterNodeStyleAppearanceChangeHandler` allows the importation of diagram with `Package` nodes that have custom appearance. +* `EditSysMLPackageNodeAppearanceEventHandler implements IDiagramEventHandler` adds the needed `appearanceChanges` to the `diagramContext` after receiving the mutation. +* `SysMLPackageNodeAppearanceHandler implements INodeAppearanceHandler` handles how the node is updated from the `appearanceChanges`. +* A GraphQL mutation is also added through `editSysMLPackageNodeAppearance`. +* Same mechanism is applied to `ImportedPackage`, `Note` and `ViewFrame` nodes. == v2025.8.0 diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLImportedPackageNodeStyle.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLImportedPackageNodeStyle.java index 992ef9ce4..426f87850 100644 --- a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLImportedPackageNodeStyle.java +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLImportedPackageNodeStyle.java @@ -46,6 +46,10 @@ public static Builder newSysMLImportedPackageNodeStyle() { return new Builder(); } + public static Builder newSysMLImportedPackageNodeStyle(SysMLImportedPackageNodeStyle nodeStyle) { + return new Builder(nodeStyle); + } + public String getBackground() { return this.background; } @@ -95,6 +99,14 @@ private Builder() { // Prevent instantiation } + private Builder(SysMLImportedPackageNodeStyle nodeStyle) { + this.background = nodeStyle.getBackground(); + this.borderColor = nodeStyle.getBorderColor(); + this.borderSize = nodeStyle.getBorderSize(); + this.borderStyle = nodeStyle.getBorderStyle(); + this.childrenLayoutStrategy = nodeStyle.getChildrenLayoutStrategy(); + } + public Builder background(String background) { this.background = Objects.requireNonNull(background); return this; diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLNoteNodeStyle.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLNoteNodeStyle.java index c7d6e4140..106dcca0e 100644 --- a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLNoteNodeStyle.java +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLNoteNodeStyle.java @@ -47,6 +47,10 @@ public static Builder newSysMLNoteNodeStyle() { return new Builder(); } + public static Builder newSysMLNoteNodeStyle(SysMLNoteNodeStyle nodeStyle) { + return new Builder(nodeStyle); + } + public String getBackground() { return this.background; } @@ -96,6 +100,14 @@ private Builder() { // Prevent instantiation } + private Builder(SysMLNoteNodeStyle nodeStyle) { + this.background = nodeStyle.getBackground(); + this.borderColor = nodeStyle.getBorderColor(); + this.borderSize = nodeStyle.getBorderSize(); + this.borderStyle = nodeStyle.getBorderStyle(); + this.childrenLayoutStrategy = nodeStyle.getChildrenLayoutStrategy(); + } + public Builder background(String background) { this.background = Objects.requireNonNull(background); return this; diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLPackageNodeStyle.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLPackageNodeStyle.java index 4901e4634..0b8e74dc8 100644 --- a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLPackageNodeStyle.java +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLPackageNodeStyle.java @@ -47,6 +47,10 @@ public static Builder newSysMLPackageNodeStyle() { return new Builder(); } + public static Builder newSysMLPackageNodeStyle(SysMLPackageNodeStyle nodeStyle) { + return new Builder(nodeStyle); + } + public String getBackground() { return this.background; } @@ -96,6 +100,14 @@ private Builder() { // Prevent instantiation } + private Builder(SysMLPackageNodeStyle nodeStyle) { + this.background = nodeStyle.getBackground(); + this.borderColor = nodeStyle.getBorderColor(); + this.borderSize = nodeStyle.getBorderSize(); + this.borderStyle = nodeStyle.getBorderStyle(); + this.childrenLayoutStrategy = nodeStyle.getChildrenLayoutStrategy(); + } + public Builder background(String background) { this.background = Objects.requireNonNull(background); return this; diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLViewFrameNodeStyle.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLViewFrameNodeStyle.java index 036cc0a6b..dde18afbb 100644 --- a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLViewFrameNodeStyle.java +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLViewFrameNodeStyle.java @@ -48,6 +48,10 @@ public static Builder newSysMLViewFrameNodeStyle() { return new Builder(); } + public static Builder newSysMLViewFrameNodeStyle(SysMLViewFrameNodeStyle nodeStyle) { + return new Builder(nodeStyle); + } + public String getBackground() { return this.background; } @@ -103,6 +107,15 @@ private Builder() { // Prevent instantiation } + private Builder(SysMLViewFrameNodeStyle nodeStyle) { + this.background = nodeStyle.getBackground(); + this.borderColor = nodeStyle.getBorderColor(); + this.borderSize = nodeStyle.getBorderSize(); + this.borderStyle = nodeStyle.getBorderStyle(); + this.borderRadius = nodeStyle.getBorderRadius(); + this.childrenLayoutStrategy = nodeStyle.getChildrenLayoutStrategy(); + } + public Builder background(String background) { this.background = Objects.requireNonNull(background); return this; diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLImportedPackageNodeAppearanceInput.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLImportedPackageNodeAppearanceInput.java new file mode 100644 index 000000000..5949f5c1a --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLImportedPackageNodeAppearanceInput.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.dto; + +import java.util.UUID; + +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramInput; + +/** + * Input for the edition of a SysMLImportedPackage node's appearance. + * + * @author arichard + */ +public record EditSysMLImportedPackageNodeAppearanceInput(UUID id, String editingContextId, String representationId, String nodeId, SysMLImportedPackageNodeAppearanceInput appearance) + implements IDiagramInput { +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLNoteNodeAppearanceInput.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLNoteNodeAppearanceInput.java new file mode 100644 index 000000000..5a5f3f8d7 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLNoteNodeAppearanceInput.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.dto; + +import java.util.UUID; + +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramInput; + +/** + * Input for the edition of a SysMLPackage node's appearance. + * + * @author arichard + */ +public record EditSysMLNoteNodeAppearanceInput(UUID id, String editingContextId, String representationId, String nodeId, SysMLNoteNodeAppearanceInput appearance) implements IDiagramInput { +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLPackageNodeAppearanceInput.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLPackageNodeAppearanceInput.java new file mode 100644 index 000000000..3a1b2ceea --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLPackageNodeAppearanceInput.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.dto; + +import java.util.UUID; + +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramInput; + +/** + * Input for the edition of a SysMLPackage node's appearance. + * + * @author arichard + */ +public record EditSysMLPackageNodeAppearanceInput(UUID id, String editingContextId, String representationId, String nodeId, SysMLPackageNodeAppearanceInput appearance) implements IDiagramInput { +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLViewFrameNodeAppearanceInput.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLViewFrameNodeAppearanceInput.java new file mode 100644 index 000000000..f328012a6 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/EditSysMLViewFrameNodeAppearanceInput.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.dto; + +import java.util.UUID; + +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramInput; + +/** + * Input for the edition of a SysMLViewFrame node's appearance. + * + * @author arichard + */ +public record EditSysMLViewFrameNodeAppearanceInput(UUID id, String editingContextId, String representationId, String nodeId, SysMLViewFrameNodeAppearanceInput appearance) implements IDiagramInput { +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLImportedPackageNodeAppearanceInput.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLImportedPackageNodeAppearanceInput.java new file mode 100644 index 000000000..a37200262 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLImportedPackageNodeAppearanceInput.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.dto; + +import org.eclipse.sirius.components.diagrams.LineStyle; + +/** + * Input for the edition of a SysMLImportedPackage node's appearance. + * + * @author arichard + */ +public record SysMLImportedPackageNodeAppearanceInput(String background, String borderColor, Integer borderSize, LineStyle borderStyle) { +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLNoteNodeAppearanceInput.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLNoteNodeAppearanceInput.java new file mode 100644 index 000000000..f7e08a11d --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLNoteNodeAppearanceInput.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.dto; + +import org.eclipse.sirius.components.diagrams.LineStyle; + +/** + * Input for the edition of a SysMLNote node's appearance. + * + * @author arichard + */ +public record SysMLNoteNodeAppearanceInput(String background, String borderColor, Integer borderSize, LineStyle borderStyle) { +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLPackageNodeAppearanceInput.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLPackageNodeAppearanceInput.java new file mode 100644 index 000000000..5fb5af5b9 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLPackageNodeAppearanceInput.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.dto; + +import org.eclipse.sirius.components.diagrams.LineStyle; + +/** + * Input for the edition of a SysMLPackage node's appearance. + * + * @author arichard + */ +public record SysMLPackageNodeAppearanceInput(String background, String borderColor, Integer borderSize, LineStyle borderStyle) { +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLViewFrameNodeAppearanceInput.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLViewFrameNodeAppearanceInput.java new file mode 100644 index 000000000..8516dea34 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/dto/SysMLViewFrameNodeAppearanceInput.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.dto; + +import org.eclipse.sirius.components.diagrams.LineStyle; + +/** + * Input for the edition of a SysMLViewFrame node's appearance. + * + * @author arichard + */ +public record SysMLViewFrameNodeAppearanceInput(String background, String borderColor, Integer borderSize, LineStyle borderStyle, int borderRadius) { +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLImportedPackageNodeAppearanceDataFetcher.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLImportedPackageNodeAppearanceDataFetcher.java new file mode 100644 index 000000000..e83cb1878 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLImportedPackageNodeAppearanceDataFetcher.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.graphql; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.sirius.components.annotations.spring.graphql.MutationDataFetcher; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates; +import org.eclipse.sirius.components.graphql.api.IEditingContextDispatcher; +import org.eclipse.sirius.components.graphql.api.IExceptionWrapper; +import org.eclipse.syson.application.nodes.dto.EditSysMLImportedPackageNodeAppearanceInput; + +import graphql.schema.DataFetchingEnvironment; + +/** + * The data fetcher used to edit the appearance of a SysMLImportedPackage node. + * + * @author arichard + */ +@MutationDataFetcher(type = "Mutation", field = "editSysMLImportedPackageNodeAppearance") +public class MutationEditSysMLImportedPackageNodeAppearanceDataFetcher implements IDataFetcherWithFieldCoordinates> { + + private static final String INPUT_ARGUMENT = "input"; + + private final ObjectMapper objectMapper; + + private final IExceptionWrapper exceptionWrapper; + + private final IEditingContextDispatcher editingContextDispatcher; + + public MutationEditSysMLImportedPackageNodeAppearanceDataFetcher(ObjectMapper objectMapper, IExceptionWrapper exceptionWrapper, IEditingContextDispatcher editingContextDispatcher) { + this.objectMapper = Objects.requireNonNull(objectMapper); + this.exceptionWrapper = Objects.requireNonNull(exceptionWrapper); + this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher); + } + + @Override + public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { + Object argument = environment.getArgument(INPUT_ARGUMENT); + var input = this.objectMapper.convertValue(argument, EditSysMLImportedPackageNodeAppearanceInput.class); + + return this.exceptionWrapper.wrapMono(() -> this.editingContextDispatcher.dispatchMutation(input.editingContextId(), input), input).toFuture(); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLNoteNodeAppearanceDataFetcher.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLNoteNodeAppearanceDataFetcher.java new file mode 100644 index 000000000..2b9a630cb --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLNoteNodeAppearanceDataFetcher.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.graphql; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.sirius.components.annotations.spring.graphql.MutationDataFetcher; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates; +import org.eclipse.sirius.components.graphql.api.IEditingContextDispatcher; +import org.eclipse.sirius.components.graphql.api.IExceptionWrapper; +import org.eclipse.syson.application.nodes.dto.EditSysMLNoteNodeAppearanceInput; + +import graphql.schema.DataFetchingEnvironment; + +/** + * The data fetcher used to edit the appearance of a SysMLNote node. + * + * @author arichard + */ +@MutationDataFetcher(type = "Mutation", field = "editSysMLNoteNodeAppearance") +public class MutationEditSysMLNoteNodeAppearanceDataFetcher implements IDataFetcherWithFieldCoordinates> { + + private static final String INPUT_ARGUMENT = "input"; + + private final ObjectMapper objectMapper; + + private final IExceptionWrapper exceptionWrapper; + + private final IEditingContextDispatcher editingContextDispatcher; + + public MutationEditSysMLNoteNodeAppearanceDataFetcher(ObjectMapper objectMapper, IExceptionWrapper exceptionWrapper, IEditingContextDispatcher editingContextDispatcher) { + this.objectMapper = Objects.requireNonNull(objectMapper); + this.exceptionWrapper = Objects.requireNonNull(exceptionWrapper); + this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher); + } + + @Override + public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { + Object argument = environment.getArgument(INPUT_ARGUMENT); + var input = this.objectMapper.convertValue(argument, EditSysMLNoteNodeAppearanceInput.class); + + return this.exceptionWrapper.wrapMono(() -> this.editingContextDispatcher.dispatchMutation(input.editingContextId(), input), input).toFuture(); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLPackageNodeAppearanceDataFetcher.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLPackageNodeAppearanceDataFetcher.java new file mode 100644 index 000000000..3b461268f --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLPackageNodeAppearanceDataFetcher.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.graphql; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.sirius.components.annotations.spring.graphql.MutationDataFetcher; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates; +import org.eclipse.sirius.components.graphql.api.IEditingContextDispatcher; +import org.eclipse.sirius.components.graphql.api.IExceptionWrapper; +import org.eclipse.syson.application.nodes.dto.EditSysMLPackageNodeAppearanceInput; + +import graphql.schema.DataFetchingEnvironment; + +/** + * The data fetcher used to edit the appearance of a SysMLPackage node. + * + * @author arichard + */ +@MutationDataFetcher(type = "Mutation", field = "editSysMLPackageNodeAppearance") +public class MutationEditSysMLPackageNodeAppearanceDataFetcher implements IDataFetcherWithFieldCoordinates> { + + private static final String INPUT_ARGUMENT = "input"; + + private final ObjectMapper objectMapper; + + private final IExceptionWrapper exceptionWrapper; + + private final IEditingContextDispatcher editingContextDispatcher; + + public MutationEditSysMLPackageNodeAppearanceDataFetcher(ObjectMapper objectMapper, IExceptionWrapper exceptionWrapper, IEditingContextDispatcher editingContextDispatcher) { + this.objectMapper = Objects.requireNonNull(objectMapper); + this.exceptionWrapper = Objects.requireNonNull(exceptionWrapper); + this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher); + } + + @Override + public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { + Object argument = environment.getArgument(INPUT_ARGUMENT); + var input = this.objectMapper.convertValue(argument, EditSysMLPackageNodeAppearanceInput.class); + + return this.exceptionWrapper.wrapMono(() -> this.editingContextDispatcher.dispatchMutation(input.editingContextId(), input), input).toFuture(); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLViewFrameNodeAppearanceDataFetcher.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLViewFrameNodeAppearanceDataFetcher.java new file mode 100644 index 000000000..8d74b5b26 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/graphql/MutationEditSysMLViewFrameNodeAppearanceDataFetcher.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.graphql; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.sirius.components.annotations.spring.graphql.MutationDataFetcher; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.graphql.api.IDataFetcherWithFieldCoordinates; +import org.eclipse.sirius.components.graphql.api.IEditingContextDispatcher; +import org.eclipse.sirius.components.graphql.api.IExceptionWrapper; +import org.eclipse.syson.application.nodes.dto.EditSysMLViewFrameNodeAppearanceInput; + +import graphql.schema.DataFetchingEnvironment; + +/** + * The data fetcher used to edit the appearance of a SysMLViewFrame node. + * + * @author arichard + */ +@MutationDataFetcher(type = "Mutation", field = "editSysMLViewFrameNodeAppearance") +public class MutationEditSysMLViewFrameNodeAppearanceDataFetcher implements IDataFetcherWithFieldCoordinates> { + + private static final String INPUT_ARGUMENT = "input"; + + private final ObjectMapper objectMapper; + + private final IExceptionWrapper exceptionWrapper; + + private final IEditingContextDispatcher editingContextDispatcher; + + public MutationEditSysMLViewFrameNodeAppearanceDataFetcher(ObjectMapper objectMapper, IExceptionWrapper exceptionWrapper, IEditingContextDispatcher editingContextDispatcher) { + this.objectMapper = Objects.requireNonNull(objectMapper); + this.exceptionWrapper = Objects.requireNonNull(exceptionWrapper); + this.editingContextDispatcher = Objects.requireNonNull(editingContextDispatcher); + } + + @Override + public CompletableFuture get(DataFetchingEnvironment environment) throws Exception { + Object argument = environment.getArgument(INPUT_ARGUMENT); + var input = this.objectMapper.convertValue(argument, EditSysMLViewFrameNodeAppearanceInput.class); + + return this.exceptionWrapper.wrapMono(() -> this.editingContextDispatcher.dispatchMutation(input.editingContextId(), input), input).toFuture(); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLImportedPackageNodeStyleAppearanceChangeHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLImportedPackageNodeStyleAppearanceChangeHandler.java new file mode 100644 index 000000000..70a1fa6d2 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLImportedPackageNodeStyleAppearanceChangeHandler.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.services; + +import java.util.Optional; + +import org.eclipse.sirius.components.diagrams.INodeStyle; +import org.eclipse.sirius.components.diagrams.events.appearance.IAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBackgroundAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderColorAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderSizeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderStyleAppearanceChange; +import org.eclipse.sirius.web.application.project.services.api.IDiagramImporterNodeStyleAppearanceChangeHandler; +import org.eclipse.syson.application.nodes.SysMLImportedPackageNodeStyle; +import org.springframework.stereotype.Service; + +/** + * Implementation to handle SysMLImportedPackage node style. + * + * @author arichard + */ +@Service +public class DiagramImporterSysMLImportedPackageNodeStyleAppearanceChangeHandler implements IDiagramImporterNodeStyleAppearanceChangeHandler { + + @Override + public boolean canHandle(INodeStyle nodeStyle) { + return nodeStyle instanceof SysMLImportedPackageNodeStyle; + } + + @Override + public Optional handle(String nodeId, INodeStyle nodeStyle, String customizedStyleProperty) { + if (nodeStyle instanceof SysMLImportedPackageNodeStyle customNodeStyle) { + return switch (customizedStyleProperty) { + case SysMLImportedPackageNodeAppearanceHandler.BACKGROUND -> Optional.of(new NodeBackgroundAppearanceChange(nodeId, customNodeStyle.getBackground())); + case SysMLImportedPackageNodeAppearanceHandler.BORDER_COLOR -> Optional.of(new NodeBorderColorAppearanceChange(nodeId, customNodeStyle.getBorderColor())); + case SysMLImportedPackageNodeAppearanceHandler.BORDER_SIZE -> Optional.of(new NodeBorderSizeAppearanceChange(nodeId, customNodeStyle.getBorderSize())); + case SysMLImportedPackageNodeAppearanceHandler.BORDER_STYLE -> Optional.of(new NodeBorderStyleAppearanceChange(nodeId, customNodeStyle.getBorderStyle())); + default -> Optional.empty(); + }; + } + return Optional.empty(); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLNoteNodeStyleAppearanceChangeHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLNoteNodeStyleAppearanceChangeHandler.java new file mode 100644 index 000000000..7ab80fcb6 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLNoteNodeStyleAppearanceChangeHandler.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.services; + +import java.util.Optional; + +import org.eclipse.sirius.components.diagrams.INodeStyle; +import org.eclipse.sirius.components.diagrams.events.appearance.IAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBackgroundAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderColorAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderSizeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderStyleAppearanceChange; +import org.eclipse.sirius.web.application.project.services.api.IDiagramImporterNodeStyleAppearanceChangeHandler; +import org.eclipse.syson.application.nodes.SysMLNoteNodeStyle; +import org.springframework.stereotype.Service; + +/** + * Implementation to handle SysMLNote node style. + * + * @author arichard + */ +@Service +public class DiagramImporterSysMLNoteNodeStyleAppearanceChangeHandler implements IDiagramImporterNodeStyleAppearanceChangeHandler { + + @Override + public boolean canHandle(INodeStyle nodeStyle) { + return nodeStyle instanceof SysMLNoteNodeStyle; + } + + @Override + public Optional handle(String nodeId, INodeStyle nodeStyle, String customizedStyleProperty) { + if (nodeStyle instanceof SysMLNoteNodeStyle customNodeStyle) { + return switch (customizedStyleProperty) { + case SysMLNoteNodeAppearanceHandler.BACKGROUND -> Optional.of(new NodeBackgroundAppearanceChange(nodeId, customNodeStyle.getBackground())); + case SysMLNoteNodeAppearanceHandler.BORDER_COLOR -> Optional.of(new NodeBorderColorAppearanceChange(nodeId, customNodeStyle.getBorderColor())); + case SysMLNoteNodeAppearanceHandler.BORDER_SIZE -> Optional.of(new NodeBorderSizeAppearanceChange(nodeId, customNodeStyle.getBorderSize())); + case SysMLNoteNodeAppearanceHandler.BORDER_STYLE -> Optional.of(new NodeBorderStyleAppearanceChange(nodeId, customNodeStyle.getBorderStyle())); + default -> Optional.empty(); + }; + } + return Optional.empty(); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLPackageNodeStyleAppearanceChangeHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLPackageNodeStyleAppearanceChangeHandler.java new file mode 100644 index 000000000..a5aeacc57 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLPackageNodeStyleAppearanceChangeHandler.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.services; + +import java.util.Optional; + +import org.eclipse.sirius.components.diagrams.INodeStyle; +import org.eclipse.sirius.components.diagrams.events.appearance.IAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBackgroundAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderColorAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderSizeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderStyleAppearanceChange; +import org.eclipse.sirius.web.application.project.services.api.IDiagramImporterNodeStyleAppearanceChangeHandler; +import org.eclipse.syson.application.nodes.SysMLPackageNodeStyle; +import org.springframework.stereotype.Service; + +/** + * Implementation to handle SysMLPackage node style. + * + * @author arichard + */ +@Service +public class DiagramImporterSysMLPackageNodeStyleAppearanceChangeHandler implements IDiagramImporterNodeStyleAppearanceChangeHandler { + + @Override + public boolean canHandle(INodeStyle nodeStyle) { + return nodeStyle instanceof SysMLPackageNodeStyle; + } + + @Override + public Optional handle(String nodeId, INodeStyle nodeStyle, String customizedStyleProperty) { + if (nodeStyle instanceof SysMLPackageNodeStyle customNodeStyle) { + return switch (customizedStyleProperty) { + case SysMLPackageNodeAppearanceHandler.BACKGROUND -> Optional.of(new NodeBackgroundAppearanceChange(nodeId, customNodeStyle.getBackground())); + case SysMLPackageNodeAppearanceHandler.BORDER_COLOR -> Optional.of(new NodeBorderColorAppearanceChange(nodeId, customNodeStyle.getBorderColor())); + case SysMLPackageNodeAppearanceHandler.BORDER_SIZE -> Optional.of(new NodeBorderSizeAppearanceChange(nodeId, customNodeStyle.getBorderSize())); + case SysMLPackageNodeAppearanceHandler.BORDER_STYLE -> Optional.of(new NodeBorderStyleAppearanceChange(nodeId, customNodeStyle.getBorderStyle())); + default -> Optional.empty(); + }; + } + return Optional.empty(); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLViewFrameNodeStyleAppearanceChangeHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLViewFrameNodeStyleAppearanceChangeHandler.java new file mode 100644 index 000000000..217f28e2f --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/DiagramImporterSysMLViewFrameNodeStyleAppearanceChangeHandler.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.services; + +import java.util.Optional; + +import org.eclipse.sirius.components.diagrams.INodeStyle; +import org.eclipse.sirius.components.diagrams.events.appearance.IAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBackgroundAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderColorAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderRadiusAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderSizeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderStyleAppearanceChange; +import org.eclipse.sirius.web.application.project.services.api.IDiagramImporterNodeStyleAppearanceChangeHandler; +import org.eclipse.syson.application.nodes.SysMLViewFrameNodeStyle; +import org.springframework.stereotype.Service; + +/** + * Implementation to handle SysMLViewFrame node style. + * + * @author arichard + */ +@Service +public class DiagramImporterSysMLViewFrameNodeStyleAppearanceChangeHandler implements IDiagramImporterNodeStyleAppearanceChangeHandler { + + @Override + public boolean canHandle(INodeStyle nodeStyle) { + return nodeStyle instanceof SysMLViewFrameNodeStyle; + } + + @Override + public Optional handle(String nodeId, INodeStyle nodeStyle, String customizedStyleProperty) { + if (nodeStyle instanceof SysMLViewFrameNodeStyle customNodeStyle) { + return switch (customizedStyleProperty) { + case SysMLViewFrameNodeAppearanceHandler.BACKGROUND -> Optional.of(new NodeBackgroundAppearanceChange(nodeId, customNodeStyle.getBackground())); + case SysMLViewFrameNodeAppearanceHandler.BORDER_COLOR -> Optional.of(new NodeBorderColorAppearanceChange(nodeId, customNodeStyle.getBorderColor())); + case SysMLViewFrameNodeAppearanceHandler.BORDER_SIZE -> Optional.of(new NodeBorderSizeAppearanceChange(nodeId, customNodeStyle.getBorderSize())); + case SysMLViewFrameNodeAppearanceHandler.BORDER_STYLE -> Optional.of(new NodeBorderStyleAppearanceChange(nodeId, customNodeStyle.getBorderStyle())); + case SysMLViewFrameNodeAppearanceHandler.BORDER_RADIUS -> Optional.of(new NodeBorderRadiusAppearanceChange(nodeId, customNodeStyle.getBorderRadius())); + default -> Optional.empty(); + }; + } + return Optional.empty(); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLImportedPackageNodeAppearanceEventHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLImportedPackageNodeAppearanceEventHandler.java new file mode 100644 index 000000000..1ea7cd550 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLImportedPackageNodeAppearanceEventHandler.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.services; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.api.Monitoring; +import org.eclipse.sirius.components.collaborative.diagrams.DiagramChangeKind; +import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext; +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramEventHandler; +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramInput; +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramQueryService; +import org.eclipse.sirius.components.collaborative.diagrams.messages.ICollaborativeDiagramMessageService; +import org.eclipse.sirius.components.core.api.ErrorPayload; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.core.api.SuccessPayload; +import org.eclipse.sirius.components.diagrams.Node; +import org.eclipse.sirius.components.diagrams.events.appearance.EditAppearanceEvent; +import org.eclipse.sirius.components.diagrams.events.appearance.IAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBackgroundAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderColorAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderSizeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderStyleAppearanceChange; +import org.eclipse.syson.application.nodes.dto.EditSysMLImportedPackageNodeAppearanceInput; +import org.springframework.stereotype.Service; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import reactor.core.publisher.Sinks; + +/** + * Handle diagram events related to editing a SysMLImportedPackage node's appearance. + * + * @author arichard + */ +@Service +public class EditSysMLImportedPackageNodeAppearanceEventHandler implements IDiagramEventHandler { + + private final ICollaborativeDiagramMessageService messageService; + + private final IDiagramQueryService diagramQueryService; + + private final Counter counter; + + public EditSysMLImportedPackageNodeAppearanceEventHandler(ICollaborativeDiagramMessageService messageService, IDiagramQueryService diagramQueryService, MeterRegistry meterRegistry) { + this.messageService = Objects.requireNonNull(messageService); + this.diagramQueryService = Objects.requireNonNull(diagramQueryService); + this.counter = Counter.builder(Monitoring.EVENT_HANDLER) + .tag(Monitoring.NAME, this.getClass().getSimpleName()) + .register(meterRegistry); + } + + @Override + public boolean canHandle(IDiagramInput diagramInput) { + return diagramInput instanceof EditSysMLImportedPackageNodeAppearanceInput; + } + + @Override + public void handle(Sinks.One payloadSink, Sinks.Many changeDescriptionSink, IEditingContext editingContext, DiagramContext diagramContext, + IDiagramInput diagramInput) { + this.counter.increment(); + + String message = this.messageService.invalidInput(diagramInput.getClass().getSimpleName(), EditSysMLImportedPackageNodeAppearanceInput.class.getSimpleName()); + IPayload payload = new ErrorPayload(diagramInput.id(), message); + ChangeDescription changeDescription = new ChangeDescription(ChangeKind.NOTHING, diagramInput.representationId(), diagramInput); + + if (diagramInput instanceof EditSysMLImportedPackageNodeAppearanceInput editAppearanceInput) { + String nodeId = editAppearanceInput.nodeId(); + Optional optionalNode = this.diagramQueryService.findNodeById(diagramContext.diagram(), nodeId); + if (optionalNode.isPresent()) { + List appearanceChanges = new ArrayList<>(); + + Optional.ofNullable(editAppearanceInput.appearance().background()).ifPresent(background -> appearanceChanges.add(new NodeBackgroundAppearanceChange(nodeId, background))); + Optional.ofNullable(editAppearanceInput.appearance().borderColor()).ifPresent(borderColor -> appearanceChanges.add(new NodeBorderColorAppearanceChange(nodeId, borderColor))); + Optional.ofNullable(editAppearanceInput.appearance().borderSize()).ifPresent(borderSize -> appearanceChanges.add(new NodeBorderSizeAppearanceChange(nodeId, borderSize))); + Optional.ofNullable(editAppearanceInput.appearance().borderStyle()).ifPresent(borderStyle -> appearanceChanges.add(new NodeBorderStyleAppearanceChange(nodeId, borderStyle))); + + diagramContext.diagramEvents().add(new EditAppearanceEvent(appearanceChanges)); + payload = new SuccessPayload(diagramInput.id()); + changeDescription = new ChangeDescription(DiagramChangeKind.DIAGRAM_APPEARANCE_CHANGE, diagramInput.representationId(), diagramInput); + } else { + String nodeNotFoundMessage = this.messageService.nodeNotFound(nodeId); + payload = new ErrorPayload(diagramInput.id(), nodeNotFoundMessage); + } + } + + payloadSink.tryEmitValue(payload); + changeDescriptionSink.tryEmitNext(changeDescription); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLNoteNodeAppearanceEventHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLNoteNodeAppearanceEventHandler.java new file mode 100644 index 000000000..ee243c5ff --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLNoteNodeAppearanceEventHandler.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.services; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.api.Monitoring; +import org.eclipse.sirius.components.collaborative.diagrams.DiagramChangeKind; +import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext; +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramEventHandler; +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramInput; +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramQueryService; +import org.eclipse.sirius.components.collaborative.diagrams.messages.ICollaborativeDiagramMessageService; +import org.eclipse.sirius.components.core.api.ErrorPayload; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.core.api.SuccessPayload; +import org.eclipse.sirius.components.diagrams.Node; +import org.eclipse.sirius.components.diagrams.events.appearance.EditAppearanceEvent; +import org.eclipse.sirius.components.diagrams.events.appearance.IAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBackgroundAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderColorAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderSizeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderStyleAppearanceChange; +import org.eclipse.syson.application.nodes.dto.EditSysMLNoteNodeAppearanceInput; +import org.springframework.stereotype.Service; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import reactor.core.publisher.Sinks; + +/** + * Handle diagram events related to editing a SysMLNote node's appearance. + * + * @author arichard + */ +@Service +public class EditSysMLNoteNodeAppearanceEventHandler implements IDiagramEventHandler { + + private final ICollaborativeDiagramMessageService messageService; + + private final IDiagramQueryService diagramQueryService; + + private final Counter counter; + + public EditSysMLNoteNodeAppearanceEventHandler(ICollaborativeDiagramMessageService messageService, IDiagramQueryService diagramQueryService, MeterRegistry meterRegistry) { + this.messageService = Objects.requireNonNull(messageService); + this.diagramQueryService = Objects.requireNonNull(diagramQueryService); + this.counter = Counter.builder(Monitoring.EVENT_HANDLER) + .tag(Monitoring.NAME, this.getClass().getSimpleName()) + .register(meterRegistry); + } + + @Override + public boolean canHandle(IDiagramInput diagramInput) { + return diagramInput instanceof EditSysMLNoteNodeAppearanceInput; + } + + @Override + public void handle(Sinks.One payloadSink, Sinks.Many changeDescriptionSink, IEditingContext editingContext, DiagramContext diagramContext, + IDiagramInput diagramInput) { + this.counter.increment(); + + String message = this.messageService.invalidInput(diagramInput.getClass().getSimpleName(), EditSysMLNoteNodeAppearanceInput.class.getSimpleName()); + IPayload payload = new ErrorPayload(diagramInput.id(), message); + ChangeDescription changeDescription = new ChangeDescription(ChangeKind.NOTHING, diagramInput.representationId(), diagramInput); + + if (diagramInput instanceof EditSysMLNoteNodeAppearanceInput editAppearanceInput) { + String nodeId = editAppearanceInput.nodeId(); + Optional optionalNode = this.diagramQueryService.findNodeById(diagramContext.diagram(), nodeId); + if (optionalNode.isPresent()) { + List appearanceChanges = new ArrayList<>(); + + Optional.ofNullable(editAppearanceInput.appearance().background()).ifPresent(background -> appearanceChanges.add(new NodeBackgroundAppearanceChange(nodeId, background))); + Optional.ofNullable(editAppearanceInput.appearance().borderColor()).ifPresent(borderColor -> appearanceChanges.add(new NodeBorderColorAppearanceChange(nodeId, borderColor))); + Optional.ofNullable(editAppearanceInput.appearance().borderSize()).ifPresent(borderSize -> appearanceChanges.add(new NodeBorderSizeAppearanceChange(nodeId, borderSize))); + Optional.ofNullable(editAppearanceInput.appearance().borderStyle()).ifPresent(borderStyle -> appearanceChanges.add(new NodeBorderStyleAppearanceChange(nodeId, borderStyle))); + + diagramContext.diagramEvents().add(new EditAppearanceEvent(appearanceChanges)); + payload = new SuccessPayload(diagramInput.id()); + changeDescription = new ChangeDescription(DiagramChangeKind.DIAGRAM_APPEARANCE_CHANGE, diagramInput.representationId(), diagramInput); + } else { + String nodeNotFoundMessage = this.messageService.nodeNotFound(nodeId); + payload = new ErrorPayload(diagramInput.id(), nodeNotFoundMessage); + } + } + + payloadSink.tryEmitValue(payload); + changeDescriptionSink.tryEmitNext(changeDescription); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLPackageNodeAppearanceEventHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLPackageNodeAppearanceEventHandler.java new file mode 100644 index 000000000..2729da428 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLPackageNodeAppearanceEventHandler.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.services; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.api.Monitoring; +import org.eclipse.sirius.components.collaborative.diagrams.DiagramChangeKind; +import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext; +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramEventHandler; +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramInput; +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramQueryService; +import org.eclipse.sirius.components.collaborative.diagrams.messages.ICollaborativeDiagramMessageService; +import org.eclipse.sirius.components.core.api.ErrorPayload; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.core.api.SuccessPayload; +import org.eclipse.sirius.components.diagrams.Node; +import org.eclipse.sirius.components.diagrams.events.appearance.EditAppearanceEvent; +import org.eclipse.sirius.components.diagrams.events.appearance.IAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBackgroundAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderColorAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderSizeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderStyleAppearanceChange; +import org.eclipse.syson.application.nodes.dto.EditSysMLPackageNodeAppearanceInput; +import org.springframework.stereotype.Service; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import reactor.core.publisher.Sinks; + +/** + * Handle diagram events related to editing a SysMLPackage node's appearance. + * + * @author arichard + */ +@Service +public class EditSysMLPackageNodeAppearanceEventHandler implements IDiagramEventHandler { + + private final ICollaborativeDiagramMessageService messageService; + + private final IDiagramQueryService diagramQueryService; + + private final Counter counter; + + public EditSysMLPackageNodeAppearanceEventHandler(ICollaborativeDiagramMessageService messageService, IDiagramQueryService diagramQueryService, MeterRegistry meterRegistry) { + this.messageService = Objects.requireNonNull(messageService); + this.diagramQueryService = Objects.requireNonNull(diagramQueryService); + this.counter = Counter.builder(Monitoring.EVENT_HANDLER) + .tag(Monitoring.NAME, this.getClass().getSimpleName()) + .register(meterRegistry); + } + + @Override + public boolean canHandle(IDiagramInput diagramInput) { + return diagramInput instanceof EditSysMLPackageNodeAppearanceInput; + } + + @Override + public void handle(Sinks.One payloadSink, Sinks.Many changeDescriptionSink, IEditingContext editingContext, DiagramContext diagramContext, + IDiagramInput diagramInput) { + this.counter.increment(); + + String message = this.messageService.invalidInput(diagramInput.getClass().getSimpleName(), EditSysMLPackageNodeAppearanceInput.class.getSimpleName()); + IPayload payload = new ErrorPayload(diagramInput.id(), message); + ChangeDescription changeDescription = new ChangeDescription(ChangeKind.NOTHING, diagramInput.representationId(), diagramInput); + + if (diagramInput instanceof EditSysMLPackageNodeAppearanceInput editAppearanceInput) { + String nodeId = editAppearanceInput.nodeId(); + Optional optionalNode = this.diagramQueryService.findNodeById(diagramContext.diagram(), nodeId); + if (optionalNode.isPresent()) { + List appearanceChanges = new ArrayList<>(); + + Optional.ofNullable(editAppearanceInput.appearance().background()).ifPresent(background -> appearanceChanges.add(new NodeBackgroundAppearanceChange(nodeId, background))); + Optional.ofNullable(editAppearanceInput.appearance().borderColor()).ifPresent(borderColor -> appearanceChanges.add(new NodeBorderColorAppearanceChange(nodeId, borderColor))); + Optional.ofNullable(editAppearanceInput.appearance().borderSize()).ifPresent(borderSize -> appearanceChanges.add(new NodeBorderSizeAppearanceChange(nodeId, borderSize))); + Optional.ofNullable(editAppearanceInput.appearance().borderStyle()).ifPresent(borderStyle -> appearanceChanges.add(new NodeBorderStyleAppearanceChange(nodeId, borderStyle))); + + diagramContext.diagramEvents().add(new EditAppearanceEvent(appearanceChanges)); + payload = new SuccessPayload(diagramInput.id()); + changeDescription = new ChangeDescription(DiagramChangeKind.DIAGRAM_APPEARANCE_CHANGE, diagramInput.representationId(), diagramInput); + } else { + String nodeNotFoundMessage = this.messageService.nodeNotFound(nodeId); + payload = new ErrorPayload(diagramInput.id(), nodeNotFoundMessage); + } + } + + payloadSink.tryEmitValue(payload); + changeDescriptionSink.tryEmitNext(changeDescription); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLViewFrameNodeAppearanceEventHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLViewFrameNodeAppearanceEventHandler.java new file mode 100644 index 000000000..79d759bca --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/EditSysMLViewFrameNodeAppearanceEventHandler.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.services; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import org.eclipse.sirius.components.collaborative.api.ChangeDescription; +import org.eclipse.sirius.components.collaborative.api.ChangeKind; +import org.eclipse.sirius.components.collaborative.api.Monitoring; +import org.eclipse.sirius.components.collaborative.diagrams.DiagramChangeKind; +import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext; +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramEventHandler; +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramInput; +import org.eclipse.sirius.components.collaborative.diagrams.api.IDiagramQueryService; +import org.eclipse.sirius.components.collaborative.diagrams.messages.ICollaborativeDiagramMessageService; +import org.eclipse.sirius.components.core.api.ErrorPayload; +import org.eclipse.sirius.components.core.api.IEditingContext; +import org.eclipse.sirius.components.core.api.IPayload; +import org.eclipse.sirius.components.core.api.SuccessPayload; +import org.eclipse.sirius.components.diagrams.Node; +import org.eclipse.sirius.components.diagrams.events.appearance.EditAppearanceEvent; +import org.eclipse.sirius.components.diagrams.events.appearance.IAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBackgroundAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderColorAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderRadiusAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderSizeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderStyleAppearanceChange; +import org.eclipse.syson.application.nodes.dto.EditSysMLViewFrameNodeAppearanceInput; +import org.springframework.stereotype.Service; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.MeterRegistry; +import reactor.core.publisher.Sinks; + +/** + * Handle diagram events related to editing a SysMLViewFrame node's appearance. + * + * @author arichard + */ +@Service +public class EditSysMLViewFrameNodeAppearanceEventHandler implements IDiagramEventHandler { + + private final ICollaborativeDiagramMessageService messageService; + + private final IDiagramQueryService diagramQueryService; + + private final Counter counter; + + public EditSysMLViewFrameNodeAppearanceEventHandler(ICollaborativeDiagramMessageService messageService, IDiagramQueryService diagramQueryService, MeterRegistry meterRegistry) { + this.messageService = Objects.requireNonNull(messageService); + this.diagramQueryService = Objects.requireNonNull(diagramQueryService); + this.counter = Counter.builder(Monitoring.EVENT_HANDLER) + .tag(Monitoring.NAME, this.getClass().getSimpleName()) + .register(meterRegistry); + } + + @Override + public boolean canHandle(IDiagramInput diagramInput) { + return diagramInput instanceof EditSysMLViewFrameNodeAppearanceInput; + } + + @Override + public void handle(Sinks.One payloadSink, Sinks.Many changeDescriptionSink, IEditingContext editingContext, DiagramContext diagramContext, + IDiagramInput diagramInput) { + this.counter.increment(); + + String message = this.messageService.invalidInput(diagramInput.getClass().getSimpleName(), EditSysMLViewFrameNodeAppearanceInput.class.getSimpleName()); + IPayload payload = new ErrorPayload(diagramInput.id(), message); + ChangeDescription changeDescription = new ChangeDescription(ChangeKind.NOTHING, diagramInput.representationId(), diagramInput); + + if (diagramInput instanceof EditSysMLViewFrameNodeAppearanceInput editAppearanceInput) { + String nodeId = editAppearanceInput.nodeId(); + Optional optionalNode = this.diagramQueryService.findNodeById(diagramContext.diagram(), nodeId); + if (optionalNode.isPresent()) { + List appearanceChanges = new ArrayList<>(); + + Optional.ofNullable(editAppearanceInput.appearance().background()).ifPresent(background -> appearanceChanges.add(new NodeBackgroundAppearanceChange(nodeId, background))); + Optional.ofNullable(editAppearanceInput.appearance().borderColor()).ifPresent(borderColor -> appearanceChanges.add(new NodeBorderColorAppearanceChange(nodeId, borderColor))); + Optional.ofNullable(editAppearanceInput.appearance().borderSize()).ifPresent(borderSize -> appearanceChanges.add(new NodeBorderSizeAppearanceChange(nodeId, borderSize))); + Optional.ofNullable(editAppearanceInput.appearance().borderStyle()).ifPresent(borderStyle -> appearanceChanges.add(new NodeBorderStyleAppearanceChange(nodeId, borderStyle))); + Optional.ofNullable(editAppearanceInput.appearance().borderRadius()).ifPresent(borderRadius -> appearanceChanges.add(new NodeBorderRadiusAppearanceChange(nodeId, borderRadius))); + + diagramContext.diagramEvents().add(new EditAppearanceEvent(appearanceChanges)); + payload = new SuccessPayload(diagramInput.id()); + changeDescription = new ChangeDescription(DiagramChangeKind.DIAGRAM_APPEARANCE_CHANGE, diagramInput.representationId(), diagramInput); + } else { + String nodeNotFoundMessage = this.messageService.nodeNotFound(nodeId); + payload = new ErrorPayload(diagramInput.id(), nodeNotFoundMessage); + } + } + + payloadSink.tryEmitValue(payload); + changeDescriptionSink.tryEmitNext(changeDescription); + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLImportedPackageNodeAppearanceHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLImportedPackageNodeAppearanceHandler.java new file mode 100644 index 000000000..ae73b376f --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLImportedPackageNodeAppearanceHandler.java @@ -0,0 +1,170 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.services; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.sirius.components.diagrams.INodeStyle; +import org.eclipse.sirius.components.diagrams.LineStyle; +import org.eclipse.sirius.components.diagrams.components.NodeAppearance; +import org.eclipse.sirius.components.diagrams.events.appearance.INodeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBackgroundAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderColorAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderSizeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderStyleAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.ResetNodeAppearanceChange; +import org.eclipse.sirius.components.diagrams.renderer.INodeAppearanceHandler; +import org.eclipse.syson.application.nodes.SysMLImportedPackageNodeStyle; +import org.springframework.stereotype.Service; + +/** + * Service used to handle the customization of a SysMLImportedPackage node's appearance. + * + * @author arichard + */ +@Service +public class SysMLImportedPackageNodeAppearanceHandler implements INodeAppearanceHandler { + + public static final String BACKGROUND = "BACKGROUND"; + + public static final String BORDER_COLOR = "BORDER_COLOR"; + + public static final String BORDER_SIZE = "BORDER_SIZE"; + + public static final String BORDER_STYLE = "BORDER_STYLE"; + + @Override + public boolean canHandle(INodeStyle nodeStyle) { + return nodeStyle instanceof SysMLImportedPackageNodeStyle; + } + + @Override + public NodeAppearance handle(INodeStyle providedStyle, List changes, Optional previousNodeAppearance) { + Set customizedStyleProperties = previousNodeAppearance.map(NodeAppearance::customizedStyleProperties).orElse(new LinkedHashSet<>()); + Optional optionalPreviousNodeStyle = previousNodeAppearance.map(NodeAppearance::style); + if (providedStyle instanceof SysMLImportedPackageNodeStyle providedSysMLImportedPackageNodeStyle) { + SysMLImportedPackageNodeStyle.Builder styleBuilder = SysMLImportedPackageNodeStyle.newSysMLImportedPackageNodeStyle(providedSysMLImportedPackageNodeStyle); + this.handleBackground(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderColor(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderSize(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderStyle(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + return new NodeAppearance(styleBuilder.build(), customizedStyleProperties); + } else { + return new NodeAppearance(providedStyle, customizedStyleProperties); + } + } + + private void handleBackground(SysMLImportedPackageNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BACKGROUND, changes, customizedStyleProperties)) { + Optional optionalBackgroundChange = changes.stream() + .filter(NodeBackgroundAppearanceChange.class::isInstance) + .map(NodeBackgroundAppearanceChange.class::cast) + .findFirst(); + + if (optionalBackgroundChange.isPresent()) { + String newBackground = optionalBackgroundChange.get().background(); + styleBuilder.background(newBackground); + customizedStyleProperties.add(BACKGROUND); + } else if (customizedStyleProperties.contains(BACKGROUND) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLImportedPackageNodeStyle previousNodeStyle) { + String previousBackground = previousNodeStyle.getBackground(); + styleBuilder.background(previousBackground); + } else { + customizedStyleProperties.remove(BACKGROUND); + } + } + } + + private void handleBorderColor(SysMLImportedPackageNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_COLOR, changes, customizedStyleProperties)) { + Optional optionalBorderColorChange = changes.stream() + .filter(NodeBorderColorAppearanceChange.class::isInstance) + .map(NodeBorderColorAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderColorChange.isPresent()) { + String newBorderColor = optionalBorderColorChange.get().borderColor(); + styleBuilder.borderColor(newBorderColor); + customizedStyleProperties.add(BORDER_COLOR); + } else if (customizedStyleProperties.contains(BORDER_COLOR) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLImportedPackageNodeStyle previousNodeStyle) { + String previousBorderColor = previousNodeStyle.getBorderColor(); + styleBuilder.borderColor(previousBorderColor); + } else { + customizedStyleProperties.remove(BORDER_COLOR); + } + } + } + + private void handleBorderSize(SysMLImportedPackageNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_SIZE, changes, customizedStyleProperties)) { + Optional optionalBorderSizeChange = changes.stream() + .filter(NodeBorderSizeAppearanceChange.class::isInstance) + .map(NodeBorderSizeAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderSizeChange.isPresent()) { + int newBorderSize = optionalBorderSizeChange.get().borderSize(); + styleBuilder.borderSize(newBorderSize); + customizedStyleProperties.add(BORDER_SIZE); + } else if (customizedStyleProperties.contains(BORDER_SIZE) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLImportedPackageNodeStyle previousNodeStyle) { + int previousBorderSize = previousNodeStyle.getBorderSize(); + styleBuilder.borderSize(previousBorderSize); + } else { + customizedStyleProperties.remove(BORDER_SIZE); + } + } + } + + private void handleBorderStyle(SysMLImportedPackageNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_STYLE, changes, customizedStyleProperties)) { + Optional optionalBorderStyleChange = changes.stream() + .filter(NodeBorderStyleAppearanceChange.class::isInstance) + .map(NodeBorderStyleAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderStyleChange.isPresent()) { + LineStyle newBorderStyle = optionalBorderStyleChange.get().borderStyle(); + styleBuilder.borderStyle(newBorderStyle); + customizedStyleProperties.add(BORDER_STYLE); + } else if (customizedStyleProperties.contains(BORDER_STYLE) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLImportedPackageNodeStyle previousNodeStyle) { + LineStyle previousBorderStyle = previousNodeStyle.getBorderStyle(); + styleBuilder.borderStyle(previousBorderStyle); + } else { + customizedStyleProperties.remove(BORDER_STYLE); + } + } + } + + private boolean handleResetChange(String propertyName, List changes, Set customizedStyleProperties) { + boolean resetChange = changes.stream() + .filter(ResetNodeAppearanceChange.class::isInstance) + .map(ResetNodeAppearanceChange.class::cast) + .anyMatch(reset -> Objects.equals(reset.propertyName(), propertyName)); + + if (resetChange) { + customizedStyleProperties.remove(propertyName); + } + return resetChange; + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLNoteNodeAppearanceHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLNoteNodeAppearanceHandler.java new file mode 100644 index 000000000..37677ff28 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLNoteNodeAppearanceHandler.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.services; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.sirius.components.diagrams.INodeStyle; +import org.eclipse.sirius.components.diagrams.LineStyle; +import org.eclipse.sirius.components.diagrams.components.NodeAppearance; +import org.eclipse.sirius.components.diagrams.events.appearance.INodeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBackgroundAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderColorAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderSizeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderStyleAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.ResetNodeAppearanceChange; +import org.eclipse.sirius.components.diagrams.renderer.INodeAppearanceHandler; +import org.eclipse.syson.application.nodes.SysMLNoteNodeStyle; +import org.springframework.stereotype.Service; + +/** + * Service used to handle the customization of a SysMLNote node's appearance. + * + * @author arichard + */ +@Service +public class SysMLNoteNodeAppearanceHandler implements INodeAppearanceHandler { + + public static final String BACKGROUND = "BACKGROUND"; + + public static final String BORDER_COLOR = "BORDER_COLOR"; + + public static final String BORDER_SIZE = "BORDER_SIZE"; + + public static final String BORDER_STYLE = "BORDER_STYLE"; + + @Override + public boolean canHandle(INodeStyle nodeStyle) { + return nodeStyle instanceof SysMLNoteNodeStyle; + } + + @Override + public NodeAppearance handle(INodeStyle providedStyle, List changes, Optional previousNodeAppearance) { + Set customizedStyleProperties = previousNodeAppearance.map(NodeAppearance::customizedStyleProperties).orElse(new LinkedHashSet<>()); + Optional optionalPreviousNodeStyle = previousNodeAppearance.map(NodeAppearance::style); + if (providedStyle instanceof SysMLNoteNodeStyle providedSysMLNoteNodeStyle) { + SysMLNoteNodeStyle.Builder styleBuilder = SysMLNoteNodeStyle.newSysMLNoteNodeStyle(providedSysMLNoteNodeStyle); + this.handleBackground(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderColor(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderSize(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderStyle(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + return new NodeAppearance(styleBuilder.build(), customizedStyleProperties); + } else { + return new NodeAppearance(providedStyle, customizedStyleProperties); + } + } + + private void handleBackground(SysMLNoteNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BACKGROUND, changes, customizedStyleProperties)) { + Optional optionalBackgroundChange = changes.stream() + .filter(NodeBackgroundAppearanceChange.class::isInstance) + .map(NodeBackgroundAppearanceChange.class::cast) + .findFirst(); + + if (optionalBackgroundChange.isPresent()) { + String newBackground = optionalBackgroundChange.get().background(); + styleBuilder.background(newBackground); + customizedStyleProperties.add(BACKGROUND); + } else if (customizedStyleProperties.contains(BACKGROUND) && optionalPreviousNodeStyle.isPresent() && optionalPreviousNodeStyle.get() instanceof SysMLNoteNodeStyle previousNodeStyle) { + String previousBackground = previousNodeStyle.getBackground(); + styleBuilder.background(previousBackground); + } else { + customizedStyleProperties.remove(BACKGROUND); + } + } + } + + private void handleBorderColor(SysMLNoteNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_COLOR, changes, customizedStyleProperties)) { + Optional optionalBorderColorChange = changes.stream() + .filter(NodeBorderColorAppearanceChange.class::isInstance) + .map(NodeBorderColorAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderColorChange.isPresent()) { + String newBorderColor = optionalBorderColorChange.get().borderColor(); + styleBuilder.borderColor(newBorderColor); + customizedStyleProperties.add(BORDER_COLOR); + } else if (customizedStyleProperties.contains(BORDER_COLOR) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLNoteNodeStyle previousNodeStyle) { + String previousBorderColor = previousNodeStyle.getBorderColor(); + styleBuilder.borderColor(previousBorderColor); + } else { + customizedStyleProperties.remove(BORDER_COLOR); + } + } + } + + private void handleBorderSize(SysMLNoteNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_SIZE, changes, customizedStyleProperties)) { + Optional optionalBorderSizeChange = changes.stream() + .filter(NodeBorderSizeAppearanceChange.class::isInstance) + .map(NodeBorderSizeAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderSizeChange.isPresent()) { + int newBorderSize = optionalBorderSizeChange.get().borderSize(); + styleBuilder.borderSize(newBorderSize); + customizedStyleProperties.add(BORDER_SIZE); + } else if (customizedStyleProperties.contains(BORDER_SIZE) && optionalPreviousNodeStyle.isPresent() && optionalPreviousNodeStyle.get() instanceof SysMLNoteNodeStyle previousNodeStyle) { + int previousBorderSize = previousNodeStyle.getBorderSize(); + styleBuilder.borderSize(previousBorderSize); + } else { + customizedStyleProperties.remove(BORDER_SIZE); + } + } + } + + private void handleBorderStyle(SysMLNoteNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_STYLE, changes, customizedStyleProperties)) { + Optional optionalBorderStyleChange = changes.stream() + .filter(NodeBorderStyleAppearanceChange.class::isInstance) + .map(NodeBorderStyleAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderStyleChange.isPresent()) { + LineStyle newBorderStyle = optionalBorderStyleChange.get().borderStyle(); + styleBuilder.borderStyle(newBorderStyle); + customizedStyleProperties.add(BORDER_STYLE); + } else if (customizedStyleProperties.contains(BORDER_STYLE) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLNoteNodeStyle previousNodeStyle) { + LineStyle previousBorderStyle = previousNodeStyle.getBorderStyle(); + styleBuilder.borderStyle(previousBorderStyle); + } else { + customizedStyleProperties.remove(BORDER_STYLE); + } + } + } + + private boolean handleResetChange(String propertyName, List changes, Set customizedStyleProperties) { + boolean resetChange = changes.stream() + .filter(ResetNodeAppearanceChange.class::isInstance) + .map(ResetNodeAppearanceChange.class::cast) + .anyMatch(reset -> Objects.equals(reset.propertyName(), propertyName)); + + if (resetChange) { + customizedStyleProperties.remove(propertyName); + } + return resetChange; + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLPackageNodeAppearanceHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLPackageNodeAppearanceHandler.java new file mode 100644 index 000000000..3ea75933b --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLPackageNodeAppearanceHandler.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.services; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.sirius.components.diagrams.INodeStyle; +import org.eclipse.sirius.components.diagrams.LineStyle; +import org.eclipse.sirius.components.diagrams.components.NodeAppearance; +import org.eclipse.sirius.components.diagrams.events.appearance.INodeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBackgroundAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderColorAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderSizeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderStyleAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.ResetNodeAppearanceChange; +import org.eclipse.sirius.components.diagrams.renderer.INodeAppearanceHandler; +import org.eclipse.syson.application.nodes.SysMLPackageNodeStyle; +import org.springframework.stereotype.Service; + +/** + * Service used to handle the customization of a SysMLPackage node's appearance. + * + * @author arichard + */ +@Service +public class SysMLPackageNodeAppearanceHandler implements INodeAppearanceHandler { + + public static final String BACKGROUND = "BACKGROUND"; + + public static final String BORDER_COLOR = "BORDER_COLOR"; + + public static final String BORDER_SIZE = "BORDER_SIZE"; + + public static final String BORDER_STYLE = "BORDER_STYLE"; + + @Override + public boolean canHandle(INodeStyle nodeStyle) { + return nodeStyle instanceof SysMLPackageNodeStyle; + } + + @Override + public NodeAppearance handle(INodeStyle providedStyle, List changes, Optional previousNodeAppearance) { + Set customizedStyleProperties = previousNodeAppearance.map(NodeAppearance::customizedStyleProperties).orElse(new LinkedHashSet<>()); + Optional optionalPreviousNodeStyle = previousNodeAppearance.map(NodeAppearance::style); + if (providedStyle instanceof SysMLPackageNodeStyle providedSysMLPackageNodeStyle) { + SysMLPackageNodeStyle.Builder styleBuilder = SysMLPackageNodeStyle.newSysMLPackageNodeStyle(providedSysMLPackageNodeStyle); + this.handleBackground(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderColor(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderSize(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderStyle(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + return new NodeAppearance(styleBuilder.build(), customizedStyleProperties); + } else { + return new NodeAppearance(providedStyle, customizedStyleProperties); + } + } + + private void handleBackground(SysMLPackageNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BACKGROUND, changes, customizedStyleProperties)) { + Optional optionalBackgroundChange = changes.stream() + .filter(NodeBackgroundAppearanceChange.class::isInstance) + .map(NodeBackgroundAppearanceChange.class::cast) + .findFirst(); + + if (optionalBackgroundChange.isPresent()) { + String newBackground = optionalBackgroundChange.get().background(); + styleBuilder.background(newBackground); + customizedStyleProperties.add(BACKGROUND); + } else if (customizedStyleProperties.contains(BACKGROUND) && optionalPreviousNodeStyle.isPresent() && optionalPreviousNodeStyle.get() instanceof SysMLPackageNodeStyle previousNodeStyle) { + String previousBackground = previousNodeStyle.getBackground(); + styleBuilder.background(previousBackground); + } else { + customizedStyleProperties.remove(BACKGROUND); + } + } + } + + private void handleBorderColor(SysMLPackageNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_COLOR, changes, customizedStyleProperties)) { + Optional optionalBorderColorChange = changes.stream() + .filter(NodeBorderColorAppearanceChange.class::isInstance) + .map(NodeBorderColorAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderColorChange.isPresent()) { + String newBorderColor = optionalBorderColorChange.get().borderColor(); + styleBuilder.borderColor(newBorderColor); + customizedStyleProperties.add(BORDER_COLOR); + } else if (customizedStyleProperties.contains(BORDER_COLOR) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLPackageNodeStyle previousNodeStyle) { + String previousBorderColor = previousNodeStyle.getBorderColor(); + styleBuilder.borderColor(previousBorderColor); + } else { + customizedStyleProperties.remove(BORDER_COLOR); + } + } + } + + private void handleBorderSize(SysMLPackageNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_SIZE, changes, customizedStyleProperties)) { + Optional optionalBorderSizeChange = changes.stream() + .filter(NodeBorderSizeAppearanceChange.class::isInstance) + .map(NodeBorderSizeAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderSizeChange.isPresent()) { + int newBorderSize = optionalBorderSizeChange.get().borderSize(); + styleBuilder.borderSize(newBorderSize); + customizedStyleProperties.add(BORDER_SIZE); + } else if (customizedStyleProperties.contains(BORDER_SIZE) && optionalPreviousNodeStyle.isPresent() && optionalPreviousNodeStyle.get() instanceof SysMLPackageNodeStyle previousNodeStyle) { + int previousBorderSize = previousNodeStyle.getBorderSize(); + styleBuilder.borderSize(previousBorderSize); + } else { + customizedStyleProperties.remove(BORDER_SIZE); + } + } + } + + private void handleBorderStyle(SysMLPackageNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_STYLE, changes, customizedStyleProperties)) { + Optional optionalBorderStyleChange = changes.stream() + .filter(NodeBorderStyleAppearanceChange.class::isInstance) + .map(NodeBorderStyleAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderStyleChange.isPresent()) { + LineStyle newBorderStyle = optionalBorderStyleChange.get().borderStyle(); + styleBuilder.borderStyle(newBorderStyle); + customizedStyleProperties.add(BORDER_STYLE); + } else if (customizedStyleProperties.contains(BORDER_STYLE) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLPackageNodeStyle previousNodeStyle) { + LineStyle previousBorderStyle = previousNodeStyle.getBorderStyle(); + styleBuilder.borderStyle(previousBorderStyle); + } else { + customizedStyleProperties.remove(BORDER_STYLE); + } + } + } + + private boolean handleResetChange(String propertyName, List changes, Set customizedStyleProperties) { + boolean resetChange = changes.stream() + .filter(ResetNodeAppearanceChange.class::isInstance) + .map(ResetNodeAppearanceChange.class::cast) + .anyMatch(reset -> Objects.equals(reset.propertyName(), propertyName)); + + if (resetChange) { + customizedStyleProperties.remove(propertyName); + } + return resetChange; + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLViewFrameNodeAppearanceHandler.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLViewFrameNodeAppearanceHandler.java new file mode 100644 index 000000000..6d73d1380 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/services/SysMLViewFrameNodeAppearanceHandler.java @@ -0,0 +1,196 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.nodes.services; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.sirius.components.diagrams.INodeStyle; +import org.eclipse.sirius.components.diagrams.LineStyle; +import org.eclipse.sirius.components.diagrams.components.NodeAppearance; +import org.eclipse.sirius.components.diagrams.events.appearance.INodeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBackgroundAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderColorAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderRadiusAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderSizeAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.NodeBorderStyleAppearanceChange; +import org.eclipse.sirius.components.diagrams.events.appearance.ResetNodeAppearanceChange; +import org.eclipse.sirius.components.diagrams.renderer.INodeAppearanceHandler; +import org.eclipse.syson.application.nodes.SysMLViewFrameNodeStyle; +import org.springframework.stereotype.Service; + +/** + * Service used to handle the customization of a SysMLViewFrame node's appearance. + * + * @author arichard + */ +@Service +public class SysMLViewFrameNodeAppearanceHandler implements INodeAppearanceHandler { + + public static final String BACKGROUND = "BACKGROUND"; + + public static final String BORDER_COLOR = "BORDER_COLOR"; + + public static final String BORDER_SIZE = "BORDER_SIZE"; + + public static final String BORDER_STYLE = "BORDER_STYLE"; + + public static final String BORDER_RADIUS = "BORDER_RADIUS"; + + @Override + public boolean canHandle(INodeStyle nodeStyle) { + return nodeStyle instanceof SysMLViewFrameNodeStyle; + } + + @Override + public NodeAppearance handle(INodeStyle providedStyle, List changes, Optional previousNodeAppearance) { + Set customizedStyleProperties = previousNodeAppearance.map(NodeAppearance::customizedStyleProperties).orElse(new LinkedHashSet<>()); + Optional optionalPreviousNodeStyle = previousNodeAppearance.map(NodeAppearance::style); + if (providedStyle instanceof SysMLViewFrameNodeStyle providedSysMLViewFrameNodeStyle) { + SysMLViewFrameNodeStyle.Builder styleBuilder = SysMLViewFrameNodeStyle.newSysMLViewFrameNodeStyle(providedSysMLViewFrameNodeStyle); + this.handleBackground(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderColor(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderSize(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderStyle(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + this.handleBorderRadius(styleBuilder, changes, optionalPreviousNodeStyle, customizedStyleProperties); + return new NodeAppearance(styleBuilder.build(), customizedStyleProperties); + } else { + return new NodeAppearance(providedStyle, customizedStyleProperties); + } + } + + private void handleBackground(SysMLViewFrameNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BACKGROUND, changes, customizedStyleProperties)) { + Optional optionalBackgroundChange = changes.stream() + .filter(NodeBackgroundAppearanceChange.class::isInstance) + .map(NodeBackgroundAppearanceChange.class::cast) + .findFirst(); + + if (optionalBackgroundChange.isPresent()) { + String newBackground = optionalBackgroundChange.get().background(); + styleBuilder.background(newBackground); + customizedStyleProperties.add(BACKGROUND); + } else if (customizedStyleProperties.contains(BACKGROUND) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLViewFrameNodeStyle previousNodeStyle) { + String previousBackground = previousNodeStyle.getBackground(); + styleBuilder.background(previousBackground); + } else { + customizedStyleProperties.remove(BACKGROUND); + } + } + } + + private void handleBorderColor(SysMLViewFrameNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_COLOR, changes, customizedStyleProperties)) { + Optional optionalBorderColorChange = changes.stream() + .filter(NodeBorderColorAppearanceChange.class::isInstance) + .map(NodeBorderColorAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderColorChange.isPresent()) { + String newBorderColor = optionalBorderColorChange.get().borderColor(); + styleBuilder.borderColor(newBorderColor); + customizedStyleProperties.add(BORDER_COLOR); + } else if (customizedStyleProperties.contains(BORDER_COLOR) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLViewFrameNodeStyle previousNodeStyle) { + String previousBorderColor = previousNodeStyle.getBorderColor(); + styleBuilder.borderColor(previousBorderColor); + } else { + customizedStyleProperties.remove(BORDER_COLOR); + } + } + } + + private void handleBorderSize(SysMLViewFrameNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_SIZE, changes, customizedStyleProperties)) { + Optional optionalBorderSizeChange = changes.stream() + .filter(NodeBorderSizeAppearanceChange.class::isInstance) + .map(NodeBorderSizeAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderSizeChange.isPresent()) { + int newBorderSize = optionalBorderSizeChange.get().borderSize(); + styleBuilder.borderSize(newBorderSize); + customizedStyleProperties.add(BORDER_SIZE); + } else if (customizedStyleProperties.contains(BORDER_SIZE) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLViewFrameNodeStyle previousNodeStyle) { + int previousBorderSize = previousNodeStyle.getBorderSize(); + styleBuilder.borderSize(previousBorderSize); + } else { + customizedStyleProperties.remove(BORDER_SIZE); + } + } + } + + private void handleBorderStyle(SysMLViewFrameNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_STYLE, changes, customizedStyleProperties)) { + Optional optionalBorderStyleChange = changes.stream() + .filter(NodeBorderStyleAppearanceChange.class::isInstance) + .map(NodeBorderStyleAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderStyleChange.isPresent()) { + LineStyle newBorderStyle = optionalBorderStyleChange.get().borderStyle(); + styleBuilder.borderStyle(newBorderStyle); + customizedStyleProperties.add(BORDER_STYLE); + } else if (customizedStyleProperties.contains(BORDER_STYLE) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLViewFrameNodeStyle previousNodeStyle) { + LineStyle previousBorderStyle = previousNodeStyle.getBorderStyle(); + styleBuilder.borderStyle(previousBorderStyle); + } else { + customizedStyleProperties.remove(BORDER_STYLE); + } + } + } + + private void handleBorderRadius(SysMLViewFrameNodeStyle.Builder styleBuilder, List changes, Optional optionalPreviousNodeStyle, + Set customizedStyleProperties) { + if (!this.handleResetChange(BORDER_RADIUS, changes, customizedStyleProperties)) { + Optional optionalBorderRadiusChange = changes.stream() + .filter(NodeBorderRadiusAppearanceChange.class::isInstance) + .map(NodeBorderRadiusAppearanceChange.class::cast) + .findFirst(); + + if (optionalBorderRadiusChange.isPresent()) { + int newBorderRadius = optionalBorderRadiusChange.get().borderRadius(); + styleBuilder.borderRadius(newBorderRadius); + customizedStyleProperties.add(BORDER_RADIUS); + } else if (customizedStyleProperties.contains(BORDER_RADIUS) && optionalPreviousNodeStyle.isPresent() + && optionalPreviousNodeStyle.get() instanceof SysMLViewFrameNodeStyle previousNodeStyle) { + int previousBorderRadius = previousNodeStyle.getBorderRadius(); + styleBuilder.borderRadius(previousBorderRadius); + } else { + customizedStyleProperties.remove(BORDER_STYLE); + } + } + } + + private boolean handleResetChange(String propertyName, List changes, Set customizedStyleProperties) { + boolean resetChange = changes.stream() + .filter(ResetNodeAppearanceChange.class::isInstance) + .map(ResetNodeAppearanceChange.class::cast) + .anyMatch(reset -> Objects.equals(reset.propertyName(), propertyName)); + + if (resetChange) { + customizedStyleProperties.remove(propertyName); + } + return resetChange; + } +} diff --git a/backend/application/syson-application-configuration/src/main/resources/schema/sysmlcustomnodes.graphqls b/backend/application/syson-application-configuration/src/main/resources/schema/sysmlcustomnodes.graphqls index 1303c3974..37d8cf5a6 100644 --- a/backend/application/syson-application-configuration/src/main/resources/schema/sysmlcustomnodes.graphqls +++ b/backend/application/syson-application-configuration/src/main/resources/schema/sysmlcustomnodes.graphqls @@ -34,3 +34,79 @@ type SysMLViewFrameNodeStyle { borderStyle: LineStyle! borderRadius: Int! } + +input SysMLPackageNodeAppearanceInput { + background: String + borderColor: String + borderSize: Int + borderStyle: LineStyle +} + +input EditSysMLPackageNodeAppearanceInput { + id: ID! + editingContextId: ID! + representationId: ID! + nodeId: ID! + appearance: SysMLPackageNodeAppearanceInput! +} + +union EditSysMLPackageNodeAppearancePayload = ErrorPayload | SuccessPayload + +input SysMLImportedPackageNodeAppearanceInput { + background: String + borderColor: String + borderSize: Int + borderStyle: LineStyle +} + +input EditSysMLImportedPackageNodeAppearanceInput { + id: ID! + editingContextId: ID! + representationId: ID! + nodeId: ID! + appearance: SysMLImportedPackageNodeAppearanceInput! +} + +union EditSysMLImportedPackageNodeAppearancePayload = ErrorPayload | SuccessPayload + +input SysMLNoteNodeAppearanceInput { + background: String + borderColor: String + borderSize: Int + borderStyle: LineStyle +} + +input EditSysMLNoteNodeAppearanceInput { + id: ID! + editingContextId: ID! + representationId: ID! + nodeId: ID! + appearance: SysMLNoteNodeAppearanceInput! +} + +union EditSysMLNoteNodeAppearancePayload = ErrorPayload | SuccessPayload + +input SysMLViewFrameNodeAppearanceInput { + background: String + borderColor: String + borderSize: Int + borderStyle: LineStyle + borderRadius: Int +} + +input EditSysMLViewFrameNodeAppearanceInput { + id: ID! + editingContextId: ID! + representationId: ID! + nodeId: ID! + appearance: SysMLViewFrameNodeAppearanceInput! +} + +union EditSysMLViewFrameNodeAppearancePayload = ErrorPayload | SuccessPayload + +extend type Mutation { + editSysMLPackageNodeAppearance(input: EditSysMLPackageNodeAppearanceInput!): EditSysMLPackageNodeAppearancePayload! + editSysMLImportedPackageNodeAppearance(input: EditSysMLImportedPackageNodeAppearanceInput!): EditSysMLImportedPackageNodeAppearancePayload! + editSysMLNoteNodeAppearance(input: EditSysMLNoteNodeAppearanceInput!): EditSysMLNoteNodeAppearancePayload! + editSysMLViewFrameNodeAppearance(input: EditSysMLViewFrameNodeAppearanceInput!): EditSysMLViewFrameNodeAppearancePayload! +} \ No newline at end of file diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLImportedPackageNodeAppearanceControllerTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLImportedPackageNodeAppearanceControllerTests.java new file mode 100644 index 000000000..0cc5e991a --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLImportedPackageNodeAppearanceControllerTests.java @@ -0,0 +1,246 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.controllers.diagrams; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.sirius.components.diagrams.tests.DiagramEventPayloadConsumer.assertRefreshedDiagramThat; + +import java.time.Duration; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput; +import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload; +import org.eclipse.sirius.components.collaborative.diagrams.dto.ResetNodeAppearanceInput; +import org.eclipse.sirius.components.diagrams.LineStyle; +import org.eclipse.sirius.components.diagrams.tests.graphql.ResetNodeAppearanceMutationRunner; +import org.eclipse.sirius.components.diagrams.tests.navigation.DiagramNavigator; +import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState; +import org.eclipse.syson.AbstractIntegrationTests; +import org.eclipse.syson.application.controllers.diagrams.graphql.EditSysMLImportedPackageNodeAppearanceMutationRunner; +import org.eclipse.syson.application.data.AllCustomNodesProjectData; +import org.eclipse.syson.application.nodes.SysMLImportedPackageNodeStyle; +import org.eclipse.syson.application.nodes.dto.EditSysMLImportedPackageNodeAppearanceInput; +import org.eclipse.syson.application.nodes.dto.SysMLImportedPackageNodeAppearanceInput; +import org.eclipse.syson.services.diagrams.api.IGivenDiagramSubscription; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; +import org.springframework.transaction.annotation.Transactional; + +import reactor.core.publisher.Flux; +import reactor.test.StepVerifier; + +/** + * Tests for SysMLImportedPackage node appearance edition. + * + * @author arichard + */ +@Transactional +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class EditSysMLImportedPackageNodeAppearanceControllerTests extends AbstractIntegrationTests { + + @Autowired + private IGivenInitialServerState givenInitialServerState; + + @Autowired + private IGivenDiagramSubscription givenDiagramSubscription; + + @Autowired + private EditSysMLImportedPackageNodeAppearanceMutationRunner editSysMLImportedPackageNodeAppearanceMutationRunner; + + @Autowired + private ResetNodeAppearanceMutationRunner resetNodeAppearanceMutationRunner; + + @BeforeEach + public void beforeEach() { + this.givenInitialServerState.initialize(); + } + + private Flux givenDiagramSubscription() { + var diagramEventInput = new DiagramEventInput(UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID, + AllCustomNodesProjectData.GraphicalIds.DIAGRAM_ID); + var flux = this.givenDiagramSubscription.subscribe(diagramEventInput); + return flux; + } + + @DisplayName("GIVEN a diagram, WHEN we edit all its appearance and reset changes, THEN the diagram is properly updated") + @Sql(scripts = { AllCustomNodesProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, + config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Test + public void givenDiagramWhenWeEditAllItsAppearanceAndResetChangesThenTheDiagramIsProperlyUpdated() { + var flux = this.givenDiagramSubscription(); + var diagramId = new AtomicReference(); + var siriusWebApplicationNodeId = new AtomicReference(); + + Consumer initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + diagramId.set(diagram.getId()); + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.IMPORTED_PACKAGE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLImportedPackageNodeStyle) + .extracting(node -> (SysMLImportedPackageNodeStyle) node.getStyle()) + .allMatch(sysMLImportedPackageNodeStyle -> "#ffffff".equals(sysMLImportedPackageNodeStyle.getBackground())) + .allMatch(sysMLImportedPackageNodeStyle -> "#000000".equals(sysMLImportedPackageNodeStyle.getBorderColor())) + .allMatch(sysMLImportedPackageNodeStyle -> sysMLImportedPackageNodeStyle.getBorderSize() == 1) + .allMatch(sysMLImportedPackageNodeStyle -> LineStyle.Solid.equals(sysMLImportedPackageNodeStyle.getBorderStyle())); + + var siriusWebApplicationNode = new DiagramNavigator(diagram).nodeWithLabel(AllCustomNodesProjectData.Labels.IMPORTED_PACKAGE).getNode(); + siriusWebApplicationNodeId.set(siriusWebApplicationNode.getId()); + }); + + Runnable setNodeCustomAppearance = () -> { + var appearanceInput = new SysMLImportedPackageNodeAppearanceInput("red", "blue", 5, LineStyle.Dash); + + var input = new EditSysMLImportedPackageNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + appearanceInput); + + this.editSysMLImportedPackageNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.IMPORTED_PACKAGE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLImportedPackageNodeStyle) + .extracting(node -> (SysMLImportedPackageNodeStyle) node.getStyle()) + .allMatch(sysMLImportedPackageNodeStyle -> "red".equals(sysMLImportedPackageNodeStyle.getBackground())) + .allMatch(sysMLImportedPackageNodeStyle -> "blue".equals(sysMLImportedPackageNodeStyle.getBorderColor())) + .allMatch(sysMLImportedPackageNodeStyle -> sysMLImportedPackageNodeStyle.getBorderSize() == 5) + .allMatch(sysMLImportedPackageNodeStyle -> LineStyle.Dash.equals(sysMLImportedPackageNodeStyle.getBorderStyle())); + }); + + Runnable resetNodeCustomAppearance = () -> { + var input = new ResetNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + List.of("BACKGROUND", "BORDER_COLOR", "BORDER_SIZE", "BORDER_STYLE")); + + this.resetNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterResetCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.IMPORTED_PACKAGE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLImportedPackageNodeStyle) + .extracting(node -> (SysMLImportedPackageNodeStyle) node.getStyle()) + .allMatch(sysMLImportedPackageNodeStyle -> "#ffffff".equals(sysMLImportedPackageNodeStyle.getBackground())) + .allMatch(sysMLImportedPackageNodeStyle -> "#000000".equals(sysMLImportedPackageNodeStyle.getBorderColor())) + .allMatch(sysMLImportedPackageNodeStyle -> sysMLImportedPackageNodeStyle.getBorderSize() == 1) + .allMatch(sysMLImportedPackageNodeStyle -> LineStyle.Solid.equals(sysMLImportedPackageNodeStyle.getBorderStyle())); + }); + + StepVerifier.create(flux) + .consumeNextWith(initialDiagramContentConsumer) + .then(setNodeCustomAppearance) + .consumeNextWith(updatedAfterCustomAppearanceDiagramContentConsumer) + .then(resetNodeCustomAppearance) + .consumeNextWith(updatedAfterResetCustomAppearanceDiagramContentConsumer) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + @DisplayName("GIVEN a diagram, WHEN we edit two of its appearance and reset one change, THEN only one property is reset") + @Sql(scripts = { AllCustomNodesProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, + config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Test + public void givenDiagramWhenWeEditTwoOfItsAppearanceAndResetOneChangeThenOnlyOnePropertyIsReset() { + var flux = this.givenDiagramSubscription(); + var diagramId = new AtomicReference(); + var siriusWebApplicationNodeId = new AtomicReference(); + + Consumer initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + diagramId.set(diagram.getId()); + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.IMPORTED_PACKAGE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLImportedPackageNodeStyle) + .extracting(node -> (SysMLImportedPackageNodeStyle) node.getStyle()) + .allMatch(sysMLImportedPackageNodeStyle -> "#ffffff".equals(sysMLImportedPackageNodeStyle.getBackground())) + .allMatch(sysMLImportedPackageNodeStyle -> sysMLImportedPackageNodeStyle.getBorderSize() == 1); + + var siriusWebApplicationNode = new DiagramNavigator(diagram).nodeWithLabel(AllCustomNodesProjectData.Labels.IMPORTED_PACKAGE).getNode(); + siriusWebApplicationNodeId.set(siriusWebApplicationNode.getId()); + }); + + Runnable setNodeCustomAppearance = () -> { + var appearanceInput = new SysMLImportedPackageNodeAppearanceInput("red", null, 5, null); + + var input = new EditSysMLImportedPackageNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + appearanceInput); + + this.editSysMLImportedPackageNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.IMPORTED_PACKAGE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLImportedPackageNodeStyle) + .extracting(node -> (SysMLImportedPackageNodeStyle) node.getStyle()) + .allMatch(sysMLImportedPackageNodeStyle -> "red".equals(sysMLImportedPackageNodeStyle.getBackground())) + .allMatch(sysMLImportedPackageNodeStyle -> sysMLImportedPackageNodeStyle.getBorderSize() == 5); + }); + + Runnable resetNodeCustomAppearance = () -> { + var input = new ResetNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + List.of("BORDER_SIZE")); + + this.resetNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterResetCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.IMPORTED_PACKAGE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLImportedPackageNodeStyle) + .extracting(node -> (SysMLImportedPackageNodeStyle) node.getStyle()) + .allMatch(sysMLImportedPackageNodeStyle -> "red".equals(sysMLImportedPackageNodeStyle.getBackground())) + .allMatch(sysMLImportedPackageNodeStyle -> sysMLImportedPackageNodeStyle.getBorderSize() == 1); + }); + + StepVerifier.create(flux) + .consumeNextWith(initialDiagramContentConsumer) + .then(setNodeCustomAppearance) + .consumeNextWith(updatedAfterCustomAppearanceDiagramContentConsumer) + .then(resetNodeCustomAppearance) + .consumeNextWith(updatedAfterResetCustomAppearanceDiagramContentConsumer) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + +} \ No newline at end of file diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLNoteNodeAppearanceControllerTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLNoteNodeAppearanceControllerTests.java new file mode 100644 index 000000000..752a277fe --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLNoteNodeAppearanceControllerTests.java @@ -0,0 +1,246 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.controllers.diagrams; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.sirius.components.diagrams.tests.DiagramEventPayloadConsumer.assertRefreshedDiagramThat; + +import java.time.Duration; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput; +import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload; +import org.eclipse.sirius.components.collaborative.diagrams.dto.ResetNodeAppearanceInput; +import org.eclipse.sirius.components.diagrams.LineStyle; +import org.eclipse.sirius.components.diagrams.tests.graphql.ResetNodeAppearanceMutationRunner; +import org.eclipse.sirius.components.diagrams.tests.navigation.DiagramNavigator; +import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState; +import org.eclipse.syson.AbstractIntegrationTests; +import org.eclipse.syson.application.controllers.diagrams.graphql.EditSysMLNoteNodeAppearanceMutationRunner; +import org.eclipse.syson.application.data.AllCustomNodesProjectData; +import org.eclipse.syson.application.nodes.SysMLNoteNodeStyle; +import org.eclipse.syson.application.nodes.dto.EditSysMLNoteNodeAppearanceInput; +import org.eclipse.syson.application.nodes.dto.SysMLNoteNodeAppearanceInput; +import org.eclipse.syson.services.diagrams.api.IGivenDiagramSubscription; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; +import org.springframework.transaction.annotation.Transactional; + +import reactor.core.publisher.Flux; +import reactor.test.StepVerifier; + +/** + * Tests for SysMLNote node appearance edition. + * + * @author arichard + */ +@Transactional +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class EditSysMLNoteNodeAppearanceControllerTests extends AbstractIntegrationTests { + + @Autowired + private IGivenInitialServerState givenInitialServerState; + + @Autowired + private IGivenDiagramSubscription givenDiagramSubscription; + + @Autowired + private EditSysMLNoteNodeAppearanceMutationRunner editSysMLNoteNodeAppearanceMutationRunner; + + @Autowired + private ResetNodeAppearanceMutationRunner resetNodeAppearanceMutationRunner; + + @BeforeEach + public void beforeEach() { + this.givenInitialServerState.initialize(); + } + + private Flux givenDiagramSubscription() { + var diagramEventInput = new DiagramEventInput(UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID, + AllCustomNodesProjectData.GraphicalIds.DIAGRAM_ID); + var flux = this.givenDiagramSubscription.subscribe(diagramEventInput); + return flux; + } + + @DisplayName("GIVEN a diagram, WHEN we edit all its appearance and reset changes, THEN the diagram is properly updated") + @Sql(scripts = { AllCustomNodesProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, + config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Test + public void givenDiagramWhenWeEditAllItsAppearanceAndResetChangesThenTheDiagramIsProperlyUpdated() { + var flux = this.givenDiagramSubscription(); + var diagramId = new AtomicReference(); + var siriusWebApplicationNodeId = new AtomicReference(); + + Consumer initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + diagramId.set(diagram.getId()); + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.NOTE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLNoteNodeStyle) + .extracting(node -> (SysMLNoteNodeStyle) node.getStyle()) + .allMatch(sysMLNoteNodeStyle -> "#ffffff".equals(sysMLNoteNodeStyle.getBackground())) + .allMatch(sysMLNoteNodeStyle -> "#000000".equals(sysMLNoteNodeStyle.getBorderColor())) + .allMatch(sysMLNoteNodeStyle -> sysMLNoteNodeStyle.getBorderSize() == 1) + .allMatch(sysMLNoteNodeStyle -> LineStyle.Solid.equals(sysMLNoteNodeStyle.getBorderStyle())); + + var siriusWebApplicationNode = new DiagramNavigator(diagram).nodeWithLabel(AllCustomNodesProjectData.Labels.NOTE).getNode(); + siriusWebApplicationNodeId.set(siriusWebApplicationNode.getId()); + }); + + Runnable setNodeCustomAppearance = () -> { + var appearanceInput = new SysMLNoteNodeAppearanceInput("red", "blue", 5, LineStyle.Dash); + + var input = new EditSysMLNoteNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + appearanceInput); + + this.editSysMLNoteNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.NOTE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLNoteNodeStyle) + .extracting(node -> (SysMLNoteNodeStyle) node.getStyle()) + .allMatch(sysMLNoteNodeStyle -> "red".equals(sysMLNoteNodeStyle.getBackground())) + .allMatch(sysMLNoteNodeStyle -> "blue".equals(sysMLNoteNodeStyle.getBorderColor())) + .allMatch(sysMLNoteNodeStyle -> sysMLNoteNodeStyle.getBorderSize() == 5) + .allMatch(sysMLNoteNodeStyle -> LineStyle.Dash.equals(sysMLNoteNodeStyle.getBorderStyle())); + }); + + Runnable resetNodeCustomAppearance = () -> { + var input = new ResetNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + List.of("BACKGROUND", "BORDER_COLOR", "BORDER_SIZE", "BORDER_STYLE")); + + this.resetNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterResetCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.NOTE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLNoteNodeStyle) + .extracting(node -> (SysMLNoteNodeStyle) node.getStyle()) + .allMatch(sysMLNoteNodeStyle -> "#ffffff".equals(sysMLNoteNodeStyle.getBackground())) + .allMatch(sysMLNoteNodeStyle -> "#000000".equals(sysMLNoteNodeStyle.getBorderColor())) + .allMatch(sysMLNoteNodeStyle -> sysMLNoteNodeStyle.getBorderSize() == 1) + .allMatch(sysMLNoteNodeStyle -> LineStyle.Solid.equals(sysMLNoteNodeStyle.getBorderStyle())); + }); + + StepVerifier.create(flux) + .consumeNextWith(initialDiagramContentConsumer) + .then(setNodeCustomAppearance) + .consumeNextWith(updatedAfterCustomAppearanceDiagramContentConsumer) + .then(resetNodeCustomAppearance) + .consumeNextWith(updatedAfterResetCustomAppearanceDiagramContentConsumer) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + @DisplayName("GIVEN a diagram, WHEN we edit two of its appearance and reset one change, THEN only one property is reset") + @Sql(scripts = { AllCustomNodesProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, + config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Test + public void givenDiagramWhenWeEditTwoOfItsAppearanceAndResetOneChangeThenOnlyOnePropertyIsReset() { + var flux = this.givenDiagramSubscription(); + var diagramId = new AtomicReference(); + var siriusWebApplicationNodeId = new AtomicReference(); + + Consumer initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + diagramId.set(diagram.getId()); + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.NOTE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLNoteNodeStyle) + .extracting(node -> (SysMLNoteNodeStyle) node.getStyle()) + .allMatch(sysMLNoteNodeStyle -> "#ffffff".equals(sysMLNoteNodeStyle.getBackground())) + .allMatch(sysMLNoteNodeStyle -> sysMLNoteNodeStyle.getBorderSize() == 1); + + var siriusWebApplicationNode = new DiagramNavigator(diagram).nodeWithLabel(AllCustomNodesProjectData.Labels.NOTE).getNode(); + siriusWebApplicationNodeId.set(siriusWebApplicationNode.getId()); + }); + + Runnable setNodeCustomAppearance = () -> { + var appearanceInput = new SysMLNoteNodeAppearanceInput("red", null, 5, null); + + var input = new EditSysMLNoteNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + appearanceInput); + + this.editSysMLNoteNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.NOTE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLNoteNodeStyle) + .extracting(node -> (SysMLNoteNodeStyle) node.getStyle()) + .allMatch(sysMLNoteNodeStyle -> "red".equals(sysMLNoteNodeStyle.getBackground())) + .allMatch(sysMLNoteNodeStyle -> sysMLNoteNodeStyle.getBorderSize() == 5); + }); + + Runnable resetNodeCustomAppearance = () -> { + var input = new ResetNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + List.of("BORDER_SIZE")); + + this.resetNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterResetCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.NOTE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLNoteNodeStyle) + .extracting(node -> (SysMLNoteNodeStyle) node.getStyle()) + .allMatch(sysMLNoteNodeStyle -> "red".equals(sysMLNoteNodeStyle.getBackground())) + .allMatch(sysMLNoteNodeStyle -> sysMLNoteNodeStyle.getBorderSize() == 1); + }); + + StepVerifier.create(flux) + .consumeNextWith(initialDiagramContentConsumer) + .then(setNodeCustomAppearance) + .consumeNextWith(updatedAfterCustomAppearanceDiagramContentConsumer) + .then(resetNodeCustomAppearance) + .consumeNextWith(updatedAfterResetCustomAppearanceDiagramContentConsumer) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + +} \ No newline at end of file diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLPackageNodeAppearanceControllerTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLPackageNodeAppearanceControllerTests.java new file mode 100644 index 000000000..f005261d2 --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLPackageNodeAppearanceControllerTests.java @@ -0,0 +1,246 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.controllers.diagrams; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.sirius.components.diagrams.tests.DiagramEventPayloadConsumer.assertRefreshedDiagramThat; + +import java.time.Duration; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput; +import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload; +import org.eclipse.sirius.components.collaborative.diagrams.dto.ResetNodeAppearanceInput; +import org.eclipse.sirius.components.diagrams.LineStyle; +import org.eclipse.sirius.components.diagrams.tests.graphql.ResetNodeAppearanceMutationRunner; +import org.eclipse.sirius.components.diagrams.tests.navigation.DiagramNavigator; +import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState; +import org.eclipse.syson.AbstractIntegrationTests; +import org.eclipse.syson.application.controllers.diagrams.graphql.EditSysMLPackageNodeAppearanceMutationRunner; +import org.eclipse.syson.application.data.AllCustomNodesProjectData; +import org.eclipse.syson.application.nodes.SysMLPackageNodeStyle; +import org.eclipse.syson.application.nodes.dto.EditSysMLPackageNodeAppearanceInput; +import org.eclipse.syson.application.nodes.dto.SysMLPackageNodeAppearanceInput; +import org.eclipse.syson.services.diagrams.api.IGivenDiagramSubscription; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; +import org.springframework.transaction.annotation.Transactional; + +import reactor.core.publisher.Flux; +import reactor.test.StepVerifier; + +/** + * Tests for SysMLPackage node appearance edition. + * + * @author arichard + */ +@Transactional +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class EditSysMLPackageNodeAppearanceControllerTests extends AbstractIntegrationTests { + + @Autowired + private IGivenInitialServerState givenInitialServerState; + + @Autowired + private IGivenDiagramSubscription givenDiagramSubscription; + + @Autowired + private EditSysMLPackageNodeAppearanceMutationRunner editSysMLPackageNodeAppearanceMutationRunner; + + @Autowired + private ResetNodeAppearanceMutationRunner resetNodeAppearanceMutationRunner; + + @BeforeEach + public void beforeEach() { + this.givenInitialServerState.initialize(); + } + + private Flux givenDiagramSubscription() { + var diagramEventInput = new DiagramEventInput(UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID, + AllCustomNodesProjectData.GraphicalIds.DIAGRAM_ID); + var flux = this.givenDiagramSubscription.subscribe(diagramEventInput); + return flux; + } + + @DisplayName("GIVEN a diagram, WHEN we edit all its appearance and reset changes, THEN the diagram is properly updated") + @Sql(scripts = { AllCustomNodesProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, + config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Test + public void givenDiagramWhenWeEditAllItsAppearanceAndResetChangesThenTheDiagramIsProperlyUpdated() { + var flux = this.givenDiagramSubscription(); + var diagramId = new AtomicReference(); + var siriusWebApplicationNodeId = new AtomicReference(); + + Consumer initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + diagramId.set(diagram.getId()); + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.PACKAGE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLPackageNodeStyle) + .extracting(node -> (SysMLPackageNodeStyle) node.getStyle()) + .allMatch(sysMLPackageNodeStyle -> "#ffffff".equals(sysMLPackageNodeStyle.getBackground())) + .allMatch(sysMLPackageNodeStyle -> "#000000".equals(sysMLPackageNodeStyle.getBorderColor())) + .allMatch(sysMLPackageNodeStyle -> sysMLPackageNodeStyle.getBorderSize() == 1) + .allMatch(sysMLPackageNodeStyle -> LineStyle.Solid.equals(sysMLPackageNodeStyle.getBorderStyle())); + + var siriusWebApplicationNode = new DiagramNavigator(diagram).nodeWithLabel(AllCustomNodesProjectData.Labels.PACKAGE).getNode(); + siriusWebApplicationNodeId.set(siriusWebApplicationNode.getId()); + }); + + Runnable setNodeCustomAppearance = () -> { + var appearanceInput = new SysMLPackageNodeAppearanceInput("red", "blue", 5, LineStyle.Dash); + + var input = new EditSysMLPackageNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + appearanceInput); + + this.editSysMLPackageNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.PACKAGE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLPackageNodeStyle) + .extracting(node -> (SysMLPackageNodeStyle) node.getStyle()) + .allMatch(sysMLPackageNodeStyle -> "red".equals(sysMLPackageNodeStyle.getBackground())) + .allMatch(sysMLPackageNodeStyle -> "blue".equals(sysMLPackageNodeStyle.getBorderColor())) + .allMatch(sysMLPackageNodeStyle -> sysMLPackageNodeStyle.getBorderSize() == 5) + .allMatch(sysMLPackageNodeStyle -> LineStyle.Dash.equals(sysMLPackageNodeStyle.getBorderStyle())); + }); + + Runnable resetNodeCustomAppearance = () -> { + var input = new ResetNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + List.of("BACKGROUND", "BORDER_COLOR", "BORDER_SIZE", "BORDER_STYLE")); + + this.resetNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterResetCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.PACKAGE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLPackageNodeStyle) + .extracting(node -> (SysMLPackageNodeStyle) node.getStyle()) + .allMatch(sysMLPackageNodeStyle -> "#ffffff".equals(sysMLPackageNodeStyle.getBackground())) + .allMatch(sysMLPackageNodeStyle -> "#000000".equals(sysMLPackageNodeStyle.getBorderColor())) + .allMatch(sysMLPackageNodeStyle -> sysMLPackageNodeStyle.getBorderSize() == 1) + .allMatch(sysMLPackageNodeStyle -> LineStyle.Solid.equals(sysMLPackageNodeStyle.getBorderStyle())); + }); + + StepVerifier.create(flux) + .consumeNextWith(initialDiagramContentConsumer) + .then(setNodeCustomAppearance) + .consumeNextWith(updatedAfterCustomAppearanceDiagramContentConsumer) + .then(resetNodeCustomAppearance) + .consumeNextWith(updatedAfterResetCustomAppearanceDiagramContentConsumer) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + @DisplayName("GIVEN a diagram, WHEN we edit two of its appearance and reset one change, THEN only one property is reset") + @Sql(scripts = { AllCustomNodesProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, + config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Test + public void givenDiagramWhenWeEditTwoOfItsAppearanceAndResetOneChangeThenOnlyOnePropertyIsReset() { + var flux = this.givenDiagramSubscription(); + var diagramId = new AtomicReference(); + var siriusWebApplicationNodeId = new AtomicReference(); + + Consumer initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + diagramId.set(diagram.getId()); + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.PACKAGE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLPackageNodeStyle) + .extracting(node -> (SysMLPackageNodeStyle) node.getStyle()) + .allMatch(sysMLPackageNodeStyle -> "#ffffff".equals(sysMLPackageNodeStyle.getBackground())) + .allMatch(sysMLPackageNodeStyle -> sysMLPackageNodeStyle.getBorderSize() == 1); + + var siriusWebApplicationNode = new DiagramNavigator(diagram).nodeWithLabel(AllCustomNodesProjectData.Labels.PACKAGE).getNode(); + siriusWebApplicationNodeId.set(siriusWebApplicationNode.getId()); + }); + + Runnable setNodeCustomAppearance = () -> { + var appearanceInput = new SysMLPackageNodeAppearanceInput("red", null, 5, null); + + var input = new EditSysMLPackageNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + appearanceInput); + + this.editSysMLPackageNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.PACKAGE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLPackageNodeStyle) + .extracting(node -> (SysMLPackageNodeStyle) node.getStyle()) + .allMatch(sysMLPackageNodeStyle -> "red".equals(sysMLPackageNodeStyle.getBackground())) + .allMatch(sysMLPackageNodeStyle -> sysMLPackageNodeStyle.getBorderSize() == 5); + }); + + Runnable resetNodeCustomAppearance = () -> { + var input = new ResetNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + List.of("BORDER_SIZE")); + + this.resetNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterResetCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.PACKAGE)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLPackageNodeStyle) + .extracting(node -> (SysMLPackageNodeStyle) node.getStyle()) + .allMatch(sysMLPackageNodeStyle -> "red".equals(sysMLPackageNodeStyle.getBackground())) + .allMatch(sysMLPackageNodeStyle -> sysMLPackageNodeStyle.getBorderSize() == 1); + }); + + StepVerifier.create(flux) + .consumeNextWith(initialDiagramContentConsumer) + .then(setNodeCustomAppearance) + .consumeNextWith(updatedAfterCustomAppearanceDiagramContentConsumer) + .then(resetNodeCustomAppearance) + .consumeNextWith(updatedAfterResetCustomAppearanceDiagramContentConsumer) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + +} \ No newline at end of file diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLViewFrameNodeAppearanceControllerTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLViewFrameNodeAppearanceControllerTests.java new file mode 100644 index 000000000..6bdd6b85d --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/EditSysMLViewFrameNodeAppearanceControllerTests.java @@ -0,0 +1,249 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.controllers.diagrams; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.eclipse.sirius.components.diagrams.tests.DiagramEventPayloadConsumer.assertRefreshedDiagramThat; + +import java.time.Duration; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramEventInput; +import org.eclipse.sirius.components.collaborative.diagrams.dto.DiagramRefreshedEventPayload; +import org.eclipse.sirius.components.collaborative.diagrams.dto.ResetNodeAppearanceInput; +import org.eclipse.sirius.components.diagrams.LineStyle; +import org.eclipse.sirius.components.diagrams.tests.graphql.ResetNodeAppearanceMutationRunner; +import org.eclipse.sirius.components.diagrams.tests.navigation.DiagramNavigator; +import org.eclipse.sirius.web.tests.services.api.IGivenInitialServerState; +import org.eclipse.syson.AbstractIntegrationTests; +import org.eclipse.syson.application.controllers.diagrams.graphql.EditSysMLViewFrameNodeAppearanceMutationRunner; +import org.eclipse.syson.application.data.AllCustomNodesProjectData; +import org.eclipse.syson.application.nodes.SysMLViewFrameNodeStyle; +import org.eclipse.syson.application.nodes.dto.EditSysMLViewFrameNodeAppearanceInput; +import org.eclipse.syson.application.nodes.dto.SysMLViewFrameNodeAppearanceInput; +import org.eclipse.syson.services.diagrams.api.IGivenDiagramSubscription; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; +import org.springframework.transaction.annotation.Transactional; + +import reactor.core.publisher.Flux; +import reactor.test.StepVerifier; + +/** + * Tests for SysMLViewFrame node appearance edition. + * + * @author arichard + */ +@Transactional +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class EditSysMLViewFrameNodeAppearanceControllerTests extends AbstractIntegrationTests { + + @Autowired + private IGivenInitialServerState givenInitialServerState; + + @Autowired + private IGivenDiagramSubscription givenDiagramSubscription; + + @Autowired + private EditSysMLViewFrameNodeAppearanceMutationRunner editSysMLViewFrameNodeAppearanceMutationRunner; + + @Autowired + private ResetNodeAppearanceMutationRunner resetNodeAppearanceMutationRunner; + + @BeforeEach + public void beforeEach() { + this.givenInitialServerState.initialize(); + } + + private Flux givenDiagramSubscription() { + var diagramEventInput = new DiagramEventInput(UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID, + AllCustomNodesProjectData.GraphicalIds.DIAGRAM_ID); + var flux = this.givenDiagramSubscription.subscribe(diagramEventInput); + return flux; + } + + @DisplayName("GIVEN a diagram, WHEN we edit all its appearance and reset changes, THEN the diagram is properly updated") + @Sql(scripts = { AllCustomNodesProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, + config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Test + public void givenDiagramWhenWeEditAllItsAppearanceAndResetChangesThenTheDiagramIsProperlyUpdated() { + var flux = this.givenDiagramSubscription(); + var diagramId = new AtomicReference(); + var siriusWebApplicationNodeId = new AtomicReference(); + + Consumer initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + diagramId.set(diagram.getId()); + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.VIEW_FRAME)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLViewFrameNodeStyle) + .extracting(node -> (SysMLViewFrameNodeStyle) node.getStyle()) + .allMatch(sysMLViewFrameNodeStyle -> "#ffffff".equals(sysMLViewFrameNodeStyle.getBackground())) + .allMatch(sysMLViewFrameNodeStyle -> "#000000".equals(sysMLViewFrameNodeStyle.getBorderColor())) + .allMatch(sysMLViewFrameNodeStyle -> sysMLViewFrameNodeStyle.getBorderSize() == 1) + .allMatch(sysMLViewFrameNodeStyle -> LineStyle.Solid.equals(sysMLViewFrameNodeStyle.getBorderStyle())) + .allMatch(sysMLViewFrameNodeStyle -> sysMLViewFrameNodeStyle.getBorderRadius() == 10); + + var siriusWebApplicationNode = new DiagramNavigator(diagram).nodeWithLabel(AllCustomNodesProjectData.Labels.VIEW_FRAME).getNode(); + siriusWebApplicationNodeId.set(siriusWebApplicationNode.getId()); + }); + + Runnable setNodeCustomAppearance = () -> { + var appearanceInput = new SysMLViewFrameNodeAppearanceInput("red", "blue", 5, LineStyle.Dash, 5); + + var input = new EditSysMLViewFrameNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + appearanceInput); + + this.editSysMLViewFrameNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.VIEW_FRAME)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLViewFrameNodeStyle) + .extracting(node -> (SysMLViewFrameNodeStyle) node.getStyle()) + .allMatch(sysMLViewFrameNodeStyle -> "red".equals(sysMLViewFrameNodeStyle.getBackground())) + .allMatch(sysMLViewFrameNodeStyle -> "blue".equals(sysMLViewFrameNodeStyle.getBorderColor())) + .allMatch(sysMLViewFrameNodeStyle -> sysMLViewFrameNodeStyle.getBorderSize() == 5) + .allMatch(sysMLViewFrameNodeStyle -> LineStyle.Dash.equals(sysMLViewFrameNodeStyle.getBorderStyle())) + .allMatch(sysMLViewFrameNodeStyle -> sysMLViewFrameNodeStyle.getBorderRadius() == 5); + }); + + Runnable resetNodeCustomAppearance = () -> { + var input = new ResetNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + List.of("BACKGROUND", "BORDER_COLOR", "BORDER_RADIUS", "BORDER_SIZE", "BORDER_STYLE")); + + this.resetNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterResetCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.VIEW_FRAME)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLViewFrameNodeStyle) + .extracting(node -> (SysMLViewFrameNodeStyle) node.getStyle()) + .allMatch(sysMLViewFrameNodeStyle -> "#ffffff".equals(sysMLViewFrameNodeStyle.getBackground())) + .allMatch(sysMLViewFrameNodeStyle -> "#000000".equals(sysMLViewFrameNodeStyle.getBorderColor())) + .allMatch(sysMLViewFrameNodeStyle -> sysMLViewFrameNodeStyle.getBorderSize() == 1) + .allMatch(sysMLViewFrameNodeStyle -> LineStyle.Solid.equals(sysMLViewFrameNodeStyle.getBorderStyle())) + .allMatch(sysMLViewFrameNodeStyle -> sysMLViewFrameNodeStyle.getBorderRadius() == 10); + }); + + StepVerifier.create(flux) + .consumeNextWith(initialDiagramContentConsumer) + .then(setNodeCustomAppearance) + .consumeNextWith(updatedAfterCustomAppearanceDiagramContentConsumer) + .then(resetNodeCustomAppearance) + .consumeNextWith(updatedAfterResetCustomAppearanceDiagramContentConsumer) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + + @DisplayName("GIVEN a diagram, WHEN we edit two of its appearance and reset one change, THEN only one property is reset") + @Sql(scripts = { AllCustomNodesProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, + config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Test + public void givenDiagramWhenWeEditTwoOfItsAppearanceAndResetOneChangeThenOnlyOnePropertyIsReset() { + var flux = this.givenDiagramSubscription(); + var diagramId = new AtomicReference(); + var siriusWebApplicationNodeId = new AtomicReference(); + + Consumer initialDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + diagramId.set(diagram.getId()); + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.VIEW_FRAME)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLViewFrameNodeStyle) + .extracting(node -> (SysMLViewFrameNodeStyle) node.getStyle()) + .allMatch(sysMLViewFrameNodeStyle -> "#ffffff".equals(sysMLViewFrameNodeStyle.getBackground())) + .allMatch(sysMLViewFrameNodeStyle -> sysMLViewFrameNodeStyle.getBorderSize() == 1); + + var siriusWebApplicationNode = new DiagramNavigator(diagram).nodeWithLabel(AllCustomNodesProjectData.Labels.VIEW_FRAME).getNode(); + siriusWebApplicationNodeId.set(siriusWebApplicationNode.getId()); + }); + + Runnable setNodeCustomAppearance = () -> { + var appearanceInput = new SysMLViewFrameNodeAppearanceInput("red", null, 5, null, 5); + + var input = new EditSysMLViewFrameNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + appearanceInput); + + this.editSysMLViewFrameNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.VIEW_FRAME)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLViewFrameNodeStyle) + .extracting(node -> (SysMLViewFrameNodeStyle) node.getStyle()) + .allMatch(sysMLViewFrameNodeStyle -> "red".equals(sysMLViewFrameNodeStyle.getBackground())) + .allMatch(sysMLViewFrameNodeStyle -> sysMLViewFrameNodeStyle.getBorderSize() == 5); + }); + + Runnable resetNodeCustomAppearance = () -> { + var input = new ResetNodeAppearanceInput( + UUID.randomUUID(), + AllCustomNodesProjectData.EDITING_CONTEXT_ID.toString(), + diagramId.get(), + siriusWebApplicationNodeId.get(), + List.of("BORDER_SIZE")); + + this.resetNodeAppearanceMutationRunner.run(input); + }; + + Consumer updatedAfterResetCustomAppearanceDiagramContentConsumer = assertRefreshedDiagramThat(diagram -> { + assertThat(diagram.getNodes()) + .filteredOn(node -> node.getInsideLabel() != null && node.getInsideLabel().getText().equals(AllCustomNodesProjectData.Labels.VIEW_FRAME)) + .hasSize(1) + .allMatch(node -> node.getStyle() instanceof SysMLViewFrameNodeStyle) + .extracting(node -> (SysMLViewFrameNodeStyle) node.getStyle()) + .allMatch(sysMLViewFrameNodeStyle -> "red".equals(sysMLViewFrameNodeStyle.getBackground())) + .allMatch(sysMLViewFrameNodeStyle -> sysMLViewFrameNodeStyle.getBorderSize() == 1); + }); + + StepVerifier.create(flux) + .consumeNextWith(initialDiagramContentConsumer) + .then(setNodeCustomAppearance) + .consumeNextWith(updatedAfterCustomAppearanceDiagramContentConsumer) + .then(resetNodeCustomAppearance) + .consumeNextWith(updatedAfterResetCustomAppearanceDiagramContentConsumer) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } + +} \ No newline at end of file diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLImportedPackageNodeAppearanceMutationRunner.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLImportedPackageNodeAppearanceMutationRunner.java new file mode 100644 index 000000000..15e5afd2e --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLImportedPackageNodeAppearanceMutationRunner.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.controllers.diagrams.graphql; + +import java.util.Objects; + +import org.eclipse.sirius.components.core.api.IInput; +import org.eclipse.sirius.components.graphql.tests.api.IGraphQLRequestor; +import org.eclipse.sirius.components.graphql.tests.api.IMutationRunner; +import org.springframework.stereotype.Service; + +/** + * + * Used to edit a SysMLImportedPackage node's appearance. + * + * @author arichard + */ +@Service +public class EditSysMLImportedPackageNodeAppearanceMutationRunner implements IMutationRunner { + + private static final String EDIT_SYSML_IMPORTED_PACKAGE_NODE_APPEARANCE_MUTATION = """ + mutation editSysMLImportedPackageNodeAppearance($input: EditSysMLImportedPackageNodeAppearanceInput!) { + editSysMLImportedPackageNodeAppearance(input: $input) { + __typename + ... on ErrorPayload { + messages { + body + level + } + } + ... on SuccessPayload { + messages { + body + level + } + } + } + } + """; + + private final IGraphQLRequestor graphQLRequestor; + + public EditSysMLImportedPackageNodeAppearanceMutationRunner(IGraphQLRequestor graphQLRequestor) { + this.graphQLRequestor = Objects.requireNonNull(graphQLRequestor); + } + + @Override + public String run(IInput input) { + return this.graphQLRequestor.execute(EDIT_SYSML_IMPORTED_PACKAGE_NODE_APPEARANCE_MUTATION, input); + } +} \ No newline at end of file diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLNoteNodeAppearanceMutationRunner.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLNoteNodeAppearanceMutationRunner.java new file mode 100644 index 000000000..e4882d458 --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLNoteNodeAppearanceMutationRunner.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.controllers.diagrams.graphql; + +import java.util.Objects; + +import org.eclipse.sirius.components.core.api.IInput; +import org.eclipse.sirius.components.graphql.tests.api.IGraphQLRequestor; +import org.eclipse.sirius.components.graphql.tests.api.IMutationRunner; +import org.springframework.stereotype.Service; + +/** + * + * Used to edit a SysMLNote node's appearance. + * + * @author arichard + */ +@Service +public class EditSysMLNoteNodeAppearanceMutationRunner implements IMutationRunner { + + private static final String EDIT_SYSML_NOTE_NODE_APPEARANCE_MUTATION = """ + mutation editSysMLNoteNodeAppearance($input: EditSysMLNoteNodeAppearanceInput!) { + editSysMLNoteNodeAppearance(input: $input) { + __typename + ... on ErrorPayload { + messages { + body + level + } + } + ... on SuccessPayload { + messages { + body + level + } + } + } + } + """; + + private final IGraphQLRequestor graphQLRequestor; + + public EditSysMLNoteNodeAppearanceMutationRunner(IGraphQLRequestor graphQLRequestor) { + this.graphQLRequestor = Objects.requireNonNull(graphQLRequestor); + } + + @Override + public String run(IInput input) { + return this.graphQLRequestor.execute(EDIT_SYSML_NOTE_NODE_APPEARANCE_MUTATION, input); + } +} \ No newline at end of file diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLPackageNodeAppearanceMutationRunner.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLPackageNodeAppearanceMutationRunner.java new file mode 100644 index 000000000..3e14748e2 --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLPackageNodeAppearanceMutationRunner.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.controllers.diagrams.graphql; + +import java.util.Objects; + +import org.eclipse.sirius.components.core.api.IInput; +import org.eclipse.sirius.components.graphql.tests.api.IGraphQLRequestor; +import org.eclipse.sirius.components.graphql.tests.api.IMutationRunner; +import org.springframework.stereotype.Service; + +/** + * + * Used to edit a SysMLPackage node's appearance. + * + * @author arichard + */ +@Service +public class EditSysMLPackageNodeAppearanceMutationRunner implements IMutationRunner { + + private static final String EDIT_SYSML_PACKAGE_NODE_APPEARANCE_MUTATION = """ + mutation editSysMLPackageNodeAppearance($input: EditSysMLPackageNodeAppearanceInput!) { + editSysMLPackageNodeAppearance(input: $input) { + __typename + ... on ErrorPayload { + messages { + body + level + } + } + ... on SuccessPayload { + messages { + body + level + } + } + } + } + """; + + private final IGraphQLRequestor graphQLRequestor; + + public EditSysMLPackageNodeAppearanceMutationRunner(IGraphQLRequestor graphQLRequestor) { + this.graphQLRequestor = Objects.requireNonNull(graphQLRequestor); + } + + @Override + public String run(IInput input) { + return this.graphQLRequestor.execute(EDIT_SYSML_PACKAGE_NODE_APPEARANCE_MUTATION, input); + } +} \ No newline at end of file diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLViewFrameNodeAppearanceMutationRunner.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLViewFrameNodeAppearanceMutationRunner.java new file mode 100644 index 000000000..b10241450 --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/graphql/EditSysMLViewFrameNodeAppearanceMutationRunner.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.controllers.diagrams.graphql; + +import java.util.Objects; + +import org.eclipse.sirius.components.core.api.IInput; +import org.eclipse.sirius.components.graphql.tests.api.IGraphQLRequestor; +import org.eclipse.sirius.components.graphql.tests.api.IMutationRunner; +import org.springframework.stereotype.Service; + +/** + * + * Used to edit a SysMLViewFrame node's appearance. + * + * @author arichard + */ +@Service +public class EditSysMLViewFrameNodeAppearanceMutationRunner implements IMutationRunner { + + private static final String EDIT_SYSML_VIEW_FRAME_NODE_APPEARANCE_MUTATION = """ + mutation editSysMLViewFrameNodeAppearance($input: EditSysMLViewFrameNodeAppearanceInput!) { + editSysMLViewFrameNodeAppearance(input: $input) { + __typename + ... on ErrorPayload { + messages { + body + level + } + } + ... on SuccessPayload { + messages { + body + level + } + } + } + } + """; + + private final IGraphQLRequestor graphQLRequestor; + + public EditSysMLViewFrameNodeAppearanceMutationRunner(IGraphQLRequestor graphQLRequestor) { + this.graphQLRequestor = Objects.requireNonNull(graphQLRequestor); + } + + @Override + public String run(IInput input) { + return this.graphQLRequestor.execute(EDIT_SYSML_VIEW_FRAME_NODE_APPEARANCE_MUTATION, input); + } +} \ No newline at end of file diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/data/AllCustomNodesProjectData.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/data/AllCustomNodesProjectData.java new file mode 100644 index 000000000..8c70d1e14 --- /dev/null +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/data/AllCustomNodesProjectData.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.syson.application.data; + +/** + * Ids for project "AllCustomNodes". + * + * @author arichard + */ +public class AllCustomNodesProjectData { + + public static final String EDITING_CONTEXT_ID = "aeb3587e-29ae-425e-b4fb-c33745002aac"; + + public static final String SCRIPT_PATH = "/scripts/database-content/AllCustomNodes.sql"; + + /** + * Ids of the graphical elements elements. + * + * @author Arthur Daussy + */ + public static final class GraphicalIds { + + public static final String DIAGRAM_ID = "894983da-5371-41ef-bc80-9dc8a120a226"; + + } + + /** + * Ids of the semantic elements. + * + * @author arichard + */ + public static final class SemanticIds { + + public static final String ROOT_PACKAGE_ELEMENT_ID = "dd708dd2-a885-4bad-9900-5d20b8cd59d1"; + } + + /** + * Labels of the semantic elements. + * + * @author arichard + */ + public static final class Labels { + + public static final String PACKAGE = "Package1"; + + public static final String IMPORTED_PACKAGE = "\u00ABprivate\u00BB\nActions"; + + public static final String NOTE = "\u00ABcomment\u00BB\n\nadd comment here"; + + public static final String VIEW_FRAME = "\u00ABview\u00BB view2 : StandardViewDefinitions::GeneralView"; + + } +} diff --git a/backend/application/syson-application/src/test/resources/scripts/database-content/AllCustomNodes.sql b/backend/application/syson-application/src/test/resources/scripts/database-content/AllCustomNodes.sql new file mode 100644 index 000000000..cace81d19 --- /dev/null +++ b/backend/application/syson-application/src/test/resources/scripts/database-content/AllCustomNodes.sql @@ -0,0 +1,100 @@ +-- +-- PostgreSQL database dump +-- + +-- Dumped from database version 17.5 (Debian 17.5-1.pgdg120+1) +-- Dumped by pg_dump version 17.6 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- Data for Name: semantic_data; Type: TABLE DATA; Schema: public; Owner: dbuser +-- + +INSERT INTO public.semantic_data (id, created_on, last_modified_on) VALUES ('aeb3587e-29ae-425e-b4fb-c33745002aac', '2025-09-17 09:19:53.424174+00', '2025-09-17 09:22:27.029296+00'); + + +-- +-- Data for Name: document; Type: TABLE DATA; Schema: public; Owner: dbuser +-- + +INSERT INTO public.document (id, semantic_data_id, name, content, created_on, last_modified_on, is_read_only) VALUES ('1b7d760c-d9e0-4908-8157-106e2b48c916', 'aeb3587e-29ae-425e-b4fb-c33745002aac', 'SysMLv2.sysml', '{"json":{"version":"1.0","encoding":"utf-8"},"ns":{"sysml":"http://www.eclipse.org/syson/sysml"},"migration":{"lastMigrationPerformed":"none","migrationVersion":"2025.8.0-202508220000"},"content":[{"id":"f6fa7af2-8756-41ac-a759-57adcfcfc01f","eClass":"sysml:Namespace","data":{"elementId":"624409cb-54f5-4421-ae60-d467872fd85c","ownedRelationship":[{"id":"d9634fd6-23fb-46ca-bb57-38cb304dbc4e","eClass":"sysml:OwningMembership","data":{"elementId":"6614125e-d10b-42cb-8447-8c2cb27edc7a","ownedRelatedElement":[{"id":"1885c2a4-0b1f-489a-923c-2087d2b8125d","eClass":"sysml:Package","data":{"declaredName":"RootPackage","elementId":"dd708dd2-a885-4bad-9900-5d20b8cd59d1","ownedRelationship":[{"id":"8f044b65-8e75-4e0a-91f6-39564738341e","eClass":"sysml:OwningMembership","data":{"elementId":"a9e7db1d-d340-4622-94b5-caf0fb6f2ee2","ownedRelatedElement":[{"id":"e3155a70-343d-473c-a893-47afe98aa0ed","eClass":"sysml:ViewUsage","data":{"declaredName":"General View","elementId":"269e0b43-6b2d-45b7-a222-aed97a8e08c8","ownedRelationship":[{"id":"2e868297-714d-4141-890a-4199fbab8fa8","eClass":"sysml:FeatureTyping","data":{"elementId":"4c3839fe-12ce-430d-84f0-0e046fcb904f","type":"sysml:ViewDefinition sysmllibrary:///faf517ae-dbcd-30a4-b3b9-3d9cb3bbf5c1#03904fdf-d6f2-57b1-92d5-95d36b8208dc","typedFeature":"e3155a70-343d-473c-a893-47afe98aa0ed"}},{"id":"59519d0a-9efa-4062-b245-093a0576fe66","eClass":"sysml:MembershipExpose","data":{"elementId":"ffe0cbff-ba9e-4ee3-a016-fe901e2a02a6","importedMembership":"50a20733-1a29-4c6f-a8c1-10c3220266a8"}},{"id":"bb275e59-4566-4e9d-8cb1-94f545360ad3","eClass":"sysml:MembershipExpose","data":{"elementId":"b6e65a66-7831-4a14-a0a3-9f8693b5031b","isRecursive":true,"importedMembership":"21723abf-13ca-4064-9188-47973d940eb5"}},{"id":"2c42fd0c-1bcd-4bfb-878c-6cfcf327f9c4","eClass":"sysml:MembershipExpose","data":{"elementId":"df96045f-df41-42a1-9d50-28cb1f98f50b","importedMembership":"d2487e26-72c8-4fda-b47d-36005e22a99d"}}]}}]}},{"id":"50a20733-1a29-4c6f-a8c1-10c3220266a8","eClass":"sysml:OwningMembership","data":{"elementId":"9bb4143f-a750-4eb6-aa8f-fbe7075c57a2","ownedRelatedElement":[{"id":"35401cff-45df-4f97-ba90-75f7eea53310","eClass":"sysml:PartUsage","data":{"declaredName":"part1","elementId":"07430d6b-9d5f-49bc-a3d3-5d02a8a167a6","ownedRelationship":[{"id":"418bb15d-69f6-4b58-a03e-5da06841f71c","eClass":"sysml:OwningMembership","data":{"elementId":"bea042e8-efbe-4d28-b7bd-d58375d133e8","ownedRelatedElement":[{"id":"3166be3d-7cdc-4e31-8e33-c8ea31f9fe79","eClass":"sysml:Comment","data":{"elementId":"ecbcc102-a1d5-41a1-84c6-0a228ffa5c23","body":"add comment here"}}]}}],"isComposite":true}}]}},{"id":"21723abf-13ca-4064-9188-47973d940eb5","eClass":"sysml:OwningMembership","data":{"elementId":"f67f445f-26cb-4419-a175-9a4815685574","ownedRelatedElement":[{"id":"ccb0ef46-46b7-4c45-8426-6927eece71f0","eClass":"sysml:Package","data":{"declaredName":"Package1","elementId":"ba1fd6b7-30b4-48f3-a492-eb1c3b3dca9b"}}]}},{"id":"4ad3f152-0aee-45f1-a2dd-ace82cb98cdd","eClass":"sysml:NamespaceImport","data":{"elementId":"95c4812b-e865-4f0f-918e-50f151583502","importedNamespace":"sysml:LibraryPackage sysmllibrary:///ea54fd17-52d6-3366-82aa-494d0678e42d#60005f8a-dbfc-599c-89b6-26ab49420da3"}},{"id":"d2487e26-72c8-4fda-b47d-36005e22a99d","eClass":"sysml:OwningMembership","data":{"elementId":"65bdeb77-7c32-496b-9307-048b22173a62","ownedRelatedElement":[{"id":"911e49b9-3bdb-462f-b7b4-c45e66fe8d0b","eClass":"sysml:ViewUsage","data":{"declaredName":"view2","elementId":"912b0116-5133-49f4-972f-47a799a669b0","ownedRelationship":[{"id":"98aff6da-9cac-45b4-aff8-06fb4a5c9714","eClass":"sysml:FeatureTyping","data":{"elementId":"a79580fb-0c0c-46f8-85b9-5a6c6fcfc98b","type":"sysml:ViewDefinition sysmllibrary:///faf517ae-dbcd-30a4-b3b9-3d9cb3bbf5c1#03904fdf-d6f2-57b1-92d5-95d36b8208dc","typedFeature":"911e49b9-3bdb-462f-b7b4-c45e66fe8d0b"}}],"isComposite":true}}]}}]}}]}}]}}]}', '2025-09-17 09:22:27.02929+00', '2025-09-17 09:22:27.02929+00', false); + + +-- +-- Data for Name: image; Type: TABLE DATA; Schema: public; Owner: dbuser +-- + + + +-- +-- Data for Name: library; Type: TABLE DATA; Schema: public; Owner: dbuser +-- + + + +-- +-- Data for Name: project; Type: TABLE DATA; Schema: public; Owner: dbuser +-- + +INSERT INTO public.project (id, name, created_on, last_modified_on) VALUES ('bb1eae48-3d32-4547-92f2-02f56798ed5c', 'AllCustomNodes', '2025-09-17 09:19:53.410605+00', '2025-09-17 09:20:05.859971+00'); + + +-- +-- Data for Name: nature; Type: TABLE DATA; Schema: public; Owner: dbuser +-- + + + +-- +-- Data for Name: project_image; Type: TABLE DATA; Schema: public; Owner: dbuser +-- + + + +-- +-- Data for Name: project_semantic_data; Type: TABLE DATA; Schema: public; Owner: dbuser +-- + +INSERT INTO public.project_semantic_data (id, project_id, semantic_data_id, name, created_on, last_modified_on) VALUES ('5155c6a0-5785-47d5-adab-51758ecd83aa', 'bb1eae48-3d32-4547-92f2-02f56798ed5c', 'aeb3587e-29ae-425e-b4fb-c33745002aac', 'main', '2025-09-17 09:19:53.438895+00', '2025-09-17 09:19:53.438895+00'); + + +-- +-- Data for Name: representation_metadata; Type: TABLE DATA; Schema: public; Owner: dbuser +-- + +INSERT INTO public.representation_metadata (id, target_object_id, description_id, label, kind, created_on, last_modified_on, documentation, semantic_data_id) VALUES ('894983da-5371-41ef-bc80-9dc8a120a226', 'e3155a70-343d-473c-a893-47afe98aa0ed', 'siriusComponents://representationDescription?kind=diagramDescription&sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=db495705-e917-319b-af55-a32ad63f4089', 'General View', 'siriusComponents://representation?type=Diagram', '2025-09-17 09:19:53.83229+00', '2025-09-17 09:19:53.83229+00', '', 'aeb3587e-29ae-425e-b4fb-c33745002aac'); + + +-- +-- Data for Name: representation_content; Type: TABLE DATA; Schema: public; Owner: dbuser +-- + +INSERT INTO public.representation_content (id, content, last_migration_performed, migration_version, created_on, last_modified_on) VALUES ('894983da-5371-41ef-bc80-9dc8a120a226', '{"id":"894983da-5371-41ef-bc80-9dc8a120a226","kind":"siriusComponents://representation?type=Diagram","targetObjectId":"e3155a70-343d-473c-a893-47afe98aa0ed","descriptionId":"siriusComponents://representationDescription?kind=diagramDescription&sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=db495705-e917-319b-af55-a32ad63f4089","nodes":[{"id":"2bcf0a92-1fdc-3a9e-8669-dadee19f18d3","type":"customnode:sysmlimportedpackage","targetObjectId":"4ad3f152-0aee-45f1-a2dd-ace82cb98cdd","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=NamespaceImport","targetObjectLabel":"import Actions::*","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=4b5e1adb-c89b-306c-997a-185081f79ad3","borderNode":false,"modifiers":[],"state":"Normal","collapsingState":"EXPANDED","insideLabel":{"id":"7a505d31-e279-352d-8c23-3c22ab7cb511","text":"«private»\nActions","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":14,"bold":false,"italic":false,"underline":false,"strikeThrough":false,"iconURL":["/icons/full/obj16/NamespaceImport.svg","/icons/full/ovr16/VisibilityKind_private.svg"],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":false,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"WRAP","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"#ffffff","borderColor":"#000000","borderSize":1,"borderStyle":"Solid","childrenLayoutStrategy":{"kind":"FreeForm"}},"borderNodes":[],"childNodes":[],"defaultWidth":300,"defaultHeight":100,"labelEditable":false,"pinned":false,"customizedStyleProperties":[]},{"id":"96e43f6d-4051-3f6c-8f70-ced68856a512","type":"customnode:sysmlnote","targetObjectId":"3166be3d-7cdc-4e31-8e33-c8ea31f9fe79","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=Comment","targetObjectLabel":"Comment","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=e654cd17-6874-31a7-b323-54e9b63499a8","borderNode":false,"modifiers":[],"state":"Normal","collapsingState":"EXPANDED","insideLabel":{"id":"07f6335e-6964-3786-a17a-d5646f30140d","text":"«comment»\n\nadd comment here","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":14,"bold":false,"italic":false,"underline":false,"strikeThrough":false,"iconURL":["/icons/full/obj16/Comment.svg"],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":false,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"WRAP","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"#ffffff","borderColor":"#000000","borderSize":1,"borderStyle":"Solid","childrenLayoutStrategy":{"kind":"FreeForm"}},"borderNodes":[],"childNodes":[],"defaultWidth":200,"defaultHeight":70,"labelEditable":true,"pinned":false,"customizedStyleProperties":[]},{"id":"84ba7c64-44ff-3e94-a5ef-737fb13fdb5f","type":"customnode:sysmlpackage","targetObjectId":"ccb0ef46-46b7-4c45-8426-6927eece71f0","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=Package","targetObjectLabel":"Package1","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=c0ac286a-69c6-389a-9635-a559ec3e942d","borderNode":false,"modifiers":[],"state":"Normal","collapsingState":"EXPANDED","insideLabel":{"id":"12873ae0-5c41-38d5-8c71-361d094f36ab","text":"Package1","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":14,"bold":false,"italic":false,"underline":false,"strikeThrough":false,"iconURL":["/icons/full/obj16/Package.svg"],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":false,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"ELLIPSIS","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"#ffffff","borderColor":"#000000","borderSize":1,"borderStyle":"Solid","childrenLayoutStrategy":{"kind":"FreeForm"}},"borderNodes":[],"childNodes":[],"defaultWidth":200,"defaultHeight":101,"labelEditable":true,"pinned":false,"customizedStyleProperties":[]},{"id":"c7998634-4bd5-3724-8880-85fb5d12a8ff","type":"node:rectangle","targetObjectId":"35401cff-45df-4f97-ba90-75f7eea53310","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=PartUsage","targetObjectLabel":"part1","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=bd119f62-45c5-3868-9727-9f954e05e4fa","borderNode":false,"modifiers":[],"state":"Normal","collapsingState":"EXPANDED","insideLabel":{"id":"14f894a5-30ed-3866-81df-8bf9e799afbc","text":"«part»\npart1","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":14,"bold":false,"italic":false,"underline":false,"strikeThrough":false,"iconURL":["/icons/full/obj16/PartUsage.svg"],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":true,"headerSeparatorDisplayMode":"IF_CHILDREN","overflowStrategy":"WRAP","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"#ffffff","borderColor":"#000000","borderSize":1,"borderRadius":10,"borderStyle":"Solid","childrenLayoutStrategy":{"areChildNodesDraggable":false,"topGap":0,"bottomGap":0,"growableNodeIds":["siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=30a9de2f-14f9-3de6-b68e-06b79b675555","siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=c47f5c71-1cc7-3f23-8c03-c335c2d13c66"],"kind":"List"}},"borderNodes":[],"childNodes":[{"id":"24a9f29a-7718-31d1-886e-4e4e90eb5745","type":"node:rectangle","targetObjectId":"35401cff-45df-4f97-ba90-75f7eea53310","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=PartUsage","targetObjectLabel":"part1","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=c901d8ce-4c57-3ede-8fdb-3c5aa91b67ba","borderNode":false,"modifiers":["Hidden"],"state":"Hidden","collapsingState":"EXPANDED","insideLabel":{"id":"ebd182b3-37dc-316f-818d-d45f47948485","text":"doc","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":12,"bold":false,"italic":true,"underline":false,"strikeThrough":false,"iconURL":[],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":true,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"NONE","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"transparent","borderColor":"#000000","borderSize":1,"borderRadius":0,"borderStyle":"Solid","childrenLayoutStrategy":{"areChildNodesDraggable":true,"topGap":0,"bottomGap":10,"growableNodeIds":[],"kind":"List"}},"borderNodes":[],"childNodes":[],"defaultWidth":155,"defaultHeight":60,"labelEditable":false,"pinned":false,"customizedStyleProperties":[]},{"id":"bb4a0bad-df01-3024-b578-ca22c2238157","type":"node:rectangle","targetObjectId":"35401cff-45df-4f97-ba90-75f7eea53310","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=PartUsage","targetObjectLabel":"part1","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=a1300415-10e4-37bb-87ed-206ec95079f0","borderNode":false,"modifiers":["Hidden"],"state":"Hidden","collapsingState":"EXPANDED","insideLabel":{"id":"29f5299d-53c2-3bc3-9096-3fb3e03bcb36","text":"attributes","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":12,"bold":false,"italic":true,"underline":false,"strikeThrough":false,"iconURL":[],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":true,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"NONE","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"transparent","borderColor":"#000000","borderSize":1,"borderRadius":0,"borderStyle":"Solid","childrenLayoutStrategy":{"areChildNodesDraggable":true,"topGap":0,"bottomGap":10,"growableNodeIds":[],"kind":"List"}},"borderNodes":[],"childNodes":[],"defaultWidth":155,"defaultHeight":60,"labelEditable":false,"pinned":false,"customizedStyleProperties":[]},{"id":"747bd6cf-1a71-3ac6-8606-ab838477c8ff","type":"node:rectangle","targetObjectId":"35401cff-45df-4f97-ba90-75f7eea53310","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=PartUsage","targetObjectLabel":"part1","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=f664d1f2-e48d-3f5a-a073-141fc0ddc418","borderNode":false,"modifiers":["Hidden"],"state":"Hidden","collapsingState":"EXPANDED","insideLabel":{"id":"9eb2a4de-2b8f-3d13-83a2-7ab44c1a8933","text":"actions","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":12,"bold":false,"italic":true,"underline":false,"strikeThrough":false,"iconURL":[],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":true,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"NONE","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"transparent","borderColor":"#000000","borderSize":1,"borderRadius":0,"borderStyle":"Solid","childrenLayoutStrategy":{"areChildNodesDraggable":true,"topGap":0,"bottomGap":10,"growableNodeIds":[],"kind":"List"}},"borderNodes":[],"childNodes":[],"defaultWidth":155,"defaultHeight":60,"labelEditable":false,"pinned":false,"customizedStyleProperties":[]},{"id":"f0c5e9af-7963-3a21-9f1d-9d794b42dc09","type":"node:rectangle","targetObjectId":"35401cff-45df-4f97-ba90-75f7eea53310","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=PartUsage","targetObjectLabel":"part1","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=cc126737-2324-3253-ae11-37d5b0dee7b9","borderNode":false,"modifiers":["Hidden"],"state":"Hidden","collapsingState":"EXPANDED","insideLabel":{"id":"c55891d3-c4ed-3242-9d61-230960b22fe1","text":"ports","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":12,"bold":false,"italic":true,"underline":false,"strikeThrough":false,"iconURL":[],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":true,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"NONE","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"transparent","borderColor":"#000000","borderSize":1,"borderRadius":0,"borderStyle":"Solid","childrenLayoutStrategy":{"areChildNodesDraggable":true,"topGap":0,"bottomGap":10,"growableNodeIds":[],"kind":"List"}},"borderNodes":[],"childNodes":[],"defaultWidth":155,"defaultHeight":60,"labelEditable":false,"pinned":false,"customizedStyleProperties":[]},{"id":"0b885323-e650-3e4e-a4d7-397695fa40c2","type":"node:rectangle","targetObjectId":"35401cff-45df-4f97-ba90-75f7eea53310","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=PartUsage","targetObjectLabel":"part1","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=30a9de2f-14f9-3de6-b68e-06b79b675555","borderNode":false,"modifiers":["Hidden"],"state":"Hidden","collapsingState":"EXPANDED","insideLabel":{"id":"34608ab0-04ce-3a6c-ba7f-5d38f818a2ac","text":"action flow","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":12,"bold":false,"italic":true,"underline":false,"strikeThrough":false,"iconURL":[],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":true,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"NONE","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"transparent","borderColor":"#000000","borderSize":1,"borderRadius":0,"borderStyle":"Solid","childrenLayoutStrategy":{"kind":"FreeForm"}},"borderNodes":[],"childNodes":[],"defaultWidth":155,"defaultHeight":150,"labelEditable":false,"pinned":false,"customizedStyleProperties":[]},{"id":"5d10a8fc-a74d-30be-b1a5-0680423bb1df","type":"node:rectangle","targetObjectId":"35401cff-45df-4f97-ba90-75f7eea53310","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=PartUsage","targetObjectLabel":"part1","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=c47f5c71-1cc7-3f23-8c03-c335c2d13c66","borderNode":false,"modifiers":["Hidden"],"state":"Hidden","collapsingState":"EXPANDED","insideLabel":{"id":"9fc660d2-62b6-3b35-9282-5f8d56eddaf4","text":"state transition","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":12,"bold":false,"italic":true,"underline":false,"strikeThrough":false,"iconURL":[],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":true,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"NONE","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"transparent","borderColor":"#000000","borderSize":1,"borderRadius":0,"borderStyle":"Solid","childrenLayoutStrategy":{"kind":"FreeForm"}},"borderNodes":[],"childNodes":[],"defaultWidth":155,"defaultHeight":150,"labelEditable":false,"pinned":false,"customizedStyleProperties":[]},{"id":"eac78b2a-e2f0-3dd4-8341-7ef407b3d574","type":"node:rectangle","targetObjectId":"35401cff-45df-4f97-ba90-75f7eea53310","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=PartUsage","targetObjectLabel":"part1","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=c97028bb-f0ba-3e9e-97a6-170cb6345d62","borderNode":false,"modifiers":["Hidden"],"state":"Hidden","collapsingState":"EXPANDED","insideLabel":{"id":"e022e645-23ac-39e3-9bb3-36036af7ba40","text":"states","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":12,"bold":false,"italic":true,"underline":false,"strikeThrough":false,"iconURL":[],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":true,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"NONE","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"transparent","borderColor":"#000000","borderSize":1,"borderRadius":0,"borderStyle":"Solid","childrenLayoutStrategy":{"areChildNodesDraggable":true,"topGap":0,"bottomGap":10,"growableNodeIds":[],"kind":"List"}},"borderNodes":[],"childNodes":[],"defaultWidth":155,"defaultHeight":60,"labelEditable":false,"pinned":false,"customizedStyleProperties":[]},{"id":"7f67b8ff-bccb-3478-a8d0-1adabdc2c2f9","type":"node:rectangle","targetObjectId":"35401cff-45df-4f97-ba90-75f7eea53310","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=PartUsage","targetObjectLabel":"part1","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=a57f3491-bd3e-38c6-bb8b-b0a4b570bd3a","borderNode":false,"modifiers":["Hidden"],"state":"Hidden","collapsingState":"EXPANDED","insideLabel":{"id":"ca19671b-02f7-31a1-86b8-ae9caeff325f","text":"exhibit states","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":12,"bold":false,"italic":true,"underline":false,"strikeThrough":false,"iconURL":[],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":true,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"NONE","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"transparent","borderColor":"#000000","borderSize":1,"borderRadius":0,"borderStyle":"Solid","childrenLayoutStrategy":{"areChildNodesDraggable":true,"topGap":0,"bottomGap":10,"growableNodeIds":[],"kind":"List"}},"borderNodes":[],"childNodes":[],"defaultWidth":155,"defaultHeight":60,"labelEditable":false,"pinned":false,"customizedStyleProperties":[]},{"id":"2325e8cd-9c0c-306d-a931-e3d81ff078e1","type":"node:rectangle","targetObjectId":"35401cff-45df-4f97-ba90-75f7eea53310","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=PartUsage","targetObjectLabel":"part1","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=fe94bbc6-f9c3-34cb-90fa-34a6701f9c17","borderNode":false,"modifiers":["Hidden"],"state":"Hidden","collapsingState":"EXPANDED","insideLabel":{"id":"8402c02b-91a5-327e-b37f-c5c58f15f9a5","text":"perform actions","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":12,"bold":false,"italic":true,"underline":false,"strikeThrough":false,"iconURL":[],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":true,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"NONE","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"transparent","borderColor":"#000000","borderSize":1,"borderRadius":0,"borderStyle":"Solid","childrenLayoutStrategy":{"areChildNodesDraggable":true,"topGap":0,"bottomGap":10,"growableNodeIds":[],"kind":"List"}},"borderNodes":[],"childNodes":[],"defaultWidth":155,"defaultHeight":60,"labelEditable":false,"pinned":false,"customizedStyleProperties":[]}],"defaultWidth":155,"defaultHeight":60,"labelEditable":true,"pinned":false,"customizedStyleProperties":[]},{"id":"b0d1e4e0-a9ad-3d1c-bf16-cb15881464f2","type":"customnode:sysmlviewframe","targetObjectId":"911e49b9-3bdb-462f-b7b4-c45e66fe8d0b","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=ViewUsage","targetObjectLabel":"view2","descriptionId":"siriusComponents://nodeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=7001fab9-43ec-356c-8dad-26574a6b2d53","borderNode":false,"modifiers":[],"state":"Normal","collapsingState":"EXPANDED","insideLabel":{"id":"95b36563-2161-303e-9423-0a0200b03711","text":"«view» view2 : StandardViewDefinitions::GeneralView","insideLabelLocation":"TOP_CENTER","style":{"color":"#000000","fontSize":14,"bold":false,"italic":false,"underline":false,"strikeThrough":false,"iconURL":["/icons/full/obj16/ViewUsage.svg"],"background":"transparent","borderColor":"black","borderSize":0,"borderRadius":3,"borderStyle":"Solid","maxWidth":null},"isHeader":false,"headerSeparatorDisplayMode":"NEVER","overflowStrategy":"ELLIPSIS","textAlign":"CENTER","customizedStyleProperties":[]},"outsideLabels":[],"style":{"background":"#ffffff","borderColor":"#000000","borderSize":1,"borderStyle":"Solid","borderRadius":10,"childrenLayoutStrategy":{"kind":"FreeForm"}},"borderNodes":[],"childNodes":[],"defaultWidth":300,"defaultHeight":101,"labelEditable":true,"pinned":false,"customizedStyleProperties":[]}],"edges":[{"id":"7c2134f1-cf81-3e20-8201-89c347b0469e","type":"edge:straight","targetObjectId":"3166be3d-7cdc-4e31-8e33-c8ea31f9fe79","targetObjectKind":"siriusComponents://semantic?domain=sysml&entity=Comment","targetObjectLabel":"Comment","descriptionId":"siriusComponents://edgeDescription?sourceKind=view&sourceId=8dcd14b0-6259-3193-ad2c-743f394c68e4&sourceElementId=2a32ca7e-3477-3476-88ec-a853059c2aa7","beginLabel":null,"centerLabel":null,"endLabel":null,"sourceId":"96e43f6d-4051-3f6c-8f70-ced68856a512","targetId":"c7998634-4bd5-3724-8880-85fb5d12a8ff","modifiers":[],"state":"Normal","style":{"size":1,"lineStyle":"Dash","sourceArrow":"None","targetArrow":"None","color":"#000000"},"centerLabelEditable":false,"customizedStyleProperties":[]}],"layoutData":{"nodeLayoutData":{"747bd6cf-1a71-3ac6-8606-ab838477c8ff":{"id":"747bd6cf-1a71-3ac6-8606-ab838477c8ff","position":{"x":0.0,"y":0.0},"size":{"width":155.0,"height":60.0},"resizedByUser":false,"handleLayoutData":[]},"c7998634-4bd5-3724-8880-85fb5d12a8ff":{"id":"c7998634-4bd5-3724-8880-85fb5d12a8ff","position":{"x":394.0,"y":483.0},"size":{"width":155.0,"height":60.0},"resizedByUser":false,"handleLayoutData":[]},"f0c5e9af-7963-3a21-9f1d-9d794b42dc09":{"id":"f0c5e9af-7963-3a21-9f1d-9d794b42dc09","position":{"x":0.0,"y":0.0},"size":{"width":155.0,"height":60.0},"resizedByUser":false,"handleLayoutData":[]},"2bcf0a92-1fdc-3a9e-8669-dadee19f18d3":{"id":"2bcf0a92-1fdc-3a9e-8669-dadee19f18d3","position":{"x":12.0,"y":173.0},"size":{"width":300.0,"height":100.0},"resizedByUser":false,"handleLayoutData":[]},"2325e8cd-9c0c-306d-a931-e3d81ff078e1":{"id":"2325e8cd-9c0c-306d-a931-e3d81ff078e1","position":{"x":0.0,"y":0.0},"size":{"width":155.0,"height":60.0},"resizedByUser":false,"handleLayoutData":[]},"5d10a8fc-a74d-30be-b1a5-0680423bb1df":{"id":"5d10a8fc-a74d-30be-b1a5-0680423bb1df","position":{"x":0.0,"y":0.0},"size":{"width":155.0,"height":150.0},"resizedByUser":false,"handleLayoutData":[]},"0b885323-e650-3e4e-a4d7-397695fa40c2":{"id":"0b885323-e650-3e4e-a4d7-397695fa40c2","position":{"x":0.0,"y":0.0},"size":{"width":155.0,"height":150.0},"resizedByUser":false,"handleLayoutData":[]},"96e43f6d-4051-3f6c-8f70-ced68856a512":{"id":"96e43f6d-4051-3f6c-8f70-ced68856a512","position":{"x":372.0,"y":333.0},"size":{"width":200.0,"height":70.0},"resizedByUser":false,"handleLayoutData":[]},"24a9f29a-7718-31d1-886e-4e4e90eb5745":{"id":"24a9f29a-7718-31d1-886e-4e4e90eb5745","position":{"x":0.0,"y":0.0},"size":{"width":155.0,"height":60.0},"resizedByUser":false,"handleLayoutData":[]},"7f67b8ff-bccb-3478-a8d0-1adabdc2c2f9":{"id":"7f67b8ff-bccb-3478-a8d0-1adabdc2c2f9","position":{"x":0.0,"y":0.0},"size":{"width":155.0,"height":60.0},"resizedByUser":false,"handleLayoutData":[]},"b0d1e4e0-a9ad-3d1c-bf16-cb15881464f2":{"id":"b0d1e4e0-a9ad-3d1c-bf16-cb15881464f2","position":{"x":12.0,"y":333.0},"size":{"width":300.0,"height":101.0},"resizedByUser":false,"handleLayoutData":[]},"84ba7c64-44ff-3e94-a5ef-737fb13fdb5f":{"id":"84ba7c64-44ff-3e94-a5ef-737fb13fdb5f","position":{"x":72.0,"y":12.0},"size":{"width":200.0,"height":101.0},"resizedByUser":false,"handleLayoutData":[]},"eac78b2a-e2f0-3dd4-8341-7ef407b3d574":{"id":"eac78b2a-e2f0-3dd4-8341-7ef407b3d574","position":{"x":0.0,"y":0.0},"size":{"width":155.0,"height":60.0},"resizedByUser":false,"handleLayoutData":[]},"bb4a0bad-df01-3024-b578-ca22c2238157":{"id":"bb4a0bad-df01-3024-b578-ca22c2238157","position":{"x":0.0,"y":0.0},"size":{"width":155.0,"height":60.0},"resizedByUser":false,"handleLayoutData":[]}},"edgeLayoutData":{"7c2134f1-cf81-3e20-8201-89c347b0469e":{"id":"7c2134f1-cf81-3e20-8201-89c347b0469e","bendingPoints":[],"edgeAnchorLayoutData":[]}},"labelLayoutData":{}}}', 'none', '2025.8.0-202506301700', '2025-09-17 09:19:53.845467+00', '2025-09-17 09:22:27.059243+00'); + + +-- +-- Data for Name: semantic_data_dependency; Type: TABLE DATA; Schema: public; Owner: dbuser +-- + + + +-- +-- Data for Name: semantic_data_domain; Type: TABLE DATA; Schema: public; Owner: dbuser +-- + +INSERT INTO public.semantic_data_domain (semantic_data_id, uri) VALUES ('aeb3587e-29ae-425e-b4fb-c33745002aac', 'http://www.eclipse.org/syson/sysml'); + + +-- +-- PostgreSQL database dump complete +-- + diff --git a/backend/application/syson-application/src/test/resources/scripts/dump-test-data.sh b/backend/application/syson-application/src/test/resources/scripts/dump-test-data.sh index 7d2c80e09..6ca80741f 100755 --- a/backend/application/syson-application/src/test/resources/scripts/dump-test-data.sh +++ b/backend/application/syson-application/src/test/resources/scripts/dump-test-data.sh @@ -16,10 +16,8 @@ fi echo "Extracting test data from syson-db to ./${1}" # Remove winpty if you are not calling the script from git bash -winpty pg_dump --host localhost --port 5433 --file "./${1}" --username dbuser --format=p --encoding UTF8 --data-only --column-inserts --table public.document --table public.project --table public.representation_metadata --table public.representation_content --table public.semantic_data --table public.project_semantic_data --table public.semantic_data_dependency --table public.semantic_data_domain --table public.image --table public.library --table public.nature --table public.project_image syson-db -echo "Done" -echo "Cleaning test data" -sed -i "/^SELECT pg_catalog.set_config('search_path', '', false);/d" ./${1} +pg_dump --host localhost --port 5433 --file "./${1}" --username dbuser --format=p --encoding UTF8 --data-only --column-inserts --table public.document --table public.project --table public.representation_metadata --table public.representation_content --table public.semantic_data --table public.project_semantic_data --table public.semantic_data_dependency --table public.semantic_data_domain --table public.image --table public.library --table public.nature --table public.project_image syson-db echo "Done" + exit 0 \ No newline at end of file diff --git a/doc/content/modules/user-manual/pages/release-notes/2025.10.0.adoc b/doc/content/modules/user-manual/pages/release-notes/2025.10.0.adoc index 0426a32ee..c6ca91efc 100644 --- a/doc/content/modules/user-manual/pages/release-notes/2025.10.0.adoc +++ b/doc/content/modules/user-manual/pages/release-notes/2025.10.0.adoc @@ -45,6 +45,7 @@ This contribution introduces some breaking changes: == New features - In diagrams, it is now possible to switch from one _ViewDefinition_ to another one without having to re-create the diagram. +- In diagrams, it is now possible to change the appearance (color, font...) of all diagram elements, through the new _Palette_ menu _Appearance_. == Bug fixes diff --git a/frontend/syson-components/src/index.ts b/frontend/syson-components/src/index.ts index 3b37847ae..0e08a1455 100644 --- a/frontend/syson-components/src/index.ts +++ b/frontend/syson-components/src/index.ts @@ -10,10 +10,10 @@ * Contributors: * Obeo - initial API and implementation *******************************************************************************/ -export { InsertTextualSysMLMenuContribution } from './extensions/InsertTextualSysMLv2MenuContribution'; -export { InsertTextualSysMLv2Modal } from './extensions/InsertTextualSysMLv2Modal'; export { SysONDocumentTreeItemContextMenuContribution } from './extensions/contextMenu/SysONDocumentTreeItemContextMenuContribution'; export { SysONObjectTreeItemContextMenuContribution } from './extensions/contextMenu/SysONObjectTreeItemContextMenuContribution'; +export { InsertTextualSysMLMenuContribution } from './extensions/InsertTextualSysMLv2MenuContribution'; +export { InsertTextualSysMLv2Modal } from './extensions/InsertTextualSysMLv2Modal'; export { SysONNavigationBarMenuIcon } from './extensions/navigationBarMenu/SysONNavigationBarMenuIcon'; export { PublishProjectSysMLContentsAsLibraryCommand } from './extensions/omnibox/PublishProjectSysMLContentsAsLibraryCommand'; export type { PublishProjectSysMLContentsAsLibraryCommandState } from './extensions/omnibox/PublishProjectSysMLContentsAsLibraryCommand.types'; @@ -26,13 +26,46 @@ export { useInsertTextualSysMLv2 } from './extensions/useInsertTextualSysMLv2'; export { SysMLImportedPackageNode } from './nodes/imported_package/SysMLImportedPackageNode'; export { SysMLImportedPackageNodeConverter } from './nodes/imported_package/SysMLImportedPackageNodeConverter'; export { SysMLImportedPackageNodeLayoutHandler } from './nodes/imported_package/SysMLImportedPackageNodeLayoutHandler'; +export { SysMLImportedPackageNodePaletteAppearanceSection } from './nodes/imported_package/SysMLImportedPackageNodePaletteAppearanceSection'; +export type { SysMLImportedPackageNodePaletteAppearanceSectionState } from './nodes/imported_package/SysMLImportedPackageNodePaletteAppearanceSection.types'; +export { SysMLImportedPackageNodePart } from './nodes/imported_package/SysMLImportedPackageNodePart'; +export { + type GQLSysMLImportedPackageNodeStyle, + type SysMLImportedPackageNodePartProps, +} from './nodes/imported_package/SysMLImportedPackageNodePart.types'; +export { useUpdateSysMLImportedPackageNodeAppearance } from './nodes/imported_package/useUpdateSysMLImportedPackageNodeAppearance'; export { SysMLNoteNode } from './nodes/note/SysMLNoteNode'; export { SysMLNoteNodeConverter } from './nodes/note/SysMLNoteNodeConverter'; export { SysMLNoteNodeLayoutHandler } from './nodes/note/SysMLNoteNodeLayoutHandler'; +export { SysMLNoteNodePaletteAppearanceSection } from './nodes/note/SysMLNoteNodePaletteAppearanceSection'; +export type { SysMLNoteNodePaletteAppearanceSectionState } from './nodes/note/SysMLNoteNodePaletteAppearanceSection.types'; +export { SysMLNoteNodePart } from './nodes/note/SysMLNoteNodePart'; +export { type GQLSysMLNoteNodeStyle, type SysMLNoteNodePartProps } from './nodes/note/SysMLNoteNodePart.types'; +export { useUpdateSysMLNoteNodeAppearance } from './nodes/note/useUpdateSysMLNoteNodeAppearance'; export { SysMLPackageNode } from './nodes/package/SysMLPackageNode'; export { SysMLPackageNodeConverter } from './nodes/package/SysMLPackageNodeConverter'; export { SysMLPackageNodeLayoutHandler } from './nodes/package/SysMLPackageNodeLayoutHandler'; +export { SysMLPackageNodePaletteAppearanceSection } from './nodes/package/SysMLPackageNodePaletteAppearanceSection'; +export type { SysMLPackageNodePaletteAppearanceSectionState } from './nodes/package/SysMLPackageNodePaletteAppearanceSection.types'; +export { SysMLPackageNodePart } from './nodes/package/SysMLPackageNodePart'; +export { + type GQLSysMLPackageNodeStyle, + type SysMLPackageNodePartProps, +} from './nodes/package/SysMLPackageNodePart.types'; +export { useUpdateSysMLPackageNodeAppearance } from './nodes/package/useUpdateSysMLPackageNodeAppearance'; +export { + type GQLEditSysMLPackageNodeAppearancePayload, + type UseUpdateSysMLPackageNodeAppearanceValue, +} from './nodes/package/useUpdateSysMLPackageNodeAppearance.types'; export { sysMLNodesStyleDocumentTransform } from './nodes/SysMLNodesDocumentTransform'; export { SysMLViewFrameNode } from './nodes/view_frame/SysMLViewFrameNode'; export { SysMLViewFrameNodeConverter } from './nodes/view_frame/SysMLViewFrameNodeConverter'; export { SysMLViewFrameNodeLayoutHandler } from './nodes/view_frame/SysMLViewFrameNodeLayoutHandler'; +export { SysMLViewFrameNodePaletteAppearanceSection } from './nodes/view_frame/SysMLViewFrameNodePaletteAppearanceSection'; +export type { SysMLViewFrameNodePaletteAppearanceSectionState } from './nodes/view_frame/SysMLViewFrameNodePaletteAppearanceSection.types'; +export { SysMLViewFrameNodePart } from './nodes/view_frame/SysMLViewFrameNodePart'; +export { + type GQLSysMLViewFrameNodeStyle, + type SysMLViewFrameNodePartProps, +} from './nodes/view_frame/SysMLViewFrameNodePart.types'; +export { useUpdateSysMLViewFrameNodeAppearance } from './nodes/view_frame/useUpdateSysMLViewFrameNodeAppearance'; diff --git a/frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePaletteAppearanceSection.tsx b/frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePaletteAppearanceSection.tsx new file mode 100644 index 000000000..97c65c5b8 --- /dev/null +++ b/frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePaletteAppearanceSection.tsx @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { + LabelAppearancePart, + PaletteAppearanceSectionContributionComponentProps, +} from '@eclipse-sirius/sirius-components-diagrams'; + +import { SysMLImportedPackageNodePart } from './SysMLImportedPackageNodePart'; + +export const SysMLImportedPackageNodePaletteAppearanceSection = ({ + element, + elementId, +}: PaletteAppearanceSectionContributionComponentProps) => { + return ( + <> + + {element.data.insideLabel ? ( + + ) : null} + + ); +}; diff --git a/frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePaletteAppearanceSection.types.ts b/frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePaletteAppearanceSection.types.ts new file mode 100644 index 000000000..1170b0048 --- /dev/null +++ b/frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePaletteAppearanceSection.types.ts @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +export interface SysMLImportedPackageNodePaletteAppearanceSectionState { + background: string; + borderColor: string; + borderSize: number; + borderStyle: string; +} diff --git a/frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePart.tsx b/frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePart.tsx new file mode 100644 index 000000000..8cbd8429b --- /dev/null +++ b/frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePart.tsx @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { + AppearanceColorPicker, + AppearanceNumberTextfield, + AppearanceSelect, + DiagramContext, + DiagramContextValue, + useResetNodeAppearance, +} from '@eclipse-sirius/sirius-components-diagrams'; +import LineStyleIcon from '@mui/icons-material/LineStyle'; +import LineWeightIcon from '@mui/icons-material/LineWeight'; +import Box from '@mui/material/Box'; +import ListItem from '@mui/material/ListItem'; +import Typography from '@mui/material/Typography'; +import { useContext } from 'react'; +import { + GQLSysMLImportedPackageNodeStyle, + SysMLImportedPackageNodePartProps, +} from './SysMLImportedPackageNodePart.types'; +import { useUpdateSysMLImportedPackageNodeAppearance } from './useUpdateSysMLImportedPackageNodeAppearance'; +import { GQLSysMLImportedPackageNodeAppearanceInput } from './useUpdateSysMLImportedPackageNodeAppearance.types'; + +const LINE_STYLE_OPTIONS = [ + { value: 'Solid', label: 'Solid' }, + { value: 'Dash', label: 'Dash' }, + { value: 'Dot', label: 'Dot' }, + { value: 'Dash_Dot', label: 'Dash Dot' }, +]; + +export const SysMLImportedPackageNodePart = ({ element }: SysMLImportedPackageNodePartProps) => { + const style = element.data.nodeAppearanceData.gqlStyle as GQLSysMLImportedPackageNodeStyle; + const customizedStyleProperties = element.data.nodeAppearanceData.customizedStyleProperties; + + const { editingContextId, diagramId } = useContext(DiagramContext); + const { updateSysMLImportedPackageNodeAppearance } = useUpdateSysMLImportedPackageNodeAppearance(); + const { resetNodeStyleProperties } = useResetNodeAppearance(); + + const handleResetProperty = (customizedStyleProperty: string) => + resetNodeStyleProperties(editingContextId, diagramId, element.id, [customizedStyleProperty]); + + const handleEditProperty = (newValue: Partial) => + updateSysMLImportedPackageNodeAppearance(editingContextId, diagramId, element.id, newValue); + + const isDisabled = (property: string) => !customizedStyleProperties.includes(property); + + return ( + ({ paddingX: theme.spacing(1), paddingBottom: theme.spacing(1) })}> + + Style + + handleEditProperty({ background: newValue })} + onReset={() => handleResetProperty('BACKGROUND')}> + + handleEditProperty({ borderColor: newValue })} + onReset={() => handleResetProperty('BORDER_COLOR')}> + + } + label={'Border Size'} + initialValue={style.borderSize} + isDisabled={isDisabled('BORDER_SIZE')} + onEdit={(newValue) => handleEditProperty({ borderSize: newValue })} + onReset={() => handleResetProperty('BORDER_SIZE')}> + + } + label={'Border Line Style'} + options={LINE_STYLE_OPTIONS} + initialValue={style.borderStyle} + isDisabled={isDisabled('BORDER_STYLE')} + onEdit={(newValue) => handleEditProperty({ borderStyle: newValue })} + onReset={() => handleResetProperty('BORDER_STYLE')}> + + + ); +}; diff --git a/frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePart.types.ts b/frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePart.types.ts new file mode 100644 index 000000000..8505859ef --- /dev/null +++ b/frontend/syson-components/src/nodes/imported_package/SysMLImportedPackageNodePart.types.ts @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { GQLNodeStyle, NodeData } from '@eclipse-sirius/sirius-components-diagrams'; +import { InternalNode, Node } from '@xyflow/react'; + +export interface GQLSysMLImportedPackageNodeStyle extends GQLNodeStyle { + background: string; + borderColor: string; + borderSize: number; + borderStyle: string; +} + +export interface SysMLImportedPackageNodePartProps { + element: InternalNode>; +} diff --git a/frontend/syson-components/src/nodes/imported_package/useUpdateSysMLImportedPackageNodeAppearance.ts b/frontend/syson-components/src/nodes/imported_package/useUpdateSysMLImportedPackageNodeAppearance.ts new file mode 100644 index 000000000..16bbedc94 --- /dev/null +++ b/frontend/syson-components/src/nodes/imported_package/useUpdateSysMLImportedPackageNodeAppearance.ts @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { gql, useMutation } from '@apollo/client'; +import { useReporting } from '@eclipse-sirius/sirius-components-core'; +import { + GQLEditSysMLImportedPackageNodeAppearanceData, + GQLEditSysMLImportedPackageNodeAppearanceVariables, + GQLSysMLImportedPackageNodeAppearanceInput, + UseUpdateSysMLImportedPackageNodeAppearanceValue, +} from './useUpdateSysMLImportedPackageNodeAppearance.types'; + +export const editSysMLImportedPackageNodeAppearanceMutation = gql` + mutation editSysMLImportedPackageNodeAppearance($input: EditSysMLImportedPackageNodeAppearanceInput!) { + editSysMLImportedPackageNodeAppearance(input: $input) { + __typename + ... on ErrorPayload { + messages { + body + level + } + } + ... on SuccessPayload { + messages { + body + level + } + } + } + } +`; + +export const useUpdateSysMLImportedPackageNodeAppearance = (): UseUpdateSysMLImportedPackageNodeAppearanceValue => { + const [editSysMLImportedPackageNodeAppearance, editSysMLImportedPackageNodeAppearanceResult] = useMutation< + GQLEditSysMLImportedPackageNodeAppearanceData, + GQLEditSysMLImportedPackageNodeAppearanceVariables + >(editSysMLImportedPackageNodeAppearanceMutation); + + useReporting( + editSysMLImportedPackageNodeAppearanceResult, + (data: GQLEditSysMLImportedPackageNodeAppearanceData) => data.editSysMLImportedPackageNodeAppearance + ); + + const updateSysMLImportedPackageNodeAppearance = ( + editingContextId: string, + representationId: string, + nodeId: string, + appearance: Partial + ) => + editSysMLImportedPackageNodeAppearance({ + variables: { + input: { + id: crypto.randomUUID(), + editingContextId, + representationId, + nodeId, + appearance, + }, + }, + }); + + return { + updateSysMLImportedPackageNodeAppearance, + }; +}; diff --git a/frontend/syson-components/src/nodes/imported_package/useUpdateSysMLImportedPackageNodeAppearance.types.ts b/frontend/syson-components/src/nodes/imported_package/useUpdateSysMLImportedPackageNodeAppearance.types.ts new file mode 100644 index 000000000..f69610c49 --- /dev/null +++ b/frontend/syson-components/src/nodes/imported_package/useUpdateSysMLImportedPackageNodeAppearance.types.ts @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { GQLErrorPayload, GQLSuccessPayload } from '@eclipse-sirius/sirius-components-core'; + +export interface UseUpdateSysMLImportedPackageNodeAppearanceValue { + updateSysMLImportedPackageNodeAppearance: ( + editingContextId: string, + representationId: string, + nodeId: string, + appearance: Partial + ) => void; +} + +export interface GQLEditSysMLImportedPackageNodeAppearanceData { + editSysMLImportedPackageNodeAppearance: GQLEditSysMLImportedPackageNodeAppearancePayload; +} + +export type GQLEditSysMLImportedPackageNodeAppearancePayload = GQLErrorPayload | GQLSuccessPayload; + +export interface GQLEditSysMLImportedPackageNodeAppearanceVariables { + input: GQLEditSysMLImportedPackageNodeAppearanceInput; +} + +export interface GQLEditSysMLImportedPackageNodeAppearanceInput { + id: string; + editingContextId: string; + representationId: string; + nodeId: string; + appearance: Partial; +} + +export interface GQLSysMLImportedPackageNodeAppearanceInput { + background: string; + borderColor: string; + borderSize: number; + borderStyle: string; +} diff --git a/frontend/syson-components/src/nodes/note/SysMLNoteNodePaletteAppearanceSection.tsx b/frontend/syson-components/src/nodes/note/SysMLNoteNodePaletteAppearanceSection.tsx new file mode 100644 index 000000000..87645274a --- /dev/null +++ b/frontend/syson-components/src/nodes/note/SysMLNoteNodePaletteAppearanceSection.tsx @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { + LabelAppearancePart, + PaletteAppearanceSectionContributionComponentProps, +} from '@eclipse-sirius/sirius-components-diagrams'; + +import { SysMLNoteNodePart } from './SysMLNoteNodePart'; + +export const SysMLNoteNodePaletteAppearanceSection = ({ + element, + elementId, +}: PaletteAppearanceSectionContributionComponentProps) => { + return ( + <> + + {element.data.insideLabel ? ( + + ) : null} + + ); +}; diff --git a/frontend/syson-components/src/nodes/note/SysMLNoteNodePaletteAppearanceSection.types.ts b/frontend/syson-components/src/nodes/note/SysMLNoteNodePaletteAppearanceSection.types.ts new file mode 100644 index 000000000..5a9db8774 --- /dev/null +++ b/frontend/syson-components/src/nodes/note/SysMLNoteNodePaletteAppearanceSection.types.ts @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +export interface SysMLNoteNodePaletteAppearanceSectionState { + background: string; + borderColor: string; + borderSize: number; + borderStyle: string; +} diff --git a/frontend/syson-components/src/nodes/note/SysMLNoteNodePart.tsx b/frontend/syson-components/src/nodes/note/SysMLNoteNodePart.tsx new file mode 100644 index 000000000..71e52e05a --- /dev/null +++ b/frontend/syson-components/src/nodes/note/SysMLNoteNodePart.tsx @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { + AppearanceColorPicker, + AppearanceNumberTextfield, + AppearanceSelect, + DiagramContext, + DiagramContextValue, + useResetNodeAppearance, +} from '@eclipse-sirius/sirius-components-diagrams'; +import LineStyleIcon from '@mui/icons-material/LineStyle'; +import LineWeightIcon from '@mui/icons-material/LineWeight'; +import Box from '@mui/material/Box'; +import ListItem from '@mui/material/ListItem'; +import Typography from '@mui/material/Typography'; +import { useContext } from 'react'; +import { GQLSysMLNoteNodeStyle, SysMLNoteNodePartProps } from './SysMLNoteNodePart.types'; +import { useUpdateSysMLNoteNodeAppearance } from './useUpdateSysMLNoteNodeAppearance'; +import { GQLSysMLNoteNodeAppearanceInput } from './useUpdateSysMLNoteNodeAppearance.types'; + +const LINE_STYLE_OPTIONS = [ + { value: 'Solid', label: 'Solid' }, + { value: 'Dash', label: 'Dash' }, + { value: 'Dot', label: 'Dot' }, + { value: 'Dash_Dot', label: 'Dash Dot' }, +]; + +export const SysMLNoteNodePart = ({ element }: SysMLNoteNodePartProps) => { + const style = element.data.nodeAppearanceData.gqlStyle as GQLSysMLNoteNodeStyle; + const customizedStyleProperties = element.data.nodeAppearanceData.customizedStyleProperties; + + const { editingContextId, diagramId } = useContext(DiagramContext); + const { updateSysMLNoteNodeAppearance } = useUpdateSysMLNoteNodeAppearance(); + const { resetNodeStyleProperties } = useResetNodeAppearance(); + + const handleResetProperty = (customizedStyleProperty: string) => + resetNodeStyleProperties(editingContextId, diagramId, element.id, [customizedStyleProperty]); + + const handleEditProperty = (newValue: Partial) => + updateSysMLNoteNodeAppearance(editingContextId, diagramId, element.id, newValue); + + const isDisabled = (property: string) => !customizedStyleProperties.includes(property); + + return ( + ({ paddingX: theme.spacing(1), paddingBottom: theme.spacing(1) })}> + + Style + + handleEditProperty({ background: newValue })} + onReset={() => handleResetProperty('BACKGROUND')}> + + handleEditProperty({ borderColor: newValue })} + onReset={() => handleResetProperty('BORDER_COLOR')}> + + } + label={'Border Size'} + initialValue={style.borderSize} + isDisabled={isDisabled('BORDER_SIZE')} + onEdit={(newValue) => handleEditProperty({ borderSize: newValue })} + onReset={() => handleResetProperty('BORDER_SIZE')}> + + } + label={'Border Line Style'} + options={LINE_STYLE_OPTIONS} + initialValue={style.borderStyle} + isDisabled={isDisabled('BORDER_STYLE')} + onEdit={(newValue) => handleEditProperty({ borderStyle: newValue })} + onReset={() => handleResetProperty('BORDER_STYLE')}> + + + ); +}; diff --git a/frontend/syson-components/src/nodes/note/SysMLNoteNodePart.types.ts b/frontend/syson-components/src/nodes/note/SysMLNoteNodePart.types.ts new file mode 100644 index 000000000..81c769695 --- /dev/null +++ b/frontend/syson-components/src/nodes/note/SysMLNoteNodePart.types.ts @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { GQLNodeStyle, NodeData } from '@eclipse-sirius/sirius-components-diagrams'; +import { InternalNode, Node } from '@xyflow/react'; + +export interface GQLSysMLNoteNodeStyle extends GQLNodeStyle { + background: string; + borderColor: string; + borderSize: number; + borderStyle: string; +} + +export interface SysMLNoteNodePartProps { + element: InternalNode>; +} diff --git a/frontend/syson-components/src/nodes/note/useUpdateSysMLNoteNodeAppearance.ts b/frontend/syson-components/src/nodes/note/useUpdateSysMLNoteNodeAppearance.ts new file mode 100644 index 000000000..e4ed19417 --- /dev/null +++ b/frontend/syson-components/src/nodes/note/useUpdateSysMLNoteNodeAppearance.ts @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { gql, useMutation } from '@apollo/client'; +import { useReporting } from '@eclipse-sirius/sirius-components-core'; +import { + GQLEditSysMLNoteNodeAppearanceData, + GQLEditSysMLNoteNodeAppearanceVariables, + GQLSysMLNoteNodeAppearanceInput, + UseUpdateSysMLNoteNodeAppearanceValue, +} from './useUpdateSysMLNoteNodeAppearance.types'; + +export const editSysMLNoteNodeAppearanceMutation = gql` + mutation editSysMLNoteNodeAppearance($input: EditSysMLNoteNodeAppearanceInput!) { + editSysMLNoteNodeAppearance(input: $input) { + __typename + ... on ErrorPayload { + messages { + body + level + } + } + ... on SuccessPayload { + messages { + body + level + } + } + } + } +`; + +export const useUpdateSysMLNoteNodeAppearance = (): UseUpdateSysMLNoteNodeAppearanceValue => { + const [editSysMLNoteNodeAppearance, editSysMLNoteNodeAppearanceResult] = useMutation< + GQLEditSysMLNoteNodeAppearanceData, + GQLEditSysMLNoteNodeAppearanceVariables + >(editSysMLNoteNodeAppearanceMutation); + + useReporting( + editSysMLNoteNodeAppearanceResult, + (data: GQLEditSysMLNoteNodeAppearanceData) => data.editSysMLNoteNodeAppearance + ); + + const updateSysMLNoteNodeAppearance = ( + editingContextId: string, + representationId: string, + nodeId: string, + appearance: Partial + ) => + editSysMLNoteNodeAppearance({ + variables: { + input: { + id: crypto.randomUUID(), + editingContextId, + representationId, + nodeId, + appearance, + }, + }, + }); + + return { + updateSysMLNoteNodeAppearance, + }; +}; diff --git a/frontend/syson-components/src/nodes/note/useUpdateSysMLNoteNodeAppearance.types.ts b/frontend/syson-components/src/nodes/note/useUpdateSysMLNoteNodeAppearance.types.ts new file mode 100644 index 000000000..2426f49b0 --- /dev/null +++ b/frontend/syson-components/src/nodes/note/useUpdateSysMLNoteNodeAppearance.types.ts @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { GQLErrorPayload, GQLSuccessPayload } from '@eclipse-sirius/sirius-components-core'; + +export interface UseUpdateSysMLNoteNodeAppearanceValue { + updateSysMLNoteNodeAppearance: ( + editingContextId: string, + representationId: string, + nodeId: string, + appearance: Partial + ) => void; +} + +export interface GQLEditSysMLNoteNodeAppearanceData { + editSysMLNoteNodeAppearance: GQLEditSysMLNoteNodeAppearancePayload; +} + +export type GQLEditSysMLNoteNodeAppearancePayload = GQLErrorPayload | GQLSuccessPayload; + +export interface GQLEditSysMLNoteNodeAppearanceVariables { + input: GQLEditSysMLNoteNodeAppearanceInput; +} + +export interface GQLEditSysMLNoteNodeAppearanceInput { + id: string; + editingContextId: string; + representationId: string; + nodeId: string; + appearance: Partial; +} + +export interface GQLSysMLNoteNodeAppearanceInput { + background: string; + borderColor: string; + borderSize: number; + borderStyle: string; +} diff --git a/frontend/syson-components/src/nodes/package/SysMLPackageNodePaletteAppearanceSection.tsx b/frontend/syson-components/src/nodes/package/SysMLPackageNodePaletteAppearanceSection.tsx new file mode 100644 index 000000000..ef1ae9c56 --- /dev/null +++ b/frontend/syson-components/src/nodes/package/SysMLPackageNodePaletteAppearanceSection.tsx @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { + LabelAppearancePart, + PaletteAppearanceSectionContributionComponentProps, +} from '@eclipse-sirius/sirius-components-diagrams'; + +import { SysMLPackageNodePart } from './SysMLPackageNodePart'; + +export const SysMLPackageNodePaletteAppearanceSection = ({ + element, + elementId, +}: PaletteAppearanceSectionContributionComponentProps) => { + return ( + <> + + {element.data.insideLabel ? ( + + ) : null} + + ); +}; diff --git a/frontend/syson-components/src/nodes/package/SysMLPackageNodePaletteAppearanceSection.types.ts b/frontend/syson-components/src/nodes/package/SysMLPackageNodePaletteAppearanceSection.types.ts new file mode 100644 index 000000000..28bd69956 --- /dev/null +++ b/frontend/syson-components/src/nodes/package/SysMLPackageNodePaletteAppearanceSection.types.ts @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +export interface SysMLPackageNodePaletteAppearanceSectionState { + background: string; + borderColor: string; + borderSize: number; + borderStyle: string; +} diff --git a/frontend/syson-components/src/nodes/package/SysMLPackageNodePart.tsx b/frontend/syson-components/src/nodes/package/SysMLPackageNodePart.tsx new file mode 100644 index 000000000..1094fef2b --- /dev/null +++ b/frontend/syson-components/src/nodes/package/SysMLPackageNodePart.tsx @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { + AppearanceColorPicker, + AppearanceNumberTextfield, + AppearanceSelect, + DiagramContext, + DiagramContextValue, + useResetNodeAppearance, +} from '@eclipse-sirius/sirius-components-diagrams'; +import LineStyleIcon from '@mui/icons-material/LineStyle'; +import LineWeightIcon from '@mui/icons-material/LineWeight'; +import Box from '@mui/material/Box'; +import ListItem from '@mui/material/ListItem'; +import Typography from '@mui/material/Typography'; +import { useContext } from 'react'; +import { GQLSysMLPackageNodeStyle, SysMLPackageNodePartProps } from './SysMLPackageNodePart.types'; +import { useUpdateSysMLPackageNodeAppearance } from './useUpdateSysMLPackageNodeAppearance'; +import { GQLSysMLPackageNodeAppearanceInput } from './useUpdateSysMLPackageNodeAppearance.types'; + +const LINE_STYLE_OPTIONS = [ + { value: 'Solid', label: 'Solid' }, + { value: 'Dash', label: 'Dash' }, + { value: 'Dot', label: 'Dot' }, + { value: 'Dash_Dot', label: 'Dash Dot' }, +]; + +export const SysMLPackageNodePart = ({ element }: SysMLPackageNodePartProps) => { + const style = element.data.nodeAppearanceData.gqlStyle as GQLSysMLPackageNodeStyle; + const customizedStyleProperties = element.data.nodeAppearanceData.customizedStyleProperties; + + const { editingContextId, diagramId } = useContext(DiagramContext); + const { updateSysMLPackageNodeAppearance } = useUpdateSysMLPackageNodeAppearance(); + const { resetNodeStyleProperties } = useResetNodeAppearance(); + + const handleResetProperty = (customizedStyleProperty: string) => + resetNodeStyleProperties(editingContextId, diagramId, element.id, [customizedStyleProperty]); + + const handleEditProperty = (newValue: Partial) => + updateSysMLPackageNodeAppearance(editingContextId, diagramId, element.id, newValue); + + const isDisabled = (property: string) => !customizedStyleProperties.includes(property); + + return ( + ({ paddingX: theme.spacing(1), paddingBottom: theme.spacing(1) })}> + + Style + + handleEditProperty({ background: newValue })} + onReset={() => handleResetProperty('BACKGROUND')}> + + handleEditProperty({ borderColor: newValue })} + onReset={() => handleResetProperty('BORDER_COLOR')}> + + } + label={'Border Size'} + initialValue={style.borderSize} + isDisabled={isDisabled('BORDER_SIZE')} + onEdit={(newValue) => handleEditProperty({ borderSize: newValue })} + onReset={() => handleResetProperty('BORDER_SIZE')}> + + } + label={'Border Line Style'} + options={LINE_STYLE_OPTIONS} + initialValue={style.borderStyle} + isDisabled={isDisabled('BORDER_STYLE')} + onEdit={(newValue) => handleEditProperty({ borderStyle: newValue })} + onReset={() => handleResetProperty('BORDER_STYLE')}> + + + ); +}; diff --git a/frontend/syson-components/src/nodes/package/SysMLPackageNodePart.types.ts b/frontend/syson-components/src/nodes/package/SysMLPackageNodePart.types.ts new file mode 100644 index 000000000..6b89afa0c --- /dev/null +++ b/frontend/syson-components/src/nodes/package/SysMLPackageNodePart.types.ts @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { GQLNodeStyle, NodeData } from '@eclipse-sirius/sirius-components-diagrams'; +import { InternalNode, Node } from '@xyflow/react'; + +export interface GQLSysMLPackageNodeStyle extends GQLNodeStyle { + background: string; + borderColor: string; + borderSize: number; + borderStyle: string; +} + +export interface SysMLPackageNodePartProps { + element: InternalNode>; +} diff --git a/frontend/syson-components/src/nodes/package/useUpdateSysMLPackageNodeAppearance.ts b/frontend/syson-components/src/nodes/package/useUpdateSysMLPackageNodeAppearance.ts new file mode 100644 index 000000000..6c7e0b978 --- /dev/null +++ b/frontend/syson-components/src/nodes/package/useUpdateSysMLPackageNodeAppearance.ts @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { gql, useMutation } from '@apollo/client'; +import { useReporting } from '@eclipse-sirius/sirius-components-core'; +import { + GQLEditSysMLPackageNodeAppearanceData, + GQLEditSysMLPackageNodeAppearanceVariables, + GQLSysMLPackageNodeAppearanceInput, + UseUpdateSysMLPackageNodeAppearanceValue, +} from './useUpdateSysMLPackageNodeAppearance.types'; + +export const editSysMLPackageNodeAppearanceMutation = gql` + mutation editSysMLPackageNodeAppearance($input: EditSysMLPackageNodeAppearanceInput!) { + editSysMLPackageNodeAppearance(input: $input) { + __typename + ... on ErrorPayload { + messages { + body + level + } + } + ... on SuccessPayload { + messages { + body + level + } + } + } + } +`; + +export const useUpdateSysMLPackageNodeAppearance = (): UseUpdateSysMLPackageNodeAppearanceValue => { + const [editSysMLPackageNodeAppearance, editSysMLPackageNodeAppearanceResult] = useMutation< + GQLEditSysMLPackageNodeAppearanceData, + GQLEditSysMLPackageNodeAppearanceVariables + >(editSysMLPackageNodeAppearanceMutation); + + useReporting( + editSysMLPackageNodeAppearanceResult, + (data: GQLEditSysMLPackageNodeAppearanceData) => data.editSysMLPackageNodeAppearance + ); + + const updateSysMLPackageNodeAppearance = ( + editingContextId: string, + representationId: string, + nodeId: string, + appearance: Partial + ) => + editSysMLPackageNodeAppearance({ + variables: { + input: { + id: crypto.randomUUID(), + editingContextId, + representationId, + nodeId, + appearance, + }, + }, + }); + + return { + updateSysMLPackageNodeAppearance, + }; +}; diff --git a/frontend/syson-components/src/nodes/package/useUpdateSysMLPackageNodeAppearance.types.ts b/frontend/syson-components/src/nodes/package/useUpdateSysMLPackageNodeAppearance.types.ts new file mode 100644 index 000000000..986f40be8 --- /dev/null +++ b/frontend/syson-components/src/nodes/package/useUpdateSysMLPackageNodeAppearance.types.ts @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { GQLErrorPayload, GQLSuccessPayload } from '@eclipse-sirius/sirius-components-core'; + +export interface UseUpdateSysMLPackageNodeAppearanceValue { + updateSysMLPackageNodeAppearance: ( + editingContextId: string, + representationId: string, + nodeId: string, + appearance: Partial + ) => void; +} + +export interface GQLEditSysMLPackageNodeAppearanceData { + editSysMLPackageNodeAppearance: GQLEditSysMLPackageNodeAppearancePayload; +} + +export type GQLEditSysMLPackageNodeAppearancePayload = GQLErrorPayload | GQLSuccessPayload; + +export interface GQLEditSysMLPackageNodeAppearanceVariables { + input: GQLEditSysMLPackageNodeAppearanceInput; +} + +export interface GQLEditSysMLPackageNodeAppearanceInput { + id: string; + editingContextId: string; + representationId: string; + nodeId: string; + appearance: Partial; +} + +export interface GQLSysMLPackageNodeAppearanceInput { + background: string; + borderColor: string; + borderRadius: number; + borderSize: number; + borderStyle: string; +} diff --git a/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePaletteAppearanceSection.tsx b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePaletteAppearanceSection.tsx new file mode 100644 index 000000000..6ec66f9ce --- /dev/null +++ b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePaletteAppearanceSection.tsx @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { + LabelAppearancePart, + PaletteAppearanceSectionContributionComponentProps, +} from '@eclipse-sirius/sirius-components-diagrams'; + +import { SysMLViewFrameNodePart } from './SysMLViewFrameNodePart'; + +export const SysMLViewFrameNodePaletteAppearanceSection = ({ + element, + elementId, +}: PaletteAppearanceSectionContributionComponentProps) => { + return ( + <> + + {element.data.insideLabel ? ( + + ) : null} + + ); +}; diff --git a/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePaletteAppearanceSection.types.ts b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePaletteAppearanceSection.types.ts new file mode 100644 index 000000000..e249e4988 --- /dev/null +++ b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePaletteAppearanceSection.types.ts @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +export interface SysMLViewFrameNodePaletteAppearanceSectionState { + background: string; + borderColor: string; + borderRadius: number; + borderSize: number; + borderStyle: string; +} diff --git a/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePart.tsx b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePart.tsx new file mode 100644 index 000000000..d4d2934dd --- /dev/null +++ b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePart.tsx @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ + +import { + AppearanceColorPicker, + AppearanceNumberTextfield, + AppearanceSelect, + DiagramContext, + DiagramContextValue, + useResetNodeAppearance, +} from '@eclipse-sirius/sirius-components-diagrams'; +import LineStyleIcon from '@mui/icons-material/LineStyle'; +import LineWeightIcon from '@mui/icons-material/LineWeight'; +import Box from '@mui/material/Box'; +import ListItem from '@mui/material/ListItem'; +import Typography from '@mui/material/Typography'; +import { useContext } from 'react'; +import { GQLSysMLViewFrameNodeStyle, SysMLViewFrameNodePartProps } from './SysMLViewFrameNodePart.types'; +import { useUpdateSysMLViewFrameNodeAppearance } from './useUpdateSysMLViewFrameNodeAppearance'; +import { GQLSysMLViewFrameNodeAppearanceInput } from './useUpdateSysMLViewFrameNodeAppearance.types'; + +const LINE_STYLE_OPTIONS = [ + { value: 'Solid', label: 'Solid' }, + { value: 'Dash', label: 'Dash' }, + { value: 'Dot', label: 'Dot' }, + { value: 'Dash_Dot', label: 'Dash Dot' }, +]; + +export const SysMLViewFrameNodePart = ({ element }: SysMLViewFrameNodePartProps) => { + const style = element.data.nodeAppearanceData.gqlStyle as GQLSysMLViewFrameNodeStyle; + const customizedStyleProperties = element.data.nodeAppearanceData.customizedStyleProperties; + + const { editingContextId, diagramId } = useContext(DiagramContext); + const { updateSysMLViewFrameNodeAppearance } = useUpdateSysMLViewFrameNodeAppearance(); + const { resetNodeStyleProperties } = useResetNodeAppearance(); + + const handleResetProperty = (customizedStyleProperty: string) => + resetNodeStyleProperties(editingContextId, diagramId, element.id, [customizedStyleProperty]); + + const handleEditProperty = (newValue: Partial) => + updateSysMLViewFrameNodeAppearance(editingContextId, diagramId, element.id, newValue); + + const isDisabled = (property: string) => !customizedStyleProperties.includes(property); + + return ( + ({ paddingX: theme.spacing(1), paddingBottom: theme.spacing(1) })}> + + Style + + handleEditProperty({ background: newValue })} + onReset={() => handleResetProperty('BACKGROUND')}> + + handleEditProperty({ borderColor: newValue })} + onReset={() => handleResetProperty('BORDER_COLOR')}> + + } + label={'Border Size'} + initialValue={style.borderSize} + isDisabled={isDisabled('BORDER_SIZE')} + onEdit={(newValue) => handleEditProperty({ borderSize: newValue })} + onReset={() => handleResetProperty('BORDER_SIZE')}> + + } + label={'Border Line Style'} + options={LINE_STYLE_OPTIONS} + initialValue={style.borderStyle} + isDisabled={isDisabled('BORDER_STYLE')} + onEdit={(newValue) => handleEditProperty({ borderStyle: newValue })} + onReset={() => handleResetProperty('BORDER_STYLE')}> + + } + label={'Border Radius'} + initialValue={style.borderRadius} + isDisabled={isDisabled('BORDER_RADIUS')} + onEdit={(newValue) => handleEditProperty({ borderRadius: newValue })} + onReset={() => handleResetProperty('BORDER_RADIUS')}> + + + ); +}; diff --git a/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePart.types.ts b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePart.types.ts new file mode 100644 index 000000000..c56ae81a1 --- /dev/null +++ b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodePart.types.ts @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { GQLNodeStyle, NodeData } from '@eclipse-sirius/sirius-components-diagrams'; +import { InternalNode, Node } from '@xyflow/react'; + +export interface GQLSysMLViewFrameNodeStyle extends GQLNodeStyle { + background: string; + borderColor: string; + borderRadius: number; + borderSize: number; + borderStyle: string; +} + +export interface SysMLViewFrameNodePartProps { + element: InternalNode>; +} diff --git a/frontend/syson-components/src/nodes/view_frame/useUpdateSysMLViewFrameNodeAppearance.ts b/frontend/syson-components/src/nodes/view_frame/useUpdateSysMLViewFrameNodeAppearance.ts new file mode 100644 index 000000000..07f0ab29f --- /dev/null +++ b/frontend/syson-components/src/nodes/view_frame/useUpdateSysMLViewFrameNodeAppearance.ts @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { gql, useMutation } from '@apollo/client'; +import { useReporting } from '@eclipse-sirius/sirius-components-core'; +import { + GQLEditSysMLViewFrameNodeAppearanceData, + GQLEditSysMLViewFrameNodeAppearanceVariables, + GQLSysMLViewFrameNodeAppearanceInput, + UseUpdateSysMLViewFrameNodeAppearanceValue, +} from './useUpdateSysMLViewFrameNodeAppearance.types'; + +export const editSysMLViewFrameNodeAppearanceMutation = gql` + mutation editSysMLViewFrameNodeAppearance($input: EditSysMLViewFrameNodeAppearanceInput!) { + editSysMLViewFrameNodeAppearance(input: $input) { + __typename + ... on ErrorPayload { + messages { + body + level + } + } + ... on SuccessPayload { + messages { + body + level + } + } + } + } +`; + +export const useUpdateSysMLViewFrameNodeAppearance = (): UseUpdateSysMLViewFrameNodeAppearanceValue => { + const [editSysMLViewFrameNodeAppearance, editSysMLViewFrameNodeAppearanceResult] = useMutation< + GQLEditSysMLViewFrameNodeAppearanceData, + GQLEditSysMLViewFrameNodeAppearanceVariables + >(editSysMLViewFrameNodeAppearanceMutation); + + useReporting( + editSysMLViewFrameNodeAppearanceResult, + (data: GQLEditSysMLViewFrameNodeAppearanceData) => data.editSysMLViewFrameNodeAppearance + ); + + const updateSysMLViewFrameNodeAppearance = ( + editingContextId: string, + representationId: string, + nodeId: string, + appearance: Partial + ) => + editSysMLViewFrameNodeAppearance({ + variables: { + input: { + id: crypto.randomUUID(), + editingContextId, + representationId, + nodeId, + appearance, + }, + }, + }); + + return { + updateSysMLViewFrameNodeAppearance, + }; +}; diff --git a/frontend/syson-components/src/nodes/view_frame/useUpdateSysMLViewFrameNodeAppearance.types.ts b/frontend/syson-components/src/nodes/view_frame/useUpdateSysMLViewFrameNodeAppearance.types.ts new file mode 100644 index 000000000..6875c6340 --- /dev/null +++ b/frontend/syson-components/src/nodes/view_frame/useUpdateSysMLViewFrameNodeAppearance.types.ts @@ -0,0 +1,48 @@ +/******************************************************************************* + * Copyright (c) 2025 Obeo. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +import { GQLErrorPayload, GQLSuccessPayload } from '@eclipse-sirius/sirius-components-core'; + +export interface UseUpdateSysMLViewFrameNodeAppearanceValue { + updateSysMLViewFrameNodeAppearance: ( + editingContextId: string, + representationId: string, + nodeId: string, + appearance: Partial + ) => void; +} + +export interface GQLEditSysMLViewFrameNodeAppearanceData { + editSysMLViewFrameNodeAppearance: GQLEditSysMLViewFrameNodeAppearancePayload; +} + +export type GQLEditSysMLViewFrameNodeAppearancePayload = GQLErrorPayload | GQLSuccessPayload; + +export interface GQLEditSysMLViewFrameNodeAppearanceVariables { + input: GQLEditSysMLViewFrameNodeAppearanceInput; +} + +export interface GQLEditSysMLViewFrameNodeAppearanceInput { + id: string; + editingContextId: string; + representationId: string; + nodeId: string; + appearance: Partial; +} + +export interface GQLSysMLViewFrameNodeAppearanceInput { + background: string; + borderColor: string; + borderRadius: number; + borderSize: number; + borderStyle: string; +} diff --git a/frontend/syson/src/index.tsx b/frontend/syson/src/index.tsx index e4eb67c67..dd1be6f36 100644 --- a/frontend/syson/src/index.tsx +++ b/frontend/syson/src/index.tsx @@ -13,7 +13,12 @@ import { loadDevMessages, loadErrorMessages } from '@apollo/client/dev'; import { ExtensionRegistry } from '@eclipse-sirius/sirius-components-core'; -import { diagramPanelActionExtensionPoint, NodeTypeContribution } from '@eclipse-sirius/sirius-components-diagrams'; +import { + diagramPanelActionExtensionPoint, + NodeTypeContribution, + PaletteAppearanceSectionContributionProps, + paletteAppearanceSectionExtensionPoint, +} from '@eclipse-sirius/sirius-components-diagrams'; import { GQLOmniboxCommand, OmniboxCommandOverrideContribution, @@ -45,16 +50,20 @@ import { SysMLImportedPackageNode, SysMLImportedPackageNodeConverter, SysMLImportedPackageNodeLayoutHandler, + SysMLImportedPackageNodePaletteAppearanceSection, sysMLNodesStyleDocumentTransform, SysMLNoteNode, SysMLNoteNodeConverter, SysMLNoteNodeLayoutHandler, + SysMLNoteNodePaletteAppearanceSection, SysMLPackageNode, SysMLPackageNodeConverter, SysMLPackageNodeLayoutHandler, + SysMLPackageNodePaletteAppearanceSection, SysMLViewFrameNode, SysMLViewFrameNodeConverter, SysMLViewFrameNodeLayoutHandler, + SysMLViewFrameNodePaletteAppearanceSection, SysONDiagramPanelMenu, SysONDocumentTreeItemContextMenuContribution, SysONExtensionRegistryMergeStrategy, @@ -176,9 +185,48 @@ extensionRegistry.putData(treeItemCon data: treeItemContextMenuOverrideContributions, }); -/* - * Custom node contribution - */ +/******************************************************************************* + * + * Custom nodes appearance contributions + * + *******************************************************************************/ +const customNodePaletteAppearanceSectionContribution: PaletteAppearanceSectionContributionProps[] = [ + { + canHandle: (element) => { + return element.type === 'sysMLPackageNode'; + }, + component: SysMLPackageNodePaletteAppearanceSection, + }, + { + canHandle: (element) => { + return element.type === 'sysMLImportedPackageNode'; + }, + component: SysMLImportedPackageNodePaletteAppearanceSection, + }, + { + canHandle: (element) => { + return element.type === 'sysMLNoteNode'; + }, + component: SysMLNoteNodePaletteAppearanceSection, + }, + { + canHandle: (element) => { + return element.type === 'sysMLViewFrameNode'; + }, + component: SysMLViewFrameNodePaletteAppearanceSection, + }, +]; + +extensionRegistry.putData(paletteAppearanceSectionExtensionPoint, { + identifier: `syson_${paletteAppearanceSectionExtensionPoint.identifier}`, + data: customNodePaletteAppearanceSectionContribution, +}); + +/******************************************************************************* + * + * Custom nodes contributions + * + *******************************************************************************/ const nodeTypeRegistry: NodeTypeRegistry = { nodeLayoutHandlers: [ new SysMLPackageNodeLayoutHandler(),