OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [swing/] [plaf/] [basic/] [BasicDirectoryModel.java] - Blame information for rev 772

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* BasicDirectoryModel.java --
2
   Copyright (C) 2005, 2006  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
package javax.swing.plaf.basic;
39
 
40
import java.beans.PropertyChangeEvent;
41
import java.beans.PropertyChangeListener;
42
import java.io.File;
43
import java.util.Collections;
44
import java.util.Comparator;
45
import java.util.Iterator;
46
import java.util.List;
47
import java.util.Vector;
48
import javax.swing.AbstractListModel;
49
import javax.swing.JFileChooser;
50
import javax.swing.SwingUtilities;
51
import javax.swing.event.ListDataEvent;
52
import javax.swing.filechooser.FileSystemView;
53
 
54
 
55
/**
56
 * Implements an AbstractListModel for directories where the source
57
 * of the files is a JFileChooser object.
58
 *
59
 * This class is used for sorting and ordering the file list in
60
 * a JFileChooser L&F object.
61
 */
62
public class BasicDirectoryModel extends AbstractListModel
63
  implements PropertyChangeListener
64
{
65
  /** The list of files itself */
66
  private Vector contents;
67
 
68
  /**
69
   * The directories in the list.
70
   */
71
  private Vector directories;
72
 
73
  /**
74
   * The files in the list.
75
   */
76
  private Vector files;
77
 
78
  /** The listing mode of the associated JFileChooser,
79
      either FILES_ONLY, DIRECTORIES_ONLY or FILES_AND_DIRECTORIES */
80
  private int listingMode;
81
 
82
  /** The JFileCooser associated with this model */
83
  private JFileChooser filechooser;
84
 
85
  /**
86
   * The thread that loads the file view.
87
   */
88
  private DirectoryLoadThread loadThread;
89
 
90
  /**
91
   * This thread is responsible for loading file lists from the
92
   * current directory and updating the model.
93
   */
94
  private class DirectoryLoadThread extends Thread
95
  {
96
 
97
    /**
98
     * Updates the Swing list model.
99
     */
100
    private class UpdateSwingRequest
101
      implements Runnable
102
    {
103
 
104
      private List added;
105
      private int addIndex;
106
      private List removed;
107
      private int removeIndex;
108
      private boolean cancel;
109
 
110
      UpdateSwingRequest(List add, int ai, List rem, int ri)
111
      {
112
        added = add;
113
        addIndex = ai;
114
        removed = rem;
115
        removeIndex = ri;
116
        cancel = false;
117
      }
118
 
119
      public void run()
120
      {
121
        if (! cancel)
122
          {
123
            int numRemoved = removed == null ? 0 : removed.size();
124
            int numAdded = added == null ? 0 : added.size();
125
            synchronized (contents)
126
              {
127
                if (numRemoved > 0)
128
                  contents.removeAll(removed);
129
                if (numAdded > 0)
130
                  contents.addAll(added);
131
 
132
                files = null;
133
                directories = null;
134
              }
135
            if (numRemoved > 0 && numAdded == 0)
136
              fireIntervalRemoved(BasicDirectoryModel.this, removeIndex,
137
                                  removeIndex + numRemoved - 1);
138
            else if (numRemoved == 0 && numAdded > 0)
139
              fireIntervalAdded(BasicDirectoryModel.this, addIndex,
140
                                addIndex + numAdded - 1);
141
            else
142
              fireContentsChanged();
143
          }
144
      }
145
 
146
      void cancel()
147
      {
148
        cancel = true;
149
      }
150
    }
151
 
152
    /**
153
     * The directory beeing loaded.
154
     */
155
    File directory;
156
 
157
    /**
158
     * Stores all UpdateSwingRequests that are sent to the event queue.
159
     */
160
    private UpdateSwingRequest pending;
161
 
162
    /**
163
     * Creates a new DirectoryLoadThread that loads the specified
164
     * directory.
165
     *
166
     * @param dir the directory to load
167
     */
168
    DirectoryLoadThread(File dir)
169
    {
170
      super("Basic L&F directory loader");
171
      directory = dir;
172
    }
173
 
174
    public void run()
175
    {
176
      FileSystemView fsv = filechooser.getFileSystemView();
177
      File[] files = fsv.getFiles(directory,
178
                                  filechooser.isFileHidingEnabled());
179
 
180
      // Occasional check if we have been interrupted.
181
      if (isInterrupted())
182
        return;
183
 
184
      // Check list for accepted files.
185
      Vector accepted = new Vector();
186
      for (int i = 0; i < files.length; i++)
187
        {
188
          if (filechooser.accept(files[i]))
189
            accepted.add(files[i]);
190
        }
191
 
192
      // Occasional check if we have been interrupted.
193
      if (isInterrupted())
194
        return;
195
 
196
      // Sort list.
197
      sort(accepted);
198
 
199
      // Now split up directories from files so that we get the directories
200
      // listed before the files.
201
      Vector newFiles = new Vector();
202
      Vector newDirectories = new Vector();
203
      for (Iterator i = accepted.iterator(); i.hasNext();)
204
        {
205
          File f = (File) i.next();
206
          boolean traversable = filechooser.isTraversable(f);
207
          if (traversable)
208
            newDirectories.add(f);
209
          else if (! traversable && filechooser.isFileSelectionEnabled())
210
            newFiles.add(f);
211
 
212
          // Occasional check if we have been interrupted.
213
          if (isInterrupted())
214
            return;
215
 
216
        }
217
 
218
      // Build up new file cache. Try to update only the changed elements.
219
      // This will be important for actions like adding new files or
220
      // directories inside a large file list.
221
      Vector newCache = new Vector(newDirectories);
222
      newCache.addAll(newFiles);
223
 
224
      int newSize = newCache.size();
225
      int oldSize = contents.size();
226
      if (newSize < oldSize)
227
        {
228
          // Check for removed interval.
229
          int start = -1;
230
          int end = -1;
231
          boolean found = false;
232
          for (int i = 0; i < newSize && !found; i++)
233
            {
234
              if (! newCache.get(i).equals(contents.get(i)))
235
                {
236
                  start = i;
237
                  end = i + oldSize - newSize;
238
                  found = true;
239
                }
240
            }
241
          if (start >= 0 && end > start
242
              && contents.subList(end, oldSize)
243
                                    .equals(newCache.subList(start, newSize)))
244
            {
245
              // Occasional check if we have been interrupted.
246
              if (isInterrupted())
247
                return;
248
 
249
              Vector removed = new Vector(contents.subList(start, end));
250
              UpdateSwingRequest r = new UpdateSwingRequest(null, 0,
251
                                                            removed, start);
252
              invokeLater(r);
253
              newCache = null;
254
            }
255
        }
256
      else if (newSize > oldSize)
257
        {
258
          // Check for inserted interval.
259
          int start = oldSize;
260
          int end = newSize;
261
          boolean found = false;
262
          for (int i = 0; i < oldSize && ! found; i++)
263
            {
264
              if (! newCache.get(i).equals(contents.get(i)))
265
                {
266
                  start = i;
267
                  boolean foundEnd = false;
268
                  for (int j = i; j < newSize && ! foundEnd; j++)
269
                    {
270
                      if (newCache.get(j).equals(contents.get(i)))
271
                        {
272
                          end = j;
273
                          foundEnd = true;
274
                        }
275
                    }
276
                  end = i + oldSize - newSize;
277
                }
278
            }
279
          if (start >= 0 && end > start
280
              && newCache.subList(end, newSize)
281
                                    .equals(contents.subList(start, oldSize)))
282
            {
283
              // Occasional check if we have been interrupted.
284
              if (isInterrupted())
285
                return;
286
 
287
              List added = newCache.subList(start, end);
288
              UpdateSwingRequest r = new UpdateSwingRequest(added, start,
289
                                                            null, 0);
290
              invokeLater(r);
291
              newCache = null;
292
            }
293
        }
294
 
295
      // Handle complete list changes (newCache != null).
296
      if (newCache != null && ! contents.equals(newCache))
297
        {
298
          // Occasional check if we have been interrupted.
299
          if (isInterrupted())
300
            return;
301
          UpdateSwingRequest r = new UpdateSwingRequest(newCache, 0,
302
                                                        contents, 0);
303
          invokeLater(r);
304
        }
305
    }
306
 
307
    /**
308
     * Wraps SwingUtilities.invokeLater() and stores the request in
309
     * a Vector so that we can still cancel it later.
310
     *
311
     * @param update the request to invoke
312
     */
313
    private void invokeLater(UpdateSwingRequest update)
314
    {
315
      pending = update;
316
      SwingUtilities.invokeLater(update);
317
    }
318
 
319
    /**
320
     * Cancels all pending update requests that might be in the AWT
321
     * event queue.
322
     */
323
    void cancelPending()
324
    {
325
      if (pending != null)
326
        pending.cancel();
327
    }
328
  }
329
 
330
  /** A Comparator class/object for sorting the file list. */
331
  private Comparator comparator = new Comparator()
332
    {
333
      public int compare(Object o1, Object o2)
334
      {
335
        if (lt((File) o1, (File) o2))
336
          return -1;
337
        else
338
          return 1;
339
      }
340
    };
341
 
342
  /**
343
   * Creates a new BasicDirectoryModel object.
344
   *
345
   * @param filechooser DOCUMENT ME!
346
   */
347
  public BasicDirectoryModel(JFileChooser filechooser)
348
  {
349
    this.filechooser = filechooser;
350
    filechooser.addPropertyChangeListener(this);
351
    listingMode = filechooser.getFileSelectionMode();
352
    contents = new Vector();
353
    validateFileCache();
354
  }
355
 
356
  /**
357
   * Returns whether a given (File) object is included in the list.
358
   *
359
   * @param o - The file object to test.
360
   *
361
   * @return <code>true</code> if the list contains the given object.
362
   */
363
  public boolean contains(Object o)
364
  {
365
    return contents.contains(o);
366
  }
367
 
368
  /**
369
   * Fires a content change event.
370
   */
371
  public void fireContentsChanged()
372
  {
373
    fireContentsChanged(this, 0, getSize() - 1);
374
  }
375
 
376
  /**
377
   * Returns a Vector of (java.io.File) objects containing
378
   * the directories in this list.
379
   *
380
   * @return a Vector
381
   */
382
  public Vector<File> getDirectories()
383
  {
384
    // Synchronize this with the UpdateSwingRequest for the case when
385
    // contents is modified.
386
    synchronized (contents)
387
      {
388
        Vector dirs = directories;
389
        if (dirs == null)
390
          {
391
            // Initializes this in getFiles().
392
            getFiles();
393
            dirs = directories;
394
          }
395
        return dirs;
396
      }
397
  }
398
 
399
  /**
400
   * Returns the (java.io.File) object at
401
   * an index in the list.
402
   *
403
   * @param index The list index
404
   * @return a File object
405
   */
406
  public Object getElementAt(int index)
407
  {
408
    if (index > getSize() - 1)
409
      return null;
410
    return contents.elementAt(index);
411
  }
412
 
413
  /**
414
   * Returns a Vector of (java.io.File) objects containing
415
   * the files in this list.
416
   *
417
   * @return a Vector
418
   */
419
  public Vector<File>  getFiles()
420
  {
421
    synchronized (contents)
422
      {
423
        Vector f = files;
424
        if (f == null)
425
          {
426
            f = new Vector();
427
            Vector d = new Vector(); // Directories;
428
            for (Iterator i = contents.iterator(); i.hasNext();)
429
              {
430
                File file = (File) i.next();
431
                if (filechooser.isTraversable(file))
432
                  d.add(file);
433
                else
434
                  f.add(file);
435
              }
436
            files = f;
437
            directories = d;
438
          }
439
        return f;
440
      }
441
  }
442
 
443
  /**
444
   * Returns the size of the list, which only includes directories
445
   * if the JFileChooser is set to DIRECTORIES_ONLY.
446
   *
447
   * Otherwise, both directories and files are included in the count.
448
   *
449
   * @return The size of the list.
450
   */
451
  public int getSize()
452
  {
453
    return contents.size();
454
  }
455
 
456
  /**
457
   * Returns the index of an (java.io.File) object in the list.
458
   *
459
   * @param o The object - normally a File.
460
   *
461
   * @return the index of that object, or -1 if it is not in the list.
462
   */
463
  public int indexOf(Object o)
464
  {
465
    return contents.indexOf(o);
466
  }
467
 
468
  /**
469
   * Obsoleted method which does nothing.
470
   */
471
  public void intervalAdded(ListDataEvent e)
472
  {
473
    // obsoleted
474
  }
475
 
476
  /**
477
   * Obsoleted method which does nothing.
478
   */
479
  public void intervalRemoved(ListDataEvent e)
480
  {
481
    // obsoleted
482
  }
483
 
484
  /**
485
   * Obsoleted method which does nothing.
486
   */
487
  public void invalidateFileCache()
488
  {
489
    // obsoleted
490
  }
491
 
492
  /**
493
   * Less than, determine the relative order in the list of two files
494
   * for sorting purposes.
495
   *
496
   * The order is: directories < files, and thereafter alphabetically,
497
   * using the default locale collation.
498
   *
499
   * @param a the first file
500
   * @param b the second file
501
   *
502
   * @return <code>true</code> if a > b, <code>false</code> if a < b.
503
   */
504
  protected boolean lt(File a, File b)
505
  {
506
    boolean aTrav = filechooser.isTraversable(a);
507
    boolean bTrav = filechooser.isTraversable(b);
508
 
509
    if (aTrav == bTrav)
510
      {
511
        String aname = a.getName().toLowerCase();
512
        String bname = b.getName().toLowerCase();
513
        return (aname.compareTo(bname) < 0) ? true : false;
514
      }
515
    else
516
      {
517
        if (aTrav)
518
          return true;
519
        else
520
          return false;
521
      }
522
  }
523
 
524
  /**
525
   * Listens for a property change; the change in file selection mode of the
526
   * associated JFileChooser. Reloads the file cache on that event.
527
   *
528
   * @param e - A PropertyChangeEvent.
529
   */
530
  public void propertyChange(PropertyChangeEvent e)
531
  {
532
    String property = e.getPropertyName();
533
    if (property.equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)
534
        || property.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)
535
        || property.equals(JFileChooser.FILE_HIDING_CHANGED_PROPERTY)
536
        || property.equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)
