com.google.gwt.gen2.table.client.SelectionGrid.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.gen2.table.client.SelectionGrid.java

Source

/*
 * Copyright 2008 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.gen2.table.client;

import com.google.gwt.dom.client.InputElement;
import com.google.gwt.gen2.event.shared.HandlerRegistration;
import com.google.gwt.gen2.table.event.client.CellHighlightEvent;
import com.google.gwt.gen2.table.event.client.CellHighlightHandler;
import com.google.gwt.gen2.table.event.client.CellUnhighlightEvent;
import com.google.gwt.gen2.table.event.client.CellUnhighlightHandler;
import com.google.gwt.gen2.table.event.client.HasCellHighlightHandlers;
import com.google.gwt.gen2.table.event.client.HasCellUnhighlightHandlers;
import com.google.gwt.gen2.table.event.client.HasRowHighlightHandlers;
import com.google.gwt.gen2.table.event.client.HasRowSelectionHandlers;
import com.google.gwt.gen2.table.event.client.HasRowUnhighlightHandlers;
import com.google.gwt.gen2.table.event.client.RowHighlightEvent;
import com.google.gwt.gen2.table.event.client.RowHighlightHandler;
import com.google.gwt.gen2.table.event.client.RowSelectionEvent;
import com.google.gwt.gen2.table.event.client.RowSelectionHandler;
import com.google.gwt.gen2.table.event.client.RowUnhighlightEvent;
import com.google.gwt.gen2.table.event.client.RowUnhighlightHandler;
import com.google.gwt.gen2.table.event.client.TableEvent.Row;
import com.google.gwt.gen2.table.override.client.Grid;
import com.google.gwt.gen2.table.override.client.OverrideDOM;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

/**
 * A variation of the {@link Grid} that supports row or cell highlight and row
 * selection.
 * 
 * <h3>CSS Style Rules</h3>
 * 
 * <ul class="css">
 * 
 * <li>tr.selected { applied to selected rows }</li>
 * 
 * <li>tr.highlighted { applied to row currently being highlighted }</li>
 * 
 * <li>td.highlighted { applied to cell currently being highlighted }</li>
 * 
 * </ul>
 */
