/* * Copyright (c) 2014, IETR/INSA of Rennes * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the IETR/INSA of Rennes nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ package net.sf.orcc.xdf.ui.layout; import java.util.Map; import net.sf.orcc.xdf.ui.util.PropsUtil; import org.eclipse.graphiti.features.IFeatureProvider; import org.eclipse.graphiti.features.context.ICustomContext; import org.eclipse.graphiti.features.custom.AbstractCustomFeature; import org.eclipse.graphiti.mm.pictograms.Connection; import org.eclipse.graphiti.mm.pictograms.PictogramElement; import org.eclipse.graphiti.mm.pictograms.Shape; import de.cau.cs.kieler.core.alg.BasicProgressMonitor; import de.cau.cs.kieler.core.kgraph.KEdge; import de.cau.cs.kieler.core.kgraph.KGraphElement; import de.cau.cs.kieler.core.kgraph.KNode; import de.cau.cs.kieler.kiml.klayoutdata.KEdgeLayout; import de.cau.cs.kieler.kiml.klayoutdata.KShapeLayout; import de.cau.cs.kieler.kiml.options.LayoutOptions; import de.cau.cs.kieler.kiml.options.PortConstraints; import de.cau.cs.kieler.klay.layered.LayeredLayoutProvider; /** * This custom feature implements an auto-layout for any graph. It uses the * LayeredLayout algorithm from Kieler project. More information: * http://www.informatik.uni-kiel.de/en/rtsys/kieler/ * * @author Antoine Lorence * */ public class AutoLayoutFeature extends AbstractCustomFeature { private boolean hasDoneChanges; final private String layoutName; public AutoLayoutFeature(IFeatureProvider fp, final String layoutName) { super(fp); hasDoneChanges = false; this.layoutName = layoutName; } @Override public String getDescription() { return "Layout diagram with Kieler Layouter"; //$NON-NLS-1$ } @Override public String getName() { return layoutName; //$NON-NLS-1$ } @Override public boolean canExecute(ICustomContext context) { return true; } @Override public boolean hasDoneChanges() { return hasDoneChanges; } @Override public void execute(ICustomContext ctxt) { final XdfDiagramLayoutManager manager = new XdfDiagramLayoutManager(getDiagram()); configureLayout(manager.getTopLevelNode(), manager.getPeKGraphMap()); final LayeredLayoutProvider provider = new LayeredLayoutProvider(); provider.doLayout(manager.getTopLevelNode(), new BasicProgressMonitor()); manager.applyLayout(); hasDoneChanges = true; } private void configureLayout(final KNode diagramNode, final Map<PictogramElement, KGraphElement> peKnodeMap) { for (final Shape shape : getDiagram().getChildren()) { final KShapeLayout shapeLayout = ((KNode) peKnodeMap.get(shape)).getData(KShapeLayout.class); if (PropsUtil.isInstance(shape)) { if (shapeLayout != null) { configureInstanceNode(shapeLayout); } } else if (PropsUtil.isPort(shape)) { if (shapeLayout != null) { configureNetworkPortNode(shapeLayout); } } } for (final Connection connection : getDiagram().getConnections()) { final KEdgeLayout edgeLayout = ((KEdge) peKnodeMap.get(connection)).getData(KEdgeLayout.class); if (edgeLayout != null) { configureConnectionEdge(edgeLayout); } } final KShapeLayout diagramLayout = diagramNode.getData(KShapeLayout.class); if (diagramLayout != null) { configureDiagramNode(diagramLayout); } } protected void configureDiagramNode(final KShapeLayout diagramLayout) { diagramLayout.setProperty(LayoutOptions.SPACING, 30.0f); /* * Some options have been tested in the past: * * mappingShapeLayout.setProperty(Properties.NODE_LAYERING, * LayeringStrategy.LONGEST_PATH); * mappingShapeLayout.setProperty(Properties.MERGE_PORTS, true); * mappingShapeLayout.setProperty(Properties.CROSS_MIN, * CrossingMinimizationStrategy.INTERACTIVE); */ } protected void configureInstanceNode(final KShapeLayout instanceLayout) { // We never want to move port inside an Instance instanceLayout.setProperty(LayoutOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_POS); } protected void configureNetworkPortNode(final KShapeLayout portLayout) { } protected void configureConnectionEdge(final KEdgeLayout edgeLayout) { } }