KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > SnowMailClient > view > MailView


1 package SnowMailClient.view;
2
3 import java.awt.Insets JavaDoc;
4 import snow.utils.StringUtils;
5 import snow.texteditor.*;
6 import java.awt.EventQueue JavaDoc;
7 import java.awt.FlowLayout JavaDoc;
8 import java.awt.Color JavaDoc;
9 import SnowMailClient.SnowMailClientApp;
10 import SnowMailClient.Language.Language;
11 import SnowMailClient.SpamFilter.*;
12 import SnowMailClient.model.*;
13 import SnowMailClient.model.multipart.*;
14 import SnowMailClient.model.accounts.*;
15 import SnowMailClient.model.events.*;
16 import snow.utils.gui.*;
17 import snow.sortabletable.*;
18 import snow.lookandfeel.*;
19 import SnowMailClient.html.*;
20 import SnowMailClient.view.html.*;
21 import SnowMailClient.view.traceView.*;
22 import SnowMailClient.view.attachments.*;
23 import SnowMailClient.gnupg.GnuPGLink;
24 import SnowMailClient.gnupg.model.*;
25 import SnowMailClient.gnupg.Main.GnuPGCommands;
26 import SnowMailClient.keyboard.*;
27 import java.awt.BorderLayout JavaDoc;
28 import java.awt.event.*;
29 import java.text.*;
30 import javax.swing.*;
31 import javax.swing.undo.*;
32 import javax.swing.event.*;
33 import javax.swing.text.*;
34 import javax.swing.border.*;
35 import javax.swing.plaf.basic.BasicComboBoxEditor JavaDoc;
36 import java.util.*;
37 import java.io.ByteArrayInputStream JavaDoc;
38 import java.beans.*;
39
40 /** Displays or Edits a Single Mail Message.
41 */

42 public final class MailView extends SnowBackgroundPanel
43                       implements UndoableEditListener, MailMessageChangeListener
44 {
45   // parameters
46
private final static int TimeToMarkAsRead = 1000*5;
47
48   // a single instance is made and kept for the whole time
49
private final ViewTextDialog fullMailContentView;
50   private final HTMLSecureViewer hTMLViewer;
51
52   private int fontSize = UIManager.getFont("Label.font").getSize();
53
54   private MailMessage message;
55   private final SimpleDocument doc = new SimpleDocument();
56   private final JTextPane textPane = new JTextPane(doc);
57   protected final snow.texteditor.SearchPanel searchPanel = new snow.texteditor.SearchPanel(textPane, doc);
58   // cool: double clicking on words selects all same words.
59
final ArrayList<Object JavaDoc> selectedWordTags = new ArrayList<Object JavaDoc>();
60   public static SimpleColorHighlighter errorHighlighter = new SimpleColorHighlighter( new Color JavaDoc(200, 130, 30, 50) );
61   public static SimpleColorHighlighter autoSelectHighlighter = new SimpleColorHighlighter( new Color JavaDoc(120, 120, 120, 50) );
62
63   private JPanel headerPanel = null;
64   private JScrollPane jsp;
65   private final UndoManager undoManager = new UndoManager();
66   private boolean undoEnabled = true;
67
68   private final JComboBox fromFieldCB = new JComboBox();
69   private final JTextField toField = new JTextField(12); // recipients
70

71   private final JCheckBox encryptCB = new JCheckBox(Language.translate("encrypt"));
72   private final JCheckBox signCB = new JCheckBox(Language.translate("sign"));
73
74   private final JPanel encryptCBPanel = new JPanel();
75   private final JPanel signCBPanel = new JPanel();
76
77   private final JTextField subjectField = new JTextField(25);
78   //private final JTextField searchTF = new JTextField(4);
79

80   private final JTextArea errorLabel = new JTextArea();
81   private final JTextArea mailStatusLabel = new JTextArea(); // sent, received, not sent, encrypted
82

83   private final JSplitPane multipartSlit;
84   private final MimeTreePanel mimeTreePanel;
85
86   final private JButton optionsButton = new JButton(Language.translate("Options"));
87   final private JButton decryptButton = new JButton(Language.translate("Decrypt"));
88   final private JButton verifyButton = new JButton(Language.translate("Verify signature"));
89   final private JButton browseAddressButton = new JButton(Language.translate("To")+": ");
90
91   final private JButton attachmentsButton = new JButton(Language.translate("Attachments")+": ");
92   final private AttachmentBar attachementsPanel = new AttachmentBar();
93
94   // add to spam, remove, add to address...
95
final private JButton fromOptionsButton = new JButton(Language.translate("From")+": ");
96
97   private boolean contentHasChanged = false;
98
99   private final JButton fromCategoryButton = new JButton(" ");
100
101   // used to decide if message has been read...
102
private long setMessageTime = 0;
103
104   // #### problem with actionListener : a set of the value when message changes call the listener !!
105
// so we activate/deactivate it manually
106
private final ItemListener fromFieldItemListener;
107
108   // created on first call
109
private KeyboardDialog keyboardDialog;
110
111   public MailView( MailAccounts accounts)
112   {
113     super(new BorderLayout JavaDoc(0,0));
114
115     fullMailContentView = new ViewTextDialog("fullMailContentView",
116          Language.translate("Full mail message content"), false);
117
118     hTMLViewer = new HTMLSecureViewer(SnowMailClientApp.getInstance(),
119        Language.translate("HTML Viewer"));
120     SnowMailClientApp.getInstance().getProperties().setComponentSizeFromINIFile(
121        hTMLViewer, "hTMLViewer", fontSize*55,fontSize*65, 50,50);
122
123     jsp = new JScrollPane(textPane);
124     jsp.setBorder(null);
125
126     // header
127
//
128
headerPanel = new EFCNBackgroundPanel(new BorderLayout JavaDoc(0,0),
129       EFCNBackgroundPanel.ApplyVerticalHighLight,
130       EFCNBackgroundPanel.MediumGradientStrength,
131       EFCNBackgroundPanel.PanelBackground
132     );
133
134     add(headerPanel, BorderLayout.NORTH);
135     headerPanel.setOpaque(false);
136
137     mimeTreePanel = new MimeTreePanel();
138     mimeTreePanel.setAttachementsQuickPanel(this.attachementsPanel);
139
140     multipartSlit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
141        mimeTreePanel,
142        jsp);
143     add(multipartSlit, BorderLayout.CENTER);
144     multipartSlit.setDividerLocation(0);
145     multipartSlit.setOneTouchExpandable(true);
146     multipartSlit.setOpaque(false);
147
148     add(searchPanel, BorderLayout.SOUTH);
149
150     jsp.setOpaque(false);
151     jsp.getViewport().setOpaque(false);
152     textPane.setOpaque(false);
153
154
155     JPanel fromToSubjPanel = new JPanel( );
156     GridLayout3 gl = new GridLayout3(3,fromToSubjPanel);
157
158     fromToSubjPanel.setOpaque(false);
159     fromToSubjPanel.setBorder(new EmptyBorder(fontSize/2,fontSize/2,fontSize/2,fontSize/2));
160     headerPanel.add(fromToSubjPanel, BorderLayout.CENTER);
161
162     // From
163

164     gl.add(fromOptionsButton, false);
165     setButtonSmallHeight(fromOptionsButton);
166     gl.add(fromFieldCB, true);
167     signCBPanel.add(this.signCB);
168     signCBPanel.setOpaque(false);
169     signCBPanel.setBorder(null);
170     signCB.setBorder(null);
171     gl.add(this.signCBPanel,false);
172     fromFieldCB.setOpaque(false);
173     signCB.setOpaque(false);
174     fromOptionsButton.addActionListener(new ActionListener()
175       { public void actionPerformed(ActionEvent e)
176         {
177            addressMenuPressed();
178         }
179       });
180     signCB.addActionListener(new ActionListener()
181       { public void actionPerformed(ActionEvent e)
182         {
183            //
184
if(message!=null)
185            {
186               message.setMustBeSigned(signCB.isSelected());
187            }
188         }
189       });
190
191     // To
192

193     gl.add( browseAddressButton, false);
194     setButtonSmallHeight(browseAddressButton);
195     gl.add( toField, true);
196     this.encryptCBPanel.add(this.encryptCB);
197     encryptCB.setBorder(null);
198     this.encryptCBPanel.setOpaque(false);
199     encryptCBPanel.setBorder(null);
200     gl.add(encryptCBPanel,false);
201     toField.setOpaque(false);
202     encryptCB.setOpaque(false);
203     encryptCB.addActionListener(new ActionListener()
204       { public void actionPerformed(ActionEvent e)
205         {
206            //
207
if(message!=null)
208            {
209               message.setMustBeEncrypted(encryptCB.isSelected());
210            }
211         }
212       });
213
214     // Subject
215

216     gl.add(new JContrastLabel(Language.translate("Subject")+": "), false);
217     gl.add(subjectField, true);
218     JLabel la = new JLabel("");
219     la.setBorder(null);
220     gl.add(la,false);
221     subjectField.setOpaque(false);
222
223
224     // Map tab to focus on the text ### not working
225
subjectField.addKeyListener(new KeyAdapter()
226     {
227       @Override JavaDoc public void keyTyped(KeyEvent ee)
228       {
229          if(ee.getKeyCode()==KeyEvent.VK_TAB)
230          {
231             textPane.requestFocus();
232          }
233       }
234     });
235
236     // Attachments
237
gl.add(attachmentsButton, false);
238     setButtonSmallHeight(attachmentsButton);
239     gl.add(attachementsPanel, true);
240     attachementsPanel.setLayout(new BoxLayout(attachementsPanel, BoxLayout.X_AXIS));
241     attachmentsButton.addActionListener(new ActionListener()
242     {
243        public void actionPerformed(ActionEvent ae)
244        {
245          attachmentButtonPressed();
246        }
247     });
248
249     // Options
250

251     JPanel optionsPanel = new JPanel();
252     optionsPanel.setBorder(new EmptyBorder(2,0,0,2));
253     optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.Y_AXIS));
254     optionsPanel.setOpaque(false);
255     headerPanel.add(optionsPanel, BorderLayout.EAST);
256
257
258     optionsButton.setEnabled(false);
259     optionsButton.setFont(ThemesManager.getInstance().getSmallFont());
260     optionsPanel.add(SnowMailClientApp.wrapRight(optionsButton));
261     this.setButtonSmallHeight(optionsButton);
262     optionsButton.addActionListener(new ActionListener()
263       { public void actionPerformed(ActionEvent e)
264         {
265           optionsButtonPressed();
266         }
267       });
268
269     optionsPanel.add(SnowMailClientApp.wrapRight(decryptButton));
270     decryptButton.setFont(ThemesManager.getInstance().getSmallFont());
271     decryptButton.setBackground(Color.orange);
272     this.setButtonSmallHeight(decryptButton);
273     decryptButton.addActionListener(new ActionListener()
274       { public void actionPerformed(ActionEvent e)
275         {
276           decryptButtonPressed();
277         }
278       });
279
280     optionsPanel.add(SnowMailClientApp.wrapRight(verifyButton));
281     verifyButton.setFont(ThemesManager.getInstance().getSmallFont());
282     verifyButton.setBackground(Color.orange);
283     this.setButtonSmallHeight(verifyButton);
284     verifyButton.addActionListener(new ActionListener()
285       { public void actionPerformed(ActionEvent e)
286         {
287           verifyButtonPressed();
288         }
289       });
290
291     JPanel searchPanel = new JPanel(new FlowLayout JavaDoc(FlowLayout.RIGHT,0,0));
292     searchPanel.setOpaque(false);
293     optionsPanel.add(searchPanel);
294
295     JButton searchButton = new JButton(Icons.SearchIcon.shared18);
296     searchButton.setMargin(new Insets JavaDoc(1,1,1,1));
297     searchPanel.add(searchButton);
298     searchButton.setToolTipText("Ctrl + F");
299     searchButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
300        MailView.this.searchPanel.CTRL_F_pressed();
301     } });
302
303     Vector<String JavaDoc> accountNamesToSend = new Vector<String JavaDoc>();
304     String JavaDoc[] accNames = new String JavaDoc[accounts.getRowCount()];
305     for(int i=0; i<accNames.length; i++)
306     {
307        MailAccount ma = accounts.getAccount(i);
308        if(ma.getUseToSendMails())
309        {
310           accountNamesToSend.add("\""+ma.getName()+"\" <"+ma.getAddress()+">");
311        }
312     }
313
314     fromFieldCB.setModel(new DefaultComboBoxModel(accountNamesToSend));
315     fromFieldCB.setEditable(true);
316
317     // focus cycle and edit notify
318

