Search in sources :

Example 1 with IGraphElementVisitor

use of org.eclipse.elk.core.util.IGraphElementVisitor in project elk by eclipse.

the class DiagramLayoutEngine method layout.

/**
 * Perform layout on the given layout graph mapping. If zero or one layout configurator is
 * passed, the layout engine is executed exactly once. If multiple layout configurators are
 * passed, the layout engine is executed accordingly often, but the resulting layout is applied
 * only once. This is useful for composition of multiple algorithms that process only parts of
 * the graph. Layout listeners are notified before and after the layout has been computed.
 *
 * @param mapping
 *            a mapping for the layout graph
 * @param progressMonitor
 *            a progress monitor to which progress of the layout algorithm is reported
 * @param params
 *            layout parameters
 * @return a status indicating success or failure
 */
public IStatus layout(final LayoutMapping mapping, final IElkProgressMonitor progressMonitor, final Parameters params) {
    mapping.setProperty(MAPPING_CONNECTOR, connector);
    handleAncestors(mapping, params);
    LinkedList<IGraphElementVisitor> visitors = new LinkedList<IGraphElementVisitor>();
    visitors.add(algorithmResolver);
    // Set up graph validators
    if (params.getGlobalSettings().getProperty(CoreOptions.VALIDATE_OPTIONS)) {
        visitors.add(layoutOptionValidatorProvider.get());
    }
    if (params.getGlobalSettings().getProperty(CoreOptions.VALIDATE_GRAPH)) {
        visitors.add(graphValidatorProvider.get());
    }
    // Notify listeners of the to-be-executed layout
    LayoutConnectorsService.getInstance().fireLayoutAboutToStart(mapping, progressMonitor);
    IStatus status = null;
    if (params.configurators.isEmpty()) {
        // Perform layout without any extra configuration
        IGraphElementVisitor[] visitorsArray = visitors.toArray(new IGraphElementVisitor[visitors.size()]);
        status = layout(mapping, progressMonitor, visitorsArray);
    } else if (params.configurators.size() == 1) {
        // Perform layout once with an extra configuration
        visitors.addFirst(params.configurators.get(0));
        IGraphElementVisitor[] visitorsArray = visitors.toArray(new IGraphElementVisitor[visitors.size()]);
        status = layout(mapping, progressMonitor, visitorsArray);
    } else {
        // Perform layout multiple times with different configurations
        progressMonitor.begin("Diagram layout engine", params.configurators.size());
        ListIterator<IGraphElementVisitor> configIter = params.configurators.listIterator();
        while (configIter.hasNext()) {
            visitors.addFirst(configIter.next());
            IGraphElementVisitor[] visitorsArray = visitors.toArray(new IGraphElementVisitor[visitors.size()]);
            status = layout(mapping, progressMonitor, visitorsArray);
            if (!status.isOK()) {
                break;
            }
            visitors.removeFirst();
            // If an additional layout configurator is attached to the graph, consider it in the future
            LayoutConfigurator addConfig = mapping.getLayoutGraph().getProperty(LayoutConfigurator.ADD_LAYOUT_CONFIG);
            if (addConfig != null) {
                ListIterator<IGraphElementVisitor> configIter2 = params.configurators.listIterator(configIter.nextIndex());
                while (configIter2.hasNext()) {
                    IGraphElementVisitor c = configIter2.next();
                    if (c instanceof LayoutConfigurator) {
                        ((LayoutConfigurator) c).overrideWith(addConfig);
                    }
                }
            }
        }
        progressMonitor.done();
        // Log the final result to be displayed in our debug views
        progressMonitor.logGraph(mapping.getLayoutGraph(), "Result");
    }
    mapping.setProperty(MAPPING_STATUS, status);
    // Notify listeners of the executed layout
    LayoutConnectorsService.getInstance().fireLayoutDone(mapping, progressMonitor);
    return status;
}
Also used : IStatus(org.eclipse.core.runtime.IStatus) ListIterator(java.util.ListIterator) LinkedList(java.util.LinkedList) IGraphElementVisitor(org.eclipse.elk.core.util.IGraphElementVisitor) LayoutConfigurator(org.eclipse.elk.core.LayoutConfigurator)

