KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > suberic > pooka > gui > FolderPanel


1 package net.suberic.pooka.gui;
2 import net.suberic.pooka.*;
3 import net.suberic.util.*;
4 import net.suberic.util.swing.*;
5 import net.suberic.util.gui.ConfigurableKeyBinding;
6 import net.suberic.util.gui.ConfigurableToolbar;
7 import java.awt.*;
8 import java.awt.dnd.*;
9 import java.awt.event.*;
10 import javax.mail.*;
11 import javax.swing.*;
12 import javax.swing.event.*;
13 import javax.swing.table.*;
14 import javax.swing.tree.*;
15 import javax.swing.text.TextAction JavaDoc;
16 import javax.swing.plaf.metal.MetalTheme JavaDoc;
17 import net.suberic.pooka.gui.*;
18 import java.util.Vector JavaDoc;
19 import java.util.LinkedList JavaDoc;
20
21
22 /**
23  * This class displays the Stores and Folders for Pooka.
24  */

25 public class FolderPanel extends JPanel implements ItemListChangeListener, UserProfileContainer, ThemeSupporter, ThemeListener {
26   MainPanel mainPanel=null;
27   JTree folderTree;
28   DefaultTreeModel folderModel;
29   Session session;
30   ConfigurableKeyBinding keyBindings;
31   ConfigurableToolbar folderPanelToolbar;
32   MetalTheme JavaDoc currentTheme = null;
33   DropTarget mDropTarget = null;
34   TransferHandler mTransferHandler = null;
35
36   private Action JavaDoc[] defaultActions = {
37     new NewMessageAction()
38   };
39
40   /**
41    * This creates and configures a new FolderPanel.
42    */

43   public FolderPanel(MainPanel newMainPanel) {
44
45     this.setLayout(new BorderLayout());
46
47     mainPanel=newMainPanel;
48
49     setPreferredSize(new Dimension(Integer.parseInt(Pooka.getProperty("Pooka.folderPanel.hsize", "200")), Integer.parseInt(Pooka.getProperty("Pooka.folderPanel.vsize", Pooka.getProperty("Pooka.vsize","570")))));
50
51     folderModel = new DefaultTreeModel(createTreeRoot());
52     folderTree = new JTree(folderModel);
53
54     JScrollPane jsp = new JScrollPane(folderTree);
55     //this.getViewport().add(folderTree);
56

57     folderPanelToolbar = Pooka.getUIFactory().createFolderPanelToolbar();
58     //new ConfigurableToolbar("FolderToolbar", Pooka.getResources());
59
if (folderPanelToolbar != null) {
60       folderPanelToolbar.setActive(getActions());
61       this.add("North", folderPanelToolbar);
62     }
63
64     this.add("Center", jsp);
65
66     folderTree.addMouseListener(new MouseAdapter() {
67
68         public void mouseClicked(MouseEvent e) {
69           if (e.getClickCount() == 2) {
70             MailTreeNode tmpNode = getSelectedNode();
71             if (tmpNode != null) {
72               String JavaDoc actionCommand = Pooka.getProperty("FolderPanel.2xClickAction", "file-open");
73               Action JavaDoc clickAction = getSelectedNode().getAction(actionCommand);
74               if (clickAction != null ) {
75                 clickAction.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, actionCommand));
76               }
77
78             }
79           }
80         }
81
82         public void mousePressed(MouseEvent e) {
83           if (e.isPopupTrigger()) {
84             // see if anything is selected
85
TreePath path = folderTree.getClosestPathForLocation(e.getX(), e.getY());
86             if (folderTree.getPathBounds(path).contains(e.getX(), e.getY())) {
87               // this means that we're clicking on a node. make
88
// sure that it's selected.
89

90               if (!folderTree.isPathSelected(path))
91                 folderTree.setSelectionPath(path);
92             }
93
94             MailTreeNode tmpNode = getSelectedNode();
95             if (tmpNode != null) {
96               tmpNode.showPopupMenu(folderTree, e);
97
98             }
99           }
100         }
101
102         public void mouseReleased(MouseEvent e) {
103           if (e.isPopupTrigger()) {
104             // see if anything is selected
105
TreePath path = folderTree.getClosestPathForLocation(e.getX(), e.getY());
106             if (folderTree.getPathBounds(path).contains(e.getX(), e.getY())) {
107               // this means that we're clicking on a node. make
108
// sure that it's selected.
109

110               if (!folderTree.isPathSelected(path))
111                 folderTree.setSelectionPath(path);
112             }
113
114             MailTreeNode tmpNode = getSelectedNode();
115             if (tmpNode != null) {
116               tmpNode.showPopupMenu(folderTree, e);
117
118             }
119           }
120         }
121       });
122
123     folderTree.addTreeSelectionListener(new TreeSelectionListener() {
124         public void valueChanged(javax.swing.event.TreeSelectionEvent JavaDoc e) {
125           getMainPanel().refreshActiveMenus();
126           getMainPanel().refreshCurrentUser();
127           refreshActiveMenus();
128           keyBindings.setActive(getActions());
129         }
130       });
131
132     folderTree.setCellRenderer(new EnhancedFolderTreeCellRenderer());
133
134     mDropTarget = new FolderTreeDropTarget();
135     mTransferHandler = new net.suberic.pooka.gui.dnd.FolderTransferHandler();
136     folderTree.setDropTarget(mDropTarget);
137
138     folderTree.setTransferHandler(mTransferHandler);
139
140     keyBindings = new ConfigurableKeyBinding(this, "FolderPanel.keyBindings", Pooka.getResources());
141     keyBindings.setActive(getActions());
142
143     // if the FolderPanel itself ever gets focus, pass it on to the
144
// folderTree.
145
this.addFocusListener(new FocusAdapter() {
146         public void focusGained(FocusEvent e) {
147           folderTree.requestFocusInWindow();
148         }
149       });
150
151     Pooka.getHelpBroker().enableHelpKey(this, "ui.folderPanel", Pooka.getHelpBroker().getHelpSet());
152
153     this.configureInterfaceStyle();
154
155   }
156
157   /**
158    * Configures the interfaceStyle for this Pane.
159    */

