KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > tasklist > docscan > SourceTasksView


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.tasklist.docscan;
21 import java.awt.*;
22 import java.awt.event.*;
23 import java.beans.PropertyChangeEvent JavaDoc;
24 import java.beans.PropertyChangeListener JavaDoc;
25 import java.io.*;
26 import java.lang.reflect.InvocationTargetException JavaDoc;
27 import java.util.*;
28 import java.util.List JavaDoc;
29
30 import javax.swing.*;
31 import javax.swing.event.PopupMenuListener JavaDoc;
32 import javax.swing.event.PopupMenuEvent JavaDoc;
33 import javax.swing.border.Border JavaDoc;
34 import javax.swing.border.CompoundBorder JavaDoc;
35 import javax.accessibility.AccessibleContext JavaDoc;
36 import javax.swing.event.ListDataEvent JavaDoc;
37 import javax.swing.event.ListDataListener JavaDoc;
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 /**
65  * View containing only source tasks (TODOs) either for
66  * all files in project or for current file.
67  *
68  * @author Petr Kuzel
69  */

70 final class SourceTasksView extends TaskListView implements SourceTasksAction.ScanProgressMonitor, SuggestionView {
71
72     private static final long serialVersionUID = 1;
73
74     // The category should be DIFFERENT from the category used
75
// for the default suggestion view (the active scanning view)
76
// such that the "Show Suggestions View" action does not
77
// locate and reuse these windows - and so they can have different
78
// column configurations (filename is not useful in the active
79
// suggestions view window, but is critical in the directory
80
// scan for example.)
81
final static String JavaDoc CATEGORY = "sourcetasks"; // NOI18N
82

83     // keep consistent with SourceTasksAction icon
84
private final static String JavaDoc ICON_PATH = "org/netbeans/modules/tasklist/docscan/todosAction.gif"; // NOI18N
85

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     //XXX keep with sync with SuggestionNode, hidden dependency
93
// static final String PROP_SUGG_PRIO = "suggPrio"; // NOI18N
94
// static final String PROP_SUGG_FILE = "suggFile"; // NOI18N
95
// static final String PROP_SUGG_LINE = "suggLine"; // NOI18N
96
// static final String PROP_SUGG_CAT = "suggCat"; // NOI18N
97
// static final String PROP_SUGG_LOC = "suggLoc"; // NOI18N
98

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     // current job or null if snapshot
105
private SuggestionsBroker.Job job;
106
107     // all files results or null
108
private TaskList resultsSnapshot;
109
110     // if terminated then describes why
111
private String JavaDoc reasonMsg;
112
113     /** background scanning or null */
114     private Background background;
115
116     /** Selcted folder to be scanned or null */
117     /*package*/ FileObject selectedFolder;
118
119     private static final int RECENT_ITEMS_COUNT = 4;
120     private ArrayList recentFolders = new ArrayList(RECENT_ITEMS_COUNT);
121
122     /** Active opened files job or null */
123     private SuggestionsBroker.AllOpenedJob allJob;
124
125     private final TabState[] tabStates = new TabState[MODE_COUNT];
126
127     //#45006 save action key that was registered by WS
128
private Object JavaDoc windowSystemESCActionKey;
129
130     /**
131      * Externalization entry point (readExternal).
132      */

133     public SourceTasksView() {
134         super();
135         // readExternal, init
136
}
137
138     /**
139      * Construct TODOs from all files in project.
140      * @param list live tasklist driving view
141      */

142     public SourceTasksView(SourceTasksList list) {
143         super(
144                 CATEGORY,
145                 Util.getString("win-title"),
146                 Utilities.loadImage(ICON_PATH), // NOI18N
147
true,
148                 list
149         );
150
151         init();
152     }
153
154     /**
155      * Creates TODOs views for current file.
156      * @param job live tasklist monitoring current file
157      */

158     SourceTasksView(SuggestionsBroker.Job job) {
159         super(
160                 CATEGORY,
161                 Util.getString("win-title"),
162                 Utilities.loadImage(ICON_PATH), // NOI18N
163
true,
164                 createFilteredList(job.getSuggestionsList())
165         );
166         this.job = job;
167         init();
168     }
169
170     /**
171      * Common initialization code shared by constructor and externalization
172      */

173     private void init() {
174         // When the tab is alone in a container, don't show a tab;
175
// the category nodes provide enough feedback.
176
putClientProperty("TabPolicy", "HideWhenAlone"); // NOI18N
177

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       // after the center component was created, it is save to getTable
225
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       // we need to provide a specialized node factory because we need
243
// SourceTaskNodes for SuggestionImpls and don't want to
244
// override SuggestionImpl just for that (it would be correct
245
// but to much work)
246
return new TaskListNode(getModel(),
247                   new TaskListNode.NodeFactory() {
248                 public Node createNode(Object JavaDoc task) {
249                   if (task instanceof SuggestionImpl) {
250                     return new SourceTaskNode((SuggestionImpl)task);//, new SourceTaskChildren((SuggestionImpl)task));
251
}
252                   else
253                     return ((Task)task).createNode()[0];
254                 }
255                   });
256     }
257
258
259     private ColumnProperty[] allFilesColumns;
260     private ColumnProperty[] currentFileColumns;
261
262     /** Create columes according to current getMode(). */
263     protected ColumnProperty[] createColumns() {
264         // No point allowing other attributes of the task since that's
265
// all we support for scan items (they are not created by
266
// the user - and they are not persisted.
267

268         // See overridden loadColumnConfiguration to supress
269
// loading from sourcetasks_columns.xml
270

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 JavaDoc();
295         }
296     }
297
298     protected ColumnProperty getMainColumn(int width) {
299       return createColumns()[0];
300     }
301
302
303     protected void loadColumnsConfiguration() {
304         // TODO read from proper file
305
}
306
307     protected void storeColumnsConfiguration() {
308         // XXX write to proper file
309
// also note direct call to treeTable.setProperties in subview switch
310
// that bypass setting proper client values at columns
311
}
312
313     private ColumnProperty createMainColumn(int width) {
314         return new ColumnProperty(
315                 MAIN_COLUMN_UID, // UID -- never change (part of serialization
316
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, // UID -- never change (part of serialization
325
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, // UID -- never change (part of serialization
335
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, // UID -- never change (part of serialization
346
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, // UID -- never change (part of serialization
356
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) { // XXX how relates to deserialization?, is it called at all?
369
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         // keep on mind that it's still alive, just invisible
389
// Until garbage collected it can be reopen at any time
390
// restoring all data from caches (fields).
391
}
392
393     /** Returns "todo-window" */
394     protected String JavaDoc preferredID() {
395         return "todo-window"; // NOI18N
396
}
397
398     public void writeExternal(ObjectOutput objectOutput) throws IOException {
399
400         Cache.store();
401
402         // It's called by window system depending on actual value of:
403
// putClientProperty("PersistenceType", "OnlyOpened"|"Never");
404

405         // version 1 format
406
// write int 1
407
// skip call to super.writeExternal
408
// write bool snapshot flag
409

410         // version 2 format appends
411
// recentFiles
412
objectOutput.writeInt(2); // version
413

414         // Super method is driven by a private
415
// filed passed in contructor and it denies
416
// to write anything => fails on read on OptionalDataException
417
//super.writeExternal(objectOutput);
418

419         boolean snapshot = job == null;
420         objectOutput.writeBoolean(snapshot);
421         if (snapshot) {
422             // write down tasklist, we know it's not hierachical
423
// TaskList list = getList();
424
// Task root = list.getRoot();
425
// LinkedList tasks = root.getSubtasks();
426
// Iterator it = tasks.iterator();
427
// objectOutput.writeInt(tasks.size());
428
// while (it.hasNext()) {
429
// SuggestionImpl task = (SuggestionImpl) it.next();
430
// String summary = task.getSummary();
431
// String file = task.getFileBaseName();
432
// int line = task.getLine().getLineNumber();
433
// int prio = task.getPriorityNumber();
434
// objectOutput.writeUTF(summary);
435
// objectOutput.writeUTF(file);
436
// objectOutput.writeInt(line);
437
// objectOutput.writeInt(prio);
438
// }
439
}
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     // TODO support de/seriliazation for "all oponed" mode
450
public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException JavaDoc {
451
452         super.category = CATEGORY;
453         super.setName(Util.getString("win-title"));
454         super.setIcon(Utilities.loadImage(ICON_PATH)); // NOI18N
455

456         int version = objectInput.readInt();
457         if (version == 1 || version == 2) {
458             // read writeExternal
459
//super.readExternal(objectInput);
460

461             boolean snapshot = objectInput.readBoolean();
462     // if (snapshot) {
463
// // read cache
464
// int size = objectInput.readInt();
465
// Children.Array tasks = new Children.Array();
466
// for (int i = 0; i<size; i++) {
467
// String summary = objectInput.readUTF();
468
// String file = objectInput.readUTF();
469
// int line = objectInput.readInt();
470
// int prio = objectInput.readInt();
471
// tasks.add(new Node[] {new SourceTaskNode(summary, file, line, prio)});
472
// }
473
// getExplorerManager().setRootContext(new AbstractNode(tasks));
474
// } else {
475
// XXX defer to isShowing
476
job = SuggestionsBroker.getDefault().startBroker(new SourceTasksProviderAcceptor());
477                 this.category = CATEGORY;
478                 registerTaskListView(this);
479                 setModel(createFilteredList(job.getSuggestionsList()));
480      // }
481

482             if (version == 2) {
483                 recentFolders = (ArrayList) objectInput.readObject();
484             }
485         }
486
487         init();
488
489     }
490
491     public String JavaDoc 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 JavaDoc toString() {
502         return "SourceTasksView@" + hashCode();
503     }
504
505     // North component ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
506

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     // Misiatus shows selected folder, limit info
529
// and filter status
530
private void updateMiniStatus() {
531         assert SwingUtilities.isEventDispatchThread();
532         String JavaDoc prefix = "";
533         getMiniStatus().setHorizontalAlignment(SwingConstants.LEFT);
534         StringBuffer JavaDoc msg = new StringBuffer JavaDoc(80);
535         if (job == null && allJob== null && selectedFolder != null) {
536             if (msg.length() > 0) prefix = ", "; // NOI18N
537
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 = ", "; // NOI18N
542
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     /*package*/ AbstractButton getRefresh() {
551         if (refresh == null) {
552             Image image = Utilities.loadImage("org/netbeans/modules/tasklist/docscan/refresh.png"); // NOI18N
553
JButton button = new JButton(new ImageIcon(image));
554             button.setToolTipText(Util.getString("rescan_hint") + " (r)"); // NOI18N
555
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     /*package*/ AbstractButton getAllFiles() {
593         if (allFilesButton == null) {
594             JToggleButton button = new JToggleButton(Util.getString("see-folder"));
595             String JavaDoc tooltiptext ;
596             if (selectedFolder == null) {
597                 tooltiptext = Util.getString("see-folder_hint1");
598             } else {
599                 // restored from settings
600
tooltiptext = Util.getString("see-folder_hint2");
601             }
602
603             button.setToolTipText(tooltiptext + " (s)"); // NOI18N
604

605             group.add(button);
606             button.setSelected(job == null);
607             button.addActionListener(dispatcher);
608             adjustToobarButton(button);
609 // JButton pop = new JButton("V");
610
// adjustHeight(pop);
611
// JToggleButton both = new JToggleButton();
612
// both.setLayout(new BorderLayout());
613
// button.setBorder(null);
614
// pop.setBorder(null);
615
// both.add(button, BorderLayout.WEST);
616
// both.add(pop, BorderLayout.EAST);
617

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)"); // NOI18N
632
button.addActionListener(dispatcher);
633             adjustToobarButton(button);
634
635             button.getAccessibleContext().setAccessibleName(Util.getString("select-folder"));
636             button.getAccessibleContext().setAccessibleDescription(Util.getString("selector_hint"));
637             // DBG button.setBorder(BorderFactory.createLineBorder(Color.GREEN));
638
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"))); // NOI18N
650
// setMargin(new Insets(10, 0, 9, 0));
651
}
652
653         public Dimension getPreferredSize() {
654 // Dimension dim = getAllFiles().getPreferredSize();
655
// int HEURITICS_FOR_OCEAN_LF = 1; // get botton aligned with Selected Folder button
656
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)); // NOI18N
678
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)); // NOI18N
693
item.addActionListener(new RecentActionListener(fo));
694             popup.add(item);
695             i++;
696         }
697
698         popup.addPopupMenuListener(new PopupMenuListener JavaDoc() {
699             public void popupMenuWillBecomeVisible(PopupMenuEvent JavaDoc e) {
700             }
701
702             public void popupMenuWillBecomeInvisible(PopupMenuEvent JavaDoc e) {
703             }
704
705             public void popupMenuCanceled(PopupMenuEvent JavaDoc 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)"); // NOI18N
756
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"); // NOI18N
774
JButton button = new JButton(new ImageIcon(image));
775             button.setToolTipText(Util.getString("goto_hint") + " (e)"); // NOI18N
776
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     /** Eliminates action listener inner classes. */
788     private class Dispatcher implements ActionListener {
789         public void actionPerformed(ActionEvent e) {
790             Object JavaDoc 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           // JPopupMenu popup = new JPopupMenu();
822

823
824 // Iterator it = getFilters().iterator();
825
// while (it.hasNext()) {
826
// final Filter f = (Filter)it.next();
827
// JMenuItem item = new JMenuItem(f.getName());
828
// item.addActionListener(new ActionListener() {
829
// public void actionPerformed(ActionEvent e) {
830
// setFilter(f);
831
// }
832
// });
833
// popup.add(item);
834
// }
835

836 // popup.show(filterButton, 0, filterButton.getHeight() - 2);
837

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           // updateMiniStatus();
843
}
844             
845         }
846     }
847
848
849
850     private final ActionListener dispatcher = new Dispatcher();
851
852     /** Toolbar controls must be smaller and should be tarnsparent*/
853     private void adjustToobarButton(final AbstractButton button) {
854
855         button.setMargin(new Insets(0, 3, 0, 3));
856
857         // workaround for Ocean L&F clutter - toolbars use gradient.
858
// To make the gradient visible under buttons the content area must not
859
// be filled. To support rollover it must be temporarily filled
860
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 // if (button instanceof JToggleButton) {
877
// if (buttonBorder == null) { // for some l&f's, core will supply one
878
// buttonBorder = UIManager.getBorder("nb.tabbutton.border"); //NOI18N
879
// }
880
//
881
// if (buttonBorder == null) {
882
// JToolBar toolbar = new JToolBar();
883
// toolbar.setRollover(true);
884
// toolbar.add(button);
885
// buttonBorder = button.getBorder();
886
// toolbar.remove(button);
887
// }
888
//
889
// button.setBorder(buttonBorder);
890
// }
891

892         adjustToolbarComponentSize(button);
893     }
894     
895     private void adjustToolbarComponentSize(JComponent button) {
896         // as we cannot get the button small enough using the margin and border...
897
if (button.getBorder() instanceof CompoundBorder JavaDoc) { // from BasicLookAndFeel
898
Dimension pref = button.getPreferredSize();
899             pref.height = getToolbarHeight();
900
901             // XXX #41827 workaround w2k, that adds eclipsis (...) insted of actual text
902
if ("Windows".equals(UIManager.getLookAndFeel().getID())) { // NOI18N
903
pref.width += 9;
904             }
905             button.setPreferredSize(pref);
906         }
907
908     }
909
910     public void updateFilterCount() {
911         // do not write anything
912
}
913
914     protected Component createNorthComponent() {
915
916         JToolBar toolbar = new JToolBar();
917         toolbar.setFloatable(false);
918         toolbar.putClientProperty("JToolBar.isRollover", Boolean.TRUE); // NOI18N
919
Border JavaDoc 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         // wrapped in JPanel it looks better on Ocean, GTK+ plaf worse on Metal
928
JPanel wrapper = new JPanel();
929         wrapper.setOpaque(false); // Ocean L&F toolbars use gradients
930
wrapper.setLayout(new FlowLayout(FlowLayout.CENTER,0,0));
931         wrapper.add(getFolderSelector());
932         toolbar.add(wrapper);
933
934         //JSeparator separator = new JSeparator(JSeparator.VERTICAL); // Ocean L&F doe snot support vertical separators
935
JPanel separator = new JPanel();
936         separator.setOpaque(false); // Ocean L&F toolbars use gradients
937
toolbar.add(separator);
938         toolbar.add(getGoto());
939         toolbar.add(getRefresh());
940         toolbar.add(getFilterIconButton());
941         toolbar.add(getFilterCombo());
942
943         //JSeparator separator2 = new JSeparator(JSeparator.VERTICAL); // Ocean L&F doe snot support vertical separators
944
JPanel separator2 = new JPanel();
945         separator2.setOpaque(false); // Ocean L&F toolbars use gradients
946
toolbar.add(separator2);
947         toolbar.add(getMiniStatus());
948
949         // Eliminates double height toolbar on Metal L&F
950
toolbar.setPreferredSize(new Dimension(Integer.MAX_VALUE, getToolbarHeight()));
951         return toolbar;
952
953     }
954
955     /**
956      * Hardcoded toolbar layout. It eliminates need
957      * for nested panels their look is hardly maintanable
958      * accross several look and feels
959      * (e.g. strange layouting panel borders on GTK+).
960      */

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); // 1 verySoftBevel compensation
982
horizont += width;
983             }
984         }
985
986         public void addLayoutComponent(String JavaDoc 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    // Monitor impl ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1011

1012    private int realFolders = 0;
1013    private int estimatedFolders = -1;
1014
1015    /** Currently scanned folder or null. */
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 JavaDoc() {
1029            public void run() {
1030                if (estimate == -1) {
1031                    Cache.load(); // hide this possibly long operation here
1032
}
1033            }
1034        });
1035    }
1036
1037    public void scanStarted() {
1038        
1039        realFolders = 0;
1040        reasonMsg = null;
1041                
1042        SwingUtilities.invokeLater(new Runnable JavaDoc() {
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 JavaDoc() {
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 JavaDoc() {
1103            public void run() {
1104                updateMiniStatus();
1105            }
1106        });
1107    }
1108
1109    // AWT request handlers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1110

1111    private void handleStop() {
1112        background.interrupt();
1113        getMiniStatus().setText(Util.getString("stopping"));
1114    }
1115
1116    /** Programatically invokes action retaining UI effect as it was done by user. */
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        // TODO should stop current job and restore it on component showing
1134
// it requires separate mode field instead of deriving it from job fields
1135
super.componentHidden();
1136    }
1137
1138    // used by unit test
1139
/*package*/ ObservableList discloseModel() {
1140        return getModel();
1141    }
1142
1143    /*package*/ Object JavaDoc discloseTable() {
1144        return treeTable;
1145    }
1146
1147    /*package*/ Node discloseNode() {
1148        return rootNode;
1149    }
1150
1151    /** User clicked all files mode. Start allJob. */
1152    private void handleOpenedFiles() {
1153
1154        // we are still in old mode, stop it
1155
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        // enter new mode
1172

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    /** User clicked selected folder, restore from cache or ask for context */
1188    private void handleAllFiles() {
1189
1190        // prepare (& check) new mode parameters
1191

1192        if (selectedFolder == null) {
1193            if (recentFolders.size() > 0) {
1194                showFolderSelectorPopup();
1195            } else {
1196                handleSelectFolder();
1197            }
1198            // all popup branches and selectors contain handleAllFiles() call
1199
return;
1200        } else {
1201            // it might be resored from persitent setting and unavailable
1202
DataObject seletedDataFolder = null;
1203            try {
1204                 seletedDataFolder = DataObject.find(selectedFolder);
1205            } catch (DataObjectNotFoundException e) {
1206                // let it be null
1207
}
1208            if (seletedDataFolder == null) {
1209                if (recentFolders.size() > 0) {
1210                    showFolderSelectorPopup();
1211                } else {
1212                    handleSelectFolder();
1213                }
1214                return;
1215            }
1216        }
1217
1218        // terminate old mode
1219

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        // enter new mode
1236

1237        allFilesButton.setToolTipText(Util.getMessage("see-folder-hint2", createLabel(selectedFolder)) + " (s)"); // NOI18N
1238
((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; // invalid folder
1263
}
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 JavaDoc createLabel(FileObject fo) {
1285        String JavaDoc 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                // keep empty path
1293
}
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    /** Determine toggle buttons status from internal state. */
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    /** Stores filter state for current mode */
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    /** Restore filter state from saved one for given mode. */
1324    private void loadFilterState(int mode) { // XXX mode param could be replaced by getMode()
1325
// TabState state = tabStates[mode -1];
1326
// if (state != null) {
1327
// setFilter(state.filter, false);
1328
// setFiltered(state.filtered);
1329
// } else {
1330
// setFiltered(false);
1331
// setFilter(null, false); // new filter instance request later on in FilterAction
1332
// }
1333
}
1334
1335    // XXX detects listener leaks
1336
private void releaseWorkaround() {
1337        ObservableList filter = getModel();
1338        if (filter instanceof FilteredTasksList) {
1339            ((FilteredTasksList)filter).byebye();
1340        }
1341    }
1342
1343    /** Switches to current file mode. */
1344    private void handleCurrentFile() {
1345
1346        // terminate previous mode
1347

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        // enter new mode
1363

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            // setModel() above triggers IAE in IconManager after gc()
1372
getRefresh().setEnabled(false);
1373            getTable().requestFocusInWindow();
1374            updateMiniStatus();
1375            putClientProperty(JComponent.TOOL_TIP_TEXT_KEY, getToolTipText());
1376        }
1377    }
1378
1379    /** Let user choose what folder to scan and set selectedFolder field. */
1380    private void handleSelectFolder() {
1381
1382        if (background != null) handleStop();
1383        background = null;
1384
1385        // prepare content for selector
1386
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            // no folders selected keep previous one
1403
} 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 JavaDoc 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    /** Set background process that feeds this view */
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    /**
1462     * Gives up CPU until all known AWT events get dispatched.
1463     */

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 JavaDoc() {
1474                public void run() {
1475                    // nothing no deadlock can occure
1476
}
1477            });
1478        } catch (InterruptedException JavaDoc ignore) {
1479        } catch (InvocationTargetException JavaDoc ignore) {
1480        }
1481    }
1482
1483    public boolean isObserved(String JavaDoc 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 JavaDoc getAccessibleContext() {
1500        AccessibleContext JavaDoc 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 enabled
1517
Filter filter; // last filter
1518
}
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")); // NOI18N
1530
filterIconButton = new JButton(icon);
1531        adjustToobarButton(filterIconButton);
1532            filterIconButton.setToolTipText(Util.getString("filter_hint") + " (shift+f)"); // NOI18N
1533
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 JavaDoc() {
1551                public void propertyChange(PropertyChangeEvent JavaDoc evt) {onFiltersChanged(evt);}
1552            });
1553        }
1554        
1555        public void addListDataListener(javax.swing.event.ListDataListener JavaDoc l) {
1556            if (lsnrs.indexOf(l) == -1) {
1557                lsnrs.add(l);
1558            }
1559        }
1560        
1561        public Object JavaDoc 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 JavaDoc 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 JavaDoc l) {
1594            lsnrs.remove(l);
1595        }
1596        
1597        public void setSelectedItem(Object JavaDoc anItem) {
1598            rep.setActive(((Filter.ListModelElement)anItem).filter);
1599        }
1600        
1601        private void onFiltersChanged(PropertyChangeEvent JavaDoc 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 JavaDoc evt = new ListDataEvent JavaDoc(this, ListDataEvent.CONTENTS_CHANGED, 0, Integer.MAX_VALUE);
1614            List JavaDoc clone = null;
1615            synchronized(lsnrs) {
1616                clone = new ArrayList(lsnrs);
1617            }
1618            Iterator it = clone.iterator();
1619            while (it.hasNext()) {
1620                ((ListDataListener JavaDoc)it.next()).contentsChanged(evt);
1621            }
1622        }
1623        
1624        private List JavaDoc 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)"); // NOI18N
1641
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