View Javadoc
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 }