Example 2 with IGraphElementVisitor

use of org.eclipse.elk.core.util.IGraphElementVisitor in project elk by eclipse.

the class DiagramLayoutEngine method handleAncestors.

/**
 * Handle the ancestors of the parent element if {@link CoreOptions#LAYOUT_ANCESTORS} is set.
 * For every ancestor node of the parent element (i.e. {@link LayoutMapping#getParentElement()}),
 * all containing elements that are not ancestors are excluded from layout.
 *
 * @param mapping
 *            a mapping for the layout graph
 * @param params
 *            layout parameters
 */
protected void handleAncestors(final LayoutMapping mapping, final Parameters params) {
    boolean layoutAncestors = params.getGlobalSettings().getProperty(CoreOptions.LAYOUT_ANCESTORS);
    if (layoutAncestors) {
        // Mark all parallel areas for exclusion from layout
        ElkGraphElement graphElem = mapping.getGraphMap().inverse().get(mapping.getParentElement());
        if (graphElem instanceof ElkNode && ((ElkNode) graphElem).getParent() != null) {
            if (params.configurators.isEmpty()) {
                params.configurators.add(new LayoutConfigurator());
            }
            ElkNode node = (ElkNode) graphElem;
            do {
                ElkNode parent = node.getParent();
                for (ElkNode child : parent.getChildren()) {
                    if (child != node) {
                        for (IGraphElementVisitor c : params.configurators) {
                            if (c instanceof LayoutConfigurator) {
                                IPropertyHolder childConfig = ((LayoutConfigurator) c).configure(child);
                                // Do not layout the content of the child node
                                childConfig.setProperty(CoreOptions.NO_LAYOUT, true);
                                // Do not change the size of the child node
                                childConfig.setProperty(CoreOptions.NODE_SIZE_CONSTRAINTS, SizeConstraint.fixed());
                                // Do not move the ports of the child node
                                childConfig.setProperty(CoreOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_POS);
                            }
                        }
                    }
                }
                node = parent;
            } while (node.getParent() != null);
        }
    }
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) ElkGraphElement(org.eclipse.elk.graph.ElkGraphElement) IPropertyHolder(org.eclipse.elk.graph.properties.IPropertyHolder) LayoutConfigurator(org.eclipse.elk.core.LayoutConfigurator) IGraphElementVisitor(org.eclipse.elk.core.util.IGraphElementVisitor)

Example 3 with IGraphElementVisitor

use of org.eclipse.elk.core.util.IGraphElementVisitor in project elk by eclipse.

the class DiagramLayoutEngine method addDiagramConfig.

/**
 * Create a diagram layout configuration and add it to the setup.
 */
protected void addDiagramConfig(final Parameters params, final LayoutMapping layoutMapping) {
    LayoutConfigurator diagramConfig = configManager.createConfigurator(layoutMapping);
    if (params.configurators.isEmpty()) {
        params.addLayoutRun(diagramConfig);
    } else {
        ListIterator<IGraphElementVisitor> configIter = params.configurators.listIterator();
        while (configIter.hasNext()) {
            boolean isFirstConfig = !configIter.hasPrevious();
            IGraphElementVisitor setupConfig = configIter.next();
            if (setupConfig instanceof LayoutConfigurator) {
                LayoutConfigurator layoutConfigurator = (LayoutConfigurator) setupConfig;
                if (params.overrideDiagramConfig) {
                    if (isFirstConfig || layoutConfigurator.isClearLayout()) {
                        LayoutConfigurator newConfig;
                        if (configIter.hasNext()) {
                            newConfig = new LayoutConfigurator().overrideWith(diagramConfig);
                        } else {
                            newConfig = diagramConfig;
                        }
                        configIter.set(newConfig.overrideWith(layoutConfigurator));
                    }
                } else {
                    layoutConfigurator.overrideWith(diagramConfig);
                }
            }
        }
    }
}
Also used : LayoutConfigurator(org.eclipse.elk.core.LayoutConfigurator) IGraphElementVisitor(org.eclipse.elk.core.util.IGraphElementVisitor)

