getNodeComparator() {
return nodeComparator;
}
/**
* Tells the current sorting order of the given column.
*
* @param column the column to get its sorting order
* @return true if the column is sorted in ascending order
*/
public boolean isAscending(int column) {
assert column > 0 : "Column 0 isn't sortable"; //$NON-NLS-1$
assert column < columnPosition.length : "Column " + column + " is out of bounds (" + columnPosition.length + " columns)"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
return sortingColumns[columnPosition[column]].ascending;
}
/**
* Gets the number of the last column that was selected for sorting.
*
* @return column number
*/
public int getSortingColumn() {
if (sortingColumns != null && sortingColumns.length > 0) {
return sortingColumns[0].number;
}
return -1;
}
/**
* Checks to see whether the given column is sorted.
* @param column the column index
* @return true if the column is sorted, false otherwise.
*/
public boolean isSorted(int column) {
return getSortingPrecedence(column) != -1;
}
/**
* Finds the precedence (order) of the specified column among the columns used for
* sorting.
* @param column to column to get it's precedence
* @return the precedence of the column or -1 if it's not used for sorting
*/
public int getSortingPrecedence(int column) {
if (column == 0) return -1;
assert column < columnPosition.length : "Column " + column + " is out of bounds (" + columnPosition.length + " columns)"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
if (sortingColumns != null && sortingColumns.length > 0) {
return (columnPosition[column] < nextAppendColumnPosition) ? columnPosition[column] : -1;
}
return -1;
}
/**
* Gets the precedence/order of the next column that will be appended to the list
* of sorting column.
* @return value of 1 signifies that only one column is used for sorting
*/
public int getNextAppendColumnPosition() {
return nextAppendColumnPosition;
}
/**
* Set the ascending order of a column and making it the first column that
* is compared when comparing nodes.
*
* @param column the sorting column
* @param ascending true if the sorting order should be ascending
*/
public void setAscending(int column, boolean ascending) {
assert column > 0 : "Column 0 isn't sortable"; //$NON-NLS-1$
assert column < columnPosition.length : "Column " + column + " is out of bounds (" + columnPosition.length + " columns)"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
int currColPos = columnPosition[column];
Column col = sortingColumns[currColPos];
col.ascending = ascending;
if (currColPos > 0) {
nextAppendColumnPosition = 0;
setSorting(column);
}
nextAppendColumnPosition = 1;
}
/**
* Set the ascending order of a column and append it the last sorting column that
* is compared when comparing nodes.
*
* @param column the sorting column
* @param ascending true if the sorting order should be ascending
*/
public void appendAscending(int column, boolean ascending) {
assert column > 0 : "Column 0 isn't sortable"; //$NON-NLS-1$
assert column < columnPosition.length : "Column " + column + " is out of bounds (" + columnPosition.length + " columns)"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
int currColPos = columnPosition[column];
Column col = sortingColumns[currColPos];
col.ascending = ascending;
if (currColPos >= nextAppendColumnPosition) {
setSorting(column);
}
}
/**
* Updates the sorting criterion, resetting the order of columns and the direction
* according to the user's request.
* By default, the specified column will become
* the most significant column. If "append" was specified, the specified column
* will be moved after the last, previously appended column.
*
The direction of sorting by the specified column will be toggled if order
* the column are compared wasn't modified.
* @param column the column to update
* @param append false if the column should become the most significant column,
* true if the last appended column
*/
public void updateSorting(int column, boolean append) {
assert column > 0 : "Column 0 isn't sortable"; //$NON-NLS-1$
assert column < columnPosition.length : "Column " + column + " is out of bounds (" + columnPosition.length + " columns)"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
int currColPos = columnPosition[column];
Column col = sortingColumns[currColPos];
/**
* When not in "append" mode, if the column is already the most significant
* column, just toggle it's direction. Otherwise, promote the column but
* keep it's direction.
*/
if (!append) {
if (currColPos == 0) {
col.ascending = !col.ascending;
} else {
setAscending(column, col.ascending);
}
nextAppendColumnPosition = 1;
}
/**
* When in append mode, if the column was already selected for sorting, then
* only toggle it's direction. Otherwise, promote the column and keep
* the direction.
*/
else {
if (currColPos < nextAppendColumnPosition) {
col.ascending = !col.ascending;
} else {
setSorting(column);
}
}
}
private void setSorting (int column) {
int currColPos = columnPosition[column];
Column col = sortingColumns[currColPos];
for (int from = currColPos - 1; from >= nextAppendColumnPosition; --from) {
int to = from + 1;
sortingColumns[to] = sortingColumns[from];
columnPosition[sortingColumns[to].number] = to;
}
sortingColumns[nextAppendColumnPosition] = col;
columnPosition[column] = nextAppendColumnPosition;
++nextAppendColumnPosition;
}
void setRowCount(int rowCount) {
this.rowCount = rowCount;
}
void setSortingCanceled(boolean cancelSorting) {
this.cancelSorting = cancelSorting;
}
/**
* Compare two nodes by comparing all their values according to the order
* of columns in {@link GroupingSorter#sortingColumns}.
*/
class NodeComparator implements Comparator {
public int compare(Node node1, Node node2) {
if (cancelSorting) {
throw new InterruptedRuntimeException();
}
// If the number of rows to be sorted is small, consider all columns for
// comparing nodes. If the rows is large, only consider the sorting columns
// the user selected.
int loopMax = (rowCount < FULL_SORT_THRESHOLD) ? sortingColumns.length : nextAppendColumnPosition;
for (int i = 0; i < loopMax; ++i) {
int col = sortingColumns[i].number;
Object val1 = node1.getValueAt(col);
Object val2 = node2.getValueAt(col);
int comp = VALUE_COMPARATOR.compare(val1, val2);
if (comp != 0) {
if (sortingColumns[i].ascending)
return comp;
else
return -comp;
}
}
return 0;
}
}
/**
* Holds the number and sorting order of a column.
*/
static class Column {
/**
* The column number.
*/
final int number;
/**
* If true, than this column is sorted in ascending order.
*/
boolean ascending;
/**
* Sets the column number and ascending.
*
* @param number the column number.
* @param ascending if true, than this column is sorted in ascending order
*/
public Column(int number, boolean ascending) {
this.number = number;
this.ascending = ascending;
}
}
}