1 package net.suberic.pooka.gui; 2 import javax.swing.*; 3 import java.awt.Cursor ; 4 import java.awt.event.ActionEvent ; 5 import javax.swing.tree.*; 6 import javax.mail.Store ; 7 import javax.mail.Folder ; 8 import javax.mail.MessagingException ; 9 import java.util.*; 10 import net.suberic.pooka.*; 11 import net.suberic.util.thread.*; 12 import javax.mail.FolderNotFoundException ; 13 import net.suberic.pooka.FolderInfo; 14 import javax.mail.event.*; 15 16 public class FolderNode extends MailTreeNode implements MessageChangedListener, UserProfileContainer, ConnectionListener { 17 18 protected FolderInfo folderInfo = null; 19 protected boolean hasLoaded = false; 20 21 22 28 public FolderNode(FolderInfo newFolderInfo, JComponent newParent) { 29 super(newFolderInfo, newParent); 30 folderInfo = newFolderInfo; 31 32 folderInfo.setFolderNode(this); 33 34 commands = new Hashtable(); 35 36 defaultActions = new Action[] { 37 new ActionWrapper(new OpenAction(), folderInfo.getFolderThread()), 38 new ActionWrapper(new ReconnectAction(), folderInfo.getFolderThread()), 39 new ActionWrapper(new CloseAction(), folderInfo.getFolderThread()), 40 new UnsubscribeAction(), 41 new NewFolderAction(), 42 new DeleteAction() 43 }; 44 45 Action[] actions = defaultActions; 46 47 if (actions != null) { 48 for (int i = 0; i < actions.length; i++) { 49 Action a = actions[i]; 50 commands.put(a.getValue(Action.NAME), a); 51 } 52 } 53 54 folderInfo.addMessageCountListener(new MessageCountAdapter() { 55 public void messagesAdded(MessageCountEvent e) { 56 if ( folderInfo.notifyNewMessagesMain()) { 57 Pooka.getUIFactory().getMessageNotificationManager().notifyNewMessagesReceived(e, getFolderInfo().getFolderID()); 58 } 59 updateNode(); 60 } 61 62 public void messagesRemoved(MessageCountEvent e) { 63 updateNode(); 64 65 } 66 }); 67 68 folderInfo.addMessageChangedListener(this); 69 folderInfo.addConnectionListener(this); 70 loadChildren(); 71 72 } 73 74 75 78 public boolean isLeaf() { 79 if (getChildCount() < 1) 80 return true; 81 else 82 return false; 83 } 84 85 88 public Folder getFolder() { 89 return folderInfo.getFolder(); 90 } 91 92 98 public void loadChildren() { 99 Runnable runMe = new Runnable () { 100 public void run() { 101 doLoadChildren(); 102 } 103 }; 104 105 if (SwingUtilities.isEventDispatchThread()) 106 doLoadChildren(); 107 else { 108 try { 109 SwingUtilities.invokeAndWait(runMe); 110 } catch (Exception ie) { 111 } 112 } 113 } 114 115 119 private void doLoadChildren() { 120 Enumeration origChildren = super.children(); 121 Vector origChildrenVector = new Vector(); 122 while (origChildren.hasMoreElements()) 123 origChildrenVector.add(origChildren.nextElement()); 124 125 Vector folderChildren = getFolderInfo().getChildren(); 126 127 if (folderChildren != null) { 128 for (int i = 0; i < folderChildren.size(); i++) { 129 FolderNode node = popChild(((FolderInfo)folderChildren.elementAt(i)).getFolderName(), origChildrenVector); 130 if (node == null) { 131 node = new FolderNode((FolderInfo)folderChildren.elementAt(i), getParentContainer()); 132 insert(node, 0); 135 } 136 } 137 138 } 139 140 removeChildren(origChildrenVector); 141 142 hasLoaded=true; 143 144 } 146 147 157 public FolderNode popChild(String childName, Vector childrenList) { 158 if (children != null) { 159 for (int i = 0; i < childrenList.size(); i++) 160 if (((FolderNode)childrenList.elementAt(i)).getFolderInfo().getFolderName().equals(childName)) { 161 FolderNode fn = (FolderNode)childrenList.elementAt(i); 162 childrenList.remove(fn); 163 return fn; 164 } 165 } 166 167 return null; 169 } 170 171 177 178 public void configurePopupMenu() { 179 if (popupMenu == null) { 180 popupMenu = new net.suberic.util.gui.ConfigurablePopupMenu(); 181 if (getFolderInfo().isTrashFolder()) 182 popupMenu.configureComponent("TrashFolderNode.popupMenu", Pooka.getResources()); 183 else if (getFolderInfo().isOutboxFolder()) 184 popupMenu.configureComponent("OutboxFolderNode.popupMenu", Pooka.getResources()); 185 else if (getFolderInfo() instanceof net.suberic.pooka.cache.CachingFolderInfo && ! ((net.suberic.pooka.cache.CachingFolderInfo) getFolderInfo()).getCacheHeadersOnly()) 186 popupMenu.configureComponent("CachingFolderNode.popupMenu", Pooka.getResources()); 187 else 188 popupMenu.configureComponent("FolderNode.popupMenu", Pooka.getResources()); 189 190 updatePopupTheme(); 191 192 } 193 194 popupMenu.setActive(getActions()); 195 } 196 197 201 public void removeChildren(Vector removeList) { 202 for (int i = 0; i < removeList.size(); i++) { 203 if (removeList.elementAt(i) instanceof javax.swing.tree.MutableTreeNode ) 204 this.remove((javax.swing.tree.MutableTreeNode )removeList.elementAt(i)); 205 } 206 } 207 208 211 public void makeVisible() { 212 javax.swing.SwingUtilities.invokeLater(new Runnable () { 213 public void run() { 214 javax.swing.JTree folderTree = ((FolderPanel)getParentContainer()).getFolderTree(); 215 TreeNode[] nodeList = ((DefaultTreeModel)folderTree.getModel()).getPathToRoot(FolderNode.this); 216 TreePath path = new TreePath(nodeList); 217 folderTree.makeVisible(path); 218 } 219 }); 220 } 221 222 public void messageChanged(MessageChangedEvent mce) { 223 updateNode(); 224 } 225 226 public void closed(ConnectionEvent e) { 227 updateNode(); 228 } 229 230 public void opened(ConnectionEvent e) { 231 updateNode(); 232 } 233 234 public void disconnected(ConnectionEvent e) { 235 updateNode(); 236 } 237 238 239 int lastFolderStatus = -1; 240 boolean lastUnread = false; 241 boolean lastNewMessages = false; 242 243 247 public void updateNode() { 248 javax.swing.SwingUtilities.invokeLater(new Runnable () { 249 public void run() { 250 FolderInfo fi = getFolderInfo(); 251 if (fi != null) { 252 int currentStatus = fi.getStatus(); 253 boolean hasUnread = fi.hasUnread(); 254 boolean hasNewMessages = fi.hasNewMessages(); 255 256 if (currentStatus != lastFolderStatus || hasUnread != lastUnread || hasNewMessages != lastNewMessages) { 257 lastFolderStatus = currentStatus; 258 lastUnread = hasUnread; 259 lastNewMessages = hasNewMessages; 260 javax.swing.JTree folderTree = ((FolderPanel)getParentContainer()).getFolderTree(); 262 ((DefaultTreeModel)folderTree.getModel()).nodeChanged(FolderNode.this); 263 } 264 } 265 } 266 }); 267 } 268 269 274 public void unsubscribeFolder() { 275 String message; 276 if (isLeaf()) 277 message = Pooka.getProperty("Folder.unsubscribeConfirm", "Do you really want to unsubscribe from the following folder?"); 278 else 279 message = Pooka.getProperty("Folder.unsubscribeConfirm.notLeaf", "Do you really want to unsubscribe from \nthis folder and all its children?"); 280 281 int response = Pooka.getUIFactory().showConfirmDialog(message + "\n" + getFolderInfo().getFolderName(), Pooka.getProperty("Folder.unsubscribeConfirm.title", "Unsubscribe from Folder"), JOptionPane.YES_NO_OPTION); 282 283 if (response == JOptionPane.YES_OPTION) { 284 getFolderInfo().getFolderThread().addToQueue(new javax.swing.AbstractAction () { 285 public void actionPerformed(java.awt.event.ActionEvent e) { 286 getFolderInfo().unsubscribe(); 287 } 288 } , new java.awt.event.ActionEvent (this, 0, "folder-unsubscribe")); 289 } 290 } 291 292 297 public void deleteFolder() { 298 String message; 299 if (isLeaf()) 300 message = Pooka.getProperty("Folder.deleteConfirm", "Do you really want to delete from the following folder?"); 301 else 302 message = Pooka.getProperty("Folder.deleteConfirm.notLeaf", "Do you really want to delete \nthis folder and all its children?"); 303 304 int response = Pooka.getUIFactory().showConfirmDialog(message + "\n" + getFolderInfo().getFolderName(), Pooka.getProperty("Folder.deleteConfirm.title", "Delete Folder"), JOptionPane.YES_NO_OPTION); 305 306 if (response == JOptionPane.YES_OPTION) { 307 message = Pooka.getProperty("Folder.deleteConfirm.secondMessage", "Are you sure? This will permanently remove the folder and all of its messages"); 308 int responseTwo = Pooka.getUIFactory().showConfirmDialog(message, Pooka.getProperty("Folder.deleteConfirm.secondMessage.title", "Are you sure?"), JOptionPane.YES_NO_OPTION); 309 if (responseTwo == JOptionPane.YES_OPTION) { 310 311 getFolderInfo().getFolderThread().addToQueue(new javax.swing.AbstractAction () { 312 public void actionPerformed(java.awt.event.ActionEvent e) { 313 try { 314 getFolderInfo().delete(); 315 } catch(MessagingException me) { 316 final Exception fme = me; 317 SwingUtilities.invokeLater(new Runnable () { 318 public void run() { 319 Pooka.getUIFactory().showError("Error deleting folder: ", fme); 320 } 321 }); 322 } 323 } 324 } , new java.awt.event.ActionEvent (this, 0, "folder-delete")); 325 } 326 } 327 } 328 329 333 public void newFolder() { 334 if ((getFolderInfo().getType() & Folder.HOLDS_FOLDERS) != 0) { 335 String message = Pooka.getProperty("Folder.newFolder", "Subscribe/create new subfolder of") + " " + getFolderInfo().getFolderName(); 336 337 JLabel messageLabel = new JLabel(message); 338 339 JPanel typePanel = new JPanel(); 340 typePanel.setBorder(BorderFactory.createEtchedBorder()); 341 342 JRadioButton messagesButton = new JRadioButton(Pooka.getProperty("Folder.new.messages.label", "Contains Messages"), true); 343 JRadioButton foldersButton = new JRadioButton(Pooka.getProperty("Folder.new.folders.label", "Contains Folders")); 344 345 ButtonGroup bg = new ButtonGroup(); 346 bg.add(messagesButton); 347 bg.add(foldersButton); 348 349 typePanel.add(messagesButton); 350 typePanel.add(foldersButton); 351 352 Object [] inputPanels = new Object [] { 353 messageLabel, 354 typePanel 355 }; 356 357 final String response = Pooka.getUIFactory().showInputDialog(inputPanels, Pooka.getProperty("Folder.new.title", "Create new Folder")); 358 359 int type = javax.mail.Folder.HOLDS_MESSAGES; 360 if (foldersButton.isSelected()) { 361 type = javax.mail.Folder.HOLDS_FOLDERS; 362 } 363 364 final int finalType = type; 365 366 if (response != null && response.length() > 0) { 367 getFolderInfo().getFolderThread().addToQueue(new javax.swing.AbstractAction () { 368 public void actionPerformed(java.awt.event.ActionEvent e) { 369 try { 370 getFolderInfo().createSubFolder(response, finalType); 371 } catch (MessagingException me) { 372 final Exception fme = me; 373 SwingUtilities.invokeLater(new Runnable () { 374 public void run() { 375 Pooka.getUIFactory().showError(fme.getMessage()); 376 } 377 }); 378 379 me.printStackTrace(); 380 } 381 } 382 } , new java.awt.event.ActionEvent (this, 0, "folder-new")); 383 } 384 } 385 } 386 387 390 public void openFolder(boolean pReconnect) { 391 openFolder(pReconnect, true); 392 } 393 394 397 public void openFolder(boolean pReconnect, boolean pSelectFolder) { 398 399 try { 400 getFolderInfo().loadAllMessages(); 401 402 if (! getFolderInfo().isSortaOpen() || (pReconnect && ! getFolderInfo().isConnected())) { 403 getFolderInfo().openFolder(javax.mail.Folder.READ_WRITE, pReconnect); 404 } 405 406 int firstUnread = -1; 407 int messageCount = -1; 408 409 final int folderType = getFolderInfo().getType(); 410 411 if (getFolderInfo().isSortaOpen() && (folderType & Folder.HOLDS_MESSAGES) != 0 && getFolderInfo().getFolderDisplayUI() == null) { 412 firstUnread = getFolderInfo().getFirstUnreadMessage(); 413 messageCount = getFolderInfo().getMessageCount(); 414 } 415 416 final int finalFirstUnread = firstUnread; 417 final int finalMessageCount = messageCount; 418 final boolean fSelectFolder = pSelectFolder; 419 420 SwingUtilities.invokeLater(new Runnable () { 421 public void run() { 422 423 if ((folderType & Folder.HOLDS_MESSAGES) != 0) { 424 if (getFolderInfo().getFolderDisplayUI() != null) { 425 getFolderInfo().getFolderDisplayUI().openFolderDisplay(fSelectFolder); 426 } else { 427 getFolderInfo().setFolderDisplayUI(Pooka.getUIFactory().createFolderDisplayUI(getFolderInfo())); 428 if (Pooka.getProperty("Pooka.autoSelectFirstUnread", "true").equalsIgnoreCase("true")) { 429 if (finalFirstUnread >= 0) 430 getFolderInfo().getFolderDisplayUI().selectMessage(finalFirstUnread); 431 else 432 getFolderInfo().getFolderDisplayUI().selectMessage(finalMessageCount); 433 } else { 434 if (finalFirstUnread >= 0) 435 getFolderInfo().getFolderDisplayUI().makeSelectionVisible(finalFirstUnread); 436 else 437 getFolderInfo().getFolderDisplayUI().makeSelectionVisible(finalMessageCount); 438 439 } 440 getFolderInfo().getFolderDisplayUI().openFolderDisplay(fSelectFolder); 441 } 442 443 } 444 if ((folderType & Folder.HOLDS_FOLDERS) != 0) { 445 javax.swing.JTree folderTree = ((FolderPanel)getParentContainer()).getFolderTree(); 446 folderTree.expandPath(folderTree.getSelectionPath()); 447 } 448 } 449 }); 450 } catch (MessagingException me) { 451 final MessagingException newMe = me; 452 SwingUtilities.invokeLater(new Runnable () { 453 public void run() { 454 Pooka.getUIFactory().showError(Pooka.getProperty("error.Folder.openFailed", "Failed to open folder") + " " + getFolderInfo().getFolderID(), newMe); 455 } 456 }); 457 } 458 459 } 460 461 464 public String getFolderID() { 465 return getFolderInfo().getFolderID(); 466 } 467 468 471 public FolderInfo getFolderInfo() { 472 return folderInfo; 473 } 474 475 479 public String toString() { 480 if (getFolderInfo() != null) { 481 String folderName = getFolderInfo().getFolderName(); 482 if (getFolderInfo().hasUnread()) { 483 return folderName + " (" + getFolderInfo().getUnreadCount() + ")"; 484 } else { 485 return folderName; 486 } 487 } else { 488 return "no folder name"; 489 } 490 } 491 492 493 public UserProfile getDefaultProfile() { 495 if (getFolderInfo() != null) 496 return getFolderInfo().getDefaultProfile(); 497 else 498 return null; 499 } 500 501 public Action[] getActions() { 502 if (getFolderInfo().getActions() != null) 503 return javax.swing.text.TextAction.augmentList(getFolderInfo().getActions(), defaultActions); 504 else 505 return defaultActions; 506 } 507 508 public Action[] defaultActions; 509 510 class OpenAction extends AbstractAction { 511 512 OpenAction() { 513 super("file-open"); 514 } 515 516 OpenAction(String nm) { 517 super(nm); 518 } 519 520 public void actionPerformed(ActionEvent e) { 521 SwingUtilities.invokeLater(new Runnable () { 522 public void run() { 523 ((FolderPanel)getParentContainer()).getMainPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 524 } 525 }); 526 527 openFolder(false); 528 529 SwingUtilities.invokeLater(new Runnable () { 530 public void run() { 531 ((FolderPanel)getParentContainer()).getMainPanel().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 532 } 533 }); 534 } 535 536 } 537 538 class ReconnectAction extends AbstractAction { 539 540 ReconnectAction() { 541 super("folder-connect"); 542 } 543 544 ReconnectAction(String nm) { 545 super(nm); 546 } 547 548 public void actionPerformed(ActionEvent e) { 549 SwingUtilities.invokeLater(new Runnable () { 550 public void run() { 551 ((FolderPanel)getParentContainer()).getMainPanel().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 552 } 553 }); 554 555 openFolder(true); 556 557 SwingUtilities.invokeLater(new Runnable () { 558 public void run() { 559 ((FolderPanel)getParentContainer()).getMainPanel().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 560 } 561 }); 562 } 563 564 } 565 566 class UnsubscribeAction extends AbstractAction { 567 568 UnsubscribeAction() { 569 super("folder-unsubscribe"); 570 } 571 572 public void actionPerformed(ActionEvent e) { 573 unsubscribeFolder(); 574 } 575 576 } 577 578 class DeleteAction extends AbstractAction { 579 580 DeleteAction() { 581 super("folder-delete"); 582 } 583 584 public void actionPerformed(ActionEvent e) { 585 deleteFolder(); 586 } 587 588 } 589 590 class NewFolderAction extends AbstractAction { 591 592 NewFolderAction() { 593 super("folder-new"); 594 } 595 596 public void actionPerformed(ActionEvent e) { 597 newFolder(); 598 } 599 600 } 601 602 class CloseAction extends AbstractAction { 603 604 CloseAction() { 605 super("folder-close"); 606 } 607 608 public void actionPerformed(ActionEvent e) { 609 try { 610 getFolderInfo().closeFolder(false); 611 } catch (Exception ex) { 612 System.out.println("caught exception: " + ex.getMessage()); 613 } 614 } 615 616 } 617 } 618 619 | Popular Tags |