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