/*
* Carrot2 project.
*
* Copyright (C) 2002-2016, Dawid Weiss, Stanisław Osiński.
* All rights reserved.
*
* Refer to the full license file "carrot2.LICENSE"
* in the root folder of the repository checkout or at:
* http://www.carrot2.org/carrot2.LICENSE
*/
package org.carrot2.workbench.core.ui;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.carrot2.core.Cluster;
import org.carrot2.core.ProcessingResult;
import org.eclipse.jface.viewers.IPostSelectionProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.carrot2.shaded.guava.common.collect.Lists;
import org.carrot2.shaded.guava.common.collect.Maps;
/**
* Simple SWT composite wrapping a {@link TreeViewer} and displaying a {@link Cluster}
* and/or sub-clusters.
*/
public final class ClusterTree
extends Composite
implements IPostSelectionProvider
{
private TreeViewer treeViewer;
private List<Cluster> previousClusters;
/**
* Content provider for the tree.
*/
@SuppressWarnings("unchecked")
private final ITreeContentProvider contentProvider = new ITreeContentProvider()
{
private Map<Cluster, Cluster> parents = Maps.newIdentityHashMap();
/*
* Root tree elements.
*/
public Object [] getElements(Object treeRoot)
{
return ((List<Cluster>) treeRoot).toArray();
}
/*
* Children elements.
*/
public Object [] getChildren(Object parentElement)
{
final Cluster c = (Cluster) parentElement;
return c.getSubclusters().toArray();
}
public Object getParent(Object element)
{
return parents.get(element);
}
public boolean hasChildren(Object parentElement)
{
final Cluster c = (Cluster) parentElement;
return c.getSubclusters().size() > 0;
}
public void dispose()
{
// Empty
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
{
// Build parents mapping.
this.parents.clear();
if (newInput != null)
{
recurse((List<Cluster>) newInput, null);
}
}
/** Recursively build parents map. */
private void recurse(List<Cluster> clusters, Cluster parent)
{
for (Cluster c : clusters)
{
parents.put(c, parent);
recurse(c.getSubclusters(), c);
}
}
};
/*
*
*/
public ClusterTree(Composite parent, int style)
{
super(parent, style);
createComponents();
}
/*
*
*/
public void dispose()
{
treeViewer.getTree().dispose();
super.dispose();
}
/**
* Resets the display to show a new set of clusters.
*/
public void show(final List<Cluster> clusters)
{
if (clusters == null || clusters.isEmpty())
{
clear();
}
else
{
ClusterLabelPaths clp = null;
if (previousClusters != null)
clp = ClusterLabelPaths.from(previousClusters, getExpandedClusters());
treeViewer.setInput(clusters);
if (clp != null)
treeViewer.setExpandedElements(clp.filterMatching(clusters).toArray());
previousClusters = clusters;
}
}
/** Return a list of expanded clusters in the current tree. */
private List<Cluster> getExpandedClusters()
{
List<Cluster> expanded = Lists.newArrayList();
for (Object o : this.treeViewer.getExpandedElements())
{
expanded.add((Cluster) o);
}
return expanded;
}
/**
* Resets the display to show all clusters from a {@link ProcessingResult}.
*/
public void show(final ProcessingResult result)
{
final List<Cluster> clusters = result.getClusters();
show(clusters);
}
/**
* Clear the display.
*/
public void clear()
{
previousClusters = null;
treeViewer.setInput(Collections.emptyList());
}
/**
* Create GUI components and set up listeners.
*/
private void createComponents()
{
this.setLayout(new FillLayout());
treeViewer = new TreeViewer(this, SWT.MULTI);
treeViewer.setLabelProvider(new ClusterLabelProvider());
treeViewer.setContentProvider(contentProvider);
treeViewer.setInput(Collections.emptyList());
treeViewer.setAutoExpandLevel(1);
}
public void addSelectionChangedListener(ISelectionChangedListener listener)
{
this.treeViewer.addSelectionChangedListener(listener);
}
public ISelection getSelection()
{
return this.treeViewer.getSelection();
}
public void removeSelectionChangedListener(ISelectionChangedListener listener)
{
this.treeViewer.removeSelectionChangedListener(listener);
}
public void setSelection(ISelection selection)
{
this.treeViewer.setSelection(selection);
// Expand the paths of a tree selection (all).
if (selection instanceof TreeSelection)
{
for (TreePath tp : ((TreeSelection) selection).getPaths())
{
this.treeViewer.reveal(tp);
}
}
}
public void addPostSelectionChangedListener(ISelectionChangedListener listener)
{
this.treeViewer.addPostSelectionChangedListener(listener);
}
public void removePostSelectionChangedListener(ISelectionChangedListener listener)
{
this.treeViewer.removePostSelectionChangedListener(listener);
}
public void expandAll()
{
this.treeViewer.expandAll();
}
public void collapseAll()
{
this.treeViewer.collapseAll();
}
}