1 package net.suberic.pooka.gui; 2 import net.suberic.pooka.*; 3 import net.suberic.pooka.gui.search.SearchForm; 4 import javax.mail.*; 5 import javax.mail.internet.MimeMessage ; 6 import javax.mail.event.*; 7 import javax.mail.search.SearchTerm ; 8 import java.awt.*; 9 import java.awt.event.*; 10 import javax.swing.*; 11 import javax.swing.plaf.basic.*; 12 import javax.swing.table.*; 13 import javax.swing.text.TextAction ; 14 import java.util.*; 15 import net.suberic.pooka.event.MessageLoadedEvent; 16 import net.suberic.util.gui.*; 17 import net.suberic.util.event.*; 18 import net.suberic.util.thread.*; 19 import net.suberic.util.swing.*; 20 21 26 27 public class FolderInternalFrame extends JInternalFrame implements FolderDisplayUI { 28 FolderInfo folderInfo = null; 29 FolderDisplayPanel folderDisplay = null; 30 FolderStatusBar folderStatusBar = null; 31 MessagePanel messagePanel = null; 32 ConfigurableToolbar toolbar; 33 ConfigurableKeyBinding keyBindings; 34 boolean enabled = true; 35 36 39 public FolderInternalFrame(FolderInfo newFolderInfo, MessagePanel newMessagePanel) { 40 super(newFolderInfo.getFolderDisplayName(), true, true, true, true); 41 42 this.getContentPane().setLayout(new BorderLayout()); 43 44 messagePanel = newMessagePanel; 45 46 setFolderInfo(newFolderInfo); 47 48 getFolderInfo().setFolderDisplayUI(this); 49 50 defaultActions = new Action [] { 51 new CloseAction(), 52 new ActionWrapper(new ExpungeAction(), getFolderInfo().getFolderThread()), 53 new NextMessageAction(), 54 new PreviousMessageAction(), 55 new NextUnreadMessageAction(), 56 new GotoMessageAction(), 57 new SearchAction(), 58 new SelectAllAction() 59 }; 60 61 65 setFolderStatusBar(new FolderStatusBar(this.getFolderInfo())); 66 67 folderDisplay = new FolderDisplayPanel(getFolderInfo()); 68 69 if (getFolderInfo() != null && getFolderInfo().isOutboxFolder()) 70 toolbar = new ConfigurableToolbar("OutboxWindowToolbar", Pooka.getResources()); 71 else 72 toolbar = new ConfigurableToolbar("FolderWindowToolbar", Pooka.getResources()); 73 this.getContentPane().add("North", toolbar); 74 this.getContentPane().add("Center", folderDisplay); 75 this.getContentPane().add("South", getFolderStatusBar()); 76 77 int height = Integer.parseInt(Pooka.getProperty(getFolderInfo().getFolderProperty() + ".windowLocation.height", Pooka.getProperty("FolderWindow.height", "380"))); 78 int width = Integer.parseInt(Pooka.getProperty(getFolderInfo().getFolderProperty() + ".windowLocation.width", Pooka.getProperty("FolderWindow.width","570"))); 79 80 this.setPreferredSize(new Dimension(width, height)); 81 82 this.setSize(this.getPreferredSize()); 83 84 keyBindings = new ConfigurableKeyBinding(this, "FolderWindow.keyBindings", Pooka.getResources()); 85 86 keyBindings.setActive(getActions()); 87 toolbar.setActive(getActions()); 88 89 92 this.addFocusListener(new FocusAdapter() { 93 public void focusGained(FocusEvent e) { 94 folderDisplay.requestFocusInWindow(); 95 } 96 }); 97 98 FocusTraversalPolicy ftp = new LayoutFocusTraversalPolicy() { 99 public Component getInitialComponent(JInternalFrame jif) { 100 if (jif instanceof FolderInternalFrame) { 101 return ((FolderInternalFrame) jif).getFolderDisplay(); 102 } 103 104 return super.getInitialComponent(jif); 105 } 106 }; 107 this.setFocusTraversalPolicy(ftp); 108 109 getFolderDisplay().getMessageTable().getSelectionModel().addListSelectionListener(new SelectionListener()); 110 111 this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 112 113 this.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter () { 114 public void internalFrameClosed(javax.swing.event.InternalFrameEvent e) { 115 saveWindowSettings(); 116 getFolderInfo().setFolderDisplayUI(null); 117 } 118 }); 119 120 if (getUI() instanceof BasicInternalFrameUI) { 121 ((BasicInternalFrameUI) getUI()).getNorthPane().addMouseListener(new MouseAdapter() { 122 123 public void mousePressed(MouseEvent evt) { 124 if (evt.getButton() == MouseEvent.BUTTON2) { 125 try { 126 Object messagePanel = SwingUtilities.getAncestorOfClass(Class.forName("net.suberic.pooka.gui.MessagePanel"), FolderInternalFrame.this); 127 if (messagePanel != null) { 128 ((MessagePanel) messagePanel).unselectAndMoveToBack(FolderInternalFrame.this); 129 evt.consume(); 130 } 131 } catch (Exception e) { 132 getLogger().log(java.util.logging.Level.FINE, "exception lowering FolderInternalFrame", e); 133 } 134 } 135 } 136 137 }); 138 } 139 } 140 141 142 public FolderInternalFrame(PreviewFolderPanel pfp, MessagePanel newMessagePanel) { 143 super(pfp.getFolderInfo().getFolderDisplayName(), true, true, true, true); 144 145 FolderInfo newFolderInfo = pfp.getFolderInfo(); 146 147 this.getContentPane().setLayout(new BorderLayout()); 148 149 messagePanel = newMessagePanel; 150 151 setFolderInfo(newFolderInfo); 152 153 defaultActions = new Action [] { 154 new CloseAction(), 155 new ActionWrapper(new ExpungeAction(), getFolderInfo().getFolderThread()), 156 new NextMessageAction(), 157 new PreviousMessageAction(), 158 new GotoMessageAction(), 159 new SearchAction() 160 }; 161 162 166 setFolderStatusBar(new FolderStatusBar(this.getFolderInfo())); 167 168 folderDisplay = pfp.getFolderDisplay(); 169 toolbar = new ConfigurableToolbar("FolderWindowToolbar", Pooka.getResources()); 170 this.getContentPane().add("North", toolbar); 171 this.getContentPane().add("Center", folderDisplay); 172 this.getContentPane().add("South", getFolderStatusBar()); 173 174 int height = Integer.parseInt(Pooka.getProperty(getFolderInfo().getFolderProperty() + ".windowLocation.height", Pooka.getProperty("FolderWindow.height", "380"))); 175 int width = Integer.parseInt(Pooka.getProperty(getFolderInfo().getFolderProperty() + ".windowLocation.width", Pooka.getProperty("FolderWindow.width","570"))); 176 177 this.setPreferredSize(new Dimension(width, height)); 178 179 this.setSize(this.getPreferredSize()); 180 181 keyBindings = new ConfigurableKeyBinding(this, "FolderWindow.keyBindings", Pooka.getResources()); 182 183 keyBindings.setActive(getActions()); 184 toolbar.setActive(getActions()); 185 186 189 this.addFocusListener(new FocusAdapter() { 190 public void focusGained(FocusEvent e) { 191 folderDisplay.requestFocusInWindow(); 192 } 193 }); 194 195 getFolderDisplay().getMessageTable().getSelectionModel().addListSelectionListener(new SelectionListener()); 196 197 this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 198 199 this.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter () { 200 public void internalFrameClosed(javax.swing.event.InternalFrameEvent e) { 201 saveWindowSettings(); 202 getFolderInfo().setFolderDisplayUI(null); 203 } 204 }); 205 206 if (getUI() instanceof BasicInternalFrameUI) { 207 ((BasicInternalFrameUI) getUI()).getNorthPane().addMouseListener(new MouseAdapter() { 208 209 public void mousePressed(MouseEvent evt) { 210 if (evt.getButton() == MouseEvent.BUTTON2) { 211 try { 212 Object messagePanel = SwingUtilities.getAncestorOfClass(Class.forName("net.suberic.pooka.gui.MessagePanel"), FolderInternalFrame.this); 213 if (messagePanel != null) { 214 ((MessagePanel) messagePanel).unselectAndMoveToBack(FolderInternalFrame.this); 215 evt.consume(); 216 } 217 } catch (Exception e) { 218 getLogger().log(java.util.logging.Level.FINE, "exception lowering FolderInternalFrame", e); 219 } 220 } 221 } 222 223 }); 224 } 225 } 226 227 230 public void saveWindowSettings() { 231 String folderProperty = getFolderInfo().getFolderProperty(); 232 233 MessagePanel mp = getMessagePanel(); 235 236 int x = getX() + ((JScrollPane)mp.getUIComponent()).getHorizontalScrollBar().getValue(); 237 int y = getY() + ((JScrollPane)mp.getUIComponent()).getVerticalScrollBar().getValue(); 238 239 Pooka.setProperty(folderProperty + ".windowLocation.x", Integer.toString(x)); 240 Pooka.setProperty(folderProperty + ".windowLocation.y", Integer.toString(y)); 241 242 Pooka.setProperty(folderProperty + ".windowLocation.height", Integer.toString(getHeight())); 243 Pooka.setProperty(folderProperty + ".windowLocation.width", Integer.toString(getWidth())); 244 245 getFolderDisplay().saveTableSettings(); 246 } 247 248 252 public void searchFolder() { 253 getFolderInfo().showSearchFolder(); 254 } 255 256 262 public MessageProxy getSelectedMessage() { 263 return getFolderDisplay().getSelectedMessage(); 264 } 265 266 269 public void resize() { 270 this.setSize(getParent().getSize()); 271 } 272 273 276 public void openFolderDisplay() { 277 openFolderDisplay(true); 278 } 279 280 283 public void openFolderDisplay(boolean selected) { 284 final boolean fSelected = selected; 285 Runnable runMe = new Runnable () { 286 public void run() { 287 getMessagePanel().openFolderWindow(FolderInternalFrame.this, fSelected); 288 } 289 }; 290 if (SwingUtilities.isEventDispatchThread()) 291 runMe.run(); 292 else 293 SwingUtilities.invokeLater(runMe); 294 } 295 296 299 public void closeFolderDisplay(){ 300 Runnable runMe = new Runnable () { 301 public void run() { 302 303 try { 304 saveWindowSettings(); 305 setClosed(true); 306 } catch (java.beans.PropertyVetoException e) { 307 } 308 } 309 }; 310 if (SwingUtilities.isEventDispatchThread()) { 311 runMe.run(); 312 } else { 313 SwingUtilities.invokeLater(runMe); 314 } 315 316 317 } 318 319 322 public void expungeMessages() { 323 try { 324 getFolderInfo().getFolder().expunge(); 325 } catch (MessagingException me) { 326 showError(Pooka.getProperty("error.Message.ExpungeErrorMessage", "Error: could not expunge messages.") +"\n" + me.getMessage()); 327 } 328 } 329 330 335 public void showError(String errorMessage, String title) { 336 final String errorMsg = errorMessage; 337 final String realTitle = title; 338 Runnable runMe = new Runnable () { 339 public void run() { 340 JOptionPane.showInternalMessageDialog(getMessagePanel(), errorMsg, realTitle, JOptionPane.ERROR_MESSAGE); 341 } 342 }; 343 344 if (SwingUtilities.isEventDispatchThread()) { 345 runMe.run(); 346 } else { 347 SwingUtilities.invokeLater(runMe); 348 } 349 } 350 351 356 public void showError(String errorMessage) { 357 showError(errorMessage, Pooka.getProperty("Error", "Error")); 358 } 359 360 365 public void showError(String errorMessage, Exception e) { 366 showError(errorMessage, Pooka.getProperty("Error", "Error"), e); 367 } 368 369 374 public void showError(String errorMessage, String title, Exception e) { 375 showError(errorMessage + e.getMessage(), title); 376 e.printStackTrace(); 377 } 378 379 382 public String formatMessage(String message) { 383 return Pooka.getUIFactory().formatMessage(message); 384 } 385 386 391 public String showInputDialog(String pInputMessage, String pTitle) { 392 final String inputMessage = pInputMessage; 393 final String title = pTitle; 394 final ResponseWrapper fResponseWrapper = new ResponseWrapper(); 395 396 Runnable runMe = new Runnable () { 397 public void run() { 398 fResponseWrapper.setString(JOptionPane.showInternalInputDialog(getMessagePanel(), inputMessage, title, JOptionPane.QUESTION_MESSAGE)); 399 } 400 }; 401 402 if (! SwingUtilities.isEventDispatchThread()) { 403 try { 404 SwingUtilities.invokeAndWait(runMe); 405 } catch (Exception e) { 406 } 407 } else { 408 runMe.run(); 409 } 410 411 return fResponseWrapper.getString(); 412 } 413 414 419 public int selectMessage(int messageNumber) { 420 return getFolderDisplay().selectMessage(messageNumber); 421 } 422 423 428 public void makeSelectionVisible(int messageNumber) { 429 getFolderDisplay().makeSelectionVisible(messageNumber); 430 } 431 432 public int selectNextMessage() { 433 return getFolderDisplay().selectNextMessage(); 434 } 435 436 public int selectPreviousMessage() { 437 return getFolderDisplay().selectPreviousMessage(); 438 } 439 440 public int selectNextUnreadMessage() { 441 return getFolderDisplay().selectNextUnreadMessage(); 442 } 443 444 449 public void resetFolderTableModel(FolderTableModel ftm) { 450 getFolderDisplay().resetFolderTableModel(ftm); 451 } 452 453 457 public void showStatusMessage(String msg) { 458 Pooka.getUIFactory().showStatusMessage(getFolderInfo().getFolderID() + ": " + msg); 459 } 460 461 465 public void clearStatusMessage() { 466 Pooka.getUIFactory().clearStatus(); 467 } 468 469 475 public void setBusy(boolean newBusy) { 476 final boolean newValue = newBusy; 477 478 Runnable runMe = new Runnable () { 479 public void run() { 480 if (newValue) 481 FolderInternalFrame.this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 482 else 483 FolderInternalFrame.this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 484 } 485 }; 486 487 if (SwingUtilities.isEventDispatchThread()) 488 runMe.run(); 489 else 490 SwingUtilities.invokeLater(runMe); 491 } 492 493 496 public void updateStatus(String message) { 497 Pooka.getUIFactory().showStatusMessage(message); 498 } 499 500 503 public void updateStatus(Event e, String message) { 504 if (message != null) 505 updateStatus(message); 506 507 } 508 509 511 public MessagePanel getMessagePanel() { 512 if (messagePanel != null) 513 return messagePanel; 514 else { 515 ContentPanel cp = Pooka.getMainPanel().getContentPanel(); 516 if (cp instanceof MessagePanel) 517 return (MessagePanel) cp; 518 else 519 return null; 520 } 521 } 522 523 public FolderDisplayPanel getFolderDisplay() { 524 return folderDisplay; 525 } 526 527 public void setFolderInfo(FolderInfo newValue) { 528 folderInfo=newValue; 529 } 530 531 public FolderInfo getFolderInfo() { 532 return folderInfo; 533 } 534 535 public FolderStatusBar getFolderStatusBar() { 536 return folderStatusBar; 537 } 538 539 public void setFolderStatusBar(FolderStatusBar newValue) { 540 folderStatusBar = newValue; 541 } 542 543 public java.util.logging.Logger getLogger() { 544 return java.util.logging.Logger.getLogger("Pooka.debug.gui"); 545 } 546 547 551 552 public class SelectionListener implements javax.swing.event.ListSelectionListener { 553 SelectionListener() { 554 } 555 556 public void valueChanged(javax.swing.event.ListSelectionEvent e) { 557 if (toolbar != null) 559 toolbar.setActive(getActions()); 560 if (keyBindings != null) 561 keyBindings.setActive(getActions()); 562 } 563 } 564 565 574 575 public void registerKeyboardAction(ActionListener anAction, 576 String aCommand, KeyStroke aKeyStroke, int aCondition) { 577 super.registerKeyboardAction(anAction, aCommand, aKeyStroke, aCondition); 578 579 getFolderDisplay().registerKeyboardAction(anAction, aCommand, aKeyStroke, aCondition); 580 folderStatusBar.registerKeyboardAction(anAction, aCommand, aKeyStroke, aCondition); 581 toolbar.registerKeyboardAction(anAction, aCommand, aKeyStroke, aCondition); 582 } 583 584 592 593 public void unregisterKeyboardAction(KeyStroke aKeyStroke) { 594 super.unregisterKeyboardAction(aKeyStroke); 595 596 getFolderDisplay().unregisterKeyboardAction(aKeyStroke); 597 folderStatusBar.unregisterKeyboardAction(aKeyStroke); 598 toolbar.unregisterKeyboardAction(aKeyStroke); 599 } 600 601 604 605 public UserProfile getDefaultProfile() { 606 if (getFolderInfo() != null) { 607 return getFolderInfo().getDefaultProfile(); 608 } 609 else { 610 return null; 611 } 612 } 613 614 620 public boolean isEnabled() { 621 return enabled; 622 } 623 624 628 public void setEnabled(boolean newValue) { 629 enabled = newValue; 630 } 631 632 634 639 public void handleMessageLoaded(MessageLoadedEvent e) { 640 final MessageLoadedEvent event = e; 641 642 Runnable runMe = new Runnable () { 643 644 public void run() { 645 if (event.getType() == MessageLoadedEvent.LOADING_STARTING) { 646 if (getFolderStatusBar().getTracker() != null) { 647 getFolderStatusBar().setTracker(new LoadMessageTracker(event.getLoadedMessageCount(), 0, event.getNumMessages())); 648 getFolderStatusBar().getLoaderPanel().add(getFolderStatusBar().getTracker()); 649 } 650 } else if (event.getType() == MessageLoadedEvent.LOADING_COMPLETE) { 651 652 if (getFolderStatusBar().getTracker() != null) { 653 getFolderStatusBar().getLoaderPanel().remove(getFolderStatusBar().getTracker()); 654 getFolderStatusBar().setTracker(null); 655 } 656 } else if (event.getType() == MessageLoadedEvent.MESSAGES_LOADED) { 657 if (getFolderStatusBar().getTracker() != null) 658 getFolderStatusBar().getTracker().handleMessageLoaded(event); 659 } 660 getFolderStatusBar().repaint(); 661 } 662 }; 663 664 if (!SwingUtilities.isEventDispatchThread()) { 665 SwingUtilities.invokeLater(runMe); 666 } else { 667 runMe.run(); 668 } 669 } 670 671 673 676 public void closed(ConnectionEvent e) { 677 678 } 679 680 683 public void disconnected(ConnectionEvent e) { 684 685 } 686 687 690 public void opened(ConnectionEvent e) { 691 692 } 693 694 698 public void messagesAdded(MessageCountEvent e) { 699 if (getFolderStatusBar() != null) 700 getFolderStatusBar().messagesAdded(e); 701 } 702 703 707 public void messagesRemoved(MessageCountEvent e) { 708 if (getFolderStatusBar() != null) 709 getFolderStatusBar().messagesRemoved(e); 710 711 Runnable updateAdapter = new Runnable () { 712 public void run() { 713 if (toolbar != null) 715 toolbar.setActive(getActions()); 716 if (keyBindings != null) 717 keyBindings.setActive(getActions()); 718 } 719 }; 720 if (SwingUtilities.isEventDispatchThread()) 721 updateAdapter.run(); 722 else 723 SwingUtilities.invokeLater(updateAdapter); 724 725 } 726 727 public void messageChanged(MessageChangedEvent e) { 729 if (getFolderStatusBar() != null) 730 getFolderStatusBar().messageChanged(e); 731 if (getFolderDisplay() != null) 732 getFolderDisplay().moveSelectionOnRemoval(e); 733 734 final MessageInfo mi = getFolderInfo().getMessageInfo(e.getMessage()); 735 if (mi != null) { 736 SwingUtilities.invokeLater(new Runnable () { 737 public void run() { 738 if (mi.getMessageProxy() != null) 742 getFolderDisplay().repaintMessage(mi.getMessageProxy()); 743 } 744 }); 745 } 746 } 747 748 753 private void moveSelectionOnRemoval(MessageChangedEvent e) { 754 try { 755 if ((!Pooka.getProperty("Pooka.autoExpunge", "true").equalsIgnoreCase("true")) && e.getMessageChangeType() == MessageChangedEvent.FLAGS_CHANGED && (e.getMessage().isExpunged() || e.getMessage().getFlags().contains(Flags.Flag.DELETED))) { 757 MessageProxy selectedProxy = getSelectedMessage(); 758 if ( selectedProxy != null && selectedProxy.getMessageInfo().getMessage().equals(e.getMessage())) { 759 SwingUtilities.invokeLater(new Runnable () { 760 public void run() { 761 selectNextMessage(); 762 } 763 }); 764 } 765 } 766 } catch (MessagingException me) { 767 } 768 } 769 770 775 private void moveSelectionOnRemoval(MessageCountEvent e) { 776 MessageProxy selectedProxy = getSelectedMessage(); 777 Message [] removedMsgs = e.getMessages(); 778 if (selectedProxy != null) { 779 boolean found = false; 780 Message currentMsg = selectedProxy.getMessageInfo().getMessage(); 781 for (int i = 0; (found == false && i < removedMsgs.length); i++) { 782 if (currentMsg.equals(removedMsgs[i])) { 783 found = true; 784 } 785 } 786 787 if (found) { 788 SwingUtilities.invokeLater(new Runnable () { 789 public void run() { 790 selectNextMessage(); 791 } 792 }); 793 } 794 } 795 } 796 797 801 public void removeRows(java.util.Vector removedProxies) { 802 getFolderDisplay().removeRows(removedProxies); 803 } 804 805 808 public Action [] getActions() { 809 if (isEnabled()) { 810 Action [] returnValue = defaultActions; 811 812 if (getFolderDisplay() != null) { 813 returnValue = TextAction.augmentList(getFolderDisplay().getActions(), returnValue); 814 } 815 816 return returnValue; 817 } else { 818 return null; 819 } 820 821 839 840 841 } 842 843 public Action [] getDefaultActions() { 844 return defaultActions; 845 } 846 847 849 851 private Action [] defaultActions; 852 853 class CloseAction extends AbstractAction { 854 855 CloseAction() { 856 super("file-close"); 857 } 858 859 public void actionPerformed(ActionEvent e) { 860 closeFolderDisplay(); 861 } 862 } 863 864 public class ExpungeAction extends AbstractAction { 865 866 ExpungeAction() { 867 super("message-expunge"); 868 } 869 870 public void actionPerformed(ActionEvent e) { 871 expungeMessages(); 872 } 873 } 874 875 876 public class NextMessageAction extends AbstractAction { 877 878 NextMessageAction() { 879 super("message-next"); 880 } 881 882 public void actionPerformed(ActionEvent e) { 883 selectNextMessage(); 884 } 885 } 886 887 public class PreviousMessageAction extends AbstractAction { 888 889 PreviousMessageAction() { 890 super("message-previous"); 891 } 892 893 public void actionPerformed(ActionEvent e) { 894 selectPreviousMessage(); 895 } 896 } 897 898 public class NextUnreadMessageAction extends AbstractAction { 899 900 NextUnreadMessageAction() { 901 super("message-next-unread"); 902 } 903 904 public void actionPerformed(ActionEvent e) { 905 selectNextUnreadMessage(); 906 } 907 } 908 909 public class GotoMessageAction extends AbstractAction { 910 911 GotoMessageAction() { 912 super("message-goto"); 913 } 914 915 public void actionPerformed(ActionEvent e) { 916 getFolderStatusBar().activateGotoDialog(); 917 } 918 } 919 920 public class SearchAction extends AbstractAction { 921 922 SearchAction() { 923 super("folder-search"); 924 } 925 926 public void actionPerformed(ActionEvent e) { 927 searchFolder(); 928 } 929 } 930 931 public class SelectAllAction extends AbstractAction { 932 933 SelectAllAction() { 934 super("select-all"); 935 } 936 937 public void actionPerformed(ActionEvent e) { 938 getFolderDisplay().selectAll(); 939 } 940 } 941 942 } 943 944 945 946 947 948 | Popular Tags |