diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 84796babc..d51a042d6 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -1,6 +1,23 @@ = Changelog -== v2025.4.0 (work in progress) +== v2025.6.0 (work in progress) + +=== Shapes + +=== Breaking changes + +=== Dependency update + +=== Bug fixes + +=== Improvements + +=== New features + +- https://github.com/eclipse-syson/syson/issues/1237[#1237] [general-view] Add `ViewUsage` node in the General View. + + +== v2025.4.0 === Shapes 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 new file mode 100644 index 000000000..8b8f50f42 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLViewFrameNodeStyle.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * 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; + +import java.text.MessageFormat; +import java.util.Objects; + +import org.eclipse.sirius.components.annotations.Immutable; +import org.eclipse.sirius.components.diagrams.INodeStyle; +import org.eclipse.sirius.components.diagrams.LineStyle; + +/** + * The SysML view frame node style. + * + * @author frouene + */ +@Immutable +public final class SysMLViewFrameNodeStyle implements INodeStyle { + + private String background; + + private String borderColor; + + private int borderSize; + + private LineStyle borderStyle; + + private int borderRadius; + + private SysMLViewFrameNodeStyle() { + // Prevent instantiation + } + + public static Builder newSysMLViewFrameNodeStyle() { + return new Builder(); + } + + public String getBackground() { + return this.background; + } + + public String getBorderColor() { + return this.borderColor; + } + + public int getBorderSize() { + return this.borderSize; + } + + public LineStyle getBorderStyle() { + return this.borderStyle; + } + + public int getBorderRadius() { + return this.borderRadius; + } + + @Override + public String toString() { + String pattern = "{0} '{'color: {1}, border: '{' background: {2}, size: {3}, style: {4} '}''}'"; + return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.background, this.borderColor, this.borderSize, this.borderStyle); + } + + /** + * The builder used to create the view frame node style. + * + * @author frouene + */ + @SuppressWarnings("checkstyle:HiddenField") + public static final class Builder { + + private String background; + + private String borderColor; + + private int borderSize; + + private LineStyle borderStyle; + + private int borderRadius; + + private Builder() { + // Prevent instantiation + } + + public Builder background(String background) { + this.background = Objects.requireNonNull(background); + return this; + } + + public Builder borderColor(String borderColor) { + this.borderColor = Objects.requireNonNull(borderColor); + return this; + } + + public Builder borderSize(int borderSize) { + this.borderSize = borderSize; + return this; + } + + public Builder borderStyle(LineStyle borderStyle) { + this.borderStyle = Objects.requireNonNull(borderStyle); + return this; + } + + public Builder borderRadius(int borderRadius) { + this.borderRadius = borderRadius; + return this; + } + + public SysMLViewFrameNodeStyle build() { + SysMLViewFrameNodeStyle nodeStyleDescription = new SysMLViewFrameNodeStyle(); + nodeStyleDescription.background = Objects.requireNonNull(this.background); + nodeStyleDescription.borderColor = Objects.requireNonNull(this.borderColor); + nodeStyleDescription.borderSize = this.borderSize; + nodeStyleDescription.borderStyle = Objects.requireNonNull(this.borderStyle); + nodeStyleDescription.borderRadius = this.borderRadius; + return nodeStyleDescription; + } + } +} diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLViewFrameNodeStyleProvider.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLViewFrameNodeStyleProvider.java new file mode 100644 index 000000000..50ec13221 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/nodes/SysMLViewFrameNodeStyleProvider.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * 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; + +import java.util.Optional; + +import org.eclipse.sirius.components.diagrams.INodeStyle; +import org.eclipse.sirius.components.diagrams.LineStyle; +import org.eclipse.sirius.components.view.FixedColor; +import org.eclipse.sirius.components.view.diagram.NodeStyleDescription; +import org.eclipse.sirius.components.view.emf.diagram.INodeStyleProvider; +import org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription; +import org.springframework.stereotype.Service; + +/** + * This class provides style information for the view frame custom node. + * + * @author frouene + */ +@Service +public class SysMLViewFrameNodeStyleProvider implements INodeStyleProvider { + + public static final String NODE_SYSML_VIEW_FRAME = "customnode:sysmlviewframe"; + + @Override + public Optional getNodeType(NodeStyleDescription nodeStyle) { + if (nodeStyle instanceof SysMLViewFrameNodeStyleDescription) { + return Optional.of(NODE_SYSML_VIEW_FRAME); + } + return Optional.empty(); + } + + @Override + public Optional createNodeStyle(NodeStyleDescription nodeStyle, Optional optionalEditingContextId) { + Optional iNodeStyle = Optional.empty(); + Optional nodeType = this.getNodeType(nodeStyle); + if (nodeType.isPresent()) { + return Optional.of(SysMLViewFrameNodeStyle.newSysMLViewFrameNodeStyle() + .background(Optional.ofNullable(((SysMLViewFrameNodeStyleDescription) nodeStyle).getBackground()) + .filter(FixedColor.class::isInstance) + .map(FixedColor.class::cast) + .map(FixedColor::getValue) + .orElse("transparent")) + .borderColor(Optional.ofNullable(nodeStyle.getBorderColor()) + .filter(FixedColor.class::isInstance) + .map(FixedColor.class::cast) + .map(FixedColor::getValue) + .orElse("black")) + .borderSize(nodeStyle.getBorderSize()) + .borderStyle(LineStyle.valueOf(nodeStyle.getBorderLineStyle().getLiteral())) + .borderRadius(nodeStyle.getBorderRadius()) + .build()); + } + + return iNodeStyle; + } +} 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 1ec0e1de5..1303c3974 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 @@ -23,4 +23,14 @@ type SysMLNoteNodeStyle { borderColor: String! borderSize: Int! borderStyle: LineStyle! -} \ No newline at end of file +} + +extend union INodeStyle = SysMLViewFrameNodeStyle + +type SysMLViewFrameNodeStyle { + background: String! + borderColor: String! + borderSize: Int! + borderStyle: LineStyle! + borderRadius: Int! +} diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVTopNodeCreationTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVTopNodeCreationTests.java index 258344045..9c172d13e 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVTopNodeCreationTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/diagrams/general/view/GVTopNodeCreationTests.java @@ -66,7 +66,6 @@ import org.eclipse.syson.services.diagrams.api.IGivenDiagramSubscription; import org.eclipse.syson.sysml.Element; import org.eclipse.syson.sysml.LibraryPackage; -import org.eclipse.syson.sysml.Membership; import org.eclipse.syson.sysml.Namespace; import org.eclipse.syson.sysml.SysmlPackage; import org.eclipse.syson.util.IDescriptionNameGenerator; @@ -96,55 +95,38 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class GVTopNodeCreationTests extends AbstractIntegrationTests { + private final IDescriptionNameGenerator descriptionNameGenerator = new GVDescriptionNameGenerator(); @Autowired private IGivenInitialServerState givenInitialServerState; - @Autowired private IGivenDiagramReference givenDiagram; - @Autowired private IGivenDiagramDescription givenDiagramDescription; - @Autowired private IGivenDiagramSubscription givenDiagramSubscription; - @Autowired private IDiagramIdProvider diagramIdProvider; - @Autowired private IIdentityService identityService; - @Autowired private IObjectSearchService objectSearchService; - @Autowired private NodeCreationTester nodeCreationTester; - @Autowired private SemanticRunnableFactory semanticRunnableFactory; - @Autowired private DiagramComparator diagramComparator; - @Autowired private SelectionDialogTreeEventSubscriptionRunner selectionDialogTreeEventSubscriptionRunner; - @Autowired private RepresentationIdBuilder representationIdBuilder; - @Autowired private IViewDiagramDescriptionSearchService viewDiagramDescriptionSearchService; - private DiagramDescriptionIdProvider diagramDescriptionIdProvider; - private Step verifier; - private AtomicReference diagram; - private DiagramDescription diagramDescription; - private final IDescriptionNameGenerator descriptionNameGenerator = new GVDescriptionNameGenerator(); - private static Stream topNodeParameters() { return Stream.of( Arguments.of(SysmlPackage.eINSTANCE.getAttributeUsage(), 3), @@ -180,7 +162,8 @@ private static Stream topNodeParameters() { Arguments.of(SysmlPackage.eINSTANCE.getSatisfyRequirementUsage(), 7), Arguments.of(SysmlPackage.eINSTANCE.getStateUsage(), 4), Arguments.of(SysmlPackage.eINSTANCE.getStateDefinition(), 4), - Arguments.of(SysmlPackage.eINSTANCE.getExhibitStateUsage(), 4) + Arguments.of(SysmlPackage.eINSTANCE.getExhibitStateUsage(), 4), + Arguments.of(SysmlPackage.eINSTANCE.getViewUsage(), 0) ).map(TestNameGenerator::namedArguments); } @@ -222,9 +205,9 @@ public void createTopNode(EClass eClass, int compartmentCount) { .ifPresentOrElse(newDiagram -> { int createdNodesExpectedCount = 1 + compartmentCount; new CheckDiagramElementCount(this.diagramComparator) - .hasNewEdgeCount(0) - .hasNewNodeCount(createdNodesExpectedCount) - .check(this.diagram.get(), newDiagram); + .hasNewEdgeCount(0) + .hasNewNodeCount(createdNodesExpectedCount) + .check(this.diagram.get(), newDiagram); String newNodeDescriptionName = this.descriptionNameGenerator.getNodeName(eClass); @@ -272,7 +255,7 @@ public void createTopNamespaceImportNode() { this.diagram, null, creationToolId, - List.of(new ToolVariable("selectedObject", libId.get().get(), ToolVariableType.OBJECT_ID))); + List.of(new ToolVariable("selectedObject", libId.get().get(), ToolVariableType.OBJECT_ID))); }); Consumer updatedDiagramConsumer = payload -> Optional.of(payload) @@ -356,7 +339,7 @@ private Optional getISQAcousticsLibraryPackageElement(Resource r .filter(Namespace.class::isInstance) .map(Namespace.class::cast) .flatMap(namespace -> namespace.getOwnedMembership().stream()) - .map(Membership.class::cast) + .map(t -> t) .flatMap(membership -> membership.getRelatedElement().stream()) .filter(LibraryPackage.class::isInstance) .filter(element -> "ISQAcoustics".equals(element.getDeclaredName())) diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel-edit/src/main/java/org/eclipse/syson/sysmlcustomnodes/provider/SysMLCustomnodesItemProviderAdapterFactory.java b/backend/metamodel/syson-siriusweb-customnodes-metamodel-edit/src/main/java/org/eclipse/syson/sysmlcustomnodes/provider/SysMLCustomnodesItemProviderAdapterFactory.java index 3f2100e02..abf10cf9a 100644 --- a/backend/metamodel/syson-siriusweb-customnodes-metamodel-edit/src/main/java/org/eclipse/syson/sysmlcustomnodes/provider/SysMLCustomnodesItemProviderAdapterFactory.java +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel-edit/src/main/java/org/eclipse/syson/sysmlcustomnodes/provider/SysMLCustomnodesItemProviderAdapterFactory.java @@ -161,6 +161,30 @@ public Adapter createSysMLImportedPackageNodeStyleDescriptionAdapter() { return this.sysMLImportedPackageNodeStyleDescriptionItemProvider; } + /** + * This keeps track of the one adapter used for all + * {@link org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription} instances. + * + * + * @generated + */ + protected SysMLViewFrameNodeStyleDescriptionItemProvider sysMLViewFrameNodeStyleDescriptionItemProvider; + + /** + * This creates an adapter for a {@link org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription}. + * + * @generated + */ + @Override + public Adapter createSysMLViewFrameNodeStyleDescriptionAdapter() { + if (this.sysMLViewFrameNodeStyleDescriptionItemProvider == null) { + this.sysMLViewFrameNodeStyleDescriptionItemProvider = new SysMLViewFrameNodeStyleDescriptionItemProvider(this); + } + + return this.sysMLViewFrameNodeStyleDescriptionItemProvider; + } + /** * This returns the root adapter factory that contains this factory. * @@ -267,6 +291,8 @@ public void dispose() { this.sysMLNoteNodeStyleDescriptionItemProvider.dispose(); if (this.sysMLImportedPackageNodeStyleDescriptionItemProvider != null) this.sysMLImportedPackageNodeStyleDescriptionItemProvider.dispose(); + if (this.sysMLViewFrameNodeStyleDescriptionItemProvider != null) + this.sysMLViewFrameNodeStyleDescriptionItemProvider.dispose(); } /** @@ -323,6 +349,9 @@ public Object caseNodeDescription(NodeDescription object) { this.newChildDescriptors.add(this.createChildParameter(DiagramPackage.Literals.NODE_DESCRIPTION__STYLE, SysMLCustomnodesFactory.eINSTANCE.createSysMLImportedPackageNodeStyleDescription())); + this.newChildDescriptors.add(this.createChildParameter(DiagramPackage.Literals.NODE_DESCRIPTION__STYLE, + SysMLCustomnodesFactory.eINSTANCE.createSysMLViewFrameNodeStyleDescription())); + return null; } @@ -342,6 +371,9 @@ public Object caseConditionalNodeStyle(ConditionalNodeStyle object) { this.newChildDescriptors.add(this.createChildParameter(DiagramPackage.Literals.CONDITIONAL_NODE_STYLE__STYLE, SysMLCustomnodesFactory.eINSTANCE.createSysMLImportedPackageNodeStyleDescription())); + this.newChildDescriptors.add(this.createChildParameter(DiagramPackage.Literals.CONDITIONAL_NODE_STYLE__STYLE, + SysMLCustomnodesFactory.eINSTANCE.createSysMLViewFrameNodeStyleDescription())); + return null; } diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel-edit/src/main/java/org/eclipse/syson/sysmlcustomnodes/provider/SysMLViewFrameNodeStyleDescriptionItemProvider.java b/backend/metamodel/syson-siriusweb-customnodes-metamodel-edit/src/main/java/org/eclipse/syson/sysmlcustomnodes/provider/SysMLViewFrameNodeStyleDescriptionItemProvider.java new file mode 100644 index 000000000..90afed188 --- /dev/null +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel-edit/src/main/java/org/eclipse/syson/sysmlcustomnodes/provider/SysMLViewFrameNodeStyleDescriptionItemProvider.java @@ -0,0 +1,237 @@ +/******************************************************************************* + * 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.sysmlcustomnodes.provider; + +import java.util.Collection; +import java.util.List; + +import org.eclipse.emf.common.notify.AdapterFactory; +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.common.util.ResourceLocator; +import org.eclipse.emf.edit.provider.ComposeableAdapterFactory; +import org.eclipse.emf.edit.provider.IEditingDomainItemProvider; +import org.eclipse.emf.edit.provider.IItemLabelProvider; +import org.eclipse.emf.edit.provider.IItemPropertyDescriptor; +import org.eclipse.emf.edit.provider.IItemPropertySource; +import org.eclipse.emf.edit.provider.IStructuredItemContentProvider; +import org.eclipse.emf.edit.provider.ITreeItemContentProvider; +import org.eclipse.emf.edit.provider.ItemPropertyDescriptor; +import org.eclipse.emf.edit.provider.ItemProviderAdapter; +import org.eclipse.emf.edit.provider.ViewerNotification; +import org.eclipse.sirius.components.view.diagram.DiagramPackage; +import org.eclipse.syson.sysmlcustomnodes.SysMLCustomnodesPackage; +import org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription; + +/** + * This is the item provider adapter for a {@link org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription} + * object. + * + * @generated + */ +public class SysMLViewFrameNodeStyleDescriptionItemProvider + extends ItemProviderAdapter + implements + IEditingDomainItemProvider, + IStructuredItemContentProvider, + ITreeItemContentProvider, + IItemLabelProvider, + IItemPropertySource { + + /** + * This constructs an instance from a factory and a notifier. + * + * @generated + */ + public SysMLViewFrameNodeStyleDescriptionItemProvider(AdapterFactory adapterFactory) { + super(adapterFactory); + } + + /** + * This returns the property descriptors for the adapted class. + * + * @generated + */ + @Override + public List getPropertyDescriptors(Object object) { + if (this.itemPropertyDescriptors == null) { + super.getPropertyDescriptors(object); + + this.addBorderColorPropertyDescriptor(object); + this.addBorderRadiusPropertyDescriptor(object); + this.addBorderSizePropertyDescriptor(object); + this.addBorderLineStylePropertyDescriptor(object); + this.addBackgroundPropertyDescriptor(object); + } + return this.itemPropertyDescriptors; + } + + /** + * This adds a property descriptor for the Border Color feature. + * + * @generated + */ + protected void addBorderColorPropertyDescriptor(Object object) { + this.itemPropertyDescriptors.add(this.createItemPropertyDescriptor(((ComposeableAdapterFactory) this.adapterFactory).getRootAdapterFactory(), + this.getResourceLocator(), + this.getString("_UI_BorderStyle_borderColor_feature"), + this.getString("_UI_PropertyDescriptor_description", "_UI_BorderStyle_borderColor_feature", "_UI_BorderStyle_type"), + DiagramPackage.Literals.BORDER_STYLE__BORDER_COLOR, + true, + false, + false, + null, + null, + null)); + } + + /** + * This adds a property descriptor for the Border Radius feature. + * + * @generated + */ + protected void addBorderRadiusPropertyDescriptor(Object object) { + this.itemPropertyDescriptors.add(this.createItemPropertyDescriptor(((ComposeableAdapterFactory) this.adapterFactory).getRootAdapterFactory(), + this.getResourceLocator(), + this.getString("_UI_BorderStyle_borderRadius_feature"), + this.getString("_UI_PropertyDescriptor_description", "_UI_BorderStyle_borderRadius_feature", "_UI_BorderStyle_type"), + DiagramPackage.Literals.BORDER_STYLE__BORDER_RADIUS, + true, + false, + false, + ItemPropertyDescriptor.INTEGRAL_VALUE_IMAGE, + null, + null)); + } + + /** + * This adds a property descriptor for the Border Size feature. + * + * @generated + */ + protected void addBorderSizePropertyDescriptor(Object object) { + this.itemPropertyDescriptors.add(this.createItemPropertyDescriptor(((ComposeableAdapterFactory) this.adapterFactory).getRootAdapterFactory(), + this.getResourceLocator(), + this.getString("_UI_BorderStyle_borderSize_feature"), + this.getString("_UI_PropertyDescriptor_description", "_UI_BorderStyle_borderSize_feature", "_UI_BorderStyle_type"), + DiagramPackage.Literals.BORDER_STYLE__BORDER_SIZE, + true, + false, + false, + ItemPropertyDescriptor.INTEGRAL_VALUE_IMAGE, + null, + null)); + } + + /** + * This adds a property descriptor for the Border Line Style feature. + * + * @generated + */ + protected void addBorderLineStylePropertyDescriptor(Object object) { + this.itemPropertyDescriptors.add(this.createItemPropertyDescriptor(((ComposeableAdapterFactory) this.adapterFactory).getRootAdapterFactory(), + this.getResourceLocator(), + this.getString("_UI_BorderStyle_borderLineStyle_feature"), + this.getString("_UI_PropertyDescriptor_description", "_UI_BorderStyle_borderLineStyle_feature", "_UI_BorderStyle_type"), + DiagramPackage.Literals.BORDER_STYLE__BORDER_LINE_STYLE, + true, + false, + false, + ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, + null, + null)); + } + + /** + * This adds a property descriptor for the Background feature. + * + * @generated + */ + protected void addBackgroundPropertyDescriptor(Object object) { + this.itemPropertyDescriptors.add(this.createItemPropertyDescriptor(((ComposeableAdapterFactory) this.adapterFactory).getRootAdapterFactory(), + this.getResourceLocator(), + this.getString("_UI_SysMLViewFrameNodeStyleDescription_background_feature"), + this.getString("_UI_PropertyDescriptor_description", "_UI_SysMLViewFrameNodeStyleDescription_background_feature", "_UI_SysMLViewFrameNodeStyleDescription_type"), + SysMLCustomnodesPackage.Literals.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BACKGROUND, + true, + false, + true, + null, + null, + null)); + } + + /** + * This returns SysMLViewFrameNodeStyleDescription.gif. + * + * @generated + */ + @Override + public Object getImage(Object object) { + return this.overlayImage(object, this.getResourceLocator().getImage("full/obj16/SysMLViewFrameNodeStyleDescription")); + } + + /** + * This returns the label text for the adapted class. + * + * @generated + */ + @Override + public String getText(Object object) { + SysMLViewFrameNodeStyleDescription sysMLViewFrameNodeStyleDescription = (SysMLViewFrameNodeStyleDescription) object; + return this.getString("_UI_SysMLViewFrameNodeStyleDescription_type") + " " + sysMLViewFrameNodeStyleDescription.getBorderRadius(); + } + + /** + * This handles model notifications by calling {@link #updateChildren} to update any cached children and by creating + * a viewer notification, which it passes to {@link #fireNotifyChanged}. + * + * @generated + */ + @Override + public void notifyChanged(Notification notification) { + this.updateChildren(notification); + + switch (notification.getFeatureID(SysMLViewFrameNodeStyleDescription.class)) { + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_COLOR: + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_RADIUS: + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_SIZE: + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_LINE_STYLE: + this.fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), false, true)); + return; + } + super.notifyChanged(notification); + } + + /** + * This adds {@link org.eclipse.emf.edit.command.CommandParameter}s describing the children that can be created + * under this object. + * + * @generated + */ + @Override + protected void collectNewChildDescriptors(Collection newChildDescriptors, Object object) { + super.collectNewChildDescriptors(newChildDescriptors, object); + } + + /** + * Return the resource locator for this item provider's resources. + * + * @generated + */ + @Override + public ResourceLocator getResourceLocator() { + return SysMLCustomNodesEditPlugin.INSTANCE; + } + +} diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel-edit/src/main/resources/plugin.properties b/backend/metamodel/syson-siriusweb-customnodes-metamodel-edit/src/main/resources/plugin.properties index 1fde97357..6cc82fdc5 100644 --- a/backend/metamodel/syson-siriusweb-customnodes-metamodel-edit/src/main/resources/plugin.properties +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel-edit/src/main/resources/plugin.properties @@ -9,27 +9,29 @@ # Contributors: # Obeo - initial API and implementation -pluginName = SysMLCustomnodes Edit Support -providerName = www.example.org +pluginName=SysMLCustomnodes Edit Support +providerName=www.example.org -_UI_CreateChild_text = {0} -_UI_CreateChild_text2 = {1} {0} -_UI_CreateChild_text3 = {1} -_UI_CreateChild_tooltip = Create New {0} Under {1} Feature -_UI_CreateChild_description = Create a new child of type {0} for the {1} feature of the selected {2}. -_UI_CreateSibling_description = Create a new sibling of type {0} for the selected {2}, under the {1} feature of their parent. +_UI_CreateChild_text={0} +_UI_CreateChild_text2={1} {0} +_UI_CreateChild_text3={1} +_UI_CreateChild_tooltip=Create New {0} Under {1} Feature +_UI_CreateChild_description=Create a new child of type {0} for the {1} feature of the selected {2}. +_UI_CreateSibling_description=Create a new sibling of type {0} for the selected {2}, under the {1} feature of their parent. -_UI_PropertyDescriptor_description = The {0} of the {1} +_UI_PropertyDescriptor_description=The {0} of the {1} -_UI_SysMLPackageNodeStyleDescription_type = Sys ML Package Node Style Description -_UI_SysMLNoteNodeStyleDescription_type = Sys ML Note Node Style Description -_UI_SysMLImportedPackageNodeStyleDescription_type = Sys ML Imported Package Node Style Description -_UI_Unknown_type = Object +_UI_SysMLPackageNodeStyleDescription_type=Sys ML Package Node Style Description +_UI_SysMLNoteNodeStyleDescription_type=Sys ML Note Node Style Description +_UI_SysMLImportedPackageNodeStyleDescription_type=Sys ML Imported Package Node Style Description +_UI_SysMLViewFrameNodeStyleDescription_type=Sys ML View Frame Node Style Description +_UI_Unknown_type=Object -_UI_Unknown_datatype= Value +_UI_Unknown_datatype=Value -_UI_SysMLPackageNodeStyleDescription_background_feature = Background -_UI_SysMLNoteNodeStyleDescription_background_feature = Background -_UI_SysMLImportedPackageNodeStyleDescription_background_feature = Background -_UI_Unknown_feature = Unspecified +_UI_SysMLPackageNodeStyleDescription_background_feature=Background +_UI_SysMLNoteNodeStyleDescription_background_feature=Background +_UI_SysMLImportedPackageNodeStyleDescription_background_feature=Background +_UI_SysMLViewFrameNodeStyleDescription_background_feature=Background +_UI_Unknown_feature=Unspecified diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/SysMLCustomnodesFactory.java b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/SysMLCustomnodesFactory.java index d776b0855..3f9afedd7 100644 --- a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/SysMLCustomnodesFactory.java +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/SysMLCustomnodesFactory.java @@ -56,6 +56,15 @@ public interface SysMLCustomnodesFactory extends EFactory { */ SysMLImportedPackageNodeStyleDescription createSysMLImportedPackageNodeStyleDescription(); + /** + * Returns a new object of class 'Sys ML View Frame Node Style Description'. + * + * @return a new object of class 'Sys ML View Frame Node Style Description'. + * @generated + */ + SysMLViewFrameNodeStyleDescription createSysMLViewFrameNodeStyleDescription(); + /** * Returns the package supported by this factory. * diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/SysMLCustomnodesPackage.java b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/SysMLCustomnodesPackage.java index 44ef557cb..15f200b5b 100644 --- a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/SysMLCustomnodesPackage.java +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/SysMLCustomnodesPackage.java @@ -269,6 +269,75 @@ public interface SysMLCustomnodesPackage extends EPackage { */ int SYS_ML_IMPORTED_PACKAGE_NODE_STYLE_DESCRIPTION_OPERATION_COUNT = DiagramPackage.NODE_STYLE_DESCRIPTION_OPERATION_COUNT + 0; + /** + * The meta object id for the '{@link org.eclipse.syson.sysmlcustomnodes.impl.SysMLViewFrameNodeStyleDescriptionImpl + * Sys ML View Frame Node Style Description}' class. + * + * @see org.eclipse.syson.sysmlcustomnodes.impl.SysMLViewFrameNodeStyleDescriptionImpl + * @see org.eclipse.syson.sysmlcustomnodes.impl.SysMLCustomnodesPackageImpl#getSysMLViewFrameNodeStyleDescription() + * @generated + */ + int SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION = 3; + + /** + * The feature id for the 'Border Color' reference. + * + * @generated + * @ordered + */ + int SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_COLOR = DiagramPackage.NODE_STYLE_DESCRIPTION__BORDER_COLOR; + + /** + * The feature id for the 'Border Radius' attribute. + * + * @generated + * @ordered + */ + int SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_RADIUS = DiagramPackage.NODE_STYLE_DESCRIPTION__BORDER_RADIUS; + + /** + * The feature id for the 'Border Size' attribute. + * + * @generated + * @ordered + */ + int SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_SIZE = DiagramPackage.NODE_STYLE_DESCRIPTION__BORDER_SIZE; + + /** + * The feature id for the 'Border Line Style' attribute. + * + * @generated + * @ordered + */ + int SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_LINE_STYLE = DiagramPackage.NODE_STYLE_DESCRIPTION__BORDER_LINE_STYLE; + + /** + * The feature id for the 'Background' reference. + * + * @generated + * @ordered + */ + int SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BACKGROUND = DiagramPackage.NODE_STYLE_DESCRIPTION_FEATURE_COUNT + 0; + + /** + * The number of structural features of the 'Sys ML View Frame Node Style Description' class. + * + * @generated + * @ordered + */ + int SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION_FEATURE_COUNT = DiagramPackage.NODE_STYLE_DESCRIPTION_FEATURE_COUNT + 1; + + /** + * The number of operations of the 'Sys ML View Frame Node Style Description' class. + * + * @generated + * @ordered + */ + int SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION_OPERATION_COUNT = DiagramPackage.NODE_STYLE_DESCRIPTION_OPERATION_COUNT + 0; + /** * Returns the meta object for class '{@link org.eclipse.syson.sysmlcustomnodes.SysMLPackageNodeStyleDescription * Sys ML Package Node Style Description}'. @@ -336,6 +405,28 @@ public interface SysMLCustomnodesPackage extends EPackage { */ EReference getSysMLImportedPackageNodeStyleDescription_Background(); + /** + * Returns the meta object for class '{@link org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription + * Sys ML View Frame Node Style Description}'. + * + * @return the meta object for class 'Sys ML View Frame Node Style Description'. + * @see org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription + * @generated + */ + EClass getSysMLViewFrameNodeStyleDescription(); + + /** + * Returns the meta object for the reference + * '{@link org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription#getBackground + * Background}'. + * + * @return the meta object for the reference 'Background'. + * @see org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription#getBackground() + * @see #getSysMLViewFrameNodeStyleDescription() + * @generated + */ + EReference getSysMLViewFrameNodeStyleDescription_Background(); + /** * Returns the factory that creates the instances of the model. * @@ -415,6 +506,25 @@ interface Literals { */ EReference SYS_ML_IMPORTED_PACKAGE_NODE_STYLE_DESCRIPTION__BACKGROUND = eINSTANCE.getSysMLImportedPackageNodeStyleDescription_Background(); + /** + * The meta object literal for the + * '{@link org.eclipse.syson.sysmlcustomnodes.impl.SysMLViewFrameNodeStyleDescriptionImpl Sys ML View Frame + * Node Style Description}' class. + * + * @see org.eclipse.syson.sysmlcustomnodes.impl.SysMLViewFrameNodeStyleDescriptionImpl + * @see org.eclipse.syson.sysmlcustomnodes.impl.SysMLCustomnodesPackageImpl#getSysMLViewFrameNodeStyleDescription() + * @generated + */ + EClass SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION = eINSTANCE.getSysMLViewFrameNodeStyleDescription(); + + /** + * The meta object literal for the 'Background' reference feature. + * + * @generated + */ + EReference SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BACKGROUND = eINSTANCE.getSysMLViewFrameNodeStyleDescription_Background(); + } } // SysMLCustomnodesPackage diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/SysMLViewFrameNodeStyleDescription.java b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/SysMLViewFrameNodeStyleDescription.java new file mode 100644 index 000000000..e3e87febc --- /dev/null +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/SysMLViewFrameNodeStyleDescription.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.sysmlcustomnodes; + +import org.eclipse.sirius.components.view.UserColor; +import org.eclipse.sirius.components.view.diagram.NodeStyleDescription; + +/** + * A representation of the model object 'Sys ML View Frame Node Style + * Description'. + * + *