319     if(fromFieldCB.getEditor().getEditorComponent() instanceof JComponent)
320     {
321       ((JComponent) fromFieldCB.getEditor().getEditorComponent()).setOpaque(false);
322     }
323
324     fromFieldCB.getEditor().addActionListener(new ActionListener()
325       { public void actionPerformed(ActionEvent e)
326         {
327           toField.requestFocus();
328         }
329       });
330
331     toField.addActionListener(new ActionListener()
332       { public void actionPerformed(ActionEvent e)
333         {
334           setBrowseAddressesButtonText(); // TODO: also in the keylistener !
335
subjectField.requestFocus();
336         }
337       });
338
339     browseAddressButton.addActionListener(new ActionListener()
340       { public void actionPerformed(ActionEvent e)
341         {
342           browseToAddressAction();
343         }
344       });
345
346     subjectField.addActionListener(new ActionListener()
347       { public void actionPerformed(ActionEvent e)
348         {
349           textPane.requestFocus();
350         }
351       });
352
353     JPanel statusPanel = new JPanel();
354     statusPanel.setLayout(new BoxLayout(statusPanel, BoxLayout.Y_AXIS));
355     statusPanel.add(this.mailStatusLabel);
356
357     statusPanel.add(this.errorLabel);
358
359     mailStatusLabel.setVisible(false);
360     mailStatusLabel.setOpaque(false);
361     mailStatusLabel.setBorder(new EmptyBorder(1,3,1,1));
362     mailStatusLabel.setEditable(false);
363
364     headerPanel.add(statusPanel, BorderLayout.SOUTH);
365     errorLabel.setVisible(false);
366     errorLabel.setOpaque(false);
367     errorLabel.setBorder(new EmptyBorder(1,3,1,1));
368     errorLabel.setForeground(Color.red);
369     errorLabel.setEditable(false);
370
371
372     KeyAdapter headerEditionKeyAdapter = new KeyAdapter()
373     {
374       @Override JavaDoc public void keyReleased(KeyEvent e)
375       {
376          saveActualEditedHeader();
377       }
378     };
379
380     // message textPane
381
//
382
textPane.addKeyListener(new KeyAdapter()
383     {
384       @Override JavaDoc public void keyReleased(KeyEvent e)
385       {
386          // through the message's change event mechanism
387
notifyContentEditionListeners();
388       }
389     });
390     DefaultStyledDocument doc = (DefaultStyledDocument) textPane.getStyledDocument();
391     doc.addUndoableEditListener(this);
392
393
394     this.registerKeyboardAction( new ActionListener(){ public void actionPerformed(ActionEvent e){ undo(); }},
395                                                KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_MASK, true),
396                                                JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
397
398     this.registerKeyboardAction( new ActionListener(){ public void actionPerformed(ActionEvent e){ redo(); }},
399                                                KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_MASK, true),
400                                                JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
401
402
403     Style defaultStyle = //StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
404
textPane.getStyle("default");
405
406     Style searchHitStyle = doc.addStyle("SearchHit", defaultStyle);
407     StyleConstants.setBackground(searchHitStyle, Color.yellow);
408     StyleConstants.setBold(searchHitStyle, true);
409
410     toField.addKeyListener(headerEditionKeyAdapter);
411     subjectField.addKeyListener(headerEditionKeyAdapter);
412     BasicComboBoxEditor JavaDoc cbeditor = (BasicComboBoxEditor JavaDoc) fromFieldCB.getEditor();
413     cbeditor.getEditorComponent().addKeyListener(headerEditionKeyAdapter);
414
415     // #### problem with actionListener : a set of the value when message changes call the listener !!
416
// so we activate/deactivate it manually
417
fromFieldItemListener = new ItemListener()
418     {
419       public void itemStateChanged(ItemEvent e)
420       {
421          if(e.getStateChange()==ItemEvent.SELECTED)
422          {
423            saveActualEditedHeader();
424          }
425       }
426     };
427     fromFieldCB.addItemListener(fromFieldItemListener);
428
429
430     this.textPane.addPropertyChangeListener(
431      new PropertyChangeListener()
432      {
433         public void propertyChange(PropertyChangeEvent e)
434         {
435             String JavaDoc name = e.getPropertyName();
436             if (name.equals("UI"))
437              {
438                SwingUtilities.invokeLater( new Runnable JavaDoc()
439                 {
440                    public void run()
441                    {
442                      updateSpecialUI();
443                    }
444                 });
445              }
446         /* else
447             {
448               System.out.println(">"+name);
449             }*/

450         }
451      });
452
453      textPane.addMouseListener(new MouseAdapter()
454      {
455        @Override JavaDoc public void mousePressed(MouseEvent me)
456        {
457           if(me.isPopupTrigger())
458           {
459             showPopup(me);
460           }
461        }
462
463        @Override JavaDoc public void mouseReleased(MouseEvent me)
464        {
465           if(me.isPopupTrigger())
466           {
467             showPopup(me);
468           }
469        }
470
471        @Override JavaDoc public void mouseClicked(MouseEvent me)
472        {
473           if(!me.isPopupTrigger())
474           {
475              clearAutoSelectedWords();
476              if(me.getClickCount()==2)
477              {
478                doubleClicked(me);
479              }
480           }
481        }
482      });
483
484      this.registerKeyboardAction(new ActionListener()
485      {
486        public void actionPerformed(ActionEvent ae)
487        {
488           String JavaDoc selectedText = getSelectedOrWordAtCaret();
489           if(selectedText!=null)
490           {
491              clearAutoSelectedWords();
492              autoSelectWords(selectedText);
493           }
494        }
495      }, "Highlight all occurences", KeyStroke.getKeyStroke(KeyEvent.VK_K, KeyEvent.CTRL_MASK,false), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
496
497
498      // init
499
EventQueue.invokeLater(new Runnable JavaDoc()
500      {
501        public void run()
502        {
503          setMessage(message); // normally null at startup, but not always !!!!
504
}
505      });
506   } // initialize
507

