Search in sources :

Example 1 with LayoutAlgorithmData

use of org.eclipse.elk.core.data.LayoutAlgorithmData in project elk by eclipse.

the class AlgorithmSelectionDialog method createSelectionTree.

/**
 * Create the dialog area that displays the selection tree and filter text.
 *
 * @param parent the parent composite
 * @return the control for the selection area
 */
private Control createSelectionTree(final Composite parent) {
    Composite composite = new Composite(parent, SWT.NONE);
    // create filter text
    final Text filterText = new Text(composite, SWT.BORDER);
    filterText.setText(Messages.getString("elk.ui.59"));
    filterText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
    filterText.setForeground(parent.getDisplay().getSystemColor(SWT.COLOR_GRAY));
    // create tree viewer
    final TreeViewer treeViewer = new TreeViewer(composite, SWT.SINGLE | SWT.V_SCROLL | SWT.BORDER);
    final AlgorithmContentProvider contentProvider = new AlgorithmContentProvider();
    treeViewer.setContentProvider(contentProvider);
    treeViewer.setLabelProvider(new LabelProvider() {

        @Override
        public String getText(final Object element) {
            if (element instanceof LayoutAlgorithmData) {
                LayoutAlgorithmData algoData = (LayoutAlgorithmData) element;
                String bundleName = algoData.getBundleName();
                if (bundleName == null) {
                    return algoData.getName();
                } else {
                    return algoData.getName() + " (" + bundleName + ")";
                }
            } else if (element instanceof LayoutCategoryData) {
                LayoutCategoryData typeData = (LayoutCategoryData) element;
                if (typeData.getName() == null) {
                    return "Other";
                } else {
                    return typeData.getName();
                }
            }
            return super.getText(element);
        }
    });
    treeViewer.setComparator(new ViewerComparator() {

        public int category(final Object element) {
            if (element instanceof LayoutCategoryData) {
                LayoutCategoryData typeData = (LayoutCategoryData) element;
                // the "Other" layout type has empty identifier and is put to the bottom
                return typeData.getId().length() == 0 ? 1 : 0;
            }
            return super.category(element);
        }
    });
    treeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
    treeViewer.setInput(LayoutMetaDataService.getInstance());
    treeViewer.expandAll();
    treeViewer.addDoubleClickListener(new IDoubleClickListener() {

        public void doubleClick(final DoubleClickEvent event) {
            okPressed();
        }
    });
    // set up a filter on the tree viewer using the filter text
    final Maybe<Boolean> filterChanged = new Maybe<Boolean>(Boolean.FALSE);
    final Maybe<Boolean> filterLeft = new Maybe<Boolean>(Boolean.FALSE);
    filterText.addModifyListener(new ModifyListener() {

        public void modifyText(final ModifyEvent e) {
            if (!filterChanged.get()) {
                filterChanged.set(Boolean.TRUE);
                filterText.setForeground(null);
                int pos = filterText.getCaretPosition();
                String newText = filterText.getText(pos - 1, pos - 1);
                filterText.setText(newText);
                filterText.setSelection(pos);
            } else {
                contentProvider.updateFilter(filterText.getText());
                treeViewer.refresh();
                treeViewer.expandAll();
                ILayoutMetaData selected = contentProvider.getBestFilterMatch();
                if (selected != null) {
                    treeViewer.setSelection(new StructuredSelection(selected));
                }
            }
        }
    });
    filterText.addFocusListener(new FocusListener() {

        public void focusGained(final FocusEvent e) {
            if (filterLeft.get() && !filterChanged.get()) {
                filterChanged.set(Boolean.TRUE);
                filterText.setForeground(null);
                filterText.setText("");
            }
        }

        public void focusLost(final FocusEvent e) {
            filterLeft.set(Boolean.TRUE);
        }
    });
    treeViewer.addFilter(new ViewerFilter() {

        public boolean select(final Viewer viewer, final Object parentElement, final Object element) {
            return contentProvider.applyFilter(element);
        }
    });
    // add a selection listener to the tree so that the selected element is displayed
    treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {

        public void selectionChanged(final SelectionChangedEvent event) {
            IStructuredSelection selection = (IStructuredSelection) event.getSelection();
            Object element = selection.getFirstElement();
            if (element instanceof ILayoutMetaData) {
                updateValue((ILayoutMetaData) element);
            }
        }
    });
    composite.setLayout(new GridLayout());
    GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
    gridData.minimumWidth = SELECTION_WIDTH;
    composite.setLayoutData(gridData);
    // register all selection listeners that have been stored in a list
    selectionProvider = treeViewer;
    for (ISelectionChangedListener listener : selectionListeners) {
        selectionProvider.addSelectionChangedListener(listener);
    }
    return composite;
}
Also used : ModifyListener(org.eclipse.swt.events.ModifyListener) ViewerFilter(org.eclipse.jface.viewers.ViewerFilter) TreeViewer(org.eclipse.jface.viewers.TreeViewer) StructuredSelection(org.eclipse.jface.viewers.StructuredSelection) IStructuredSelection(org.eclipse.jface.viewers.IStructuredSelection) Viewer(org.eclipse.jface.viewers.Viewer) TreeViewer(org.eclipse.jface.viewers.TreeViewer) SelectionChangedEvent(org.eclipse.jface.viewers.SelectionChangedEvent) IStructuredSelection(org.eclipse.jface.viewers.IStructuredSelection) FocusEvent(org.eclipse.swt.events.FocusEvent) ModifyEvent(org.eclipse.swt.events.ModifyEvent) GridLayout(org.eclipse.swt.layout.GridLayout) IDoubleClickListener(org.eclipse.jface.viewers.IDoubleClickListener) LayoutCategoryData(org.eclipse.elk.core.data.LayoutCategoryData) Maybe(org.eclipse.elk.core.util.Maybe) Composite(org.eclipse.swt.widgets.Composite) ViewerComparator(org.eclipse.jface.viewers.ViewerComparator) ISelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener) Text(org.eclipse.swt.widgets.Text) DoubleClickEvent(org.eclipse.jface.viewers.DoubleClickEvent) LayoutAlgorithmData(org.eclipse.elk.core.data.LayoutAlgorithmData) GridData(org.eclipse.swt.layout.GridData) ILayoutMetaData(org.eclipse.elk.core.data.ILayoutMetaData) LabelProvider(org.eclipse.jface.viewers.LabelProvider) FocusListener(org.eclipse.swt.events.FocusListener)

Example 2 with LayoutAlgorithmData

use of org.eclipse.elk.core.data.LayoutAlgorithmData in project elk by eclipse.

the class AlgorithmSelectionDialog method updateValue.

/**
 * Update the currently displayed value of the description area according
 * to the tree selection.
 *
 * @param layoutData the currently selected layout data
 */
private void updateValue(final ILayoutMetaData layoutData) {
    layouterHint = layoutData.getId();
    String name = layoutData.getName();
    if (name == null || name.length() == 0) {
        name = layoutData instanceof LayoutAlgorithmData ? Messages.getString("elk.ui.61") : Messages.getString("elk.ui.8");
    }
    displayNameLabel.setText(name);
    String description = layoutData.getDescription();
    if (description == null || description.length() == 0) {
        description = Messages.getString("elk.ui.60");
    }
    descriptionLabel.setText(description);
    Image image = imageCache.get(layoutData);
    if (image == null && layoutData instanceof LayoutAlgorithmData) {
        LayoutAlgorithmData algorithmData = (LayoutAlgorithmData) layoutData;
        String path = algorithmData.getPreviewImagePath();
        String bundleId = algorithmData.getDefiningBundleId();
        if (!Strings.isNullOrEmpty(path) && !Strings.isNullOrEmpty(bundleId)) {
            ImageDescriptor imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin(bundleId, path);
            if (imageDescriptor != null) {
                image = createAndScaleImage(imageDescriptor);
                if (image != null) {
                    imageCache.put(layoutData, image);
                }
            }
        }
    }
    imageLabel.setImage(image);
    imageLabel.getParent().layout();
    // Enable the OK button only if a layout algorithm is selected
    Button okButton = getButton(IDialogConstants.OK_ID);
    if (okButton != null) {
        okButton.setEnabled(layoutData instanceof LayoutAlgorithmData);
    }
}
Also used : LayoutAlgorithmData(org.eclipse.elk.core.data.LayoutAlgorithmData) Button(org.eclipse.swt.widgets.Button) ImageDescriptor(org.eclipse.jface.resource.ImageDescriptor) Image(org.eclipse.swt.graphics.Image)

