1 /////////////////////////////////////////////////////////////////////////////////////////////// 2 // checkstyle: Checks Java source code and other text files for adherence to a set of rules. 3 // Copyright (C) 2001-2024 the original author or authors. 4 // 5 // This library is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 2.1 of the License, or (at your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 /////////////////////////////////////////////////////////////////////////////////////////////// 19 20 package com.puppycrawl.tools.checkstyle.gui; 21 22 import javax.swing.ListSelectionModel; 23 import javax.swing.tree.DefaultTreeSelectionModel; 24 import javax.swing.tree.TreePath; 25 26 /** 27 * ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel 28 * to listen for changes in the ListSelectionModel it maintains. Once 29 * a change in the ListSelectionModel happens, the paths are updated 30 * in the DefaultTreeSelectionModel. 31 * 32 */ 33 final class ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel { 34 35 /** A unique serial version identifier. */ 36 private static final long serialVersionUID = 2267930983939339510L; 37 /** TreeTable to perform updates on. */ 38 private final TreeTable treeTable; 39 /** Set to true when we are updating the ListSelectionModel. */ 40 private boolean updatingListSelectionModel; 41 42 /** 43 * Constructor to initialise treeTable. 44 * 45 * @param jTreeTable TreeTable to perform updates on. 46 */ 47 /* package */ ListToTreeSelectionModelWrapper(TreeTable jTreeTable) { 48 treeTable = jTreeTable; 49 getListSelectionModel().addListSelectionListener(event -> { 50 updateSelectedPathsFromSelectedRows(); 51 }); 52 } 53 54 /** 55 * Returns the list selection model. ListToTreeSelectionModelWrapper 56 * listens for changes to this model and updates the selected paths 57 * accordingly. 58 * 59 * @return the list selection model 60 */ 61 public ListSelectionModel getListSelectionModel() { 62 return listSelectionModel; 63 } 64 65 /** 66 * This is overridden to set {@code updatingListSelectionModel} 67 * and message super. This is the only place DefaultTreeSelectionModel 68 * alters the ListSelectionModel. 69 */ 70 @Override 71 public void resetRowSelection() { 72 if (!updatingListSelectionModel) { 73 updatingListSelectionModel = true; 74 try { 75 super.resetRowSelection(); 76 } 77 finally { 78 updatingListSelectionModel = false; 79 } 80 } 81 // Notice how we don't message super if 82 // updatingListSelectionModel is true. If 83 // updatingListSelectionModel is true, it implies the 84 // ListSelectionModel has already been updated and the 85 // paths are the only thing that needs to be updated. 86 } 87 88 /** 89 * If {@code updatingListSelectionModel} is false, this will 90 * reset the selected paths from the selected rows in the list 91 * selection model. 92 */ 93 private void updateSelectedPathsFromSelectedRows() { 94 if (!updatingListSelectionModel) { 95 updatingListSelectionModel = true; 96 try { 97 // This is way expensive, ListSelectionModel needs an 98 // enumerator for iterating. 99 final int min = listSelectionModel.getMinSelectionIndex(); 100 final int max = listSelectionModel.getMaxSelectionIndex(); 101 102 clearSelection(); 103 if (min != -1 && max != -1) { 104 for (int counter = min; counter <= max; counter++) { 105 updateSelectedPathIfRowIsSelected(counter); 106 } 107 } 108 } 109 finally { 110 updatingListSelectionModel = false; 111 } 112 } 113 } 114 115 /** 116 * If the row at given index is selected, selected paths are updated. 117 * 118 * @param counter number of row. 119 */ 120 private void updateSelectedPathIfRowIsSelected(int counter) { 121 if (listSelectionModel.isSelectedIndex(counter)) { 122 final TreePath selPath = treeTable.getTree().getPathForRow(counter); 123 124 if (selPath != null) { 125 addSelectionPath(selPath); 126 } 127 } 128 } 129 130 }