KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.suberic.pooka.gui;
2
3 import javax.swing.tree.DefaultMutableTreeNode JavaDoc;
4 import javax.swing.JComponent JavaDoc;
5 import javax.mail.*;
6 import net.suberic.pooka.Pooka;
7 import net.suberic.pooka.FolderInfo;
8 import net.suberic.pooka.StoreInfo;
9 import net.suberic.util.thread.ActionWrapper;
10 import net.suberic.pooka.gui.search.*;
11 import net.suberic.pooka.gui.filechooser.*;
12 import java.util.StringTokenizer JavaDoc;
13 import java.util.Vector JavaDoc;
14 import java.util.Enumeration JavaDoc;
15 import java.util.logging.Logger JavaDoc;
16 import javax.swing.*;
17 import java.awt.Cursor JavaDoc;
18 import javax.mail.event.*;
19
20 /**
21  * The display in the FolderPanel for a Store.
22  */

23 public class StoreNode extends MailTreeNode {
24
25   protected StoreInfo store = null;
26   protected String JavaDoc displayName = null;
27   protected boolean hasLoaded = false;
28
29   public StoreNode(StoreInfo newStore, JComponent JavaDoc parent) {
30     super(newStore, parent);
31     store = newStore;
32     newStore.setStoreNode(this);
33     displayName=Pooka.getProperty("Store." + store.getStoreID() + ".displayName", store.getStoreID());
34     setCommands();
35     loadChildren();
36     defaultActions = new Action[] {
37       new ActionWrapper(new OpenAction(), getStoreInfo().getStoreThread()),
38       new ActionWrapper(new SubscribeAction(), getStoreInfo().getStoreThread()),
39       new TestAction(),
40       new NewFolderAction(),
41       new ActionWrapper(new DisconnectAction(), getStoreInfo().getStoreThread()),
42       new EditAction(),
43       new StatusAction()
44     };
45
46   }
47
48   /**
49    * this method returns false--a store is never a leaf.
50    */

51   public boolean isLeaf() {
52     return false;
53   }
54
55
56   /**
57    * This loads or updates the top-level children of the Store.
58    */

59   public void loadChildren() {
60     Runnable JavaDoc runMe = new Runnable JavaDoc() {
61         public void run() {
62           doLoadChildren();
63         }
64       };
65
66     if (SwingUtilities.isEventDispatchThread())
67       doLoadChildren();
68     else {
69       try {
70         SwingUtilities.invokeAndWait(runMe);
71       } catch (Exception JavaDoc ie) {
72       }
73     }
74   }
75
76   /**
77    * Does the actual work for loading the children. performed on the swing
78    * gui thread.
79    */

80   private void doLoadChildren() {
81     Logger JavaDoc logger = Logger.getLogger("Store." + getStoreInfo().getStoreID());
82     logger.fine("calling loadChildren() for " + getStoreInfo().getStoreID());
83
84     Enumeration JavaDoc origChildren = super.children();
85     Vector JavaDoc origChildrenVector = new Vector JavaDoc();
86     while (origChildren.hasMoreElements())
87       origChildrenVector.add(origChildren.nextElement());
88
89     logger.fine(getStoreInfo().getStoreID() + ": origChildrenVector.size() = " + origChildrenVector.size());
90
91     Vector JavaDoc storeChildren = getStoreInfo().getChildren();
92
93     logger.fine(getStoreInfo().getStoreID() + ": storeChildren.size() = " + storeChildren.size());
94
95     if (storeChildren != null) {
96       for (int i = 0; i < storeChildren.size(); i++) {
97         FolderNode node = popChild(((FolderInfo)storeChildren.elementAt(i)).getFolderName(), origChildrenVector);
98         if (node == null) {
99           node = new FolderNode((FolderInfo)storeChildren.elementAt(i), getParentContainer());
100           // we used insert here, since add() would mak
101
// another recursive call to getChildCount();
102
insert(node, 0);
103         }
104       }
105
106     }
107
108     removeChildren(origChildrenVector);
109
110     hasLoaded=true;
111
112
113     javax.swing.JTree JavaDoc folderTree = ((FolderPanel)getParentContainer()).getFolderTree();
114     if (folderTree != null && folderTree.getModel() instanceof javax.swing.tree.DefaultTreeModel JavaDoc) {
115       ((javax.swing.tree.DefaultTreeModel JavaDoc)folderTree.getModel()).nodeStructureChanged(this);
116     }
117
118   }
119
120   /**
121    * This goes through the Vector of FolderNodes provided and
122    * returns the FolderNode for the given childName, if one exists.
123    * It will also remove the Found FolderNode from the childrenList
124    * Vector.
125    *
126    * If a FolderNode that corresponds with the given childName does
127    * not exist, this returns null.
128    *
129    */

130   public FolderNode popChild(String JavaDoc childName, Vector JavaDoc childrenList) {
131     if (children != null) {
132       for (int i = 0; i < childrenList.size(); i++)
133         if (((FolderNode)childrenList.elementAt(i)).getFolderInfo().getFolderName().equals(childName)) {
134           FolderNode fn = (FolderNode)childrenList.elementAt(i);
135           childrenList.remove(fn);
136           return fn;
137         }
138     }
139
140     // no match.
141
return null;
142   }
143
144   /**
145    * This removes all the items in removeList from the list of this
146    * node's children.
147    */

148   public void removeChildren(Vector JavaDoc removeList) {
149     for (int i = 0; i < removeList.size(); i++) {
150       if (removeList.elementAt(i) instanceof javax.swing.tree.MutableTreeNode JavaDoc)
151         this.remove((javax.swing.tree.MutableTreeNode JavaDoc)removeList.elementAt(i));
152     }
153   }
154
155   /**
156    * This creates the current PopupMenu if there is not one. It then
157    * will configure the PopupMenu with the current actions.
158    *
159    * Overrides MailTreeNode.configurePopupMenu();
160    */

161
162   public void configurePopupMenu() {
163     if (popupMenu == null) {
164       popupMenu = new net.suberic.util.gui.ConfigurablePopupMenu();
165       popupMenu.configureComponent("StoreNode.popupMenu", Pooka.getResources());
166       updatePopupTheme();
167     }
168
169     popupMenu.setActive(getActions());
170
171   }
172
173   /**
174    * This opens up a dialog asking if the user wants to subscribe to a
175    * subfolder.
176    */

177   public void newFolder() {
178     String JavaDoc message = Pooka.getProperty("Folder.newFolder", "Subscribe/create new subfolder of") + " " + getStoreInfo().getStoreID();
179
180     JLabel messageLabel = new JLabel(message);
181
182     JPanel typePanel = new JPanel();
183     typePanel.setBorder(BorderFactory.createEtchedBorder());
184
185     JRadioButton messagesButton = new JRadioButton(Pooka.getProperty("Folder.new.messages.label", "Contains Messages"), true);
186     JRadioButton foldersButton = new JRadioButton(Pooka.getProperty("Folder.new.folders.label", "Contains Folders"));
187
188     ButtonGroup bg = new ButtonGroup();
189     bg.add(messagesButton);
190     bg.add(foldersButton);
191
192     typePanel.add(messagesButton);
193     typePanel.add(foldersButton);
194
195     Object JavaDoc[] inputPanels = new Object JavaDoc[] {
196       messageLabel,
197       typePanel
198     };
199
200     final String JavaDoc response = Pooka.getUIFactory().showInputDialog(inputPanels, Pooka.getProperty("Folder.new.title", "Create new Folder"));
201
202     int type = javax.mail.Folder.HOLDS_MESSAGES;
203     if (foldersButton.isSelected()) {
204       type = javax.mail.Folder.HOLDS_FOLDERS;
205     }
206
207     final int finalType = type;
208
209     if (response != null && response.length() > 0) {
210       getStoreInfo().getStoreThread().addToQueue(new javax.swing.AbstractAction JavaDoc() {
211           public void actionPerformed(java.awt.event.ActionEvent JavaDoc e) {
212             try {
213               getStoreInfo().createSubFolder(response, finalType);
214             } catch (MessagingException me) {
215               final Exception JavaDoc fme = me;
216               SwingUtilities.invokeLater(new Runnable JavaDoc() {
217                   public void run() {
218                     Pooka.getUIFactory().showError(fme.getMessage());
219                   }
220                 });
221
222               me.printStackTrace();
223             }
224           }
225         } , new java.awt.event.ActionEvent JavaDoc(this, 0, "folder-new"));
226     }
227   }
228
229   /**
230    * Sets a busy cursor on this node.
231    */

232   public void setBusy(boolean newBusy) {
233     final boolean newValue = newBusy;
234
235     Runnable JavaDoc runMe = new Runnable JavaDoc() {
236         public void run() {
237           if (newValue)
238             getParentContainer().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
239           else
240             getParentContainer().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
241         }
242       };
243
244     if (SwingUtilities.isEventDispatchThread())
245       runMe.run();
246     else
247       SwingUtilities.invokeLater(runMe);
248
249   }
250
251   /**
252    * Returns the StoreID of this node's folder, or null if no StoreInfo
253    * is set.
254    */

255   public String JavaDoc getStoreID() {
256     if (store != null)
257       return store.getStoreID();
258     else
259       return null;
260   }
261
262   /**
263    * Returns the StoreInfo of this node's folder, or null if no StoreInfo
264    * is set.
265    */

266   public StoreInfo getStoreInfo() {
267     return store;
268   }
269
270   /**
271    * We override toString() so we can display the store URLName
272    * without the password.
273    */

274   public String JavaDoc toString() {
275     return displayName;
276   }
277
278   public boolean isConnected() {
279     if (store != null) {
280       return store.isConnected();
281     } else
282       return false;
283   }
284
285   public Action[] defaultActions;
286
287   public Action[] getDefaultActions() {
288     return defaultActions;
289   }
290
291   class OpenAction extends AbstractAction {
292
293     OpenAction() {
294       super("file-open");
295       this.putValue(Action.SHORT_DESCRIPTION, "file-open on Store " + getStoreID());
296     }
297
298     OpenAction(String JavaDoc nm) {
299       super(nm);
300     }
301
302     public void actionPerformed(java.awt.event.ActionEvent JavaDoc e) {
303       if (!store.isConnected())
304         try {
305           store.connectStore();
306         } catch (MessagingException me) {
307           // I should make this easier.
308
Pooka.getUIFactory().showError(Pooka.getProperty("error.Store.connectionFailed", "Failed to open connection to Mail Store."), me);
309         }
310       javax.swing.JTree JavaDoc folderTree = ((FolderPanel)getParentContainer()).getFolderTree();
311       folderTree.expandPath(folderTree.getSelectionPath());
312     }
313   }
314
315   class SubscribeAction extends AbstractAction {
316
317     SubscribeAction() {
318       super("folder-subscribe");
319
320     }
321
322     public void actionPerformed(java.awt.event.ActionEvent JavaDoc e) {
323       SwingUtilities.invokeLater(new Runnable JavaDoc() {
324           public void run() {
325             Pooka.getUIFactory().showStatusMessage("Connecting to " + getStoreInfo().getStoreID() + " to get list of folders...");
326             setBusy(true);
327           }
328         });
329
330       // this is happening on the store thread.
331
final MailFileSystemView mfsv = new MailFileSystemView(getStoreInfo());
332
333       SwingUtilities.invokeLater(new Runnable JavaDoc() {
334           public void run() {
335             final Logger JavaDoc storeLogger = Logger.getLogger("Store." + getStoreInfo().getStoreID());
336             final Logger JavaDoc guiLogger = Logger.getLogger("Pooka.debug.gui.filechooser");
337
338             JFileChooser jfc =
339               new JFileChooser(getStoreInfo().getStoreID(), mfsv);
340             jfc.setMultiSelectionEnabled(true);
341             jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
342             int returnValue =
343               jfc.showDialog(getParentContainer(),
344                              Pooka.getProperty("FolderEditorPane.Select",
345                                                "Select"));
346             if (returnValue == JFileChooser.APPROVE_OPTION) {
347               guiLogger.fine("got " + jfc.getSelectedFile() + " as a return value.");
348
349               final java.io.File JavaDoc[] selectedFiles = jfc.getSelectedFiles();
350
351               getStoreInfo().getStoreThread().addToQueue(new javax.swing.AbstractAction JavaDoc() {
352                   public void actionPerformed(java.awt.event.ActionEvent JavaDoc ae) {
353                     for (int i = 0 ; selectedFiles != null && i < selectedFiles.length; i++) {
354                       net.suberic.pooka.gui.filechooser.FolderFileWrapper wrapper = (net.suberic.pooka.gui.filechooser.FolderFileWrapper) selectedFiles[i];
355                       try {
356                         // if it doesn't exist, try to create it.
357
if (! wrapper.exists()) {
358                           wrapper.getFolder().create(Folder.HOLDS_MESSAGES);
359                         }
360                         String JavaDoc absFileName = wrapper.getAbsolutePath();
361                         int firstSlash = absFileName.indexOf('/');
362                         String JavaDoc normalizedFileName = absFileName;
363                         if (firstSlash >= 0)
364                           normalizedFileName = absFileName.substring(firstSlash);
365
366                         guiLogger.fine("adding folder " + normalizedFileName + "; absFileName = " + absFileName);
367                         storeLogger.fine("adding folder " + normalizedFileName);
368
369                         getStoreInfo().subscribeFolder(normalizedFileName);
370                       } catch (MessagingException me) {
371                         final String JavaDoc folderName = wrapper.getName();
372                         SwingUtilities.invokeLater(new Runnable JavaDoc() {
373                             public void run() {
374                               Pooka.getUIFactory().showError(Pooka.getProperty("error.creatingFolder", "Error creating folder ") + folderName);
375                             }
376                           });
377                       }
378                     }
379                   }
380                 }, new java.awt.event.ActionEvent JavaDoc(this, 0, "folder-subscribe"));
381             }
382
383             Pooka.getUIFactory().clearStatus();
384             setBusy(false);
385           }
386         });
387     }
388   }
389
390   class TestAction extends AbstractAction {
391
392     TestAction() {
393       super("file-test");
394     }
395
396     public void actionPerformed(java.awt.event.ActionEvent JavaDoc e) {
397
398     }
399
400   }
401
402   class DisconnectAction extends AbstractAction {
403
404     DisconnectAction() {
405       super("file-close");
406     }
407
408     public void actionPerformed(java.awt.event.ActionEvent JavaDoc e) {
409       try {
410         getStoreInfo().disconnectStore();
411       } catch (Exception JavaDoc ex) {
412         System.out.println("caught exception: " + ex.getMessage());
413       }
414     }
415   }
416
417   class NewFolderAction extends AbstractAction {
418
419     NewFolderAction() {
420       super("folder-new");
421     }
422
423     public void actionPerformed(java.awt.event.ActionEvent JavaDoc e) {
424       newFolder();
425     }
426
427   }
428
429   class EditAction extends AbstractAction {
430
431     EditAction() {
432       super("file-edit");
433     }
434
435     EditAction(String JavaDoc nm) {
436       super(nm);
437     }
438
439     public void actionPerformed(java.awt.event.ActionEvent JavaDoc e) {
440       Pooka.getUIFactory().showEditorWindow(getStoreInfo().getStoreProperty(), getStoreInfo().getStoreProperty(), "Store.editor");
441     }
442   }
443
444   class StatusAction extends AbstractAction {
445
446     StatusAction() {
447       super("store-status");
448     }
449
450     public void actionPerformed(java.awt.event.ActionEvent JavaDoc e) {
451       getStoreInfo().showStatus();
452     }
453   }
454 }
455
456
Popular Tags