From 37081f17d565eb0e0cc73f8f04b9fd9cb25c5e60 Mon Sep 17 00:00:00 2001 From: Simon Barner <barner@fortiss.org> Date: Tue, 2 Sep 2014 12:47:00 +0000 Subject: [PATCH] - Add comparator that sorts rows according to hierarchy level. Elements within one hierarchy level are sorted by name. refs 1841 --- .../view/GenericAnnotationView.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/GenericAnnotationView.java b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/GenericAnnotationView.java index a8ddfe832..3ad0201e5 100644 --- a/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/GenericAnnotationView.java +++ b/org.fortiss.tooling.base.ui/trunk/src/org/fortiss/tooling/base/ui/annotation/view/GenericAnnotationView.java @@ -21,19 +21,24 @@ import java.util.Collection; import java.util.Set; import java.util.TreeSet; +import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.EditingSupport; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.fortiss.tooling.base.model.element.IAnnotatedSpecification; +import org.fortiss.tooling.base.model.element.IModelElement; import org.fortiss.tooling.base.ui.annotation.AnnotationEntry; import org.fortiss.tooling.base.ui.annotation.editingsupport.ElementNameEditingSupport; import org.fortiss.tooling.base.ui.annotation.valueprovider.IAnnotationValueProvider; +import org.fortiss.tooling.kernel.model.INamedElement; /** * <p> @@ -178,6 +183,99 @@ public class GenericAnnotationView extends AnnotationViewPartBase { } } + /** + * Comparator that sorts rows according to hierarchy level. Elements within one hierarchy level + * are sorted by name. + */ + private class HierarchicalNameComparator extends ViewerComparator { + + /** Computes the level of an {@link IModelElement} in the tree */ + private int getLevel(EObject o) { + int level = 0; + while(o.eContainer() != null) { + level++; + o = o.eContainer(); + } + + return level; + } + + /** + * Returns the ancestor of the {@link IModelElement} {@code modelElement} that is + * {@code levelsUp} levels above model element in the hierarchy, or {@code null}, in case + * {@code levelsUp} > depth(modelElement}. + */ + private EObject getAncestor(EObject o, int levelsUp) { + while(o.eContainer() != null && levelsUp > 0) { + o = o.eContainer(); + levelsUp--; + } + return o; + + } + + /** {@inheritDoc} */ + @Override + public int compare(Viewer viewer, Object o1, Object o2) { + if(o1 instanceof AnnotationEntry && o2 instanceof AnnotationEntry) { + IModelElement modelElement1 = ((AnnotationEntry)o1).getModelElement(); + IModelElement modelElement2 = ((AnnotationEntry)o2).getModelElement(); + int modelElement1Level = getLevel(modelElement1); + int modelElement2Level = getLevel(modelElement2); + + EObject e1 = modelElement1; + EObject e2 = modelElement2; + + if(modelElement1Level < modelElement2Level) { + // Element1 is higher than element2: Get ancestor of element2 that is at the + // level as the element1. + EObject ancestor = + getAncestor(modelElement2, modelElement2Level - modelElement1Level); + + if(modelElement1 == ancestor) { + // Element1 is offspring of element2 + return -1; + } + + // Further comparison starts on elements at the same level + e2 = ancestor; + } else if(modelElement1Level > modelElement2Level) { + // Element2 is higher than element1: Get ancestor of element1 that is at the + // level as the element2. + EObject ancestor = + getAncestor(modelElement1, modelElement1Level - modelElement2Level); + + if(modelElement2 == ancestor) { + // Element2 is offspring of element1 + return 1; + } + + // Further comparison starts on elements at the same level + e1 = ancestor; + } + // Find direct children of common root element of element1 and element2... + do { + if(e1.eContainer() == e2.eContainer()) { + break; + } + e1 = e1.eContainer(); + e2 = e2.eContainer(); + } while(true); + + // ... and compare them by name... + if(e1 instanceof INamedElement && e2 instanceof INamedElement) { + // Elements are at the same level -> compare by name + return(((INamedElement)e1).getName().compareTo(((INamedElement)e2).getName())); + } + } + + // ... or hash code (as a fallback ordering) + // int Integer.compare(int x, int y) requires JDK 1.7 which is not available + // on the build server + return new Integer(o1.hashCode()).compareTo(o2.hashCode()); + } + } + /** {@inheritDoc} */ @Override protected void update(Collection<AnnotationEntry> annotationEntries) { @@ -249,6 +347,8 @@ public class GenericAnnotationView extends AnnotationViewPartBase { table.setLinesVisible(true); createModelElementColumn(); + + tableViewer.setComparator(new HierarchicalNameComparator()); } /** Creates the (leading) column which displays the model elements */ -- GitLab