Example 3 with LayoutAlgorithmData

use of org.eclipse.elk.core.data.LayoutAlgorithmData in project elk by eclipse.

the class LayoutOptionLabelProvider method getText.

@Override
@SuppressWarnings("rawtypes")
public String getText(final Object element) {
    switch(optionData.getType()) {
        case STRING:
            if (CoreOptions.ALGORITHM.equals(optionData) || optionData.getId().equals(LayoutPropertyDescriptor.DISCO_LAYOUT_ALG_ID)) {
                LayoutMetaDataService layoutDataService = LayoutMetaDataService.getInstance();
                LayoutAlgorithmData algorithmData = layoutDataService.getAlgorithmData((String) element);
                if (algorithmData != null) {
                    String bundleName = algorithmData.getBundleName();
                    if (bundleName == null) {
                        return algorithmData.getName();
                    } else {
                        return algorithmData.getName() + " (" + bundleName + ")";
                    }
                }
                return Messages.getString("elk.ui.8");
            }
            break;
        case BOOLEAN:
            if (element instanceof Boolean) {
                return ((Boolean) element).toString();
            }
        // fall through so the same method as for enums is applied
        case ENUM:
            if (element instanceof Integer) {
                return optionData.getChoices()[(Integer) element];
            }
            break;
        case ENUMSET:
            if (element instanceof String) {
                return (String) element;
            } else if (element instanceof String[]) {
                String[] arr = (String[]) element;
                if (arr.length == 0) {
                    return "";
                } else {
                    StringBuilder builder = new StringBuilder();
                    for (String s : arr) {
                        builder.append(", ").append(s);
                    }
                    return builder.substring(2);
                }
            } else if (element instanceof EnumSet) {
                EnumSet set = (EnumSet) element;
                if (set.isEmpty()) {
                    return "";
                }
                StringBuilder builder = new StringBuilder();
                for (Object o : set) {
                    builder.append(", " + ((Enum) o).name());
                }
                return builder.substring(2);
            }
    }
    return element.toString();
}
Also used : LayoutAlgorithmData(org.eclipse.elk.core.data.LayoutAlgorithmData) EnumSet(java.util.EnumSet) LayoutMetaDataService(org.eclipse.elk.core.data.LayoutMetaDataService)

Example 4 with LayoutAlgorithmData

use of org.eclipse.elk.core.data.LayoutAlgorithmData in project elk by eclipse.

the class RecursiveGraphLayoutEngine method layoutRecursively.

/**
 * Recursive function to enable layout of hierarchy. The leafs are laid out first to use their
 * layout information in the levels above.
 *
 * <p>This method returns self loops routed inside the given layout node. Those will have
 * coordinates relative to the node's top left corner, which is incorrect. Once the node's
 * final coordinates in its container are determined, any inside self loops will have to be offset
 * by the node's position.</p>
 *
 * @param layoutNode the node with children to be laid out
 * @param testController an optional test controller if this layout run is part of a unit test
 * @param progressMonitor monitor used to keep track of progress
 * @return list of self loops routed inside the node.
 */
