@Override
    public void setRowData(final int start, final List<? extends T> values) {
        final int valuesLength = values.size();
        final int valuesEnd = start + valuesLength;

        // Calculate the bounded start (inclusive) and end index (exclusive).
        final int pageStart = getPageStart();
        final int pageEnd = getPageStart() + getPageSize();
        final int boundedStart = Math.max(start, pageStart);
        final int boundedEnd = Math.min(valuesEnd, pageEnd);
        if (start != pageStart && boundedStart >= boundedEnd) {
            // The data is out of range for the current page.
            // Intentionally allow empty lists that start on the page start.
            return;
        }

        // Create placeholders up to the specified index.
        final PendingState<T> pending = ensurePendingState();
        final int cacheOffset = Math.max(0, boundedStart - pageStart - getVisibleItemCount());
        for (int i = 0; i < cacheOffset; i++) {
            pending.rowData.add(null);
        }

        // Insert the new values into the data array.
        for (int i = boundedStart; i < boundedEnd; i++) {
            final T value = values.get(i - start);
            final int dataIndex = i - pageStart;
            if (dataIndex < getVisibleItemCount()) {
                pending.rowData.set(dataIndex, value);
            } else {
                pending.rowData.add(value);
            }
        }

        // Remember the range that has been replaced.
        pending.replaceRange(boundedStart - cacheOffset, boundedEnd);

        // Fire a row count change event after updating the data.
        if (valuesEnd > getRowCount()) {
            setRowCount(valuesEnd, isRowCountExact());
        }
    }
Set the row index of the keyboard selected element.

@param index       the row index
@param stealFocus  true to steal focus
@param forceUpdate force the update even if the row didn't change
stroom-core-client-widget/src/main/java/com/google/gwt/user/cellview/client/HasDataPresenter.java