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;
}
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);
}
}
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();
}
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();
}
}
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();
}
Aggregations