public class SelectionGrid extends Grid implements HasRowHighlightHandlers, HasRowUnhighlightHandlers,
        HasCellHighlightHandlers, HasCellUnhighlightHandlers, HasRowSelectionHandlers {
    /**
     * This class contains methods used to format a table's cells.
     */
    public class SelectionGridCellFormatter extends CellFormatter {
        @Override
        protected Element getRawElement(int row, int column) {
            if (selectionPolicy.hasInputColumn()) {
                column += 1;
            }
            return super.getRawElement(row, column);
        }
    }

    /**
     * This class contains methods used to format a table's rows.
     */
    public class SelectionGridRowFormatter extends RowFormatter {
        @Override
        protected Element getRawElement(int row) {
            return super.getRawElement(row);
        }
    }

    /**
     * Selection policies.
     * 
     * <ul>
     * <li>ONE_ROW - one row can be selected at a time</li>
     * <li>MULTI_ROW - multiple rows can be selected at a time</li>
     * <li>CHECKBOX - multiple rows can be selected using checkboxes</li>
     * <li>RADIO - one row can be selected using radio buttons</li>
     * </ul>
     */
    public static enum SelectionPolicy {
        ONE_ROW(null), MULTI_ROW(null), CHECKBOX("<input type='checkbox'/>"), RADIO(
                "<input name='%NAME%' type='radio'/>");

        private String inputHtml;

        private SelectionPolicy(String inputHtml) {
            this.inputHtml = inputHtml;
        }

        /**
         * @return true if the policy requires a selection column
         */
        public boolean hasInputColumn() {
            return inputHtml != null;
        }

        /**
         * @return the HTML string used for this policy
         */
        private String getInputHtml() {
            return inputHtml;
        }
    }

    /**
     * Unique IDs assigned to the grids.
     */
    private static int uniqueID = 0;

    /**
     * The cell element currently being highlight.
     */
    private Element highlightedCellElem = null;

    /**
     * The index of the cell currently being highlight.
     */
    private int highlightedCellIndex = -1;

    /**
     * The row element currently being highlight.
     */
    private Element highlightedRowElem = null;

    /**
     * The index of the row currently being highlight.
     */
    private int highlightedRowIndex = -1;

    /**
     * Unique ID of this grid.
     */
    private int id;

    /**
     * The index of the row that the user selected last.
     */
    private int lastSelectedRowIndex = -1;

    /**
     * The rows that are currently selected.
     */
    private Map<Integer, Element> selectedRows = new HashMap<Integer, Element>();

    /**
     * A boolean indicating if selection is enabled disabled.
     */
    private boolean selectionEnabled = true;

    /**
     * The selection policy determines if the user can select zero, one, or many
     * rows.
     */
    private SelectionPolicy selectionPolicy = SelectionPolicy.MULTI_ROW;

    /**
     * Construct a new {@link SelectionGrid}.
     */
    public SelectionGrid() {
        super();
        id = uniqueID++;
        setCellFormatter(new SelectionGridCellFormatter());
        setRowFormatter(new SelectionGridRowFormatter());

        // Sink highlight and selection events
        sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT | Event.ONMOUSEDOWN | Event.ONCLICK);
    }

    /**
     * Constructs a {@link SelectionGrid} with the requested size.
     * 
     * @param rows the number of rows
     * @param columns the number of columns
     * @throws IndexOutOfBoundsException
     */
    public SelectionGrid(int rows, int columns) {
        this();
        resize(rows, columns);
    }

    public HandlerRegistration addCellHighlightHandler(CellHighlightHandler handler) {
        return addHandler(CellHighlightEvent.TYPE, handler);
    }

    public HandlerRegistration addCellUnhighlightHandler(CellUnhighlightHandler handler) {
        return addHandler(CellUnhighlightEvent.TYPE, handler);
    }

    public HandlerRegistration addRowHighlightHandler(RowHighlightHandler handler) {
        return addHandler(RowHighlightEvent.TYPE, handler);
    }

    public HandlerRegistration addRowSelectionHandler(RowSelectionHandler handler) {
        return addHandler(RowSelectionEvent.TYPE, handler);
    }

    public HandlerRegistration addRowUnhighlightHandler(RowUnhighlightHandler handler) {
        return addHandler(RowUnhighlightEvent.TYPE, handler);
    }

    /**
     * Deselect all selected rows in the data table.
     */
    public void deselectAllRows() {
        deselectAllRows(true);
    }

    /**
     * Deselect a row in the grid. This method is safe to call even if the row is
     * not selected, or doesn't exist (out of bounds).
     * 
     * @param row the row index
     */
    public void deselectRow(int row) {
        deselectRow(row, true);
    }

    /**
     * @return the set of selected row indexes
     */
    public Set<Integer> getSelectedRows() {
        return selectedRows.keySet();
    }

    /**
     * Explicitly gets the {@link SelectionGridCellFormatter}. The results of
     * {@link com.google.gwt.gen2.table.override.client.HTMLTable#getCellFormatter()}
     * may also be downcast to a {@link SelectionGridCellFormatter}.
     * 
     * @return the FlexTable's cell formatter
     */
    public SelectionGridCellFormatter getSelectionGridCellFormatter() {
        return (SelectionGridCellFormatter) getCellFormatter();
    }

    /**
     * Explicitly gets the {@link SelectionGridRowFormatter}. The results of
     * {@link com.google.gwt.gen2.table.override.client.HTMLTable#getRowFormatter()}
     * may also be downcast to a {@link SelectionGridRowFormatter}.
     * 
     * @return the FlexTable's cell formatter
     */
    public SelectionGridRowFormatter getSelectionGridRowFormatter() {
        return (SelectionGridRowFormatter) getRowFormatter();
    }

    /**
     * @return the selection policy
     */
    public SelectionPolicy getSelectionPolicy() {
        return selectionPolicy;
    }

    @Override
    public int insertRow(int beforeRow) {
        deselectAllRows();
        return super.insertRow(beforeRow);
    }

    /**
     * @param row the row index
     * @return true if the row is selected, false if not
     */
    public boolean isRowSelected(int row) {
        return selectedRows.containsKey(new Integer(row));
    }

    /**
     * @return true if selection is enabled
     */
    public boolean isSelectionEnabled() {
        return selectionEnabled;
    }

    @Override
    public void onBrowserEvent(Event event) {
        super.onBrowserEvent(event);
        Element targetRow = null;
        Element targetCell = null;

        switch (DOM.eventGetType(event)) {
        // Highlight the cell on mouse over
        case Event.ONMOUSEOVER:
            Element cellElem = getEventTargetCell(event);
            if (cellElem != null) {
                highlightCell(cellElem);
            }
            break;

        // Unhighlight on mouse out
        case Event.ONMOUSEOUT:
            Element toElem = DOM.eventGetToElement(event);
            if (highlightedRowElem != null && (toElem == null || !highlightedRowElem.isOrHasChild(toElem))) {
                // Check that the coordinates are not directly over the cell
                int clientX = event.getClientX() + Window.getScrollLeft();
                int clientY = event.getClientY() + Window.getScrollTop();
                int rowLeft = highlightedRowElem.getAbsoluteLeft();
                int rowTop = highlightedRowElem.getAbsoluteTop();
                int rowWidth = highlightedRowElem.getOffsetWidth();
                int rowHeight = highlightedRowElem.getOffsetHeight();
                int rowBottom = rowTop + rowHeight;
                int rowRight = rowLeft + rowWidth;
                if (clientX > rowLeft && clientX < rowRight && clientY > rowTop && clientY < rowBottom) {
                    return;
                }

                // Unhighlight the current cell
                highlightCell(null);
            }
            break;

        // Select a row on click
        case Event.ONMOUSEDOWN: {
            // Ignore if selection is disabled
            if (!selectionEnabled) {
                return;
            }

            // Get the target row
            targetCell = getEventTargetCell(event);
            if (targetCell == null) {
                return;
            }
            targetRow = DOM.getParent(targetCell);
            int targetRowIndex = getRowIndex(targetRow);

            // Select the row
            if (selectionPolicy == SelectionPolicy.MULTI_ROW) {
                boolean shiftKey = DOM.eventGetShiftKey(event);
                boolean ctrlKey = DOM.eventGetCtrlKey(event) || DOM.eventGetMetaKey(event);

                // Prevent default text selection
                if (ctrlKey || shiftKey) {
                    event.preventDefault();
                }

                // Select the rows
                selectRow(targetRowIndex, ctrlKey, shiftKey);
            } else if (selectionPolicy == SelectionPolicy.ONE_ROW
                    || (selectionPolicy == SelectionPolicy.RADIO && targetCell == targetRow.getFirstChild())) {
                selectRow(-1, targetRow, true, true);
                lastSelectedRowIndex = targetRowIndex;
            }
        }
            break;

        // Prevent native inputs from being checked
        case Event.ONCLICK: {
            // Ignore if selection is disabled
            if (!selectionEnabled) {
                return;
            }

            // Get the target row
            targetCell = getEventTargetCell(event);
            if (targetCell == null) {
                return;
            }
            targetRow = DOM.getParent(targetCell);
            int targetRowIndex = getRowIndex(targetRow);

            // Select the row
            if (selectionPolicy == SelectionPolicy.CHECKBOX && targetCell == targetRow.getFirstChild()) {
                selectRow(targetRowIndex, true, DOM.eventGetShiftKey(event));
            }
        }
            break;
        }
    }

    @Override
    public void removeRow(int row) {
        deselectAllRows();
        super.removeRow(row);
    }

    /**
     * Select all rows in the table.
     */
    public void selectAllRows() {
        // Get the currently selected rows
        Set<Row> oldRowSet = getSelectedRowsSet();

        // Select all rows
        RowFormatter rowFormatter = getRowFormatter();
        int rowCount = getRowCount();
        for (int i = 0; i < rowCount; i++) {
            if (!selectedRows.containsKey(i)) {
                selectRow(i, rowFormatter.getElement(i), false, false);
            }
        }

        // Trigger the event
        fireRowSelectionEvent(oldRowSet);
    }

    /**
     * Select a row in the data table.
     * 
     * @param row the row index
     * @param unselectAll unselect all other rows first
     * @throws IndexOutOfBoundsException
     */
    public void selectRow(int row, boolean unselectAll) {
        selectRow(row, getRowFormatter().getElement(row), unselectAll, true);
    }

    /**
     * Select a row in the data table. Simulate the effect of a shift click and/or
     * control click. This method ignores the selection policy, which only applies
     * to user selection via mouse events.
     * 
     * @param row the row index
     * @param ctrlKey true to simulate a control click
     * @param shiftKey true to simulate a shift selection
     * @throws IndexOutOfBoundsException
     */
    public void selectRow(int row, boolean ctrlKey, boolean shiftKey) {
        // Check the row bounds
        checkRowBounds(row);

        // Get the old list of selected rows
        Set<Row> oldRowList = getSelectedRowsSet();

        // Deselect all rows
        if (!ctrlKey) {
            deselectAllRows(false);
        }

        boolean isSelected = selectedRows.containsKey(new Integer(row));
        if (shiftKey && (lastSelectedRowIndex > -1)) {
            // Shift+select rows
            SelectionGridRowFormatter formatter = getSelectionGridRowFormatter();
            int firstRow = Math.min(row, lastSelectedRowIndex);
            int lastRow = Math.max(row, lastSelectedRowIndex);
            lastRow = Math.min(lastRow, getRowCount() - 1);
            for (int curRow = firstRow; curRow <= lastRow; curRow++) {
                if (isSelected) {
                    deselectRow(curRow, false);
                } else {
                    selectRow(curRow, formatter.getRawElement(curRow), false, false);
                }
            }

            // Fire Event
            lastSelectedRowIndex = row;
            fireRowSelectionEvent(oldRowList);
        } else if (isSelected) {
            // Ctrl+unselect a selected row
            deselectRow(row, false);
            lastSelectedRowIndex = row;
            fireRowSelectionEvent(oldRowList);
        } else {
            // Select the row
            SelectionGridRowFormatter formatter = getSelectionGridRowFormatter();
            selectRow(row, formatter.getRawElement(row), false, false);
            lastSelectedRowIndex = row;
            fireRowSelectionEvent(oldRowList);
        }
    }

    /**
     * Enable or disable row selection.
     * 
     * @param enabled true to enable, false to disable
     */
    public void setSelectionEnabled(boolean enabled) {
        selectionEnabled = enabled;

        // Update the input elements
        if (selectionPolicy.hasInputColumn()) {
            SelectionGridCellFormatter formatter = getSelectionGridCellFormatter();
            int rowCount = getRowCount();
            for (int i = 0; i < rowCount; i++) {
                Element td = formatter.getRawElement(i, -1);
                setInputEnabled(selectionPolicy, td, enabled);
            }
        }
    }

    /**
     * Set the selection policy, which determines if the user can select zero,
     * one, or multiple rows.
     * 
     * @param selectionPolicy the selection policy
     */
    public void setSelectionPolicy(SelectionPolicy selectionPolicy) {
        if (this.selectionPolicy == selectionPolicy) {
            return;
        }
        deselectAllRows();

        // Update the input column
        if (selectionPolicy.hasInputColumn()) {
            if (this.selectionPolicy.hasInputColumn()) {
                // Update the existing input column
                String inputHtml = getInputHtml(selectionPolicy);
                for (int i = 0; i < numRows; i++) {
                    Element tr = getRowFormatter().getElement(i);
                    tr.getFirstChildElement().setInnerHTML(inputHtml);
                }
            } else {
                // Add an input column to every row
                String inputHtml = getInputHtml(selectionPolicy);
                Element td = createCell();
                td.setInnerHTML(inputHtml);
                for (int i = 0; i < numRows; i++) {
                    Element tr = getRowFormatter().getElement(i);
                    tr.insertBefore(td.cloneNode(true), tr.getFirstChildElement());
                }
            }
        } else if (this.selectionPolicy.hasInputColumn()) {
            // Remove the input column from every row
            for (int i = 0; i < numRows; i++) {
                Element tr = getRowFormatter().getElement(i);
                tr.removeChild(tr.getFirstChildElement());
            }
        }
        this.selectionPolicy = selectionPolicy;

        // Update the enabled state
        setSelectionEnabled(selectionEnabled);
    }

    @Override
    protected Element createRow() {
        Element tr = super.createRow();
        if (selectionPolicy.hasInputColumn()) {
            Element td = createCell();
            td.setPropertyString("align", "center");
            td.setInnerHTML(getInputHtml(selectionPolicy));
            DOM.insertChild(tr, td, 0);
            if (!selectionEnabled) {
                setInputEnabled(selectionPolicy, td, false);
            }
        }
        return tr;
    }

    /**
     * Deselect all selected rows in the data table.
     * 
     * @param fireEvent true to fire events
     */
    protected void deselectAllRows(boolean fireEvent) {
        // Get the old list of selected rows
        Set<Row> oldRows = null;
        if (fireEvent) {
            oldRows = getSelectedRowsSet();
        }

        // Deselect all rows
        boolean hasInputColumn = selectionPolicy.hasInputColumn();
        for (Element rowElem : selectedRows.values()) {
            setStyleName(rowElem, "selected", false);
            if (hasInputColumn) {
                setInputSelected(getSelectionPolicy(), (Element) rowElem.getFirstChildElement(), false);
            }
        }

        // Clear out the rows
        selectedRows.clear();

        // Fire event
        if (fireEvent) {
            fireRowSelectionEvent(oldRows);
        }
    }

    /**
     * Deselect a row in the grid. This method is safe to call even if the row is
     * not selected, or doesn't exist (out of bounds).
     * 
     * @param row the row index
     * @param fireEvent true to fire events
     */
    protected void deselectRow(int row, boolean fireEvent) {
        Element rowElem = selectedRows.remove(new Integer(row));
        if (rowElem != null) {
            // Get the old list of selected rows
            Set<Row> oldRows = null;
            if (fireEvent) {
                oldRows = getSelectedRowsSet();
            }

            // Deselect the row
            setStyleName(rowElem, "selected", false);
            if (selectionPolicy.hasInputColumn()) {
                setInputSelected(getSelectionPolicy(), (Element) rowElem.getFirstChildElement(), false);
            }

            // Fire Event
            if (fireEvent) {
                fireRowSelectionEvent(oldRows);
            }
        }
    }

    /**
     * Fire a {@link RowSelectionEvent}. This method will automatically add the
     * currently selected rows.
     * 
     * @param oldRowSet the set of previously selected rows
     */
    protected void fireRowSelectionEvent(Set<Row> oldRowSet) {
        Set<Row> newRowList = getSelectedRowsSet();
        if (newRowList.equals(oldRowSet)) {
            return;
        }
        fireEvent(new RowSelectionEvent(oldRowSet, newRowList));
    }

    @Override
    protected int getCellIndex(Element rowElem, Element cellElem) {
        int index = super.getCellIndex(rowElem, cellElem);
        if (selectionPolicy.hasInputColumn()) {
            index--;
        }
        return index;
    }

    @Override
    protected int getDOMCellCount(int row) {
        int count = super.getDOMCellCount(row);
        if (getSelectionPolicy().hasInputColumn()) {
            count--;
        }
        return count;
    }

    /**
     * Get the html used to create the native input selection element.
     * 
     * @param selectionPolicy the associated {@link SelectionPolicy}
     * @return the html representation of the input element
     */
    protected String getInputHtml(SelectionPolicy selectionPolicy) {
        String inputHtml = selectionPolicy.getInputHtml();
        if (inputHtml != null) {
            inputHtml = inputHtml.replace("%NAME%", "__gwtSelectionGrid" + id);
        }
        return inputHtml;
    }

    /**
     * @return a map or selected row indexes to their elements
     */
    protected Map<Integer, Element> getSelectedRowsMap() {
        return selectedRows;
    }

    /**
     * @return a list of selected rows to pass into a {@link RowSelectionEvent}
     */
    protected Set<Row> getSelectedRowsSet() {
        Set<Row> rowSet = new TreeSet<Row>();
        for (Integer rowIndex : selectedRows.keySet()) {
            rowSet.add(new Row(rowIndex.intValue()));
        }
        return rowSet;
    }

    /**
     * Set the current highlighted cell.
     * 
     * @param cellElem the cell element
     */
    protected void highlightCell(Element cellElem) {
        // Ignore if the cell is already being highlighted
        if (cellElem == highlightedCellElem) {
            return;
        }

        // Get the row element
        Element rowElem = null;
        if (cellElem != null) {
            rowElem = DOM.getParent(cellElem);
        }

        // Unhighlight the current cell
        if (highlightedCellElem != null) {
            setStyleName(highlightedCellElem, "highlighted", false);
            fireEvent(new CellUnhighlightEvent(highlightedRowIndex, highlightedCellIndex));
            highlightedCellElem = null;
            highlightedCellIndex = -1;

            // Unhighlight the current row if it changed
            if (rowElem != highlightedRowElem) {
                setStyleName(highlightedRowElem, "highlighted", false);
                fireEvent(new RowUnhighlightEvent(highlightedRowIndex));
                highlightedRowElem = null;
                highlightedRowIndex = -1;
            }
        }

        // Highlight the cell
        if (cellElem != null) {
            setStyleName(cellElem, "highlighted", true);
            highlightedCellElem = cellElem;
            highlightedCellIndex = OverrideDOM.getCellIndex(cellElem);

            // Highlight the row if it changed
            if (highlightedRowElem == null) {
                setStyleName(rowElem, "highlighted", true);
                highlightedRowElem = rowElem;
                highlightedRowIndex = getRowIndex(highlightedRowElem);
                fireEvent(new RowHighlightEvent(highlightedRowIndex));
            }

            // Fire listeners
            fireEvent(new CellHighlightEvent(highlightedRowIndex, highlightedCellIndex));
        }
    }

    /**
     * Select a row in the data table.
     * 
     * @param row the row index, or -1 if unknown
     * @param rowElem the row element
     * @param unselectAll true to unselect all currently selected rows
     * @param fireEvent true to fire the select event to listeners
     */
    protected void selectRow(int row, Element rowElem, boolean unselectAll, boolean fireEvent) {
        // Get the row index if needed
        if (row < 0) {
            row = getRowIndex(rowElem);
        }

        // Ignore request if row already selected
        Integer rowI = new Integer(row);
        if (selectedRows.containsKey(rowI)) {
            return;
        }

        // Get the old list of selected rows
        Set<Row> oldRowSet = null;
        if (fireEvent) {
            oldRowSet = getSelectedRowsSet();
        }

        // Deselect current rows
        if (unselectAll) {
            deselectAllRows(false);
        }

        // Select the new row
        selectedRows.put(rowI, rowElem);
        setStyleName(rowElem, "selected", true);
        if (selectionPolicy.hasInputColumn()) {
            setInputSelected(getSelectionPolicy(), (Element) rowElem.getFirstChildElement(), true);
        }

        // Fire grid listeners
        if (fireEvent) {
            fireRowSelectionEvent(oldRowSet);
        }
    }

    @Override
    protected void setBodyElement(Element element) {
        super.setBodyElement(element);
        if (!selectionEnabled) {
            setSelectionEnabled(selectionEnabled);
        }
    }

    /**
     * Enabled or disabled the native input element in the given cell. This method
     * should correspond with the HTML returned from {@link #getInputHtml}.
     * 
     * @param selectionPolicy the associated {@link SelectionPolicy}
     * @param td the cell containing the element
     * @param enabled true to enable, false to disable
     */
    protected void setInputEnabled(SelectionPolicy selectionPolicy, Element td, boolean enabled) {
        ((InputElement) td.getFirstChild()).setDisabled(!enabled);
    }

    /**
     * Select the native input element in the given cell. This method should
     * correspond with the HTML returned from {@link #getInputHtml}.
     * 
     * @param selectionPolicy the associated {@link SelectionPolicy}
     * @param td the cell containing the element
     * @param selected true to select, false to deselect
     */
    protected void setInputSelected(SelectionPolicy selectionPolicy, Element td, boolean selected) {
        ((InputElement) td.getFirstChild()).setChecked(selected);
    }
}