Coverage Report - org.kuali.student.common.ui.client.widgets.table.scroll.Table
 
Classes in this File Line Coverage Branch Coverage Complexity
Table
0%
0/202
0%
0/98
2.415
Table$1
0%
0/9
0%
0/6
2.415
Table$2
0%
0/9
0%
0/6
2.415
Table$3
0%
0/11
0%
0/8
2.415
Table$4
0%
0/3
N/A
2.415
Table$5
0%
0/3
N/A
2.415
Table$6
0%
0/3
N/A
2.415
Table$7
0%
0/3
N/A
2.415
Table$8
0%
0/3
N/A
2.415
Table$FocusType
0%
0/4
N/A
2.415
Table$SelectionStyle
N/A
N/A
2.415
Table$TableUiBinder
N/A
N/A
2.415
 
 1  
 package org.kuali.student.common.ui.client.widgets.table.scroll;
 2  
 
 3  
 import java.util.ArrayList;
 4  
 import java.util.List;
 5  
 
 6  
 import org.kuali.student.common.ui.client.widgets.list.HasSelectionChangeHandlers;
 7  
 import org.kuali.student.common.ui.client.widgets.list.SelectionChangeEvent;
 8  
 import org.kuali.student.common.ui.client.widgets.list.SelectionChangeHandler;
 9  
 import org.kuali.student.common.ui.client.widgets.notification.LoadingDiv;
 10  
 
 11  
 import com.google.gwt.core.client.GWT;
 12  
 import com.google.gwt.event.dom.client.ChangeEvent;
 13  
 import com.google.gwt.event.dom.client.ChangeHandler;
 14  
 import com.google.gwt.event.dom.client.ClickEvent;
 15  
 import com.google.gwt.event.dom.client.ClickHandler;
 16  
 import com.google.gwt.event.dom.client.HasChangeHandlers;
 17  
 import com.google.gwt.event.dom.client.HasClickHandlers;
 18  
 import com.google.gwt.event.dom.client.KeyCodes;
 19  
 import com.google.gwt.event.dom.client.KeyDownEvent;
 20  
 import com.google.gwt.event.dom.client.KeyDownHandler;
 21  
 import com.google.gwt.event.dom.client.ScrollEvent;
 22  
 import com.google.gwt.event.dom.client.ScrollHandler;
 23  
 import com.google.gwt.event.shared.HandlerRegistration;
 24  
 import com.google.gwt.resources.client.CssResource;
 25  
 import com.google.gwt.uibinder.client.UiBinder;
 26  
 import com.google.gwt.uibinder.client.UiField;
 27  
 import com.google.gwt.uibinder.client.UiHandler;
 28  
 import com.google.gwt.user.client.Element;
 29  
 import com.google.gwt.user.client.ui.CheckBox;
 30  
 import com.google.gwt.user.client.ui.Composite;
 31  
 import com.google.gwt.user.client.ui.FlexTable;
 32  
 import com.google.gwt.user.client.ui.FocusPanel;
 33  
 import com.google.gwt.user.client.ui.HTMLPanel;
 34  
 import com.google.gwt.user.client.ui.Label;
 35  
 import com.google.gwt.user.client.ui.ScrollPanel;
 36  
 import com.google.gwt.user.client.ui.Widget;
 37  
 import com.google.gwt.user.client.ui.HTMLTable.Cell;
 38  
 import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
 39  
 
 40  
 /**
 41  
  * A table with UiBinder.
 42  
  */
 43  0
 public class Table extends Composite implements HasRetrieveAdditionalDataHandlers, HasSelectionChangeHandlers {
 44  
 
 45  0
     private int headerSelectedCellIndex = -1;
 46  
 
 47  0
     private FocusType focusType = FocusType.NONE;
 48  
 
 49  0
     private static TableUiBinder uiBinder = GWT.create(TableUiBinder.class);
 50  0
     private final List<RetrieveAdditionalDataHandler> retrieveDataHandlers = new ArrayList<RetrieveAdditionalDataHandler>();
 51  
 
 52  
     interface TableUiBinder extends UiBinder<Widget, Table> {
 53  
     }
 54  
 
 55  
     interface SelectionStyle extends CssResource {
 56  
         String selectedRow();
 57  
 
 58  
         String columnAscending();
 59  
 
 60  
         String columnDescending();
 61  
 
 62  
         String selectedHeaderCell();
 63  
     }
 64  
 
 65  0
     private static enum FocusType {
 66  0
         HEADER,
 67  0
         BODY,
 68  0
         NONE
 69  
     }
 70  
 
 71  
     @UiField
 72  
     FlexTable header;
 73  
     @UiField
 74  
     MouseHoverFlexTable table;
 75  
     @UiField
 76  
     SelectionStyle selectionStyle;
 77  
     @UiField
 78  
     ScrollPanel scrollPanel;
 79  
     @UiField
 80  
     FocusPanel focusPanel;
 81  
     @UiField
 82  
     FocusPanel headerFocusPanel;
 83  
     @UiField
 84  
     HTMLPanel panel;
 85  
 
 86  
     private TableModel tableModel;
 87  0
     private final LoadingDiv loading = new LoadingDiv();
 88  
 
 89  0
     public Table() {
 90  0
         initWidget(uiBinder.createAndBindUi(this));
 91  
 
 92  0
         scrollPanel.addScrollHandler(new ScrollHandler() {
 93  
             @Override
 94  
             public void onScroll(ScrollEvent event) {
 95  0
                 int position = scrollPanel.getScrollPosition();
 96  
                 // see 6th comment in KSLAB-1790; possibly not created yet?
 97  0
                 if (null != scrollPanel.getWidget()) {
 98  0
                     int size = scrollPanel.getWidget().getOffsetHeight();
 99  0
                     int diff = size - scrollPanel.getOffsetHeight();
 100  0
                     if (position == diff) {
 101  0
                         for (int i = 0; i < retrieveDataHandlers.size(); i++) {
 102  0
                             retrieveDataHandlers.get(i).onAdditionalDataRequest();
 103  
                         }
 104  
                     }
 105  
                 }
 106  0
             }
 107  
         });
 108  0
         addHandlers();
 109  0
     }
 110  
     
 111  
     public void removeAllRows(){
 112  0
             table.removeAllRows();
 113  0
     }
 114  
 
 115  
     public void removeContent(){
 116  0
             getScrollPanel().clear();
 117  0
     }
 118  
  
 119  
     public void addContent(){
 120  0
             getScrollPanel().setWidget(getContent());
 121  0
     }
 122  
     
 123  
     private void addHandlers() {
 124  0
         focusPanel.addKeyDownHandler(new KeyDownHandler() {
 125  
 
 126  
             @Override
 127  
             public void onKeyDown(KeyDownEvent event) {
 128  0
                 int code = event.getNativeKeyCode();
 129  0
                 if (code == KeyCodes.KEY_DOWN) {
 130  0
                     processKeyUpAndDownEvent(TablePredicateFactory.DOWN_RIGHT_PREDICATE);
 131  0
                 } else if (code == KeyCodes.KEY_UP) {
 132  0
                     processKeyUpAndDownEvent(TablePredicateFactory.UP_LEFT_PREDICATE);
 133  0
                 } else if (code == ' ') {
 134  0
                     processSpaceClick();
 135  
                 }
 136  0
             }
 137  
         });
 138  0
         headerFocusPanel.addKeyDownHandler(new KeyDownHandler() {
 139  
             @Override
 140  
             public void onKeyDown(KeyDownEvent event) {
 141  0
                 int code = event.getNativeKeyCode();
 142  0
                 if (code == KeyCodes.KEY_RIGHT) {
 143  0
                     processKeyLeftRight(TablePredicateFactory.DOWN_RIGHT_PREDICATE);
 144  0
                 } else if (code == KeyCodes.KEY_LEFT) {
 145  0
                     processKeyLeftRight(TablePredicateFactory.UP_LEFT_PREDICATE);
 146  0
                 } else if (code == KeyCodes.KEY_DOWN) {
 147  0
                     processKeyDownOnHeader();
 148  0
                 } else if (code == ' ') {
 149  0
                     onTableHeaderClicked(headerSelectedCellIndex, true);
 150  
                 }
 151  0
             }
 152  
         });
 153  0
     }
 154  
 
 155  
     private void processKeyDownOnHeader() {
 156  0
         changeFocus(FocusType.BODY);
 157  0
         Row currentRow = tableModel.getRow(0);
 158  0
         tableModel.setCurrentIndex(0);
 159  0
         currentRow.setHighlighted(true);
 160  0
         updateTableSelection();
 161  0
         removeHeaderSelection();
 162  0
     }
 163  
 
 164  
     private void removeHeaderSelection() {
 165  0
         if (headerSelectedCellIndex >= 0) {
 166  0
             header.getCellFormatter().removeStyleName(0, headerSelectedCellIndex, selectionStyle.selectedHeaderCell());
 167  0
             headerSelectedCellIndex = -1;
 168  
         }
 169  0
     }
 170  
 
 171  
     private void processKeyLeftRight(TablePredicateFactory.Predicate tablePredicate) {
 172  0
         if (tablePredicate.indexCondition(headerSelectedCellIndex, tableModel.getColumnCount())) {
 173  0
             header.getCellFormatter().removeStyleName(0, headerSelectedCellIndex, selectionStyle.selectedHeaderCell());
 174  0
             headerSelectedCellIndex = tablePredicate.nextIndex(headerSelectedCellIndex);
 175  0
             header.getCellFormatter().addStyleName(0, headerSelectedCellIndex, selectionStyle.selectedHeaderCell());
 176  
 
 177  
         }
 178  0
     }
 179  
 
 180  
     private void processSpaceClick() {
 181  0
         int index = tableModel.getCurrentIndex();
 182  0
         if (index >= 0) {
 183  0
             Row currentRow = tableModel.getRow(index);
 184  0
             boolean selected = currentRow.isSelected();
 185  0
             if (selected) {
 186  0
                 currentRow.setSelected(false);
 187  
             } else {
 188  0
                 tableModel.setSelectedRow(index);
 189  
             }
 190  0
             updateTableSelection();
 191  
         }
 192  0
     }
 193  
 
 194  
     private void processKeyUpAndDownEvent(TablePredicateFactory.Predicate tablePredicate) {
 195  0
         int currentIndex = tableModel.getCurrentIndex();
 196  0
         Row currentRow = tableModel.getRow(currentIndex);
 197  0
         if (currentIndex == 0 && tablePredicate.moveType() == TablePredicateFactory.MoveType.UP_LEFT) {
 198  0
             tableModel.getRow(currentIndex).setHighlighted(false);
 199  0
             tableModel.setCurrentIndex(-1);
 200  0
             headerSelectedCellIndex = 0;
 201  0
             changeFocus(FocusType.HEADER);
 202  0
             header.getCellFormatter().addStyleName(0, 0, selectionStyle.selectedHeaderCell());
 203  
         } else {
 204  0
             if (currentRow.isHighlighted() && tablePredicate.indexCondition(currentIndex, tableModel.getRowCount())) {
 205  0
                 currentRow.setHighlighted(false);
 206  0
                 currentIndex = tablePredicate.nextIndex(currentIndex);
 207  0
                 tableModel.getRow(currentIndex).setHighlighted(true);
 208  0
                 tableModel.setCurrentIndex(currentIndex);
 209  0
                 scrollPanel.ensureVisible(table.getWidget(currentIndex, 0));
 210  
             }
 211  
         }
 212  0
         updateTableSelection();
 213  0
     }
 214  
 
 215  
     public FlexTable getHeader() {
 216  0
         return header;
 217  
     }
 218  
 
 219  
     public FlexTable getContent() {
 220  0
         return table;
 221  
     }
 222  
 
 223  
     public ScrollPanel getScrollPanel() {
 224  0
         return scrollPanel;
 225  
     }
 226  
 
 227  
     public void setTableModel(TableModel m) {
 228  0
         tableModel = m;
 229  0
         table.setModel(tableModel);
 230  0
         if (m instanceof AbstractTableModel) {
 231  0
             ((AbstractTableModel) tableModel).addTableModelListener(new TableModelListener() {
 232  
                 @Override
 233  
                 public void tableChanged(TableModelEvent e) {
 234  0
                     updateTable(e);
 235  0
                 }
 236  
             });
 237  0
             ((AbstractTableModel) tableModel).fireTableStructureChanged();
 238  
         }
 239  0
     }
 240  
     
 241  
     public TableModel getTableModel(){
 242  0
             return tableModel;
 243  
     }
 244  
 
 245  
     @UiHandler("table")
 246  
     void onTableClicked(ClickEvent event) {
 247  0
         removeHeaderSelection();
 248  
         //changeFocus(FocusType.BODY);
 249  0
         Cell cell = table.getCellForEvent(event);
 250  
 
 251  0
         if (cell == null) {
 252  0
             return;
 253  
         }
 254  0
         int cellIndex = cell.getCellIndex();
 255  0
         int rowIndex = cell.getRowIndex();
 256  0
         tableModel.setCurrentIndex(rowIndex);
 257  0
         Row row = tableModel.getRow(rowIndex);
 258  
 
 259  0
         if (tableModel.isMultipleSelectable() == false) {
 260  0
             for (int r = 0; r < tableModel.getRowCount(); r++) {
 261  0
                 if (r != rowIndex) {
 262  0
                     tableModel.getRow(r).setSelected(false);
 263  
                 }
 264  
             }
 265  0
             row.setSelected(!row.isSelected());
 266  0
             updateTableSelection();
 267  0
             for (int r = 0; r < tableModel.getRowCount(); r++) {
 268  0
                 updateTableCell(r, 0);
 269  
             }
 270  
         } else {
 271  0
             if (cellIndex == 0) {
 272  0
                 return;
 273  
             }
 274  0
             row.setSelected(!row.isSelected());
 275  0
             updateTableSelection();
 276  0
             updateTableCell(rowIndex, 0);
 277  
         }
 278  0
     }
 279  
 
 280  
     @UiHandler("header")
 281  
     void onTableHeaderClicked(ClickEvent event) {
 282  0
         Cell cell = header.getCellForEvent(event);
 283  0
         if (cell != null) {
 284  0
             onTableHeaderClicked(cell.getCellIndex(), false);
 285  
         }
 286  0
     }
 287  
 
 288  
     private void onTableHeaderClicked(int cellIndex, boolean propagateEventIfNotSortingColumn) {
 289  0
         if (cellIndex == 0 && tableModel.isMultipleSelectable() && propagateEventIfNotSortingColumn) {
 290  0
             Widget widget = header.getWidget(0, 0);
 291  0
             if (widget instanceof CheckBox) {
 292  0
                 CheckBox checkBox = (CheckBox) widget;
 293  0
                 boolean correctValue = !checkBox.getValue();
 294  0
                 checkBox.setValue(correctValue);
 295  0
                 for (int row = 0; row < tableModel.getRowCount(); row++) {
 296  0
                     tableModel.getRow(row).setSelected(correctValue);
 297  0
                     updateTableSelection();
 298  
                 }
 299  
             }
 300  0
         } else {
 301  0
             removeHeaderSelection();
 302  
         }
 303  0
         headerSelectedCellIndex = cellIndex;
 304  0
         Column col = tableModel.getColumn(cellIndex);
 305  0
         tableModel.sort(col);
 306  0
     }
 307  
 
 308  
     private void onTableClicked(int row, String columnId,
 309  
                                 TableCellWidget cellWidget) {
 310  0
         onTableCellChanged(row, columnId, cellWidget);
 311  0
     }
 312  
 
 313  
     private void onTableCellChanged(int rowIndex, String columnId,
 314  
                                     TableCellWidget cellWidget) {
 315  0
         Row row = tableModel.getRow(rowIndex);
 316  0
         if ("RowHeader".equals(columnId)) {
 317  0
             row.setSelected(!row.isSelected());
 318  0
             updateTableSelection();
 319  
         }
 320  0
         row.setCellData(columnId,
 321  
                 cellWidget.getCellEditorValue());
 322  0
     }
 323  
 
 324  
     private void updateTableSelection() {
 325  0
         int count = tableModel.getRowCount();
 326  0
         for (int i = 0; i < count; i++) {
 327  0
             Element tr = table.getRowFormatter().getElement(i);
 328  0
             if (tableModel.getRow(i).isSelected()) {
 329  0
                     tr.setAttribute("class", "table-row-selected");
 330  
             } else {
 331  0
                 tr.setAttribute("class", "table-row");
 332  
             }
 333  0
             if (tableModel.getRow(i).isHighlighted()) {
 334  0
                     tr.setAttribute("class", "table-row-hover");
 335  
             }
 336  0
             if (tableModel.isMultipleSelectable()) {
 337  0
                 updateTableCell(i, 0);
 338  
             }
 339  
         }
 340  0
         SelectionChangeEvent.fire(this);
 341  0
     }
 342  
 
 343  
     private void changeFocus(FocusType focusType) {
 344  0
         this.focusType = focusType;
 345  0
         if (focusType == FocusType.HEADER) {
 346  0
             headerFocusPanel.setFocus(true);
 347  0
         } else if (focusType == FocusType.BODY) {
 348  0
             focusPanel.setFocus(true);
 349  
         }
 350  0
     }
 351  
 
 352  
     public void updateTable(TableModelEvent event) {
 353  0
         if (event.getType() == TableModelEvent.TableStructure) {
 354  0
             updateTableStructure();
 355  0
             updateTableData();
 356  0
         } else if (event.getType() == TableModelEvent.TableData) {
 357  0
             updateTableData();
 358  0
         } else if (event.getType() == TableModelEvent.CellUpdate) {
 359  0
             updateTableCell(event.getFirstRow(), event.getColumn());
 360  
         }
 361  0
     }
 362  
 
 363  
     private void updateTableData() {
 364  0
         for (int r = 0; r < tableModel.getRowCount(); r++) {
 365  0
             int columnCount = tableModel.getColumnCount();
 366  0
             for (int c = 0; c < columnCount; c++) {
 367  0
                 updateTableCell(r, c);
 368  
             }
 369  
         }
 370  0
         updateTableSelection();
 371  0
     }
 372  
 
 373  
     private void updateTableCell(final int r, final int c) {
 374  0
         int columnCount = tableModel.getColumnCount();
 375  0
         for (int i = 0; i < columnCount - 1; i++) {
 376  0
             Column col = tableModel.getColumn(i);
 377  0
             table.getColumnFormatter().setWidth(i, col.getWidth());
 378  
         }
 379  0
         final String columnId = tableModel.getColumn(c).getId();
 380  0
         Row row = tableModel.getRow(r);
 381  0
         Object v = null;
 382  0
         if ("RowHeader".equals(columnId)) {
 383  0
             v = row.isSelected();
 384  
         } else {
 385  0
             v = row.getCellData(columnId);
 386  
         }
 387  0
         if ("RowHeader".equals(columnId) == false) {
 388  0
             if (v != null) {
 389  0
                 table.setWidget(r, c, new Label(v.toString()));
 390  
             } else {
 391  0
                 table.setHTML(r, c, "&nbsp;");
 392  
             }
 393  0
             return;
 394  
         }
 395  0
         final TableCellWidget widget = new TableCellWidget(v);
 396  0
         widget.setCellEditorValue(v);
 397  0
         if (widget instanceof HasClickHandlers) {
 398  0
             ((HasClickHandlers) widget)
 399  0
                     .addClickHandler(new ClickHandler() {
 400  
                         @Override
 401  
                         public void onClick(ClickEvent event) {
 402  0
                             onTableClicked(r, columnId, widget);
 403  0
                         }
 404  
                     });
 405  
         }
 406  0
         if (widget instanceof HasChangeHandlers) {
 407  0
             ((HasChangeHandlers) widget)
 408  0
                     .addChangeHandler(new ChangeHandler() {
 409  
                         @Override
 410  
                         public void onChange(ChangeEvent event) {
 411  0
                             onTableCellChanged(r, columnId, widget);
 412  
 
 413  0
                         }
 414  
                     });
 415  
         }
 416  0
         table.setWidget(r, c, widget);
 417  0
     }
 418  
 
 419  
     private void updateTableStructure() {
 420  0
         int columnCount = tableModel.getColumnCount();
 421  0
         for (int i = 0; i < columnCount; i++) {
 422  0
             Column col = tableModel.getColumn(i);
 423  0
             header.setWidget(0, i, col.getColumnTitleWidget());
 424  
         }
 425  0
         for (int i = 0; i < columnCount - 1; i++) {
 426  0
             Column col = tableModel.getColumn(i);
 427  0
             header.getColumnFormatter().setWidth(i, col.getWidth());
 428  
         }
 429  0
         for (int i = 0; i < columnCount; i++) {
 430  0
             Column col = tableModel.getColumn(i);
 431  
 
 432  0
             header.getCellFormatter().removeStyleName(0, i, selectionStyle.columnAscending());
 433  0
             header.getCellFormatter().removeStyleName(0, i, selectionStyle.columnDescending());
 434  
 
 435  0
             if (col.getSortDirection() == Column.Ascending) {
 436  0
                 header.getCellFormatter().addStyleName(0, i, selectionStyle.columnAscending());
 437  0
             } else if (col.getSortDirection() == Column.Descending) {
 438  0
                 header.getCellFormatter().addStyleName(0, i, selectionStyle.columnDescending());
 439  
             }
 440  
         }
 441  0
     }
 442  
 
 443  
     @Override
 444  
     public HandlerRegistration addRetrieveAdditionalDataHandler(
 445  
             final RetrieveAdditionalDataHandler handler) {
 446  0
         retrieveDataHandlers.add(handler);
 447  0
         HandlerRegistration result = new HandlerRegistration() {
 448  
             @Override
 449  
             public void removeHandler() {
 450  0
                 retrieveDataHandlers.remove(handler);
 451  0
             }
 452  
         };
 453  0
         return result;
 454  
     }
 455  
 
 456  
     public void displayLoading(boolean isLoading) {
 457  0
         changeFocus(FocusType.BODY);
 458  0
         final int x = scrollPanel.getAbsoluteLeft() + scrollPanel.getOffsetWidth();
 459  0
         final int y = scrollPanel.getAbsoluteTop() + scrollPanel.getOffsetHeight();
 460  0
         if (isLoading) {
 461  0
             loading.setPopupPositionAndShow(new PositionCallback() {
 462  
 
 463  
                 @Override
 464  
                 public void setPosition(int offsetWidth, int offsetHeight) {
 465  0
                     loading.setPopupPosition(x - offsetWidth, y + 1);
 466  0
                 }
 467  
             });
 468  
         } else {
 469  0
             loading.hide();
 470  
         }
 471  0
     }
 472  
 
 473  
         /**
 474  
          * @see org.kuali.student.common.ui.client.widgets.list.HasSelectionChangeHandlers#addSelectionChangeHandler(org.kuali.student.common.ui.client.widgets.list.SelectionChangeHandler)
 475  
          */
 476  
         @Override
 477  
         public HandlerRegistration addSelectionChangeHandler(
 478  
                         SelectionChangeHandler handler) {
 479  0
                 return addHandler(handler, SelectionChangeEvent.getType());
 480  
         }
 481  
 }