508
509   public void hideAttachmentSplit()
510   {
511      multipartSlit.setDividerLocation(0);
512   }
513
514   public void mailMessageChanged(MailMessage source, MailMessageChangeListener.MailMessageChangeType type, String JavaDoc detail )
515   {
516      if(type==MailMessageChangeListener.MailMessageChangeType.DECRYPTED)
517      {
518         // enforce repaint, everything have changed!
519
MailMessage actual = this.message;
520         this.setMessage(null);
521         this.setMessage(actual);
522      }
523   }
524
525   //
526
// UNDO
527
//
528

529   /** Called at each changes of the edited document (insert, delete).
530      are added to the undo manager to be redoed.
531      also notifies the edition listeners.
532   */

533   public void undoableEditHappened(UndoableEditEvent e)
534   {
535     if(undoEnabled)
536     {
537       undoManager.addEdit(e.getEdit());
538     }
539
540     // used this occasion to notify the edition listeners
541
this.notifyContentEditionListeners();
542   }
543
544   /** For the undo manager or CTRL + Z
545   */

546   public void undo()
547   {
548      try
549      {
550         if(undoManager.canUndo())
551         {
552           undoManager.undo();
553         }
554      }
555      catch(Exception JavaDoc cue)
556      {
557         // not only UndoExceptions....
558
cue.printStackTrace();
559      }
560   }
561
562   public void redo()
563   {
564      try
565      {
566         if(undoManager.canRedo())
567         {
568           undoManager.redo();
569         }
570      }
571      catch(Exception JavaDoc cue)
572      {
573         // not only UndoExceptions....
574
cue.printStackTrace();
575      }
576   }
577
578   private void attachmentButtonPressed()
579   {
580     if(message==null) return;
581     JPopupMenu popup = new JPopupMenu("Attachment popup");
582     if(message.isEditable())
583     {
584       JMenuItem miAddAttachment = new JMenuItem(Language.translate("Add attachment"), Icons.PlusIcon.shared10);
585       popup.add(miAddAttachment);
586       miAddAttachment.addActionListener(new ActionListener()
587       {
588         public void actionPerformed(ActionEvent ae)
589         {
590            mimeTreePanel.addAttachmentAction();
591         }
592       });
593     }
594
595     JMenuItem miShowMimeTree = new JMenuItem(Language.translate("Show mime tree"));
596     popup.add(miShowMimeTree);
597     miShowMimeTree.addActionListener(new ActionListener()
598     {
599       public void actionPerformed(ActionEvent ae)
600       {
601         if(multipartSlit.getDividerLocation()<120)
602         {
603           multipartSlit.setDividerLocation(120);
604         }
605       }
606     });
607
608     popup.show( this.attachmentsButton, 0, 20);
609   }
610
611   private void verifyButtonPressed()
612   {
613     if(message==null) return;
614     if(!message.lookIfContentIsPGPSigned())
615     {
616       JOptionPane.showMessageDialog(SnowMailClientApp.getInstance(),
617         Language.translate("The message is not in GPG format"),
618         Language.translate("Cannot decrypt mail"), JOptionPane.ERROR_MESSAGE);
619     }
620
621     try
622     {
623       System.out.println("Verify signature of:\n" + message.getMessageBody());
624
625       GnuPGLink gpg = SnowMailClientApp.getInstance().getGnuPGLink();
626       ByteArrayInputStream JavaDoc bin = new ByteArrayInputStream JavaDoc(message.getMessageBody().getBytes());
627       Vector<SignatureVerificationResult> sigs = GnuPGCommands.verifySignature(gpg.getPathToGPG(), bin, null);
628       //for(SignatureVerificationResult
629
message.setSignatureVerification(sigs);
630
631     }
632     catch(Exception JavaDoc er)
633     {
634       JOptionPane.showMessageDialog(SnowMailClientApp.getInstance(),
635         er.getMessage(),
636         Language.translate("Cannot verify signature"), JOptionPane.ERROR_MESSAGE);
637     }
638   }
639
640   private void decryptButtonPressed()
641   {
642     if(message==null) return;
643     if(!message.lookIfContentIsPGPEncrypted())
644     {
645       JOptionPane.showMessageDialog(SnowMailClientApp.getInstance(),
646         Language.translate("The message is not in GPG format"),
647         Language.translate("Cannot decrypt mail"), JOptionPane.ERROR_MESSAGE);
648     }
649
650     try
651     {
652       // ensure that the call to the message function will be successful !
653

654       GnuPGLink gpg = SnowMailClientApp.getInstance().getGnuPGLink();
655       String JavaDoc[] uk = GnuPGCommands.determineUsedKey(gpg.getPathToGPG(), message.getMessageBody(),null);
656       //System.out.println("uk=" + uk[0] + "," + uk[1]);
657

658       Address ad = new Address(uk[1]);
659       GnuPGKeyID[] keys = gpg.getSecretKeyIDForAddress(ad.getMailAddress());
660       if(keys.length==0)
661       {
662          throw new Exception JavaDoc(Language.translate("No GPG key found for %",uk[1]));
663       }
664
665       byte[] pass = gpg.getPasswordForKeyAskIfNotFoundOrNotValid(
666                            keys[0], true, SnowMailClientApp.getInstance());
667
668       String JavaDoc decryptedMessage = GnuPGCommands.decryptBufferForRecipient(
669                            gpg.getPathToGPG(), message.getMessageBody(), keys[0], pass, null);
670
671       //System.out.println("dec="+dec);
672

673       message.setDecryptedMessage(decryptedMessage);
674     }
675     catch(Exception JavaDoc er)
676     {
677       JOptionPane.showMessageDialog(SnowMailClientApp.getInstance(),
678         er.getMessage(),
679         Language.translate("Cannot decrypt mail"), JOptionPane.ERROR_MESSAGE);
680     }
681   }
682
683   private void optionsButtonPressed()
684   {
685       if(message==null) return;
686
687       JPopupMenu popup = new JPopupMenu("Options");
688
689       JMenuItem keyboardItem = new JMenuItem(Language.translate("Keyboard"));
690
691       if(message.isEditable())
692       {
693         popup.add(keyboardItem);
694         popup.addSeparator();
695       }
696
697       keyboardItem.addActionListener(new ActionListener()
698       {
699           public void actionPerformed(ActionEvent e)
700           {
701               if(keyboardDialog==null)
702               {
703                 keyboardDialog = new KeyboardDialog(SnowMailClientApp.getInstance());
704                 keyboardDialog.setTarget(textPane);
705                 SnowMailClientApp.getInstance().getProperties().setComponentLocationFromINIFile(
706                       keyboardDialog, "KeyboardDialog", 300,200);
707                 keyboardDialog.setKeyboard(new PolishMap());
708                 keyboardDialog.pack();
709               }
710
711               keyboardDialog.setVisible(true);
712           }
713       });
714
715       JMenuItem fullViewItem = new JMenuItem(Language.translate("Full content"));
716
717       popup.add(fullViewItem);
718       fullViewItem.addActionListener(new ActionListener()
719       {
720          public void actionPerformed(ActionEvent e)
721          {
722             if(message!=null)
723             {
724                saveActualMessage();
725                // bof bof, for big mails, this is not especially good...
726
if(message.getCompleteContentAsString().length()>100000) // 100ko
727
{
728                  fullMailContentView.setText(
729                          Language.translate( "The message is too big to be displayed, you see just the first 100kB here" )
730                        + "\n\n"
731                        + message.getCompleteContentAsString().substring(0, 50000)
732                    );
733                }
734                else
735                {
736                  fullMailContentView.setText(message.getCompleteContentAsString());
737                }
738             }
739             else
740             {
741                fullMailContentView.setText(Language.translate("No message selected."));
742             }
743             fullMailContentView.setVisible(true);
744           }
745       });
746
747       JMenuItem fullSendViewItem = new JMenuItem(Language.translate("Content as to be sent"));
748       if(SnowMailClientApp.debug)
749       {
750         popup.add(fullSendViewItem);
751       }
752       fullSendViewItem.addActionListener(new ActionListener()
753       {
754          public void actionPerformed(ActionEvent ae)
755          {
756             if(message!=null)
757             {
758                saveActualMessage();
759                try
760                {
761                  byte[] cc = message.getCompleteContentToSend(null,null, null, null);
762                  fullMailContentView.setText(new String JavaDoc(cc));
763                }
764                catch(Exception JavaDoc ex)
765                {
766                  fullMailContentView.setText("Error getting sent content: "+ex.getMessage());
767                }
768             }
769             else
770             {
771                fullMailContentView.setText(Language.translate("No message selected."));
772             }
773             fullMailContentView.setVisible(true);
774           }
775       });
776
777       JMenuItem viewHTMLBT = new JMenuItem(Language.translate("View HTML"));
778       if(message.lookIfContentIsHTML())
779       {
780         popup.add(viewHTMLBT);
781       }
782
783       viewHTMLBT.addActionListener(new ActionListener()
784         { public void actionPerformed(ActionEvent e)
785           {
786             viewHTMLAction();
787           }
788         });
789
790       if(message.getHeader().hasEntry("Received") )
791       {
792
793         JMenuItem viewTrace = new JMenuItem(Language.translate("Trace"));
794         SnowMailClientApp.getInstance().addAdvancedComponent(viewTrace);
795         popup.addSeparator();
796         popup.add(viewTrace);
797
798         viewTrace.addActionListener(new ActionListener()
799           { public void actionPerformed(ActionEvent e)
800             {
801               viewTraceAction();
802             }
803           });
804       }
805
806       JMenuItem viewSPAMStat = new JMenuItem(Language.translate("Spam Stat"));
807
808       JComponent sep = new JPopupMenu.Separator();
809       SnowMailClientApp.getInstance().addAdvancedComponent(sep);
810       popup.add(sep);
811
812       popup.add(viewSPAMStat);
813       SnowMailClientApp.getInstance().addAdvancedComponent(viewSPAMStat);
814
815       viewSPAMStat.addActionListener(new ActionListener()
816       { public void actionPerformed(ActionEvent e)
817           {
818             SpamResult spamResult = SnowMailClientApp.getInstance().getWordStatistic().calculateSpamProbability(message);
819             SpamResult spamResultHeader = SnowMailClientApp.getInstance().getWordStatistic().calculateSpamProbability(message.getHeader());
820
821             StringBuffer JavaDoc sb = new StringBuffer JavaDoc(Language.translate("SPAM probability")+" = "+spamResult.getProbability()+"\n");
822             sb.append(Language.translate("Header SPAM probability")+" = "+spamResultHeader.getProbability()+"\n");
823
824             sb.append("\r\n\r\n"+Language.translate("Message most relevant words")+"\r\n");
825             for(int i=0; i<spamResult.getMostSignificantWords().size(); i++)
826             {
827               Word wi = spamResult.getMostSignificantWords().get(i);
828               sb.append("\r\n "+wi.toString());
829             }
830
831             sb.append("\r\n\r\n" + Language.translate("Header most relevant words")+"\r\n");
832             for(int i=0; i<spamResultHeader.getMostSignificantWords().size(); i++)
833             {
834               Word wi = spamResultHeader.getMostSignificantWords().get(i);
835               sb.append("\r\n "+wi.toString());
836             }
837
838             sb.append("\r\n\r\n" + Language.translate("All message words") + "\r\n");
839             for(int i=0; i<spamResultHeader.getAllWords().size(); i++)
840             {
841               Word wi = spamResultHeader.getAllWords().get(i);
842               sb.append("\r\n "+wi.toString());
843             }
844
845             fullMailContentView.setText(sb.toString());
846             fullMailContentView.setVisible(true);
847           }
848       });
849
850       popup.show( this.optionsButton, 0, fontSize*3/2);
851   }
852
853   public void callBeforeTerminating()
854   {
855      if(keyboardDialog!=null)
856      {
857        SnowMailClientApp.getInstance().getProperties().saveComponentLocationInINIFile(keyboardDialog, "KeyboardDialog");
858      }
859   }
860
861   /** Called when UI changes
862   */

