KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > SnowMailClient > view > FolderView


1 package SnowMailClient.view;
2
3 import SnowMailClient.view.folders.*;
4 import SnowMailClient.view.actions.*;
5 import snow.sortabletable.*;
6 import snow.utils.storage.*;
7 import SnowMailClient.SnowMailClientApp;
8 import SnowMailClient.model.*;
9 import SnowMailClient.model.events.*;
10 import SnowMailClient.model.folders.*;
11 import snow.utils.gui.*;
12 import SnowMailClient.model.folders.*;
13 import SnowMailClient.Language.Language;
14
15 import java.awt.*;
16 import java.awt.dnd.*;
17 import java.awt.event.*;
18 import javax.swing.*;
19 import javax.swing.tree.*;
20 import javax.swing.event.*;
21 import java.beans.*;
22
23
24 /** view one folder (inbox, ...)
25   + search feature
26 */

27 public class FolderView extends SnowBackgroundPanel implements
28      ListSelectionListener,
29      MailFolderListener
30 {
31   private final JTable table = new JTable();
32   private final JLabel northLabel = new JLabel("");
33   MailFolder folder;
34   FolderTreeNode folderNode;
35
36   FoldersView foldersView;
37   MailView mailView;
38
39   SortableTableModel sortableTableModel;
40   AdvancedSearchPanel searchPanel;
41
42   AppProperties props;
43
44   public int fontSize = UIManager.getFont("Label.font").getSize();
45   final private DeleteMailAction deleteMailAction;
46
47   public FolderView(AppProperties props, final FoldersView foldersView, MailView mailView)
48   {
49     super(new BorderLayout(0,0));
50
51     this.props = props;
52     this.foldersView = foldersView;
53     this.mailView = mailView;
54
55     deleteMailAction = new DeleteMailAction(FolderView.this, SnowMailClientApp.getInstance().getFoldersModel().getDeletedFolder());
56     this.registerKeyboardAction( deleteMailAction,
57                                  KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0, true),
58                                  JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
59
60
61     JScrollPane jsp = new JScrollPane(table);
62
63
64     jsp.getViewport().setOpaque(false);
65     jsp.setOpaque(false);
66     table.setOpaque(false);
67     add(jsp, BorderLayout.CENTER);
68
69     // North
70
//
71
JPanel northPanel = new EFCNBackgroundPanel(new BorderLayout(),
72       EFCNBackgroundPanel.ApplyVerticalHighLight,
73       EFCNBackgroundPanel.MediumGradientStrength,
74       EFCNBackgroundPanel.PanelBackground
75     );
76
77     northPanel.add(northLabel, BorderLayout.WEST);
78     northLabel.setFont(new Font("Dialog", Font.BOLD, fontSize+2));
79
80     add(northPanel, BorderLayout.NORTH);
81     northPanel.setBorder(BorderFactory.createEmptyBorder(fontSize/2,fontSize,fontSize/2,fontSize/2));
82     northLabel.setOpaque(false);
83
84
85     searchPanel = new AdvancedSearchPanel(Language.translate("Search: "), null, sortableTableModel, false);
86     northPanel.add(searchPanel, BorderLayout.EAST);
87
88     searchPanel.addSearchChangeListener(new ChangeListener()
89     {
90       public void stateChanged(ChangeEvent ce)
91       {
92           updateTitleLabel();
93
94           // select the first if no selection
95
if(getTableSelectionCount()==0 && table.getRowCount()>0)
96           {
97             table.getSelectionModel().setSelectionInterval(0,0);
98           }
99       }
100     });
101
102     // listen to tree selections
103
foldersView.installFolderSelectionListener(this);
104
105
106     table.getSelectionModel().addListSelectionListener(this);
107
108     installDragAndPopup();
109
110     this.addPropertyChangeListener(
111      new PropertyChangeListener()
112      {
113         public void propertyChange(PropertyChangeEvent e)
114         {
115             String JavaDoc name = e.getPropertyName();
116             if (name.equals("ancestor"))
117              {
118                SwingUtilities.invokeLater( new Runnable JavaDoc()
119                 {
120                    public void run()
121                    {
122                      updateSpecialUI();
123                    }
124                 });
125              }
126         }
127      });
128
129
130   } // Constructor
131

132
133   private void updateSpecialUI()
134   {
135      fontSize = UIManager.getFont("Label.font").getSize();
136      northLabel.setFont(new Font("Dialog", Font.BOLD, fontSize+2));
137   }
138
139   /** and the mouse listener
140   */

141   private void installDragAndPopup()
142   {
143
144     MouseListener ml = new MouseAdapter()
145     {
146         @Override JavaDoc public void mousePressed(MouseEvent e)
147         {
148             if(e.isPopupTrigger())
149             {
150                displayPopup(e);
151             }
152         }
153
154         @Override JavaDoc public void mouseReleased(MouseEvent e)
155         {
156             // important: deactivate the drag info used by the folders tree !
157
isDragGestureStartedFromTable = false;
158             if(e.isPopupTrigger())
159             {
160                displayPopup(e);
161             }
162         }
163
164         public void displayPopup(MouseEvent e)
165         {
166            JPopupMenu menu = new JPopupMenu("Mail folder table popup");
167            if(getTableSelectionCount()>0)
168            {
169               menu.add(new AddToSpamAction(FolderView.this));
170               menu.add(new AddToHAMAction(FolderView.this));
171               menu.add(new RemoveSPAMCategory(FolderView.this));
172               menu.addSeparator();
173               menu.add(new CopyMessagesToClipboardAsText(FolderView.this));
174               menu.addSeparator();
175               menu.add(deleteMailAction);
176
177               if(SnowMailClientApp.debug)
178               {
179                 menu.addSeparator();
180                 JMenuItem parseDebug = new JMenuItem("Parse debug");
181                 menu.add(parseDebug);
182                 parseDebug.addActionListener(new ActionListener(){
183                   public void actionPerformed(ActionEvent ae)
184                   {
185                     MailMessage[] mess = getSelectedMessages();
186                     for(int i=0; i<mess.length; i++)
187                     {
188                       MailMessage mm = new MailMessage();
189                       mm.debug = true;
190                       mm.parse(mess[i].getCompleteContentAsString());
191                     }
192
193                   }
194                 });
195               }
196
197            }
198
199            menu.show(table, e.getX(), e.getY());
200
201         }
202     };
203
204     table.addMouseListener(ml);
205
206     table.setDragEnabled(true);
207
208     MailDnDTransferHandler mdth = new MailDnDTransferHandler("FolderView", this);
209     table.setTransferHandler(mdth);
210
211     // This detects the drags initiated from the table
212
//
213
DragGestureRecognizer dr = DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(
214       table,
215       DnDConstants.ACTION_COPY_OR_MOVE,
216       new DragGestureListener()
217       {
218          public void dragGestureRecognized(DragGestureEvent dge)
219          {
220             //System.out.println("Drag gesture started on table");
221
isDragGestureStartedFromTable = true;
222             // ### draw
223
}
224       });
225
226
227
228     // Global
229
/*DragSource.getDefaultDragSource().addDragSourceListener(new DragSourceListener()
230     {
231         public void dragDropEnd(DragSourceDropEvent dsde)
232         {
233           System.out.println("End");
234         }
235         public void dragEnter(DragSourceDragEvent dsde)
236         {
237           System.out.println("Enter "+dsde.getSource().getClass());
238         }
239         public void dragExit(DragSourceEvent dse)
240         {
241           //System.out.println("Exit");
242         }
243         public void dragOver(DragSourceDragEvent dsde)
244         {
245           //System.out.println("Over");
246         }
247         public void dropActionChanged(DragSourceDragEvent dsde)
248         {
249           //System.out.println("ActionChanged "+dsde);
250         }
251     }); */

252
253   }
254
255   public boolean isDragGestureStartedFromTable = false;
256
257
258   /** used to to enable/disable actions
259   */

260   public synchronized ListSelectionModel getTableSelectionModel()
261   {
262     return table.getSelectionModel();
263   }
264   public synchronized int getTableSelectionCount() { return table.getSelectedRowCount(); }
265   public synchronized int getTableRowCount() { return table.getRowCount(); }
266
267
268   /** Set the displayed mail folder
269   */

270   public synchronized void setMailFolder(FolderTreeNode newFolderNode, MailFolder newFolder)
271   {
272     if(!SwingUtilities.isEventDispatchThread()) new Throwable JavaDoc("must be EDT").printStackTrace();
273
274     if(newFolder!=null)
275     {
276       //System.out.println("FolderView: set mail folder "+newFolder.getFolderName());
277
}
278     else
279     {
280       //System.out.println("FolderView: set mail folder null.");
281
}
282
283     // deinstall old listeners on the old folder
284
if(this.folder!=null)
285     {
286        folder.removeMailFolderListener(this);
287        if(sortableTableModel!=null)
288        {
289          // store the sorted column in the model
290
folder.saveSortedColumnFromView(
291                   sortableTableModel.getSortedColumn(),
292                   sortableTableModel.getSortOrderIsAscending());
293        }
294     }
295
296     boolean isNewFolder = ( this.folder != newFolder );
297
298     // install the new folder
299
this.folder = newFolder;
300     this.folderNode = newFolderNode;
301
302     if(folder!=null)
303     {
304       folder.addMailFolderListener(this);
305
306
307       if(this.sortableTableModel!=null)
308       {
309          // subsequent folder changes only the basic model.
310
sortableTableModel.setBasicTableModel(folder,
311                 folder.getSortedColumn(),
312                 folder.getIsSortingAscendingOrder()
313          );
314       }
315       else
316       {
317          // only created once, for the first folder
318
sortableTableModel = new SortableTableModel(folder,
319                 folder.getSortedColumn(), folder.getIsSortingAscendingOrder());
320          table.setModel(sortableTableModel);
321          sortableTableModel.installGUI(table);
322          searchPanel.setSortableTableModel(sortableTableModel);
323
324          table.setDefaultRenderer(Object JavaDoc.class, new FolderViewTableCellRenderer(this, sortableTableModel));
325          table.getColumnModel().getColumn(3).setMaxWidth(fontSize*12);
326          table.getColumnModel().getColumn(3).setMinWidth(fontSize*12);
327          table.getColumnModel().getColumn(4).setMaxWidth(fontSize*7); // size
328
table.getColumnModel().getColumn(5).setMaxWidth(fontSize*2); // Spam
329
}
330
331
332       setVisible(true);
333     }
334     else
335     {
336       setVisible(false);
337     }
338
339     // select the first if no selection
340
if(getTableSelectionCount()==0 || isNewFolder )
341     {
342       if(table.getRowCount()>0)
343       {
344         //System.out.println("Select the first message");
345
// select the first message
346
table.getSelectionModel().setSelectionInterval(0,0);
347       }
348     }
349
350     updateTitleLabel();
351   }
352
353
354   public synchronized MailFolder getMailFolder()
355   {
356     return folder;
357   }
358
359
360   public synchronized FolderTreeNode getFolderNode()
361   {
362     return folderNode;
363   }
364
365
366   /** contain the number of mails, of new mails and of filtered mails.
367   */

368   private synchronized void updateTitleLabel()
369   {
370     if(folder!=null)
371     {
372        String JavaDoc name = folder.getFolderName();
373        int numberOfMails = folder.getRowCount();
374        int nn = folder.getNumberOfNewMails();
375        name += " ["+numberOfMails+" "+Language.translate("mail")+(numberOfMails==1?"":"s");
376        if(nn>0)
377        {
378          name += ", "+Language.translate("% new", ""+nn);
379        }
380
381        int found = this.sortableTableModel.getRowCount();
382        if(sortableTableModel.isSearchActive())
383        {
384          name += ", "+found+" "+Language.translate("matching search");
385        }
386
387        name+="]";
388
389        if(folder.hasContentChanged()) name += " (*)";
390        northLabel.setText(name);
391     }
392     else
393     {
394        northLabel.setText(Language.translate("No folder selected"));
395     }
396   }
397
398   private MailMessage selectedMessage = null;
399
400
401   //
402
// MailFolderListener
403
//
404

405   public void folderSizeChanged()
406   {
407     //System.out.println("Folder size changed");
408
updateTitleLabel();
409   }
410
411   public void folderStored()
412   {
413     //System.out.println("Folder stored");
414
updateTitleLabel();
415   }
416
417   /** the folder was closed from outside !
418       maybe to free memory.
419   */

420   public void folderClosed()
421   {
422     // We must close the view too !!
423
// deinstall old listeners on the old folder
424
/* if(this.folder!=null)
425     {
426        folder.removeMailFolderListener(this); // CONCURENT MODIFICATION !!! => BAD BAD BAD
427        if(sortableTableModel!=null)
428        {
429          // store the sorted column in the model
430          folder.saveSortedColumnFromView(
431                   sortableTableModel.getSortedColumn(),
432                   sortableTableModel.getSortOrderIsAscending());
433        }
434        folder = null;
435        this.folderNode = null;
436
437        //setVisible(false);
438     }*/

439   }
440
441   /** called when one of the messages i nthis folder has been edited
442   */

443   public void folderContentEdited(MailMessageChangeListener.MailMessageChangeType change)
444   {
445     if(change == MailMessageChangeListener.MailMessageChangeType.IN_EDITION)
446     {
447       // DO nothing
448
System.out.println("FolderView: in edition");
449     }
450     else
451     {
452        // update the table data (from, to , subject, date !)
453
//table.invalidate();
454
table.repaint();
455     }
456     updateTitleLabel();
457   }
458
459
460   /** called from the search results selection
461       should be called in the EDT
462   */

463   public synchronized void setMessageToView(MailMessage mess)
464   {
465     new Throwable JavaDoc().printStackTrace();
466
467     // ok, already selected
468
if(this.selectedMessage==mess) return;
469     if(this.folder==null) return; // nothing to search
470

471     for(MailMessage mi: folder.getAllMessages())
472     {
473        //MailMessage mi = folder.getMessageAt(i);
474
if(mi==mess)
475        {
476          mi.selectedInView = true;
477        }
478        else
479        {
480          mi.selectedInView = false;
481        }
482     }
483     folder.fireTableRowsUpdated(0, folder.getRowCount()-1);
484   }
485
486
487   /** selection listener, multiple selection is allowed,
488       this looks if the message is already selected, it doesn't change
489   */

490   public synchronized void valueChanged(ListSelectionEvent eBof)
491   {
492     // ?
493
//if(this.isDragGestureStartedFromTable) return;
494

495
496     int[] tableSelection = table.getSelectedRows();
497     // 1: look if the selected message is in the list
498
for(int i=0; i<tableSelection.length; i++)
499     {
500       int modelPos = this.sortableTableModel.getIndexInUnsortedFromTablePos(tableSelection[i]);
501       MailMessage message = folder.getMessageAt(modelPos);
502       if(message==selectedMessage && message!=null)
503       {
504         return; // do nothing, it is already selected !!
505
}
506     }
507
508     // it is not in the list => show the first
509
if(tableSelection.length>0)
510     {
511       int modelPos = this.sortableTableModel.getIndexInUnsortedFromTablePos(tableSelection[0]);
512       MailMessage message = folder.getMessageAt(modelPos);
513       mailView.setMessage( message );
514       selectedMessage = message;
515     }
516     else
517     {
518       // or nothing if no selection
519
mailView.setMessage(null);
520       selectedMessage = null;
521     }
522   }
523
524   /** return the selected messages
525   */

526   public synchronized MailMessage[] getSelectedMessages()
527   {
528     int[] rowTable = table.getSelectedRows();
529     MailMessage[] selMess = new MailMessage[rowTable.length];
530     for(int i=0; i<selMess.length; i++)
531     {
532       int modelPos = this.sortableTableModel.getIndexInUnsortedFromTablePos(rowTable[i]);
533       selMess[i] = folder.getMessageAt(modelPos);
534     }
535     return selMess;
536   }
537
538   /** called from the remove selected mail action
539     ### problem, when the table event come (because remove),
540       the table is re-sorted and the sel-1 is sometimes bad positioned
541   */

542   public void removeMail(MailMessage mess) throws Exception JavaDoc
543   {
544     int sel = table.getSelectedRow();
545
546     this.getMailFolder().removeMessage(mess);
547
548     // select next mail
549
if( table.getRowCount()==0)
550     {
551       return; // no chance !
552
}
553
554     if(sel>=0 && sel<table.getRowCount())
555     {
556       table.setRowSelectionInterval(sel,sel);
557     }
558     else if(sel-1>=0 && sel-1<table.getRowCount())
559     {
560       table.setRowSelectionInterval(sel-1,sel-1);
561     }
562   }
563
564 } // FolderView
Popular Tags