KickJava   Java API By Example, From Geeks To Geeks.

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


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.util.swing.*;
6 import javax.swing.plaf.metal.MetalTheme JavaDoc;
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
18 /**
19  * A window for entering new messages.
20  */

21 public class NewMessageInternalFrame extends MessageInternalFrame implements NewMessageUI {
22
23   public boolean firstShow = true;
24
25   /**
26    * Creates a NewMessageInternalFrame from the given Message.
27    */

28   public NewMessageInternalFrame(MessagePanel newParentContainer, NewMessageProxy newMsgProxy) {
29     super(newParentContainer, newMsgProxy);
30
31     configureMessageInternalFrame();
32
33     /*
34       this.addFocusListener(new FocusAdapter() {
35       public void focusGained(FocusEvent e) {
36       if (getMessageDisplay() != null)
37       getMessageDisplay().requestFocusInWindow();
38       }
39       });
40     */

41
42     FocusTraversalPolicy ftp = new LayoutFocusTraversalPolicy() {
43         public Component JavaDoc getInitialComponent(JInternalFrame jif) {
44           if (jif instanceof MessageInternalFrame) {
45             return ((MessageInternalFrame) jif).getMessageDisplay();
46           }
47
48           return super.getInitialComponent(jif);
49         }
50       };
51     this.setFocusTraversalPolicy(ftp);
52
53     this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
54     this.addInternalFrameListener(new InternalFrameAdapter() {
55         public void internalFrameClosing(InternalFrameEvent ife) {
56           handleClose();
57         }
58       });
59   }
60
61   public NewMessageInternalFrame(MessagePanel newParentContainer, NewMessageFrame source) {
62     parentContainer = newParentContainer;
63     messageDisplay = source.getMessageDisplay();
64     messageDisplay.setMessageUI(this);
65     msg = source.getMessageProxy();
66     toolbar = source.getToolbar();
67     keyBindings = source.getKeyBindings();
68
69     this.getContentPane().add("North", toolbar);
70     this.getContentPane().add("Center", messageDisplay);
71
72     toolbar.setActive(this.getActions());
73
74     Point loc = source.getLocationOnScreen();
75     SwingUtilities.convertPointFromScreen(loc, parentContainer);
76     this.setLocation(loc);
77
78     configureInterfaceStyle();
79
80     this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
81     this.addInternalFrameListener(new InternalFrameAdapter() {
82         public void internalFrameClosing(InternalFrameEvent ife) {
83           handleClose();
84         }
85       });
86
87   }
88
89   /**
90    * This configures the MessageInternalFrame. This means that here is
91    * where we create the headerPanel and editorPane and add them to the
92    * splitPane.
93    */

94   protected void configureMessageInternalFrame() {
95
96     try {
97       this.createDefaultActions();
98
99       this.setTitle(Pooka.getProperty("Pooka.messageWindow.messageTitle.newMessage", "New Message"));
100
101       messageDisplay = new NewMessageDisplayPanel(this);
102       messageDisplay.configureMessageDisplay();
103
104       toolbar = new ConfigurableToolbar("NewMessageWindowToolbar", Pooka.getResources());
105
106       this.getContentPane().add("North", toolbar);
107       this.getContentPane().add("Center", messageDisplay);
108
109       toolbar.setActive(this.getActions());
110
111       keyBindings = new ConfigurableKeyBinding(this, "NewMessageWindow.keyBindings", Pooka.getResources());
112       keyBindings.setActive(getActions());
113     } catch (MessagingException me) {
114       showError(Pooka.getProperty("error.MessageInternalFrame.errorLoadingMessage", "Error loading Message: ") + "\n" + me.getMessage(), Pooka.getProperty("error.MessageInternalFrame.errorLoadingMessage.title", "Error loading message."));
115       me.printStackTrace();
116     }
117
118     configureInterfaceStyle();
119
120   }
121
122   /**
123    * Gets the Theme object from the ThemeManager which is appropriate
124    * for this UI.
125    */

126   public MetalTheme JavaDoc getTheme(ThemeManager tm) {
127     UserProfile up = getSelectedProfile();
128     if (up != null) {
129       String JavaDoc id = Pooka.getProperty(up.getUserProperty() + ".theme", "");
130       if (id != null && ! id.equals("")) {
131         return tm.getTheme(id);
132       }
133     }
134
135     return tm.getDefaultTheme();
136   }
137
138   /**
139    * Closes the message window. This checks to see if the underlying
140    * message is modified, and if so, pops up a dialog to make sure that
141    * you really want to close the window.
142    *
143    * Currently, saveDraft isn't implemented, so 'yes' acts as 'cancel'.
144    */

145   public void closeMessageUI() {
146     try {
147       this.setClosed(true);
148     } catch (java.beans.PropertyVetoException JavaDoc e) {
149     }
150
151   }
152
153   /**
154    * Handles what happens when someone tries to close this window.
155    */

156   private void handleClose() {
157     // first, make sure this is still a valid NewMessageUI.
158
NewMessageProxy nmp = (NewMessageProxy)getMessageProxy();
159     if (nmp == null || nmp.getNewMessageUI() != this) {
160       setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
161     } else {
162       setDefaultCloseOperation(JInternalFrame.DO_NOTHING_ON_CLOSE);
163       if (((NewMessageProxy)getMessageProxy()).promptForClose()) {
164         int saveDraft = promptSaveDraft();
165         switch (saveDraft) {
166         case JOptionPane.YES_OPTION:
167           ((NewMessageProxy)getMessageProxy()).saveDraft();
168           break;
169         case JOptionPane.NO_OPTION:
170           NewMessageProxy.getUnsentProxies().remove(getMessageProxy());
171           setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
172         default:
173           return;
174         }
175       } else {
176         NewMessageProxy.getUnsentProxies().remove(getMessageProxy());
177         setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
178       }
179
180     }
181   }
182
183   /**
184    * Prompts the user to see if she wants to save this message as a draft.
185    *
186    * If the message is not modified, returns JOptionPane.NO_OPTION.
187    */

188   public int promptSaveDraft() {
189     if (isModified()) {
190       return showConfirmDialog(Pooka.getProperty("error.saveDraft.message", "This message has unsaved changes. Would you like to save a draft copy?"), Pooka.getProperty("error.saveDraft.title", "Save Draft"), JOptionPane.YES_NO_CANCEL_OPTION);
191     } else {
192       return JOptionPane.NO_OPTION;
193     }
194
195   }
196
197   public void detachWindow() {
198     NewMessageFrame nmf = new NewMessageFrame(this);
199
200     getMessageProxy().setMessageUI(nmf);
201
202     nmf.setVisible(true);
203     try {
204       this.setClosed(true);
205     } catch (java.beans.PropertyVetoException JavaDoc pve) {
206     }
207   }
208
209   /**
210    * This returns the values in the MesssageWindow as a set of
211    * InternetHeaders.
212    */

213   public InternetHeaders getMessageHeaders() throws MessagingException {
214     return getNewMessageDisplay().getMessageHeaders();
215   }
216
217   /**
218    * This registers the Keyboard action not only for the FolderWindow
219    * itself, but also for pretty much all of its children, also. This
220    * is to work around something which I think is a bug in jdk 1.2.
221    * (this is not really necessary in jdk 1.3.)
222    *
223    * Overrides JComponent.registerKeyboardAction(ActionListener anAction,
224    * String aCommand, KeyStroke aKeyStroke, int aCondition)
225    */

226
227   public void registerKeyboardAction(ActionListener anAction,
228                                      String JavaDoc aCommand, KeyStroke aKeyStroke, int aCondition) {
229     if (messageDisplay != null)
230       messageDisplay.registerKeyboardAction(anAction, aCommand, aKeyStroke, aCondition);
231     toolbar.registerKeyboardAction(anAction, aCommand, aKeyStroke, aCondition);
232   }
233
234   /**
235    * This unregisters the Keyboard action not only for the FolderWindow
236    * itself, but also for pretty much all of its children, also. This
237    * is to work around something which I think is a bug in jdk 1.2.
238    * (this is not really necessary in jdk 1.3.)
239    *
240    * Overrides JComponent.unregisterKeyboardAction(KeyStroke aKeyStroke)
241    */

242
243   public void unregisterKeyboardAction(KeyStroke aKeyStroke) {
244     if (messageDisplay != null)
245       messageDisplay.unregisterKeyboardAction(aKeyStroke);
246     toolbar.unregisterKeyboardAction(aKeyStroke);
247   }
248
249   /**
250    * This notifies the NewMessageUI that the attachment at the
251    * provided index has been removed. This does not actually remove
252    * the attachment, but rather should be called by the MessageProxy
253    * when an attachment has been removed.
254    */

255   public void attachmentRemoved(int index) {
256     getNewMessageDisplay().attachmentRemoved(index);
257   }
258
259   /**
260    * This notifies the NewMessageUI that an attachment has been added
261    * at the provided index. This does not actually add an attachment,
262    * but rather should be called by the MessageProxy when an attachment
263    * has been added.
264    */

265   public void attachmentAdded(int index) {
266     getNewMessageDisplay().attachmentAdded(index);
267   }
268
269   /**
270    * Pops up a JFileChooser and returns the results.
271    *
272    * Note: i'd like to have this working so that you can attach multiple
273    * files at once, but it seems that the JFileChooser really doesn't
274    * want to return an array with anything in it for getSelectedFiles().
275    * So for now, I'll leave the Pooka API as is, but only ever return a
276    * single entry in the File array.
277    */

278   public File JavaDoc[] getFiles(String JavaDoc title, String JavaDoc buttonText) {
279     JFileChooser jfc;
280     String JavaDoc currentDirectoryPath = Pooka.getProperty("Pooka.tmp.currentDirectory", "");
281     if (currentDirectoryPath == "")
282       jfc = new JFileChooser();
283     else
284       jfc = new JFileChooser(currentDirectoryPath);
285
286     jfc.setDialogTitle(title);
287     jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
288     jfc.setMultiSelectionEnabled(true);
289     int a = jfc.showDialog(this, buttonText);
290
291     Pooka.getResources().setProperty("Pooka.tmp.currentDirectory", jfc.getCurrentDirectory().getPath(), true);
292
293     if (a == JFileChooser.APPROVE_OPTION)
294       return jfc.getSelectedFiles();
295     else
296       return null;
297   }
298
299   /**
300    * As specified by interface net.suberic.pooka.UserProfileContainer.
301    *
302    * This implementation returns the DefaultProfile of the associated
303    * MessageProxy if the MessageInternalFrame is not editable. If the
304    * MessageInternalFrame is editable, it returns the currently selected
305    * UserProfile object.
306    */

307
308   public UserProfile getDefaultProfile() {
309     if (isEditable())
310       return getSelectedProfile();
311     else
312       return getMessageProxy().getDefaultProfile();
313   }
314
315   /**
316    * Shows an Address Selection form for the given AddressEntryTextArea.
317    */

318   public void showAddressWindow(AddressEntryTextArea aeta) {
319     JInternalFrame jif = new JInternalFrame(Pooka.getProperty("AddressBookTable.title", "Choose Address"), true, true, true, true);
320     jif.getContentPane().add(new AddressBookSelectionPanel(aeta, jif));
321     jif.pack();
322
323     getParentContainer().add(jif);
324     jif.setLocation(getParentContainer().getNewWindowLocation(jif, true));
325
326     jif.setVisible(true);
327     try {
328       jif.setSelected(true);
329     } catch (java.beans.PropertyVetoException JavaDoc pve) {
330     }
331
332   }
333
334   /**
335    * This method returns the UserProfile currently selected in the
336    * drop-down menu.
337    */

338
339   public UserProfile getSelectedProfile() {
340     return getNewMessageDisplay().getSelectedProfile();
341   }
342
343   /**
344    * sets the currently selected Profile.
345    */

346   public void setSelectedProfile(UserProfile newProfile) {
347     getNewMessageDisplay().setSelectedProfile(newProfile);
348   }
349
350   /**
351    * Shows a SendFailedDialog.
352    */

353   public SendFailedDialog showSendFailedDialog(OutgoingMailServer server, javax.mail. MessagingException JavaDoc sfe) {
354     // note that this should always be invoked on the AWTEventThread.
355
SendFailedDialog sfd = new SendFailedDialog(server, sfe);
356     sfd.configureComponent();
357     //Pooka.getUIFactory().showConfirmDialog(new Object[] { sfd }, "Error sending message", 1);
358
JOptionPane.showInternalMessageDialog((MessagePanel)Pooka.getMainPanel().getContentPanel(), new Object JavaDoc[] { sfd }, "Error sending message", JOptionPane.QUESTION_MESSAGE);
359     return sfd;
360   }
361
362   /**
363    * Overrides JComponent.addNotify().
364    *
365    * We override addNotify() here to set the proper splitPane location.
366    */

367
368   public void addNotify() {
369     super.addNotify();
370
371     if (firstShow) {
372       getMessageDisplay().sizeToDefault();
373       resizeByWidth();
374       firstShow = false;
375     }
376   }
377
378   public boolean isEditable() {
379     return true;
380   }
381
382   public boolean isModified() {
383     return getNewMessageDisplay().isModified();
384   }
385
386   public void setModified(boolean mod) {
387     getNewMessageDisplay().setModified(mod);
388   }
389
390   /**
391    * Sets this as busy or not busy.
392    */

393   public void setBusy(boolean newValue) {
394     super.setBusy(newValue);
395
396     final boolean fNewValue = newValue;
397     Runnable JavaDoc runMe = new Runnable JavaDoc() {
398         public void run() {
399           setEnabled(! fNewValue);
400         }
401       };
402
403     if (SwingUtilities.isEventDispatchThread()) {
404       runMe.run();
405     } else {
406       SwingUtilities.invokeLater(runMe);
407     }
408
409   }
410
411   /**
412    * Sets this editor as enabled or disabled.
413    */

414   public void setEnabled(boolean enabled) {
415     super.setEnabled(enabled);
416     toolbar.setEnabled(enabled);
417     getNewMessageDisplay().setEnabled(enabled);
418   }
419
420   public NewMessageDisplayPanel getNewMessageDisplay() {
421     return (NewMessageDisplayPanel) messageDisplay;
422   }
423
424   //------- Actions ----------//
425

426   /**
427    * performTextAction grabs the focused component on the
428    * MessageInternalFrame and, if it is a JTextComponent, tries to get it
429    * to perform the appropriate ActionEvent.
430    */

431   public void performTextAction(String JavaDoc name, ActionEvent e) {
432     getNewMessageDisplay().performTextAction(name, e);
433   }
434
435   public Action JavaDoc[] getActions() {
436     Action JavaDoc[] returnValue = getDefaultActions();
437
438     if (getMessageDisplay() != null && getMessageDisplay().getActions() != null)
439       returnValue = TextAction.augmentList(getMessageDisplay().getActions(), returnValue);
440
441     return returnValue;
442   }
443
444   public Action JavaDoc[] getDefaultActions() {
445     return defaultActions;
446   }
447
448
449   private void createDefaultActions() {
450     // The actions supported by the window itself.
451

452     /*defaultActions = new Action[] {
453       new CloseAction(),
454       new CutAction(),
455       new CopyAction(),
456       new PasteAction(),
457       new TestAction()
458       };
459
460       defaultActions = new Action[] {
461       new CloseAction(),
462       };
463     */

464   }
465
466   //-----------actions----------------
467

468
469   class CloseAction extends AbstractAction {
470
471     CloseAction() {
472       super("file-close");
473     }
474
475     public void actionPerformed(ActionEvent e) {
476       closeMessageUI();
477     }
478   }
479
480   class CutAction extends AbstractAction {
481
482     CutAction() {
483       super("cut-to-clipboard");
484     }
485
486     public void actionPerformed(ActionEvent e) {
487       performTextAction((String JavaDoc)getValue(Action.NAME), e);
488     }
489   }
490
491   class CopyAction extends AbstractAction {
492
493     CopyAction() {
494       super("copy-to-clipboard");
495     }
496
497     public void actionPerformed(ActionEvent e) {
498       performTextAction((String JavaDoc)getValue(Action.NAME), e);
499     }
500   }
501
502   class PasteAction extends AbstractAction {
503
504     PasteAction() {
505       super("paste-from-clipboard");
506     }
507
508     public void actionPerformed(ActionEvent e) {
509       performTextAction((String JavaDoc)getValue(Action.NAME), e);
510     }
511   }
512
513   class TestAction extends AbstractAction {
514
515     TestAction() {
516       super("test");
517     }
518
519     public void actionPerformed(ActionEvent e) {
520       System.out.println(net.suberic.pooka.MailUtilities.wrapText(getMessageText()));
521     }
522   }
523
524 }
525
526
527
528
529
530
Popular Tags