863   private void updateSpecialUI()
864   {
865     //System.out.println("MailView.updateSpecialUI()");
866
if(jsp!=null)
867     {
868       fontSize = UIManager.getFont("Label.font").getSize();
869       jsp.setOpaque(false);
870       jsp.getViewport().setOpaque(false);
871     }
872
873     textPane.setOpaque(false);
874     textPane.setFont(UIManager.getFont("TextPane.font"));
875   }
876
877
878   /** This is used to reflect in real times the changes in header data
879       in the table view during edit in the mailview...
880   */

881   private void saveActualEditedHeader()
882   {
883     if(message!=null)
884     {
885        message.setMessageHeader(
886            new Address((String JavaDoc) this.fromFieldCB.getSelectedItem()),
887            Address.parseAddressList(this.toField.getText()),
888            this.subjectField.getText()
889        );
890     }
891   }
892
893   /** Only call in special cases (backup, termination, ...)
894       otherwise, this is managed from the view itself,
895
896       Called:
897       1) when the selection changes, when one click on another message...
898   */

899   public void saveActualMessage()
900   {
901     // reset new flag
902
//
903
if( message!=null && message.getIsNew() )
904     {
905        // only if it has been read => has been show for at least 5 secs
906
long now = System.currentTimeMillis();
907        if(now-setMessageTime>TimeToMarkAsRead)
908        {
909           message.setIsNoMoreNew();
910        }
911     }
912
913     // save actual message if editable
914
//
915
if(message!=null /* && message.isEditable()*/ // [May2007]: allow removing attachements...
916
&&
917       ( (contentHasChanged && message.isEditable()) || this.mimeTreePanel.getHasChanged()))
918     {
919       // if(contentHasChanged) System.out.println("contentHasChanged");
920
// if(mimeTreePanel.getHasChanged()) System.out.println("mtree changed");
921

922        // always call this ...
923
// mime or flat are treated there (text is either stored as plain in the mime tree) or as raw body
924
message.setMessage(
925            new Address((String JavaDoc) this.fromFieldCB.getSelectedItem()),
926            Address.parseAddressList(this.toField.getText()),
927            this.subjectField.getText(),
928            this.textPane.getText()
929        );
930
931        if(message.isEditable())
932        {
933          message.setActualDate();
934        }
935     }
936
937     //fullMailContentView.saveSizeAndLocation();
938
SnowMailClientApp.getInstance().getProperties().saveComponentSizeInINIFile(
939       this.hTMLViewer, "hTMLViewer");
940
941     // reset the change detector
942
contentHasChanged = false;
943   }
944
945   private int lastFoundPosition = -1;
946
947   /** Causes the highlight of the selected text
948   */

