summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorPatrik Lindström <patrik@vaadin.com>2014-06-17 18:30:04 +0300
committerPatrik Lindström <patrik@vaadin.com>2014-06-26 16:15:05 +0300
commit6294a26ab8ae5df83d25318c4a8b14db34f5b8a4 (patch)
tree6513a1c58d8b0e9b1699981269c630335ddd858b /client
parentf4a538019bc6c5abeeb453d9f116088d03d7c32f (diff)
downloadvaadin-framework-6294a26ab8ae5df83d25318c4a8b14db34f5b8a4.tar.gz
vaadin-framework-6294a26ab8ae5df83d25318c4a8b14db34f5b8a4.zip
Implement Grid client-side Sorting API (#13334)
Change-Id: I9ab18c93bdc1aaf66aa2701c3939311671a60f04
Diffstat (limited to 'client')
-rw-r--r--client/src/com/vaadin/client/ui/grid/Grid.java287
-rw-r--r--client/src/com/vaadin/client/ui/grid/datasources/ListDataSource.java42
-rw-r--r--client/src/com/vaadin/client/ui/grid/sort/Sort.java155
-rw-r--r--client/src/com/vaadin/client/ui/grid/sort/SortEvent.java112
-rw-r--r--client/src/com/vaadin/client/ui/grid/sort/SortEventHandler.java38
-rw-r--r--client/src/com/vaadin/client/ui/grid/sort/SortOrder.java73
-rw-r--r--client/tests/src/com/vaadin/client/ui/grid/ListDataSourceTest.java27
7 files changed, 626 insertions, 108 deletions
diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java
index dfcda40b04..1739e28608 100644
--- a/client/src/com/vaadin/client/ui/grid/Grid.java
+++ b/client/src/com/vaadin/client/ui/grid/Grid.java
@@ -49,16 +49,21 @@ import com.vaadin.client.ui.grid.selection.SelectionModel;
import com.vaadin.client.ui.grid.selection.SelectionModelMulti;
import com.vaadin.client.ui.grid.selection.SelectionModelNone;
import com.vaadin.client.ui.grid.selection.SelectionModelSingle;
+import com.vaadin.client.ui.grid.sort.Sort;
+import com.vaadin.client.ui.grid.sort.SortEvent;
+import com.vaadin.client.ui.grid.sort.SortEventHandler;
+import com.vaadin.client.ui.grid.sort.SortOrder;
import com.vaadin.shared.ui.grid.GridConstants;
import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.shared.ui.grid.Range;
import com.vaadin.shared.ui.grid.ScrollDestination;
+import com.vaadin.shared.ui.grid.SortDirection;
import com.vaadin.shared.util.SharedUtil;
/**
* A data grid view that supports columns and lazy loading of data rows from a
* data source.
- *
+ *
* <h3>Columns</h3>
* <p>
* The {@link GridColumn} class defines the renderer used to render a cell in
@@ -72,15 +77,15 @@ import com.vaadin.shared.util.SharedUtil;
* specific column index using {@link Grid#getColumn(int)}.
* </p>
* <p>
- *
+ *
* TODO Explain about headers/footers once the multiple header/footer api has
* been implemented
- *
+ *
* <h3>Data sources</h3>
* <p>
* TODO Explain about what a data source is and how it should be implemented.
* </p>
- *
+ *
* @param <T>
* The row type of the grid. The row type is the POJO type from where
* the data is retrieved into the column cells.
@@ -213,6 +218,12 @@ public class Grid<T> extends Composite implements
*/
private GridColumn<?, T> lastFrozenColumn;
+ /**
+ * Current sort order. The (private) sort() method reads this list to
+ * determine the order in which to present rows.
+ */
+ private List<SortOrder> sortOrder = new ArrayList<SortOrder>();
+
private Renderer<Boolean> selectColumnRenderer = null;
private SelectionColumn selectionColumn;
@@ -269,10 +280,10 @@ public class Grid<T> extends Composite implements
/**
* Base class for grid columns internally used by the Grid. The user should
* use {@link GridColumn} when creating new columns.
- *
+ *
* @param <C>
* the column type
- *
+ *
* @param <T>
* the row type
*/
@@ -320,7 +331,7 @@ public class Grid<T> extends Composite implements
/**
* Constructs a new column with a custom renderer.
- *
+ *
* @param renderer
* The renderer to use for rendering the cells
*/
@@ -334,7 +345,7 @@ public class Grid<T> extends Composite implements
/**
* Constructs a new column with custom renderers for rows, header and
* footer cells.
- *
+ *
* @param bodyRenderer
* The renderer to use for rendering body cells
* @param headerRenderer
@@ -355,7 +366,7 @@ public class Grid<T> extends Composite implements
/**
* Internally used by the grid to set itself
- *
+ *
* @param grid
*/
private void setGrid(Grid<T> grid) {
@@ -371,7 +382,7 @@ public class Grid<T> extends Composite implements
/**
* Gets text in the header of the column. By default the header caption
* is empty.
- *
+ *
* @return the text displayed in the column caption
*/
public String getHeaderCaption() {
@@ -380,7 +391,7 @@ public class Grid<T> extends Composite implements
/**
* Returns the renderer used for rendering the header cells
- *
+ *
* @return a renderer that renders header cells
*/
public Renderer<String> getHeaderRenderer() {
@@ -389,7 +400,7 @@ public class Grid<T> extends Composite implements
/**
* Sets the renderer that renders header cells. Should not be null.
- *
+ *
* @param renderer
* The renderer to use for rendering header cells.
*/
@@ -405,7 +416,7 @@ public class Grid<T> extends Composite implements
/**
* Returns the renderer used for rendering the footer cells
- *
+ *
* @return a renderer that renders footer cells
*/
public Renderer<String> getFooterRenderer() {
@@ -414,7 +425,7 @@ public class Grid<T> extends Composite implements
/**
* Sets the renderer that renders footer cells. Should not be null.
- *
+ *
* @param renderer
* The renderer to use for rendering footer cells.
*/
@@ -430,7 +441,7 @@ public class Grid<T> extends Composite implements
/**
* Sets the text in the header of the column.
- *
+ *
* @param caption
* the text displayed in the column header
*/
@@ -449,7 +460,7 @@ public class Grid<T> extends Composite implements
/**
* Gets text in the footer of the column. By default the footer caption
* is empty.
- *
+ *
* @return The text displayed in the footer of the column
*/
public String getFooterCaption() {
@@ -458,7 +469,7 @@ public class Grid<T> extends Composite implements
/**
* Sets text in the footer of the column.
- *
+ *
* @param caption
* the text displayed in the footer of the column
*/
@@ -476,7 +487,7 @@ public class Grid<T> extends Composite implements
/**
* Is the column visible. By default all columns are visible.
- *
+ *
* @return <code>true</code> if the column is visible
*/
@Override
@@ -486,7 +497,7 @@ public class Grid<T> extends Composite implements
/**
* Sets a column as visible in the grid.
- *
+ *
* @param visible
* <code>true</code> if the column should be displayed in the
* grid
@@ -515,19 +526,26 @@ public class Grid<T> extends Composite implements
}
/**
- * Returns the data that should be rendered into the cell.
- *
+ * Returns the data that should be rendered into the cell. By default
+ * returning Strings and Widgets are supported. If the return type is a
+ * String then it will be treated as preformatted text.
+ * <p>
+ * To support other types you will need to pass a custom renderer to the
+ * column via the column constructor.
+ *
* @param row
* The row object that provides the cell content.
- *
+ *
* @return The cell content
*/
public abstract C getValue(T row);
/**
- * Returns the renderer used to render the cells of this column.
- *
- * @return the renderer to render the cell content with
+ * The renderer to render the cell width. By default renders the data as
+ * a String or adds the widget into the cell if the column type is of
+ * widget type.
+ *
+ * @return The renderer to render the cell content with
*/
public Renderer<? super C> getRenderer() {
return bodyRenderer;
@@ -535,7 +553,7 @@ public class Grid<T> extends Composite implements
/**
* Finds the index of this column instance
- *
+ *
*/
private int findIndexOfColumn() {
return grid.findVisibleColumnIndex((GridColumn<?, T>) this);
@@ -544,7 +562,7 @@ public class Grid<T> extends Composite implements
/**
* Sets the pixel width of the column. Use a negative value for the grid
* to autosize column based on content and available space
- *
+ *
* @param pixels
* the width in pixels or negative for auto sizing
*/
@@ -561,7 +579,7 @@ public class Grid<T> extends Composite implements
/**
* Returns the pixel width of the column
- *
+ *
* @return pixel width of the column
*/
public int getWidth() {
@@ -594,7 +612,7 @@ public class Grid<T> extends Composite implements
/**
* Constructs an updater for updating a header / footer
- *
+ *
* @param rows
* The row container
* @param inverted
@@ -607,17 +625,17 @@ public class Grid<T> extends Composite implements
/**
* Gets the header/footer caption value
- *
+ *
* @param column
* The column to get the value for.
- *
+ *
* @return The value that should be rendered for the column caption
*/
public abstract String getColumnValue(GridColumn<?, T> column);
/**
* Gets the group caption value
- *
+ *
* @param group
* The group for with the caption value should be returned
* @return The value that should be rendered for the column caption
@@ -626,34 +644,34 @@ public class Grid<T> extends Composite implements
/**
* Is the row visible in the header/footer
- *
+ *
* @param row
* the row to check
- *
+ *
* @return <code>true</code> if the row should be visible
*/
public abstract boolean isRowVisible(ColumnGroupRow<T> row);
/**
* Should the first row be visible
- *
+ *
* @return <code>true</code> if the first row should be visible
*/
public abstract boolean firstRowIsVisible();
/**
* The renderer that renders the cell
- *
+ *
* @param column
* The column for which the cell should be rendered
- *
+ *
* @return renderer used for rendering
*/
public abstract Renderer<String> getRenderer(GridColumn<?, T> column);
/**
* The renderer that renders the cell for column groups
- *
+ *
* @param group
* The group that should be rendered
* @return renderer used for rendering
@@ -780,7 +798,7 @@ public class Grid<T> extends Composite implements
/**
* Creates the header updater that updates the escalator header rows from
* the column and column group rows.
- *
+ *
* @return the updater that updates the data in the escalator.
*/
private EscalatorUpdater createHeaderUpdater() {
@@ -950,7 +968,7 @@ public class Grid<T> extends Composite implements
/**
* Creates the footer updater that updates the escalator footer rows from
* the column and column group rows.
- *
+ *
* @return the updater that updates the data in the escalator.
*/
private EscalatorUpdater createFooterUpdater() {
@@ -990,7 +1008,7 @@ public class Grid<T> extends Composite implements
/**
* Refreshes header or footer rows on demand
- *
+ *
* @param rows
* The row container
* @param firstRowIsVisible
@@ -1042,7 +1060,7 @@ public class Grid<T> extends Composite implements
/**
* Adds a column as the last column in the grid.
- *
+ *
* @param column
* the column to add
*/
@@ -1052,7 +1070,7 @@ public class Grid<T> extends Composite implements
/**
* Inserts a column into a specific position in the grid.
- *
+ *
* @param index
* the index where the column should be inserted into
* @param column
@@ -1161,7 +1179,7 @@ public class Grid<T> extends Composite implements
/**
* Removes a column from the grid.
- *
+ *
* @param column
* the column to remove
*/
@@ -1196,7 +1214,7 @@ public class Grid<T> extends Composite implements
/**
* Returns the amount of columns in the grid.
- *
+ *
* @return The number of columns in the grid
*/
public int getColumnCount() {
@@ -1205,7 +1223,7 @@ public class Grid<T> extends Composite implements
/**
* Returns a list of columns in the grid.
- *
+ *
* @return A unmodifiable list of the columns in the grid
*/
public List<GridColumn<?, T>> getColumns() {
@@ -1215,7 +1233,7 @@ public class Grid<T> extends Composite implements
/**
* Returns a column by its index in the grid.
- *
+ *
* @param index
* the index of the column
* @return The column in the given index
@@ -1232,30 +1250,30 @@ public class Grid<T> extends Composite implements
/**
* Set the column headers visible.
- *
+ *
* <p>
* A column header is a single cell header on top of each column reserved
* for a specific header for that column. The column header can be set by
* {@link GridColumn#setHeaderCaption(String)} and column headers cannot be
* merged with other column headers.
* </p>
- *
+ *
* <p>
* All column headers occupy the first header row of the grid. If you do not
* wish to show the column headers in the grid you should hide the row by
* setting visibility of the header row to <code>false</code>.
* </p>
- *
+ *
* <p>
* If you want to merge the column headers into groups you can use
* {@link ColumnGroupRow}s to group columns together and give them a common
* header. See {@link #addColumnGroupRow()} for details.
* </p>
- *
+ *
* <p>
* The header row is by default visible.
* </p>
- *
+ *
* @param visible
* <code>true</code> if header rows should be visible
*/
@@ -1269,7 +1287,7 @@ public class Grid<T> extends Composite implements
/**
* Are the column headers visible
- *
+ *
* @return <code>true</code> if they are visible
*/
public boolean isColumnHeadersVisible() {
@@ -1278,30 +1296,30 @@ public class Grid<T> extends Composite implements
/**
* Set the column footers visible.
- *
+ *
* <p>
* A column footer is a single cell footer below of each column reserved for
* a specific footer for that column. The column footer can be set by
* {@link GridColumn#setFooterCaption(String)} and column footers cannot be
* merged with other column footers.
* </p>
- *
+ *
* <p>
* All column footers occupy the first footer row of the grid. If you do not
* wish to show the column footers in the grid you should hide the row by
* setting visibility of the footer row to <code>false</code>.
* </p>
- *
+ *
* <p>
* If you want to merge the column footers into groups you can use
* {@link ColumnGroupRow}s to group columns together and give them a common
* footer. See {@link #addColumnGroupRow()} for details.
* </p>
- *
+ *
* <p>
* The footer row is by default hidden.
* </p>
- *
+ *
* @param visible
* <code>true</code> if the footer row should be visible
*/
@@ -1315,9 +1333,9 @@ public class Grid<T> extends Composite implements
/**
* Are the column footers visible
- *
+ *
* @return <code>true</code> if they are visible
- *
+ *
*/
public boolean isColumnFootersVisible() {
return columnFootersVisible;
@@ -1325,15 +1343,15 @@ public class Grid<T> extends Composite implements
/**
* Adds a new column group row to the grid.
- *
+ *
* <p>
* Column group rows are rendered in the header and footer of the grid.
* Column group rows are made up of column groups which groups together
* columns for adding a common auxiliary header or footer for the columns.
* </p>
- *
+ *
* Example usage:
- *
+ *
* <pre>
* // Add a new column group row to the grid
* ColumnGroupRow row = grid.addColumnGroupRow();
@@ -1347,7 +1365,7 @@ public class Grid<T> extends Composite implements
* // Set a common footer for &quot;Column1&quot; and &quot;Column2&quot;
* column12.setFooter(&quot;Column 1&amp;2&quot;);
* </pre>
- *
+ *
* @return a column group row instance you can use to add column groups
*/
public ColumnGroupRow<T> addColumnGroupRow() {
@@ -1360,10 +1378,10 @@ public class Grid<T> extends Composite implements
/**
* Adds a new column group row to the grid at a specific index.
- *
+ *
* @see #addColumnGroupRow() {@link Grid#addColumnGroupRow()} for example
* usage
- *
+ *
* @param rowIndex
* the index where the column group row should be added
* @return a column group row instance you can use to add column groups
@@ -1378,7 +1396,7 @@ public class Grid<T> extends Composite implements
/**
* Removes a column group row
- *
+ *
* @param row
* The row to remove
*/
@@ -1390,9 +1408,9 @@ public class Grid<T> extends Composite implements
/**
* Get the column group rows
- *
+ *
* @return a unmodifiable list of column group rows
- *
+ *
*/
public List<ColumnGroupRow<T>> getColumnGroupRows() {
return Collections.unmodifiableList(new ArrayList<ColumnGroupRow<T>>(
@@ -1401,7 +1419,7 @@ public class Grid<T> extends Composite implements
/**
* Returns the column group for a row and column
- *
+ *
* @param row
* The row of the column
* @param column
@@ -1425,7 +1443,7 @@ public class Grid<T> extends Composite implements
* <p>
* <em>Note:</em> This method will change the widget's size in the browser
* only if {@link #getHeightMode()} returns {@link HeightMode#CSS}.
- *
+ *
* @see #setHeightMode(HeightMode)
*/
@Override
@@ -1440,7 +1458,7 @@ public class Grid<T> extends Composite implements
/**
* Sets the data source used by this grid.
- *
+ *
* @param dataSource
* the data source to use, not null
* @throws IllegalArgumentException
@@ -1493,7 +1511,7 @@ public class Grid<T> extends Composite implements
* <p>
* All columns up to and including the given column will be frozen in place
* when the grid is scrolled sideways.
- *
+ *
* @param lastFrozenColumn
* the rightmost column to freeze, or <code>null</code> to not
* have any columns frozen
@@ -1526,7 +1544,7 @@ public class Grid<T> extends Composite implements
* <em>Note:</em> Most usually, this method returns the very value set with
* {@link #setLastFrozenColumn(GridColumn)}. This value, however, can be
* reset to <code>null</code> if the column is removed from this grid.
- *
+ *
* @return the rightmost frozen column in the grid, or <code>null</code> if
* no columns are frozen.
*/
@@ -1546,7 +1564,7 @@ public class Grid<T> extends Composite implements
/**
* Scrolls to a certain row, using {@link ScrollDestination#ANY}.
- *
+ *
* @param rowIndex
* zero-based index of the row to scroll to.
* @throws IllegalArgumentException
@@ -1560,7 +1578,7 @@ public class Grid<T> extends Composite implements
/**
* Scrolls to a certain row, using user-specified scroll destination.
- *
+ *
* @param rowIndex
* zero-based index of the row to scroll to.
* @param destination
@@ -1579,7 +1597,7 @@ public class Grid<T> extends Composite implements
/**
* Scrolls to a certain row using only user-specified parameters.
- *
+ *
* @param rowIndex
* zero-based index of the row to scroll to.
* @param destination
@@ -1636,7 +1654,7 @@ public class Grid<T> extends Composite implements
* <p>
* If Grid is currently not in {@link HeightMode#ROW}, the given value is
* remembered, and applied once the mode is applied.
- *
+ *
* @param rows
* The height in terms of number of rows displayed in Grid's
* body. If Grid doesn't contain enough rows, white space is
@@ -1648,7 +1666,7 @@ public class Grid<T> extends Composite implements
* infinite}
* @throws IllegalArgumentException
* if {@code rows} is {@link Double#isNaN(double) NaN}
- *
+ *
* @see #setHeightMode(HeightMode)
*/
public void setHeightByRows(double rows) throws IllegalArgumentException {
@@ -1660,7 +1678,7 @@ public class Grid<T> extends Composite implements
* {@link #getHeightMode()} is {@link HeightMode#ROW}.
* <p>
* By default, it is {@value Escalator#DEFAULT_HEIGHT_BY_ROWS}.
- *
+ *
* @return the amount of rows that should be shown in Grid's body, while in
* {@link HeightMode#ROW}.
* @see #setHeightByRows(double)
@@ -1680,7 +1698,7 @@ public class Grid<T> extends Composite implements
* <em>Note:</em> If headers/footers are inserted or removed, the widget
* will resize itself to still display the required amount of rows in its
* body. It also takes the horizontal scrollbar into account.
- *
+ *
* @param heightMode
* the mode in to which Grid should be set
*/
@@ -1702,7 +1720,7 @@ public class Grid<T> extends Composite implements
* Returns the current {@link HeightMode} the Grid is in.
* <p>
* Defaults to {@link HeightMode#CSS}.
- *
+ *
* @return the current HeightMode
*/
public HeightMode getHeightMode() {
@@ -1865,7 +1883,7 @@ public class Grid<T> extends Composite implements
/**
* Accesses the package private method Widget#setParent()
- *
+ *
* @param widget
* The widget to access
* @param parent
@@ -1878,7 +1896,7 @@ public class Grid<T> extends Composite implements
/**
* Sets the current selection model.
- *
+ *
* @param selectionModel
* a selection model implementation.
* @throws IllegalArgumentException
@@ -1896,7 +1914,7 @@ public class Grid<T> extends Composite implements
/**
* Gets a reference to the current selection model.
- *
+ *
* @return the currently used SelectionModel instance.
*/
public SelectionModel<T> getSelectionModel() {
@@ -1907,7 +1925,7 @@ public class Grid<T> extends Composite implements
* Sets current selection mode.
* <p>
* This is a shorthand method for {@link Grid#setSelectionModel}.
- *
+ *
* @param mode
* a selection mode value
* @see {@link SelectionMode}.
@@ -1919,7 +1937,7 @@ public class Grid<T> extends Composite implements
/**
* Test if a row is selected.
- *
+ *
* @param row
* a row object
* @return true, if the current selection model considers the provided row
@@ -1935,7 +1953,7 @@ public class Grid<T> extends Composite implements
* Only selection models implementing {@link SelectionModel.Single} and
* {@link SelectionModel.Multi} are supported; for anything else, an
* exception will be thrown.
- *
+ *
* @param row
* a row object
* @return <code>true</code> iff the current selection changed
@@ -1960,7 +1978,7 @@ public class Grid<T> extends Composite implements
* Only selection models implementing {@link SelectionModel.Single} and
* {@link SelectionModel.Multi} are supported; for anything else, an
* exception will be thrown.
- *
+ *
* @param row
* a row object
* @return <code>true</code> iff the current selection changed
@@ -1985,7 +2003,7 @@ public class Grid<T> extends Composite implements
* Only selection models implementing {@link SelectionModel.Single} are
* valid for this method; for anything else, use the
* {@link Grid#getSelectedRows()} method.
- *
+ *
* @return a selected row reference, or null, if no row is selected
* @throws IllegalStateException
* if the current selection model is not an instance of
@@ -2002,7 +2020,7 @@ public class Grid<T> extends Composite implements
/**
* Gets currently selected rows from the current selection model.
- *
+ *
* @return a non-null collection containing all currently selected rows.
*/
public Collection<T> getSelectedRows() {
@@ -2015,4 +2033,91 @@ public class Grid<T> extends Composite implements
return addHandler(handler, SelectionChangeEvent.getType());
}
+ /**
+ * Sets the current sort order using the fluid Sort API. Read the
+ * documentation for {@link Sort} for more information.
+ *
+ * @param s
+ * a sort instance
+ */
+ public void sort(Sort s) {
+ setSortOrder(s.build());
+ }
+
+ /**
+ * Sorts the Grid data in ascending order along one column.
+ *
+ * @param column
+ * a grid column reference
+ */
+ public <C> void sort(GridColumn<C, T> column) {
+ sort(column, SortDirection.ASCENDING);
+ }
+
+ /**
+ * Sorts the Grid data along one column.
+ *
+ * @param column
+ * a grid column reference
+ * @param direction
+ * a sort direction value
+ */
+ public <C> void sort(GridColumn<C, T> column, SortDirection direction) {
+ sort(Sort.by(column, direction));
+ }
+
+ /**
+ * Sets the sort order to use. Setting this causes the Grid to re-sort
+ * itself.
+ *
+ * @param order
+ * a sort order list. If set to null, the sort order is cleared.
+ */
+ public void setSortOrder(List<SortOrder> order) {
+ sortOrder.clear();
+ if (order != null) {
+ sortOrder.addAll(order);
+ }
+ sort();
+ }
+
+ /**
+ * Get a copy of the current sort order array.
+ *
+ * @return a copy of the current sort order array
+ */
+ public List<SortOrder> getSortOrder() {
+ return Collections.unmodifiableList(sortOrder);
+ }
+
+ /**
+ * Register a GWT event handler for a sorting event. This handler gets
+ * called whenever this Grid needs its data source to provide data sorted in
+ * a specific order.
+ *
+ * @param handler
+ * a sort event handler
+ * @return the registration for the event
+ */
+ public HandlerRegistration addSortHandler(SortEventHandler<T> handler) {
+ return addHandler(handler, SortEvent.getType());
+ }
+
+ /**
+ * Apply sorting to data source.
+ */
+ private void sort() {
+ fireEvent(new SortEvent<T>(this,
+ Collections.unmodifiableList(sortOrder)));
+ }
+
+ /**
+ * Missing getDataSource method. TODO: remove this and other duplicates
+ * after The Merge
+ *
+ * @return a DataSource reference
+ */
+ public DataSource<T> getDataSource() {
+ return dataSource;
+ }
}
diff --git a/client/src/com/vaadin/client/ui/grid/datasources/ListDataSource.java b/client/src/com/vaadin/client/ui/grid/datasources/ListDataSource.java
index 94c32bfb33..97b358a299 100644
--- a/client/src/com/vaadin/client/ui/grid/datasources/ListDataSource.java
+++ b/client/src/com/vaadin/client/ui/grid/datasources/ListDataSource.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2014 Vaadin Ltd.
- *
+ *
* 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
@@ -18,6 +18,8 @@ package com.vaadin.client.ui.grid.datasources;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
@@ -30,23 +32,23 @@ import com.vaadin.shared.util.SharedUtil;
* A simple list based on an in-memory data source for simply adding a list of
* row pojos to the grid. Based on a wrapped list instance which supports adding
* and removing of items.
- *
+ *
* <p>
* Usage:
- *
+ *
* <pre>
* ListDataSource&lt;Integer&gt; ds = new ListDataSource&lt;Integer&gt;(1, 2, 3, 4);
- *
+ *
* // Add item to the data source
* ds.asList().add(5);
- *
+ *
* // Remove item from the data source
* ds.asList().remove(3);
- *
+ *
* // Add multiple items
* ds.asList().addAll(Arrays.asList(5, 6, 7));
* </pre>
- *
+ *
* @since 7.4
* @author Vaadin Ltd
*/
@@ -342,8 +344,8 @@ public class ListDataSource<T> implements DataSource<T> {
* data source after the data source has been constructed. To add or remove
* items to the data source after it has been constructed use
* {@link ListDataSource#asList()}.
- *
- *
+ *
+ *
* @param datasource
* The list to use for providing the data to the grid
*/
@@ -359,7 +361,7 @@ public class ListDataSource<T> implements DataSource<T> {
* Constructs a data source with a set of rows. You can dynamically add and
* remove rows from the data source via the list you get from
* {@link ListDataSource#asList()}
- *
+ *
* @param rows
* The rows to initially add to the data source
*/
@@ -401,7 +403,7 @@ public class ListDataSource<T> implements DataSource<T> {
* <p>
* Note: The list is not the same list as passed into the data source via
* the constructor.
- *
+ *
* @return Returns a list implementation that wraps the real list that backs
* the data source and provides events for the data source
* listeners.
@@ -416,4 +418,18 @@ public class ListDataSource<T> implements DataSource<T> {
+ row;
return new RowHandleImpl(row);
}
+
+ /**
+ * Sort entire container according to a {@link Comparator}.
+ *
+ * @param comparator
+ * a comparator object, which compares two data source entries
+ * (beans/pojos)
+ */
+ public void sort(Comparator<T> comparator) {
+ Collections.sort(ds, comparator);
+ if (changeHandler != null) {
+ changeHandler.dataUpdated(0, ds.size());
+ }
+ }
}
diff --git a/client/src/com/vaadin/client/ui/grid/sort/Sort.java b/client/src/com/vaadin/client/ui/grid/sort/Sort.java
new file mode 100644
index 0000000000..fdf3c64d60
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/grid/sort/Sort.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.client.ui.grid.sort;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.vaadin.client.ui.grid.GridColumn;
+import com.vaadin.shared.ui.grid.SortDirection;
+
+/**
+ * Fluid Sort descriptor object.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ * @param T
+ * grid data type
+ */
+public class Sort {
+
+ private final Sort previous;
+ private final SortOrder order;
+ private final int count;
+
+ /**
+ * Basic constructor, used by the {@link #by(GridColumn)} and
+ * {@link #by(GridColumn, SortDirection)} methods.
+ *
+ * @param column
+ * a grid column
+ * @param direction
+ * a sort direction
+ */
+ private Sort(GridColumn<?, ?> column, SortDirection direction) {
+ previous = null;
+ count = 1;
+ order = new SortOrder(column, direction);
+ }
+
+ /**
+ * Extension constructor. Performs object equality checks on all previous
+ * Sort objects in the chain to make sure that the column being passed in
+ * isn't already used earlier (which would indicate a bug). If the column
+ * has been used before, this constructor throws an
+ * {@link IllegalStateException}.
+ *
+ * @param previous
+ * the sort instance that the new sort instance is to extend
+ * @param column
+ * a (previously unused) grid column reference
+ * @param direction
+ * a sort direction
+ */
+ private Sort(Sort previous, GridColumn<?, ?> column, SortDirection direction) {
+ this.previous = previous;
+ count = previous.count + 1;
+ order = new SortOrder(column, direction);
+
+ Sort s = previous;
+ while (s != null) {
+ if (s.order.getColumn() == column) {
+ throw new IllegalStateException(
+ "Can not sort along the same column twice");
+ }
+ s = s.previous;
+ }
+ }
+
+ /**
+ * Start building a Sort order by sorting a provided column in ascending
+ * order.
+ *
+ * @param column
+ * a grid column object reference
+ * @return a sort instance, typed to the grid data type
+ */
+ public static Sort by(GridColumn<?, ?> column) {
+ return by(column, SortDirection.ASCENDING);
+ }
+
+ /**
+ * Start building a Sort order by sorting a provided column.
+ *
+ * @param column
+ * a grid column object reference
+ * @param direction
+ * indicator of sort direction - either ascending or descending
+ * @return a sort instance, typed to the grid data type
+ */
+ public static Sort by(GridColumn<?, ?> column, SortDirection direction) {
+ return new Sort(column, direction);
+ }
+
+ /**
+ * Continue building a Sort order. The provided column is sorted in
+ * ascending order if the previously added columns have been evaluated as
+ * equals.
+ *
+ * @param column
+ * a grid column object reference
+ * @return a sort instance, typed to the grid data type
+ */
+ public Sort then(GridColumn<?, ?> column) {
+ return then(column, SortDirection.ASCENDING);
+ }
+
+ /**
+ * Continue building a Sort order. The provided column is sorted in
+ * specified order if the previously added columns have been evaluated as
+ * equals.
+ *
+ * @param column
+ * a grid column object reference
+ * @param direction
+ * indicator of sort direction - either ascending or descending
+ * @return a sort instance, typed to the grid data type
+ */
+ public Sort then(GridColumn<?, ?> column, SortDirection direction) {
+ return new Sort(this, column, direction);
+ }
+
+ /**
+ * Build a sort order list. This method is called internally by Grid when
+ * calling {@link com.vaadin.client.ui.grid.Grid#sort(Sort)}, but can also
+ * be called manually to create a SortOrder list, which can also be provided
+ * directly to Grid.
+ *
+ * @return a sort order list.
+ */
+ public List<SortOrder> build() {
+
+ List<SortOrder> order = new ArrayList<SortOrder>(count);
+
+ Sort s = this;
+ for (int i = count - 1; i >= 0; --i) {
+ order.add(0, s.order);
+ s = s.previous;
+ }
+
+ return order;
+ }
+}
diff --git a/client/src/com/vaadin/client/ui/grid/sort/SortEvent.java b/client/src/com/vaadin/client/ui/grid/sort/SortEvent.java
new file mode 100644
index 0000000000..d39cdfc4f2
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/grid/sort/SortEvent.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.client.ui.grid.sort;
+
+import java.util.List;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.vaadin.client.data.DataSource;
+import com.vaadin.client.ui.grid.Grid;
+
+/**
+ * A sort event, fired by the Grid when it needs its data source to provide data
+ * sorted in a specific manner.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public class SortEvent<T> extends GwtEvent<SortEventHandler<?>> {
+
+ private static final Type<SortEventHandler<?>> TYPE = new Type<SortEventHandler<?>>();
+
+ private final Grid<T> grid;
+ private final List<SortOrder> order;
+
+ /**
+ * Creates a new Sort Event. All provided parameters are final, and passed
+ * on as-is.
+ *
+ * @param grid
+ * a grid reference
+ * @param datasource
+ * a reference to the grid's data source
+ * @param order
+ * an array dictating the desired sort order of the data source
+ */
+ public SortEvent(Grid<T> grid, List<SortOrder> order) {
+ this.grid = grid;
+ this.order = order;
+ }
+
+ @Override
+ public Type<SortEventHandler<?>> getAssociatedType() {
+ return TYPE;
+ }
+
+ /**
+ * Static access to the GWT event type identifier associated with this Event
+ * class
+ *
+ * @return a type object, uniquely describing this event type.
+ */
+ public static Type<SortEventHandler<?>> getType() {
+ return TYPE;
+ }
+
+ /**
+ * Get access to the Grid that fired this event
+ *
+ * @return the grid instance
+ */
+ @Override
+ public Grid<T> getSource() {
+ return grid;
+ }
+
+ /**
+ * Get access to the Grid that fired this event
+ *
+ * @return the grid instance
+ */
+ public Grid<T> getGrid() {
+ return grid;
+ }
+
+ /**
+ * Access the data source of the Grid that fired this event
+ *
+ * @return a data source instance
+ */
+ public DataSource<T> getDataSource() {
+ return grid.getDataSource();
+ }
+
+ /**
+ * Get the sort ordering that is to be applied to the Grid
+ *
+ * @return a list of sort order objects
+ */
+ public List<SortOrder> getOrder() {
+ return order;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void dispatch(SortEventHandler<?> handler) {
+ ((SortEventHandler<T>) handler).sort(this);
+ }
+
+}
diff --git a/client/src/com/vaadin/client/ui/grid/sort/SortEventHandler.java b/client/src/com/vaadin/client/ui/grid/sort/SortEventHandler.java
new file mode 100644
index 0000000000..8895b43631
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/grid/sort/SortEventHandler.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.client.ui.grid.sort;
+
+import com.google.gwt.event.shared.EventHandler;
+
+/**
+ * Handler for a Grid sort event, called when the Grid needs its data source to
+ * provide data sorted in a specific manner.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ */
+public interface SortEventHandler<T> extends EventHandler {
+
+ /**
+ * Handle sorting of the Grid. This method is called when a re-sorting of
+ * the Grid's data is requested.
+ *
+ * @param event
+ * the sort event
+ */
+ public void sort(SortEvent<T> event);
+
+}
diff --git a/client/src/com/vaadin/client/ui/grid/sort/SortOrder.java b/client/src/com/vaadin/client/ui/grid/sort/SortOrder.java
new file mode 100644
index 0000000000..bd76124d0c
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/grid/sort/SortOrder.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * 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 com.vaadin.client.ui.grid.sort;
+
+import com.vaadin.client.ui.grid.GridColumn;
+import com.vaadin.shared.ui.grid.SortDirection;
+
+/**
+ * Sort order descriptor. Contains column and direction references.
+ *
+ * @since 7.4
+ * @author Vaadin Ltd
+ * @param T
+ * grid data type
+ */
+public class SortOrder {
+
+ private final GridColumn<?, ?> column;
+ private final SortDirection direction;
+
+ /**
+ * Create a sort order descriptor.
+ *
+ * @param column
+ * a grid column descriptor object
+ * @param direction
+ * a sorting direction value (ascending or descending)
+ */
+ public SortOrder(GridColumn<?, ?> column, SortDirection direction) {
+ if (column == null) {
+ throw new IllegalArgumentException(
+ "Grid column reference can not be null!");
+ }
+ if (direction == null) {
+ throw new IllegalArgumentException(
+ "Direction value can not be null!");
+ }
+ this.column = column;
+ this.direction = direction;
+ }
+
+ /**
+ * Returns the {@link GridColumn} reference given in the constructor.
+ *
+ * @return a grid column reference
+ */
+ public GridColumn<?, ?> getColumn() {
+ return column;
+ }
+
+ /**
+ * Returns the {@link SortDirection} value given in the constructor.
+ *
+ * @return a sort direction value
+ */
+ public SortDirection getDirection() {
+ return direction;
+ }
+
+}
diff --git a/client/tests/src/com/vaadin/client/ui/grid/ListDataSourceTest.java b/client/tests/src/com/vaadin/client/ui/grid/ListDataSourceTest.java
index 5c5e88bf69..823eb224ea 100644
--- a/client/tests/src/com/vaadin/client/ui/grid/ListDataSourceTest.java
+++ b/client/tests/src/com/vaadin/client/ui/grid/ListDataSourceTest.java
@@ -1,12 +1,12 @@
/*
* Copyright 2000-2013 Vaadin Ltd.
- *
+ *
* 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
@@ -16,8 +16,10 @@
package com.vaadin.client.ui.grid;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import java.util.Arrays;
+import java.util.Comparator;
import org.easymock.EasyMock;
import org.junit.Test;
@@ -26,7 +28,7 @@ import com.vaadin.client.data.DataChangeHandler;
import com.vaadin.client.ui.grid.datasources.ListDataSource;
/**
- *
+ *
* @since 7.2
* @author Vaadin Ltd
*/
@@ -175,4 +177,21 @@ public class ListDataSourceTest {
ds.asList().iterator().remove();
}
+ @Test
+ public void sortColumn() {
+ ListDataSource<Integer> ds = new ListDataSource<Integer>(3, 4, 2, 3, 1);
+
+ // TODO Should be simplified to sort(). No point in providing these
+ // trivial comparators.
+ ds.sort(new Comparator<Integer>() {
+ @Override
+ public int compare(Integer o1, Integer o2) {
+ return o1.compareTo(o2);
+ }
+ });
+
+ assertTrue(Arrays.equals(ds.asList().toArray(), new Integer[] { 1, 2,
+ 3, 3, 4 }));
+ }
+
}