Commit 2c392508 authored by Simon Barner's avatar Simon Barner
Browse files

Ensure that renaming of project root elements that are currently not selected...

Ensure that renaming of project root elements that are currently not selected as source/target view is propagated to source/target view selection comboboxes.
- ModelListenerEditorBase
 - Remove modelListerner
 - Turn fileProjectListener into EContentAdapter
 - Add renameModel(IProjectRootElement)
- AllocationTableEditor
 - Adjust implementations of addModel(), removeModel()
 - Implement renameModel()
refs 2950
parent 6e568d63
AllocationTableEditor.java 29c3af7d1eb9ec1746c735830999f86d4e56a25c YELLOW
AllocationTableEditor.java 0c91284a3413f4a02589fd4183b8ff92ba00f09a YELLOW
AllocationTableEditorUtils.java 3f53fc3ce279be40ca18d6d63f3f7f830ec4eb86 RED
ModelListenerEditorBase.java cc5eb6ae4ece7093d835e3a00c886a7cf813ce3c YELLOW
ModelListenerEditorBase.java 6145b0682ffc82fee4c09ab51530506e79f286ad YELLOW
......@@ -22,6 +22,7 @@ import static org.fortiss.af3.allocation.utils.AllocationUtils.checkAllocationEn
import static org.fortiss.tooling.common.util.LambdaUtils.asStream;
import static org.fortiss.tooling.kernel.ui.util.SelectionUtils.checkAndPickFirst;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.getFirstChildWithType;
import static org.fortiss.tooling.kernel.utils.KernelModelElementUtils.getParentElement;
import static org.fortiss.tooling.kernel.utils.KernelModelElementUtils.runAsCommand;
import java.util.Collection;
......@@ -171,9 +172,11 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
@Override
protected void addModel(IProjectRootElement model) {
if(sourceModelType.isAssignableFrom(model.getClass())) {
addModel(gui.getComboViewerSource(), model);
updateViewPointSelectionComboBox(gui.getComboViewerSource(),
getModels(sourceModelType), editedObject.getSourceView());
} else if(targetModelType.isAssignableFrom(model.getClass())) {
addModel(gui.getComboViewerTarget(), model);
updateViewPointSelectionComboBox(gui.getComboViewerTarget(),
getModels(targetModelType), editedObject.getTargetView());
}
}
......@@ -181,21 +184,27 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
@Override
protected void removeModel(IProjectRootElement model) {
if(sourceModelType.isAssignableFrom(model.getClass())) {
removeModel(gui.getComboViewerSource(), model);
updateViewPointSelectionComboBox(gui.getComboViewerSource(),
getModels(sourceModelType), editedObject.getSourceView());
} else if(targetModelType.isAssignableFrom(model.getClass())) {
removeModel(gui.getComboViewerTarget(), model);
updateViewPointSelectionComboBox(gui.getComboViewerTarget(),
getModels(targetModelType), editedObject.getTargetView());
}
}
/** {@inheritDoc} */
@Override
protected void refresh(IProjectRootElement model) {
protected void renameModel(IProjectRootElement model) {
if(sourceModelType.isAssignableFrom(model.getClass())) {
updateViewPointSelectionComboBox(gui.getComboViewerSource(),
getModels(sourceModelType), editedObject.getSourceView());
gui.getComboViewerSource().refresh();
} else if(targetModelType.isAssignableFrom(model.getClass())) {
updateViewPointSelectionComboBox(gui.getComboViewerTarget(),
getModels(targetModelType), editedObject.getTargetView());
gui.getComboViewerTarget().refresh();
}
gui.getTreeViewer().refresh();
}
/** Predicate of the given {@code object} is of any of the given entity types. */
......@@ -266,6 +275,19 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
updateEntityChanged(entity);
}
/** {@inheritDoc} */
@Override
protected void renameEntity(IModelElement entity) {
IProjectRootElement rootElement = getParentElement(entity, IProjectRootElement.class, true);
// Needed to handle models where the visible top-model element is not a IProjectRootElement
renameModel(rootElement);
if(rootElement == editedObject.getSourceView() ||
rootElement == editedObject.getTargetView()) {
gui.getTreeViewer().refresh();
}
}
/********************* Implementation of IWorkbenchPart *********************/
/** {@inheritDoc} */
......@@ -291,13 +313,15 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
updateEntityTypeComboBox(gui.getComboViewerTargetEntityType(), targetEntityTypes,
editedObject.getTargetView(), this::setTargetEntityType);
setupViewPointSelectionComboBox(gui.getComboViewerSource(), getModels(sourceModelType),
editedObject.getSourceView(), editedObject::setSourceView,
setupViewPointSelectionComboBox(gui.getComboViewerSource(), editedObject::setSourceView,
editedObject::getSourceView);
updateViewPointSelectionComboBox(gui.getComboViewerSource(), getModels(sourceModelType),
editedObject.getSourceView());
setupViewPointSelectionComboBox(gui.getComboViewerTarget(), getModels(targetModelType),
editedObject.getTargetView(), editedObject::setTargetView,
setupViewPointSelectionComboBox(gui.getComboViewerTarget(), editedObject::setTargetView,
editedObject::getTargetView);
updateViewPointSelectionComboBox(gui.getComboViewerTarget(), getModels(targetModelType),
editedObject.getTargetView());
gui.getCheckboxShowSourceModelHierarchy().addSelectionListener(
new SourceModelHierarchyCheckBoxSelectionListener());
......@@ -394,17 +418,12 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
*
* @param comboViewer
* {@link ComboViewer} to be initialized.
* @param models
* Available models to be shown in {@code comboViewer}.
* @param selectedModel
* Initially selected model.
* @param modelSetter
* Method used to store the extracted view into the model.
* @param modelGetter
* Method used to extract the view that is currently set in the model.
*/
private void setupViewPointSelectionComboBox(ComboViewer comboViewer,
List<IProjectRootElement> models, IHierarchicElement selectedModel,
Consumer<IHierarchicElement> modelSetter, Supplier<IHierarchicElement> modelGetter) {
comboViewer.setContentProvider(new ArrayContentProvider());
comboViewer.setLabelProvider(new LabelProvider() {
......@@ -417,55 +436,46 @@ public abstract class AllocationTableEditor<T extends AllocationTable> extends
comboViewer.addSelectionChangedListener(new ModelViewComboBoxSelectionListener(modelSetter,
modelGetter));
}
/**
* Updates {@link ComboViewer} to display the given set of {@code models} and to select the
* {@code selectedElement}.
*
* @param comboViewer
* {@link ComboViewer} to be initialized.
* @param models
* Available models to be shown in {@code comboViewer}.
* @param selectedModel
* Initially selected model.
*/
private void updateViewPointSelectionComboBox(ComboViewer comboViewer,
List<IProjectRootElement> models, IHierarchicElement selectedModel) {
comboViewer.setInput(models);
if(selectedModel != null) {
comboViewer.setSelection(new StructuredSelection(selectedModel));
}
}
/**
* Adds the given {@code model} to the {@link AllocationTableEditor}. If in its
* {@link ComboViewer} no model is currently selected, the method sets the selection of a
* {@link ComboViewer} to the given element.
*/
private void addModel(ComboViewer comboViewer, IProjectRootElement model) {
// Add to ComboViewer and select it in case there was no selection before
comboViewer.add(model);
Combo combo = comboViewer.getCombo();
if(combo.getSelectionIndex() == -1) {
if(combo.getItemCount() == 0) {
combo.deselectAll();
} else if(combo.getSelectionIndex() == -1) {
// ComboViewer.getInput() does not contain the newly added element. Hence, iterate over
// the list of Items and determine the specific index and it to set the selection. This
// approach also circumvents the creation of possibly problematic {@link
// SelectionChangedEvent}s.
for(int i = 0; i < combo.getItems().length; i++) {
if(comboViewer.getElementAt(i) == model) {
if(comboViewer.getElementAt(i) == selectedModel) {
combo.select(i);
break;
}
}
}
// Update table in case the currently selected target or source view has just been added
// (required to restore table view after undoing a the removal of the source or target view)
if(editedObject.getSourceView() == model || editedObject.getTargetView() == model) {
treeViewerManager.updateTreeViewer();
}
}
/** Removes a model from a {@link AllocationTableEditor}. */
private void removeModel(ComboViewer comboViewer, IProjectRootElement model) {
// Remove from ComboViewer
comboViewer.remove(model);
Combo combo = comboViewer.getCombo();
if(combo.getItemCount() == 0) {
combo.deselectAll();
}
// Update table in case the currently selected target or source view has been deleted
if(editedObject.getSourceView() == null || editedObject.getTargetView() == null) {
treeViewerManager.updateTreeViewer();
}
// Ensure that model entity tree-viewer is in sync with model selection combo-box
treeViewerManager.updateTreeViewer();
}
/********************* Miscellaneous options *********************/
......
......@@ -21,7 +21,6 @@ import static org.eclipse.emf.common.notify.Notification.REMOVING_ADAPTER;
import static org.eclipse.emf.common.notify.Notification.SET;
import static org.fortiss.af3.project.utils.ProjectUtils.getFileProject;
import static org.fortiss.tooling.kernel.model.FortissToolingKernelPackage.Literals.INAMED_ELEMENT__NAME;
import static org.fortiss.tooling.kernel.utils.KernelModelElementUtils.getParentElement;
import static org.fortiss.tooling.kernel.utils.KernelModelElementUtils.runAsCommand;
import java.util.function.Consumer;
......@@ -29,7 +28,6 @@ import java.util.function.Supplier;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EContentAdapter;
import org.eclipse.swt.widgets.Composite;
......@@ -47,51 +45,16 @@ import org.fortiss.tooling.kernel.model.IProjectRootElement;
*/
public abstract class ModelListenerEditorBase<T extends EObject> extends GEFEditorBase<T> {
/** {@link EContentAdapter} to watch model for added / removed / renamed entities. */
private EContentAdapter modelListener = new EContentAdapter() {
/** {@inheritDoc} */
@Override
public void notifyChanged(Notification notification) {
super.notifyChanged(notification);
int eventType = notification.getEventType();
if(eventType == REMOVING_ADAPTER) {
return;
}
if(eventType == ADD) {
Object newValue = notification.getNewValue();
if(isEditedEntity(newValue)) {
IModelElement entity = (IModelElement)newValue;
Display.getDefault().syncExec(() -> addEntity(entity));
}
} else if(eventType == REMOVE) {
Object oldValue = notification.getOldValue();
if(isEditedEntity(oldValue)) {
IModelElement entity = (IModelElement)oldValue;
Display.getDefault().syncExec(() -> removeEntity(entity));
}
} else if(eventType == SET && notification.getFeature() == INAMED_ELEMENT__NAME &&
notification.getNotifier() instanceof EObject) {
// This also handles the case when the model is renamed. It cannot be done in the
// fileProjectListener since the name of some models is stored in its root entity
// (e.g., component architecture).
IProjectRootElement model =
getParentElement((EObject)notification.getNotifier(),
IProjectRootElement.class, true);
Display.getDefault().syncExec(() -> refresh(model));
}
}
};
/**
* Adapter to watch a {@link FileProject} for added / removed / renamed
* {@link IProjectRootElement}s.
* {@link IProjectRootElement}s and added / removed / renamed entities.
*/
private Adapter fileProjectListener = new AdapterImpl() {
private Adapter fileProjectListener = new EContentAdapter() {
/** {@inheritDoc} */
@Override
public void notifyChanged(Notification notification) {
super.notifyChanged(notification);
int eventType = notification.getEventType();
if(eventType == REMOVING_ADAPTER) {
return;
......@@ -102,12 +65,27 @@ public abstract class ModelListenerEditorBase<T extends EObject> extends GEFEdit
if(isEditedModel(newValue)) {
IProjectRootElement model = (IProjectRootElement)newValue;
Display.getDefault().syncExec(() -> addModel(model));
} else if(isEditedEntity(newValue)) {
IModelElement entity = (IModelElement)newValue;
Display.getDefault().syncExec(() -> addEntity(entity));
}
} else if(eventType == REMOVE) {
Object oldValue = notification.getOldValue();
if(isEditedModel(oldValue)) {
IProjectRootElement model = (IProjectRootElement)oldValue;
Display.getDefault().syncExec(() -> removeModel(model));
} else if(isEditedEntity(oldValue)) {
IModelElement entity = (IModelElement)oldValue;
Display.getDefault().syncExec(() -> removeEntity(entity));
}
} else if(eventType == SET && notification.getFeature() == INAMED_ELEMENT__NAME) {
Object changedValue = notification.getNotifier();
if(changedValue instanceof IProjectRootElement) {
Display.getDefault().syncExec(
() -> renameModel((IProjectRootElement)changedValue));
} else if(changedValue instanceof IModelElement) {
Display.getDefault().syncExec(() -> renameEntity((IModelElement)changedValue));
}
}
}
......@@ -128,12 +106,29 @@ public abstract class ModelListenerEditorBase<T extends EObject> extends GEFEdit
/** Hook to inform the editor that {@code model} has been removed from the project. */
protected abstract void removeModel(IProjectRootElement model);
/** Hook to inform the editor that {@code model} has been renamed. */
protected abstract void renameModel(IProjectRootElement model);
/** Hook to inform the editor that an {@code entity} has been added to a model. */
protected abstract void addEntity(IModelElement entity);
/** Hook to inform the editor that an {@code entity} has been removed from a model. */
protected abstract void removeEntity(IModelElement entity);
/**
* <p>
* Hook to update entity names in the editor.
* </p>
* <b>Note:</b> This method does not refresh the contents of the {@code model}. See:
* <ul>
* <li>{@link #addModel(IProjectRootElement)}</li>
* <li>{@link #removeModel(IProjectRootElement)}</li>
* <li>{@link #addEntity(IModelElement)}</li>
* <li> {@link #removeEntity(IModelElement)})</li>
* </ul>
*/
protected abstract void renameEntity(IModelElement entity);
/**
* Reflects a change in the selected models
*
......@@ -153,29 +148,8 @@ public abstract class ModelListenerEditorBase<T extends EObject> extends GEFEdit
modelSetter.accept((IHierarchicElement)model);
});
}
// Do this here since (model == oldModel) when the editor is opened for the first time.
if(oldModel != null) {
oldModel.eAdapters().remove(modelListener);
}
if(model != null) {
model.eAdapters().add(modelListener);
}
}
/**
* <p>
* Hook to refresh a model in the editor.
* </p>
* <b>Note:</b> This method does not refresh the contents of the {@code model}. See:
* <ul>
* <li>{@link #addModel(IProjectRootElement)}</li>
* <li>{@link #removeModel(IProjectRootElement)}</li>
* <li>{@link #addEntity(IModelElement)}</li>
* <li> {@link #removeEntity(IModelElement)})</li>
* </ul>
*/
protected abstract void refresh(IProjectRootElement model);
/** {@inheritDoc} */
@Override
public void createPartControl(Composite parent) {
......@@ -188,13 +162,7 @@ public abstract class ModelListenerEditorBase<T extends EObject> extends GEFEdit
public void dispose() {
super.dispose();
FileProject fileProject = (FileProject)fileProjectListener.getTarget();
FileProject fileProject = getFileProject(editedObject);
fileProject.eAdapters().remove(fileProjectListener);
for(IProjectRootElement model : fileProject.getRootElements()) {
if(isEditedModel(model)) {
model.eAdapters().remove(modelListener);
}
}
}
}
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