Search in sources :

Example 1 with ILayoutProcessor

use of org.eclipse.elk.core.alg.ILayoutProcessor in project elk by eclipse.

the class RadialLayoutProvider method layout.

@Override
public void layout(final ElkNode layoutGraph, final IElkProgressMonitor progressMonitor) {
    List<ILayoutProcessor<ElkNode>> algorithm = assembleAlgorithm(layoutGraph);
    progressMonitor.begin("Radial layout", algorithm.size());
    // if requested, compute nodes's dimensions, place node labels, ports, port labels, etc.
    if (!layoutGraph.getProperty(RadialOptions.OMIT_NODE_MICRO_LAYOUT)) {
        NodeMicroLayout.forGraph(layoutGraph).execute();
    }
    // pre calculate the root node and save it
    ElkNode root = RadialUtil.findRoot(layoutGraph);
    layoutGraph.setProperty(InternalProperties.ROOT_NODE, root);
    if (root == null) {
        throw new IllegalArgumentException("The given graph is not a tree!");
    }
    // Calculate the radius or take the one given by the user.
    double layoutRadius = layoutGraph.getProperty(RadialOptions.RADIUS);
    if (layoutRadius == 0) {
        layoutRadius = RadialUtil.findLargestNodeInGraph(layoutGraph);
    }
    layoutGraph.setProperty(RadialOptions.RADIUS, layoutRadius);
    // execute the different phases
    for (ILayoutProcessor<ElkNode> processor : assembleAlgorithm(layoutGraph)) {
        processor.process(layoutGraph, progressMonitor.subTask(1));
    }
    progressMonitor.done();
}
Also used : ElkNode(org.eclipse.elk.graph.ElkNode) ILayoutProcessor(org.eclipse.elk.core.alg.ILayoutProcessor)

Example 2 with ILayoutProcessor

use of org.eclipse.elk.core.alg.ILayoutProcessor in project elk by eclipse.

the class ElkLayered method layout.

// //////////////////////////////////////////////////////////////////////////////
// Actual Layout
/**
 * Perform the five phases of the layered layouter.
 *
 * @param lgraph the graph that is to be laid out
 * @param monitor a progress monitor
 */
private void layout(final LGraph lgraph, final IElkProgressMonitor monitor) {
    boolean monitorWasAlreadyRunning = monitor.isRunning();
    if (!monitorWasAlreadyRunning) {
        monitor.begin("Component Layout", 1);
    }
    List<ILayoutProcessor<LGraph>> algorithm = lgraph.getProperty(InternalProperties.PROCESSORS);
    float monitorProgress = 1.0f / algorithm.size();
    if (monitor.isLoggingEnabled()) {
        // Print the algorithm configuration
        monitor.log("ELK Layered uses the following " + algorithm.size() + " modules:");
        int slot = 0;
        for (ILayoutProcessor<LGraph> processor : algorithm) {
            // SUPPRESS CHECKSTYLE NEXT MagicNumber
            String gwtDoesntSupportPrintf = (slot < 10 ? "0" : "") + (slot++);
            monitor.log("   Slot " + gwtDoesntSupportPrintf + ": " + processor.getClass().getName());
        }
    }
    // Invoke each layout processor
    int slotIndex = 0;
    for (ILayoutProcessor<LGraph> processor : algorithm) {
        if (monitor.isCanceled()) {
            return;
        }
        // elkjs-exclude-start
        if (monitor.isLoggingEnabled()) {
            DebugUtil.logDebugGraph(monitor, lgraph, slotIndex, "Before " + processor.getClass().getSimpleName());
        }
        // elkjs-exclude-end
        notifyProcessorReady(lgraph, processor);
        processor.process(lgraph, monitor.subTask(monitorProgress));
        notifyProcessorFinished(lgraph, processor);
        slotIndex++;
    }
    // elkjs-exclude-start
    if (monitor.isLoggingEnabled()) {
        DebugUtil.logDebugGraph(monitor, lgraph, slotIndex, "Finished");
    }
    // second loop to avoid ConcurrentModificationExceptions)
    for (Layer layer : lgraph) {
        lgraph.getLayerlessNodes().addAll(layer.getNodes());
        layer.getNodes().clear();
    }
    for (LNode node : lgraph.getLayerlessNodes()) {
        node.setLayer(null);
    }
    lgraph.getLayers().clear();
    if (!monitorWasAlreadyRunning) {
        monitor.done();
    }
}
Also used : ILayoutProcessor(org.eclipse.elk.core.alg.ILayoutProcessor) LNode(org.eclipse.elk.alg.layered.graph.LNode) LGraph(org.eclipse.elk.alg.layered.graph.LGraph) Layer(org.eclipse.elk.alg.layered.graph.Layer) SizeConstraint(org.eclipse.elk.core.options.SizeConstraint)

