diff --git a/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/AadlPropertyView.xtend b/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/AadlPropertyView.xtend index 78942ce9883..063a4c76b36 100644 --- a/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/AadlPropertyView.xtend +++ b/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/AadlPropertyView.xtend @@ -129,6 +129,11 @@ import org.osate.xtext.aadl2.ui.MyAadl2Activator import static extension org.eclipse.emf.ecore.util.EcoreUtil.getURI import static extension org.eclipse.xtext.EcoreUtil2.getContainerOfType import static extension org.osate.aadl2.modelsupport.util.AadlUtil.isSameOrRefines +import org.eclipse.xtext.resource.SaveOptions +import org.eclipse.emf.transaction.RecordingCommand +import org.eclipse.core.runtime.Adapters +import org.eclipse.jface.viewers.ITreeSelection +import org.eclipse.emf.ecore.resource.Resource /** * View that displays the AADL property value associations within a given AADL @@ -205,8 +210,8 @@ class AadlPropertyView extends ViewPart { var package IXtextDocument xtextDocument = null - var ResourceSet resourceSetFromSelection = null - + var package Resource resourceFromSelection; + /* Only show properties from this group (or all properties if empty) */ var ArrayList currentPropertyGroup = new ArrayList @@ -251,6 +256,9 @@ class AadlPropertyView extends ViewPart { } override partClosed(IWorkbenchPart part) { + if (part instanceof XtextEditor && xtextDocument === (part as XtextEditor).document) { + xtextDocument = null + } } override partBroughtToTop(IWorkbenchPart part) { @@ -278,16 +286,9 @@ class AadlPropertyView extends ViewPart { val IXtextModelListener xtextModelListener = [ if (modelListenerEnabled) { - synchronized (jobLock) { - if (cachePropertyLookupJob !== null && cachePropertyLookupJob.state != Job.NONE) { - cachePropertyLookupJob.cancel - } - if (input !== null) { - cachePropertyLookupJob = createCachePropertyLookupJob(input, null) - cachePropertyLookupJob.schedule - } - } - }] + runCachePropertyLookupJob(input, null) + } + ] override createPartControl(Composite parent) { pageBook = new PageBook(parent, SWT.NULL) @@ -448,7 +449,7 @@ class AadlPropertyView extends ViewPart { } def package boolean canEdit(Object element) { - if (xtextDocument === null) { + if (xtextDocument === null && !(resourceFromSelection instanceof XtextResource)) { false } else { safeRead[ extension it | @@ -559,29 +560,19 @@ class AadlPropertyView extends ViewPart { toolTipText = SHOW_DEFAULT_TOOL_TIP ] - - removeElementAction = new Action("Remove") { override run() { val selectedElement = (treeViewer.selection as IStructuredSelection).firstElement as TreeEntry switch treeElement : selectedElement.treeElement { URI: { - val postModificationUpdate = xtextDocument.modify[ + val postModificationUpdate = modify[ switch treeElementObject : resourceSet.getEObject(treeElement, true) { Property: { val associationURI = cachedPropertyAssociations.get( (selectedElement.parent as TreeEntry).treeElement).get(selectedElement.treeElement) val association = resourceSet.getEObject(associationURI, true) as PropertyAssociation (association.owner as NamedElement).ownedPropertyAssociations.remove(association); - [| - synchronized (jobLock) { - if (cachePropertyLookupJob !== null && - cachePropertyLookupJob.state != Job.NONE) { - cachePropertyLookupJob.cancel - } - cachePropertyLookupJob = createCachePropertyLookupJob(input, null) - cachePropertyLookupJob.schedule - }] + [|runCachePropertyLookupJob(input, null)] } BasicPropertyAssociation: { (treeElementObject.owner as RecordValue).ownedFieldValues.remove(treeElementObject); @@ -591,7 +582,7 @@ class AadlPropertyView extends ViewPart { postModificationUpdate.apply } RangeElement: { - xtextDocument.modify( + modify( new IUnitOfWork.Void { override process(XtextResource state) throws Exception { ((state.resourceSet.getEObject((treeElement as RangeElement).expressionURI, true) as PropertyExpression). @@ -601,7 +592,7 @@ class AadlPropertyView extends ViewPart { treeViewer.refresh(selectedElement.parent) } ListElement: { - xtextDocument.modify( + modify( new IUnitOfWork.Void { override process(XtextResource state) throws Exception { ((state.resourceSet.getEObject((treeElement as ListElement).expressionURI, true) as PropertyExpression). @@ -673,9 +664,10 @@ class AadlPropertyView extends ViewPart { val propertyURI = selectedElement.treeElement as URI val associationURI = cachedPropertyAssociations.get((selectedElement.parent as TreeEntry).treeElement). get(propertyURI) - val postModificationUpdate = xtextDocument.modify[ + val postModificationUpdate = modify [ var ()=>void update = [|] val inputElement = resourceSet.getEObject(input, true) as NamedElement + resolveProperties(inputElement) if (associationURI !== null) { val oldPA = resourceSet.getEObject(associationURI, true) as PropertyAssociation val newPA = EcoreUtil.copy(oldPA) @@ -683,15 +675,7 @@ class AadlPropertyView extends ViewPart { if (oldPA.appliesTos.size == 1) { // non-shared local contained => remove the PA (oldPA.owner as NamedElement).ownedPropertyAssociations.remove(oldPA) - update = [| - synchronized (jobLock) { - if (cachePropertyLookupJob !== null && - cachePropertyLookupJob.state != Job.NONE) { - cachePropertyLookupJob.cancel - } - cachePropertyLookupJob = createCachePropertyLookupJob(input, null) - cachePropertyLookupJob.schedule - }] + update = [|runCachePropertyLookupJob(input, null)] } else if (oldPA.appliesTos.size > 1) { // shared local contained => remove from applies to list val toRemove = oldPA.appliesTos.findFirst[ @@ -723,9 +707,10 @@ class AadlPropertyView extends ViewPart { val propertyURI = selectedElement.treeElement as URI val associationURI = cachedPropertyAssociations.get((selectedElement.parent as TreeEntry).treeElement). get(propertyURI) - val postModificationUpdate = xtextDocument.modify[ + val postModificationUpdate = modify [ var ()=>void update = [|] val inputElement = resourceSet.getEObject(input, true) as NamedElement + resolveProperties(inputElement) if (associationURI !== null) { val oldPA = resourceSet.getEObject(associationURI, true) as PropertyAssociation val newPA = EcoreUtil.copy(oldPA) @@ -740,15 +725,7 @@ class AadlPropertyView extends ViewPart { if (oldPA.appliesTos.size == 0 && oldPA.owner === inputElement) { // local PA inputElement.ownedPropertyAssociations.remove(oldPA) - update = [| - synchronized (jobLock) { - if (cachePropertyLookupJob !== null && - cachePropertyLookupJob.state != Job.NONE) { - cachePropertyLookupJob.cancel - } - cachePropertyLookupJob = createCachePropertyLookupJob(input, null) - cachePropertyLookupJob.schedule - }] + update = [|runCachePropertyLookupJob(input, null)] } else if (oldPA.appliesTos.size > 1) { // shared local contained => remove from applies to list val toRemove = oldPA.appliesTos.findFirst[ @@ -794,6 +771,55 @@ class AadlPropertyView extends ViewPart { } } } + + /** + * When editing a raw XtextResouce, this calls the getProperty() method for all property associations owned by a specified named element. + * This is needed because under certain conditions the property reference is not updated and this can result in a broken proxy. + * An exception is thrown when resolving the proxy. Resolving the property before making a modification prevents this from happening. + */ + def resolveProperties(NamedElement element) { + if(xtextDocument === null) { + for(PropertyAssociation pa : element.ownedPropertyAssociations) { + pa.property + } + } + } + + def package modify(IUnitOfWork work) { + if (xtextDocument !== null) { + xtextDocument.modify(work); + } else if(resourceFromSelection instanceof XtextResource) { + val resource = resourceFromSelection as XtextResource; + var cmd = new RecordingCommand(editingDomain as TransactionalEditingDomain) { + T result; + + override protected doExecute() { + result = work.exec(resource) + } + } + + editingDomain.commandStack.execute(cmd) + + // Run the serializer. Otherwise if an invalid modification is made, the resource could be erased. + // Sanity check to ensure that we don't save if the modification caused serialization to fail. + // We need to undo to restore the resource to a valid state because the resource may still in use by the owner of the resource(such as the graphical editor) + val serializedSrc = resource.getSerializer().serialize(resource.getContents().get(0)); + val modificationSuccessful = serializedSrc !== null && !serializedSrc.trim().isEmpty(); + if (!modificationSuccessful) { + if(!editingDomain.getCommandStack().canUndo() || editingDomain.getCommandStack.getUndoCommand() != cmd) { + throw new RuntimeException("Property modification failed and unable to undo. Unexpected state.") + } + + editingDomain.getCommandStack().undo() + } + + resourceFromSelection.save(SaveOptions.newBuilder().format().getOptions().toOptionsMap()) + + cmd.result + } else { + throw new RuntimeException("Unsupported case. Cannot modify model without an Xtext Document or an Xtext resource") + } + } def private createContextMenu() { new MenuManager => [ @@ -833,16 +859,16 @@ class AadlPropertyView extends ViewPart { openPropertyAssociationAction.enabled = #[PropertyStatus.INHERITED, PropertyStatus.LOCAL, PropertyStatus.LOCAL_CONTAINED ].contains(propertyStatus) - createLocalAssociationAction.enabled = xtextDocument !== null && (propertyStatus == + createLocalAssociationAction.enabled = (propertyStatus == PropertyStatus.INHERITED || propertyStatus == PropertyStatus.DEFAULT || propertyStatus == PropertyStatus.UNDEFINED) && safeRead[ extension it | val inputElement = input.getEObject(true) inputElement instanceof AadlPackage || inputElement instanceof Classifier || inputElement instanceof Subcomponent || inputElement instanceof ModalPath || inputElement instanceof BehavioralFeature || inputElement instanceof Prototype || - inputElement instanceof Feature || inputElement instanceof ModeFeature + inputElement instanceof Feature ||inputElement instanceof ModeFeature ] - createLocalContainedAssociationAction.enabled = xtextDocument !== null && (propertyStatus == + createLocalContainedAssociationAction.enabled = (propertyStatus == PropertyStatus.INHERITED || propertyStatus == PropertyStatus.DEFAULT || propertyStatus == PropertyStatus.UNDEFINED) && safeRead[ extension it | val inputElement = input.getEObject(true) @@ -850,23 +876,27 @@ class AadlPropertyView extends ViewPart { inputElement instanceof BehavioralFeature || inputElement instanceof Prototype || inputElement instanceof Feature || inputElement instanceof ModeFeature ] - makeLocalAction.enabled = xtextDocument !== null && - #[PropertyStatus.INHERITED, PropertyStatus.LOCAL_CONTAINED, PropertyStatus.LOCAL_SHARED, - PropertyStatus.DEFAULT - ].contains(propertyStatus) - makeLocalContainedAction.enabled = xtextDocument !== null && - #[PropertyStatus.INHERITED, PropertyStatus.LOCAL, PropertyStatus.LOCAL_SHARED, - PropertyStatus.DEFAULT - ].contains(propertyStatus) && safeRead[ extension it | - val inputElement = input.getEObject(true) - inputElement instanceof Subcomponent || inputElement instanceof ModalPath || - inputElement instanceof BehavioralFeature || inputElement instanceof Prototype || - inputElement instanceof Feature || inputElement instanceof ModeFeature - ] + makeLocalAction.enabled = #[ + PropertyStatus.INHERITED, + PropertyStatus.LOCAL_CONTAINED, + PropertyStatus.LOCAL_SHARED, + PropertyStatus.DEFAULT + ].contains(propertyStatus) + makeLocalContainedAction.enabled = #[ + PropertyStatus.INHERITED, + PropertyStatus.LOCAL, + PropertyStatus.LOCAL_SHARED, + PropertyStatus.DEFAULT + ].contains(propertyStatus) && safeRead[ extension it | + val inputElement = input.getEObject(true) + inputElement instanceof Subcomponent || inputElement instanceof ModalPath || + inputElement instanceof BehavioralFeature ||inputElement instanceof Prototype || + inputElement instanceof Feature || inputElement instanceof ModeFeature + ] } } - removeElementAction.enabled = xtextDocument !== null && canEdit(firstSelectedElement) && + removeElementAction.enabled = canEdit(firstSelectedElement) && switch treeElement : firstSelectedElement.treeElement { URI: safeRead[ extension it | @@ -903,6 +933,14 @@ class AadlPropertyView extends ViewPart { xtextDocument = (part as XtextEditor).document xtextDocument.readOnly[new EObjectAtOffsetHelper().resolveContainedElementAt(it, selection.offset)] } + // Outline selection + ITreeSelection: { + val propertySource = Adapters.adapt(selection, IAadlPropertySource) + if (propertySource !== null) { + xtextDocument = propertySource.document + propertySource.namedElement + } + } IStructuredSelection case selection.size == 1: { switch selectedObject : selection.firstElement { EObject: { @@ -1008,7 +1046,7 @@ class AadlPropertyView extends ViewPart { } if (currentSelectionURI !== null) { editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(currentSelection) - resourceSetFromSelection = currentSelection.eResource.resourceSet + resourceFromSelection = currentSelection.eResource if (currentSelectionURI == previousSelectionURI) { if (treeElementToSelect !== null) { treeViewer.setSelection(new StructuredSelection(treeElementToSelect), true) @@ -1016,14 +1054,7 @@ class AadlPropertyView extends ViewPart { pageBook.showPage(treeViewerComposite) } else { previousSelectionURI = currentSelectionURI - - synchronized (jobLock) { - if (cachePropertyLookupJob !== null && cachePropertyLookupJob.state != Job.NONE) { - cachePropertyLookupJob.cancel - } - cachePropertyLookupJob = createCachePropertyLookupJob(currentSelectionURI, treeElementToSelect) - cachePropertyLookupJob.schedule - } + runCachePropertyLookupJob(currentSelectionURI, treeElementToSelect) } } else { @@ -1035,7 +1066,7 @@ class AadlPropertyView extends ViewPart { } pageBook.showPage(noPropertiesLabel) editingDomain = null - resourceSetFromSelection = null + resourceFromSelection = null previousSelectionURI = null } @@ -1077,14 +1108,20 @@ class AadlPropertyView extends ViewPart { } def package safeRead((ResourceSet)=>T operation) { + safeReadResource [resource | + operation.apply(resource.resourceSet); + ] + } + + def package safeReadResource((Resource)=>T operation) { if (xtextDocument !== null) { - xtextDocument.readOnly[operation.apply(resourceSet)] + xtextDocument.readOnly(operation) } else if (editingDomain instanceof TransactionalEditingDomain) { try { TransactionUtil.runExclusive(editingDomain, new RunnableWithResult.Impl { override run() { - result = operation.apply(editingDomain.resourceSet) + result = operation.apply(resourceFromSelection) status = Status.OK_STATUS } }) @@ -1094,7 +1131,7 @@ class AadlPropertyView extends ViewPart { operation.apply(null) } } else { - operation.apply(resourceSetFromSelection) + operation.apply(resourceFromSelection) } } @@ -1169,4 +1206,16 @@ class AadlPropertyView extends ViewPart { } } } + + def package runCachePropertyLookupJob(URI elementURI, Object objectToSelect) { + synchronized (jobLock) { + if (cachePropertyLookupJob !== null && + cachePropertyLookupJob.state != Job.NONE) { + cachePropertyLookupJob.cancel + } + cachePropertyLookupJob = createCachePropertyLookupJob(elementURI, objectToSelect) + cachePropertyLookupJob.schedule + } + } + } diff --git a/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/ValueColumnEditingSupport.xtend b/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/ValueColumnEditingSupport.xtend index 7caa329b0ba..e7f914a4738 100644 --- a/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/ValueColumnEditingSupport.xtend +++ b/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/ValueColumnEditingSupport.xtend @@ -36,7 +36,6 @@ package org.osate.xtext.aadl2.ui.propertyview import de.itemis.xtext.utils.jface.viewers.XtextStyledTextCellEditor import org.eclipse.emf.common.util.URI -import org.eclipse.emf.ecore.resource.Resource import org.eclipse.jface.viewers.EditingSupport import org.eclipse.jface.viewers.TreeViewer import org.eclipse.swt.SWT @@ -64,6 +63,7 @@ import org.osate.xtext.aadl2.ui.MyAadl2Activator import static extension org.eclipse.xtext.nodemodel.util.NodeModelUtils.findNodesForFeature import static extension org.eclipse.xtext.nodemodel.util.NodeModelUtils.getNode import static extension org.osate.aadl2.modelsupport.resources.OsateResourceUtil.convertToIResource +import org.eclipse.emf.ecore.resource.ResourceSet package class ValueColumnEditingSupport extends EditingSupport { val static EMBEDDED_RESOURCE_NAME_SUFFIX = "_embedded_for_property_view_cell_editor" @@ -104,16 +104,50 @@ package class ValueColumnEditingSupport extends EditingSupport { } override protected getCellEditor(Object element) { - new XtextStyledTextCellEditor(SWT.SINGLE, MyAadl2Activator.getInstance.getInjector(MyAadl2Activator.ORG_OSATE_XTEXT_AADL2_AADL2), propertyView.xtextDocument.readOnly[convertToIResource.project]) => [ + new XtextStyledTextCellEditor(SWT.SINGLE, MyAadl2Activator.getInstance.getInjector(MyAadl2Activator.ORG_OSATE_XTEXT_AADL2_AADL2), getProject()) => [ create(propertyView.treeViewer.tree) ] } - override protected getValue(Object element) { - propertyView.xtextDocument.readOnly[ + def private getProject() { + if(propertyView.xtextDocument === null) { + val NamedElement curSelection = propertyView.resourceFromSelection.resourceSet.getEObject(propertyView.input, + true) as NamedElement + curSelection.eResource.convertToIResource.project + } else { + propertyView.xtextDocument.readOnly[convertToIResource.project] + } + } + + override protected getValue(Object element) { + propertyView.safeReadResource[extension resource| + // Helper function. If length is negative then it is an offset from the end of the source + val getText = if (propertyView.xtextDocument === null) { + val xtextResource = resource as XtextResource + val text = xtextResource.parseResult.rootNode.text; + [int offset, int length | + val positiveLength = if(length < 0) { + text.length + length + } else { + length; + } + + text.substring(offset, offset + positiveLength) + ] + } else { + [int offset, int length | + val positiveLength = if(length < 0) { + propertyView.xtextDocument.length + length + } else { + length; + } + + propertyView.xtextDocument.get(offset, positiveLength) + ] + } + val modelUnitNameEndOffset = contents.head.findNodesForFeature(Aadl2Package.eINSTANCE.namedElement_Name).head.endOffset val endNameEndOffset = contents.head.node.lastLeaf.previousNode.endOffset - if (creatingNewLocalInEdit) { val propertyName = (element as TreeEntry).property.getQualifiedName.stripPredeclaredName val inputElement = resourceSet.getEObject(propertyView.input, true) as NamedElement @@ -168,37 +202,37 @@ package class ValueColumnEditingSupport extends EditingSupport { } else { delim } - val prefix = propertyView.xtextDocument.get(0, updateOffset) - val suffix = propertyView.xtextDocument.get(updateOffset, propertyView.xtextDocument.length - updateOffset) + val prefix = getText.apply(0, updateOffset) + val suffix = getText.apply(updateOffset, -updateOffset) new CellEditorPartialValue('''«new StringBuilder(prefix).insert(modelUnitNameEndOffset, EMBEDDED_RESOURCE_NAME_SUFFIX)»«updatePrefix»''', initialEditablePart, '''«updateSuffix»«new StringBuilder(suffix).insert(endNameEndOffset - updateOffset, EMBEDDED_RESOURCE_NAME_SUFFIX)»''' ) } else { - val expression = getPropertyExpression(element) + val expression = getPropertyExpression(resourceSet, element) val expressionNode = expression.node updateOffset = expressionNode.offset updateLength = expressionNode.length updatePrefix = "" updateSuffix = "" - initialEditablePart = serializer.serialize(expression).replaceAll("\n", "").replaceAll("\r", "").replaceAll("\t", "").trim - val prefix = propertyView.xtextDocument.get(0, expressionNode.offset) - val suffix = propertyView.xtextDocument.get(expressionNode.endOffset, propertyView.xtextDocument.length - expressionNode.endOffset) + initialEditablePart = (resource as XtextResource).serializer.serialize(expression).replaceAll("\n", "").replaceAll("\r", "").replaceAll("\t", "").trim + val prefix = getText.apply(0, expressionNode.offset) + val suffix = getText.apply(expressionNode.endOffset, -expressionNode.endOffset) new CellEditorPartialValue(new StringBuilder(prefix).insert(modelUnitNameEndOffset, EMBEDDED_RESOURCE_NAME_SUFFIX).toString, initialEditablePart, new StringBuilder(suffix).insert(endNameEndOffset - expressionNode.endOffset, EMBEDDED_RESOURCE_NAME_SUFFIX).toString ) } - ] + ]; } - private def PropertyExpression getPropertyExpression(Resource resource, Object element) { - val resourceSet = resource.resourceSet + private def PropertyExpression getPropertyExpression(ResourceSet resourceSet, Object element) { switch treeElement : (element as TreeEntry).treeElement { URI: switch treeElementObject : resourceSet.getEObject(treeElement, true) { Property: { (resourceSet.getEObject( - propertyView.cachedPropertyAssociations.get(((element as TreeEntry).parent as TreeEntry).treeElement).get(treeElement), true + propertyView.cachedPropertyAssociations.get(((element as TreeEntry).parent as TreeEntry).treeElement).get(treeElement), + true ) as PropertyAssociation).ownedValues.head.ownedValue } BasicPropertyAssociation: treeElementObject.value @@ -207,7 +241,7 @@ package class ValueColumnEditingSupport extends EditingSupport { ListElement: resourceSet.getEObject(treeElement.expressionURI, true) as PropertyExpression } } - + private def stripPredeclaredName(String qualifiedName) { val predeclaredNames = #['communication_properties::', 'deployment_properties::', 'memory_properties::', 'modeling_properties::', 'programming_properties::', 'thread_properties::', 'timing_properties::'] @@ -218,12 +252,13 @@ package class ValueColumnEditingSupport extends EditingSupport { override protected setValue(Object element, Object value) { if (creatingNewLocalInEdit || !(value as String).empty && initialEditablePart != value) { // insert new property value - propertyView.xtextDocument.modify(new IUnitOfWork.Void { + propertyView.modify(new IUnitOfWork.Void { override process(XtextResource state) throws Exception { state.update(updateOffset, updateLength, updatePrefix + value + updateSuffix) } }) + propertyView.runCachePropertyLookupJob(propertyView.input, null) propertyView.treeViewer.refresh((element as TreeEntry).propertyParent) // select inserted/modified text in editor @@ -233,7 +268,7 @@ package class ValueColumnEditingSupport extends EditingSupport { } } } - + def private static getLastLeaf(ICompositeNode node) { var INode result = node while (result instanceof ICompositeNode) { diff --git a/ge/org.osate.ge/plugin.xml b/ge/org.osate.ge/plugin.xml index 3be51852114..936e43e9a21 100644 --- a/ge/org.osate.ge/plugin.xml +++ b/ge/org.osate.ge/plugin.xml @@ -1230,6 +1230,7 @@ + diff --git a/ge/org.osate.ge/src/org/osate/ge/internal/selection/AgeBusinessObjectSelectionAdapterFactory.java b/ge/org.osate.ge/src/org/osate/ge/internal/selection/AgeBusinessObjectSelectionAdapterFactory.java index f40b30c4100..9723d276fd7 100644 --- a/ge/org.osate.ge/src/org/osate/ge/internal/selection/AgeBusinessObjectSelectionAdapterFactory.java +++ b/ge/org.osate.ge/src/org/osate/ge/internal/selection/AgeBusinessObjectSelectionAdapterFactory.java @@ -4,9 +4,15 @@ import org.eclipse.e4.core.contexts.EclipseContextFactory; import org.eclipse.e4.core.contexts.IEclipseContext; import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.xtext.ui.editor.model.IXtextDocument; +import org.osate.aadl2.NamedElement; import org.osate.ge.BusinessObjectSelection; +import org.osate.ge.internal.diagram.runtime.DiagramElement; import org.osate.ge.internal.services.AadlModificationService; import org.osate.ge.internal.ui.util.SelectionUtil; +import org.osate.ge.internal.ui.xtext.AgeXtextUtil; +import org.osate.xtext.aadl2.ui.propertyview.IAadlPropertySource; import org.osgi.framework.Bundle; import org.osgi.framework.FrameworkUtil; @@ -27,6 +33,30 @@ public T getAdapter(final Object adaptableObject, final Class adapterType return adapterType .cast(new AgeBusinessObjectSelection(SelectionUtil.getSelectedBusinessObjectContexts(selection), modificationService)); + } else if (IAadlPropertySource.class.equals(adapterType) && adaptableObject instanceof IStructuredSelection) { + final IStructuredSelection ss = (IStructuredSelection) adaptableObject; + if (ss.getFirstElement() instanceof DiagramElement) { + final DiagramElement de = (DiagramElement) ss.getFirstElement(); + // If the business object is an AADL Named Element + if (de.getBusinessObject() instanceof NamedElement) { + final NamedElement namedElement = (NamedElement) de.getBusinessObject(); + return adapterType.cast(new IAadlPropertySource() { + private final IXtextDocument document = AgeXtextUtil + .getDocumentByRootElement(namedElement.getElementRoot()); + private final NamedElement element = namedElement; + + @Override + public IXtextDocument getDocument() { + return document; + } + + @Override + public NamedElement getNamedElement() { + return element; + } + }); + } + } } return null; @@ -34,7 +64,7 @@ public T getAdapter(final Object adaptableObject, final Class adapterType @Override public Class[] getAdapterList() { - return new Class[] { BusinessObjectSelection.class }; + return new Class[] { IAadlPropertySource.class, BusinessObjectSelection.class }; } }