View Javadoc
1   /*
2    * BrowserTableModel.java
3    *
4    * Created on den 29 januari 2003, 10:25
5    */
6   
7   package net.sourceforge.jsh3modtool.gui.imagetable;
8   
9   import net.sourceforge.jsh3modtool.gui.imagetable.cache.ImageLoadingListener;
10  import net.sourceforge.jsh3modtool.gui.imagetable.cellfilters.*;
11  import net.sourceforge.jsh3modtool.gui.imagetable.cellsorters.FilenameCellSorter;
12  import net.sourceforge.jsh3modtool.gui.imagetable.cellsorters.FoldersFirstCellSorter;
13  import net.sourceforge.jsh3modtool.gui.imagetable.utils.JTableUtil;
14  
15  import java.util.*;
16  import javax.swing.table.*;
17  
18  /***
19   * A model for a JTable oontaining images
20   *
21   * @author  erma
22   */
23  public class ImageTableModel extends AbstractTableModel implements ImageLoadingListener
24  {
25      private List allItems = new ArrayList();
26      private int allItemsCount;
27  
28      private List filteredItems = new ArrayList();
29      private int  filteredItemsCount;
30  
31      private List filters = new ArrayList();
32      private Comparator filteredItemsComparator = new FilenameCellSorter();
33      private boolean useFoldersFirstWhenSorting;
34  
35      private int columnCount;
36      private int rowCount;
37  
38      /***
39       * Creates a new instance of BrowseTableModel
40       * @param cols number of columns
41       */
42      public ImageTableModel(int cols)
43      {
44          allItemsCount = 0;
45          filteredItemsCount = 0;
46          columnCount = cols;
47          recalculateRowCount();
48          
49          //updateFoldersFirstComparator();
50      }
51  
52      /*** Returns the number of columns in the model. A
53       * <code>JTable</code> uses this method to determine how many columns it
54       * should create and display by default.
55       *
56       * @return the number of columns in the model
57       * @see #getRowCount
58       */
59      public int getColumnCount()
60      {
61          return columnCount;
62      }
63  
64      /*** Returns the number of rows in the model. A
65       * <code>JTable</code> uses this method to determine how many rows it
66       * should display.  This method should be quick, as it
67       * is called frequently during rendering.
68       *
69       * @return the number of rows in the model
70       * @see #getColumnCount
71       */
72      public int getRowCount()
73      {
74          return rowCount;
75      }
76  
77      /*** Returns the value for the cell at <code>columnIndex</code> and
78       * <code>rowIndex</code>.
79       * @param row the row whose value is to be queried
80       * @param col the column whose value is to be queried
81       * @return the value Object at the specified cell
82       */
83      public Object getValueAt(int row, int col)
84      {
85          Object value = null;
86          if ( filteredItems != null )
87          {
88              int listIndex = getImageIndex( row, col );
89              if ( listIndex < filteredItemsCount )
90              {
91                  value = filteredItems.get( listIndex );
92              }
93          }
94  
95          return value;
96      }
97  
98      /*** Returns the value for the cell at <code>columnIndex</code> and
99       * <code>rowIndex</code>.
100      * @param cell the cell
101      * @return the value Object at the specified cell
102      */
103     public Object getValueAt(JTableUtil.Cell cell)
104     {
105         return getValueAt( cell.row, cell.column );
106     }
107 
108     /***
109      * Changes the number of columns
110      * @param cols the desired number of columns
111      */
112     public void setColumnCount( int cols )
113     {
114         if ( columnCount != cols )
115         {
116             columnCount = cols;
117             recalculateRowCount();
118             fireTableStructureChanged();
119         }
120     }
121 
122     /***
123      * Returns a List containing all images that passes the filter.
124      * @param filter the Cell filter to filter out images with.
125      * @return a List, can be empty
126      */
127     List getImageCells( CellFilter filter )
128     {
129         List selectedImages = new Vector();
130         ListIterator iterator = filteredItems.listIterator();
131         while ( iterator.hasNext() )
132         {
133             Object cell = iterator.next();
134             if ( cell.getClass().equals( ImageCell.class ) )
135             {
136                 ImageCell image = (ImageCell) cell;
137                 if ( filter.accept(image) )
138                 {
139                     selectedImages.add( image );
140                 }
141             }
142         }
143         return selectedImages;
144     }
145 
146     /***
147      * Returns a List containing all image cells.
148      * @return a List, can be empty.
149      */
150     List getAllImageCells()
151     {
152         List selectedImages = new Vector();
153         ListIterator iterator = filteredItems.listIterator();
154         while ( iterator.hasNext() )
155         {
156             Object cell = iterator.next();
157             if ( cell.getClass().equals( ImageCell.class ) )
158             {
159                 selectedImages.add( cell );
160             }
161         }
162         return selectedImages;
163     }
164 
165     /***
166      * Returns a List containing all images that passes the filter.
167      * @param filter the Cell filter to filter out images with.
168      * @return a List, can be empty
169      */
170    /* public List getImageProperties( CellFilter filter )
171     {
172         List selectedImages = new Vector();
173         ListIterator iterator = filteredItems.listIterator();
174         while ( iterator.hasNext() )
175         {
176             Object cell = iterator.next();
177             if ( cell.getClass().equals( ImageCell.class ) )
178             {
179                 ImageCell image = (ImageCell) cell;
180                 if ( filter.accept(image) )
181                 {
182                     selectedImages.add( image.getImageProperties() );
183                 }
184             }
185         }
186         return selectedImages;
187     }*/
188 
189     /***
190      * Return a List containing all selected image cells.
191      * @return a List
192      */
193    /*public List getSelectedImageProperties()
194     {
195         return getImageProperties( new SelectedImagesFilter(true) );
196     }*/
197 
198     /***
199      * Returns if the specified Cell should be included in the filtered list
200      * or not
201      * @param cell the cell to test
202      * @return true if and only if the cell is accepted by all filters
203      */
204     private boolean acceptedByFilters( BaseCell cell )
205     {
206         boolean passedFilters = true;
207         ListIterator iterator = filters.listIterator();
208         while ( (passedFilters) && ( iterator.hasNext() ) )
209         {
210             CellFilter filter = (CellFilter) iterator.next();
211             if ( ! filter.accept( cell ) )
212             {
213                 passedFilters = false;
214             }
215         }
216         return passedFilters;
217     }
218 
219 
220     /***
221 	 * @param nrOfImagesBefore
222 	 * @param startRow
223 	 */
224 	private void revalidateData(int nrOfImagesBefore, int startRow) {
225 		recalculateRowCount();        
226         sortFilteredItems();       
227         int endRow = rowCount;
228 
229         if ( nrOfImagesBefore == 0 )
230         {
231             fireTableDataChanged();
232         } 
233         else
234         {
235             if ( startRow == endRow )
236             {
237                 fireTableRowsUpdated( endRow - 1, endRow );
238             } 
239             else
240             {
241                 fireTableRowsInserted( startRow - 1, endRow );
242             }
243         }
244 	}
245 	
246     public void addImageModel(ImageModel imageModel)
247     {
248         int nrOfImagesBefore = allItemsCount;
249         int startRow = rowCount;
250         
251         BaseCell cell = new ImageCell(imageModel);
252         allItems.add( cell );
253         allItemsCount++;
254 
255         if ( acceptedByFilters( cell ) )
256         {
257             filteredItemsCount++;
258             filteredItems.add( cell );
259         }
260         revalidateData(nrOfImagesBefore, startRow);
261     	
262     }
263 
264     /*** Adds the specified images to the model
265      * @param filesList a list of Files
266      */
267     public void addImageModels( List filesList )
268     {
269         int nrOfImagesBefore = allItemsCount;
270         int startRow = rowCount;
271         ListIterator iterator = filesList.listIterator();
272 
273         while ( iterator.hasNext() )
274         {
275             BaseCell cell = new ImageCell((ImageModel) iterator.next());
276             if ( cell != null )
277             {
278                 allItems.add( cell );
279                 allItemsCount++;
280 
281                 if ( acceptedByFilters( cell ) )
282                 {
283                     filteredItemsCount++;
284                     filteredItems.add( cell );
285                 }
286             }
287         }
288         revalidateData(nrOfImagesBefore, startRow);
289     }
290 
291     /*** Removes the Files in the specified list from the table
292      * @param filesList a List of Files
293      */
294     /*public void removeFiles( List filesList )
295     {
296         int startRow = rowCount;
297         ListIterator iterator = filesList.listIterator();
298         while ( iterator.hasNext() )
299         {
300             BaseCell cell = findFile( (File) iterator.next() );
301             if ( cell != null )
302             {
303                 allItems.remove( cell );
304                 allItemsCount--;
305                 if ( filteredItems.remove( cell ) )
306                 {
307                     filteredItemsCount--;
308                 }
309             }
310         }
311         recalculateRowCount();
312         sortFilteredItems();
313         int endRow = rowCount;
314         fireTableRowsDeleted( startRow, endRow );
315     }*/
316     
317     /***
318      * Returns the cell that is the representation of the specified file
319      * @param file the file to find a cell for
320      * @return the cell; null if the cell wasnt found
321      */
322    /* private BaseCell findFile( File file )
323     {
324         BaseCell foundCell = null;
325         ListIterator iterator = allItems.listIterator();
326         while ( ( iterator.hasNext() ) && ( foundCell == null ) )
327         {
328             BaseCell cell = (BaseCell) iterator.next();
329             
330             if ( cell instanceof ImageCell )
331             {
332                 if ( ((ImageCell) cell).getImageProperties().getFilename().equals( file.getAbsolutePath() ) )
333                 {
334                     foundCell = cell;
335                 }
336             }
337         }
338         return foundCell;
339     }*/
340 
341 
342 	/*** Returns if the model contains the specified cell
343      * @param cell the cell to find in the model
344      * @return true if the cell is in the model; false otherwise
345      */
346     public boolean contains( BaseCell cell )
347     {
348         boolean retValue = false;
349         if ( cell != null )
350         {
351             retValue = allItems.contains( cell );
352         }
353         return retValue;
354     }
355 
356     /***
357      * Generates an Cell for the table
358      * @param file the file
359      * @return an AbstractCell
360      */
361    /* private BaseCell generateCell( File file )
362     {
363         BaseCell cell;
364         if ( file.isDirectory() )
365         {
366             cell = new FolderCell( file );
367         }
368         else
369         {
370             ImageModel imageProps = new ImageProperties( file );
371             cell = new ImageCell( imageProps );
372 
373         }
374         return cell;
375     }*/
376 
377     /*** Removes all items from the model */
378     public void clear()
379     {
380         allItems.clear();
381         filteredItems.clear();
382         allItemsCount = 0;
383         filteredItemsCount = 0;
384         recalculateRowCount();
385         fireTableDataChanged();
386     }
387 
388     /***
389      * Recalculates the number of rows.
390      */
391     private void recalculateRowCount()
392     {
393         rowCount = (int) Math.floor( (double) filteredItemsCount / (double) columnCount );
394         rowCount += ( (filteredItemsCount % columnCount) == 0 ? 0 : 1 );
395     }
396 
397     /***
398      * Invoked when an image has been loaded, specified by the index in the list
399      * This method fires a cell update event.
400      * @param cell the cell that was updated.
401      */
402     public void imageIsLoaded(BaseCell cell)
403     {
404         int cellIndex = filteredItems.indexOf( cell );
405         if ( cellIndex != -1 )
406         {
407             int row = (int) Math.floor( (double) cellIndex / (double) columnCount );
408             int col = cellIndex - ( row * columnCount );
409 
410             fireTableCellUpdated( row, col );
411         }
412         if ( cell.getClass().equals(ImageCell.class))
413         {
414             ((ImageCell)cell).resetTooltip();
415         }
416     }
417 
418     /*** Returns the number of images in the model
419      * @return number of items in table
420      */
421     public int getSize()
422     {
423         return filteredItemsCount;
424     }
425 
426     /***
427      * Returns the image index (in the list) from the cells row and column.
428      * @param row the row.
429      * @param col the col.
430      * @return the image index (in the list). 
431      */
432     int getImageIndex( int row, int col )
433     {
434         return row * columnCount + col;
435     }
436     
437     /***
438      * Returns the image index (in the list) for the specified cell.
439      * @param cell the cell to find the index for.
440      * @return the image index (in the list). 
441      */
442     int getImageIndex( BaseCell cell )
443     {
444         int index = -1;
445         JTableUtil.Cell tableCell = getTableCell(cell);
446         if ( tableCell != null )
447         {
448             index = getImageIndex(tableCell.row, tableCell.column);
449         }
450         return index;
451     }
452     
453     /***
454      * Returns the AbstractCell at the specified index (in the list).
455      * @param index the index to find the cell for.
456      * @return an AbstractCell.
457      */
458     BaseCell getCell( int index )
459     {
460         return (BaseCell) filteredItems.get(index);
461     }
462 
463 
464     /*** 
465      * Returns whetever this cell is editable or not, this
466      * implementation returns false always.
467      * @param rowIndex the row
468      * @param columnIndex the column
469      * @return false.
470      */
471     public boolean isCellEditable(int rowIndex, int columnIndex)
472     {
473         return false;
474     }
475 
476     /*** 
477      * Fires a cell update. The method checks if the cell is acceptable by the filters, if
478      * not it is removed from the filteredList.
479      * @param cell the cell to update.
480      */
481     public void fireTableCellUpdate( BaseCell cell )
482     {
483         JTableUtil.Cell tableCell = getTableCell( cell );
484 
485         if ( tableCell != null )
486         {    
487             if ( ! acceptedByFilters( cell ))
488             {
489                 filteredItems.remove(cell);
490                 filteredItemsCount = filteredItems.size();
491                 fireTableRowsDeleted(tableCell.row, tableCell.row );                   
492             }
493             else
494             {        
495                 fireTableCellUpdated( tableCell.row, tableCell.column );
496             }
497         }
498     }
499 
500     /*** Returns a JTableUtil.Cell from the specified list index
501      * @param cell the cell to find in the table
502      * @return a Cell containing the row and column of the cell
503      */
504     public JTableUtil.Cell getTableCell( BaseCell cell )
505     {
506         JTableUtil.Cell tableCell = null;
507 
508         int cellIndex = filteredItems.indexOf( cell );
509         if ( cellIndex != -1 )
510         {
511             tableCell = getTableCell( cellIndex );
512         }
513         return tableCell;
514     }
515     
516     /*** 
517      * Returns a JTableUtil.Cell that matches the specified file
518      * @param file the file to find in the filteres image cells
519      * @return a Cell containing the row and column of the cell
520      */
521    /* public JTableUtil.Cell getTableCell( File file )
522     {
523         JTableUtil.Cell tableCell = null;
524         
525         int cellIndex = 0;
526         ListIterator iterator = filteredItems.listIterator();
527         while ( iterator.hasNext() && ( tableCell == null ) )
528         {
529             Object obj = iterator.next();
530             if ( ( obj instanceof ImageCell ) && 
531                  ( ((ImageCell)obj).getImageProperties().getFilename().equals( file.getAbsolutePath() ) ) 
532                )
533             {  
534                 tableCell = getTableCell( cellIndex );
535             }
536             cellIndex++;
537         }
538         return tableCell;
539     }*/
540     
541 
542     /***
543      * Adds the filter to the filters list, the filter is used until it is
544      * removed from this list.
545      * @param filter the filter to add
546      */
547     public void addFilter( CellFilter filter )
548     {
549         filters.add( filter );
550         updateFilteredList();
551     }
552 
553     /***
554      * Removes the filter from the filters list
555      * @param filter the filter to remove
556      */
557     public void removeFilter( CellFilter filter )
558     {
559         filters.remove( filter );
560         updateFilteredList();
561     }
562 
563     /***
564      * Removes all filters from the list
565      */
566     public void removeAllFilters()
567     {
568         filters.clear();
569         updateFilteredList();
570     }
571 
572     /***
573      * Reinits the filtere items list, it copies values from the main item list
574      * to the filtered items list if it passes all filters.
575      */
576     private void updateFilteredList()
577     {
578         filteredItemsCount = 0;
579         filteredItems.clear();
580 
581         ListIterator itemIterator = allItems.listIterator();
582         while ( itemIterator.hasNext() )
583         {
584             BaseCell cell = (BaseCell) itemIterator.next();
585             if ( acceptedByFilters( cell ) )
586             {
587                 filteredItems.add( cell );
588             }
589         }
590         filteredItemsCount = filteredItems.size();
591         sortFilteredItems();
592         recalculateRowCount();
593         fireTableDataChanged();
594     }
595     
596     /***
597      * Returns a cell for the specified list index
598      * @param cellIndex the cell index.
599      * @return the cell.
600      */
601     JTableUtil.Cell getTableCell( int cellIndex )
602     {
603         int row = (int) Math.floor( (double) cellIndex / (double) columnCount );
604         int col = cellIndex - ( row * columnCount );
605 
606         return new JTableUtil.Cell( row, col );
607     }
608     
609     /***
610      * Sorts the filtereditems list. Note that it only sorts the list that is displayed
611      * and not the underlying.
612      */
613     private void sortFilteredItems()
614     {
615         Comparator c = filteredItemsComparator;
616         if (c != null)
617         {
618 	        if ( useFoldersFirstWhenSorting )
619 	        {
620 	            c = new FoldersFirstCellSorter(c);
621 	        }
622 	        Collections.sort(filteredItems, c);
623         }
624     }
625     
626     /***
627      * Sets the new cell comparator.
628      * The comparator will be activated with Cells that extends
629      * the AbstractCell class. All comparators sent to this method must
630      * be able to sort the different cells.
631      * @param comparator
632      * @see AbstractCellSorter
633      */
634     public void setCellComparator( Comparator comparator )
635     {
636         filteredItemsComparator = comparator;
637     }
638 }