Subversion Repository Public Repository

litesoft

Diff Revisions 282 vs 475 for /trunk/Java/GWT/Client/src/com/google/gwt/gen2/table/client/SortableGrid.java

Diff revisions: vs.
  @@ -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 }