KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > snow > sortabletable > SortableTableModel


1 package snow.sortabletable;
2
3
4 import javax.swing.table.*;
5 import javax.swing.event.*;
6 import javax.swing.border.*;
7 import javax.swing.*;
8 import java.awt.event.*;
9 import java.awt.*;
10 import java.util.*;
11 import java.util.regex.*;
12
13
14 /** this model wraps a basic model and allow sorting of his columns
15     the basic model remains unchanged. Only this model is sorted !
16     Features :
17       + The selection is maintained after table updates.
18       + Can installGUI() without corrupting model/view separation
19
20     usage:
21       1) make a FineGrain table model (like AbstractTableModel...)
22       2) make this class, pass 1)
23       3) make a table with this model 2)
24       4) call installGUI() with the table 3) to allow sorting
25
26 */

27 public class SortableTableModel extends AbstractTableModel
28 {
29   // these are the indices in the unsirted model corresponding to the position in this
30
// sorted model. element i is for position i in this table
31
// WITHOUT SEARCH HITS
32
final Vector<Integer JavaDoc> sortedRowIndices = new Vector<Integer JavaDoc>();
33
34   // i-th element is the index in the basic model of the ith found element
35
final Vector<Integer JavaDoc> foundBasicIndices = new Vector<Integer JavaDoc>();
36
37   // this is the unsorted model
38
private FineGrainTableModel basicTableModel;
39
40   public final static Icon SORT_ASC = new SortDirectionSelfDrawingIcon(SortDirectionSelfDrawingIcon.Ascending);
41   public final static Icon SORT_DESC = new SortDirectionSelfDrawingIcon(SortDirectionSelfDrawingIcon.Descending);
42
43
44
45   // used to remember selection when table change
46
JTable tableReference;
47   JTable tableRowHeadersReference;
48   int numberOfColumnAsRowHeaders = 0;
49
50
51   // contain the basic model column indices to show (selected = visible)
52
// 0, 1, 3, 4 for example if column2 is not visible
53
final private TreeSet<Integer JavaDoc> selectedColumns = new TreeSet<Integer JavaDoc>();
54
55   private boolean columnVisibilitiesChangeEnable = true;
56
57   /** wraps a sortable feature around your basic table model
58
59     Easy usage:
60       1) just create your model, pass it here
61       2) use this model as tablemodel for your jtable.
62       3) After that, call installGUI and pass your JTable as argument.
63   */

64   public SortableTableModel(FineGrainTableModel basicTableModel)
65   {
66      this(basicTableModel, 0, true);
67   }
68
69   public FineGrainTableModel getBasicTableModel()
70   {
71     return basicTableModel;
72   }
73
74   TableModelListener tableModelListener = null;
75   TableModelChangeListener tableModelChangeListener = null;
76
77
78   /** wraps a sortable feature around your basic table model
79
80     Easy usage:
81       1) just create your model, pass it here
82       2) use this model as tablemodel for your jtable.
83       3) After that, call installGUI and pass your JTable as argument.
84   */

85   public SortableTableModel(FineGrainTableModel basicTableModel,
86                             int sortedColumn, boolean ascending)
87   {
88      setBasicTableModel(basicTableModel, sortedColumn, ascending);
89   }
90
91
92   public void setBasicTableModel(FineGrainTableModel basicTableModel,
93                             int sortedColumn, boolean ascending)
94   {
95      removeOldListeners();
96
97      this.basicTableModel = basicTableModel;
98      this.sortedColumnInBasicModel = sortedColumn;
99      this.ascending = ascending;
100
101      basicTableModel.addTableModelListener(tableModelListener = new TableModelListener()
102      {
103         // called after the table has changed
104
public void tableChanged(TableModelEvent e)
105         {
106            //System.out.println("received tableChanged event from unsortedModel");
107
createRangeForSorting(); // range 0,...,n-1
108
internalSort();
109            internal_search();
110
111            // pass the event in same EDT for this listener
112
fireTableDataChanged();
113            //tableChanged(e); // index mismatch... should convert them... ###
114
}
115      });
116
117      basicTableModel.addModelChangeListener(tableModelChangeListener = new TableModelChangeListener()
118      {
119          public void tableModelWillChange(ChangeEvent e)
120          {
121            storeTableSelection();
122          }
123
124          public void tableModelHasChanged(ChangeEvent e)
125          {
126            restoreTableSelections();
127          }
128      });
129
130      // all columns are selected
131
for(int i=0; i<basicTableModel.getColumnCount(); i++)
132      {
133         selectedColumns.add(i);
134      }
135
136      // initial sort
137
createRangeForSorting();
138      sort(sortedColumn, ascending);
139      internal_search();
140
141
142      restoreTableSelections(); // ??? not now, but when table installed !!
143

144   } // Constructor
145

146
147   public void removeOldListeners()
148   {
149      if(basicTableModel!=null)
150      {
151        basicTableModel.removeTableModelListener(tableModelListener);
152        basicTableModel.removeModelChangeListener(tableModelChangeListener);
153      }
154
155      if(tableHeadClickMouseAdapter!=null)
156      {
157         tableRowHeadersReference.removeMouseListener(tableHeadClickMouseAdapter);
158      }
159      if(tableRefClickMouseAdapter!=null)
160      {
161         tableReference.removeMouseListener(tableRefClickMouseAdapter);
162      }
163   }
164
165
166   /** only call this when you terminate the table,
167       to keep selection stored in model (if implemented)
168   */

169   public synchronized void storeTableSelection()
170   {
171       //System.out.println("Store sel");
172
if(!SwingUtilities.isEventDispatchThread())
173       {
174          new Throwable JavaDoc("Must be called from EDT !").printStackTrace();
175       }
176
177       if(tableReference==null) return;
178
179       // store the selection (store indices of the basic model
180
int[] sel = tableReference.getSelectedRows();
181       basicTableModel.clearRowSelection();
182       for(int i=0; i<sel.length; i++)
183       {
184          int indexThis = sel[i];
185          int indexBase = getIndexInUnsortedFromTablePos(indexThis);
186          basicTableModel.setRowSelection(indexBase, true);
187       }
188   }
189
190   public synchronized void restoreTableSelections()
191   {
192      if(tableReference==null) return;
193      if(this.getRowCount()==0) return;
194
195      if(!SwingUtilities.isEventDispatchThread())
196      {
197        new Throwable JavaDoc("Must be called from EDT !").printStackTrace();
198      }
199
200      // restore selection
201
tableReference.getSelectionModel().clearSelection();
202      int[] sel = basicTableModel.getSelectedRows();
203      for(int i=0; i<sel.length; i++)
204      {
205         int indexBase = sel[i];
206         int pos = getIndexInFoundFromBasicIndex(indexBase);
207
208         if(pos>=0 && pos<tableReference.getRowCount())
209         {
210           if(tableReference.getSelectionModel().getSelectionMode()==ListSelectionModel.SINGLE_SELECTION)
211           {
212             tableReference.setRowSelectionInterval(pos, pos);
213           }
214           else
215           {
216             tableReference.addRowSelectionInterval(pos, pos);
217           }
218         }
219      }
220
221      // ### needed to display correctly !!!
222
if(tableReference!=null) tableReference.revalidate(); // .repaint();
223
if(tableRowHeadersReference!=null) tableRowHeadersReference.revalidate();
224   }
225
226
227   /** this just create a range 0.. size-1 used to sort
228   */

229   private synchronized void createRangeForSorting()
230   {
231      // nothing to do if the size is ok
232
if(sortedRowIndices.size()==basicTableModel.getRowCount()) return;
233
234      synchronized(this)
235      {
236        sortedRowIndices.removeAllElements();
237        for(int i=0; i<basicTableModel.getRowCount(); i++)
238        {
239           sortedRowIndices.addElement(i);
240        }
241      }
242   }
243
244
245   /** @return true if the search is active.
246   */

247   public synchronized boolean isSearchActive()
248   {
249      if(search1.length()>0) return true;
250      if(search2!=null) return true;
251      return false;
252   }
253
254   String JavaDoc search1 = "";
255   String JavaDoc search2 = null;
256   boolean useRegEx = false;
257   Pattern p1 = null;
258   Pattern p2 = null;
259   int searchColumn = -1; // -1 => all
260
boolean andSearch = true;
261
262   public synchronized void search(String JavaDoc str1, String JavaDoc str2, boolean useRegEx)
263   {
264     if(!SwingUtilities.isEventDispatchThread())
265     {
266       new Throwable JavaDoc("Must be called from EDT !").printStackTrace();
267     }
268
269     search1 = str1;
270     search2 = (str2!=null && str2.equals("") ? null : str2);
271     this.useRegEx = useRegEx;
272     p1=null;
273     p2=null;
274     searchColumn = -1;
275     andSearch = true;
276
277     if(useRegEx)
278     {
279       try
280       {
281         p1 = Pattern.compile(str1);
282       }
283       catch(Exception JavaDoc e){}
284
285       try
286       {
287         p2 = Pattern.compile(str1);
288       }
289       catch(Exception JavaDoc e){}
290     }
291
292     storeTableSelection();
293
294     internal_search();
295     fireTableDataChanged();
296
297     restoreTableSelections();
298   }
299
300   public synchronized void advancedSearch(String JavaDoc str1, String JavaDoc str2, boolean andSearch, boolean useRegEx, int column)
301   {
302     //System.out.println(""+column);
303
search1 = str1;
304     search2 = (str2!=null && str2.equals("") ? null : str2);
305
306     this.andSearch = andSearch;
307     this.searchColumn = column;
308     this.andSearch = andSearch;
309     this.useRegEx = useRegEx;
310
311     if(column==-1)
312     {
313       search(str1, str2, useRegEx);
314       return;
315     }
316
317     p1=null;
318     p2=null;
319
320     if(useRegEx)
321     {
322       try
323       {
324         p1 = Pattern.compile(str1);
325       }
326       catch(Exception JavaDoc e){}
327
328       try
329       {
330         p2 = Pattern.compile(str1);
331       }
332       catch(Exception JavaDoc e){}
333     }
334
335     storeTableSelection();
336
337     internal_search();
338     fireTableDataChanged();
339
340     restoreTableSelections();
341
342   }
343
344   /** search must be called after sort
345   // construct a list where the i-th element is the position in the
346   // unsorted element to be showed in the found table at i-th position
347   */

348   private synchronized void internal_search()
349   {
350     synchronized(this)
351     {
352       foundBasicIndices.removeAllElements();
353       for(int i=0; i<basicTableModel.getRowCount();i++)
354       {
355         int basicIndex = getIndexInUnsortedModel(i);
356
357         boolean hit = basicTableModel.hitForTextSearch(basicIndex, searchColumn, search1, p1);
358
359         if(!hit && andSearch) continue; // not found
360

361         if(search2!=null && !search2.equals(""))
362         {
363            boolean hit2 = basicTableModel.hitForTextSearch(basicIndex, searchColumn, search2, p2);
364            if(!hit2 && andSearch) continue; // not found
365

366            hit = hit || hit2;
367         }
368
369         if(hit)
370         {
371            foundBasicIndices.addElement(basicIndex);
372         }
373       }
374     }
375   }
376
377
378   /** SPECIAL CASE: Table with row index.
379       the two tables have the same selection model.
380   */

381   public void installGUI(JTable tHead, JTable table)
382   {
383     // synchronize the selections => simply use the same models !!
384
tHead.setSelectionModel( table.getSelectionModel() );
385
386     this.tableReference = table;
387     this.tableRowHeadersReference = tHead;
388
389     numberOfColumnAsRowHeaders = tHead.getColumnCount();
390
391     // we just install header renderers
392
setHeaders();
393     installHeaderClickListeners();
394
395   }
396
397
398   /** used to render headers...
399   */

400   public void installGUI(JTable _tableReference)
401   {
402     this.tableReference = _tableReference;
403     setHeaders(); // calls setHeadersForIndexTable()
404

405     installHeaderClickListeners();
406
407     // this is the first sel, from model, when the three methods
408
// are implemented
409
restoreTableSelections();
410
411     int fontSize = UIManager.getFont("Label.font").getSize();
412     for(int i=0; i<tableReference.getColumnCount(); i++)
413     {
414       int w = this.basicTableModel.getPreferredColumnWidth(i);
415       if(w>0)
416       {
417         tableReference.getColumnModel().getColumn(i).setPreferredWidth(w*fontSize);
418       }
419     }
420   }
421
422
423   public void setColumnVisibilityToggle(boolean enable)
424   {
425     columnVisibilitiesChangeEnable = enable;
426   }
427
428
429   /** actually only for tables without header
430     Must be caled after installGUI !
431   */

432   public void setPreferredColumnSizesFromModel()
433   {
434     if(tableReference==null) return;
435
436     int fontSize = UIManager.getFont("Label.font").getSize();
437     for(int i=0; i<tableReference.getColumnCount(); i++)
438     {
439       int pos = this.getColumnForViewIndex(i);
440       int w = this.basicTableModel.getPreferredColumnWidth(pos);
441       if(w>0)
442       {
443         tableReference.getColumnModel().getColumn(i).setPreferredWidth(w*fontSize);
444       }
445     }
446
447   }
448
449
450   MouseAdapter tableRefClickMouseAdapter = null;
451   MouseAdapter tableHeadClickMouseAdapter = null;
452
453
454   /** listen to click on the table headers used to toggle sorting
455   */

456   private void installHeaderClickListeners()
457   {
458     if(tableRefClickMouseAdapter!=null)
459     {
460        tableReference.removeMouseListener(tableRefClickMouseAdapter);
461     }
462
463     // listen to click on the table headers used to toggle sorting
464
tableReference.getTableHeader().addMouseListener(tableRefClickMouseAdapter = new MouseAdapter()
465     {
466
467       @Override JavaDoc public void mouseReleased(MouseEvent e)
468       {
469         if(e.isPopupTrigger() && columnVisibilitiesChangeEnable)
470         {
471           // on windows
472
showColumnSelectionPopup(e);
473           //e.consume();
474
}
475       }
476
477
478       public void mousePressed(MouseEvent e)
479       {
480         if(e.isPopupTrigger() && columnVisibilitiesChangeEnable)
481         {
482           // on linux
483
showColumnSelectionPopup(e);
484           //e.consume();
485
}
486       }
487
488       public void mouseClicked(MouseEvent e)
489       {
490         // [EDT]
491

492         int columnView = tableReference.getColumnModel().getColumnIndexAtX(e.getX());
493         int columnModel = tableReference.convertColumnIndexToModel(columnView);
494
495         if (columnModel >= 0)
496         {
497            //TableColumn tc = tableReference.getColumnModel().getColumn(columnModel);
498

499            // convert to model taking in account the columns that are not visible
500
int columnIndexInModel = getModelIndexForClickedColumn(columnModel);
501
502            // if this is the column already selected, invert the order
503
if (sortedColumnInBasicModel == columnIndexInModel + numberOfColumnAsRowHeaders)
504            {
505              ascending = !ascending;
506            }
507            else
508            {
509              ascending = true;
510            }
511            sortedColumnInBasicModel = columnIndexInModel + numberOfColumnAsRowHeaders;
512            //System.out.println("Sorted column in basic model = " + sortedColumnInBasicModel);
513

514            storeTableSelection();
515
516            internalSort();
517            internal_search();
518
519            fireTableDataChanged();
520
521            restoreTableSelections();
522
523            setHeaders(); // calls setHeadersForIndexTable()
524
// strange... when not invoked, is sometimes not repainted
525
if(tableReference!=null)
526            {
527               tableReference.getTableHeader().repaint(); // we're in the EDT... ok
528
}
529            if(tableRowHeadersReference!=null)
530            {
531               tableRowHeadersReference.getTableHeader().repaint(); // we're in the EDT... ok
532
}
533            //tableHeader.invalidate();
534
}
535       }
536     });
537
538
539     // index table
540
//
541
if(tableRowHeadersReference==null) return;
542
543     if(tableHeadClickMouseAdapter!=null)
544     {
545        tableRowHeadersReference.removeMouseListener(tableHeadClickMouseAdapter);
546     }
547
548
549     tableRowHeadersReference.getTableHeader().addMouseListener(tableHeadClickMouseAdapter = new MouseAdapter()
550     {
551       @Override JavaDoc public void mouseClicked(MouseEvent e)
552       {
553         //final int column = tableReference.columnAtPoint(new Point(e.getX(), e.getY()));
554
int columnView = tableRowHeadersReference.getColumnModel().getColumnIndexAtX(e.getX());
555         int columnModel = tableRowHeadersReference.convertColumnIndexToModel(columnView);
556
557         //System.out.println("Click column "+columnModel);
558

559         if (columnModel >= 0)
560         {
561            //TableColumn tc = tableRowHeadersReference.getColumnModel().getColumn(columnModel);
562
if (sortedColumnInBasicModel==columnModel)
563            {
564              ascending = !ascending;
565            }
566            else
567            {
568              ascending = true;
569            }
570            sortedColumnInBasicModel = columnModel;
571            //System.out.println("Sort column "+sortedColumn);
572

573            //setHeadersForMainTable();
574
//tableHeader.repaint();
575

576            storeTableSelection();
577
578            internalSort();
579            internal_search();
580
581            fireTableDataChanged();
582
583            restoreTableSelections();
584
585            setHeaders();
586            // strange... when not invoked, is sometimes not repainted
587
if(tableReference!=null) tableReference.getTableHeader().repaint(); // we're in the EDT... ok
588
if(tableRowHeadersReference!=null) tableRowHeadersReference.getTableHeader().repaint(); // we're in the EDT... ok
589
//tableHeader.invalidate();
590
}
591       }
592     });
593   }
594   /** @return {0,1,3} for example if column 2 is not visible
595   */

596   public int[] getVisibleColumnsIndex()
597   {
598     synchronized(this)
599     {
600       int[] rep = new int[selectedColumns.size()];
601       Integer JavaDoc[] sc = selectedColumns.toArray(new Integer JavaDoc[selectedColumns.size()]);
602       for(int i=0; i<selectedColumns.size(); i++)
603       {
604          rep[i] = sc[i];
605       }
606       return rep;
607     }
608   }
609
610   private int getModelIndexForClickedColumn(int col)
611   {
612     int[] visibleIndex = getVisibleColumnsIndex();
613     return getVisibleColumnsIndex()[col];
614   }
615
616   public void setVisibleColumns(int[] cols)
617   {
618     synchronized(this)
619     {
620       selectedColumns.clear();
621       for(int i=0; i<cols.length; i++)
622       {
623         if(cols[i]<this.basicTableModel.getColumnCount())
624         {
625           selectedColumns.add(cols[i]);
626         }
627       }
628     }
629     storeTableSelection();
630     fireTableStructureChanged(); // structure has changed, give a TableModelEvent with ROW_HEADERS row as argument
631
restoreTableSelections();
632     setHeaders();
633
634
635   }
636
637   public boolean isColumnVisible(int column)
638   {
639      return selectedColumns.contains(column);
640   }
641
642   /** @param column in the base model
643   */

644   public void setColumnVisible(int column, boolean visible)
645   {
646      if(visible)
647      {
648        selectedColumns.add(column);
649      }
650      else
651      {
652        // avoid zero columns !!!
653
if(selectedColumns.size()>1)
654        {
655          selectedColumns.remove(column);
656        }
657      }
658
659      storeTableSelection();
660      fireTableStructureChanged(); // structure has changed, give a TableModelEvent with ROW_HEADERS row as argument
661
restoreTableSelections();
662      setHeaders();
663   }
664
665   private void showColumnSelectionPopup(MouseEvent e)
666   {
667       JPopupMenu popup = new JPopupMenu("View Columns");
668       popup.add(new JLabel("View"));
669       popup.addSeparator();
670
671       // numberOfColumnAsRowHeaders first col are always visible
672
for(int i=numberOfColumnAsRowHeaders; i<this.basicTableModel.getColumnCount(); i++)
673       {
674          String JavaDoc name = basicTableModel.getColumnName(i);
675          final Integer JavaDoc index = new Integer JavaDoc(i);
676          final JCheckBoxMenuItem cb = new JCheckBoxMenuItem(name, selectedColumns.contains(index));
677          popup.add(cb);
678          cb.addActionListener(new ActionListener()
679          {
680            public void actionPerformed(ActionEvent ae)
681            {
682               setColumnVisible(index, cb.isSelected());
683            }
684          });
685       }
686
687
688       popup.show(tableReference.getTableHeader(), e.getX(), e.getY());
689   }
690
691
692   /** set the headers with sort icons.
693     [Called from EDT]
694   */

695   protected void setHeaders()
696   {
697     if(tableReference == null) return;
698
699     setHeadersForIndexTable();
700
701     //System.out.println("SC="+sortedColumn);
702

703     // for the index table
704
if (tableRowHeadersReference!=null)
705     {
706       for (int i=0; i<numberOfColumnAsRowHeaders; i++)
707       {
708         int indexModel = i;
709         int indexView = tableRowHeadersReference.convertColumnIndexToView(i);
710         TableColumn column = tableRowHeadersReference.getColumnModel().getColumn(indexView);
711         DefaultTableCellRenderer headerRenderer = new DefaultTableCellRenderer();
712         headerRenderer.setBackground(UIManager.getColor("TableHeader.background"));
713         if(indexModel==sortedColumnInBasicModel)
714         {
715           if (ascending) headerRenderer.setIcon(getAscIcon(indexModel));
716           else headerRenderer.setIcon(getDescIcon(indexModel));
717         }
718         else
719         {
720           headerRenderer.setIcon(getNoSortIcon(indexModel));
721         }
722
723         tableRowHeadersReference.getColumnModel().getColumn(indexView).setHeaderRenderer(headerRenderer);
724
725         // ??? needed, otherwise, does not correctly display.
726
tableRowHeadersReference.getTableHeader().repaint();
727       }
728     }
729
730     // table
731

732     for (int i=0; i<tableReference.getColumnCount(); i++)
733     {
734       int indexModel = i;
735       int indexView = tableReference.convertColumnIndexToView(i);
736       TableColumn column = tableReference.getColumnModel().getColumn(indexView);
737
738       DefaultTableCellRenderer headerRenderer = new DefaultTableCellRenderer();
739       headerRenderer.setBackground(UIManager.getColor("TableHeader.background"));
740
741       int sortedColViewIndex = getColumnForViewIndex(i);
742
743 /* System.out.println( "" + indexView + ",name= " + column.getIdentifier()
744                              + ", "+sortedColViewIndex+", sc="+ sortedColumnInBasicModel
745                              +" "+numberOfColumnAsRowHeaders);
746
747   */

748       if(sortedColViewIndex+numberOfColumnAsRowHeaders == sortedColumnInBasicModel)
749       {
750 /* System.out.println("sortedColumnInBasicModel = "
751             +sortedColumnInBasicModel+", view= "+sortedColViewIndex);
752 */

753          if (ascending)
754          {
755             headerRenderer.setIcon(getAscIcon(sortedColViewIndex));
756          }
757          else
758          {
759             headerRenderer.setIcon(getDescIcon(sortedColViewIndex));
760          }
761       }
762       else
763       {
764          headerRenderer.setIcon(getNoSortIcon(sortedColViewIndex));
765       }
766
767       tableReference.getColumnModel().getColumn(indexView).setHeaderRenderer(headerRenderer);
768       // ??? needed, otherwise, does not correctly display.
769
tableReference.getTableHeader().repaint();
770     }
771   }
772
773
774   private void setHeadersForIndexTable()
775   {
776     if(tableRowHeadersReference == null) return;
777
778     JTableHeader tableHeader = tableRowHeadersReference.getTableHeader();
779     for (int i=0; i<tableRowHeadersReference.getColumnCount(); i++)
780     {
781       int indexModel = i;
782       int indexView = tableRowHeadersReference.convertColumnIndexToView(i);
783
784       TableColumn column = tableRowHeadersReference.getColumnModel().getColumn(indexView);
785       DefaultTableCellRenderer headerRenderer = new DefaultTableCellRenderer();
786       headerRenderer.setBackground(UIManager.getColor("TableHeader.background"));
787
788       if(indexModel==sortedColumnInBasicModel)
789       {
790         if (ascending)
791         {
792             headerRenderer.setIcon(getAscIcon(indexModel));
793         }
794         else
795         {
796             headerRenderer.setIcon(getDescIcon(indexModel));
797         }
798       }
799       else
800       {
801         headerRenderer.setIcon(getNoSortIcon(indexModel));
802       }
803
804       tableRowHeadersReference.getColumnModel().getColumn(indexView).setHeaderRenderer(headerRenderer);
805       //tableReference.repaint();
806
}
807   }
808
809   // keep in mind what sorting is wanted, because each update must re-sort
810
int sortedColumnInBasicModel = 0;
811   boolean ascending = true;
812
813   public void sort(int column, boolean ascending)
814   {
815     synchronized(this)
816     {
817       this.sortedColumnInBasicModel = column;
818       this.ascending = ascending;
819       internalSort();
820
821       // pass the event in same EDT for this listener
822
fireTableDataChanged();
823     }
824   }
825
826   /** return true if the actual sorting order is ascending (default).
827   */

828   public boolean getSortOrderIsAscending() { return ascending;}
829
830   /** index in the basic tabel model
831   */

832   public int getSortedColumn() { return sortedColumnInBasicModel; }
833
834   public void setSortedColumnAndOrder(int col, boolean ascending)
835   {
836     this.sortedColumnInBasicModel = col;
837     this.ascending = ascending;
838   }
839
840   private void internalSort()
841   {
842     Comparator<Integer JavaDoc> comp = new Comparator<Integer JavaDoc>()
843     {
844       public int compare(Integer JavaDoc ind1, Integer JavaDoc ind2)
845       {
846         if(ascending)
847         {
848           return basicTableModel.compareForColumnSort(ind1, ind2, sortedColumnInBasicModel);
849         }
850         else
851         {
852           return basicTableModel.compareForColumnSort(ind2, ind1, sortedColumnInBasicModel);
853         }
854       }
855     };
856     //System.out.println("Sort start");
857
Collections.sort(sortedRowIndices, comp);
858     //System.out.println("Sort end");
859
}
860
861   //
862
// TableModel
863
//
864

865
866   /** @param pos id the index in this table,
867       @return the position of the element in the unsorted model
868   */

869   private int getIndexInUnsortedModel(int pos)
870   {
871      if(pos==-1) return -1;
872      if(pos>=sortedRowIndices.size()) return -1;
873
874      return sortedRowIndices.elementAt(pos);
875   }
876
877   /** positions in unsorted
878   */

879   public int getIndexInUnsortedFromTablePos(int tablePos)
880   {
881      if(tablePos==-1) return -1;
882      if(tablePos>=foundBasicIndices.size())
883      {
884 // System.out.println("tp="+tablePos+", fi="+foundBasicIndices.size());
885
return -1;
886      }
887
888      return foundBasicIndices.elementAt(tablePos);
889   }
890
891
892   /** get the view index corresponding to the one in the basicIndex
893   */

894   public int getIndexInFoundFromBasicIndex(int basicIndex)
895   {
896     if(basicIndex==-1) return -1;
897     if(basicIndex>=0 && basicIndex<basicTableModel.getRowCount())
898     {
899       int pos = foundBasicIndices.indexOf(basicIndex);
900       return pos;
901     }
902     else
903     {
904       return -1;
905     }
906   }
907
908    public Object JavaDoc getValueAt(int row, int col)
909    {
910        int pos = getIndexInUnsortedFromTablePos(row);
911        return basicTableModel.getValueAt(pos, getColumnForViewIndex(col));
912    }
913
914    public int getRowCount()
915    {
916       //System.out.println("grc="+foundBasicIndices.size());
917
return foundBasicIndices.size();
918       //# return unsortedTableModel.getRowCount();
919
}
920
921
922    public int getColumnCount()
923    {
924       return selectedColumns.size();
925       //[Old] return basicTableModel.getColumnCount();
926
}
927
928    /** if visible columns are {0,1,3}, view=2, return 3
929        BE CAREFUL: used in getColumName and getColumnClass !
930    */

931    public int getColumnForViewIndex(int viewCol)
932    {
933          synchronized(this)
934          {
935             int pos = -1;
936             // iterate over all visible columns
937
Iterator it = selectedColumns.iterator();
938             while(it.hasNext())
939             {
940                Integer JavaDoc ind = (Integer JavaDoc) it.next();
941                pos++;
942                if(pos==viewCol)
943                {
944                   return ind;
945                }
946             }
947             return -1;
948          }
949
950       /**
951        new code [Feb2004]
952        *
953
954       String colName = this.tableReference.getColumnName(viewCol);
955       for(int i=0; i<this.basicTableModel.getColumnCount(); i++)
956       {
957          if(basicTableModel.getColumnName(i).equals(colName)) return i;
958       }
959       return -1;
960         */

961    }
962
963
964
965
966
967    public boolean isCellEditable(int row, int col)
968    {
969        int pos = getIndexInUnsortedFromTablePos(row);
970        return basicTableModel.isCellEditable(pos, getColumnForViewIndex(col));
971    }
972
973    public void setValueAt(Object JavaDoc val, int row, int col)
974    {
975        int pos = getIndexInUnsortedFromTablePos(row);
976        basicTableModel.setValueAt(val, pos, getColumnForViewIndex(col));
977    }
978
979    public Class JavaDoc getColumnClass ( int column )
980    {
981       return basicTableModel.getColumnClass(getColumnForViewIndex(column));
982    }
983
984    public String JavaDoc getColumnName(int column)
985    {
986       return basicTableModel.getColumnName(getColumnForViewIndex(column));
987    }
988
989
990
991   /**
992    * returns the ascending/descending sort icons.
993    * this method may be overwritten by subclasses
994    * in order to provide their own icons
995    */

996   protected Icon getAscIcon( final int column ) { return(SORT_ASC); }
997   protected Icon getDescIcon( final int column ) { return(SORT_DESC); }
998   protected Icon getNoSortIcon( final int column ) { return(null); }
999
1000
1001
1002} // SortableAbstractTableModel
Popular Tags