Example 4 with IGraphElementVisitor

use of org.eclipse.elk.core.util.IGraphElementVisitor in project osate2 by osate.

the class DiagramElementLayoutUtil method applyProperties.

/**
 * Sets the ELK properties of elements in the specified layout mapping based on the layout options.
 * @param layoutMapping
 */
private static void applyProperties(final DiagramNode rootDiagramNode, final LayoutMapping layoutMapping) {
    // Set the minimum node size based on the ports and their assigned sides.
    final IGraphElementVisitor minNodeSizeVisitor = element -> {
        if (element instanceof ElkNode) {
            final ElkNode n = (ElkNode) element;
            final double maxLabelWidth = n.getLabels().stream().mapToDouble(l -> l.getWidth()).max().orElse(0.0);
            final double labelHeightSum = n.getLabels().stream().mapToDouble(l -> l.getHeight()).sum();
            // Determine max width for ports on the left and right sides
            final double maxLeftPortWidth = n.getPorts().stream().filter(p -> p.getProperty(CoreOptions.PORT_SIDE) == PortSide.WEST).mapToDouble(p -> p.getWidth()).max().orElse(0.0);
            final double maxRightPortWidth = n.getPorts().stream().filter(p -> p.getProperty(CoreOptions.PORT_SIDE) == PortSide.EAST).mapToDouble(p -> p.getWidth()).max().orElse(0.0);
            final DiagramNode dn = (DiagramNode) layoutMapping.getGraphMap().get(n);
            double minWidth = 0;
            if (n.getProperty(CoreOptions.NODE_LABELS_PLACEMENT).contains(NodeLabelPlacement.H_CENTER)) {
                // Ensure the minimum width is such that the label can be centered without overlapping with ports.
                // This happens because ports are inside the node due to the PORT_BORDER_OFFSET and ELK centers the labels in the remaining space.
                final double widthForPorts = 2 * Math.max(maxLeftPortWidth, maxRightPortWidth);
                minWidth = Math.max(40, maxLabelWidth + widthForPorts + PORT_WIDTH_PADDING);
            } else {
                final double widthForPorts = maxLeftPortWidth + maxRightPortWidth + PORT_WIDTH_PADDING;
                minWidth = Math.max(40, Math.max(maxLabelWidth, widthForPorts));
            }
            double minHeight = Math.max(35, labelHeightSum);
            if (dn instanceof DiagramElement) {
                final DiagramElement de = ((DiagramElement) dn);
                // Special min height handling for initial modes
                final Graphic graphic = de.getGraphic();
                if (graphic instanceof AgeShape && !((AgeShape) graphic).isResizeable() && de.hasSize()) {
                    final Dimension dim = de.getSize();
                    minHeight = dim.height;
                    minWidth = dim.width;
                    // Adjust size constraints for fixed sized shapes which do not have contents.
                    if (n.getChildren().size() == 0 || n.getLabels().size() == 0 && n.getPorts().size() == 0) {
                        final EnumSet<SizeConstraint> nodeSizeConstraints = EnumSet.of(SizeConstraint.MINIMUM_SIZE);
                        n.setProperty(CoreOptions.NODE_SIZE_CONSTRAINTS, nodeSizeConstraints);
                    }
                }
                if (graphic instanceof ModeGraphic && ((ModeGraphic) graphic).isInitialMode) {
                    minHeight += ModeGraphic.INITIAL_MODE_AREA_HEIGHT;
                }
                // Special min size handling for elements shown as image
                final Style style = de.getStyle();
                if (style != null && Boolean.TRUE.equals(style.getShowAsImage())) {
                    final Dimension dim = ((DiagramElement) dn).getSize();
                    minHeight = dim.height;
                    minWidth = dim.width;
                }
            }
            // Increase min width and min height for top level nodes.
            if (dn != null && dn.getParent() instanceof AgeDiagram) {
                minWidth = Math.max(minWidth, 200);
                minHeight = Math.max(minHeight, 100);
            }
            n.setProperty(CoreOptions.NODE_SIZE_MINIMUM, new KVector(minWidth, minHeight));
        }
    };
    ElkUtil.applyVisitors(layoutMapping.getLayoutGraph(), minNodeSizeVisitor);
    // If the top level element has a size set, don't shrink it.
    if (rootDiagramNode instanceof DiagramElement) {
        final DiagramElement rootDiagramElement = (DiagramElement) rootDiagramNode;
        final ElkGraphElement rootGraphElement = layoutMapping.getGraphMap().inverse().get(rootDiagramNode);
        if (rootGraphElement != null && rootDiagramElement.hasSize() && DiagramElementPredicates.isResizeable(rootDiagramElement)) {
            final KVector minSize = rootGraphElement.getProperty(CoreOptions.NODE_SIZE_MINIMUM);
            final double newMinWidth = Math.max(rootDiagramElement.getWidth(), minSize == null ? 0.0 : minSize.x);
            final double newMinHeight = Math.max(rootDiagramElement.getHeight(), minSize == null ? 0.0 : minSize.y);
            rootGraphElement.setProperty(CoreOptions.NODE_SIZE_MINIMUM, new KVector(newMinWidth, newMinHeight));
        }
    }
}
Also used : CoreOptions(org.eclipse.elk.core.options.CoreOptions) ArrayListMultimap(com.google.common.collect.ArrayListMultimap) PortSide(org.eclipse.elk.core.options.PortSide) LayoutMapping(org.eclipse.elk.core.service.LayoutMapping) ElkNode(org.eclipse.elk.graph.ElkNode) ElkPort(org.eclipse.elk.graph.ElkPort) IGraphElementVisitor(org.eclipse.elk.core.util.IGraphElementVisitor) RecursiveGraphLayoutEngine(org.eclipse.elk.core.RecursiveGraphLayoutEngine) DockArea(org.osate.ge.internal.diagram.runtime.DockArea) IStatus(org.eclipse.core.runtime.IStatus) BusinessObjectContext(org.osate.ge.BusinessObjectContext) Graphic(org.osate.ge.graphics.Graphic) DiagramNodePredicates(org.osate.ge.internal.diagram.runtime.DiagramNodePredicates) StatusManager(org.eclipse.ui.statushandlers.StatusManager) IEditorPart(org.eclipse.ui.IEditorPart) EnumSet(java.util.EnumSet) Collection(java.util.Collection) Set(java.util.Set) Status(org.eclipse.core.runtime.Status) SizeConstraint(org.eclipse.elk.core.options.SizeConstraint) Point(org.osate.ge.graphics.Point) Collectors(java.util.stream.Collectors) DiagramElementUtil(org.osate.ge.internal.util.DiagramElementUtil) DockingPosition(org.osate.ge.DockingPosition) Objects(java.util.Objects) List(java.util.List) Stream(java.util.stream.Stream) ElkGraphElement(org.eclipse.elk.graph.ElkGraphElement) NodeLabelPlacement(org.eclipse.elk.core.options.NodeLabelPlacement) GraphicalEditorException(org.osate.ge.internal.GraphicalEditorException) ElkEdgeSection(org.eclipse.elk.graph.ElkEdgeSection) Entry(java.util.Map.Entry) Optional(java.util.Optional) ElkEdge(org.eclipse.elk.graph.ElkEdge) AgeConnection(org.osate.ge.graphics.internal.AgeConnection) DiagramNode(org.osate.ge.internal.diagram.runtime.DiagramNode) DiagramElement(org.osate.ge.internal.diagram.runtime.DiagramElement) Dimension(org.osate.ge.graphics.Dimension) ElkGraphPackage(org.eclipse.elk.graph.ElkGraphPackage) ModeGraphic(org.osate.ge.graphics.internal.ModeGraphic) DiagramModification(org.osate.ge.internal.diagram.runtime.DiagramModification) HashSet(java.util.HashSet) ElkUtil(org.eclipse.elk.core.util.ElkUtil) Style(org.osate.ge.graphics.Style) InternalDiagramEditor(org.osate.ge.internal.ui.editor.InternalDiagramEditor) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) AgeShape(org.osate.ge.graphics.internal.AgeShape) LinkedList(java.util.LinkedList) Activator(org.osate.ge.internal.Activator) DiagramElementPredicates(org.osate.ge.internal.diagram.runtime.DiagramElementPredicates) ElkLabel(org.eclipse.elk.graph.ElkLabel) KVector(org.eclipse.elk.core.math.KVector) Label(org.osate.ge.graphics.internal.Label) BasicProgressMonitor(org.eclipse.elk.core.util.BasicProgressMonitor) ElkShape(org.eclipse.elk.graph.ElkShape) Adapters(org.eclipse.core.runtime.Adapters) AgeDiagram(org.osate.ge.internal.diagram.runtime.AgeDiagram) AgeDiagramUtil(org.osate.ge.internal.diagram.runtime.AgeDiagramUtil) Comparator(java.util.Comparator) StyleProvider(org.osate.ge.internal.diagram.runtime.styling.StyleProvider) Collections(java.util.Collections) StyleCalculator(org.osate.ge.internal.diagram.runtime.styling.StyleCalculator) DiagramNode(org.osate.ge.internal.diagram.runtime.DiagramNode) ElkNode(org.eclipse.elk.graph.ElkNode) Graphic(org.osate.ge.graphics.Graphic) ModeGraphic(org.osate.ge.graphics.internal.ModeGraphic) EnumSet(java.util.EnumSet) ModeGraphic(org.osate.ge.graphics.internal.ModeGraphic) AgeShape(org.osate.ge.graphics.internal.AgeShape) Dimension(org.osate.ge.graphics.Dimension) DiagramElement(org.osate.ge.internal.diagram.runtime.DiagramElement) AgeDiagram(org.osate.ge.internal.diagram.runtime.AgeDiagram) Style(org.osate.ge.graphics.Style) KVector(org.eclipse.elk.core.math.KVector) ElkGraphElement(org.eclipse.elk.graph.ElkGraphElement) IGraphElementVisitor(org.eclipse.elk.core.util.IGraphElementVisitor)

Aggregations

IGraphElementVisitor (org.eclipse.elk.core.util.IGraphElementVisitor)4 LayoutConfigurator (org.eclipse.elk.core.LayoutConfigurator)3 LinkedList (java.util.LinkedList)2 IStatus (org.eclipse.core.runtime.IStatus)2 ElkGraphElement (org.eclipse.elk.graph.ElkGraphElement)2 ElkNode (org.eclipse.elk.graph.ElkNode)2 ArrayListMultimap (com.google.common.collect.ArrayListMultimap)1 ImmutableList (com.google.common.collect.ImmutableList)1 Lists (com.google.common.collect.Lists)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 Comparator (java.util.Comparator)1 EnumSet (java.util.EnumSet)1 HashSet (java.util.HashSet)1 List (java.util.List)1 ListIterator (java.util.ListIterator)1 Entry (java.util.Map.Entry)1 Objects (java.util.Objects)1 Optional (java.util.Optional)1 Set (java.util.Set)1