KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > columba > mail > gui > tree > TreeView


1 //The contents of this file are subject to the Mozilla Public License Version 1.1
2
//(the "License"); you may not use this file except in compliance with the
3
//License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
4
//
5
//Software distributed under the License is distributed on an "AS IS" basis,
6
//WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
7
//for the specific language governing rights and
8
//limitations under the License.
9
//
10
//The Original Code is "The Columba Project"
11
//
12
//The Initial Developers of the Original Code are Frederik Dietz and Timo Stich.
13
//Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
14
//
15
//All Rights Reserved.
16
package org.columba.mail.gui.tree;
17
18 import java.awt.Point JavaDoc;
19 import java.awt.datatransfer.DataFlavor JavaDoc;
20 import java.awt.datatransfer.Transferable JavaDoc;
21 import java.awt.dnd.DropTarget JavaDoc;
22 import java.awt.dnd.DropTargetDragEvent JavaDoc;
23 import java.awt.dnd.DropTargetDropEvent JavaDoc;
24 import java.awt.dnd.DropTargetEvent JavaDoc;
25 import java.awt.event.ActionEvent JavaDoc;
26 import java.awt.event.ActionListener JavaDoc;
27
28 import javax.swing.JComponent JavaDoc;
29 import javax.swing.JTree JavaDoc;
30 import javax.swing.Timer JavaDoc;
31 import javax.swing.ToolTipManager JavaDoc;
32 import javax.swing.TransferHandler JavaDoc;
33 import javax.swing.tree.DefaultMutableTreeNode JavaDoc;
34 import javax.swing.tree.TreePath JavaDoc;
35
36 import org.columba.core.xml.XmlElement;
37 import org.columba.mail.config.IFolderItem;
38 import org.columba.mail.folder.IMailFolder;
39 import org.frapuccino.swing.SortedJTree;
40
41 /**
42  * this class does all the dirty work for the TreeController
43  */

