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 Stich.
013: //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
014: //
015: //All Rights Reserved.
016: package org.columba.mail.gui.tree;
017:
018: import java.io.IOException;
019: import java.io.InputStream;
020:
021: import javax.swing.JPopupMenu;
022: import javax.swing.event.EventListenerList;
023: import javax.swing.event.TreeExpansionEvent;
024: import javax.swing.event.TreeSelectionEvent;
025: import javax.swing.event.TreeSelectionListener;
026: import javax.swing.event.TreeWillExpandListener;
027: import javax.swing.tree.DefaultMutableTreeNode;
028: import javax.swing.tree.ExpandVetoException;
029: import javax.swing.tree.TreeModel;
030: import javax.swing.tree.TreePath;
031: import javax.swing.tree.TreeSelectionModel;
032:
033: import org.columba.api.gui.frame.IFrameMediator;
034: import org.columba.core.gui.menu.ExtendablePopupMenu;
035: import org.columba.core.gui.menu.MenuXMLDecoder;
036: import org.columba.core.io.DiskIO;
037: import org.columba.core.xml.XmlElement;
038: import org.columba.mail.config.IFolderItem;
039: import org.columba.mail.folder.IMailFolder;
040: import org.columba.mail.gui.tree.comparator.FolderComparator;
041: import org.columba.mail.gui.tree.comparator.UnreadFolderComparator;
042: import org.columba.mail.gui.tree.util.FolderTreeCellRenderer;
043:
044: /**
045: * this class shows the the folder hierarchy
046: */
047: public class TreeController implements TreeSelectionListener,
048: TreeWillExpandListener, ITreeController {
049:
050: private IMailFolder selectedFolder;
051:
052: private TreeView view;
053:
054: private IFrameMediator frameController;
055:
056: private ExtendablePopupMenu menu;
057:
058: private FolderComparator folderComparator;
059:
060: protected EventListenerList listenerList = new EventListenerList();
061:
062: /**
063: * Constructor for tree controller.
064: *
065: * @param controller
066: * the parent controller.
067: * @param model
068: * the tree model to display.
069: */
070: public TreeController(IFrameMediator controller,
071: FolderTreeModel model) {
072: frameController = controller;
073:
074: view = new TreeView(model);
075: view.setSortingEnabled(false);
076:
077: view.addTreeWillExpandListener(this );
078:
079: FolderTreeCellRenderer renderer = new FolderTreeCellRenderer();
080: view.setCellRenderer(renderer);
081:
082: getView().setTransferHandler(
083: new TreeViewTransferHandler(controller));
084: getView().setDragEnabled(true);
085:
086: getView().getSelectionModel().setSelectionMode(
087: TreeSelectionModel.SINGLE_TREE_SELECTION);
088:
089: getView().addTreeSelectionListener(this );
090:
091: }
092:
093: /**
094: * @see org.columba.mail.gui.tree.ITreeController#sortAscending(boolean)
095: */
096: public void sortAscending(boolean ascending) {
097: folderComparator.setAscending(ascending);
098: view.setSortingComparator(folderComparator);
099: }
100:
101: /**
102: * Returns the tree view.
103: *
104: * @return the tree view.
105: */
106: public TreeView getView() {
107: return view;
108: }
109:
110: /**
111: * Set the specified folder as seleceted.
112: *
113: * @param folder
114: * the new selected folder.
115: */
116: public void setSelected(IMailFolder folder) {
117: view.clearSelection();
118:
119: TreePath path = folder.getSelectionTreePath();
120:
121: // @author: fdietz never request focus
122: //view.requestFocus();
123: /*
124: * view.setLeadSelectionPath(path); view.setAnchorSelectionPath(path);
125: */
126: view.setSelectionPath(path);
127: view.expandPath(path);
128:
129: this .selectedFolder = folder;
130:
131: }
132:
133: /**
134: * Creates a Popup menu.
135: */
136: public void createPopupMenu() {
137: try {
138: InputStream is = DiskIO
139: .getResourceStream("org/columba/mail/action/tree_contextmenu.xml");
140:
141: menu = new MenuXMLDecoder(frameController)
142: .createPopupMenu(is);
143: } catch (IOException e) {
144: e.printStackTrace();
145: }
146: }
147:
148: /**
149: * Returns the pop up menu for the controller.
150: *
151: * @return the pop up menu.
152: */
153: public JPopupMenu getPopupMenu() {
154: return menu;
155: }
156:
157: /**
158: * @see org.columba.mail.gui.tree.ITreeController#getSelected()
159: */
160: public IMailFolder getSelected() {
161: return selectedFolder;
162: }
163:
164: /**
165: * Returns the mailFrameController.
166: *
167: * @return MailFrameController
168: */
169: public IFrameMediator getFrameController() {
170: return frameController;
171: }
172:
173: /**
174: * ****************** TreeWillExpand Interface
175: * ******************************
176: */
177:
178: /** {@inheritDoc} */
179: public void treeWillExpand(TreeExpansionEvent e)
180: throws ExpandVetoException {
181: IMailFolder treeNode = (IMailFolder) e.getPath()
182: .getLastPathComponent();
183:
184: if (treeNode == null) {
185: return;
186: }
187:
188: // save expanded state
189: saveExpandedState(treeNode, e.getPath());
190: }
191:
192: /** {@inheritDoc} */
193: public void treeWillCollapse(TreeExpansionEvent e) {
194: IMailFolder treeNode = (IMailFolder) e.getPath()
195: .getLastPathComponent();
196:
197: if (treeNode == null) {
198: return;
199: }
200:
201: // save expanded state
202: saveExpandedState(treeNode, e.getPath());
203: }
204:
205: /**
206: * Saves the tree expanded state.
207: *
208: * @param folder
209: * the folder to get the configuration for.
210: * @param path
211: * the tree path in the tree view.
212: */
213: private void saveExpandedState(IMailFolder folder, TreePath path) {
214: IFolderItem item = folder.getConfiguration();
215:
216: XmlElement property = item.getElement("property");
217:
218: // Note: we negate the expanded state because this is
219: // a will-expand/collapse listener
220: if (!getView().isExpanded(path)) {
221: property.addAttribute("expanded", "true");
222: } else {
223: property.addAttribute("expanded", "false");
224: }
225: }
226:
227: /**
228: * @see org.columba.mail.gui.tree.ITreeController#getModel()
229: */
230: public TreeModel getModel() {
231: return getView().getModel();
232: }
233:
234: /**
235: * @see org.columba.mail.gui.tree.ITreeController#setSortingEnabled(boolean)
236: */
237: public void setSortingEnabled(boolean enabled) {
238: view.setSortingEnabled(enabled);
239: }
240:
241: public void setSortingMode(SORTING_MODE_ENUM sortingMode,
242: boolean ascending) {
243:
244: if (sortingMode == SORTING_MODE_ENUM.ALPHABETICAL) {
245: setFolderComparator(new FolderComparator(ascending));
246: } else if (sortingMode == SORTING_MODE_ENUM.UNREAD_COUNT) {
247: setFolderComparator(new UnreadFolderComparator(ascending));
248: } else {
249: // no sorting
250: }
251: }
252:
253: /**
254: * Set a new folder comparator for sorting the folders.
255: *
256: * @param comparator
257: * the folder comparator to use.
258: */
259: private void setFolderComparator(FolderComparator comparator) {
260: folderComparator = comparator;
261: view.setSortingComparator(folderComparator);
262: }
263:
264: public void addFolderSelectionListener(IFolderSelectionListener l) {
265: listenerList.add(IFolderSelectionListener.class, l);
266: }
267:
268: public void removeFolderSelectionListener(IFolderSelectionListener l) {
269: listenerList.remove(IFolderSelectionListener.class, l);
270: }
271:
272: protected void fireFolderSelectionChangedEvent(IMailFolder folder) {
273:
274: IFolderSelectionEvent e = new FolderSelectionEvent(this , folder);
275: // Guaranteed to return a non-null array
276: Object[] listeners = listenerList.getListenerList();
277:
278: // Process the listeners last to first, notifying
279: // those that are interested in this event
280: for (int i = listeners.length - 2; i >= 0; i -= 2) {
281: if (listeners[i] == IFolderSelectionListener.class) {
282: ((IFolderSelectionListener) listeners[i + 1])
283: .selectionChanged(e);
284: }
285: }
286: }
287:
288: public void valueChanged(TreeSelectionEvent e) {
289: DefaultMutableTreeNode node = (DefaultMutableTreeNode) getView()
290: .getLastSelectedPathComponent();
291:
292: if (node == null)
293: return;
294:
295: // safe to cast to IMailFolder here, because only those are visible to the user
296: fireFolderSelectionChangedEvent((IMailFolder) node);
297: }
298:
299: }
|