Skip to content
Snippets Groups Projects
Commit 9c6a70bc authored by Simon Barner's avatar Simon Barner
Browse files

- Install {@link Adapter} to watch for the addition or removal of model...

- Install {@link Adapter} to watch for the addition or removal of model elements to/from elements visible in this {@link AnnotationViewPartBase} (to trigger according updates).
- Ensure that all annotations for all offspring of the currently selected are shown in the view
- AnnotationViewPartBase no longer maintains a protected attribute with the list of current annotation entries, but triggers the abstract update(Collection<AnnotationEntry>) method at the right occasions (to be implemented by concrete views).
- Possible improvement in GenericAnnotationView: efficient implementation of update(Collection<AnnotationEntry>) (instead of complete redraw).
refs 1841
parent 90c20e8f
No related branches found
No related tags found
No related merge requests found
...@@ -17,9 +17,16 @@ $Id$ ...@@ -17,9 +17,16 @@ $Id$
+--------------------------------------------------------------------------*/ +--------------------------------------------------------------------------*/
package org.fortiss.tooling.base.ui.annotation.view; package org.fortiss.tooling.base.ui.annotation.view;
import java.util.ArrayList; import java.util.Collection;
import java.util.List; import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
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.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.ISelectionListener;
...@@ -30,7 +37,9 @@ import org.fortiss.tooling.base.ui.annotation.AnnotationEntry; ...@@ -30,7 +37,9 @@ import org.fortiss.tooling.base.ui.annotation.AnnotationEntry;
import org.fortiss.tooling.base.ui.annotation.IAnnotationValueService; import org.fortiss.tooling.base.ui.annotation.IAnnotationValueService;
import org.fortiss.tooling.base.ui.editpart.DiagramEditPartBase; import org.fortiss.tooling.base.ui.editpart.DiagramEditPartBase;
import org.fortiss.tooling.base.ui.editpart.ElementEditPartBase; import org.fortiss.tooling.base.ui.editpart.ElementEditPartBase;
import org.fortiss.tooling.kernel.model.IProjectRootElement;
import org.fortiss.tooling.kernel.ui.util.SelectionUtils; import org.fortiss.tooling.kernel.ui.util.SelectionUtils;
import org.fortiss.tooling.kernel.utils.EcoreUtils;
/** /**
* This class provides a limited set of variables and methods to annotation views. Its main purposes * This class provides a limited set of variables and methods to annotation views. Its main purposes
...@@ -47,8 +56,27 @@ public abstract class AnnotationViewPartBase extends ViewPart implements ISelect ...@@ -47,8 +56,27 @@ public abstract class AnnotationViewPartBase extends ViewPart implements ISelect
/** the currently selected object */ /** the currently selected object */
private IModelElement currentlySelectedObject; private IModelElement currentlySelectedObject;
/** List of all Annotation entries of the {@link #currentlySelectedObject} */ /**
protected List<AnnotationEntry> annotationEntryList = new ArrayList<AnnotationEntry>(); * Set of {@link IModelElement}s for which the {@link #changeListener} has been installed to
* watch for model changes (to trigger an update of this {@link AnnotationViewPartBase}).
*/
Set<IModelElement> watchedModelElements = new HashSet<IModelElement>();
/**
* {@link Adapter} to watch for the addition or removal of model elements to/from elements
* visible in this {@link AnnotationViewPartBase} (to trigger according updates).
*/
private final Adapter changeListener = new AdapterImpl() {
@Override
public void notifyChanged(Notification notification) {
if((notification.getEventType() == Notification.ADD) ||
(notification.getEventType() == Notification.REMOVE)) {
if(notification.getNewValue() instanceof IModelElement) {
update((IModelElement)notification.getNewValue());
}
}
}
};
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
...@@ -59,19 +87,99 @@ public abstract class AnnotationViewPartBase extends ViewPart implements ISelect ...@@ -59,19 +87,99 @@ public abstract class AnnotationViewPartBase extends ViewPart implements ISelect
if(currentlySelectedObject == null) { if(currentlySelectedObject == null) {
ElementEditPartBase<?> editPart = ElementEditPartBase<?> editPart =
SelectionUtils.checkAndPickFirst(selection, ElementEditPartBase.class); SelectionUtils.checkAndPickFirst(selection, ElementEditPartBase.class);
if(editPart != null) if(editPart != null) {
currentlySelectedObject = (IModelElement)editPart.getModel(); currentlySelectedObject = (IModelElement)editPart.getModel();
else { } else {
// Not all editors are derived from ElementEditPartBase, most notably
// PlatformArchitectureDiagramEditPart
DiagramEditPartBase<?> diagramPart = DiagramEditPartBase<?> diagramPart =
SelectionUtils.checkAndPickFirst(selection, DiagramEditPartBase.class); SelectionUtils.checkAndPickFirst(selection, DiagramEditPartBase.class);
if(diagramPart != null) if(diagramPart != null) {
currentlySelectedObject = (IModelElement)diagramPart.getModel(); currentlySelectedObject = (IModelElement)diagramPart.getModel();
}
} }
} }
if(currentlySelectedObject != null) {
update(currentlySelectedObject);
}
}
/** Update registration of model listeners. */
private void updateChangeListener(Collection<AnnotationEntry> annotationEntryList) {
// Determine all root elements
Set<EObject> rootElements = new HashSet<EObject>();
for(AnnotationEntry entry : annotationEntryList) {
EObject rootElement = entry.getModelElement();
while(!(rootElement instanceof IProjectRootElement)) {
rootElement = rootElement.eContainer();
}
rootElements.add(rootElement);
}
// Determine all IModelElements below the current root elements
Set<IModelElement> currentWatchedModelElements = new HashSet<IModelElement>();
for(EObject rootElement : rootElements) {
for(EObject modelElement : EcoreUtils.getChildrenWithType(rootElement,
IModelElement.class)) {
currentWatchedModelElements.add((IModelElement)modelElement);
}
if(rootElement instanceof IModelElement) {
currentWatchedModelElements.add((IModelElement)rootElement);
}
}
// Add change listeners to IModelElements that are about to appear in the view
Set<IModelElement> tmpWatchedModelElements =
new HashSet<IModelElement>(currentWatchedModelElements);
tmpWatchedModelElements.removeAll(watchedModelElements);
for(EObject modelElement : tmpWatchedModelElements) {
modelElement.eAdapters().add(changeListener);
}
// Remove change listeners IModelElements that are about to disappear from the view
tmpWatchedModelElements = new HashSet<IModelElement>(watchedModelElements);
tmpWatchedModelElements.removeAll(currentWatchedModelElements);
for(EObject modelElement : tmpWatchedModelElements) {
modelElement.eAdapters().remove(changeListener);
}
annotationEntryList = IAnnotationValueService.INSTANCE.getValues(currentlySelectedObject); watchedModelElements = currentWatchedModelElements;
} }
/**
* Update the {@link AnnotationViewPartBase}: delegate update of concrete view to
* {@link #update(Collection)}, and update model change listeners.
*/
private void update(IModelElement modelElement) {
Set<AnnotationEntry> annotationEntries =
new TreeSet<AnnotationEntry>(new Comparator<AnnotationEntry>() {
/** Compare AnnotationEntries by the model element they refer to. */
@Override
public int compare(AnnotationEntry a1, AnnotationEntry a2) {
// Equality of model element implies equal hashCode(), order is arbitrary
// but not relevant for
// ensuring uniqueness of annotation entries.
return Integer.compare(a1.getModelElement().hashCode(), a2
.getModelElement().hashCode());
}
});
// Collect all AnnotationEntries for the current model element and its offspring
annotationEntries.addAll(IAnnotationValueService.INSTANCE.getValues(modelElement));
for(IModelElement childModelElement : EcoreUtils.getChildrenWithType(modelElement,
IModelElement.class)) {
annotationEntries.addAll(IAnnotationValueService.INSTANCE.getValues(childModelElement));
}
// Update the view
update(annotationEntries);
updateChangeListener(annotationEntries);
}
/** Update concrete view */
protected abstract void update(Collection<AnnotationEntry> annotationEntries);
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void createPartControl(Composite parent) { public void createPartControl(Composite parent) {
...@@ -87,6 +195,12 @@ public abstract class AnnotationViewPartBase extends ViewPart implements ISelect ...@@ -87,6 +195,12 @@ public abstract class AnnotationViewPartBase extends ViewPart implements ISelect
@Override @Override
public void dispose() { public void dispose() {
getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(this); getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(this);
for(EObject modelElement : watchedModelElements) {
modelElement.eAdapters().remove(changeListener);
}
watchedModelElements.clear();
super.dispose(); super.dispose();
} }
} }
...@@ -18,6 +18,7 @@ $Id$ ...@@ -18,6 +18,7 @@ $Id$
package org.fortiss.tooling.base.ui.annotation.view; package org.fortiss.tooling.base.ui.annotation.view;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -26,7 +27,6 @@ import org.eclipse.emf.common.util.EMap; ...@@ -26,7 +27,6 @@ import org.eclipse.emf.common.util.EMap;
import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.EditingSupport; import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
...@@ -34,7 +34,6 @@ import org.eclipse.swt.graphics.Color; ...@@ -34,7 +34,6 @@ import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Table;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.wb.swt.SWTResourceManager; import org.eclipse.wb.swt.SWTResourceManager;
import org.fortiss.tooling.base.model.element.IAnnotatedSpecification; import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
import org.fortiss.tooling.base.ui.annotation.AnnotationEntry; import org.fortiss.tooling.base.ui.annotation.AnnotationEntry;
...@@ -77,30 +76,14 @@ public class GenericAnnotationView extends AnnotationViewPartBase { ...@@ -77,30 +76,14 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public void createPartControl(Composite parent) { protected void update(Collection<AnnotationEntry> annotationEntries) {
super.createPartControl(parent); updateSingleInstanceAnnotationColumns(annotationEntries);
Composite c = new Composite(parent, SWT.NULL); updateMultiInstanceAnnotationColumns(annotationEntries);
c.setLayout(new FillLayout(SWT.HORIZONTAL));
tableViewer = new TableViewer(c, SWT.BORDER | SWT.FULL_SELECTION);
Table table = tableViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
createModelElementColumn();
}
/** {@inheritDoc} */
@Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
super.selectionChanged(part, selection);
createSingleInstanceAnnotationColumns();
createMultiInstanceAnnotationColumns();
} }
/** Create columns for ordinary (single instance) {@link IAnnotatedSpecification}s */ /** Create columns for ordinary (single instance) {@link IAnnotatedSpecification}s */
private void createSingleInstanceAnnotationColumns() { private void
updateSingleInstanceAnnotationColumns(Collection<AnnotationEntry> annotationEntries) {
/* /*
* disposes all columns of the table viewer, except the first column, which holds the names * disposes all columns of the table viewer, except the first column, which holds the names
* of the model elements * of the model elements
...@@ -115,7 +98,7 @@ public class GenericAnnotationView extends AnnotationViewPartBase { ...@@ -115,7 +98,7 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
* is no additional columns created for those specification which already have an associated * is no additional columns created for those specification which already have an associated
* column or provide complex values. * column or provide complex values.
*/ */
for(AnnotationEntry entry : annotationEntryList) { for(AnnotationEntry entry : annotationEntries) {
for(IAnnotatedSpecification spec : entry.getSpecificationsList()) { for(IAnnotatedSpecification spec : entry.getSpecificationsList()) {
if(!isExistingColumn(spec) && if(!isExistingColumn(spec) &&
!entry.allowsMultipleAnnoationInstances(spec.getClass())) { !entry.allowsMultipleAnnoationInstances(spec.getClass())) {
...@@ -125,11 +108,12 @@ public class GenericAnnotationView extends AnnotationViewPartBase { ...@@ -125,11 +108,12 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
} }
if(!tableViewer.getTable().isDisposed()) if(!tableViewer.getTable().isDisposed())
tableViewer.setInput(annotationEntryList); tableViewer.setInput(annotationEntries);
} }
/** Create columns for multi-instance {@link IAnnotatedSpecification}s */ /** Create columns for multi-instance {@link IAnnotatedSpecification}s */
private void createMultiInstanceAnnotationColumns() { private void
updateMultiInstanceAnnotationColumns(Collection<AnnotationEntry> annotationEntries) {
for(CreateAnnotationInstanceColumn col : createColumns) { for(CreateAnnotationInstanceColumn col : createColumns) {
col.dispose(); col.dispose();
} }
...@@ -144,7 +128,7 @@ public class GenericAnnotationView extends AnnotationViewPartBase { ...@@ -144,7 +128,7 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
* 'code specsAllowingMultipleValues'. * 'code specsAllowingMultipleValues'.
*/ */
List<String> specClassNamesMult = new ArrayList<String>(); List<String> specClassNamesMult = new ArrayList<String>();
for(AnnotationEntry entry : annotationEntryList) { for(AnnotationEntry entry : annotationEntries) {
for(IAnnotatedSpecification spec : entry.getSpecificationsList()) { for(IAnnotatedSpecification spec : entry.getSpecificationsList()) {
if(entry.allowsMultipleAnnoationInstances(spec.getClass()) && if(entry.allowsMultipleAnnoationInstances(spec.getClass()) &&
!specClassNamesMult.contains(spec.getClass().getSimpleName())) { !specClassNamesMult.contains(spec.getClass().getSimpleName())) {
...@@ -182,6 +166,21 @@ public class GenericAnnotationView extends AnnotationViewPartBase { ...@@ -182,6 +166,21 @@ public class GenericAnnotationView extends AnnotationViewPartBase {
tableViewer.refresh(); tableViewer.refresh();
} }
/** {@inheritDoc} */
@Override
public void createPartControl(Composite parent) {
super.createPartControl(parent);
Composite c = new Composite(parent, SWT.NULL);
c.setLayout(new FillLayout(SWT.HORIZONTAL));
tableViewer = new TableViewer(c, SWT.BORDER | SWT.FULL_SELECTION);
Table table = tableViewer.getTable();
table.setHeaderVisible(true);
table.setLinesVisible(true);
createModelElementColumn();
}
/** Creates the (leading) column which displays the model elements */ /** Creates the (leading) column which displays the model elements */
protected void createModelElementColumn() { protected void createModelElementColumn() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment