Subversion Repository Public Repository

litesoft

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

Diff revisions: vs.
  @@ -15,815 +15,899 @@
15 15 */
16 16 package com.google.gwt.gen2.table.client;
17 17
18 - import com.google.gwt.dom.client.InputElement;
19 - import com.google.gwt.gen2.event.shared.HandlerRegistration;
20 - import com.google.gwt.gen2.table.event.client.CellHighlightEvent;
21 - import com.google.gwt.gen2.table.event.client.CellHighlightHandler;
22 - import com.google.gwt.gen2.table.event.client.CellUnhighlightEvent;
23 - import com.google.gwt.gen2.table.event.client.CellUnhighlightHandler;
24 - import com.google.gwt.gen2.table.event.client.HasCellHighlightHandlers;
25 - import com.google.gwt.gen2.table.event.client.HasCellUnhighlightHandlers;
26 - import com.google.gwt.gen2.table.event.client.HasRowHighlightHandlers;
27 - import com.google.gwt.gen2.table.event.client.HasRowSelectionHandlers;
28 - import com.google.gwt.gen2.table.event.client.HasRowUnhighlightHandlers;
29 - import com.google.gwt.gen2.table.event.client.RowHighlightEvent;
30 - import com.google.gwt.gen2.table.event.client.RowHighlightHandler;
31 - import com.google.gwt.gen2.table.event.client.RowSelectionEvent;
32 - import com.google.gwt.gen2.table.event.client.RowSelectionHandler;
33 - import com.google.gwt.gen2.table.event.client.RowUnhighlightEvent;
34 - import com.google.gwt.gen2.table.event.client.RowUnhighlightHandler;
35 - import com.google.gwt.gen2.table.event.client.TableEvent.Row;
36 - import com.google.gwt.user.client.DOM;
37 - import com.google.gwt.user.client.Element;
38 - import com.google.gwt.user.client.Event;
39 - import com.google.gwt.user.client.Window;
18 + import java.util.*;
40 19
41 - import java.util.HashMap;
42 - import java.util.Map;
43 - import java.util.Set;
44 - import java.util.TreeSet;
20 + import com.google.gwt.dom.client.*;
21 + import com.google.gwt.gen2.event.shared.*;
22 + import com.google.gwt.gen2.table.event.client.*;
23 + import com.google.gwt.gen2.table.event.client.TableEvent.*;
24 + import com.google.gwt.user.client.*;
25 + import com.google.gwt.user.client.Element;
45 26
46 27 /**
47 28 * A variation of the {@link Grid} that supports row or cell highlight and row
48 29 * selection.
49 - *
30 + * <p/>
50 31 * <h3>CSS Style Rules</h3>
51 - *
32 + * <p/>
52 33 * <ul class="css">
53 - *
34 + * <p/>
54 35 * <li>tr.selected { applied to selected rows }</li>
55 - *
36 + * <p/>
56 37 * <li>tr.highlighted { applied to row currently being highlighted }</li>
57 - *
38 + * <p/>
58 39 * <li>td.highlighted { applied to cell currently being highlighted }</li>
59 - *
40 + * <p/>
60 41 * </ul>
61 42 */
62 43 public class SelectionGrid extends Grid implements HasRowHighlightHandlers,
63 - HasRowUnhighlightHandlers, HasCellHighlightHandlers,
64 - HasCellUnhighlightHandlers, HasRowSelectionHandlers {
65 - /**
66 - * This class contains methods used to format a table's cells.
67 - */
68 - public class SelectionGridCellFormatter extends CellFormatter {
69 - @Override
70 - protected Element getRawElement(int row, int column) {
71 - if (selectionPolicy.hasInputColumn()) {
72 - column += 1;
73 - }
74 - return super.getRawElement(row, column);
75 - }
76 - }
77 -
78 - /**
79 - * This class contains methods used to format a table's rows.
80 - */
81 - public class SelectionGridRowFormatter extends RowFormatter {
82 - @Override
83 - protected Element getRawElement(int row) {
84 - return super.getRawElement(row);
85 - }
86 - }
87 -
88 - /**
89 - * Selection policies.
90 - *
91 - * <ul>
92 - * <li>ONE_ROW - one row can be selected at a time</li>
93 - * <li>MULTI_ROW - multiple rows can be selected at a time</li>
94 - * <li>CHECKBOX - multiple rows can be selected using checkboxes</li>
95 - * <li>RADIO - one row can be selected using radio buttons</li>
96 - * </ul>
97 - */
98 - public static enum SelectionPolicy {
99 - ONE_ROW(null), MULTI_ROW(null), CHECKBOX("<input type='checkbox'/>"), RADIO(
100 - "<input name='%NAME%' type='radio'/>");
101 -
102 - private String inputHtml;
103 -
104 - private SelectionPolicy(String inputHtml) {
105 - this.inputHtml = inputHtml;
106 - }
107 -
108 - /**
109 - * @return true if the policy requires a selection column
110 - */
111 - public boolean hasInputColumn() {
112 - return inputHtml != null;
113 - }
114 -
115 - /**
116 - * @return the HTML string used for this policy
117 - */
118 - private String getInputHtml() {
119 - return inputHtml;
120 - }
121 - }
122 -
123 - /**
124 - * Unique IDs assigned to the grids.
125 - */
126 - private static int uniqueID = 0;
127 -
128 - /**
129 - * The cell element currently being highlight.
130 - */
131 - private Element highlightedCellElem = null;
132 -
133 - /**
134 - * The index of the cell currently being highlight.
135 - */
136 - private int highlightedCellIndex = -1;
137 -
138 - /**
139 - * The row element currently being highlight.
140 - */
141 - private Element highlightedRowElem = null;
142 -
143 - /**
144 - * The index of the row currently being highlight.
145 - */
146 - private int highlightedRowIndex = -1;
147 -
148 - /**
149 - * Unique ID of this grid.
150 - */
151 - private int id;
152 -
153 - /**
154 - * The index of the row that the user selected last.
155 - */
156 - private int lastSelectedRowIndex = -1;
157 -
158 - /**
159 - * The rows that are currently selected.
160 - */
161 - private Map<Integer, Element> selectedRows = new HashMap<Integer, Element>();
162 -
163 - /**
164 - * A boolean indicating if selection is enabled disabled.
165 - */
166 - private boolean selectionEnabled = true;
167 -
168 - /**
169 - * The selection policy determines if the user can select zero, one, or many
170 - * rows.
171 - */
172 - private SelectionPolicy selectionPolicy = SelectionPolicy.MULTI_ROW;
173 -
174 - /**
175 - * Construct a new {@link SelectionGrid}.
176 - */
177 - public SelectionGrid() {
178 - super();
179 - id = uniqueID++;
180 - setCellFormatter(new SelectionGridCellFormatter());
181 - setRowFormatter(new SelectionGridRowFormatter());
182 -
183 - // Sink highlight and selection events
184 - sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT | Event.ONMOUSEDOWN
185 - | Event.ONCLICK);
186 - }
187 -
188 - /**
189 - * Constructs a {@link SelectionGrid} with the requested size.
190 - *
191 - * @param rows the number of rows
192 - * @param columns the number of columns
193 - * @throws IndexOutOfBoundsException
194 - */
195 - public SelectionGrid(int rows, int columns) {
196 - this();
197 - resize(rows, columns);
198 - }
199 -
200 - @Override
201 - public HandlerRegistration addCellHighlightHandler(
202 - CellHighlightHandler handler) {
203 - return addHandler(CellHighlightEvent.TYPE, handler);
204 - }
205 -
206 - @Override
207 - public HandlerRegistration addCellUnhighlightHandler(
208 - CellUnhighlightHandler handler) {
209 - return addHandler(CellUnhighlightEvent.TYPE, handler);
210 - }
211 -
212 - @Override
213 - public HandlerRegistration addRowHighlightHandler(RowHighlightHandler handler) {
214 - return addHandler(RowHighlightEvent.TYPE, handler);
215 - }
216 -
217 - @Override
218 - public HandlerRegistration addRowSelectionHandler(RowSelectionHandler handler) {
219 - return addHandler(RowSelectionEvent.TYPE, handler);
220 - }
221 -
222 - @Override
223 - public HandlerRegistration addRowUnhighlightHandler(
224 - RowUnhighlightHandler handler) {
225 - return addHandler(RowUnhighlightEvent.TYPE, handler);
226 - }
227 -
228 - /**
229 - * Deselect all selected rows in the data table.
230 - */
231 - public void deselectAllRows() {
232 - deselectAllRows(true);
233 - }
234 -
235 - /**
236 - * Deselect a row in the grid. This method is safe to call even if the row is
237 - * not selected, or doesn't exist (out of bounds).
238 - *
239 - * @param row the row index
240 - */
241 - public void deselectRow(int row) {
242 - deselectRow(row, true);
243 - }
244 -
245 - /**
246 - * @return the set of selected row indexes
247 - */
248 - public Set<Integer> getSelectedRows() {
249 - return selectedRows.keySet();
250 - }
251 -
252 - /**
253 - * Explicitly gets the {@link SelectionGridCellFormatter}. The results of
254 - * {@link HTMLTable#getCellFormatter()}
255 - * may also be downcast to a {@link SelectionGridCellFormatter}.
256 - *
257 - * @return the FlexTable's cell formatter
258 - */
259 - public SelectionGridCellFormatter getSelectionGridCellFormatter() {
260 - return (SelectionGridCellFormatter) getCellFormatter();
261 - }
262 -
263 - /**
264 - * Explicitly gets the {@link SelectionGridRowFormatter}. The results of
265 - * {@link HTMLTable#getRowFormatter()}
266 - * may also be downcast to a {@link SelectionGridRowFormatter}.
267 - *
268 - * @return the FlexTable's cell formatter
269 - */
270 - public SelectionGridRowFormatter getSelectionGridRowFormatter() {
271 - return (SelectionGridRowFormatter) getRowFormatter();
272 - }
273 -
274 - /**
275 - * @return the selection policy
276 - */
277 - public SelectionPolicy getSelectionPolicy() {
278 - return selectionPolicy;
279 - }
280 -
281 - @Override
282 - public int insertRow(int beforeRow) {
283 - deselectAllRows();
284 - return super.insertRow(beforeRow);
285 - }
286 -
287 - /**
288 - * @param row the row index
289 - * @return true if the row is selected, false if not
290 - */
291 - public boolean isRowSelected(int row) {
292 - return selectedRows.containsKey(new Integer(row));
293 - }
294 -
295 - /**
296 - * @return true if selection is enabled
297 - */
298 - public boolean isSelectionEnabled() {
299 - return selectionEnabled;
300 - }
301 -
302 - @Override
303 - public void onBrowserEvent(Event event) {
304 - super.onBrowserEvent(event);
305 - Element targetRow = null;
306 - Element targetCell = null;
307 -
308 - switch (DOM.eventGetType(event)) {
309 - // Highlight the cell on mouse over
310 - case Event.ONMOUSEOVER:
311 - Element cellElem = getEventTargetCell(event);
312 - if (cellElem != null) {
313 - highlightCell(cellElem);
314 - }
315 - break;
316 -
317 - // Unhighlight on mouse out
318 - case Event.ONMOUSEOUT:
319 - Element toElem = DOM.eventGetToElement(event);
320 - if (highlightedRowElem != null
321 - && (toElem == null || !highlightedRowElem.isOrHasChild(toElem))) {
322 - // Check that the coordinates are not directly over the cell
323 - int clientX = event.getClientX() + Window.getScrollLeft();
324 - int clientY = event.getClientY() + Window.getScrollTop();
325 - int rowLeft = highlightedRowElem.getAbsoluteLeft();
326 - int rowTop = highlightedRowElem.getAbsoluteTop();
327 - int rowWidth = highlightedRowElem.getOffsetWidth();
328 - int rowHeight = highlightedRowElem.getOffsetHeight();
329 - int rowBottom = rowTop + rowHeight;
330 - int rowRight = rowLeft + rowWidth;
331 - if (clientX > rowLeft && clientX < rowRight && clientY > rowTop
332 - && clientY < rowBottom) {
44 + HasRowUnhighlightHandlers,
45 + HasCellHighlightHandlers,
46 + HasCellUnhighlightHandlers,
47 + HasRowSelectionHandlers
48 + {
49 + /**
50 + * This class contains methods used to format a table's cells.
51 + */
52 + public class SelectionGridCellFormatter extends CellFormatter
53 + {
54 + @Override
55 + protected Element getRawElement( int row, int column )
56 + {
57 + if ( selectionPolicy.hasInputColumn() )
58 + {
59 + column += 1;
60 + }
61 + return super.getRawElement( row, column );
62 + }
63 + }
64 +
65 + /**
66 + * This class contains methods used to format a table's rows.
67 + */
68 + public class SelectionGridRowFormatter extends RowFormatter
69 + {
70 + @Override
71 + protected Element getRawElement( int row )
72 + {
73 + return super.getRawElement( row );
74 + }
75 + }
76 +
77 + /**
78 + * Selection policies.
79 + * <p/>
80 + * <ul>
81 + * <li>ONE_ROW - one row can be selected at a time</li>
82 + * <li>MULTI_ROW - multiple rows can be selected at a time</li>
83 + * <li>CHECKBOX - multiple rows can be selected using checkboxes</li>
84 + * <li>RADIO - one row can be selected using radio buttons</li>
85 + * </ul>
86 + */
87 + public static enum SelectionPolicy
88 + {
89 + ONE_ROW( null ), MULTI_ROW( null ), CHECKBOX( "<input type='checkbox'/>" ), RADIO( "<input name='%NAME%' type='radio'/>" );
90 +
91 + private String inputHtml;
92 +
93 + private SelectionPolicy( String inputHtml )
94 + {
95 + this.inputHtml = inputHtml;
96 + }
97 +
98 + /**
99 + * @return true if the policy requires a selection column
100 + */
101 + public boolean hasInputColumn()
102 + {
103 + return inputHtml != null;
104 + }
105 +
106 + /**
107 + * @return the HTML string used for this policy
108 + */
109 + private String getInputHtml()
110 + {
111 + return inputHtml;
112 + }
113 + }
114 +
115 + /**
116 + * Unique IDs assigned to the grids.
117 + */
118 + private static int uniqueID = 0;
119 +
120 + /**
121 + * The cell element currently being highlight.
122 + */
123 + private Element highlightedCellElem = null;
124 +
125 + /**
126 + * The index of the cell currently being highlight.
127 + */
128 + private int highlightedCellIndex = -1;
129 +
130 + /**
131 + * The row element currently being highlight.
132 + */
133 + private Element highlightedRowElem = null;
134 +
135 + /**
136 + * The index of the row currently being highlight.
137 + */
138 + private int highlightedRowIndex = -1;
139 +
140 + /**
141 + * Unique ID of this grid.
142 + */
143 + private int id;
144 +
145 + /**
146 + * The index of the row that the user selected last.
147 + */
148 + private int lastSelectedRowIndex = -1;
149 +
150 + /**
151 + * The rows that are currently selected.
152 + */
153 + private Map<Integer, Element> selectedRows = new HashMap<Integer, Element>();
154 +
155 + /**
156 + * A boolean indicating if selection is enabled disabled.
157 + */
158 + private boolean selectionEnabled = true;
159 +
160 + /**
161 + * The selection policy determines if the user can select zero, one, or many
162 + * rows.
163 + */
164 + private SelectionPolicy selectionPolicy = SelectionPolicy.MULTI_ROW;
165 +
166 + /**
167 + * Construct a new {@link SelectionGrid}.
168 + */
169 + public SelectionGrid()
170 + {
171 + super();
172 + id = uniqueID++;
173 + setCellFormatter( new SelectionGridCellFormatter() );
174 + setRowFormatter( new SelectionGridRowFormatter() );
175 +
176 + // Sink highlight and selection events
177 + sinkEvents( Event.ONMOUSEOVER | Event.ONMOUSEOUT | Event.ONMOUSEDOWN | Event.ONCLICK );
178 + }
179 +
180 + /**
181 + * Constructs a {@link SelectionGrid} with the requested size.
182 + *
183 + * @param rows the number of rows
184 + * @param columns the number of columns
185 + *
186 + * @throws IndexOutOfBoundsException
187 + */
188 + public SelectionGrid( int rows, int columns )
189 + {
190 + this();
191 + resize( rows, columns );
192 + }
193 +
194 + @Override
195 + public HandlerRegistration addCellHighlightHandler( CellHighlightHandler handler )
196 + {
197 + return addHandler( CellHighlightEvent.TYPE, handler );
198 + }
199 +
200 + @Override
201 + public HandlerRegistration addCellUnhighlightHandler( CellUnhighlightHandler handler )
202 + {
203 + return addHandler( CellUnhighlightEvent.TYPE, handler );
204 + }
205 +
206 + @Override
207 + public HandlerRegistration addRowHighlightHandler( RowHighlightHandler handler )
208 + {
209 + return addHandler( RowHighlightEvent.TYPE, handler );
210 + }
211 +
212 + @Override
213 + public HandlerRegistration addRowSelectionHandler( RowSelectionHandler handler )
214 + {
215 + return addHandler( RowSelectionEvent.TYPE, handler );
216 + }
217 +
218 + @Override
219 + public HandlerRegistration addRowUnhighlightHandler( RowUnhighlightHandler handler )
220 + {
221 + return addHandler( RowUnhighlightEvent.TYPE, handler );
222 + }
223 +
224 + /**
225 + * Deselect all selected rows in the data table.
226 + */
227 + public void deselectAllRows()
228 + {
229 + deselectAllRows( true );
230 + }
231 +
232 + /**
233 + * Deselect a row in the grid. This method is safe to call even if the row is
234 + * not selected, or doesn't exist (out of bounds).
235 + *
236 + * @param row the row index
237 + */
238 + public void deselectRow( int row )
239 + {
240 + deselectRow( row, true );
241 + }
242 +
243 + /**
244 + * @return the set of selected row indexes
245 + */
246 + public Set<Integer> getSelectedRows()
247 + {
248 + return selectedRows.keySet();
249 + }
250 +
251 + /**
252 + * Explicitly gets the {@link SelectionGridCellFormatter}. The results of
253 + * {@link HTMLTable#getCellFormatter()}
254 + * may also be downcast to a {@link SelectionGridCellFormatter}.
255 + *
256 + * @return the FlexTable's cell formatter
257 + */
258 + public SelectionGridCellFormatter getSelectionGridCellFormatter()
259 + {
260 + return (SelectionGridCellFormatter) getCellFormatter();
261 + }
262 +
263 + /**
264 + * Explicitly gets the {@link SelectionGridRowFormatter}. The results of
265 + * {@link HTMLTable#getRowFormatter()}
266 + * may also be downcast to a {@link SelectionGridRowFormatter}.
267 + *
268 + * @return the FlexTable's cell formatter
269 + */
270 + public SelectionGridRowFormatter getSelectionGridRowFormatter()
271 + {
272 + return (SelectionGridRowFormatter) getRowFormatter();
273 + }
274 +
275 + /**
276 + * @return the selection policy
277 + */
278 + public SelectionPolicy getSelectionPolicy()
279 + {
280 + return selectionPolicy;
281 + }
282 +
283 + @Override
284 + public int insertRow( int beforeRow )
285 + {
286 + deselectAllRows();
287 + return super.insertRow( beforeRow );
288 + }
289 +
290 + /**
291 + * @param row the row index
292 + *
293 + * @return true if the row is selected, false if not
294 + */
295 + public boolean isRowSelected( int row )
296 + {
297 + return selectedRows.containsKey( new Integer( row ) );
298 + }
299 +
300 + /**
301 + * @return true if selection is enabled
302 + */
303 + public boolean isSelectionEnabled()
304 + {
305 + return selectionEnabled;
306 + }
307 +
308 + @Override
309 + public void onBrowserEvent( Event event )
310 + {
311 + super.onBrowserEvent( event );
312 + Element targetRow = null;
313 + Element targetCell = null;
314 +
315 + switch ( DOM.eventGetType( event ) )
316 + {
317 + // Highlight the cell on mouse over
318 + case Event.ONMOUSEOVER:
319 + Element cellElem = getEventTargetCell( event );
320 + if ( cellElem != null )
321 + {
322 + highlightCell( cellElem );
323 + }
324 + break;
325 +
326 + // Unhighlight on mouse out
327 + case Event.ONMOUSEOUT:
328 + Element toElem = DOM.eventGetToElement( event );
329 + if ( highlightedRowElem != null && (toElem == null || !highlightedRowElem.isOrHasChild( toElem )) )
330 + {
331 + // Check that the coordinates are not directly over the cell
332 + int clientX = event.getClientX() + Window.getScrollLeft();
333 + int clientY = event.getClientY() + Window.getScrollTop();
334 + int rowLeft = highlightedRowElem.getAbsoluteLeft();
335 + int rowTop = highlightedRowElem.getAbsoluteTop();
336 + int rowWidth = highlightedRowElem.getOffsetWidth();
337 + int rowHeight = highlightedRowElem.getOffsetHeight();
338 + int rowBottom = rowTop + rowHeight;
339 + int rowRight = rowLeft + rowWidth;
340 + if ( clientX > rowLeft && clientX < rowRight && clientY > rowTop && clientY < rowBottom )
341 + {
342 + return;
343 + }
344 +
345 + // Unhighlight the current cell
346 + highlightCell( null );
347 + }
348 + break;
349 +
350 + // Select a row on click
351 + case Event.ONMOUSEDOWN:
352 + {
353 + // Ignore if selection is disabled
354 + if ( !selectionEnabled )
355 + {
356 + return;
357 + }
358 +
359 + // Get the target row
360 + targetCell = getEventTargetCell( event );
361 + if ( targetCell == null )
362 + {
363 + return;
364 + }
365 + targetRow = DOM.getParent( targetCell );
366 + int targetRowIndex = getRowIndex( targetRow );
367 +
368 + // Select the row
369 + if ( selectionPolicy == SelectionPolicy.MULTI_ROW )
370 + {
371 + boolean shiftKey = DOM.eventGetShiftKey( event );
372 + boolean ctrlKey = DOM.eventGetCtrlKey( event ) || DOM.eventGetMetaKey( event );
373 +
374 + // Prevent default text selection
375 + if ( ctrlKey || shiftKey )
376 + {
377 + event.preventDefault();
378 + }
379 +
380 + // Select the rows
381 + selectRow( targetRowIndex, ctrlKey, shiftKey );
382 + }
383 + else if ( selectionPolicy == SelectionPolicy.ONE_ROW || (selectionPolicy == SelectionPolicy.RADIO && targetCell == targetRow.getFirstChild()) )
384 + {
385 + selectRow( -1, targetRow, true, true );
386 + lastSelectedRowIndex = targetRowIndex;
387 + }
388 + }
389 + break;
390 +
391 + // Prevent native inputs from being checked
392 + case Event.ONCLICK:
393 + {
394 + // Ignore if selection is disabled
395 + if ( !selectionEnabled )
396 + {
397 + return;
398 + }
399 +
400 + // Get the target row
401 + targetCell = getEventTargetCell( event );
402 + if ( targetCell == null )
403 + {
404 + return;
405 + }
406 + targetRow = DOM.getParent( targetCell );
407 + int targetRowIndex = getRowIndex( targetRow );
408 +
409 + // Select the row
410 + if ( selectionPolicy == SelectionPolicy.CHECKBOX && targetCell == targetRow.getFirstChild() )
411 + {
412 + selectRow( targetRowIndex, true, DOM.eventGetShiftKey( event ) );
413 + }
414 + }
415 + break;
416 + }
417 + }
418 +
419 + @Override
420 + public void removeRow( int row )
421 + {
422 + deselectAllRows();
423 + super.removeRow( row );
424 + }
425 +
426 + /**
427 + * Select all rows in the table.
428 + */
429 + public void selectAllRows()
430 + {
431 + // Get the currently selected rows
432 + Set<Row> oldRowSet = getSelectedRowsSet();
433 +
434 + // Select all rows
435 + RowFormatter rowFormatter = getRowFormatter();
436 + int rowCount = getRowCount();
437 + for ( int i = 0; i < rowCount; i++ )
438 + {
439 + if ( !selectedRows.containsKey( i ) )
440 + {
441 + selectRow( i, rowFormatter.getElement( i ), false, false );
442 + }
443 + }
444 +
445 + // Trigger the event
446 + fireRowSelectionEvent( oldRowSet );
447 + }
448 +
449 + /**
450 + * Select a row in the data table.
451 + *
452 + * @param row the row index
453 + * @param unselectAll unselect all other rows first
454 + *
455 + * @throws IndexOutOfBoundsException
456 + */
457 + public void selectRow( int row, boolean unselectAll )
458 + {
459 + selectRow( row, getRowFormatter().getElement( row ), unselectAll, true );
460 + }
461 +
462 + /**
463 + * Select a row in the data table. Simulate the effect of a shift click and/or
464 + * control click. This method ignores the selection policy, which only applies
465 + * to user selection via mouse events.
466 + *
467 + * @param row the row index
468 + * @param ctrlKey true to simulate a control click
469 + * @param shiftKey true to simulate a shift selection
470 + *
471 + * @throws IndexOutOfBoundsException
472 + */
473 + public void selectRow( int row, boolean ctrlKey, boolean shiftKey )
474 + {
475 + // Check the row bounds
476 + checkRowBounds( row );
477 +
478 + // Get the old list of selected rows
479 + Set<Row> oldRowList = getSelectedRowsSet();
480 +
481 + // Deselect all rows
482 + if ( !ctrlKey )
483 + {
484 + deselectAllRows( false );
485 + }
486 +
487 + boolean isSelected = selectedRows.containsKey( new Integer( row ) );
488 + if ( shiftKey && (lastSelectedRowIndex > -1) )
489 + {
490 + // Shift+select rows
491 + SelectionGridRowFormatter formatter = getSelectionGridRowFormatter();
492 + int firstRow = Math.min( row, lastSelectedRowIndex );
493 + int lastRow = Math.max( row, lastSelectedRowIndex );
494 + lastRow = Math.min( lastRow, getRowCount() - 1 );
495 + for ( int curRow = firstRow; curRow <= lastRow; curRow++ )
496 + {
497 + if ( isSelected )
498 + {
499 + deselectRow( curRow, false );
500 + }
501 + else
502 + {
503 + selectRow( curRow, formatter.getRawElement( curRow ), false, false );
504 + }
505 + }
506 +
507 + // Fire Event
508 + lastSelectedRowIndex = row;
509 + fireRowSelectionEvent( oldRowList );
510 + }
511 + else if ( isSelected )
512 + {
513 + // Ctrl+unselect a selected row
514 + deselectRow( row, false );
515 + lastSelectedRowIndex = row;
516 + fireRowSelectionEvent( oldRowList );
517 + }
518 + else
519 + {
520 + // Select the row
521 + SelectionGridRowFormatter formatter = getSelectionGridRowFormatter();
522 + selectRow( row, formatter.getRawElement( row ), false, false );
523 + lastSelectedRowIndex = row;
524 + fireRowSelectionEvent( oldRowList );
525 + }
526 + }
527 +
528 + /**
529 + * Enable or disable row selection.
530 + *
531 + * @param enabled true to enable, false to disable
532 + */
533 + public void setSelectionEnabled( boolean enabled )
534 + {
535 + selectionEnabled = enabled;
536 +
537 + // Update the input elements
538 + if ( selectionPolicy.hasInputColumn() )
539 + {
540 + SelectionGridCellFormatter formatter = getSelectionGridCellFormatter();
541 + int rowCount = getRowCount();
542 + for ( int i = 0; i < rowCount; i++ )
543 + {
544 + Element td = formatter.getRawElement( i, -1 );
545 + setInputEnabled( selectionPolicy, td, enabled );
546 + }
547 + }
548 + }
549 +
550 + /**
551 + * Set the selection policy, which determines if the user can select zero,
552 + * one, or multiple rows.
553 + *
554 + * @param selectionPolicy the selection policy
555 + */
556 + public void setSelectionPolicy( SelectionPolicy selectionPolicy )
557 + {
558 + if ( this.selectionPolicy == selectionPolicy )
559 + {
333 560 return;
334 - }
561 + }
562 + deselectAllRows();
563 +
564 + // Update the input column
565 + if ( selectionPolicy.hasInputColumn() )
566 + {
567 + if ( this.selectionPolicy.hasInputColumn() )
568 + {
569 + // Update the existing input column
570 + String inputHtml = getInputHtml( selectionPolicy );
571 + for ( int i = 0; i < numRows; i++ )
572 + {
573 + Element tr = getRowFormatter().getElement( i );
574 + tr.getFirstChildElement().setInnerHTML( inputHtml );
575 + }
576 + }
577 + else
578 + {
579 + // Add an input column to every row
580 + String inputHtml = getInputHtml( selectionPolicy );
581 + Element td = createCell();
582 + td.setInnerHTML( inputHtml );
583 + for ( int i = 0; i < numRows; i++ )
584 + {
585 + Element tr = getRowFormatter().getElement( i );
586 + tr.insertBefore( td.cloneNode( true ), tr.getFirstChildElement() );
587 + }
588 + }
589 + }
590 + else if ( this.selectionPolicy.hasInputColumn() )
591 + {
592 + // Remove the input column from every row
593 + for ( int i = 0; i < numRows; i++ )
594 + {
595 + Element tr = getRowFormatter().getElement( i );
596 + tr.removeChild( tr.getFirstChildElement() );
597 + }
598 + }
599 + this.selectionPolicy = selectionPolicy;
600 +
601 + // Update the enabled state
602 + setSelectionEnabled( selectionEnabled );
603 + }
604 +
605 + @Override
606 + protected Element createRow()
607 + {
608 + Element tr = super.createRow();
609 + if ( selectionPolicy.hasInputColumn() )
610 + {
611 + Element td = createCell();
612 + td.setPropertyString( "align", "center" );
613 + td.setInnerHTML( getInputHtml( selectionPolicy ) );
614 + DOM.insertChild( tr, td, 0 );
615 + if ( !selectionEnabled )
616 + {
617 + setInputEnabled( selectionPolicy, td, false );
618 + }
619 + }
620 + return tr;
621 + }
622 +
623 + /**
624 + * Deselect all selected rows in the data table.
625 + *
626 + * @param fireEvent true to fire events
627 + */
628 + protected void deselectAllRows( boolean fireEvent )
629 + {
630 + // Get the old list of selected rows
631 + Set<Row> oldRows = null;
632 + if ( fireEvent )
633 + {
634 + oldRows = getSelectedRowsSet();
635 + }
636 +
637 + // Deselect all rows
638 + boolean hasInputColumn = selectionPolicy.hasInputColumn();
639 + for ( Element rowElem : selectedRows.values() )
640 + {
641 + setStyleName( rowElem, "selected", false );
642 + if ( hasInputColumn )
643 + {
644 + setInputSelected( getSelectionPolicy(), (Element) rowElem.getFirstChildElement(), false );
645 + }
646 + }
647 +
648 + // Clear out the rows
649 + selectedRows.clear();
650 +
651 + // Fire event
652 + if ( fireEvent )
653 + {
654 + fireRowSelectionEvent( oldRows );
655 + }
656 + }
335 657
336 - // Unhighlight the current cell
337 - highlightCell(null);
658 + /**
659 + * Deselect a row in the grid. This method is safe to call even if the row is
660 + * not selected, or doesn't exist (out of bounds).
661 + *
662 + * @param row the row index
663 + * @param fireEvent true to fire events
664 + */
665 + protected void deselectRow( int row, boolean fireEvent )
666 + {
667 + Element rowElem = selectedRows.remove( new Integer( row ) );
668 + if ( rowElem != null )
669 + {
670 + // Get the old list of selected rows
671 + Set<Row> oldRows = null;
672 + if ( fireEvent )
673 + {
674 + oldRows = getSelectedRowsSet();
675 + }
676 +
677 + // Deselect the row
678 + setStyleName( rowElem, "selected", false );
679 + if ( selectionPolicy.hasInputColumn() )
680 + {
681 + setInputSelected( getSelectionPolicy(), (Element) rowElem.getFirstChildElement(), false );
682 + }
683 +
684 + // Fire Event
685 + if ( fireEvent )
686 + {
687 + fireRowSelectionEvent( oldRows );
688 + }
338 689 }
339 - break;
690 + }
691 +
692 + /**
693 + * Fire a {@link RowSelectionEvent}. This method will automatically add the
694 + * currently selected rows.
695 + *
696 + * @param oldRowSet the set of previously selected rows
697 + */
698 + protected void fireRowSelectionEvent( Set<Row> oldRowSet )
699 + {
700 + Set<Row> newRowList = getSelectedRowsSet();
701 + if ( newRowList.equals( oldRowSet ) )
702 + {
703 + return;
704 + }
705 + fireEvent( new RowSelectionEvent( oldRowSet, newRowList ) );
706 + }
340 707
341 - // Select a row on click
342 - case Event.ONMOUSEDOWN: {
343 - // Ignore if selection is disabled
344 - if (!selectionEnabled) {
345 - return;
346 - }
347 -
348 - // Get the target row
349 - targetCell = getEventTargetCell(event);
350 - if (targetCell == null) {
351 - return;
352 - }
353 - targetRow = DOM.getParent(targetCell);
354 - int targetRowIndex = getRowIndex(targetRow);
355 -
356 - // Select the row
357 - if (selectionPolicy == SelectionPolicy.MULTI_ROW) {
358 - boolean shiftKey = DOM.eventGetShiftKey(event);
359 - boolean ctrlKey = DOM.eventGetCtrlKey(event)
360 - || DOM.eventGetMetaKey(event);
361 -
362 - // Prevent default text selection
363 - if (ctrlKey || shiftKey) {
364 - event.preventDefault();
365 - }
366 -
367 - // Select the rows
368 - selectRow(targetRowIndex, ctrlKey, shiftKey);
369 - } else if (selectionPolicy == SelectionPolicy.ONE_ROW
370 - || (selectionPolicy == SelectionPolicy.RADIO && targetCell == targetRow.getFirstChild())) {
371 - selectRow(-1, targetRow, true, true);
372 - lastSelectedRowIndex = targetRowIndex;
373 - }
374 - }
375 - break;
376 -
377 - // Prevent native inputs from being checked
378 - case Event.ONCLICK: {
379 - // Ignore if selection is disabled
380 - if (!selectionEnabled) {
381 - return;
382 - }
383 -
384 - // Get the target row
385 - targetCell = getEventTargetCell(event);
386 - if (targetCell == null) {
387 - return;
388 - }
389 - targetRow = DOM.getParent(targetCell);
390 - int targetRowIndex = getRowIndex(targetRow);
391 -
392 - // Select the row
393 - if (selectionPolicy == SelectionPolicy.CHECKBOX
394 - && targetCell == targetRow.getFirstChild()) {
395 - selectRow(targetRowIndex, true, DOM.eventGetShiftKey(event));
396 - }
397 - }
398 - break;
399 - }
400 - }
401 -
402 - @Override
403 - public void removeRow(int row) {
404 - deselectAllRows();
405 - super.removeRow(row);
406 - }
407 -
408 - /**
409 - * Select all rows in the table.
410 - */
411 - public void selectAllRows() {
412 - // Get the currently selected rows
413 - Set<Row> oldRowSet = getSelectedRowsSet();
414 -
415 - // Select all rows
416 - RowFormatter rowFormatter = getRowFormatter();
417 - int rowCount = getRowCount();
418 - for (int i = 0; i < rowCount; i++) {
419 - if (!selectedRows.containsKey(i)) {
420 - selectRow(i, rowFormatter.getElement(i), false, false);
421 - }
422 - }
423 -
424 - // Trigger the event
425 - fireRowSelectionEvent(oldRowSet);
426 - }
427 -
428 - /**
429 - * Select a row in the data table.
430 - *
431 - * @param row the row index
432 - * @param unselectAll unselect all other rows first
433 - * @throws IndexOutOfBoundsException
434 - */
435 - public void selectRow(int row, boolean unselectAll) {
436 - selectRow(row, getRowFormatter().getElement(row), unselectAll, true);
437 - }
438 -
439 - /**
440 - * Select a row in the data table. Simulate the effect of a shift click and/or
441 - * control click. This method ignores the selection policy, which only applies
442 - * to user selection via mouse events.
443 - *
444 - * @param row the row index
445 - * @param ctrlKey true to simulate a control click
446 - * @param shiftKey true to simulate a shift selection
447 - * @throws IndexOutOfBoundsException
448 - */
449 - public void selectRow(int row, boolean ctrlKey, boolean shiftKey) {
450 - // Check the row bounds
451 - checkRowBounds(row);
452 -
453 - // Get the old list of selected rows
454 - Set<Row> oldRowList = getSelectedRowsSet();
455 -
456 - // Deselect all rows
457 - if (!ctrlKey) {
458 - deselectAllRows(false);
459 - }
460 -
461 - boolean isSelected = selectedRows.containsKey(new Integer(row));
462 - if (shiftKey && (lastSelectedRowIndex > -1)) {
463 - // Shift+select rows
464 - SelectionGridRowFormatter formatter = getSelectionGridRowFormatter();
465 - int firstRow = Math.min(row, lastSelectedRowIndex);
466 - int lastRow = Math.max(row, lastSelectedRowIndex);
467 - lastRow = Math.min(lastRow, getRowCount() - 1);
468 - for (int curRow = firstRow; curRow <= lastRow; curRow++) {
469 - if (isSelected) {
470 - deselectRow(curRow, false);
471 - } else {
472 - selectRow(curRow, formatter.getRawElement(curRow), false, false);
473 - }
474 - }
475 -
476 - // Fire Event
477 - lastSelectedRowIndex = row;
478 - fireRowSelectionEvent(oldRowList);
479 - } else if (isSelected) {
480 - // Ctrl+unselect a selected row
481 - deselectRow(row, false);
482 - lastSelectedRowIndex = row;
483 - fireRowSelectionEvent(oldRowList);
484 - } else {
485 - // Select the row
486 - SelectionGridRowFormatter formatter = getSelectionGridRowFormatter();
487 - selectRow(row, formatter.getRawElement(row), false, false);
488 - lastSelectedRowIndex = row;
489 - fireRowSelectionEvent(oldRowList);
490 - }
491 - }
492 -
493 - /**
494 - * Enable or disable row selection.
495 - *
496 - * @param enabled true to enable, false to disable
497 - */
498 - public void setSelectionEnabled(boolean enabled) {
499 - selectionEnabled = enabled;
500 -
501 - // Update the input elements
502 - if (selectionPolicy.hasInputColumn()) {
503 - SelectionGridCellFormatter formatter = getSelectionGridCellFormatter();
504 - int rowCount = getRowCount();
505 - for (int i = 0; i < rowCount; i++) {
506 - Element td = formatter.getRawElement(i, -1);
507 - setInputEnabled(selectionPolicy, td, enabled);
508 - }
509 - }
510 - }
511 -
512 - /**
513 - * Set the selection policy, which determines if the user can select zero,
514 - * one, or multiple rows.
515 - *
516 - * @param selectionPolicy the selection policy
517 - */
518 - public void setSelectionPolicy(SelectionPolicy selectionPolicy) {
519 - if (this.selectionPolicy == selectionPolicy) {
520 - return;
521 - }
522 - deselectAllRows();
523 -
524 - // Update the input column
525 - if (selectionPolicy.hasInputColumn()) {
526 - if (this.selectionPolicy.hasInputColumn()) {
527 - // Update the existing input column
528 - String inputHtml = getInputHtml(selectionPolicy);
529 - for (int i = 0; i < numRows; i++) {
530 - Element tr = getRowFormatter().getElement(i);
531 - tr.getFirstChildElement().setInnerHTML(inputHtml);
532 - }
533 - } else {
534 - // Add an input column to every row
535 - String inputHtml = getInputHtml(selectionPolicy);
536 - Element td = createCell();
537 - td.setInnerHTML(inputHtml);
538 - for (int i = 0; i < numRows; i++) {
539 - Element tr = getRowFormatter().getElement(i);
540 - tr.insertBefore(td.cloneNode(true), tr.getFirstChildElement());
541 - }
542 - }
543 - } else if (this.selectionPolicy.hasInputColumn()) {
544 - // Remove the input column from every row
545 - for (int i = 0; i < numRows; i++) {
546 - Element tr = getRowFormatter().getElement(i);
547 - tr.removeChild(tr.getFirstChildElement());
548 - }
549 - }
550 - this.selectionPolicy = selectionPolicy;
551 -
552 - // Update the enabled state
553 - setSelectionEnabled(selectionEnabled);
554 - }
555 -
556 - @Override
557 - protected Element createRow() {
558 - Element tr = super.createRow();
559 - if (selectionPolicy.hasInputColumn()) {
560 - Element td = createCell();
561 - td.setPropertyString("align", "center");
562 - td.setInnerHTML(getInputHtml(selectionPolicy));
563 - DOM.insertChild(tr, td, 0);
564 - if (!selectionEnabled) {
565 - setInputEnabled(selectionPolicy, td, false);
566 - }
567 - }
568 - return tr;
569 - }
570 -
571 - /**
572 - * Deselect all selected rows in the data table.
573 - *
574 - * @param fireEvent true to fire events
575 - */
576 - protected void deselectAllRows(boolean fireEvent) {
577 - // Get the old list of selected rows
578 - Set<Row> oldRows = null;
579 - if (fireEvent) {
580 - oldRows = getSelectedRowsSet();
581 - }
582 -
583 - // Deselect all rows
584 - boolean hasInputColumn = selectionPolicy.hasInputColumn();
585 - for (Element rowElem : selectedRows.values()) {
586 - setStyleName(rowElem, "selected", false);
587 - if (hasInputColumn) {
588 - setInputSelected(getSelectionPolicy(),
589 - (Element) rowElem.getFirstChildElement(), false);
590 - }
591 - }
592 -
593 - // Clear out the rows
594 - selectedRows.clear();
595 -
596 - // Fire event
597 - if (fireEvent) {
598 - fireRowSelectionEvent(oldRows);
599 - }
600 - }
601 -
602 - /**
603 - * Deselect a row in the grid. This method is safe to call even if the row is
604 - * not selected, or doesn't exist (out of bounds).
605 - *
606 - * @param row the row index
607 - * @param fireEvent true to fire events
608 - */
609 - protected void deselectRow(int row, boolean fireEvent) {
610 - Element rowElem = selectedRows.remove(new Integer(row));
611 - if (rowElem != null) {
612 - // Get the old list of selected rows
613 - Set<Row> oldRows = null;
614 - if (fireEvent) {
615 - oldRows = getSelectedRowsSet();
616 - }
617 -
618 - // Deselect the row
619 - setStyleName(rowElem, "selected", false);
620 - if (selectionPolicy.hasInputColumn()) {
621 - setInputSelected(getSelectionPolicy(),
622 - (Element) rowElem.getFirstChildElement(), false);
623 - }
624 -
625 - // Fire Event
626 - if (fireEvent) {
627 - fireRowSelectionEvent(oldRows);
628 - }
629 - }
630 - }
631 -
632 - /**
633 - * Fire a {@link RowSelectionEvent}. This method will automatically add the
634 - * currently selected rows.
635 - *
636 - * @param oldRowSet the set of previously selected rows
637 - */
638 - protected void fireRowSelectionEvent(Set<Row> oldRowSet) {
639 - Set<Row> newRowList = getSelectedRowsSet();
640 - if (newRowList.equals(oldRowSet)) {
641 - return;
642 - }
643 - fireEvent(new RowSelectionEvent(oldRowSet, newRowList));
644 - }
645 -
646 - @Override
647 - protected int getCellIndex(Element rowElem, Element cellElem) {
648 - int index = super.getCellIndex(rowElem, cellElem);
649 - if (selectionPolicy.hasInputColumn()) {
650 - index--;
651 - }
652 - return index;
653 - }
654 -
655 - @Override
656 - protected int getDOMCellCount(int row) {
657 - int count = super.getDOMCellCount(row);
658 - if (getSelectionPolicy().hasInputColumn()) {
659 - count--;
660 - }
661 - return count;
662 - }
663 -
664 - /**
665 - * Get the html used to create the native input selection element.
666 - *
667 - * @param selectionPolicy the associated {@link SelectionPolicy}
668 - * @return the html representation of the input element
669 - */
670 - protected String getInputHtml(SelectionPolicy selectionPolicy) {
671 - String inputHtml = selectionPolicy.getInputHtml();
672 - if (inputHtml != null) {
673 - inputHtml = inputHtml.replace("%NAME%", "__gwtSelectionGrid" + id);
674 - }
675 - return inputHtml;
676 - }
677 -
678 - /**
679 - * @return a map or selected row indexes to their elements
680 - */
681 - protected Map<Integer, Element> getSelectedRowsMap() {
682 - return selectedRows;
683 - }
684 -
685 - /**
686 - * @return a list of selected rows to pass into a {@link RowSelectionEvent}
687 - */
688 - protected Set<Row> getSelectedRowsSet() {
689 - Set<Row> rowSet = new TreeSet<Row>();
690 - for (Integer rowIndex : selectedRows.keySet()) {
691 - rowSet.add(new Row(rowIndex.intValue()));
692 - }
693 - return rowSet;
694 - }
695 -
696 - /**
697 - * Set the current highlighted cell.
698 - *
699 - * @param cellElem the cell element
700 - */
701 - protected void highlightCell(Element cellElem) {
702 - // Ignore if the cell is already being highlighted
703 - if (cellElem == highlightedCellElem) {
704 - return;
705 - }
706 -
707 - // Get the row element
708 - Element rowElem = null;
709 - if (cellElem != null) {
710 - rowElem = DOM.getParent(cellElem);
711 - }
712 -
713 - // Unhighlight the current cell
714 - if (highlightedCellElem != null) {
715 - setStyleName(highlightedCellElem, "highlighted", false);
716 - fireEvent(new CellUnhighlightEvent(highlightedRowIndex,
717 - highlightedCellIndex));
718 - highlightedCellElem = null;
719 - highlightedCellIndex = -1;
720 -
721 - // Unhighlight the current row if it changed
722 - if (rowElem != highlightedRowElem) {
723 - setStyleName(highlightedRowElem, "highlighted", false);
724 - fireEvent(new RowUnhighlightEvent(highlightedRowIndex));
725 - highlightedRowElem = null;
726 - highlightedRowIndex = -1;
727 - }
728 - }
729 -
730 - // Highlight the cell
731 - if (cellElem != null) {
732 - setStyleName(cellElem, "highlighted", true);
733 - highlightedCellElem = cellElem;
734 - highlightedCellIndex = OverrideDOM.getCellIndex(cellElem);
735 -
736 - // Highlight the row if it changed
737 - if (highlightedRowElem == null) {
738 - setStyleName(rowElem, "highlighted", true);
739 - highlightedRowElem = rowElem;
740 - highlightedRowIndex = getRowIndex(highlightedRowElem);
741 - fireEvent(new RowHighlightEvent(highlightedRowIndex));
742 - }
743 -
744 - // Fire listeners
745 - fireEvent(new CellHighlightEvent(highlightedRowIndex,
746 - highlightedCellIndex));
747 - }
748 - }
749 -
750 - /**
751 - * Select a row in the data table.
752 - *
753 - * @param row the row index, or -1 if unknown
754 - * @param rowElem the row element
755 - * @param unselectAll true to unselect all currently selected rows
756 - * @param fireEvent true to fire the select event to listeners
757 - */
758 - protected void selectRow(int row, Element rowElem, boolean unselectAll,
759 - boolean fireEvent) {
760 - // Get the row index if needed
761 - if (row < 0) {
762 - row = getRowIndex(rowElem);
763 - }
764 -
765 - // Ignore request if row already selected
766 - Integer rowI = new Integer(row);
767 - if (selectedRows.containsKey(rowI)) {
768 - return;
769 - }
770 -
771 - // Get the old list of selected rows
772 - Set<Row> oldRowSet = null;
773 - if (fireEvent) {
774 - oldRowSet = getSelectedRowsSet();
775 - }
776 -
777 - // Deselect current rows
778 - if (unselectAll) {
779 - deselectAllRows(false);
780 - }
781 -
782 - // Select the new row
783 - selectedRows.put(rowI, rowElem);
784 - setStyleName(rowElem, "selected", true);
785 - if (selectionPolicy.hasInputColumn()) {
786 - setInputSelected(getSelectionPolicy(),
787 - (Element) rowElem.getFirstChildElement(), true);
788 - }
789 -
790 - // Fire grid listeners
791 - if (fireEvent) {
792 - fireRowSelectionEvent(oldRowSet);
793 - }
794 - }
795 -
796 - @Override
797 - protected void setBodyElement(Element element) {
798 - super.setBodyElement(element);
799 - if (!selectionEnabled) {
800 - setSelectionEnabled(selectionEnabled);
801 - }
802 - }
803 -
804 - /**
805 - * Enabled or disabled the native input element in the given cell. This method
806 - * should correspond with the HTML returned from {@link #getInputHtml}.
807 - *
808 - * @param selectionPolicy the associated {@link SelectionPolicy}
809 - * @param td the cell containing the element
810 - * @param enabled true to enable, false to disable
811 - */
812 - protected void setInputEnabled(SelectionPolicy selectionPolicy, Element td,
813 - boolean enabled) {
814 - ((InputElement) td.getFirstChild()).setDisabled(!enabled);
815 - }
816 -
817 - /**
818 - * Select the native input element in the given cell. This method should
819 - * correspond with the HTML returned from {@link #getInputHtml}.
820 - *
821 - * @param selectionPolicy the associated {@link SelectionPolicy}
822 - * @param td the cell containing the element
823 - * @param selected true to select, false to deselect
824 - */
825 - protected void setInputSelected(SelectionPolicy selectionPolicy, Element td,
826 - boolean selected) {
827 - ((InputElement) td.getFirstChild()).setChecked(selected);
828 - }
708 + @Override
709 + protected int getCellIndex( Element rowElem, Element cellElem )
710 + {
711 + int index = super.getCellIndex( rowElem, cellElem );
712 + if ( selectionPolicy.hasInputColumn() )
713 + {
714 + index--;
715 + }
716 + return index;
717 + }
718 +
719 + @Override
720 + protected int getDOMCellCount( int row )
721 + {
722 + int count = super.getDOMCellCount( row );
723 + if ( getSelectionPolicy().hasInputColumn() )
724 + {
725 + count--;
726 + }
727 + return count;
728 + }
729 +
730 + /**
731 + * Get the html used to create the native input selection element.
732 + *
733 + * @param selectionPolicy the associated {@link SelectionPolicy}
734 + *
735 + * @return the html representation of the input element
736 + */
737 + protected String getInputHtml( SelectionPolicy selectionPolicy )
738 + {
739 + String inputHtml = selectionPolicy.getInputHtml();
740 + if ( inputHtml != null )
741 + {
742 + inputHtml = inputHtml.replace( "%NAME%", "__gwtSelectionGrid" + id );
743 + }
744 + return inputHtml;
745 + }
746 +
747 + /**
748 + * @return a map or selected row indexes to their elements
749 + */
750 + protected Map<Integer, Element> getSelectedRowsMap()
751 + {
752 + return selectedRows;
753 + }
754 +
755 + /**
756 + * @return a list of selected rows to pass into a {@link RowSelectionEvent}
757 + */
758 + protected Set<Row> getSelectedRowsSet()
759 + {
760 + Set<Row> rowSet = new TreeSet<Row>();
761 + for ( Integer rowIndex : selectedRows.keySet() )
762 + {
763 + rowSet.add( new Row( rowIndex.intValue() ) );
764 + }
765 + return rowSet;
766 + }
767 +
768 + /**
769 + * Set the current highlighted cell.
770 + *
771 + * @param cellElem the cell element
772 + */
773 + protected void highlightCell( Element cellElem )
774 + {
775 + // Ignore if the cell is already being highlighted
776 + if ( cellElem == highlightedCellElem )
777 + {
778 + return;
779 + }
780 +
781 + // Get the row element
782 + Element rowElem = null;
783 + if ( cellElem != null )
784 + {
785 + rowElem = DOM.getParent( cellElem );
786 + }
787 +
788 + // Unhighlight the current cell
789 + if ( highlightedCellElem != null )
790 + {
791 + setStyleName( highlightedCellElem, "highlighted", false );
792 + fireEvent( new CellUnhighlightEvent( highlightedRowIndex, highlightedCellIndex ) );
793 + highlightedCellElem = null;
794 + highlightedCellIndex = -1;
795 +
796 + // Unhighlight the current row if it changed
797 + if ( rowElem != highlightedRowElem )
798 + {
799 + setStyleName( highlightedRowElem, "highlighted", false );
800 + fireEvent( new RowUnhighlightEvent( highlightedRowIndex ) );
801 + highlightedRowElem = null;
802 + highlightedRowIndex = -1;
803 + }
804 + }
805 +
806 + // Highlight the cell
807 + if ( cellElem != null )
808 + {
809 + setStyleName( cellElem, "highlighted", true );
810 + highlightedCellElem = cellElem;
811 + highlightedCellIndex = OverrideDOM.getCellIndex( cellElem );
812 +
813 + // Highlight the row if it changed
814 + if ( highlightedRowElem == null )
815 + {
816 + setStyleName( rowElem, "highlighted", true );
817 + highlightedRowElem = rowElem;
818 + highlightedRowIndex = getRowIndex( highlightedRowElem );
819 + fireEvent( new RowHighlightEvent( highlightedRowIndex ) );
820 + }
821 +
822 + // Fire listeners
823 + fireEvent( new CellHighlightEvent( highlightedRowIndex, highlightedCellIndex ) );
824 + }
825 + }
826 +
827 + /**
828 + * Select a row in the data table.
829 + *
830 + * @param row the row index, or -1 if unknown
831 + * @param rowElem the row element
832 + * @param unselectAll true to unselect all currently selected rows
833 + * @param fireEvent true to fire the select event to listeners
834 + */
835 + protected void selectRow( int row, Element rowElem, boolean unselectAll, boolean fireEvent )
836 + {
837 + // Get the row index if needed
838 + if ( row < 0 )
839 + {
840 + row = getRowIndex( rowElem );
841 + }
842 +
843 + // Ignore request if row already selected
844 + Integer rowI = new Integer( row );
845 + if ( selectedRows.containsKey( rowI ) )
846 + {
847 + return;
848 + }
849 +
850 + // Get the old list of selected rows
851 + Set<Row> oldRowSet = null;
852 + if ( fireEvent )
853 + {
854 + oldRowSet = getSelectedRowsSet();
855 + }
856 +
857 + // Deselect current rows
858 + if ( unselectAll )
859 + {
860 + deselectAllRows( false );
861 + }
862 +
863 + // Select the new row
864 + selectedRows.put( rowI, rowElem );
865 + setStyleName( rowElem, "selected", true );
866 + if ( selectionPolicy.hasInputColumn() )
867 + {
868 + setInputSelected( getSelectionPolicy(), (Element) rowElem.getFirstChildElement(), true );
869 + }
870 +
871 + // Fire grid listeners
872 + if ( fireEvent )
873 + {
874 + fireRowSelectionEvent( oldRowSet );
875 + }
876 + }
877 +
878 + @Override
879 + protected void setBodyElement( Element element )
880 + {
881 + super.setBodyElement( element );
882 + if ( !selectionEnabled )
883 + {
884 + setSelectionEnabled( selectionEnabled );
885 + }
886 + }
887 +
888 + /**
889 + * Enabled or disabled the native input element in the given cell. This method
890 + * should correspond with the HTML returned from {@link #getInputHtml}.
891 + *
892 + * @param selectionPolicy the associated {@link SelectionPolicy}
893 + * @param td the cell containing the element
894 + * @param enabled true to enable, false to disable
895 + */
896 + protected void setInputEnabled( SelectionPolicy selectionPolicy, Element td, boolean enabled )
897 + {
898 + ((InputElement) td.getFirstChild()).setDisabled( !enabled );
899 + }
900 +
901 + /**
902 + * Select the native input element in the given cell. This method should
903 + * correspond with the HTML returned from {@link #getInputHtml}.
904 + *
905 + * @param selectionPolicy the associated {@link SelectionPolicy}
906 + * @param td the cell containing the element
907 + * @param selected true to select, false to deselect
908 + */
909 + protected void setInputSelected( SelectionPolicy selectionPolicy, Element td, boolean selected )
910 + {
911 + ((InputElement) td.getFirstChild()).setChecked( selected );
912 + }
829 913 }