package com.gwt.ui.client.supertable; import java.util.ArrayList; import java.util.Collections; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; 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.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwt.event.dom.client.KeyPressHandler; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; 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.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.HTML; 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.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; import com.gwt.ui.client.resources.Images; import com.gwt.ui.client.toolbar.Toolbar; import com.gwt.ui.client.toolbar.ToolbarPanel; /** * * @author ibouakl * */ public class SuperTable extends FlexTable implements HasDoubleClickHandlers { private static final String SORT_BY_SELECTED_ROWS = "Sort by selected rows"; private ColumnProperty[] columnsProperty; private ListBox commandList; private int currentPage = 0; private int headerRowCount = 0; private ArrayList<Widget> headers = new ArrayList<Widget>(); private ArrayList<SuperTableListener> listeners = new ArrayList<SuperTableListener>(); private Label pageNumLabel; private TextBox rpp; private int[] selectedCell = new int[] { -1, -1 }; private ArrayList<Integer> selectedRowIndices = new ArrayList<Integer>(); private ArrayList<Widget[]> tableContent = new ArrayList<Widget[]>(); private SuperTableProperty tableProperty; private ToolbarPanel toolbarPanel; private Toolbar userBar; private SuperTableColumnSelector sel; /** * An empty constructor for this class. If you use this constructor, please use the setter methods for setting the table and column * properties before adding any rows to the table. */ public SuperTable() { this(null, new SuperTableProperty()); } /** * A constructor for this class. The default value for the table properties is user if this constructor is used. * * @param columnsProperty column property object */ public SuperTable(ColumnProperty[] columnsProperty) { this(columnsProperty, new SuperTableProperty()); } /** * A constructor for this class with the column and table property objects supplied as parameters. * * @param columnsProperty tableProperty for each column in the table. * @param tableProperty table tableProperty. */ public SuperTable(ColumnProperty[] columnsProperty, SuperTableProperty properties) { super(); this.columnsProperty = columnsProperty; this.tableProperty = properties; properties.setParent(this); setStyleName("gwtcomp-SuperTable"); if (columnsProperty != null) { populateHeader(); } initTableListener(); sinkEvents(Event.ONMOUSEOVER); sinkEvents(Event.ONMOUSEOUT); } public void clearData() { removeAllRows(); clear(); init(); if (columnsProperty != null) { populateHeader(); } initTableListener(); } private void init() { headerRowCount = 0; currentPage = 0; selectedRowIndices = new ArrayList<Integer>(); headers = new ArrayList<Widget>(); tableContent = new ArrayList<Widget[]>(); selectedCell = new int[] { -1, -1 }; setStyleName("gwtcomp-SuperTable"); } /** * Add a row to the table * * @param row widgets belonging to the row, each element in the array contains a column entry for the row. */ public void addRow(Widget[] row) { addRow(row, false); } /** * Add a row to the table and set it to selected. * * @param row widgets belonging to the row, each element in the array contains a column entry for the row. * @param selected whether the row is selected (will only be set to selected if SuperTableProperty.rowSelectionEnabled() is set to * true). */ public void addRow(Widget[] row, boolean selected) { int count = tableContent.size(); int index = getRowCount(); tableContent.add(row); if (tableProperty.isRowSelectionEnabled() && selected) { selectedRowIndices.add(new Integer(count)); } else { selected = false; } setCurrentPageLabel(); int start = getFirstRowIndex(); if ((tableProperty.isPagingEnabled()) && (count >= start + tableProperty.getRecordsPerPage())) { if (selected) { dispatchRowSelectionEvent(count, selected, row); } return; } String rownum = Integer.toString(count + 1); HTML rowindex = new HTML(tableProperty.isRowSelectionEnabled() ? HTMLHelper.boxedText(rownum) : rownum); if (tableProperty.isRowSelectionEnabled()) { CheckBox checkBox = new CheckBox(); checkBox.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { int row = getCellForEvent(event).getRowIndex(); int rindex = 0; if (tableProperty.isPagingEnabled()) { rindex = ((currentPage * tableProperty.getRecordsPerPage()) + (row - headerRowCount)); } else { rindex = row - headerRowCount; } int loc = findInSelectedIndices(rindex); boolean selected = false; if (loc >= 0) // already selected { selected = false; selectedRowIndices.remove(loc); } else // not selected { selected = true; selectedRowIndices.add(new Integer(rindex)); } setRowStyle(selected, row); Widget[] w = tableContent.get(rindex); dispatchRowSelectionEvent(rindex, selected, w); } }); setWidget(index, 0, checkBox); } else { setWidget(index, 0, rowindex); } getCellFormatter().setStyleName(index, 0, "gwtcomp-SuperTableCell"); getCellFormatter().setHorizontalAlignment(index, 0, HasHorizontalAlignment.ALIGN_CENTER); getCellFormatter().setVerticalAlignment(index, 0, HasVerticalAlignment.ALIGN_MIDDLE); if (tableProperty.isRowSelectionEnabled()) { rowindex.setStyleName("gwtcomp-SuperTableRowSelector"); } int col = 1; for (int i = 0; i < row.length; i++) { if (columnsProperty[i].isDisplayed() == false) { continue; } setWidget(index, col, row[i]); getCellFormatter().setStyleName(index, col, "gwtcomp-SuperTableCell"); getCellFormatter().setHorizontalAlignment(index, col, columnsProperty[i].getHorizontalAlignment()); getCellFormatter().setVerticalAlignment(index, col, columnsProperty[i].getVerticalAlignment()); col++; } setRowStyle(selected, index); if (selected == true) { dispatchRowSelectionEvent(count, selected, row); } } /** * Add a table listener. The listener can be used by the application to get notified of various events. * * @param listener the listener object. */ public void addTableListener(SuperTableListener listener) { listeners.add(listener); } /** * Add an entry into the user tool bar. The user toolbar is added at the top of the table header. It is to the right of the table * navigation (next, previous, first, etc.) toolbar. An application can add one or more widgets into this toolbar. * * @param w the widget to add. */ public void addToUserToolbar(Widget w) { if (userBar == null) { return; } userBar.addWidget(w); toolbarPanel.redraw(); } /** * Adds a user header. The application may add zero or more application-specific header. The header is added in a new row immediately * above the table header. * * @param widget the widget to add. Normally, a panel of some type is added. */ public void addUserHeader(Widget widget) { headers.add(widget); removeAllColumns(false); populateBody(); } /* * Removes all columns except the header columns. * * @see com.google.gwt.user.client.ui.HTMLTable#clear() */ public void clear() { removeAllColumns(true); } /** * Delete a row from the table. * * @param index the index starting with 0. */ public void deleteRow(int index) { // if the cell was selected, unselect it if (selectedCell[0] == index) { dispatchCellSelectionEvent(index, selectedCell[1], false, tableContent.get(selectedCell[0])[selectedCell[1]]); selectedCell[0] = -1; selectedCell[1] = -1; } int sel = findInSelectedIndices(index); if (sel >= 0) { dispatchRowSelectionEvent(index, false, tableContent.get(sel)); // adjust the rest of the selected items int size = selectedRowIndices.size(); for (int i = sel + 1; i < size; i++) { int n = selectedRowIndices.get(i).intValue(); selectedRowIndices.set(i, new Integer(n - 1)); } selectedRowIndices.remove(sel); } tableContent.remove(index); int start = getFirstRowIndex(); if ((tableProperty.isPagingEnabled()) && (index >= start + tableProperty.getRecordsPerPage())) { // outside of the current page, no display action required except // displaying the page. setCurrentPageLabel(); return; } removeAllColumns(false); populateBody(); } /** * Returns the column property object. * * @return Returns the columnsProperty. */ public ColumnProperty[] getColumnsProperty() { return columnsProperty; } /** * Returns the list box containing the application-defined list action items. This list box is located inside the command toolbar. * Applications can add their own items and listeners to the list. * * @return Returns the commandList. */ public ListBox getCommandList() { return commandList; } /** * Returns the row count in a current page. If paging is not enabled, the record count is the number of rows. If paging is enabled, the * size is determined by the rows per page table property. * * @return record count */ public int getCurrentPageRecordCount() { int records = getRowCount() - headerRowCount; return records; } /** * Returns the index of the first row in the current page. If paging is not enabled, the index is zero. * * @return the first row index */ public int getFirstRowIndex() { if (!tableProperty.isPagingEnabled()) { return 0; } int start = tableProperty.getRecordsPerPage() * currentPage; return start; } /** * Returns all the rows entries (and columns) * * @return the rows */ public Widget[][] getRows() { return (Widget[][])tableContent.toArray(); } /** * Return the number of rows. * * @return the number of rows */ public int getRowSize() { return tableContent.size(); } /** * Returns the user-selected cell. The first element in the returned array contains the row index and the second element contains the * column index. * * @return A null is returned if the user has not selected a row. */ public int[] getSelectedCell() { if ((selectedCell[0] == -1) || (selectedCell[1] == -1)) { return null; } return selectedCell; } /** * Returns the selected row index. If multiple rows are selected, only the first one is returned. * * @return the row index starting with 0, -1 if no rows are selected. */ public int getSelectedRowIndex() { int size = selectedRowIndices.size(); if (size == 0) { return -1; } return selectedRowIndices.get(0).intValue(); } /** * Returns the indicies of the selected rows. * * @return If no rows are selected, an empty array is returned. */ public int[] getSelectedRowIndices() { int size = selectedRowIndices.size(); int[] ret = new int[size]; for (int i = 0; i < size; i++) { ret[i] = selectedRowIndices.get(i).intValue(); } return ret; } /** * Returns the content of the table in array list format. * * @return Returns the tableContent. */ public ArrayList<Widget[]> getTableContent() { return tableContent; } /** * Returns the table property. * * @return Returns the SuperTableProperty object associated with this table. */ public SuperTableProperty getTableProperty() { return tableProperty; } /** * Returns the toolbar panel object on the first row. Applications can add their own toolbars into this panel. However, applications can * also use the user tool bar which is part of this panel. * * @return Returns the toolbarPanel. */ public ToolbarPanel getToolbarPanel() { return toolbarPanel; } /** * Returns the user tool bar. * * @return Returns the userBar. */ public Toolbar getUserBar() { return userBar; } /** * Is the given cell selected? * * @param row row index * @param col column index * @return true if the cell is selected. */ public boolean isCellSelected(int row, int col) { return ((row == selectedCell[0]) && (col == selectedCell[1])) ? true : false; } /** * Check if a row is in the current page. If the table property has the paging set, the table content is displayed one page at a time. * Therefore a given row may not be in the currently-displayed page. * * @param row the row number starting with 0. * @return true if the row is in the current page. */ public boolean isRowInPage(int row) { return (row >= getFirstRowIndex()) && (row < getFirstRowIndex() + getCurrentPageRecordCount()); } /** * Returns if the row is selected. * * @param row row number starting with 0. * @return true if the row is selected, false otherwise. */ public boolean isRowSelected(int row) { int index = findInSelectedIndices(row); return index >= 0 ? true : false; } /** * Remove a table listener. * * @param listener the listener object to remove. */ public void removeTableListener(SuperTableListener listener) { listeners.remove(listener); } /** * Replaces the widget in a given cell with a new one. * * @param w the new widget object. * @param row row index * @param col column index */ public void setCell(Widget w, int row, int col) { Widget[] columns = tableContent.get(row); columns[col] = w; setRow(columns, row); } /** * Select/deselect a cell. This method is not yet implemented. * * @param row * @param col * @param selected */ public void setCellSelected(int row, int col, boolean selected) { if (!tableProperty.isCellSelectionEnabled()) { return; } Window.alert("setCellSelected() is not yet implemented. Sorry!"); } /** * Sets the column property. This method must be called prior to adding the first row. * * @param columnsProperty The columnsProperty to set. */ public void setColumnsProperty(ColumnProperty[] columnsProperty) { this.columnsProperty = columnsProperty; populateHeader(); } /** * Replaces a row with a new row. All row and cell attributes remain the same. * * @param row the new row * @param index the row index. */ public void setRow(Widget[] row, int index) { setRow(row, index, null); } public boolean downRow(int index) { if (index < headerRowCount + getRowSize() - 1) { Widget[] x = tableContent.get(index - headerRowCount); Widget[] y = tableContent.get(index + 1 - headerRowCount); tableContent.set(index - headerRowCount, y); tableContent.set(index + 1 - headerRowCount, x); populateBody(); return true; } return false; } public boolean upRow(int index){ if(index> headerRowCount){ Widget[] x = tableContent.get(index - headerRowCount); Widget[] y = tableContent.get(index - 1 - headerRowCount); tableContent.set(index - headerRowCount, y); tableContent.set(index - 1 - headerRowCount, x); populateBody(); return true; } return false; } /** * Replaces a row with a new row. * * @param row the new row * @param index the row index * @param selected if set to null, the row attribute is not modified; if not null, the row is set selected or not according to the * value. */ public void setRow(Widget[] row, int index, Boolean selected) { tableContent.set(index, row); boolean dispatch = false; if (selected != null) { int sel = findInSelectedIndices(index); if (tableProperty.isRowSelectionEnabled() && selected.booleanValue()) { if (sel < 0) { dispatch = true; selectedRowIndices.add(new Integer(index)); } } else { if (sel >= 0) { dispatch = true; selectedRowIndices.remove(sel); } } } int start = getFirstRowIndex(); if ((tableProperty.isPagingEnabled()) && (index >= start + tableProperty.getRecordsPerPage())) { if (dispatch) { dispatchRowSelectionEvent(index, selected.booleanValue(), row); } return; } int ind = index + headerRowCount - start; String rownum = Integer.toString(index + 1); HTML rowindex = new HTML(tableProperty.isRowSelectionEnabled() ? HTMLHelper.boxedText(rownum) : rownum); setWidget(ind, 0, rowindex); getCellFormatter().setStyleName(ind, 0, "gwtcomp-SuperTableCell"); getCellFormatter().setHorizontalAlignment(ind, 0, HasHorizontalAlignment.ALIGN_CENTER); getCellFormatter().setVerticalAlignment(ind, 0, HasVerticalAlignment.ALIGN_MIDDLE); if (tableProperty.isRowSelectionEnabled()) { rowindex.setStyleName("gwtcomp-SuperTableRowSelector"); } int col = 1; for (int i = 0; i < row.length; i++) { if (columnsProperty[i].isDisplayed() == false) { continue; } setWidget(ind, col, row[i]); if ((selectedCell[0] == index) && (selectedCell[1] == i)) { getCellFormatter().setStyleName(ind, col, "gwtcomp-SuperTableCellSelected"); } else { getCellFormatter().setStyleName(ind, col, "gwtcomp-SuperTableCell"); } getCellFormatter().setHorizontalAlignment(ind, col, columnsProperty[i].getHorizontalAlignment()); getCellFormatter().setVerticalAlignment(ind, col, columnsProperty[i].getVerticalAlignment()); col++; } if (selected != null) { setRowStyle(selected.booleanValue(), ind); } if (dispatch) { dispatchRowSelectionEvent(index, selected.booleanValue(), row); } } /** * Select or deselect a row. * * @param row row index * @param selected true or false. */ public void setRowSelected(int row, boolean selected) { if (!tableProperty.isRowSelectionEnabled()) { return; } Widget[] w = tableContent.get(row); setRow(w, row, new Boolean(selected)); } /** * Sets the table property. This method must be called prior to adding the first row and after calling the setColumnsProperty() method * for it to work properly. * * @param tableProperty The tableProperty to set. */ public void setTableProperty(SuperTableProperty tableProperty) { this.tableProperty = tableProperty; tableProperty.setParent(this); populateHeader(); } private int countPages() { if (!tableProperty.isPagingEnabled()) { return 1; } if (tableProperty.getRecordsPerPage() == 0) { return 0; } int pages = tableContent.size() / tableProperty.getRecordsPerPage(); if (tableContent.size() % tableProperty.getRecordsPerPage() > 0) { pages++; } return pages; } private int countVisibleColumns() { int size = columnsProperty.length; for (int i = 0; i < columnsProperty.length; i++) { if (!columnsProperty[i].isDisplayed()) { size--; } } return size; } private void dispatchCellSelectionEvent(int row, int col, boolean select, Widget w) { if (!tableProperty.isCellSelectionEnabled()) { return; } for (int i = 0; i < listeners.size(); i++) { SuperTableListener listener = listeners.get(i); listener.cellSelected(select, row, col, w); } } private void dispatchRowSelectionEvent(int index, boolean selected, Widget[] w) { if (!tableProperty.isRowSelectionEnabled()) { return; } for (int i = 0; i < listeners.size(); i++) { SuperTableListener listener = listeners.get(i); listener.rowSelected(selected, index, w); } } private int findInSelectedIndices(int index) { int loc = -1; for (int i = 0; i < selectedRowIndices.size(); i++) { Integer sel = selectedRowIndices.get(i); if (sel.intValue() == index) { loc = i; break; } } return loc; } private void initColumnHeaders() { getRowFormatter().setVerticalAlign(headerRowCount, HasVerticalAlignment.ALIGN_TOP); class SortListener implements ClickHandler { private boolean asc; private int column; public SortListener(boolean asc, int column) { this.asc = asc; this.column = column; } @Override public void onClick(ClickEvent arg0) { processSort(column, asc); } } getCellFormatter().setStyleName(headerRowCount, 0, "gwtcomp-SuperTableHeader"); initAllRowSelector(); int col = 1; for (int i = 0; i < columnsProperty.length; i++) { if (!columnsProperty[i].isDisplayed()) { continue; } HorizontalPanel hp = new HorizontalPanel(); if (columnsProperty[i].getAscendingSortComparator() != null) { Image asc_link = new Image(Images.IMAGES.downIcon()); asc_link.addStyleName("gwtcomp-SortArrow"); asc_link.setTitle("Sort in ascending order"); asc_link.addClickHandler(new SortListener(true, i)); hp.add(asc_link); } if (columnsProperty[i].getDescendingSortComparator() != null) { Image dsc_link = new Image(Images.IMAGES.upIcon()); dsc_link.addStyleName("gwtcomp-SortArrow"); dsc_link.setTitle("Sort in descending order"); dsc_link.addClickHandler(new SortListener(false, i)); hp.add(dsc_link); } hp.add(new HTML(HTMLHelper.bold(columnsProperty[i].getHeader()))); getCellFormatter().setStyleName(headerRowCount, col, "gwtcomp-SuperTableHeader"); if (columnsProperty[i].getWidth() != null) { getCellFormatter().setWidth(headerRowCount, col, columnsProperty[i].getWidth()); } getCellFormatter().setWordWrap(headerRowCount, col, false); setWidget(headerRowCount, col++, hp); } headerRowCount++; } private void initAllRowSelector() { if (!tableProperty.isRowSelectionEnabled()) { return; } CheckBox selectall = new CheckBox(); selectall.setTitle("Select all rows"); setWidget(headerRowCount, 0, selectall); getCellFormatter().setHorizontalAlignment(headerRowCount, 0, HasHorizontalAlignment.ALIGN_CENTER); selectall.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent sender) { int start = getFirstRowIndex(); int records = 0; if (tableProperty.isPagingEnabled()) { records = tableProperty.getRecordsPerPage(); if (start + tableProperty.getRecordsPerPage() > tableContent.size()) { records = tableContent.size() - start; } } else { records = tableContent.size(); } CheckBox box = (CheckBox)sender.getSource(); if (box.getValue()) // select all { for (int i = 0; i < records; i++) { // go through all the visible items and select them int loc = findInSelectedIndices(start + i); if (loc >= 0) // already selected { continue; } processRowSelectionEvent(i + headerRowCount, start + i); } } else // unselect all { // go through all the visible items and unselect them for (int i = 0; i < records; i++) { // go through all the visible items and unselect // them int loc = findInSelectedIndices(start + i); if (loc < 0) // already unselected { continue; } processRowSelectionEvent(i + headerRowCount, start + i); } } } }); } private void initColumnSelector() { Toolbar bar = new Toolbar(); bar.setHorizontalSpacing(10); Image img = new Image(Images.IMAGES.rebuildIcon()); bar.addWidget(img); img.setTitle("Show/Hide columns"); img.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent sender) { sel = new SuperTableColumnSelector(columnsProperty, new SuperTableColumnSelectorListener() { public void columnSelectionChanged(ColumnProperty[] columns) { columnsProperty = columns; removeAllColumns(false); populateBody(); } }); sel.setPopupPosition(sender.getRelativeElement().getAbsoluteLeft(), sender.getRelativeElement().getAbsoluteTop() + 10); sel.show(); } }); toolbarPanel.addToolbar(bar); } private void initCommandBar() { Toolbar sbar = new Toolbar(); sbar.setHorizontalSpacing(10); commandList = new ListBox(); commandList.setWidth("100px"); commandList.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent arg0) { if (isSortBySelected()) { ArrayList<Widget[]> selected = new ArrayList<Widget[]>(); for (int i = 0; i < selectedRowIndices.size(); i++) { int index = selectedRowIndices.get(i).intValue(); Widget[] row = tableContent.get(index); selected.add(row); } int size = selected.size(); selectedRowIndices.clear(); for (int i = 0; i < size; i++) { tableContent.remove(selected.get(i)); tableContent.add(0, selected.get(i)); selectedRowIndices.add(new Integer(i)); } currentPage = 0; removeAllColumns(false); populateBody(); } } }); sbar.addWidget(commandList); commandList.addItem("None"); toolbarPanel.addToolbar(sbar); } private void initPagingBar() { Toolbar pbar = new Toolbar(); pbar.setHorizontalSpacing(10); Image first = new Image(Images.IMAGES.startIcon()); first.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent arg0) { currentPage = 0; removeAllColumns(false); populateBody(); } }); pbar.addWidget(first); first.setTitle("First page"); Image next = new Image(Images.IMAGES.nextIcon()); next.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent arg0) { if (currentPage >= countPages() - 1) { return; } currentPage++; removeAllColumns(false); populateBody(); } }); pbar.addWidget(next); next.setTitle("Next Page"); Image prev = new Image(Images.IMAGES.previousIcon()); prev.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent arg0) { if (currentPage <= 0) { return; } currentPage--; removeAllColumns(false); populateBody(); } }); pbar.addWidget(prev); prev.setTitle("Previous Page"); Image last = new Image(Images.IMAGES.finishIcon()); last.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent arg0) { currentPage = countPages() - 1; removeAllColumns(false); populateBody(); } }); pbar.addWidget(last); last.setTitle("Last Page"); HorizontalPanel records = new HorizontalPanel(); records.setSpacing(2); records.add(new Label("Records/Page")); rpp = new TextBox(); rpp.addKeyDownHandler(new KeyDownHandler() { @Override public void onKeyDown(KeyDownEvent arg0) { // TODO Auto-generated method stub } }); rpp.addKeyUpHandler(new KeyUpHandler() { @Override public void onKeyUp(KeyUpEvent arg0) { // TODO Auto-generated method stub } }); rpp.addKeyPressHandler(new KeyPressHandler() { @Override public void onKeyPress(KeyPressEvent event) { if (KeyCodes.KEY_ENTER == event.getNativeEvent().getKeyCode()) { processRecordsPerPageChange(); } } }); rpp.setMaxLength(3); rpp.setVisibleLength(3); rpp.setText(tableProperty.getRecordsPerPage() + ""); records.add(rpp); Button display = new Button("Display"); display.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent arg0) { processRecordsPerPageChange(); } }); records.add(display); pageNumLabel = new Label("000/000"); records.add(pageNumLabel); pbar.addWidget(records); toolbarPanel.addToolbar(pbar); } private void initTableActions() { if (tableProperty.isCommandBarEnabled()) { commandList.addItem(SORT_BY_SELECTED_ROWS); } } /** * Method to add css (highlight) on mouse over and on mouse out. When the user move the mouse on a row, we change the color. * * @author ibouakl */ 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);// get the index row getRowFormatter().addStyleName(row, "gwtcomp-grid-row-highlight");// add the style gwtcomp-grid-row-highlight 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);// get the index row getRowFormatter().removeStyleName(row, "gwtcomp-grid-row-highlight");// remove the style gwtcomp-grid-row-highlight break; } default: { // Do nothing } } } /** * init the listeners * * @author ibouakl */ private void initTableListener() { addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { Cell cell = getCellForEvent(event); processTableEvent(cell.getRowIndex(), cell.getCellIndex()); } }); } private void initToolbar() { if (!tableProperty.isToolbarEnabled()) { return; } toolbarPanel = new ToolbarPanel(); getFlexCellFormatter().setColSpan(0, 0, countVisibleColumns() + 1); setWidget(headerRowCount++, 0, toolbarPanel); if (tableProperty.isColumnSelectorEnabled()) { initColumnSelector(); } if (tableProperty.isPagingEnabled()) { initPagingBar(); } if (tableProperty.isCommandBarEnabled()) { initCommandBar(); } initUserBar(); if (tableProperty.isRowSelectionEnabled()) { initTableActions(); } } private void initUserBar() { if (userBar == null) { userBar = new Toolbar(); userBar.setHorizontalSpacing(10); } toolbarPanel.addToolbar(userBar); } private void initUserHeaders() { for (int i = 0; i < headers.size(); i++) { Widget w = headers.get(i); setWidget(headerRowCount++, 0, w); getFlexCellFormatter().setColSpan(headerRowCount - 1, 0, countVisibleColumns() + 1); w.setWidth("100%"); } } private boolean isSortBySelected() { if (commandList == null) { return false; } int index = commandList.getSelectedIndex(); if (index < 0) { return false; } if (!commandList.getItemText(index).equals(SORT_BY_SELECTED_ROWS)) { return false; } return true; } private void populateBody() { int start = getFirstRowIndex(); int records = 0; if (tableProperty.isPagingEnabled()) { records = tableProperty.getRecordsPerPage(); if (start + tableProperty.getRecordsPerPage() > tableContent.size()) { records = tableContent.size() - start; } } else { records = tableContent.size(); } for (int i = 0; i < records; i++) { String rownum = Integer.toString(start + i + 1); HTML rowindex = new HTML(tableProperty.isRowSelectionEnabled() ? HTMLHelper.boxedText(rownum) : rownum); // setWidget(i + headerRowCount, 0, rowindex); getCellFormatter().setStyleName(i + headerRowCount, 0, "gwtcomp-SuperTableCell"); getCellFormatter().setHorizontalAlignment(i + headerRowCount, 0, HasHorizontalAlignment.ALIGN_CENTER); getCellFormatter().setVerticalAlignment(i + headerRowCount, 0, HasVerticalAlignment.ALIGN_MIDDLE); if (tableProperty.isRowSelectionEnabled()) { rowindex.setStyleName("gwtcomp-SuperTableRowSelector"); CheckBox checkBox = new CheckBox(); checkBox.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { int row = getCellForEvent(event).getRowIndex(); int rindex = 0; if (tableProperty.isPagingEnabled()) { rindex = ((currentPage * tableProperty.getRecordsPerPage()) + (row - headerRowCount)); } else { rindex = row - headerRowCount; } int loc = findInSelectedIndices(rindex); boolean selected = false; if (loc >= 0) // already selected { selected = false; selectedRowIndices.remove(loc); } else // not selected { selected = true; selectedRowIndices.add(new Integer(rindex)); } setRowStyle(selected, row); Widget[] w = tableContent.get(rindex); dispatchRowSelectionEvent(rindex, selected, w); } }); setWidget(i + headerRowCount, 0, checkBox); } else { setWidget(i + headerRowCount, 0, rowindex); } Widget[] row = tableContent.get(i + start); int col = 1; for (int j = 0; j < row.length; j++) { if (columnsProperty[j].isDisplayed() == false) { continue; } setWidget(i + headerRowCount, col, row[j]); getCellFormatter().setHorizontalAlignment(i + headerRowCount, col, columnsProperty[j].getHorizontalAlignment()); getCellFormatter().setVerticalAlignment(i + headerRowCount, col, columnsProperty[j].getVerticalAlignment()); if ((selectedCell[0] == i + start) && (selectedCell[1] == j)) { getCellFormatter().setStyleName(i + headerRowCount, col, "gwtcomp-SuperTableCellSelected"); } else { getCellFormatter().setStyleName(i + headerRowCount, col, "gwtcomp-SuperTableCell"); } col++; } int selected = findInSelectedIndices(i + start); setRowStyle((selected >= 0 ? true : false), i + headerRowCount); if (getWidget(i + headerRowCount, 0) instanceof CheckBox) ((CheckBox)getWidget(i + headerRowCount, 0)).setValue((selected >= 0 ? true : false)); } setCurrentPageLabel(); } private void populateHeader() { initToolbar(); initUserHeaders(); initColumnHeaders(); } private void processCellSelectionEvent(int row, int cell, int rindex) { // some columns may be hidden because of the column selector. // Find out the correct column number. int cindex = 0; for (int i = 0; i < columnsProperty.length; i++) { if (!columnsProperty[i].isDisplayed()) { cindex++; } if (i == (cell - 1)) { break; } } cindex += (cell - 1); boolean select = false; if ((rindex == selectedCell[0]) && (cindex == selectedCell[1])) { select = false; getCellFormatter().setStyleName(row, cell, "gwtcomp-SuperTableCell"); selectedCell[0] = -1; selectedCell[1] = -1; } else { select = true; // remove the style of the previously selected cell if ((selectedCell[0] >= 0) && (selectedCell[1] >= 0)) { if (isRowInPage(selectedCell[0])) { int r = headerRowCount + selectedCell[0] - getFirstRowIndex(); getCellFormatter().setStyleName(r, selectedCell[1] + 1, "gwtcomp-SuperTableCell"); } } selectedCell[0] = rindex; selectedCell[1] = cindex; getFlexCellFormatter().setStyleName(row, cell, "gwtcomp-SuperTableCellSelected"); } Widget w = tableContent.get(rindex)[cindex]; dispatchCellSelectionEvent(rindex, cindex, select, w); } private void processRecordsPerPageChange() { int r = tableProperty.getRecordsPerPage(); try { r = Integer.parseInt(rpp.getText().trim()); if (r == 0) { // set it back to what it was before rpp.setText(tableProperty.getRecordsPerPage() + ""); return; } } catch (NumberFormatException e) { // set it back to what it was before rpp.setText(r + ""); return; } currentPage = 0; // reset the page number tableProperty.setRecordsPerPage(r); removeAllColumns(false); populateBody(); } private void processRowSelectionEvent(int row, int rindex) { int loc = findInSelectedIndices(rindex); boolean selected = false; if (loc >= 0) // already selected { selected = false; selectedRowIndices.remove(loc); } else // not selected { selected = true; selectedRowIndices.add(new Integer(rindex)); } setRowStyle(selected, row); if (getWidget(row, 0) instanceof CheckBox) ((CheckBox)getWidget(row, 0)).setValue(selected); Widget[] w = tableContent.get(rindex); dispatchRowSelectionEvent(rindex, selected, w); } private void processSort(int col, boolean asc) { int start = getFirstRowIndex(); int records = getCurrentPageRecordCount(); Widget selcell = null; if ((selectedCell[0] >= 0) && (selectedCell[1] >= 0)) { if (isRowInPage(selectedCell[0])) { selcell = tableContent.get(selectedCell[0])[selectedCell[1]]; } } // Copy the table content of this page into a separate array. // Also, save information on the selected rows ArrayList<Widget[]> selected = new ArrayList<Widget[]>(); ArrayList<Widget[]> list = new ArrayList<Widget[]>(); for (int i = 0; i < records; i++) { list.add(tableContent.get(start + i)); int sel = findInSelectedIndices(start + i); if (sel >= 0) { Widget[] row = tableContent.get(start + i); dispatchRowSelectionEvent(start + i, false, row); selected.add(row); selectedRowIndices.remove(sel); } } // sort it Collections.sort(list, asc == true ? columnsProperty[col].getAscendingSortComparator() : columnsProperty[col].getDescendingSortComparator()); // replace the sorted list in the table content and adjust the selected // rows for (int i = 0; i < list.size(); i++) { Widget[] w = (Widget[])list.get(i); tableContent.set(start + i, w); if ((selcell != null) && (selcell == w[selectedCell[1]])) { selectedCell[0] = start + i; dispatchCellSelectionEvent(selectedCell[0], selectedCell[1], true, selcell); } for (int j = 0; j < selected.size(); j++) { Widget[] sw = (Widget[])selected.get(j); if (w == sw) { selectedRowIndices.add(new Integer(start + i)); dispatchRowSelectionEvent(start + i, true, w); break; } } } removeAllColumns(false); populateBody(); } private void processTableEvent(int row, int cell) { if (tableProperty == null) { return; } if (row < headerRowCount) { return; } int rindex = 0; if (tableProperty.isPagingEnabled()) { rindex = ((currentPage * tableProperty.getRecordsPerPage()) + (row - headerRowCount)); } else { rindex = row - headerRowCount; } if ((cell == 0) && !(getWidget(row, 0) instanceof CheckBox) && (tableProperty.isRowSelectionEnabled())) { processRowSelectionEvent(row, rindex); } else if (tableProperty.isCellSelectionEnabled()) { processCellSelectionEvent(row, cell, rindex); } } private void removeAllColumns(boolean clearHistory) { int count = getRowCount(); for (int i = count - 1; i >= 0; i--) { removeRow(i); } if (clearHistory == true) { selectedRowIndices.clear(); selectedCell[0] = -1; selectedCell[1] = -1; tableContent.clear(); } headerRowCount = 0; populateHeader(); } private void setCurrentPageLabel() { if (tableProperty.isPagingEnabled()) { pageNumLabel.setText((currentPage + 1) + "/" + countPages()); } } private void setRowStyle(boolean selected, int index) { if (tableProperty.isRowSelectionEnabled() && selected) { getRowFormatter().setStyleName(index, "gwtcomp-SuperTableRowSelected"); } else if (((index - headerRowCount) % 2) == 0) { getRowFormatter().setStyleName(index, "gwtcomp-SuperTableRowEven"); } else { getRowFormatter().setStyleName(index, "gwtcomp-SuperTableRowOdd"); } } /** * In some cases, the table does not display the toolbar panel properly for very complex reasons. This method is provided to manually * redraw the panel. (This is a temporary solution until a completely transparent solution is found.) */ public void redraw() { if (toolbarPanel != null) { toolbarPanel.redraw(); } } @Override public HandlerRegistration addDoubleClickHandler(DoubleClickHandler handler) { return addDomHandler(handler, DoubleClickEvent.getType()); } public SuperTableColumnSelector getSel() { return sel; } }