001: //The contents of this file are subject to the Mozilla Public License Version 1.1
002: //(the "License"); you may not use this file except in compliance with the
003: //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
004: //
005: //Software distributed under the License is distributed on an "AS IS" basis,
006: //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
007: //for the specific language governing rights and
008: //limitations under the License.
009: //
010: //The Original Code is "The Columba Project"
011: //
012: //The Initial Developers of the Original Code are Frederik Dietz and Timo
013: // Stich.
014: //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
015: //
016: //All Rights Reserved.
017: package org.columba.mail.gui.message;
018:
019: import java.awt.BorderLayout;
020: import java.awt.Color;
021: import java.awt.event.ComponentEvent;
022: import java.awt.event.ComponentListener;
023:
024: import javax.swing.BorderFactory;
025: import javax.swing.JComponent;
026: import javax.swing.JPanel;
027: import javax.swing.UIManager;
028: import javax.swing.border.Border;
029: import javax.swing.border.LineBorder;
030: import javax.swing.event.EventListenerList;
031:
032: import org.columba.core.charset.CharsetEvent;
033: import org.columba.core.charset.CharsetListener;
034: import org.columba.core.charset.CharsetOwnerInterface;
035: import org.columba.core.command.CommandCancelledException;
036: import org.columba.core.command.CommandProcessor;
037: import org.columba.core.gui.menu.ExtendablePopupMenu;
038: import org.columba.core.xml.XmlElement;
039: import org.columba.mail.command.IMailFolderCommandReference;
040: import org.columba.mail.command.MailFolderCommandReference;
041: import org.columba.mail.config.MailConfig;
042: import org.columba.mail.folder.IMailbox;
043: import org.columba.mail.gui.frame.MailFrameMediator;
044: import org.columba.mail.gui.message.command.ViewMessageCommand;
045: import org.columba.mail.gui.message.filter.PGPMessageFilter;
046: import org.columba.mail.gui.message.viewer.HeaderViewer;
047: import org.columba.mail.gui.message.viewer.MessageBorder;
048: import org.columba.mail.gui.message.viewer.SecurityStatusViewer;
049: import org.columba.mail.gui.message.viewer.SpamStatusViewer;
050: import org.columba.mail.gui.message.viewer.TextViewer;
051: import org.columba.ristretto.message.MimePart;
052: import org.columba.ristretto.message.MimeTree;
053: import org.columba.ristretto.message.MimeType;
054:
055: /**
056: * Shows the message. This includes message headers, body text, attachments and
057: * status.
058: */
059: public class MessageController extends JPanel implements
060: CharsetListener, IMessageController {
061:
062: private MailFrameMediator frameController;
063:
064: private SecurityStatusViewer securityStatusViewer;
065:
066: private TextViewer bodytextViewer;
067:
068: private SpamStatusViewer spamStatusViewer;
069:
070: private HeaderViewer headerController;
071:
072: private PGPMessageFilter pgpFilter;
073:
074: private ExtendablePopupMenu menu;
075:
076: private IMailbox folder;
077:
078: private Object uid;
079:
080: protected EventListenerList listenerList = new EventListenerList();
081:
082: public MessageController(MailFrameMediator frameMediator) {
083: this .frameController = frameMediator;
084:
085: Border outterBorder = BorderFactory.createCompoundBorder(
086: BorderFactory.createEmptyBorder(5, 5, 5, 5),
087: new MessageBorder(Color.LIGHT_GRAY, 1, true));
088: Border innerBorder = BorderFactory.createCompoundBorder(
089: outterBorder, new LineBorder(Color.WHITE, 5, true));
090:
091: setBorder(innerBorder);
092:
093: initComponents();
094:
095: layoutComponents();
096:
097: ((CharsetOwnerInterface) getFrameController())
098: .addCharsetListener(this );
099:
100: addComponentListener(new ComponentListener() {
101:
102: public void componentHidden(ComponentEvent e) {
103: }
104:
105: public void componentMoved(ComponentEvent e) {
106: }
107:
108: public void componentResized(ComponentEvent e) {
109: try {
110: if (getSelectedMessageId() != null) {
111: updateGUI();
112: repaint();
113: }
114:
115: } catch (Exception e1) {
116: e1.printStackTrace();
117: }
118: }
119:
120: public void componentShown(ComponentEvent e) {
121: }
122:
123: });
124: }
125:
126: private void initComponents() {
127: spamStatusViewer = new SpamStatusViewer(this );
128: bodytextViewer = new TextViewer(this );
129: securityStatusViewer = new SecurityStatusViewer();
130: headerController = new HeaderViewer(this , securityStatusViewer,
131: spamStatusViewer);
132:
133: pgpFilter = new PGPMessageFilter(getFrameController(), this );
134: pgpFilter.addSecurityStatusListener(securityStatusViewer);
135:
136: }
137:
138: private void layoutComponents() {
139:
140: Color backgroundColor = UIManager
141: .getColor("TextField.background");
142:
143: setLayout(new BorderLayout());
144:
145: JPanel top = new JPanel();
146: top.setBackground(backgroundColor);
147: top.setLayout(new BorderLayout());
148:
149: if (spamStatusViewer.isVisible())
150: top.add(spamStatusViewer.getView(), BorderLayout.NORTH);
151:
152: top.add(headerController, BorderLayout.CENTER);
153:
154: add(top, BorderLayout.NORTH);
155:
156: // JPanel bottom = new JPanel();
157: // bottom.setBackground(backgroundColor);
158: //
159: // bottom.setLayout(new BorderLayout());
160:
161: JComponent c = bodytextViewer.getView();
162: c.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
163: c.setBackground(backgroundColor);
164: // bottom.add(c, BorderLayout.CENTER);
165:
166: add(c, BorderLayout.CENTER);
167: }
168:
169: public void clear() {
170: // TODO implement clear()
171:
172: }
173:
174: /**
175: * @param folder
176: * @param uid
177: * @return
178: * @throws Exception
179: * @see org.columba.mail.gui.message.IMessageController#filterMessage(org.columba.mail.folder.IMailbox,
180: * java.lang.Object)
181: */
182: public IMailFolderCommandReference filterMessage(IMailbox folder,
183: Object uid) throws Exception {
184: return pgpFilter.filter(folder, uid);
185: }
186:
187: /**
188: * Returns the mailFrameController.
189: *
190: * @return MailFrameController
191: */
192: public MailFrameMediator getFrameController() {
193: return frameController;
194: }
195:
196: /**
197: * @param e
198: * @see org.columba.core.util.CharsetListener#charsetChanged(org.columba.core.util.CharsetEvent)
199: */
200: public void charsetChanged(CharsetEvent e) {
201: CommandProcessor.getInstance().addOp(
202: new ViewMessageCommand(getFrameController(),
203: ((MailFrameMediator) getFrameController())
204: .getTableSelection()));
205: }
206:
207: /** *********************************************************************** */
208:
209: /**
210: * Show message in messages viewer. Should be called in
211: * <code>Command.execute()</code> or in another background thread.
212: *
213: * @param folder
214: * selected folder
215: * @param uid
216: * selected message UID
217: * @throws Exception
218: */
219: public void showMessage(IMailbox folder, Object uid)
220: throws Exception {
221: this .folder = folder;
222: this .uid = uid;
223:
224: // if necessary decrypt/verify message
225: IMailFolderCommandReference newRefs = filterMessage(folder, uid);
226:
227: // map to new reference
228: if (newRefs != null) {
229: folder = (IMailbox) newRefs.getSourceFolder();
230: uid = newRefs.getUids()[0];
231: }
232:
233: MimeTree mimePartTree = folder.getMimePartTree(uid);
234: if (mimePartTree == null)
235: throw new CommandCancelledException(
236: "Message does not exist anymore.");
237:
238: MimePart mp = chooseBodyPart(mimePartTree);
239: if (mp != null)
240: bodytextViewer.view(folder, uid, mp.getAddress(), this
241: .getFrameController());
242:
243: spamStatusViewer.view(folder, uid, this .getFrameController());
244: securityStatusViewer.view(folder, uid, this
245: .getFrameController());
246:
247: headerController.view(folder, uid, this .getFrameController());
248:
249: // notify all interested listeners
250: fireMessageSelectionChangedEvent(folder, uid.toString());
251: }
252:
253: /**
254: * Revalidate message viewer components.
255: * <p>
256: * Call this method after showMessage() to force a repaint():
257: * @throws Exception
258: *
259: */
260: public void updateGUI() throws Exception {
261:
262: bodytextViewer.updateGUI();
263:
264: spamStatusViewer.updateGUI();
265: securityStatusViewer.updateGUI();
266:
267: headerController.updateGUI();
268:
269: }
270:
271: /**
272: * @see org.columba.mail.gui.message.IMessageController#getSelectedReference()
273: */
274: public IMailFolderCommandReference getSelectedReference() {
275: return new MailFolderCommandReference(folder,
276: new Object[] { uid });
277: }
278:
279: public JComponent getView() {
280: return this ;
281: }
282:
283: /**
284: * @see org.columba.mail.gui.message.IMessageController#getSelectedText()
285: */
286: public String getSelectedText() {
287: return bodytextViewer.getSelectedText();
288: }
289:
290: /**
291: * @see org.columba.mail.gui.message.IMessageController#getText()
292: */
293: public String getText() {
294: return bodytextViewer.getText();
295: }
296:
297: public IMailbox getSelectedFolder() {
298: return folder;
299: }
300:
301: public Object getSelectedMessageId() {
302: return uid;
303: }
304:
305: private MimePart chooseBodyPart(MimeTree mimePartTree) {
306: MimePart bodyPart = null;
307:
308: XmlElement html = MailConfig.getInstance()
309: .getMainFrameOptionsConfig().getRoot().getElement(
310: "/options/html");
311:
312: // ensure that there is an HTML part in the email, otherwise JTextPanel
313: // throws a RuntimeException
314:
315: // Which Bodypart shall be shown? (html/plain)
316: if ((Boolean.valueOf(html.getAttribute("prefer"))
317: .booleanValue())
318: && hasHtmlPart(mimePartTree.getRootMimeNode())) {
319: bodyPart = mimePartTree.getFirstTextPart("html");
320: } else {
321: bodyPart = mimePartTree.getFirstTextPart("plain");
322: }
323:
324: return bodyPart;
325:
326: }
327:
328: private boolean hasHtmlPart(MimePart mimeTypes) {
329:
330: if (mimeTypes.getHeader().getMimeType().equals(
331: new MimeType("text", "plain")))
332: return true; // exit immediately
333:
334: java.util.List children = mimeTypes.getChilds();
335:
336: for (int i = 0; i < children.size(); i++) {
337: if (hasHtmlPart(mimeTypes.getChild(i)))
338: return true;
339: }
340:
341: return false;
342:
343: }
344:
345: /**
346: * @see org.columba.mail.gui.message.IMessageController#setCaretPosition(int)
347: */
348: public void setCaretPosition(int position) {
349: bodytextViewer.setCaretPosition(position);
350: }
351:
352: /**
353: * @see org.columba.mail.gui.message.IMessageController#moveCaretPosition(int)
354: */
355: public void moveCaretPosition(int position) {
356: bodytextViewer.moveCaretPosition(position);
357: }
358:
359: public void addMessageSelectionListener(IMessageSelectionListener l) {
360: listenerList.add(IMessageSelectionListener.class, l);
361: }
362:
363: public void removeMessageSelectionListener(
364: IMessageSelectionListener l) {
365: listenerList.remove(IMessageSelectionListener.class, l);
366: }
367:
368: protected void fireMessageSelectionChangedEvent(IMailbox folder,
369: String messageId) {
370:
371: IMessageSelectionEvent e = new MessageSelectionEvent(this ,
372: folder, messageId);
373: // Guaranteed to return a non-null array
374: Object[] listeners = listenerList.getListenerList();
375:
376: // Process the listeners last to first, notifying
377: // those that are interested in this event
378: for (int i = listeners.length - 2; i >= 0; i -= 2) {
379: if (listeners[i] == IMessageSelectionListener.class) {
380: ((IMessageSelectionListener) listeners[i + 1])
381: .selectionChanged(e);
382: }
383: }
384: }
385:
386: }
|