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
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ Make sure diagnostics are sorted according to their validated element and its co
- https://github.com/eclipse-syson/syson/issues/2057[#2057] [diagrams] Add the support for empty value for multiplicity in the ANTLR grammar.
- https://github.com/eclipse-syson/syson/issues/2053[#2053] [diagrams] The graphical `ForkNode` and `JoinNode` now use `RectangularNodeStyleDescription` and are restricted to horizontal resizing.
Consequently, their entire footprint is filled with black, ensuring that all incoming and outgoing edges maintain a valid connection point.
- https://github.com/eclipse-syson/syson/issues/2085[#2085] [views-explorer] Adapt views explorer to group diagram representations by view definition.


=== New features

Expand Down
2 changes: 1 addition & 1 deletion backend/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

<groupId>org.eclipse.syson</groupId>
<artifactId>syson-application-parent</artifactId>
<version>2026.1.5</version>
<version>2026.1.6</version>

<name>syson-application-parent</name>
<description>SysON Application Parent</description>
Expand Down
20 changes: 10 additions & 10 deletions backend/application/syson-application-configuration/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</parent>
<groupId>org.eclipse.syson</groupId>
<artifactId>syson-application-configuration</artifactId>
<version>2026.1.5</version>
<version>2026.1.6</version>
<name>syson-application-configuration</name>
<description>SysON Application Configuration</description>

Expand Down Expand Up @@ -69,42 +69,42 @@
<dependency>
<groupId>org.eclipse.syson</groupId>
<artifactId>syson-sysml-metamodel</artifactId>
<version>2026.1.5</version>
<version>2026.1.6</version>
</dependency>
<dependency>
<groupId>org.eclipse.syson</groupId>
<artifactId>syson-sysml-metamodel-edit</artifactId>
<version>2026.1.5</version>
<version>2026.1.6</version>
</dependency>
<dependency>
<groupId>org.eclipse.syson</groupId>
<artifactId>syson-services</artifactId>
<version>2026.1.5</version>
<version>2026.1.6</version>
</dependency>
<dependency>
<groupId>org.eclipse.syson</groupId>
<artifactId>syson-model-services</artifactId>
<version>2026.1.5</version>
<version>2026.1.6</version>
</dependency>
<dependency>
<groupId>org.eclipse.syson</groupId>
<artifactId>syson-form-services</artifactId>
<version>2026.1.5</version>
<version>2026.1.6</version>
</dependency>
<dependency>
<groupId>org.eclipse.syson</groupId>
<artifactId>syson-diagram-services</artifactId>
<version>2026.1.5</version>
<version>2026.1.6</version>
</dependency>
<dependency>
<groupId>org.eclipse.syson</groupId>
<artifactId>syson-siriusweb-customnodes-metamodel</artifactId>
<version>2026.1.5</version>
<version>2026.1.6</version>
</dependency>
<dependency>
<groupId>org.eclipse.syson</groupId>
<artifactId>syson-siriusweb-customnodes-metamodel-edit</artifactId>
<version>2026.1.5</version>
<version>2026.1.6</version>
</dependency>
<!-- Test Dependencies -->
<dependency>
Expand All @@ -120,7 +120,7 @@
<dependency>
<groupId>org.eclipse.syson</groupId>
<artifactId>syson-tests</artifactId>
<version>2026.1.5</version>
<version>2026.1.6</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*******************************************************************************
* 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.application.views.explorer;

import java.util.AbstractMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.IObjectSearchService;
import org.eclipse.sirius.components.core.api.IURLParser;
import org.eclipse.sirius.components.diagrams.description.DiagramDescription;
import org.eclipse.sirius.components.representations.IRepresentationDescription;
import org.eclipse.sirius.web.application.views.viewsexplorer.services.RepresentationDescriptionType;
import org.eclipse.sirius.web.application.views.viewsexplorer.services.RepresentationKind;
import org.eclipse.sirius.web.application.views.viewsexplorer.services.api.IViewsExplorerContentServiceDelegate;
import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.RepresentationMetadata;
import org.eclipse.syson.sysml.ViewDefinition;
import org.eclipse.syson.sysml.ViewUsage;
import org.springframework.stereotype.Service;

