Skip to content

Commit

Permalink
[1831] Integrate a new API for layout based on DiagramLayoutData with…
Browse files Browse the repository at this point in the history
… a dummy implementation

Bug: #1831
Signed-off-by: Pierre-Charles David <[email protected]>
  • Loading branch information
pcdavid committed Mar 7, 2023
1 parent bc7bce6 commit 91a0409
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.eclipse.sirius.components.collaborative.diagrams;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
Expand All @@ -34,7 +35,9 @@
import org.eclipse.sirius.components.diagrams.description.DiagramDescription;
import org.eclipse.sirius.components.diagrams.events.ArrangeAllEvent;
import org.eclipse.sirius.components.diagrams.events.IDiagramEvent;
import org.eclipse.sirius.components.diagrams.layout.api.IDiagramLayoutEngine;
import org.eclipse.sirius.components.diagrams.layout.api.ILayoutService;
import org.eclipse.sirius.components.diagrams.layoutdata.DiagramLayoutData;
import org.eclipse.sirius.components.diagrams.renderer.DiagramRenderer;
import org.eclipse.sirius.components.representations.Element;
import org.eclipse.sirius.components.representations.IOperationValidator;
Expand Down Expand Up @@ -62,18 +65,21 @@ public class DiagramCreationService implements IDiagramCreationService {

private final ILayoutService layoutService;

private final IDiagramLayoutEngine diagramLayoutEngine;

private final IOperationValidator operationValidator;

private final Timer timer;

private final Logger logger = LoggerFactory.getLogger(DiagramCreationService.class);

public DiagramCreationService(IRepresentationDescriptionSearchService representationDescriptionSearchService, IRepresentationPersistenceService representationPersistenceService,
IObjectService objectService, ILayoutService layoutService, IOperationValidator operationValidator, MeterRegistry meterRegistry) {
IObjectService objectService, ILayoutService layoutService, IDiagramLayoutEngine diagramLayoutEngine, IOperationValidator operationValidator, MeterRegistry meterRegistry) {
this.representationDescriptionSearchService = Objects.requireNonNull(representationDescriptionSearchService);
this.representationPersistenceService = Objects.requireNonNull(representationPersistenceService);
this.objectService = Objects.requireNonNull(objectService);
this.layoutService = Objects.requireNonNull(layoutService);
this.diagramLayoutEngine = Objects.requireNonNull(diagramLayoutEngine);
this.operationValidator = Objects.requireNonNull(operationValidator);
// @formatter:off
this.timer = Timer.builder(Monitoring.REPRESENTATION_EVENT_PROCESSOR_REFRESH)
Expand Down Expand Up @@ -145,6 +151,19 @@ private Diagram doRender(String label, Object targetObject, IEditingContext edit
newDiagram = this.layoutService.incrementalLayout(editingContext, newDiagram, optionalDiagramElementEvent);
}

if (newDiagram.getLabel().endsWith("__EXPERIMENTAL")) {
DiagramLayoutData emptyLayoutData = new DiagramLayoutData(Map.of(), Map.of(), Map.of());
DiagramLayoutData newLayoutData;
// The auto layout is used for the first rendering and after that if it is activated
if (this.shouldPerformFullLayout(optionalDiagramContext, diagramDescription)) {
newLayoutData = this.diagramLayoutEngine.layout(newDiagram, emptyLayoutData, Optional.empty());
} else {
var previousLayoutData = optionalPreviousDiagram.map(Diagram::getLayoutData).orElse(emptyLayoutData);
newLayoutData = this.diagramLayoutEngine.layout(newDiagram, previousLayoutData, optionalDiagramElementEvent);
}
newDiagram = Diagram.newDiagram(newDiagram).layoutData(newLayoutData).build();
}

this.representationPersistenceService.save(editingContext, newDiagram);

long end = System.currentTimeMillis();
Expand Down Expand Up @@ -176,8 +195,8 @@ private boolean shouldPerformFullLayout(Optional<IDiagramContext> optionalDiagra
return optionalDiagramContext.isEmpty()
|| diagramDescription.isAutoLayout()
|| optionalDiagramContext.map(IDiagramContext::getDiagramEvent)
.filter(ArrangeAllEvent.class::isInstance)
.isPresent();
.filter(ArrangeAllEvent.class::isInstance)
.isPresent();
// @formatter:on
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*******************************************************************************
* Copyright (c) 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
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.components.diagrams.layout.api;

import java.util.Map;
import java.util.Optional;

import org.eclipse.sirius.components.diagrams.Diagram;
import org.eclipse.sirius.components.diagrams.events.IDiagramEvent;
import org.eclipse.sirius.components.diagrams.layoutdata.DiagramLayoutData;

/**
* Used to layout diagrams.
*
* @author pcdavid
*/
public interface IDiagramLayoutEngine {
/**
* Computes the new layout to be used for a diagram and its content.
*
* @param diagram
* the diagram's structure (nodes, edges, etc.).
* @param previousLayoutData
* the layout data from the previous version of the diagram. This may be empty for the initial layout or
* for a "full" layout.
* @param optionalEvent
* if the (incremental) layout was triggered by a user operation (e.g. the invocation of a tool at a
* specific position) the corresponding event with the information relevant for the layout will be
* available here.
* @return the layout information to be used for the new version of the diagram.
*/
DiagramLayoutData layout(Diagram diagram, DiagramLayoutData previousLayoutData, Optional<IDiagramEvent> optionalDiagramEvent);

/**
* Implementation which does nothing, used for mocks in unit tests.
*
* @author pcdavid
*/
class NoOp implements IDiagramLayoutEngine {

@Override
public DiagramLayoutData layout(Diagram diagram, DiagramLayoutData previousLayoutData, Optional<IDiagramEvent> optionalDiagramEvent) {
return Optional.ofNullable(previousLayoutData).orElse(new DiagramLayoutData(Map.of(), Map.of(), Map.of()));
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*******************************************************************************
* Copyright (c) 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
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.components.diagrams.layout.experimental;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import org.eclipse.sirius.components.diagrams.Diagram;
import org.eclipse.sirius.components.diagrams.Node;
import org.eclipse.sirius.components.diagrams.events.IDiagramEvent;
import org.eclipse.sirius.components.diagrams.events.MoveEvent;
import org.eclipse.sirius.components.diagrams.layout.api.IDiagramLayoutEngine;
import org.eclipse.sirius.components.diagrams.layoutdata.DiagramLayoutData;
import org.eclipse.sirius.components.diagrams.layoutdata.NodeLayoutData;
import org.eclipse.sirius.components.diagrams.layoutdata.Position;
import org.eclipse.sirius.components.diagrams.layoutdata.Size;
import org.springframework.stereotype.Service;

/**
* The new layout engine.
*
* @author pcdavid
*/
@Service
public class DiagramLayoutEngine implements IDiagramLayoutEngine {
@Override
public DiagramLayoutData layout(Diagram diagram, DiagramLayoutData previousLayoutData, Optional<IDiagramEvent> optionalDiagramEvent) {
Map<String, NodeLayoutData> nodeLayoutData = new HashMap<>();

int i = 0;
for (Node node : diagram.getNodes()) {
String nodeId = node.getId();
NodeLayoutData defaultNodeLayout = new NodeLayoutData(nodeId, new Position(50.0 * i, 0.0), new Size(40, 40));
NodeLayoutData nodeLayout = previousLayoutData.nodeLayoutData().getOrDefault(nodeId, defaultNodeLayout);
nodeLayoutData.put(nodeId, nodeLayout);
i++;
}

optionalDiagramEvent.filter(MoveEvent.class::isInstance).map(MoveEvent.class::cast).ifPresent(moveEvent -> {
if (nodeLayoutData.containsKey(moveEvent.nodeId())) {
org.eclipse.sirius.components.diagrams.Position newPosition = moveEvent.newPosition();
NodeLayoutData data = nodeLayoutData.get(moveEvent.nodeId());
nodeLayoutData.put(data.id(), new NodeLayoutData(data.id(), new Position(newPosition.getX(), newPosition.getY()), data.size()));
}
});

return new DiagramLayoutData(nodeLayoutData, previousLayoutData.edgeLayoutData(), previousLayoutData.labelLayoutData());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.eclipse.sirius.components.core.api.IObjectService;
import org.eclipse.sirius.components.core.api.IRepresentationDescriptionSearchService;
import org.eclipse.sirius.components.diagrams.Diagram;
import org.eclipse.sirius.components.diagrams.layout.api.IDiagramLayoutEngine;
import org.eclipse.sirius.components.diagrams.layout.api.ILayoutService;
import org.eclipse.sirius.components.emf.services.EditingContext;
import org.eclipse.sirius.components.emf.services.JSONResourceFactory;
Expand Down Expand Up @@ -158,7 +159,7 @@ public Optional<IRepresentationDescription> findById(IEditingContext editingCont
IObjectService objectService = new IObjectService.NoOp();
ILayoutService layoutService = new ILayoutService.NoOp();
MeterRegistry meterRegistry = new SimpleMeterRegistry();
var diagramCreationService = new DiagramCreationService(representationDescriptionSearchService, new IRepresentationPersistenceService.NoOp(), objectService, layoutService, new IOperationValidator.NoOp(), meterRegistry);
var diagramCreationService = new DiagramCreationService(representationDescriptionSearchService, new IRepresentationPersistenceService.NoOp(), objectService, layoutService, new IDiagramLayoutEngine.NoOp(), new IOperationValidator.NoOp(), meterRegistry);

IEditingContext editinContext = new IEditingContext.NoOp();

Expand Down

0 comments on commit 91a0409

Please sign in to comment.