/**
* <copyright>
* </copyright>
*
*
*/
package org.dresdenocl.language.ocl.resource.ocl.ui;
import java.util.LinkedHashSet;
import java.util.Set;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil.EqualityHelper;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.jface.viewers.IElementComparer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
/**
* This custom implementation of a TreeViewer expands the tree automatically up to
* a specified depth.
*/
public class OclOutlinePageTreeViewer extends TreeViewer {
public class TypeFilter extends ViewerFilter {
private Set<EClass> filteredTypes = new LinkedHashSet<EClass>();
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (element instanceof EObject) {
EObject eObject = (EObject) element;
for (EClass filteredType : filteredTypes) {
if (filteredType.isInstance(eObject)) {
return false;
}
}
}
return true;
}
public Set<EClass> getFilteredTypes() {
return filteredTypes;
}
}
private static class FlatEObjectComparer extends EqualityHelper {
private static final long serialVersionUID = 1L;
@Override
protected boolean haveEqualReference(EObject eObject1, EObject eObject2, EReference reference) {
return true;
}
@Override
protected boolean equalFeatureMaps(FeatureMap featureMap1, FeatureMap featureMap2) {
return true;
}
}
private boolean suppressNotifications = false;
private boolean linkWithEditor = false;
private boolean autoExpand = false;
private TypeFilter typeFilter = new TypeFilter();
public OclOutlinePageTreeViewer(Composite parent, int style) {
super(parent, style);
addFilter(typeFilter);
setComparer(new IElementComparer() {
public int hashCode(Object element) {
String s = toString(element);
if (s != null) {
return s.hashCode();
}
return element.hashCode();
}
public boolean equals(Object o1, Object o2) {
if (o1 instanceof EObject && o2 instanceof EObject) {
return new FlatEObjectComparer().equals((EObject) o1, (EObject) o2);
}
String s1 = toString(o1);
String s2 = toString(o2);
if (s1 != null) {
return s1.equals(s2);
}
return o1.equals(o2);
}
private String toString(Object o) {
if (o instanceof String) {
return (String) o;
}
if (o instanceof Resource) {
return ((Resource) o).getURI().toString();
}
return null;
}
});
}
public void setSelection(ISelection selection, boolean reveal) {
if (!linkWithEditor) {
return;
}
if (selection instanceof org.dresdenocl.language.ocl.resource.ocl.ui.OclEObjectSelection) {
suppressNotifications = true;
super.setSelection(selection, reveal);
suppressNotifications = false;
}
else {
super.setSelection(selection, reveal);
}
}
protected void handleSelect(SelectionEvent event) {
if (event.item == null) {
// In the cases of an invalid document, the tree widget in the outline might fire
// an event (with item == null) without user interaction. We do not want to react
// to that event.
} else {
super.handleSelect(event);
}
}
protected void handleInvalidSelection(ISelection selection, ISelection newSelection) {
// this may not fire a selection changed event to avoid cyclic events between
// editor and outline
}
public void refresh(Object element, boolean updateLabels) {
super.refresh(element, updateLabels);
doAutoExpand();
}
public void refresh(Object element) {
super.refresh(element);
doAutoExpand();
}
public void refresh() {
super.refresh();
doAutoExpand();
}
public void refresh(boolean updateLabels) {
super.refresh(updateLabels);
doAutoExpand();
}
public void setAutoExpand(boolean autoExpand) {
this.autoExpand = autoExpand;
}
public void expandToLevel(int level) {
// we need to catch exceptions here, because refreshing the outline does sometimes
// cause the LabelProviders to throw exceptions, if the model is in some
// inconsistent state.
try {
super.expandToLevel(level);
} catch (Exception e) {
org.dresdenocl.language.ocl.resource.ocl.mopp.OclPlugin.logError("Exception while refreshing outline view", e);
}
}
protected void fireSelectionChanged(SelectionChangedEvent event) {
if (suppressNotifications) {
return;
}
super.fireSelectionChanged(event);
}
public void setLinkWithEditor(boolean on) {
this.linkWithEditor = on;
}
private void doAutoExpand() {
if (!autoExpand) {
return;
}
expandToLevel(getAutoExpandLevel());
}
public void addTypeToFilter(EClass typeToFilter) {
typeFilter.getFilteredTypes().add(typeToFilter);
}
public void removeTypeToFilter(EClass typeToNotFilter) {
typeFilter.getFilteredTypes().remove(typeToNotFilter);
}
public void setSuppressNotifications(boolean suppressNotifications) {
this.suppressNotifications = suppressNotifications;
}
}