< prev index next >

src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java

Print this page
rev 1580 : 6727661: Code improvement and warnings removing from the swing/plaf packages
Summary: Removed unnecessary castings and other warnings
Reviewed-by: alexp
Contributed-by: Florian Brunner <fbrunnerlist@gmx.ch>


  26 package javax.swing.plaf.basic;
  27 
  28 import java.io.File;
  29 import java.util.*;
  30 import javax.swing.*;
  31 import javax.swing.filechooser.*;
  32 import javax.swing.event.*;
  33 import java.beans.*;
  34 
  35 import sun.awt.shell.ShellFolder;
  36 
  37 /**
  38  * Basic implementation of a file list.
  39  *
  40  * @author Jeff Dinkins
  41  */
  42 public class BasicDirectoryModel extends AbstractListModel implements PropertyChangeListener {
  43 
  44     private JFileChooser filechooser = null;
  45     // PENDING(jeff) pick the size more sensibly
  46     private Vector fileCache = new Vector(50);
  47     private LoadFilesThread loadThread = null;
  48     private Vector files = null;
  49     private Vector directories = null;
  50     private int fetchID = 0;
  51 
  52     private PropertyChangeSupport changeSupport;
  53 
  54     private boolean busy = false;
  55 
  56     public BasicDirectoryModel(JFileChooser filechooser) {
  57         this.filechooser = filechooser;
  58         validateFileCache();
  59     }
  60 
  61     public void propertyChange(PropertyChangeEvent e) {
  62         String prop = e.getPropertyName();
  63         if(prop == JFileChooser.DIRECTORY_CHANGED_PROPERTY ||
  64            prop == JFileChooser.FILE_VIEW_CHANGED_PROPERTY ||
  65            prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY ||
  66            prop == JFileChooser.FILE_HIDING_CHANGED_PROPERTY ||
  67            prop == JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY) {
  68             validateFileCache();
  69         } else if ("UI".equals(prop)) {


  89             loadThread.cancelRunnables();
  90             loadThread = null;
  91         }
  92     }
  93 
  94     public Vector<File> getDirectories() {
  95         synchronized(fileCache) {
  96             if (directories != null) {
  97                 return directories;
  98             }
  99             Vector fls = getFiles();
 100             return directories;
 101         }
 102     }
 103 
 104     public Vector<File> getFiles() {
 105         synchronized(fileCache) {
 106             if (files != null) {
 107                 return files;
 108             }
 109             files = new Vector();
 110             directories = new Vector();
 111             directories.addElement(filechooser.getFileSystemView().createFileObject(
 112                 filechooser.getCurrentDirectory(), "..")
 113             );
 114 
 115             for (int i = 0; i < getSize(); i++) {
 116                 File f = (File)fileCache.get(i);
 117                 if (filechooser.isTraversable(f)) {
 118                     directories.add(f);
 119                 } else {
 120                     files.add(f);
 121                 }
 122             }
 123             return files;
 124         }
 125     }
 126 
 127     public void validateFileCache() {
 128         File currentDirectory = filechooser.getCurrentDirectory();
 129         if (currentDirectory == null) {
 130             return;
 131         }
 132         if (loadThread != null) {
 133             loadThread.interrupt();
 134             loadThread.cancelRunnables();
 135         }
 136 


 198     protected void sort(Vector<? extends File> v){
 199         ShellFolder.sortFiles(v);
 200     }
 201 
 202     // Obsolete - not used
 203     protected boolean lt(File a, File b) {
 204         // First ignore case when comparing
 205         int diff = a.getName().toLowerCase().compareTo(b.getName().toLowerCase());
 206         if (diff != 0) {
 207             return diff < 0;
 208         } else {
 209             // May differ in case (e.g. "mail" vs. "Mail")
 210             return a.getName().compareTo(b.getName()) < 0;
 211         }
 212     }
 213 
 214 
 215     class LoadFilesThread extends Thread {
 216         File currentDirectory = null;
 217         int fid;
 218         Vector runnables = new Vector(10);
 219 
 220         public LoadFilesThread(File currentDirectory, int fid) {
 221             super("Basic L&F File Loading Thread");
 222             this.currentDirectory = currentDirectory;
 223             this.fid = fid;
 224         }
 225 
 226         private void invokeLater(Runnable runnable) {
 227             runnables.addElement(runnable);
 228             SwingUtilities.invokeLater(runnable);
 229         }
 230 
 231         public void run() {
 232             run0();
 233             setBusy(false, fid);
 234         }
 235 
 236         public void run0() {
 237             try {
 238                 FileSystemView fileSystem = filechooser.getFileSystemView();
 239 
 240                 File[] list = fileSystem.getFiles(currentDirectory, filechooser.isFileHidingEnabled());
 241 
 242                 Vector<File> acceptsList = new Vector<File>();
 243 
 244                 if (isInterrupted()) {
 245                     return;
 246                 }
 247 
 248                 // run through the file list, add directories and selectable files to fileCache
 249                 for (int i = 0; i < list.length; i++) {
 250                     if(filechooser.accept(list[i])) {
 251                         acceptsList.addElement(list[i]);
 252                     }
 253                 }
 254 
 255                 if (isInterrupted()) {
 256                     return;
 257                 }
 258 
 259                 // First sort alphabetically by filename
 260                 sort(acceptsList);
 261 
 262                 Vector newDirectories = new Vector(50);
 263                 Vector newFiles = new Vector();
 264                 // run through list grabbing directories in chunks of ten
 265                 for(int i = 0; i < acceptsList.size(); i++) {
 266                     File f = (File) acceptsList.elementAt(i);
 267                     boolean isTraversable = filechooser.isTraversable(f);
 268                     if (isTraversable) {
 269                         newDirectories.addElement(f);
 270                     } else if (!isTraversable && filechooser.isFileSelectionEnabled()) {
 271                         newFiles.addElement(f);
 272                     }
 273                     if(isInterrupted()) {
 274                         return;
 275                     }
 276                 }
 277 
 278                 Vector newFileCache = new Vector(newDirectories);
 279                 newFileCache.addAll(newFiles);
 280 
 281                 int newSize = newFileCache.size();
 282                 int oldSize = fileCache.size();
 283 
 284                 if (newSize > oldSize) {
 285                     //see if interval is added
 286                     int start = oldSize;
 287                     int end = newSize;
 288                     for (int i = 0; i < oldSize; i++) {
 289                         if (!newFileCache.get(i).equals(fileCache.get(i))) {
 290                             start = i;
 291                             for (int j = i; j < newSize; j++) {
 292                                 if (newFileCache.get(j).equals(fileCache.get(i))) {
 293                                     end = j;
 294                                     break;
 295                                 }
 296                             }
 297                             break;
 298                         }


 304                         }
 305                         invokeLater(new DoChangeContents(newFileCache.subList(start, end), start, null, 0, fid));
 306                         newFileCache = null;
 307                     }
 308                 } else if (newSize < oldSize) {
 309                     //see if interval is removed
 310                     int start = -1;
 311                     int end = -1;
 312                     for (int i = 0; i < newSize; i++) {
 313                         if (!newFileCache.get(i).equals(fileCache.get(i))) {
 314                             start = i;
 315                             end = i + oldSize - newSize;
 316                             break;
 317                         }
 318                     }
 319                     if (start >= 0 && end > start
 320                         && fileCache.subList(end, oldSize).equals(newFileCache.subList(start, newSize))) {
 321                         if(isInterrupted()) {
 322                             return;
 323                         }
 324                         invokeLater(new DoChangeContents(null, 0, new Vector(fileCache.subList(start, end)),
 325                                                          start, fid));
 326                         newFileCache = null;
 327                     }
 328                 }
 329                 if (newFileCache != null && !fileCache.equals(newFileCache)) {
 330                     if (isInterrupted()) {
 331                         cancelRunnables(runnables);
 332                     }
 333                     invokeLater(new DoChangeContents(newFileCache, 0, fileCache, 0, fid));
 334                 }
 335             } catch (RuntimeException e) {
 336                 if (!(e.getCause() instanceof InterruptedException /* just exit on interruption */)) {
 337                     throw e;
 338                 }
 339             }
 340         }
 341 
 342 
 343         public void cancelRunnables(Vector runnables) {
 344             for(int i = 0; i < runnables.size(); i++) {
 345                 ((DoChangeContents)runnables.elementAt(i)).cancel();
 346             }
 347         }
 348 
 349         public void cancelRunnables() {
 350             cancelRunnables(runnables);
 351         }
 352    }
 353 
 354 
 355     /**
 356      * Adds a PropertyChangeListener to the listener list. The listener is
 357      * registered for all bound properties of this class.
 358      * <p>
 359      * If <code>listener</code> is <code>null</code>,
 360      * no exception is thrown and no action is performed.
 361      *
 362      * @param    listener  the property change listener to be added
 363      *
 364      * @see #removePropertyChangeListener
 365      * @see #getPropertyChangeListeners


 438      * busy when it is running a separate (interruptable)
 439      * thread in order to load the contents of a directory.
 440      */
 441     private synchronized void setBusy(final boolean busy, int fid) {
 442         if (fid == fetchID) {
 443             boolean oldValue = this.busy;
 444             this.busy = busy;
 445 
 446             if (changeSupport != null && busy != oldValue) {
 447                 SwingUtilities.invokeLater(new Runnable() {
 448                     public void run() {
 449                         firePropertyChange("busy", !busy, busy);
 450                     }
 451                 });
 452             }
 453         }
 454     }
 455 
 456 
 457     class DoChangeContents implements Runnable {
 458         private List addFiles;
 459         private List remFiles;
 460         private boolean doFire = true;
 461         private int fid;
 462         private int addStart = 0;
 463         private int remStart = 0;
 464         private int change;
 465 
 466         public DoChangeContents(List addFiles, int addStart, List remFiles, int remStart, int fid) {
 467             this.addFiles = addFiles;
 468             this.addStart = addStart;
 469             this.remFiles = remFiles;
 470             this.remStart = remStart;
 471             this.fid = fid;
 472         }
 473 
 474         synchronized void cancel() {
 475                 doFire = false;
 476         }
 477 
 478         public synchronized void run() {
 479             if (fetchID == fid && doFire) {
 480                 int remSize = (remFiles == null) ? 0 : remFiles.size();
 481                 int addSize = (addFiles == null) ? 0 : addFiles.size();
 482                 synchronized(fileCache) {
 483                     if (remSize > 0) {
 484                         fileCache.removeAll(remFiles);
 485                     }
 486                     if (addSize > 0) {


  26 package javax.swing.plaf.basic;
  27 
  28 import java.io.File;
  29 import java.util.*;
  30 import javax.swing.*;
  31 import javax.swing.filechooser.*;
  32 import javax.swing.event.*;
  33 import java.beans.*;
  34 
  35 import sun.awt.shell.ShellFolder;
  36 
  37 /**
  38  * Basic implementation of a file list.
  39  *
  40  * @author Jeff Dinkins
  41  */
  42 public class BasicDirectoryModel extends AbstractListModel implements PropertyChangeListener {
  43 
  44     private JFileChooser filechooser = null;
  45     // PENDING(jeff) pick the size more sensibly
  46     private Vector<File> fileCache = new Vector<File>(50);
  47     private LoadFilesThread loadThread = null;
  48     private Vector<File> files = null;
  49     private Vector<File> directories = null;
  50     private int fetchID = 0;
  51 
  52     private PropertyChangeSupport changeSupport;
  53 
  54     private boolean busy = false;
  55 
  56     public BasicDirectoryModel(JFileChooser filechooser) {
  57         this.filechooser = filechooser;
  58         validateFileCache();
  59     }
  60 
  61     public void propertyChange(PropertyChangeEvent e) {
  62         String prop = e.getPropertyName();
  63         if(prop == JFileChooser.DIRECTORY_CHANGED_PROPERTY ||
  64            prop == JFileChooser.FILE_VIEW_CHANGED_PROPERTY ||
  65            prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY ||
  66            prop == JFileChooser.FILE_HIDING_CHANGED_PROPERTY ||
  67            prop == JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY) {
  68             validateFileCache();
  69         } else if ("UI".equals(prop)) {


  89             loadThread.cancelRunnables();
  90             loadThread = null;
  91         }
  92     }
  93 
  94     public Vector<File> getDirectories() {
  95         synchronized(fileCache) {
  96             if (directories != null) {
  97                 return directories;
  98             }
  99             Vector fls = getFiles();
 100             return directories;
 101         }
 102     }
 103 
 104     public Vector<File> getFiles() {
 105         synchronized(fileCache) {
 106             if (files != null) {
 107                 return files;
 108             }
 109             files = new Vector<File>();
 110             directories = new Vector<File>();
 111             directories.addElement(filechooser.getFileSystemView().createFileObject(
 112                 filechooser.getCurrentDirectory(), "..")
 113             );
 114 
 115             for (int i = 0; i < getSize(); i++) {
 116                 File f = fileCache.get(i);
 117                 if (filechooser.isTraversable(f)) {
 118                     directories.add(f);
 119                 } else {
 120                     files.add(f);
 121                 }
 122             }
 123             return files;
 124         }
 125     }
 126 
 127     public void validateFileCache() {
 128         File currentDirectory = filechooser.getCurrentDirectory();
 129         if (currentDirectory == null) {
 130             return;
 131         }
 132         if (loadThread != null) {
 133             loadThread.interrupt();
 134             loadThread.cancelRunnables();
 135         }
 136 


 198     protected void sort(Vector<? extends File> v){
 199         ShellFolder.sortFiles(v);
 200     }
 201 
 202     // Obsolete - not used
 203     protected boolean lt(File a, File b) {
 204         // First ignore case when comparing
 205         int diff = a.getName().toLowerCase().compareTo(b.getName().toLowerCase());
 206         if (diff != 0) {
 207             return diff < 0;
 208         } else {
 209             // May differ in case (e.g. "mail" vs. "Mail")
 210             return a.getName().compareTo(b.getName()) < 0;
 211         }
 212     }
 213 
 214 
 215     class LoadFilesThread extends Thread {
 216         File currentDirectory = null;
 217         int fid;
 218         Vector<DoChangeContents> runnables = new Vector<DoChangeContents>(10);
 219 
 220         public LoadFilesThread(File currentDirectory, int fid) {
 221             super("Basic L&F File Loading Thread");
 222             this.currentDirectory = currentDirectory;
 223             this.fid = fid;
 224         }
 225 
 226         private void invokeLater(DoChangeContents runnable) {
 227             runnables.addElement(runnable);
 228             SwingUtilities.invokeLater(runnable);
 229         }
 230 
 231         public void run() {
 232             run0();
 233             setBusy(false, fid);
 234         }
 235 
 236         public void run0() {
 237             try {
 238                 FileSystemView fileSystem = filechooser.getFileSystemView();
 239 
 240                 File[] list = fileSystem.getFiles(currentDirectory, filechooser.isFileHidingEnabled());
 241 
 242                 Vector<File> acceptsList = new Vector<File>();
 243 
 244                 if (isInterrupted()) {
 245                     return;
 246                 }
 247 
 248                 // run through the file list, add directories and selectable files to fileCache
 249                 for (File file : list) {
 250                     if (filechooser.accept(file)) {
 251                         acceptsList.addElement(file);
 252                     }
 253                 }
 254 
 255                 if (isInterrupted()) {
 256                     return;
 257                 }
 258 
 259                 // First sort alphabetically by filename
 260                 sort(acceptsList);
 261 
 262                 Vector<File> newDirectories = new Vector<File>(50);
 263                 Vector<File> newFiles = new Vector<File>();
 264                 // run through list grabbing directories in chunks of ten
 265                 for(int i = 0; i < acceptsList.size(); i++) {
 266                     File f = acceptsList.elementAt(i);
 267                     boolean isTraversable = filechooser.isTraversable(f);
 268                     if (isTraversable) {
 269                         newDirectories.addElement(f);
 270                     } else if (!isTraversable && filechooser.isFileSelectionEnabled()) {
 271                         newFiles.addElement(f);
 272                     }
 273                     if(isInterrupted()) {
 274                         return;
 275                     }
 276                 }
 277 
 278                 Vector<File> newFileCache = new Vector<File>(newDirectories);
 279                 newFileCache.addAll(newFiles);
 280 
 281                 int newSize = newFileCache.size();
 282                 int oldSize = fileCache.size();
 283 
 284                 if (newSize > oldSize) {
 285                     //see if interval is added
 286                     int start = oldSize;
 287                     int end = newSize;
 288                     for (int i = 0; i < oldSize; i++) {
 289                         if (!newFileCache.get(i).equals(fileCache.get(i))) {
 290                             start = i;
 291                             for (int j = i; j < newSize; j++) {
 292                                 if (newFileCache.get(j).equals(fileCache.get(i))) {
 293                                     end = j;
 294                                     break;
 295                                 }
 296                             }
 297                             break;
 298                         }


 304                         }
 305                         invokeLater(new DoChangeContents(newFileCache.subList(start, end), start, null, 0, fid));
 306                         newFileCache = null;
 307                     }
 308                 } else if (newSize < oldSize) {
 309                     //see if interval is removed
 310                     int start = -1;
 311                     int end = -1;
 312                     for (int i = 0; i < newSize; i++) {
 313                         if (!newFileCache.get(i).equals(fileCache.get(i))) {
 314                             start = i;
 315                             end = i + oldSize - newSize;
 316                             break;
 317                         }
 318                     }
 319                     if (start >= 0 && end > start
 320                         && fileCache.subList(end, oldSize).equals(newFileCache.subList(start, newSize))) {
 321                         if(isInterrupted()) {
 322                             return;
 323                         }
 324                         invokeLater(new DoChangeContents(null, 0, new Vector<File>(fileCache.subList(start, end)),
 325                                                          start, fid));
 326                         newFileCache = null;
 327                     }
 328                 }
 329                 if (newFileCache != null && !fileCache.equals(newFileCache)) {
 330                     if (isInterrupted()) {
 331                         cancelRunnables(runnables);
 332                     }
 333                     invokeLater(new DoChangeContents(newFileCache, 0, fileCache, 0, fid));
 334                 }
 335             } catch (RuntimeException e) {
 336                 if (!(e.getCause() instanceof InterruptedException /* just exit on interruption */)) {
 337                     throw e;
 338                 }
 339             }
 340         }
 341 
 342 
 343         public void cancelRunnables(Vector<DoChangeContents> runnables) {
 344             for (DoChangeContents runnable : runnables) {
 345                 runnable.cancel();
 346             }
 347         }
 348 
 349         public void cancelRunnables() {
 350             cancelRunnables(runnables);
 351         }
 352    }
 353 
 354 
 355     /**
 356      * Adds a PropertyChangeListener to the listener list. The listener is
 357      * registered for all bound properties of this class.
 358      * <p>
 359      * If <code>listener</code> is <code>null</code>,
 360      * no exception is thrown and no action is performed.
 361      *
 362      * @param    listener  the property change listener to be added
 363      *
 364      * @see #removePropertyChangeListener
 365      * @see #getPropertyChangeListeners


 438      * busy when it is running a separate (interruptable)
 439      * thread in order to load the contents of a directory.
 440      */
 441     private synchronized void setBusy(final boolean busy, int fid) {
 442         if (fid == fetchID) {
 443             boolean oldValue = this.busy;
 444             this.busy = busy;
 445 
 446             if (changeSupport != null && busy != oldValue) {
 447                 SwingUtilities.invokeLater(new Runnable() {
 448                     public void run() {
 449                         firePropertyChange("busy", !busy, busy);
 450                     }
 451                 });
 452             }
 453         }
 454     }
 455 
 456 
 457     class DoChangeContents implements Runnable {
 458         private List<File> addFiles;
 459         private List<File> remFiles;
 460         private boolean doFire = true;
 461         private int fid;
 462         private int addStart = 0;
 463         private int remStart = 0;

 464 
 465         public DoChangeContents(List<File> addFiles, int addStart, List<File> remFiles, int remStart, int fid) {
 466             this.addFiles = addFiles;
 467             this.addStart = addStart;
 468             this.remFiles = remFiles;
 469             this.remStart = remStart;
 470             this.fid = fid;
 471         }
 472 
 473         synchronized void cancel() {
 474                 doFire = false;
 475         }
 476 
 477         public synchronized void run() {
 478             if (fetchID == fid && doFire) {
 479                 int remSize = (remFiles == null) ? 0 : remFiles.size();
 480                 int addSize = (addFiles == null) ? 0 : addFiles.size();
 481                 synchronized(fileCache) {
 482                     if (remSize > 0) {
 483                         fileCache.removeAll(remFiles);
 484                     }
 485                     if (addSize > 0) {
< prev index next >