1 //////////////////////////////////////////////////////////////////////////////// 2 // checkstyle: Checks Java source code for adherence to a set of rules. 3 // Copyright (C) 2001-2019 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 class ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel { 34 35 private static final long serialVersionUID = 2267930983939339510L; 36 /** TreeTable to perform updates on. */ 37 private final TreeTable treeTable; 38 /** Set to true when we are updating the ListSelectionModel. */ 39 private boolean updatingListSelectionModel; 40 41 /** 42 * Constructor to initialise treeTable. 43 * @param jTreeTable TreeTable to perform updates on. 44 */ 45 /* package */ ListToTreeSelectionModelWrapper(TreeTable jTreeTable) { 46 treeTable = jTreeTable; 47 getListSelectionModel().addListSelectionListener(event -> { 48 updateSelectedPathsFromSelectedRows(); 49 }); 50 } 51 52 /** 53 * Returns the list selection model. ListToTreeSelectionModelWrapper 54 * listens for changes to this model and updates the selected paths 55 * accordingly. 56 * 57 * @return the list selection model 58 */ 59 protected final ListSelectionModel getListSelectionModel() { 60 return listSelectionModel; 61 } 62 63 /** 64 * This is overridden to set {@code updatingListSelectionModel} 65 * and message super. This is the only place DefaultTreeSelectionModel 66 * alters the ListSelectionModel. 67 */ 68 @Override 69 public void resetRowSelection() { 70 if (!updatingListSelectionModel) { 71 updatingListSelectionModel = true; 72 try { 73 super.resetRowSelection(); 74 } 75 finally { 76 updatingListSelectionModel = false; 77 } 78 } 79 // Notice how we don't message super if 80 // updatingListSelectionModel is true. If 81 // updatingListSelectionModel is true, it implies the 82 // ListSelectionModel has already been updated and the 83 // paths are the only thing that needs to be updated. 84 } 85 86 /** 87 * If {@code updatingListSelectionModel} is false, this will 88 * reset the selected paths from the selected rows in the list 89 * selection model. 90 */ 91 private void updateSelectedPathsFromSelectedRows() { 92 if (!updatingListSelectionModel) { 93 updatingListSelectionModel = true; 94 try { 95 // This is way expensive, ListSelectionModel needs an 96 // enumerator for iterating. 97 final int min = listSelectionModel.getMinSelectionIndex(); 98 final int max = listSelectionModel.getMaxSelectionIndex(); 99 100 clearSelection(); 101 if (min != -1 && max != -1) { 102 for (int counter = min; counter <= max; counter++) { 103 updateSelectedPathIfRowIsSelected(counter); 104 } 105 } 106 } 107 finally { 108 updatingListSelectionModel = false; 109 } 110 } 111 } 112 113 /** 114 * If the row at given index is selected, selected paths are updated. 115 * @param counter number of row. 116 */ 117 private void updateSelectedPathIfRowIsSelected(int counter) { 118 if (listSelectionModel.isSelectedIndex(counter)) { 119 final TreePath selPath = treeTable.getTree().getPathForRow(counter); 120 121 if (selPath != null) { 122 addSelectionPath(selPath); 123 } 124 } 125 } 126 127 }