| 1 | package com.jsql.view.swing.table; | |
| 2 | ||
| 3 | import javax.swing.*; | |
| 4 | import javax.swing.event.ChangeEvent; | |
| 5 | import javax.swing.event.ChangeListener; | |
| 6 | import javax.swing.table.DefaultTableModel; | |
| 7 | import javax.swing.table.TableColumn; | |
| 8 | import javax.swing.table.TableColumnModel; | |
| 9 | import java.beans.PropertyChangeEvent; | |
| 10 | import java.beans.PropertyChangeListener; | |
| 11 | ||
| 12 | /** | |
| 13 | * Prevent the specified number of columns from scrolling horizontally in | |
| 14 | * the scroll pane. The table must already exist in the scroll pane. | |
| 15 | * | |
| 16 | * The functionality is accomplished by creating a second JTable (fixed) | |
| 17 | * that will share the TableModel and SelectionModel of the main table. | |
| 18 | * This table will be used as the row header of the scroll pane. | |
| 19 | * | |
| 20 | * The fixed table created can be accessed by using the getFixedTable() | |
| 21 | * method. will be returned from this method. It will allow you to: | |
| 22 | * | |
| 23 | * You can change the model of the main table and the change will be | |
| 24 | * reflected in the fixed model. However, you cannot change the structure | |
| 25 | * of the model. | |
| 26 | */ | |
| 27 | public class FixedColumnTable implements ChangeListener, PropertyChangeListener { | |
| 28 | | |
| 29 | private JTable mainTable; | |
| 30 | | |
| 31 | private JTable fixedTable; | |
| 32 | | |
| 33 | private JScrollPane scrollPane; | |
| 34 | ||
| 35 | /** | |
| 36 | * Specify the number of columns to be fixed and the scroll pane | |
| 37 | * containing the table. | |
| 38 | */ | |
| 39 | public void fixColumnSize(int fixedColumns, JScrollPane scrollPane) { | |
| 40 | this.scrollPane = scrollPane; | |
| 41 | ||
| 42 | this.mainTable = (JTable) scrollPane.getViewport().getView(); | |
| 43 |
1
1. fixColumnSize : removed call to javax/swing/JTable::setAutoCreateColumnsFromModel → NO_COVERAGE |
this.mainTable.setAutoCreateColumnsFromModel(false); |
| 44 |
1
1. fixColumnSize : removed call to javax/swing/JTable::addPropertyChangeListener → NO_COVERAGE |
this.mainTable.addPropertyChangeListener(this); |
| 45 | ||
| 46 | // Use the existing table to create a new table sharing | |
| 47 | // the DataModel and ListSelectionModel | |
| 48 | this.fixedTable = new JTable() { | |
| 49 | @Override | |
| 50 | public boolean isCellEditable(int row,int column) { | |
| 51 |
1
1. isCellEditable : replaced boolean return with true for com/jsql/view/swing/table/FixedColumnTable$1::isCellEditable → NO_COVERAGE |
return false; |
| 52 | } | |
| 53 | }; | |
| 54 | | |
| 55 |
1
1. fixColumnSize : removed call to javax/swing/JTable::setAutoCreateColumnsFromModel → NO_COVERAGE |
this.fixedTable.setAutoCreateColumnsFromModel(false); |
| 56 | | |
| 57 | final DefaultTableModel modelFixedTable = new DefaultTableModel() { | |
| 58 | @Override | |
| 59 | public int getColumnCount() { | |
| 60 |
1
1. getColumnCount : replaced int return with 0 for com/jsql/view/swing/table/FixedColumnTable$2::getColumnCount → NO_COVERAGE |
return 2; |
| 61 | } | |
| 62 | @Override | |
| 63 | public boolean isCellEditable(int row, int col) { | |
| 64 |
1
1. isCellEditable : replaced boolean return with true for com/jsql/view/swing/table/FixedColumnTable$2::isCellEditable → NO_COVERAGE |
return false; |
| 65 | } | |
| 66 | @Override | |
| 67 | public int getRowCount() { | |
| 68 |
1
1. getRowCount : replaced int return with 0 for com/jsql/view/swing/table/FixedColumnTable$2::getRowCount → NO_COVERAGE |
return FixedColumnTable.this.mainTable.getRowCount(); |
| 69 | } | |
| 70 | @Override | |
| 71 | public Class<?> getColumnClass(int colNum) { | |
| 72 | Class<?> columnClass; | |
| 73 |
1
1. getColumnClass : negated conditional → NO_COVERAGE |
if (colNum == 0) { |
| 74 | columnClass = String.class; | |
| 75 | } else { | |
| 76 | columnClass = super.getColumnClass(colNum); | |
| 77 | } | |
| 78 |
1
1. getColumnClass : replaced return value with null for com/jsql/view/swing/table/FixedColumnTable$2::getColumnClass → NO_COVERAGE |
return columnClass; |
| 79 | } | |
| 80 | }; | |
| 81 | | |
| 82 |
1
1. fixColumnSize : removed call to javax/swing/JTable::setModel → NO_COVERAGE |
this.fixedTable.setModel(modelFixedTable); |
| 83 |
1
1. fixColumnSize : removed call to javax/swing/JTable::setSelectionModel → NO_COVERAGE |
this.fixedTable.setSelectionModel(this.mainTable.getSelectionModel()); |
| 84 | | |
| 85 |
1
1. fixColumnSize : removed call to javax/swing/JTable::setRowHeight → NO_COVERAGE |
this.fixedTable.setRowHeight(20); |
| 86 |
1
1. fixColumnSize : removed call to javax/swing/JTable::setFocusable → NO_COVERAGE |
this.fixedTable.setFocusable(false); |
| 87 |
1
1. fixColumnSize : removed call to javax/swing/table/JTableHeader::setReorderingAllowed → NO_COVERAGE |
this.fixedTable.getTableHeader().setReorderingAllowed(false); |
| 88 | | |
| 89 | // Remove the fixed columns from the main table | |
| 90 | // and add them to the fixed table | |
| 91 | TableColumnModel columnModel = this.mainTable.getColumnModel(); | |
| 92 |
2
1. fixColumnSize : negated conditional → NO_COVERAGE 2. fixColumnSize : changed conditional boundary → NO_COVERAGE |
for (var i = 0 ; i < fixedColumns ; i++) { |
| 93 | TableColumn column = columnModel.getColumn(i); | |
| 94 |
1
1. fixColumnSize : removed call to javax/swing/table/TableColumn::setMinWidth → NO_COVERAGE |
column.setMinWidth(0); |
| 95 |
1
1. fixColumnSize : removed call to javax/swing/table/TableColumn::setMaxWidth → NO_COVERAGE |
column.setMaxWidth(0); |
| 96 |
1
1. fixColumnSize : removed call to javax/swing/table/TableColumnModel::addColumn → NO_COVERAGE |
this.fixedTable.getColumnModel().addColumn(new TableColumn(i)); |
| 97 | } | |
| 98 | ||
| 99 |
1
1. fixColumnSize : removed call to javax/swing/table/TableColumn::setCellRenderer → NO_COVERAGE |
this.fixedTable.getColumnModel().getColumn(0).setCellRenderer(new RowHeaderRenderer()); |
| 100 |
1
1. fixColumnSize : removed call to javax/swing/table/TableColumn::setResizable → NO_COVERAGE |
this.fixedTable.getColumnModel().getColumn(0).setResizable(false); |
| 101 |
1
1. fixColumnSize : removed call to javax/swing/table/TableColumn::setPreferredWidth → NO_COVERAGE |
this.fixedTable.getColumnModel().getColumn(0).setPreferredWidth(38); |
| 102 |
1
1. fixColumnSize : removed call to javax/swing/table/TableColumn::setCellRenderer → NO_COVERAGE |
this.fixedTable.getColumnModel().getColumn(1).setCellRenderer(new RowHeaderRenderer()); |
| 103 |
1
1. fixColumnSize : removed call to javax/swing/table/TableColumn::setResizable → NO_COVERAGE |
this.fixedTable.getColumnModel().getColumn(1).setResizable(false); |
| 104 |
1
1. fixColumnSize : removed call to javax/swing/table/TableColumn::setPreferredWidth → NO_COVERAGE |
this.fixedTable.getColumnModel().getColumn(1).setPreferredWidth(38); |
| 105 | ||
| 106 |
1
1. fixColumnSize : removed call to javax/swing/RowSorter::addRowSorterListener → NO_COVERAGE |
this.mainTable.getRowSorter().addRowSorterListener(rowSorterEvent -> { |
| 107 |
1
1. lambda$fixColumnSize$0 : removed call to javax/swing/table/DefaultTableModel::fireTableDataChanged → NO_COVERAGE |
modelFixedTable.fireTableDataChanged(); |
| 108 | // Copy data from hidden column in main table | |
| 109 |
2
1. lambda$fixColumnSize$0 : negated conditional → NO_COVERAGE 2. lambda$fixColumnSize$0 : changed conditional boundary → NO_COVERAGE |
for (var i = 0; i < this.mainTable.getRowCount() ; i++) { |
| 110 |
1
1. lambda$fixColumnSize$0 : removed call to javax/swing/JTable::setValueAt → NO_COVERAGE |
this.fixedTable.setValueAt(this.mainTable.getValueAt(i, 0), i, 0); |
| 111 |
1
1. lambda$fixColumnSize$0 : removed call to javax/swing/JTable::setValueAt → NO_COVERAGE |
this.fixedTable.setValueAt(this.mainTable.getValueAt(i, 1), i, 1); |
| 112 | } | |
| 113 | }); | |
| 114 | | |
| 115 |
1
1. fixColumnSize : removed call to javax/swing/ListSelectionModel::addListSelectionListener → NO_COVERAGE |
this.mainTable.getSelectionModel().addListSelectionListener(listSelectionEvent -> |
| 116 |
2
1. lambda$fixColumnSize$1 : Replaced integer subtraction with addition → NO_COVERAGE 2. lambda$fixColumnSize$1 : removed call to javax/swing/table/DefaultTableModel::fireTableRowsUpdated → NO_COVERAGE |
modelFixedTable.fireTableRowsUpdated(0, modelFixedTable.getRowCount() - 1) |
| 117 | ); | |
| 118 | | |
| 119 | // Copy data from first column of main table to fixed column | |
| 120 |
2
1. fixColumnSize : changed conditional boundary → NO_COVERAGE 2. fixColumnSize : negated conditional → NO_COVERAGE |
for (var i = 0 ; i < this.mainTable.getRowCount() ; i++) { |
| 121 |
1
1. fixColumnSize : removed call to javax/swing/JTable::setValueAt → NO_COVERAGE |
this.fixedTable.setValueAt(this.mainTable.getValueAt(i, 0), i, 0); |
| 122 |
1
1. fixColumnSize : removed call to javax/swing/JTable::setValueAt → NO_COVERAGE |
this.fixedTable.setValueAt(this.mainTable.getValueAt(i, 1), i, 1); |
| 123 | } | |
| 124 | | |
| 125 | // Add the fixed table to the scroll pane | |
| 126 |
1
1. fixColumnSize : removed call to javax/swing/JTable::setPreferredScrollableViewportSize → NO_COVERAGE |
this.fixedTable.setPreferredScrollableViewportSize(this.fixedTable.getPreferredSize()); |
| 127 |
1
1. fixColumnSize : removed call to javax/swing/JScrollPane::setRowHeaderView → NO_COVERAGE |
scrollPane.setRowHeaderView(this.fixedTable); |
| 128 |
1
1. fixColumnSize : removed call to javax/swing/JScrollPane::setCorner → NO_COVERAGE |
scrollPane.setCorner(ScrollPaneConstants.UPPER_LEFT_CORNER, this.fixedTable.getTableHeader()); |
| 129 | ||
| 130 | // Synchronize scrolling of the row header with the main table | |
| 131 |
1
1. fixColumnSize : removed call to javax/swing/JViewport::addChangeListener → NO_COVERAGE |
scrollPane.getRowHeader().addChangeListener(this); |
| 132 | } | |
| 133 | ||
| 134 | /** | |
| 135 | * Implement the ChangeListener | |
| 136 | */ | |
| 137 | @Override | |
| 138 | public void stateChanged(ChangeEvent e) { | |
| 139 | // Sync the scroll pane scrollbar with the row header | |
| 140 | JViewport viewport = (JViewport) e.getSource(); | |
| 141 |
1
1. stateChanged : removed call to javax/swing/JScrollBar::setValue → NO_COVERAGE |
this.scrollPane.getVerticalScrollBar().setValue(viewport.getViewPosition().y); |
| 142 | } | |
| 143 | | |
| 144 | /** | |
| 145 | * Implement the PropertyChangeListener | |
| 146 | */ | |
| 147 | @Override | |
| 148 | public void propertyChange(PropertyChangeEvent e) { | |
| 149 | // Keep the fixed table in sync with the main table | |
| 150 |
1
1. propertyChange : negated conditional → NO_COVERAGE |
if ("selectionModel".equals(e.getPropertyName())) { |
| 151 |
1
1. propertyChange : removed call to javax/swing/JTable::setSelectionModel → NO_COVERAGE |
this.fixedTable.setSelectionModel(this.mainTable.getSelectionModel()); |
| 152 | } | |
| 153 | ||
| 154 |
1
1. propertyChange : negated conditional → NO_COVERAGE |
if ("model".equals(e.getPropertyName())) { |
| 155 |
1
1. propertyChange : removed call to javax/swing/JTable::setModel → NO_COVERAGE |
this.fixedTable.setModel(this.mainTable.getModel()); |
| 156 | } | |
| 157 | } | |
| 158 | } | |
Mutations | ||
| 43 |
1.1 |
|
| 44 |
1.1 |
|
| 51 |
1.1 |
|
| 55 |
1.1 |
|
| 60 |
1.1 |
|
| 64 |
1.1 |
|
| 68 |
1.1 |
|
| 73 |
1.1 |
|
| 78 |
1.1 |
|
| 82 |
1.1 |
|
| 83 |
1.1 |
|
| 85 |
1.1 |
|
| 86 |
1.1 |
|
| 87 |
1.1 |
|
| 92 |
1.1 2.2 |
|
| 94 |
1.1 |
|
| 95 |
1.1 |
|
| 96 |
1.1 |
|
| 99 |
1.1 |
|
| 100 |
1.1 |
|
| 101 |
1.1 |
|
| 102 |
1.1 |
|
| 103 |
1.1 |
|
| 104 |
1.1 |
|
| 106 |
1.1 |
|
| 107 |
1.1 |
|
| 109 |
1.1 2.2 |
|
| 110 |
1.1 |
|
| 111 |
1.1 |
|
| 115 |
1.1 |
|
| 116 |
1.1 2.2 |
|
| 120 |
1.1 2.2 |
|
| 121 |
1.1 |
|
| 122 |
1.1 |
|
| 126 |
1.1 |
|
| 127 |
1.1 |
|
| 128 |
1.1 |
|
| 131 |
1.1 |
|
| 141 |
1.1 |
|
| 150 |
1.1 |
|
| 151 |
1.1 |
|
| 154 |
1.1 |
|
| 155 |
1.1 |