I know this question is ooooold, but I just solved the problem for a TreeList I was working on...
I used a TreeList.Format
which doubles as an ISortModel
for my SortHeaderLayer
.
The Comparator
is directly applied to the SortedList
while ISortModel
's getComparatorsForColumnIndex(int)
and getColumnComparator(int)
may return null
.
The Comparator
always takes the whole path to a TreeNode
into account and never returns 0
unless the TreeNode
s are truly identical.
Setting SortDirectionEnum.NONE
in ISortModel
's sort(int, SortDirectionEnum, boolean)
triggers a fallback to ascending order of column 0.
private class MyTreeFormat implements TreeList.Format<TreeNode>, ISortModel {
private final IColumnPropertyAccessor<TreeNode> columnPropertyAccessor;
public MyTreeFormat(final IColumnPropertyAccessor<TreeNode> columnPropertyAccessor) {
this.columnPropertyAccessor = columnPropertyAccessor;
}
// never return 0 unless node1 == node2, else the list will be in arbitrary order and mess up the tree
private final Comparator<TreeNode> comparator = new Comparator<TreeNode>() {
@Override
public int compare(final TreeNode node1, final TreeNode node2) {
if (node1 == node2) return 0;
// paths from root to node 1&2
final Iterator<TreeNode> piter1 = node1.getPath().iterator();
final Iterator<TreeNode> piter2 = node2.getPath().iterator();
while (piter1.hasNext() && piter2.hasNext()) {
final int result = doCompare(piter1.next(), piter2.next());
if (result != 0) return result;
}
return 0;
}
private int doCompare(final TreeNode node1, final TreeNode node2) {
if (node1 == node2) return 0;
int result;
if (sortedColumnIndex == 0) {
result = SpecialComparatorForColumn0.getInstance().compare(node1.getId(), node2.getId());
} else {
final Object data1 = columnPropertyAccessor.getDataValue(node1, sortedColumnIndex);
final Object data2 = columnPropertyAccessor.getDataValue(node2, sortedColumnIndex);
final String s1, s2;
// we have some Date columns while all other columns are Strings:
if (data1 instanceof Date) {
s1 = MY_SIMPLE_DATE_FORMAT.format((Date) data1);
s2 = MY_SIMPLE_DATE_FORMAT.format((Date) data2);
} else {
s1 = String.valueOf(data1);
s2 = String.valueOf(data2);
}
result = s1.compareToIgnoreCase(s2);
if (result == 0) result = SpecialComparatorForColumn0.getInstance().compare(node1.getId(), node2.getId()); // ensures same order for equal values in sort column !!
}
return result * (sortDirection == SortDirectionEnum.ASC ? 1 : -1);
}
};
@Override
public void getPath(final List<TreeNode> path, final TreeNode element) {
for (final TreeNode TreeNode : element.getPath()) {
path.add(TreeNode);
}
}
/**
* Simply always return <code>true</code>.
*
* @return <code>true</code> if this element can have child elements, or
* <code>false</code> if it is always a leaf node.
*/
@Override
public boolean allowsChildren(final TreeNode element) {
return true;
}
/**
* Returns the comparator used to order path elements of the specified
* depth. If enforcing order at this level is not intended, this method
* should return <code>null</code>. We do a simple sorting of the last
* names of the persons to show so the tree nodes are sorted in
* alphabetical order.
*/
@Override
public Comparator<? super TreeNode> getComparator(final int depth) {
return comparator;
}
/* ---------- ISortModel implementation START ----------
* ISortModel for the SortHeaderLayer
* sort only allowed by a single column at a time
* key was to set the sorted list's comparator on sort(...) so the whole tree is reordered on a click on the column header
*/
private int sortedColumnIndex = 0;
private int sortedColumnIndexOld = 0;
private SortDirectionEnum sortDirection = SortDirectionEnum.DESC;
@Override
public List<Integer> getSortedColumnIndexes() {
return Collections.singletonList(sortedColumnIndex);
}
@Override
public boolean isColumnIndexSorted(final int columnIndex) {
return sortedColumnIndex == columnIndex;
}
@Override
public SortDirectionEnum getSortDirection(final int columnIndex) {
if (columnIndex == sortedColumnIndexOld) return sortDirection;
else {
sortedColumnIndexOld = columnIndex;
return sortDirection = SortDirectionEnum.NONE;
}
}
@Override
public int getSortOrder(final int columnIndex) {
return 0;
}
@SuppressWarnings("rawtypes")
@Override
public List<Comparator> getComparatorsForColumnIndex(final int columnIndex) {
return null;
}
@Override
public Comparator<?> getColumnComparator(final int columnIndex) {
return null;
}
@Override
public void sort(final int columnIndex, final SortDirectionEnum sortDirection, final boolean accumulate) {
if (sortDirection == SortDirectionEnum.NONE) {
this.sortDirection = SortDirectionEnum.ASC;
this.sortedColumnIndex = 0;
} else {
this.sortDirection = sortDirection;
this.sortedColumnIndex = columnIndex;
}
bodyLayerStack.getSortedList().setComparator(comparator);
}
@Override
public void clear() {
sort(0, SortDirectionEnum.ASC, false);
}
}