949   public synchronized void searchText(String JavaDoc text, boolean searchNext)
950   {
951      DefaultStyledDocument doc = (DefaultStyledDocument) textPane.getStyledDocument();
952
953      // important, don't use the textpane getText method(), line feeds doesn't have the same length !!
954
String JavaDoc textUp = "";
955      try
956      {
957        textUp = doc.getText(0, doc.getLength()).toUpperCase();
958      }
959      catch(Exception JavaDoc e)
960      {
961        e.printStackTrace();
962      }
963
964      // reset the style for the whole document
965
Style defaultStyle = textPane.getStyle("default");
966      doc.setCharacterAttributes(0, textUp.length(), defaultStyle, true);
967
968      if(text.length()==0)
969      {
970         // nothing to find !!
971
return;
972      }
973
974      if(searchNext)
975      {
976         lastFoundPosition = textUp.indexOf(text.toUpperCase(), lastFoundPosition+1);
977      }
978      else
979      {
980         lastFoundPosition = -1;
981      }
982
983
984      // search from beginning if either not found from now or not search next
985
if(lastFoundPosition==-1)
986      {
987         lastFoundPosition = textUp.indexOf(text.toUpperCase(), 0);
988      }
989
990      if(lastFoundPosition!=-1)
991      {
992         try
993         {
994            Style highlightStyle = doc.getStyle("SearchHit");
995            if(highlightStyle==null)
996            {
997              System.out.println("MailView textsearch highlightStyle is null !");
998            }
999            else
1000           {
1001             doc.setCharacterAttributes(lastFoundPosition, text.length(), highlightStyle, true);
1002             textPane.setCaretPosition(lastFoundPosition);
1003           }
1004        }
1005        catch(Exception JavaDoc e)
1006        {
1007           e.printStackTrace();
1008        }
1009     }
1010  }
1011
1012  /** Sets the message to view, save the actual,...
1013  */