protected List<ElkEdge> layoutRecursively(final ElkNode layoutNode, final TestController testController, final IElkProgressMonitor progressMonitor) {
    if (progressMonitor.isCanceled()) {
        return Collections.emptyList();
    }
    // Check if the node should be laid out at all
    if (layoutNode.getProperty(CoreOptions.NO_LAYOUT)) {
        return Collections.emptyList();
    }
    // We have to process the node if it has children...
    final boolean hasChildren = !layoutNode.getChildren().isEmpty();
    // ...or if inside self loop processing is enabled and it actually has inside self loops
    final List<ElkEdge> insideSelfLoops = gatherInsideSelfLoops(layoutNode);
    final boolean hasInsideSelfLoops = !insideSelfLoops.isEmpty();
    if (hasChildren || hasInsideSelfLoops) {
        // Fetch the layout algorithm that should be used to compute a layout for its content
        final LayoutAlgorithmData algorithmData = layoutNode.getProperty(CoreOptions.RESOLVED_ALGORITHM);
        if (algorithmData == null) {
            throw new UnsupportedConfigurationException("Resolved algorithm is not set;" + " apply a LayoutAlgorithmResolver before computing layout.");
        }
        final boolean supportsInsideSelfLoops = algorithmData.supportsFeature(GraphFeature.INSIDE_SELF_LOOPS);
        // Persist the Hierarchy Handling in the nodes by querying the parent node
        evaluateHierarchyHandlingInheritance(layoutNode);
        // algorithm doesn't actually support inside self loops, we cancel
        if (!hasChildren && hasInsideSelfLoops && !supportsInsideSelfLoops) {
            return Collections.emptyList();
        }
        // We collect inside self loops of children and post-process them later
        List<ElkEdge> childrenInsideSelfLoops = Lists.newArrayList();
        // If the layout provider supports hierarchy, it is expected to layout the node's compound
        // node children as well
        int nodeCount;
        if (layoutNode.getProperty(CoreOptions.HIERARCHY_HANDLING) == HierarchyHandling.INCLUDE_CHILDREN && (algorithmData.supportsFeature(GraphFeature.COMPOUND) || algorithmData.supportsFeature(GraphFeature.CLUSTERS))) {
            // The layout algorithm will compute a layout for multiple levels of hierarchy under the current one
            nodeCount = countNodesWithHierarchy(layoutNode);
            // Look for nodes that stop the hierarchy handling, evaluating the inheritance on the way
            final Queue<ElkNode> nodeQueue = Lists.newLinkedList();
            nodeQueue.addAll(layoutNode.getChildren());
            while (!nodeQueue.isEmpty()) {
                ElkNode node = nodeQueue.poll();
                // Persist the Hierarchy Handling in every case. (Won't hurt with nodes that are
                // evaluated in the next recursion)
                evaluateHierarchyHandlingInheritance(node);
                final boolean stopHierarchy = node.getProperty(CoreOptions.HIERARCHY_HANDLING) == HierarchyHandling.SEPARATE_CHILDREN;
                // In that case, a separate recursive call is used for child nodes
                if (stopHierarchy || (node.hasProperty(CoreOptions.ALGORITHM) && !algorithmData.equals(node.getProperty(CoreOptions.RESOLVED_ALGORITHM)))) {
                    List<ElkEdge> childLayoutSelfLoops = layoutRecursively(node, testController, progressMonitor);
                    childrenInsideSelfLoops.addAll(childLayoutSelfLoops);
                    // Explicitly disable hierarchical layout for the child node. Simplifies the
                    // handling of switching algorithms in the layouter.
                    node.setProperty(CoreOptions.HIERARCHY_HANDLING, HierarchyHandling.SEPARATE_CHILDREN);
                    // Apply the LayoutOptions.SCALE_FACTOR if present
                    ElkUtil.applyConfiguredNodeScaling(node);
                } else {
                    // Child should be included in current layout, possibly adding its own children
                    nodeQueue.addAll(node.getChildren());
                }
            }
        } else {
            // Layout each compound node contained in this node separately
            nodeCount = layoutNode.getChildren().size();
            for (ElkNode child : layoutNode.getChildren()) {
                List<ElkEdge> childLayoutSelfLoops = layoutRecursively(child, testController, progressMonitor);
                childrenInsideSelfLoops.addAll(childLayoutSelfLoops);
                // Apply the LayoutOptions.SCALE_FACTOR if present
                ElkUtil.applyConfiguredNodeScaling(child);
            }
        }
        if (progressMonitor.isCanceled()) {
            return Collections.emptyList();
        }
        // from being laid out again
        for (final ElkEdge selfLoop : childrenInsideSelfLoops) {
            selfLoop.setProperty(CoreOptions.NO_LAYOUT, true);
        }
        executeAlgorithm(layoutNode, algorithmData, testController, progressMonitor.subTask(nodeCount));
        // Post-process the inner self loops we collected
        postProcessInsideSelfLoops(childrenInsideSelfLoops);
        // Return our own inside self loops to be processed later
        if (hasInsideSelfLoops && supportsInsideSelfLoops) {
            return insideSelfLoops;
        } else {
            return Collections.emptyList();
        }
    } else {
        return Collections.emptyList();
    }
}
Also used : LayoutAlgorithmData(org.eclipse.elk.core.data.LayoutAlgorithmData) ElkNode(org.eclipse.elk.graph.ElkNode) ElkBendPoint(org.eclipse.elk.graph.ElkBendPoint) ElkEdge(org.eclipse.elk.graph.ElkEdge)

