use of org.osate.ge.internal.GraphicalEditorException in project osate2 by osate.
the class DefaultDiagramService method findDiagramsByContextBusinessObject.
@Override
public List<InternalDiagramReference> findDiagramsByContextBusinessObject(final Object bo) {
final CanonicalBusinessObjectReference boReference = referenceService.getCanonicalReference(bo);
if (boReference == null) {
throw new GraphicalEditorException("Unable to get canonical reference for business object : " + bo);
}
final IProject project = ProjectUtil.getProjectForBoOrThrow(bo);
// Build a set containing the project containing the business object and all projects which reference that project.
final HashSet<IProject> relevantProjects = new HashSet<>();
relevantProjects.add(project);
for (final IProject referencingProject : project.getReferencingProjects()) {
if (referencingProject.isAccessible()) {
relevantProjects.add(referencingProject);
}
}
final Map<IFile, InternalDiagramEditor> fileToEditorMap = getOpenEditorsMap(relevantProjects);
// Add saved diagram files if they are not open
return savedDiagramIndex.getDiagramsByContext(relevantProjects.stream(), boReference).stream().map(e -> new InternalDiagramReference(e, fileToEditorMap.get(e.getDiagramFile()))).collect(Collectors.toList());
}
use of org.osate.ge.internal.GraphicalEditorException in project osate2 by osate.
the class DefaultAadlModificationService method performModification.
private <TagType, BusinessObjectType extends EObject> ModificationResult performModification(final Modification<TagType, BusinessObjectType> modification, final Set<IProject> projectsToBuild) {
final TagType tag = modification.getTag();
// Determine the object to modify
final BusinessObjectType bo = modification.getTagToBusinessObjectMapper().apply(tag);
if (bo == null) {
return ModificationResult.createFailure();
}
if (!(bo.eResource() instanceof XtextResource)) {
throw new GraphicalEditorException("Unexpected case. Resource is not an XtextResource");
}
// Try to get the Xtext document
String rootQualifiedName = null;
URI rootResourceUri = null;
if (bo.eResource() != null) {
final Object root = bo.eResource() == null ? null : bo.eResource().getContents().get(0);
if (root instanceof NamedElement) {
final NamedElement rootNamedElement = (NamedElement) root;
rootQualifiedName = rootNamedElement.getQualifiedName();
rootResourceUri = rootNamedElement.eResource().getURI();
}
}
final IXtextDocument doc = AgeXtextUtil.getDocumentByRootElement(rootQualifiedName, rootResourceUri);
final String originalTextContents;
final ModifySafelyResults modifySafelyResult;
if (doc == null) {
// Modify the EMF resource directly
final XtextResource res = (XtextResource) bo.eResource();
try {
originalTextContents = getText(res);
} catch (RuntimeException ex) {
throw new GraphicalEditorException("Unable to modify model. Unable to get AADL source text. Check model for errors.", ex);
}
// Check if the AADL file is editable.
final IResource aadlResource = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(res.getURI().toPlatformString(true)));
if (aadlResource instanceof IFile) {
final IFile aadlFile = (IFile) aadlResource;
if (aadlFile.isReadOnly()) {
final IStatus status = ResourcesPlugin.getWorkspace().validateEdit(new IFile[] { aadlFile }, IWorkspace.VALIDATE_PROMPT);
if (!status.isOK() || aadlFile.isReadOnly()) {
final String extMessage = status.isOK() ? "" : status.getMessage();
throw new GraphicalEditorException("One or more AADL files are not read-only. " + extMessage);
}
}
}
modifySafelyResult = modifySafely(res, tag, bo, modification.getModifier(), true);
if (modifySafelyResult.modificationSuccessful) {
// Save the model
try {
res.save(SaveOptions.newBuilder().format().getOptions().toOptionsMap());
} catch (final IOException e) {
throw new GraphicalEditorException(e);
}
}
// Try to get the project for the resource and add it to the list of projects to build.
final URI resourceUri = res.getURI();
if (resourceUri != null) {
final IPath projectPath = new Path(resourceUri.toPlatformString(true)).uptoSegment(1);
final IResource projectResource = ResourcesPlugin.getWorkspace().getRoot().findMember(projectPath);
if (projectResource instanceof IProject) {
projectsToBuild.add((IProject) projectResource);
}
}
} else {
prepareToEditDocument(doc);
// If the element is in an annex, determine the root actual/parsed annex element
final EObject parsedAnnexRoot = getParsedAnnexRoot(bo);
// Store original contents
originalTextContents = doc.get();
// If the element which needs to be edited is in an annex, modify the default annex element. This is needed because objects inside
// of annexes may not have unique URI's
final EObject objectToModify = parsedAnnexRoot == null ? bo : parsedAnnexRoot.eContainer();
final URI modificationObjectUri = EcoreUtil.getURI(objectToModify);
modifySafelyResult = doc.modify(new IUnitOfWork<ModifySafelyResults, XtextResource>() {
@SuppressWarnings("unchecked")
@Override
public ModifySafelyResults exec(final XtextResource res) throws Exception {
final EObject objectToModify = res.getResourceSet().getEObject(modificationObjectUri, true);
if (objectToModify == null) {
return new ModifySafelyResults(false);
}
if (parsedAnnexRoot != null && (objectToModify instanceof DefaultAnnexLibrary || objectToModify instanceof DefaultAnnexSubclause)) {
return modifyAnnexInXtextDocument(res, objectToModify, tag, bo, modification.getModifier());
} else {
return modifySafely(res, tag, (BusinessObjectType) objectToModify, modification.getModifier(), false);
}
}
});
// Call the after modification callback
if (modifySafelyResult.modificationSuccessful) {
// Call readonly on the document. This will should cause Xtext's reconciler to be called to ensure the document matches the
// model and trigger model change events.
doc.readOnly(res -> null);
}
}
if (modifySafelyResult.modificationSuccessful) {
return ModificationResult.createSuccess(rootQualifiedName, rootResourceUri, originalTextContents);
} else {
return ModificationResult.createFailure();
}
}
use of org.osate.ge.internal.GraphicalEditorException in project osate2 by osate.
the class DiagramElementLayoutUtil method layoutFlowIndicators.
/**
* Sets the position and bendpoints of all specified flow indicators. Intended to provide a default position for flow indicators in cases
* where only contents are being layed out. This layout will be replaced by the ELK produced layout when the flow indicator's container
* is layed out.
*
* This function simply positions flow indicators such that they are in a after existing indicators.
* @param m is the modification to use to modify the diagram.
* @param flowIndicatorsToLayout is the stream of flow indicators to layout.
* @param layoutInfoProvider is the source for layout info needed to determine source anchor points.
*/
public static void layoutFlowIndicators(final DiagramModification m, final Stream<DiagramElement> flowIndicatorsToLayout, final LayoutInfoProvider layoutInfoProvider) {
Objects.requireNonNull(flowIndicatorsToLayout, "flowIndicators must not be null");
// Create set of a start elements in which we are interested.
final Set<DiagramNode> startElements = flowIndicatorsToLayout.map(n -> n.getStartElement()).collect(Collectors.toSet());
if (startElements.isEmpty()) {
return;
}
// Search diagram and build a multimap mapping start elements to the flow indicators which reference them.
final ArrayListMultimap<DiagramElement, DiagramElement> startElementToFlowIndicators = ArrayListMultimap.create();
m.getDiagram().getAllDescendants().filter(q -> q instanceof DiagramElement && DiagramElementPredicates.isFlowIndicator((DiagramElement) q)).forEachOrdered(q -> {
final DiagramElement e = (DiagramElement) q;
final DiagramElement start = e.getStartElement();
if (startElements.contains(start)) {
startElementToFlowIndicators.put(start, e);
}
});
// Process each start element
for (DiagramElement startElement : startElementToFlowIndicators.keySet()) {
// Skip start elements that haven't been positioned
if (!startElement.hasPosition()) {
continue;
}
// Skip if unable to determine what side the start element is on. Flow indicators are only supported when there is a source element which is docked.
final DockArea dockArea = getNonGroupDockArea(startElement);
if (dockArea == null) {
continue;
}
// Sort by X or Y based on dock area. Flow indicators without a position are sorted at the end.
final List<DiagramElement> flowIndicatorsForStartElement = startElementToFlowIndicators.get(startElement);
flowIndicatorsForStartElement.sort((e1, e2) -> {
if (e1.hasPosition() && e2.hasPosition()) {
if (dockArea.isLeftOrRight()) {
return Double.compare(e1.getY(), e2.getY());
} else {
return Double.compare(e1.getX(), e2.getX());
}
} else if (e1.hasPosition()) {
return -1;
} else if (e2.hasPosition()) {
return 1;
} else {
return 0;
}
});
// Flow indicators are positions based on the first undocked container. Need to find that container.
final DiagramElement indicatorContainer = DiagramElementUtil.getUndockedDiagramElement(flowIndicatorsForStartElement.get(0).getParent());
// Skip if we are unable to determine the container or if the container doesn't have a size.
if (indicatorContainer == null || !indicatorContainer.hasSize()) {
continue;
}
final Point containerAbsPosition = getAbsolutePosition(indicatorContainer);
//
// Determine how to adjust position of bendpoints and indicator positions based on the dock area
//
final Point startAnchorPosition = getPortAnchorOffset(startElement, dockArea, containerAbsPosition, layoutInfoProvider);
final double initialPositionOffsetX;
final double initialPositionOffsetY;
final double positionIncrementX;
final double positionIncrementY;
switch(dockArea) {
case LEFT:
initialPositionOffsetX = INCREMENTAL_FLOW_INDICATOR_PRIMARY_OFFSET;
initialPositionOffsetY = 0;
positionIncrementX = 0.0;
positionIncrementY = INCREMENTAL_FLOW_INDICATOR_SECONDARY_INCREMENT;
break;
case RIGHT:
initialPositionOffsetX = -INCREMENTAL_FLOW_INDICATOR_PRIMARY_OFFSET;
initialPositionOffsetY = 0;
positionIncrementX = 0;
positionIncrementY = INCREMENTAL_FLOW_INDICATOR_SECONDARY_INCREMENT;
break;
case TOP:
initialPositionOffsetX = 0;
initialPositionOffsetY = INCREMENTAL_FLOW_INDICATOR_PRIMARY_OFFSET;
positionIncrementX = INCREMENTAL_FLOW_INDICATOR_SECONDARY_INCREMENT;
positionIncrementY = 0;
break;
case BOTTOM:
initialPositionOffsetX = 0;
initialPositionOffsetY = -INCREMENTAL_FLOW_INDICATOR_PRIMARY_OFFSET;
positionIncrementX = INCREMENTAL_FLOW_INDICATOR_SECONDARY_INCREMENT;
positionIncrementY = 0;
break;
case GROUP:
default:
// Our dock area should never have the group value and all other values should be handled
throw new GraphicalEditorException("Unexpected case: " + dockArea);
}
// Calculate absolute position for the start anchor. Used for bendpoints
final Point startAnchorAbsPosition = new Point(containerAbsPosition.x + startAnchorPosition.x, containerAbsPosition.y + startAnchorPosition.y);
// Determine initial of the first flow indicator relative to it's container.
// This is only used when there all flow indicators do not have a position
final Point firstPosition = new Point(startAnchorPosition.x + initialPositionOffsetX, startAnchorPosition.y + initialPositionOffsetY);
Point nextPosition = firstPosition;
for (DiagramElement indicator : flowIndicatorsForStartElement) {
final Point currentPosition;
if (indicator.hasPosition()) {
currentPosition = indicator.getPosition();
} else {
// Set the position
currentPosition = nextPosition;
m.setPosition(indicator, nextPosition);
// The first flow indicator should not need bendpoints, to reset them
if (nextPosition.equals(firstPosition)) {
m.setBendpoints(indicator, ImmutableList.of());
} else {
// Set bendpoints
final Point bp1 = new Point(startAnchorAbsPosition.x + (initialPositionOffsetX * INCREMENTAL_FLOW_INDICATOR_BENDPOINT_OFFSET_SCALING), startAnchorAbsPosition.y + (initialPositionOffsetY * INCREMENTAL_FLOW_INDICATOR_BENDPOINT_OFFSET_SCALING));
final Point positionAbs = new Point(containerAbsPosition.x + nextPosition.x, +containerAbsPosition.y + nextPosition.y);
final Point bp2 = new Point(positionAbs.x - (initialPositionOffsetX * (1.0 - INCREMENTAL_FLOW_INDICATOR_BENDPOINT_OFFSET_SCALING)), positionAbs.y - (initialPositionOffsetY * (1.0 - INCREMENTAL_FLOW_INDICATOR_BENDPOINT_OFFSET_SCALING)));
m.setBendpoints(indicator, ImmutableList.of(bp1, bp2));
}
}
// Determine the next position
nextPosition = new Point(currentPosition.x + positionIncrementX, currentPosition.y + positionIncrementY);
}
}
}
use of org.osate.ge.internal.GraphicalEditorException in project osate2 by osate.
the class DiagramElementLayoutUtil method applyShapeLayout.
private static void applyShapeLayout(final LayoutMapping mapping, final DiagramModification m) {
// Modify shapes
for (Entry<ElkGraphElement, Object> e : mapping.getGraphMap().entrySet()) {
final ElkGraphElement elkElement = e.getKey();
final Object mappedValue = e.getValue();
final boolean isTopLevelElement = isTopLevel(elkElement);
if (!(elkElement instanceof ElkShape)) {
continue;
}
final ElkShape elkShape = (ElkShape) elkElement;
if (!(mappedValue instanceof DiagramElement)) {
continue;
}
final DiagramElement de = (DiagramElement) mappedValue;
if (!(de.getGraphic() instanceof AgeShape)) {
continue;
}
if (de.getGraphic() instanceof Label) {
continue;
}
// Set Position. Don't set the position of top level elements
if (!isTopLevelElement && DiagramElementPredicates.isMoveableShape(de)) {
// Determine position for the element
double x = elkShape.getX();
double y = elkShape.getY();
// If the diagram element has a parent port, subtract the parent port position from the ELK port position to determine the relative position
if (de.getDockArea() == DockArea.GROUP) {
final ElkPort parentPort = (ElkPort) mapping.getGraphMap().inverse().get(de.getParent());
if (parentPort != null) {
final PortSide side = parentPort.getProperty(CoreOptions.PORT_SIDE);
if (PortSide.SIDES_NORTH_SOUTH.contains(side)) {
x = elkShape.getX() - parentPort.getX();
} else if (PortSide.SIDES_EAST_WEST.contains(side)) {
y = elkShape.getY() - parentPort.getY();
} else {
throw new GraphicalEditorException("Unexpected side: " + side);
}
}
}
DiagramElementLayoutUtil.moveElement(m, de, new Point(x, y));
// Set the dock area
if (de.getDockArea() != DockArea.GROUP && de.getDockArea() != null) {
final DockArea newDockArea = PortSideUtil.getDockArea(elkShape.getProperty(CoreOptions.PORT_SIDE));
if (newDockArea != null) {
m.setDockArea(de, newDockArea);
}
}
}
// Set the size
if (DiagramElementPredicates.isResizeable(de)) {
m.setSize(de, new Dimension(elkShape.getWidth(), elkShape.getHeight()));
}
}
}
use of org.osate.ge.internal.GraphicalEditorException in project osate2 by osate.
the class DiagramSerialization method createElement.
private static void createElement(final IProject project, final DiagramModification m, final DiagramNode container, final org.osate.ge.diagram.DiagramElement mmChild, final Map<Long, UUID> legacyIdToUuidMap) {
final String[] refSegs = toReferenceSegments(mmChild.getBo());
if (refSegs == null) {
throw new GraphicalEditorException("Invalid element. Invalid business object reference.");
}
final RelativeBusinessObjectReference relReference = new RelativeBusinessObjectReference(refSegs);
final Object bo = InternalReferenceUtil.createEmbeddedObject(relReference, mmChild.getBoData());
// Set the ID
final UUID uuid = UUID.fromString(mmChild.getUuid());
final DiagramElement newElement = new DiagramElement(container, bo, null, relReference, uuid);
// Size and Position
newElement.setPosition(convertPoint(mmChild.getPosition()));
newElement.setSize(convertDimension(mmChild.getSize()));
// Dock Area
final String dockAreaId = mmChild.getDockArea();
if (dockAreaId != null) {
final DockArea dockArea = DockArea.getById(dockAreaId);
if (dockArea != null) {
newElement.setDockArea(dockArea);
}
}
// Style
final Boolean showAsImage = mmChild.getShowAsImage();
final Color background = mmChild.getBackground() != null ? parseColor(mmChild.getBackground()) : null;
final IPath image = mmChild.getImage() != null ? project.getFile(Path.fromPortableString(mmChild.getImage())).getFullPath() : null;
final Color fontColor = mmChild.getFontColor() != null ? parseColor(mmChild.getFontColor()) : null;
final Color outline = mmChild.getOutline() != null ? parseColor(mmChild.getOutline()) : null;
final Double lineWidth = mmChild.getLineWidth();
final Double fontSize = mmChild.getFontSize();
final Boolean primaryLabelVisible = mmChild.getPrimaryLabelVisible();
newElement.setStyle(StyleBuilder.create().backgroundColor(background).showAsImage(showAsImage).imagePath(image).fontColor(fontColor).outlineColor(outline).fontSize(fontSize).lineWidth(lineWidth).primaryLabelVisible(primaryLabelVisible).build());
// Bendpoints
final org.osate.ge.diagram.BendpointList mmBendpoints = mmChild.getBendpoints();
if (mmBendpoints == null) {
newElement.setBendpoints(Collections.emptyList());
} else {
newElement.setBendpoints(mmBendpoints.getPoint().stream().map(DiagramSerialization::convertPoint).collect(Collectors.toList()));
}
// Primary Label Position (Only Supported for Connections)
newElement.setConnectionPrimaryLabelPosition(convertPoint(mmChild.getPrimaryLabelPosition()));
// Add the element
m.addElement(newElement);
// Create children
readElements(project, m, newElement, mmChild, legacyIdToUuidMap);
}
Aggregations