Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/structuremergeviewer/filters/StructureMergeViewerFilter.java')
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/structuremergeviewer/filters/StructureMergeViewerFilter.java208
1 files changed, 208 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/structuremergeviewer/filters/StructureMergeViewerFilter.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/structuremergeviewer/filters/StructureMergeViewerFilter.java
new file mode 100644
index 000000000..5297665f2
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/structuremergeviewer/filters/StructureMergeViewerFilter.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 2013 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters;
+
+import static com.google.common.base.Predicates.not;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.eventbus.EventBus;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notifier;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.Match;
+import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters.IDifferenceFilterSelectionChangeEvent.Action;
+import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.DifferenceGroup;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+
+/**
+ * This will be used by the structure viewer to filter out its list of differences according to a number of
+ * provided predicates.
+ * <p>
+ * <b>Note</b> that this filter acts as an "OR" predicate between all provided ones, and that filters are
+ * "exclude" filters. Basically, that means if the user selects two filters, any difference that applies for
+ * any of these two filters will be <i>hidden</i> from the view, contrarily to "classic" {@link ViewerFilter}
+ * that act as "AND" predicates for "include" filters, forcing any displayed element to meet the criterion of
+ * all provided filters.
+ * </p>
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ * @since 3.0
+ */
+public class StructureMergeViewerFilter extends ViewerFilter {
+ /** The set of predicates known by this filter. */
+ private Set<Predicate<? super EObject>> predicates = Sets.newLinkedHashSet();
+
+ /** List of all TreeViewers on which this filter is applied. */
+ private List<TreeViewer> viewers = Lists.newArrayList();
+
+ /** The {@link EventBus} associated with this filter. */
+ private EventBus eventBus;
+
+ /**
+ * Constructs the difference filter.
+ *
+ * @param eventBus
+ * The {@link EventBus} which will be associated with this filter.
+ */
+ public StructureMergeViewerFilter(EventBus eventBus) {
+ this.eventBus = eventBus;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object,
+ * java.lang.Object)
+ */
+ @Override
+ public boolean select(Viewer viewer, Object parentElement, Object element) {
+ if (predicates.isEmpty()) {
+ return true;
+ }
+ boolean result = false;
+ final Predicate<? super EObject> predicate = Predicates.or(predicates);
+
+ if (predicates.isEmpty()) {
+ result = true;
+ } else if (element instanceof Adapter) {
+ Notifier notifier = ((Adapter)element).getTarget();
+ if (notifier instanceof Diff) {
+ final Diff diff = (Diff)notifier;
+ result = !predicate.apply(diff);
+ } else if (notifier instanceof Match) {
+ final Iterator<Diff> differences = ((Match)notifier).getAllDifferences().iterator();
+ result = Iterators.any(differences, not(predicate));
+ }
+ } else if (element instanceof DifferenceGroup) {
+ final Iterator<? extends Diff> differences = ((DifferenceGroup)element).getDifferences()
+ .iterator();
+ result = Iterators.any(differences, not(predicate));
+ } else if (element instanceof Adapter && ((Adapter)element).getTarget() instanceof EObject) {
+ /*
+ * Same code as the DiffNode case... extracted here as this is aimed at handling the cases not
+ * known at the time of writing (and the case of the "MatchResource" elements).
+ */
+ final EObject target = (EObject)((Adapter)element).getTarget();
+ result = !predicate.apply(target);
+ }
+
+ return result;
+ }
+
+ /**
+ * Add the predicate of the given {@link IDifferenceFilter}.
+ *
+ * @param filter
+ * The given {@link IDifferenceFilter}.
+ */
+ public void addFilter(IDifferenceFilter filter) {
+ addPredicate(filter.getPredicate());
+ eventBus.post(new IDifferenceFilterSelectionChangeEvent.DefaultFilterSelectionChangeEvent(filter, Action.ADD));
+ }
+
+ /**
+ * Remove the predicate of the given {@link IDifferenceFilter}.
+ *
+ * @param filter
+ * The given {@link IDifferenceFilter}.
+ */
+ public void removeFilter(IDifferenceFilter filter) {
+ removePredicate(filter.getPredicate());
+ eventBus.post(new IDifferenceFilterSelectionChangeEvent.DefaultFilterSelectionChangeEvent(filter, Action.REMOVE));
+ }
+
+ /**
+ * Add a predicate to the set known by this filter.
+ *
+ * @param predicate
+ * The new predicate for differences to be accepted by this viewer. No effect if already
+ * accepted.
+ */
+ public void addPredicate(Predicate<? super EObject> predicate) {
+ final boolean changed = predicates.add(predicate);
+ if (changed) {
+ refreshViewers();
+ }
+ }
+
+ /**
+ * Removes a predicate from those accepted by this filter.
+ *
+ * @param predicate
+ * The predicate that should no longer by accepted by this filter. No effect if it was not one
+ * of the accepted ones.
+ */
+ public void removePredicate(Predicate<? super EObject> predicate) {
+ final boolean changed = predicates.remove(predicate);
+ if (changed) {
+ refreshViewers();
+ }
+ }
+
+ /**
+ * Refreshes the viewers registered with this filter. Will try and conserve the expanded tree paths when
+ * possible.
+ */
+ private void refreshViewers() {
+ for (TreeViewer viewer : viewers) {
+ final TreePath[] paths = viewer.getExpandedTreePaths();
+ viewer.refresh();
+ viewer.setExpandedTreePaths(paths);
+ }
+ }
+
+ /**
+ * Install this filter on the given viewer.
+ * <p>
+ * Note that this will also install a dispose listener on that viewer in order to remove the filter
+ * whenever the viewer is disposed.
+ * </p>
+ *
+ * @param viewer
+ * the viewer on which the filter will be installed
+ */
+ public void install(final TreeViewer viewer) {
+ viewer.addFilter(this);
+ viewer.getTree().addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ uninstall(viewer);
+ }
+ });
+ viewers.add(viewer);
+ }
+
+ /**
+ * Uninstall this filter from the given viewer.
+ *
+ * @param viewer
+ * The viewer from which the filter should be removed.
+ */
+ public void uninstall(TreeViewer viewer) {
+ viewer.removeFilter(this);
+ viewers.remove(viewer);
+ }
+
+}

Back to the top