1014  public void setMessage(MailMessage newMessage)
1015  {
1016    // do nothing if the message is the same
1017
// this occurs if the header is clicked for sorting
1018
if(newMessage!=null && message == newMessage)
1019    {
1020       return;
1021    }
1022
1023    //new Throwable().printStackTrace();
1024

1025    // save old message (only done if necessary)
1026
saveActualMessage();
1027
1028    // used to decide when a message has been read
1029
setMessageTime = System.currentTimeMillis();
1030
1031    // remove listener
1032
if(message!=null) message.removeChangeListener(this);
1033
1034    // set the message
1035
this.message = newMessage;
1036    if(message!=null) message.addChangeListener(this);
1037    this.mimeTreePanel.setMessage(message);
1038
1039    multipartSlit.setDividerLocation(0);
1040
1041    if(message!=null)
1042    {
1043
1044/* double p = SnowMailClientApp.getInstance().getWordStatistic().calculateSpamProbability(message);
1045      System.out.println("SPAM Probability calculated = "+p);
1046      p = SnowMailClientApp.getInstance().getWordStatistic().calculateSpamProbability(message.getHeader());
1047      System.out.println("Header SPAM Probability = "+p);
1048*/

1049
1050      // sets the text
1051
// for non editable messages (received) maybe HTML
1052
//
1053
setTextAreaContent_from_Message(message);
1054
1055      setVisible(true);
1056      headerPanel.setEnabled(true);
1057      textPane.setEnabled(true);
1058      optionsButton.setEnabled(true);
1059      fromOptionsButton.setEnabled(true);
1060
1061      // from
1062
// BE Careful here
1063
fromFieldCB.removeItemListener(fromFieldItemListener);
1064      fromFieldCB.setSelectedItem( message.getFromAddress().toString() );
1065      fromFieldCB.addItemListener(fromFieldItemListener);
1066
1067      if(SnowMailClientApp.getInstance().getAddressBook().getAddress(message.getFromAddress().getMailAddress())!=null)
1068      {
1069        fromFieldCB.setBackground(ThemesManager.getInstance().getGreen());
1070        fromFieldCB.setOpaque(true);
1071      }
1072      else if(SnowMailClientApp.getInstance().getSpamBook().getAddress(message.getFromAddress().getMailAddress())!=null)
1073      {
1074        fromFieldCB.setBackground(ThemesManager.getInstance().getRed()); //
1075
fromFieldCB.setOpaque(true);
1076      }
1077      else
1078      {
1079        fromFieldCB.setOpaque(false);
1080      }
1081
1082      toField.setText( message.getToAddressesText() );
1083      setBrowseAddressesButtonText();
1084      subjectField.setText( message.getSubject() );
1085
1086      toField.setEditable(message.isEditable());
1087      browseAddressButton.setEnabled(message.isEditable());
1088      fromFieldCB.setEnabled(message.isEditable()); // not edit !
1089
subjectField.setEditable(message.isEditable());
1090
1091      this.signCB.setVisible(message.isEditable());
1092      this.encryptCB.setVisible(message.isEditable());
1093
1094      this.signCB.setSelected(message.getMustBeSigned());
1095      this.encryptCB.setSelected(message.getMustBeEncrypted());
1096
1097      if(message.hasParseError())
1098      {
1099        this.setMailErrorRemark(message.getErrorMessage());
1100      }
1101      else
1102      {
1103        this.setMailErrorRemark("");
1104      }
1105
1106      this.setMailStatusRemark( message.getStatusRemark() );
1107
1108      this.decryptButton.setVisible(message.lookIfContentIsPGPEncrypted());
1109      this.verifyButton.setVisible(message.lookIfContentIsPGPSigned());
1110
1111      boolean viewAtt = message.isEditable()
1112            || (message.getMimeTree()!=null && message.getMimeTree().isMimeMessageFormat());
1113      this.attachementsPanel.setVisible( viewAtt );
1114      attachmentsButton.setVisible( viewAtt );
1115    }
1116    else
1117    {
1118      // message is null
1119
browseAddressButton.setEnabled(false);
1120
1121      errorLabel.setVisible(false);
1122
1123      setMessageTextPaneText("");
1124
1125      toField.setText("");
1126      setBrowseAddressesButtonText();
1127      subjectField.setText("");
1128      fromFieldCB.setSelectedIndex(-1);
1129      fromFieldCB.setOpaque(false);
1130
1131      textPane.setEnabled(false);
1132      headerPanel.setEnabled(false);
1133      optionsButton.setEnabled(false);
1134      fromOptionsButton.setEnabled(false);
1135
1136      toField.setEditable(false);
1137      fromFieldCB.setEnabled(false);
1138      subjectField.setEditable(false);
1139      textPane.setEditable(false);
1140
1141      this.signCB.setVisible(false);
1142      this.encryptCB.setVisible(false);
1143      verifyButton.setVisible(false);
1144
1145
1146      fullMailContentView.setText("");
1147
1148      setMailStatusRemark("");
1149      setMailErrorRemark("");
1150
1151      this.decryptButton.setVisible(false);
1152
1153      this.attachementsPanel.setVisible(false);
1154      attachmentsButton.setVisible( false );
1155    }
1156
1157  }
1158
1159  private void setMailStatusRemark(String JavaDoc text)
1160  {
1161    mailStatusLabel.setText(text);
1162    mailStatusLabel.setVisible(text.length()>0);
1163  }
1164
1165  private void setMailErrorRemark(String JavaDoc text)
1166  {
1167    this.errorLabel.setText(text);
1168    errorLabel.setVisible(text.length()>0);
1169  }
1170
1171  private void setMessageTextPaneText(String JavaDoc text)
1172  {
1173       // make no sense otherwise !
1174
this.undoManager.discardAllEdits();
1175      this.undoEnabled = false;
1176      textPane.setText(text);
1177      textPane.setCaretPosition(0);
1178      this.undoEnabled = true;
1179  }
1180
1181  private void setButtonSmallHeight(JButton comp)
1182  {
1183  // GUIUtils.setNarrowInsets(comp);
1184
GUIUtils.setSmallDimensions(comp);
1185
1186    /* comp.setPreferredSize(new Dimension(
1187      (int) comp.getPreferredSize().getWidth(),
1188      (int) this.subjectField.getPreferredSize().getHeight()));*/

1189  }
1190
1191
1192  /** null if no message actually edited
1193  */

1194  public MailMessage getMessage()
1195  {
1196    return message;
1197  }
1198
1199  //maybe null
1200
String JavaDoc getSelectedOrWordAtCaret()
1201  {
1202
1203          if((textPane.getSelectionEnd()-textPane.getSelectionStart())>0)
1204          {
1205            return textPane.getSelectedText();
1206          }
1207          else
1208          {
1209            // detect the word at the cursor
1210
return DocumentUtils.getWordAt(doc, textPane.getCaretPosition());
1211          }
1212  }
1213
1214
1215  /** this set the content of the mail to view in the text area
1216
1217     1) if the message is editable (composed), it is always pure text and
1218        the plain/text of multipart content is shown.
1219
1220     2) if the message is not editable (received, sent)
1221        if it is in HTML format, display a secure html (without images)
1222        ...
1223  */

