package com.gwt.ui.client.masterview;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.DoubleClickHandler;
import com.google.gwt.event.dom.client.HasDoubleClickHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
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.ui.FlexTable;
public class Grid extends FlexTable implements HasDoubleClickHandlers {
private int sortedColumn = -1;
private String sortType;
private final List<Column> columns = new ArrayList<Column>();
private boolean filteringEnabled;
private final DataSource dataSource;
private final GridRenderer renderer;
private boolean selectionEnabled = false;
private int selectedRow = -1;
/**
* Public constructor for the grid.
*
* @param dataSource source of the initialData items for the grid to render.
*/
@SuppressWarnings("unchecked")
public Grid(DataSource dataSource) {
this.dataSource = dataSource;
dataSource.addDataSourceListener(new DataSourceListener() {
@Override
public void onDataChanged(int readItemsCount, int allItemsCount) {
renderItems();
}
});
renderer = new GridRenderer(dataSource, this);
setStyleName(renderer.getGridStyle());
sortType = SortConstants.NO_SORTING;
super.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Cell cell = getCellForEvent(event);
if (cell.getRowIndex() >= 1) {
return;
}
sortColumn(cell.getCellIndex());
}
});
sinkEvents(Event.ONMOUSEOVER);
sinkEvents(Event.ONMOUSEOUT);
addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (selectionEnabled) {
int row = getCellForEvent(event).getRowIndex();
if (row >= getFirstRowWithDataNumber()) {
if (selectedRow >= getFirstRowWithDataNumber()) {
getRowFormatter().removeStyleName(selectedRow, "gwtcomp-SuperTableRowSelected");
}
selectedRow = row;
getRowFormatter().setStyleName(selectedRow, "gwtcomp-SuperTableRowSelected");
}
}
}
});
}
/**
* Renders the grid.
*/
public void render() {
renderer.renderHeader(columns);
if (isFilteringEnabled()) {
renderer.renderFilters(columns);
}
renderItems();
}
public void renderItems() {
int rowNumber = getFirstRowWithDataNumber();
int rowsForItems = renderer.renderItems(columns, dataSource);
int neededRowsCount = rowNumber + rowsForItems;
deleteExcessRows(neededRowsCount);
}
/**
* <p>
* Deletes redundant rows left from previous rendering (if necessary).
* </p>
*
* @param neededRowsCount
*/
protected void deleteExcessRows(int neededRowsCount) {
int rowsToDelete = getRowCount() - neededRowsCount;
while (rowsToDelete > 0) {
removeRow(getRowCount() - 1);
rowsToDelete--;
}
}
public int getFirstRowWithDataNumber() {
if (isFilteringEnabled()) {
return 2;
} else {
return 1;
}
}
/**
* <p>
* Method is overriden to render the grid after loading.
* </p>
*/
@Override
protected void onLoad() {
render();
}
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEOVER: {
Element td = getEventTargetCell(event);
if (td == null) {
return;
}
Element tr = DOM.getParent(td);
Element body = DOM.getParent(tr);
int row = DOM.getChildIndex(body, tr);
renderer.highlightRow(row);
break;
}
case Event.ONMOUSEOUT: {
Element td = getEventTargetCell(event);
if (td == null) {
return;
}
Element tr = DOM.getParent(td);
Element body = DOM.getParent(tr);
int row = DOM.getChildIndex(body, tr);
renderer.cancelRowHighlighting(row);
break;
}
default: {
// Do nothing
}
}
}
public void append(Column column) {
columns.add(column);
}
public void sortColumn(int columnIndex) {
if (sortedColumn != -1) {
getCellFormatter().setStyleName(0, sortedColumn, renderer.getHeaderCellStyle());
}
Column columnToSort = (Column)columns.get(columnIndex);
if (!columnToSort.isSortable()) {
return;
}
dataSource.setPropertyToSort(columnToSort.getPropertyName());
if (sortType.equals(SortConstants.NO_SORTING)) {
getCellFormatter().setStyleName(0, columnIndex, renderer.getCellAscendingSortingStyle());
sortType = SortConstants.SORT_ASC;
dataSource.setSortType(SortConstants.SORT_ASC);
} else if (sortType.equals(SortConstants.SORT_ASC)) {
getCellFormatter().removeStyleName(0, sortedColumn, renderer.getCellAscendingSortingStyle());
getCellFormatter().setStyleName(0, columnIndex, renderer.getCellDescendingSortingStyle());
sortType = SortConstants.SORT_DESC;
dataSource.setSortType(SortConstants.SORT_DESC);
} else if (sortType.equals(SortConstants.SORT_DESC)) {
getCellFormatter().removeStyleName(0, sortedColumn, renderer.getCellDescendingSortingStyle());
sortType = SortConstants.NO_SORTING;
dataSource.setSortType(SortConstants.NO_SORTING);
}
sortedColumn = columnIndex;
}
/**
* <p>
* Applies a filter (just a plain expression string) to a column.
* </p>
*
* @param column a column to which a filter will be applied.
* @param text a filter expression to apply.
*/
public void applyFilter(Column column, String text) {
dataSource.clearFiltersByProperty(column.getPropertyName());
dataSource.addFilter(new Filter(column.getPropertyName(), text));
}
public void removeFilter(Column column) {
dataSource.clearFiltersByProperty(column.getPropertyName());
}
public boolean isFilteringEnabled() {
return filteringEnabled;
}
public void setFilteringEnabled(boolean filteringEnabled) {
this.filteringEnabled = filteringEnabled;
}
public DataSource getDataSource() {
return dataSource;
}
public int getRowDataCount() {
return dataSource.isEmpty() ? 0 : getRowCount();
}
public boolean isSelectionEnabled() {
return selectionEnabled;
}
public void setSelectionEnabled(boolean selectionEnabled) {
this.selectionEnabled = selectionEnabled;
}
public int getSelectedRow() {
return selectedRow;
}
@Override
public HandlerRegistration addDoubleClickHandler(DoubleClickHandler handler) {
return addDomHandler(handler, DoubleClickEvent.getType());
}
}