diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 42a85d572..8839a202b 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -53,6 +53,7 @@ A new compartment named _satisfy requirements_ has also been added to `PartDefin - https://github.com/eclipse-syson/syson/issues/1395[#1395] Provide a way to duplicate a semantic element ans its representation node in the _General View_ diagram. - https://github.com/eclipse-syson/syson/issues/1740[#1740] [diagrams] Add _items_ compartment and graphical border node on `PortDefinition` graphical nodes in the _General View_ diagram. - https://github.com/eclipse-syson/syson/issues/1786[#1786] [export] Implement textual export of `RequirementConstraintMembership`. +- https://github.com/eclipse-syson/syson/issues/1771[#1740] [services] Add `IDetailViewHelpTextProvider` service in order to add help text to properties widgets == v2025.12.0 diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/configuration/SysMLv2PropertiesConfigurer.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/configuration/SysMLv2PropertiesConfigurer.java index 3f062a407..a765c5d19 100644 --- a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/configuration/SysMLv2PropertiesConfigurer.java +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/configuration/SysMLv2PropertiesConfigurer.java @@ -53,6 +53,7 @@ import org.eclipse.sirius.components.view.widget.reference.ReferenceFactory; import org.eclipse.sirius.components.view.widget.reference.ReferenceWidgetDescription; import org.eclipse.syson.application.services.DetailsViewService; +import org.eclipse.syson.form.services.api.IDetailsViewHelpTextProvider; import org.eclipse.syson.form.services.aql.FormMutationAQLService; import org.eclipse.syson.form.services.aql.FormQueryAQLService; import org.eclipse.syson.model.services.ModelMutationElementService; @@ -76,6 +77,8 @@ public class SysMLv2PropertiesConfigurer implements IPropertiesDescriptionRegist private static final String GET_DETAILS_VIEW_LABEL_SERVICE = "getDetailsViewLabel"; + private static final String GET_DETAILS_VIEW_HELP_TEXT_SERVICE = "getDetailsViewHelpText"; + private static final String CORE_PROPERTIES = "Core Properties"; private static final String ADVANCED_PROPERTIES = "Advanced Properties"; @@ -118,13 +121,16 @@ public class SysMLv2PropertiesConfigurer implements IPropertiesDescriptionRegist private final IReadOnlyObjectPredicate readOnlyObjectPredicate; + private final List detailViewHelpTextProviders; + public SysMLv2PropertiesConfigurer(List composedAdapterFactoryDescriptors, ViewFormDescriptionConverter converter, IFeedbackMessageService feedbackMessageService, - ILabelService labelService, final IReadOnlyObjectPredicate readOnlyObjectPredicate) { + ILabelService labelService, List detailViewHelpTextProviders, final IReadOnlyObjectPredicate readOnlyObjectPredicate) { this.composedAdapterFactoryDescriptors = Objects.requireNonNull(composedAdapterFactoryDescriptors); this.converter = Objects.requireNonNull(converter); this.feedbackMessageService = Objects.requireNonNull(feedbackMessageService); this.labelService = Objects.requireNonNull(labelService); this.readOnlyObjectPredicate = Objects.requireNonNull(readOnlyObjectPredicate); + this.detailViewHelpTextProviders = Objects.requireNonNull(detailViewHelpTextProviders); this.utilService = new UtilService(); } @@ -147,7 +153,7 @@ public void addPropertiesDescriptions(IPropertiesDescriptionRegistry registry) { // Convert the View-based FormDescription and register the result into the system AQLInterpreter interpreter = new AQLInterpreter(List.of(), - List.of(new DetailsViewService(this.composedAdapterFactoryDescriptors, this.feedbackMessageService, this.readOnlyObjectPredicate), this.labelService, this.utilService, + List.of(new DetailsViewService(this.composedAdapterFactoryDescriptors, this.feedbackMessageService, this.readOnlyObjectPredicate, this.detailViewHelpTextProviders), this.labelService, this.utilService, new ModelMutationAQLService(new ModelMutationElementService()), new ModelQueryAQLService(), new FormMutationAQLService(), new FormQueryAQLService()), List.of(SysmlPackage.eINSTANCE)); ViewConverterResult converterResult = this.converter.convert(viewFormDescription, List.of(), interpreter); @@ -548,6 +554,7 @@ private WidgetDescription createLabelWidget() { LabelDescription label = FormFactory.eINSTANCE.createLabelDescription(); label.setName("LabelWidget"); label.setLabelExpression(AQLUtils.getSelfServiceCallExpression(GET_DETAILS_VIEW_LABEL_SERVICE, E_STRUCTURAL_FEATURE)); + label.setHelpExpression(AQLUtils.getSelfServiceCallExpression(GET_DETAILS_VIEW_HELP_TEXT_SERVICE, E_STRUCTURAL_FEATURE)); label.setValueExpression(AQLUtils.getSelfServiceCallExpression("eGet", E_STRUCTURAL_FEATURE)); return label; } @@ -556,6 +563,7 @@ private WidgetDescription createTextAreaFieldWidget() { TextAreaDescription textArea = FormFactory.eINSTANCE.createTextAreaDescription(); textArea.setName("TextAreaWidget"); textArea.setLabelExpression(AQLUtils.getSelfServiceCallExpression(GET_DETAILS_VIEW_LABEL_SERVICE, E_STRUCTURAL_FEATURE)); + textArea.setHelpExpression(AQLUtils.getSelfServiceCallExpression(GET_DETAILS_VIEW_HELP_TEXT_SERVICE, E_STRUCTURAL_FEATURE)); textArea.setValueExpression(AQLUtils.getSelfServiceCallExpression("eGet", E_STRUCTURAL_FEATURE)); textArea.setIsEnabledExpression(AQL_NOT_SELF_IS_READ_ONLY_E_STRUCTURAL_FEATURE); ChangeContext setNewValueOperation = ViewFactory.eINSTANCE.createChangeContext(); @@ -568,6 +576,7 @@ private WidgetDescription createTextfieldWidget() { TextfieldDescription textfield = FormFactory.eINSTANCE.createTextfieldDescription(); textfield.setName("TextfieldWidget"); textfield.setLabelExpression(AQLUtils.getSelfServiceCallExpression(GET_DETAILS_VIEW_LABEL_SERVICE, E_STRUCTURAL_FEATURE)); + textfield.setHelpExpression(AQLUtils.getSelfServiceCallExpression(GET_DETAILS_VIEW_HELP_TEXT_SERVICE, E_STRUCTURAL_FEATURE)); textfield.setValueExpression(AQLUtils.getSelfServiceCallExpression("eGet", E_STRUCTURAL_FEATURE)); textfield.setIsEnabledExpression(AQL_NOT_SELF_IS_READ_ONLY_E_STRUCTURAL_FEATURE); ChangeContext setNewValueOperation = ViewFactory.eINSTANCE.createChangeContext(); @@ -581,6 +590,7 @@ private WidgetDescription createCheckboxWidget() { checkbox.setName("CheckboxWidget"); checkbox.setLabelExpression(AQLUtils.getSelfServiceCallExpression(GET_DETAILS_VIEW_LABEL_SERVICE, E_STRUCTURAL_FEATURE)); checkbox.setValueExpression(AQLUtils.getSelfServiceCallExpression("eGet", E_STRUCTURAL_FEATURE)); + checkbox.setHelpExpression(AQLUtils.getSelfServiceCallExpression(GET_DETAILS_VIEW_HELP_TEXT_SERVICE, E_STRUCTURAL_FEATURE)); checkbox.setIsEnabledExpression(AQL_NOT_SELF_IS_READ_ONLY_E_STRUCTURAL_FEATURE); ChangeContext setNewValueOperation = ViewFactory.eINSTANCE.createChangeContext(); setNewValueOperation.setExpression(AQLUtils.getSelfServiceCallExpression("setNewValue", List.of(E_STRUCTURAL_FEATURE, ViewFormDescriptionConverter.NEW_VALUE))); @@ -592,6 +602,7 @@ private WidgetDescription createRadioWidget() { RadioDescription radio = FormFactory.eINSTANCE.createRadioDescription(); radio.setName("RadioWidget"); radio.setLabelExpression(AQLUtils.getSelfServiceCallExpression(GET_DETAILS_VIEW_LABEL_SERVICE, E_STRUCTURAL_FEATURE)); + radio.setHelpExpression(AQLUtils.getSelfServiceCallExpression(GET_DETAILS_VIEW_HELP_TEXT_SERVICE, E_STRUCTURAL_FEATURE)); radio.setCandidatesExpression(AQLUtils.getSelfServiceCallExpression("getEnumCandidates", E_STRUCTURAL_FEATURE)); radio.setCandidateLabelExpression("aql:candidate.name"); radio.setValueExpression(AQLUtils.getSelfServiceCallExpression("getEnumValue", E_STRUCTURAL_FEATURE)); @@ -606,6 +617,7 @@ private WidgetDescription createReferenceWidget() { ReferenceWidgetDescription refWidget = ReferenceFactory.eINSTANCE.createReferenceWidgetDescription(); refWidget.setName("ReferenceWidget"); refWidget.setLabelExpression(AQLUtils.getSelfServiceCallExpression(GET_DETAILS_VIEW_LABEL_SERVICE, E_STRUCTURAL_FEATURE)); + refWidget.setHelpExpression(AQLUtils.getSelfServiceCallExpression(GET_DETAILS_VIEW_HELP_TEXT_SERVICE, E_STRUCTURAL_FEATURE)); refWidget.setReferenceNameExpression(AQLConstants.AQL + E_STRUCTURAL_FEATURE + ".name"); refWidget.setReferenceOwnerExpression(AQLConstants.AQL_SELF); refWidget.setIsEnabledExpression(AQL_NOT_SELF_IS_READ_ONLY_E_STRUCTURAL_FEATURE); diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/services/DetailsViewService.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/services/DetailsViewService.java index ecd6c9302..7a299c5d7 100644 --- a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/services/DetailsViewService.java +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/services/DetailsViewService.java @@ -36,6 +36,7 @@ import org.eclipse.sirius.components.core.api.IReadOnlyObjectPredicate; import org.eclipse.sirius.components.representations.Message; import org.eclipse.sirius.components.representations.MessageLevel; +import org.eclipse.syson.form.services.api.IDetailsViewHelpTextProvider; import org.eclipse.syson.application.configuration.SysMLv2PropertiesConfigurer; import org.eclipse.syson.services.ElementInitializerSwitch; import org.eclipse.syson.services.ImportService; @@ -83,20 +84,23 @@ public class DetailsViewService { private final IFeedbackMessageService feedbackMessageService; + private final IReadOnlyObjectPredicate readOnlyObjectPredicate; + + private final List detailsViewHelpTextProviders; + private final ImportService importService; private final ElementInitializerSwitch elementInitializerSwitch; private final EEnumLiteral unsetEnumLiteral; - private final IReadOnlyObjectPredicate readOnlyObjectPredicate; - private final UtilService utilService; - public DetailsViewService(List composedAdapterFactoryDescriptors, IFeedbackMessageService feedbackMessageService, IReadOnlyObjectPredicate readOnlyObjectPredicate) { + public DetailsViewService(List composedAdapterFactoryDescriptors, IFeedbackMessageService feedbackMessageService, IReadOnlyObjectPredicate readOnlyObjectPredicate, List detailsViewHelpTextProviders) { this.composedAdapterFactoryDescriptors = Objects.requireNonNull(composedAdapterFactoryDescriptors); this.feedbackMessageService = Objects.requireNonNull(feedbackMessageService); this.readOnlyObjectPredicate = Objects.requireNonNull(readOnlyObjectPredicate); + this.detailsViewHelpTextProviders = Objects.requireNonNull(detailsViewHelpTextProviders); this.importService = new ImportService(); this.elementInitializerSwitch = new ElementInitializerSwitch(); this.unsetEnumLiteral = EcoreFactory.eINSTANCE.createEEnumLiteral(); @@ -109,6 +113,14 @@ public String getDetailsViewLabel(Element element, EStructuralFeature eStructura return this.getLabelProvider().apply(element, eStructuralFeature); } + public String getDetailsViewHelpText(Element element, EStructuralFeature eStructuralFeature) { + return this.detailsViewHelpTextProviders.stream() + .filter(provider -> provider.canHandle(element, eStructuralFeature)) + .findFirst() + .map(provider -> provider.getHelpText(element, eStructuralFeature)) + .orElse(""); + } + public List getAdvancedFeatures(Element element) { List coreFeatures = new CoreFeaturesSwitch().doSwitch(element); return element.eClass().getEAllStructuralFeatures().stream().filter(feature -> !coreFeatures.contains(feature)).toList(); diff --git a/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/services/form/IsCompositeIsReferenceDetailViewHelpTextProvider.java b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/services/form/IsCompositeIsReferenceDetailViewHelpTextProvider.java new file mode 100644 index 000000000..f4333c684 --- /dev/null +++ b/backend/application/syson-application-configuration/src/main/java/org/eclipse/syson/application/services/form/IsCompositeIsReferenceDetailViewHelpTextProvider.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * 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.services.form; + +import java.util.Objects; + +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.syson.form.services.api.IDetailsViewHelpTextProvider; +import org.eclipse.syson.sysml.Element; +import org.eclipse.syson.sysml.SysmlPackage; +import org.springframework.stereotype.Service; + +/** + * Provides custom Help text for the Details view widgets of the features isComposite and isReference. + * + * @author mcharfadi + */ +@Service +public class IsCompositeIsReferenceDetailViewHelpTextProvider implements IDetailsViewHelpTextProvider { + @Override + public boolean canHandle(Element element, EStructuralFeature eStructuralFeature) { + return Objects.equals(eStructuralFeature, SysmlPackage.eINSTANCE.getFeature_IsComposite()) || + Objects.equals(eStructuralFeature, SysmlPackage.eINSTANCE.getUsage_IsReference()); + } + + @Override + public String getHelpText(Element element, EStructuralFeature eStructuralFeature) { + var helpText = ""; + if (Objects.equals(eStructuralFeature, SysmlPackage.eINSTANCE.getFeature_IsComposite())) { + helpText = "Opposite value of isReference"; + } else if (Objects.equals(eStructuralFeature, SysmlPackage.eINSTANCE.getUsage_IsReference())) { + helpText = "Opposite value of isComposite (cannot be edited, edit isComposite instead)"; + } + return helpText; + } +} diff --git a/backend/application/syson-application-configuration/src/test/java/org/eclipse/syson/application/services/DetailsViewServiceTest.java b/backend/application/syson-application-configuration/src/test/java/org/eclipse/syson/application/services/DetailsViewServiceTest.java index 130d380b3..affb81e96 100644 --- a/backend/application/syson-application-configuration/src/test/java/org/eclipse/syson/application/services/DetailsViewServiceTest.java +++ b/backend/application/syson-application-configuration/src/test/java/org/eclipse/syson/application/services/DetailsViewServiceTest.java @@ -49,7 +49,7 @@ public void setUp() { // SysON for the moment. List composedAdapterFactoryDescriptors = List.of(); this.detailsViewService = new DetailsViewService(composedAdapterFactoryDescriptors, new IFeedbackMessageService.NoOp(), - new ComposedReadOnlyObjectPredicate(List.of(new SysONReadOnlyObjectPredicateDelegate()), new DefaultReadOnlyObjectPredicate())); + new ComposedReadOnlyObjectPredicate(List.of(new SysONReadOnlyObjectPredicateDelegate()), new DefaultReadOnlyObjectPredicate()), List.of()); } @Test diff --git a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/details/view/DetailsViewControllerIntegrationTests.java b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/details/view/DetailsViewControllerIntegrationTests.java index 407c9d975..6391f075d 100644 --- a/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/details/view/DetailsViewControllerIntegrationTests.java +++ b/backend/application/syson-application/src/test/java/org/eclipse/syson/application/controllers/details/view/DetailsViewControllerIntegrationTests.java @@ -15,14 +15,20 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.eclipse.sirius.components.forms.tests.FormEventPayloadConsumer.assertRefreshedFormThat; +import com.jayway.jsonpath.JsonPath; + import java.time.Duration; import java.util.List; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import org.eclipse.sirius.components.collaborative.forms.dto.FormRefreshedEventPayload; +import org.eclipse.sirius.components.forms.Checkbox; import org.eclipse.sirius.components.forms.LabelWidget; import org.eclipse.sirius.components.forms.Textfield; +import org.eclipse.sirius.components.forms.tests.graphql.HelpTextQueryRunner; import org.eclipse.sirius.components.forms.tests.navigation.FormNavigator; import org.eclipse.sirius.web.application.views.details.dto.DetailsEventInput; import org.eclipse.sirius.web.tests.graphql.DetailsEventSubscriptionRunner; @@ -56,6 +62,9 @@ public class DetailsViewControllerIntegrationTests extends AbstractIntegrationTe @Autowired private DetailsEventSubscriptionRunner detailsEventSubscriptionRunner; + @Autowired + private HelpTextQueryRunner helpTextQueryRunner; + @Autowired private RepresentationIdBuilder representationIdBuilder; @@ -96,4 +105,71 @@ public void givenAPartUsageWhenWeSubscribeToItsPropertiesEventThenTheFormIsSent( } + @Test + @DisplayName("GIVEN a PartUsage, WHEN we request the help text, THEN the help text is send") + @Sql(scripts = { SimpleProjectElementsTestProjectData.SCRIPT_PATH }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, + config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + @Sql(scripts = { "/scripts/cleanup.sql" }, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, config = @SqlConfig(transactionMode = SqlConfig.TransactionMode.ISOLATED)) + public void givenAPartUsageWhenWeRequestHelpTextThenHelpTextIsSend() { + var detailsRepresentationId = this.representationIdBuilder.buildDetailsRepresentationId(List.of(SimpleProjectElementsTestProjectData.SemanticIds.PART_ID)); + var input = new DetailsEventInput(UUID.randomUUID(), SimpleProjectElementsTestProjectData.EDITING_CONTEXT_ID, detailsRepresentationId); + var flux = this.detailsEventSubscriptionRunner.run(input).filter(FormRefreshedEventPayload.class::isInstance); + + var isCompositeWidgetId = new AtomicReference(); + var isReferenceWidgetId = new AtomicReference(); + var isPortionWidgetId = new AtomicReference(); + Consumer formContentConsumer = assertRefreshedFormThat(form -> { + var isCompositeWidget = new FormNavigator(form).page("Advanced").group("Part Properties").findWidget("Is Composite", Checkbox.class); + var isReferenceWidget = new FormNavigator(form).page("Advanced").group("Part Properties").findWidget("Is Reference", Checkbox.class); + var isPortionWidget = new FormNavigator(form).page("Advanced").group("Part Properties").findWidget("Is Portion", Checkbox.class); + assertThat(isCompositeWidget).isNotNull(); + assertThat(isReferenceWidget).isNotNull(); + isCompositeWidgetId.set(isCompositeWidget.getId()); + isReferenceWidgetId.set(isReferenceWidget.getId()); + isPortionWidgetId.set(isPortionWidget.getId()); + }); + + Runnable requestIsCompositeHelpText = () -> { + Map variables = Map.of( + "editingContextId", SimpleProjectElementsTestProjectData.EDITING_CONTEXT_ID, + "representationId", detailsRepresentationId, + "widgetId", isCompositeWidgetId.get() + ); + var result = this.helpTextQueryRunner.run(variables); + + String helpText = JsonPath.read(result, "$.data.viewer.editingContext.representation.description.helpText"); + assertThat(helpText).isEqualTo("Opposite value of isReference"); + }; + + Runnable requestIsReferenceHelpText = () -> { + Map variables = Map.of( + "editingContextId", SimpleProjectElementsTestProjectData.EDITING_CONTEXT_ID, + "representationId", detailsRepresentationId, + "widgetId", isReferenceWidgetId.get() + ); + var result = this.helpTextQueryRunner.run(variables); + + String helpText = JsonPath.read(result, "$.data.viewer.editingContext.representation.description.helpText"); + assertThat(helpText).isEqualTo("Opposite value of isComposite (cannot be edited, edit isComposite instead)"); + }; + Runnable requestIsPortionHelpText = () -> { + Map variables = Map.of( + "editingContextId", SimpleProjectElementsTestProjectData.EDITING_CONTEXT_ID, + "representationId", detailsRepresentationId, + "widgetId", isPortionWidgetId.get() + ); + var result = this.helpTextQueryRunner.run(variables); + + String helpText = JsonPath.read(result, "$.data.viewer.editingContext.representation.description.helpText"); + assertThat(helpText).isEmpty(); + }; + + StepVerifier.create(flux) + .consumeNextWith(formContentConsumer) + .then(requestIsCompositeHelpText) + .then(requestIsReferenceHelpText) + .then(requestIsPortionHelpText) + .thenCancel() + .verify(Duration.ofSeconds(10)); + } } diff --git a/backend/services/syson-form-services/src/main/java/org/eclipse/syson/form/services/api/IDetailsViewHelpTextProvider.java b/backend/services/syson-form-services/src/main/java/org/eclipse/syson/form/services/api/IDetailsViewHelpTextProvider.java new file mode 100644 index 000000000..35bcd4d52 --- /dev/null +++ b/backend/services/syson-form-services/src/main/java/org/eclipse/syson/form/services/api/IDetailsViewHelpTextProvider.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * 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.form.services.api; + +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.syson.sysml.Element; + +/** + * Provides custom Help text for the Details view widgets. + * + * @author mcharfadi + */ +public interface IDetailsViewHelpTextProvider { + + boolean canHandle(Element element, EStructuralFeature eStructuralFeature); + + String getHelpText(Element element, EStructuralFeature eStructuralFeature); + +} diff --git a/doc/content/modules/user-manual/pages/release-notes/2026.1.0.adoc b/doc/content/modules/user-manual/pages/release-notes/2026.1.0.adoc index 8021702be..a23feb19d 100644 --- a/doc/content/modules/user-manual/pages/release-notes/2026.1.0.adoc +++ b/doc/content/modules/user-manual/pages/release-notes/2026.1.0.adoc @@ -110,6 +110,8 @@ a|image::release-notes-enumeration-definition-after.png[Enumeration definition n - In diagrams, an _items_ compartment is now available on `PortDefinition` graphical nodes to display `ItemUsage`. - In diagrams, an `ItemUsage` graphical border node is now available on `PortDefinition` graphical nodes. - In diagrams, when creating an element from a compartment, it will not be displayed by default on the diagram, but only in the compartment. +- In the _Advanced_ tab of the _Details_ view, _isComposite_ and _isReference_ properties (checkbox widgets) now have a help text. + == Technical details