537
        || property.equals(JFileChooser.FILE_VIEW_CHANGED_PROPERTY)
538
        )
539
      {
540
        validateFileCache();
541
      }
542
  }
543
 
544
  /**
545
   * Renames a file - However, does <I>not</I> re-sort the list
546
   * or replace the old file with the new one in the list.
547
   *
548
   * @param oldFile The old file
549
   * @param newFile The new file name
550
   *
551
   * @return <code>true</code> if the rename succeeded
552
   */
553
  public boolean renameFile(File oldFile, File newFile)
554
  {
555
    return oldFile.renameTo( newFile );
556
  }
557
 
558
  /**
559
   * Sorts a Vector of File objects.
560
   *
561
   * @param v The Vector to sort.
562
   */
563
  protected void sort(Vector<? extends File> v)
564
  {
565
    Collections.sort(v, comparator);
566
  }
567
 
568
  /**
569
   * Re-loads the list of files
570
   */
571
  public void validateFileCache()
572
  {
573
    File dir = filechooser.getCurrentDirectory();
574
    if (dir != null)
575
      {
576
        // Cancel all pending requests.
577
        if (loadThread != null)
578
          {
579
            loadThread.interrupt();
580
            loadThread.cancelPending();
581
          }
582
        loadThread = new DirectoryLoadThread(dir);
583
        loadThread.start();
584
      }
585
  }
586
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.