1 19 20 package org.netbeans.modules.tasklist.docscan; 21 import java.awt.*; 22 import java.awt.event.*; 23 import java.beans.PropertyChangeEvent ; 24 import java.beans.PropertyChangeListener ; 25 import java.io.*; 26 import java.lang.reflect.InvocationTargetException ; 27 import java.util.*; 28 import java.util.List ; 29 30 import javax.swing.*; 31 import javax.swing.event.PopupMenuListener ; 32 import javax.swing.event.PopupMenuEvent ; 33 import javax.swing.border.Border ; 34 import javax.swing.border.CompoundBorder ; 35 import javax.accessibility.AccessibleContext ; 36 import javax.swing.event.ListDataEvent ; 37 import javax.swing.event.ListDataListener ; 38 import org.netbeans.api.progress.ProgressHandle; 39 import org.netbeans.api.progress.ProgressHandleFactory; 40 import org.openide.util.HelpCtx; 41 42 import org.openide.util.NbBundle; 43 import org.openide.util.Utilities; 44 import org.openide.util.UserCancelException; 45 import org.openide.util.actions.SystemAction; 46 import org.openide.filesystems.FileObject; 47 import org.openide.filesystems.FileStateInvalidException; 48 import org.openide.filesystems.FileUtil; 49 import org.openide.nodes.*; 50 import org.openide.loaders.*; 51 import org.openide.windows.TopComponent; 52 53 54 import org.netbeans.modules.tasklist.core.*; 55 import org.netbeans.modules.tasklist.core.filter.Filter; 56 import org.netbeans.modules.tasklist.suggestions.*; 57 import org.netbeans.modules.tasklist.core.filter.FilterRepository; 58 import org.netbeans.modules.tasklist.core.filter.FiltersPanel; 59 import org.openide.awt.Mnemonics; 60 import org.openide.util.Cancellable; 61 62 63 64 70 final class SourceTasksView extends TaskListView implements SourceTasksAction.ScanProgressMonitor, SuggestionView { 71 72 private static final long serialVersionUID = 1; 73 74 final static String CATEGORY = "sourcetasks"; 83 private final static String ICON_PATH = "org/netbeans/modules/tasklist/docscan/todosAction.gif"; 86 private final int MAIN_COLUMN_UID = 2352; 87 private final int PRIORITY_COLUMN_UID = 7896; 88 private final int FILE_COLUMN_UID = 8902; 89 private final int LINE_COLUMN_UID = 6646; 90 private final int LOCATION_COLUMN_UID = 6512; 91 92 99 private static final int CURRENT_FILE_MODE = 1; 100 private static final int OPENED_FILES_MODE = 2; 101 private static final int SELECTED_FOLDER_MODE = 3; 102 private static final int MODE_COUNT = SELECTED_FOLDER_MODE; 103 104 private SuggestionsBroker.Job job; 106 107 private TaskList resultsSnapshot; 109 110 private String reasonMsg; 112 113 114 private Background background; 115 116 117 FileObject selectedFolder; 118 119 private static final int RECENT_ITEMS_COUNT = 4; 120 private ArrayList recentFolders = new ArrayList(RECENT_ITEMS_COUNT); 121 122 123 private SuggestionsBroker.AllOpenedJob allJob; 124 125 private final TabState[] tabStates = new TabState[MODE_COUNT]; 126 127 private Object windowSystemESCActionKey; 129 130 133 public SourceTasksView() { 134 super(); 135 } 137 138 142 public SourceTasksView(SourceTasksList list) { 143 super( 144 CATEGORY, 145 Util.getString("win-title"), 146 Utilities.loadImage(ICON_PATH), true, 148 list 149 ); 150 151 init(); 152 } 153 154 158 SourceTasksView(SuggestionsBroker.Job job) { 159 super( 160 CATEGORY, 161 Util.getString("win-title"), 162 Utilities.loadImage(ICON_PATH), true, 164 createFilteredList(job.getSuggestionsList()) 165 ); 166 this.job = job; 167 init(); 168 } 169 170 173 private void init() { 174 putClientProperty("TabPolicy", "HideWhenAlone"); 178 InputMap inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 179 180 KeyStroke refresh = KeyStroke.getKeyStroke(KeyEvent.VK_R, 0); 181 inputMap.put(refresh, refresh); 182 getActionMap().put(refresh, new DelegateAction(getRefresh())); 183 184 KeyStroke editfilter = KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.SHIFT_MASK); 185 inputMap.put(editfilter, editfilter); 186 getActionMap().put(editfilter, new DelegateAction(getFilterIconButton())); 187 188 KeyStroke filtercombo = KeyStroke.getKeyStroke(KeyEvent.VK_F, 0); 189 inputMap.put(filtercombo, "filtercombo"); 190 AbstractAction a = new AbstractAction("filtercombo") { 191 public void actionPerformed(ActionEvent e) { 192 filterCombo.showPopup(); 193 filterCombo.requestFocus(); 194 } 195 }; 196 a.setEnabled(true); 197 getActionMap().put("filtercombo", a); 198 199 KeyStroke editor = KeyStroke.getKeyStroke(KeyEvent.VK_E, 0); 200 inputMap.put(editor, editor); 201 getActionMap().put(editor, new DelegateAction(getGoto())); 202 203 KeyStroke current = KeyStroke.getKeyStroke(KeyEvent.VK_C, 0); 204 inputMap.put(current, current); 205 getActionMap().put(current, new DelegateAction(getCurrentFile())); 206 207 KeyStroke opened = KeyStroke.getKeyStroke(KeyEvent.VK_O, 0); 208 inputMap.put(opened, opened); 209 getActionMap().put(opened, new DelegateAction(getOpenedFiles())); 210 211 KeyStroke folder = KeyStroke.getKeyStroke(KeyEvent.VK_S, 0); 212 inputMap.put(folder, folder); 213 getActionMap().put(folder, new DelegateAction(getAllFiles())); 214 215 KeyStroke selectFolder = KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.SHIFT_MASK); 216 inputMap.put(selectFolder, selectFolder); 217 getActionMap().put(selectFolder, new DelegateAction(getFolderSelector())); 218 219 } 220 221 protected Component createCenterComponent() { 222 Component ret = super.createCenterComponent(); 223 224 getTable().getAccessibleContext().setAccessibleName(Util.getString("treetable")); 226 getTable().getAccessibleContext().setAccessibleDescription(Util.getString("treetable_hint")); 227 228 return ret; 229 } 230 231 232 233 public int getPersistenceType() { 234 return TopComponent.PERSISTENCE_ONLY_OPENED; 235 } 236 237 public HelpCtx getHelpCtx() { 238 return new HelpCtx(SourceTasksView.class); 239 } 240 241 protected Node createRootNode() { 242 return new TaskListNode(getModel(), 247 new TaskListNode.NodeFactory() { 248 public Node createNode(Object task) { 249 if (task instanceof SuggestionImpl) { 250 return new SourceTaskNode((SuggestionImpl)task); } 252 else 253 return ((Task)task).createNode()[0]; 254 } 255 }); 256 } 257 258 259 private ColumnProperty[] allFilesColumns; 260 private ColumnProperty[] currentFileColumns; 261 262 263 protected ColumnProperty[] createColumns() { 264 268 271 switch (getMode()) { 272 case CURRENT_FILE_MODE: 273 if (currentFileColumns == null) { 274 currentFileColumns = new ColumnProperty[]{ 275 createMainColumn(800), 276 createPriorityColumn(false, 100), 277 createLineColumn(true, 50) 278 }; 279 } 280 return currentFileColumns; 281 282 case OPENED_FILES_MODE: 283 case SELECTED_FOLDER_MODE: 284 if (allFilesColumns == null) { 285 allFilesColumns = new ColumnProperty[]{ 286 createMainColumn(800), 287 createPriorityColumn(false, 100), 288 createLocationColumn(true, 200), 289 }; 290 } 291 return allFilesColumns; 292 293 default: 294 throw new IllegalStateException (); 295 } 296 } 297 298 protected ColumnProperty getMainColumn(int width) { 299 return createColumns()[0]; 300 } 301 302 303 protected void loadColumnsConfiguration() { 304 } 306 307 protected void storeColumnsConfiguration() { 308 } 312 313 private ColumnProperty createMainColumn(int width) { 314 return new ColumnProperty( 315 MAIN_COLUMN_UID, SourceTaskProperties.PROP_TASK, 317 true, 318 width); 319 } 320 321 322 private ColumnProperty createPriorityColumn(boolean visible, int width) { 323 return new ColumnProperty( 324 PRIORITY_COLUMN_UID, SourceTaskProperties.PROP_PRIORITY, 326 true, 327 visible, 328 width 329 ); 330 } 331 332 private ColumnProperty createFileColumn(boolean visible, int width) { 333 ColumnProperty file = new ColumnProperty( 334 FILE_COLUMN_UID, SourceTaskProperties.PROP_FILENAME, 336 true, 337 visible, 338 width 339 ); 340 return file; 341 } 342 343 private ColumnProperty createLineColumn(boolean visible, int width) { 344 return new ColumnProperty( 345 LINE_COLUMN_UID, SourceTaskProperties.PROP_LINE_NUMBER, 347 true, 348 visible, 349 width 350 ); 351 } 352 353 private ColumnProperty createLocationColumn(boolean visible, int width) { 354 ColumnProperty location = new ColumnProperty( 355 LOCATION_COLUMN_UID, SourceTaskProperties.PROP_LOCATION, 357 true, 358 visible, 359 width 360 ); 361 return location; 362 363 } 364 365 protected void componentOpened() { 366 super.componentOpened(); 367 setNorthComponentVisible(true); 368 if (job == null) { handleCurrentFile(); 370 } 371 372 updateButtonsState(); 373 } 374 375 protected void componentClosed() { 376 super.componentClosed(); 377 if (background != null) background.interrupt(); 378 Cache.store(); 379 releaseWorkaround(); 380 if (job != null) { 381 job.stopBroker(); 382 job = null; 383 } 384 if (allJob != null) { 385 allJob.stopBroker(); 386 allJob = null; 387 } 388 } 392 393 394 protected String preferredID() { 395 return "todo-window"; } 397 398 public void writeExternal(ObjectOutput objectOutput) throws IOException { 399 400 Cache.store(); 401 402 405 410 objectOutput.writeInt(2); 414 419 boolean snapshot = job == null; 420 objectOutput.writeBoolean(snapshot); 421 if (snapshot) { 422 } 440 441 ArrayList recent = recentFolders; 442 if (selectedFolder != null) { 443 recent = new ArrayList(recentFolders); 444 addRecent(recent, selectedFolder); 445 } 446 objectOutput.writeObject(recent); 447 } 448 449 public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException { 451 452 super.category = CATEGORY; 453 super.setName(Util.getString("win-title")); 454 super.setIcon(Utilities.loadImage(ICON_PATH)); 456 int version = objectInput.readInt(); 457 if (version == 1 || version == 2) { 458 461 boolean snapshot = objectInput.readBoolean(); 462 job = SuggestionsBroker.getDefault().startBroker(new SourceTasksProviderAcceptor()); 477 this.category = CATEGORY; 478 registerTaskListView(this); 479 setModel(createFilteredList(job.getSuggestionsList())); 480 482 if (version == 2) { 483 recentFolders = (ArrayList) objectInput.readObject(); 484 } 485 } 486 487 init(); 488 489 } 490 491 public String getToolTipText() { 492 int mode = getMode(); 493 switch(mode) { 494 case CURRENT_FILE_MODE: return Util.getString("win-tt-c"); 495 case OPENED_FILES_MODE: return Util.getString("win-tt-o"); 496 case SELECTED_FOLDER_MODE: return Util.getString("win-tt-f"); 497 } 498 return null; 499 } 500 501 public String toString() { 502 return "SourceTasksView@" + hashCode(); 503 } 504 505 507 private ProgressHandle progress; 508 private JButton stop; 509 private AbstractButton refresh; 510 private JComponent prev; 511 private JComponent next; 512 513 private Cancellable cancellable = new Cancellable(){ 514 public boolean cancel(){ 515 handleStop(); 516 return true; 517 } 518 }; 519 520 private ProgressHandle getProgress() { 521 if (progress == null) { 522 progress = ProgressHandleFactory.createHandle(Util.getString("searching"), cancellable); 523 progress.start(); 524 } 525 return progress; 526 } 527 528 private void updateMiniStatus() { 531 assert SwingUtilities.isEventDispatchThread(); 532 String prefix = ""; 533 getMiniStatus().setHorizontalAlignment(SwingConstants.LEFT); 534 StringBuffer msg = new StringBuffer (80); 535 if (job == null && allJob== null && selectedFolder != null) { 536 if (msg.length() > 0) prefix = ", "; msg.append(prefix + Util.getMessage("ctx-flag", createLabel(selectedFolder))); 538 } 539 540 if (reasonMsg != null && job == null && allJob== null) { 541 if (msg.length() > 0) prefix = ", "; msg.append(prefix + Util.getMessage("usa-flag", "" + TLUtils.recursiveCount(getModel().getTasks().iterator()))); 543 getMiniStatus().setToolTipText(reasonMsg); 544 } else { 545 getMiniStatus().setToolTipText(""); 546 } 547 getMiniStatus().setText(msg.toString()); 548 } 549 550 AbstractButton getRefresh() { 551 if (refresh == null) { 552 Image image = Utilities.loadImage("org/netbeans/modules/tasklist/docscan/refresh.png"); JButton button = new JButton(new ImageIcon(image)); 554 button.setToolTipText(Util.getString("rescan_hint") + " (r)"); button.setEnabled(job == null); 556 button.addActionListener(dispatcher); 557 adjustToobarButton(button); 558 559 button.getAccessibleContext().setAccessibleName(Util.getString("rescan")); 560 button.getAccessibleContext().setAccessibleDescription(Util.getString("rescan_hint")); 561 562 563 refresh = button; 564 } 565 return refresh; 566 } 567 568 private JComponent getPrev() { 569 if (prev == null) { 570 JButton button = new JButton("Prev (Shift+F12)"); 571 button.addActionListener(dispatcher); 572 adjustToobarButton(button); 573 prev = button; 574 } 575 return prev; 576 } 577 578 private JComponent getNext() { 579 if (next == null) { 580 JButton button = new JButton("Next (F12)"); 581 button.addActionListener(dispatcher); 582 adjustToobarButton(button); 583 next = button; 584 } 585 return next; 586 } 587 588 589 private AbstractButton allFilesButton; 590 private ButtonGroup group = new ButtonGroup();; 591 592 AbstractButton getAllFiles() { 593 if (allFilesButton == null) { 594 JToggleButton button = new JToggleButton(Util.getString("see-folder")); 595 String tooltiptext ; 596 if (selectedFolder == null) { 597 tooltiptext = Util.getString("see-folder_hint1"); 598 } else { 599 tooltiptext = Util.getString("see-folder_hint2"); 601 } 602 603 button.setToolTipText(tooltiptext + " (s)"); 605 group.add(button); 606 button.setSelected(job == null); 607 button.addActionListener(dispatcher); 608 adjustToobarButton(button); 609 618 button.getAccessibleContext().setAccessibleName(Util.getString("see-folder")); 619 button.getAccessibleContext().setAccessibleDescription(tooltiptext); 620 621 allFilesButton = button; 622 623 } 624 return allFilesButton; 625 } 626 627 private AbstractButton folderSelector; 628 private AbstractButton getFolderSelector() { 629 if (folderSelector == null) { 630 JButton button = new DropDown(); 631 button.setToolTipText(Util.getString("selector_hint") + " (S)"); button.addActionListener(dispatcher); 633 adjustToobarButton(button); 634 635 button.getAccessibleContext().setAccessibleName(Util.getString("select-folder")); 636 button.getAccessibleContext().setAccessibleDescription(Util.getString("selector_hint")); 637 folderSelector = button; 639 } 640 return folderSelector; 641 } 642 643 class DropDown extends JButton { 644 645 private static final long serialVersionUID = 1; 646 private static final int DROPDOWN_WIDTH = 15; 647 648 DropDown() { 649 super(new ImageIcon(Utilities.loadImage("org/netbeans/modules/tasklist/docscan/dropdown.gif"))); } 652 653 public Dimension getPreferredSize() { 654 return new Dimension(DROPDOWN_WIDTH, getToolbarHeight()); 657 } 658 } 659 660 private void showFolderSelectorPopup() { 661 JPopupMenu popup = new JPopupMenu(); 662 JMenuItem choose = new JMenuItem(); 663 Mnemonics.setLocalizedText(choose, Util.getString("Lbl_select-folder")); 664 choose.addActionListener(new ActionListener() { 665 public void actionPerformed(ActionEvent e) { 666 handleSelectFolder(); 667 } 668 }); 669 popup.add(choose); 670 671 Iterator it = recentFolders.iterator(); 672 int i = 1; 673 if (it.hasNext() || selectedFolder != null) popup.addSeparator(); 674 675 if (selectedFolder != null) { 676 JMenuItem item = new JMenuItem(); 677 Mnemonics.setLocalizedText(item, "&0 " + createLabel(selectedFolder)); item.addActionListener(new ActionListener() { 679 public void actionPerformed(ActionEvent e) { 680 if (getAllFiles().isSelected()) return; 681 handleAllFiles(); 682 } 683 }); 684 popup.add(item); 685 } 686 687 while (it.hasNext()) { 688 final FileObject fo = (FileObject) it.next(); 689 if (fo == null || fo.isValid() == false) continue; 690 if (fo.equals(selectedFolder)) continue; 691 JMenuItem item = new JMenuItem(); 692 Mnemonics.setLocalizedText(item, "&" + i + " " + createLabel(fo)); item.addActionListener(new RecentActionListener(fo)); 694 popup.add(item); 695 i++; 696 } 697 698 popup.addPopupMenuListener(new PopupMenuListener () { 699 public void popupMenuWillBecomeVisible(PopupMenuEvent e) { 700 } 701 702 public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { 703 } 704 705 public void popupMenuCanceled(PopupMenuEvent e) { 706 if (selectedFolder == null) { 707 getCurrentFile().doClick(0); 708 } 709 } 710 711 }); 712 popup.show(getAllFiles(), 0, getAllFiles().getHeight()); 713 } 714 715 private class RecentActionListener implements ActionListener { 716 717 private final FileObject fo; 718 719 RecentActionListener(FileObject recent) { 720 fo = recent; 721 } 722 723 public void actionPerformed(ActionEvent e) { 724 updateRecent(selectedFolder); 725 selectedFolder = fo; 726 resultsSnapshot = null; 727 handleAllFiles(); 728 } 729 } 730 731 private AbstractButton openedFiles; 732 733 private AbstractButton getOpenedFiles() { 734 if (openedFiles == null) { 735 JToggleButton button = new JToggleButton(Util.getString("opened")); 736 button.setToolTipText(Util.getString("opened_desc")); 737 group.add(button); 738 button.setSelected(getMode() == OPENED_FILES_MODE); 739 button.addActionListener(dispatcher); 740 adjustToobarButton(button); 741 742 button.getAccessibleContext().setAccessibleName(Util.getString("opened")); 743 button.getAccessibleContext().setAccessibleDescription(Util.getString("opened_desc")); 744 745 openedFiles = button; 746 } 747 return openedFiles; 748 } 749 750 private AbstractButton currentFile; 751 752 private AbstractButton getCurrentFile() { 753 if (currentFile == null) { 754 JToggleButton button = new JToggleButton(Util.getString("see-file")); 755 button.setToolTipText(Util.getString("see-file_hint") + " (c)"); group.add(button); 757 button.setSelected(getMode() == CURRENT_FILE_MODE); 758 button.addActionListener(dispatcher); 759 adjustToobarButton(button); 760 761 button.getAccessibleContext().setAccessibleName(Util.getString("see-file")); 762 button.getAccessibleContext().setAccessibleDescription(Util.getString("see-file_hint")); 763 764 currentFile = button; 765 } 766 return currentFile; 767 } 768 769 private AbstractButton gotoPresenter; 770 771 private AbstractButton getGoto() { 772 if (gotoPresenter == null) { 773 Image image = Utilities.loadImage("org/netbeans/modules/tasklist/docscan/gotosource.png"); JButton button = new JButton(new ImageIcon(image)); 775 button.setToolTipText(Util.getString("goto_hint") + " (e)"); button.addActionListener(dispatcher); 777 adjustToobarButton(button); 778 779 button.getAccessibleContext().setAccessibleName(Util.getString("goto")); 780 button.getAccessibleContext().setAccessibleDescription(Util.getString("goto_hint")); 781 782 gotoPresenter = button; 783 } 784 return gotoPresenter; 785 } 786 787 788 private class Dispatcher implements ActionListener { 789 public void actionPerformed(ActionEvent e) { 790 Object obj = e.getSource(); 791 if (obj == getGoto()) { 792 GoToTaskAction gotoAction = (GoToTaskAction) SystemAction.get(GoToTaskAction.class); 793 if (gotoAction.isEnabled()) { 794 gotoAction.performAction(); 795 } else { 796 Toolkit.getDefaultToolkit().beep(); 797 } 798 } else if (obj == getCurrentFile()) { 799 handleCurrentFile(); 800 } else if (obj == getOpenedFiles()) { 801 handleOpenedFiles(); 802 } else if (obj == getFolderSelector()) { 803 if (recentFolders.size() > 0 || selectedFolder != null) { 804 showFolderSelectorPopup(); 805 } else { 806 handleSelectFolder(); 807 } 808 } else if (obj == getAllFiles()) { 809 handleAllFiles(); 810 } else if (obj == getRefresh()) { 811 handleRefresh(); 812 } else if (obj == getPrev()) { 813 handlePrev(); 814 } else if (obj == getNext()) { 815 handleNext(); 816 } else if (obj == getFilterCombo()) { 817 if (filterCombo.getSelectedItem() != null) { 818 setFilter(((Filter.ListModelElement)(filterCombo.getSelectedItem())).filter); 819 } 820 821 823 824 836 838 } else if (obj == getFilterIconButton()) { 839 FilterSourceTasksAction action = (FilterSourceTasksAction) SystemAction.get(FilterSourceTasksAction.class); 840 putClientProperty(FiltersPanel.SELECTED_FILTER, getFilterCombo().getSelectedItem()); 841 action.actionPerformed(e); 842 } 844 845 } 846 } 847 848 849 850 private final ActionListener dispatcher = new Dispatcher(); 851 852 853 private void adjustToobarButton(final AbstractButton button) { 854 855 button.setMargin(new Insets(0, 3, 0, 3)); 856 857 if (button instanceof JToggleButton == false) { 861 button.setContentAreaFilled(false); 862 button.setBorderPainted(false); 863 button.addMouseListener(new MouseAdapter() { 864 public void mouseEntered(MouseEvent e) { 865 button.setContentAreaFilled(true); 866 button.setBorderPainted(true); 867 } 868 869 public void mouseExited(MouseEvent e) { 870 button.setContentAreaFilled(false); 871 button.setBorderPainted(false); 872 } 873 }); 874 } 875 876 892 adjustToolbarComponentSize(button); 893 } 894 895 private void adjustToolbarComponentSize(JComponent button) { 896 if (button.getBorder() instanceof CompoundBorder ) { Dimension pref = button.getPreferredSize(); 899 pref.height = getToolbarHeight(); 900 901 if ("Windows".equals(UIManager.getLookAndFeel().getID())) { pref.width += 9; 904 } 905 button.setPreferredSize(pref); 906 } 907 908 } 909 910 public void updateFilterCount() { 911 } 913 914 protected Component createNorthComponent() { 915 916 JToolBar toolbar = new JToolBar(); 917 toolbar.setFloatable(false); 918 toolbar.putClientProperty("JToolBar.isRollover", Boolean.TRUE); Border verysoftbevelborder = BorderFactory.createMatteBorder(0,0,1,0,toolbar.getBackground().darker().darker()); 920 toolbar.setBorder(verysoftbevelborder); 921 toolbar.setLayout(new ToolbarLayout()); 922 923 toolbar.add(getCurrentFile()); 924 toolbar.add(getOpenedFiles()); 925 toolbar.add(getAllFiles()); 926 927 JPanel wrapper = new JPanel(); 929 wrapper.setOpaque(false); wrapper.setLayout(new FlowLayout(FlowLayout.CENTER,0,0)); 931 wrapper.add(getFolderSelector()); 932 toolbar.add(wrapper); 933 934 JPanel separator = new JPanel(); 936 separator.setOpaque(false); toolbar.add(separator); 938 toolbar.add(getGoto()); 939 toolbar.add(getRefresh()); 940 toolbar.add(getFilterIconButton()); 941 toolbar.add(getFilterCombo()); 942 943 JPanel separator2 = new JPanel(); 945 separator2.setOpaque(false); toolbar.add(separator2); 947 toolbar.add(getMiniStatus()); 948 949 toolbar.setPreferredSize(new Dimension(Integer.MAX_VALUE, getToolbarHeight())); 951 return toolbar; 952 953 } 954 955 961 private class ToolbarLayout implements LayoutManager { 962 963 public void removeLayoutComponent(Component comp) { 964 } 965 966 public void layoutContainer(Container parent) { 967 Dimension max = parent.getSize(); 968 int label = max.width - preferredLayoutSize(parent).width; 969 970 int components = parent.getComponentCount(); 971 int horizont = 0; 972 for (int i = 0; i<components; i++) { 973 JComponent comp = (JComponent) parent.getComponent(i); 974 if (comp.isVisible() == false) continue; 975 comp.setLocation(horizont, 0); 976 Dimension pref = comp.getPreferredSize(); 977 int width = pref.width; 978 if (comp == getMiniStatus()) { 979 width = label; 980 } 981 comp.setSize(width, getToolbarHeight() - 1); horizont += width; 983 } 984 } 985 986 public void addLayoutComponent(String name, Component comp) { 987 } 988 989 public Dimension minimumLayoutSize(Container parent) { 990 int components = parent.getComponentCount(); 991 int horizont = 0; 992 for (int i = 0; i<components; i++) { 993 Component comp = parent.getComponent(i); 994 if (comp.isVisible() == false) continue; 995 comp.setLocation(horizont, 0); 996 Dimension pref = comp.getPreferredSize(); 997 horizont += pref.width; 998 } 999 1000 return new Dimension(horizont, getToolbarHeight()); 1001 } 1002 1003 public Dimension preferredLayoutSize(Container parent) { 1004 return getMinimumSize(); 1005 } 1006 1007 } 1008 1009 1010 1012 private int realFolders = 0; 1013 private int estimatedFolders = -1; 1014 1015 1016 private FileObject scannedFolder; 1017 1018 public void estimate(final int estimate) { 1019 scannedFolder = null; 1020 estimatedFolders = estimate; 1021 1022 if (estimate == -1) { 1023 getProgress().switchToIndeterminate (); 1024 } else { 1025 getProgress().switchToDeterminate(estimatedFolders); 1026 } 1027 1028 SwingUtilities.invokeLater(new Runnable () { 1029 public void run() { 1030 if (estimate == -1) { 1031 Cache.load(); } 1033 } 1034 }); 1035 } 1036 1037 public void scanStarted() { 1038 1039 realFolders = 0; 1040 reasonMsg = null; 1041 1042 SwingUtilities.invokeLater(new Runnable () { 1043 public void run() { 1044 getRefresh().setEnabled(false); 1045 } 1046 }); 1047 1048 } 1049 1050 public void folderEntered(final FileObject folder) { 1051 scannedFolder = folder; 1052 1053 if (estimatedFolders > 0) { 1054 realFolders++; 1055 if(realFolders > estimatedFolders){ 1056 estimatedFolders = realFolders; 1057 getProgress().switchToDeterminate(estimatedFolders); 1058 } 1059 getProgress().progress(realFolders); 1060 } 1061 1062 handlePendingAWTEvents(); 1063 } 1064 1065 public void fileScanned(FileObject fo) { 1066 handlePendingAWTEvents(); 1067 } 1068 1069 public void folderScanned(FileObject fo) { 1070 handlePendingAWTEvents(); 1071 } 1072 1073 public void scanTerminated(final int reason) { 1074 if (reason == -1) { 1075 reasonMsg = Util.getString("mem_ter"); 1076 } else if (reason == -2) { 1077 reasonMsg = Util.getString("usr-ter"); 1078 } else if (reason == -3) { 1079 reasonMsg = Util.getString("usa-ter"); 1080 } 1081 } 1082 1083 public void scanFinished() { 1084 1085 estimatedFolders = -1; 1086 progressFinished(); 1087 1088 SwingUtilities.invokeLater(new Runnable () { 1089 public void run() { 1090 getRefresh().setEnabled(job == null); 1091 updateMiniStatus(); 1092 } 1093 }); 1094 } 1095 1096 private void progressFinished(){ 1097 getProgress().finish(); 1098 progress = null; 1099 } 1100 1101 public void statistics(final int todos) { 1102 SwingUtilities.invokeLater(new Runnable () { 1103 public void run() { 1104 updateMiniStatus(); 1105 } 1106 }); 1107 } 1108 1109 1111 private void handleStop() { 1112 background.interrupt(); 1113 getMiniStatus().setText(Util.getString("stopping")); 1114 } 1115 1116 1117 private static class DelegateAction extends AbstractAction { 1118 1119 private static final long serialVersionUID = 1; 1120 1121 AbstractButton target; 1122 1123 DelegateAction(AbstractButton target) { 1124 this.target = target; 1125 } 1126 1127 public void actionPerformed(ActionEvent e) { 1128 target.doClick(); 1129 } 1130 } 1131 1132 protected void componentHidden() { 1133 super.componentHidden(); 1136 } 1137 1138 ObservableList discloseModel() { 1140 return getModel(); 1141 } 1142 1143 Object discloseTable() { 1144 return treeTable; 1145 } 1146 1147 Node discloseNode() { 1148 return rootNode; 1149 } 1150 1151 1152 private void handleOpenedFiles() { 1153 1154 saveFilterState(); 1156 1157 switch (getMode()) { 1158 case CURRENT_FILE_MODE: 1159 job.stopBroker(); 1160 job = null; 1161 break; 1162 case OPENED_FILES_MODE: 1163 return; 1164 case SELECTED_FOLDER_MODE: 1165 if (background != null) handleStop(); 1166 background = null; 1167 break; 1168 } 1169 releaseWorkaround(); 1170 1171 1173 allJob = SuggestionsBroker.getDefault().startAllOpenedBroker(new SourceTasksProviderAcceptor()); 1174 1175 treeTable.setProperties(createColumns()); 1176 treeTable.setTreePreferredWidth(createColumns()[0].getWidth()); 1177 TaskList list = allJob.getSuggestionList(); 1178 setModel(list); 1179 loadFilterState(OPENED_FILES_MODE); 1180 getRefresh().setEnabled(false); 1181 getTable().requestFocusInWindow(); 1182 1183 updateMiniStatus(); 1184 putClientProperty(JComponent.TOOL_TIP_TEXT_KEY, getToolTipText()); 1185 } 1186 1187 1188 private void handleAllFiles() { 1189 1190 1192 if (selectedFolder == null) { 1193 if (recentFolders.size() > 0) { 1194 showFolderSelectorPopup(); 1195 } else { 1196 handleSelectFolder(); 1197 } 1198 return; 1200 } else { 1201 DataObject seletedDataFolder = null; 1203 try { 1204 seletedDataFolder = DataObject.find(selectedFolder); 1205 } catch (DataObjectNotFoundException e) { 1206 } 1208 if (seletedDataFolder == null) { 1209 if (recentFolders.size() > 0) { 1210 showFolderSelectorPopup(); 1211 } else { 1212 handleSelectFolder(); 1213 } 1214 return; 1215 } 1216 } 1217 1218 1220 saveFilterState(); 1221 1222 switch (getMode()) { 1223 case CURRENT_FILE_MODE: 1224 job.stopBroker(); 1225 job = null; 1226 break; 1227 case OPENED_FILES_MODE: 1228 allJob.stopBroker(); 1229 allJob = null; 1230 break; 1231 case SELECTED_FOLDER_MODE: 1232 break; 1233 } 1234 1235 1237 allFilesButton.setToolTipText(Util.getMessage("see-folder-hint2", createLabel(selectedFolder)) + " (s)"); ((JToggleButton)allFilesButton).setSelected(true); 1239 1240 treeTable.setProperties(createColumns()); 1241 treeTable.setTreePreferredWidth(createColumns()[0].getWidth()); 1242 TaskList list; 1243 if (resultsSnapshot == null) { 1244 list = new SourceTasksList(); 1245 } else { 1246 list = resultsSnapshot; 1247 } 1248 releaseWorkaround(); 1249 setModel(list); 1250 loadFilterState(SELECTED_FOLDER_MODE); 1251 getRefresh().setEnabled(true); 1252 getTable().requestFocusInWindow(); 1253 1254 if (list != resultsSnapshot) { 1255 try { 1256 DataObject.Container one = 1257 (DataObject.Container) DataObject.find(selectedFolder); 1258 DataObject.Container[] folders = new DataObject.Container[] {one}; 1259 background = SourceTasksScanner.scanTasksAsync(this, folders); 1260 resultsSnapshot = list; 1261 } catch (DataObjectNotFoundException e) { 1262 selectedFolder = null; } 1264 } else { 1265 getMiniStatus().setText(Util.getMessage("restored", createLabel(selectedFolder))); 1266 } 1267 1268 putClientProperty(JComponent.TOOL_TIP_TEXT_KEY, getToolTipText()); 1269 } 1270 1271 private void handleRefresh() { 1272 this.getList().clear(); 1273 DataObject.Container one; 1274 try { 1275 one = (DataObject.Container) DataObject.find(selectedFolder); 1276 DataObject.Container[] folders = new DataObject.Container[] {one}; 1277 background = SourceTasksScanner.scanTasksAsync(this, folders); 1278 getTable().requestFocusInWindow(); 1279 } catch (DataObjectNotFoundException e) { 1280 getMiniStatus().setText(Util.getMessage("refresh-err",createLabel(selectedFolder))); 1281 } 1282 } 1283 1284 private static String createLabel(FileObject fo) { 1285 String path; 1286 File file = FileUtil.toFile(fo); 1287 if (file == null) { 1288 path = fo.getPath(); 1289 try { 1290 path = fo.getFileSystem().getDisplayName() + path; 1291 } catch (FileStateInvalidException e) { 1292 } 1294 } else { 1295 path = file.getPath(); 1296 } 1297 if (path.length() > 60) { 1298 return "..." + path.substring(path.length() - 57); 1299 } else { 1300 return path; 1301 } 1302 } 1303 1304 1305 private int getMode() { 1306 if (job != null) return CURRENT_FILE_MODE; 1307 if (allJob != null) return OPENED_FILES_MODE; 1308 return SELECTED_FOLDER_MODE; 1309 } 1310 1311 1312 private void saveFilterState() { 1313 int mode = getMode(); 1314 TabState state = tabStates[mode -1]; 1315 if (state == null) { 1316 tabStates[mode -1] = new TabState(); 1317 state = tabStates[mode -1]; 1318 } 1319 state.filtered = isFiltered(); 1320 state.filter = getFilter(); 1321 } 1322 1323 1324 private void loadFilterState(int mode) { } 1334 1335 private void releaseWorkaround() { 1337 ObservableList filter = getModel(); 1338 if (filter instanceof FilteredTasksList) { 1339 ((FilteredTasksList)filter).byebye(); 1340 } 1341 } 1342 1343 1344 private void handleCurrentFile() { 1345 1346 1348 saveFilterState(); 1349 switch (getMode()) { 1350 case CURRENT_FILE_MODE: 1351 return; 1352 case OPENED_FILES_MODE: 1353 allJob.stopBroker(); 1354 allJob = null; 1355 break; 1356 case SELECTED_FOLDER_MODE: 1357 if (background != null) handleStop(); 1358 background = null; 1359 break; 1360 } 1361 1362 1364 try { 1365 job = SuggestionsBroker.getDefault().startBroker(new SourceTasksProviderAcceptor()); 1366 treeTable.setProperties(createColumns()); 1367 treeTable.setTreePreferredWidth(createColumns()[0].getWidth()); 1368 setModel(createFilteredList(job.getSuggestionsList())); 1369 loadFilterState(CURRENT_FILE_MODE); 1370 } finally { 1371 getRefresh().setEnabled(false); 1373 getTable().requestFocusInWindow(); 1374 updateMiniStatus(); 1375 putClientProperty(JComponent.TOOL_TIP_TEXT_KEY, getToolTipText()); 1376 } 1377 } 1378 1379 1380 private void handleSelectFolder() { 1381 1382 if (background != null) handleStop(); 1383 background = null; 1384 1385 final Node content = Choosers.projectView(); 1387 NodeOperation op = NodeOperation.getDefault(); 1388 1389 try { 1390 Node[] selected = op.select(Util.getString("sel_title"), Util.getString("sel-head"), content, new NodeAcceptor() { 1391 public boolean acceptNodes(Node[] nodes) { 1392 return nodes.length == 1 && nodes[0] != content && nodes[0].getLookup().lookup(FileObject.class) != null; 1393 } 1394 }); 1395 1396 resultsSnapshot = null; 1397 updateRecent(selectedFolder); 1398 selectedFolder = (FileObject) selected[0].getLookup().lookup(FileObject.class); 1399 1400 handleAllFiles(); 1401 } catch (UserCancelException e) { 1402 } finally { 1404 Choosers.icons = null; 1405 } 1406 } 1407 1408 private void updateRecent(FileObject fo) { 1409 addRecent(recentFolders, fo); 1410 } 1411 1412 private static void addRecent(java.util.List recentFolders, FileObject fo) { 1413 if (fo == null) return; 1414 if (recentFolders.contains(fo) == false) { 1415 if (recentFolders.size() == RECENT_ITEMS_COUNT) { 1416 recentFolders.remove(recentFolders.size() -1); 1417 } 1418 recentFolders.add(0, fo); 1419 } else { 1420 recentFolders.remove(fo); 1421 recentFolders.add(0, fo); 1422 } 1423 } 1424 1425 private void handlePrev() { 1426 prevTask(); 1427 } 1428 1429 private void handleNext() { 1430 nextTask(); 1431 } 1432 1433 1434 final void setBackground(Background background) { 1435 this.background = background; 1436 } 1437 1438 private void updateButtonsState() { 1439 switch (getMode()) { 1440 case CURRENT_FILE_MODE: 1441 currentFile.setSelected(true); 1442 openedFiles.setSelected(false); 1443 folderSelector.setSelected(false); 1444 break; 1445 case OPENED_FILES_MODE: 1446 currentFile.setSelected(false); 1447 openedFiles.setSelected(true); 1448 folderSelector.setSelected(false); 1449 break; 1450 1451 case SELECTED_FOLDER_MODE: 1452 currentFile.setSelected(false); 1453 openedFiles.setSelected(false); 1454 folderSelector.setSelected(true); 1455 break; 1456 } 1457 } 1458 1459 private static long lastUISync = System.currentTimeMillis(); 1460 1461 1464 public static void handlePendingAWTEvents() { 1465 if (SwingUtilities.isEventDispatchThread()) return; 1466 1467 long now = System.currentTimeMillis(); 1468 if (now - lastUISync < 103) return; 1469 1470 lastUISync = now; 1471 1472 try { 1473 SwingUtilities.invokeAndWait(new Runnable () { 1474 public void run() { 1475 } 1477 }); 1478 } catch (InterruptedException ignore) { 1479 } catch (InvocationTargetException ignore) { 1480 } 1481 } 1482 1483 public boolean isObserved(String category) { 1484 return isShowing() && SourceTaskProvider.TYPE.equals(category); 1485 } 1486 1487 public SuggestionList getSuggestionsModel() { 1488 return null; 1489 } 1490 1491 private static ObservableList createFilteredList(TaskList list) { 1492 return new FilteredTasksList(list); 1493 } 1494 1495 public org.netbeans.modules.tasklist.core.filter.Filter createFilter() { 1496 return new SourceTasksFilter(NbBundle.getMessage(SourceTaskNode.class, "new-filter-name")); 1497 } 1498 1499 public AccessibleContext getAccessibleContext() { 1500 AccessibleContext ret = super.getAccessibleContext(); 1501 switch (getMode()) { 1502 case CURRENT_FILE_MODE: 1503 ret.setAccessibleDescription(Util.getString("file_desc11")); 1504 break; 1505 case OPENED_FILES_MODE: 1506 ret.setAccessibleDescription(Util.getString("opened_desc11")); 1507 break; 1508 case SELECTED_FOLDER_MODE: 1509 ret.setAccessibleDescription(Util.getMessage("folder_desc11", createLabel(selectedFolder))); 1510 break; 1511 } 1512 return ret; 1513 } 1514 1515 private static class TabState { 1516 boolean filtered; Filter filter; } 1519 1520 protected void setFiltered() { 1521 super.setFiltered(); 1522 } 1523 1524 1525 private JButton filterIconButton = null; 1526 1527 private AbstractButton getFilterIconButton() { 1528 if (filterIconButton == null) { 1529 Icon icon = new ImageIcon(Utilities.loadImage("org/netbeans/modules/tasklist/docscan/filter.png")); filterIconButton = new JButton(icon); 1531 adjustToobarButton(filterIconButton); 1532 filterIconButton.setToolTipText(Util.getString("filter_hint") + " (shift+f)"); filterIconButton.addActionListener(dispatcher); 1534 1535 filterIconButton.getAccessibleContext().setAccessibleName(Util.getString("filter")); 1536 filterIconButton.getAccessibleContext().setAccessibleDescription(Util.getString("filter_hint")); 1537 1538 } 1539 1540 return filterIconButton; 1541 } 1542 1543 private JComboBox filterCombo = null; 1544 1545 1546 private static class FiltersComboModel implements ComboBoxModel { 1547 1548 public FiltersComboModel(FilterRepository rep) { 1549 this.rep = rep; 1550 rep.addPropertyChangeListener(new PropertyChangeListener () { 1551 public void propertyChange(PropertyChangeEvent evt) {onFiltersChanged(evt);} 1552 }); 1553 } 1554 1555 public void addListDataListener(javax.swing.event.ListDataListener l) { 1556 if (lsnrs.indexOf(l) == -1) { 1557 lsnrs.add(l); 1558 } 1559 } 1560 1561 public Object getElementAt(int index) { 1562 if (elements == null) prepareElements(); 1563 return elements[index]; 1564 } 1565 1566 private void prepareElements() { 1567 elements = new Filter.ListModelElement[rep.size()+1]; 1568 elements[0] = new Filter.ListModelElement(null); 1569 1570 Iterator it = rep.iterator(); 1571 for (int i = 1; i < rep.size()+1; i++) 1572 elements[i] = new Filter.ListModelElement((Filter)it.next()); 1573 1574 if (activei >= rep.size()+1) activei = -1; 1575 1576 } 1577 1578 public Object getSelectedItem() { 1579 if (elements == null) prepareElements(); 1580 if (activei == -1) { 1581 Filter f = rep.getActive(); 1582 for (int i = 0 ; i < elements.length; i++) 1583 if (elements[i].filter == f) { activei = i; break;} 1584 } 1585 1586 return (activei >= 0)?elements[activei]:null; 1587 } 1588 1589 public int getSize() { 1590 return rep.size()+1; 1591 } 1592 1593 public void removeListDataListener(javax.swing.event.ListDataListener l) { 1594 lsnrs.remove(l); 1595 } 1596 1597 public void setSelectedItem(Object anItem) { 1598 rep.setActive(((Filter.ListModelElement)anItem).filter); 1599 } 1600 1601 private void onFiltersChanged(PropertyChangeEvent evt) { 1602 if (evt.getPropertyName().equals(FilterRepository.PROP_FILTERS)) { 1603 elements = null; 1604 fireContentsChanged(); 1605 } else 1606 if (evt.getPropertyName().equals(FilterRepository.PROP_ACTIVE_FILTER)) { 1607 activei = -1; 1608 fireContentsChanged(); 1609 } 1610 } 1611 1612 private void fireContentsChanged() { 1613 ListDataEvent evt = new ListDataEvent (this, ListDataEvent.CONTENTS_CHANGED, 0, Integer.MAX_VALUE); 1614 List clone = null; 1615 synchronized(lsnrs) { 1616 clone = new ArrayList(lsnrs); 1617 } 1618 Iterator it = clone.iterator(); 1619 while (it.hasNext()) { 1620 ((ListDataListener )it.next()).contentsChanged(evt); 1621 } 1622 } 1623 1624 private List lsnrs = Collections.synchronizedList(new LinkedList()); 1625 private Filter.ListModelElement [] elements = null; 1626 private int activei = -1; 1627 private FilterRepository rep = null; 1628 } 1629 1630 private JComboBox getFilterCombo() { 1631 if (filterCombo == null) { 1632 filterCombo = new JComboBox(new FiltersComboModel(getFilters())); 1633 filterCombo.addActionListener(dispatcher); 1634 adjustToolbarComponentSize(filterCombo); 1635 Dimension dim = filterCombo.getPreferredSize(); 1636 dim.width = 150; 1637 dim.height = getToolbarHeight(); 1638 filterCombo.setPreferredSize(dim); 1639 1640 filterCombo.setToolTipText(Util.getString("choose-filter_hint") + " (f)"); filterCombo.getAccessibleContext().setAccessibleName(Util.getString("choose-filter")); 1642 filterCombo.getAccessibleContext().setAccessibleDescription(Util.getString("choose-filter_hint")); 1643 1644 } 1645 1646 return filterCombo; 1647 } 1648 1649 1650} 1651 | Popular Tags |