Set default sort order for initial header click on gwt cell table
Asked Answered
S

4

8

I have a GWT CellTable with sortable columns very similar to the developer's guide example (http://code.google.com/webtoolkit/doc/latest/DevGuideUiCellTable.html#columnSorting).

However, I would like to have certain columns sort descending instead of ascending by default. That is, if column A is not currently sorted and I click on it's header, I want column A to be sorted descending on that first click and ascending on the second click. But I do still want other columns to sort as they currently do - using ascending order on the first click.

Aside from the Column.setSortable(boolean) method to set sortability and the ColumnSortList.push(ColumnSortInfo) method to manually trigger a sort, there doesn't seem to be much control over the process.

Is there a way to accomplish this goal?

Skeptic answered 29/2, 2012 at 18:30 Comment(0)
S
8

Column.setDefaultSortAscending(false) is the easy way to do this; no custom CellTable required.

Subtropical answered 25/8, 2012 at 20:46 Comment(1)
Looks like this was just recently added to the api. Thanks for the update.Skeptic
S
5

I was able to extend CellTable to do exactly what I wanted basically by overriding the onColumnSort(ColumnSortEvent) method of the ListHandler associated with the table. This is the meat/potatoes of the implementation. I had to do a little maintenance under the covers to keep track of whether or not a column had been sorted when you are about to sort it again.