+ * The following features are supported: + *

+ *
    + *
  • {@link org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription#getBackground + * Background}
  • + *
+ * + * @model + * @generated + * @see org.eclipse.syson.sysmlcustomnodes.SysMLCustomnodesPackage#getSysMLViewFrameNodeStyleDescription() + */ +public interface SysMLViewFrameNodeStyleDescription extends NodeStyleDescription { + + /** + * Returns the value of the 'Background' reference. + * + * @return the value of the 'Background' reference. + * @model + * @generated + * @see #setBackground(UserColor) + * @see org.eclipse.syson.sysmlcustomnodes.SysMLCustomnodesPackage#getSysMLViewFrameNodeStyleDescription_Background() + */ + UserColor getBackground(); + + /** + * Sets the value of the '{@link org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription#getBackground + * Background}' reference. + * + * @param value + * the new value of the 'Background' reference. + * @generated + * @see #getBackground() + */ + void setBackground(UserColor value); + +} // SysMLViewFrameNodeStyleDescription diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/impl/SysMLCustomnodesFactoryImpl.java b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/impl/SysMLCustomnodesFactoryImpl.java index 86fd9beb5..ca12c8085 100644 --- a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/impl/SysMLCustomnodesFactoryImpl.java +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/impl/SysMLCustomnodesFactoryImpl.java @@ -22,6 +22,7 @@ import org.eclipse.syson.sysmlcustomnodes.SysMLImportedPackageNodeStyleDescription; import org.eclipse.syson.sysmlcustomnodes.SysMLNoteNodeStyleDescription; import org.eclipse.syson.sysmlcustomnodes.SysMLPackageNodeStyleDescription; +import org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription; /** * An implementation of the model Factory. @@ -69,6 +70,8 @@ public EObject create(EClass eClass) { return this.createSysMLNoteNodeStyleDescription(); case SysMLCustomnodesPackage.SYS_ML_IMPORTED_PACKAGE_NODE_STYLE_DESCRIPTION: return this.createSysMLImportedPackageNodeStyleDescription(); + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION: + return this.createSysMLViewFrameNodeStyleDescription(); default: throw new IllegalArgumentException("The class '" + eClass.getName() + "' is not a valid classifier"); } @@ -107,6 +110,17 @@ public SysMLImportedPackageNodeStyleDescription createSysMLImportedPackageNodeSt return sysMLImportedPackageNodeStyleDescription; } + /** + * + * + * @generated + */ + @Override + public SysMLViewFrameNodeStyleDescription createSysMLViewFrameNodeStyleDescription() { + SysMLViewFrameNodeStyleDescriptionImpl sysMLViewFrameNodeStyleDescription = new SysMLViewFrameNodeStyleDescriptionImpl(); + return sysMLViewFrameNodeStyleDescription; + } + /** * * diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/impl/SysMLCustomnodesPackageImpl.java b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/impl/SysMLCustomnodesPackageImpl.java index 3e441eb7d..ee58dccfe 100644 --- a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/impl/SysMLCustomnodesPackageImpl.java +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/impl/SysMLCustomnodesPackageImpl.java @@ -23,6 +23,7 @@ import org.eclipse.syson.sysmlcustomnodes.SysMLImportedPackageNodeStyleDescription; import org.eclipse.syson.sysmlcustomnodes.SysMLNoteNodeStyleDescription; import org.eclipse.syson.sysmlcustomnodes.SysMLPackageNodeStyleDescription; +import org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription; /** * An implementation of the model Package. @@ -51,6 +52,13 @@ public class SysMLCustomnodesPackageImpl extends EPackageImpl implements SysMLCu */ private EClass sysMLImportedPackageNodeStyleDescriptionEClass = null; + /** + * + * + * @generated + */ + private EClass sysMLViewFrameNodeStyleDescriptionEClass = null; + /** * Creates an instance of the model Package, registered with {@link org.eclipse.emf.ecore.EPackage.Registry * EPackage.Registry} by the package package URI value. @@ -178,6 +186,26 @@ public EReference getSysMLImportedPackageNodeStyleDescription_Background() { return (EReference) this.sysMLImportedPackageNodeStyleDescriptionEClass.getEStructuralFeatures().get(0); } + /** + * + * + * @generated + */ + @Override + public EClass getSysMLViewFrameNodeStyleDescription() { + return this.sysMLViewFrameNodeStyleDescriptionEClass; + } + + /** + * + * + * @generated + */ + @Override + public EReference getSysMLViewFrameNodeStyleDescription_Background() { + return (EReference) this.sysMLViewFrameNodeStyleDescriptionEClass.getEStructuralFeatures().get(0); + } + /** * * @@ -215,6 +243,9 @@ public void createPackageContents() { this.sysMLImportedPackageNodeStyleDescriptionEClass = this.createEClass(SYS_ML_IMPORTED_PACKAGE_NODE_STYLE_DESCRIPTION); this.createEReference(this.sysMLImportedPackageNodeStyleDescriptionEClass, SYS_ML_IMPORTED_PACKAGE_NODE_STYLE_DESCRIPTION__BACKGROUND); + + this.sysMLViewFrameNodeStyleDescriptionEClass = this.createEClass(SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION); + this.createEReference(this.sysMLViewFrameNodeStyleDescriptionEClass, SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BACKGROUND); } /** @@ -252,6 +283,7 @@ public void initializePackageContents() { this.sysMLPackageNodeStyleDescriptionEClass.getESuperTypes().add(theDiagramPackage.getNodeStyleDescription()); this.sysMLNoteNodeStyleDescriptionEClass.getESuperTypes().add(theDiagramPackage.getNodeStyleDescription()); this.sysMLImportedPackageNodeStyleDescriptionEClass.getESuperTypes().add(theDiagramPackage.getNodeStyleDescription()); + this.sysMLViewFrameNodeStyleDescriptionEClass.getESuperTypes().add(theDiagramPackage.getNodeStyleDescription()); // Initialize classes, features, and operations; add parameters this.initEClass(this.sysMLPackageNodeStyleDescriptionEClass, SysMLPackageNodeStyleDescription.class, "SysMLPackageNodeStyleDescription", !IS_ABSTRACT, !IS_INTERFACE, @@ -270,6 +302,12 @@ public void initializePackageContents() { SysMLImportedPackageNodeStyleDescription.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + this.initEClass(this.sysMLViewFrameNodeStyleDescriptionEClass, SysMLViewFrameNodeStyleDescription.class, "SysMLViewFrameNodeStyleDescription", !IS_ABSTRACT, !IS_INTERFACE, + IS_GENERATED_INSTANCE_CLASS); + this.initEReference(this.getSysMLViewFrameNodeStyleDescription_Background(), theViewPackage.getUserColor(), null, "background", null, 0, 1, SysMLViewFrameNodeStyleDescription.class, + !IS_TRANSIENT, + !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + // Create resource this.createResource(eNS_URI); } diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/impl/SysMLViewFrameNodeStyleDescriptionImpl.java b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/impl/SysMLViewFrameNodeStyleDescriptionImpl.java new file mode 100644 index 000000000..f1191076c --- /dev/null +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/impl/SysMLViewFrameNodeStyleDescriptionImpl.java @@ -0,0 +1,412 @@ +/******************************************************************************* + * 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.sysmlcustomnodes.impl; + +import org.eclipse.emf.common.notify.Notification; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.InternalEObject; +import org.eclipse.emf.ecore.impl.ENotificationImpl; +import org.eclipse.emf.ecore.impl.MinimalEObjectImpl; +import org.eclipse.sirius.components.view.UserColor; +import org.eclipse.sirius.components.view.diagram.LineStyle; +import org.eclipse.syson.sysmlcustomnodes.SysMLCustomnodesPackage; +import org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription; + +/** + * An implementation of the model object 'Sys ML View Frame Node Style + * Description'. + *

+ * The following features are implemented: + *

+ *
    + *
  • {@link org.eclipse.syson.sysmlcustomnodes.impl.SysMLViewFrameNodeStyleDescriptionImpl#getBorderColor Border + * Color}
  • + *
  • {@link org.eclipse.syson.sysmlcustomnodes.impl.SysMLViewFrameNodeStyleDescriptionImpl#getBorderRadius Border + * Radius}
  • + *
  • {@link org.eclipse.syson.sysmlcustomnodes.impl.SysMLViewFrameNodeStyleDescriptionImpl#getBorderSize Border + * Size}
  • + *
  • {@link org.eclipse.syson.sysmlcustomnodes.impl.SysMLViewFrameNodeStyleDescriptionImpl#getBorderLineStyle + * Border Line Style}
  • + *
  • {@link org.eclipse.syson.sysmlcustomnodes.impl.SysMLViewFrameNodeStyleDescriptionImpl#getBackground + * Background}
  • + *
+ * + * @generated + */ +public class SysMLViewFrameNodeStyleDescriptionImpl extends MinimalEObjectImpl.Container implements SysMLViewFrameNodeStyleDescription { + + /** + * The default value of the '{@link #getBorderRadius() Border Radius}' attribute. + * + * + * @generated + * @ordered + * @see #getBorderRadius() + */ + protected static final int BORDER_RADIUS_EDEFAULT = 3; + /** + * The default value of the '{@link #getBorderSize() Border Size}' attribute. + * + * @generated + * @ordered + * @see #getBorderSize() + */ + protected static final int BORDER_SIZE_EDEFAULT = 1; + /** + * The default value of the '{@link #getBorderLineStyle() Border Line Style}' attribute. + * + * @generated + * @ordered + * @see #getBorderLineStyle() + */ + protected static final LineStyle BORDER_LINE_STYLE_EDEFAULT = LineStyle.SOLID; + /** + * The cached value of the '{@link #getBorderColor() Border Color}' reference. + * + * @generated + * @ordered + * @see #getBorderColor() + */ + protected UserColor borderColor; + /** + * The cached value of the '{@link #getBorderRadius() Border Radius}' attribute. + * + * + * @generated + * @ordered + * @see #getBorderRadius() + */ + protected int borderRadius = BORDER_RADIUS_EDEFAULT; + /** + * The cached value of the '{@link #getBorderSize() Border Size}' attribute. + * + * @generated + * @ordered + * @see #getBorderSize() + */ + protected int borderSize = BORDER_SIZE_EDEFAULT; + /** + * The cached value of the '{@link #getBorderLineStyle() Border Line Style}' attribute. + * + * @generated + * @ordered + * @see #getBorderLineStyle() + */ + protected LineStyle borderLineStyle = BORDER_LINE_STYLE_EDEFAULT; + + /** + * The cached value of the '{@link #getBackground() Background}' reference. + * + * @generated + * @ordered + * @see #getBackground() + */ + protected UserColor background; + + /** + * + * + * @generated + */ + protected SysMLViewFrameNodeStyleDescriptionImpl() { + super(); + } + + /** + * + * + * @generated + */ + @Override + protected EClass eStaticClass() { + return SysMLCustomnodesPackage.Literals.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION; + } + + /** + * + * + * @generated + */ + @Override + public UserColor getBorderColor() { + if (this.borderColor != null && this.borderColor.eIsProxy()) { + InternalEObject oldBorderColor = (InternalEObject) this.borderColor; + this.borderColor = (UserColor) this.eResolveProxy(oldBorderColor); + if (this.borderColor != oldBorderColor) { + if (this.eNotificationRequired()) + this.eNotify(new ENotificationImpl(this, Notification.RESOLVE, SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_COLOR, oldBorderColor, this.borderColor)); + } + } + return this.borderColor; + } + + /** + * + * + * @generated + */ + @Override + public void setBorderColor(UserColor newBorderColor) { + UserColor oldBorderColor = this.borderColor; + this.borderColor = newBorderColor; + if (this.eNotificationRequired()) + this.eNotify(new ENotificationImpl(this, Notification.SET, SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_COLOR, oldBorderColor, this.borderColor)); + } + + /** + * + * + * @generated + */ + public UserColor basicGetBorderColor() { + return this.borderColor; + } + + /** + * + * + * @generated + */ + @Override + public int getBorderRadius() { + return this.borderRadius; + } + + /** + * + * + * @generated + */ + @Override + public void setBorderRadius(int newBorderRadius) { + int oldBorderRadius = this.borderRadius; + this.borderRadius = newBorderRadius; + if (this.eNotificationRequired()) + this.eNotify(new ENotificationImpl(this, Notification.SET, SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_RADIUS, oldBorderRadius, this.borderRadius)); + } + + /** + * + * + * @generated + */ + @Override + public int getBorderSize() { + return this.borderSize; + } + + /** + * + * + * @generated + */ + @Override + public void setBorderSize(int newBorderSize) { + int oldBorderSize = this.borderSize; + this.borderSize = newBorderSize; + if (this.eNotificationRequired()) + this.eNotify(new ENotificationImpl(this, Notification.SET, SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_SIZE, oldBorderSize, this.borderSize)); + } + + /** + * + * + * @generated + */ + @Override + public LineStyle getBorderLineStyle() { + return this.borderLineStyle; + } + + /** + * + * + * @generated + */ + @Override + public void setBorderLineStyle(LineStyle newBorderLineStyle) { + LineStyle oldBorderLineStyle = this.borderLineStyle; + this.borderLineStyle = newBorderLineStyle == null ? BORDER_LINE_STYLE_EDEFAULT : newBorderLineStyle; + if (this.eNotificationRequired()) + this.eNotify(new ENotificationImpl(this, Notification.SET, SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_LINE_STYLE, oldBorderLineStyle, this.borderLineStyle)); + } + + /** + * + * + * @generated + */ + @Override + public UserColor getBackground() { + if (this.background != null && this.background.eIsProxy()) { + InternalEObject oldBackground = (InternalEObject) this.background; + this.background = (UserColor) this.eResolveProxy(oldBackground); + if (this.background != oldBackground) { + if (this.eNotificationRequired()) + this.eNotify(new ENotificationImpl(this, Notification.RESOLVE, SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BACKGROUND, oldBackground, this.background)); + } + } + return this.background; + } + + /** + * + * + * @generated + */ + @Override + public void setBackground(UserColor newBackground) { + UserColor oldBackground = this.background; + this.background = newBackground; + if (this.eNotificationRequired()) + this.eNotify(new ENotificationImpl(this, Notification.SET, SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BACKGROUND, oldBackground, this.background)); + } + + /** + * + * + * @generated + */ + public UserColor basicGetBackground() { + return this.background; + } + + /** + * + * + * @generated + */ + @Override + public Object eGet(int featureID, boolean resolve, boolean coreType) { + switch (featureID) { + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_COLOR: + if (resolve) + return this.getBorderColor(); + return this.basicGetBorderColor(); + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_RADIUS: + return this.getBorderRadius(); + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_SIZE: + return this.getBorderSize(); + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_LINE_STYLE: + return this.getBorderLineStyle(); + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BACKGROUND: + if (resolve) + return this.getBackground(); + return this.basicGetBackground(); + } + return super.eGet(featureID, resolve, coreType); + } + + /** + * + * + * @generated + */ + @Override + public void eSet(int featureID, Object newValue) { + switch (featureID) { + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_COLOR: + this.setBorderColor((UserColor) newValue); + return; + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_RADIUS: + this.setBorderRadius((Integer) newValue); + return; + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_SIZE: + this.setBorderSize((Integer) newValue); + return; + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_LINE_STYLE: + this.setBorderLineStyle((LineStyle) newValue); + return; + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BACKGROUND: + this.setBackground((UserColor) newValue); + return; + } + super.eSet(featureID, newValue); + } + + /** + * + * + * @generated + */ + @Override + public void eUnset(int featureID) { + switch (featureID) { + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_COLOR: + this.setBorderColor(null); + return; + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_RADIUS: + this.setBorderRadius(BORDER_RADIUS_EDEFAULT); + return; + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_SIZE: + this.setBorderSize(BORDER_SIZE_EDEFAULT); + return; + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_LINE_STYLE: + this.setBorderLineStyle(BORDER_LINE_STYLE_EDEFAULT); + return; + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BACKGROUND: + this.setBackground(null); + return; + } + super.eUnset(featureID); + } + + /** + * + * + * @generated + */ + @Override + public boolean eIsSet(int featureID) { + switch (featureID) { + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_COLOR: + return this.borderColor != null; + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_RADIUS: + return this.borderRadius != BORDER_RADIUS_EDEFAULT; + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_SIZE: + return this.borderSize != BORDER_SIZE_EDEFAULT; + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BORDER_LINE_STYLE: + return this.borderLineStyle != BORDER_LINE_STYLE_EDEFAULT; + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION__BACKGROUND: + return this.background != null; + } + return super.eIsSet(featureID); + } + + /** + * + * + * @generated + */ + @Override + public String toString() { + if (this.eIsProxy()) + return super.toString(); + + String result = super.toString() + " (borderRadius: " + + this.borderRadius + + ", borderSize: " + + this.borderSize + + ", borderLineStyle: " + + this.borderLineStyle + + ')'; + return result; + } + +} // SysMLViewFrameNodeStyleDescriptionImpl diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/util/SysMLCustomnodesAdapterFactory.java b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/util/SysMLCustomnodesAdapterFactory.java index 9242e0e33..77c8d347e 100644 --- a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/util/SysMLCustomnodesAdapterFactory.java +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/util/SysMLCustomnodesAdapterFactory.java @@ -22,6 +22,7 @@ import org.eclipse.syson.sysmlcustomnodes.SysMLImportedPackageNodeStyleDescription; import org.eclipse.syson.sysmlcustomnodes.SysMLNoteNodeStyleDescription; import org.eclipse.syson.sysmlcustomnodes.SysMLPackageNodeStyleDescription; +import org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription; /** * The Adapter Factory for the model. It provides an adapter createXXX @@ -89,6 +90,11 @@ public Adapter caseSysMLImportedPackageNodeStyleDescription(SysMLImportedPackage return SysMLCustomnodesAdapterFactory.this.createSysMLImportedPackageNodeStyleDescriptionAdapter(); } + @Override + public Adapter caseSysMLViewFrameNodeStyleDescription(SysMLViewFrameNodeStyleDescription object) { + return SysMLCustomnodesAdapterFactory.this.createSysMLViewFrameNodeStyleDescriptionAdapter(); + } + @Override public Adapter caseBorderStyle(BorderStyle object) { return SysMLCustomnodesAdapterFactory.this.createBorderStyleAdapter(); @@ -161,6 +167,20 @@ public Adapter createSysMLImportedPackageNodeStyleDescriptionAdapter() { return null; } + /** + * Creates a new adapter for an object of class + * '{@link org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription Sys ML View Frame Node Style + * Description}'. This default implementation returns null so that we can easily ignore + * cases; it's useful to ignore a case when inheritance will catch all the cases anyway. + * + * @return the new adapter. + * @see org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription + * @generated + */ + public Adapter createSysMLViewFrameNodeStyleDescriptionAdapter() { + return null; + } + /** * Creates a new adapter for an object of class '{@link org.eclipse.sirius.components.view.diagram.BorderStyle * Border Style}'. This default implementation returns null so that we can easily diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/util/SysMLCustomnodesSwitch.java b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/util/SysMLCustomnodesSwitch.java index f68a86b60..a6ac46533 100644 --- a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/util/SysMLCustomnodesSwitch.java +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/java/org/eclipse/syson/sysmlcustomnodes/util/SysMLCustomnodesSwitch.java @@ -21,6 +21,7 @@ import org.eclipse.syson.sysmlcustomnodes.SysMLImportedPackageNodeStyleDescription; import org.eclipse.syson.sysmlcustomnodes.SysMLNoteNodeStyleDescription; import org.eclipse.syson.sysmlcustomnodes.SysMLPackageNodeStyleDescription; +import org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription; /** * The Switch for the model's inheritance hierarchy. It supports the call @@ -106,6 +107,17 @@ protected T doSwitch(int classifierID, EObject theEObject) { result = this.defaultCase(theEObject); return result; } + case SysMLCustomnodesPackage.SYS_ML_VIEW_FRAME_NODE_STYLE_DESCRIPTION: { + SysMLViewFrameNodeStyleDescription sysMLViewFrameNodeStyleDescription = (SysMLViewFrameNodeStyleDescription) theEObject; + T result = this.caseSysMLViewFrameNodeStyleDescription(sysMLViewFrameNodeStyleDescription); + if (result == null) + result = this.caseNodeStyleDescription(sysMLViewFrameNodeStyleDescription); + if (result == null) + result = this.caseBorderStyle(sysMLViewFrameNodeStyleDescription); + if (result == null) + result = this.defaultCase(theEObject); + return result; + } default: return this.defaultCase(theEObject); } @@ -157,6 +169,22 @@ public T caseSysMLImportedPackageNodeStyleDescription(SysMLImportedPackageNodeSt return null; } + /** + * Returns the result of interpreting the object as an instance of 'Sys ML View Frame Node Style + * Description'. This implementation returns null; returning a non-null result will + * terminate the switch. + * + * @param object + * the target of the switch. + * @return the result of interpreting the object as an instance of 'Sys ML View Frame Node Style + * Description'. + * @see #doSwitch(org.eclipse.emf.ecore.EObject) doSwitch(EObject) + * @generated + */ + public T caseSysMLViewFrameNodeStyleDescription(SysMLViewFrameNodeStyleDescription object) { + return null; + } + /** * Returns the result of interpreting the object as an instance of 'Border Style'. * This implementation returns null; returning a non-null result will terminate the switch. diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/resources/model/sysml-customnodes.ecore b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/resources/model/sysml-customnodes.ecore index 4f25b83e6..b81a1a6aa 100644 --- a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/resources/model/sysml-customnodes.ecore +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/resources/model/sysml-customnodes.ecore @@ -12,4 +12,8 @@ eSuperTypes="../../../../../sirius-components-view-diagram/src/main/resources/model/diagram.ecore#//NodeStyleDescription"> + + + diff --git a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/resources/model/sysml-customnodes.genmodel b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/resources/model/sysml-customnodes.genmodel index e66a5fb0c..298b25424 100644 --- a/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/resources/model/sysml-customnodes.genmodel +++ b/backend/metamodel/syson-siriusweb-customnodes-metamodel/src/main/resources/model/sysml-customnodes.genmodel @@ -22,5 +22,8 @@ + + + diff --git a/backend/services/syson-services/src/main/java/org/eclipse/syson/services/MultiLineLabelSwitch.java b/backend/services/syson-services/src/main/java/org/eclipse/syson/services/MultiLineLabelSwitch.java index 733446266..37fe80cc3 100644 --- a/backend/services/syson-services/src/main/java/org/eclipse/syson/services/MultiLineLabelSwitch.java +++ b/backend/services/syson-services/src/main/java/org/eclipse/syson/services/MultiLineLabelSwitch.java @@ -70,6 +70,7 @@ import org.eclipse.syson.sysml.UseCaseDefinition; import org.eclipse.syson.sysml.UseCaseUsage; import org.eclipse.syson.sysml.VariantMembership; +import org.eclipse.syson.sysml.ViewUsage; import org.eclipse.syson.sysml.VisibilityKind; import org.eclipse.syson.sysml.helper.LabelConstants; import org.eclipse.syson.sysml.util.SysmlSwitch; @@ -227,6 +228,7 @@ public String caseAssignmentActionUsage(AssignmentActionUsage object) { .append(this.assignmentActionUsageDetails(object)); return label.toString(); } + @Override public String caseCaseDefinition(CaseDefinition object) { StringBuilder label = new StringBuilder(); @@ -784,11 +786,26 @@ public String caseStateUsage(StateUsage object) { return label.toString(); } + @Override + public String caseViewUsage(ViewUsage object) { + StringBuilder label = new StringBuilder(); + label + .append(this.getBasicNamePrefix(object)) + .append(LabelConstants.OPEN_QUOTE) + .append(this.reference(object)) + .append("view") + .append(LabelConstants.CLOSE_QUOTE) + .append(LabelConstants.SPACE) + .append(this.caseElement(object)) + .append(this.labelService.getTypingLabel(object)); + return label.toString(); + } + /** * Builds the string value for Parallel StateUsage or StateDefinition. * * @param isParallel - * Whether the State is parallel or not. + * Whether the State is parallel or not. */ private StringBuilder getIsParallel(boolean isParallel) { StringBuilder parallel = new StringBuilder(); diff --git a/backend/views/syson-diagram-general-view/src/main/java/org/eclipse/syson/diagram/general/view/GeneralViewDiagramDescriptionProvider.java b/backend/views/syson-diagram-general-view/src/main/java/org/eclipse/syson/diagram/general/view/GeneralViewDiagramDescriptionProvider.java index 851223558..d9a5f3d45 100644 --- a/backend/views/syson-diagram-general-view/src/main/java/org/eclipse/syson/diagram/general/view/GeneralViewDiagramDescriptionProvider.java +++ b/backend/views/syson-diagram-general-view/src/main/java/org/eclipse/syson/diagram/general/view/GeneralViewDiagramDescriptionProvider.java @@ -97,6 +97,7 @@ import org.eclipse.syson.diagram.general.view.nodes.RequirementUsageActorsCompartmentNodeDescriptionProvider; import org.eclipse.syson.diagram.general.view.nodes.RequirementUsageStakeholdersCompartmentNodeDescriptionProvider; import org.eclipse.syson.diagram.general.view.nodes.RequirementUsageSubjectCompartmentNodeDescriptionProvider; +import org.eclipse.syson.diagram.general.view.nodes.ViewFrameNodeDescriptionProvider; import org.eclipse.syson.sysml.FeatureDirectionKind; import org.eclipse.syson.sysml.SysmlPackage; import org.eclipse.syson.util.AQLUtils; @@ -240,7 +241,8 @@ public class GeneralViewDiagramDescriptionProvider implements IRepresentationDes SysmlPackage.eINSTANCE.getOccurrenceDefinition(), SysmlPackage.eINSTANCE.getExhibitStateUsage(), SysmlPackage.eINSTANCE.getStateUsage(), - SysmlPackage.eINSTANCE.getStateDefinition() + SysmlPackage.eINSTANCE.getStateDefinition(), + SysmlPackage.eINSTANCE.getViewUsage() )); public static final ToolSectionDescription ANALYSIS_TOOL_SECTIONS = new ToolSectionDescription(ToolConstants.ANALYSIS, List.of( @@ -612,6 +614,7 @@ private List> createAllCustomNodeDescripti customNodeDescriptionProviders.add(new ReferencingPerformActionUsageNodeDescriptionProvider(colorProvider)); customNodeDescriptionProviders.add(new ActorNodeDescriptionProvider(colorProvider)); customNodeDescriptionProviders.add(new ImportedPackageNodeDescriptionProvider(colorProvider, this.getDescriptionNameGenerator())); + customNodeDescriptionProviders.add(new ViewFrameNodeDescriptionProvider(colorProvider, this.getDescriptionNameGenerator())); return customNodeDescriptionProviders; } diff --git a/backend/views/syson-diagram-general-view/src/main/java/org/eclipse/syson/diagram/general/view/nodes/ViewFrameNodeDescriptionProvider.java b/backend/views/syson-diagram-general-view/src/main/java/org/eclipse/syson/diagram/general/view/nodes/ViewFrameNodeDescriptionProvider.java new file mode 100644 index 000000000..b6dc9ece2 --- /dev/null +++ b/backend/views/syson-diagram-general-view/src/main/java/org/eclipse/syson/diagram/general/view/nodes/ViewFrameNodeDescriptionProvider.java @@ -0,0 +1,146 @@ +/******************************************************************************* + * 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.diagram.general.view.nodes; + +import java.util.ArrayList; +import java.util.Objects; + +import org.eclipse.sirius.components.view.builder.IViewDiagramElementFinder; +import org.eclipse.sirius.components.view.builder.generated.diagram.FreeFormLayoutStrategyDescriptionBuilder; +import org.eclipse.sirius.components.view.builder.providers.IColorProvider; +import org.eclipse.sirius.components.view.diagram.DiagramDescription; +import org.eclipse.sirius.components.view.diagram.HeaderSeparatorDisplayMode; +import org.eclipse.sirius.components.view.diagram.InsideLabelDescription; +import org.eclipse.sirius.components.view.diagram.InsideLabelPosition; +import org.eclipse.sirius.components.view.diagram.InsideLabelStyle; +import org.eclipse.sirius.components.view.diagram.LabelOverflowStrategy; +import org.eclipse.sirius.components.view.diagram.LabelTextAlign; +import org.eclipse.sirius.components.view.diagram.NodeDescription; +import org.eclipse.sirius.components.view.diagram.NodePalette; +import org.eclipse.sirius.components.view.diagram.NodeStyleDescription; +import org.eclipse.sirius.components.view.diagram.NodeToolSection; +import org.eclipse.sirius.components.view.diagram.SynchronizationPolicy; +import org.eclipse.sirius.components.view.diagram.UserResizableDirection; +import org.eclipse.syson.diagram.common.view.nodes.AbstractNodeDescriptionProvider; +import org.eclipse.syson.sysml.SysmlPackage; +import org.eclipse.syson.sysmlcustomnodes.SysMLCustomnodesFactory; +import org.eclipse.syson.sysmlcustomnodes.SysMLViewFrameNodeStyleDescription; +import org.eclipse.syson.util.AQLConstants; +import org.eclipse.syson.util.AQLUtils; +import org.eclipse.syson.util.IDescriptionNameGenerator; +import org.eclipse.syson.util.SysMLMetamodelHelper; +import org.eclipse.syson.util.ViewConstants; + +/** + * @author frouene + */ +public class ViewFrameNodeDescriptionProvider extends AbstractNodeDescriptionProvider { + + protected final IDescriptionNameGenerator descriptionNameGenerator; + + public ViewFrameNodeDescriptionProvider(IColorProvider colorProvider, IDescriptionNameGenerator descriptionNameGenerator) { + super(colorProvider); + this.descriptionNameGenerator = Objects.requireNonNull(descriptionNameGenerator); + } + + @Override + public NodeDescription create() { + String domainType = SysMLMetamodelHelper.buildQualifiedName(SysmlPackage.eINSTANCE.getViewUsage()); + return this.diagramBuilderHelper.newNodeDescription() + .collapsible(true) + .childrenLayoutStrategy(new FreeFormLayoutStrategyDescriptionBuilder().build()) + .defaultHeightExpression("101") + .defaultWidthExpression("300") + .domainType(domainType) + .insideLabel(this.createInsideLabelDescription()) + .name(this.getNodeDescriptionName()) + .semanticCandidatesExpression("aql:self.getAllReachable(" + domainType + ")") + .style(this.createViewFrameNodeStyle()) + .userResizable(UserResizableDirection.BOTH) + .synchronizationPolicy(SynchronizationPolicy.UNSYNCHRONIZED) + .build(); + } + + @Override + public void link(DiagramDescription diagramDescription, IViewDiagramElementFinder cache) { + cache.getNodeDescription(this.getNodeDescriptionName()).ifPresent(nodeDescription -> { + nodeDescription.setPalette(this.createNodePalette(nodeDescription, cache)); + diagramDescription.getNodeDescriptions().add(nodeDescription); + }); + } + + private String getNodeDescriptionName() { + return this.descriptionNameGenerator.getNodeName(SysmlPackage.eINSTANCE.getViewUsage()); + } + + protected NodeStyleDescription createViewFrameNodeStyle() { + + SysMLViewFrameNodeStyleDescription nodeStyleDescription = SysMLCustomnodesFactory.eINSTANCE.createSysMLViewFrameNodeStyleDescription(); + nodeStyleDescription.setBorderColor(this.colorProvider.getColor(ViewConstants.DEFAULT_BORDER_COLOR)); + nodeStyleDescription.setBorderRadius(10); + nodeStyleDescription.setBackground(this.colorProvider.getColor(ViewConstants.DEFAULT_BACKGROUND_COLOR)); + return nodeStyleDescription; + } + + protected InsideLabelDescription createInsideLabelDescription() { + return this.diagramBuilderHelper.newInsideLabelDescription() + .labelExpression("aql:self.getContainerLabel()") + .position(InsideLabelPosition.TOP_CENTER) + .style(this.createInsideLabelStyle()) + .textAlign(LabelTextAlign.CENTER) + .overflowStrategy(LabelOverflowStrategy.ELLIPSIS) + .build(); + } + + protected InsideLabelStyle createInsideLabelStyle() { + return this.diagramBuilderHelper.newInsideLabelStyle() + .borderSize(0) + .headerSeparatorDisplayMode(HeaderSeparatorDisplayMode.NEVER) + .labelColor(this.colorProvider.getColor(ViewConstants.DEFAULT_LABEL_COLOR)) + .showIconExpression(AQLUtils.getSelfServiceCallExpression("showIcon")) + .withHeader(false) + .build(); + } + + private NodePalette createNodePalette(NodeDescription nodeDescription, IViewDiagramElementFinder cache) { + var changeContext = this.viewBuilderHelper.newChangeContext() + .expression("aql:self.deleteFromModel()"); + + var deleteTool = this.diagramBuilderHelper.newDeleteTool() + .name("Delete from Model") + .body(changeContext.build()); + + var callEditService = this.viewBuilderHelper.newChangeContext() + .expression(AQLConstants.AQL_SELF + ".directEditNode(newLabel)"); + + var editTool = this.diagramBuilderHelper.newLabelEditTool() + .name("Edit") + .initialDirectEditLabelExpression(AQLConstants.AQL_SELF + ".getDefaultInitialDirectEditLabel()") + .body(callEditService.build()); + + + return this.diagramBuilderHelper.newNodePalette() + .deleteTool(deleteTool.build()) + .labelEditTool(editTool.build()) + .toolSections(this.createToolSections(cache)) + .build(); + } + + private NodeToolSection[] createToolSections(IViewDiagramElementFinder cache) { + var sections = new ArrayList(); + + sections.add(this.defaultToolsFactory.createDefaultHideRevealNodeToolSection()); + + return sections.toArray(NodeToolSection[]::new); + } +} diff --git a/doc/content/modules/user-manual/assets/images/view-usage-nodes.png b/doc/content/modules/user-manual/assets/images/view-usage-nodes.png new file mode 100644 index 000000000..85b924731 Binary files /dev/null and b/doc/content/modules/user-manual/assets/images/view-usage-nodes.png differ diff --git a/doc/content/modules/user-manual/pages/release-notes/2025.6.0.adoc b/doc/content/modules/user-manual/pages/release-notes/2025.6.0.adoc new file mode 100644 index 000000000..d896327f3 --- /dev/null +++ b/doc/content/modules/user-manual/pages/release-notes/2025.6.0.adoc @@ -0,0 +1,26 @@ += 2025.6.0 (work in progress) + +== Key highlights + + +== Breaking changes + + +== Bug fixes + + +== New features + +- `ViewUsage` may now be displayed and created from the _General View_. + +image::view-usage-nodes.png[ViewUsage nodes, width=65%,height=65%] + + +== Improvements + + +== Dependency update + + +== Technical details + diff --git a/frontend/syson-components/src/index.ts b/frontend/syson-components/src/index.ts index bf9558d1d..78095dcf0 100644 --- a/frontend/syson-components/src/index.ts +++ b/frontend/syson-components/src/index.ts @@ -30,3 +30,6 @@ export { SysMLPackageNode } from './nodes/package/SysMLPackageNode'; export { SysMLPackageNodeConverter } from './nodes/package/SysMLPackageNodeConverter'; export { SysMLPackageNodeLayoutHandler } from './nodes/package/SysMLPackageNodeLayoutHandler'; 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'; diff --git a/frontend/syson-components/src/nodes/SysMLNodesDocumentTransform.ts b/frontend/syson-components/src/nodes/SysMLNodesDocumentTransform.ts index d79fc295c..c498a8636 100644 --- a/frontend/syson-components/src/nodes/SysMLNodesDocumentTransform.ts +++ b/frontend/syson-components/src/nodes/SysMLNodesDocumentTransform.ts @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2024 Obeo. + * Copyright (c) 2024, 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 @@ -69,6 +69,14 @@ const backgroundField: SelectionNode = { }, }; +const borderRadiusField: SelectionNode = { + kind: Kind.FIELD, + name: { + kind: Kind.NAME, + value: 'borderRadius', + }, +}; + export const sysMLNodesStyleDocumentTransform = new DocumentTransform((document) => { if (shouldTransform(document)) { const transformedDocument = visit(document, { @@ -124,6 +132,21 @@ export const sysMLNodesStyleDocumentTransform = new DocumentTransform((document) }, }; + const sysMLViewFrameNodeStyleInlineFragment: InlineFragmentNode = { + kind: Kind.INLINE_FRAGMENT, + selectionSet: { + kind: Kind.SELECTION_SET, + selections: [borderColorField, borderSizeField, borderStyleField, backgroundField, borderRadiusField], + }, + typeCondition: { + kind: Kind.NAMED_TYPE, + name: { + kind: Kind.NAME, + value: 'SysMLViewFrameNodeStyle', + }, + }, + }; + return { ...field, selectionSet: { @@ -133,6 +156,7 @@ export const sysMLNodesStyleDocumentTransform = new DocumentTransform((document) sysMLPackageNodeStyleInlineFragment, sysMLImportedPackageNodeStyleInlineFragment, sysMLNoteNodeStyleInlineFragment, + sysMLViewFrameNodeStyleInlineFragment, ], }, }; diff --git a/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNode.tsx b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNode.tsx new file mode 100644 index 000000000..5512b696f --- /dev/null +++ b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNode.tsx @@ -0,0 +1,178 @@ +/******************************************************************************* + * 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 { getCSSColor } from '@eclipse-sirius/sirius-components-core'; +import { + ConnectionCreationHandles, + ConnectionHandles, + ConnectionTargetHandle, + DiagramContext, + DiagramContextValue, + DiagramElementPalette, + Label, + useConnectorNodeStyle, + useDrop, + useDropNodeStyle, + useRefreshConnectionHandles, +} from '@eclipse-sirius/sirius-components-diagrams'; +import { Theme, useTheme } from '@mui/material/styles'; +import { Node, NodeProps, NodeResizer } from '@xyflow/react'; +import React, { memo, useContext } from 'react'; + +import { NodeComponentsMap, SysMLViewFrameNodeData } from './SysMLViewFrameNode.types'; + +const sysMLViewFrameNodeStyle = ( + theme: Theme, + style: React.CSSProperties, + selected: boolean, + hovered: boolean, + faded: boolean +): React.CSSProperties => { + const packageContainerStyle: React.CSSProperties = { + display: 'flex', + padding: '0px', + width: '100%', + height: '100%', + opacity: faded ? '0.4' : '', + ...style, + backgroundColor: 'transparent', + }; + + if (selected || hovered) { + packageContainerStyle.outline = `${theme.palette.selected} solid 1px`; + } + + return packageContainerStyle; +}; + +const viewFrameNameCompartmentStyle = ( + theme: Theme, + style: React.CSSProperties, + faded: boolean +): React.CSSProperties => { + return { + display: 'flex', + position: 'absolute', + top: 0, + left: 0, + width: '70%', + padding: '4px 8px', + opacity: faded ? '0.4' : '', + ...style, + background: getCSSColor(String(style.background), theme), + overflowX: 'clip', + borderBottomLeftRadius: '0px', + borderTopRightRadius: '0px', + }; +}; + +const viewFrameContainerStyle = (theme: Theme, style: React.CSSProperties, faded: boolean): React.CSSProperties => { + return { + display: 'flex', + padding: '8px', + width: '100%', + height: '100%', + opacity: faded ? '0.4' : '', + ...style, + background: getCSSColor(String(style.background), theme), + borderWidth: '0px', + }; +}; + +const resizeLineStyle = (theme: Theme): React.CSSProperties => { + return { borderWidth: theme.spacing(0.15) }; +}; + +const resizeHandleStyle = (theme: Theme): React.CSSProperties => { + return { + width: theme.spacing(1), + height: theme.spacing(1), + borderRadius: '100%', + }; +}; + +export const SysMLViewFrameNode: NodeComponentsMap['sysMLViewFrameNode'] = memo( + ({ data, id, selected, dragging }: NodeProps>) => { + const { readOnly } = useContext(DiagramContext); + const theme: Theme = useTheme(); + const { onDrop, onDragOver } = useDrop(); + const { style: connectionFeedbackStyle } = useConnectorNodeStyle(id, data.nodeDescription.id); + const { style: dropFeedbackStyle } = useDropNodeStyle(data.isDropNodeTarget, data.isDropNodeCandidate, dragging); + + const handleOnDrop = (event: React.DragEvent) => { + onDrop(event, id); + }; + + const label: any = { + ...data.insideLabel, + style: { + ...data?.insideLabel?.style, + whiteSpace: 'pre', + overflow: 'hidden', + paddingRight: '0', + justifyContent: 'flex-start', + textAlign: 'left', + }, + }; + + useRefreshConnectionHandles(id, data.connectionHandles); + + return ( + <> + {data.nodeDescription?.userResizable && !readOnly ? ( + !data.isBorderNode} + keepAspectRatio={data.nodeDescription?.keepAspectRatio} + /> + ) : null} +
+ {selected ? ( + + ) : null} + {selected ? : null} + + +
+ {data.insideLabel ?
+
+
+ + ); + } +); diff --git a/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNode.types.ts b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNode.types.ts new file mode 100644 index 000000000..fc4ebbcae --- /dev/null +++ b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNode.types.ts @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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 { Node, NodeProps } from '@xyflow/react'; +import { FC } from 'react'; + +export interface SysMLViewFrameNodeData extends NodeData {} + +export interface GQLSysMLViewFrameNodeStyle extends GQLNodeStyle { + background: string; + borderColor: string; + borderStyle: string; + borderSize: string; + borderRadius: string; +} + +export interface NodeDataMap { + sysMLViewFrameNode: SysMLViewFrameNodeData; +} + +export type NodeComponentsMap = { + [K in keyof NodeDataMap]: FC>>; +}; diff --git a/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodeConverter.ts b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodeConverter.ts new file mode 100644 index 000000000..68e215335 --- /dev/null +++ b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodeConverter.ts @@ -0,0 +1,194 @@ +/******************************************************************************* + * 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 { + BorderNodePosition, + ConnectionHandle, + GQLDiagram, + GQLDiagramDescription, + GQLEdge, + GQLHandleLayoutData, + GQLNode, + GQLNodeDescription, + GQLNodeLayoutData, + GQLNodeStyle, + GQLViewModifier, + IConvertEngine, + INodeConverter, + convertHandles, + convertInsideLabel, + convertLineStyle, + convertOutsideLabels, + isListLayoutStrategy, +} from '@eclipse-sirius/sirius-components-diagrams'; +import { Node, XYPosition } from '@xyflow/react'; + +import { SysMLViewFrameNodeData, GQLSysMLViewFrameNodeStyle } from './SysMLViewFrameNode.types'; + +const defaultPosition: XYPosition = { x: 0, y: 0 }; + +const toViewFrameNode = ( + gqlDiagram: GQLDiagram, + gqlNode: GQLNode, + gqlParentNode: GQLNode | null, + nodeDescription: GQLNodeDescription, + isBorderNode: boolean, + gqlEdges: GQLEdge[] +): Node => { + const { + targetObjectId, + targetObjectLabel, + targetObjectKind, + descriptionId, + id, + insideLabel, + outsideLabels, + state, + pinned, + style, + labelEditable, + } = gqlNode; + + const handleLayoutData: GQLHandleLayoutData[] = gqlDiagram.layoutData.nodeLayoutData + .filter((nodeLayoutData) => nodeLayoutData.id === id) + .flatMap((nodeLayoutData) => nodeLayoutData.handleLayoutData); + + const connectionHandles: ConnectionHandle[] = convertHandles(gqlNode.id, gqlEdges, handleLayoutData); + + const gqlNodeLayoutData: GQLNodeLayoutData | undefined = gqlDiagram.layoutData.nodeLayoutData.find( + (nodeLayoutData) => nodeLayoutData.id === id + ); + const isNew = gqlDiagram.layoutData.nodeLayoutData.find((nodeLayoutData) => nodeLayoutData.id === id) === undefined; + const resizedByUser = gqlNodeLayoutData?.resizedByUser ?? false; + + const data: SysMLViewFrameNodeData = { + targetObjectId, + targetObjectLabel, + targetObjectKind, + descriptionId, + style: { + display: 'flex', + background: style.background, + borderColor: style.borderColor, + borderWidth: style.borderSize, + borderStyle: convertLineStyle(style.borderStyle), + borderRadius: style.borderRadius, + }, + insideLabel: null, + outsideLabels: convertOutsideLabels(outsideLabels), + faded: state === GQLViewModifier.Faded, + pinned, + isBorderNode: isBorderNode, + nodeDescription, + defaultWidth: gqlNode.defaultWidth, + defaultHeight: gqlNode.defaultHeight, + borderNodePosition: isBorderNode ? BorderNodePosition.EAST : null, + connectionHandles, + labelEditable, + isNew, + resizedByUser, + isListChild: isListLayoutStrategy(gqlParentNode?.childrenLayoutStrategy), + isDropNodeTarget: false, + isDropNodeCandidate: false, + isHovered: false, + }; + + data.insideLabel = convertInsideLabel( + insideLabel, + data, + `${style.borderSize}px ${style.borderStyle} ${style.borderColor}` + ); + + if (data.insideLabel) { + data.insideLabel.isHeader = true; + data.insideLabel.headerPosition = 'TOP'; + } + + const node: Node = { + id, + type: 'sysMLViewFrameNode', + data, + position: defaultPosition, + hidden: gqlNode.state === GQLViewModifier.Hidden, + }; + + if (gqlParentNode) { + node.parentId = gqlParentNode.id; + } + + const nodeLayoutData = gqlDiagram.layoutData.nodeLayoutData.filter((data) => data.id === id)[0]; + if (nodeLayoutData) { + const { + position, + size: { height, width }, + } = nodeLayoutData; + node.position = position; + node.height = height; + node.width = width; + node.style = { + ...node.style, + width: `${node.width}px`, + height: `${node.height}px`, + }; + } + + return node; +}; + +export class SysMLViewFrameNodeConverter implements INodeConverter { + canHandle(gqlNode: GQLNode) { + return gqlNode.style.__typename === 'SysMLViewFrameNodeStyle'; + } + + handle( + convertEngine: IConvertEngine, + gqlDiagram: GQLDiagram, + gqlNode: GQLNode, + gqlEdges: GQLEdge[], + parentNode: GQLNode | null, + isBorderNode: boolean, + nodes: Node[], + diagramDescription: GQLDiagramDescription, + nodeDescriptions: GQLNodeDescription[] + ) { + const nodeDescription: GQLNodeDescription | undefined = nodeDescriptions.find( + (description) => description.id === gqlNode.descriptionId + ); + if (nodeDescription) { + nodes.push(toViewFrameNode(gqlDiagram, gqlNode, parentNode, nodeDescription, isBorderNode, gqlEdges)); + } + const borderNodeDescriptions: GQLNodeDescription[] = (nodeDescription?.borderNodeDescriptionIds ?? []).flatMap( + (nodeDescriptionId) => + diagramDescription.nodeDescriptions.filter((nodeDescription) => nodeDescription.id === nodeDescriptionId) + ); + const childNodeDescriptions: GQLNodeDescription[] = (nodeDescription?.childNodeDescriptionIds ?? []).flatMap( + (nodeDescriptionId) => + diagramDescription.nodeDescriptions.filter((nodeDescription) => nodeDescription.id === nodeDescriptionId) + ); + convertEngine.convertNodes( + gqlDiagram, + gqlNode.borderNodes ?? [], + gqlNode, + nodes, + diagramDescription, + borderNodeDescriptions + ); + convertEngine.convertNodes( + gqlDiagram, + gqlNode.childNodes ?? [], + gqlNode, + nodes, + diagramDescription, + childNodeDescriptions + ); + } +} diff --git a/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodeLayoutHandler.ts b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodeLayoutHandler.ts new file mode 100644 index 000000000..09398519d --- /dev/null +++ b/frontend/syson-components/src/nodes/view_frame/SysMLViewFrameNodeLayoutHandler.ts @@ -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 + *******************************************************************************/ +import { + Diagram, + DiagramNodeType, + ForcedDimensions, + ILayoutEngine, + INodeLayoutHandler, + NodeData, + computeNodesBox, + computePreviousSize, + findNodeIndex, + getBorderNodeExtent, + getChildNodePosition, + getDefaultOrMinHeight, + getDefaultOrMinWidth, + getEastBorderNodeFootprintHeight, + getHeaderHeightFootprint, + getNorthBorderNodeFootprintWidth, + getSouthBorderNodeFootprintWidth, + getWestBorderNodeFootprintHeight, + setBorderNodesPosition, +} from '@eclipse-sirius/sirius-components-diagrams'; +import { Dimensions, Node, Rect } from '@xyflow/react'; +import { SysMLViewFrameNodeData } from './SysMLViewFrameNode.types'; + +const rectangularNodePadding: number = 8; + +export class SysMLViewFrameNodeLayoutHandler implements INodeLayoutHandler { + public canHandle(node: Node): boolean { + return node.type === 'sysMLViewFrameNode'; + } + + public handle( + layoutEngine: ILayoutEngine, + previousDiagram: Diagram | null, + node: Node, + visibleNodes: Node[], + directChildren: Node[], + newlyAddedNode: Node | undefined, + forceDimensions?: ForcedDimensions + ) { + const nodeIndex = findNodeIndex(visibleNodes, node.id); + const nodeElement = document.getElementById(`${node.id}-rectangularNode-${nodeIndex}`)?.children[0]; + const borderWidth = nodeElement ? parseFloat(window.getComputedStyle(nodeElement).borderWidth) : 0; + if (directChildren.length > 0) { + this.handleParentNode( + layoutEngine, + previousDiagram, + node, + visibleNodes, + directChildren, + newlyAddedNode, + borderWidth, + forceDimensions + ); + } else { + this.handleLeafNode(previousDiagram, node, visibleNodes, borderWidth, forceDimensions); + } + } + + private handleParentNode( + layoutEngine: ILayoutEngine, + previousDiagram: Diagram | null, + node: Node, + visibleNodes: Node[], + directChildren: Node[], + newlyAddedNode: Node | undefined, + borderWidth: number, + forceDimensions?: ForcedDimensions + ) { + layoutEngine.layoutNodes(previousDiagram, visibleNodes, directChildren, newlyAddedNode); + + const nodeIndex: number = findNodeIndex(visibleNodes, node.id); + const labelElement: HTMLElement | null = document.getElementById(`${node.id}-label-${nodeIndex}`); + const headerHeightFootprint: number = labelElement + ? getHeaderHeightFootprint(labelElement, node.data.insideLabel, 'TOP') + : 33; + + const borderNodes: Node[] = directChildren.filter((node) => node.data.isBorderNode); + const directNodesChildren: Node[] = directChildren.filter((child) => !child.data.isBorderNode); + + // Update children position to be under the label and at the right padding. + directNodesChildren.forEach((child, index) => { + const previousNode = (previousDiagram?.nodes ?? []).find((prevNode) => prevNode.id === child.id); + const createdNode = newlyAddedNode?.id === child.id ? newlyAddedNode : undefined; + + if (!!createdNode) { + child.position = createdNode.position; + if (child.position.y < borderWidth + headerHeightFootprint + rectangularNodePadding) { + child.position = { ...child.position, y: borderWidth + headerHeightFootprint + rectangularNodePadding }; + } + } else if (previousNode) { + child.position = previousNode.position; + if (previousNode && previousNode.position.y < headerHeightFootprint + rectangularNodePadding) { + child.position = { ...child.position, y: headerHeightFootprint + rectangularNodePadding }; + } else { + child.position = child.position; + } + if (previousNode && previousNode.position.x < 0) { + child.position = { ...child.position, x: rectangularNodePadding }; + } + } else { + child.position = getChildNodePosition(visibleNodes, child, headerHeightFootprint, borderWidth); + if (child.position.y < headerHeightFootprint + rectangularNodePadding) { + child.position = { ...child.position, y: child.position.y + headerHeightFootprint }; + } + const previousSibling = directNodesChildren[index - 1]; + if (previousSibling) { + child.position = getChildNodePosition( + visibleNodes, + child, + headerHeightFootprint, + borderWidth, + previousSibling + ); + } + if (child.position.x < 0) { + child.position = { ...child.position, x: rectangularNodePadding }; + } + } + }); + + // Update node to layout size + // WARN: We suppose label are always on top of children (that wrong) + const childrenContentBox: Rect = computeNodesBox(visibleNodes, directNodesChildren); // WARN: The current content box algorithm does not take the margin of direct children (it should) + const directChildrenAwareNodeWidth: number = + childrenContentBox.x + childrenContentBox.width + rectangularNodePadding; + const northBorderNodeFootprintWidth: number = getNorthBorderNodeFootprintWidth( + visibleNodes, + borderNodes, + previousDiagram + ); + const southBorderNodeFootprintWidth: number = getSouthBorderNodeFootprintWidth( + visibleNodes, + borderNodes, + previousDiagram + ); + + const nodeMinComputeWidth: number = + Math.max( + directChildrenAwareNodeWidth, + northBorderNodeFootprintWidth, + southBorderNodeFootprintWidth, + node.data.defaultWidth && !node.data.resizedByUser ? node.data.defaultWidth : 0 + ) + + borderWidth * 2; + + // WARN: the label is not used for the height because children are already position under the label + const directChildrenAwareNodeHeight: number = + childrenContentBox.y + childrenContentBox.height + rectangularNodePadding; + const eastBorderNodeFootprintHeight: number = getEastBorderNodeFootprintHeight( + visibleNodes, + borderNodes, + previousDiagram + ); + const westBorderNodeFootprintHeight: number = getWestBorderNodeFootprintHeight( + visibleNodes, + borderNodes, + previousDiagram + ); + + const nodeMinComputeHeight: number = + Math.max( + directChildrenAwareNodeHeight, + eastBorderNodeFootprintHeight, + westBorderNodeFootprintHeight, + node.data.defaultHeight && !node.data.resizedByUser ? node.data.defaultHeight : 0 + ) + + borderWidth * 2; + + const nodeWidth: number = forceDimensions?.width ?? getDefaultOrMinWidth(nodeMinComputeWidth, node); + const nodeHeight: number = getDefaultOrMinHeight(nodeMinComputeHeight, node); + + const previousNode: Node | undefined = (previousDiagram?.nodes ?? []).find( + (prevNode) => prevNode.id === node.id + ); + const previousDimensions: Dimensions = computePreviousSize(previousNode, node); + if (node.data.resizedByUser) { + if (nodeMinComputeWidth > previousDimensions.width) { + node.width = nodeMinComputeWidth; + } else { + node.width = previousDimensions.width; + } + if (nodeMinComputeHeight > previousDimensions.height) { + node.height = nodeMinComputeHeight; + } else { + node.height = previousDimensions.height; + } + } else { + node.width = nodeWidth; + node.height = nodeHeight; + } + + // Update border nodes positions + borderNodes.forEach((borderNode) => { + borderNode.extent = getBorderNodeExtent(node, borderNode); + }); + setBorderNodesPosition(borderNodes, node, previousDiagram); + } + + private handleLeafNode( + previousDiagram: Diagram | null, + node: Node, + visibleNodes: Node[], + _borderWidth: number, + _forceDimensions?: ForcedDimensions + ) { + const nodeIndex: number = findNodeIndex(visibleNodes, node.id); + const labelElement: HTMLElement | null = document.getElementById(`${node.id}-label-${nodeIndex}`); + + const labelHeight: number = + rectangularNodePadding + (labelElement?.getBoundingClientRect().height ?? 0) + rectangularNodePadding; + + const minNodeWidth: number = node.data.resizedByUser ? 75 : node.data.defaultWidth ?? 75; + const minNodeHeight: number = Math.max(labelHeight, node.data.resizedByUser ? 50 : node.data.defaultHeight ?? 50); + + const previousNode: Node | undefined = (previousDiagram?.nodes ?? []).find( + (prevNode) => prevNode.id === node.id + ); + const previousDimensions: Dimensions = computePreviousSize(previousNode, node); + + if (node.data.resizedByUser) { + if (minNodeWidth > previousDimensions.width) { + node.width = minNodeWidth; + } else { + node.width = previousDimensions.width; + } + if (minNodeHeight > previousDimensions.height) { + node.height = minNodeHeight; + } else { + node.height = previousDimensions.height; + } + } else { + node.width = minNodeWidth; + node.height = minNodeHeight; + } + } +} diff --git a/frontend/syson/src/index.tsx b/frontend/syson/src/index.tsx index 2183eb4c9..23c0d3b92 100644 --- a/frontend/syson/src/index.tsx +++ b/frontend/syson/src/index.tsx @@ -28,6 +28,7 @@ import { treeItemContextMenuEntryExtensionPoint, treeItemContextMenuEntryOverrideExtensionPoint, TreeItemContextMenuOverrideContribution, + GQLTreeItemContextMenuEntry, } from '@eclipse-sirius/sirius-components-trees'; import { ApolloClientOptionsConfigurer, @@ -57,10 +58,11 @@ import { SysMLPackageNodeLayoutHandler, SysONDiagramPanelMenu, SysONNavigationBarMenuIcon, + SysMLViewFrameNodeLayoutHandler, + SysMLViewFrameNodeConverter, + SysMLViewFrameNode, } from '@eclipse-syson/syson-components'; import { createRoot } from 'react-dom/client'; - -import { GQLTreeItemContextMenuEntry } from '@eclipse-sirius/sirius-components-trees'; import { httpOrigin, wsOrigin } from './core/URL'; import { SysONDocumentTreeItemContextMenuContribution } from './extensions/SysONDocumentTreeItemContextMenuContribution'; import { SysONExtensionRegistryMergeStrategy } from './extensions/SysONExtensionRegistryMergeStrategy'; @@ -176,16 +178,19 @@ const nodeTypeRegistry: NodeTypeRegistry = { new SysMLPackageNodeLayoutHandler(), new SysMLNoteNodeLayoutHandler(), new SysMLImportedPackageNodeLayoutHandler(), + new SysMLViewFrameNodeLayoutHandler(), ], nodeConverters: [ new SysMLPackageNodeConverter(), new SysMLNoteNodeConverter(), new SysMLImportedPackageNodeConverter(), + new SysMLViewFrameNodeConverter(), ], nodeTypeContributions: [ , , , + , ], };