.getHeader(footerParent);
if (header != null) {
int headerIndex = isHeader ? headerBuilder.getRowIndex(targetTableRow) :
footerBuilder.getRowIndex(targetTableRow);
Context context = new Context(headerIndex, col, header.getKey());
if (cellConsumesEventType(header.getCell(), eventType)) {
header.onBrowserEvent(context, headerParent, event);
}
if (isSelect) {
// Preview the event, and possibily disable the column sort event. The event preview is
// forced even if the header cell does not consume click event
shouldSortColumn = header.onPreviewColumnSortEvent(context, headerParent, event);
}
}
}
// Sort the header.
if (isSelect && shouldSortColumn && columnParent != null) {
Column<T, ?> column =
isHeader ? headerBuilder.getColumn(columnParent) : footerBuilder
.getColumn(columnParent);
if (column != null && column.isSortable()) {
/*
* Force the headers to refresh the next time data is pushed so we
* update the sort icon in the header.
*/
headersDirty = true;
updatingSortList = true;
sortList.push(column);
updatingSortList = false;
ColumnSortEvent.fire(this, sortList);
}
}
} else if (targetTableSection == tbody) {
/*
* Get the row index of the data value. This may not correspond to the DOM
* row index if the user specifies multiple table rows per row object.
*/
int absRow = tableBuilder.getRowValueIndex(targetTableRow);
int relRow = absRow - getPageStart();
int subrow = tableBuilder.getSubrowValueIndex(targetTableRow);
if (!skipRowHoverCheck) {
boolean isRowChange = hoveringRow != targetTableRow;
if (BrowserEvents.MOUSEOVER.equals(eventType)) {
// Unstyle the old row if it is still part of the table.
if (hoveringRow != null && getTableBodyElement().isOrHasChild(hoveringRow)) {
setRowHover(hoveringRow, event, false, isRowChange);
}
hoveringRow = targetTableRow;
setRowHover(hoveringRow, event, true, isRowChange);
} else if (BrowserEvents.MOUSEOUT.equals(eventType) && hoveringRow != null) {
boolean unhover = true;
if (!skipRowHoverFloatElementCheck) {
// Ignore events happening directly over the hovering row. If there are floating element
// on top of the row, mouseout event should not be triggered. This is to avoid the flickring
// effect if the floating element is shown/hide based on hover event.
int clientX = event.getClientX() + Window.getScrollLeft();
int clientY = event.getClientY() + Window.getScrollTop();
int rowLeft = hoveringRow.getAbsoluteLeft();
int rowTop = hoveringRow.getAbsoluteTop();
int rowWidth = hoveringRow.getOffsetWidth();
int rowHeight = hoveringRow.getOffsetHeight();
int rowBottom = rowTop + rowHeight;
int rowRight = rowLeft + rowWidth;
unhover = clientX < rowLeft || clientX > rowRight || clientY < rowTop || clientY > rowBottom;
}
if (unhover) {
setRowHover(hoveringRow, event, false, isRowChange);
hoveringRow = null;
}
}
}
// If the event causes us to page, then the physical index will be out
// of bounds of the underlying data.
if (!isRowWithinBounds(relRow)) {
return;
}
/*
* Fire a preview event. The preview event is fired even if the TD does
* not contain a cell so the selection handler and keyboard handler have a
* chance to act.
*/
boolean isSelectionHandled =
handlesSelection
|| KeyboardSelectionPolicy.BOUND_TO_SELECTION == getKeyboardSelectionPolicy();
T value = getVisibleItem(relRow);
/*
* Create a new context based on the dom column index instead of using the
* user provided one from TableBuilder. We trigger cell preview events for
* table cells even if there is no associated Cell instance. If we used
* the user provided context, we could get inconsistent states where the
* Context is sometimes user provided and sometimes generated based on the
* DOM column index.
*/
Context context = new Context(absRow, col, getValueKey(value), subrow);
CellPreviewEvent<T> previewEvent =
CellPreviewEvent.fire(this, event, this, context, value, cellIsEditing,
isSelectionHandled);
// Pass the event to the cell.