/**
* Customize the retrieval of the content of the views explorer for SysON.
*
* @author frouene
*/
@Service
public class SysONViewsExplorerContentServiceDelegate implements IViewsExplorerContentServiceDelegate {

private final IURLParser urlParser;

private final IObjectSearchService objectSearchService;

public SysONViewsExplorerContentServiceDelegate(IURLParser urlParser, IObjectSearchService objectSearchService) {
this.urlParser = Objects.requireNonNull(urlParser);
this.objectSearchService = Objects.requireNonNull(objectSearchService);
}

@Override
public boolean canHandle(IEditingContext editingContext) {
return true;
}

@Override
public List<RepresentationKind> getContents(IEditingContext editingContext, List<RepresentationMetadata> representationMetadata, Map<String, IRepresentationDescription> representationDescriptions) {
var descriptionTypes = this.groupByDescriptionType(editingContext, representationMetadata, representationDescriptions);
return this.groupByKind(descriptionTypes);
}

private List<RepresentationDescriptionType> groupByDescriptionType(IEditingContext editingContext, List<RepresentationMetadata> allMetadata,
Map<String, IRepresentationDescription> allDescriptions) {
var metadataToViewDefinitionMap = allMetadata.stream()
.flatMap(metadata ->
this.objectSearchService.getObject(editingContext, metadata.getTargetObjectId())
.stream()
.filter(ViewUsage.class::isInstance)
.map(ViewUsage.class::cast)
.map(ViewUsage::getViewDefinition)
.map(viewDefinition -> new AbstractMap.SimpleEntry<>(metadata, viewDefinition))
)
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(existing, replacement) -> existing
));

Map<ViewDefinition, List<RepresentationMetadata>> viewDefinitionToMetadataMap = allMetadata.stream()
.collect(Collectors.groupingBy(metadataToViewDefinitionMap::get));

return viewDefinitionToMetadataMap.entrySet().stream()
.map(entry -> {
ViewDefinition viewDefinition = entry.getKey();
String viewDefinitionName = viewDefinition.getDeclaredShortName();
RepresentationMetadata firstMetadata = entry.getValue().get(0);
String descriptionId = firstMetadata.getDescriptionId();
IRepresentationDescription representationDescription = allDescriptions.get(descriptionId);

return Optional.ofNullable(representationDescription)
.map(rd -> {
if (rd instanceof DiagramDescription) {
return new RepresentationDescriptionType(viewDefinitionName, rd, entry.getValue());
}
return new RepresentationDescriptionType(descriptionId, rd, entry.getValue());
});
})
.flatMap(Optional::stream)
.toList();
}