1224  private void setTextAreaContent_from_Message(MailMessage mess)
1225  {
1226      textPane.setEditable(mess.isEditable());
1227
1228      if(MimeUtils.isMultipart(mess))
1229      {
1230           MimeTreeModel treeModel = mess.getMimeTree();
1231           MimePart textPart = treeModel.getFirstPlainTextPart();
1232           if(textPart!=null)
1233           {
1234              String JavaDoc cont = textPart.getBodyAsText();
1235              this.setMessageTextPaneText(cont);
1236
1237           }
1238           else
1239           {
1240
1241              // TODO:
1242
// show the parsed html !!
1243
MimePart mpH = treeModel.getFirstHTMLTextPart();
1244              if(mpH!=null)
1245              {
1246                String JavaDoc cont = mpH.getBodyAsText();
1247                try
1248                {
1249                  HTMLTextExtractor he = new HTMLTextExtractor(cont, true);
1250                  setMessageTextPaneText("No text part in the mail, here is the first extracted html\n"+he.getTextOnly());
1251                }
1252                catch(Exception JavaDoc e)
1253                {
1254                  setMessageTextPaneText("No text part in the mail, here is the first html part\n"+cont);
1255                }
1256              }
1257              else
1258              {
1259                setMessageTextPaneText("No text part in the mail");
1260              }
1261           }
1262      }
1263      else
1264      {
1265        // not multipart
1266

1267        if(mess.isEditable())
1268        {
1269          // always only text in the editable messages...
1270

1271          setMessageTextPaneText(mess.getMessageBody());
1272        }
1273        else
1274        {
1275          if(mess.lookIfContentIsHTML())
1276          {
1277            try
1278            {
1279              HTMLTextExtractor he = new HTMLTextExtractor(mess.getMessageBody(), true);
1280              setMessageTextPaneText(
1281                Language.translate("The message content is in HTML format. Here is the extracted text. Use options to see the original.")
1282                  +"\n\n"
1283                  +he.getTextOnly());
1284            }
1285            catch(Exception JavaDoc e)
1286            {
1287              setMessageTextPaneText(mess.getMessageBody());
1288            }
1289          }
1290          else
1291          {
1292            setMessageTextPaneText(mess.getMessageBody());
1293          }
1294        }
1295      }
1296  }
1297
1298
1299
1300  private void viewHTMLAction()
1301  {
1302     if(message==null) return;
1303
1304     MimeTreeModel treeModel = message.getMimeTree();
1305     MimePart htmlPart = treeModel.getFirstHTMLTextPart();
1306     String JavaDoc cont = "";
1307     if(htmlPart!=null)
1308     {
1309        try
1310        {
1311           HTMLFromMIME htmm = new HTMLFromMIME(treeModel);
1312           cont = htmm.getHTMLCodeWithLocalizedLinks();
1313        }
1314        catch(Exception JavaDoc e)
1315        {
1316           cont = Language.translate("Error")+": "+e.getMessage();
1317        }
1318     }
1319     else
1320     {
1321        cont = message.getMessageBody();
1322        try
1323        {
1324          HTMLCleaner hc = new HTMLCleaner(cont, false);
1325          cont = hc.getCleanHTMLText();
1326        }
1327        catch(Exception JavaDoc ee)
1328        {
1329          cont = ee.getMessage();
1330        }
1331     }
1332     hTMLViewer.setHTMLSource(cont);
1333     hTMLViewer.setVisible(true);
1334  }
1335
1336  private void viewTraceAction()
1337  {
1338     if(message==null) return;
1339     new TraceViewDialog(SnowMailClientApp.getInstance(), message.getHeader());
1340  }
1341
1342  private void addressMenuPressed()
1343  {
1344    final AddressBook addressBook = SnowMailClientApp.getInstance().getAddressBook();
1345    final AddressBook spamBook = SnowMailClientApp.getInstance().getSpamBook();
1346
1347    JPopupMenu addressMenu = new JPopupMenu(Language.translate("Address"));
1348
1349
1350    if( !addressBook.hasAddress(message.getFromAddress().getMailAddress()) )
1351    {
1352      JMenuItem addAdd = new JMenuItem(Language.translate("Add to addressbook"), Icons.PlusIcon.shared10);
1353      addressMenu.add(addAdd);
1354      addAdd.addActionListener(new ActionListener()
1355      {
1356        public void actionPerformed(ActionEvent e)
1357        {
1358          if( message!=null)
1359          {
1360            Address a = message.getFromAddress();
1361            addressBook.addAddress( a );
1362          }
1363        }
1364      });
1365    }
1366
1367    if( !spamBook.hasAddress(message.getFromAddress().getMailAddress()) )
1368    {
1369      JMenuItem addSPAM = new JMenuItem(Language.translate("Add to SPAM list"), Icons.PlusIcon.shared10);
1370      addressMenu.add(addSPAM);
1371      addSPAM.addActionListener(new ActionListener()
1372      {
1373        public void actionPerformed(ActionEvent e)
1374        {
1375          if( message!=null)
1376          {
1377            Address a = message.getFromAddress();
1378            spamBook.addAddress( a );
1379          }
1380        }
1381      });
1382    }
1383
1384    addressMenu.show(this.fromOptionsButton, 0, fontSize*3/2);
1385
1386  }
1387
1388  private boolean browseToAddressAction_add = false;
1389
1390  /** select the mail recipients To from the address book
1391  */

1392  private void browseToAddressAction()
1393  {
1394     AddressBook adb = SnowMailClientApp.getInstance().getAddressBook();
1395     Vector<Address> addresses = Address.parseAddressList(toField.getText());
1396     adb.setSelectedAddresses(addresses);
1397
1398     final JDialog browseAddress = new JDialog(SnowMailClientApp.getInstance(),
1399                         Language.translate("Select receipient(s) to send the mail"), true);
1400     browseAddress.getContentPane().setLayout(new BorderLayout JavaDoc());
1401     CloseControlPanel ccp = new CloseControlPanel(browseAddress, true, true, Language.translate("Use only selected"));
1402     JButton addSelectedButton = new JButton(Language.translate("Add selected"), Icons.PlusIcon.shared10);
1403     ccp.add(addSelectedButton);
1404     browseToAddressAction_add = false;
1405     addSelectedButton.setBackground( ccp.getOkButton().getBackground() );
1406     addSelectedButton.addActionListener(new ActionListener()
1407     {
1408       public void actionPerformed(ActionEvent ae)
1409       {
1410         browseToAddressAction_add = true;
1411         browseAddress.setVisible(false);
1412         browseAddress.dispose();
1413       }
1414     });
1415
1416     browseAddress.getContentPane().add(ccp, BorderLayout.SOUTH);
1417     final SortableTableModel stm = new SortableTableModel(adb,0,true);
1418     JTable table = new JTable(stm);
1419     stm.installGUI(table);
1420     browseAddress.getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
1421     table.getColumnModel().getColumn(0).setPreferredWidth(200);
1422     table.getColumnModel().getColumn(1).setPreferredWidth(300);
1423
1424     // north
1425
//
1426
final JTextField searchTF = new JTextField(8);
1427     final JTextField searchTF2 = new JTextField(8);
1428     JPanel northPanel = new JPanel(new FlowLayout JavaDoc(FlowLayout.LEFT));
1429     browseAddress.getContentPane().add(northPanel, BorderLayout.NORTH);
1430     northPanel.add(new JLabel(Language.translate("Search")+":"));
1431     northPanel.add(searchTF);
1432     northPanel.add(new JLabel(" & "));
1433     northPanel.add(searchTF2);
1434     KeyAdapter ska = new KeyAdapter()
1435     {
1436        @Override JavaDoc public void keyReleased(KeyEvent e)
1437        {
1438           stm.search(searchTF.getText(), searchTF2.getText(), false);
1439        }
1440     };
1441     searchTF.addKeyListener(ska);
1442     searchTF2.addKeyListener(ska);
1443
1444     SnowMailClientApp.getInstance().getProperties().setComponentSizeFromINIFile(
1445       browseAddress, "browseAddressDialog", 600,400,100,20);
1446
1447     // MODAL
1448
browseAddress.setVisible(true);
1449     SnowMailClientApp.getInstance().getProperties().saveComponentSizeInINIFile(
1450       browseAddress, "browseAddressDialog");
1451
1452     if(ccp.getWasCancelled()) return;
1453
1454     // force a key event to update the selection store in the stm
1455
ska.keyReleased(null);
1456     int[] sel = adb.getSelectedRows();
1457     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1458     for(int i=0; i<sel.length; i++)
1459     {
1460        Address ad = adb.getAddressAt(sel[i]);
1461        sb.append(ad.toString());
1462        if(i<sel.length-1) sb.append("; ");
1463     }
1464
1465     if(browseToAddressAction_add)
1466     {
1467       if(toField.getText().trim().length()>0)
1468       {
1469         toField.setText(toField.getText().trim()+"; "+sb.toString());
1470       }
1471       else
1472       {
1473         toField.setText(sb.toString());
1474       }
1475     }
1476     else
1477     {
1478       // replace the existing address !
1479
toField.setText(sb.toString());
1480     }
1481
1482     saveActualEditedHeader();
1483
1484     setBrowseAddressesButtonText();
1485  }
1486
1487  /**
1488  */

