SortableTable Widget for GWT
/* * SortableTable Widget for GWT library of Google, Inc. * * Copyright (c) 2006 Parvinder Thapar * http://psthapar.googlepages.com/ * * This library is free software; you can redistribute * it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or * (at your option) any later version. This library is * distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNULesser General Public License for more details. * You should have received a copy of the GNU Lesser General * PublicLicense along with this library; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package com.java2s.gwt.client; import java.util.ArrayList; import java.util.List; import java.util.Collections; import java.util.Iterator; import java.util.Date; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.HTMLTable.CellFormatter; import com.google.gwt.user.client.ui.HTMLTable.RowFormatter; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.SourcesTableEvents; import com.google.gwt.user.client.ui.TableListener; public class GWTClient implements EntryPoint{ /** * This is the entry point method. */ public void onModuleLoad() { final SortableTable sortableTable = new SortableTable(); sortableTable.setWidth(500 + "px"); sortableTable.setStyleName("sortableTable"); sortableTable.setBorderWidth(1); sortableTable.setCellPadding(4); sortableTable.setCellSpacing(1); sortableTable.addColumnHeader("Employee", 0); sortableTable.addColumnHeader("Days", 1); sortableTable.addColumnHeader("Hire Date", 2); sortableTable.addColumnHeader("Bonus", 3); // The rowIndex should begin with 1 as rowIndex 0 is for the Header // Any row with index == 0 will not be displayed. sortableTable.setValue(1, 0, "Parvinder Thapar"); sortableTable.setValue(1, 1, new Integer(28)); sortableTable.setValue(1, 2, new SimpleDate(2005, 10, 25)); sortableTable.setValue(1, 3, new Float("125.27")); sortableTable.setValue(2, 0, "David Brooks"); sortableTable.setValue(2, 1, new Integer(32)); sortableTable.setValue(2, 2, new SimpleDate(2000, 4, 1)); sortableTable.setValue(2, 3, new Float("105.78")); sortableTable.setValue(3, 0, "Raj Rajendran"); sortableTable.setValue(3, 1, new Integer(30)); sortableTable.setValue(3, 2, new SimpleDate(2001, 12, 9)); sortableTable.setValue(3, 3, new Float("236.82")); sortableTable.setValue(4, 0, "Brian Foley"); sortableTable.setValue(4, 1, new Integer(38)); sortableTable.setValue(4, 2, new SimpleDate(2003, 2, 24)); sortableTable.setValue(4, 3, new Float("489.29")); sortableTable.setValue(5, 0, "Visala Dhara"); sortableTable.setValue(5, 1, new Integer(30)); sortableTable.setValue(5, 2, new SimpleDate(2001, 4, 23)); sortableTable.setValue(5, 3, new Float("892.72")); sortableTable.setValue(6, 0, "Wasim Khan"); sortableTable.setValue(6, 1, new Integer(35)); sortableTable.setValue(6, 2, new SimpleDate(1999, 7, 10)); sortableTable.setValue(6, 3, new Float("1242.89")); sortableTable.setValue(7, 0, "Bob Hammel"); sortableTable.setValue(7, 1, new Integer(56)); sortableTable.setValue(7, 2, new SimpleDate(1995, 2, 14)); sortableTable.setValue(7, 3, new Float("107.21")); sortableTable.setValue(8, 0, "Jeanie Sa-ville"); sortableTable.setValue(8, 1, new Integer(58)); sortableTable.setValue(8, 2, new SimpleDate(1989, 6, 1)); sortableTable.setValue(8, 3, new Float("2372.42")); sortableTable.setValue(9, 0, "Scott Loyet"); sortableTable.setValue(9, 1, new Integer(42)); sortableTable.setValue(9, 2, new SimpleDate(1992, 2, 29)); sortableTable.setValue(9, 3, new Float("896.74")); sortableTable.setValue(10, 0, "Dennis Twiss"); sortableTable.setValue(10, 1, new Integer(59)); sortableTable.setValue(10, 2, new SimpleDate(1990, 4, 15)); sortableTable.setValue(10, 3, new Float("1896.74")); sortableTable.setValue(11, 0, "Mike McIntosh"); sortableTable.setValue(11, 1, new Integer(76)); sortableTable.setValue(11, 2, new SimpleDate(1982, 5, 25)); sortableTable.setValue(11, 3, new Float("689.77")); sortableTable.setValue(12, 0, "Andrews Andy"); sortableTable.setValue(12, 1, new Integer(62)); sortableTable.setValue(12, 2, new SimpleDate(1994, 1, 15)); sortableTable.setValue(12, 3, new Float("829.24")); sortableTable.setValue(13, 0, "Bob Regent"); sortableTable.setValue(13, 1, new Integer(29)); sortableTable.setValue(13, 2, new SimpleDate(1996, 3, 12)); sortableTable.setValue(13, 3, new Float("621.52")); sortableTable.setValue(14, 0, "Chris Chalmers"); sortableTable.setValue(14, 1, new Integer(32)); sortableTable.setValue(14, 2, new SimpleDate(1997, 4, 1)); sortableTable.setValue(14, 3, new Float("804.26")); sortableTable.setValue(15, 0, "Christopher Mathrusse"); sortableTable.setValue(15, 1, new Integer(64)); sortableTable.setValue(15, 2, new SimpleDate(2005, 9, 10)); sortableTable.setValue(15, 3, new Float("761.25")); sortableTable.setValue(16, 0, "John Smith"); sortableTable.setValue(16, 1, new Integer(56)); sortableTable.setValue(16, 2, new SimpleDate(1992, 3, 16)); sortableTable.setValue(16, 3, new Float("789.29")); sortableTable.setValue(17, 0, "Jane Smith"); sortableTable.setValue(17, 1, new Integer(45)); sortableTable.setValue(17, 2, new SimpleDate(1989, 7, 25)); sortableTable.setValue(17, 3, new Float("2254.87")); sortableTable.setValue(18, 0, "Jason Chen"); sortableTable.setValue(18, 1, new Integer(37)); sortableTable.setValue(18, 2, new SimpleDate(1995, 8, 24)); sortableTable.setValue(18, 3, new Float("978.32")); sortableTable.setValue(19, 0, "Tina Matt"); sortableTable.setValue(19, 1, new Integer(49)); sortableTable.setValue(19, 2, new SimpleDate(1998, 9, 15)); sortableTable.setValue(19, 3, new Float("189.64")); sortableTable.setValue(20, 0, "Roxanne Rocks"); sortableTable.setValue(20, 1, new Integer(43)); sortableTable.setValue(20, 2, new SimpleDate(1992, 11, 12)); sortableTable.setValue(20, 3, new Float("1209.73")); // In your application code, the following should be part // of the looop that adds the data to the Table. // Since we have some hard-coded data here, this is done // separately down here.... // Please note that this is totally optional. This has nothing // to do with the Sorting capabilities of the widget. // This is just the cosmetics injection to the table. // Set Style Name for the header RowFormatter rowFormatter = sortableTable.getRowFormatter(); rowFormatter.setStyleName(0, "tableHeader"); // Set the Styles for the Data Rows and Columns CellFormatter cellFormatter = sortableTable.getCellFormatter(); // Set the styles for the headers for (int colIndex=0; colIndex<4; colIndex++){ cellFormatter.setStyleName(0, colIndex, "headerStyle"); cellFormatter.setAlignment(0, colIndex, HasHorizontalAlignment.ALIGN_CENTER, HasVerticalAlignment.ALIGN_MIDDLE); } for(int rowIndex=1; rowIndex<21; rowIndex++){ if(rowIndex%2 == 0){ rowFormatter.setStyleName(rowIndex, "customRowStyle"); }else{ rowFormatter.setStyleName(rowIndex, "tableRow"); } for (int colIndex=0; colIndex<4; colIndex++){ cellFormatter.setStyleName(rowIndex, colIndex, "customFont"); if(colIndex == 1 || colIndex == 3){ cellFormatter.setAlignment(rowIndex, colIndex, HasHorizontalAlignment.ALIGN_RIGHT, HasVerticalAlignment.ALIGN_MIDDLE); }else if(colIndex == 0){ cellFormatter.setAlignment(rowIndex, colIndex, HasHorizontalAlignment.ALIGN_LEFT, HasVerticalAlignment.ALIGN_MIDDLE); }if(colIndex == 2){ cellFormatter.setAlignment(rowIndex, colIndex, HasHorizontalAlignment.ALIGN_CENTER, HasVerticalAlignment.ALIGN_MIDDLE); } } } // Add the table to the doc RootPanel.get("slot1").add(sortableTable); } } class SimpleDate extends Date { public SimpleDate(){ super(); } public SimpleDate(int year, int month, int date){ super(year-1900, month-1, date); } public int compareTo(Object other) { Date otherDate = (Date)other; return super.compareTo(otherDate); } public String toString(){ return this.formatDate_DDMONYYYY(this); } /* * formatDate_DDMONYYYY * * Formats the date in DDMONYYYY format * * @param (Date to be formatted) * @return String */ private String formatDate_DDMONYYYY(Date date){ String[] MONTHS = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; StringBuffer dateStr = new StringBuffer(); if(date.getDate() < 10){ dateStr.append("0"); } dateStr.append(date.getDate()); dateStr.append(" "); dateStr.append(MONTHS[date.getMonth()]); dateStr.append(" "); dateStr.append((date.getYear()+1900)); return dateStr.toString(); } /* * formatDate_MMDDYYYY * * Formats the date in MMDDYYYY format * * @param (Date to be formatted) * @return String */ private String formatDate_MMDDYYYY (Date date){ StringBuffer strDate = new StringBuffer(); if(this.getMonth() < 9){ strDate.append("0"); } strDate.append(this.getMonth()+1); strDate.append("/"); if(this.getDate() < 10){ strDate.append("0"); } strDate.append(this.getDate()); strDate.append("/"); strDate.append((this.getYear()+1900)); return strDate.toString(); } } /* * SortableTable Widget for GWT library of Google, Inc. * * Copyright (c) 2006 Parvinder Thapar * http://psthapar.googlepages.com/ * * This library is free software; you can redistribute * it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or * (at your option) any later version. This library is * distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNULesser General Public License for more details. * You should have received a copy of the GNU Lesser General * PublicLicense along with this library; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* * RowData defines one row in a Sortable Table */ class RowData implements Comparable { // Maintains the list of the columns in the table List columnValues = new ArrayList(); // Keeps the current column index being sorted int sortColIndex = 0; /* * addColumnValue * * Adds the Comparable Value in the List of columns * * @param Comparable */ public void addColumnValue(Comparable value){ this.columnValues.add(value); } /* * addColumnValue * * Adds the Comparable Value in the specific index in the * List of columns * * @param colIndex (int) * @param Comparable */ public void addColumnValue(int index, Comparable value){ if(index >= this.columnValues.size()){ addNullColumns(index); } this.columnValues.set(index, value); } /* * getColumnValue * * Retrieves the Comparable Object from the List of columns * * @param colIndex (int) * @return Object */ public Object getColumnValue(int index){ return this.columnValues.get(index); } /* * addColumnValues * * Retrieves the list of column values * * @return List */ public List getColumnValues() { return columnValues; } /* * setColumnValues * * Sets the List to the List of column values * * @param List */ public void setColumnValues(List columnValues) { this.columnValues = columnValues; } /* * getSortColIndex * * Returns the current column index being sorted * * @return colIndex (int) */ public int getSortColIndex() { return sortColIndex; } /* * setSortColIndex * * Sets the current column index being sorted * * @param colIndex (int) */ public void setSortColIndex(int sortColIndex) { this.sortColIndex = sortColIndex; } /* * compareTo * * Implementation of Interface Comparable * Returns the compare result to another RowData object * * @param colIndex (int) */ public int compareTo(Object other) { if(null == other){ return -1; } RowData otherRow = (RowData)other; Comparable obj1 = (Comparable)this.getColumnValue(this.sortColIndex); Comparable obj2 = (Comparable)otherRow.getColumnValue(this.sortColIndex); return obj1.compareTo(obj2); } /* * addNullColumns * * Adds the Null columns in the table row * * @param colIndex (int) * @deprecated */ private void addNullColumns(int index){ for(int nullIndex=this.columnValues.size(); nullIndex<=index; nullIndex++){ columnValues.add(null); } } } /* * SortableTable Widget for GWT library of Google, Inc. * * Copyright (c) 2006 Parvinder Thapar * http://psthapar.googlepages.com/ * * This library is free software; you can redistribute * it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or * (at your option) any later version. This library is * distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNULesser General Public License for more details. * You should have received a copy of the GNU Lesser General * PublicLicense along with this library; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Sortable Interface defines the signatures and the * constants for the sortable table */ interface Sortable { // Constants defining the current direction of the // sort on a column public static int SORT_ASC = 0; public static int SORT_DESC = 1; /* * sort * * Defines what happens when the column is sorted * * @param columnIndex to be sorted (int) */ public void sort(int columnIndex); } /* * SortableTable Widget for GWT library of Google, Inc. * * Copyright (c) 2006 Parvinder Thapar * http://psthapar.googlepages.com/ * * This library is free software; you can redistribute * it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software * Foundation; either version 2.1 of the License, or * (at your option) any later version. This library is * distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNULesser General Public License for more details. * You should have received a copy of the GNU Lesser General * PublicLicense along with this library; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* * SortableTable is a type of FlexTable which allows Sorting * on its column. Sorting is done totally on the client side. * No server side call is made in this table. * * Current implementation of Sortable Table needs <code>Comparable</code> * Object in its column values to be able to sort them correctly * * The objects being set in the column values must implement the interface * <code>Comparable</code> and implement methods: compareTo() and * toString() * * {@link com.google.gwt.user.client.ui.FlexTable} * {@link java.lang.Comparable} */ class SortableTable extends FlexTable implements Sortable, TableListener { // Holds the current column being sorted private int sortColIndex = -1; // Holds the current direction of sort: Asc/ Desc private int sortDirection = -1; // The default image to show acending order arrow private String sortAscImage = "images/asc.gif"; //The default image to show descending order arrow private String sortDescImage = "images/desc.gif"; // The default image to show the blank image // This is needed to paint the columns other than // the one which is being sorted. // Should be same length and width as the asc/ desc // images. private String blankImage = "images/blank.gif"; // Holds the data rows of the table // This is a list of RowData Object private List tableRows = new ArrayList(); // Holds the data for the column headers private List tableHeader = new ArrayList(); /* * Default Constructor * * Calls the super class constructor * and adds a TableListener object */ public SortableTable(){ super(); this.addTableListener(this); } /* * addColumnHeader * * Adds the Column Header to the table * Uses the rowIndex 0 to add the header names. * Renders the name and the asc/desc/blank gif * to the column * * @param columnName (String) * @param columnIndex (int) */ public void addColumnHeader(String name, int index){ tableHeader.add(index, name); this.renderTableHeader(name, index); } /* * setValue * * Sets the values in specifed row/column * Expects a Comparable Object for sorting * * @param rowIndex (int) * @param columnIndex (int) * @param Value (Comparable) */ public void setValue(int rowIndex, int colIndex, Comparable value){ // The rowIndex should begin with 1 as rowIndex 0 is for the Header // Any row with index == 0 will not be displayed. if(rowIndex == 0){ return; } if((rowIndex-1) >= this.tableRows.size() || null == tableRows.get(rowIndex-1)){ tableRows.add(rowIndex-1, new RowData()); } RowData rowData = (RowData)this.tableRows.get(rowIndex-1); rowData.addColumnValue(colIndex, value); this.setHTML(rowIndex, colIndex, "" + value.toString()+ ""); } /* * sort * * Implementation of Sortable Interface, this * method decribes how to sort the specified * column. It checks the current sort direction * and flips it * * @param columnIndex (int) */ public void sort(int columnIndex){ Collections.sort(this.tableRows); if(this.sortColIndex != columnIndex){ // New Column Header clicked // Reset the sortDirection to ASC this.sortDirection = SORT_ASC; }else{ // Same Column Header clicked // Reverse the sortDirection this.sortDirection = (this.sortDirection == SORT_ASC)? SORT_DESC:SORT_ASC; } this.sortColIndex = columnIndex; } /* * onCellClicked * * Implementation of Table Listener Interface, this * method decribes what to do when a cell is clicked * It checks for the header row and calls the sort * method to sort the table * * @param sender (SourcesTableEvents) * @param rowIndex (int) * @param colIndex (int) */ public void onCellClicked(SourcesTableEvents sender, int row, int col) { if(row != 0){ return; } this.setSortColIndex(col); this.sort(col); this.drawTable(); } /* * getSortAscImage * * Getter for Sort Ascending Image * * @return String */ public String getSortAscImage() { return sortAscImage; } /* * setSortAscImage * * Setter for Sort Ascending Image * * @param relative path + image name (String) * e.g. images/asc.gif */ public void setSortAscImage(String sortAscImage) { this.sortAscImage = sortAscImage; } /* * getSortDescImage * * Getter for Sort Descending Image * * @return String */ public String getSortDescImage() { return sortDescImage; } /* * setSortDescImgage * * Setter for Sort Descending Image * * @param relative path + image name (String) * e.g. images/desc.gif */ public void setSortDescImgage(String sortDescImgage) { this.sortDescImage = sortDescImgage; } /* * getBlankImage * * Getter for blank Image * * @return String */ public String getBlankImage() { return blankImage; } /* * setBlankImage * * Setter for the blank Image * * @param relative path + image name (String) * e.g. images/blank.gif */ public void setBlankImage(String blankImage) { this.blankImage = blankImage; } /* * drawTable * * Renders the header as well as the body * of the table */ protected void drawTable(){ this.displayTableHeader(); this.displayTableBody(); } /* * displayTableHeader * * Renders only the table header */ private void displayTableHeader(){ int colIndex=0; for(Iterator colHeaderIter = this.tableHeader.iterator(); colHeaderIter.hasNext();){ String colHeader = (String)colHeaderIter.next(); this.renderTableHeader(colHeader, colIndex++); } } /* * displayTableBody * * Renders the body or the remaining rows of the table * except the header. * It checks the sort direction and displays the rows * accordingly */ private void displayTableBody(){ if(this.sortDirection == SORT_ASC || this.sortDirection == -1){ // Ascending order and Default Display for(int rowIndex=0; rowIndex<tableRows.size(); rowIndex++){ RowData columns = (RowData)tableRows.get(rowIndex); for(int colIndex=0; colIndex<columns.getColumnValues().size(); colIndex++){ Object value = columns.getColumnValue(colIndex); if(null != value){ this.setHTML(rowIndex+1, colIndex, value.toString()); } } } }else{ // Descending Order Display for(int rowIndex=tableRows.size()-1, rowNum = 1; rowIndex>=0; rowIndex--, rowNum++){ RowData columns = (RowData)tableRows.get(rowIndex); for(int colIndex=0; colIndex<columns.getColumnValues().size(); colIndex++){ Object value = columns.getColumnValue(colIndex); if(null != value){ this.setHTML(rowNum, colIndex, value.toString()); } } } } } /* * setSortColIndex * * Sets the current column index being sorted * * @param column index being sorted (int) */ private void setSortColIndex(int sortIndex){ for(int rowIndex=0; rowIndex<tableRows.size(); rowIndex++){ RowData row = (RowData)tableRows.get(rowIndex); row.setSortColIndex(sortIndex); } } /* * renderTableHeader * Renders a particular column in the Table Header * * @param Column Name (String) * @param Column Index (int) */ private void renderTableHeader(String name, int index){ StringBuffer headerText = new StringBuffer(); headerText.append(name); headerText.append(" <img border='0' src="); if(this.sortColIndex == index){ if(this.sortDirection == SORT_ASC){ headerText.append("'" + this.sortAscImage + "' alt='Ascending' "); }else{ headerText.append("'" + this.sortDescImage + "' alt='Descending' "); } }else{ headerText.append("'" + this.blankImage + "'"); } headerText.append("/>"); this.setHTML(0, index, headerText.toString()); } }