Example 3 with ILayoutProcessor

use of org.eclipse.elk.core.alg.ILayoutProcessor in project elk by eclipse.

the class ElkLayered method isLayoutTestFinished.

/**
 * Checks if the current test run still has processors to be executed for the algorithm to finish.
 *
 * @param state the current test execution state
 * @return {@code true} if the current test run has not finished yet. If there is no current
 *         test run, the result is undefined.
 */
public boolean isLayoutTestFinished(final TestExecutionState state) {
    LGraph graph = state.graphs.get(0);
    List<ILayoutProcessor<LGraph>> algorithm = graph.getProperty(InternalProperties.PROCESSORS);
    return algorithm != null && state.step >= algorithm.size();
}
Also used : ILayoutProcessor(org.eclipse.elk.core.alg.ILayoutProcessor) LGraph(org.eclipse.elk.alg.layered.graph.LGraph)

Example 4 with ILayoutProcessor

use of org.eclipse.elk.core.alg.ILayoutProcessor in project elk by eclipse.

the class ElkLayered method hierarchicalLayout.

/**
 * Processors can be marked as operating on the full hierarchy by using the {@link IHierarchyAwareLayoutProcessor}
 * interface.
 *
 * All graphs are collected using a breadth-first search and this list is reversed, so that for each graph, all
 * following graphs are on the same hierarchy level or higher, i.e. closer to the parent graph. Each graph then has
 * a unique configuration of ELK Layered, which is comprised of a sequence of processors. The processors can vary
 * depending on the characteristics of each graph. The list of graphs and their algorithms is then traversed. If a
 * processor is not hierarchical it is simply executed. If it it is hierarchical and this graph is not the root
 * graph, this processor is skipped and the algorithm is paused until the processor has been executed on the root
 * graph. Then the algorithm is continued, starting with the level lowest in the hierarchy, i.e. furthest away from
 * the root graph.
 */
private void hierarchicalLayout(final LGraph lgraph, final IElkProgressMonitor monitor) {
    // Perform a reversed breadth first search: The graphs in the lowest hierarchy come first.
    Collection<LGraph> graphs = collectAllGraphsBottomUp(lgraph);
    // We have to make sure that hierarchical processors don't break the control flow
    // of the following layout execution (see e.g. #228). To be precise, if the root node of
    // the hierarchical graph doesn't include a hierarchical processor, nor may any of the children.
    reviewAndCorrectHierarchicalProcessors(lgraph, graphs);
    // Get list of processors for each graph, since they can be different.
    // Iterators are used, so that processing of a graph can be paused and continued easily.
    int work = 0;
    List<Pair<LGraph, Iterator<ILayoutProcessor<LGraph>>>> graphsAndAlgorithms = new ArrayList<>();
    for (LGraph g : graphs) {
        graphConfigurator.prepareGraphForLayout(g);
        List<ILayoutProcessor<LGraph>> processors = g.getProperty(InternalProperties.PROCESSORS);
        work += processors.size();
        Iterator<ILayoutProcessor<LGraph>> algorithm = processors.iterator();
        graphsAndAlgorithms.add(Pair.of(g, algorithm));
    }
    monitor.begin("Recursive hierarchical layout", work);
    // When the root graph has finished layout, the layout is complete.
    int slotIndex = 0;
    Iterator<ILayoutProcessor<LGraph>> rootProcessors = getProcessorsForRootGraph(graphsAndAlgorithms);
    while (rootProcessors.hasNext()) {
        // Layout from bottom up
        for (Pair<LGraph, Iterator<ILayoutProcessor<LGraph>>> graphAndAlgorithm : graphsAndAlgorithms) {
            Iterator<ILayoutProcessor<LGraph>> processors = graphAndAlgorithm.getSecond();
            LGraph graph = graphAndAlgorithm.getFirst();
            while (processors.hasNext()) {
                ILayoutProcessor<LGraph> processor = processors.next();
                if (!(processor instanceof IHierarchyAwareLayoutProcessor)) {
                    // elkjs-exclude-start
                    if (monitor.isLoggingEnabled()) {
                        DebugUtil.logDebugGraph(monitor, graph, slotIndex, "Before " + processor.getClass().getSimpleName());
                    }
                    // elkjs-exclude-end
                    notifyProcessorReady(graph, processor);
                    processor.process(graph, monitor.subTask(1));
                    notifyProcessorFinished(graph, processor);
                    slotIndex++;
                } else if (isRoot(graph)) {
                    // elkjs-exclude-start
                    if (monitor.isLoggingEnabled()) {
                        DebugUtil.logDebugGraph(monitor, graph, slotIndex, "Before " + processor.getClass().getSimpleName());
                    }
                    // elkjs-exclude-end
                    // If processor operates on the full hierarchy, it must be executed on the root
                    notifyProcessorReady(graph, processor);
                    processor.process(graph, monitor.subTask(1));
                    notifyProcessorFinished(graph, processor);
                    slotIndex++;
                    // Continue operation with the graph at the bottom of the hierarchy
                    break;
                } else {
                    // skip this processor and pause execution until root graph has processed.
                    break;
                }
            }
        }
    }
    // elkjs-exclude-start
    if (monitor.isLoggingEnabled()) {
        DebugUtil.logDebugGraph(monitor, lgraph, slotIndex, "Finished");
    }
    // elkjs-exclude-end
    monitor.done();
}
Also used : ILayoutProcessor(org.eclipse.elk.core.alg.ILayoutProcessor) ArrayList(java.util.ArrayList) LGraph(org.eclipse.elk.alg.layered.graph.LGraph) SizeConstraint(org.eclipse.elk.core.options.SizeConstraint) ListIterator(java.util.ListIterator) Iterator(java.util.Iterator) Pair(org.eclipse.elk.core.util.Pair)

