Skip to content

Commit

Permalink
[2388] Add support for image overlay
Browse files Browse the repository at this point in the history
Bug: #2388
Signed-off-by: Florian ROUËNÉ <florian.rouene@obeosoft.com>
  • Loading branch information
frouene authored and pcdavid committed Oct 30, 2023
1 parent 864d905 commit 7c51f40
Show file tree
Hide file tree
Showing 234 changed files with 2,077 additions and 1,592 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

=== Architectural decision records

- [ADR-111] Add support for image overlay

=== Breaking changes

Expand All @@ -29,6 +30,7 @@ For example, Diagram & Form domains are not root domains because `DiagramDescrip
- https://github.com/eclipse-sirius/sirius-web/issues/1712[#1712] [diagram] The GraphQL type `Node` must now implement `isLabelEditable` boolean field.
- https://github.com/eclipse-sirius/sirius-web/issues/2456[#2456] [sirius-web] The GraphQL field `CreateChildSuccessPayload` now expects to have a list of messages.
- https://github.com/eclipse-sirius/sirius-web/issues/1982[#1982] [diagram] Change the diagram structure. The Node's 'label' attribute has been renamed into 'insideLabel' and its type changed from `Label` to `InsideLabel` (which is currently identical to `Label` except for the name).
- https://github.com/eclipse-sirius/sirius-web/issues/2388[#2388] [core] The `IObjectService.getImagePath` API changed and now must return a list containing all the image paths to compose/overlay.

=== Dependency update

Expand Down Expand Up @@ -75,6 +77,9 @@ This coupling will be removed in the near future as a consequence, the dependenc
- https://github.com/eclipse-sirius/sirius-web/issues/2475[#2475] [diagram] Prevent nodes to move each diagram refresh event. Only the size is still updated.
- https://github.com/eclipse-sirius/sirius-web/issues/2485[#2485] [view] Change the default size of View Node Description from 1x1 to 150x70.
- https://github.com/eclipse-sirius/sirius-web/issues/2493[2493] [diagram] Disable double click to zoom in with ReactFlow.
- https://github.com/eclipse-sirius/sirius-web/issues/2388[#2388] [core] Added support for image overlay in icons.
All icons can now be composed of multiple images, which will be overlayed on top of each other.
An example of use has been added on the domain entity items.

== v2023.10.0

Expand Down Expand Up @@ -134,6 +139,8 @@ They are loaded in every studio project but hidden in the explorer.
They are also made readonly in the details view.
Applications derived from Sirius Web may have to ensure that references to default colors are properly resolved when loading a view model.
- https://github.com/eclipse-sirius/sirius-web/issues/2191[#2191] [view] The Color property on ImageNodeStyle has been removed.
- https://github.com/eclipse-sirius/sirius-web/issues/2388[#2388] [tree] `treeItem` is no longer composed of a single string for the imageURL, but of a list of strings to take into account composite images.
The `IObjectService.getImagePath` API changed and now must return a list containing all the image paths.

=== Dependency update

Expand Down
34 changes: 34 additions & 0 deletions doc/adrs/111_add_support_for_image_overlay.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
= ADR-111 - Add support for image overlay

== Context

Despite the fact that more than one image can be contribute for an EMF label, only the first one is displayed on the UI.
So it's not possible for a specifier to build icons composed of several layers.

== Decision

* Change the `IObjectService` methode `getImagePath` to no longer return a single _string_ but the list of all the image paths.
* Change all the `.graphql` schemas to no longer support single _string_ but an array of _string_.
* Change the image rendering to merge all the image layers into one _div_ where:

```css
imageContainer: {
position: 'relative',
},

