/**
* AdvancedTable is GWT table widget that supports data paging, filtering
* and column sorting. Paging, filtering and sorting are done by the server
* side. The table uses a data provider, the class TableModelService.
*
* How to use it:
*
* AdvancedTable table = new AdvancedTable();
* TableModelServiceAsync someTableService =
* <create table model service async>;
* table.setTableModelService(usersTableService);
* RootPanel.get().add(table);
*
* (c) 2007 by Svetlin Nakov - http://www.nakov.com
* National Academy for Software Development - http://academy.devbg.org
* This software is freeware. Use it at your own risk.
*/
package example.client;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SourcesTableEvents;
import com.google.gwt.user.client.ui.TableListener;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HTMLTable.RowFormatter;
public class AdvancedTable extends Composite {
private static final int DEFAULT_PAGE_SIZE = 6;
private static final String DEFAULT_TABLE_WIDTH = "430px";
private static final String DEFAULT_TABLE_HEIGHT = "210px";
private static final int NAVIGATION_PANEL_HEIGHT = 26;
private static final int STATUS_INFO = 1001;
private static final int STATUS_ERROR = 1002;
private static final int STATUS_WAIT = 1003;
private static final String SORT_ASC_SYMBOL = " \u25b2";
private static final String SORT_DESC_SYMBOL = " \u25bc";
private static final String MARK_COLUMN_TITLE = "\u00bb";
private static final int NO_ROW_SELECTED = -1;
private static final String DEFAULT_ROW_STYLE = "advancedTableRow";
private static final String SELECTED_ROW_STYLE = "advancedTableSelectedRow";
private static final String NULL_DISPLAY_VALUE = " ";
private ScrollPanel scrollPanelGrid;
private HorizontalPanel navigationPanel;
private final Grid grid;
private final Label statusLabel;
private final Button buttonFirstPage;
private final Button buttonPrevPage;
private final Button buttonNextPage;
private final Button buttonLastPage;
private ArrayList rowSelectionListeners;
private int pageSize = DEFAULT_PAGE_SIZE;
private boolean firstColumnVisible = true;
private boolean allowRowMark = false;
private TableModelServiceAsync tableModelService;
private TableColumn[] columns;
private DataFilter[] filters;
private String[][] pageRows;
private int totalRowsCount;
private int currentPageRowsCount;
private int currentPageStartRow;
private int currentPageIndex;
private String sortColumnName;
private boolean sortOrder;
private int selectedRowIndex;
private Set markedRows = new HashSet();
public AdvancedTable() {
super();
final DockPanel contentDockPanel = new DockPanel();
initWidget(contentDockPanel);
contentDockPanel.setSize("100%", "100%");
this.setSize(DEFAULT_TABLE_WIDTH, DEFAULT_TABLE_HEIGHT);
scrollPanelGrid = new ScrollPanel();
scrollPanelGrid.setSize("100%", "100%");
contentDockPanel.add(scrollPanelGrid, DockPanel.CENTER);
contentDockPanel.setCellWidth(scrollPanelGrid, "100%");
contentDockPanel.setCellHeight(scrollPanelGrid, "100%");
grid = new Grid();
grid.setCellSpacing(0);
grid.setBorderWidth(1);
scrollPanelGrid.add(grid);
grid.setSize("100%", "100%");
// Display a preview of the table (when not in browser mode)
if (! GWT.isScript()) {
grid.resize(DEFAULT_PAGE_SIZE+1, 3);
grid.setText(0, 0, "Column 1");
grid.setText(0, 1, "Column 2");
grid.setText(0, 2, "Column 3");
}
// Add event handler to perform sorting on header column click
// and row selection on row click
this.grid.addTableListener(new TableListener() {
public void onCellClicked(SourcesTableEvents sender,
int row, int column) {
AdvancedTable.this.cellClicked(row, column);
}
});
navigationPanel = new HorizontalPanel();
contentDockPanel.add(navigationPanel, DockPanel.SOUTH);
navigationPanel.setSize("100%", "26px");
contentDockPanel.setCellHeight(navigationPanel, "26px");
contentDockPanel.setCellWidth(navigationPanel, "100%");
contentDockPanel.setCellVerticalAlignment(navigationPanel,
HasVerticalAlignment.ALIGN_BOTTOM);
final Button buttonRefresh = new Button();
navigationPanel.add(buttonRefresh);
navigationPanel.setCellHeight(buttonRefresh, "23px");
buttonRefresh.setSize("70", "23");
navigationPanel.setCellVerticalAlignment(buttonRefresh,
HasVerticalAlignment.ALIGN_BOTTOM);
buttonRefresh.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
AdvancedTable.this.buttonRefreshClicked();
}
});
buttonRefresh.setText("Refresh");
statusLabel = new Label();
navigationPanel.add(statusLabel);
statusLabel.setHeight("20px");
navigationPanel.setCellHeight(statusLabel, "23px");
navigationPanel.setCellHorizontalAlignment(
statusLabel, HasHorizontalAlignment.ALIGN_RIGHT);
navigationPanel.setCellVerticalAlignment(
statusLabel, HasVerticalAlignment.ALIGN_BOTTOM);
showStatus("Table model service not available.", STATUS_ERROR);
buttonFirstPage = new Button();
navigationPanel.add(buttonFirstPage);
navigationPanel.setCellHeight(buttonFirstPage, "23px");
buttonFirstPage.setSize("25", "23");
navigationPanel.setCellVerticalAlignment(buttonFirstPage,
HasVerticalAlignment.ALIGN_BOTTOM);
buttonFirstPage.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
AdvancedTable.this.buttonFirstPageClicked();
}
});
navigationPanel.setCellHorizontalAlignment(
buttonFirstPage, HasHorizontalAlignment.ALIGN_RIGHT);
navigationPanel.setCellWidth(buttonFirstPage, "30px");
buttonFirstPage.setText("<<");
buttonPrevPage = new Button();
navigationPanel.add(buttonPrevPage);
navigationPanel.setCellHeight(buttonPrevPage, "23px");
buttonPrevPage.setSize("20", "23");
navigationPanel.setCellVerticalAlignment(buttonPrevPage,
HasVerticalAlignment.ALIGN_BOTTOM);
buttonPrevPage.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
AdvancedTable.this.buttonPrevPageClicked();
}
});
navigationPanel.setCellHorizontalAlignment(
buttonPrevPage, HasHorizontalAlignment.ALIGN_RIGHT);
navigationPanel.setCellWidth(buttonPrevPage, "23px");
buttonPrevPage.setText("<");
buttonNextPage = new Button();
navigationPanel.add(buttonNextPage);
navigationPanel.setCellHeight(buttonNextPage, "23px");
buttonNextPage.setSize("20", "23");
navigationPanel.setCellVerticalAlignment(buttonNextPage,
HasVerticalAlignment.ALIGN_BOTTOM);
buttonNextPage.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
AdvancedTable.this.buttonNextPageClicked();
}
});
navigationPanel.setCellHorizontalAlignment(
buttonNextPage, HasHorizontalAlignment.ALIGN_RIGHT);
navigationPanel.setCellWidth(buttonNextPage, "23px");
buttonNextPage.setText(">");
buttonLastPage = new Button();
navigationPanel.add(buttonLastPage);
navigationPanel.setCellHeight(buttonLastPage