Example 5 with ILayoutProcessor

use of org.eclipse.elk.core.alg.ILayoutProcessor in project elk by eclipse.

the class ElkLayered method runLayoutTestUntil.

/**
 * Runs the algorithm on the current test graphs up to the point where the given phase or
 * processor has finished executing. If parts of the algorithm were already executed using this
 * or other layout test methods, execution is resumed from there. If the given phase or
 * processor is not among those processors that have not yet executed, an exception is thrown.
 * Also, if there is no current layout test run, an exception is thrown.
 *
 * @param phase the phase or processor to stop after
 * @param inclusive {@code true} if the specified phase should be executed as well
 * @param state the current test execution state
 * @throws IllegalArgumentException
 *             if the given layout processor is not part of the processors that are still to be
 *             executed.
 */
public void runLayoutTestUntil(final Class<? extends ILayoutProcessor<LGraph>> phase, final boolean inclusive, final TestExecutionState state) {
    List<ILayoutProcessor<LGraph>> algorithm = state.graphs.get(0).getProperty(InternalProperties.PROCESSORS);
    // check if the given phase exists in our current algorithm configuration
    boolean phaseExists = false;
    ListIterator<ILayoutProcessor<LGraph>> algorithmIterator = algorithm.listIterator(state.step);
    int phaseIndex = state.step;
    while (algorithmIterator.hasNext() && !phaseExists) {
        if (algorithmIterator.next().getClass().equals(phase)) {
            phaseExists = true;
            if (inclusive) {
                phaseIndex++;
            }
        } else {
            phaseIndex++;
        }
    }
    if (!phaseExists) {
        // FIXME actually, we want to know when a processor is not
        // part of the algorithm's configuration because this might be
        // wrong behavior.
        // However, in the current test framework there is no way
        // to differentiate between 'it's ok' and 'it's not'.
        // throw new IllegalArgumentException(
        // "Given processor not part of the remaining algorithm.");
        System.err.println("Given processor " + phase + " not part of the remaining algorithm.");
    }
    // perform the layout up to and including that phase
    algorithmIterator = algorithm.listIterator(state.step);
    for (; state.step < phaseIndex; state.step++) {
        layoutTest(state.graphs, algorithmIterator.next());
    }
}
Also used : ILayoutProcessor(org.eclipse.elk.core.alg.ILayoutProcessor) SizeConstraint(org.eclipse.elk.core.options.SizeConstraint)

Aggregations

ILayoutProcessor (org.eclipse.elk.core.alg.ILayoutProcessor)6 LGraph (org.eclipse.elk.alg.layered.graph.LGraph)3 SizeConstraint (org.eclipse.elk.core.options.SizeConstraint)3 ElkNode (org.eclipse.elk.graph.ElkNode)2 Sets (com.google.common.collect.Sets)1 ArrayList (java.util.ArrayList)1 Iterator (java.util.Iterator)1 List (java.util.List)1 ListIterator (java.util.ListIterator)1 Set (java.util.Set)1 TEdge (org.eclipse.elk.alg.common.TEdge)1 IOverlapHandler (org.eclipse.elk.alg.common.spore.IOverlapHandler)1 InternalProperties (org.eclipse.elk.alg.common.spore.InternalProperties)1 ScanlineOverlapCheck (org.eclipse.elk.alg.common.spore.ScanlineOverlapCheck)1 SVGImage (org.eclipse.elk.alg.common.utils.SVGImage)1 LNode (org.eclipse.elk.alg.layered.graph.LNode)1 Layer (org.eclipse.elk.alg.layered.graph.Layer)1 Graph (org.eclipse.elk.alg.spore.graph.Graph)1 OverlapRemovalStrategy (org.eclipse.elk.alg.spore.options.OverlapRemovalStrategy)1 RootSelection (org.eclipse.elk.alg.spore.options.RootSelection)1