зеркало из https://github.com/mozilla/pjs.git
283 строки
8.0 KiB
Java
283 строки
8.0 KiB
Java
/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License
|
|
* Version 1.0 (the "License"); you may not use this file except in
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS"
|
|
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
|
* the License for the specific language governing rights and limitations
|
|
* under the License.
|
|
*
|
|
* The Original Code is the Grendel mail/news client.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape Communications
|
|
* Corporation. Portions created by Netscape are Copyright (C) 1997
|
|
* Netscape Communications Corporation. All Rights Reserved.
|
|
*
|
|
* Created: Will Scullin <scullin@netscape.com>, 17 Dec 1997.
|
|
*/
|
|
|
|
package grendel.ui;
|
|
|
|
import java.util.Enumeration;
|
|
import java.util.Hashtable;
|
|
import java.util.Vector;
|
|
|
|
import javax.swing.Icon;
|
|
import javax.swing.ImageIcon;
|
|
|
|
import javax.mail.Message;
|
|
import javax.mail.MessagingException;
|
|
|
|
import calypso.util.Assert;
|
|
|
|
import grendel.storage.MessageExtra;
|
|
import grendel.storage.MessageExtraFactory;
|
|
import grendel.view.FolderView;
|
|
import grendel.view.MessageSetViewObserver;
|
|
import grendel.view.ViewedMessage;
|
|
import grendel.widgets.TreePath;
|
|
import grendel.widgets.TreeTableDataModel;
|
|
import grendel.widgets.TreeTableModelBroadcaster;
|
|
import grendel.widgets.TreeTableModelEvent;
|
|
import grendel.widgets.TreeTableModelListener;
|
|
|
|
|
|
//
|
|
// MessageModel. Maps a FolderView into a TreeTableDataModel.
|
|
//
|
|
|
|
class MessageModel implements TreeTableDataModel {
|
|
Hashtable fCollapsed = new Hashtable();
|
|
FolderView fView = null;
|
|
TreeTableModelListener fListeners;
|
|
ViewObserver fViewObserver = new ViewObserver();
|
|
|
|
Icon fMessageIcon;
|
|
Icon fMessageReadIcon;
|
|
|
|
public MessageModel() {
|
|
fMessageIcon = new ImageIcon(getClass().getResource("images/msg-small.gif"));
|
|
fMessageReadIcon = new ImageIcon(getClass().getResource("images/msgRead-small.gif"));
|
|
}
|
|
|
|
public void setFolderView(FolderView aView) {
|
|
if (fView != null) {
|
|
fView.removeObserver(fViewObserver);
|
|
}
|
|
fView = aView;
|
|
if (fView != null) {
|
|
fView.addObserver(fViewObserver);
|
|
}
|
|
}
|
|
|
|
public boolean showRoot() {
|
|
return true;
|
|
}
|
|
|
|
// Navigation stuff
|
|
public Object getRoot() {
|
|
return fView.getMessageRoot();
|
|
}
|
|
|
|
public boolean isLeaf(Object aNode) {
|
|
ViewedMessage node = (ViewedMessage) aNode;
|
|
|
|
return node.getChild() == null;
|
|
}
|
|
|
|
public Enumeration getChildren(Object aNode) {
|
|
return null;
|
|
}
|
|
|
|
public Object getChild(Object aNode) {
|
|
ViewedMessage node = (ViewedMessage) aNode;
|
|
|
|
return node.getChild();
|
|
}
|
|
|
|
public Object getNextSibling(Object aNode) {
|
|
ViewedMessage node = (ViewedMessage) aNode;
|
|
|
|
return node.getNext();
|
|
}
|
|
|
|
// Attributes
|
|
public void setCollapsed(TreePath aPath, boolean aCollapsed) {
|
|
TreeTableModelEvent event =
|
|
new TreeTableModelEvent(this, aPath);
|
|
|
|
if (aCollapsed) {
|
|
if (fCollapsed.put(aPath, "x") == null) {
|
|
if (fListeners != null) {
|
|
fListeners.nodeCollapsed(event);
|
|
}
|
|
}
|
|
} else {
|
|
if (fCollapsed.remove(aPath) != null) {
|
|
if (fListeners != null) {
|
|
fListeners.nodeExpanded(event);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean isCollapsed(TreePath aPath) {
|
|
return fCollapsed.containsKey(aPath);
|
|
}
|
|
|
|
public Object getData(Object aNode, Object aID) {
|
|
ViewedMessage node = (ViewedMessage) aNode;
|
|
|
|
if (node.isDummy()) {
|
|
Message m = node.getChild().getMessage();
|
|
if (aID == FolderPanel.kReadID)
|
|
return Boolean.TRUE;
|
|
else if (aID == FolderPanel.kSubjectID) {
|
|
return Util.GetSubject(m);
|
|
}
|
|
return "";
|
|
}
|
|
|
|
Message m = node.getMessage();
|
|
Assert.Assertion(m != null);
|
|
|
|
if (m == null) {
|
|
return "";
|
|
} else if (aID == FolderPanel.kSubjectID) {
|
|
return Util.GetSubject(m);
|
|
} else {
|
|
MessageExtra mextra = MessageExtraFactory.Get(m);
|
|
Object result = null;
|
|
try {
|
|
if (aID == FolderPanel.kSenderID) {
|
|
result = mextra.getAuthor();
|
|
} else if (aID == FolderPanel.kDateID) {
|
|
result = mextra.simplifiedDate();
|
|
} else if (aID == FolderPanel.kReadID) {
|
|
result = mextra.isRead() ? Boolean.TRUE : Boolean.FALSE;
|
|
} else if (aID == FolderPanel.kFlagID) {
|
|
result = mextra.isFlagged() ? Boolean.TRUE : Boolean.FALSE;
|
|
} else if (aID == FolderPanel.kDeletedID) {
|
|
result = mextra.isDeleted() ? Boolean.TRUE : Boolean.FALSE;
|
|
} else {
|
|
throw new Error("unknown column");
|
|
}
|
|
} catch (MessagingException e) {
|
|
result = "???"; // ### Is this reasonable?
|
|
}
|
|
if (result == null) result = "";
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public void setData(Object aNode, Object aID, Object aValue) {
|
|
ViewedMessage node = (ViewedMessage) aNode;
|
|
Message m = node.getMessage();
|
|
if (m != null) {
|
|
MessageExtra mextra = MessageExtraFactory.Get(m);
|
|
boolean b = ((Boolean) aValue).booleanValue();
|
|
|
|
try {
|
|
if (aID == FolderPanel.kReadID) {
|
|
System.out.println("marking " + Util.GetSubject(m) + " read " + b);
|
|
mextra.setIsRead(b);
|
|
} else if (aID == FolderPanel.kFlagID) {
|
|
mextra.setFlagged(b);
|
|
} else if (aID == FolderPanel.kDeletedID) {
|
|
mextra.setDeleted(b);
|
|
}
|
|
} catch (MessagingException e) {
|
|
// ### Shouldn't we report the error to the user or something?
|
|
}
|
|
}
|
|
}
|
|
|
|
public Icon getIcon(Object aNode) {
|
|
ViewedMessage node = (ViewedMessage) aNode;
|
|
Message m = node.getMessage();
|
|
if (m == null) {
|
|
return fMessageIcon;
|
|
} else {
|
|
try {
|
|
if (MessageExtraFactory.Get(m).isRead()) {
|
|
return fMessageReadIcon;
|
|
}
|
|
} catch (MessagingException e) {
|
|
}
|
|
return fMessageIcon;
|
|
}
|
|
}
|
|
|
|
public Icon getOverlayIcon(Object aNode) {
|
|
return null;
|
|
}
|
|
|
|
public void addTreeTableModelListener(TreeTableModelListener aListener) {
|
|
fListeners = TreeTableModelBroadcaster.add(fListeners, aListener);
|
|
}
|
|
|
|
public void removeTreeTableModelListener(TreeTableModelListener aListener) {
|
|
fListeners = TreeTableModelBroadcaster.remove(fListeners, aListener);
|
|
}
|
|
|
|
TreePath createTreePath(ViewedMessage aNode) {
|
|
Vector pathVector = new Vector();
|
|
|
|
while (aNode != null) {
|
|
pathVector.insertElementAt(aNode, 0);
|
|
aNode = aNode.getParent();
|
|
}
|
|
|
|
return new TreePath(pathVector);
|
|
}
|
|
|
|
class ViewObserver implements MessageSetViewObserver {
|
|
public void messagesChanged(Enumeration inserted,
|
|
Enumeration deleted,
|
|
Enumeration changed) {
|
|
if (fListeners != null) {
|
|
Object children[] = new Object[1];
|
|
ViewedMessage node;
|
|
TreePath path;
|
|
|
|
if (inserted != null) {
|
|
System.out.println("Inserted messages");
|
|
while (inserted.hasMoreElements()) {
|
|
node = (ViewedMessage) inserted.nextElement();
|
|
|
|
path = createTreePath(node.getParent());
|
|
children[0] = node;
|
|
|
|
fListeners.nodeInserted(new TreeTableModelEvent(this, path, children));
|
|
}
|
|
}
|
|
if (deleted != null) {
|
|
System.out.println("Deleted messages");
|
|
while (deleted.hasMoreElements()) {
|
|
node = (ViewedMessage) deleted.nextElement();
|
|
|
|
path = createTreePath(node.getParent());
|
|
children[0] = node;
|
|
|
|
fListeners.nodeDeleted(new TreeTableModelEvent(this, path, children));
|
|
}
|
|
}
|
|
if (changed != null) {
|
|
while (changed.hasMoreElements()) {
|
|
node = (ViewedMessage) changed.nextElement();
|
|
|
|
Message m = node.getMessage();
|
|
System.out.println("'" + Util.GetSubject(m) + "' changed");
|
|
|
|
path = createTreePath(node);
|
|
fListeners.nodeChanged(new TreeTableModelEvent(this, path, null));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|