/*
* Copyright 2010 The Rabbit Eclipse Plug-in Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package rabbit.ui.internal.viewers;
import static com.google.common.base.Preconditions.checkNotNull;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreePathViewerSorter;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.Widget;
/**
* A comparator for sorting the a {@link TreeViewer} when the user is clicked on
* a column.
* <p>
* To register a column for sorting, simply call the column's
* {@link TreeColumn#addSelectionListener(SelectionListener)} method and pass in
* an instance of this class.
* </p>
* <p>
* Subclasses need to override
* {@link #doCompare(Viewer, TreePath, Object, Object)} to do the actual
* comparing of the elements.
* </p>
*/
public abstract class TreeViewerColumnSorter
extends TreePathViewerSorter implements SelectionListener {
/**
* One of {@link SWT#NONE}, {@link SWT#UP}, {@link SWT#DOWN}.
*/
private int sortDirection;
private TreeColumn selectedColumn;
private final TreeViewer viewer;
/**
* Constructor.
* @param parent The parent viewer.
* @throws NullPointerException If argument is null.
*/
public TreeViewerColumnSorter(TreeViewer parent) {
viewer = checkNotNull(parent);
sortDirection = SWT.NONE;
selectedColumn = null;
}
@Override
public int compare(Viewer v, TreePath parentPath, Object e1, Object e2) {
int cat1 = category(e1);
int cat2 = category(e2);
int value = 0;
if (cat1 != cat2) {
value = cat1 - cat2;
} else {
value = doCompare(v, parentPath, e1, e2);
}
if (sortDirection == SWT.DOWN) {
value *= -1;
}
return value;
}
/**
* Gets the currently selected column.
* @return The selected column.
*/
public TreeColumn getSelectedColumn() {
return selectedColumn;
}
/**
* @return the viewer
*/
public TreeViewer getViewer() {
return viewer;
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
// Do nothing.
}
@Override
public void widgetSelected(SelectionEvent e) {
Widget item = e.widget;
if (!(item instanceof TreeColumn)) {
return;
}
TreePath[] expandedTreePaths = viewer.getExpandedTreePaths();
selectedColumn = (TreeColumn) e.widget;
Tree tree = selectedColumn.getParent();
TreeColumn previousColumn = tree.getSortColumn();
sortDirection = tree.getSortDirection();
if (previousColumn == selectedColumn) {
sortDirection = (sortDirection == SWT.UP) ? SWT.DOWN : SWT.UP;
} else {
tree.setSortColumn(selectedColumn);
sortDirection = SWT.UP;
viewer.setComparator(this);
}
viewer.refresh();
tree.setSortDirection(sortDirection);
viewer.setExpandedTreePaths(expandedTreePaths);
}
/**
* Compares the given elements. Subclasses overriding this method does not
* need to care about sorting descendingly, this will be handled by the super
* class.
*
* @param v The viewer.
* @param parentPath the parent path of the elements, or null if the elements
* are root elements.
* @param e1 The first element.
* @param e2 The second element.
* @return A negative value if the first element is consider less than the
* second element, a zero if the first element is consider equal to
* the second element, a positive value if the first element is
* consider greater than the second element,
*/
protected abstract int doCompare(Viewer v, TreePath parentPath, Object e1,
Object e2);
}