001: // The contents of this file are subject to the Mozilla Public License Version
002: // 1.1
003: //(the "License"); you may not use this file except in compliance with the
004: //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
005: //
006: //Software distributed under the License is distributed on an "AS IS" basis,
007: //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
008: //for the specific language governing rights and
009: //limitations under the License.
010: //
011: //The Original Code is "The Columba Project"
012: //
013: //The Initial Developers of the Original Code are Frederik Dietz and Timo
014: // Stich.
015: //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
016: //
017: //All Rights Reserved.
018: package org.columba.mail.gui.table.model;
019:
020: import java.util.Enumeration;
021: import java.util.HashMap;
022: import java.util.List;
023: import java.util.Map;
024: import java.util.Vector;
025:
026: import javax.swing.event.ChangeEvent;
027: import javax.swing.event.ListSelectionEvent;
028: import javax.swing.event.TableColumnModelEvent;
029: import javax.swing.tree.DefaultTreeModel;
030: import javax.swing.tree.TreePath;
031:
032: import org.columba.mail.gui.table.IHeaderTableModel;
033: import org.columba.mail.message.ColumbaHeader;
034: import org.columba.mail.message.ICloseableIterator;
035: import org.columba.mail.message.IColumbaHeader;
036: import org.columba.mail.message.IHeaderList;
037: import org.frapuccino.treetable.AbstractTreeTableModel;
038: import org.frapuccino.treetable.CustomTreeTableCellRenderer;
039:
040: public class HeaderTableModel extends AbstractTreeTableModel implements
041: IHeaderTableModel {
042:
043: /**
044: * list of column IDs
045: */
046: private List columns = new Vector();
047:
048: protected IHeaderList headerList;
049:
050: /**
051: *
052: * We cache all <class>MessageNode </class> here.
053: *
054: * This is much faster than searching through the complete <class>HeaderList
055: * </class> all the time.
056: *
057: */
058: protected Map map = new HashMap();
059:
060: protected MessageNode root;
061:
062: private boolean enableThreadedView;
063:
064: private Vector visitors = new Vector();
065:
066: public HeaderTableModel() {
067: }
068:
069: public HeaderTableModel(String[] c) {
070: // add array to vector
071: for (int i = 0; i < c.length; i++) {
072: columns.add(c[i]);
073: }
074: }
075:
076: public void registerVisitor(ModelVisitor visitor) {
077: visitors.add(visitor);
078: }
079:
080: /**
081: * ***************************** implements TableModelModifier
082: * ******************
083: */
084:
085: /*
086: * (non-Javadoc)
087: *
088: * @see org.columba.mail.gui.table.model.TableModelModifier#modify(java.lang.Object[])
089: */
090: public void modify(Object[] uids) {
091: for (int i = 0; i < uids.length; i++) {
092: MessageNode node = (MessageNode) map.get(uids[i]);
093:
094: IColumbaHeader header = getHeaderList().get(uids[i]);
095: if (header == null)
096: continue;
097:
098: node.setUserObject(header);
099:
100: if (node != null) {
101: // update treemodel
102: getTreeModel().nodeChanged(node);
103: }
104: }
105:
106: }
107:
108: /*
109: * (non-Javadoc)
110: *
111: * @see org.columba.mail.gui.table.model.TableModelModifier#remove(java.lang.Object[])
112: */
113: public void remove(Object[] uids) {
114: if (uids != null) {
115: for (int i = 0; i < uids.length; i++) {
116: MessageNode node = (MessageNode) map.get(uids[i]);
117:
118: if (node != null) {
119: map.remove(node);
120:
121: if (node.getParent() != null) {
122: getTreeModel().removeNodeFromParent(node);
123: }
124: }
125: }
126:
127: }
128: }
129:
130: public void reset() {
131: if (root == null) {
132: root = new MessageNode(new ColumbaHeader(), "0");
133:
134: tree.setRootNode(root);
135: }
136:
137: // remove all children from tree
138: root.removeAllChildren();
139:
140: // clear messagenode cache
141: map.clear();
142:
143: if ((headerList == null) || (headerList.count() == 0)) {
144: // table is empty
145: // -> just display empty table
146:
147: getTreeModel().nodeStructureChanged(getRootNode());
148:
149: fireTableDataChanged();
150:
151: return;
152: }
153:
154: }
155:
156: public void update() {
157: if ((headerList == null) || (headerList.count() == 0)) {
158: // table is empty
159: // -> just display empty table
160: root.removeAllChildren();
161:
162: getTreeModel().nodeStructureChanged(getRootNode());
163:
164: fireTableDataChanged();
165:
166: return;
167: }
168:
169: // add every header from HeaderList to the table as MessageNode
170: ICloseableIterator it;
171: for (it = headerList.keyIterator(); it.hasNext();) {
172: // get unique id
173: Object uid = it.next();
174:
175: if (!map.containsKey(uid)) {
176: // get header
177: IColumbaHeader header = headerList.get(uid);
178:
179: // create MessageNode
180: MessageNode child = new MessageNode(header, uid);
181:
182: // add this node to cache
183: map.put(uid, child);
184:
185: // add node to tree
186: root.add(child);
187: }
188: }
189: it.close();
190:
191: Enumeration e = visitors.elements();
192: while (e.hasMoreElements()) {
193: ModelVisitor v = (ModelVisitor) e.nextElement();
194: v.visit(this );
195: }
196:
197: getTreeModel().nodeStructureChanged(getRootNode());
198:
199: fireTableDataChanged();
200: }
201:
202: public void clear() {
203: root = new MessageNode(new ColumbaHeader(), "0");
204: tree.setRootNode(root);
205:
206: }
207:
208: /*
209: * (non-Javadoc)
210: *
211: * @see org.columba.mail.gui.table.model.TableModelModifier#set(org.columba.mail.message.HeaderList)
212: */
213: public void set(IHeaderList headerList) {
214: this .headerList = headerList;
215:
216: reset();
217: update();
218: }
219:
220: /** ********************** getter/setter methods *************************** */
221: public void enableThreadedView(boolean b) {
222: enableThreadedView = b;
223: }
224:
225: public MessageNode getRootNode() {
226: return root;
227: }
228:
229: public IHeaderList getHeaderList() {
230: return headerList;
231: }
232:
233: public MessageNode getMessageNode(Object uid) {
234: return (MessageNode) map.get(uid);
235: }
236:
237: public DefaultTreeModel getTreeModel() {
238: return (DefaultTreeModel) getTree().getModel();
239: }
240:
241: /** ******************* AbstractTableModel implementation ******************* */
242: public int getColumnCount() {
243: return columns.size();
244: }
245:
246: public int getRowCount() {
247: if (getTree() != null) {
248: return getTree().getRowCount();
249: } else {
250: return 0;
251: }
252: }
253:
254: public Object getValueAt(int row, int col) {
255: //if ( col == 0 ) return tree;
256: TreePath treePath = getTree().getPathForRow(row);
257: if (treePath == null)
258: return null;
259:
260: return (MessageNode) treePath.getLastPathComponent();
261: }
262:
263: /**
264: * Get row for node.
265: *
266: * @param node
267: * selected message node
268: * @return current row of node
269: */
270: public int getRow(MessageNode node) {
271:
272: for (int i = 0; i < getTree().getRowCount(); i++) {
273: MessageNode n = (MessageNode) getValueAt(i, 0);
274: if (n.getUid().equals(node.getUid()))
275: return i;
276: }
277:
278: return -1;
279: }
280:
281: public String getColumnName(int column) {
282: return (String) columns.get(column);
283: }
284:
285: public int getColumnNumber(String name) {
286: for (int i = 0; i < getColumnCount(); i++) {
287: if (name.equals(getColumnName(i))) {
288: return i;
289: }
290: }
291:
292: return -1;
293: }
294:
295: /**
296: * Get the class which is responsible for renderering this column.
297: * <p>
298: * If the threaded-view is enabled, return a custom tree cell renderer.
299: * <p>
300: *
301: * @see org.columba.mail.gui.table.TableView#enableThreadedView
302: */
303: public Class getColumnClass(int column) {
304: if (enableThreadedView) {
305: if (getColumnName(column).equals("Subject")) {
306: return CustomTreeTableCellRenderer.class;
307: }
308: }
309:
310: return getValueAt(0, column).getClass();
311: }
312:
313: public boolean isCellEditable(int row, int col) {
314: String name = getColumnName(col);
315:
316: if (name.equalsIgnoreCase("Subject")) {
317: return true;
318: }
319:
320: return false;
321: }
322:
323: /**
324: * Set column IDs
325: *
326: * @param c
327: * array of column IDs
328: */
329: public void setColumns(String[] c) {
330: columns = new Vector();
331:
332: // add array to vector
333: for (int i = 0; i < c.length; i++) {
334: columns.add(c[i]);
335: }
336: }
337:
338: /**
339: * Add column to table model.
340: *
341: * @param c
342: * new column ID
343: */
344: public void addColumn(String c) {
345: columns.add(c);
346: }
347:
348: /**
349: * Clear column list.
350: *
351: */
352: public void clearColumns() {
353: columns.clear();
354: }
355:
356: /**
357: * @see org.columba.mail.gui.table.IHeaderTableModel#getMessageNodeAtRow(int)
358: */
359: public MessageNode getMessageNodeAtRow(int index) {
360: return (MessageNode) getValueAt(index, 0);
361: }
362:
363: public void columnMarginChanged(ChangeEvent e) {
364: }
365:
366: public void columnSelectionChanged(ListSelectionEvent e) {
367: }
368:
369: public void columnAdded(TableColumnModelEvent e) {
370: }
371:
372: public void columnMoved(TableColumnModelEvent e) {
373: if (e.getFromIndex() != e.getToIndex()) {
374: columns.add(e.getToIndex(), columns
375: .remove(e.getFromIndex()));
376: }
377: }
378:
379: public void columnRemoved(TableColumnModelEvent e) {
380: }
381:
382: }
|