160   public void configureInterfaceStyle() {
161     configureInterfaceStyle(false);
162   }
163
164   private void configureInterfaceStyle(boolean pForce) {
165     final boolean force = pForce;
166     Runnable JavaDoc runMe = new Runnable JavaDoc() {
167         public void run() {
168           try {
169             Pooka.getUIFactory().getPookaThemeManager().updateUI(FolderPanel.this, FolderPanel.this, force);
170             LinkedList JavaDoc allNodes = getAllNodes();
171             for (int i = 0; i < allNodes.size(); i++) {
172               Object JavaDoc currentNode = allNodes.get(i);
173               if (currentNode instanceof MailTreeNode) {
174                 ((MailTreeNode) currentNode).updatePopupTheme();
175               }
176             }
177           } catch (Exception JavaDoc e) {
178
179           }
180         }
181       };
182
183     if (! SwingUtilities.isEventDispatchThread()) {
184       SwingUtilities.invokeLater(runMe);
185     } else {
186       runMe.run();
187     }
188
189   }
190
191   /**
192    * Gets the Theme object from the ThemeManager which is appropriate
193    * for this UI.
194    */

195   public MetalTheme JavaDoc getTheme(ThemeManager tm) {
196     String JavaDoc id = Pooka.getProperty("Pooka.folderPanel.theme", "");
197     if (id != null && ! id.equals("")) {
198       return tm.getTheme(id);
199     }
200
201     return tm.getDefaultTheme();
202   }
203
204   /**
205    * Gets the currently configured Theme.
206    */

207   public MetalTheme JavaDoc getCurrentTheme() {
208     return currentTheme;
209   }
210
211   /**
212    * Sets the Theme that this component is currently using.
213    */

214   public void setCurrentTheme(MetalTheme JavaDoc newTheme) {
215     if (currentTheme != null && currentTheme instanceof ConfigurableMetalTheme) {
216       ((ConfigurableMetalTheme)currentTheme).removeThemeListener(this);
217     }
218     currentTheme = newTheme;
219
220     if (currentTheme != null && currentTheme instanceof ConfigurableMetalTheme) {
221       ((ConfigurableMetalTheme)currentTheme).addThemeListener(this);
222     }
223   }
224
225   /**
226    * Called when the specifics of a Theme change.
227    */

228   public void themeChanged(ConfigurableMetalTheme theme) {
229     // we should really only be getting messages from our own current themes,
230
// but, hey, it never hurts to check.
231
if (currentTheme != null && currentTheme == theme) {
232       SwingUtilities.invokeLater(new Runnable JavaDoc() {
233           public void run() {
234             configureInterfaceStyle(true);
235           }
236         });
237     }
238   }
239
240   /**
241    * This returns the currently highlighted node on the FolderTree.
242    */

243   public MailTreeNode getSelectedNode() {
244     TreePath tp = folderTree.getSelectionPath();
245
246     if (tp != null) {
247       return (MailTreeNode)tp.getLastPathComponent();
248     } else {
249       return null;
250     }
251   }
252
253   /**
254    * This creates the tree root from the StoreList of the StoreManager.
255    */