1489  private void setBrowseAddressesButtonText()
1490  {
1491    List<Address> adds = Address.parseAddressList(this.toField.getText());
1492
1493    if(adds.size()<=1)
1494    {
1495      this.browseAddressButton.setText(Language.translate("To")+":");
1496    }
1497    else
1498    {
1499      this.browseAddressButton.setText(Language.translate("% Tos", ""+adds.size())+":");
1500      setButtonSmallHeight(browseAddressButton);
1501    }
1502
1503  }
1504
1505
1506  // Editor popup and word highlight
1507
//
1508

1509  /** Override this to create custom behaviour.
1510  */

1511  protected void lineClicked(MouseEvent me)
1512  {
1513  }
1514
1515  /** Override this to create custom behaviour. Now selecting all same words.
1516  */

1517  protected void doubleClicked(MouseEvent me)
1518  {
1519       int sl = textPane.getSelectionEnd()-textPane.getSelectionStart();
1520       if(sl>0 && sl<1000)
1521       {
1522          String JavaDoc sel = textPane.getSelectedText();
1523          // highlight them all !
1524
autoSelectWords(sel);
1525       }
1526  }
1527
1528  private void clearAutoSelectedWords()
1529  {
1530     //System.out.println("Clearing "+selectedWordTags.size()+" sel tags");
1531
for(Object JavaDoc o : selectedWordTags)
1532     {
1533        textPane.getHighlighter().removeHighlight(o);
1534     }
1535     selectedWordTags.clear();
1536     searchPanel.setInfoText("");
1537  }
1538
1539  private void autoSelectWords(String JavaDoc w)
1540  {
1541     try
1542     {
1543       int[] visibleBounds = DocumentUtils.getVisibleDocPosBounds(textPane, jsp);
1544
1545       // the quick part first:
1546
String JavaDoc part = textPane.getText(visibleBounds[0], visibleBounds[1]-visibleBounds[0]);
1547       int pos = -1;
1548       while((pos=part.indexOf(w,pos+1))>=0)
1549       {
1550          selectedWordTags.add( textPane.getHighlighter().addHighlight(
1551                    pos+visibleBounds[0], pos+visibleBounds[0]+w.length(), doc.autoSelectHighlighter));
1552       }
1553
1554       // the whole document now (ignoring already performed part)
1555

1556       part = doc.getText();
1557       //textPane.getText(0, doc.getLength()); /// AAAAAAHHH textPane.getText() gives different content!
1558
pos = -1;
1559       while((pos=part.indexOf(w,pos+1))>=0)
1560       {
1561          if(pos<=visibleBounds[0] || pos>=visibleBounds[1])
1562          {
1563             selectedWordTags.add( textPane.getHighlighter().addHighlight(
1564                    pos, pos+w.length(), doc.autoSelectHighlighter));
1565          }
1566       }
1567
1568       searchPanel.setInfoText(""+selectedWordTags.size()+" occurence"+(selectedWordTags.size()==1?"":"s")
1569          +" of \""+StringUtils.shortFormForDisplay(w, 30)+"\"");
1570
1571       if(!searchPanel.isVisible() && selectedWordTags.size()>1)
1572       {
1573          searchPanel.setVisible(true);
1574       }
1575     }
1576     catch(Exception JavaDoc e) {
1577       e.printStackTrace();
1578     }
1579  }
1580
1581
1582  protected Object JavaDoc actualHighlightTag = null;
1583  protected void setHighlightedElementOnly(final Element lineElt)
1584  {
1585     if(actualHighlightTag!=null)
1586     {
1587       textPane.getHighlighter().removeHighlight(actualHighlightTag);
1588     }
1589
1590     if(lineElt!=null)
1591     {
1592       try
1593       {
1594         actualHighlightTag = textPane.getHighlighter().addHighlight(lineElt.getStartOffset(), lineElt.getEndOffset(),
1595            errorHighlighter);
1596       }
1597       catch(Exception JavaDoc e) { e.printStackTrace(); }
1598     }
1599  }
1600
1601
1602  public void showPopup(MouseEvent me)
1603  {
1604     JPopupMenu pop = createPopupBase(me);
1605     pop.show(textPane, me.getX(), me.getY());
1606  }
1607
1608
1609  /** Defines copy paste ops very useful to paste stacktraces
1610      from client exceptions for example...
1611  */

1612  public JPopupMenu createPopupBase(MouseEvent me)
1613  {
1614     JPopupMenu popup = new JPopupMenu("");
1615
1616     // the menu is accessed through the context menu (right click) and maybe at another location
1617
// than the caret => use the clicked point position to detect the work (if no selection)
1618
final int clickedPos = textPane.viewToModel(me.getPoint());
1619
1620     DocViewUtils.addStandardPopupDocumentActions(popup, doc, searchPanel, textPane, clickedPos);
1621
1622
1623     String JavaDoc selectedText = "";
1624     if((textPane.getSelectionEnd()-textPane.getSelectionStart())>0)
1625     {
1626       selectedText = textPane.getSelectedText();
1627     }
1628     else
1629     {
1630       // detect the word at the cursot
1631
selectedText = DocumentUtils.getWordAt(doc, clickedPos);
1632     }
1633
1634     if(selectedText!=null && selectedText.length()<1000)
1635     {
1636       final String JavaDoc fSel = selectedText;
1637       JMenuItem ht = new JMenuItem("Highlight all \""+StringUtils.shortFormForDisplay(selectedText, 70)+"\"");
1638       ht.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_K, KeyEvent.CTRL_MASK,false));
1639       popup.addSeparator();
1640       popup.add(ht);
1641       ht.addActionListener(new ActionListener()
1642       {
1643         public void actionPerformed(ActionEvent ae)
1644         {
1645            clearAutoSelectedWords();
1646            autoSelectWords(fSel);
1647         }
1648       });
1649     }
1650
1651     return popup;
1652  }
1653
1654  // edition listeners (FolderView)
1655
//
1656

1657  /** The view does no edit during the content edition.
1658     This just changes the state of the folder to "changed" to ensure later saving.
1659  */

1660  private void notifyContentEditionListeners()
1661  {
1662    // System.out.println("mailview: edited");
1663
contentHasChanged = true;
1664
1665    if(message!=null)
1666    {
1667      message.notifyThatThisMessageIsBeingEditedNow("content edited in the view");
1668    }
1669  }
1670
1671} // MailView
Popular Tags