Example 5 with LayoutAlgorithmData

use of org.eclipse.elk.core.data.LayoutAlgorithmData in project elk by eclipse.

the class LayoutConfigurationManager method getOptionValue.

/**
 * Retrieve the currently valid value for the given layout option. If no value is found in the
 * given configuration store, a default value is taken.
 *
 * @param optionData a layout option descriptor
 * @param config a layout configuration store from which to fetch values
 */
public Object getOptionValue(final LayoutOptionData optionData, final ILayoutConfigurationStore config) {
    Object result = getRawOptionValue(optionData, config);
    if (optionData.equals(CoreOptions.ALGORITHM)) {
        LayoutAlgorithmData algoData = LayoutMetaDataService.getInstance().getAlgorithmDataBySuffixOrDefault((String) result, layoutAlgorithmResolver.getDefaultLayoutAlgorithmID());
        if (algoData != null) {
            return algoData.getId();
        }
    } else if (result != null) {
        return result;
    }
    if (optionData.getTargets().contains(LayoutOptionData.Target.PARENTS)) {
        // Check default value of the content layout algorithm
        LayoutAlgorithmData algoData = getAlgorithm(config);
        if (algoData != null) {
            result = algoData.getDefaultValue(optionData);
            if (result != null) {
                return result;
            }
        }
    } else {
        // Check default value of the container layout algorithm
        ILayoutConfigurationStore parentConfig = config.getParent();
        if (parentConfig != null) {
            LayoutAlgorithmData algoData = getAlgorithm(parentConfig);
            if (algoData != null) {
                result = algoData.getDefaultValue(optionData);
                if (result != null) {
                    return result;
                }
            }
        }
    }
    // Fall back to default value of the option itself
    result = optionData.getDefault();
    if (result != null) {
        return result;
    }
    // Fall back to default-default value
    return optionData.getDefaultDefault();
}
Also used : LayoutAlgorithmData(org.eclipse.elk.core.data.LayoutAlgorithmData)

Aggregations

LayoutAlgorithmData (org.eclipse.elk.core.data.LayoutAlgorithmData)16 ElkNode (org.eclipse.elk.graph.ElkNode)5 AbstractLayoutProvider (org.eclipse.elk.core.AbstractLayoutProvider)4 LayoutMetaDataService (org.eclipse.elk.core.data.LayoutMetaDataService)4 List (java.util.List)2 Graph (org.eclipse.elk.alg.spore.graph.Graph)2 LayoutCategoryData (org.eclipse.elk.core.data.LayoutCategoryData)2 ElkUtil (org.eclipse.elk.core.util.ElkUtil)2 ElkBendPoint (org.eclipse.elk.graph.ElkBendPoint)2 Sets (com.google.common.collect.Sets)1 ArrayList (java.util.ArrayList)1 EnumSet (java.util.EnumSet)1 LinkedHashSet (java.util.LinkedHashSet)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 ElkGraphTransformer (org.eclipse.elk.alg.disco.transform.ElkGraphTransformer)1