Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ Also use that same tool in the `interconnection` compartment.
- https://github.com/eclipse-syson/syson/issues/2172[#2172] [diagrams] Add keybinding to the _Duplicate Element_ tool (ctrl+d).
- https://github.com/eclipse-syson/syson/issues/2166[#2166] [diagrams] Reorganize tools to create `ExhibitStateUsage` graphical nodes, to ends up with two tools, one for parallel, one for non-parallel.
Both tools optionally allow selecting an existing `StateUsage` to exhibit.
- https://github.com/eclipse-syson/syson/issues/2179[#2179] [diagrams] Improve selection dialog by regrouping all standard libraries candidates under a "Libraries" category.

=== New features

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.eclipse.sirius.components.graphql.tests.ExecuteEditingContextFunctionRunner;
import org.eclipse.sirius.components.graphql.tests.ExecuteEditingContextFunctionSuccessPayload;
import org.eclipse.sirius.components.trees.Tree;
import org.eclipse.sirius.components.trees.TreeItem;
import org.eclipse.sirius.components.view.diagram.NodeTool;
import org.eclipse.sirius.components.view.diagram.SelectionDialogDescription;
import org.eclipse.sirius.components.view.emf.diagram.IDiagramIdProvider;
Expand All @@ -73,6 +74,7 @@
import org.eclipse.syson.sysml.LibraryPackage;
import org.eclipse.syson.sysml.Namespace;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.tree.explorer.fragments.LibrariesDirectory;
import org.eclipse.syson.util.IDescriptionNameGenerator;
import org.eclipse.syson.util.SysONRepresentationDescriptionIdentifiers;
import org.eclipse.syson.util.ViewConstants;
Expand All @@ -98,6 +100,10 @@
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GVTopNodeCreationTests extends AbstractIntegrationTests {

private static final String KERML_SELECTION_DIALOG_ID = UUID.nameUUIDFromBytes("SysON_KerML_Directory".getBytes()).toString();

private static final String SYSML_SELECTION_DIALOG_ID = UUID.nameUUIDFromBytes("SysON_SysML_Directory".getBytes()).toString();

private final IDescriptionNameGenerator descriptionNameGenerator = new SDVDescriptionNameGenerator();

@Autowired
Expand Down Expand Up @@ -358,12 +364,62 @@ public void givenAnEmptySysMLProjectWhenWeSubscribeToTheSelectionDialogTreeOfThe
var input = new SelectionDialogTreeEventInput(UUID.randomUUID(), GeneralViewEmptyTestProjectData.EDITING_CONTEXT, representationId);
var treeFlux = this.selectionDialogTreeEventSubscriptionRunner.run(input).flux();

var hasResourceRootContent = this.getTreeSubscriptionConsumer(tree -> {
// 95 is the number of standard libraries
assertThat(tree.getChildren()).isNotEmpty().hasSize(95);
var hasSelectionDialogRootContent = this.getTreeSubscriptionConsumer(tree -> {
assertThat(tree.getChildren()).isNotEmpty();

TreeItem librariesItem = tree.getChildren().stream()
.filter(treeItem -> LibrariesDirectory.LIBRARIES_DIRECTORY_ID.equals(treeItem.getId()))
.findFirst()
.orElseThrow();
assertThat(librariesItem.getLabel().toString()).isEqualTo("Libraries");
assertThat(librariesItem.isEditable()).isFalse();
assertThat(librariesItem.isDeletable()).isFalse();
assertThat(librariesItem.isSelectable()).isFalse();
assertThat(librariesItem.isHasChildren()).isTrue();

assertThat(tree.getChildren()).anySatisfy(treeItem -> {
assertThat(treeItem.getId()).isEqualTo(LibrariesDirectory.LIBRARIES_DIRECTORY_ID);
assertThat(treeItem.getLabel().toString()).isEqualTo("Libraries");
});
});

var expandedRepresentationId = this.representationIdBuilder.buildSelectionRepresentationId(selectionDialogDescriptionId.get().get(), GeneralViewEmptyTestProjectData.EDITING_CONTEXT,
List.of(LibrariesDirectory.LIBRARIES_DIRECTORY_ID));
var expandedInput = new SelectionDialogTreeEventInput(UUID.randomUUID(), GeneralViewEmptyTestProjectData.EDITING_CONTEXT, expandedRepresentationId);
var expandedTreeFlux = this.selectionDialogTreeEventSubscriptionRunner.run(expandedInput).flux();

var hasExpandedLibrariesContent = this.getTreeSubscriptionConsumer(tree -> {
TreeItem librariesItem = tree.getChildren().stream()
.filter(treeItem -> LibrariesDirectory.LIBRARIES_DIRECTORY_ID.equals(treeItem.getId()))
.findFirst()
.orElseThrow();

assertThat(librariesItem.getChildren()).hasSize(2);
assertThat(librariesItem.getChildren()).anySatisfy(treeItem -> {
assertThat(treeItem.getId()).isEqualTo(KERML_SELECTION_DIALOG_ID);
assertThat(treeItem.getLabel().toString()).isEqualTo("KerML");
assertThat(treeItem.isEditable()).isFalse();
assertThat(treeItem.isDeletable()).isFalse();
assertThat(treeItem.isSelectable()).isFalse();
assertThat(treeItem.isHasChildren()).isTrue();
});
assertThat(librariesItem.getChildren()).anySatisfy(treeItem -> {
assertThat(treeItem.getId()).isEqualTo(SYSML_SELECTION_DIALOG_ID);
assertThat(treeItem.getLabel().toString()).isEqualTo("SysML");
assertThat(treeItem.isEditable()).isFalse();
assertThat(treeItem.isDeletable()).isFalse();
assertThat(treeItem.isSelectable()).isFalse();
assertThat(treeItem.isHasChildren()).isTrue();
});
});

StepVerifier.create(treeFlux)
.consumeNextWith(hasResourceRootContent)
.consumeNextWith(hasSelectionDialogRootContent)
.thenCancel()
.verify(Duration.ofSeconds(10));

StepVerifier.create(expandedTreeFlux)
.consumeNextWith(hasExpandedLibrariesContent)
.thenCancel()
.verify(Duration.ofSeconds(10));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.syson.diagram.services.utils.ViewFilterSwitch;
Expand Down Expand Up @@ -130,16 +128,7 @@ public List<ReferenceUsage> getExposedSubjects(Element element, EClass domainTyp
.toList();
}

public List<Element> getAllReachableRequirements(EObject eObject) {
List<EObject> allRequirementUsages = this.utilService.getAllReachableType(eObject, SysmlPackage.eINSTANCE.getRequirementUsage(), false);
List<EObject> allRequirementDefinitions = this.utilService.getAllReachableType(eObject, SysmlPackage.eINSTANCE.getRequirementDefinition(), false);
return Stream.concat(allRequirementUsages.stream(), allRequirementDefinitions.stream())
.filter(Element.class::isInstance)
.map(Element.class::cast)
.toList();
}

Set<Element> getDirectExposedElements(ViewUsage viewUsage) {
private Set<Element> getDirectExposedElements(ViewUsage viewUsage) {
var directExposedElements = new HashSet<Element>();
List<Expose> exposedElements = viewUsage.getOwnedRelationship().stream()
.filter(Expose.class::isInstance)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import java.util.Objects;

import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.sirius.components.collaborative.diagrams.DiagramContext;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.diagrams.Diagram;
Expand Down Expand Up @@ -79,13 +78,6 @@ public boolean canCreateFlowUsage(ConnectionUsage connection) {
return this.diagramQueryElementService.canCreateFlowUsage(connection);
}

/**
* {@link DiagramQueryExposeService#getAllReachableRequirements(EObject)}.
*/
public List<Element> getAllReachableRequirements(EObject eObject) {
return this.diagramQueryExposeService.getAllReachableRequirements(eObject);
}

/**
* {@link DiagramQueryLabelService#getBorderNodeUsageLabel(Usage)}.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright (c) 2026 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.tree.selectiondialog.services;

import org.eclipse.sirius.components.core.api.IIdentityServiceDelegate;
import org.eclipse.syson.tree.explorer.services.api.ISysONExplorerFragment;
import org.springframework.stereotype.Service;

/**
* Identity service for SelectionDialog, to handle ISysONExplorerFragment elements.
*
* @author arichard
*/
@Service
public class SysONSelectionDialogFragmentIdentityService implements IIdentityServiceDelegate {

@Override
public boolean canHandle(Object object) {
return object instanceof ISysONExplorerFragment;
}

@Override
public String getId(Object object) {
String id = null;
if (object instanceof ISysONExplorerFragment fragment) {
id = fragment.getId();
}
return id;
}

@Override
public String getKind(Object object) {
String kind = null;
if (object instanceof ISysONExplorerFragment fragment) {
kind = fragment.getKind();
}
return kind;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*******************************************************************************
* Copyright (c) 2026 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.tree.selectiondialog.services;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.sirius.components.core.api.ILabelServiceDelegate;
import org.eclipse.sirius.components.core.api.labels.StyledString;
import org.eclipse.syson.tree.explorer.services.api.ISysONExplorerFragment;
import org.springframework.stereotype.Service;

/**
* Label service for SelectionDialog, to handle ISysONExplorerFragment elements.
*
* @author arichard
*/
@Service
public class SysONSelectionDialogFragmentLabelService implements ILabelServiceDelegate {

@Override
public boolean canHandle(Object object) {
return object instanceof ISysONExplorerFragment;
}

@Override
public StyledString getStyledLabel(Object object) {
String label = "";
if (object instanceof ISysONExplorerFragment fragment) {
label = fragment.getLabel();
}
return StyledString.of(label);
}

@Override
public List<String> getImagePaths(Object object) {
List<String> imagePaths = new ArrayList<>();
if (object instanceof ISysONExplorerFragment fragment) {
imagePaths = fragment.getIconURL();
}
return imagePaths;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*******************************************************************************
* Copyright (c) 2026 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.tree.explorer.services;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.List;

import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.RepresentationMetadata;
import org.eclipse.syson.tree.explorer.services.api.ISysONExplorerFragment;
import org.eclipse.syson.tree.selectiondialog.services.SysONSelectionDialogFragmentIdentityService;
import org.eclipse.syson.tree.selectiondialog.services.SysONSelectionDialogFragmentLabelService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

/**
* Tests for selection dialog services handling {@link ISysONExplorerFragment}.
*
* @author arichard
*/
@SuppressWarnings("checkstyle:MultipleStringLiterals")
public class SysONSelectionDialogFragmentServicesTest {

@Test
@DisplayName("GIVEN a selection dialog fragment identity service, WHEN the input is a fragment or not, THEN ids and kinds are resolved with the expected fallback")
public void identityServiceHandlesFragmentsAndFallsBackForOtherObjects() {
var service = new SysONSelectionDialogFragmentIdentityService();
var fragment = new TestFragment("fragment-id", "fragment-kind", "Fragment", List.of("icons/LibraryResource.svg"));

assertThat(service.canHandle(fragment)).isTrue();
assertThat(service.canHandle("not-a-fragment")).isFalse();
assertThat(service.getId(fragment)).isEqualTo("fragment-id");
assertThat(service.getKind(fragment)).isEqualTo("fragment-kind");
assertThat(service.getId("not-a-fragment")).isNull();
assertThat(service.getKind("not-a-fragment")).isNull();
}

@Test
@DisplayName("GIVEN a selection dialog fragment label service, WHEN the input is a fragment or not, THEN labels and icons are resolved with the expected fallback")
public void labelServiceHandlesFragmentsAndFallsBackForOtherObjects() {
var service = new SysONSelectionDialogFragmentLabelService();
var fragment = new TestFragment("fragment-id", "fragment-kind", "Fragment", List.of("icons/LibraryResource.svg"));

assertThat(service.canHandle(fragment)).isTrue();
assertThat(service.canHandle("not-a-fragment")).isFalse();
assertThat(service.getStyledLabel(fragment).toString()).isEqualTo("Fragment");
assertThat(service.getImagePaths(fragment)).containsExactly("icons/LibraryResource.svg");
assertThat(service.getStyledLabel("not-a-fragment").toString()).isEmpty();
assertThat(service.getImagePaths("not-a-fragment")).isEmpty();
}

/**
* Simple {@link ISysONExplorerFragment} stub used to exercise selection dialog delegates.
*
* @author arichard
*/
private static final class TestFragment implements ISysONExplorerFragment {

private final String id;

private final String kind;

private final String label;

private final List<String> iconURL;

private TestFragment(String id, String kind, String label, List<String> iconURL) {
this.id = id;
this.kind = kind;
this.label = label;
this.iconURL = iconURL;
}

@Override
public String getId() {
return this.id;
}

@Override
public String getTooltip() {
return this.label;
}

@Override
public String getLabel() {
return this.label;
}

@Override
public String getKind() {
return this.kind;
}

@Override
public Object getParent() {
return null;
}

@Override
public List<String> getIconURL() {
return this.iconURL;
}

@Override
public boolean hasChildren(IEditingContext editingContext, List<RepresentationMetadata> existingRepresentations, List<String> expandedIds, List<String> activeFilterIds) {
return false;
}

@Override
public List<Object> getChildren(IEditingContext editingContext, List<RepresentationMetadata> existingRepresentations, List<String> expandedIds, List<String> activeFilterIds) {
return List.of();
}

@Override
public boolean isEditable() {
return false;
}

@Override
public boolean isDeletable() {
return false;
}

@Override
public boolean isSelectable() {
return true;
}
}
}
Loading
Loading