diff options
Diffstat (limited to 'plugins/org.eclipse.etrice.ui.layout/src/org')
4 files changed, 977 insertions, 0 deletions
diff --git a/plugins/org.eclipse.etrice.ui.layout/src/org/eclipse/etrice/ui/layout/BehaviorDiagramLayoutManager.java b/plugins/org.eclipse.etrice.ui.layout/src/org/eclipse/etrice/ui/layout/BehaviorDiagramLayoutManager.java new file mode 100644 index 000000000..63329e1b2 --- /dev/null +++ b/plugins/org.eclipse.etrice.ui.layout/src/org/eclipse/etrice/ui/layout/BehaviorDiagramLayoutManager.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Jayant Gupta (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.ui.layout; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.etrice.core.room.StateGraph; +import org.eclipse.etrice.core.room.TrPoint; +import org.eclipse.etrice.ui.behavior.editor.BehaviorEditor; +import org.eclipse.etrice.ui.behavior.support.StateSupport; +import org.eclipse.graphiti.mm.pictograms.Anchor; +import org.eclipse.graphiti.mm.pictograms.Diagram; +import org.eclipse.graphiti.mm.pictograms.PictogramElement; +import org.eclipse.graphiti.mm.pictograms.Shape; +import org.eclipse.graphiti.ui.internal.parts.IPictogramElementEditPart; + +import de.cau.cs.kieler.core.kgraph.KNode; +import de.cau.cs.kieler.kiml.LayoutContext; +import de.cau.cs.kieler.kiml.config.VolatileLayoutConfig; +import de.cau.cs.kieler.kiml.graphiti.KimlGraphitiUtil; +import de.cau.cs.kieler.kiml.options.LayoutOptions; +import de.cau.cs.kieler.kiml.ui.diagram.LayoutMapping; +import de.cau.cs.kieler.kiml.util.KimlUtil; + +/** + * Layout Manager implementation for eTrice Structure Editor. + * + * @author jayant + */ +@SuppressWarnings("restriction") +public class BehaviorDiagramLayoutManager extends ETriceDiagramLayoutManager { + + /** + * {@inheritDoc} + * + * @author jayant + */ + @Override + public boolean supports(final Object object) { + + return object instanceof BehaviorEditor + || object instanceof IPictogramElementEditPart + || object instanceof PictogramElement; + + } + + /** + * {@inheritDoc} + * + * @author jayant + */ + @Override + protected void buildLayoutGraphForBoundingBox( + LayoutMapping<PictogramElement> mapping, Diagram diagram, + KNode diagramNode, boolean onlyVisible) { + + if (onlyVisible) { + for (Shape boundingBox : ((Diagram) diagram).getChildren()) { + if (boundingBox.isVisible()) { + buildAllLevels(mapping, boundingBox, diagramNode); + break; + } + } + } else { + // This happens when the user requests Layout of the whole hierarchy + // of Diagrams in the behavior editor + // FIXME need to be corrected. + for (Shape boundingBox : ((Diagram) diagram).getChildren()) + buildAllLevels(mapping, boundingBox, diagramNode); + } + + } + + /** the fixed minimal height of nodes. */ + public static final float MIN_HEIGHT = StateSupport.DEFAULT_SIZE_Y; + /** the fixed minimal width of shapes. */ + public static final float MIN_WIDHT = StateSupport.DEFAULT_SIZE_X; + + /** + * {@inheritDoc} + * + * @author jayant + */ + protected KNode createNode(final LayoutMapping<PictogramElement> mapping, + final KNode parentNode, final Shape shape) { + KNode node = KimlUtil.createInitializedNode(); + node.setParent(parentNode); + + setCurrentPositionAndSize(mapping, parentNode, node, shape); + + VolatileLayoutConfig staticConfig = mapping + .getProperty(KimlGraphitiUtil.STATIC_CONFIG); + // FIXME find a way to specify the minimal size dynamically + + staticConfig.setValue(LayoutOptions.MIN_WIDTH, node, + LayoutContext.GRAPH_ELEM, MIN_WIDHT); + staticConfig.setValue(LayoutOptions.MIN_HEIGHT, node, + LayoutContext.GRAPH_ELEM, MIN_HEIGHT); + + mapping.getGraphMap().put(node, shape); + + // gather all connections directly connected to the Node (not the + // connections connected via ports). These only exist in the behavior + // editor. + for (Anchor anchor : shape.getAnchors()) { + mapping.getProperty(KimlGraphitiUtil.CONNECTIONS).addAll( + anchor.getOutgoingConnections()); + } + + return node; + } + + + + /** + * {@inheritDoc} + * + * @author jayant + */ + @Override + protected boolean isPort(Shape shape) { + EObject modelObject = shape.getLink().getBusinessObjects().get(0); + if (modelObject instanceof TrPoint) + return true; + + return false; + } + + /** + * {@inheritDoc} + * + * @author jayant + */ + @Override + protected boolean isTopLevelBoundingBox(Shape shape) { + EObject modelObject = shape.getLink().getBusinessObjects().get(0); + if (modelObject instanceof StateGraph) + return true; + + return false; + } +} diff --git a/plugins/org.eclipse.etrice.ui.layout/src/org/eclipse/etrice/ui/layout/ETriceDiagramLayoutManager.java b/plugins/org.eclipse.etrice.ui.layout/src/org/eclipse/etrice/ui/layout/ETriceDiagramLayoutManager.java new file mode 100644 index 000000000..a5a83b706 --- /dev/null +++ b/plugins/org.eclipse.etrice.ui.layout/src/org/eclipse/etrice/ui/layout/ETriceDiagramLayoutManager.java @@ -0,0 +1,526 @@ +/******************************************************************************* + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Jayant Gupta (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.ui.layout; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.etrice.ui.common.editor.RoomDiagramEditor; +import org.eclipse.gef.EditPart; +import org.eclipse.graphiti.mm.algorithms.AbstractText; +import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm; +import org.eclipse.graphiti.mm.pictograms.Anchor; +import org.eclipse.graphiti.mm.pictograms.Connection; +import org.eclipse.graphiti.mm.pictograms.ContainerShape; +import org.eclipse.graphiti.mm.pictograms.Diagram; +import org.eclipse.graphiti.mm.pictograms.FreeFormConnection; +import org.eclipse.graphiti.mm.pictograms.PictogramElement; +import org.eclipse.graphiti.mm.pictograms.Shape; +import org.eclipse.graphiti.ui.editor.DiagramEditor; +import org.eclipse.graphiti.ui.internal.parts.IPictogramElementEditPart; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.PlatformUI; + +import de.cau.cs.kieler.core.kgraph.KGraphElement; +import de.cau.cs.kieler.core.kgraph.KLabeledGraphElement; +import de.cau.cs.kieler.core.kgraph.KNode; +import de.cau.cs.kieler.core.kgraph.KPort; +import de.cau.cs.kieler.kiml.LayoutContext; +import de.cau.cs.kieler.kiml.config.VolatileLayoutConfig; +import de.cau.cs.kieler.kiml.graphiti.GefDiagramLayoutManager; +import de.cau.cs.kieler.kiml.graphiti.GraphitiLayoutCommand; +import de.cau.cs.kieler.kiml.graphiti.GraphitiLayoutConfig; +import de.cau.cs.kieler.kiml.graphiti.KimlGraphitiUtil; +import de.cau.cs.kieler.kiml.klayoutdata.KInsets; +import de.cau.cs.kieler.kiml.klayoutdata.KShapeLayout; +import de.cau.cs.kieler.kiml.klayoutdata.impl.KShapeLayoutImpl; +import de.cau.cs.kieler.kiml.ui.diagram.LayoutMapping; +import de.cau.cs.kieler.kiml.util.KimlUtil; + +/** + * The abstract class to support the creation of eTrice + * {@link BehaviorDiagramLayoutManager } and + * {@link StructureDiagramLayoutmanager} + * + * @author jayant + */ +@SuppressWarnings("restriction") +public abstract class ETriceDiagramLayoutManager extends + GefDiagramLayoutManager<PictogramElement> { + + /** + * {@inheritDoc} + */ + public abstract boolean supports(Object object); + + /** + * {@inheritDoc} + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + public Object getAdapter(final Object object, final Class adapterType) { + if (adapterType.isAssignableFrom(GraphitiLayoutConfig.class)) { + return layoutConfig; + } else if (adapterType + .isAssignableFrom(IPictogramElementEditPart.class)) { + if (object instanceof IPictogramElementEditPart) { + return object; + } else if (object instanceof DiagramEditor) { + return ((DiagramEditor) object).getGraphicalViewer() + .getContents(); + } + } else if (adapterType.isAssignableFrom(EObject.class)) { + if (object instanceof IPictogramElementEditPart) { + PictogramElement pe = ((IPictogramElementEditPart) object) + .getPictogramElement(); + if (pe.getLink() != null) { + List<EObject> businessObjects = pe.getLink() + .getBusinessObjects(); + if (!businessObjects.isEmpty()) { + return businessObjects.get(0); + } + } + } else if (object instanceof PictogramElement) { + PictogramElement pe = (PictogramElement) object; + if (pe.getLink() != null) { + List<EObject> businessObjects = pe.getLink() + .getBusinessObjects(); + if (!businessObjects.isEmpty()) { + return businessObjects.get(0); + } + } + } + } else if (adapterType.isAssignableFrom(PictogramElement.class)) { + if (object instanceof PictogramElement) { + return object; + } else if (object instanceof IPictogramElementEditPart) { + return ((IPictogramElementEditPart) object) + .getPictogramElement(); + } else if (object instanceof DiagramEditor) { + EditPart contents = ((DiagramEditor) object) + .getGraphicalViewer().getContents(); + if (contents instanceof IPictogramElementEditPart) { + return ((IPictogramElementEditPart) contents) + .getPictogramElement(); + } + } + } else if (adapterType + .isAssignableFrom(TransactionalEditingDomain.class)) { + if (object instanceof DiagramEditor) { + return ((DiagramEditor) object).getEditingDomain(); + } else if (object instanceof IPictogramElementEditPart) { + return ((IPictogramElementEditPart) object) + .getConfigurationProvider().getDiagramEditor() + .getEditingDomain(); + } + } + if (object instanceof IAdaptable) { + return ((IAdaptable) object).getAdapter(adapterType); + } + return null; + } + + /** + * {@inheritDoc} + */ + @Override + public Class<?>[] getAdapterList() { + return new Class<?>[] { PictogramElement.class }; + } + + /** + * {@inheritDoc} + * + * @author jayant + */ + + @Override + protected void transferLayout(final LayoutMapping<PictogramElement> mapping) { + DiagramEditor diagramEditor = mapping + .getProperty(KimlGraphitiUtil.DIAGRAM_EDITOR); + ETriceLayoutCommand command = new ETriceLayoutCommand( + diagramEditor.getEditingDomain(), diagramEditor + .getDiagramTypeProvider().getFeatureProvider()); + for (Entry<KGraphElement, PictogramElement> entry : mapping + .getGraphMap().entrySet()) { + command.add(entry.getKey(), entry.getValue()); + } + mapping.setProperty(KimlGraphitiUtil.LAYOUT_COMMAND, command); + } + + /** + * {@inheritDoc} + */ + @Override + protected void applyLayout(final LayoutMapping<PictogramElement> mapping) { + TransactionalEditingDomain editingDomain = mapping.getProperty( + KimlGraphitiUtil.DIAGRAM_EDITOR).getEditingDomain(); + editingDomain.getCommandStack().execute( + mapping.getProperty(KimlGraphitiUtil.LAYOUT_COMMAND)); + } + + /** the cached layout configuration for Graphiti. */ + private GraphitiLayoutConfig layoutConfig = new GraphitiLayoutConfig(); + + /** + * {@inheritDoc} + */ + @Override + public LayoutMapping<PictogramElement> buildLayoutGraph( + final IWorkbenchPart workbenchPart, final Object diagramPart) { + LayoutMapping<PictogramElement> mapping = new LayoutMapping<PictogramElement>( + this); + mapping.setProperty(KimlGraphitiUtil.CONNECTIONS, + new LinkedList<Connection>()); + mapping.setProperty(KimlGraphitiUtil.STATIC_CONFIG, + new VolatileLayoutConfig()); + + if (workbenchPart instanceof RoomDiagramEditor) { + mapping.setProperty(KimlGraphitiUtil.DIAGRAM_EDITOR, + (RoomDiagramEditor) workbenchPart); + } + + EditPart layoutRootPart = null; + if (diagramPart instanceof IPictogramElementEditPart) { + layoutRootPart = (EditPart) diagramPart; + } else if (mapping.getProperty(KimlGraphitiUtil.DIAGRAM_EDITOR) != null) { + layoutRootPart = mapping + .getProperty(KimlGraphitiUtil.DIAGRAM_EDITOR) + .getGraphicalViewer().getContents(); + } + if (!(layoutRootPart instanceof IPictogramElementEditPart)) { + throw new UnsupportedOperationException( + "Not supported by this layout manager: Workbench part " + + workbenchPart + ", Edit part " + diagramPart); + } + PictogramElement element = ((IPictogramElementEditPart) layoutRootPart) + .getPictogramElement(); + mapping.setParentElement(element); + + if (element instanceof Diagram) { + + KNode diagramNode = KimlUtil.createInitializedNode(); + KShapeLayout shapeLayout = diagramNode.getData(KShapeLayout.class); + GraphicsAlgorithm ga = element.getGraphicsAlgorithm(); + shapeLayout.setPos(ga.getX(), ga.getY()); + shapeLayout.setSize(ga.getWidth(), ga.getHeight()); + mapping.getGraphMap().put(diagramNode, element); + + // Node creation for currently visible top-level Container + // Shape(Bounding Box) in + // eTrice Diagrams + buildLayoutGraphForBoundingBox(mapping, (Diagram) element, + diagramNode, true); + + mapping.setLayoutGraph(diagramNode); + + } else if (element instanceof Shape) { + + if ( isTopLevelBoundingBox( (Shape)element) ) { + // The selected Element is the Top Level Top Level Bounding Box + mapping.setLayoutGraph((KNode) buildAllLevels(mapping, + (Shape) element, null)); + } else { + KGraphElement internalKGraphElement = createKGaphElementFromShape( + mapping, null, (Shape) element); + + if (internalKGraphElement instanceof KNode) { + // The selected Element is a Node. + for (Shape childShape : ((ContainerShape) element) + .getChildren()) { + + createKGaphElementFromShape(mapping, + internalKGraphElement, childShape); + } + + mapping.setLayoutGraph((KNode) internalKGraphElement); + + } else { + // The selected Element is a Port or an Edge Label. + + // Giving the user a SWT dialog indicating that this Shape + // cannot be lay-outed. + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + MessageBox dialog = new MessageBox(shell, SWT.ICON_ERROR + | SWT.OK | SWT.CANCEL); + dialog.setText("Invalid Layout Call"); + dialog.setMessage("This shape connot be layouted saparately."); + System.out.println(dialog.open()); + + } + + } + } else if (element instanceof FreeFormConnection) { + // This gives the user a SWT dialog indicating this is a connection and + // cannot be lay-outed. + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() + .getShell(); + MessageBox dialog = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK + | SWT.CANCEL); + dialog.setText("Invalid Layout Call"); + dialog.setMessage("A connection connot be layouted saparately"); + System.out.println(dialog.open()); + } + + for (Connection entry : mapping + .getProperty(KimlGraphitiUtil.CONNECTIONS)) { + KimlGraphitiUtil.createEdge(mapping, entry); + } + + // create a layout configuration + mapping.getLayoutConfigs().add( + mapping.getProperty(KimlGraphitiUtil.STATIC_CONFIG)); + mapping.getLayoutConfigs().add(layoutConfig); + + return mapping; + } + + /** + * Identifies the visible Bounding Box (Top Level Container) and delegates + * the control to {@link #buildAllLevels(LayoutMapping, Shape, KNode)} + * + * @param mapping + * the mapping of pictogram elements to graph elements + * @param diagram + * @param diagramNode + * @param onlyVisible + * + * @author jayant + */ + protected abstract void buildLayoutGraphForBoundingBox( + final LayoutMapping<PictogramElement> mapping, + final Diagram diagram, final KNode diagramNode, + final boolean onlyVisible); + + /** + * Develops the complete LayoutGraph for the eTrice Diagram starting from + * the Bounding Box. + * + * @param mapping + * the mapping of pictogram elements to graph elements + * @param topLevelBoundingBox + * The Top Level Container Shape containing all other shapes + * @param diagramNode + * The KNode corresponding to the Diagram + * + * @author jayant + */ + /* This is fairly general for both the eTrice editors */ + protected KNode buildAllLevels(LayoutMapping<PictogramElement> mapping, + Shape topLevelBoundingBox, KNode diagramNode) { + // Top Level + KNode topLevelBoundingBoxNode = createNode(mapping, diagramNode, + topLevelBoundingBox); + + for (Shape secondtLevelShape : ((ContainerShape) topLevelBoundingBox) + .getChildren()) { + // Second Level + KGraphElement secondLevelKGraphElement = createKGaphElementFromShape( + mapping, topLevelBoundingBoxNode, secondtLevelShape); + + if (secondLevelKGraphElement instanceof KNode) { + for (Shape thirdLevelShape : ((ContainerShape) secondtLevelShape) + .getChildren()) { + // Third Level + createKGaphElementFromShape(mapping, + secondLevelKGraphElement, thirdLevelShape); + } + } + } + + return topLevelBoundingBoxNode; + } + + /** + * Identifies the type of Shape (Label, Port or Node) and creates the + * corresponding KGraphElement Element + * + * @param mapping + * the mapping of pictogram elements to graph elements + * @param parent + * the parent KNode + * @param shape + * the shape for which a KGraphElement is required + * + * @return the created KGraphElement for the given Shape + * + * @author jayant + */ + /* This is fairly general for both the eTrice editors */ + private KGraphElement createKGaphElementFromShape( + LayoutMapping<PictogramElement> mapping, KGraphElement parent, + Shape shape) { + + GraphicsAlgorithm ga = shape.getGraphicsAlgorithm(); + + // Checking whether this shape is a label + if (ga instanceof AbstractText) { + + KInsets parentInsets = parent.getData(KShapeLayout.class) + .getProperty(GraphitiLayoutCommand.INVIS_INSETS); + + assert (parentInsets != null) : "There must be an invisible insets attached to all ports and nodes(except diagramNode)"; + return KimlGraphitiUtil.createLabel((KLabeledGraphElement) parent, + (AbstractText) ga, -parentInsets.getLeft(), + -parentInsets.getTop()); + } + + else if (shape instanceof ContainerShape) { + + // Checking whether this shape is a Port + if (isPort(shape)) + return createPort(mapping, (KNode) parent, shape); + + else + // This shape is a node + return createNode(mapping, (KNode) parent, shape); + + } else + return null; + } + + /** + * {@inheritDoc} + * + * @author jayant + */ + protected abstract KNode createNode( + final LayoutMapping<PictogramElement> mapping, + final KNode parentNode, final Shape shape); + + /** + * Create a port for the layout graph. + * + * @param mapping + * the mapping of pictogram elements to graph elements + * @param parentNode + * the parent node + * @param shape + * the shape for a new port + * @return a new layout node + * + * @author jayant + */ + /* This is fairly general for both the eTrice editors */ + protected KPort createPort(final LayoutMapping<PictogramElement> mapping, + final KNode parentNode, final Shape shape) { + KPort port = KimlUtil.createInitializedPort(); + port.setNode(parentNode); + + setCurrentPositionAndSize(mapping, parentNode, port, shape); + + mapping.getGraphMap().put(port, shape.getAnchors().get(0)); + + // Set Port label + Shape portLabelShape = ((ContainerShape) shape).getChildren().get(0); + createKGaphElementFromShape(mapping, port, portLabelShape); + + // gather all connections connected to the parentNode via this port + for (Anchor anchor : shape.getAnchors()) { + mapping.getProperty(KimlGraphitiUtil.CONNECTIONS).addAll( + anchor.getOutgoingConnections()); + } + + return port; + } + + /** + * Sets the insets(border) and calculates the position and size of the + * KgraphElement. + * + * @param mapping + * the mapping of pictogram elements to graph elements + * @param parentNode + * the parent node + * @param kelem + * the kGraphElement whose size and position is to be determined + * @param shape + * the corresponding shape + * + * @author jayant + */ + /* + * This is fairly general for both the eTrice editors and same for Nodes and + * Ports + */ + public static void setCurrentPositionAndSize( + final LayoutMapping<PictogramElement> mapping, + final KNode parentNode, final KGraphElement kelem, final Shape shape) { + + VolatileLayoutConfig staticConfig = mapping + .getProperty(KimlGraphitiUtil.STATIC_CONFIG); + + KShapeLayout shapeLayout = kelem.getData(KShapeLayout.class); + GraphicsAlgorithm ga = shape.getGraphicsAlgorithm(); + + // Calculate and set the invisible insets + KInsets shapeInsets = KimlGraphitiUtil.calcInsets(ga); + shapeLayout + .setProperty(GraphitiLayoutCommand.INVIS_INSETS, shapeInsets); + staticConfig.setValue(GraphitiLayoutCommand.INVIS_INSETS, kelem, + LayoutContext.GRAPH_ELEM, shapeInsets); + + // Get the parent insets + KInsets parentInsets = parentNode == null ? null : parentNode.getData( + KShapeLayout.class).getProperty( + GraphitiLayoutCommand.INVIS_INSETS); + + // Set Position + if (parentInsets == null) { + shapeLayout.setPos(ga.getX() + shapeInsets.getLeft(), ga.getY() + + shapeInsets.getTop()); + } else { + shapeLayout.setPos( + ga.getX() + shapeInsets.getLeft() - parentInsets.getLeft(), + ga.getY() + shapeInsets.getTop() - parentInsets.getTop()); + } + + // Set Size + shapeLayout + .setSize( + ga.getWidth() - shapeInsets.getLeft() + - shapeInsets.getRight(), + ga.getHeight() - shapeInsets.getTop() + - shapeInsets.getBottom()); + + // the modification flag must initially be false + ((KShapeLayoutImpl) shapeLayout).resetModificationFlag(); + + } + + /** + * Determines whether the given shape is a port. + * + * @param shape the shape to be investigated + * @return true if the {@code shape} is a port else false + * + * @author jayant + */ + protected abstract boolean isPort(Shape shape); + + /** + * Determines whether the given shape is a Top Level Bounding Box or not. + * + * @param shape the shape to be investigated + * @return true if the {@code shape} is the Top Level Bounding Box + * + * @author jayant + */ + protected abstract boolean isTopLevelBoundingBox(Shape shape); + +} diff --git a/plugins/org.eclipse.etrice.ui.layout/src/org/eclipse/etrice/ui/layout/ETriceLayoutCommand.java b/plugins/org.eclipse.etrice.ui.layout/src/org/eclipse/etrice/ui/layout/ETriceLayoutCommand.java new file mode 100644 index 000000000..c09dabf46 --- /dev/null +++ b/plugins/org.eclipse.etrice.ui.layout/src/org/eclipse/etrice/ui/layout/ETriceLayoutCommand.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Jayant Gupta (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.ui.layout; + +import java.util.List; + +import org.eclipse.emf.transaction.TransactionalEditingDomain; +import org.eclipse.graphiti.features.IFeatureProvider; +import org.eclipse.graphiti.features.context.impl.LayoutContext; +import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm; +import org.eclipse.graphiti.mm.algorithms.styles.Point; +import org.eclipse.graphiti.mm.pictograms.Anchor; +import org.eclipse.graphiti.mm.pictograms.ContainerShape; +import org.eclipse.graphiti.mm.pictograms.FreeFormConnection; +import org.eclipse.graphiti.mm.pictograms.PictogramElement; +import org.eclipse.graphiti.services.Graphiti; + +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.core.kgraph.KPort; +import de.cau.cs.kieler.core.math.KVector; +import de.cau.cs.kieler.core.math.KVectorChain; +import de.cau.cs.kieler.kiml.graphiti.GraphitiLayoutCommand; +import de.cau.cs.kieler.kiml.klayoutdata.KInsets; +import de.cau.cs.kieler.kiml.klayoutdata.KShapeLayout; + +/** + * A command for applying the result of automatic layout to an eTrice + * editor(Graphiti) diagram. + * + * @author jayant + */ +public class ETriceLayoutCommand extends GraphitiLayoutCommand { + + public ETriceLayoutCommand(TransactionalEditingDomain domain, + IFeatureProvider thefeatureProvider) { + super(domain, thefeatureProvider); + } + + /** + * {@inheritDoc} + * + * @author jayant + */ + @Override + protected void applyPortLayout(KPort kport, PictogramElement pelem) { + + ContainerShape shape = (ContainerShape) ((Anchor) pelem).getParent(); + + setCalculatedPositionAndSize(kport, kport.getNode(), shape); + }; + + /** + * {@inheritDoc} + * + * @author jayant + */ + @Override + protected void applyNodeLayout(KNode knode, PictogramElement pelem) { + + setCalculatedPositionAndSize(knode, knode.getParent(), + (ContainerShape) pelem); + + }; + + /** + * {@inheritDoc} + * + */ + /* + * The code used in this function has been taken from + * GraphitilayoutCommand.applyEdgeLayout() method. (Removing some unwanted + * code) + */ + @Override + protected void applyEdgeLayout(final KEdge kedge, + final PictogramElement pelem) { + // create bend points for the edge + KVectorChain bendPoints = getBendPoints(kedge); + + if (pelem instanceof FreeFormConnection) { + FreeFormConnection connection = (FreeFormConnection) pelem; + List<Point> pointList = connection.getBendpoints(); + // add the bend points to the connection, reusing existing points + for (int i = 0; i < bendPoints.size(); i++) { + KVector kpoint = bendPoints.get(i); + if (i >= pointList.size()) { + Point point = Graphiti.getGaService().createPoint( + (int) Math.round(kpoint.x), + (int) Math.round(kpoint.y)); + pointList.add(point); + } else { + Point point = pointList.get(i); + point.setX((int) Math.round(kpoint.x)); + point.setY((int) Math.round(kpoint.y)); + } + } + while (pointList.size() > bendPoints.size()) { + pointList.remove(pointList.size() - 1); + } + } + } + + /** + * Sets the calculated position and size from a KGraph Model-Element (Node or + * Port) back to the corresponding diagram shape. + * + * @param kelem + * the KGraph Model Element (Node/Port) + * @param parentNode + * for nodes : the parent node , for ports : the containing node + * @param shape + * the corresponding pictogram element for Node/Port + * + * @author jayant + */ + /* + * This function derives its code majorly from + * GraphitilayoutCommand.applyNodeLayout() method + */ + private void setCalculatedPositionAndSize(final KGraphElement kelem, + KNode parentNode, final ContainerShape shape) { + + KShapeLayout shapeLayout = kelem.getData(KShapeLayout.class); + float xpos = shapeLayout.getXpos(); + float ypos = shapeLayout.getYpos(); + + if (parentNode != null) { + KInsets parentInsets = parentNode.getData(KShapeLayout.class) + .getProperty(INVIS_INSETS); + if (parentInsets != null) { + xpos += parentInsets.getLeft(); + ypos += parentInsets.getRight(); + } + } + + float width = shapeLayout.getWidth(); + float height = shapeLayout.getHeight(); + + KInsets nodeInsets = shapeLayout.getProperty(INVIS_INSETS); + if (nodeInsets != null) { + xpos -= nodeInsets.getLeft(); + ypos -= nodeInsets.getTop(); + width += nodeInsets.getLeft() + nodeInsets.getRight(); + height += nodeInsets.getTop() + nodeInsets.getBottom(); + } + + GraphicsAlgorithm ga = shape.getGraphicsAlgorithm(); + + ga.setX(Math.round(xpos)); + ga.setY(Math.round(ypos)); + ga.setWidth(Math.round(width)); + ga.setHeight(Math.round(height)); + + featureProvider.layoutIfPossible(new LayoutContext(shape)); + } +} diff --git a/plugins/org.eclipse.etrice.ui.layout/src/org/eclipse/etrice/ui/layout/StructureDiagramLayoutmanager.java b/plugins/org.eclipse.etrice.ui.layout/src/org/eclipse/etrice/ui/layout/StructureDiagramLayoutmanager.java new file mode 100644 index 000000000..5dd544f9d --- /dev/null +++ b/plugins/org.eclipse.etrice.ui.layout/src/org/eclipse/etrice/ui/layout/StructureDiagramLayoutmanager.java @@ -0,0 +1,134 @@ +/******************************************************************************* + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * CONTRIBUTORS: + * Jayant Gupta (initial contribution) + * + *******************************************************************************/ +package org.eclipse.etrice.ui.layout; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.etrice.core.room.ActorClass; +import org.eclipse.etrice.core.room.InterfaceItem; +import org.eclipse.etrice.core.room.SAPoint; +import org.eclipse.etrice.core.room.SPPoint; +import org.eclipse.etrice.ui.structure.editor.StructureEditor; +import org.eclipse.etrice.ui.structure.support.ActorContainerRefSupport; +import org.eclipse.graphiti.mm.pictograms.Diagram; +import org.eclipse.graphiti.mm.pictograms.PictogramElement; +import org.eclipse.graphiti.mm.pictograms.Shape; +import org.eclipse.graphiti.ui.internal.parts.IPictogramElementEditPart; + +import de.cau.cs.kieler.core.kgraph.KNode; +import de.cau.cs.kieler.kiml.LayoutContext; +import de.cau.cs.kieler.kiml.config.VolatileLayoutConfig; +import de.cau.cs.kieler.kiml.graphiti.KimlGraphitiUtil; +import de.cau.cs.kieler.kiml.options.LayoutOptions; +import de.cau.cs.kieler.kiml.ui.diagram.LayoutMapping; +import de.cau.cs.kieler.kiml.util.KimlUtil; + +/** + * Layout Manager implementation for eTrice Structure Editor. + * + * @author jayant + */ +@SuppressWarnings("restriction") +public class StructureDiagramLayoutmanager extends ETriceDiagramLayoutManager { + + /** + * {@inheritDoc} + * + * @author jayant + */ + @Override + public boolean supports(final Object object) { + + return object instanceof StructureEditor + || object instanceof IPictogramElementEditPart + || object instanceof PictogramElement; + + } + + /** + * {@inheritDoc} + * + * @author jayant + */ + @Override + protected void buildLayoutGraphForBoundingBox( + LayoutMapping<PictogramElement> mapping, Diagram diagram, + KNode diagramNode, boolean onlyVisible) { + + for (Shape boundingBox : ((Diagram) diagram).getChildren()) { + if (boundingBox.isVisible()) { + buildAllLevels(mapping, boundingBox, diagramNode); + break; + } + } + } + + /** the fixed minimal height of nodes. */ + public static final float MIN_HEIGHT = ActorContainerRefSupport.DEFAULT_SIZE_Y; + /** the fixed minimal width of shapes. */ + public static final float MIN_WIDHT = ActorContainerRefSupport.DEFAULT_SIZE_X; + + /** + * {@inheritDoc} + * + * @author jayant + */ + protected KNode createNode(final LayoutMapping<PictogramElement> mapping, + final KNode parentNode, final Shape shape) { + KNode node = KimlUtil.createInitializedNode(); + node.setParent(parentNode); + + setCurrentPositionAndSize(mapping, parentNode, node, shape); + + VolatileLayoutConfig staticConfig = mapping + .getProperty(KimlGraphitiUtil.STATIC_CONFIG); + // FIXME find a way to specify the minimal size dynamically + + staticConfig.setValue(LayoutOptions.MIN_WIDTH, node, + LayoutContext.GRAPH_ELEM, MIN_WIDHT); + staticConfig.setValue(LayoutOptions.MIN_HEIGHT, node, + LayoutContext.GRAPH_ELEM, MIN_HEIGHT); + + mapping.getGraphMap().put(node, shape); + + return node; + } + + /** + * {@inheritDoc} + * + * @author jayant + */ + @Override + protected boolean isPort(Shape shape) { + EObject modelObject = shape.getLink().getBusinessObjects().get(0); + if (modelObject instanceof InterfaceItem + || modelObject instanceof SPPoint + || modelObject instanceof SAPoint) + return true; + + return false; + } + + /** + * {@inheritDoc} + * + * @author jayant + */ + @Override + protected boolean isTopLevelBoundingBox(Shape shape) { + EObject modelObject = shape.getLink().getBusinessObjects().get(0); + if (modelObject instanceof ActorClass) + return true; + + return false; + } + +} |