use of org.gwtproject.cell.client.HasCell in project gwtproject by treblereel.
the class AbstractCellTable method onBrowserEvent2.
@Override
protected void onBrowserEvent2(Event event) {
// Get the event target.
EventTarget eventTarget = event.getEventTarget();
if (!Element.is(eventTarget)) {
return;
}
final Element target = event.getEventTarget().cast();
// Find the cell where the event occurred.
TableSectionElement tbody = getTableBodyElement();
TableSectionElement tfoot = getTableFootElement();
TableSectionElement thead = getTableHeadElement();
TableSectionElement targetTableSection = null;
TableCellElement targetTableCell = null;
Element cellParent = null;
// Header in the headerBuilder.
Element headerParent = null;
// Column in the headerBuilder.
Element headerColumnParent = null;
// Header in the footerBuilder.
Element footerParent = null;
// Column in the footerBuilder.
Element footerColumnParent = null;
{
Element maybeTableCell = null;
Element cur = target;
/*
* If an event happens in the TD element but outside the cell's div, we want
* to handle it as if it happened within the table cell.
*/
if (TableCellElement.TAG_TD.equalsIgnoreCase(cur.getTagName()) && tableBuilder.isColumn(cur.getFirstChildElement())) {
cur = cur.getFirstChildElement();
}
while (cur != null && targetTableSection == null) {
/*
* Found the table section. Return the most recent cell element that we
* discovered.
*/
if (cur == tbody || cur == tfoot || cur == thead) {
// We found the table section.
targetTableSection = cur.cast();
if (maybeTableCell != null) {
targetTableCell = maybeTableCell.cast();
break;
}
}
// Look for a table cell.
String tagName = cur.getTagName();
if (TableCellElement.TAG_TD.equalsIgnoreCase(tagName) || TableCellElement.TAG_TH.equalsIgnoreCase(tagName)) {
/*
* Found a table cell, but we can't return yet because it may be part
* of a sub table within the a CellTable cell.
*/
maybeTableCell = cur;
}
// Look for the most immediate cell parent if not already found.
if (cellParent == null && tableBuilder.isColumn(cur)) {
cellParent = cur;
}
/*
* Look for the most immediate header parent if not already found. Its
* possible that the footer or header will mistakenly identify a header
* from the other section, so we remember both. When we eventually reach
* the target table section element, we'll know for sure if its a header
* of footer.
*/
if (headerParent == null && headerBuilder.isHeader(cur)) {
headerParent = cur;
}
if (footerParent == null && footerBuilder.isHeader(cur)) {
footerParent = cur;
}
// Look for the most immediate column parent if not already found.
if (headerColumnParent == null && headerBuilder.isColumn(cur)) {
headerColumnParent = cur;
}
if (footerColumnParent == null && footerBuilder.isColumn(cur)) {
footerColumnParent = cur;
}
// Iterate.
cur = cur.getParentElement();
}
}
if (targetTableCell == null) {
return;
}
// parent.
if (legacyRenderRowValues) {
cellParent = targetTableCell.getFirstChildElement();
}
/*
* Forward the event to the associated header, footer, or column.
*/
TableRowElement targetTableRow = targetTableCell.getParentElement().cast();
String eventType = event.getType();
boolean isSelect = BrowserEvents.CLICK.equals(eventType) || (BrowserEvents.KEYDOWN.equals(eventType) && event.getKeyCode() == KeyCodes.KEY_ENTER);
int col = targetTableCell.getCellIndex();
if (targetTableSection == thead || targetTableSection == tfoot) {
boolean isHeader = (targetTableSection == thead);
headerParent = isHeader ? headerParent : footerParent;
Element columnParent = isHeader ? headerColumnParent : footerColumnParent;
boolean shouldSortColumn = true;
// Fire the event to the header.
if (headerParent != null) {
Header<?> header = isHeader ? headerBuilder.getHeader(headerParent) : footerBuilder.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;
}
}
}
// 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.
if (cellParent != null && !previewEvent.isCanceled()) {
HasCell<T, ?> column;
if (legacyRenderRowValues) {
column = columns.get(col);
} else {
column = tableBuilder.getColumn(context, value, cellParent);
}
if (column != null) {
fireEventToCell(event, eventType, cellParent, value, context, column);
}
}
}
}
Aggregations