| OLD | NEW | 
|    1 package autotest.common.table; |    1 package autotest.common.table; | 
|    2  |    2  | 
|    3 import autotest.common.SimpleCallback; |    3 import autotest.common.SimpleCallback; | 
|    4 import autotest.common.table.DataSource.DataCallback; |    4 import autotest.common.table.DataSource.DataCallback; | 
|    5 import autotest.common.table.DataSource.Query; |    5 import autotest.common.table.DataSource.Query; | 
|    6 import autotest.common.table.DataSource.SortDirection; |    6 import autotest.common.table.DataSource.SortDirection; | 
|    7 import autotest.common.table.DataSource.SortSpec; |    7 import autotest.common.table.DataSource.SortSpec; | 
|    8 import autotest.common.ui.Paginator; |    8 import autotest.common.ui.Paginator; | 
|    9  |    9  | 
|   10 import com.google.gwt.json.client.JSONObject; |   10 import com.google.gwt.json.client.JSONObject; | 
|   11 import com.google.gwt.user.client.ui.Composite; |   11 import com.google.gwt.user.client.ui.Composite; | 
|   12 import com.google.gwt.user.client.ui.HTMLPanel; |   12 import com.google.gwt.user.client.ui.HTMLPanel; | 
|   13 import com.google.gwt.user.client.ui.Image; |   13 import com.google.gwt.user.client.ui.Image; | 
|   14  |   14  | 
|   15 import java.util.ArrayList; |   15 import java.util.ArrayList; | 
|   16 import java.util.Collections; |   16 import java.util.Collections; | 
|   17 import java.util.Iterator; |   17 import java.util.Iterator; | 
|   18 import java.util.List; |   18 import java.util.List; | 
|   19  |   19  | 
|   20 /** |   20 /** | 
|   21  * Extended DataTable supporting sorting, filtering and pagination. |   21  * Extended DataTable supporting sorting, filtering and pagination. | 
|   22  */ |   22  */ | 
|   23 public class DynamicTable extends DataTable implements DataCallback { |   23 public class DynamicTable extends DataTable implements DataCallback { | 
|   24     public static final int NO_COLUMN = -1; |   24     public static final int NO_COLUMN = -1; | 
|   25     public static final String SORT_UP_IMAGE = "arrow_up.png", |   25     public static final String SORT_UP_IMAGE = "arrow_up.png", | 
|   26                                SORT_DOWN_IMAGE = "arrow_down.png"; |   26                                SORT_DOWN_IMAGE = "arrow_down.png"; | 
|   27      |   27  | 
|   28     public static interface DynamicTableListener extends DataTableListener { |   28     public static interface DynamicTableListener extends DataTableListener { | 
|   29         public void onTableRefreshed(); |   29         public void onTableRefreshed(); | 
|   30     } |   30     } | 
|   31      |   31  | 
|   32     static class SortIndicator extends Composite { |   32     static class SortIndicator extends Composite { | 
|   33         public int column; |   33         public int column; | 
|   34         private Image image = new Image(); |   34         private Image image = new Image(); | 
|   35          |   35  | 
|   36         public SortIndicator(int column) { |   36         public SortIndicator(int column) { | 
|   37             this.column = column; |   37             this.column = column; | 
|   38             initWidget(image); |   38             initWidget(image); | 
|   39             setVisible(false); |   39             setVisible(false); | 
|   40         } |   40         } | 
|   41          |   41  | 
|   42         public void sortOn(SortDirection direction) { |   42         public void sortOn(SortDirection direction) { | 
|   43             image.setUrl(direction == SortDirection.ASCENDING ? SORT_UP_IMAGE : 
     SORT_DOWN_IMAGE); |   43             image.setUrl(direction == SortDirection.ASCENDING ? SORT_UP_IMAGE : 
     SORT_DOWN_IMAGE); | 
|   44             setVisible(true); |   44             setVisible(true); | 
|   45         } |   45         } | 
|   46          |   46  | 
|   47         public void sortOff() { |   47         public void sortOff() { | 
|   48             setVisible(false); |   48             setVisible(false); | 
|   49         } |   49         } | 
|   50     } |   50     } | 
|   51      |   51  | 
|   52     protected DataSource dataSource; |   52     protected DataSource dataSource; | 
|   53     private Query currentQuery; |   53     private Query currentQuery; | 
|   54      |   54  | 
|   55     private boolean clientSortable = false; |   55     private boolean clientSortable = false; | 
|   56     private SortIndicator[] sortIndicators; |   56     private SortIndicator[] sortIndicators; | 
|   57     private List<SortSpec> sortColumns = new ArrayList<SortSpec>(); |   57     private List<SortSpec> sortColumns = new ArrayList<SortSpec>(); | 
|   58      |   58  | 
|   59     protected List<Filter> filters = new ArrayList<Filter>(); |   59     protected List<Filter> filters = new ArrayList<Filter>(); | 
|   60     protected List<Paginator> paginators = new ArrayList<Paginator>(); |   60     protected List<Paginator> paginators = new ArrayList<Paginator>(); | 
|   61     protected Integer rowsPerPage; |   61     protected Integer rowsPerPage; | 
|   62      |   62  | 
|   63     protected List<DynamicTableListener> dynamicTableListeners =  |   63     protected List<DynamicTableListener> dynamicTableListeners = | 
|   64         new ArrayList<DynamicTableListener>(); |   64         new ArrayList<DynamicTableListener>(); | 
|   65      |   65  | 
|   66     public DynamicTable(String[][] columns, DataSource dataSource) { |   66     public DynamicTable(String[][] columns, DataSource dataSource) { | 
|   67         super(columns); |   67         super(columns); | 
|   68         setDataSource(dataSource); |   68         setDataSource(dataSource); | 
|   69     } |   69     } | 
|   70      |   70  | 
|   71     // SORTING |   71     // SORTING | 
|   72      |   72  | 
|   73     /** |   73     /** | 
|   74      * Makes the table client sortable, that is, sortable by the user by  |   74      * Makes the table client sortable, that is, sortable by the user by | 
|   75      * clicking on column headers.  |   75      * clicking on column headers. | 
|   76      */ |   76      */ | 
|   77     public void makeClientSortable() { |   77     public void makeClientSortable() { | 
|   78         this.clientSortable = true; |   78         this.clientSortable = true; | 
|   79         table.getRowFormatter().addStyleName(0,  |   79         table.getRowFormatter().addStyleName(0, | 
|   80                                          DataTable.HEADER_STYLE + "-sortable"); |   80                                          DataTable.HEADER_STYLE + "-sortable"); | 
|   81          |   81  | 
|   82         sortIndicators = new SortIndicator[columns.length]; |   82         sortIndicators = new SortIndicator[columns.length]; | 
|   83         for(int i = 0; i < columns.length; i++) { |   83         for(int i = 0; i < columns.length; i++) { | 
|   84             sortIndicators[i] = new SortIndicator(i); |   84             sortIndicators[i] = new SortIndicator(i); | 
|   85              |   85  | 
|   86             // we have to use an HTMLPanel here to preserve styles correctly and |   86             // we have to use an HTMLPanel here to preserve styles correctly and | 
|   87             // not break hover |   87             // not break hover | 
|   88             // we add a <span> with a unique ID to hold the sort indicator |   88             // we add a <span> with a unique ID to hold the sort indicator | 
|   89             String name = columns[i][COL_TITLE]; |   89             String name = columns[i][COL_TITLE]; | 
|   90             String id = HTMLPanel.createUniqueId(); |   90             String id = HTMLPanel.createUniqueId(); | 
|   91             HTMLPanel panel = new HTMLPanel(name +  |   91             HTMLPanel panel = new HTMLPanel(name + | 
|   92                                             " <span id=\"" + id + "\"></span>"); |   92                                             " <span id=\"" + id + "\"></span>"); | 
|   93             panel.add(sortIndicators[i], id); |   93             panel.add(sortIndicators[i], id); | 
|   94             table.setWidget(0, i, panel); |   94             table.setWidget(0, i, panel); | 
|   95         } |   95         } | 
|   96     } |   96     } | 
|   97      |   97  | 
|   98     private void updateSortIndicators() { |   98     private void updateSortIndicators() { | 
|   99         if (!clientSortable) { |   99         if (!clientSortable) { | 
|  100             return; |  100             return; | 
|  101         } |  101         } | 
|  102          |  102  | 
|  103         SortSpec firstSpec = getFirstSortSpec(); |  103         SortSpec firstSpec = getFirstSortSpec(); | 
|  104         for (SortIndicator indicator : sortIndicators) { |  104         for (SortIndicator indicator : sortIndicators) { | 
|  105             if (columns[indicator.column][COL_NAME].equals(firstSpec.getField())
     ) { |  105             if (columns[indicator.column][COL_NAME].equals(firstSpec.getField())
     ) { | 
|  106                 indicator.sortOn(firstSpec.getDirection()); |  106                 indicator.sortOn(firstSpec.getDirection()); | 
|  107             } else { |  107             } else { | 
|  108                 indicator.sortOff(); |  108                 indicator.sortOff(); | 
|  109             } |  109             } | 
|  110         } |  110         } | 
|  111     } |  111     } | 
|  112  |  112  | 
|  113     private SortSpec getFirstSortSpec() { |  113     private SortSpec getFirstSortSpec() { | 
|  114         if (sortColumns.isEmpty()) { |  114         if (sortColumns.isEmpty()) { | 
|  115             return null; |  115             return null; | 
|  116         } |  116         } | 
|  117         return sortColumns.get(0); |  117         return sortColumns.get(0); | 
|  118     } |  118     } | 
|  119      |  119  | 
|  120     /** |  120     /** | 
|  121      * Set column on which data is sorted.  You must call <code>refresh()</code> |  121      * Set column on which data is sorted.  You must call <code>refresh()</code> | 
|  122      * after this to display the results. |  122      * after this to display the results. | 
|  123      * @param columnField field of the column to sort on |  123      * @param columnField field of the column to sort on | 
|  124      * @param sortDirection DynamicTable.ASCENDING or DynamicTable.DESCENDING |  124      * @param sortDirection DynamicTable.ASCENDING or DynamicTable.DESCENDING | 
|  125      */ |  125      */ | 
|  126     public void sortOnColumn(String columnField, SortDirection sortDirection) { |  126     public void sortOnColumn(String columnField, SortDirection sortDirection) { | 
|  127         // remove any existing sort on this column |  127         // remove any existing sort on this column | 
|  128         for (Iterator<SortSpec> i = sortColumns.iterator(); i.hasNext(); ) { |  128         for (Iterator<SortSpec> i = sortColumns.iterator(); i.hasNext(); ) { | 
|  129             if (i.next().getField().equals(columnField)) { |  129             if (i.next().getField().equals(columnField)) { | 
|  130                 i.remove(); |  130                 i.remove(); | 
|  131                 break; |  131                 break; | 
|  132             } |  132             } | 
|  133         } |  133         } | 
|  134          |  134  | 
|  135         sortColumns.add(0, new SortSpec(columnField, sortDirection)); |  135         sortColumns.add(0, new SortSpec(columnField, sortDirection)); | 
|  136         updateSortIndicators(); |  136         updateSortIndicators(); | 
|  137     } |  137     } | 
|  138      |  138  | 
|  139     /** |  139     /** | 
|  140      * Defaults to ascending order. |  140      * Defaults to ascending order. | 
|  141      */ |  141      */ | 
|  142     public void sortOnColumn(String columnField) { |  142     public void sortOnColumn(String columnField) { | 
|  143         sortOnColumn(columnField, SortDirection.ASCENDING); |  143         sortOnColumn(columnField, SortDirection.ASCENDING); | 
|  144     } |  144     } | 
|  145      |  145  | 
|  146     public void clearSorts() { |  146     public void clearSorts() { | 
|  147         sortColumns.clear(); |  147         sortColumns.clear(); | 
|  148         updateSortIndicators(); |  148         updateSortIndicators(); | 
|  149     } |  149     } | 
|  150      |  150  | 
|  151     // PAGINATION |  151     // PAGINATION | 
|  152      |  152  | 
|  153     /** |  153     /** | 
|  154      * Attach a new paginator to this table. |  154      * Attach a new paginator to this table. | 
|  155      */ |  155      */ | 
|  156     public void attachPaginator(Paginator paginator) { |  156     public void attachPaginator(Paginator paginator) { | 
|  157         assert rowsPerPage != null; |  157         assert rowsPerPage != null; | 
|  158         paginators.add(paginator); |  158         paginators.add(paginator); | 
|  159         paginator.addCallback(new SimpleCallback() { |  159         paginator.addCallback(new SimpleCallback() { | 
|  160             public void doCallback(Object source) { |  160             public void doCallback(Object source) { | 
|  161                 setPaginatorStart(((Paginator) source).getStart()); |  161                 setPaginatorStart(((Paginator) source).getStart()); | 
|  162                 fetchPage(); |  162                 fetchPage(); | 
|  163             }  |  163             } | 
|  164         }); |  164         }); | 
|  165         paginator.setResultsPerPage(rowsPerPage.intValue()); |  165         paginator.setResultsPerPage(rowsPerPage.intValue()); | 
|  166     } |  166     } | 
|  167      |  167  | 
|  168     /** |  168     /** | 
|  169      * Set the page size of this table (only useful if you attach paginators). |  169      * Set the page size of this table (only useful if you attach paginators). | 
|  170      */ |  170      */ | 
|  171     public void setRowsPerPage(int rowsPerPage) { |  171     public void setRowsPerPage(int rowsPerPage) { | 
|  172         assert rowsPerPage > 0; |  172         assert rowsPerPage > 0; | 
|  173         this.rowsPerPage = Integer.valueOf(rowsPerPage); |  173         this.rowsPerPage = Integer.valueOf(rowsPerPage); | 
|  174         for (Paginator paginator : paginators) { |  174         for (Paginator paginator : paginators) { | 
|  175             paginator.setResultsPerPage(rowsPerPage); |  175             paginator.setResultsPerPage(rowsPerPage); | 
|  176         } |  176         } | 
|  177     } |  177     } | 
|  178      |  178  | 
|  179     /** |  179     /** | 
|  180      * Set start row for pagination.  You must call  |  180      * Set start row for pagination.  You must call | 
|  181      * <code>refresh()</code> after this to display the results. |  181      * <code>refresh()</code> after this to display the results. | 
|  182      */ |  182      */ | 
|  183     public void setPaginatorStart(int start) { |  183     public void setPaginatorStart(int start) { | 
|  184         for (Paginator paginator : paginators) { |  184         for (Paginator paginator : paginators) { | 
|  185             paginator.setStart(start); |  185             paginator.setStart(start); | 
|  186         } |  186         } | 
|  187     } |  187     } | 
|  188      |  188  | 
|  189     protected void refreshPaginators() { |  189     protected void refreshPaginators() { | 
|  190         for (Paginator paginator : paginators) { |  190         for (Paginator paginator : paginators) { | 
|  191             paginator.update(); |  191             paginator.update(); | 
|  192         } |  192         } | 
|  193     } |  193     } | 
|  194      |  194  | 
|  195     protected void updatePaginatorTotalResults(int totalResults) { |  195     protected void updatePaginatorTotalResults(int totalResults) { | 
|  196         for (Paginator paginator : paginators) { |  196         for (Paginator paginator : paginators) { | 
|  197             paginator.setNumTotalResults(totalResults); |  197             paginator.setNumTotalResults(totalResults); | 
|  198         } |  198         } | 
|  199     } |  199     } | 
|  200      |  200  | 
|  201      |  201  | 
|  202     // FILTERING |  202     // FILTERING | 
|  203      |  203  | 
|  204     public void addFilter(Filter filter) { |  204     public void addFilter(Filter filter) { | 
|  205         filters.add(filter); |  205         filters.add(filter); | 
|  206         filter.addCallback(new SimpleCallback() { |  206         filter.addCallback(new SimpleCallback() { | 
|  207             public void doCallback(Object source) { |  207             public void doCallback(Object source) { | 
|  208                 setPaginatorStart(0); |  208                 setPaginatorStart(0); | 
|  209                 refresh(); |  209                 refresh(); | 
|  210             } |  210             } | 
|  211         }); |  211         }); | 
|  212     } |  212     } | 
|  213      |  213  | 
|  214     protected void addFilterParams(JSONObject params) { |  214     protected void addFilterParams(JSONObject params) { | 
|  215         for (Filter filter : filters) { |  215         for (Filter filter : filters) { | 
|  216             if (filter.isActive()) { |  216             if (filter.isActive()) { | 
|  217                 filter.addParams(params); |  217                 filter.addParams(params); | 
|  218             } |  218             } | 
|  219         } |  219         } | 
|  220     } |  220     } | 
|  221      |  221  | 
|  222     public boolean isAnyUserFilterActive() { |  222     public boolean isAnyUserFilterActive() { | 
|  223         for (Filter filter : filters) { |  223         for (Filter filter : filters) { | 
|  224             if (filter.isUserControlled() && filter.isActive()) { |  224             if (filter.isUserControlled() && filter.isActive()) { | 
|  225                 return true; |  225                 return true; | 
|  226             } |  226             } | 
|  227         } |  227         } | 
|  228  |  228  | 
|  229         return false; |  229         return false; | 
|  230     } |  230     } | 
|  231      |  231  | 
|  232      |  232  | 
|  233     // DATA MANAGEMENT |  233     // DATA MANAGEMENT | 
|  234      |  234  | 
|  235     public void refresh() { |  235     public void refresh() { | 
|  236         JSONObject params = new JSONObject(); |  236         JSONObject params = new JSONObject(); | 
|  237         addFilterParams(params); |  237         addFilterParams(params); | 
|  238         dataSource.query(params, this); |  238         dataSource.query(params, this); | 
|  239     } |  239     } | 
|  240  |  240  | 
|  241     @Override |  241     @Override | 
|  242     public void onQueryReady(Query query) { |  242     public void onQueryReady(Query query) { | 
|  243         currentQuery = query; |  243         currentQuery = query; | 
|  244         if (!paginators.isEmpty()) { |  244         if (!paginators.isEmpty()) { | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
|  271     public void handlePage(List<JSONObject> data) { |  271     public void handlePage(List<JSONObject> data) { | 
|  272         clear(); |  272         clear(); | 
|  273         addRows(data); |  273         addRows(data); | 
|  274         refreshPaginators(); |  274         refreshPaginators(); | 
|  275         notifyListenersRefreshed(); |  275         notifyListenersRefreshed(); | 
|  276     } |  276     } | 
|  277  |  277  | 
|  278     public String[] getRowData(int row) { |  278     public String[] getRowData(int row) { | 
|  279         String[] data = new String[columns.length]; |  279         String[] data = new String[columns.length]; | 
|  280         for (int i = 0; i < columns.length; i++) { |  280         for (int i = 0; i < columns.length; i++) { | 
|  281             if(isWidgetColumn(i)) |  281             if(isWidgetColumn(i)) { | 
|  282                 continue; |  282                 continue; | 
 |  283             } | 
|  283             data[i] = table.getHTML(row, i); |  284             data[i] = table.getHTML(row, i); | 
|  284         } |  285         } | 
|  285         return data; |  286         return data; | 
|  286     } |  287     } | 
|  287      |  288  | 
|  288     public DataSource getDataSource() { |  289     public DataSource getDataSource() { | 
|  289         return dataSource; |  290         return dataSource; | 
|  290     } |  291     } | 
|  291      |  292  | 
|  292     public void setDataSource(DataSource dataSource) { |  293     public void setDataSource(DataSource dataSource) { | 
|  293         this.dataSource = dataSource; |  294         this.dataSource = dataSource; | 
|  294     } |  295     } | 
|  295      |  296  | 
|  296     public Query getCurrentQuery() { |  297     public Query getCurrentQuery() { | 
|  297         return currentQuery; |  298         return currentQuery; | 
|  298     } |  299     } | 
|  299      |  300  | 
|  300      |  301  | 
|  301     // INPUT |  302     // INPUT | 
|  302      |  303  | 
|  303     @Override |  304     @Override | 
|  304     protected void onCellClicked(int row, int cell, boolean isRightClick) { |  305     protected void onCellClicked(int row, int cell, boolean isRightClick) { | 
|  305         if (row == headerRow) { |  306         if (row == headerRow) { | 
|  306             if (isWidgetColumn(cell)) { |  307             if (isWidgetColumn(cell)) { | 
|  307                 // ignore sorting on widget columns |  308                 // ignore sorting on widget columns | 
|  308                 return; |  309                 return; | 
|  309             } |  310             } | 
|  310             String columnName = columns[cell][COL_NAME]; |  311             String columnName = columns[cell][COL_NAME]; | 
|  311             SortDirection newSortDirection = SortDirection.ASCENDING; |  312             SortDirection newSortDirection = SortDirection.ASCENDING; | 
|  312             SortSpec firstSortSpec = getFirstSortSpec(); |  313             SortSpec firstSortSpec = getFirstSortSpec(); | 
|  313             // when clicking on the last sorted field, invert the sort |  314             // when clicking on the last sorted field, invert the sort | 
|  314             if (firstSortSpec != null && columnName.equals(firstSortSpec.getFiel
     d())) { |  315             if (firstSortSpec != null && columnName.equals(firstSortSpec.getFiel
     d())) { | 
|  315                 newSortDirection = invertSortDirection(firstSortSpec.getDirectio
     n()); |  316                 newSortDirection = invertSortDirection(firstSortSpec.getDirectio
     n()); | 
|  316             } |  317             } | 
|  317              |  318  | 
|  318             sortOnColumn(columnName, newSortDirection); |  319             sortOnColumn(columnName, newSortDirection); | 
|  319             refresh(); |  320             refresh(); | 
|  320             return; |  321             return; | 
|  321         } |  322         } | 
|  322          |  323  | 
|  323         super.onCellClicked(row, cell, isRightClick); |  324         super.onCellClicked(row, cell, isRightClick); | 
|  324     } |  325     } | 
|  325      |  326  | 
|  326     private SortDirection invertSortDirection(SortDirection direction) { |  327     private SortDirection invertSortDirection(SortDirection direction) { | 
|  327         return direction == SortDirection.ASCENDING ?  |  328         return direction == SortDirection.ASCENDING ? | 
|  328                                         SortDirection.DESCENDING : SortDirection
     .ASCENDING; |  329                                         SortDirection.DESCENDING : SortDirection
     .ASCENDING; | 
|  329     } |  330     } | 
|  330  |  331  | 
|  331     public void addListener(DynamicTableListener listener) { |  332     public void addListener(DynamicTableListener listener) { | 
|  332         super.addListener(listener); |  333         super.addListener(listener); | 
|  333         dynamicTableListeners.add(listener); |  334         dynamicTableListeners.add(listener); | 
|  334     } |  335     } | 
|  335      |  336  | 
|  336     public void removeListener(DynamicTableListener listener) { |  337     public void removeListener(DynamicTableListener listener) { | 
|  337         super.removeListener(listener); |  338         super.removeListener(listener); | 
|  338         dynamicTableListeners.remove(listener); |  339         dynamicTableListeners.remove(listener); | 
|  339     } |  340     } | 
|  340      |  341  | 
|  341     protected void notifyListenersRefreshed() { |  342     protected void notifyListenersRefreshed() { | 
|  342         for (DynamicTableListener listener : dynamicTableListeners) { |  343         for (DynamicTableListener listener : dynamicTableListeners) { | 
|  343             listener.onTableRefreshed(); |  344             listener.onTableRefreshed(); | 
|  344         } |  345         } | 
|  345     } |  346     } | 
|  346      |  347  | 
|  347     public List<SortSpec> getSortSpecs() { |  348     public List<SortSpec> getSortSpecs() { | 
|  348         return Collections.unmodifiableList(sortColumns); |  349         return Collections.unmodifiableList(sortColumns); | 
|  349     } |  350     } | 
|  350  |  351  | 
|  351     public void onError(JSONObject errorObject) { |  352     public void onError(JSONObject errorObject) { | 
|  352         // nothing to do |  353         // nothing to do | 
|  353     } |  354     } | 
|  354 } |  355 } | 
| OLD | NEW |