|
@@ -15,426 +15,480 @@ |
15 |
15 |
|
*/ |
16 |
16 |
|
package com.google.gwt.gen2.table.client; |
17 |
17 |
|
|
18 |
|
- |
import com.google.gwt.gen2.event.shared.HandlerRegistration; |
19 |
|
- |
import com.google.gwt.gen2.table.client.TableModelHelper.ColumnSortInfo; |
20 |
|
- |
import com.google.gwt.gen2.table.client.TableModelHelper.ColumnSortList; |
21 |
|
- |
import com.google.gwt.gen2.table.event.client.ColumnSortEvent; |
22 |
|
- |
import com.google.gwt.gen2.table.event.client.ColumnSortHandler; |
23 |
|
- |
import com.google.gwt.gen2.table.event.client.HasColumnSortHandlers; |
24 |
|
- |
import com.google.gwt.user.client.DOM; |
25 |
|
- |
import com.google.gwt.user.client.Element; |
26 |
|
- |
|
27 |
|
- |
import java.util.ArrayList; |
28 |
|
- |
import java.util.Collections; |
29 |
|
- |
import java.util.Comparator; |
30 |
|
- |
import java.util.List; |
31 |
|
- |
import java.util.Map; |
|
18 |
+ |
import java.util.*; |
|
19 |
+ |
|
|
20 |
+ |
import com.google.gwt.gen2.event.shared.*; |
|
21 |
+ |
import com.google.gwt.gen2.table.client.TableModelHelper.*; |
|
22 |
+ |
import com.google.gwt.gen2.table.event.client.*; |
|
23 |
+ |
import com.google.gwt.user.client.*; |
32 |
24 |
|
|
33 |
25 |
|
/** |
34 |
26 |
|
* A variation of the {@link Grid} |
35 |
27 |
|
* that supports sorting and row movement. |
36 |
28 |
|
*/ |
37 |
|
- |
public class SortableGrid extends SelectionGrid implements |
38 |
|
- |
HasColumnSortHandlers { |
39 |
|
- |
/** |
40 |
|
- |
* The column sorter defines an algorithm to sort columns. |
41 |
|
- |
*/ |
42 |
|
- |
public abstract static class ColumnSorter { |
43 |
|
- |
/** |
44 |
|
- |
* Override this method to implement a custom column sorting algorithm. |
45 |
|
- |
* |
46 |
|
- |
* @param grid the grid that the sorting will be applied to |
47 |
|
- |
* @param sortList the list of columns to sort by |
48 |
|
- |
* @param callback the callback object when sorting is complete |
49 |
|
- |
*/ |
50 |
|
- |
public abstract void onSortColumn(SortableGrid grid, |
51 |
|
- |
ColumnSortList sortList, SortableGrid.ColumnSorterCallback callback); |
52 |
|
- |
} |
53 |
|
- |
|
54 |
|
- |
/** |
55 |
|
- |
* The default {@link ColumnSorter} used if no other {@link ColumnSorter} is |
56 |
|
- |
* specified. This column sorted uses a quicksort algorithm to sort columns. |
57 |
|
- |
*/ |
58 |
|
- |
private static class DefaultColumnSorter extends ColumnSorter { |
59 |
|
- |
@Override |
60 |
|
- |
public void onSortColumn(SortableGrid grid, ColumnSortList sortList, |
61 |
|
- |
SortableGrid.ColumnSorterCallback callback) { |
62 |
|
- |
// Get the primary column and sort order |
63 |
|
- |
int column = sortList.getPrimaryColumn(); |
64 |
|
- |
boolean ascending = sortList.isPrimaryAscending(); |
65 |
|
- |
|
66 |
|
- |
// Get all of the cell elements |
67 |
|
- |
SelectionGridCellFormatter formatter = grid.getSelectionGridCellFormatter(); |
68 |
|
- |
int rowCount = grid.getRowCount(); |
69 |
|
- |
List<Element> tdElems = new ArrayList<Element>(rowCount); |
70 |
|
- |
for (int i = 0; i < rowCount; i++) { |
71 |
|
- |
tdElems.add(formatter.getRawElement(i, column)); |
72 |
|
- |
} |
73 |
|
- |
|
74 |
|
- |
// Sort the cell elements |
75 |
|
- |
if (ascending) { |
76 |
|
- |
Collections.sort(tdElems, new Comparator<Element>() { |
77 |
|
- |
@Override |
78 |
|
- |
public int compare(Element o1, Element o2) { |
79 |
|
- |
return o1.getInnerText().compareTo(o2.getInnerText()); |
80 |
|
- |
} |
81 |
|
- |
}); |
82 |
|
- |
} else { |
83 |
|
- |
Collections.sort(tdElems, new Comparator<Element>() { |
84 |
|
- |
@Override |
85 |
|
- |
public int compare(Element o1, Element o2) { |
86 |
|
- |
return o2.getInnerText().compareTo(o1.getInnerText()); |
87 |
|
- |
} |
88 |
|
- |
}); |
89 |
|
- |
} |
90 |
|
- |
|
91 |
|
- |
// Convert tdElems to trElems, reversing if needed |
92 |
|
- |
Element[] trElems = new Element[rowCount]; |
93 |
|
- |
for (int i = 0; i < rowCount; i++) { |
94 |
|
- |
trElems[i] = DOM.getParent(tdElems.get(i)); |
95 |
|
- |
} |
96 |
|
- |
|
97 |
|
- |
// Use the callback to complete the sorting |
98 |
|
- |
callback.onSortingComplete(trElems); |
99 |
|
- |
} |
100 |
|
- |
} |
101 |
|
- |
|
102 |
|
- |
/** |
103 |
|
- |
* Callback that is called when the row sorting is complete. |
104 |
|
- |
*/ |
105 |
|
- |
public class ColumnSorterCallback { |
106 |
|
- |
/** |
107 |
|
- |
* An array of the tr elements that should be reselected. |
|
29 |
+ |
public class SortableGrid extends SelectionGrid implements HasColumnSortHandlers |
|
30 |
+ |
{ |
|
31 |
+ |
/** |
|
32 |
+ |
* The column sorter defines an algorithm to sort columns. |
108 |
33 |
|
*/ |
109 |
|
- |
private Element[] selectedRows; |
|
34 |
+ |
public abstract static class ColumnSorter |
|
35 |
+ |
{ |
|
36 |
+ |
/** |
|
37 |
+ |
* Override this method to implement a custom column sorting algorithm. |
|
38 |
+ |
* |
|
39 |
+ |
* @param grid the grid that the sorting will be applied to |
|
40 |
+ |
* @param sortList the list of columns to sort by |
|
41 |
+ |
* @param callback the callback object when sorting is complete |
|
42 |
+ |
*/ |
|
43 |
+ |
public abstract void onSortColumn( SortableGrid grid, ColumnSortList sortList, SortableGrid.ColumnSorterCallback callback ); |
|
44 |
+ |
} |
110 |
45 |
|
|
111 |
46 |
|
/** |
112 |
|
- |
* Construct a new {@link ColumnSorterCallback}. |
|
47 |
+ |
* The default {@link ColumnSorter} used if no other {@link ColumnSorter} is |
|
48 |
+ |
* specified. This column sorted uses a quicksort algorithm to sort columns. |
113 |
49 |
|
*/ |
114 |
|
- |
protected ColumnSorterCallback(Element[] selectedRows) { |
115 |
|
- |
this.selectedRows = selectedRows; |
|
50 |
+ |
private static class DefaultColumnSorter extends ColumnSorter |
|
51 |
+ |
{ |
|
52 |
+ |
@Override |
|
53 |
+ |
public void onSortColumn( SortableGrid grid, ColumnSortList sortList, SortableGrid.ColumnSorterCallback callback ) |
|
54 |
+ |
{ |
|
55 |
+ |
// Get the primary column and sort order |
|
56 |
+ |
int column = sortList.getPrimaryColumn(); |
|
57 |
+ |
boolean ascending = sortList.isPrimaryAscending(); |
|
58 |
+ |
|
|
59 |
+ |
// Get all of the cell elements |
|
60 |
+ |
SelectionGridCellFormatter formatter = grid.getSelectionGridCellFormatter(); |
|
61 |
+ |
int rowCount = grid.getRowCount(); |
|
62 |
+ |
List<Element> tdElems = new ArrayList<Element>( rowCount ); |
|
63 |
+ |
for ( int i = 0; i < rowCount; i++ ) |
|
64 |
+ |
{ |
|
65 |
+ |
tdElems.add( formatter.getRawElement( i, column ) ); |
|
66 |
+ |
} |
|
67 |
+ |
|
|
68 |
+ |
// Sort the cell elements |
|
69 |
+ |
if ( ascending ) |
|
70 |
+ |
{ |
|
71 |
+ |
Collections.sort( tdElems, new Comparator<Element>() |
|
72 |
+ |
{ |
|
73 |
+ |
@Override |
|
74 |
+ |
public int compare( Element o1, Element o2 ) |
|
75 |
+ |
{ |
|
76 |
+ |
return o1.getInnerText().compareTo( o2.getInnerText() ); |
|
77 |
+ |
} |
|
78 |
+ |
} ); |
|
79 |
+ |
} |
|
80 |
+ |
else |
|
81 |
+ |
{ |
|
82 |
+ |
Collections.sort( tdElems, new Comparator<Element>() |
|
83 |
+ |
{ |
|
84 |
+ |
@Override |
|
85 |
+ |
public int compare( Element o1, Element o2 ) |
|
86 |
+ |
{ |
|
87 |
+ |
return o2.getInnerText().compareTo( o1.getInnerText() ); |
|
88 |
+ |
} |
|
89 |
+ |
} ); |
|
90 |
+ |
} |
|
91 |
+ |
|
|
92 |
+ |
// Convert tdElems to trElems, reversing if needed |
|
93 |
+ |
Element[] trElems = new Element[rowCount]; |
|
94 |
+ |
for ( int i = 0; i < rowCount; i++ ) |
|
95 |
+ |
{ |
|
96 |
+ |
trElems[i] = DOM.getParent( tdElems.get( i ) ); |
|
97 |
+ |
} |
|
98 |
+ |
|
|
99 |
+ |
// Use the callback to complete the sorting |
|
100 |
+ |
callback.onSortingComplete( trElems ); |
|
101 |
+ |
} |
116 |
102 |
|
} |
117 |
103 |
|
|
118 |
104 |
|
/** |
119 |
|
- |
* Set the order of all rows after a column sort request. |
120 |
|
- |
* |
121 |
|
- |
* This method takes an array of the row indexes in this Grid, ordered |
122 |
|
- |
* according to their new positions in the Grid. |
123 |
|
- |
* |
124 |
|
- |
* @param trIndexes the row index in their new order |
|
105 |
+ |
* Callback that is called when the row sorting is complete. |
125 |
106 |
|
*/ |
126 |
|
- |
public void onSortingComplete(int[] trIndexes) { |
127 |
|
- |
// Convert indexes to row elements |
128 |
|
- |
SelectionGridRowFormatter formatter = getSelectionGridRowFormatter(); |
129 |
|
- |
Element[] trElems = new Element[trIndexes.length]; |
130 |
|
- |
for (int i = 0; i < trElems.length; i++) { |
131 |
|
- |
trElems[i] = formatter.getRawElement(trIndexes[i]); |
132 |
|
- |
} |
|
107 |
+ |
public class ColumnSorterCallback |
|
108 |
+ |
{ |
|
109 |
+ |
/** |
|
110 |
+ |
* An array of the tr elements that should be reselected. |
|
111 |
+ |
*/ |
|
112 |
+ |
private Element[] selectedRows; |
|
113 |
+ |
|
|
114 |
+ |
/** |
|
115 |
+ |
* Construct a new {@link ColumnSorterCallback}. |
|
116 |
+ |
*/ |
|
117 |
+ |
protected ColumnSorterCallback( Element[] selectedRows ) |
|
118 |
+ |
{ |
|
119 |
+ |
this.selectedRows = selectedRows; |
|
120 |
+ |
} |
|
121 |
+ |
|
|
122 |
+ |
/** |
|
123 |
+ |
* Set the order of all rows after a column sort request. |
|
124 |
+ |
* <p/> |
|
125 |
+ |
* This method takes an array of the row indexes in this Grid, ordered |
|
126 |
+ |
* according to their new positions in the Grid. |
|
127 |
+ |
* |
|
128 |
+ |
* @param trIndexes the row index in their new order |
|
129 |
+ |
*/ |
|
130 |
+ |
public void onSortingComplete( int[] trIndexes ) |
|
131 |
+ |
{ |
|
132 |
+ |
// Convert indexes to row elements |
|
133 |
+ |
SelectionGridRowFormatter formatter = getSelectionGridRowFormatter(); |
|
134 |
+ |
Element[] trElems = new Element[trIndexes.length]; |
|
135 |
+ |
for ( int i = 0; i < trElems.length; i++ ) |
|
136 |
+ |
{ |
|
137 |
+ |
trElems[i] = formatter.getRawElement( trIndexes[i] ); |
|
138 |
+ |
} |
|
139 |
+ |
|
|
140 |
+ |
// Call main callback method |
|
141 |
+ |
onSortingComplete( trElems ); |
|
142 |
+ |
} |
|
143 |
+ |
|
|
144 |
+ |
/** |
|
145 |
+ |
* Set the order of all rows after a column sort request. |
|
146 |
+ |
* <p/> |
|
147 |
+ |
* This method takes an array of the row elements in this Grid, ordered |
|
148 |
+ |
* according to their new positions in the Grid. |
|
149 |
+ |
* |
|
150 |
+ |
* @param trElems the row elements in their new order |
|
151 |
+ |
*/ |
|
152 |
+ |
public void onSortingComplete( Element[] trElems ) |
|
153 |
+ |
{ |
|
154 |
+ |
// Move the rows to their new positions |
|
155 |
+ |
applySort( trElems ); |
|
156 |
+ |
|
|
157 |
+ |
// Fire the listeners |
|
158 |
+ |
onSortingComplete(); |
|
159 |
+ |
} |
|
160 |
+ |
|
|
161 |
+ |
/** |
|
162 |
+ |
* Trigger the callback, but do not change the ordering of the rows. |
|
163 |
+ |
* <p/> |
|
164 |
+ |
* Use this method if your {@link ColumnSorter} rearranges the columns |
|
165 |
+ |
* manually. |
|
166 |
+ |
*/ |
|
167 |
+ |
public void onSortingComplete() |
|
168 |
+ |
{ |
|
169 |
+ |
// Reselect things that need reselecting |
|
170 |
+ |
for ( int i = 0; i < selectedRows.length; i++ ) |
|
171 |
+ |
{ |
|
172 |
+ |
int rowIndex = getRowIndex( selectedRows[i] ); |
|
173 |
+ |
if ( rowIndex >= 0 ) |
|
174 |
+ |
{ |
|
175 |
+ |
selectRow( rowIndex, false ); |
|
176 |
+ |
} |
|
177 |
+ |
} |
133 |
178 |
|
|
134 |
|
- |
// Call main callback method |
135 |
|
- |
onSortingComplete(trElems); |
|
179 |
+ |
fireColumnSorted(); |
|
180 |
+ |
} |
136 |
181 |
|
} |
137 |
182 |
|
|
138 |
183 |
|
/** |
139 |
|
- |
* Set the order of all rows after a column sort request. |
140 |
|
- |
* |
141 |
|
- |
* This method takes an array of the row elements in this Grid, ordered |
142 |
|
- |
* according to their new positions in the Grid. |
143 |
|
- |
* |
144 |
|
- |
* @param trElems the row elements in their new order |
|
184 |
+ |
* The class used to do column sorting. |
145 |
185 |
|
*/ |
146 |
|
- |
public void onSortingComplete(Element[] trElems) { |
147 |
|
- |
// Move the rows to their new positions |
148 |
|
- |
applySort(trElems); |
149 |
|
- |
|
150 |
|
- |
// Fire the listeners |
151 |
|
- |
onSortingComplete(); |
|
186 |
+ |
private ColumnSorter columnSorter = null; |
|
187 |
+ |
|
|
188 |
+ |
/** |
|
189 |
+ |
* Information about the sorted columns. |
|
190 |
+ |
*/ |
|
191 |
+ |
private ColumnSortList columnSortList = new ColumnSortList(); |
|
192 |
+ |
|
|
193 |
+ |
/** |
|
194 |
+ |
* Constructor. |
|
195 |
+ |
*/ |
|
196 |
+ |
public SortableGrid() |
|
197 |
+ |
{ |
|
198 |
+ |
super(); |
152 |
199 |
|
} |
153 |
200 |
|
|
154 |
201 |
|
/** |
155 |
|
- |
* Trigger the callback, but do not change the ordering of the rows. |
156 |
|
- |
* |
157 |
|
- |
* Use this method if your {@link ColumnSorter} rearranges the columns |
158 |
|
- |
* manually. |
159 |
|
- |
*/ |
160 |
|
- |
public void onSortingComplete() { |
161 |
|
- |
// Reselect things that need reselecting |
162 |
|
- |
for (int i = 0; i < selectedRows.length; i++) { |
163 |
|
- |
int rowIndex = getRowIndex(selectedRows[i]); |
164 |
|
- |
if (rowIndex >= 0) { |
165 |
|
- |
selectRow(rowIndex, false); |
166 |
|
- |
} |
167 |
|
- |
} |
168 |
|
- |
|
169 |
|
- |
fireColumnSorted(); |
170 |
|
- |
} |
171 |
|
- |
} |
172 |
|
- |
|
173 |
|
- |
/** |
174 |
|
- |
* The class used to do column sorting. |
175 |
|
- |
*/ |
176 |
|
- |
private ColumnSorter columnSorter = null; |
177 |
|
- |
|
178 |
|
- |
/** |
179 |
|
- |
* Information about the sorted columns. |
180 |
|
- |
*/ |
181 |
|
- |
private ColumnSortList columnSortList = new ColumnSortList(); |
182 |
|
- |
|
183 |
|
- |
/** |
184 |
|
- |
* Constructor. |
185 |
|
- |
*/ |
186 |
|
- |
public SortableGrid() { |
187 |
|
- |
super(); |
188 |
|
- |
} |
189 |
|
- |
|
190 |
|
- |
/** |
191 |
|
- |
* Constructs a {@link SortableGrid} with the requested size. |
192 |
|
- |
* |
193 |
|
- |
* @param rows the number of rows |
194 |
|
- |
* @param columns the number of columns |
195 |
|
- |
* @throws IndexOutOfBoundsException |
196 |
|
- |
*/ |
197 |
|
- |
public SortableGrid(int rows, int columns) { |
198 |
|
- |
this(); |
199 |
|
- |
resize(rows, columns); |
200 |
|
- |
} |
|
202 |
+ |
* Constructs a {@link SortableGrid} with the requested size. |
|
203 |
+ |
* |
|
204 |
+ |
* @param rows the number of rows |
|
205 |
+ |
* @param columns the number of columns |
|
206 |
+ |
* |
|
207 |
+ |
* @throws IndexOutOfBoundsException |
|
208 |
+ |
*/ |
|
209 |
+ |
public SortableGrid( int rows, int columns ) |
|
210 |
+ |
{ |
|
211 |
+ |
this(); |
|
212 |
+ |
resize( rows, columns ); |
|
213 |
+ |
} |
201 |
214 |
|
|
202 |
215 |
|
@Override |
203 |
|
- |
public HandlerRegistration addColumnSortHandler(ColumnSortHandler handler) { |
204 |
|
- |
return addHandler(ColumnSortEvent.TYPE, handler); |
205 |
|
- |
} |
206 |
|
- |
|
207 |
|
- |
/** |
208 |
|
- |
* @return the column sorter used to sort columns |
209 |
|
- |
*/ |
210 |
|
- |
public ColumnSorter getColumnSorter() { |
211 |
|
- |
return getColumnSorter(false); |
212 |
|
- |
} |
213 |
|
- |
|
214 |
|
- |
/** |
215 |
|
- |
* @return the {@link ColumnSortList} of previously sorted columns |
216 |
|
- |
*/ |
217 |
|
- |
public ColumnSortList getColumnSortList() { |
218 |
|
- |
return columnSortList; |
219 |
|
- |
} |
220 |
|
- |
|
221 |
|
- |
/** |
222 |
|
- |
* Move a row up (relative to the screen) one index to a lesser index. |
223 |
|
- |
* |
224 |
|
- |
* @param row the row index to move |
225 |
|
- |
* @throws IndexOutOfBoundsException |
226 |
|
- |
*/ |
227 |
|
- |
public void moveRowDown(int row) { |
228 |
|
- |
swapRows(row, row + 1); |
229 |
|
- |
} |
230 |
|
- |
|
231 |
|
- |
/** |
232 |
|
- |
* Move a row down (relative to the screen) one index to a greater index. |
233 |
|
- |
* |
234 |
|
- |
* @param row the row index to move |
235 |
|
- |
* @throws IndexOutOfBoundsException |
236 |
|
- |
*/ |
237 |
|
- |
public void moveRowUp(int row) { |
238 |
|
- |
swapRows(row, row - 1); |
239 |
|
- |
} |
240 |
|
- |
|
241 |
|
- |
/** |
242 |
|
- |
* Completely reverse the order of all rows in the table. |
243 |
|
- |
*/ |
244 |
|
- |
public void reverseRows() { |
245 |
|
- |
int lastRow = numRows - 1; |
246 |
|
- |
for (int i = 0; i < numRows / 2; i++) { |
247 |
|
- |
swapRowsRaw(i, lastRow); |
248 |
|
- |
lastRow--; |
249 |
|
- |
} |
250 |
|
- |
|
251 |
|
- |
// Set the column sorting as reversed |
252 |
|
- |
for (ColumnSortInfo sortInfo : columnSortList) { |
253 |
|
- |
sortInfo.setAscending(!sortInfo.isAscending()); |
254 |
|
- |
} |
255 |
|
- |
fireColumnSorted(); |
256 |
|
- |
} |
257 |
|
- |
|
258 |
|
- |
/** |
259 |
|
- |
* Set the {@link ColumnSorter}. |
260 |
|
- |
* |
261 |
|
- |
* @param sorter the new {@link ColumnSorter} |
262 |
|
- |
*/ |
263 |
|
- |
public void setColumnSorter(ColumnSorter sorter) { |
264 |
|
- |
this.columnSorter = sorter; |
265 |
|
- |
} |
266 |
|
- |
|
267 |
|
- |
/** |
268 |
|
- |
* Set the current {@link ColumnSortList} and fire an event. |
269 |
|
- |
* |
270 |
|
- |
* @param columnSortList the new {@link ColumnSortList} |
271 |
|
- |
*/ |
272 |
|
- |
public void setColumnSortList(ColumnSortList columnSortList) { |
273 |
|
- |
setColumnSortList(columnSortList, true); |
274 |
|
- |
} |
275 |
|
- |
|
276 |
|
- |
/** |
277 |
|
- |
* Set the current {@link ColumnSortList} and optionally fire an event. |
278 |
|
- |
* |
279 |
|
- |
* @param columnSortList the new {@link ColumnSortList} |
280 |
|
- |
* @param fireEvents true to trigger the onSort event |
281 |
|
- |
*/ |
282 |
|
- |
public void setColumnSortList(ColumnSortList columnSortList, |
283 |
|
- |
boolean fireEvents) { |
284 |
|
- |
assert columnSortList != null : "columnSortList cannot be null"; |
285 |
|
- |
this.columnSortList = columnSortList; |
286 |
|
- |
if (fireEvents) { |
287 |
|
- |
fireColumnSorted(); |
288 |
|
- |
} |
289 |
|
- |
} |
290 |
|
- |
|
291 |
|
- |
/** |
292 |
|
- |
* Sort the grid according to the specified column. If the column is already |
293 |
|
- |
* sorted, reverse sort it. |
294 |
|
- |
* |
295 |
|
- |
* @param column the column to sort |
296 |
|
- |
* @throws IndexOutOfBoundsException |
297 |
|
- |
*/ |
298 |
|
- |
public void sortColumn(int column) { |
299 |
|
- |
if (column == columnSortList.getPrimaryColumn()) { |
300 |
|
- |
sortColumn(column, !columnSortList.isPrimaryAscending()); |
301 |
|
- |
} else { |
302 |
|
- |
sortColumn(column, true); |
303 |
|
- |
} |
304 |
|
- |
} |
305 |
|
- |
|
306 |
|
- |
/** |
307 |
|
- |
* Sort the grid according to the specified column. |
308 |
|
- |
* |
309 |
|
- |
* @param column the column to sort |
310 |
|
- |
* @param ascending sort the column in ascending order |
311 |
|
- |
* @throws IndexOutOfBoundsException |
312 |
|
- |
*/ |
313 |
|
- |
public void sortColumn(int column, boolean ascending) { |
314 |
|
- |
// Verify the column bounds |
315 |
|
- |
if (column < 0) { |
316 |
|
- |
throw new IndexOutOfBoundsException( |
317 |
|
- |
"Cannot access a column with a negative index: " + column); |
318 |
|
- |
} else if (column >= numColumns) { |
319 |
|
- |
throw new IndexOutOfBoundsException("Column index: " + column |
320 |
|
- |
+ ", Column size: " + numColumns); |
321 |
|
- |
} |
322 |
|
- |
|
323 |
|
- |
// Add the sorting to the list of sorted columns |
324 |
|
- |
columnSortList.add(new ColumnSortInfo(column, ascending)); |
325 |
|
- |
|
326 |
|
- |
// Use the onSort method to actually sort the column |
327 |
|
- |
Element[] selectedRows = getSelectedRowsMap().values().toArray( |
328 |
|
- |
new Element[0]); |
329 |
|
- |
deselectAllRows(); |
330 |
|
- |
getColumnSorter(true).onSortColumn(this, columnSortList, |
331 |
|
- |
new SortableGrid.ColumnSorterCallback(selectedRows)); |
332 |
|
- |
} |
333 |
|
- |
|
334 |
|
- |
/** |
335 |
|
- |
* Swap the positions of two rows. |
336 |
|
- |
* |
337 |
|
- |
* @param row1 the first row to swap |
338 |
|
- |
* @param row2 the second row to swap |
339 |
|
- |
* @throws IndexOutOfBoundsException |
340 |
|
- |
*/ |
341 |
|
- |
public void swapRows(int row1, int row2) { |
342 |
|
- |
checkRowBounds(row1); |
343 |
|
- |
checkRowBounds(row2); |
344 |
|
- |
swapRowsRaw(row1, row2); |
345 |
|
- |
} |
346 |
|
- |
|
347 |
|
- |
/** |
348 |
|
- |
* Fire column sorted event to listeners. |
349 |
|
- |
*/ |
350 |
|
- |
protected void fireColumnSorted() { |
351 |
|
- |
fireEvent(new ColumnSortEvent(columnSortList)); |
352 |
|
- |
} |
353 |
|
- |
|
354 |
|
- |
/** |
355 |
|
- |
* Get the {@link ColumnSorter}. Optionally create a |
356 |
|
- |
* {@link DefaultColumnSorter} if the user hasn't specified one already. |
357 |
|
- |
* |
358 |
|
- |
* @param createAsNeeded create a default sorter if needed |
359 |
|
- |
* @return the column sorter |
360 |
|
- |
*/ |
361 |
|
- |
protected ColumnSorter getColumnSorter(boolean createAsNeeded) { |
362 |
|
- |
if ((columnSorter == null) && createAsNeeded) { |
363 |
|
- |
columnSorter = new DefaultColumnSorter(); |
364 |
|
- |
} |
365 |
|
- |
return columnSorter; |
366 |
|
- |
} |
367 |
|
- |
|
368 |
|
- |
/** |
369 |
|
- |
* Swap two rows without checking the cell bounds. |
370 |
|
- |
* |
371 |
|
- |
* @param row1 the first row to swap |
372 |
|
- |
* @param row2 the second row to swap |
373 |
|
- |
*/ |
374 |
|
- |
protected void swapRowsRaw(int row1, int row2) { |
375 |
|
- |
Element tbody = getBodyElement(); |
376 |
|
- |
if (row1 == row2 + 1) { |
377 |
|
- |
// Just move row1 up one |
378 |
|
- |
Element tr = getSelectionGridRowFormatter().getRawElement(row1); |
379 |
|
- |
int index = OverrideDOM.getRowIndex(tr); |
380 |
|
- |
DOM.removeChild(tbody, tr); |
381 |
|
- |
DOM.insertChild(tbody, tr, index - 1); |
382 |
|
- |
} else if (row2 == row1 + 1) { |
383 |
|
- |
// Just move row2 up one |
384 |
|
- |
Element tr = getSelectionGridRowFormatter().getRawElement(row2); |
385 |
|
- |
int index = OverrideDOM.getRowIndex(tr); |
386 |
|
- |
DOM.removeChild(tbody, tr); |
387 |
|
- |
DOM.insertChild(tbody, tr, index - 1); |
388 |
|
- |
} else if (row1 == row2) { |
389 |
|
- |
// Do nothing if rows are the same |
390 |
|
- |
return; |
391 |
|
- |
} else { |
392 |
|
- |
// Remove both rows |
393 |
|
- |
Element tr1 = getSelectionGridRowFormatter().getRawElement(row1); |
394 |
|
- |
Element tr2 = getSelectionGridRowFormatter().getRawElement(row2); |
395 |
|
- |
int index1 = OverrideDOM.getRowIndex(tr1); |
396 |
|
- |
int index2 = OverrideDOM.getRowIndex(tr2); |
397 |
|
- |
DOM.removeChild(tbody, tr1); |
398 |
|
- |
DOM.removeChild(tbody, tr2); |
399 |
|
- |
|
400 |
|
- |
// Reinsert them into the table |
401 |
|
- |
if (row1 > row2) { |
402 |
|
- |
DOM.insertChild(tbody, tr1, index2); |
403 |
|
- |
DOM.insertChild(tbody, tr2, index1); |
404 |
|
- |
} else if (row1 < row2) { |
405 |
|
- |
DOM.insertChild(tbody, tr2, index1); |
406 |
|
- |
DOM.insertChild(tbody, tr1, index2); |
407 |
|
- |
} |
408 |
|
- |
} |
409 |
|
- |
|
410 |
|
- |
// Update the selected rows table |
411 |
|
- |
Map<Integer, Element> selectedRows = getSelectedRowsMap(); |
412 |
|
- |
Element tr1 = selectedRows.remove(new Integer(row1)); |
413 |
|
- |
Element tr2 = selectedRows.remove(new Integer(row2)); |
414 |
|
- |
if (tr1 != null) { |
415 |
|
- |
selectedRows.put(new Integer(row2), tr1); |
416 |
|
- |
} |
417 |
|
- |
if (tr2 != null) { |
418 |
|
- |
selectedRows.put(new Integer(row1), tr2); |
419 |
|
- |
} |
420 |
|
- |
} |
421 |
|
- |
|
422 |
|
- |
/** |
423 |
|
- |
* Set the order of all rows after a column sort request. |
424 |
|
- |
* |
425 |
|
- |
* This method takes an array of the row elements in this Grid, ordered |
426 |
|
- |
* according to their new positions in the Grid. |
427 |
|
- |
* |
428 |
|
- |
* @param trElems the row elements in their new order |
429 |
|
- |
*/ |
430 |
|
- |
void applySort(Element[] trElems) { |
431 |
|
- |
// Move the rows to their new positions |
432 |
|
- |
Element bodyElem = getBodyElement(); |
433 |
|
- |
for (int i = trElems.length - 1; i >= 0; i--) { |
434 |
|
- |
if (trElems[i] != null) { |
435 |
|
- |
DOM.removeChild(bodyElem, trElems[i]); |
436 |
|
- |
DOM.insertChild(bodyElem, trElems[i], 0); |
437 |
|
- |
} |
|
216 |
+ |
public HandlerRegistration addColumnSortHandler( ColumnSortHandler handler ) |
|
217 |
+ |
{ |
|
218 |
+ |
return addHandler( ColumnSortEvent.TYPE, handler ); |
|
219 |
+ |
} |
|
220 |
+ |
|
|
221 |
+ |
/** |
|
222 |
+ |
* @return the column sorter used to sort columns |
|
223 |
+ |
*/ |
|
224 |
+ |
public ColumnSorter getColumnSorter() |
|
225 |
+ |
{ |
|
226 |
+ |
return getColumnSorter( false ); |
|
227 |
+ |
} |
|
228 |
+ |
|
|
229 |
+ |
/** |
|
230 |
+ |
* @return the {@link ColumnSortList} of previously sorted columns |
|
231 |
+ |
*/ |
|
232 |
+ |
public ColumnSortList getColumnSortList() |
|
233 |
+ |
{ |
|
234 |
+ |
return columnSortList; |
|
235 |
+ |
} |
|
236 |
+ |
|
|
237 |
+ |
/** |
|
238 |
+ |
* Move a row up (relative to the screen) one index to a lesser index. |
|
239 |
+ |
* |
|
240 |
+ |
* @param row the row index to move |
|
241 |
+ |
* |
|
242 |
+ |
* @throws IndexOutOfBoundsException |
|
243 |
+ |
*/ |
|
244 |
+ |
public void moveRowDown( int row ) |
|
245 |
+ |
{ |
|
246 |
+ |
swapRows( row, row + 1 ); |
|
247 |
+ |
} |
|
248 |
+ |
|
|
249 |
+ |
/** |
|
250 |
+ |
* Move a row down (relative to the screen) one index to a greater index. |
|
251 |
+ |
* |
|
252 |
+ |
* @param row the row index to move |
|
253 |
+ |
* |
|
254 |
+ |
* @throws IndexOutOfBoundsException |
|
255 |
+ |
*/ |
|
256 |
+ |
public void moveRowUp( int row ) |
|
257 |
+ |
{ |
|
258 |
+ |
swapRows( row, row - 1 ); |
|
259 |
+ |
} |
|
260 |
+ |
|
|
261 |
+ |
/** |
|
262 |
+ |
* Completely reverse the order of all rows in the table. |
|
263 |
+ |
*/ |
|
264 |
+ |
public void reverseRows() |
|
265 |
+ |
{ |
|
266 |
+ |
int lastRow = numRows - 1; |
|
267 |
+ |
for ( int i = 0; i < numRows / 2; i++ ) |
|
268 |
+ |
{ |
|
269 |
+ |
swapRowsRaw( i, lastRow ); |
|
270 |
+ |
lastRow--; |
|
271 |
+ |
} |
|
272 |
+ |
|
|
273 |
+ |
// Set the column sorting as reversed |
|
274 |
+ |
for ( ColumnSortInfo sortInfo : columnSortList ) |
|
275 |
+ |
{ |
|
276 |
+ |
sortInfo.setAscending( !sortInfo.isAscending() ); |
|
277 |
+ |
} |
|
278 |
+ |
fireColumnSorted(); |
|
279 |
+ |
} |
|
280 |
+ |
|
|
281 |
+ |
/** |
|
282 |
+ |
* Set the {@link ColumnSorter}. |
|
283 |
+ |
* |
|
284 |
+ |
* @param sorter the new {@link ColumnSorter} |
|
285 |
+ |
*/ |
|
286 |
+ |
public void setColumnSorter( ColumnSorter sorter ) |
|
287 |
+ |
{ |
|
288 |
+ |
this.columnSorter = sorter; |
|
289 |
+ |
} |
|
290 |
+ |
|
|
291 |
+ |
/** |
|
292 |
+ |
* Set the current {@link ColumnSortList} and fire an event. |
|
293 |
+ |
* |
|
294 |
+ |
* @param columnSortList the new {@link ColumnSortList} |
|
295 |
+ |
*/ |
|
296 |
+ |
public void setColumnSortList( ColumnSortList columnSortList ) |
|
297 |
+ |
{ |
|
298 |
+ |
setColumnSortList( columnSortList, true ); |
|
299 |
+ |
} |
|
300 |
+ |
|
|
301 |
+ |
/** |
|
302 |
+ |
* Set the current {@link ColumnSortList} and optionally fire an event. |
|
303 |
+ |
* |
|
304 |
+ |
* @param columnSortList the new {@link ColumnSortList} |
|
305 |
+ |
* @param fireEvents true to trigger the onSort event |
|
306 |
+ |
*/ |
|
307 |
+ |
public void setColumnSortList( ColumnSortList columnSortList, boolean fireEvents ) |
|
308 |
+ |
{ |
|
309 |
+ |
assert columnSortList != null : "columnSortList cannot be null"; |
|
310 |
+ |
this.columnSortList = columnSortList; |
|
311 |
+ |
if ( fireEvents ) |
|
312 |
+ |
{ |
|
313 |
+ |
fireColumnSorted(); |
|
314 |
+ |
} |
|
315 |
+ |
} |
|
316 |
+ |
|
|
317 |
+ |
/** |
|
318 |
+ |
* Sort the grid according to the specified column. If the column is already |
|
319 |
+ |
* sorted, reverse sort it. |
|
320 |
+ |
* |
|
321 |
+ |
* @param column the column to sort |
|
322 |
+ |
* |
|
323 |
+ |
* @throws IndexOutOfBoundsException |
|
324 |
+ |
*/ |
|
325 |
+ |
public void sortColumn( int column ) |
|
326 |
+ |
{ |
|
327 |
+ |
if ( column == columnSortList.getPrimaryColumn() ) |
|
328 |
+ |
{ |
|
329 |
+ |
sortColumn( column, !columnSortList.isPrimaryAscending() ); |
|
330 |
+ |
} |
|
331 |
+ |
else |
|
332 |
+ |
{ |
|
333 |
+ |
sortColumn( column, true ); |
|
334 |
+ |
} |
|
335 |
+ |
} |
|
336 |
+ |
|
|
337 |
+ |
/** |
|
338 |
+ |
* Sort the grid according to the specified column. |
|
339 |
+ |
* |
|
340 |
+ |
* @param column the column to sort |
|
341 |
+ |
* @param ascending sort the column in ascending order |
|
342 |
+ |
* |
|
343 |
+ |
* @throws IndexOutOfBoundsException |
|
344 |
+ |
*/ |
|
345 |
+ |
public void sortColumn( int column, boolean ascending ) |
|
346 |
+ |
{ |
|
347 |
+ |
// Verify the column bounds |
|
348 |
+ |
if ( column < 0 ) |
|
349 |
+ |
{ |
|
350 |
+ |
throw new IndexOutOfBoundsException( "Cannot access a column with a negative index: " + column ); |
|
351 |
+ |
} |
|
352 |
+ |
else if ( column >= numColumns ) |
|
353 |
+ |
{ |
|
354 |
+ |
throw new IndexOutOfBoundsException( "Column index: " + column + ", Column size: " + numColumns ); |
|
355 |
+ |
} |
|
356 |
+ |
|
|
357 |
+ |
// Add the sorting to the list of sorted columns |
|
358 |
+ |
columnSortList.add( new ColumnSortInfo( column, ascending ) ); |
|
359 |
+ |
|
|
360 |
+ |
// Use the onSort method to actually sort the column |
|
361 |
+ |
Element[] selectedRows = getSelectedRowsMap().values().toArray( new Element[0] ); |
|
362 |
+ |
deselectAllRows(); |
|
363 |
+ |
getColumnSorter( true ).onSortColumn( this, columnSortList, new SortableGrid.ColumnSorterCallback( selectedRows ) ); |
|
364 |
+ |
} |
|
365 |
+ |
|
|
366 |
+ |
/** |
|
367 |
+ |
* Swap the positions of two rows. |
|
368 |
+ |
* |
|
369 |
+ |
* @param row1 the first row to swap |
|
370 |
+ |
* @param row2 the second row to swap |
|
371 |
+ |
* |
|
372 |
+ |
* @throws IndexOutOfBoundsException |
|
373 |
+ |
*/ |
|
374 |
+ |
public void swapRows( int row1, int row2 ) |
|
375 |
+ |
{ |
|
376 |
+ |
checkRowBounds( row1 ); |
|
377 |
+ |
checkRowBounds( row2 ); |
|
378 |
+ |
swapRowsRaw( row1, row2 ); |
|
379 |
+ |
} |
|
380 |
+ |
|
|
381 |
+ |
/** |
|
382 |
+ |
* Fire column sorted event to listeners. |
|
383 |
+ |
*/ |
|
384 |
+ |
protected void fireColumnSorted() |
|
385 |
+ |
{ |
|
386 |
+ |
fireEvent( new ColumnSortEvent( columnSortList ) ); |
|
387 |
+ |
} |
|
388 |
+ |
|
|
389 |
+ |
/** |
|
390 |
+ |
* Get the {@link ColumnSorter}. Optionally create a |
|
391 |
+ |
* {@link DefaultColumnSorter} if the user hasn't specified one already. |
|
392 |
+ |
* |
|
393 |
+ |
* @param createAsNeeded create a default sorter if needed |
|
394 |
+ |
* |
|
395 |
+ |
* @return the column sorter |
|
396 |
+ |
*/ |
|
397 |
+ |
protected ColumnSorter getColumnSorter( boolean createAsNeeded ) |
|
398 |
+ |
{ |
|
399 |
+ |
if ( (columnSorter == null) && createAsNeeded ) |
|
400 |
+ |
{ |
|
401 |
+ |
columnSorter = new DefaultColumnSorter(); |
|
402 |
+ |
} |
|
403 |
+ |
return columnSorter; |
|
404 |
+ |
} |
|
405 |
+ |
|
|
406 |
+ |
/** |
|
407 |
+ |
* Swap two rows without checking the cell bounds. |
|
408 |
+ |
* |
|
409 |
+ |
* @param row1 the first row to swap |
|
410 |
+ |
* @param row2 the second row to swap |
|
411 |
+ |
*/ |
|
412 |
+ |
protected void swapRowsRaw( int row1, int row2 ) |
|
413 |
+ |
{ |
|
414 |
+ |
Element tbody = getBodyElement(); |
|
415 |
+ |
if ( row1 == row2 + 1 ) |
|
416 |
+ |
{ |
|
417 |
+ |
// Just move row1 up one |
|
418 |
+ |
Element tr = getSelectionGridRowFormatter().getRawElement( row1 ); |
|
419 |
+ |
int index = OverrideDOM.getRowIndex( tr ); |
|
420 |
+ |
DOM.removeChild( tbody, tr ); |
|
421 |
+ |
DOM.insertChild( tbody, tr, index - 1 ); |
|
422 |
+ |
} |
|
423 |
+ |
else if ( row2 == row1 + 1 ) |
|
424 |
+ |
{ |
|
425 |
+ |
// Just move row2 up one |
|
426 |
+ |
Element tr = getSelectionGridRowFormatter().getRawElement( row2 ); |
|
427 |
+ |
int index = OverrideDOM.getRowIndex( tr ); |
|
428 |
+ |
DOM.removeChild( tbody, tr ); |
|
429 |
+ |
DOM.insertChild( tbody, tr, index - 1 ); |
|
430 |
+ |
} |
|
431 |
+ |
else if ( row1 == row2 ) |
|
432 |
+ |
{ |
|
433 |
+ |
// Do nothing if rows are the same |
|
434 |
+ |
return; |
|
435 |
+ |
} |
|
436 |
+ |
else |
|
437 |
+ |
{ |
|
438 |
+ |
// Remove both rows |
|
439 |
+ |
Element tr1 = getSelectionGridRowFormatter().getRawElement( row1 ); |
|
440 |
+ |
Element tr2 = getSelectionGridRowFormatter().getRawElement( row2 ); |
|
441 |
+ |
int index1 = OverrideDOM.getRowIndex( tr1 ); |
|
442 |
+ |
int index2 = OverrideDOM.getRowIndex( tr2 ); |
|
443 |
+ |
DOM.removeChild( tbody, tr1 ); |
|
444 |
+ |
DOM.removeChild( tbody, tr2 ); |
|
445 |
+ |
|
|
446 |
+ |
// Reinsert them into the table |
|
447 |
+ |
if ( row1 > row2 ) |
|
448 |
+ |
{ |
|
449 |
+ |
DOM.insertChild( tbody, tr1, index2 ); |
|
450 |
+ |
DOM.insertChild( tbody, tr2, index1 ); |
|
451 |
+ |
} |
|
452 |
+ |
else if ( row1 < row2 ) |
|
453 |
+ |
{ |
|
454 |
+ |
DOM.insertChild( tbody, tr2, index1 ); |
|
455 |
+ |
DOM.insertChild( tbody, tr1, index2 ); |
|
456 |
+ |
} |
|
457 |
+ |
} |
|
458 |
+ |
|
|
459 |
+ |
// Update the selected rows table |
|
460 |
+ |
Map<Integer, Element> selectedRows = getSelectedRowsMap(); |
|
461 |
+ |
Element tr1 = selectedRows.remove( new Integer( row1 ) ); |
|
462 |
+ |
Element tr2 = selectedRows.remove( new Integer( row2 ) ); |
|
463 |
+ |
if ( tr1 != null ) |
|
464 |
+ |
{ |
|
465 |
+ |
selectedRows.put( new Integer( row2 ), tr1 ); |
|
466 |
+ |
} |
|
467 |
+ |
if ( tr2 != null ) |
|
468 |
+ |
{ |
|
469 |
+ |
selectedRows.put( new Integer( row1 ), tr2 ); |
|
470 |
+ |
} |
|
471 |
+ |
} |
|
472 |
+ |
|
|
473 |
+ |
/** |
|
474 |
+ |
* Set the order of all rows after a column sort request. |
|
475 |
+ |
* <p/> |
|
476 |
+ |
* This method takes an array of the row elements in this Grid, ordered |
|
477 |
+ |
* according to their new positions in the Grid. |
|
478 |
+ |
* |
|
479 |
+ |
* @param trElems the row elements in their new order |
|
480 |
+ |
*/ |
|
481 |
+ |
void applySort( Element[] trElems ) |
|
482 |
+ |
{ |
|
483 |
+ |
// Move the rows to their new positions |
|
484 |
+ |
Element bodyElem = getBodyElement(); |
|
485 |
+ |
for ( int i = trElems.length - 1; i >= 0; i-- ) |
|
486 |
+ |
{ |
|
487 |
+ |
if ( trElems[i] != null ) |
|
488 |
+ |
{ |
|
489 |
+ |
DOM.removeChild( bodyElem, trElems[i] ); |
|
490 |
+ |
DOM.insertChild( bodyElem, trElems[i], 0 ); |
|
491 |
+ |
} |
|
492 |
+ |
} |
438 |
493 |
|
} |
439 |
|
- |
} |
440 |
494 |
|
} |