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