@@ -103,7 +103,13 @@ public boolean isDirectory() {
103103 return new File (this .path ).isDirectory ();
104104 }
105105
106- public File [] updatedChildrenFiles (final boolean sort ) {
106+ /**
107+ *
108+ * @param sort
109+ * @param file_filter Applies to leafs, not to directories.
110+ * @return
111+ */
112+ public File [] updatedChildrenFiles (final boolean sort , final FileFilter file_filter ) {
107113 final File file = new File (this .path );
108114 if (!file .isDirectory ()) {
109115 return new File [0 ];
@@ -112,7 +118,8 @@ public File[] updatedChildrenFiles(final boolean sort) {
112118 @ Override
113119 public boolean accept (final File f ) {
114120 return !f .isHidden () && !f .getName ().endsWith ("~" )
115- && !re_ignored_extensions .matcher (f .getName ()).matches ();
121+ && !re_ignored_extensions .matcher (f .getName ()).matches ()
122+ && (f .isDirectory () || file_filter .accept (f ));
116123 }
117124 });
118125 if (sort ) Arrays .sort (files );
@@ -122,11 +129,11 @@ public boolean accept(final File f) {
122129 /**
123130 * If it's a directory, add a Node for each of its visible files.
124131 */
125- public synchronized void populateChildren (final DefaultTreeModel model ) {
132+ public synchronized void populateChildren (final DefaultTreeModel model , final FileFilter file_filter ) {
126133 try {
127134 if (isLeaf ()) return ;
128135 int index = 0 ;
129- for (final File file : updatedChildrenFiles (true )) {
136+ for (final File file : updatedChildrenFiles (true , file_filter )) {
130137 // Can't use add: would try to insert at getChildCount(), which is the wrong value here
131138 model .insertNodeInto (new Node (file .getAbsolutePath ()), this , index ++);
132139 }
@@ -207,9 +214,9 @@ public synchronized void removeAllChildren(final DefaultTreeModel model) {
207214 }
208215 }
209216
210- public synchronized void updateChildrenList (final DefaultTreeModel model ) {
217+ public synchronized void updateChildrenList (final DefaultTreeModel model , final FileFilter file_filter ) {
211218 removeAllChildren (model );
212- populateChildren (model );
219+ populateChildren (model , file_filter );
213220 }
214221 }
215222
@@ -225,6 +232,7 @@ public interface LeafListener {
225232
226233 private final HashSet <String > ignored_extensions = new HashSet <>();
227234 private Pattern re_ignored_extensions = Pattern .compile ("^.*$" , Pattern .CASE_INSENSITIVE ); // match all
235+ private FileFilter file_filter = ((f ) -> true );
228236
229237 public FileSystemTree (final Logger log )
230238 {
@@ -238,7 +246,7 @@ public FileSystemTree(final Logger log)
238246 @ Override
239247 public void treeWillExpand (TreeExpansionEvent event ) throws ExpandVetoException {
240248 final Node node = ((Node )event .getPath ().getLastPathComponent ());
241- node .populateChildren (getModel ());
249+ node .populateChildren (getModel (), file_filter );
242250 dir_watcher .register (node );
243251 }
244252
@@ -329,6 +337,46 @@ private void updateIgnoreExtensionPattern() {
329337 this .re_ignored_extensions = Pattern .compile (s .toString (), Pattern .CASE_INSENSITIVE );
330338 }
331339 }
340+
341+ public void setFileFilter (final FileFilter file_filter ) {
342+ this .file_filter = file_filter ;
343+ updateRecursively (file_filter );
344+ }
345+
346+ private void updateRecursively (final FileFilter file_filter ) {
347+ // Find expanded directories
348+ final ArrayList <Node > stack = new ArrayList <>();
349+ final Node root = (Node ) this .getModel ().getRoot ();
350+ for (int i =root .getChildCount () -1 ; i >-1 ; --i ) {
351+ stack .add ((Node )root .getChildAt (i ));
352+ }
353+ final ArrayList <Node > stack2 = new ArrayList <>(stack ); // copy for second phase
354+ final HashSet <String > expanded = new HashSet <>();
355+ while (!stack .isEmpty ()) {
356+ final Node node = stack .remove (0 );
357+ if (this .isExpanded (new TreePath (node .getPath ()))) {
358+ expanded .add (node .path );
359+ for (int i =node .getChildCount () -1 ; i >-1 ; --i ) {
360+ final Node child = node .getChildAt (i );
361+ if (child .isDirectory ()) stack .add (child );
362+ }
363+ }
364+ }
365+ // Re-list all files, filtering
366+ while (!stack2 .isEmpty ()) {
367+ final Node node = stack2 .remove (0 );
368+ if (expanded .contains (node .path )) {
369+ node .removeAllChildren (this .getModel ());
370+ node .populateChildren (this .getModel (), file_filter );
371+ final int count = node .getChildCount ();
372+ if (count > 0 ) expandPath (new TreePath (node .getChildAt (0 ).getPath ())); // awkward way to ensure parent is expanded
373+ for (int i =0 ; i <count ; ++i ) {
374+ final Node child = node .getChildAt (i );
375+ if (expanded .contains (child .path )) stack2 .add (child );
376+ }
377+ }
378+ }
379+ }
332380
333381 synchronized public void addLeafListener (final LeafListener l ) {
334382 this .leaf_listeners .add (l );
@@ -508,7 +556,7 @@ public void run() {
508556
509557 SwingUtilities .invokeLater (() -> {
510558 for (final Node node : nodes ) {
511- node .updateChildrenList (FileSystemTree .this .getModel ());
559+ node .updateChildrenList (FileSystemTree .this .getModel (), file_filter );
512560 FileSystemTree .this .expandPath (new TreePath (node .getPath ()));
513561 }
514562 });
0 commit comments