One thing that confused me (and was not clear in google's examples) was that using the ColumnSortList.push() method does not actually trigger a sort like clicking does, but instead just changes the underlying state of how the column thinks it is sorted.

When I was ready to utilize this table I made, I basically did the following:

SortedCellTable<MyRowObject> table = new SortedCellTable<MyRowObject>();
table.addColumn(colOne, "one", true); // sortable column
table.addColumn(colTwo, "two", true); //sortable column
table.addColumn(colThree, "three", false); // unsortable column

table.setDefaultSortOrder(colOne, true); // sorts ascending on first click
table.setDefaultSortOrder(colTwo, false); // sorts descending on first click

table.setInitialSortColumn(colTwo); // sort this column as soon as data is set

table.setComparator(colOne, colOneComp); // use this comparator when sorting colOne
table.setComparator(colTwo, colTwoComp); // use this comparator when sorting colTwo

panel.add(table); // add the table to our view
// ...sometime later, asynchronously...
table.setList(myRowObjectList);

Here is the SortedCellTable implementation:

public class SortedCellTable<T> extends CellTable<T> {
/**
 * To keep track of the currently sorted column
 */
private Column<T, ?> currentlySortedColumn;
/**
 * Tells us which way to sort a column initially
 */
private Map<Column<T, ?>, Boolean> defaultSortOrderMap = new HashMap<Column<T, ?>, Boolean>();
/**
 * Comparators associated with their columns
 */
private Map<Column<T, ?>, Comparator<T>> comparators = new HashMap<Column<T, ?>, Comparator<T>>();
/**
 * Column to sort when the data provider's list is refreshed using
 * {@link SortedCellTable#setList(List)}
 */
private Column<T, ?> initialSortColumn;
/**
 * Data provider we will attach to this table
 */
private ListDataProvider<T> dataProvider;
/**
 * Special column sorting handler that will allow us to do more controlled
 * sorting
 */
ListHandler<T> columnSortHandler;

public SortedCellTable() {
    super();
    dataProvider = new ListDataProvider<T>();
    dataProvider.addDataDisplay(this);
    columnSortHandler = new ListHandler<T>(dataProvider.getList()) {

        @Override
        public void onColumnSort(ColumnSortEvent event) {
            @SuppressWarnings("unchecked")
            Column<T, ?> column = (Column<T, ?>) event.getColumn();
            if (column == null) {
                return;
            }

            if (column.equals(currentlySortedColumn)) {
                // Default behavior
                super.onColumnSort(event);
            } else {
                // Initial sort; look up which direction we need
                final Comparator<T> comparator = comparators.get(column);
                if (comparator == null) {
                    return;
                }

                Boolean ascending = defaultSortOrderMap.get(column);
                if (ascending == null || ascending) {
                    // Default behavior
                    super.onColumnSort(event);
                } else {
                    // Sort the column descending
                    Collections.sort(getList(), new Comparator<T>() {
                        public int compare(T o1, T o2) {
                            return -comparator.compare(o1, o2);
                        }
                    });
                    // Set the proper arrow in the header
                    getColumnSortList().push(
                            new ColumnSortInfo(column, false));
                }
                currentlySortedColumn = column;
            }
        }

        @Override
        public void setComparator(Column<T, ?> column,
                Comparator<T> comparator) {
            comparators.put(column, comparator);
            super.setComparator(column, comparator);
        }

    };
    addColumnSortHandler(columnSortHandler);
}

/**
 * Adds a column to the table and sets its sortable state
 * 
 * @param column
 * @param headerName
 * @param sortable
 */
public void addColumn(Column<T, ?> column, String headerName,
        boolean sortable) {
    addColumn(column, headerName);
    column.setSortable(sortable);
    if (sortable) {
        defaultSortOrderMap.put(column, true);
    }
}

/**
 * Adds a column to the table and sets its sortable state
 * 
 * @param column
 * @param header
 * @param sortable
 */
public void addColumn(Column<T, ?> column, Header<?> header,
        boolean sortable) {
    addColumn(column, header);
    column.setSortable(sortable);
    if (sortable) {
        defaultSortOrderMap.put(column, true);
    }
}

/**
 * Sets the column to sort when the data list is reset using
 * {@link SortedCellTable#setList(List)}
 * 
 * @param column
 */
public void setInitialSortColumn(Column<T, ?> column) {
    initialSortColumn = column;
}

/**
 * Sets a comparator to use when sorting the given column
 * 
 * @param column
 * @param comparator
 */
public void setComparator(Column<T, ?> column, Comparator<T> comparator) {
    columnSortHandler.setComparator(column, comparator);
}

/**
 * Sets the sort order to use when this column is clicked and it was not
 * previously sorted
 * 
 * @param column
 * @param ascending
 */
public void setDefaultSortOrder(Column<T, ?> column, boolean ascending) {
    defaultSortOrderMap.put(column, ascending);
}

/**
 * Sets the table's data provider list and sorts the table based on the
 * column given in {@link SortedCellTable#setInitialSortColumn(Column)}
 * 
 * @param list
 */
public void setList(List<T> list) {
    dataProvider.getList().clear();
    if (list != null) {
        for (T t : list) {
            dataProvider.getList().add(t);
        }
    }

    // Do a first-time sort based on which column was set in
    // setInitialSortColumn()
    if (initialSortColumn != null) {
        Collections.sort(dataProvider.getList(), new Comparator<T>() {

            @Override
            public int compare(T o1, T o2) {
                return (defaultSortOrderMap.get(initialSortColumn) ? 1 : -1)
                        * comparators.get(initialSortColumn)
                                .compare(o1, o2);
            }

        });
        // Might as well get the little arrow on the header to make it
        // official
        getColumnSortList().push(
                new ColumnSortInfo(initialSortColumn, defaultSortOrderMap
                        .get(initialSortColumn)));
        currentlySortedColumn = initialSortColumn;
    }
}
}
Skeptic answered 1/3, 2012 at 13:4 Comment(0)
M
2

Take a look at GWT CellTable columnsorting. (Someone voted it down because he/she did not agree with my approach?)

It is not the answer to your question, but it advocates that you get to the basics of Celltable before attempting anything illustrated by the celltable examples.

By getting to understand the basic behaviour and requirements of Cell/Grid tables, the sorting of columns will manifest itself clearly.

The sorting is performed by your supplying an implementation of comparator. On my part, I had tried a few ways of implementing comparator to suit the various ways I wanted columns sorted.

Minos answered 1/3, 2012 at 4:33 Comment(3)
Thanks for the response. I agree with you in your linked post that the examples do not adequately convey the capabilities and approach necessary for tangoing with the CellTable. I was able to subclass CellTable to do what I wanted. I will post as a response.Skeptic
To aid people who are looking for answers, you should mark your response as the answer.Minos
Thank you for the tip. Since I am new it wants me to wait a day before I can mark it.Skeptic
R
1

instead of

someTable.getColumnSortList().push(provider.getDefaultSortColumn());

use

someTable.getColumnSortList().push(new ColumnSortInfo(provider.getDefaultSortColumn(), false));
Riffraff answered 6/12, 2012 at 18:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.