From 3691d9cbf0b966b17de26fdc6e74915ea91ca58e Mon Sep 17 00:00:00 2001 From: "ryan.mcilnay" Date: Tue, 16 Oct 2018 13:30:08 -0500 Subject: [PATCH 1/8] property view editing support in graphical editor --- .../ui/propertyview/AadlPropertyView.xtend | 1137 +++++++++-------- .../ui/propertyview/IAadlPropertySource.java | 5 + .../ValueColumnEditingSupport.xtend | 284 +++- .../GraphitiEditPartAdapterFactory.java | 8 + 4 files changed, 842 insertions(+), 592 deletions(-) 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..b88b274b021 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 @@ -1,13 +1,13 @@ /* - * + * * * Copyright 2014 by Carnegie Mellon University, all rights reserved. - * + * * Use of the Open Source AADL Tool Environment (OSATE) is subject to the terms of the license set forth * at http://www.eclipse.org/org/documents/epl-v10.html. - * + * * NO WARRANTY - * + * * ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER PROPERTY OR RIGHTS GRANTED OR PROVIDED BY * CARNEGIE MELLON UNIVERSITY PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN "AS-IS" BASIS. * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, @@ -17,14 +17,14 @@ * REGARDLESS OF WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. LICENSEE AGREES THAT IT WILL NOT * MAKE ANY WARRANTY ON BEHALF OF CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON CONCERNING THE * APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE DELIVERABLES UNDER THIS LICENSE. - * + * * Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie Mellon University, its trustees, officers, * employees, and agents from all claims or demands made against them (and any related losses, expenses, or * attorney's fees) arising out of, or relating to Licensee's and/or its sub licensees' negligent use or willful * misuse of or negligent conduct or willful misconduct regarding the Software, facilities, or other rights or * assistance granted by Carnegie Mellon University under this License, including, but not limited to, any claims of * product liability, personal injury, death, damage to property, or violation of any laws or regulations. - * + * * Carnegie Mellon Carnegie Mellon University Software Engineering Institute authored documents are sponsored by the U.S. Department * of Defense under Contract F19628-00-C-0003. Carnegie Mellon University retains copyrights in all material produced * under this contract. The U.S. Government retains a non-exclusive, royalty-free license to publish or reproduce these @@ -129,6 +129,9 @@ 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.ui.part.EditorPart /** * View that displays the AADL property value associations within a given AADL @@ -142,7 +145,7 @@ class AadlPropertyView extends ViewPart { val static SHOW_ALL_AVAILABLE_PROPERTIES = "Show all available properties" val static HIDE_DEFAULT_TOOL_TIP = "Hide default property values" val static SHOW_DEFAULT_TOOL_TIP = "Show default property values" - + val static NO_PROPERTIES_TO_SHOW = "No properties to show: Please select a single AADL element that can have properties." val static POPULATING_VIEW = "Populating AADL Property Values view." @@ -205,7 +208,7 @@ class AadlPropertyView extends ViewPart { var package IXtextDocument xtextDocument = null - var ResourceSet resourceSetFromSelection = null + var package ResourceSet resourceSetFromSelection = null /* Only show properties from this group (or all properties if empty) */ var ArrayList currentPropertyGroup = new ArrayList @@ -221,15 +224,17 @@ class AadlPropertyView extends ViewPart { var IURIEditorOpener editorOpener var URI previousSelectionURI = null + + var IAadlPropertySource propertySource = null var CachePropertyLookupJob cachePropertyLookupJob = null val jobLock = new Object - //If the URIs were resolved to EObjects, then this would be a Map> + // If the URIs were resolved to EObjects, then this would be a Map> val package Map> cachedPropertyAssociations = Collections.synchronizedMap(newLinkedHashMap) var ArrayList importedPropertyGroups = new ArrayList - + val ISelectionListener selectionListener = [ part, selection | /* * Change the view when the selection changes. @@ -251,6 +256,9 @@ class AadlPropertyView extends ViewPart { } override partClosed(IWorkbenchPart part) { + if (part instanceof XtextEditor) { + xtextDocument = null + } } override partBroughtToTop(IWorkbenchPart part) { @@ -262,6 +270,8 @@ class AadlPropertyView extends ViewPart { if (selectionProvider instanceof IPostSelectionProvider) { selectionProvider.addPostSelectionChangedListener(selectionChangedListener) } + } else if(part instanceof EditorPart) { + updateSelection(part.editorSite.selectionProvider.selection) } } } @@ -273,21 +283,14 @@ class AadlPropertyView extends ViewPart { } ] - //This flag is necessary because calling IURIEditorOpener.open causes a model change event. This event should be ignored when calling IURIEditorOpener.open + // This flag is necessary because calling IURIEditorOpener.open causes a model change event. This event should be ignored when calling IURIEditorOpener.open var modelListenerEnabled = true 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 - } - } - }] + updateView(input, null) + } + ] override createPartControl(Composite parent) { pageBook = new PageBook(parent, SWT.NULL) @@ -311,20 +314,20 @@ class AadlPropertyView extends ViewPart { override protected isLeafMatch(Viewer viewer, Object element) { var thisTree = viewer as TreeViewer val labelProvider = thisTree.getLabelProvider(0) as ColumnLabelProvider - val contentProvider = thisTree.getContentProvider() as ITreeContentProvider - - // first go up to propertyset / property name + val contentProvider = thisTree.getContentProvider() as ITreeContentProvider + + // first go up to propertyset / property name // see https://github.com/osate/osate2/issues/605) - var current = element - var parent = contentProvider.getParent(element) - while (contentProvider.getParent(parent) instanceof TreeEntry) { - current = parent - parent = contentProvider.getParent(parent) - } - - val propertysetName = labelProvider.getText(parent)?:'' + var current = element + var parent = contentProvider.getParent(element) + while (contentProvider.getParent(parent) instanceof TreeEntry) { + current = parent + parent = contentProvider.getParent(parent) + } + + val propertysetName = labelProvider.getText(parent) ?: '' var propertyName = labelProvider.getText(current) - + return wordMatches(propertyName) && (currentPropertyGroup.size == 0 || isMatch(propertyName, propertysetName)) } @@ -341,7 +344,6 @@ class AadlPropertyView extends ViewPart { var match = false if ((children !== null) && (children.length > 0)) { - for (var i = 0; i < children.length && !match; i++) { match = anyChildrenMatch(thisTree, children.get(i)) } @@ -351,9 +353,9 @@ class AadlPropertyView extends ViewPart { return match } - + def isMatch(String elementName, String parentName) { - for (e: currentPropertyGroup) { + for (e : currentPropertyGroup) { if (e.parent === null && elementName == (e.element as String)) { return true } @@ -361,9 +363,9 @@ class AadlPropertyView extends ViewPart { return true } } - + return false - } + } } // Hack to kill optimization that disables filter when text is empty patternFilter.setPattern("org.eclipse.ui.keys.optimization.false") @@ -396,7 +398,7 @@ class AadlPropertyView extends ViewPart { column.text = "Status" val gc = new GC(column.parent) treeColumnLayout.setColumnData(column, - new ColumnPixelData(PropertyStatus.values.map[gc.stringExtent(toString).x].max + 5, true, true)) + new ColumnPixelData(PropertyStatus.values.map[gc.stringExtent(toString).x].max + 5, true, true)) gc.dispose labelProvider = new StatusColumnLabelProvider(this) ] @@ -423,7 +425,6 @@ class AadlPropertyView extends ViewPart { } override dispose() { - synchronized (jobLock) { if (cachePropertyLookupJob !== null) { cachePropertyLookupJob.cancel @@ -448,44 +449,40 @@ class AadlPropertyView extends ViewPart { } def package boolean canEdit(Object element) { - if (xtextDocument === null) { - false - } else { - safeRead[ extension it | - switch treeElement : (element as TreeEntry).treeElement { - URI: - switch treeElementEObject : treeElement.getEObject(true) { - Property: { - val associationURI = cachedPropertyAssociations.get( - ((element as TreeEntry).parent as TreeEntry).treeElement).get(treeElement) - getPropertyStatusNeverUndefined(associationURI).editable && - !(associationURI.getEObject(true) as PropertyAssociation).modal - } - BasicPropertyAssociation: { - val containingAssociation = treeElementEObject.getContainerOfType(PropertyAssociation) - getPropertyStatusNeverUndefined(containingAssociation).editable && - !containingAssociation.modal - } - default: - false + safeRead[ extension it | + switch treeElement : (element as TreeEntry).treeElement { + URI: + switch treeElementEObject : treeElement.getEObject(true) { + Property: { + val associationURI = cachedPropertyAssociations.get( + ((element as TreeEntry).parent as TreeEntry).treeElement).get(treeElement) + getPropertyStatusNeverUndefined(associationURI).editable && + !(associationURI.getEObject(true) as PropertyAssociation).modal } - RangeElement: { - val containingAssociation = (treeElement.expressionURI.getEObject(true) as PropertyExpression). - getContainerOfType(PropertyAssociation) - getPropertyStatusNeverUndefined(containingAssociation).editable && - !containingAssociation.modal - } - ListElement: { - val containingAssociation = (treeElement.expressionURI.getEObject(true) as PropertyExpression). - getContainerOfType(PropertyAssociation) - getPropertyStatusNeverUndefined(containingAssociation).editable && - !containingAssociation.modal + BasicPropertyAssociation: { + val containingAssociation = treeElementEObject.getContainerOfType(PropertyAssociation) + getPropertyStatusNeverUndefined(containingAssociation).editable && + !containingAssociation.modal + } + default: + false } - default: - false + RangeElement: { + val containingAssociation = (treeElement.expressionURI.getEObject(true) as PropertyExpression). + getContainerOfType(PropertyAssociation) + getPropertyStatusNeverUndefined(containingAssociation).editable && + !containingAssociation.modal } - ] - } + ListElement: { + val containingAssociation = (treeElement.expressionURI.getEObject(true) as PropertyExpression). + getContainerOfType(PropertyAssociation) + getPropertyStatusNeverUndefined(containingAssociation).editable && + !containingAssociation.modal + } + default: + false + } + ] } def package getInput() { @@ -502,29 +499,29 @@ class AadlPropertyView extends ViewPart { viewSite.actionBars.toolBarManager.add(it) toolTipText = COLLAPSE_ALL_TOOL_TIP ] - + // Show only property groups defined with the with clause showOnlyImportedPropertiesAction = new Action("Show Only Imported Property Groups", IAction.AS_CHECK_BOX) { override run() { - showOnlyImportedPropertiesAction.toolTipText = if(showOnlyImportedPropertiesAction.checked) { - SHOW_ONLY_IMPORTED_PROPERTIES + showOnlyImportedPropertiesAction.toolTipText = if (showOnlyImportedPropertiesAction.checked) { + SHOW_ONLY_IMPORTED_PROPERTIES } else { SHOW_ALL_AVAILABLE_PROPERTIES } - - if(showOnlyImportedPropertiesAction.checked) { + + if (showOnlyImportedPropertiesAction.checked) { currentPropertyGroup = new ArrayList(importedPropertyGroups) } else { currentPropertyGroup.clear() } - + treeViewer.refresh() - } + } } => [ - enabled = false - imageDescriptor = MyAadl2Activator.getImageDescriptor("icons/propertyview/filter_ps.png") - toolTipText = SHOW_ONLY_IMPORTED_PROPERTIES - viewSite.actionBars.toolBarManager.add(it) + enabled = false + imageDescriptor = MyAadl2Activator.getImageDescriptor("icons/propertyview/filter_ps.png") + toolTipText = SHOW_ONLY_IMPORTED_PROPERTIES + viewSite.actionBars.toolBarManager.add(it) ] showUndefinedAction = new Action(null, IAction.AS_CHECK_BOX) { @@ -534,7 +531,7 @@ class AadlPropertyView extends ViewPart { } else { SHOW_UNDEFINED_TOOL_TIP } - + treeViewer.refresh } } => [ @@ -550,7 +547,7 @@ class AadlPropertyView extends ViewPart { } else { SHOW_DEFAULT_TOOL_TIP } - + treeViewer.refresh } } => [ @@ -559,58 +556,100 @@ 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[ - 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 - }] - } - BasicPropertyAssociation: { - (treeElementObject.owner as RecordValue).ownedFieldValues.remove(treeElementObject); - [|treeViewer.refresh(selectedElement.parent)] + if (xtextDocument === null) { + [| + val treeElementObject = resourceSetFromSelection.getEObject(treeElement, true) + switch treeElementObject { + Property: { + val associationURI = cachedPropertyAssociations.get( + (selectedElement.parent as TreeEntry).treeElement).get( + selectedElement.treeElement) + val association = resourceSetFromSelection.getEObject(associationURI, + true) as PropertyAssociation + (association.owner as NamedElement).ownedPropertyAssociations.remove( + association) + } + BasicPropertyAssociation: { + (treeElementObject.owner as RecordValue).ownedFieldValues.remove( + treeElementObject); + } + } + + (resourceSetFromSelection.getEObject(input, true).eResource as XtextResource).save( + SaveOptions.newBuilder().format().getOptions().toOptionsMap()) + updateView(input, null) + ].executeCommand + } else { + val postModificationUpdate = xtextDocument.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); + [| + updateView(input, null) + ] + } + BasicPropertyAssociation: { + (treeElementObject.owner as RecordValue).ownedFieldValues.remove( + treeElementObject); + [|treeViewer.refresh(selectedElement.parent)] + } } - }] - postModificationUpdate.apply + ] + postModificationUpdate.apply + } } RangeElement: { - xtextDocument.modify( - new IUnitOfWork.Void { + if (xtextDocument === null) { + val inputElement = resourceSetFromSelection.getEObject(input, true) as NamedElement + [| + ((editingDomain.resourceSet.getEObject((treeElement as RangeElement).expressionURI, + true) as PropertyExpression).owner as RangeValue).delta = null + (inputElement.eResource as XtextResource).save( + SaveOptions.newBuilder().format().getOptions().toOptionsMap()) + ].executeCommand + } else { + xtextDocument.modify(new IUnitOfWork.Void { override process(XtextResource state) throws Exception { - ((state.resourceSet.getEObject((treeElement as RangeElement).expressionURI, true) as PropertyExpression). - owner as RangeValue).delta = null + ((state.resourceSet.getEObject((treeElement as RangeElement).expressionURI, + true) as PropertyExpression).owner as RangeValue).delta = null } }) - treeViewer.refresh(selectedElement.parent) + treeViewer.refresh(selectedElement.parent) + } } ListElement: { - xtextDocument.modify( - new IUnitOfWork.Void { + if (xtextDocument === null) { + val inputElement = resourceSetFromSelection.getEObject(input, true) as NamedElement + [| + ((resourceSetFromSelection.getEObject((treeElement as ListElement).expressionURI, + true) as PropertyExpression).owner as ListValue).ownedListElements.remove( + (treeElement as ListElement).index + ) + (inputElement.eResource as XtextResource).save( + SaveOptions.newBuilder().format().getOptions().toOptionsMap()) + ].executeCommand + } else { + xtextDocument.modify(new IUnitOfWork.Void { override process(XtextResource state) throws Exception { - ((state.resourceSet.getEObject((treeElement as ListElement).expressionURI, true) as PropertyExpression). - owner as ListValue).ownedListElements.remove( + ((state.resourceSet.getEObject((treeElement as ListElement).expressionURI, + true) as PropertyExpression).owner as ListValue).ownedListElements.remove( (treeElement as ListElement).index ) } }) - treeViewer.refresh(selectedElement.parent) + treeViewer.refresh(selectedElement.parent) + } } } } @@ -639,17 +678,17 @@ class AadlPropertyView extends ViewPart { val uriToOpen = safeRead[ extension it | val associationTemp = cachedPropertyAssociations.get((selectedElement.parent as TreeEntry).treeElement). - get(selectedElement.treeElement).getEObject(true) - + get(selectedElement.treeElement).getEObject(true) + val association = switch associationTemp { - PropertyAssociationInstance : { + PropertyAssociationInstance: { associationTemp.getPropertyAssociation(); } PropertyAssociation : associationTemp default : null } - + val inputElement = input.getEObject(true) (if (inputElement instanceof RefinableElement) { association.appliesTos.map[containmentPathElements.last].filter [ @@ -673,46 +712,18 @@ 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[ - var ()=>void update = [|] - val inputElement = resourceSet.getEObject(input, true) as NamedElement - if (associationURI !== null) { - val oldPA = resourceSet.getEObject(associationURI, true) as PropertyAssociation - val newPA = EcoreUtil.copy(oldPA) - newPA.appliesTos.clear - 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 - }] - } else if (oldPA.appliesTos.size > 1) { - // shared local contained => remove from applies to list - val toRemove = oldPA.appliesTos.findFirst[ - path.namedElement === inputElement - ] - oldPA.appliesTos.remove(toRemove) - } - inputElement.ownedPropertyAssociations.add(newPA) - } else { - // copy property's default value - val property = resourceSet.getEObject(propertyURI, true) as Property - inputElement.createOwnedPropertyAssociation => [ - it.property = property - createOwnedValue => [ - ownedValue = EcoreUtil.copy(property.defaultValue) - ] - ] - } - update - ] - postModificationUpdate.apply + + if (xtextDocument !== null) { + val postModificationUpdate = xtextDocument.modify [ + makeLocalProc(resourceSet, associationURI, propertyURI) + ] + postModificationUpdate.apply + } else { + [| + makeLocalProc(resourceSetFromSelection, associationURI, propertyURI) + saveAndRefreshSelection(resourceSetFromSelection.getEObject(input, true).eResource as XtextResource) + ].executeCommand + } } } @@ -723,58 +734,17 @@ 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[ - var ()=>void update = [|] - val inputElement = resourceSet.getEObject(input, true) as NamedElement - if (associationURI !== null) { - val oldPA = resourceSet.getEObject(associationURI, true) as PropertyAssociation - val newPA = EcoreUtil.copy(oldPA) - newPA.appliesTos.clear - newPA.appliesTos.add( - Aadl2Factory.eINSTANCE.createContainedNamedElement => [ - createPath => [ - namedElement = inputElement - ] - ] - ) - 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 - }] - } else if (oldPA.appliesTos.size > 1) { - // shared local contained => remove from applies to list - val toRemove = oldPA.appliesTos.findFirst[ - path.namedElement === inputElement - ] - oldPA.appliesTos.remove(toRemove) - } - (inputElement.owner as NamedElement).ownedPropertyAssociations.add(newPA) - } else { - // copy property's default value - val property = resourceSet.getEObject(propertyURI, true) as Property - (inputElement.owner as NamedElement).createOwnedPropertyAssociation => [ - it.property = property - createOwnedValue => [ - ownedValue = EcoreUtil.copy(property.defaultValue) - ] - appliesTos.add(Aadl2Factory.eINSTANCE.createContainedNamedElement => [ - createPath => [ - namedElement = inputElement - ] - ]) - ] - } - update - ] - postModificationUpdate.apply + if (xtextDocument !== null) { + val postModificationUpdate = xtextDocument.modify [ + makeLocalContainedProc(resourceSet, associationURI, propertyURI) + ] + postModificationUpdate.apply + } else { + [| + makeLocalContainedProc(resourceSetFromSelection, associationURI, propertyURI) + saveAndRefreshSelection(resourceSetFromSelection.getEObject(input, true).eResource as XtextResource) + ].executeCommand + } } } @@ -795,6 +765,96 @@ class AadlPropertyView extends ViewPart { } } + def private saveAndRefreshSelection(XtextResource resource) { + // Save resource + resource.save(SaveOptions.newBuilder().format().getOptions().toOptionsMap()) + + // Refresh editor selection + propertySource.refreshEditorSelection + } + + def private makeLocalContainedProc(ResourceSet resourceSet, URI associationURI, URI propertyURI) { + var ()=>void update = [|] + val inputElement = resourceSet.getEObject(input, true) as NamedElement + if (associationURI !== null) { + val oldPA = resourceSet.getEObject(associationURI, true) as PropertyAssociation + val newPA = EcoreUtil.copy(oldPA) + newPA.appliesTos.clear + newPA.appliesTos.add( + Aadl2Factory.eINSTANCE.createContainedNamedElement => [ + createPath => [ + namedElement = inputElement + ] + ] + ) + if (oldPA.appliesTos.size == 0 && oldPA.owner === inputElement) { + // local PA + inputElement.ownedPropertyAssociations.remove(oldPA) + update = [| + updateView(input, null) + ] + } else if (oldPA.appliesTos.size > 1) { + // shared local contained => remove from applies to list + val toRemove = oldPA.appliesTos.findFirst [ + path.namedElement === inputElement + ] + oldPA.appliesTos.remove(toRemove) + } + (inputElement.owner as NamedElement).ownedPropertyAssociations.add(newPA) + } else { + // copy property's default value + val property = resourceSet.getEObject(propertyURI, true) as Property + (inputElement.owner as NamedElement).createOwnedPropertyAssociation => [ + it.property = property + createOwnedValue => [ + ownedValue = EcoreUtil.copy(property.defaultValue) + ] + appliesTos.add(Aadl2Factory.eINSTANCE.createContainedNamedElement => [ + createPath => [ + namedElement = inputElement + ] + ]) + ] + } + + update + } + + def private makeLocalProc(ResourceSet resourceSet, URI associationURI, URI propertyURI) { + var ()=>void update = [|] + val inputElement = resourceSet.getEObject(input, true) as NamedElement + if (associationURI !== null) { + val oldPA = resourceSet.getEObject(associationURI, true) as PropertyAssociation + val newPA = EcoreUtil.copy(oldPA) + newPA.appliesTos.clear + if (oldPA.appliesTos.size == 1) { + // non-shared local contained => remove the PA + (oldPA.owner as NamedElement).ownedPropertyAssociations.remove(oldPA) + update = [| + updateView(input, null) + ] + } else if (oldPA.appliesTos.size > 1) { + // shared local contained => remove from applies to list + val toRemove = oldPA.appliesTos.findFirst [ + path.namedElement === inputElement + ] + oldPA.appliesTos.remove(toRemove) + } + inputElement.ownedPropertyAssociations.add(newPA) + } else { + // copy property's default value + val property = resourceSet.getEObject(propertyURI, true) as Property + inputElement.createOwnedPropertyAssociation => [ + it.property = property + createOwnedValue => [ + ownedValue = EcoreUtil.copy(property.defaultValue) + ] + ] + } + + update + } + def private createContextMenu() { new MenuManager => [ removeAllWhenShown = true @@ -813,7 +873,7 @@ class AadlPropertyView extends ViewPart { makeLocalAction.enabled = false makeLocalContainedAction.enabled = false removeElementAction.enabled = false - + val selection = treeViewer.selection as IStructuredSelection if (selection.size == 1) { val firstSelectedElement = selection.firstElement as TreeEntry @@ -822,351 +882,378 @@ class AadlPropertyView extends ViewPart { openDefinitionAction.enabled = safeRead[ extension it | val treeElementEObject = (firstSelectedElement.treeElement as URI).getEObject(true) treeElementEObject instanceof PropertySet || treeElementEObject instanceof Property || - treeElementEObject instanceof BasicPropertyAssociation || - treeElementEObject instanceof BasicProperty + treeElementEObject instanceof BasicPropertyAssociation || + treeElementEObject instanceof BasicProperty ] - if (safeRead[extension it| - (firstSelectedElement.treeElement as URI).getEObject(true) instanceof Property]) { - val propertyStatus = getPropertyStatus( - (firstSelectedElement.parent as TreeEntry).treeElement as URI, - firstSelectedElement.treeElement as URI) - openPropertyAssociationAction.enabled = #[PropertyStatus.INHERITED, PropertyStatus.LOCAL, - PropertyStatus.LOCAL_CONTAINED - ].contains(propertyStatus) - createLocalAssociationAction.enabled = xtextDocument !== null && (propertyStatus == - PropertyStatus.INHERITED || propertyStatus == PropertyStatus.DEFAULT || - propertyStatus == PropertyStatus.UNDEFINED) && safeRead[ extension it | - val inputElement = input.getEObject(true) - inputElement instanceof AadlPackage || inputElement instanceof Classifier || + if (safeRead[ extension it | + (firstSelectedElement.treeElement as URI).getEObject(true) instanceof Property]) { + val propertyStatus = getPropertyStatus( + (firstSelectedElement.parent as TreeEntry).treeElement as URI, + firstSelectedElement.treeElement as URI) + openPropertyAssociationAction.enabled = #[PropertyStatus.INHERITED, PropertyStatus.LOCAL, + PropertyStatus.LOCAL_CONTAINED + ].contains(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 + ] + createLocalContainedAssociationAction.enabled = (propertyStatus == + PropertyStatus.INHERITED || propertyStatus == PropertyStatus.DEFAULT || + propertyStatus == PropertyStatus.UNDEFINED) && 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 - ] - createLocalContainedAssociationAction.enabled = xtextDocument !== null && (propertyStatus == - PropertyStatus.INHERITED || propertyStatus == PropertyStatus.DEFAULT || - propertyStatus == PropertyStatus.UNDEFINED) && 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 = 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) && - switch treeElement : firstSelectedElement.treeElement { - URI: - safeRead[ extension it | - switch treeElementEObject : treeElement.getEObject(true) { - Property: - true - BasicPropertyAssociation: - (treeElementEObject.owner as RecordValue).ownedFieldValues.size >= 2 - default: - false - }] - RangeElement: - treeElement.label == RangeElement.DELTA_LABEL - ListElement: - true - default: - false + removeElementAction.enabled = canEdit(firstSelectedElement) && + switch treeElement : firstSelectedElement.treeElement { + URI: + safeRead[ extension it | + switch treeElementEObject : treeElement.getEObject(true) { + Property: + true + BasicPropertyAssociation: + (treeElementEObject.owner as RecordValue).ownedFieldValues.size >= 2 + default: + false + }] + RangeElement: + treeElement.label == RangeElement.DELTA_LABEL + ListElement: + true + default: + false + } } - } - add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)) - ] - treeViewer.control.menu = createContextMenu(treeViewer.control) - site.registerContextMenu(it, treeViewer) - ] - } - - def private updateSelection(IWorkbenchPart part, ISelection selection) { - xtextDocument?.removeModelListener(xtextModelListener) - val currentSelection = switch selection { - case selection.empty: { - null - } - ITextSelection case part instanceof XtextEditor: { - xtextDocument = (part as XtextEditor).document - xtextDocument.readOnly[new EObjectAtOffsetHelper().resolveContainedElementAt(it, selection.offset)] + add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)) + ] + treeViewer.control.menu = createContextMenu(treeViewer.control) + site.registerContextMenu(it, treeViewer) + ] } - IStructuredSelection case selection.size == 1: { - switch selectedObject : selection.firstElement { - EObject: { - xtextDocument = null - selectedObject + + def private updateSelection(IWorkbenchPart part, ISelection selection) { + xtextDocument?.removeModelListener(xtextModelListener) + + val currentSelection = switch selection { + case selection.empty: { + null } - EObjectNode: { - xtextDocument = selectedObject.document - selectedObject.readOnly[it] + ITextSelection case part instanceof XtextEditor: { + xtextDocument = (part as XtextEditor).document + xtextDocument.readOnly [new EObjectAtOffsetHelper().resolveContainedElementAt(it, selection.offset)] } - IAdaptable: { - val propertySource = selectedObject.getAdapter(IAadlPropertySource) - if (propertySource !== null) { - xtextDocument = propertySource.document - propertySource.namedElement + IStructuredSelection case selection.size == 1: { + switch selectedObject : selection.firstElement { + EObject: { + xtextDocument = null + selectedObject + } + EObjectNode: { + xtextDocument = selectedObject.document + selectedObject.readOnly[it] + } + IAdaptable: { + propertySource = selectedObject.getAdapter(IAadlPropertySource) + if (propertySource !== null) { + xtextDocument = propertySource.document + propertySource.namedElement + } + } } } } - } - } - xtextDocument?.addModelListener(xtextModelListener) - var Object treeElementToSelect - val currentSelectionURI = try { - switch currentSelection { - PropertySet, - Property, - PropertyType, - PropertyConstant, - PackageSection: - null - NamedElement: - currentSelection.URI - PropertyAssociation case currentSelection.appliesTos.empty: { - treeElementToSelect = new TreeEntry( - new TreeEntry(currentSelection.owner.URI, - currentSelection.property.getContainerOfType(PropertySet).URI), currentSelection.property.URI) - currentSelection.owner.URI - } - PropertyAssociation case currentSelection.appliesTos.size == 1 && - currentSelection.appliesTos.head.containmentPathElements.size == 1: { - treeElementToSelect = new TreeEntry( - new TreeEntry( - currentSelection.appliesTos.head.containmentPathElements.head.namedElement.URI, - currentSelection.property.getContainerOfType(PropertySet).URI - ), currentSelection.property.URI) - currentSelection.appliesTos.head.containmentPathElements.head.namedElement.URI - } - ContainmentPathElement case currentSelection.path === null && - currentSelection.owner instanceof ContainedNamedElement: { - treeElementToSelect = new TreeEntry( - new TreeEntry( - currentSelection.namedElement.URI, - currentSelection.getContainerOfType(PropertyAssociation).property. - getContainerOfType(PropertySet).URI - ), currentSelection.getContainerOfType(PropertyAssociation).property.URI) - currentSelection.namedElement.URI - } - BasicPropertyAssociation, - PropertyExpression: { - val path = new ArrayDeque - if (currentSelection instanceof BasicPropertyAssociation) { - path.push(currentSelection.URI) - } - var currentElement = currentSelection.owner - var Element previousElement = currentSelection - while (currentElement !== null && !(currentElement instanceof PropertyAssociation)) { - switch currentElement { - ModalPropertyValue case (currentElement.owner as PropertyAssociation).modal, - BasicPropertyAssociation: - path.push(currentElement.URI) - ListValue: - path.push( - new ListElement(currentElement.ownedListElements.indexOf(previousElement), - previousElement.URI)) - RangeValue: - path.push( - new RangeElement( - switch previousElement { - case currentElement.minimum: RangeElement.MINIMUM_LABEL - case currentElement.maximum: RangeElement.MAXIMUM_LABEL - case currentElement.delta: RangeElement.DELTA_LABEL - }, previousElement.URI)) + + xtextDocument?.addModelListener(xtextModelListener) + var Object treeElementToSelect + val currentSelectionURI = try { + switch currentSelection { + PropertySet, + Property, + PropertyType, + PropertyConstant, + PackageSection: + null + NamedElement: + currentSelection.URI + PropertyAssociation case currentSelection.appliesTos.empty: { + treeElementToSelect = new TreeEntry( + new TreeEntry(currentSelection.owner.URI, + currentSelection.property.getContainerOfType(PropertySet).URI), currentSelection.property.URI) + currentSelection.owner.URI + } + PropertyAssociation case currentSelection.appliesTos.size == 1 && + currentSelection.appliesTos.head.containmentPathElements.size == 1: { + treeElementToSelect = new TreeEntry( + new TreeEntry( + currentSelection.appliesTos.head.containmentPathElements.head.namedElement.URI, + currentSelection.property.getContainerOfType(PropertySet).URI + ), currentSelection.property.URI) + currentSelection.appliesTos.head.containmentPathElements.head.namedElement.URI + } + ContainmentPathElement case currentSelection.path === null && + currentSelection.owner instanceof ContainedNamedElement: { + treeElementToSelect = new TreeEntry( + new TreeEntry( + currentSelection.namedElement.URI, + currentSelection.getContainerOfType(PropertyAssociation).property. + getContainerOfType(PropertySet).URI + ), currentSelection.getContainerOfType(PropertyAssociation).property.URI) + currentSelection.namedElement.URI + } + BasicPropertyAssociation, + PropertyExpression: { + val path = new ArrayDeque + if (currentSelection instanceof BasicPropertyAssociation) { + path.push(currentSelection.URI) + } + var currentElement = currentSelection.owner + var Element previousElement = currentSelection + while (currentElement !== null && !(currentElement instanceof PropertyAssociation)) { + switch currentElement { + ModalPropertyValue case (currentElement.owner as PropertyAssociation).modal, + BasicPropertyAssociation: + path.push(currentElement.URI) + ListValue: + path.push( + new ListElement(currentElement.ownedListElements.indexOf(previousElement), + previousElement.URI)) + RangeValue: + path.push( + new RangeElement( + switch previousElement { + case currentElement.minimum: RangeElement.MINIMUM_LABEL + case currentElement.maximum: RangeElement.MAXIMUM_LABEL + case currentElement.delta: RangeElement.DELTA_LABEL + }, previousElement.URI)) + } + previousElement = currentElement + currentElement = currentElement.owner + } + if (currentElement instanceof PropertyAssociation) { + path.push(currentElement.property.URI) + val root = if (currentElement.appliesTos.empty) { + currentElement.owner.URI + } else if (currentElement.appliesTos.size == 1 && + currentElement.appliesTos.head.containmentPathElements.size == 1) { + currentElement.appliesTos.head.containmentPathElements.head.namedElement.URI + } + treeElementToSelect = path.fold( + new TreeEntry(root, currentElement.property.getContainerOfType(PropertySet).URI), + [new TreeEntry($0, $1)]) + root + } + } } - previousElement = currentElement - currentElement = currentElement.owner + } catch (NullPointerException e) { } - if (currentElement instanceof PropertyAssociation) { - path.push(currentElement.property.URI) - val root = if (currentElement.appliesTos.empty) { - currentElement.owner.URI - } else if (currentElement.appliesTos.size == 1 && - currentElement.appliesTos.head.containmentPathElements.size == 1) { - currentElement.appliesTos.head.containmentPathElements.head.namedElement.URI + + if (currentSelectionURI !== null) { + editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(currentSelection) + if (currentSelection !== null && currentSelection.eResource !== null) { + resourceSetFromSelection = currentSelection.eResource.resourceSet + if (currentSelectionURI == previousSelectionURI) { + if (treeElementToSelect !== null) { + treeViewer.setSelection(new StructuredSelection(treeElementToSelect), true) } - treeElementToSelect = path.fold( - new TreeEntry(root, currentElement.property.getContainerOfType(PropertySet).URI), - [new TreeEntry($0, $1)]) - root + pageBook.showPage(treeViewerComposite) + } else { + previousSelectionURI = currentSelectionURI + updateView(currentSelectionURI, treeElementToSelect) + } } + } else { + synchronized (jobLock) { + if (cachePropertyLookupJob !== null) { + cachePropertyLookupJob.cancel + cachePropertyLookupJob = null + } + } + pageBook.showPage(noPropertiesLabel) + editingDomain = null + resourceSetFromSelection = null + previousSelectionURI = null } - } - } catch (NullPointerException e) { - } - if (currentSelectionURI !== null) { - editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(currentSelection) - resourceSetFromSelection = currentSelection.eResource.resourceSet - if (currentSelectionURI == previousSelectionURI) { - if (treeElementToSelect !== null) { - treeViewer.setSelection(new StructuredSelection(treeElementToSelect), true) - } - pageBook.showPage(treeViewerComposite) - } else { - previousSelectionURI = currentSelectionURI - synchronized (jobLock) { - if (cachePropertyLookupJob !== null && cachePropertyLookupJob.state != Job.NONE) { - cachePropertyLookupJob.cancel + // Build list of imported properties for "Show only imported properties" filter button to use + var package = getPackageSection(currentSelection) + importedPropertyGroups.clear + if (package !== null) { + val units = (package as PackageSection).getImportedUnits() + + for (ModelUnit unit : units) { + if (unit instanceof PropertySet) { + for (prop : unit.ownedProperties) { + importedPropertyGroups.add(new FilterCriterion(unit.name, prop.name)) + } + } } - cachePropertyLookupJob = createCachePropertyLookupJob(currentSelectionURI, treeElementToSelect) - cachePropertyLookupJob.schedule + showOnlyImportedPropertiesAction.enabled = true + } else { + showOnlyImportedPropertiesAction.enabled = false } } - } else { - synchronized (jobLock) { - if (cachePropertyLookupJob !== null) { - cachePropertyLookupJob.cancel - cachePropertyLookupJob = null + // Recursive function to get the package section related to a node if it exists + def private EObject getPackageSection(EObject selection) { + if (selection === null) { + return null } - } - pageBook.showPage(noPropertiesLabel) - editingDomain = null - resourceSetFromSelection = null - previousSelectionURI = null - } - - // Build list of imported properties for "Show only imported properties" filter button to use - var package = getPackageSection(currentSelection) - importedPropertyGroups.clear - if (package !== null) { - val units = (package as PackageSection).getImportedUnits() - - for (ModelUnit unit: units) { - if (unit instanceof PropertySet) { - for (prop: unit.ownedProperties) { - importedPropertyGroups.add(new FilterCriterion(unit.name, prop.name)) + + if (selection instanceof PackageSection) { + return selection + } else if (selection instanceof Element) { + var owner = selection.owner + if (owner !== null) { + getPackageSection(owner) } } } - showOnlyImportedPropertiesAction.enabled = true - } else { - showOnlyImportedPropertiesAction.enabled = false - } - } - // Recursive function to get the package section related to a node if it exists - def private EObject getPackageSection(EObject selection) { - - if (selection === null ) { - return null - } - - if (selection instanceof PackageSection) { - return selection - } - else if (selection instanceof Element){ - var owner = selection.owner - if (owner !== null) { - getPackageSection(owner) + def package safeRead((ResourceSet)=>T operation) { + // text editor open, click element. close text editor. go to diagram and null is thrown + if (xtextDocument !== null) { + xtextDocument.readOnly[operation.apply(resourceSet)] + } else if (editingDomain instanceof TransactionalEditingDomain) { + try { + TransactionUtil.runExclusive(editingDomain, new RunnableWithResult.Impl { + override run() { + result = operation.apply(editingDomain.resourceSet) + status = Status.OK_STATUS + } + }) + } catch (InterruptedException e) { + + // Allow the operation to determine what the result should be + operation.apply(null) + } + } else { + operation.apply(resourceSetFromSelection) + } } - } - } - - def package safeRead((ResourceSet)=>T operation) { - if (xtextDocument !== null) { - xtextDocument.readOnly[operation.apply(resourceSet)] - } else if (editingDomain instanceof TransactionalEditingDomain) { - try { - TransactionUtil.runExclusive(editingDomain, - new RunnableWithResult.Impl { - override run() { - result = operation.apply(editingDomain.resourceSet) - status = Status.OK_STATUS - } - }) - } catch (InterruptedException e) { - //Allow the operation to determine what the result should be - operation.apply(null) + def package createCachePropertyLookupJob(URI elementURI, Object objectToSelect) { + new CachePropertyLookupJob(elementURI, this, site.shell.display, scopeProvider, [| + pageBook.showPage(populatingViewLabel) + ], [| + treeViewer.input = elementURI + if (objectToSelect !== null) { + treeViewer.setSelection(new StructuredSelection(objectToSelect), true) + } + pageBook.showPage(treeViewerComposite) + ]) } - } else { - operation.apply(resourceSetFromSelection) - } - } - def private createCachePropertyLookupJob(URI elementURI, Object objectToSelect) { - new CachePropertyLookupJob(elementURI, this, site.shell.display, scopeProvider, - [| - pageBook.showPage(populatingViewLabel) - ], - [| - treeViewer.input = elementURI - if (objectToSelect !== null) { - treeViewer.setSelection(new StructuredSelection(objectToSelect), true) - } - pageBook.showPage(treeViewerComposite) - ]) - } - - def package getPropertyStatus(URI propertySetURI, URI propertyURI) { - safeRead[ extension it | - val associationURI = cachedPropertyAssociations.get(propertySetURI).get(propertyURI) - if (associationURI !== null) { - val association = associationURI.getEObject(true) as PropertyAssociation - val inputElement = input.getEObject(true) - if (inputElement == association.owner) { - PropertyStatus.LOCAL - } else if (association.appliesTos.exists[inputElement == containmentPathElements.last.namedElement]) { - if (association.appliesTos.size > 1) { - PropertyStatus.LOCAL_SHARED + def package getPropertyStatus(URI propertySetURI, URI propertyURI) { + safeRead[ extension it | + val associationURI = cachedPropertyAssociations.get(propertySetURI).get(propertyURI) + if (associationURI !== null) { + val association = associationURI.getEObject(true) as PropertyAssociation + if (association === null) { + associationURI.getEObject(true) as PropertyAssociation + } + val inputElement = input.getEObject(true) + if (inputElement == association.owner) { + PropertyStatus.LOCAL + } else if (association.appliesTos.exists [ + inputElement == containmentPathElements.last.namedElement + ]) { + if (association.appliesTos.size > 1) { + PropertyStatus.LOCAL_SHARED + } else { + PropertyStatus.LOCAL_CONTAINED + } + } else { + PropertyStatus.INHERITED + } + } else if ((propertyURI.getEObject(true) as Property).defaultValue !== null) { + PropertyStatus.DEFAULT } else { - PropertyStatus.LOCAL_CONTAINED + PropertyStatus.UNDEFINED } + ] + } + + def private getPropertyStatusNeverUndefined(URI associationURI) { + if (associationURI !== null) { + safeRead[ extension it | + val association = associationURI.getEObject(true) as PropertyAssociation + val inputElement = input.getEObject(true) + if (inputElement == association.owner) { + PropertyStatus.LOCAL + } else if (association.appliesTos.exists [ + inputElement == containmentPathElements.last.namedElement + ]) { + PropertyStatus.LOCAL_CONTAINED + } else { + PropertyStatus.INHERITED + } + ] } else { - PropertyStatus.INHERITED + PropertyStatus.DEFAULT } - } else if ((propertyURI.getEObject(true) as Property).defaultValue !== null) { - PropertyStatus.DEFAULT - } else { - PropertyStatus.UNDEFINED } - ] - } - def private getPropertyStatusNeverUndefined(URI associationURI) { - if (associationURI !== null) { - safeRead[ extension it | - val association = associationURI.getEObject(true) as PropertyAssociation - val inputElement = input.getEObject(true) - if (inputElement == association.owner) { - PropertyStatus.LOCAL - } else if (association.appliesTos.exists[inputElement == containmentPathElements.last.namedElement]) { - PropertyStatus.LOCAL_CONTAINED + def package getPropertyStatusNeverUndefined(extension ResourceSet resourceSet, + PropertyAssociation association) { + if (association === null) { + PropertyStatus.DEFAULT } else { - PropertyStatus.INHERITED + val inputElement = input.getEObject(true) + if (inputElement == association.owner) { + PropertyStatus.LOCAL + } else if (association.appliesTos. + exists[inputElement == containmentPathElements.last.namedElement]) { + PropertyStatus.LOCAL_CONTAINED + } else { + PropertyStatus.INHERITED + } } - ] - } else { - PropertyStatus.DEFAULT - } - } + } - def package getPropertyStatusNeverUndefined(extension ResourceSet resourceSet, PropertyAssociation association) { - if (association === null) { - PropertyStatus.DEFAULT - } else { - val inputElement = input.getEObject(true) - if (inputElement == association.owner) { - PropertyStatus.LOCAL - } else if (association.appliesTos.exists[inputElement == containmentPathElements.last.namedElement]) { - PropertyStatus.LOCAL_CONTAINED - } else { - PropertyStatus.INHERITED + def package updateView(URI elementURI, Object objectToSelect) { + synchronized (jobLock) { + if (cachePropertyLookupJob !== null && cachePropertyLookupJob.state != Job.NONE) { + cachePropertyLookupJob.cancel + } + cachePropertyLookupJob = createCachePropertyLookupJob(elementURI, objectToSelect) + cachePropertyLookupJob.schedule + } } + + def package executeCommand(()=>void proc) { + var cmd = new RecordingCommand(editingDomain as TransactionalEditingDomain) { + override protected doExecute() { + proc.apply + } + } + + editingDomain.commandStack.execute(cmd) + } } - } -} + \ No newline at end of file diff --git a/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/IAadlPropertySource.java b/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/IAadlPropertySource.java index 77969cba12d..2d591fbcf7c 100644 --- a/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/IAadlPropertySource.java +++ b/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/IAadlPropertySource.java @@ -20,4 +20,9 @@ public interface IAadlPropertySource { * @return the Xtext document */ IXtextDocument getDocument(); + + /** + * Refresh editor selection + */ + void refreshEditorSelection(); } \ No newline at end of file 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..bd50e8555eb 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 @@ -1,13 +1,13 @@ /* - * + * * * Copyright 2014 by Carnegie Mellon University, all rights reserved. - * + * * Use of the Open Source AADL Tool Environment (OSATE) is subject to the terms of the license set forth * at http://www.eclipse.org/org/documents/epl-v10.html. - * + * * NO WARRANTY - * + * * ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER PROPERTY OR RIGHTS GRANTED OR PROVIDED BY * CARNEGIE MELLON UNIVERSITY PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN "AS-IS" BASIS. * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, @@ -17,14 +17,14 @@ * REGARDLESS OF WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. LICENSEE AGREES THAT IT WILL NOT * MAKE ANY WARRANTY ON BEHALF OF CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON CONCERNING THE * APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE DELIVERABLES UNDER THIS LICENSE. - * + * * Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie Mellon University, its trustees, officers, * employees, and agents from all claims or demands made against them (and any related losses, expenses, or * attorney's fees) arising out of, or relating to Licensee's and/or its sub licensees' negligent use or willful * misuse of or negligent conduct or willful misconduct regarding the Software, facilities, or other rights or * assistance granted by Carnegie Mellon University under this License, including, but not limited to, any claims of * product liability, personal injury, death, damage to property, or violation of any laws or regulations. - * + * * Carnegie Mellon Carnegie Mellon University Software Engineering Institute authored documents are sponsored by the U.S. Department * of Defense under Contract F19628-00-C-0003. Carnegie Mellon University retains copyrights in all material produced * under this contract. The U.S. Government retains a non-exclusive, royalty-free license to publish or reproduce these @@ -64,14 +64,16 @@ 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 +import org.eclipse.xtext.resource.SaveOptions package class ValueColumnEditingSupport extends EditingSupport { val static EMBEDDED_RESOURCE_NAME_SUFFIX = "_embedded_for_property_view_cell_editor" - + val AadlPropertyView propertyView - + val delim = System.getProperty("line.separator") - + var creatingNewLocalInEdit = false var newContained = false var String initialEditablePart @@ -84,7 +86,7 @@ package class ValueColumnEditingSupport extends EditingSupport { super(treeViewer) this.propertyView = propertyView } - + override protected canEdit(Object element) { if (propertyView.nextEditIsLocalCreation) { creatingNewLocalInEdit = true @@ -102,49 +104,71 @@ package class ValueColumnEditingSupport extends EditingSupport { propertyView.canEdit(element) } } - + override protected getCellEditor(Object element) { - new XtextStyledTextCellEditor(SWT.SINGLE, MyAadl2Activator.getInstance.getInjector(MyAadl2Activator.ORG_OSATE_XTEXT_AADL2_AADL2), propertyView.xtextDocument.readOnly[convertToIResource.project]) => [ + if (propertyView.xtextDocument === null) { + val NamedElement curSelection = propertyView.resourceSetFromSelection.getEObject(propertyView.input, + true) as NamedElement + new XtextStyledTextCellEditor(SWT.SINGLE, + MyAadl2Activator.getInstance.getInjector(MyAadl2Activator.ORG_OSATE_XTEXT_AADL2_AADL2), + curSelection.eResource.convertToIResource.project) => [ + create(propertyView.treeViewer.tree) + ] + } else { + new XtextStyledTextCellEditor(SWT.SINGLE, + MyAadl2Activator.getInstance.getInjector(MyAadl2Activator.ORG_OSATE_XTEXT_AADL2_AADL2), propertyView. + xtextDocument.readOnly[convertToIResource.project]) => [ create(propertyView.treeViewer.tree) - ] + ] + } } - + override protected getValue(Object element) { - propertyView.xtextDocument.readOnly[ - val modelUnitNameEndOffset = contents.head.findNodesForFeature(Aadl2Package.eINSTANCE.namedElement_Name).head.endOffset + if (propertyView.xtextDocument === null) { + val inputElement = propertyView.resourceSetFromSelection.getEObject(propertyView.input, + true) as NamedElement + val xtextResource = inputElement.eResource as XtextResource + val contents = inputElement.eResource.contents + 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 val offsetElement = switch inputElement { AadlPackage, Classifier: inputElement case !newContained: inputElement default: inputElement.containingClassifier - } + } val firstPA = offsetElement.ownedPropertyAssociations.empty initialEditablePart = '' updateOffset = if (firstPA) { switch offsetElement { AadlPackage, FeatureGroupType, - ComponentClassifier case offsetElement.ownedAnnexSubclauses.empty: offsetElement.node.lastLeaf.previousNode.previousNode.offset - ComponentClassifier: offsetElement.ownedAnnexSubclauses.head.node.offset - Subcomponent case !offsetElement.ownedModeBindings.empty: offsetElement.ownedModeBindings.head.node.previousNode.previousNode.previousNode.offset + ComponentClassifier case offsetElement.ownedAnnexSubclauses.empty: + offsetElement.node.lastLeaf.previousNode.previousNode.offset + ComponentClassifier: + offsetElement.ownedAnnexSubclauses.head.node.offset + Subcomponent case !offsetElement.ownedModeBindings.empty: + offsetElement.ownedModeBindings.head.node.previousNode.previousNode.previousNode.offset ModalPath case !offsetElement.inModeOrTransitions.empty: { - offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalPath_InModeOrTransition).head.previousNode.previousNode.previousNode.offset + offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalPath_InModeOrTransition).head. + previousNode.previousNode.previousNode.offset } SubprogramCallSequence case !offsetElement.inModes.empty: { - offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalElement_InMode).head.previousNode.previousNode.previousNode.offset + offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalElement_InMode).head. + previousNode.previousNode.previousNode.offset } - default: offsetElement.node.lastLeaf.offset + default: + offsetElement.node.lastLeaf.offset } } else { offsetElement.ownedPropertyAssociations.last.node.endOffset } updateLength = 0 - val inPropertiesSection = newContained || inputElement instanceof AadlPackage || inputElement instanceof Classifier + val inPropertiesSection = newContained || inputElement instanceof AadlPackage || + inputElement instanceof Classifier updatePrefix = '' if (firstPA) { updatePrefix += if (inPropertiesSection) { @@ -168,68 +192,194 @@ package class ValueColumnEditingSupport extends EditingSupport { } else { delim } - val prefix = propertyView.xtextDocument.get(0, updateOffset) - val suffix = propertyView.xtextDocument.get(updateOffset, propertyView.xtextDocument.length - updateOffset) - new CellEditorPartialValue('''«new StringBuilder(prefix).insert(modelUnitNameEndOffset, EMBEDDED_RESOURCE_NAME_SUFFIX)»«updatePrefix»''', + + val text = xtextResource.parseResult.rootNode.text + val prefix = text.substring(0, updateOffset) + val suffix = text.substring(updateOffset, updateOffset + text.length - 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(inputElement.eResource.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) - new CellEditorPartialValue(new StringBuilder(prefix).insert(modelUnitNameEndOffset, EMBEDDED_RESOURCE_NAME_SUFFIX).toString, + initialEditablePart = xtextResource.serializer.serialize(expression).replaceAll("\n", ""). + replaceAll("\r", "").replaceAll("\t", "").trim + val text = xtextResource.parseResult.rootNode.text + val prefix = text.substring(0, expressionNode.offset) + val suffix = text.substring(expressionNode.endOffset, + expressionNode.endOffset + text.length - 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 + new StringBuilder(suffix).insert(endNameEndOffset - expressionNode.endOffset, + EMBEDDED_RESOURCE_NAME_SUFFIX).toString ) } - ] + } else { + propertyView.xtextDocument.readOnly [ + 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 + val offsetElement = switch inputElement { + AadlPackage, + Classifier: inputElement + case !newContained: inputElement + default: inputElement.containingClassifier + } + val firstPA = offsetElement.ownedPropertyAssociations.empty + initialEditablePart = '' + updateOffset = if (firstPA) { + switch offsetElement { + AadlPackage, + FeatureGroupType, + ComponentClassifier case offsetElement.ownedAnnexSubclauses.empty: + offsetElement.node.lastLeaf.previousNode.previousNode.offset + ComponentClassifier: offsetElement.ownedAnnexSubclauses.head.node.offset + Subcomponent case !offsetElement.ownedModeBindings.empty: offsetElement.ownedModeBindings.head.node.previousNode.previousNode.previousNode.offset + ModalPath case !offsetElement.inModeOrTransitions.empty: { + offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalPath_InModeOrTransition). + head.previousNode.previousNode.previousNode.offset + } + SubprogramCallSequence case !offsetElement.inModes.empty: { + offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalElement_InMode).head. + previousNode.previousNode.previousNode.offset + } + default: + offsetElement.node.lastLeaf.offset + } + } else { + offsetElement.ownedPropertyAssociations.last.node.endOffset + } + updateLength = 0 + val inPropertiesSection = newContained || inputElement instanceof AadlPackage || + inputElement instanceof Classifier + updatePrefix = '' + if (firstPA) { + updatePrefix += if (inPropertiesSection) { + '''properties«delim»''' + } else { + ''' {''' + } + } else { + updatePrefix += delim + } + updatePrefix += '''«propertyName» => ''' + updateSuffix = '' + if (newContained) { + updateSuffix += ''' applies to «inputElement.name»''' + } + updateSuffix += ';' + updateSuffix += if (inPropertiesSection) { + '' + } else if (firstPA) { + '}' + } else { + delim + } + val prefix = propertyView.xtextDocument.get(0, updateOffset) + val suffix = propertyView.xtextDocument.get(updateOffset, + propertyView.xtextDocument.length - 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 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) + 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 + getPropertyExpression(resource.resourceSet, element); + } + + 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 - ) as PropertyAssociation).ownedValues.head.ownedValue + URI: + switch treeElementObject : resourceSet.getEObject(treeElement, true) { + Property: { + (resourceSet.getEObject( + propertyView.cachedPropertyAssociations.get( + ((element as TreeEntry).parent as TreeEntry).treeElement).get(treeElement), + true + ) as PropertyAssociation).ownedValues.head.ownedValue + } + BasicPropertyAssociation: + treeElementObject.value } - BasicPropertyAssociation: treeElementObject.value - } - RangeElement: resourceSet.getEObject(treeElement.expressionURI, true) as PropertyExpression - ListElement: resourceSet.getEObject(treeElement.expressionURI, true) as PropertyExpression + RangeElement: + resourceSet.getEObject(treeElement.expressionURI, true) as PropertyExpression + 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::'] - val toStrip = predeclaredNames.findFirst[qualifiedName.toLowerCase.startsWith(it)]?:'' + 'modeling_properties::', 'programming_properties::', 'thread_properties::', 'timing_properties::'] + val toStrip = predeclaredNames.findFirst[qualifiedName.toLowerCase.startsWith(it)] ?: '' qualifiedName.substring(toStrip.length) } 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 { - override process(XtextResource state) throws Exception { - state.update(updateOffset, updateLength, updatePrefix + value + updateSuffix) + val strippedVal = (value as String).replaceAll("\\s+","") + if(!(strippedVal as String).empty) { + if (creatingNewLocalInEdit || initialEditablePart != strippedVal) { + // insert new property value + if (propertyView.xtextDocument !== null) { + propertyView.xtextDocument.modify(new IUnitOfWork.Void { + override process(XtextResource state) throws Exception { + state.update(updateOffset, updateLength, updatePrefix + strippedVal + updateSuffix) + } + }) + + propertyView.treeViewer.refresh((element as TreeEntry).propertyParent) + + // select inserted/modified text in editor + val activeEditor = propertyView.site.workbenchWindow.activePage.activeEditor + if (activeEditor instanceof ITextEditor) { + activeEditor.selectAndReveal(updateOffset, + updatePrefix.length + (strippedVal as String).length + updateSuffix.length) + } + } else { + val inputElement = propertyView.resourceSetFromSelection.getEObject(propertyView.input, + true) as NamedElement + val xtextResource = inputElement.eResource as XtextResource + propertyView.executeCommand([| + xtextResource.update(updateOffset, updateLength, updatePrefix + strippedVal + updateSuffix) + xtextResource.save(SaveOptions.newBuilder().format().getOptions().toOptionsMap()) + propertyView.updateView(propertyView.input, null) + ]) } - }) - - propertyView.treeViewer.refresh((element as TreeEntry).propertyParent) - - // select inserted/modified text in editor - val activeEditor = propertyView.site.workbenchWindow.activePage.activeEditor - if (activeEditor instanceof ITextEditor) { - activeEditor.selectAndReveal(updateOffset, updatePrefix.length +(value as String).length + updateSuffix.length) } } } @@ -241,7 +391,7 @@ package class ValueColumnEditingSupport extends EditingSupport { } result ?: node } - + def private static getPreviousNode(INode node) { var lln = node.previousSibling while (lln instanceof HiddenLeafNode) { @@ -249,9 +399,9 @@ package class ValueColumnEditingSupport extends EditingSupport { } lln } - + def private TreeEntry getPropertyParent(TreeEntry element) { - if (element.treeElement instanceof URI && propertyView.safeRead[extension it | (element.treeElement as URI).getEObject(true) instanceof Property]) { + if (element.treeElement instanceof URI && propertyView.safeRead [extension it | (element.treeElement as URI).getEObject(true) instanceof Property]) { element } else { (element.parent as TreeEntry).propertyParent @@ -259,7 +409,7 @@ package class ValueColumnEditingSupport extends EditingSupport { } def private Property getProperty(TreeEntry element) { - propertyView.safeRead[extension it | + propertyView.safeRead [ extension it | if (element.treeElement instanceof URI && (element.treeElement as URI).getEObject(true) instanceof Property) { (element.treeElement as URI).getEObject(true) } else { @@ -267,4 +417,4 @@ package class ValueColumnEditingSupport extends EditingSupport { } ] as Property } -} \ No newline at end of file +} diff --git a/ge/org.osate.ge/src/org/osate/ge/internal/ui/editor/GraphitiEditPartAdapterFactory.java b/ge/org.osate.ge/src/org/osate/ge/internal/ui/editor/GraphitiEditPartAdapterFactory.java index e381ad1b7a3..f1dcaca03f7 100644 --- a/ge/org.osate.ge/src/org/osate/ge/internal/ui/editor/GraphitiEditPartAdapterFactory.java +++ b/ge/org.osate.ge/src/org/osate/ge/internal/ui/editor/GraphitiEditPartAdapterFactory.java @@ -82,6 +82,7 @@ public T getAdapter(Object adaptableObject, Class adapterType) { return adapterType.cast(new IAadlPropertySource() { private final IXtextDocument document = AgeXtextUtil.getDocumentByRootElement(namedElement.getElementRoot()); private final NamedElement element = namedElement; + private final AgeDiagramEditor editor = (AgeDiagramEditor) editorPart; @Override public IXtextDocument getDocument() { @@ -92,6 +93,13 @@ public IXtextDocument getDocument() { public NamedElement getNamedElement() { return element; } + + @Override + public void refreshEditorSelection() { + editor.clearSelection(); + editor.setFocus(); + editor.selectDiagramElements(new DiagramElement[] { de }); + } }); } } else if(DiagramElement.class.equals(adapterType)) { From 280696e3a4269a8f728b6500bd17067e109c75c3 Mon Sep 17 00:00:00 2001 From: "ryan.mcilnay" Date: Thu, 25 Oct 2018 13:36:01 -0500 Subject: [PATCH 2/8] property view editor support --- .../ui/propertyview/AadlPropertyView.xtend | 123 ++++--- .../ui/propertyview/IAadlPropertySource.java | 5 - .../ValueColumnEditingSupport.xtend | 301 +++++++----------- .../GraphitiEditPartAdapterFactory.java | 8 - 4 files changed, 169 insertions(+), 268 deletions(-) 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 b88b274b021..95cd8343d65 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 @@ -224,9 +224,9 @@ class AadlPropertyView extends ViewPart { var IURIEditorOpener editorOpener var URI previousSelectionURI = null + + var IWorkbenchPart selectedPart = null - var IAadlPropertySource propertySource = null - var CachePropertyLookupJob cachePropertyLookupJob = null val jobLock = new Object @@ -256,7 +256,7 @@ class AadlPropertyView extends ViewPart { } override partClosed(IWorkbenchPart part) { - if (part instanceof XtextEditor) { + if (part instanceof XtextEditor && xtextDocument === (part as XtextEditor).document) { xtextDocument = null } } @@ -270,7 +270,7 @@ class AadlPropertyView extends ViewPart { if (selectionProvider instanceof IPostSelectionProvider) { selectionProvider.addPostSelectionChangedListener(selectionChangedListener) } - } else if(part instanceof EditorPart) { + } else if (part instanceof EditorPart) { updateSelection(part.editorSite.selectionProvider.selection) } } @@ -563,38 +563,25 @@ class AadlPropertyView extends ViewPart { URI: { if (xtextDocument === null) { [| - val treeElementObject = resourceSetFromSelection.getEObject(treeElement, true) + val treeElementObject = resourceSetFromSelection.getEObject(treeElement, true) switch treeElementObject { Property: { - val associationURI = cachedPropertyAssociations.get( - (selectedElement.parent as TreeEntry).treeElement).get( - selectedElement.treeElement) - val association = resourceSetFromSelection.getEObject(associationURI, - true) as PropertyAssociation - (association.owner as NamedElement).ownedPropertyAssociations.remove( - association) + removePropertyAssociation(selectedElement, resourceSetFromSelection) } BasicPropertyAssociation: { (treeElementObject.owner as RecordValue).ownedFieldValues.remove( treeElementObject); + treeViewer.refresh(selectedElement.parent) } } - (resourceSetFromSelection.getEObject(input, true).eResource as XtextResource).save( - SaveOptions.newBuilder().format().getOptions().toOptionsMap()) - updateView(input, null) + saveAndRefreshSelection(resourceSetFromSelection.getEObject(input, true).eResource as XtextResource) ].executeCommand } else { val postModificationUpdate = xtextDocument.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); + removePropertyAssociation(selectedElement, resourceSet); [| updateView(input, null) ] @@ -614,9 +601,10 @@ class AadlPropertyView extends ViewPart { val inputElement = resourceSetFromSelection.getEObject(input, true) as NamedElement [| ((editingDomain.resourceSet.getEObject((treeElement as RangeElement).expressionURI, - true) as PropertyExpression).owner as RangeValue).delta = null - (inputElement.eResource as XtextResource).save( - SaveOptions.newBuilder().format().getOptions().toOptionsMap()) + true) as PropertyExpression).owner as RangeValue).delta = null + (inputElement.eResource as XtextResource).save( + SaveOptions.newBuilder().format().getOptions().toOptionsMap()) + treeViewer.refresh(selectedElement.parent) ].executeCommand } else { xtextDocument.modify(new IUnitOfWork.Void { @@ -630,14 +618,15 @@ class AadlPropertyView extends ViewPart { } ListElement: { if (xtextDocument === null) { - val inputElement = resourceSetFromSelection.getEObject(input, true) as NamedElement [| ((resourceSetFromSelection.getEObject((treeElement as ListElement).expressionURI, true) as PropertyExpression).owner as ListValue).ownedListElements.remove( (treeElement as ListElement).index ) + val inputElement = resourceSetFromSelection.getEObject(input, true) as NamedElement (inputElement.eResource as XtextResource).save( SaveOptions.newBuilder().format().getOptions().toOptionsMap()) + treeViewer.refresh(selectedElement.parent) ].executeCommand } else { xtextDocument.modify(new IUnitOfWork.Void { @@ -676,7 +665,6 @@ class AadlPropertyView extends ViewPart { override run() { val selectedElement = (treeViewer.selection as IStructuredSelection).firstElement as TreeEntry val uriToOpen = safeRead[ extension it | - val associationTemp = cachedPropertyAssociations.get((selectedElement.parent as TreeEntry).treeElement). get(selectedElement.treeElement).getEObject(true) @@ -712,15 +700,14 @@ class AadlPropertyView extends ViewPart { val propertyURI = selectedElement.treeElement as URI val associationURI = cachedPropertyAssociations.get((selectedElement.parent as TreeEntry).treeElement). get(propertyURI) - if (xtextDocument !== null) { val postModificationUpdate = xtextDocument.modify [ - makeLocalProc(resourceSet, associationURI, propertyURI) + makeLocalProperty(resourceSet, associationURI, propertyURI) ] postModificationUpdate.apply } else { [| - makeLocalProc(resourceSetFromSelection, associationURI, propertyURI) + makeLocalProperty(resourceSetFromSelection, associationURI, propertyURI) saveAndRefreshSelection(resourceSetFromSelection.getEObject(input, true).eResource as XtextResource) ].executeCommand } @@ -736,13 +723,14 @@ class AadlPropertyView extends ViewPart { get(propertyURI) if (xtextDocument !== null) { val postModificationUpdate = xtextDocument.modify [ - makeLocalContainedProc(resourceSet, associationURI, propertyURI) + makeLocalContainedProperty(resourceSet, associationURI, propertyURI) ] postModificationUpdate.apply } else { [| - makeLocalContainedProc(resourceSetFromSelection, associationURI, propertyURI) - saveAndRefreshSelection(resourceSetFromSelection.getEObject(input, true).eResource as XtextResource) + makeLocalContainedProperty(resourceSetFromSelection, associationURI, propertyURI) + saveAndRefreshSelection(resourceSetFromSelection.getEObject(input, true).eResource as XtextResource) + ].executeCommand } } @@ -764,16 +752,25 @@ class AadlPropertyView extends ViewPart { } } } + + def private removePropertyAssociation(TreeEntry selectedElement, ResourceSet resourceSet) { + 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) + } def private saveAndRefreshSelection(XtextResource resource) { // Save resource resource.save(SaveOptions.newBuilder().format().getOptions().toOptionsMap()) // Refresh editor selection - propertySource.refreshEditorSelection + selectedPart.setFocus() + updateSelection(new StructuredSelection) } - def private makeLocalContainedProc(ResourceSet resourceSet, URI associationURI, URI propertyURI) { + def private makeLocalContainedProperty(ResourceSet resourceSet, URI associationURI, URI propertyURI) { var ()=>void update = [|] val inputElement = resourceSet.getEObject(input, true) as NamedElement if (associationURI !== null) { @@ -820,7 +817,7 @@ class AadlPropertyView extends ViewPart { update } - def private makeLocalProc(ResourceSet resourceSet, URI associationURI, URI propertyURI) { + def private makeLocalProperty(ResourceSet resourceSet, URI associationURI, URI propertyURI) { var ()=>void update = [|] val inputElement = resourceSet.getEObject(input, true) as NamedElement if (associationURI !== null) { @@ -959,7 +956,7 @@ class AadlPropertyView extends ViewPart { def private updateSelection(IWorkbenchPart part, ISelection selection) { xtextDocument?.removeModelListener(xtextModelListener) - + selectedPart = part val currentSelection = switch selection { case selection.empty: { null @@ -979,7 +976,7 @@ class AadlPropertyView extends ViewPart { selectedObject.readOnly[it] } IAdaptable: { - propertySource = selectedObject.getAdapter(IAadlPropertySource) + val propertySource = selectedObject.getAdapter(IAadlPropertySource) if (propertySource !== null) { xtextDocument = propertySource.document propertySource.namedElement @@ -1127,7 +1124,8 @@ class AadlPropertyView extends ViewPart { if (selection instanceof PackageSection) { return selection - } else if (selection instanceof Element) { + } + else if (selection instanceof Element){ var owner = selection.owner if (owner !== null) { getPackageSection(owner) @@ -1136,13 +1134,13 @@ class AadlPropertyView extends ViewPart { } def package safeRead((ResourceSet)=>T operation) { - // text editor open, click element. close text editor. go to diagram and null is thrown if (xtextDocument !== null) { xtextDocument.readOnly[operation.apply(resourceSet)] } else if (editingDomain instanceof TransactionalEditingDomain) { try { - TransactionUtil.runExclusive(editingDomain, new RunnableWithResult.Impl { - override run() { + TransactionUtil.runExclusive(editingDomain, + new RunnableWithResult.Impl { + override run() { result = operation.apply(editingDomain.resourceSet) status = Status.OK_STATUS } @@ -1157,16 +1155,18 @@ class AadlPropertyView extends ViewPart { } } - def package createCachePropertyLookupJob(URI elementURI, Object objectToSelect) { - new CachePropertyLookupJob(elementURI, this, site.shell.display, scopeProvider, [| - pageBook.showPage(populatingViewLabel) - ], [| - treeViewer.input = elementURI - if (objectToSelect !== null) { - treeViewer.setSelection(new StructuredSelection(objectToSelect), true) - } - pageBook.showPage(treeViewerComposite) - ]) + def private createCachePropertyLookupJob(URI elementURI, Object objectToSelect) { + new CachePropertyLookupJob(elementURI, this, site.shell.display, scopeProvider, + [| + pageBook.showPage(populatingViewLabel) + ], + [| + treeViewer.input = elementURI + if (objectToSelect !== null) { + treeViewer.setSelection(new StructuredSelection(objectToSelect), true) + } + pageBook.showPage(treeViewerComposite) + ]) } def package getPropertyStatus(URI propertySetURI, URI propertyURI) { @@ -1174,15 +1174,10 @@ class AadlPropertyView extends ViewPart { val associationURI = cachedPropertyAssociations.get(propertySetURI).get(propertyURI) if (associationURI !== null) { val association = associationURI.getEObject(true) as PropertyAssociation - if (association === null) { - associationURI.getEObject(true) as PropertyAssociation - } val inputElement = input.getEObject(true) if (inputElement == association.owner) { PropertyStatus.LOCAL - } else if (association.appliesTos.exists [ - inputElement == containmentPathElements.last.namedElement - ]) { + } else if (association.appliesTos.exists[inputElement == containmentPathElements.last.namedElement]) { if (association.appliesTos.size > 1) { PropertyStatus.LOCAL_SHARED } else { @@ -1206,9 +1201,7 @@ class AadlPropertyView extends ViewPart { val inputElement = input.getEObject(true) if (inputElement == association.owner) { PropertyStatus.LOCAL - } else if (association.appliesTos.exists [ - inputElement == containmentPathElements.last.namedElement - ]) { + } else if (association.appliesTos.exists[inputElement == containmentPathElements.last.namedElement]) { PropertyStatus.LOCAL_CONTAINED } else { PropertyStatus.INHERITED @@ -1219,16 +1212,14 @@ class AadlPropertyView extends ViewPart { } } - def package getPropertyStatusNeverUndefined(extension ResourceSet resourceSet, - PropertyAssociation association) { + def package getPropertyStatusNeverUndefined(extension ResourceSet resourceSet, PropertyAssociation association) { if (association === null) { PropertyStatus.DEFAULT } else { val inputElement = input.getEObject(true) if (inputElement == association.owner) { PropertyStatus.LOCAL - } else if (association.appliesTos. - exists[inputElement == containmentPathElements.last.namedElement]) { + } else if (association.appliesTos.exists[inputElement == containmentPathElements.last.namedElement]) { PropertyStatus.LOCAL_CONTAINED } else { PropertyStatus.INHERITED @@ -1238,6 +1229,8 @@ class AadlPropertyView extends ViewPart { def package updateView(URI elementURI, Object objectToSelect) { synchronized (jobLock) { + if(input !== null && resourceSetFromSelection !== null) { + } if (cachePropertyLookupJob !== null && cachePropertyLookupJob.state != Job.NONE) { cachePropertyLookupJob.cancel } diff --git a/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/IAadlPropertySource.java b/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/IAadlPropertySource.java index 2d591fbcf7c..77969cba12d 100644 --- a/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/IAadlPropertySource.java +++ b/core/org.osate.xtext.aadl2.ui/src/org/osate/xtext/aadl2/ui/propertyview/IAadlPropertySource.java @@ -20,9 +20,4 @@ public interface IAadlPropertySource { * @return the Xtext document */ IXtextDocument getDocument(); - - /** - * Refresh editor selection - */ - void refreshEditorSelection(); } \ No newline at end of file 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 bd50e8555eb..2e072795e25 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 @@ -66,6 +65,7 @@ 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 import org.eclipse.xtext.resource.SaveOptions +import org.eclipse.xtext.serializer.ISerializer package class ValueColumnEditingSupport extends EditingSupport { val static EMBEDDED_RESOURCE_NAME_SUFFIX = "_embedded_for_property_view_cell_editor" @@ -106,222 +106,61 @@ package class ValueColumnEditingSupport extends EditingSupport { } override protected getCellEditor(Object element) { - if (propertyView.xtextDocument === null) { + new XtextStyledTextCellEditor(SWT.SINGLE, MyAadl2Activator.getInstance.getInjector(MyAadl2Activator.ORG_OSATE_XTEXT_AADL2_AADL2), getProject()) => [ + create(propertyView.treeViewer.tree) + ] + } + + def private getProject() { + if(propertyView.xtextDocument === null) { val NamedElement curSelection = propertyView.resourceSetFromSelection.getEObject(propertyView.input, true) as NamedElement - new XtextStyledTextCellEditor(SWT.SINGLE, - MyAadl2Activator.getInstance.getInjector(MyAadl2Activator.ORG_OSATE_XTEXT_AADL2_AADL2), - curSelection.eResource.convertToIResource.project) => [ - create(propertyView.treeViewer.tree) - ] + curSelection.eResource.convertToIResource.project } else { - new XtextStyledTextCellEditor(SWT.SINGLE, - MyAadl2Activator.getInstance.getInjector(MyAadl2Activator.ORG_OSATE_XTEXT_AADL2_AADL2), propertyView. - xtextDocument.readOnly[convertToIResource.project]) => [ - create(propertyView.treeViewer.tree) - ] + propertyView.xtextDocument.readOnly[convertToIResource.project] } } - + override protected getValue(Object element) { if (propertyView.xtextDocument === null) { val inputElement = propertyView.resourceSetFromSelection.getEObject(propertyView.input, true) as NamedElement val xtextResource = inputElement.eResource as XtextResource - val contents = inputElement.eResource.contents + val contents = xtextResource.contents val modelUnitNameEndOffset = contents.head.findNodesForFeature( Aadl2Package.eINSTANCE.namedElement_Name).head.endOffset val endNameEndOffset = contents.head.node.lastLeaf.previousNode.endOffset + val text = xtextResource.parseResult.rootNode.text if (creatingNewLocalInEdit) { - val propertyName = (element as TreeEntry).property.getQualifiedName.stripPredeclaredName - val offsetElement = switch inputElement { - AadlPackage, - Classifier: inputElement - case !newContained: inputElement - default: inputElement.containingClassifier - } - val firstPA = offsetElement.ownedPropertyAssociations.empty - initialEditablePart = '' - updateOffset = if (firstPA) { - switch offsetElement { - AadlPackage, - FeatureGroupType, - ComponentClassifier case offsetElement.ownedAnnexSubclauses.empty: - offsetElement.node.lastLeaf.previousNode.previousNode.offset - ComponentClassifier: - offsetElement.ownedAnnexSubclauses.head.node.offset - Subcomponent case !offsetElement.ownedModeBindings.empty: - offsetElement.ownedModeBindings.head.node.previousNode.previousNode.previousNode.offset - ModalPath case !offsetElement.inModeOrTransitions.empty: { - offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalPath_InModeOrTransition).head. - previousNode.previousNode.previousNode.offset - } - SubprogramCallSequence case !offsetElement.inModes.empty: { - offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalElement_InMode).head. - previousNode.previousNode.previousNode.offset - } - default: - offsetElement.node.lastLeaf.offset - } - } else { - offsetElement.ownedPropertyAssociations.last.node.endOffset - } - updateLength = 0 - val inPropertiesSection = newContained || inputElement instanceof AadlPackage || - inputElement instanceof Classifier - updatePrefix = '' - if (firstPA) { - updatePrefix += if (inPropertiesSection) { - '''properties«delim»''' - } else { - ''' {''' - } - } else { - updatePrefix += delim - } - updatePrefix += '''«propertyName» => ''' - updateSuffix = '' - if (newContained) { - updateSuffix += ''' applies to «inputElement.name»''' - } - updateSuffix += ';' - updateSuffix += if (inPropertiesSection) { - '' - } else if (firstPA) { - '}' - } else { - delim - } - - val text = xtextResource.parseResult.rootNode.text - val prefix = text.substring(0, updateOffset) - val suffix = text.substring(updateOffset, updateOffset + text.length - 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)»''' - ) + val ()=> String getPrefix = [|text.substring(0, updateOffset)] + val ()=> String getSuffix = [|text.substring(updateOffset, updateOffset + text.length - updateOffset)] + editNewProperty(element, inputElement, xtextResource.resourceSet, getPrefix, getSuffix, modelUnitNameEndOffset, endNameEndOffset) } else { - val expression = getPropertyExpression(inputElement.eResource.resourceSet, element) - val expressionNode = expression.node - updateOffset = expressionNode.offset - updateLength = expressionNode.length - updatePrefix = "" - updateSuffix = "" - initialEditablePart = xtextResource.serializer.serialize(expression).replaceAll("\n", ""). - replaceAll("\r", "").replaceAll("\t", "").trim - val text = xtextResource.parseResult.rootNode.text - val prefix = text.substring(0, expressionNode.offset) - val suffix = text.substring(expressionNode.endOffset, - expressionNode.endOffset + text.length - 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 - ) + val (ICompositeNode)=> String getPrefix = [expressionNode| text.substring(0, expressionNode.offset)] + val (ICompositeNode)=> String getSuffix = [expressionNode| text.substring(expressionNode.endOffset, + expressionNode.endOffset + text.length - expressionNode.endOffset)] + editExistingProperty(element, xtextResource.resourceSet, xtextResource.serializer, getPrefix, getSuffix, modelUnitNameEndOffset, endNameEndOffset) } } else { propertyView.xtextDocument.readOnly [ - val modelUnitNameEndOffset = contents.head.findNodesForFeature( - Aadl2Package.eINSTANCE.namedElement_Name).head.endOffset + 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 - val offsetElement = switch inputElement { - AadlPackage, - Classifier: inputElement - case !newContained: inputElement - default: inputElement.containingClassifier - } - val firstPA = offsetElement.ownedPropertyAssociations.empty - initialEditablePart = '' - updateOffset = if (firstPA) { - switch offsetElement { - AadlPackage, - FeatureGroupType, - ComponentClassifier case offsetElement.ownedAnnexSubclauses.empty: - offsetElement.node.lastLeaf.previousNode.previousNode.offset - ComponentClassifier: offsetElement.ownedAnnexSubclauses.head.node.offset - Subcomponent case !offsetElement.ownedModeBindings.empty: offsetElement.ownedModeBindings.head.node.previousNode.previousNode.previousNode.offset - ModalPath case !offsetElement.inModeOrTransitions.empty: { - offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalPath_InModeOrTransition). - head.previousNode.previousNode.previousNode.offset - } - SubprogramCallSequence case !offsetElement.inModes.empty: { - offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalElement_InMode).head. - previousNode.previousNode.previousNode.offset - } - default: - offsetElement.node.lastLeaf.offset - } - } else { - offsetElement.ownedPropertyAssociations.last.node.endOffset - } - updateLength = 0 - val inPropertiesSection = newContained || inputElement instanceof AadlPackage || - inputElement instanceof Classifier - updatePrefix = '' - if (firstPA) { - updatePrefix += if (inPropertiesSection) { - '''properties«delim»''' - } else { - ''' {''' - } - } else { - updatePrefix += delim - } - updatePrefix += '''«propertyName» => ''' - updateSuffix = '' - if (newContained) { - updateSuffix += ''' applies to «inputElement.name»''' - } - updateSuffix += ';' - updateSuffix += if (inPropertiesSection) { - '' - } else if (firstPA) { - '}' - } else { - delim - } - val prefix = propertyView.xtextDocument.get(0, updateOffset) - val suffix = propertyView.xtextDocument.get(updateOffset, - propertyView.xtextDocument.length - 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)»''' - ) + val ()=> String getPrefix = [|propertyView.xtextDocument.get(0, updateOffset)] + val ()=> String getSuffix = [|propertyView.xtextDocument.get(updateOffset, + propertyView.xtextDocument.length - updateOffset)] + editNewProperty(element, inputElement, resourceSet, getPrefix, getSuffix, modelUnitNameEndOffset, endNameEndOffset) } else { - val expression = getPropertyExpression(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) - 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 - ) + val (ICompositeNode)=> String getPrefix = [expressionNode| propertyView.xtextDocument.get(0, expressionNode.offset)] + val (ICompositeNode)=> String getSuffix = [expressionNode| propertyView.xtextDocument.get(expressionNode.endOffset, + propertyView.xtextDocument.length - expressionNode.endOffset)] + editExistingProperty(element, resourceSet, serializer, getPrefix, getSuffix, modelUnitNameEndOffset, endNameEndOffset) } ] } } - private def PropertyExpression getPropertyExpression(Resource resource, Object element) { - getPropertyExpression(resource.resourceSet, element); - } - private def PropertyExpression getPropertyExpression(ResourceSet resourceSet, Object element) { switch treeElement : (element as TreeEntry).treeElement { URI: @@ -383,6 +222,88 @@ package class ValueColumnEditingSupport extends EditingSupport { } } } + + def private editNewProperty(Object element, NamedElement inputElement, ResourceSet resourceSet, ()=>String getPrefix, ()=>String getSuffix, int modelUnitNameEndOffset, int endNameEndOffset) { + val propertyName = (element as TreeEntry).property.getQualifiedName.stripPredeclaredName + val offsetElement = switch inputElement { + AadlPackage, + Classifier: inputElement + case !newContained: inputElement + default: inputElement.containingClassifier + } + val firstPA = offsetElement.ownedPropertyAssociations.empty + initialEditablePart = '' + updateOffset = if (firstPA) { + switch offsetElement { + AadlPackage, + FeatureGroupType, + ComponentClassifier case offsetElement.ownedAnnexSubclauses.empty: offsetElement.node.lastLeaf.previousNode.previousNode.offset + ComponentClassifier: offsetElement.ownedAnnexSubclauses.head.node.offset + Subcomponent case !offsetElement.ownedModeBindings.empty: offsetElement.ownedModeBindings.head.node.previousNode.previousNode.previousNode.offset + ModalPath case !offsetElement.inModeOrTransitions.empty: { + offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalPath_InModeOrTransition).head.previousNode.previousNode.previousNode.offset + } + SubprogramCallSequence case !offsetElement.inModes.empty: { + offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalElement_InMode).head.previousNode.previousNode.previousNode.offset + } + default: offsetElement.node.lastLeaf.offset + } + } else { + offsetElement.ownedPropertyAssociations.last.node.endOffset + } + updateLength = 0 + val inPropertiesSection = newContained || inputElement instanceof AadlPackage || inputElement instanceof Classifier + updatePrefix = '' + if (firstPA) { + updatePrefix += if (inPropertiesSection) { + '''properties«delim»''' + } else { + ''' {''' + } + } else { + updatePrefix += delim + } + updatePrefix += '''«propertyName» => ''' + updateSuffix = '' + if (newContained) { + updateSuffix += ''' applies to «inputElement.name»''' + } + updateSuffix += ';' + updateSuffix += if (inPropertiesSection) { + '' + } else if (firstPA) { + '}' + } else { + delim + } + val prefix = getPrefix.apply + val suffix = getSuffix.apply + new CellEditorPartialValue( + '''«new StringBuilder(prefix).insert(modelUnitNameEndOffset, EMBEDDED_RESOURCE_NAME_SUFFIX)»«updatePrefix»''', + initialEditablePart, + '''«updateSuffix»«new StringBuilder(suffix).insert(endNameEndOffset - updateOffset, EMBEDDED_RESOURCE_NAME_SUFFIX)»''' + ) + } + + def private editExistingProperty(Object element, ResourceSet resourceSet, ISerializer serializer, (ICompositeNode)=>String getPrefix, (ICompositeNode)=>String getSuffix, int modelUnitNameEndOffset, int endNameEndOffset) { + 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 = getPrefix.apply(expressionNode) + val suffix = getSuffix.apply(expressionNode) + 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 + ) + } def private static getLastLeaf(ICompositeNode node) { var INode result = node diff --git a/ge/org.osate.ge/src/org/osate/ge/internal/ui/editor/GraphitiEditPartAdapterFactory.java b/ge/org.osate.ge/src/org/osate/ge/internal/ui/editor/GraphitiEditPartAdapterFactory.java index f1dcaca03f7..e381ad1b7a3 100644 --- a/ge/org.osate.ge/src/org/osate/ge/internal/ui/editor/GraphitiEditPartAdapterFactory.java +++ b/ge/org.osate.ge/src/org/osate/ge/internal/ui/editor/GraphitiEditPartAdapterFactory.java @@ -82,7 +82,6 @@ public T getAdapter(Object adaptableObject, Class adapterType) { return adapterType.cast(new IAadlPropertySource() { private final IXtextDocument document = AgeXtextUtil.getDocumentByRootElement(namedElement.getElementRoot()); private final NamedElement element = namedElement; - private final AgeDiagramEditor editor = (AgeDiagramEditor) editorPart; @Override public IXtextDocument getDocument() { @@ -93,13 +92,6 @@ public IXtextDocument getDocument() { public NamedElement getNamedElement() { return element; } - - @Override - public void refreshEditorSelection() { - editor.clearSelection(); - editor.setFocus(); - editor.selectDiagramElements(new DiagramElement[] { de }); - } }); } } else if(DiagramElement.class.equals(adapterType)) { From 85da0a963fb287275fa075dedb7bba78204ef88b Mon Sep 17 00:00:00 2001 From: "ryan.mcilnay" Date: Fri, 26 Oct 2018 12:36:52 -0500 Subject: [PATCH 3/8] properties view editor support --- .../ui/propertyview/AadlPropertyView.xtend | 760 +++++++++--------- .../ValueColumnEditingSupport.xtend | 61 +- 2 files changed, 410 insertions(+), 411 deletions(-) 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 95cd8343d65..1dee32ee2ee 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 @@ -1,13 +1,13 @@ /* - * + * * * Copyright 2014 by Carnegie Mellon University, all rights reserved. - * + * * Use of the Open Source AADL Tool Environment (OSATE) is subject to the terms of the license set forth * at http://www.eclipse.org/org/documents/epl-v10.html. - * + * * NO WARRANTY - * + * * ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER PROPERTY OR RIGHTS GRANTED OR PROVIDED BY * CARNEGIE MELLON UNIVERSITY PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN "AS-IS" BASIS. * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, @@ -17,14 +17,14 @@ * REGARDLESS OF WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. LICENSEE AGREES THAT IT WILL NOT * MAKE ANY WARRANTY ON BEHALF OF CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON CONCERNING THE * APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE DELIVERABLES UNDER THIS LICENSE. - * + * * Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie Mellon University, its trustees, officers, * employees, and agents from all claims or demands made against them (and any related losses, expenses, or * attorney's fees) arising out of, or relating to Licensee's and/or its sub licensees' negligent use or willful * misuse of or negligent conduct or willful misconduct regarding the Software, facilities, or other rights or * assistance granted by Carnegie Mellon University under this License, including, but not limited to, any claims of * product liability, personal injury, death, damage to property, or violation of any laws or regulations. - * + * * Carnegie Mellon Carnegie Mellon University Software Engineering Institute authored documents are sponsored by the U.S. Department * of Defense under Contract F19628-00-C-0003. Carnegie Mellon University retains copyrights in all material produced * under this contract. The U.S. Government retains a non-exclusive, royalty-free license to publish or reproduce these @@ -145,7 +145,7 @@ class AadlPropertyView extends ViewPart { val static SHOW_ALL_AVAILABLE_PROPERTIES = "Show all available properties" val static HIDE_DEFAULT_TOOL_TIP = "Hide default property values" val static SHOW_DEFAULT_TOOL_TIP = "Show default property values" - + val static NO_PROPERTIES_TO_SHOW = "No properties to show: Please select a single AADL element that can have properties." val static POPULATING_VIEW = "Populating AADL Property Values view." @@ -224,17 +224,17 @@ class AadlPropertyView extends ViewPart { var IURIEditorOpener editorOpener var URI previousSelectionURI = null - + var IWorkbenchPart selectedPart = null - + var CachePropertyLookupJob cachePropertyLookupJob = null val jobLock = new Object - // If the URIs were resolved to EObjects, then this would be a Map> + //If the URIs were resolved to EObjects, then this would be a Map> val package Map> cachedPropertyAssociations = Collections.synchronizedMap(newLinkedHashMap) var ArrayList importedPropertyGroups = new ArrayList - + val ISelectionListener selectionListener = [ part, selection | /* * Change the view when the selection changes. @@ -265,6 +265,7 @@ class AadlPropertyView extends ViewPart { } override partActivated(IWorkbenchPart part) { + System.err.println(part + " part") if (part instanceof XtextEditor) { val selectionProvider = part.internalSourceViewer.selectionProvider if (selectionProvider instanceof IPostSelectionProvider) { @@ -283,7 +284,7 @@ class AadlPropertyView extends ViewPart { } ] - // This flag is necessary because calling IURIEditorOpener.open causes a model change event. This event should be ignored when calling IURIEditorOpener.open + //This flag is necessary because calling IURIEditorOpener.open causes a model change event. This event should be ignored when calling IURIEditorOpener.open var modelListenerEnabled = true val IXtextModelListener xtextModelListener = [ @@ -314,20 +315,20 @@ class AadlPropertyView extends ViewPart { override protected isLeafMatch(Viewer viewer, Object element) { var thisTree = viewer as TreeViewer val labelProvider = thisTree.getLabelProvider(0) as ColumnLabelProvider - val contentProvider = thisTree.getContentProvider() as ITreeContentProvider - - // first go up to propertyset / property name + val contentProvider = thisTree.getContentProvider() as ITreeContentProvider + + // first go up to propertyset / property name // see https://github.com/osate/osate2/issues/605) - var current = element - var parent = contentProvider.getParent(element) - while (contentProvider.getParent(parent) instanceof TreeEntry) { - current = parent - parent = contentProvider.getParent(parent) - } - - val propertysetName = labelProvider.getText(parent) ?: '' + var current = element + var parent = contentProvider.getParent(element) + while (contentProvider.getParent(parent) instanceof TreeEntry) { + current = parent + parent = contentProvider.getParent(parent) + } + + val propertysetName = labelProvider.getText(parent)?:'' var propertyName = labelProvider.getText(current) - + return wordMatches(propertyName) && (currentPropertyGroup.size == 0 || isMatch(propertyName, propertysetName)) } @@ -344,6 +345,7 @@ class AadlPropertyView extends ViewPart { var match = false if ((children !== null) && (children.length > 0)) { + for (var i = 0; i < children.length && !match; i++) { match = anyChildrenMatch(thisTree, children.get(i)) } @@ -353,9 +355,9 @@ class AadlPropertyView extends ViewPart { return match } - + def isMatch(String elementName, String parentName) { - for (e : currentPropertyGroup) { + for (e: currentPropertyGroup) { if (e.parent === null && elementName == (e.element as String)) { return true } @@ -363,9 +365,9 @@ class AadlPropertyView extends ViewPart { return true } } - + return false - } + } } // Hack to kill optimization that disables filter when text is empty patternFilter.setPattern("org.eclipse.ui.keys.optimization.false") @@ -398,7 +400,7 @@ class AadlPropertyView extends ViewPart { column.text = "Status" val gc = new GC(column.parent) treeColumnLayout.setColumnData(column, - new ColumnPixelData(PropertyStatus.values.map[gc.stringExtent(toString).x].max + 5, true, true)) + new ColumnPixelData(PropertyStatus.values.map[gc.stringExtent(toString).x].max + 5, true, true)) gc.dispose labelProvider = new StatusColumnLabelProvider(this) ] @@ -425,6 +427,7 @@ class AadlPropertyView extends ViewPart { } override dispose() { + synchronized (jobLock) { if (cachePropertyLookupJob !== null) { cachePropertyLookupJob.cancel @@ -499,29 +502,29 @@ class AadlPropertyView extends ViewPart { viewSite.actionBars.toolBarManager.add(it) toolTipText = COLLAPSE_ALL_TOOL_TIP ] - + // Show only property groups defined with the with clause showOnlyImportedPropertiesAction = new Action("Show Only Imported Property Groups", IAction.AS_CHECK_BOX) { override run() { - showOnlyImportedPropertiesAction.toolTipText = if (showOnlyImportedPropertiesAction.checked) { - SHOW_ONLY_IMPORTED_PROPERTIES + showOnlyImportedPropertiesAction.toolTipText = if(showOnlyImportedPropertiesAction.checked) { + SHOW_ONLY_IMPORTED_PROPERTIES } else { SHOW_ALL_AVAILABLE_PROPERTIES } - - if (showOnlyImportedPropertiesAction.checked) { + + if(showOnlyImportedPropertiesAction.checked) { currentPropertyGroup = new ArrayList(importedPropertyGroups) } else { currentPropertyGroup.clear() } - + treeViewer.refresh() - } + } } => [ - enabled = false - imageDescriptor = MyAadl2Activator.getImageDescriptor("icons/propertyview/filter_ps.png") - toolTipText = SHOW_ONLY_IMPORTED_PROPERTIES - viewSite.actionBars.toolBarManager.add(it) + enabled = false + imageDescriptor = MyAadl2Activator.getImageDescriptor("icons/propertyview/filter_ps.png") + toolTipText = SHOW_ONLY_IMPORTED_PROPERTIES + viewSite.actionBars.toolBarManager.add(it) ] showUndefinedAction = new Action(null, IAction.AS_CHECK_BOX) { @@ -531,7 +534,7 @@ class AadlPropertyView extends ViewPart { } else { SHOW_UNDEFINED_TOOL_TIP } - + treeViewer.refresh } } => [ @@ -547,7 +550,7 @@ class AadlPropertyView extends ViewPart { } else { SHOW_DEFAULT_TOOL_TIP } - + treeViewer.refresh } } => [ @@ -665,18 +668,19 @@ class AadlPropertyView extends ViewPart { override run() { val selectedElement = (treeViewer.selection as IStructuredSelection).firstElement as TreeEntry val uriToOpen = safeRead[ extension it | - val associationTemp = cachedPropertyAssociations.get((selectedElement.parent as TreeEntry).treeElement). - get(selectedElement.treeElement).getEObject(true) + val associationTemp = cachedPropertyAssociations.get((selectedElement.parent as TreeEntry).treeElement). + get(selectedElement.treeElement).getEObject(true) + val association = switch associationTemp { - PropertyAssociationInstance: { + PropertyAssociationInstance : { associationTemp.getPropertyAssociation(); } PropertyAssociation : associationTemp default : null } - + val inputElement = input.getEObject(true) (if (inputElement instanceof RefinableElement) { association.appliesTos.map[containmentPathElements.last].filter [ @@ -752,7 +756,7 @@ class AadlPropertyView extends ViewPart { } } } - + def private removePropertyAssociation(TreeEntry selectedElement, ResourceSet resourceSet) { val associationURI = cachedPropertyAssociations.get( (selectedElement.parent as TreeEntry).treeElement).get( @@ -870,7 +874,7 @@ class AadlPropertyView extends ViewPart { makeLocalAction.enabled = false makeLocalContainedAction.enabled = false removeElementAction.enabled = false - + val selection = treeViewer.selection as IStructuredSelection if (selection.size == 1) { val firstSelectedElement = selection.firstElement as TreeEntry @@ -879,374 +883,374 @@ class AadlPropertyView extends ViewPart { openDefinitionAction.enabled = safeRead[ extension it | val treeElementEObject = (firstSelectedElement.treeElement as URI).getEObject(true) treeElementEObject instanceof PropertySet || treeElementEObject instanceof Property || - treeElementEObject instanceof BasicPropertyAssociation || - treeElementEObject instanceof BasicProperty + treeElementEObject instanceof BasicPropertyAssociation || + treeElementEObject instanceof BasicProperty ] - if (safeRead[ extension it | - (firstSelectedElement.treeElement as URI).getEObject(true) instanceof Property]) { - val propertyStatus = getPropertyStatus( - (firstSelectedElement.parent as TreeEntry).treeElement as URI, - firstSelectedElement.treeElement as URI) - openPropertyAssociationAction.enabled = #[PropertyStatus.INHERITED, PropertyStatus.LOCAL, - PropertyStatus.LOCAL_CONTAINED - ].contains(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 - ] - createLocalContainedAssociationAction.enabled = (propertyStatus == - PropertyStatus.INHERITED || propertyStatus == PropertyStatus.DEFAULT || - propertyStatus == PropertyStatus.UNDEFINED) && 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) + if (safeRead[extension it| + (firstSelectedElement.treeElement as URI).getEObject(true) instanceof Property]) { + val propertyStatus = getPropertyStatus( + (firstSelectedElement.parent as TreeEntry).treeElement as URI, + firstSelectedElement.treeElement as URI) + openPropertyAssociationAction.enabled = #[PropertyStatus.INHERITED, PropertyStatus.LOCAL, + PropertyStatus.LOCAL_CONTAINED + ].contains(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 BehavioralFeature || inputElement instanceof Prototype || + inputElement instanceof Feature ||inputElement instanceof ModeFeature + ] + createLocalContainedAssociationAction.enabled = (propertyStatus == + PropertyStatus.INHERITED || propertyStatus == PropertyStatus.DEFAULT || + propertyStatus == PropertyStatus.UNDEFINED) && 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 = canEdit(firstSelectedElement) && - switch treeElement : firstSelectedElement.treeElement { - URI: - safeRead[ extension it | - switch treeElementEObject : treeElement.getEObject(true) { - Property: - true - BasicPropertyAssociation: - (treeElementEObject.owner as RecordValue).ownedFieldValues.size >= 2 - default: - false - }] - RangeElement: - treeElement.label == RangeElement.DELTA_LABEL - ListElement: - true - default: - false - } + removeElementAction.enabled = canEdit(firstSelectedElement) && + switch treeElement : firstSelectedElement.treeElement { + URI: + safeRead[ extension it | + switch treeElementEObject : treeElement.getEObject(true) { + Property: + true + BasicPropertyAssociation: + (treeElementEObject.owner as RecordValue).ownedFieldValues.size >= 2 + default: + false + }] + RangeElement: + treeElement.label == RangeElement.DELTA_LABEL + ListElement: + true + default: + false } - add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)) - ] - treeViewer.control.menu = createContextMenu(treeViewer.control) - site.registerContextMenu(it, treeViewer) - ] - } + } + add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)) + ] + treeViewer.control.menu = createContextMenu(treeViewer.control) + site.registerContextMenu(it, treeViewer) + ] + } - def private updateSelection(IWorkbenchPart part, ISelection selection) { - xtextDocument?.removeModelListener(xtextModelListener) - selectedPart = part - val currentSelection = switch selection { - case selection.empty: { - null + def private updateSelection(IWorkbenchPart part, ISelection selection) { + System.err.println(selection.class + " selection") + xtextDocument?.removeModelListener(xtextModelListener) + selectedPart = part + val currentSelection = switch selection { + case selection.empty: { + null + } + ITextSelection case part instanceof XtextEditor: { + xtextDocument = (part as XtextEditor).document + xtextDocument.readOnly[new EObjectAtOffsetHelper().resolveContainedElementAt(it, selection.offset)] + } + IStructuredSelection case selection.size == 1: { + switch selectedObject : selection.firstElement { + EObject: { + xtextDocument = null + selectedObject } - ITextSelection case part instanceof XtextEditor: { - xtextDocument = (part as XtextEditor).document - xtextDocument.readOnly [new EObjectAtOffsetHelper().resolveContainedElementAt(it, selection.offset)] + EObjectNode: { + xtextDocument = selectedObject.document + selectedObject.readOnly[it] } - IStructuredSelection case selection.size == 1: { - switch selectedObject : selection.firstElement { - EObject: { - xtextDocument = null - selectedObject - } - EObjectNode: { - xtextDocument = selectedObject.document - selectedObject.readOnly[it] - } - IAdaptable: { - val propertySource = selectedObject.getAdapter(IAadlPropertySource) - if (propertySource !== null) { - xtextDocument = propertySource.document - propertySource.namedElement - } - } + IAdaptable: { + val propertySource = selectedObject.getAdapter(IAadlPropertySource) + if (propertySource !== null) { + xtextDocument = propertySource.document + propertySource.namedElement } } } - - xtextDocument?.addModelListener(xtextModelListener) - var Object treeElementToSelect - val currentSelectionURI = try { - switch currentSelection { - PropertySet, - Property, - PropertyType, - PropertyConstant, - PackageSection: - null - NamedElement: - currentSelection.URI - PropertyAssociation case currentSelection.appliesTos.empty: { - treeElementToSelect = new TreeEntry( - new TreeEntry(currentSelection.owner.URI, - currentSelection.property.getContainerOfType(PropertySet).URI), currentSelection.property.URI) - currentSelection.owner.URI - } - PropertyAssociation case currentSelection.appliesTos.size == 1 && - currentSelection.appliesTos.head.containmentPathElements.size == 1: { - treeElementToSelect = new TreeEntry( - new TreeEntry( - currentSelection.appliesTos.head.containmentPathElements.head.namedElement.URI, - currentSelection.property.getContainerOfType(PropertySet).URI - ), currentSelection.property.URI) - currentSelection.appliesTos.head.containmentPathElements.head.namedElement.URI - } - ContainmentPathElement case currentSelection.path === null && - currentSelection.owner instanceof ContainedNamedElement: { - treeElementToSelect = new TreeEntry( - new TreeEntry( - currentSelection.namedElement.URI, - currentSelection.getContainerOfType(PropertyAssociation).property. - getContainerOfType(PropertySet).URI - ), currentSelection.getContainerOfType(PropertyAssociation).property.URI) - currentSelection.namedElement.URI - } - BasicPropertyAssociation, - PropertyExpression: { - val path = new ArrayDeque - if (currentSelection instanceof BasicPropertyAssociation) { - path.push(currentSelection.URI) - } - var currentElement = currentSelection.owner - var Element previousElement = currentSelection - while (currentElement !== null && !(currentElement instanceof PropertyAssociation)) { - switch currentElement { - ModalPropertyValue case (currentElement.owner as PropertyAssociation).modal, - BasicPropertyAssociation: - path.push(currentElement.URI) - ListValue: - path.push( - new ListElement(currentElement.ownedListElements.indexOf(previousElement), - previousElement.URI)) - RangeValue: - path.push( - new RangeElement( - switch previousElement { - case currentElement.minimum: RangeElement.MINIMUM_LABEL - case currentElement.maximum: RangeElement.MAXIMUM_LABEL - case currentElement.delta: RangeElement.DELTA_LABEL - }, previousElement.URI)) - } - previousElement = currentElement - currentElement = currentElement.owner - } - if (currentElement instanceof PropertyAssociation) { - path.push(currentElement.property.URI) - val root = if (currentElement.appliesTos.empty) { - currentElement.owner.URI - } else if (currentElement.appliesTos.size == 1 && - currentElement.appliesTos.head.containmentPathElements.size == 1) { - currentElement.appliesTos.head.containmentPathElements.head.namedElement.URI - } - treeElementToSelect = path.fold( - new TreeEntry(root, currentElement.property.getContainerOfType(PropertySet).URI), - [new TreeEntry($0, $1)]) - root - } - } - } - } catch (NullPointerException e) { + } + } + xtextDocument?.addModelListener(xtextModelListener) + var Object treeElementToSelect + val currentSelectionURI = try { + switch currentSelection { + PropertySet, + Property, + PropertyType, + PropertyConstant, + PackageSection: + null + NamedElement: + currentSelection.URI + PropertyAssociation case currentSelection.appliesTos.empty: { + treeElementToSelect = new TreeEntry( + new TreeEntry(currentSelection.owner.URI, + currentSelection.property.getContainerOfType(PropertySet).URI), currentSelection.property.URI) + currentSelection.owner.URI + } + PropertyAssociation case currentSelection.appliesTos.size == 1 && + currentSelection.appliesTos.head.containmentPathElements.size == 1: { + treeElementToSelect = new TreeEntry( + new TreeEntry( + currentSelection.appliesTos.head.containmentPathElements.head.namedElement.URI, + currentSelection.property.getContainerOfType(PropertySet).URI + ), currentSelection.property.URI) + currentSelection.appliesTos.head.containmentPathElements.head.namedElement.URI + } + ContainmentPathElement case currentSelection.path === null && + currentSelection.owner instanceof ContainedNamedElement: { + treeElementToSelect = new TreeEntry( + new TreeEntry( + currentSelection.namedElement.URI, + currentSelection.getContainerOfType(PropertyAssociation).property. + getContainerOfType(PropertySet).URI + ), currentSelection.getContainerOfType(PropertyAssociation).property.URI) + currentSelection.namedElement.URI + } + BasicPropertyAssociation, + PropertyExpression: { + val path = new ArrayDeque + if (currentSelection instanceof BasicPropertyAssociation) { + path.push(currentSelection.URI) } - - if (currentSelectionURI !== null) { - editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(currentSelection) - if (currentSelection !== null && currentSelection.eResource !== null) { - resourceSetFromSelection = currentSelection.eResource.resourceSet - if (currentSelectionURI == previousSelectionURI) { - if (treeElementToSelect !== null) { - treeViewer.setSelection(new StructuredSelection(treeElementToSelect), true) - } - pageBook.showPage(treeViewerComposite) - } else { - previousSelectionURI = currentSelectionURI - updateView(currentSelectionURI, treeElementToSelect) + var currentElement = currentSelection.owner + var Element previousElement = currentSelection + while (currentElement !== null && !(currentElement instanceof PropertyAssociation)) { + switch currentElement { + ModalPropertyValue case (currentElement.owner as PropertyAssociation).modal, + BasicPropertyAssociation: + path.push(currentElement.URI) + ListValue: + path.push( + new ListElement(currentElement.ownedListElements.indexOf(previousElement), + previousElement.URI)) + RangeValue: + path.push( + new RangeElement( + switch previousElement { + case currentElement.minimum: RangeElement.MINIMUM_LABEL + case currentElement.maximum: RangeElement.MAXIMUM_LABEL + case currentElement.delta: RangeElement.DELTA_LABEL + }, previousElement.URI)) } + previousElement = currentElement + currentElement = currentElement.owner } - } else { - synchronized (jobLock) { - if (cachePropertyLookupJob !== null) { - cachePropertyLookupJob.cancel - cachePropertyLookupJob = null - } + if (currentElement instanceof PropertyAssociation) { + path.push(currentElement.property.URI) + val root = if (currentElement.appliesTos.empty) { + currentElement.owner.URI + } else if (currentElement.appliesTos.size == 1 && + currentElement.appliesTos.head.containmentPathElements.size == 1) { + currentElement.appliesTos.head.containmentPathElements.head.namedElement.URI + } + treeElementToSelect = path.fold( + new TreeEntry(root, currentElement.property.getContainerOfType(PropertySet).URI), + [new TreeEntry($0, $1)]) + root } - pageBook.showPage(noPropertiesLabel) - editingDomain = null - resourceSetFromSelection = null - previousSelectionURI = null } - - // Build list of imported properties for "Show only imported properties" filter button to use - var package = getPackageSection(currentSelection) - importedPropertyGroups.clear - if (package !== null) { - val units = (package as PackageSection).getImportedUnits() - - for (ModelUnit unit : units) { - if (unit instanceof PropertySet) { - for (prop : unit.ownedProperties) { - importedPropertyGroups.add(new FilterCriterion(unit.name, prop.name)) - } - } + } + } catch (NullPointerException e) { + } + if (currentSelectionURI !== null) { + editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(currentSelection) + if (currentSelection !== null && currentSelection.eResource !== null) { + resourceSetFromSelection = currentSelection.eResource.resourceSet + if (currentSelectionURI == previousSelectionURI) { + if (treeElementToSelect !== null) { + treeViewer.setSelection(new StructuredSelection(treeElementToSelect), true) } - showOnlyImportedPropertiesAction.enabled = true + pageBook.showPage(treeViewerComposite) } else { - showOnlyImportedPropertiesAction.enabled = false + previousSelectionURI = currentSelectionURI + updateView(currentSelectionURI, treeElementToSelect) } } + } else { - // Recursive function to get the package section related to a node if it exists - def private EObject getPackageSection(EObject selection) { - if (selection === null) { - return null - } - - if (selection instanceof PackageSection) { - return selection - } - else if (selection instanceof Element){ - var owner = selection.owner - if (owner !== null) { - getPackageSection(owner) - } + synchronized (jobLock) { + if (cachePropertyLookupJob !== null) { + cachePropertyLookupJob.cancel + cachePropertyLookupJob = null } } - - def package safeRead((ResourceSet)=>T operation) { - if (xtextDocument !== null) { - xtextDocument.readOnly[operation.apply(resourceSet)] - } else if (editingDomain instanceof TransactionalEditingDomain) { - try { - TransactionUtil.runExclusive(editingDomain, - new RunnableWithResult.Impl { - override run() { - result = operation.apply(editingDomain.resourceSet) - status = Status.OK_STATUS - } - }) - } catch (InterruptedException e) { - - // Allow the operation to determine what the result should be - operation.apply(null) + pageBook.showPage(noPropertiesLabel) + editingDomain = null + resourceSetFromSelection = null + previousSelectionURI = null + } + + // Build list of imported properties for "Show only imported properties" filter button to use + var package = getPackageSection(currentSelection) + importedPropertyGroups.clear + if (package !== null) { + val units = (package as PackageSection).getImportedUnits() + + for (ModelUnit unit: units) { + if (unit instanceof PropertySet) { + for (prop: unit.ownedProperties) { + importedPropertyGroups.add(new FilterCriterion(unit.name, prop.name)) } - } else { - operation.apply(resourceSetFromSelection) } } + showOnlyImportedPropertiesAction.enabled = true + } else { + showOnlyImportedPropertiesAction.enabled = false + } + } - def private createCachePropertyLookupJob(URI elementURI, Object objectToSelect) { - new CachePropertyLookupJob(elementURI, this, site.shell.display, scopeProvider, - [| - pageBook.showPage(populatingViewLabel) - ], - [| - treeViewer.input = elementURI - if (objectToSelect !== null) { - treeViewer.setSelection(new StructuredSelection(objectToSelect), true) + // Recursive function to get the package section related to a node if it exists + def private EObject getPackageSection(EObject selection) { + + if (selection === null ) { + return null + } + + if (selection instanceof PackageSection) { + return selection + } + else if (selection instanceof Element){ + var owner = selection.owner + if (owner !== null) { + getPackageSection(owner) + } + } + } + + def package safeRead((ResourceSet)=>T operation) { + if (xtextDocument !== null) { + xtextDocument.readOnly[operation.apply(resourceSet)] + } else if (editingDomain instanceof TransactionalEditingDomain) { + try { + TransactionUtil.runExclusive(editingDomain, + new RunnableWithResult.Impl { + override run() { + result = operation.apply(editingDomain.resourceSet) + status = Status.OK_STATUS } - pageBook.showPage(treeViewerComposite) - ]) + }) + } catch (InterruptedException e) { + + //Allow the operation to determine what the result should be + operation.apply(null) } + } else { + operation.apply(resourceSetFromSelection) + } + } - def package getPropertyStatus(URI propertySetURI, URI propertyURI) { - safeRead[ extension it | - val associationURI = cachedPropertyAssociations.get(propertySetURI).get(propertyURI) - if (associationURI !== null) { - val association = associationURI.getEObject(true) as PropertyAssociation - val inputElement = input.getEObject(true) - if (inputElement == association.owner) { - PropertyStatus.LOCAL - } else if (association.appliesTos.exists[inputElement == containmentPathElements.last.namedElement]) { - if (association.appliesTos.size > 1) { - PropertyStatus.LOCAL_SHARED - } else { - PropertyStatus.LOCAL_CONTAINED - } - } else { - PropertyStatus.INHERITED - } - } else if ((propertyURI.getEObject(true) as Property).defaultValue !== null) { - PropertyStatus.DEFAULT + def private createCachePropertyLookupJob(URI elementURI, Object objectToSelect) { + new CachePropertyLookupJob(elementURI, this, site.shell.display, scopeProvider, + [| + pageBook.showPage(populatingViewLabel) + ], + [| + treeViewer.input = elementURI + if (objectToSelect !== null) { + treeViewer.setSelection(new StructuredSelection(objectToSelect), true) + } + pageBook.showPage(treeViewerComposite) + ]) + } + + def package getPropertyStatus(URI propertySetURI, URI propertyURI) { + safeRead[ extension it | + val associationURI = cachedPropertyAssociations.get(propertySetURI).get(propertyURI) + if (associationURI !== null) { + val association = associationURI.getEObject(true) as PropertyAssociation + val inputElement = input.getEObject(true) + if (inputElement == association.owner) { + PropertyStatus.LOCAL + } else if (association.appliesTos.exists[inputElement == containmentPathElements.last.namedElement]) { + if (association.appliesTos.size > 1) { + PropertyStatus.LOCAL_SHARED } else { - PropertyStatus.UNDEFINED + PropertyStatus.LOCAL_CONTAINED } - ] - } - - def private getPropertyStatusNeverUndefined(URI associationURI) { - if (associationURI !== null) { - safeRead[ extension it | - val association = associationURI.getEObject(true) as PropertyAssociation - val inputElement = input.getEObject(true) - if (inputElement == association.owner) { - PropertyStatus.LOCAL - } else if (association.appliesTos.exists[inputElement == containmentPathElements.last.namedElement]) { - PropertyStatus.LOCAL_CONTAINED - } else { - PropertyStatus.INHERITED - } - ] } else { - PropertyStatus.DEFAULT + PropertyStatus.INHERITED } + } else if ((propertyURI.getEObject(true) as Property).defaultValue !== null) { + PropertyStatus.DEFAULT + } else { + PropertyStatus.UNDEFINED } + ] + } - def package getPropertyStatusNeverUndefined(extension ResourceSet resourceSet, PropertyAssociation association) { - if (association === null) { - PropertyStatus.DEFAULT + def private getPropertyStatusNeverUndefined(URI associationURI) { + if (associationURI !== null) { + safeRead[ extension it | + val association = associationURI.getEObject(true) as PropertyAssociation + val inputElement = input.getEObject(true) + if (inputElement == association.owner) { + PropertyStatus.LOCAL + } else if (association.appliesTos.exists[inputElement == containmentPathElements.last.namedElement]) { + PropertyStatus.LOCAL_CONTAINED } else { - val inputElement = input.getEObject(true) - if (inputElement == association.owner) { - PropertyStatus.LOCAL - } else if (association.appliesTos.exists[inputElement == containmentPathElements.last.namedElement]) { - PropertyStatus.LOCAL_CONTAINED - } else { - PropertyStatus.INHERITED - } + PropertyStatus.INHERITED } + ] + } else { + PropertyStatus.DEFAULT + } + } + + def package getPropertyStatusNeverUndefined(extension ResourceSet resourceSet, PropertyAssociation association) { + if (association === null) { + PropertyStatus.DEFAULT + } else { + val inputElement = input.getEObject(true) + if (inputElement == association.owner) { + PropertyStatus.LOCAL + } else if (association.appliesTos.exists[inputElement == containmentPathElements.last.namedElement]) { + PropertyStatus.LOCAL_CONTAINED + } else { + PropertyStatus.INHERITED } + } + } - def package updateView(URI elementURI, Object objectToSelect) { - synchronized (jobLock) { - if(input !== null && resourceSetFromSelection !== null) { - } - if (cachePropertyLookupJob !== null && cachePropertyLookupJob.state != Job.NONE) { - cachePropertyLookupJob.cancel - } - cachePropertyLookupJob = createCachePropertyLookupJob(elementURI, objectToSelect) - cachePropertyLookupJob.schedule - } + def package updateView(URI elementURI, Object objectToSelect) { + synchronized (jobLock) { + if(input !== null && resourceSetFromSelection !== null) { } - - def package executeCommand(()=>void proc) { - var cmd = new RecordingCommand(editingDomain as TransactionalEditingDomain) { - override protected doExecute() { - proc.apply - } - } - - editingDomain.commandStack.execute(cmd) - } + if (cachePropertyLookupJob !== null && cachePropertyLookupJob.state != Job.NONE) { + cachePropertyLookupJob.cancel + } + cachePropertyLookupJob = createCachePropertyLookupJob(elementURI, objectToSelect) + cachePropertyLookupJob.schedule } - \ No newline at end of file + } + + def package executeCommand(()=>void proc) { + var cmd = new RecordingCommand(editingDomain as TransactionalEditingDomain) { + override protected doExecute() { + proc.apply + } + } + + editingDomain.commandStack.execute(cmd) + } +} 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 2e072795e25..048f231f8de 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 @@ -1,13 +1,13 @@ /* - * + * * * Copyright 2014 by Carnegie Mellon University, all rights reserved. - * + * * Use of the Open Source AADL Tool Environment (OSATE) is subject to the terms of the license set forth * at http://www.eclipse.org/org/documents/epl-v10.html. - * + * * NO WARRANTY - * + * * ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER PROPERTY OR RIGHTS GRANTED OR PROVIDED BY * CARNEGIE MELLON UNIVERSITY PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN "AS-IS" BASIS. * CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, @@ -17,14 +17,14 @@ * REGARDLESS OF WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. LICENSEE AGREES THAT IT WILL NOT * MAKE ANY WARRANTY ON BEHALF OF CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON CONCERNING THE * APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE DELIVERABLES UNDER THIS LICENSE. - * + * * Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie Mellon University, its trustees, officers, * employees, and agents from all claims or demands made against them (and any related losses, expenses, or * attorney's fees) arising out of, or relating to Licensee's and/or its sub licensees' negligent use or willful * misuse of or negligent conduct or willful misconduct regarding the Software, facilities, or other rights or * assistance granted by Carnegie Mellon University under this License, including, but not limited to, any claims of * product liability, personal injury, death, damage to property, or violation of any laws or regulations. - * + * * Carnegie Mellon Carnegie Mellon University Software Engineering Institute authored documents are sponsored by the U.S. Department * of Defense under Contract F19628-00-C-0003. Carnegie Mellon University retains copyrights in all material produced * under this contract. The U.S. Government retains a non-exclusive, royalty-free license to publish or reproduce these @@ -69,11 +69,11 @@ import org.eclipse.xtext.serializer.ISerializer package class ValueColumnEditingSupport extends EditingSupport { val static EMBEDDED_RESOURCE_NAME_SUFFIX = "_embedded_for_property_view_cell_editor" - + val AadlPropertyView propertyView - + val delim = System.getProperty("line.separator") - + var creatingNewLocalInEdit = false var newContained = false var String initialEditablePart @@ -86,7 +86,7 @@ package class ValueColumnEditingSupport extends EditingSupport { super(treeViewer) this.propertyView = propertyView } - + override protected canEdit(Object element) { if (propertyView.nextEditIsLocalCreation) { creatingNewLocalInEdit = true @@ -104,7 +104,7 @@ package class ValueColumnEditingSupport extends EditingSupport { propertyView.canEdit(element) } } - + override protected getCellEditor(Object element) { new XtextStyledTextCellEditor(SWT.SINGLE, MyAadl2Activator.getInstance.getInjector(MyAadl2Activator.ORG_OSATE_XTEXT_AADL2_AADL2), getProject()) => [ create(propertyView.treeViewer.tree) @@ -163,29 +163,24 @@ package class ValueColumnEditingSupport extends EditingSupport { 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 - ) as PropertyAssociation).ownedValues.head.ownedValue - } - BasicPropertyAssociation: - treeElementObject.value + URI: switch treeElementObject : resourceSet.getEObject(treeElement, true) { + Property: { + (resourceSet.getEObject( + propertyView.cachedPropertyAssociations.get(((element as TreeEntry).parent as TreeEntry).treeElement).get(treeElement), + true + ) as PropertyAssociation).ownedValues.head.ownedValue } - RangeElement: - resourceSet.getEObject(treeElement.expressionURI, true) as PropertyExpression - ListElement: - resourceSet.getEObject(treeElement.expressionURI, true) as PropertyExpression + BasicPropertyAssociation: treeElementObject.value + } + RangeElement: resourceSet.getEObject(treeElement.expressionURI, true) as PropertyExpression + 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::'] - val toStrip = predeclaredNames.findFirst[qualifiedName.toLowerCase.startsWith(it)] ?: '' + 'modeling_properties::', 'programming_properties::', 'thread_properties::', 'timing_properties::'] + val toStrip = predeclaredNames.findFirst[qualifiedName.toLowerCase.startsWith(it)]?:'' qualifiedName.substring(toStrip.length) } @@ -312,7 +307,7 @@ package class ValueColumnEditingSupport extends EditingSupport { } result ?: node } - + def private static getPreviousNode(INode node) { var lln = node.previousSibling while (lln instanceof HiddenLeafNode) { @@ -320,9 +315,9 @@ package class ValueColumnEditingSupport extends EditingSupport { } lln } - + def private TreeEntry getPropertyParent(TreeEntry element) { - if (element.treeElement instanceof URI && propertyView.safeRead [extension it | (element.treeElement as URI).getEObject(true) instanceof Property]) { + if (element.treeElement instanceof URI && propertyView.safeRead[extension it | (element.treeElement as URI).getEObject(true) instanceof Property]) { element } else { (element.parent as TreeEntry).propertyParent @@ -330,7 +325,7 @@ package class ValueColumnEditingSupport extends EditingSupport { } def private Property getProperty(TreeEntry element) { - propertyView.safeRead [ extension it | + propertyView.safeRead[extension it | if (element.treeElement instanceof URI && (element.treeElement as URI).getEObject(true) instanceof Property) { (element.treeElement as URI).getEObject(true) } else { @@ -338,4 +333,4 @@ package class ValueColumnEditingSupport extends EditingSupport { } ] as Property } -} +} \ No newline at end of file From cd8c7c97c055e3d448ea8e625f744940d1a91d20 Mon Sep 17 00:00:00 2001 From: "ryan.mcilnay" Date: Fri, 26 Oct 2018 12:40:22 -0500 Subject: [PATCH 4/8] AADL property view editor support --- .../osate/xtext/aadl2/ui/propertyview/AadlPropertyView.xtend | 2 -- 1 file changed, 2 deletions(-) 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 1dee32ee2ee..c3cb400655c 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 @@ -265,7 +265,6 @@ class AadlPropertyView extends ViewPart { } override partActivated(IWorkbenchPart part) { - System.err.println(part + " part") if (part instanceof XtextEditor) { val selectionProvider = part.internalSourceViewer.selectionProvider if (selectionProvider instanceof IPostSelectionProvider) { @@ -959,7 +958,6 @@ class AadlPropertyView extends ViewPart { } def private updateSelection(IWorkbenchPart part, ISelection selection) { - System.err.println(selection.class + " selection") xtextDocument?.removeModelListener(xtextModelListener) selectedPart = part val currentSelection = switch selection { From 5b5574d3095de6bfb922e68486d52eaf36868e4e Mon Sep 17 00:00:00 2001 From: "ryan.mcilnay" Date: Mon, 29 Oct 2018 13:50:59 -0500 Subject: [PATCH 5/8] GE aadl property view support --- .../ui/propertyview/AadlPropertyView.xtend | 13 ++++++-- ge/org.osate.ge/plugin.xml | 1 + ...BusinessObjectSelectionAdapterFactory.java | 32 ++++++++++++++++++- 3 files changed, 42 insertions(+), 4 deletions(-) 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 c3cb400655c..04d1fe4480a 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 @@ -131,7 +131,8 @@ 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.ui.part.EditorPart +import org.eclipse.core.runtime.Adapters +import org.eclipse.jface.viewers.ITreeSelection /** * View that displays the AADL property value associations within a given AADL @@ -270,8 +271,6 @@ class AadlPropertyView extends ViewPart { if (selectionProvider instanceof IPostSelectionProvider) { selectionProvider.addPostSelectionChangedListener(selectionChangedListener) } - } else if (part instanceof EditorPart) { - updateSelection(part.editorSite.selectionProvider.selection) } } } @@ -968,6 +967,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: { 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..c6129fc67ef 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) { + 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 }; } } From 0886e1fe4d421613d2f23261965d38a1e03c83d3 Mon Sep 17 00:00:00 2001 From: Philip Alldredge Date: Fri, 2 Nov 2018 11:22:12 -0500 Subject: [PATCH 6/8] Cleanup. Limit changes to those necessary for the issue being implemented to allow for easier reviewing. Work around for exception. --- .../ui/propertyview/AadlPropertyView.xtend | 465 +++++++++--------- .../ValueColumnEditingSupport.xtend | 262 +++++----- 2 files changed, 338 insertions(+), 389 deletions(-) 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 04d1fe4480a..e786a47be56 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 @@ -133,6 +133,7 @@ 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 @@ -209,8 +210,8 @@ class AadlPropertyView extends ViewPart { var package IXtextDocument xtextDocument = null - var package ResourceSet resourceSetFromSelection = null - + var package Resource resourceFromSelection; + /* Only show properties from this group (or all properties if empty) */ var ArrayList currentPropertyGroup = new ArrayList @@ -287,7 +288,15 @@ class AadlPropertyView extends ViewPart { val IXtextModelListener xtextModelListener = [ if (modelListenerEnabled) { - updateView(input, null) + synchronized (jobLock) { + if (cachePropertyLookupJob !== null && cachePropertyLookupJob.state != Job.NONE) { + cachePropertyLookupJob.cancel + } + if (input !== null) { + cachePropertyLookupJob = createCachePropertyLookupJob(input, null) + cachePropertyLookupJob.schedule + } + } } ] @@ -450,40 +459,44 @@ class AadlPropertyView extends ViewPart { } def package boolean canEdit(Object element) { - safeRead[ extension it | - switch treeElement : (element as TreeEntry).treeElement { - URI: - switch treeElementEObject : treeElement.getEObject(true) { - Property: { - val associationURI = cachedPropertyAssociations.get( - ((element as TreeEntry).parent as TreeEntry).treeElement).get(treeElement) - getPropertyStatusNeverUndefined(associationURI).editable && - !(associationURI.getEObject(true) as PropertyAssociation).modal - } - BasicPropertyAssociation: { - val containingAssociation = treeElementEObject.getContainerOfType(PropertyAssociation) - getPropertyStatusNeverUndefined(containingAssociation).editable && - !containingAssociation.modal + if (xtextDocument === null && !(resourceFromSelection instanceof XtextResource)) { + false + } else { + safeRead[ extension it | + switch treeElement : (element as TreeEntry).treeElement { + URI: + switch treeElementEObject : treeElement.getEObject(true) { + Property: { + val associationURI = cachedPropertyAssociations.get( + ((element as TreeEntry).parent as TreeEntry).treeElement).get(treeElement) + getPropertyStatusNeverUndefined(associationURI).editable && + !(associationURI.getEObject(true) as PropertyAssociation).modal + } + BasicPropertyAssociation: { + val containingAssociation = treeElementEObject.getContainerOfType(PropertyAssociation) + getPropertyStatusNeverUndefined(containingAssociation).editable && + !containingAssociation.modal + } + default: + false } - default: - false + RangeElement: { + val containingAssociation = (treeElement.expressionURI.getEObject(true) as PropertyExpression). + getContainerOfType(PropertyAssociation) + getPropertyStatusNeverUndefined(containingAssociation).editable && + !containingAssociation.modal } - RangeElement: { - val containingAssociation = (treeElement.expressionURI.getEObject(true) as PropertyExpression). - getContainerOfType(PropertyAssociation) - getPropertyStatusNeverUndefined(containingAssociation).editable && - !containingAssociation.modal - } - ListElement: { - val containingAssociation = (treeElement.expressionURI.getEObject(true) as PropertyExpression). - getContainerOfType(PropertyAssociation) - getPropertyStatusNeverUndefined(containingAssociation).editable && - !containingAssociation.modal + ListElement: { + val containingAssociation = (treeElement.expressionURI.getEObject(true) as PropertyExpression). + getContainerOfType(PropertyAssociation) + getPropertyStatusNeverUndefined(containingAssociation).editable && + !containingAssociation.modal + } + default: + false } - default: - false - } - ] + ] + } } def package getInput() { @@ -562,84 +575,51 @@ class AadlPropertyView extends ViewPart { val selectedElement = (treeViewer.selection as IStructuredSelection).firstElement as TreeEntry switch treeElement : selectedElement.treeElement { URI: { - if (xtextDocument === null) { - [| - val treeElementObject = resourceSetFromSelection.getEObject(treeElement, true) - switch treeElementObject { - Property: { - removePropertyAssociation(selectedElement, resourceSetFromSelection) - } - BasicPropertyAssociation: { - (treeElementObject.owner as RecordValue).ownedFieldValues.remove( - treeElementObject); - treeViewer.refresh(selectedElement.parent) - } - } - - saveAndRefreshSelection(resourceSetFromSelection.getEObject(input, true).eResource as XtextResource) - ].executeCommand - } else { - val postModificationUpdate = xtextDocument.modify [ - switch treeElementObject : resourceSet.getEObject(treeElement, true) { - Property: { - removePropertyAssociation(selectedElement, resourceSet); - [| - updateView(input, null) - ] - } - BasicPropertyAssociation: { - (treeElementObject.owner as RecordValue).ownedFieldValues.remove( - treeElementObject); - [|treeViewer.refresh(selectedElement.parent)] - } + 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 + }] } - ] - postModificationUpdate.apply - } + BasicPropertyAssociation: { + (treeElementObject.owner as RecordValue).ownedFieldValues.remove(treeElementObject); + [|treeViewer.refresh(selectedElement.parent)] + } + }] + postModificationUpdate.apply } RangeElement: { - if (xtextDocument === null) { - val inputElement = resourceSetFromSelection.getEObject(input, true) as NamedElement - [| - ((editingDomain.resourceSet.getEObject((treeElement as RangeElement).expressionURI, - true) as PropertyExpression).owner as RangeValue).delta = null - (inputElement.eResource as XtextResource).save( - SaveOptions.newBuilder().format().getOptions().toOptionsMap()) - treeViewer.refresh(selectedElement.parent) - ].executeCommand - } else { - xtextDocument.modify(new IUnitOfWork.Void { + modify( + new IUnitOfWork.Void { override process(XtextResource state) throws Exception { - ((state.resourceSet.getEObject((treeElement as RangeElement).expressionURI, - true) as PropertyExpression).owner as RangeValue).delta = null + ((state.resourceSet.getEObject((treeElement as RangeElement).expressionURI, true) as PropertyExpression). + owner as RangeValue).delta = null } }) - treeViewer.refresh(selectedElement.parent) - } + treeViewer.refresh(selectedElement.parent) } ListElement: { - if (xtextDocument === null) { - [| - ((resourceSetFromSelection.getEObject((treeElement as ListElement).expressionURI, - true) as PropertyExpression).owner as ListValue).ownedListElements.remove( - (treeElement as ListElement).index - ) - val inputElement = resourceSetFromSelection.getEObject(input, true) as NamedElement - (inputElement.eResource as XtextResource).save( - SaveOptions.newBuilder().format().getOptions().toOptionsMap()) - treeViewer.refresh(selectedElement.parent) - ].executeCommand - } else { - xtextDocument.modify(new IUnitOfWork.Void { + modify( + new IUnitOfWork.Void { override process(XtextResource state) throws Exception { - ((state.resourceSet.getEObject((treeElement as ListElement).expressionURI, - true) as PropertyExpression).owner as ListValue).ownedListElements.remove( + ((state.resourceSet.getEObject((treeElement as ListElement).expressionURI, true) as PropertyExpression). + owner as ListValue).ownedListElements.remove( (treeElement as ListElement).index ) } }) - treeViewer.refresh(selectedElement.parent) - } + treeViewer.refresh(selectedElement.parent) } } } @@ -702,17 +682,47 @@ class AadlPropertyView extends ViewPart { val propertyURI = selectedElement.treeElement as URI val associationURI = cachedPropertyAssociations.get((selectedElement.parent as TreeEntry).treeElement). get(propertyURI) - if (xtextDocument !== null) { - val postModificationUpdate = xtextDocument.modify [ - makeLocalProperty(resourceSet, associationURI, propertyURI) - ] - postModificationUpdate.apply - } else { - [| - makeLocalProperty(resourceSetFromSelection, associationURI, propertyURI) - saveAndRefreshSelection(resourceSetFromSelection.getEObject(input, true).eResource as XtextResource) - ].executeCommand - } + 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) + newPA.appliesTos.clear + 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 + }] + } else if (oldPA.appliesTos.size > 1) { + // shared local contained => remove from applies to list + val toRemove = oldPA.appliesTos.findFirst[ + path.namedElement === inputElement + ] + oldPA.appliesTos.remove(toRemove) + } + inputElement.ownedPropertyAssociations.add(newPA) + } else { + // copy property's default value + val property = resourceSet.getEObject(propertyURI, true) as Property + inputElement.createOwnedPropertyAssociation => [ + it.property = property + createOwnedValue => [ + ownedValue = EcoreUtil.copy(property.defaultValue) + ] + ] + } + update + ] + postModificationUpdate.apply } } @@ -723,18 +733,59 @@ class AadlPropertyView extends ViewPart { val propertyURI = selectedElement.treeElement as URI val associationURI = cachedPropertyAssociations.get((selectedElement.parent as TreeEntry).treeElement). get(propertyURI) - if (xtextDocument !== null) { - val postModificationUpdate = xtextDocument.modify [ - makeLocalContainedProperty(resourceSet, associationURI, propertyURI) - ] - postModificationUpdate.apply - } else { - [| - makeLocalContainedProperty(resourceSetFromSelection, associationURI, propertyURI) - saveAndRefreshSelection(resourceSetFromSelection.getEObject(input, true).eResource as XtextResource) - - ].executeCommand - } + 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) + newPA.appliesTos.clear + newPA.appliesTos.add( + Aadl2Factory.eINSTANCE.createContainedNamedElement => [ + createPath => [ + namedElement = inputElement + ] + ] + ) + 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 + }] + } else if (oldPA.appliesTos.size > 1) { + // shared local contained => remove from applies to list + val toRemove = oldPA.appliesTos.findFirst[ + path.namedElement === inputElement + ] + oldPA.appliesTos.remove(toRemove) + } + (inputElement.owner as NamedElement).ownedPropertyAssociations.add(newPA) + } else { + // copy property's default value + val property = resourceSet.getEObject(propertyURI, true) as Property + (inputElement.owner as NamedElement).createOwnedPropertyAssociation => [ + it.property = property + createOwnedValue => [ + ownedValue = EcoreUtil.copy(property.defaultValue) + ] + appliesTos.add(Aadl2Factory.eINSTANCE.createContainedNamedElement => [ + createPath => [ + namedElement = inputElement + ] + ]) + ] + } + update + ] + postModificationUpdate.apply } } @@ -754,104 +805,32 @@ class AadlPropertyView extends ViewPart { } } } - - def private removePropertyAssociation(TreeEntry selectedElement, ResourceSet resourceSet) { - 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) - } - - def private saveAndRefreshSelection(XtextResource resource) { - // Save resource - resource.save(SaveOptions.newBuilder().format().getOptions().toOptionsMap()) - - // Refresh editor selection - selectedPart.setFocus() - updateSelection(new StructuredSelection) - } - - def private makeLocalContainedProperty(ResourceSet resourceSet, URI associationURI, URI propertyURI) { - var ()=>void update = [|] - val inputElement = resourceSet.getEObject(input, true) as NamedElement - if (associationURI !== null) { - val oldPA = resourceSet.getEObject(associationURI, true) as PropertyAssociation - val newPA = EcoreUtil.copy(oldPA) - newPA.appliesTos.clear - newPA.appliesTos.add( - Aadl2Factory.eINSTANCE.createContainedNamedElement => [ - createPath => [ - namedElement = inputElement - ] - ] - ) - if (oldPA.appliesTos.size == 0 && oldPA.owner === inputElement) { - // local PA - inputElement.ownedPropertyAssociations.remove(oldPA) - update = [| - updateView(input, null) - ] - } else if (oldPA.appliesTos.size > 1) { - // shared local contained => remove from applies to list - val toRemove = oldPA.appliesTos.findFirst [ - path.namedElement === inputElement - ] - oldPA.appliesTos.remove(toRemove) - } - (inputElement.owner as NamedElement).ownedPropertyAssociations.add(newPA) - } else { - // copy property's default value - val property = resourceSet.getEObject(propertyURI, true) as Property - (inputElement.owner as NamedElement).createOwnedPropertyAssociation => [ - it.property = property - createOwnedValue => [ - ownedValue = EcoreUtil.copy(property.defaultValue) - ] - appliesTos.add(Aadl2Factory.eINSTANCE.createContainedNamedElement => [ - createPath => [ - namedElement = inputElement - ] - ]) - ] + + /** + * 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 + } } - - update } - def private makeLocalProperty(ResourceSet resourceSet, URI associationURI, URI propertyURI) { - var ()=>void update = [|] - val inputElement = resourceSet.getEObject(input, true) as NamedElement - if (associationURI !== null) { - val oldPA = resourceSet.getEObject(associationURI, true) as PropertyAssociation - val newPA = EcoreUtil.copy(oldPA) - newPA.appliesTos.clear - if (oldPA.appliesTos.size == 1) { - // non-shared local contained => remove the PA - (oldPA.owner as NamedElement).ownedPropertyAssociations.remove(oldPA) - update = [| - updateView(input, null) - ] - } else if (oldPA.appliesTos.size > 1) { - // shared local contained => remove from applies to list - val toRemove = oldPA.appliesTos.findFirst [ - path.namedElement === inputElement - ] - oldPA.appliesTos.remove(toRemove) - } - inputElement.ownedPropertyAssociations.add(newPA) + def package modify(IUnitOfWork work) { + if (xtextDocument !== null) { + xtextDocument.modify(work); + } else if(resourceFromSelection instanceof XtextResource) { + [| + val result = work.exec(resourceFromSelection as XtextResource); + resourceFromSelection.save(SaveOptions.newBuilder().format().getOptions().toOptionsMap()); + result + ].executeCommand } else { - // copy property's default value - val property = resourceSet.getEObject(propertyURI, true) as Property - inputElement.createOwnedPropertyAssociation => [ - it.property = property - createOwnedValue => [ - ownedValue = EcoreUtil.copy(property.defaultValue) - ] - ] + throw new RuntimeException("Unsupported case. Cannot modify model without an Xtext Document or an Xtext resource"); } - - update } def private createContextMenu() { @@ -1080,16 +1059,21 @@ class AadlPropertyView extends ViewPart { } if (currentSelectionURI !== null) { editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(currentSelection) - if (currentSelection !== null && currentSelection.eResource !== null) { - resourceSetFromSelection = currentSelection.eResource.resourceSet - if (currentSelectionURI == previousSelectionURI) { - if (treeElementToSelect !== null) { - treeViewer.setSelection(new StructuredSelection(treeElementToSelect), true) + resourceFromSelection = currentSelection.eResource + if (currentSelectionURI == previousSelectionURI) { + if (treeElementToSelect !== null) { + treeViewer.setSelection(new StructuredSelection(treeElementToSelect), true) + } + pageBook.showPage(treeViewerComposite) + } else { + previousSelectionURI = currentSelectionURI + + synchronized (jobLock) { + if (cachePropertyLookupJob !== null && cachePropertyLookupJob.state != Job.NONE) { + cachePropertyLookupJob.cancel } - pageBook.showPage(treeViewerComposite) - } else { - previousSelectionURI = currentSelectionURI - updateView(currentSelectionURI, treeElementToSelect) + cachePropertyLookupJob = createCachePropertyLookupJob(currentSelectionURI, treeElementToSelect) + cachePropertyLookupJob.schedule } } } else { @@ -1102,7 +1086,7 @@ class AadlPropertyView extends ViewPart { } pageBook.showPage(noPropertiesLabel) editingDomain = null - resourceSetFromSelection = null + resourceFromSelection = null previousSelectionURI = null } @@ -1144,14 +1128,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 } }) @@ -1161,7 +1151,7 @@ class AadlPropertyView extends ViewPart { operation.apply(null) } } else { - operation.apply(resourceSetFromSelection) + operation.apply(resourceFromSelection) } } @@ -1237,25 +1227,16 @@ class AadlPropertyView extends ViewPart { } } - def package updateView(URI elementURI, Object objectToSelect) { - synchronized (jobLock) { - if(input !== null && resourceSetFromSelection !== null) { - } - if (cachePropertyLookupJob !== null && cachePropertyLookupJob.state != Job.NONE) { - cachePropertyLookupJob.cancel - } - cachePropertyLookupJob = createCachePropertyLookupJob(elementURI, objectToSelect) - cachePropertyLookupJob.schedule - } - } - - def package executeCommand(()=>void proc) { + def package executeCommand(()=>T proc) { var cmd = new RecordingCommand(editingDomain as TransactionalEditingDomain) { + T result; + override protected doExecute() { - proc.apply + result = proc.apply } } editingDomain.commandStack.execute(cmd) + cmd.result } } 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 048f231f8de..4fa2de8509a 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 @@ -64,8 +64,6 @@ import static extension org.eclipse.xtext.nodemodel.util.NodeModelUtils.findNode 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 -import org.eclipse.xtext.resource.SaveOptions -import org.eclipse.xtext.serializer.ISerializer package class ValueColumnEditingSupport extends EditingSupport { val static EMBEDDED_RESOURCE_NAME_SUFFIX = "_embedded_for_property_view_cell_editor" @@ -113,7 +111,7 @@ package class ValueColumnEditingSupport extends EditingSupport { def private getProject() { if(propertyView.xtextDocument === null) { - val NamedElement curSelection = propertyView.resourceSetFromSelection.getEObject(propertyView.input, + val NamedElement curSelection = propertyView.resourceFromSelection.resourceSet.getEObject(propertyView.input, true) as NamedElement curSelection.eResource.convertToIResource.project } else { @@ -121,44 +119,111 @@ package class ValueColumnEditingSupport extends EditingSupport { } } - override protected getValue(Object element) { - if (propertyView.xtextDocument === null) { - val inputElement = propertyView.resourceSetFromSelection.getEObject(propertyView.input, - true) as NamedElement - val xtextResource = inputElement.eResource as XtextResource - val contents = xtextResource.contents - val modelUnitNameEndOffset = contents.head.findNodesForFeature( - Aadl2Package.eINSTANCE.namedElement_Name).head.endOffset - val endNameEndOffset = contents.head.node.lastLeaf.previousNode.endOffset - val text = xtextResource.parseResult.rootNode.text - if (creatingNewLocalInEdit) { - val ()=> String getPrefix = [|text.substring(0, updateOffset)] - val ()=> String getSuffix = [|text.substring(updateOffset, updateOffset + text.length - updateOffset)] - editNewProperty(element, inputElement, xtextResource.resourceSet, getPrefix, getSuffix, modelUnitNameEndOffset, endNameEndOffset) + 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 { - val (ICompositeNode)=> String getPrefix = [expressionNode| text.substring(0, expressionNode.offset)] - val (ICompositeNode)=> String getSuffix = [expressionNode| text.substring(expressionNode.endOffset, - expressionNode.endOffset + text.length - expressionNode.endOffset)] - editExistingProperty(element, xtextResource.resourceSet, xtextResource.serializer, getPrefix, getSuffix, modelUnitNameEndOffset, endNameEndOffset) + [int offset, int length | + val positiveLength = if(length < 0) { + propertyView.xtextDocument.length + length + } else { + length; + } + + propertyView.xtextDocument.get(offset, positiveLength) + ] } - } else { - propertyView.xtextDocument.readOnly [ - val modelUnitNameEndOffset = contents.head.findNodesForFeature(Aadl2Package.eINSTANCE.namedElement_Name).head.endOffset - val endNameEndOffset = contents.head.node.lastLeaf.previousNode.endOffset - if (creatingNewLocalInEdit) { - val inputElement = resourceSet.getEObject(propertyView.input, true) as NamedElement - val ()=> String getPrefix = [|propertyView.xtextDocument.get(0, updateOffset)] - val ()=> String getSuffix = [|propertyView.xtextDocument.get(updateOffset, - propertyView.xtextDocument.length - updateOffset)] - editNewProperty(element, inputElement, resourceSet, getPrefix, getSuffix, modelUnitNameEndOffset, endNameEndOffset) + + 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 + val offsetElement = switch inputElement { + AadlPackage, + Classifier: inputElement + case !newContained: inputElement + default: inputElement.containingClassifier + } + val firstPA = offsetElement.ownedPropertyAssociations.empty + initialEditablePart = '' + updateOffset = if (firstPA) { + switch offsetElement { + AadlPackage, + FeatureGroupType, + ComponentClassifier case offsetElement.ownedAnnexSubclauses.empty: offsetElement.node.lastLeaf.previousNode.previousNode.offset + ComponentClassifier: offsetElement.ownedAnnexSubclauses.head.node.offset + Subcomponent case !offsetElement.ownedModeBindings.empty: offsetElement.ownedModeBindings.head.node.previousNode.previousNode.previousNode.offset + ModalPath case !offsetElement.inModeOrTransitions.empty: { + offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalPath_InModeOrTransition).head.previousNode.previousNode.previousNode.offset + } + SubprogramCallSequence case !offsetElement.inModes.empty: { + offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalElement_InMode).head.previousNode.previousNode.previousNode.offset + } + default: offsetElement.node.lastLeaf.offset + } } else { - val (ICompositeNode)=> String getPrefix = [expressionNode| propertyView.xtextDocument.get(0, expressionNode.offset)] - val (ICompositeNode)=> String getSuffix = [expressionNode| propertyView.xtextDocument.get(expressionNode.endOffset, - propertyView.xtextDocument.length - expressionNode.endOffset)] - editExistingProperty(element, resourceSet, serializer, getPrefix, getSuffix, modelUnitNameEndOffset, endNameEndOffset) + offsetElement.ownedPropertyAssociations.last.node.endOffset } - ] - } + updateLength = 0 + val inPropertiesSection = newContained || inputElement instanceof AadlPackage || inputElement instanceof Classifier + updatePrefix = '' + if (firstPA) { + updatePrefix += if (inPropertiesSection) { + '''properties«delim»''' + } else { + ''' {''' + } + } else { + updatePrefix += delim + } + updatePrefix += '''«propertyName» => ''' + updateSuffix = '' + if (newContained) { + updateSuffix += ''' applies to «inputElement.name»''' + } + updateSuffix += ';' + updateSuffix += if (inPropertiesSection) { + '' + } else if (firstPA) { + '}' + } else { + delim + } + 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(resourceSet, element) + val expressionNode = expression.node + updateOffset = expressionNode.offset + updateLength = expressionNode.length + updatePrefix = "" + updateSuffix = "" + 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(ResourceSet resourceSet, Object element) { @@ -185,121 +250,24 @@ package class ValueColumnEditingSupport extends EditingSupport { } override protected setValue(Object element, Object value) { - val strippedVal = (value as String).replaceAll("\\s+","") - if(!(strippedVal as String).empty) { - if (creatingNewLocalInEdit || initialEditablePart != strippedVal) { - // insert new property value - if (propertyView.xtextDocument !== null) { - propertyView.xtextDocument.modify(new IUnitOfWork.Void { - override process(XtextResource state) throws Exception { - state.update(updateOffset, updateLength, updatePrefix + strippedVal + updateSuffix) - } - }) - - propertyView.treeViewer.refresh((element as TreeEntry).propertyParent) - - // select inserted/modified text in editor - val activeEditor = propertyView.site.workbenchWindow.activePage.activeEditor - if (activeEditor instanceof ITextEditor) { - activeEditor.selectAndReveal(updateOffset, - updatePrefix.length + (strippedVal as String).length + updateSuffix.length) - } - } else { - val inputElement = propertyView.resourceSetFromSelection.getEObject(propertyView.input, - true) as NamedElement - val xtextResource = inputElement.eResource as XtextResource - propertyView.executeCommand([| - xtextResource.update(updateOffset, updateLength, updatePrefix + strippedVal + updateSuffix) - xtextResource.save(SaveOptions.newBuilder().format().getOptions().toOptionsMap()) - propertyView.updateView(propertyView.input, null) - ]) - } - } - } - } - - def private editNewProperty(Object element, NamedElement inputElement, ResourceSet resourceSet, ()=>String getPrefix, ()=>String getSuffix, int modelUnitNameEndOffset, int endNameEndOffset) { - val propertyName = (element as TreeEntry).property.getQualifiedName.stripPredeclaredName - val offsetElement = switch inputElement { - AadlPackage, - Classifier: inputElement - case !newContained: inputElement - default: inputElement.containingClassifier - } - val firstPA = offsetElement.ownedPropertyAssociations.empty - initialEditablePart = '' - updateOffset = if (firstPA) { - switch offsetElement { - AadlPackage, - FeatureGroupType, - ComponentClassifier case offsetElement.ownedAnnexSubclauses.empty: offsetElement.node.lastLeaf.previousNode.previousNode.offset - ComponentClassifier: offsetElement.ownedAnnexSubclauses.head.node.offset - Subcomponent case !offsetElement.ownedModeBindings.empty: offsetElement.ownedModeBindings.head.node.previousNode.previousNode.previousNode.offset - ModalPath case !offsetElement.inModeOrTransitions.empty: { - offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalPath_InModeOrTransition).head.previousNode.previousNode.previousNode.offset - } - SubprogramCallSequence case !offsetElement.inModes.empty: { - offsetElement.findNodesForFeature(Aadl2Package.eINSTANCE.modalElement_InMode).head.previousNode.previousNode.previousNode.offset + if (creatingNewLocalInEdit || !(value as String).empty && initialEditablePart != value) { + // insert new property value + propertyView.modify(new IUnitOfWork.Void { + override process(XtextResource state) throws Exception { + state.update(updateOffset, updateLength, updatePrefix + value + updateSuffix) } - default: offsetElement.node.lastLeaf.offset - } - } else { - offsetElement.ownedPropertyAssociations.last.node.endOffset - } - updateLength = 0 - val inPropertiesSection = newContained || inputElement instanceof AadlPackage || inputElement instanceof Classifier - updatePrefix = '' - if (firstPA) { - updatePrefix += if (inPropertiesSection) { - '''properties«delim»''' - } else { - ''' {''' + }) + + propertyView.treeViewer.refresh((element as TreeEntry).propertyParent) + + // select inserted/modified text in editor + val activeEditor = propertyView.site.workbenchWindow.activePage.activeEditor + if (activeEditor instanceof ITextEditor) { + activeEditor.selectAndReveal(updateOffset, updatePrefix.length +(value as String).length + updateSuffix.length) } - } else { - updatePrefix += delim } - updatePrefix += '''«propertyName» => ''' - updateSuffix = '' - if (newContained) { - updateSuffix += ''' applies to «inputElement.name»''' - } - updateSuffix += ';' - updateSuffix += if (inPropertiesSection) { - '' - } else if (firstPA) { - '}' - } else { - delim - } - val prefix = getPrefix.apply - val suffix = getSuffix.apply - new CellEditorPartialValue( - '''«new StringBuilder(prefix).insert(modelUnitNameEndOffset, EMBEDDED_RESOURCE_NAME_SUFFIX)»«updatePrefix»''', - initialEditablePart, - '''«updateSuffix»«new StringBuilder(suffix).insert(endNameEndOffset - updateOffset, EMBEDDED_RESOURCE_NAME_SUFFIX)»''' - ) } - def private editExistingProperty(Object element, ResourceSet resourceSet, ISerializer serializer, (ICompositeNode)=>String getPrefix, (ICompositeNode)=>String getSuffix, int modelUnitNameEndOffset, int endNameEndOffset) { - 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 = getPrefix.apply(expressionNode) - val suffix = getSuffix.apply(expressionNode) - 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 - ) - } - def private static getLastLeaf(ICompositeNode node) { var INode result = node while (result instanceof ICompositeNode) { From f36b0e5b911064eeec24cb86d2dd73e0c125e857 Mon Sep 17 00:00:00 2001 From: "ryan.mcilnay" Date: Mon, 5 Nov 2018 12:00:46 -0600 Subject: [PATCH 7/8] update cache properties on property creation and cleanup --- .../ui/propertyview/AadlPropertyView.xtend | 63 +++++-------------- .../ValueColumnEditingSupport.xtend | 1 + ...BusinessObjectSelectionAdapterFactory.java | 2 +- 3 files changed, 18 insertions(+), 48 deletions(-) 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 e786a47be56..1ef1eefe6e4 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 @@ -227,8 +227,6 @@ class AadlPropertyView extends ViewPart { var URI previousSelectionURI = null - var IWorkbenchPart selectedPart = null - var CachePropertyLookupJob cachePropertyLookupJob = null val jobLock = new Object @@ -288,15 +286,7 @@ 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) } ] @@ -582,15 +572,7 @@ class AadlPropertyView extends ViewPart { (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); @@ -693,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[ @@ -751,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[ @@ -937,7 +903,6 @@ class AadlPropertyView extends ViewPart { def private updateSelection(IWorkbenchPart part, ISelection selection) { xtextDocument?.removeModelListener(xtextModelListener) - selectedPart = part val currentSelection = switch selection { case selection.empty: { null @@ -1067,14 +1032,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 { @@ -1226,6 +1184,17 @@ 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 + } + } def package executeCommand(()=>T proc) { var cmd = new RecordingCommand(editingDomain as TransactionalEditingDomain) { 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 4fa2de8509a..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 @@ -258,6 +258,7 @@ package class ValueColumnEditingSupport extends EditingSupport { } }) + propertyView.runCachePropertyLookupJob(propertyView.input, null) propertyView.treeViewer.refresh((element as TreeEntry).propertyParent) // select inserted/modified text in editor 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 c6129fc67ef..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 @@ -36,7 +36,7 @@ public T getAdapter(final Object adaptableObject, final Class adapterType } else if (IAadlPropertySource.class.equals(adapterType) && adaptableObject instanceof IStructuredSelection) { final IStructuredSelection ss = (IStructuredSelection) adaptableObject; if (ss.getFirstElement() instanceof DiagramElement) { - DiagramElement de = (DiagramElement) ss.getFirstElement(); + 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(); From 3a98341cc35e4652f70b92cc0edd9c180cc63f89 Mon Sep 17 00:00:00 2001 From: Philip Alldredge Date: Mon, 5 Nov 2018 13:52:29 -0600 Subject: [PATCH 8/8] Fix issue with erasing resource. --- .../ui/propertyview/AadlPropertyView.xtend | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) 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 1ef1eefe6e4..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 @@ -789,13 +789,35 @@ class AadlPropertyView extends ViewPart { if (xtextDocument !== null) { xtextDocument.modify(work); } else if(resourceFromSelection instanceof XtextResource) { - [| - val result = work.exec(resourceFromSelection as XtextResource); - resourceFromSelection.save(SaveOptions.newBuilder().format().getOptions().toOptionsMap()); - result - ].executeCommand + 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"); + throw new RuntimeException("Unsupported case. Cannot modify model without an Xtext Document or an Xtext resource") } } @@ -1196,16 +1218,4 @@ class AadlPropertyView extends ViewPart { } } - def package executeCommand(()=>T proc) { - var cmd = new RecordingCommand(editingDomain as TransactionalEditingDomain) { - T result; - - override protected doExecute() { - result = proc.apply - } - } - - editingDomain.commandStack.execute(cmd) - cmd.result - } }