001: /*
002: * This file is part of the Echo Web Application Framework (hereinafter "Echo").
003: * Copyright (C) 2002-2005 NextApp, Inc.
004: *
005: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
006: *
007: * The contents of this file are subject to the Mozilla Public License Version
008: * 1.1 (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: * http://www.mozilla.org/MPL/
011: *
012: * Software distributed under the License is distributed on an "AS IS" basis,
013: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
014: * for the specific language governing rights and limitations under the
015: * License.
016: *
017: * Alternatively, the contents of this file may be used under the terms of
018: * either the GNU General Public License Version 2 or later (the "GPL"), or
019: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
020: * in which case the provisions of the GPL or the LGPL are applicable instead
021: * of those above. If you wish to allow use of your version of this file only
022: * under the terms of either the GPL or the LGPL, and not to allow others to
023: * use your version of this file under the terms of the MPL, indicate your
024: * decision by deleting the provisions above and replace them with the notice
025: * and other provisions required by the GPL or the LGPL. If you do not delete
026: * the provisions above, a recipient may use your version of this file under
027: * the terms of any one of the MPL, the GPL or the LGPL.
028: */
029:
030: package echo2example.email;
031:
032: import java.io.Serializable;
033: import java.util.Date;
034: import java.util.EventListener;
035: import java.util.EventObject;
036:
037: import javax.mail.Address;
038: import javax.mail.Folder;
039: import javax.mail.Message;
040: import javax.mail.MessagingException;
041: import javax.mail.internet.InternetAddress;
042:
043: import nextapp.echo2.app.Component;
044: import nextapp.echo2.app.Extent;
045: import nextapp.echo2.app.Label;
046: import nextapp.echo2.app.Table;
047: import nextapp.echo2.app.event.ActionEvent;
048: import nextapp.echo2.app.event.ActionListener;
049: import nextapp.echo2.app.table.AbstractTableModel;
050: import nextapp.echo2.app.table.TableCellRenderer;
051: import nextapp.echo2.app.table.TableColumnModel;
052:
053: /**
054: * A selectable <code>Table</code> which displays a list of messages.
055: */
056: public class MessageListTable extends Table {
057:
058: private static final int COLUMN_FROM = 0;
059: private static final int COLUMN_SUBJECT = 1;
060: private static final int COLUMN_DATE = 2;
061:
062: /**
063: * An event describing a message selection.
064: */
065: public class MessageSelectionEvent extends EventObject {
066:
067: private Message message;
068:
069: /**
070: * Creates a <code>MessageSelectionEvent</code>.
071: *
072: * @param message the selected message
073: */
074: public MessageSelectionEvent(Message message) {
075: super (MessageListTable.this );
076: this .message = message;
077: }
078:
079: /**
080: * Returns the selected message.
081: *
082: * @return the selected message
083: */
084: public Message getMessage() {
085: return message;
086: }
087: }
088:
089: /**
090: * A listener interface for receiving notification of message selections.
091: */
092: public static interface MessageSelectionListener extends
093: EventListener, Serializable {
094:
095: /**
096: * Invoked when a message is selected.
097: *
098: * @param e an event describing the selection
099: */
100: public void messageSelected(MessageSelectionEvent e);
101: }
102:
103: /**
104: * A <code>TableModel</code> that pulls message header data from the
105: * mail server.
106: */
107: private AbstractTableModel messageTableModel = new AbstractTableModel() {
108:
109: /**
110: * @see nextapp.echo2.app.table.TableModel#getColumnCount()
111: */
112: public int getColumnCount() {
113: return 3;
114: }
115:
116: /**
117: * @see nextapp.echo2.app.table.TableModel#getRowCount()
118: */
119: public int getRowCount() {
120: return displayedMessages == null ? 0
121: : displayedMessages.length;
122: }
123:
124: /**
125: * @see nextapp.echo2.app.table.TableModel#getValueAt(int, int)
126: */
127: public Object getValueAt(int column, int row) {
128: try {
129: switch (column) {
130: case COLUMN_FROM:
131: // Return the sender's address.
132: Address[] from = displayedMessages[row].getFrom();
133: if (from != null) {
134: InternetAddress fromAddress = ((InternetAddress) from[0]);
135: String personal = fromAddress.getPersonal();
136: return personal == null ? fromAddress
137: .getAddress() : personal;
138: } else {
139: return Messages
140: .getString("MessageListTable.UnknownSenderText");
141: }
142: case COLUMN_SUBJECT:
143: // Return the subject.
144: String subject = displayedMessages[row]
145: .getSubject();
146: if (subject != null && subject.length() > 40) {
147: subject = subject.substring(0, 40);
148: }
149: return subject;
150: case COLUMN_DATE:
151: return displayedMessages[row].getSentDate();
152: default:
153: throw new IllegalArgumentException(
154: "Invalid column.");
155: }
156: } catch (MessagingException ex) {
157: // Generally should not occur.
158: return null;
159: }
160: }
161:
162: /**
163: * @see nextapp.echo2.app.table.TableModel#getColumnName(int)
164: */
165: public String getColumnName(int column) {
166: switch (column) {
167: case COLUMN_FROM:
168: return Messages
169: .getString("MessageListTable.ColumnHeaderFrom");
170: case COLUMN_SUBJECT:
171: return Messages
172: .getString("MessageListTable.ColumnHeaderSubject");
173: case COLUMN_DATE:
174: return Messages
175: .getString("MessageListTable.ColumnHeaderDate");
176: default:
177: throw new IllegalArgumentException("Invalid column.");
178: }
179: }
180: };
181:
182: /**
183: * A renderer for the header data contained in the table of messages.
184: */
185: private TableCellRenderer messageTableCellRenderer = new TableCellRenderer() {
186:
187: /**
188: * @see nextapp.echo2.app.table.TableCellRenderer#getTableCellRendererComponent(
189: * nextapp.echo2.app.Table, java.lang.Object, int, int)
190: */
191: public Component getTableCellRendererComponent(Table table,
192: Object value, int column, int row) {
193: Label label;
194: switch (column) {
195: case COLUMN_DATE:
196: label = new Label(Messages
197: .formatDateTimeMedium((Date) value));
198: label.setLineWrap(false);
199: break;
200: case COLUMN_SUBJECT:
201: label = new Label(value == null ? (String) null
202: : MessageUtil.clean(value.toString(), 25, 50));
203: break;
204: case COLUMN_FROM:
205: label = new Label(value == null ? (String) null
206: : MessageUtil.clean(value.toString(), 30, 65));
207: break;
208: default:
209: throw new IndexOutOfBoundsException();
210: }
211: if (row % 2 == 0) {
212: label.setStyleName("MessageListTable.EvenRowLabel");
213: } else {
214: label.setStyleName("MessageListTable.OddRowLabel");
215: }
216: return label;
217: }
218: };
219:
220: private ActionListener tableActionListener = new ActionListener() {
221:
222: /**
223: * @see nextapp.echo2.app.event.ActionListener#actionPerformed(nextapp.echo2.app.event.ActionEvent)
224: */
225: public void actionPerformed(ActionEvent e) {
226: fireMessageSelection();
227: }
228: };
229:
230: private Message[] displayedMessages;
231: private Folder folder;
232: private int totalMessages;
233: private int pageIndex;
234:
235: /**
236: * Creates a new <code>MessageListTable</code>.
237: */
238: public MessageListTable() {
239: super ();
240: addActionListener(tableActionListener);
241: setStyleName("MessageListTable.Table");
242: setModel(messageTableModel);
243: setDefaultRenderer(Object.class, messageTableCellRenderer);
244:
245: TableColumnModel columnModel = getColumnModel();
246: columnModel.getColumn(0).setWidth(
247: new Extent(35, Extent.PERCENT));
248: columnModel.getColumn(1).setWidth(
249: new Extent(40, Extent.PERCENT));
250: columnModel.getColumn(2).setWidth(
251: new Extent(25, Extent.PERCENT));
252: }
253:
254: /**
255: * Adds a <code>MessageSelectionListener</code> to be notified of
256: * message selections.
257: *
258: * @param l the listener to add
259: */
260: public void addMessageSelectionListener(MessageSelectionListener l) {
261: getEventListenerList().addListener(
262: MessageSelectionListener.class, l);
263: }
264:
265: /**
266: * Notifies <code>MessageSelectionListener</code>s of a message selection.
267: */
268: private void fireMessageSelection() {
269: Message message;
270: int selectedRow = getSelectionModel().getMinSelectedIndex();
271: if (selectedRow == -1) {
272: message = null;
273: } else {
274: message = displayedMessages[selectedRow];
275: }
276: MessageSelectionEvent e = new MessageSelectionEvent(message);
277: EventListener[] listeners = getEventListenerList()
278: .getListeners(MessageSelectionListener.class);
279: for (int i = 0; i < listeners.length; ++i) {
280: ((MessageSelectionListener) listeners[i])
281: .messageSelected(e);
282: }
283: }
284:
285: /**
286: * Refreshes the current page.
287: */
288: private void refresh() {
289: if (folder == null) {
290: displayedMessages = null;
291: messageTableModel.fireTableDataChanged();
292: return;
293: }
294: try {
295: int firstMessage = pageIndex * EmailApp.MESSAGES_PER_PAGE
296: + 1;
297: int lastMessage = firstMessage + EmailApp.MESSAGES_PER_PAGE
298: - 1;
299: if (lastMessage > totalMessages) {
300: lastMessage = totalMessages;
301: }
302:
303: displayedMessages = folder.getMessages(firstMessage,
304: lastMessage);
305: messageTableModel.fireTableDataChanged();
306: } catch (MessagingException ex) {
307: ((EmailApp) getApplicationInstance())
308: .processFatalException(ex);
309: }
310: }
311:
312: /**
313: * Removes a <code>MessageSelectionListener</code> from being notified of
314: * message selections.
315: *
316: * @param l the listener to remove
317: */
318: public void removeMessageSelectionListener(
319: MessageSelectionListener l) {
320: getEventListenerList().removeListener(
321: MessageSelectionListener.class, l);
322: }
323:
324: /**
325: * Sets the displayed folder.
326: *
327: * @param newValue The new <code>Folder</code> to display.
328: */
329: public void setFolder(Folder newValue) {
330: try {
331: if (folder != null) {
332: folder.close(false);
333: folder = null;
334: }
335: folder = newValue;
336: if (folder != null) {
337: folder.open(Folder.READ_ONLY);
338: totalMessages = folder.getMessageCount();
339: }
340:
341: } catch (MessagingException ex) {
342: ((EmailApp) getApplicationInstance())
343: .processFatalException(ex);
344: }
345: getSelectionModel().clearSelection();
346: refresh();
347: fireMessageSelection();
348: }
349:
350: /**
351: * Sets the displayed page.
352: */
353: public void setPageIndex(int pageIndex) {
354: this.pageIndex = pageIndex;
355: getSelectionModel().clearSelection();
356: refresh();
357: fireMessageSelection();
358: }
359: }
|