256   private MailTreeNode createTreeRoot() {
257     MailTreeNode root = new MailTreeNode("Pooka", this);
258
259     synchronized(root) {
260       // Get the stores we have listed.
261
String JavaDoc storeID = null;
262
263       Vector JavaDoc allStoreInfos = Pooka.getStoreManager().getStoreList();
264       for (int i = 0; i < allStoreInfos.size(); i++) {
265         StoreNode storenode = new StoreNode((StoreInfo)allStoreInfos.elementAt(i), this);
266         root.add(storenode);
267       }
268
269       Pooka.getStoreManager().addItemListChangeListener(this);
270     }
271     return root;
272   }
273
274   /**
275    * refreshStores(e) goes through the list of registered stores and
276    * compares these to the value of the "Store" property. If any
277    * stores are no longer listed in that property, they are removed
278    * from the FolderPanel. If any new stores are found, they are
279    * added to the FolderPanel.
280    *
281    * This function does not add new subfolders to already existing
282    * Stores. Use refreshStore(Store) for that.
283    *
284    * This function is usually called in response to a ValueChanged
285    * action on the "Store" property.
286    */

287   public void refreshStores(ItemListChangeEvent ilce) {
288     final ItemListChangeEvent e = ilce;
289     SwingUtilities.invokeLater(new Runnable JavaDoc() {
290         public void run() {
291           Item[] removed = e.getRemoved();
292           Item[] added = e.getAdded();
293           MailTreeNode root = (MailTreeNode)getFolderTree().getModel().getRoot();
294           synchronized(root) {
295             if (removed != null && removed.length > 0) {
296               int[] removedIndices = new int[removed.length];
297               Object JavaDoc[] removedObjects = new Object JavaDoc[removed.length];
298               for (int i = 0; removed != null && i < removed.length; i++) {
299
300                 StoreInfo currentStore = (StoreInfo) removed[i];
301
302                 if (currentStore != null) {
303                   StoreNode sn = currentStore.getStoreNode();
304                   if (sn != null) {
305                     removedObjects[i] = sn;
306                     removedIndices[i] = root.getIndex(sn);
307                     root.remove(sn);
308                   }
309                 }
310               }
311               java.util.Arrays.sort(removedIndices);
312               ((DefaultTreeModel)getFolderTree().getModel()).nodesWereRemoved(root, removedIndices, removedObjects);
313             }
314
315             if (added != null && added.length > 0) {
316               int[] addedIndices = new int[added.length];
317               for (int i = 0; added != null && i < added.length ; i++) {
318                 StoreNode storenode = new StoreNode((StoreInfo)added[i], FolderPanel.this);
319                 root.add(storenode);
320                 addedIndices[i] = root.getIndex(storenode);
321                 //addStore((StoreInfo)added[i] , root);
322
}
323               ((DefaultTreeModel)getFolderTree().getModel()).nodesWereInserted(root, addedIndices);
324             }
325
326             currentTheme = null;
327             configureInterfaceStyle();
328           }
329         }
330       });
331   }
332
333
334   /**
335    * This creates a new StoreNode from the StoreInfo, and adds that
336    * StoreNode to the root of the FolderTree.
337    */

338   /*
339   public void addStore(StoreInfo store, MailTreeNode root) {
340     synchronzied(root) {
341       StoreNode storenode = new StoreNode(store, this);
342       root.add(storenode);
343     }
344   }
345   */

346
347   public MainPanel getMainPanel() {
348     return mainPanel;
349   }
350
351   public JTree getFolderTree() {
352     return folderTree;
353   }
354
355   /**
356    * Specified by interface net.suberic.util.ItemListChangeListener
357    *
358    */

359   public void itemListChanged(ItemListChangeEvent e) {
360     refreshStores(e);
361   }
362
363   /**
364    * Gets all of the children of the tree.
365    */

366   public LinkedList JavaDoc getAllNodes() {
367     Object JavaDoc root = folderModel.getRoot();
368     return parseTree(folderModel, root);
369   }
370
371   /**
372    * parses the tree.
373    */

374   public LinkedList JavaDoc parseTree(TreeModel tm, Object JavaDoc root) {
375     LinkedList JavaDoc returnValue = new LinkedList JavaDoc();
376     if (! tm.isLeaf(root)) {
377       int numChild = tm.getChildCount(root);
378       for (int i = 0; i < numChild; i++) {
379         Object JavaDoc child = tm.getChild(root, i);
380         returnValue.addAll(parseTree(tm, child));
381       }
382     }
383
384     returnValue.add(root);
385     return returnValue;
386   }
387
388   /**
389    * Specified by interface net.suberic.pooka.UserProfileContainer
390    */

391   public UserProfile getDefaultProfile() {
392     MailTreeNode selectedNode = getSelectedNode();
393
394     if (selectedNode != null && selectedNode instanceof UserProfileContainer)
395       return ((UserProfileContainer)selectedNode).getDefaultProfile();
396     else
397       return null;
398   }
399
400   /**
401    * Gets the FolderPanelToolbar.
402    */

403   public ConfigurableToolbar getFolderPanelToolbar() {
404     return folderPanelToolbar;
405   }
406
407   /**
408    * Sets the FolderPanelToolbar.
409    */

410   public void setFolderPanelToolbar(ConfigurableToolbar newFolderPanelToolbar) {
411     if (folderPanelToolbar != null)
412       this.remove(folderPanelToolbar);
413
414     folderPanelToolbar = newFolderPanelToolbar;
415
416     if (folderPanelToolbar != null)
417       this.add("North", folderPanelToolbar);
418
419   }
420
421   /**
422    * Refreshes the active menus for the FolderPanel.
423    */

424   public void refreshActiveMenus() {
425     if (folderPanelToolbar != null)
426       folderPanelToolbar.setActive(getActions());
427   }
428
429   public Action JavaDoc[] getActions() {
430     if (getSelectedNode() != null) {
431       Action JavaDoc[] nodeActions = getSelectedNode().getActions();
432       if (nodeActions != null)
433         return TextAction.augmentList(nodeActions, defaultActions);
434     }
435
436     return defaultActions;
437   }
438
439   /**
440    * Handles drag and drop events over the JTree.
441    */

442   class FolderTreeDropTarget extends DropTarget {
443     public void dragOver(DropTargetDragEvent dtde) {
444       // first see if we accept this drag.
445
if (mTransferHandler.canImport(folderTree, dtde.getCurrentDataFlavors())) {
446
447         Point e = dtde.getLocation();
448
449         TreePath path = folderTree.getClosestPathForLocation(e.x, e.y);
450
451         if (folderTree.getPathBounds(path).contains(e.x, e.y)) {
452           // check to see if this is a folder node or not. at the moment,
453
// we only support dropping into folder nodes.
454
if (path.getLastPathComponent() instanceof FolderNode) {
455             // this means that we're over a node. make it selected.
456
if (!folderTree.isPathSelected(path))
457               folderTree.setSelectionPath(path);
458
459             // and, since we can support dropping here, offer this as a
460
// drop target.
461

462
463           }
464         }
465       }
466     }
467
468     public void drop(DropTargetDropEvent dtde) {
469       boolean accept = false;
470       // first see if we accept this drag.
471
if (mTransferHandler.canImport(folderTree, dtde.getCurrentDataFlavors())) {
472
473         Point e = dtde.getLocation();
474
475         TreePath path = folderTree.getClosestPathForLocation(e.x, e.y);
476
477         if (folderTree.getPathBounds(path).contains(e.x, e.y)) {
478           // check to see if this is a folder node or not. at the moment,
479
// we only support dropping into folder nodes.
480
if (path.getLastPathComponent() instanceof FolderNode) {
481             // this means that we're over a node. make it selected.
482
if (!folderTree.isPathSelected(path))
483               folderTree.setSelectionPath(path);
484
485             // and now drop here.
486
accept = true;
487
488             dtde.acceptDrop(dtde.getDropAction());
489
490             try {
491               java.awt.datatransfer.Transferable JavaDoc trans = dtde.getTransferable();
492               boolean returnValue = mTransferHandler.importData(folderTree, trans);
493               dtde.dropComplete(returnValue);
494             } catch (RuntimeException JavaDoc re) {
495               dtde.dropComplete(false);
496             }
497           }
498         }
499       }
500
501       if (! accept) {
502         dtde.rejectDrop();
503       }
504     }
505   }
506
507   public class NewMessageAction extends AbstractAction {
508     NewMessageAction() {
509       super("message-new");
510     }
511
512     public void actionPerformed(ActionEvent e) {
513       try {
514         MessageUI nmu = Pooka.getUIFactory().createMessageUI(new NewMessageProxy(new net.suberic.pooka.NewMessageInfo(new javax.mail.internet.MimeMessage JavaDoc(mainPanel.getSession()))));
515         nmu.openMessageUI();
516       } catch (MessagingException me) {
517         Pooka.getUIFactory().showError(Pooka.getProperty("error.NewMessage.errorLoadingMessage", "Error creating new message: ") + "\n" + me.getMessage(), Pooka.getProperty("error.NewMessage.errorLoadingMessage.title", "Error creating new message."), me);
518       }
519
520     }
521
522   }
523
524
525 }
526
527
528
529
530
531
Popular Tags