private List<RepresentationKind> groupByKind(List<RepresentationDescriptionType> descriptionTypes) {
return descriptionTypes.stream()
.collect(Collectors.groupingBy(descType -> descType.representationsMetadata().get(0).getKind()))
.entrySet().stream()
.map(entry -> {
var kindId = entry.getKey();
var kindName = this.urlParser.getParameterValues(kindId).get("type").get(0);
return new RepresentationKind(kindId, kindName, entry.getValue());
})
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*******************************************************************************
* 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.application.views.explorer;

import java.util.List;
import java.util.Objects;

import org.eclipse.sirius.components.collaborative.trees.api.IRenameTreeItemHandler;
import org.eclipse.sirius.components.core.api.IEditingContext;
import org.eclipse.sirius.components.core.api.ILabelService;
import org.eclipse.sirius.components.core.api.IReadOnlyObjectPredicate;
import org.eclipse.sirius.components.core.api.labels.StyledString;
import org.eclipse.sirius.components.core.api.labels.StyledStringFragment;
import org.eclipse.sirius.components.core.api.labels.StyledStringFragmentStyle;
import org.eclipse.sirius.components.diagrams.description.DiagramDescription;
import org.eclipse.sirius.components.representations.Failure;
import org.eclipse.sirius.components.representations.IStatus;
import org.eclipse.sirius.components.trees.Tree;
import org.eclipse.sirius.components.trees.TreeItem;
import org.eclipse.sirius.web.application.views.viewsexplorer.services.RepresentationDescriptionType;
import org.eclipse.sirius.web.application.views.viewsexplorer.services.RepresentationKind;
import org.eclipse.sirius.web.application.views.viewsexplorer.services.api.IViewsExplorerLabelServiceDelegate;
import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.RepresentationMetadata;
import org.eclipse.sirius.web.domain.services.api.IMessageService;
import org.eclipse.syson.util.StandardDiagramsConstants;
import org.springframework.stereotype.Service;

/**
* Provide the behavior of the views explorer fro SysON.
*
* @author frouene
*/
@Service
public class SysONViewsExplorerLabelServiceDelegate implements IViewsExplorerLabelServiceDelegate {

private final IReadOnlyObjectPredicate readOnlyObjectPredicate;

private final List<IRenameTreeItemHandler> renameTreeItemHandlers;

private final ILabelService labelService;

private final IMessageService messageService;

public SysONViewsExplorerLabelServiceDelegate(IReadOnlyObjectPredicate readOnlyObjectPredicate, List<IRenameTreeItemHandler> renameTreeItemHandlers, ILabelService labelService, IMessageService messageService) {
this.readOnlyObjectPredicate = Objects.requireNonNull(readOnlyObjectPredicate);
this.renameTreeItemHandlers = Objects.requireNonNull(renameTreeItemHandlers);
this.labelService = Objects.requireNonNull(labelService);
this.messageService = Objects.requireNonNull(messageService);
}
@Override
public boolean canHandle(IEditingContext editingContext) {
return true;
}

@Override
public boolean isEditable(Object self) {
return !this.readOnlyObjectPredicate.test(self) && self instanceof RepresentationMetadata;
}

@Override
public StyledString getLabel(Object self) {
var result = StyledString.of("");
if (self instanceof RepresentationKind kind) {
String name = kind.name();
String size = String.valueOf(kind.representationDescriptionTypes().stream().mapToLong(descType -> descType.representationsMetadata().size()).sum());
result = this.getColoredLabel(name, size);
} else if (self instanceof RepresentationDescriptionType descriptionType) {
String name = descriptionType.description().getLabel();
if (descriptionType.description() instanceof DiagramDescription) {
name = StandardDiagramsConstants.getValueFromShortName(descriptionType.id());
}
String size = String.valueOf(descriptionType.representationsMetadata().size());
result = this.getColoredLabel(name, size);
} else {
result = this.labelService.getStyledLabel(self);
}
return result;
}

@Override
public IStatus editLabel(IEditingContext editingContext, Tree tree, TreeItem treeItem, String newValue) {
var optionalHandler = this.renameTreeItemHandlers.stream()
.filter(handler -> handler.canHandle(editingContext, treeItem, newValue))
.findFirst();

if (optionalHandler.isPresent()) {
IRenameTreeItemHandler renameTreeItemHandler = optionalHandler.get();
return renameTreeItemHandler.handle(editingContext, treeItem, newValue, tree);
}

return new Failure(this.messageService.failedToRename());
}

private StyledString getColoredLabel(String label, String size) {
return new StyledString(List.of(
new StyledStringFragment("%s (%s)".formatted(label.toUpperCase(), size), StyledStringFragmentStyle.newDefaultStyledStringFragmentStyle()
.foregroundColor("#261E588A")
.build())
));
}
}
Loading
Loading