Commit e0badd9c authored by Alexander Diewald's avatar Alexander Diewald
Browse files

- Copy operation are not dirtying the model any more: Add a write flag to...

- Copy operation are not dirtying the model any more: Add a write flag to annotation actions; Only those will are dirtying a model now.
- Context menu in the annotation view is no longer visible for non-editable annotations.
- References and multi-references are now correctly handled:
  - Correct the set logic.
  - Offer two kinds of pastes for multi-reference annotations: append, replace.
- Fix duplicated context menu entries for the SafetyIntegrityLevel annotation (details: see bug report).
refs 2361
parent 4c88453c
......@@ -427,16 +427,25 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
AnnotationEntry selEntry = (AnnotationEntry)selectedElement;
@SuppressWarnings("unchecked") Class<T> annotationType =
(Class<T>)((AnnotationLabelProvider)labelProv).getAnnotationType();
T spec = selEntry.getSpecification(annotationType);
String instanceKey = ((AnnotationLabelProvider)labelProv).getInstanceKey();
AnnotationInstSpec<T> spec =
new AnnotationInstSpec<T>(selEntry, annotationType, selEntry
.getSpecification(annotationType), instanceKey);
AnnotationInstSpec<T> instSpec =
new AnnotationInstSpec<T>(selEntry, annotationType, spec,
instanceKey);
// By Construction of the map, we can ensure that this cast will always be
// valid.
@SuppressWarnings("unchecked") IAnnotationValueProvider<T> valProvider =
(IAnnotationValueProvider<T>)annotationCtxEntries.get(spec);
addContextMenuEntries(contextMenu, valProvider, spec);
(IAnnotationValueProvider<T>)annotationCtxEntries.get(instSpec);
// Only show the context menu for:
// - Model elements that are actually annotated with the particular
// annotation.
// - Editable annotations (non-derived and no partially non-derived
// annotations).
if(spec != null && valProvider.canEdit(spec, instanceKey)) {
addContextMenuEntries(contextMenu, valProvider, instSpec);
}
}
contextMenu.setVisible(true);
}
......@@ -459,10 +468,6 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
if(selectedTableItem.getFirstElement() instanceof AnnotationEntry) {
AnnotationEntry entry = (AnnotationEntry)selectedTableItem.getFirstElement();
ITopLevelElement modelContext =
IPersistencyService.getInstance().getTopLevelElementFor(
entry.getModelElement());
AnnotationActionInputParameters parameterList = null;
if(actionEntry.getRequiredInputParameters() != null) {
MultiFieldInputDialog paramDialog =
......@@ -478,9 +483,17 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
createAnnoationActionRunnable(entry, action, actionEntry,
entrySpecification, parameterList, annotationEntries);
ITopLevelElement modelContext =
IPersistencyService.getInstance().getTopLevelElementFor(
entry.getModelElement());
boolean updateEnabled = isUpdateEnabled();
setUpdateEnabled(false);
modelContext.runAsCommand(r);
if(actionEntry.isWrite()) {
modelContext.runAsCommand(r);
} else {
modelContext.runAsNonDirtyingCommand(r);
}
setUpdateEnabled(updateEnabled);
}
}
......
......@@ -18,8 +18,10 @@ $Id$
package org.fortiss.tooling.base.annotation.valueprovider;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
......@@ -45,7 +47,7 @@ public abstract class DerivedAnnotationValueProviderBase<T extends IDerivedAnnot
private boolean isEditableByUser = false;
/** List of all supported instance keys. */
private List<String> keys = new ArrayList<String>();
private Set<String> keys = new LinkedHashSet<>();
/**
* Constructs a {@link IAnnotationValueProvider} for a pure derived annotation (i.e., an
......@@ -185,6 +187,6 @@ public abstract class DerivedAnnotationValueProviderBase<T extends IDerivedAnnot
/** {@inheritDoc} */
@Override
public List<String> getInstanceKeys(T specification) {
return keys;
return new ArrayList<>(keys);
}
}
......@@ -106,11 +106,16 @@ public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> ext
/** List of required input parameters to the annotation specific action. */
private AnnotationActionReqInputParameters inputReqParameters;
/** Flag if the action performs write (for undo/redo actions). */
private boolean isWrite;
/** Constructor defining the name and the scope of the corresponding action. */
public AnnotationActionEntry(String entryName, ActionScope scope, String instanceKey) {
public AnnotationActionEntry(String entryName, ActionScope scope, String instanceKey,
boolean isWrite) {
this.entryName = entryName;
this.scope = scope;
this.instanceKey = instanceKey;
this.isWrite = isWrite;
}
/**
......@@ -118,8 +123,8 @@ public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> ext
* list of required input parameters types and their display name must be given.
*/
public AnnotationActionEntry(String entryName, ActionScope scope, String instanceKey,
AnnotationActionReqInputParameters inputReqParameters) {
this(entryName, scope, instanceKey);
boolean isWrite, AnnotationActionReqInputParameters inputReqParameters) {
this(entryName, scope, instanceKey, isWrite);
this.inputReqParameters = inputReqParameters;
}
......@@ -150,6 +155,11 @@ public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> ext
public AnnotationActionReqInputParameters getRequiredInputParameters() {
return inputReqParameters;
}
/** Returns whether the corresponding action performs a write operation. */
public boolean isWrite() {
return isWrite;
}
}
/**
......
......@@ -32,7 +32,10 @@ import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.fortiss.tooling.base.ToolingBaseActivator;
import org.fortiss.tooling.base.annotation.AnnotationEntry;
import org.fortiss.tooling.base.annotation.valueprovider.IAnnotationValueProvider.AnnotationActionEntry.ActionScope;
import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
import org.fortiss.tooling.base.model.element.IModelElement;
......@@ -321,8 +324,19 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
AnnotationActions<T> retList = new AnnotationActions<>();
for(String instanceKey : getInstanceKeys(specification)) {
EStructuralFeature eType = null;
if(getEStructuralFeatureDescriptor(instanceKey) != null) {
eType =
getEStructuralFeatureDescriptor(instanceKey).getEStructuralFeature(
specification);
}
boolean isManyRef = eType instanceof EReference && ((EReference)eType).isMany();
retList.add(createCopyAction(instanceKey));
retList.addAll(createPasteActions(instanceKey));
retList.addAll(createPasteActions(instanceKey, isManyRef, false));
if(isManyRef) {
retList.addAll(createPasteActions(instanceKey, isManyRef, true));
}
}
return retList;
......@@ -335,35 +349,49 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
copiedAnnotation.put(instanceKey, spec);
};
AnnotationActionEntry copyDescriptor =
new AnnotationActionEntry("Copy", ActionScope.SINGLE_ITEM, instanceKey);
new AnnotationActionEntry("Copy", ActionScope.SINGLE_ITEM, instanceKey, false);
return new AnnotationAction<T>(copyDescriptor, copyAction);
}
/** Paste a selected annotation from the table. */
private List<AnnotationAction<T>> createPasteActions(String instanceKey) {
private List<AnnotationAction<T>> createPasteActions(String instanceKey, boolean isManyRef,
boolean doReplace) {
List<AnnotationAction<T>> pasteActions = new ArrayList<>();
BiConsumer<AnnotationInstSpec<T>, AnnotationActionParameters<T>> pasteAction =
(AnnotationInstSpec<T> spec, AnnotationActionParameters<T> parameters) -> {
AnnotationInstSpec<T> copiedAnnInst = copiedAnnotation.get(instanceKey);
Object copiedValue =
copiedAnnInst.getEntry().getSpecificationValue(
copiedAnnInst.getAnnotatedSpecificationType(),
copiedAnnInst.getInstanceKey());
T pasteAnnotation = parameters.getAnnotation();
if (pasteAnnotation != null) {
try {
if(spec.getInstanceKey() == null || spec.getInstanceKey().equals("")) {
setAnnotationValue(copiedValue,
pasteAnnotation);
} else {
setAnnotationValue(copiedValue, pasteAnnotation,
spec.getInstanceKey());
}
} catch(Exception e) {
// @CodeFormatterOff
(AnnotationInstSpec<T> spec, AnnotationActionParameters<T> parameters) -> {
AnnotationInstSpec<T> copiedAnnInst = copiedAnnotation.get(instanceKey);
AnnotationEntry annEntry = copiedAnnInst.getEntry();
Object copiedValue =
annEntry.getSpecificationValue(
copiedAnnInst.getAnnotatedSpecificationType(),
copiedAnnInst.getInstanceKey());
T pasteAnnotation = parameters.getAnnotation();
// Prevent pasting of copied References that may not be set due to restrictions
// in the target annotation.
if(copiedValue instanceof EReference) {
EStructuralFeatureDescriptor featurDescr =
getEStructuralFeatureDescriptor(instanceKey);
if(!featurDescr.isAvailableObject((EReference)copiedValue,
copiedAnnInst.getAnnotatedSpecification(),
annEntry.getModelElement())) {
return;
}
}
if(pasteAnnotation != null) {
try {
if(spec.getInstanceKey() == null || spec.getInstanceKey().equals("")) {
pasteValue(instanceKey, isManyRef, doReplace, copiedValue,
pasteAnnotation);
} else {
pasteValue(instanceKey, isManyRef, doReplace, copiedValue,
pasteAnnotation);
}
} catch(Exception e) {
// @CodeFormatterOff
LoggingUtils
.error(ToolingBaseActivator.getDefault(),
"Could not set the value of the annotation " +
......@@ -375,15 +403,36 @@ public abstract class ValueProviderBase<T extends IAnnotatedSpecification> imple
}
};
String pasteSuffix = !isManyRef ? "" : (doReplace ? " (replace)" : " (append)");
AnnotationActionEntry pasteDescriptor =
new AnnotationActionEntry("Paste", ActionScope.SINGLE_ITEM, instanceKey);
new AnnotationActionEntry("Paste" + pasteSuffix, ActionScope.SINGLE_ITEM,
instanceKey, true);
pasteActions.add(new AnnotationAction<T>(pasteDescriptor, pasteAction));
AnnotationActionEntry pasteAllDescriptor =
new AnnotationActionEntry("Paste to all", ActionScope.ALL_VISIBLE_ITEMS,
instanceKey);
new AnnotationActionEntry("Paste to all" + pasteSuffix,
ActionScope.ALL_VISIBLE_ITEMS, instanceKey, true);
pasteActions.add(new AnnotationAction<T>(pasteAllDescriptor, pasteAction));
return pasteActions;
}
/**
* Pastes a {@code copiedValue} to the {@code pasteAnnotation}. This method handles
* multi-reference lists; supporting append and replace operations.
*/
// NOTE: We can suppress these warnings
@SuppressWarnings({"unchecked", "rawtypes"})
private void pasteValue(String instanceKey, boolean isManyRef, boolean doReplace,
Object copiedValue, T pasteAnnotation) throws Exception {
if(!isManyRef || doReplace) {
setAnnotationValue(copiedValue, pasteAnnotation);
} else {
List<?> appendList = new ArrayList<>();
appendList.addAll(getAnnotationValue(pasteAnnotation, instanceKey));
appendList.addAll((List)copiedValue);
setAnnotationValue(appendList, pasteAnnotation);
}
}
}
......@@ -305,7 +305,8 @@ public class AnnotationUtils {
.getValue()));
AnnotationActionEntry randValuePropDescriptor =
new AnnotationActionEntry("Create random values",
ActionScope.ALL_VISIBLE_ITEMS, entry.getKey(), randInputParameters);
ActionScope.ALL_VISIBLE_ITEMS, entry.getKey(), true,
randInputParameters);
retActions
.add(new AnnotationAction<T>(randValuePropDescriptor, randomValuePropagation));
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment