KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > suberic > pooka > gui > NewMessageDisplayPanel


1 package net.suberic.pooka.gui;
2 import net.suberic.pooka.*;
3 import net.suberic.util.gui.*;
4 import net.suberic.util.swing.EntryTextArea;
5 import net.suberic.pooka.gui.crypto.*;
6
7 import javax.mail.*;
8 import javax.mail.internet.*;
9 import java.awt.*;
10 import java.awt.event.*;
11 import javax.swing.*;
12 import javax.swing.text.TextAction JavaDoc;
13 import java.util.*;
14 import javax.swing.text.JTextComponent JavaDoc;
15 import javax.swing.event.*;
16 import java.io.File JavaDoc;
17 import javax.swing.plaf.metal.*;
18 import javax.swing.plaf.*;
19
20 /**
21  * A window for entering new messages.
22  */

23 public class NewMessageDisplayPanel extends MessageDisplayPanel implements ItemListener {
24
25   JTabbedPane tabbedPane = null;
26   Container headerPanel = null;
27   boolean modified = false;
28   Hashtable inputTable;
29
30   JScrollPane headerScrollPane;
31
32   private Action JavaDoc[] defaultActions;
33
34   CryptoStatusDisplay cryptoDisplay = null;
35   Container cryptoPanel = null;
36
37   Container customHeaderPane = null;
38   JTable customHeaderTable = null;
39   JToggleButton customHeaderButton = null;
40
41   /**
42    * Creates a NewMessageDisplayPanel from the given Message.
43    */

44
45   public NewMessageDisplayPanel(NewMessageUI newMsgUI) {
46     super(newMsgUI);
47   }
48
49   /**
50    * This configures the MessageDisplayPanel. This means that here is
51    * where we create the headerPanel and editorPane and add them to the
52    * splitPane.
53    */

54   public void configureMessageDisplay() throws MessagingException {
55
56     splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
57     tabbedPane = new JTabbedPane();
58
59     inputTable = new Hashtable();
60
61     headerPanel = createHeaderInputPanel(getMessageProxy(), inputTable);
62     editorPane = createMessagePanel(getMessageProxy());
63
64     installTransferHandler();
65
66     // workaround for java bug.
67
editorPane.addPropertyChangeListener(new java.beans.PropertyChangeListener JavaDoc() {
68         public void propertyChange(java.beans.PropertyChangeEvent JavaDoc evt) {
69           String JavaDoc propertyName = evt.getPropertyName();
70           if (propertyName != null && propertyName.equalsIgnoreCase("ui")) {
71             installTransferHandler();
72           }
73         }
74       });
75
76
77     headerScrollPane = new JScrollPane(headerPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
78     tabbedPane.add(Pooka.getProperty("MessageWindow.HeaderTab", "Headers"), headerScrollPane);
79
80     if (getMessageProxy().getAttachments() != null && getMessageProxy().getAttachments().size() > 0) {
81       addAttachmentPane();
82     }
83
84     editorScrollPane = new JScrollPane(editorPane, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
85
86     splitPane.setTopComponent(tabbedPane);
87     splitPane.setBottomComponent(editorScrollPane);
88
89     this.add("Center", splitPane);
90
91     editorPane.addMouseListener(new MouseAdapter() {
92
93         public void mousePressed(MouseEvent e) {
94           if (e.isPopupTrigger()) {
95             showPopupMenu(editorPane, e);
96           }
97         }
98
99         public void mouseReleased(MouseEvent e) {
100           if (e.isPopupTrigger()) {
101             showPopupMenu(editorPane, e);
102           }
103         }
104       });
105
106     editorPane.addKeyListener(new KeyAdapter() {
107         public void keyTyped(KeyEvent e) {
108           setModified(true);
109         }
110       });
111
112     splitPane.resetToPreferredSizes();
113
114     this.addFocusListener(new FocusAdapter() {
115         public void focusGained(FocusEvent e) {
116           // if we get focus, see what we want to select by default.
117
// if there's no to: done, select to:. if there's no
118
// subject, select it. if both of those are filled out,
119
// select the message.
120

121           Component JavaDoc subjectComponent = null;
122           Component JavaDoc toComponent = null;
123
124           boolean done = false;
125
126           if (inputTable != null) {
127             String JavaDoc key;
128             Enumeration keys = inputTable.keys();
129             while (keys.hasMoreElements()) {
130               key = (String JavaDoc)(keys.nextElement());
131
132               if (key.equalsIgnoreCase("subject")) {
133                 subjectComponent = (Component JavaDoc) inputTable.get(key);
134               } else if (key.equalsIgnoreCase("to")) {
135                 toComponent = (Component JavaDoc) inputTable.get(key);
136               }
137             }
138
139             if (toComponent != null && toComponent instanceof JTextComponent JavaDoc) {
140               String JavaDoc toValue = ((JTextComponent JavaDoc) toComponent).getText();
141               if (toValue == null || toValue.length() == 0) {
142                 done = true;
143                 toComponent.requestFocusInWindow();
144               }
145             }
146
147             if (! done && subjectComponent != null && subjectComponent instanceof JTextComponent JavaDoc) {
148               String JavaDoc subjectValue = ((JTextComponent JavaDoc) subjectComponent).getText();
149               if (subjectValue == null || subjectValue.length() == 0) {
150                 done = true;
151                 subjectComponent.requestFocusInWindow();
152               }
153             }
154           }
155
156           if (! done) {
157             if (editorPane != null)
158               editorPane.requestFocusInWindow();
159           }
160         }
161       });
162
163     keyBindings = new ConfigurableKeyBinding(this, "NewMessageWindow.keyBindings", Pooka.getResources());
164     //keyBindings.setCondition(JComponent.WHEN_IN_FOCUSED_WINDOW);
165

166     keyBindings.setActive(getActions());
167
168   }
169
170   /**
171    * Sets the window to its preferred size.
172    */

173   public void sizeToDefault() {
174     Dimension prefSize = getDefaultEditorPaneSize();
175     JScrollBar vsb = editorScrollPane.getVerticalScrollBar();
176     if (vsb != null)
177       prefSize.setSize(prefSize.getWidth() + vsb.getPreferredSize().getWidth(), prefSize.getHeight());
178     editorScrollPane.setPreferredSize(prefSize);
179     int width = prefSize.width;
180     this.setPreferredSize(new Dimension(width, width));
181     this.setSize(this.getPreferredSize());
182   }
183
184   /**
185    * as defined in java.awt.event.ItemListener
186    *
187    * This implementation calls a refreshCurrentUser() on the MainPanel.
188    *
189    * It also updates the panel's interface style.
190    */

191   public void itemStateChanged(ItemEvent ie) {
192     if (ie.getStateChange() == ItemEvent.SELECTED) {
193       if (Pooka.getMainPanel() != null)
194         Pooka.getMainPanel().refreshCurrentUser();
195       SwingUtilities.invokeLater(new Runnable JavaDoc() {
196           public void run() {
197             NewMessageUI nmui = getNewMessageUI();
198             if (nmui instanceof net.suberic.util.swing.ThemeSupporter) {
199               try {
200                 Pooka.getUIFactory().getPookaThemeManager().updateUI((net.suberic.util.swing.ThemeSupporter) nmui, (java.awt.Component JavaDoc) nmui);
201                 Font currentFont = editorPane.getFont();
202                 setDefaultFont(editorPane);
203                 Font newFont = editorPane.getFont();
204                 if (currentFont != newFont) {
205                   sizeToDefault();
206                 }
207                 MessageUI mui = getMessageUI();
208                 if (mui instanceof MessageInternalFrame) {
209                   ((MessageInternalFrame) mui).resizeByWidth();
210                 } else if (mui instanceof MessageFrame) {
211                   ((MessageFrame) mui).resizeByWidth();
212                 }
213
214               } catch (Exception JavaDoc e) {
215                 if (Pooka.isDebug())
216                   System.out.println("error setting theme: " + e);
217               }
218             }
219           }
220         });
221     }
222
223   }
224
225   /**
226    * Creates the panel in which the addressing will be done, such as
227    * the To: field, Subject: field, etc.
228    */

229   public Container createHeaderInputPanel(MessageProxy pProxy, Hashtable proptDict) {
230
231     Box inputPanel = new Box(BoxLayout.Y_AXIS);
232
233     Box inputRow = new Box(BoxLayout.X_AXIS);
234
235     // Create UserProfile DropDown
236
JLabel userProfileLabel = new JLabel(Pooka.getProperty("UserProfile.label","User:"), SwingConstants.RIGHT);
237     userProfileLabel.setPreferredSize(new Dimension(75,userProfileLabel.getPreferredSize().height));
238     JComboBox profileCombo = new JComboBox(new Vector(Pooka.getPookaManager().getUserProfileManager().getUserProfileList()));
239
240
241     IconManager iconManager = Pooka.getUIFactory().getIconManager();
242
243     ImageIcon headerIcon = iconManager.getIcon(Pooka.getProperty("NewMessage.customHeader.button", "Hammer"));
244     if (headerIcon != null) {
245       java.awt.Image JavaDoc headerImage = headerIcon.getImage();
246       headerImage = headerImage.getScaledInstance(15, 15, java.awt.Image.SCALE_SMOOTH);
247       headerIcon.setImage(headerImage);
248       customHeaderButton = new JToggleButton(headerIcon);
249       customHeaderButton.setMargin(new java.awt.Insets JavaDoc(1,1,1,1));
250       customHeaderButton.setSize(15,15);
251     } else {
252       customHeaderButton = new JToggleButton();
253     }
254
255     customHeaderButton.addChangeListener(new ChangeListener() {
256
257         public void stateChanged(ChangeEvent e) {
258           if (customHeaderButton.isSelected()) {
259             selectCustomHeaderPane();
260           } else {
261             removeCustomHeaderPane();
262           }
263         }
264
265       });
266
267     customHeaderButton.setToolTipText(Pooka.getProperty("NewMessage.customHeaders.button.Tooltip", "Edit Headers"));
268
269     inputRow.add(userProfileLabel);
270     inputRow.add(profileCombo);
271     inputRow.add(customHeaderButton);
272
273     UserProfile selectedProfile = null;
274     selectedProfile = pProxy.getDefaultProfile();
275     if (selectedProfile == null)
276       if (Pooka.getMainPanel() != null)
277         selectedProfile = Pooka.getMainPanel().getCurrentUser();
278
279     if (selectedProfile == null)
280       selectedProfile = Pooka.getPookaManager().getUserProfileManager().getDefaultProfile();
281
282     if (selectedProfile != null)
283       profileCombo.setSelectedItem(selectedProfile);
284
285     profileCombo.addItemListener(this);
286
287     proptDict.put("UserProfile", profileCombo);
288
289     inputPanel.add(inputRow);
290
291     // Create Address panel
292

293     StringTokenizer tokens = new StringTokenizer(Pooka.getProperty("MessageWindow.Input.DefaultFields", "To:CC:BCC:Subject"), ":");
294     String JavaDoc currentHeader = null;
295     JLabel hdrLabel = null;
296     EntryTextArea inputField = null;
297
298     while (tokens.hasMoreTokens()) {
299       inputRow = new Box(BoxLayout.X_AXIS);
300       currentHeader=tokens.nextToken();
301       hdrLabel = new JLabel(Pooka.getProperty("MessageWindow.Input.." + currentHeader + ".label", currentHeader) + ":", SwingConstants.RIGHT);
302       hdrLabel.setPreferredSize(new Dimension(75,hdrLabel.getPreferredSize().height));
303       inputRow.add(hdrLabel);
304
305       if (currentHeader.equalsIgnoreCase("To") || currentHeader.equalsIgnoreCase("CC") || currentHeader.equalsIgnoreCase("BCC") ) {
306         try {
307           inputField = new AddressEntryTextArea(getNewMessageUI(), getNewMessageProxy().getNewMessageInfo().getHeader(Pooka.getProperty("MessageWindow.Input." + currentHeader + ".MIMEHeader", "") , ","), 1, 30);
308         } catch (MessagingException me) {
309           inputField = new net.suberic.util.swing.EntryTextArea(1, 30);
310         }
311       } else {
312         try {
313           inputField = new net.suberic.util.swing.EntryTextArea(getNewMessageProxy().getNewMessageInfo().getHeader(Pooka.getProperty("MessageWindow.Input." + currentHeader + ".MIMEHeader", "") , ","), 1, 30);
314         } catch (MessagingException me) {
315           inputField = new net.suberic.util.swing.EntryTextArea(1, 30);
316         }
317       }
318
319       inputField.setLineWrap(true);
320       inputField.setWrapStyleWord(true);
321       inputField.setBorder(BorderFactory.createEtchedBorder());
322       inputField.addKeyListener(new KeyAdapter() {
323           public void keyTyped(KeyEvent e) {
324             setModified(true);
325           }
326         });
327
328
329       inputRow.add(inputField);
330       if (inputField instanceof AddressEntryTextArea) {
331         //int height = inputField.getPreferredSize().height;
332
JButton addressButton = ((AddressEntryTextArea)inputField).createAddressButton(10, 10);
333         inputRow.add(Box.createHorizontalGlue());
334         inputRow.add(addressButton);
335       }
336       inputPanel.add(inputRow);
337
338       proptDict.put(Pooka.getProperty("MessageWindow.Input." + currentHeader + ".value", currentHeader), inputField);
339     }
340
341     return inputPanel;
342   }
343
344   /**
345    * Extends a DefaultTableModel to make it so certain columns are not
346    * editable.
347    */

348   class CustomHeaderTableModel extends javax.swing.table.DefaultTableModel JavaDoc {
349
350     // Constructor
351
public CustomHeaderTableModel(Vector headers, int rows) {
352       super(headers,rows);
353     }
354
355     // the number of rows that have uneditable headers in it.
356
int mUneditableRows = 0;
357
358     /**
359      * Sets the number of uneditable header rows we have.
360      */

361     public void setUneditableRows(int pRows) {
362       mUneditableRows = pRows;
363     }
364
365     /**
366      * Returns the number of uneditable header rows we have.
367      */

368     public int getUneditableRows() {
369       return mUneditableRows;
370     }
371
372     /**
373      * Returns whether or not this cell it editable.
374      */

375     public boolean isCellEditable(int row, int column) {
376       if (column == 0 && row < mUneditableRows) {
377         return false;
378       } else {
379         return true;
380       }
381     }
382
383   }
384
385   /**
386    * This creates a new JTextPane for the main text part of the new
387    * message. It will also include the current text of the message.
388    */

389   public JTextPane createMessagePanel(MessageProxy pProxy) {
390     JTextPane retval = new net.suberic.util.swing.ExtendedEditorPane();
391     retval.setEditorKit(new MailEditorKit());
392
393     setDefaultFont(retval);
394
395     // see if this message already has a text part, and if so,
396
// include it.
397

398     String JavaDoc origText = ((NewMessageInfo)getMessageProxy().getMessageInfo()).getTextPart(false);
399     if (origText != null && origText.length() > 0)
400       retval.setText(origText);
401
402     UserProfile profile = getSelectedProfile();
403     if (profile.autoAddSignature) {
404       retval.setCaretPosition(retval.getDocument().getLength());
405       if (profile.signatureFirst) {
406
407       }
408       addSignature(retval);
409
410     }
411
412     return retval;
413
414   }
415
416   TransferHandler mTransferHandler = null;
417   /**
418    * Installs the TransferHandler for this component.
419    */

420   public void installTransferHandler() {
421     if (editorPane != null && mTransferHandler == null) {
422       TransferHandler defaultHandler = editorPane.getTransferHandler();
423
424       net.suberic.pooka.gui.dnd.MultipleTransferHandler multiHandler = new net.suberic.pooka.gui.dnd.MultipleTransferHandler();
425       multiHandler.addTransferHandler(defaultHandler);
426       multiHandler.addTransferHandler(new net.suberic.pooka.gui.dnd.NewMessageTransferHandler());
427       mTransferHandler = multiHandler;
428     }
429
430     if (editorPane != null)
431       editorPane.setTransferHandler(mTransferHandler);
432   }
433
434   /**
435    * This adds the current user's signature to the message at the current
436    * location of the cursor.
437    */

438   public void addSignature(JEditorPane editor) {
439     String JavaDoc sig = getSelectedProfile().getSignature();
440     if (sig != null) {
441       try {
442         editor.getDocument().insertString(editor.getCaretPosition(), sig, null);
443       } catch (javax.swing.text.BadLocationException JavaDoc ble) {
444         ;
445       }
446     }
447   }
448
449   /**
450    * This returns the values in the MesssageWindow as a set of
451    * InternetHeaders.
452    */

453   public InternetHeaders getMessageHeaders() throws MessagingException {
454     InternetHeaders returnValue = new InternetHeaders();
455     String JavaDoc key;
456
457     Enumeration keys = inputTable.keys();
458     while (keys.hasMoreElements()) {
459       key = (String JavaDoc)(keys.nextElement());
460
461       if (! key.equals("UserProfile")) {
462         String JavaDoc header = new String JavaDoc(Pooka.getProperty("MessageWindow.Header." + key + ".MIMEHeader", key));
463
464         EntryTextArea inputField = (EntryTextArea) inputTable.get(key);
465         String JavaDoc value = null;
466         if (inputField instanceof AddressEntryTextArea) {
467           value = ((AddressEntryTextArea) inputField).getParsedAddresses();
468           value = ((NewMessageInfo)getMessageProxy().getMessageInfo()).convertAddressLine(value, getSelectedProfile());
469         } else {
470           value = ((EntryTextArea)(inputTable.get(key))).getText();
471           value = value.replaceAll("\n", " ");
472         }
473
474         // don't set it if it's blank.
475
if (value != null && value.length() > 0) {
476           returnValue.setHeader(header, value);
477         }
478       }
479     }
480
481     if (customHeaderButton.isSelected()) {
482       populateCustomHeaders(returnValue);
483     } else {
484       UserProfile p = getSelectedProfile();
485       p.populateHeaders(returnValue);
486       returnValue.setHeader(Pooka.getProperty("Pooka.userProfileProperty", "X-Pooka-UserProfile"), p.getName());
487     }
488
489     return returnValue;
490   }
491
492   /**
493    * This notifies the MessageDisplayPanel that an attachment has been added
494    * at the provided index. This does not actually add an attachment,
495    * but rather should be called by the MessageProxy when an attachment
496    * has been added.
497    *
498    * If an AttachmentPane does not currently exist for this
499    * MessageDisplayPanel, this method will call addAttachmentPane() to
500    * create one.
501    */

502   public void attachmentAdded(int index) {
503     if (getAttachmentPanel() == null)
504       addAttachmentPane();
505     else
506       getAttachmentPanel().getTableModel().fireTableRowsInserted(index, index);
507   }
508
509   /**
510    * This notifies the MessageDisplayPanel that the attachment at the
511    * provided index has been removed. This does not actually remove
512    * the attachment, but rather should be called by the MessageProxy
513    * when an attachment has been removed.
514    *
515    * If this removes the last attachment, the entire AttachmentPane
516    * is removed from the MessageDisplayPanel.
517    */

518   public void attachmentRemoved(int index) {
519     try {
520       java.util.List JavaDoc attach = getNewMessageProxy().getAttachments();
521       if (attach == null || attach.size() == 0) {
522         removeAttachmentPane();
523       } else {
524         getAttachmentPanel().getTableModel().fireTableRowsDeleted(index, index);
525       }
526     } catch (MessagingException me) {
527     }
528   }
529
530   /**
531    * This creates the JComponent which shows the attachments, and then
532    * adds it to the JTabbedPane.
533    *
534    */

535   public void addAttachmentPane() {
536     attachmentPanel = new AttachmentPane(getMessageProxy());
537     attachmentDisplayPanel = new JPanel();
538     attachmentDisplayPanel.add(attachmentPanel);
539
540     NewMessageUI nmui = getNewMessageUI();
541     if (nmui instanceof net.suberic.util.swing.ThemeSupporter) {
542       try {
543         Pooka.getUIFactory().getPookaThemeManager().updateUI((net.suberic.util.swing.ThemeSupporter) nmui, attachmentDisplayPanel, true);
544       } catch (Exception JavaDoc e) {
545         if (Pooka.isDebug())
546           System.out.println("error setting theme: " + e);
547       }
548     }
549     tabbedPane.add(attachmentDisplayPanel, Pooka.getProperty("MessageWindow.AttachmentTab", "Attachments"), 1);
550   }
551
552   /**
553    * This creates the JComponent which shows the encryption status, and then
554    * adds it to the JTabbedPane.
555    *
556    */

557   public void addEncryptionPane() {
558     cryptoPanel = new JPanel();
559     NewMessageCryptoDisplay nmcd = new NewMessageCryptoDisplay(getNewMessageProxy());
560     cryptoDisplay = nmcd;
561
562     cryptoPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
563     cryptoPanel.setSize(headerPanel.getSize());
564
565     ((JPanel)cryptoPanel).setBorder(BorderFactory.createEtchedBorder());
566
567     cryptoPanel.add(nmcd);
568
569     tabbedPane.add(Pooka.getProperty("MessageWindow.EncryptionTab", "Encryption"), cryptoPanel);
570   }
571
572   /**
573    * Creates a new CustomHeaderPane.
574    */

575   public Container createCustomHeaderPane() {
576
577     JPanel returnValue = new JPanel();
578     returnValue.setLayout(new BorderLayout());
579
580     Box customInputPanel = new Box(BoxLayout.Y_AXIS);
581
582     Vector headerNames = new Vector();
583     headerNames.add(Pooka.getProperty("NewMessage.customHeaders.header", "Header"));
584     headerNames.add(Pooka.getProperty("NewMessage.customHeaders.value", "Value"));
585
586     CustomHeaderTableModel dtm = new CustomHeaderTableModel(headerNames, 4);
587
588     customHeaderTable = new JTable(dtm);
589
590     // get the preconfigured properties
591

592     Properties headers = new Properties();
593
594     Properties mailProperties = getSelectedProfile().getMailProperties();
595     Enumeration keys = mailProperties.propertyNames();
596
597     String JavaDoc fromAddr = null, fromPersonal = null, replyAddr = null, replyPersonal = null;
598
599     // we want to put From and Reply-To first.
600
java.util.List JavaDoc otherProps = new ArrayList();
601
602     while (keys.hasMoreElements()) {
603       String JavaDoc key = (String JavaDoc)(keys.nextElement());
604
605       if (key.equals("FromPersonal")) {
606         fromPersonal = mailProperties.getProperty(key);
607       } else if (key.equals("From")) {
608         fromAddr = mailProperties.getProperty(key);
609       } else if (key.equals("ReplyTo")) {
610         replyAddr = mailProperties.getProperty(key);
611       } else if (key.equals("ReplyToPersonal")) {
612         replyPersonal = mailProperties.getProperty(key);
613       } else {
614         otherProps.add(key);
615       }
616     }
617
618     try {
619       if (fromAddr != null) {
620         if (fromPersonal != null && !(fromPersonal.equals("")))
621           headers.setProperty("From", new InternetAddress(fromAddr, fromPersonal).toString());
622         else
623           headers.setProperty("From", new InternetAddress(fromAddr).toString());
624       } else {
625         headers.setProperty("From", "");
626       }
627
628       if (replyAddr != null && !(replyAddr.equals(""))) {
629         if (replyPersonal != null)
630           headers.setProperty("Reply-To", new InternetAddress(replyAddr, replyPersonal).toString());
631         else
632           headers.setProperty("Reply-To", new InternetAddress(replyAddr).toString());
633       } else {
634         headers.setProperty("Reply-To", "");
635       }
636     } catch (java.io.UnsupportedEncodingException JavaDoc uee) {
637       //don't bother
638
} catch (javax.mail.MessagingException JavaDoc me) {
639       //don't bother
640
}
641
642     String JavaDoc currentHeader = null;
643     String JavaDoc currentValue = null;
644     JLabel hdrLabel = null;
645
646     javax.swing.table.DefaultTableModel JavaDoc model = (javax.swing.table.DefaultTableModel JavaDoc) customHeaderTable.getModel();
647
648     model.setValueAt("From", 0, 0);
649     model.setValueAt(headers.getProperty("From", ""), 0, 1);
650
651     model.setValueAt("Reply-To", 1, 0);
652     model.setValueAt(headers.getProperty("Reply-To", ""), 1, 1);
653
654     int row = 2;
655     Iterator it = otherProps.iterator();
656     while(it.hasNext()) {
657       currentHeader=(String JavaDoc) it.next();
658       currentValue = (String JavaDoc) headers.get(currentHeader);
659       if (currentValue == null)
660         currentValue = "";
661
662       if (model.getRowCount() <= row) {
663         model.addRow(new Vector());
664       }
665
666       model.setValueAt(currentHeader, row, 0);
667       model.setValueAt(currentValue, row, 1);
668
669       row++;
670     }
671
672     dtm.setUneditableRows(2 + otherProps.size());
673
674     customInputPanel.add(new JScrollPane(customHeaderTable));
675
676     returnValue.add(customInputPanel, BorderLayout.CENTER);
677
678     JPanel buttonPanel = new JPanel();
679     buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
680
681     IconManager iconManager = Pooka.getUIFactory().getIconManager();
682
683     ImageIcon headerIcon = iconManager.getIcon(Pooka.getProperty("NewMessage.customHeader.add.button", "Plus"));
684
685     JButton headerButton = null;
686
687     if (headerIcon != null) {
688       headerButton = new JButton(headerIcon);
689       headerButton.setMargin(new java.awt.Insets JavaDoc(0, 0, 0, 0));
690       headerButton.setSize(new java.awt.Dimension JavaDoc(10,10));
691     } else {
692       headerButton = new JButton();
693     }
694
695     headerButton.addActionListener(new AbstractAction() {
696         public void actionPerformed(ActionEvent e) {
697           javax.swing.table.DefaultTableModel JavaDoc model = (javax.swing.table.DefaultTableModel JavaDoc) customHeaderTable.getModel();
698           model.addRow(new Vector());
699         }
700       });
701
702     buttonPanel.add(new JLabel("Add Header"));
703     buttonPanel.add(headerButton);
704     buttonPanel.setBorder(BorderFactory.createEmptyBorder());
705
706     buttonPanel.setSize(buttonPanel.getMinimumSize());
707     returnValue.add(buttonPanel, BorderLayout.SOUTH);
708     return returnValue;
709
710   }
711
712   /**
713    * Populates an InternetHeaders object from the CustomHeaderPane.
714    */

715   public void populateCustomHeaders(InternetHeaders pHeaders) {
716     if (customHeaderTable.isEditing()) {
717       javax.swing.table.TableCellEditor JavaDoc tce = customHeaderTable.getCellEditor(customHeaderTable.getEditingRow(), customHeaderTable.getEditingColumn());
718       if (tce != null) {
719         tce.stopCellEditing();
720       }
721     }
722
723     int rowCount = customHeaderTable.getRowCount();
724     for (int i = 0; i < rowCount; i++) {
725       String JavaDoc header = null;
726       String JavaDoc value = null;
727       try {
728         header = (String JavaDoc) customHeaderTable.getValueAt(i, 0);
729         value = (String JavaDoc) customHeaderTable.getValueAt(i, 1);
730       } catch (ClassCastException JavaDoc cce) {
731         // ignore the header.
732
}
733
734       if (header != null && value != null && header.length() > 0 && value.length() > 0) {
735         pHeaders.setHeader(header, value);
736       }
737     }
738   }
739
740   /**
741    * Selects the custom header pane.
742    */

743   public void selectCustomHeaderPane() {
744     if (customHeaderPane == null) {
745       customHeaderPane = createCustomHeaderPane();
746       tabbedPane.add(Pooka.getProperty("MessageWindow.CustomHeaderTab", "Custom"), customHeaderPane);
747     }
748     tabbedPane.setSelectedComponent(customHeaderPane);
749   }
750
751   /**
752    * Removes the custom header pane, if any.
753    */

754   public void removeCustomHeaderPane() {
755     if (customHeaderPane != null) {
756       tabbedPane.setSelectedComponent(headerScrollPane);
757
758       tabbedPane.remove(customHeaderPane);
759     }
760     customHeaderPane = null;
761   }
762
763   /**
764    * This removes the AttachmentPane from the JTabbedPane.
765    */

766
767   public void removeAttachmentPane() {
768     if (attachmentPanel != null) {
769       tabbedPane.setSelectedComponent(headerScrollPane);
770       tabbedPane.remove(attachmentDisplayPanel);
771     }
772     attachmentPanel = null;
773     attachmentDisplayPanel = null;
774   }
775
776   /**
777    * This registers the Keyboard action not only for the FolderWindow
778    * itself, but also for pretty much all of its children, also. This
779    * is to work around something which I think is a bug in jdk 1.2.
780    * (this is not really necessary in jdk 1.3.)
781    *
782    * Overrides JComponent.registerKeyboardAction(ActionListener anAction,
783    * String aCommand, KeyStroke aKeyStroke, int aCondition)
784    */

785
786   public void registerKeyboardAction(ActionListener anAction,
787                                      String JavaDoc aCommand, KeyStroke aKeyStroke, int aCondition) {
788     super.registerKeyboardAction(anAction, aCommand, aKeyStroke, aCondition);
789
790     if (attachmentPanel != null)
791       attachmentPanel.registerKeyboardAction(anAction, aCommand, aKeyStroke, aCondition);
792     editorPane.registerKeyboardAction(anAction, aCommand, aKeyStroke, aCondition);
793     editorScrollPane.registerKeyboardAction(anAction, aCommand, aKeyStroke, aCondition);
794
795     splitPane.registerKeyboardAction(anAction, aCommand, aKeyStroke, aCondition);
796   }
797
798   /**
799    * This unregisters the Keyboard action not only for the FolderWindow
800    * itself, but also for pretty much all of its children, also. This
801    * is to work around something which I think is a bug in jdk 1.2.
802    * (this is not really necessary in jdk 1.3.)
803    *
804    * Overrides JComponent.unregisterKeyboardAction(KeyStroke aKeyStroke)
805    */

806
807   public void unregisterKeyboardAction(KeyStroke aKeyStroke) {
808     super.unregisterKeyboardAction(aKeyStroke);
809
810     if (attachmentPanel != null)
811       attachmentPanel.unregisterKeyboardAction(aKeyStroke);
812     editorPane.unregisterKeyboardAction(aKeyStroke);
813     editorScrollPane.unregisterKeyboardAction(aKeyStroke);
814     splitPane.unregisterKeyboardAction(aKeyStroke);
815   }
816
817   /**
818    * This creates and shows a PopupMenu for this component.
819    */

820   public void showPopupMenu(JComponent component, MouseEvent e) {
821     ConfigurablePopupMenu popupMenu = new ConfigurablePopupMenu();
822     popupMenu.configureComponent("NewMessageWindow.popupMenu", Pooka.getResources());
823     popupMenu.setActive(getActions());
824     NewMessageUI nmui = getNewMessageUI();
825     if (nmui instanceof net.suberic.util.swing.ThemeSupporter) {
826       try {
827         Pooka.getUIFactory().getPookaThemeManager().updateUI((net.suberic.util.swing.ThemeSupporter) nmui, popupMenu, true);
828       } catch (Exception JavaDoc etwo) {
829         if (Pooka.isDebug())
830           System.out.println("error setting theme: " + e);
831       }
832     }
833     popupMenu.show(component, e.getX(), e.getY());
834
835   }
836
837   /**
838    * As specified by interface net.suberic.pooka.UserProfileContainer.
839    *
840    * This implementation returns the DefaultProfile of the associated
841    * MessageProxy if the MessageDisplayPanel is not editable. If the
842    * MessageDisplayPanel is editable, it returns the currently selected
843    * UserProfile object.
844    */

845   public UserProfile getDefaultProfile() {
846     if (isEditable())
847       return getSelectedProfile();
848     else
849       return getMessageProxy().getDefaultProfile();
850   }
851
852
853   /**
854    * This method returns the UserProfile currently selected in the
855    * drop-down menu.
856    */

857
858   public UserProfile getSelectedProfile() {
859     return (UserProfile)(((JComboBox)(inputTable.get("UserProfile"))).getSelectedItem());
860   }
861
862   /**
863    * sets the currently selected Profile.
864    */

865   public void setSelectedProfile(UserProfile newProfile) {
866     if (newProfile != null) {
867       ((JComboBox)(inputTable.get("UserProfile"))).setSelectedItem(newProfile);
868     }
869   }
870
871   /**
872    * Overrides JComponent.addNotify().
873    *
874    * We override addNotify() here to set the proper splitPane location.
875    */

876
877   public void addNotify() {
878     super.addNotify();
879     splitPane.setDividerLocation(Math.min(tabbedPane.getPreferredSize().height + 1, Integer.parseInt(Pooka.getProperty("MessageWindow.headerPanel.vsize", "500"))));
880   }
881
882   public boolean isEditable() {
883     return true;
884   }
885
886   public boolean isModified() {
887     return modified;
888   }
889
890   public void setModified(boolean mod) {
891     if (isEditable())
892       modified=mod;
893   }
894
895   /**
896    * Returns the MessageProxy as a NewMessageProxy.
897    */

898   public NewMessageProxy getNewMessageProxy() {
899     return (NewMessageProxy) getMessageProxy();
900   }
901
902   /**
903    * Returns the MessageUI as a NewMessageUI.
904    */

905   public NewMessageUI getNewMessageUI() {
906     return (NewMessageUI) getMessageUI();
907   }
908
909   /**
910    * Shows the current display of the encryption status.
911    */

912   public net.suberic.pooka.gui.crypto.CryptoStatusDisplay getCryptoStatusDisplay() {
913     if (cryptoDisplay == null) {
914       addEncryptionPane();
915     }
916
917     return cryptoDisplay;
918   }
919
920   //------- Actions ----------//
921

922   /**
923    * performTextAction grabs the focused component on the MessageDisplayPanel
924    * and, if it is a JTextComponent, tries to get it to perform the
925    * appropriate ActionEvent.
926    */

927   public void performTextAction(String JavaDoc name, ActionEvent e) {
928     Action JavaDoc[] textActions;
929
930     Component JavaDoc focusedComponent = getFocusedComponent(this);
931
932     // this is going to suck more.
933

934     if (focusedComponent != null) {
935       if (focusedComponent instanceof JTextComponent JavaDoc) {
936         JTextComponent JavaDoc fTextComp = (JTextComponent JavaDoc) focusedComponent;
937         textActions = fTextComp.getActions();
938         Action JavaDoc selectedAction = null;
939         for (int i = 0; (selectedAction == null) && i < textActions.length; i++) {
940           if (textActions[i].getValue(Action.NAME).equals(name))
941             selectedAction = textActions[i];
942         }
943
944         if (selectedAction != null) {
945           selectedAction.actionPerformed(e);
946         }
947       }
948     }
949   }
950
951   private Component JavaDoc getFocusedComponent(Container container) {
952     Component JavaDoc[] componentList = container.getComponents();
953
954     Component JavaDoc focusedComponent = null;
955
956     // this is going to suck.
957

958     for (int i = 0; (focusedComponent == null) && i < componentList.length; i++) {
959       if (componentList[i].hasFocus())
960         focusedComponent = componentList[i];
961       else if (componentList[i] instanceof Container)
962         focusedComponent=getFocusedComponent((Container)componentList[i]);
963
964     }
965
966     return focusedComponent;
967
968   }
969
970   public Hashtable getInputTable() {
971     return inputTable;
972   }
973
974   public void setInputTable(Hashtable newInputTable) {
975     inputTable = newInputTable;
976   }
977
978   public Action JavaDoc[] getActions() {
979     Action JavaDoc[] returnValue = getDefaultActions();
980
981     if (getMessageProxy().getActions() != null) {
982       if (returnValue != null) {
983         returnValue = TextAction.augmentList(getMessageProxy().getActions(), returnValue);
984       } else {
985         returnValue = getMessageProxy().getActions();
986       }
987     }
988
989     if (getEditorPane() != null && getEditorPane().getActions() != null) {
990       if (returnValue != null) {
991         returnValue = TextAction.augmentList(getEditorPane().getActions(), returnValue);
992       } else {
993         returnValue = getEditorPane().getActions();
994       }
995     }
996
997     return returnValue;
998   }
999
1000  /**
1001   * Sets this editor as enabled or disabled.
1002   */

1003  public void setEnabled(boolean enabled) {
1004    super.setEnabled(enabled);
1005    getEditorPane().setEnabled(enabled);
1006  }
1007
1008  public Action JavaDoc[] getDefaultActions() {
1009    return defaultActions;
1010  }
1011
1012  private void createDefaultActions() {
1013    // The actions supported by the window itself.
1014

1015    /*defaultActions = new Action[] {
1016      new CloseAction(),
1017      new CutAction(),
1018      new CopyAction(),
1019      new PasteAction(),
1020      new TestAction()
1021      };*/

1022
1023    defaultActions = new Action JavaDoc[] {
1024      new AddSignatureAction(),
1025      new EditorPanelAction(),
1026      new AttachmentPanelAction(),
1027      new TestAction()
1028    };
1029  }
1030
1031  //-----------actions----------------
1032

1033  class AddSignatureAction extends AbstractAction {
1034
1035    AddSignatureAction() {
1036      super("message-add-signature");
1037    }
1038
1039    public void actionPerformed(ActionEvent e) {
1040      addSignature(editorPane);
1041    }
1042  }
1043
1044  class CutAction extends AbstractAction {
1045
1046    CutAction() {
1047      super("cut-to-clipboard");
1048    }
1049
1050    public void actionPerformed(ActionEvent e) {
1051      performTextAction((String JavaDoc)getValue(Action.NAME), e);
1052    }
1053  }
1054
1055  class CopyAction extends AbstractAction {
1056
1057    CopyAction() {
1058      super("copy-to-clipboard");
1059    }
1060
1061    public void actionPerformed(ActionEvent e) {
1062      performTextAction((String JavaDoc)getValue(Action.NAME), e);
1063    }
1064  }
1065
1066  class PasteAction extends AbstractAction {
1067
1068    PasteAction() {
1069      super("paste-from-clipboard");
1070    }
1071
1072    public void actionPerformed(ActionEvent e) {
1073      performTextAction((String JavaDoc)getValue(Action.NAME), e);
1074    }
1075  }
1076
1077  class TestAction extends AbstractAction {
1078
1079    TestAction() {
1080      super("test");
1081    }
1082
1083    public void actionPerformed(ActionEvent e) {
1084      System.out.println(net.suberic.pooka.MailUtilities.wrapText(getMessageText()));
1085    }
1086  }
1087
1088  /**
1089   * Selects the Attachment panel.
1090   */

1091  public class AttachmentPanelAction extends AbstractAction {
1092    AttachmentPanelAction() {
1093      super("message-select-attachment");
1094    }
1095
1096    public void actionPerformed(ActionEvent e) {
1097      if (attachmentPanel != null) {
1098        tabbedPane.setSelectedComponent(attachmentDisplayPanel);
1099        attachmentPanel.requestFocusInWindow();
1100      }
1101    }
1102  }
1103
1104  /**
1105   * Selects the Editor panel.
1106   */

1107  public class EditorPanelAction extends AbstractAction {
1108    EditorPanelAction() {
1109      super("message-select-editor");
1110    }
1111
1112    public void actionPerformed(ActionEvent e) {
1113      tabbedPane.setSelectedComponent(headerScrollPane);
1114    }
1115  }
1116
1117  /**
1118   * Creates a new CustomHeaderEditorPane if there is not one alrady, and
1119   * then selects it.
1120   */

1121  public class CustomHeaderPanelAction extends AbstractAction {
1122    CustomHeaderPanelAction() {
1123      super("message-custom-headers");
1124    }
1125
1126    public void actionPerformed(ActionEvent e) {
1127      customHeaderButton.setSelected(true);
1128    }
1129  }
1130
1131}
1132
1133
1134
1135
1136
1137
Popular Tags