image: {
position: 'absolute',
top: 0,
left: 0,
},
```

On each layer apply the CSS properties _z-index_ to guarantee the render order.

== Status

Accepted

== Consequences

* All API with `iconURL` will be modified to use an array of _string_ from now on.
2 changes: 1 addition & 1 deletion integration-tests/cypress/e2e/project/edit/diagram.cy.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*******************************************************************************
* Copyright (c) 2021, 2023 Obeo.
* This program and the accompanying materials
* are made available under the erms of the Eclipse Public License v2.0
* 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/
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2022 Obeo.
* Copyright (c) 2019, 2023 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
Expand Down Expand Up @@ -60,12 +60,9 @@ public ToolImageProvider(IObjectService objectService, EPackage.Registry ePackag
}

@Override
public String getImage(AbstractToolDescription abstractToolDescription) {
// @formatter:off
return this.getImagePathFromIconPath(abstractToolDescription)
.or(() -> this.getImagePathFromDomainClass(abstractToolDescription))
.orElse("");
// @formatter:on
public List<String> getIcon(AbstractToolDescription abstractToolDescription) {
var optionalImagePathFromIconPath = this.getImagePathFromIconPath(abstractToolDescription);
return optionalImagePathFromIconPath.map(List::of).orElseGet(() -> this.getImagePathFromDomainClass(abstractToolDescription));
}

private Optional<String> getImagePathFromIconPath(AbstractToolDescription abstractToolDescription) {
Expand Down Expand Up @@ -96,17 +93,15 @@ private String normalize(String iconPath) {
return path;
}

private Optional<String> getImagePathFromDomainClass(AbstractToolDescription abstractToolDescription) {
// @formatter:off
private List<String> getImagePathFromDomainClass(AbstractToolDescription abstractToolDescription) {
var optionalInstance = this.getMappings(abstractToolDescription).stream()
.map(this::getDomainClass)
.flatMap(Optional::stream)
.filter(domainClass -> !domainClass.isBlank())
.findFirst()
.flatMap(this::getInstance);
// @formatter:on

return optionalInstance.map(instance -> this.objectService.getImagePath(optionalInstance.get()));
return optionalInstance.map(this.objectService::getImagePath).orElse(List.of());
}

private List<DiagramElementMapping> getMappings(AbstractToolDescription abstractToolDescription) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ private ReferenceWidgetDescription getReferenceWidgetDescription() {
.idProvider(new WidgetIdProvider())
.labelProvider(this.getLabelProvider())
.optionsProvider(this.getOptionsProvider())
.iconURLProvider(variableManager -> "")
.iconURLProvider(variableManager -> List.of())
.itemsProvider(this::getReferenceValue)
.itemIdProvider(this::getItemId)
.itemKindProvider(this::getItemKind)
Expand Down Expand Up @@ -164,8 +164,8 @@ private String getItemLabel(VariableManager variableManager) {
return this.getItem(variableManager).map(this.objectService::getLabel).orElse("");
}

private String getItemIconURL(VariableManager variableManager) {
return this.getItem(variableManager).map(this.objectService::getImagePath).orElse("");
private List<String> getItemIconURL(VariableManager variableManager) {
return this.getItem(variableManager).map(this.objectService::getImagePath).orElse(List.of());
}

private String getItemKind(VariableManager variableManager) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public void testEdgeFromNodeToContainer() {
IIdentifierProvider identifierProvider = new IIdentifierProvider.NoOp() {
@Override
public String getIdentifier(Object element) {
return containerMappingUUID.toString();
return containerMappingUUID;
}
};
ISemanticCandidatesProviderFactory semanticCandidatesProviderFactory = SemanticCandidatesProvider::new;
Expand All @@ -98,10 +98,10 @@ private NodeDescription createNodeDescription(String id) {
.italicProvider(variableManager -> false)
.underlineProvider(variableManager -> false)
.strikeThroughProvider(variableManager -> false)
.iconURLProvider(variableManager -> "")
.iconURLProvider(variableManager -> List.of())
.build();

LabelDescription labelDescription = LabelDescription.newLabelDescription(id.toString())
LabelDescription labelDescription = LabelDescription.newLabelDescription(id)
.idProvider(variableManager -> "")
.textProvider(variableManager -> "")
.styleDescriptionProvider(variableManager -> styleDescription)
Expand Down Expand Up @@ -151,7 +151,7 @@ public void testEdgeFromContainerToNode() {
IIdentifierProvider identifierProvider = new IIdentifierProvider.NoOp() {
@Override
public String getIdentifier(Object element) {
return containerMappingUUID.toString();
return containerMappingUUID;
}
};
ISemanticCandidatesProviderFactory semanticCandidatesProviderFactory = SemanticCandidatesProvider::new;
Expand Down Expand Up @@ -191,7 +191,7 @@ public void testEdgeFromContainerToContainer() {
IIdentifierProvider identifierProvider = new IIdentifierProvider.NoOp() {
@Override
public String getIdentifier(Object element) {
return targetContainerMappingUUID.toString();
return targetContainerMappingUUID;
}
};
ISemanticCandidatesProviderFactory semanticCandidatesProviderFactory = SemanticCandidatesProvider::new;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2022 Obeo.
* Copyright (c) 2019, 2023 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
Expand All @@ -14,6 +14,8 @@

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

import java.util.List;

import org.eclipse.emf.ecore.EPackage;
import org.eclipse.sirius.components.compatibility.emf.diagrams.ToolImageProvider;
import org.eclipse.sirius.components.core.api.IObjectService;
Expand All @@ -40,8 +42,9 @@ public void testIconPathNormalization() {
EPackage.Registry ePackageRegistry = EPackage.Registry.INSTANCE;
ToolImageProvider toolImageProvider = new ToolImageProvider(objectService, ePackageRegistry);

String convertedIconPath = toolImageProvider.getImage(toolDescription);
assertThat(convertedIconPath.equals(ICON_PATH.substring(ICON_PATH.indexOf('/', 1)))).isTrue();
List<String> convertedIconPath = toolImageProvider.getIcon(toolDescription);
assertThat(convertedIconPath).hasSize(1);
assertThat(convertedIconPath.get(0).equals(ICON_PATH.substring(ICON_PATH.indexOf('/', 1)))).isTrue();
}

@Test
Expand All @@ -53,7 +56,8 @@ public void testIconNormalization() {
EPackage.Registry ePackageRegistry = EPackage.Registry.INSTANCE;
ToolImageProvider toolImageProvider = new ToolImageProvider(objectService, ePackageRegistry);

String convertedIconPath = toolImageProvider.getImage(operationAction);
assertThat(convertedIconPath.equals(ICON_PATH.substring(ICON_PATH.indexOf('/', 1)))).isTrue();
List<String> convertedIconPath = toolImageProvider.getIcon(operationAction);
assertThat(convertedIconPath).hasSize(1);
assertThat(convertedIconPath.get(0).equals(ICON_PATH.substring(ICON_PATH.indexOf('/', 1)))).isTrue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ private NodeDescription getNodeDescription(String nodeDescriptionId) {
.italicProvider(variableManager -> false)
.underlineProvider(variableManager -> false)
.strikeThroughProvider(variableManager -> false)
.iconURLProvider(variableManager -> "")
.iconURLProvider(variableManager -> List.of())
.build();

LabelDescription labelDescription = LabelDescription.newLabelDescription("labelDescriptionId")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public void initialize() {
.position(Position.at(0, 0))
.size(Size.of(10, 10))
.alignment(Position.at(0, 0))
.style(LabelStyle.newLabelStyle().color("").fontSize(0).iconURL("").build())
.style(LabelStyle.newLabelStyle().color("").fontSize(0).iconURL(List.of()).build())
.build())
.style(ImageNodeStyle.newImageNodeStyle().imageURL("").scalingFactor(0).build())
.position(Position.at(0, 0))
Expand Down Expand Up @@ -170,7 +170,7 @@ private NodeDescription getNodeDescription(String nodeDescriptionId) {
.italicProvider(variableManager -> false)
.underlineProvider(variableManager -> false)
.strikeThroughProvider(variableManager -> false)
.iconURLProvider(variableManager -> "")
.iconURLProvider(variableManager -> List.of())
.build();

LabelDescription labelDescription = LabelDescription.newLabelDescription("labelDescriptionId")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2022 Obeo.
* Copyright (c) 2019, 2023 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
Expand Down Expand Up @@ -28,6 +28,7 @@
* @author hmarchadour
*/
public class LabelStyleDescriptionConverter {

private final AQLInterpreter interpreter;

private final IObjectService objectService;
Expand All @@ -40,22 +41,20 @@ public LabelStyleDescriptionConverter(AQLInterpreter interpreter, IObjectService
public LabelStyleDescription convert(org.eclipse.sirius.viewpoint.description.style.BasicLabelStyleDescription labelStyleDescription) {
List<FontFormat> fontFormats = labelStyleDescription.getLabelFormat();

Function<VariableManager, String> iconURLProvider = (variableManager) -> {
String iconURL = "";
Function<VariableManager, List<String>> iconURLProvider = (variableManager) -> {
List<String> iconURL = List.of();
if (labelStyleDescription.isShowIcon()) {
// @formatter:off
String iconPath = labelStyleDescription.getIconPath();
if (iconPath != null && !iconPath.isEmpty()) {
int indexOfSecondSlash = iconPath.indexOf('/', 1);
if (indexOfSecondSlash != -1) {
iconURL = iconPath.substring(indexOfSecondSlash);
iconURL = List.of(iconPath.substring(indexOfSecondSlash));
}
} else {
iconURL = variableManager.get(VariableManager.SELF, Object.class)
.map(this.objectService::getImagePath)
.orElse("");
.orElse(List.of());
}
// @formatter:on
}
return iconURL;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public SelectionDescription convert(SelectModelElementVariable selectModelElemen
})
.idProvider(new GetOrCreateRandomIdProvider())
.labelProvider(variableManager -> variableManager.get(VariableManager.SELF, Object.class).map(this.objectService::getLabel).orElse(null))
.iconURLProvider(variableManager -> variableManager.get(VariableManager.SELF, Object.class).map(this.objectService::getImagePath).orElse(null))
.iconURLProvider(variableManager -> variableManager.get(VariableManager.SELF, Object.class).map(this.objectService::getImagePath).orElse(List.of()))
.targetObjectIdProvider(variableManager -> variableManager.get(VariableManager.SELF, Object.class).map(this.objectService::getId).orElse(null))
.selectionObjectsIdProvider(variableManager -> variableManager.get(VariableManager.SELF, Object.class).map(this.objectService::getId).orElse(null))
.label("Selection Description")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ private SelectDescription convertSelect(org.eclipse.sirius.properties.SelectDesc
.optionsProvider(optionsProvider)
.optionIdProvider(optionIdProvider)
.optionLabelProvider(optionLabelProvider)
.optionIconURLProvider(vm -> "")
.optionIconURLProvider(vm -> List.of())
.newValueHandler(newValueHandler)
.diagnosticsProvider(variableManager -> List.of())
.kindProvider(object -> "")
Expand Down

0 comments on commit 7c51f40

Please sign in to comment.