44 public class TreeView extends SortedJTree {
45     /** The treepath that was selected before the drag and drop began. */
46     private TreePath JavaDoc selectedPathBeforeDrag;
47
48     /** The treepath that is under the mouse pointer in a drag and drop action. */
49     private TreePath JavaDoc dropTargetPath;
50
51     /** The component is in a drag and drop action */
52     private boolean isInDndMode = false;
53
54     /**
55      * A Timer that expands/collapses leafs when the mouse hovers above it. This
56      * is only used during Drag and Drop.
57      */

58     private Timer JavaDoc dndAutoExpanderTimer;
59
60     
61
62     /**
63      * Constructa a tree view
64      *
65      * @param model
66      * the tree model that this JTree should use.
67      */

68     public TreeView(javax.swing.tree.TreeModel JavaDoc model) {
69         super(model);
70
71         ToolTipManager.sharedInstance().registerComponent(this);
72
73         putClientProperty("JTree.lineStyle", "Angled");
74
75         setShowsRootHandles(true);
76         setRootVisible(false);
77
78         //setBorder(BorderFactory.createEmptyBorder(2, 0, 2, 0));
79
IMailFolder root = (IMailFolder) treeModel.getRoot();
80
81         expand(root);
82
83         repaint();
84
85         setDropTarget(new DropHandler());
86
87         dndAutoExpanderTimer = new Timer JavaDoc(1000, new TreeLeafActionListener(this));
88         dndAutoExpanderTimer.setRepeats(false);
89     }
90
91     /**
92      * Expands the specified node so it corresponds to the expanded attribute in
93      * the configuration.
94      *
95      * @param parent
96      * node to check if it should be expanded or not.
97      */

98     public final void expand(IMailFolder parent) {
99         // get configuration from tree.xml file
100
IFolderItem item = parent.getConfiguration();
101
102         XmlElement property = item.getElement("property");
103
104         if (property != null) {
105             String JavaDoc expanded = property.getAttribute("expanded");
106
107             if (expanded == null) {
108                 expanded = "true";
109             }
110
111             // expand folder
112
int row = getRowForPath(new TreePath JavaDoc(parent.getPath()));
113
114             if (expanded.equals("true")) {
115                 expandRow(row);
116             }
117         }
118
119         // recursivly expand all children
120
for (int i = 0; i < parent.getChildCount(); i++) {
121             IMailFolder child = (IMailFolder) parent.getChildAt(i);
122             expand(child);
123         }
124     }
125
126     /**
127      * Returns the tree node that is intended for a drop action. If this method
128      * is called during a non-drag-and-drop invocation there is no guarantee
129      * what it will return.
130      *
131      * @return the folder tree node that is targeted for the drop action; null
132      * otherwise.
133      */

134     public IMailFolder getDropTargetFolder() {
135         IMailFolder node = null;
136
137         if (dropTargetPath != null) {
138             node = (IMailFolder) dropTargetPath.getLastPathComponent();
139         } else {
140             if ( getSelectionPath() != null)
141                 node = (IMailFolder) getSelectionPath().getLastPathComponent();
142         }
143
144         return node;
145     }
146
147     /**
148      * Sets the stored drop target path to null. This should be done after the
149      * getDropTargetFolder() has been used in a folder command.
150      */

151     void resetDropTargetFolder() {
152         dropTargetPath = null;
153     }
154
155     /**
156      * Returns the tree node that was selected before a drag and drop was
157      * initiated. If this method is called during a non-drag-and-drop invocation
158      * there is no guarantee what it will return.
159      *
160      * @return the folder that is being dragged; null if it wasnt initiated in
161      * this component.
162      */

163     public DefaultMutableTreeNode JavaDoc getSelectedNodeBeforeDragAction() {
164         DefaultMutableTreeNode JavaDoc node = null;
165
166         if (selectedPathBeforeDrag != null) {
167             node = (DefaultMutableTreeNode JavaDoc) selectedPathBeforeDrag
168                     .getLastPathComponent();
169         }
170
171         return node;
172     }
173
174     /**
175      * Returns true if the tree is in a Drag and Drop action.
176      *
177      * @return true if the tree is in a Drag and Drop action; false otherwise.
178      */

179     public boolean isInDndAction() {
180         return isInDndMode;
181     }
182
183     /**
184      * Sets up this TreeView for Drag and drop action. Stores the selected tree
185      * leaf before the action begins, this is used later when the Drag and drop
186      * action is completed.
187      */

188     private void setUpDndAction() {
189         isInDndMode = true;
190         selectedPathBeforeDrag = getSelectionPath();
191     }
192
193     /**
194      * Resets this TreeView after a Drag and drop action has occurred. Selects
195      * the previous selected tree leaf before the DnD action began.
196      */

197     private void resetDndAction() {
198         dndAutoExpanderTimer.stop();
199         setSelectionPath(selectedPathBeforeDrag);
200         selectedPathBeforeDrag = null;
201         isInDndMode = false;
202     }
203
204     
205
206     /**
207      * Our own drop target implementation. This treeview class uses its own drop
208      * target since the common drop target in Swing >1.4 does not provide a fine
209      * grained support for dragging items onto leafs, when some leafs does not
210      * accept new items.
211      *
212      * @author redsolo
213      */

214     
215     private class DropHandler extends DropTarget JavaDoc {
216         private boolean canImport;
217
218         /** The latest mouse location. */
219         private Point JavaDoc location;
220
221         /**
222          * Our own implementation to ask the transfer handler for each leaf the
223          * user moves above. {@inheritDoc}
224          */

225         public void dragOver(DropTargetDragEvent JavaDoc e) {
226             if ((location == null) || (!location.equals(e.getLocation()))) {
227                 location = e.getLocation();
228
229                 TreePath JavaDoc targetPath = getClosestPathForLocation(location.x,
230                         location.y);
231
232                 if ((dropTargetPath != null) && (targetPath == dropTargetPath)) {
233                     return;
234                 }
235
236                 dropTargetPath = targetPath;
237
238                 dndAutoExpanderTimer.restart();
239
240                 TreeView.this.getSelectionModel().setSelectionPath(
241                         dropTargetPath);
242
243                 DataFlavor JavaDoc[] flavors = e.getCurrentDataFlavors();
244
245                 JComponent JavaDoc c = (JComponent JavaDoc) e.getDropTargetContext()
246                         .getComponent();
247                 TransferHandler JavaDoc importer = c.getTransferHandler();
248
249                 if ((importer != null) && importer.canImport(c, flavors)) {
250                     canImport = true;
251                 } else {
252                     canImport = false;
253                 }
254
255                 int dropAction = e.getDropAction();
256
257                 if (canImport) {
258                     e.acceptDrag(dropAction);
259                 } else {
260                     e.rejectDrag();
261                 }
262             }
263         }
264
265         /** {@inheritDoc} */
266         public void dragEnter(DropTargetDragEvent JavaDoc e) {
267             setUpDndAction();
268
269             DataFlavor JavaDoc[] flavors = e.getCurrentDataFlavors();
270
271             JComponent JavaDoc c = (JComponent JavaDoc) e.getDropTargetContext().getComponent();
272             TransferHandler JavaDoc importer = c.getTransferHandler();
273
274             if ((importer != null) && importer.canImport(c, flavors)) {
275                 canImport = true;
276             } else {
277                 canImport = false;
278             }
279
280             int dropAction = e.getDropAction();
281
282             if (canImport) {
283                 e.acceptDrag(dropAction);
284             } else {
285                 e.rejectDrag();
286             }
287         }
288
289         /** {@inheritDoc} */
290         public void dragExit(DropTargetEvent JavaDoc e) {
291             resetDndAction();
292             dropTargetPath = null;
293         }
294
295         /** {@inheritDoc} */
296         public void drop(DropTargetDropEvent JavaDoc e) {
297             int dropAction = e.getDropAction();
298
299             JComponent JavaDoc c = (JComponent JavaDoc) e.getDropTargetContext().getComponent();
300             TransferHandler JavaDoc importer = c.getTransferHandler();
301
302             if (canImport && (importer != null)) {
303                 e.acceptDrop(dropAction);
304
305                 try {
306                     Transferable JavaDoc t = e.getTransferable();
307                     e.dropComplete(importer.importData(c, t));
308                 } catch (RuntimeException JavaDoc re) {
309                     e.dropComplete(false);
310                 }
311             } else {
312                 e.rejectDrop();
313             }
314
315             resetDndAction();
316         }
317
318         /** {@inheritDoc} */
319         public void dropActionChanged(DropTargetDragEvent JavaDoc e) {
320             int dropAction = e.getDropAction();
321
322             if (canImport) {
323                 e.acceptDrag(dropAction);
324             } else {
325                 e.rejectDrag();
326             }
327         }
328     }
329
330     /**
331      * An ActionListener that collapses/expands leafs in a tree.
332      *
333      * @author redsolo
334      */

335     private class TreeLeafActionListener implements ActionListener JavaDoc {
336         /**
337          * Constructs a leaf listener.
338          *
339          * @param parent
340          * the parent JTree.
341          */

342         public TreeLeafActionListener(JTree JavaDoc parent) {
343         }
344
345         /** {@inheritDoc} */
346         public void actionPerformed(ActionEvent JavaDoc e) {
347             // Do nothing if we are hovering over the root node
348
if (dropTargetPath != null) {
349                 if (isExpanded(dropTargetPath)) {
350                     collapsePath(dropTargetPath);
351                 } else {
352                     expandPath(dropTargetPath);
353                 }
354             }
355         }
356     }
357 }
Popular Tags