use of org.osate.ge.internal.diagram.runtime.DiagramNode in project osate2 by osate.
the class ModeContributionItem method refresh.
void refresh() {
final ComboViewer comboViewer = getComboViewer();
final SortedSet<ModeFeatureReference> modeFeatureReferences = new TreeSet<>((o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName()));
if (comboViewer != null) {
final ModeFeatureReference nullValue = AadlModalElementUtil.createModeFeatureReference(getNullValueString(), null, null);
modeFeatureReferences.add(nullValue);
Object selectedValue = nullValue;
final String selectedModeName = editor == null ? null : editor.getPartProperty(SELECTED_MODE_PROPERTY_KEY);
// Clear the combo box
comboViewer.setInput(null);
if (editor == null) {
return;
}
final AgeDiagram diagram = editor.getDiagram();
if (diagram != null) {
final QueryService queryService = ContributionUtil.getQueryService(editor);
if (queryService != null) {
queryService.getResults(MODE_CONTAINER_QUERY, diagram, null).stream().flatMap(modeContainer -> {
// If container contains a modal element
if (AadlModalElementUtil.getModalElement(modeContainer.getBusinessObjectContext()) != null) {
// Get qualified modes to add to the drop-down
return Stream.concat(getModeBindingFeatureReferences((DiagramNode) modeContainer.getBusinessObjectContext()), getModeFeatureReferences((DiagramNode) modeContainer.getBusinessObjectContext()));
}
return Stream.empty();
}).forEach(modeFeatureRef -> {
modeFeatureReferences.add(modeFeatureRef);
});
// Find ComboViewer selection
final Optional<ModeFeatureReference> tmpSelectedValue = modeFeatureReferences.stream().filter(tmpKey -> tmpKey.getName().equalsIgnoreCase(selectedModeName)).findAny();
if (tmpSelectedValue.isPresent()) {
selectedValue = tmpSelectedValue.get();
}
comboViewer.setLabelProvider(new LabelProvider() {
@Override
public String getText(final Object element) {
final ModeFeatureReference mf = (ModeFeatureReference) element;
return mf.getName();
}
});
comboViewer.setInput(modeFeatureReferences);
}
}
final StructuredSelection newSelection = new StructuredSelection(selectedValue);
if (!Objects.equal(newSelection, comboViewer.getSelection())) {
comboViewer.setSelection(newSelection);
onSelection(newSelection.getFirstElement());
}
}
}
use of org.osate.ge.internal.diagram.runtime.DiagramNode in project osate2 by osate.
the class DiagramElementLayoutUtil method getAbsolutePosition.
/**
* Gets the absolute position of a node. This absolute position only considers the positions of shapes.
* Connections are ignored.
* @param dn the node for which to get the absolute position.
* @return the absolute position.
*/
public static Point getAbsolutePosition(final DiagramNode dn) {
int x = 0;
int y = 0;
for (DiagramNode tmp = dn; tmp instanceof DiagramElement; tmp = tmp.getParent()) {
final DiagramElement tmpDe = (DiagramElement) tmp;
if (tmpDe.getGraphic() instanceof AgeShape) {
// Ignore connections in case the X and Y values are not 0.
x += tmpDe.getX();
y += tmpDe.getY();
}
}
return new Point(x, y);
}
use of org.osate.ge.internal.diagram.runtime.DiagramNode in project osate2 by osate.
the class DiagramElementLayoutUtil method layout.
private static void layout(final DiagramModification m, final Collection<? extends DiagramNode> nodesToLayout, final StyleProvider styleProvider, final LayoutInfoProvider layoutInfoProvider, final LayoutOptions options) {
Objects.requireNonNull(nodesToLayout, "nodesToLayout must not be null");
try {
// Layout the nodes
final RecursiveGraphLayoutEngine layoutEngine = new RecursiveGraphLayoutEngine();
for (final DiagramNode dn : nodesToLayout) {
LayoutMapping mapping;
ElkNode layoutGraph;
// Perform the first layout. This layout will not include nested ports. This will allow ELK additional flexibility when determining port
// placement.
mapping = ElkGraphBuilder.buildLayoutGraph(dn, styleProvider, layoutInfoProvider, options, !options.layoutPortsOnDefaultSides, ElkGraphBuilder.FixedPortPositionProvider.NO_OP);
layoutGraph = mapping.getLayoutGraph();
layoutGraph.setProperty(CoreOptions.ALGORITHM, LAYOUT_ALGORITHM);
applyProperties(dn, mapping);
LayoutDebugUtil.saveElkGraphToDebugProject(layoutGraph, "pass1");
layoutEngine.layout(layoutGraph, new BasicProgressMonitor());
// nested ports and performing edge routing.
if (layoutGraph.getProperty(AgeLayoutOptions.NESTED_PORTS_WERE_OMITTED)) {
final LayoutMapping initialLayoutMapping = mapping;
mapping = ElkGraphBuilder.buildLayoutGraph(dn, styleProvider, layoutInfoProvider, options, false, new ElkGraphBuilder.FixedPortPositionProvider() {
@Override
public PortSide getPortSide(final DiagramElement de) {
final ElkGraphElement ge = initialLayoutMapping.getGraphMap().inverse().get(de);
if (ge instanceof ElkPort) {
return ge.getProperty(CoreOptions.PORT_SIDE);
}
return null;
}
@Override
public Double getPortPosition(final DiagramElement de) {
final ElkGraphElement ge = initialLayoutMapping.getGraphMap().inverse().get(de);
if (ge instanceof ElkPort) {
final ElkPort port = (ElkPort) ge;
final PortSide ps = port.getProperty(CoreOptions.PORT_SIDE);
if (PortSide.SIDES_EAST_WEST.contains(ps)) {
return port.getY();
} else {
return port.getX();
}
}
return null;
}
});
layoutGraph = mapping.getLayoutGraph();
layoutGraph.setProperty(CoreOptions.ALGORITHM, LAYOUT_ALGORITHM);
applyProperties(dn, mapping);
LayoutDebugUtil.saveElkGraphToDebugProject(layoutGraph, "pass2");
layoutEngine.layout(layoutGraph, new BasicProgressMonitor());
}
LayoutDebugUtil.saveElkGraphToDebugProject(layoutGraph, "final");
applyShapeLayout(mapping, m);
applyConnectionLayout(mapping, m);
// Layout feature self loop connections. These are omitted from the ELK based layout.
dn.getAllDiagramNodes().filter(DiagramElementLayoutUtil::isFeatureSelfLoopConnection).map(DiagramElement.class::cast).forEachOrdered(de -> layoutFeatureSelfLoopConnection(de, m, layoutInfoProvider));
}
} catch (final RuntimeException ex) {
// If a layout error occurs, display the exception but do not rethrow. This is so that the operation that attempted to do the layout will continue.
// This is important because otherwise simple operations such a adding elements to the diagram will completely fail. Suppressing the error will
// degrade performance but allow the user to keep working and should ensure things stay in a valid state.
// It would be best for other parts of the code to handle exceptions properly to avoid entering into an invalid state but this is the best
// workaround.
final Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, "A layout error occured.", ex);
StatusManager.getManager().handle(status, StatusManager.SHOW | StatusManager.LOG);
}
}
use of org.osate.ge.internal.diagram.runtime.DiagramNode in project osate2 by osate.
the class DiagramElementLayoutUtil method layoutIncrementally.
/**
* Performs layout on elements in the specified diagram which have not been laid out.
* @param diagram the diagram for which to perform the incremental layout
* @param mod the modification to use to modify the diagram
* @param layoutInfoProvider the layout info provider which provides additional information required for laying out the diagram
*/
public static void layoutIncrementally(final AgeDiagram diagram, final DiagramModification mod, final LayoutInfoProvider layoutInfoProvider) {
Objects.requireNonNull(diagram, "diagram must not be null");
Objects.requireNonNull(mod, "mod must not be null");
Objects.requireNonNull(layoutInfoProvider, "layoutInfoProvider must not be null");
final IncrementalLayoutMode currentLayoutMode = LayoutPreferences.getCurrentIncrementalLayoutMode();
// Get all the nodes that need to be layed out.
final Set<DiagramNode> unfilteredNodesToLayout = getNodesToLayoutIncrementally(diagram, currentLayoutMode, new HashSet<>());
if (unfilteredNodesToLayout.size() == 0) {
return;
}
// Lay our flow indicators. In the container is eventually layed out, this will be replaced but in cases where that is not the case,
// we provide a default layout. Flow indicators are connections and as such will be filtered in the next step.
layoutFlowIndicators(mod, unfilteredNodesToLayout.stream().filter(DiagramNodePredicates::isFlowIndicator).map(DiagramElement.class::cast), layoutInfoProvider);
final Collection<DiagramNode> nodesToLayout = DiagramElementLayoutUtil.filterUnnecessaryNodes(unfilteredNodesToLayout, currentLayoutMode == IncrementalLayoutMode.LAYOUT_DIAGRAM);
if (nodesToLayout.size() == 0) {
// If the filtered node list is empty then the unfiltered list still contain feature self loop connections that need to be layed out.
unfilteredNodesToLayout.stream().filter(DiagramElementLayoutUtil::isFeatureSelfLoopConnection).map(DiagramElement.class::cast).forEachOrdered(de -> layoutFeatureSelfLoopConnection(de, mod, layoutInfoProvider));
return;
}
final LayoutOptions layoutOptions = LayoutOptions.createFromPreferences();
if (currentLayoutMode == IncrementalLayoutMode.LAYOUT_DIAGRAM) {
layout(INCREMENTAL_LAYOUT_LABEL, diagram, layoutInfoProvider, layoutOptions);
} else {
layout(mod, nodesToLayout, new StyleCalculator(diagram.getConfiguration(), StyleProvider.EMPTY), layoutInfoProvider, layoutOptions);
// Set Positions of elements which do not have a position set.
for (final DiagramNode dn : nodesToLayout) {
if (dn instanceof DiagramElement) {
final DiagramElement de = (DiagramElement) dn;
if (!de.hasPosition()) {
if (de.getDockArea() == null) {
mod.setPosition(de, new Point(0.0, 0.0));
} else if (de.getDockArea() != DockArea.GROUP && de.getParent() instanceof DiagramElement) {
final DiagramElement parent = (DiagramElement) de.getParent();
final DockingPosition defaultDockingPosition = de.getGraphicalConfiguration().getDefaultDockingPosition();
final DockArea defaultDockArea = DockArea.fromDockingPosition(defaultDockingPosition);
if (parent.hasSize()) {
final Stream<DiagramElement> otherElementsAlongSide = parent.getChildren().stream().filter(c -> c.hasPosition() && c.hasSize() && c.getDockArea() == defaultDockArea);
// Determine the position of the new element along it's preferred docking position.
double locationAlongSide;
if (defaultDockingPosition == DockingPosition.TOP || defaultDockingPosition == DockingPosition.BOTTOM) {
locationAlongSide = otherElementsAlongSide.max(Comparator.comparingDouble(c -> c.getY())).map(c -> c.getX() + c.getWidth()).orElse(0.0);
} else {
locationAlongSide = otherElementsAlongSide.max(Comparator.comparingDouble(c -> c.getY())).map(c -> c.getY() + c.getHeight()).orElse(0.0);
}
// Set position based on the docking position
switch(defaultDockingPosition) {
case TOP:
mod.setPosition(de, new Point(locationAlongSide, 0));
break;
case BOTTOM:
mod.setPosition(de, new Point(locationAlongSide, parent.getHeight()));
break;
case LEFT:
mod.setPosition(de, new Point(0, locationAlongSide));
break;
case RIGHT:
mod.setPosition(de, new Point(parent.getWidth(), locationAlongSide));
break;
default:
break;
}
}
mod.setDockArea(de, defaultDockArea);
}
}
}
}
}
}
use of org.osate.ge.internal.diagram.runtime.DiagramNode in project osate2 by osate.
the class SaveImageHandler method execute.
@Override
public Object execute(final ExecutionEvent event) throws ExecutionException {
final IEditorPart activeEditor = HandlerUtil.getActiveEditor(event);
if (!(activeEditor instanceof InternalDiagramEditor)) {
throw new RuntimeException("Unexpected editor: " + activeEditor);
}
final InternalDiagramEditor editor = (InternalDiagramEditor) activeEditor;
final InternalDiagramExportService diagramExportService = getDiagramExportService().orElseThrow();
final DiagramNode selectionOnlyExportNode = editor.getSelectedDiagramElements().stream().findFirst().filter(DiagramElementPredicates::isShape).orElse(null);
// Get the dimensions of the diagram and the current selection
final Dimension diagramDimension = diagramExportService.getDimensions(editor, editor.getDiagram());
final Dimension selectionDimension = selectionOnlyExportNode == null ? null : diagramExportService.getDimensions(editor, selectionOnlyExportNode);
final Shell parentShell = Display.getCurrent().getActiveShell();
// Display the export diagram dialog
ExportDiagramDialog.open(parentShell, diagramDimension, selectionDimension).ifPresent(r -> {
final FileDialog saveDialog = new FileDialog(parentShell, SWT.SAVE);
saveDialog.setOverwrite(true);
// TOOD; Based on format
saveDialog.setFilterExtensions(new String[] { "*" + r.getFormat().getDotExtension() });
final String filepath = saveDialog.open();
if (filepath != null) {
// Export the image
try (FileOutputStream s = new FileOutputStream(filepath, false)) {
final DiagramNode exportNode = r.getAll() ? editor.getDiagram() : selectionOnlyExportNode;
diagramExportService.export(editor, s, r.getFormat().getExporterFormat(), exportNode, r.getScaling());
} catch (final Exception ex) {
final Status status = new Status(IStatus.ERROR, FrameworkUtil.getBundle(getClass()).getSymbolicName(), "Error Exporting Diagram", ex);
StatusManager.getManager().handle(status, StatusManager.LOG | StatusManager.SHOW);
}
}
});
return null;
}
Aggregations